use commonware_actor::mailbox::{Policy, Sender};
use commonware_consensus::types::Epoch;
use commonware_cryptography::{
bls12381::primitives::{group, sharing::Sharing, variant::Variant},
PublicKey,
};
use commonware_utils::ordered::Set;
use std::collections::VecDeque;
use tracing::error;
pub enum Message<V: Variant, P: PublicKey> {
Enter(EpochTransition<V, P>),
Exit(Epoch),
}
impl<V: Variant, P: PublicKey> Policy for Message<V, P> {
type Overflow = VecDeque<Self>;
fn handle(overflow: &mut VecDeque<Self>, message: Self) {
match message {
Self::Enter(transition) => {
let epoch = transition.epoch;
if let Some(index) = overflow
.iter()
.position(|pending| matches!(pending, Self::Exit(pending) if *pending == epoch))
{
overflow.remove(index);
} else {
overflow.push_back(Self::Enter(transition));
}
}
Self::Exit(epoch) => {
if let Some(index) = overflow.iter().position(
|pending| matches!(pending, Self::Enter(pending) if pending.epoch == epoch),
) {
overflow.remove(index);
} else {
overflow.push_back(Self::Exit(epoch));
}
}
}
}
}
pub struct EpochTransition<V: Variant, P: PublicKey> {
pub epoch: Epoch,
pub poly: Option<Sharing<V>>,
pub share: Option<group::Share>,
pub dealers: Set<P>,
}
#[derive(Debug, Clone)]
pub struct Mailbox<V: Variant, P: PublicKey> {
sender: Sender<Message<V, P>>,
}
impl<V: Variant, P: PublicKey> Mailbox<V, P> {
pub const fn new(sender: Sender<Message<V, P>>) -> Self {
Self { sender }
}
pub fn enter(&mut self, transition: EpochTransition<V, P>) {
if !self.sender.enqueue(Message::Enter(transition)).accepted() {
error!("failed to send epoch transition");
}
}
pub fn exit(&mut self, epoch: Epoch) {
if !self.sender.enqueue(Message::Exit(epoch)).accepted() {
error!("failed to send epoch exit");
}
}
}