round_based/
delivery.rs

1/// Incoming message
2#[derive(Debug, Clone, Copy, Eq, PartialEq)]
3pub struct Incoming<M> {
4    /// Index of a message
5    pub id: MsgId,
6    /// Index of a party who sent the message
7    pub sender: PartyIndex,
8    /// Indicates whether it's a broadcast message (meaning that this message is received by all the
9    /// parties), or p2p (private message sent by `sender`)
10    pub msg_type: MessageType,
11    /// Received message
12    pub msg: M,
13}
14
15/// Message type (broadcast or p2p)
16#[derive(Debug, Copy, Clone, Eq, PartialEq)]
17pub enum MessageType {
18    /// Message was broadcasted
19    Broadcast {
20        /// Indicates that message was reliably broadcasted, meaning that it's guaranteed (cryptographically or through
21        /// other trust assumptions) that all honest participants of the protocol received the same message
22        reliable: bool,
23    },
24    /// P2P message
25    P2P,
26}
27
28/// Index of party involved in the protocol
29pub type PartyIndex = u16;
30/// ID of received message
31///
32/// Can be used to retrieve extra information about message from delivery layer when needed.
33/// E.g. if malicious party is detected, we need a proof that received message was sent by this
34/// party, so message id should be used to retrieve signature and original message.
35pub type MsgId = u64;
36
37impl<M> Incoming<M> {
38    /// Maps `Incoming<M>` to `Incoming<T>` by applying a function to the message body
39    pub fn map<T, F>(self, f: F) -> Incoming<T>
40    where
41        F: FnOnce(M) -> T,
42    {
43        Incoming {
44            id: self.id,
45            sender: self.sender,
46            msg_type: self.msg_type,
47            msg: f(self.msg),
48        }
49    }
50
51    /// Maps `Incoming<M>` to `Result<Incoming<T>, E>` by applying a function `fn(M) -> Result<T, E>`
52    /// to the message body
53    pub fn try_map<T, E, F>(self, f: F) -> Result<Incoming<T>, E>
54    where
55        F: FnOnce(M) -> Result<T, E>,
56    {
57        Ok(Incoming {
58            id: self.id,
59            sender: self.sender,
60            msg_type: self.msg_type,
61            msg: f(self.msg)?,
62        })
63    }
64
65    /// Converts `&Incoming<M>` to `Incoming<&M>`
66    pub fn as_ref(&self) -> Incoming<&M> {
67        Incoming {
68            id: self.id,
69            sender: self.sender,
70            msg_type: self.msg_type,
71            msg: &self.msg,
72        }
73    }
74
75    /// Checks whether it's broadcast message (regardless if it's reliable or not)
76    pub fn is_broadcast(&self) -> bool {
77        matches!(self.msg_type, MessageType::Broadcast { .. })
78    }
79
80    /// Checks if message was reliably broadcasted
81    pub fn is_reliably_broadcasted(&self) -> bool {
82        matches!(self.msg_type, MessageType::Broadcast { reliable: true })
83    }
84
85    /// Checks whether it's p2p message
86    pub fn is_p2p(&self) -> bool {
87        matches!(self.msg_type, MessageType::P2P)
88    }
89}
90
91/// Outgoing message
92#[derive(Debug, Clone, Copy, PartialEq, Eq)]
93pub struct Outgoing<M> {
94    /// Message destination: either one party (p2p message) or all parties (broadcast message)
95    pub recipient: MessageDestination,
96    /// Message being sent
97    pub msg: M,
98}
99
100impl<M> Outgoing<M> {
101    /// Constructs an outgoing message addressed to all parties
102    pub fn all_parties(msg: M) -> Self {
103        Self {
104            recipient: MessageDestination::AllParties { reliable: false },
105            msg,
106        }
107    }
108
109    /// Constructs an outgoing message addressed to all parties via reliable broadcast channel
110    pub fn reliable_broadcast(msg: M) -> Self {
111        Self {
112            recipient: MessageDestination::AllParties { reliable: true },
113            msg,
114        }
115    }
116
117    /// Constructs an outgoing message addressed to one party
118    pub fn p2p(recipient: PartyIndex, msg: M) -> Self {
119        Self {
120            recipient: MessageDestination::OneParty(recipient),
121            msg,
122        }
123    }
124
125    /// Maps `Outgoing<M>` to `Outgoing<M2>` by applying a function to the message body
126    pub fn map<M2, F>(self, f: F) -> Outgoing<M2>
127    where
128        F: FnOnce(M) -> M2,
129    {
130        Outgoing {
131            recipient: self.recipient,
132            msg: f(self.msg),
133        }
134    }
135
136    /// Converts `&Outgoing<M>` to `Outgoing<&M>`
137    pub fn as_ref(&self) -> Outgoing<&M> {
138        Outgoing {
139            recipient: self.recipient,
140            msg: &self.msg,
141        }
142    }
143
144    /// Checks whether it's broadcast message
145    pub fn is_broadcast(&self) -> bool {
146        self.recipient.is_broadcast()
147    }
148
149    /// Checks whether it's p2p message
150    pub fn is_p2p(&self) -> bool {
151        self.recipient.is_p2p()
152    }
153}
154
155/// Destination of an outgoing message
156#[derive(Debug, Copy, Clone, Eq, PartialEq)]
157pub enum MessageDestination {
158    /// Broadcast message
159    AllParties {
160        /// Indicates that message needs to be reliably broadcasted, meaning that when recipient receives this message,
161        /// it must be assured (cryptographically or through other trust assumptions) that all honest participants of the
162        /// protocol received the same message
163        reliable: bool,
164    },
165    /// P2P message
166    OneParty(PartyIndex),
167}
168
169impl MessageDestination {
170    /// Returns `true` if it's p2p message
171    pub fn is_p2p(&self) -> bool {
172        matches!(self, MessageDestination::OneParty(_))
173    }
174    /// Returns `true` if it's broadcast message (regardless if it's reliable or not)
175    pub fn is_broadcast(&self) -> bool {
176        matches!(self, MessageDestination::AllParties { .. })
177    }
178    /// Returns `true` if it's reliable broadcast message
179    pub fn is_reliable_broadcast(&self) -> bool {
180        matches!(self, MessageDestination::AllParties { reliable: true })
181    }
182}