Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

no_std and wasm support #6

Merged
merged 4 commits into from
May 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 35 additions & 9 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,34 @@ env:
CARGO_NET_GIT_FETCH_WITH_CLI: true

jobs:
build-and-test:
check-no-features:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: "true"
- name: Build no features
run: cargo build -p round-based
- name: Build with tokio
run: cargo build -p round-based --features runtime-tokio
- name: Build with all features
run: cargo build -p round-based --all-features
- name: Run tests
run: cargo test --all-features
- name: cargo check
run: cargo check -p round-based --no-default-features
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: "true"
- name: cargo check
run: cargo check -p round-based
check-all-features:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: "true"
- name: cargo check
run: cargo check -p round-based --all-features

check-fmt:
runs-on: ubuntu-latest
steps:
Expand All @@ -48,3 +61,16 @@ jobs:
cache-on-failure: "true"
- name: Run clippy
run: cargo clippy --all --lib

build-wasm-nostd:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: "true"
- name: Install wasm32-unknown-unknown toolchain
run: rustup target add wasm32-unknown-unknown
- name: Build on wasm32-unknown-unknown (no_std)
run:
(cd wasm/no_std && cargo build --target wasm32-unknown-unknown)
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/target
/wasm/no_std/target
.idea

.cargo/
Expand Down
56 changes: 27 additions & 29 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ members = [
"round-based-derive",
"examples/random-generation-protocol",
]
exclude = [
"wasm/no_std",
]
22 changes: 14 additions & 8 deletions examples/random-generation-protocol/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,24 @@ publish = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
round-based = { path = "../../round-based", features = ["derive"] }
round-based = { path = "../../round-based", default-features = false, features = ["derive"] }

tokio = { version = "1.15", features = ["rt"] }
futures = "0.3"
rand = "0.8"
sha2 = "0.10"
serde = { version = "1", features = ["derive"] }
rand_core = { version = "0.6", default-features = false }
sha2 = { version = "0.10", default-features = false }
serde = { version = "1", default-features = false, features = ["derive"] }

displaydoc = { version = "0.2", default-features = false }
thiserror = { version = "1", optional = true }

# We don't use it directy, but we need to enable `serde` feature
generic-array = { version = "0.14", features = ["serde"] }
thiserror = "1"

[dev-dependencies]
round-based = { path = "../../round-based", features = ["derive", "dev"] }
tokio = { version = "1.15", features = ["macros", "rt"] }
futures = "0.3"
hex = "0.4"
rand_chacha = "0.3"
rand_dev = "0.1"

[features]
std = ["thiserror"]
84 changes: 62 additions & 22 deletions examples/random-generation-protocol/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,53 @@
use futures::SinkExt;
use rand::RngCore;
//! Simple protocol in which parties cooperate to generate randomness

#![no_std]
#![forbid(unused_crate_dependencies, missing_docs)]

#[cfg(feature = "std")]
extern crate std;

extern crate alloc;

mod _unused_deps {
// We don't use it directy, but we need to enable `serde` feature
use generic_array as _;
}

use alloc::{vec, vec::Vec};

use serde::{Deserialize, Serialize};
use sha2::{digest::Output, Digest, Sha256};
use thiserror::Error;

use round_based::rounds_router::{
simple_store::{RoundInput, RoundInputError},
CompleteRoundError, RoundsRouter,
};
use round_based::{Delivery, Mpc, MpcParty, MsgId, Outgoing, PartyIndex, ProtocolMessage};
use round_based::{Delivery, Mpc, MpcParty, MsgId, Outgoing, PartyIndex, ProtocolMessage, SinkExt};

/// Protocol message
#[derive(Clone, Debug, PartialEq, ProtocolMessage, Serialize, Deserialize)]
pub enum Msg {
/// Round 1
CommitMsg(CommitMsg),
/// Round 2
DecommitMsg(DecommitMsg),
}

/// Message from round 1
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct CommitMsg {
/// Party commitment
pub commitment: Output<Sha256>,
}

/// Message from round 2
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct DecommitMsg {
/// Randomness generated by party
pub randomness: [u8; 32],
}

