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 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
//! Party of MPC protocol
//!
//! [`MpcParty`] is party of MPC protocol, connected to network, ready to start carrying out the protocol.
//!
//! ```rust
//! use round_based::{Mpc, MpcParty, Delivery, PartyIndex};
//!
//! # struct KeygenMsg;
//! # struct KeyShare;
//! # struct Error;
//! # type Result<T> = std::result::Result<T, Error>;
//! # async fn doc() -> Result<()> {
//! async fn keygen<M>(party: M, i: PartyIndex, n: u16) -> Result<KeyShare>
//! where
//! M: Mpc<ProtocolMessage = KeygenMsg>
//! {
//! // ...
//! # unimplemented!()
//! }
//! async fn connect() -> impl Delivery<KeygenMsg> {
//! // ...
//! # round_based::_docs::fake_delivery()
//! }
//!
//! let delivery = connect().await;
//! let party = MpcParty::connected(delivery);
//!
//! # let (i, n) = (1, 3);
//! let keyshare = keygen(party, i, n).await?;
//! # Ok(()) }
//! ```
use phantom_type::PhantomType;
use crate::delivery::Delivery;
use crate::runtime::{self, AsyncRuntime};
use crate::StdError;
/// Party of MPC protocol (trait)
///
/// [`MpcParty`] is the only struct that implement this trait. Motivation to have this trait is to fewer amount of
/// generic bounds that are needed to be specified.
///
/// Typical usage of this trait when implementing MPC protocol:
///
/// ```rust
/// use round_based::{Mpc, MpcParty, PartyIndex};
///
/// # struct Msg;
/// async fn keygen<M>(party: M, i: PartyIndex, n: u16)
/// where
/// M: Mpc<ProtocolMessage = Msg>
/// {
/// let MpcParty{ delivery, .. } = party.into_party();
/// // ...
/// }
/// ```
///
/// If we didn't have this trait, generics would be less readable:
/// ```rust
/// use round_based::{MpcParty, Delivery, runtime::AsyncRuntime, PartyIndex};
///
/// # struct Msg;
/// async fn keygen<D, R>(party: MpcParty<Msg, D, R>, i: PartyIndex, n: u16)
/// where
/// D: Delivery<Msg>,
/// R: AsyncRuntime
/// {
/// // ...
/// }
/// ```
pub trait Mpc: internal::Sealed {
/// MPC message
type ProtocolMessage;
/// Transport layer implementation
type Delivery: Delivery<
Self::ProtocolMessage,
SendError = Self::SendError,
ReceiveError = Self::ReceiveError,
>;
/// Async runtime
type Runtime: AsyncRuntime;
/// Sending message error
type SendError: StdError + Send + Sync + 'static;
/// Receiving message error
type ReceiveError: StdError + Send + Sync + 'static;
/// Converts into [`MpcParty`]
fn into_party(self) -> MpcParty<Self::ProtocolMessage, Self::Delivery, Self::Runtime>;
}
mod internal {
pub trait Sealed {}
}
/// Party of MPC protocol
#[non_exhaustive]
pub struct MpcParty<M, D, R = runtime::DefaultRuntime> {
/// Defines transport layer
pub delivery: D,
/// Defines how computationally heavy tasks should be handled
pub runtime: R,
_msg: PhantomType<M>,
}
impl<M, D> MpcParty<M, D>
where
D: Delivery<M>,
{
/// Party connected to the network
///
/// Takes the delivery object determining how to deliver/receive other parties' messages
pub fn connected(delivery: D) -> Self {
Self {
delivery,
runtime: Default::default(),
_msg: PhantomType::new(),
}
}
}
impl<M, D, X> MpcParty<M, D, X>
where
D: Delivery<M>,
{
/// Specifies a [async runtime](runtime)
pub fn set_runtime<R>(self, runtime: R) -> MpcParty<M, D, R>
where
R: AsyncRuntime,
{
MpcParty {
delivery: self.delivery,
runtime,
_msg: self._msg,
}
}
}
impl<M, D, B> internal::Sealed for MpcParty<M, D, B> {}
impl<M, D, R> Mpc for MpcParty<M, D, R>
where
D: Delivery<M>,
D::SendError: StdError + Send + Sync + 'static,
D::ReceiveError: StdError + Send + Sync + 'static,
R: AsyncRuntime,
{
type ProtocolMessage = M;
type Delivery = D;
type Runtime = R;
type SendError = D::SendError;
type ReceiveError = D::ReceiveError;
fn into_party(self) -> MpcParty<Self::ProtocolMessage, Self::Delivery, Self::Runtime> {
self
}
}