use crate::application::Block;
use commonware_actor::{
mailbox::{Policy, Sender},
Feedback,
};
use commonware_consensus::{marshal::Update, Reporter};
use commonware_cryptography::{
bls12381::{dkg::feldman_desmedt::SignedDealerLog, primitives::variant::Variant},
Hasher, Signer,
};
use commonware_utils::{acknowledgement::Exact, channel::oneshot, Acknowledgement};
use std::collections::VecDeque;
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 },
}
impl<H, C, V, A> Policy for Message<H, C, V, A>
where
H: Hasher,
C: Signer,
V: Variant,
A: Acknowledgement,
{
type Overflow = VecDeque<Self>;
fn handle(overflow: &mut VecDeque<Self>, message: Self) {
overflow.push_back(message);
}
}
#[derive(Clone)]
pub struct Mailbox<H, C, V, A = Exact>
where
H: Hasher,
C: Signer,
V: Variant,
A: Acknowledgement,
{
sender: 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: 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();
if !self
.sender
.enqueue(Message::Act {
response: response_tx,
})
.accepted()
{
error!("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>;
fn report(&mut self, update: Self::Activity) -> Feedback {
let Update::Block(block, ack_tx) = update else {
return Feedback::Ok;
};
self.sender.enqueue(Message::Finalized {
block,
response: ack_tx,
})
}
}