round_based/rounds_router/store.rs
1use crate::Incoming;
2
3/// Stores messages received at particular round
4///
5/// In MPC protocol, party at every round usually needs to receive up to `n` messages. `MessagesStore`
6/// is a container that stores messages, it knows how many messages are expected to be received,
7/// and should implement extra measures against malicious parties (e.g. prohibit message overwrite).
8///
9/// ## Procedure
10/// `MessagesStore` stores received messages. Once enough messages are received, it outputs [`MessagesStore::Output`].
11/// In order to save received messages, [`.add_message(msg)`] is called. Then, [`.wants_more()`] tells whether more
12/// messages are needed to be received. If it returned `false`, then output can be retrieved by calling [`.output()`].
13///
14/// [`.add_message(msg)`]: Self::add_message
15/// [`.wants_more()`]: Self::wants_more
16/// [`.output()`]: Self::output
17///
18/// ## Example
19/// [`RoundInput`](super::simple_store::RoundInput) is an simple messages store. Refer to its docs to see usage examples.
20pub trait MessagesStore: Sized + 'static {
21 /// Message type
22 type Msg;
23 /// Store output (e.g. `Vec<_>` of received messages)
24 type Output;
25 /// Store error
26 type Error: core::error::Error;
27
28 /// Adds received message to the store
29 ///
30 /// Returns error if message cannot be processed. Usually it means that sender behaves maliciously.
31 fn add_message(&mut self, msg: Incoming<Self::Msg>) -> Result<(), Self::Error>;
32 /// Indicates if store expects more messages to receive
33 fn wants_more(&self) -> bool;
34 /// Retrieves store output if enough messages are received
35 ///
36 /// Returns `Err(self)` if more message are needed to be received.
37 ///
38 /// If store indicated that it needs no more messages (ie `store.wants_more() == false`), then
39 /// this function must return `Ok(_)`.
40 fn output(self) -> Result<Self::Output, Self>;
41}
42
43/// Message of MPC protocol
44///
45/// MPC protocols typically consist of several rounds, each round has differently typed message.
46/// `ProtocolMessage` and [`RoundMessage`] traits are used to examine received message: `ProtocolMessage::round`
47/// determines which round message belongs to, and then `RoundMessage` trait can be used to retrieve
48/// actual round-specific message.
49///
50/// You should derive these traits using proc macro (requires `derive` feature):
51/// ```rust
52/// use round_based::ProtocolMessage;
53///
54/// #[derive(ProtocolMessage)]
55/// pub enum Message {
56/// Round1(Msg1),
57/// Round2(Msg2),
58/// // ...
59/// }
60///
61/// pub struct Msg1 { /* ... */ }
62/// pub struct Msg2 { /* ... */ }
63/// ```
64///
65/// This desugars into:
66///
67/// ```rust
68/// use round_based::rounds_router::{ProtocolMessage, RoundMessage};
69///
70/// pub enum Message {
71/// Round1(Msg1),
72/// Round2(Msg2),
73/// // ...
74/// }
75///
76/// pub struct Msg1 { /* ... */ }
77/// pub struct Msg2 { /* ... */ }
78///
79/// impl ProtocolMessage for Message {
80/// fn round(&self) -> u16 {
81/// match self {
82/// Message::Round1(_) => 1,
83/// Message::Round2(_) => 2,
84/// // ...
85/// }
86/// }
87/// }
88/// impl RoundMessage<Msg1> for Message {
89/// const ROUND: u16 = 1;
90/// fn to_protocol_message(round_message: Msg1) -> Self {
91/// Message::Round1(round_message)
92/// }
93/// fn from_protocol_message(protocol_message: Self) -> Result<Msg1, Self> {
94/// match protocol_message {
95/// Message::Round1(msg) => Ok(msg),
96/// msg => Err(msg),
97/// }
98/// }
99/// }
100/// impl RoundMessage<Msg2> for Message {
101/// const ROUND: u16 = 2;
102/// fn to_protocol_message(round_message: Msg2) -> Self {
103/// Message::Round2(round_message)
104/// }
105/// fn from_protocol_message(protocol_message: Self) -> Result<Msg2, Self> {
106/// match protocol_message {
107/// Message::Round2(msg) => Ok(msg),
108/// msg => Err(msg),
109/// }
110/// }
111/// }
112/// ```
113pub trait ProtocolMessage: Sized {
114 /// Number of round this message originates from
115 fn round(&self) -> u16;
116}
117
118/// Round message
119///
120/// See [`ProtocolMessage`] trait documentation.
121pub trait RoundMessage<M>: ProtocolMessage {
122 /// Number of the round this message belongs to
123 const ROUND: u16;
124
125 /// Converts round message into protocol message (never fails)
126 fn to_protocol_message(round_message: M) -> Self;
127 /// Extracts round message from protocol message
128 ///
129 /// Returns `Err(protocol_message)` if `protocol_message.round() != Self::ROUND`, otherwise
130 /// returns `Ok(round_message)`
131 fn from_protocol_message(protocol_message: Self) -> Result<M, Self>;
132}