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