alto_chain/actors/application/
ingress.rs

1use commonware_consensus::{
2    threshold_simplex::{Context, View},
3    Automaton as Au, Committer as Co, Proof, Relay as Re,
4};
5use commonware_cryptography::sha256::Digest;
6use futures::{
7    channel::{mpsc, oneshot},
8    SinkExt,
9};
10
11pub enum Message {
12    Genesis {
13        response: oneshot::Sender<Digest>,
14    },
15    Propose {
16        view: View,
17        parent: (View, Digest),
18        response: oneshot::Sender<Digest>,
19    },
20    Broadcast {
21        payload: Digest,
22    },
23    Verify {
24        view: View,
25        parent: (View, Digest),
26        payload: Digest,
27        response: oneshot::Sender<bool>,
28    },
29    Prepared {
30        proof: Proof,
31        payload: Digest,
32    },
33    Finalized {
34        proof: Proof,
35        payload: Digest,
36    },
37}
38
39/// Mailbox for the application.
40#[derive(Clone)]
41pub struct Mailbox {
42    sender: mpsc::Sender<Message>,
43}
44
45impl Mailbox {
46    pub(super) fn new(sender: mpsc::Sender<Message>) -> Self {
47        Self { sender }
48    }
49}
50
51impl Au for Mailbox {
52    type Digest = Digest;
53    type Context = Context<Self::Digest>;
54
55    async fn genesis(&mut self) -> Self::Digest {
56        let (response, receiver) = oneshot::channel();
57        self.sender
58            .send(Message::Genesis { response })
59            .await
60            .expect("Failed to send genesis");
61        receiver.await.expect("Failed to receive genesis")
62    }
63
64    async fn propose(&mut self, context: Context<Self::Digest>) -> oneshot::Receiver<Self::Digest> {
65        // If we linked payloads to their parent, we would include
66        // the parent in the `Context` in the payload.
67        let (response, receiver) = oneshot::channel();
68        self.sender
69            .send(Message::Propose {
70                view: context.view,
71                parent: context.parent,
72                response,
73            })
74            .await
75            .expect("Failed to send propose");
76        receiver
77    }
78
79    async fn verify(
80        &mut self,
81        context: Context<Self::Digest>,
82        payload: Self::Digest,
83    ) -> oneshot::Receiver<bool> {
84        // If we linked payloads to their parent, we would verify
85        // the parent included in the payload matches the provided `Context`.
86        let (response, receiver) = oneshot::channel();
87        self.sender
88            .send(Message::Verify {
89                view: context.view,
90                parent: context.parent,
91                payload,
92                response,
93            })
94            .await
95            .expect("Failed to send verify");
96        receiver
97    }
98}
99
100impl Re for Mailbox {
101    type Digest = Digest;
102
103    async fn broadcast(&mut self, digest: Self::Digest) {
104        self.sender
105            .send(Message::Broadcast { payload: digest })
106            .await
107            .expect("Failed to send broadcast");
108    }
109}
110
111impl Co for Mailbox {
112    type Digest = Digest;
113
114    async fn prepared(&mut self, proof: Proof, payload: Self::Digest) {
115        self.sender
116            .send(Message::Prepared { proof, payload })
117            .await
118            .expect("Failed to send notarized");
119    }
120
121    async fn finalized(&mut self, proof: Proof, payload: Self::Digest) {
122        self.sender
123            .send(Message::Finalized { proof, payload })
124            .await
125            .expect("Failed to send finalized");
126    }
127}