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}