use crate::Scheme;
use commonware_consensus::{
simplex::{
types::{Activity, Context},
Plan,
},
types::{Epoch, Round},
Automaton as Au, CertifiableAutomaton as CAu, Relay as Re, Reporter,
};
use commonware_cryptography::{ed25519::PublicKey, Digest};
use commonware_utils::channel::{mpsc, oneshot};
#[allow(clippy::large_enum_variant)]
pub enum Message<D: Digest> {
Genesis {
epoch: Epoch,
response: oneshot::Sender<D>,
},
Propose {
round: Round,
response: oneshot::Sender<D>,
},
Verify {
payload: D,
response: oneshot::Sender<bool>,
},
Report {
activity: Activity<Scheme, D>,
},
}
#[derive(Clone)]
pub struct Mailbox<D: Digest> {
sender: mpsc::Sender<Message<D>>,
}
impl<D: Digest> Mailbox<D> {
pub(super) const fn new(sender: mpsc::Sender<Message<D>>) -> Self {
Self { sender }
}
}
impl<D: Digest> Au for Mailbox<D> {
type Digest = D;
type Context = Context<Self::Digest, PublicKey>;
async fn genesis(&mut self, epoch: Epoch) -> Self::Digest {
let (response, receiver) = oneshot::channel();
self.sender
.send(Message::Genesis { epoch, response })
.await
.expect("Failed to send genesis");
receiver.await.expect("Failed to receive genesis")
}
async fn propose(
&mut self,
context: Context<Self::Digest, PublicKey>,
) -> oneshot::Receiver<Self::Digest> {
let (response, receiver) = oneshot::channel();
self.sender
.send(Message::Propose {
round: context.round,
response,
})
.await
.expect("Failed to send propose");
receiver
}
async fn verify(
&mut self,
_: Context<Self::Digest, PublicKey>,
payload: Self::Digest,
) -> oneshot::Receiver<bool> {
let (response, receiver) = oneshot::channel();
self.sender
.send(Message::Verify { payload, response })
.await
.expect("Failed to send verify");
receiver
}
}
impl<D: Digest> CAu for Mailbox<D> {
}
impl<D: Digest> Re for Mailbox<D> {
type Digest = D;
type PublicKey = PublicKey;
type Plan = Plan<PublicKey>;
async fn broadcast(&mut self, _: Self::Digest, _: Self::Plan) {
}
}
impl<D: Digest> Reporter for Mailbox<D> {
type Activity = Activity<Scheme, D>;
async fn report(&mut self, activity: Self::Activity) {
self.sender
.send(Message::Report { activity })
.await
.expect("Failed to send report");
}
}