Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ name = "pluto"
path = "src/main.rs"

[dependencies]
async-trait.workspace = true
clap.workspace = true
thiserror.workspace = true
k256.workspace = true
Expand Down
8 changes: 3 additions & 5 deletions crates/cli/src/commands/test/infra.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::{
time::{Duration, Instant},
};

use async_trait::async_trait;
use clap::Args;
use serde::Deserialize;
use tokio_util::sync::CancellationToken;
Expand Down Expand Up @@ -61,11 +62,7 @@ struct FioResultSingle {
bw: f64,
}

// `expect` cannot be used here: the lint does not fire under the current
// toolchain, so it would be flagged as an unfulfilled expectation. Kept as
// `allow` for forward compatibility. Reason: internal trait not part of the
// public API; no need for the `Send` bound the lint guards against.
#[allow(async_fn_in_trait)]
#[async_trait]
trait DiskTestTool {
async fn check_availability(&self) -> Result<()>;
async fn write_speed(&self, path: &Path, block_size_kb: i32) -> Result<f64>;
Expand All @@ -76,6 +73,7 @@ trait DiskTestTool {

struct FioTestTool;

#[async_trait]
impl DiskTestTool for FioTestTool {
async fn check_availability(&self) -> Result<()> {
let result = tokio::process::Command::new("fio")
Expand Down
1 change: 1 addition & 0 deletions crates/consensus/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ license.workspace = true
publish.workspace = true

[dependencies]
async-trait.workspace = true
axum.workspace = true
cancellation.workspace = true
chrono.workspace = true
Expand Down
28 changes: 11 additions & 17 deletions crates/consensus/src/qbft/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::{
sync::{Arc, Mutex, PoisonError},
};

use async_trait::async_trait;
use futures::future::BoxFuture;
use k256::{PublicKey, SecretKey};
use prost::{Message, Name};
Expand Down Expand Up @@ -599,6 +600,7 @@ impl Consensus {
}
}

#[async_trait]
impl crate::wrapper::Consensus for Consensus {
fn protocol_id(&self) -> String {
self.protocol_id().to_string()
Expand All @@ -608,29 +610,21 @@ impl crate::wrapper::Consensus for Consensus {
drop(Consensus::start(self, ct));
}

fn participate(
&self,
ct: CancellationToken,
duty: Duty,
) -> BoxFuture<'_, crate::wrapper::Result<()>> {
Box::pin(async move {
Consensus::participate(self, duty, &ct)
.await
.map_err(Into::into)
})
async fn participate(&self, ct: CancellationToken, duty: Duty) -> crate::wrapper::Result<()> {
Consensus::participate(self, duty, &ct)
.await
.map_err(Into::into)
}

fn propose(
async fn propose(
&self,
ct: CancellationToken,
duty: Duty,
value: pbcore::UnsignedDataSet,
) -> BoxFuture<'_, crate::wrapper::Result<()>> {
Box::pin(async move {
Consensus::propose(self, duty, value, &ct)
.await
.map_err(Into::into)
})
) -> crate::wrapper::Result<()> {
Consensus::propose(self, duty, value, &ct)
.await
.map_err(Into::into)
}

fn subscribe(&self, subscriber: crate::wrapper::Subscriber) {
Expand Down
21 changes: 11 additions & 10 deletions crates/consensus/src/wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::{
sync::{Arc, PoisonError, RwLock},
};

use futures::future::BoxFuture;
use async_trait::async_trait;
use pluto_core::{corepb::v1::core as pbcore, types::Duty};
use tokio_util::sync::CancellationToken;

Expand All @@ -30,6 +30,7 @@ pub type Subscriber =
Box<dyn Fn(Duty, pbcore::UnsignedDataSet) -> SubscriberResult + Send + Sync + 'static>;

/// Consensus implementation interface.
#[async_trait]
pub trait Consensus: Send + Sync {
/// Returns the consensus protocol ID.
fn protocol_id(&self) -> String;
Expand All @@ -38,15 +39,15 @@ pub trait Consensus: Send + Sync {
fn start(&self, ct: CancellationToken);

/// Starts participating in a consensus instance.
fn participate(&self, ct: CancellationToken, duty: Duty) -> BoxFuture<'_, Result<()>>;
async fn participate(&self, ct: CancellationToken, duty: Duty) -> Result<()>;

/// Proposes unsigned duty data for a consensus instance.
fn propose(
async fn propose(
&self,
ct: CancellationToken,
duty: Duty,
value: pbcore::UnsignedDataSet,
) -> BoxFuture<'_, Result<()>>;
) -> Result<()>;

/// Registers a callback for decided unsigned duty data.
fn subscribe(&self, subscriber: Subscriber);
Expand Down Expand Up @@ -115,7 +116,6 @@ impl ConsensusWrapper {
mod tests {
use std::sync::Mutex;

use futures::FutureExt as _;
use pluto_core::{
corepb::v1::core as pbcore,
types::{Duty, SlotNumber},
Expand Down Expand Up @@ -202,6 +202,7 @@ mod tests {
}
}

#[async_trait]
impl Consensus for TestConsensus {
fn protocol_id(&self) -> String {
self.protocol_id.clone()
Expand All @@ -211,19 +212,19 @@ mod tests {
self.record("start");
}

fn participate(&self, _ct: CancellationToken, _duty: Duty) -> BoxFuture<'_, Result<()>> {
async fn participate(&self, _ct: CancellationToken, _duty: Duty) -> Result<()> {
self.record("participate");
async { Ok(()) }.boxed()
Ok(())
}

fn propose(
async fn propose(
&self,
_ct: CancellationToken,
_duty: Duty,
_value: pbcore::UnsignedDataSet,
) -> BoxFuture<'_, Result<()>> {
) -> Result<()> {
self.record("propose");
async { Ok(()) }.boxed()
Ok(())
}

fn subscribe(&self, subscriber: Subscriber) {
Expand Down
1 change: 1 addition & 0 deletions crates/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ chrono.workspace = true
crossbeam.workspace = true
dyn-clone.workspace = true
dyn-eq.workspace = true
futures.workspace = true
hex.workspace = true
vise.workspace = true
pluto-crypto.workspace = true
Expand Down
3 changes: 2 additions & 1 deletion crates/core/src/aggsigdb/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::{
aggsigdb::types::{AggSigDB, Error},
deadline, types,
};
use async_trait::async_trait;
use std::collections::{HashMap, hash_map::Entry};
use tokio::sync;
use tokio_util::sync::CancellationToken;
Expand Down Expand Up @@ -168,7 +169,7 @@ impl MemoryDBHandle {
}
}

#[async_trait::async_trait]
#[async_trait]
impl AggSigDB for MemoryDBHandle {
async fn store(&self, duty: types::Duty, set: types::SignedDataSet) -> Result<(), Error> {
let (response_tx, response_rx) = sync::oneshot::channel();
Expand Down
4 changes: 3 additions & 1 deletion crates/core/src/aggsigdb/types.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use async_trait::async_trait;

use crate::types;

/// Errors for AggSigDB operations.
Expand All @@ -15,7 +17,7 @@ pub enum Error {
}

/// A persistent store for aggregated signed duty data.
#[async_trait::async_trait]
#[async_trait]
pub trait AggSigDB {
/// Stores aggregated signed duty data set.
async fn store(&self, duty: types::Duty, data: types::SignedDataSet) -> Result<(), Error>;
Expand Down
6 changes: 2 additions & 4 deletions crates/core/src/validatorapi/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
//! and public-share mappings needed to translate between distributed-validator
//! root keys and this node's threshold-BLS share.

use std::{any::Any, collections::HashMap, future::Future, pin::Pin, sync::Arc, time::Duration};
use std::{any::Any, collections::HashMap, future::Future, sync::Arc, time::Duration};

use async_trait::async_trait;
use axum::http::StatusCode;
use futures::future::BoxFuture;
use pluto_eth2api::{
EthBeaconNodeApiClient, GetAttesterDutiesRequest, GetAttesterDutiesResponse,
GetProposerDutiesRequest, GetProposerDutiesResponse, GetStateValidatorsResponseResponse,
Expand Down Expand Up @@ -59,9 +60,6 @@ use crate::{
/// Boxed error returned by registered callbacks.
pub type CallbackError = Box<dyn std::error::Error + Send + Sync + 'static>;

/// Boxed async callback result.
pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;

/// Subscriber callback for `Subscribe`. Receives the [`Duty`] and the
/// [`ParSignedDataSet`] by reference; the registered wrapper clones the
/// set exactly once before invoking the user closure so every subscriber
Expand Down
19 changes: 7 additions & 12 deletions crates/dkg/src/bcast/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use std::{collections::HashMap, sync::Arc};

use async_trait::async_trait;
use futures::future::BoxFuture;
use libp2p::PeerId;
use prost::{Message, Name};
Expand Down Expand Up @@ -37,20 +38,21 @@ pub(crate) struct BroadcastCommand {
}

/// Type-erased entry stored per registered message ID.
#[async_trait]
pub(crate) trait RegisteredMessage: Send + Sync {
/// Validates the incoming wrapped protobuf message.
fn check(&self, peer_id: PeerId, any: &Any) -> Result<()>;

/// Dispatches the incoming wrapped protobuf message to the typed callback.
fn callback(&self, peer_id: PeerId, msg_id: String, any: Any)
-> BoxFuture<'static, Result<()>>;
async fn callback(&self, peer_id: PeerId, msg_id: String, any: Any) -> Result<()>;
}

struct TypedRegistration<M> {
check: CheckFn<M>,
callback: CallbackFn<M>,
}

#[async_trait]
impl<M> RegisteredMessage for TypedRegistration<M>
where
M: Message + Name + Default + Clone + Send + Sync + 'static,
Expand All @@ -60,16 +62,9 @@ where
(self.check)(peer_id, &message)
}

fn callback(
&self,
peer_id: PeerId,
msg_id: String,
any: Any,
) -> BoxFuture<'static, Result<()>> {
match any.to_msg::<M>() {
Ok(message) => (self.callback)(peer_id, msg_id, message),
Err(e) => Box::pin(async move { Err(e.into()) }),
}
async fn callback(&self, peer_id: PeerId, msg_id: String, any: Any) -> Result<()> {
let message = any.to_msg::<M>()?;
(self.callback)(peer_id, msg_id, message).await
}
}

Expand Down
3 changes: 2 additions & 1 deletion crates/priority/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,7 @@ impl Component {

#[cfg(test)]
mod tests {
use async_trait::async_trait;
use pluto_core::corepb::v1::{core::Duty, priority::PriorityScoredResult};

use super::*;
Expand Down Expand Up @@ -601,7 +602,7 @@ mod tests {
#[test]
fn new_component_rejects_peer_absent_from_context() {
struct NoopConsensus;
#[async_trait::async_trait]
#[async_trait]
impl Consensus for NoopConsensus {
async fn propose_priority(
&self,
Expand Down
31 changes: 14 additions & 17 deletions crates/priority/src/p2p/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,26 +66,23 @@ impl Sender {
/// Errors with [`Error::Shutdown`] if the behaviour has been dropped, and
/// with [`Error::Transport`]/[`Error::Unsupported`] on dial or stream
/// failure. The caller is responsible for applying an exchange timeout.
pub fn send_receive(
pub async fn send_receive(
&self,
peer: PeerId,
request: PriorityMsg,
) -> BoxFuture<'static, crate::Result<PriorityMsg>> {
let command_tx = self.command_tx.clone();
Box::pin(async move {
let (response_tx, response_rx) = oneshot::channel();
command_tx
.send(Command::SendReceive {
peer,
request: OutboundRequest {
request,
response: response_tx,
},
})
.map_err(|_| Error::Shutdown)?;

response_rx.await.map_err(|_| Error::Shutdown)?
})
) -> crate::Result<PriorityMsg> {
let (response_tx, response_rx) = oneshot::channel();
self.command_tx
.send(Command::SendReceive {
peer,
request: OutboundRequest {
request,
response: response_tx,
},
})
.map_err(|_| Error::Shutdown)?;

response_rx.await.map_err(|_| Error::Shutdown)?
}
}

Expand Down
3 changes: 2 additions & 1 deletion crates/priority/src/prioritiser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,7 @@ fn start_consensus(
mod tests {
use std::sync::Mutex as StdMutex;

use async_trait::async_trait;
use chrono::{Duration as ChronoDuration, Utc};
use pluto_core::{
corepb::v1::priority::{PriorityResult, PriorityTopicProposal},
Expand Down Expand Up @@ -572,7 +573,7 @@ mod tests {
proposed: Arc<StdMutex<Vec<(Duty, PriorityResult)>>>,
}

#[async_trait::async_trait]
#[async_trait]
impl Consensus for MockConsensus {
async fn propose_priority(
&self,
Expand Down
Loading
Loading