round_based/
lib.rs

1//! ![License: MIT](https://img.shields.io/crates/l/round-based.svg)
2//! [![Docs](https://docs.rs/round-based/badge.svg)](https://docs.rs/round-based)
3//! [![Crates io](https://img.shields.io/crates/v/round-based.svg)](https://crates.io/crates/round-based)
4//! [![Discord](https://img.shields.io/discord/905194001349627914?logo=discord&logoColor=ffffff&label=Discord)](https://discordapp.com/channels/905194001349627914/1285268686147424388)
5//!
6//! An MPC framework that unifies and simplifies the way of developing and working with
7//! multiparty protocols (e.g. threshold signing, random beacons, etc.).
8//!
9//! ## Goals
10//!
11//! * Async friendly \
12//!   Async is the most simple and efficient way of doing networking in Rust
13//! * Simple, configurable \
14//!   Protocol can be carried out in a few lines of code: check out examples.
15//! * Independent of networking layer \
16//!   You may define your own networking layer and you don't need to change anything
17//!   in protocol implementation: it's agnostic of networking by default! So you can
18//!   use central delivery server, distributed redis nodes, postgres database,
19//!   p2p channels, or a public blockchain, or whatever else fits your needs.
20//!
21//! ## Example
22//! MPC protocol execution typically looks like this:
23//!
24//! ```rust
25//! # #[derive(round_based::ProtocolMsg)]
26//! # enum KeygenMsg {}
27//! # struct KeyShare;
28//! # struct Error;
29//! # type Result<T> = std::result::Result<T, Error>;
30//! # async fn doc() -> Result<()> {
31//! // protocol to be executed, takes MPC engine `M`, index of party `i`,
32//! // and number of participants `n`
33//! async fn keygen<M>(mpc: M, i: u16, n: u16) -> Result<KeyShare>
34//! where
35//!     M: round_based::Mpc<Msg = KeygenMsg>
36//! {
37//!     // ...
38//! # unimplemented!()
39//! }
40//! // establishes network connection(s) to other parties so they may communicate
41//! async fn connect() ->
42//!     impl futures::Stream<Item = Result<round_based::Incoming<KeygenMsg>>>
43//!         + futures::Sink<round_based::Outgoing<KeygenMsg>, Error = Error>
44//!         + Unpin
45//! {
46//!     // ...
47//! # round_based::_docs::fake_delivery()
48//! }
49//! let delivery = connect().await;
50//!
51//! // constructs an MPC engine, which, primarily, is used to communicate with
52//! // other parties
53//! let mpc = round_based::mpc::connected(delivery);
54//!
55//! # let (i, n) = (1, 3);
56//! // execute the protocol
57//! let keyshare = keygen(mpc, i, n).await?;
58//! # Ok(()) }
59//! ```
60//!
61//! ## Networking
62//!
63//! In order to run an MPC protocol, transport layer needs to be defined. All you have to do is to
64//! provide a channel which implements a stream and a sink for receiving and sending messages.
65//!
66//! ```rust,no_run
67//! # #[derive(round_based::ProtocolMsg)]
68//! # enum Msg {}
69//! # struct Error;
70//! # type Result<T> = std::result::Result<T, Error>;
71//! # async fn doc() -> Result<()> {
72//! async fn connect() ->
73//!     impl futures::Stream<Item = Result<round_based::Incoming<Msg>>>
74//!         + futures::Sink<round_based::Outgoing<Msg>, Error = Error>
75//!         + Unpin
76//! {
77//!     // ...
78//! # round_based::_docs::fake_delivery()
79//! }
80//!
81//! let delivery = connect().await;
82//! let party = round_based::mpc::connected(delivery);
83//!
84//! // run the protocol
85//! # Ok(()) }
86//! ```
87//!
88//! In order to guarantee the protocol security, it may require:
89//!
90//! * Message Authentication \
91//!   Guarantees message source and integrity. If protocol requires it, make sure
92//!   message was sent by claimed sender and that it hasn't been tampered with. \
93//!   This is typically achieved either through public-key cryptography (e.g.,
94//!   signing with a private key) or through symmetric mechanisms like MACs (e.g.,
95//!   HMAC) or authenticated encryption (AEAD) in point-to-point scenarios.
96//! * Message Privacy \
97//!   When a p2p message is sent, only recipient shall be able to read the content. \
98//!   It can be achieved by using symmetric or asymmetric encryption, encryption methods
99//!   come with their own trade-offs (e.g. simplicity vs forward secrecy).
100//! * Reliable Broadcast \
101//!   When party receives a reliable broadcast message it shall be ensured that
102//!   everybody else received the same message. \
103//!   Our library provides [`echo_broadcast`] support out-of-box that enforces broadcast
104//!   reliability by adding an extra communication round per each round that requires
105//!   reliable broadcast. \
106//!   More advanced techniques implement [Byzantine fault](https://en.wikipedia.org/wiki/Byzantine_fault)
107//!   tolerant broadcast
108//!
109//! ## Developing MPC protocol with `round_based`
110//! We plan to write a book guiding through MPC protocol development process, but
111//! while it's not done, you may refer to [random beacon example](https://github.com/LFDT-Lockness/round-based/blob/m/examples/random-generation-protocol/src/lib.rs)
112//! and our well-documented API.
113//!
114//! ## Features
115//!
116//! * `sim` enables protocol execution simulation, see [`sim`] module
117//!   * `sim-async` enables protocol execution simulation with tokio runtime, see [`sim::async_env`]
118//!     module
119//! * `state-machine` provides ability to carry out the protocol, defined as async function, via Sync
120//!   API, see [`state_machine`] module
121//! * `echo-broadcast` adds [`echo_broadcast`] support
122//! * `derive` is needed to use [`ProtocolMsg`](macro@ProtocolMsg) proc macro
123//! * `runtime-tokio` enables [tokio]-specific implementation of [async runtime](mpc::party::runtime)
124//!
125//! ## Join us in Discord!
126//! Feel free to reach out to us [in Discord](https://discordapp.com/channels/905194001349627914/1285268686147424388)!
127
128#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg, doc_cfg_hide))]
129#![warn(unused_crate_dependencies, missing_docs)]
130#![allow(async_fn_in_trait)]
131#![no_std]
132
133extern crate alloc;
134
135/// Fixes false-positive of `unused_crate_dependencies` lint that only occur in the tests
136#[cfg(test)]
137mod false_positives {
138    use anyhow as _;
139    use futures as _;
140    use trybuild as _;
141
142    use {hex as _, rand as _, rand_dev as _};
143
144    use sha2 as _;
145}
146
147mod delivery;
148#[cfg(feature = "echo-broadcast")]
149pub mod echo_broadcast;
150pub mod mpc;
151pub mod round;
152#[cfg(feature = "state-machine")]
153pub mod state_machine;
154
155#[cfg(feature = "sim")]
156pub mod sim;
157
158pub use self::delivery::*;
159pub use self::mpc::MpcParty;
160#[doc(no_inline)]
161pub use self::mpc::{Mpc, MpcExecution, ProtocolMsg, RoundMsg};
162
163#[doc(hidden)]
164pub mod _docs;
165
166/// Derives [`ProtocolMsg`] and [`RoundMsg`] traits
167///
168/// See [`ProtocolMsg`] docs for more details
169#[cfg(feature = "derive")]
170pub use round_based_derive::ProtocolMsg;