/// Carries out the randomness generation protocol
pub async fn protocol_of_random_generation<R, M>(
party: M,
i: PartyIndex,
Expand All @@ -34,7 +56,7 @@ pub async fn protocol_of_random_generation<R, M>(
) -> Result<[u8; 32], Error<M::ReceiveError, M::SendError>>
where
M: Mpc<ProtocolMessage = Msg>,
R: RngCore,
R: rand_core::RngCore,
{
let MpcParty { delivery, .. } = party.into_party();
let (incoming, mut outgoing) = delivery.split();
Expand Down Expand Up @@ -109,48 +131,66 @@ where
}
}

#[derive(Debug, Error)]
/// Protocol error
#[derive(Debug, displaydoc::Display)]
#[cfg_attr(feature = "std", derive(thiserror::Error))]
pub enum Error<RecvErr, SendErr> {
#[error("send a message at round 1")]
Round1Send(#[source] SendErr),
#[error("receive messages at round 1")]
Round1Receive(#[source] CompleteRoundError<RoundInputError, RecvErr>),
#[error("send a message at round 2")]
Round2Send(#[source] SendErr),
#[error("receive messages at round 2")]
Round2Receive(#[source] CompleteRoundError<RoundInputError, RecvErr>),

#[error("malicious parties: {guilty_parties:?}")]
PartiesOpenedRandomnessDoesntMatchCommitment { guilty_parties: Vec<Blame> },
/// Couldn't send a message in the first round
#[displaydoc("send a message at round 1")]
Round1Send(#[cfg_attr(feature = "std", source)] SendErr),
/// Couldn't receive a message in the first round
#[displaydoc("receive messages at round 1")]
Round1Receive(
#[cfg_attr(feature = "std", source)] CompleteRoundError<RoundInputError, RecvErr>,
),
/// Couldn't send a message in the second round
#[displaydoc("send a message at round 2")]
Round2Send(#[cfg_attr(feature = "std", source)] SendErr),
/// Couldn't receive a message in the second round
#[displaydoc("receive messages at round 2")]
Round2Receive(
#[cfg_attr(feature = "std", source)] CompleteRoundError<RoundInputError, RecvErr>,
),

/// Some of the parties cheated
#[displaydoc("malicious parties: {guilty_parties:?}")]
PartiesOpenedRandomnessDoesntMatchCommitment {
/// List of cheated parties
guilty_parties: Vec<Blame>,
},
}

/// Blames a party in cheating during the protocol
#[derive(Debug)]
pub struct Blame {
/// Index of the cheated party
pub guilty_party: PartyIndex,
/// ID of the message that party sent in the first round
pub commitment_msg: MsgId,
/// ID of the message that party sent in the second round
pub decommitment_msg: MsgId,
}

#[cfg(test)]
mod tests {
use rand::SeedableRng;
use rand_chacha::ChaCha20Rng;
use alloc::vec;

use round_based::simulation::Simulation;

use super::{protocol_of_random_generation, Msg};

#[tokio::test]
async fn main() {
let mut rng = rand_dev::DevRng::new();

let n: u16 = 5;

let mut simulation = Simulation::<Msg>::new();
let mut party_output = vec![];

for i in 0..n {
let party = simulation.add_party();
let rng = ChaCha20Rng::from_entropy();
let output = protocol_of_random_generation(party, i, n, rng);
let output = protocol_of_random_generation(party, i, n, rng.fork());
party_output.push(output);
}

Expand All @@ -161,6 +201,6 @@ mod tests {
assert_eq!(output[0], output[usize::from(i)]);
}

println!("Output randomness: {}", hex::encode(output[0]));
std::println!("Output randomness: {}", hex::encode(output[0]));
}
}
5 changes: 5 additions & 0 deletions round-based/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## v0.3.0
* Add no_std and wasm support [#6]

[#6]: https://github.com/dfns/round-based/pull/6

## v0.2.2

* fix: correct handling of stores that need no messages in RoundsRouter [#4]
Expand Down
Loading
Loading