use crate::application::Block;
use commonware_consensus::{marshal::Update, Reporter};
use commonware_cryptography::{
bls12381::{dkg::SignedDealerLog, primitives::variant::Variant},
Hasher, Signer,
};
use commonware_utils::{
acknowledgement::Exact,
channel::{mpsc, oneshot},
Acknowledgement,
};
use tracing::error;
#[allow(clippy::large_enum_variant)]
pub enum Message<H, C, V, A = Exact>
where
H: Hasher,
C: Signer,
V: Variant,
A: Acknowledgement,
{
Act {
response: oneshot::Sender<Option<SignedDealerLog<V, C>>>,
},
Finalized { block: Block<H, C, V>, response: A },
}
#[derive(Clone)]
pub struct Mailbox<H, C, V, A = Exact>
where
H: Hasher,
C: Signer,
V: Variant,
A: Acknowledgement,
{
sender: mpsc::Sender<Message<H, C, V, A>>,
}
impl<H, C, V, A> Mailbox<H, C, V, A>
where
H: Hasher,
C: Signer,
V: Variant,
A: Acknowledgement,
{
pub const fn new(sender: mpsc::Sender<Message<H, C, V, A>>) -> Self {
Self { sender }
}
pub async fn act(&mut self) -> Option<SignedDealerLog<V, C>> {
let (response_tx, response_rx) = oneshot::channel();
let message = Message::Act {
response: response_tx,
};
if let Err(err) = self.sender.send(message).await {
error!(?err, "failed to send act message");
return None;
}
match response_rx.await {
Ok(outcome) => outcome,
Err(err) => {
error!(?err, "failed to receive act response");
None
}
}
}
}
impl<H, C, V, A> Reporter for Mailbox<H, C, V, A>
where
H: Hasher,
C: Signer,
V: Variant,
A: Acknowledgement,
{
type Activity = Update<Block<H, C, V>, A>;
async fn report(&mut self, update: Self::Activity) {
let Update::Block(block, ack_tx) = update else {
return;
};
let _ = self
.sender
.send(Message::Finalized {
block,
response: ack_tx,
})
.await;
}
}