Skip to main content

commonware_glue/dkg/probe/
mailbox.rs

1use super::ActorArtifact;
2use crate::dkg::ReshareBlock;
3use commonware_actor::mailbox::{Policy, Sender};
4use commonware_consensus::{
5    marshal::core::{Mailbox as MarshalMailbox, Variant},
6    simplex::scheme::Scheme,
7};
8use commonware_cryptography::Signer;
9use commonware_utils::channel::oneshot;
10use std::collections::VecDeque;
11
12/// Messages sent to the DKG probe actor.
13pub(crate) enum Message<S, V>
14where
15    S: Scheme<V::Commitment>,
16    V: Variant,
17    V::ApplicationBlock: ReshareBlock,
18    <V::ApplicationBlock as ReshareBlock>::Signer: Signer<PublicKey = S::PublicKey>,
19{
20    /// Subscribe to the probe artifact.
21    Subscribe {
22        /// Channel used to resolve the subscriber.
23        response: oneshot::Sender<ActorArtifact<S, V>>,
24    },
25    /// Attach marshal and transition to boundary-serving mode once discovery no
26    /// no longer has pending subscribers.
27    Attach {
28        /// Marshal mailbox used to serve boundary requests.
29        marshal: MarshalMailbox<S, V>,
30    },
31}
32
33impl<S, V> Policy for Message<S, V>
34where
35    S: Scheme<V::Commitment>,
36    V: Variant,
37    V::ApplicationBlock: ReshareBlock,
38    <V::ApplicationBlock as ReshareBlock>::Signer: Signer<PublicKey = S::PublicKey>,
39{
40    type Overflow = VecDeque<Self>;
41
42    fn handle(overflow: &mut Self::Overflow, message: Self) {
43        overflow.push_back(message);
44    }
45}
46
47/// Mailbox for a running DKG probe actor.
48#[derive(Clone)]
49pub struct Mailbox<S, V>
50where
51    S: Scheme<V::Commitment>,
52    V: Variant,
53    V::ApplicationBlock: ReshareBlock,
54    <V::ApplicationBlock as ReshareBlock>::Signer: Signer<PublicKey = S::PublicKey>,
55{
56    sender: Sender<Message<S, V>>,
57}
58
59impl<S, V> Mailbox<S, V>
60where
61    S: Scheme<V::Commitment>,
62    V: Variant,
63    V::ApplicationBlock: ReshareBlock,
64    <V::ApplicationBlock as ReshareBlock>::Signer: Signer<PublicKey = S::PublicKey>,
65{
66    pub(crate) const fn new(sender: Sender<Message<S, V>>) -> Self {
67        Self { sender }
68    }
69
70    /// Subscribe to the probe artifact.
71    ///
72    /// The first live subscriber causes discovery to solicit the configured
73    /// bootstrap committee. Dropping the returned receiver cancels the
74    /// subscription. If discovery has already resolved, late subscribers receive
75    /// the cached artifact immediately.
76    pub fn subscribe(&self) -> oneshot::Receiver<ActorArtifact<S, V>> {
77        let (response, receiver) = oneshot::channel();
78        let _ = self.sender.enqueue(Message::Subscribe { response });
79        receiver
80    }
81
82    /// Attach marshal so the actor can serve peers' boundary requests.
83    ///
84    /// If discovery has pending subscribers, the actor waits until they are
85    /// resolved or dropped before entering serving. A source node can attach
86    /// marshal without ever subscribing, causing it to serve boundaries without
87    /// issuing discovery requests.
88    pub fn attach(&self, marshal: MarshalMailbox<S, V>) {
89        let _ = self.sender.enqueue(Message::Attach { marshal });
90    }
91}