Skip to content

Commit

Permalink
Merge pull request #36 from fjarri/session-params
Browse files Browse the repository at this point in the history
Merge `Signer`/`Verifier`/`Signature`/`Digest` into `SessionParameters`
  • Loading branch information
fjarri authored Oct 21, 2024
2 parents eb45e8f + 42e2d8b commit 81ed1d7
Show file tree
Hide file tree
Showing 16 changed files with 430 additions and 403 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [0.0.2] - In development

### Changed

- `Session` is now generic over `SessionParameters` instead of a bunch of separate types. ([#36])
- `MessageBundle` is not generic anymore. ([#36])


### Added

- `SerializableMap` wrapper for `BTreeMap` supporting more formats and providing some safety features. (#[32])


[#32]: https://github.com/entropyxyz/manul/pull/32
[#36]: https://github.com/entropyxyz/manul/pull/36


## [0.0.1] - 2024-10-12
Expand Down
7 changes: 2 additions & 5 deletions example/src/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use core::fmt::Debug;
use manul::protocol::*;
use rand_core::CryptoRngCore;
use serde::{Deserialize, Serialize};
use sha3::Sha3_256;
use tracing::debug;

#[derive(Debug)]
Expand Down Expand Up @@ -73,8 +72,6 @@ impl Protocol for SimpleProtocol {
type ProtocolError = SimpleProtocolError;
type CorrectnessProof = ();

type Digest = Sha3_256;

fn serialize<T: Serialize>(value: T) -> Result<Box<[u8]>, LocalError> {
bincode::serde::encode_to_vec(value, bincode::config::standard())
.map(|vec| vec.into())
Expand Down Expand Up @@ -359,7 +356,7 @@ mod tests {

use manul::{
session::{signature::Keypair, SessionOutcome},
testing::{run_sync, Signature, Signer, Verifier},
testing::{run_sync, Signer, TestingSessionParams, Verifier},
};
use rand_core::OsRng;
use tracing_subscriber::EnvFilter;
Expand Down Expand Up @@ -389,7 +386,7 @@ mod tests {
.with_env_filter(EnvFilter::from_default_env())
.finish();
let reports = tracing::subscriber::with_default(my_subscriber, || {
run_sync::<Round1<Verifier>, Signer, Verifier, Signature>(&mut OsRng, inputs).unwrap()
run_sync::<Round1<Verifier>, TestingSessionParams>(&mut OsRng, inputs).unwrap()
});

for (_id, report) in reports {
Expand Down
8 changes: 4 additions & 4 deletions example/src/simple_malicious.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use manul::{
Artifact, DirectMessage, FinalizeError, FinalizeOutcome, FirstRound, LocalError, Payload, Round, SessionId,
},
session::signature::Keypair,
testing::{round_override, run_sync, RoundOverride, RoundWrapper, Signature, Signer, Verifier},
testing::{round_override, run_sync, RoundOverride, RoundWrapper, Signer, TestingSessionParams, Verifier},
};
use rand_core::{CryptoRngCore, OsRng};
use tracing_subscriber::EnvFilter;
Expand Down Expand Up @@ -172,7 +172,7 @@ fn serialized_garbage() {
.with_env_filter(EnvFilter::from_default_env())
.finish();
let mut reports = tracing::subscriber::with_default(my_subscriber, || {
run_sync::<MaliciousRound1<Verifier>, Signer, Verifier, Signature>(&mut OsRng, run_inputs).unwrap()
run_sync::<MaliciousRound1<Verifier>, TestingSessionParams>(&mut OsRng, run_inputs).unwrap()
});

let v0 = signers[0].verifying_key();
Expand Down Expand Up @@ -218,7 +218,7 @@ fn attributable_failure() {
.with_env_filter(EnvFilter::from_default_env())
.finish();
let mut reports = tracing::subscriber::with_default(my_subscriber, || {
run_sync::<MaliciousRound1<Verifier>, Signer, Verifier, Signature>(&mut OsRng, run_inputs).unwrap()
run_sync::<MaliciousRound1<Verifier>, TestingSessionParams>(&mut OsRng, run_inputs).unwrap()
});

let v0 = signers[0].verifying_key();
Expand Down Expand Up @@ -264,7 +264,7 @@ fn attributable_failure_round2() {
.with_env_filter(EnvFilter::from_default_env())
.finish();
let mut reports = tracing::subscriber::with_default(my_subscriber, || {
run_sync::<MaliciousRound1<Verifier>, Signer, Verifier, Signature>(&mut OsRng, run_inputs).unwrap()
run_sync::<MaliciousRound1<Verifier>, TestingSessionParams>(&mut OsRng, run_inputs).unwrap()
});

let v0 = signers[0].verifying_key();
Expand Down
85 changes: 55 additions & 30 deletions example/tests/async.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ extern crate alloc;
use alloc::collections::{BTreeMap, BTreeSet};

use manul::{
protocol::{Protocol, Round},
protocol::Protocol,
session::{
signature::Keypair, CanFinalize, LocalError, MessageBundle, RoundOutcome, Session, SessionId, SessionReport,
signature::Keypair, CanFinalize, LocalError, MessageBundle, RoundOutcome, Session, SessionId,
SessionParameters, SessionReport,
},
testing::{Signature, Signer, Verifier},
testing::{Signer, TestingSessionParams, Verifier},
};
use manul_example::simple::{Inputs, Round1};
use rand::Rng;
Expand All @@ -19,16 +20,25 @@ use tokio::{
use tracing::debug;
use tracing_subscriber::{util::SubscriberInitExt, EnvFilter};

type MessageOut = (Verifier, Verifier, MessageBundle<Signature>);
type MessageIn = (Verifier, MessageBundle<Signature>);
struct MessageOut<SP: SessionParameters> {
from: SP::Verifier,
to: SP::Verifier,
message: MessageBundle,
}

struct MessageIn<SP: SessionParameters> {
from: SP::Verifier,
message: MessageBundle,
}

async fn run_session<P>(
tx: mpsc::Sender<MessageOut>,
rx: mpsc::Receiver<MessageIn>,
session: Session<P, Signer, Verifier, Signature>,
) -> Result<SessionReport<P, Verifier, Signature>, LocalError>
async fn run_session<P, SP>(
tx: mpsc::Sender<MessageOut<SP>>,
rx: mpsc::Receiver<MessageIn<SP>>,
session: Session<P, SP>,
) -> Result<SessionReport<P, SP>, LocalError>
where
P: Protocol + 'static,
P: 'static + Protocol,
SP: 'static + SessionParameters,
{
let rng = &mut OsRng;

Expand Down Expand Up @@ -58,7 +68,13 @@ where
// to be added to the accumulator.
let (message, artifact) = session.make_message(rng, destination)?;
debug!("{key:?}: sending a message to {destination:?}",);
tx.send((key, *destination, message)).await.unwrap();
tx.send(MessageOut {
from: key.clone(),
to: destination.clone(),
message,
})
.await
.unwrap();

// This will happen in a host task
session.add_artifact(&mut accum, artifact)?;
Expand All @@ -84,14 +100,14 @@ where
}

debug!("{key:?}: waiting for a message");
let (from, message) = rx.recv().await.unwrap();
let incoming = rx.recv().await.unwrap();

// Perform quick checks before proceeding with the verification.
let preprocessed = session.preprocess_message(&mut accum, &from, message)?;
let preprocessed = session.preprocess_message(&mut accum, &incoming.from, incoming.message)?;

if let Some(preprocessed) = preprocessed {
// In production usage, this will happen in a spawned task.
debug!("{key:?}: applying a message from {from:?}");
debug!("{key:?}: applying a message from {:?}", incoming.from);
let processed = session.process_message(rng, preprocessed);

// This will happen in a host task.
Expand All @@ -114,9 +130,14 @@ where
}
}

async fn message_dispatcher(txs: BTreeMap<Verifier, mpsc::Sender<MessageIn>>, rx: mpsc::Receiver<MessageOut>) {
async fn message_dispatcher<SP>(
txs: BTreeMap<SP::Verifier, mpsc::Sender<MessageIn<SP>>>,
rx: mpsc::Receiver<MessageOut<SP>>,
) where
SP: SessionParameters,
{
let mut rx = rx;
let mut messages = Vec::<MessageOut>::new();
let mut messages = Vec::<MessageOut<SP>>::new();
loop {
let msg = match rx.recv().await {
Some(msg) => msg,
Expand All @@ -132,9 +153,15 @@ async fn message_dispatcher(txs: BTreeMap<Verifier, mpsc::Sender<MessageIn>>, rx
// Pull a random message from the list,
// to increase the chances that they are delivered out of order.
let message_idx = rand::thread_rng().gen_range(0..messages.len());
let (id_from, id_to, message) = messages.swap_remove(message_idx);
let outgoing = messages.swap_remove(message_idx);

txs[&id_to].send((id_from, message)).await.unwrap();
txs[&outgoing.to]
.send(MessageIn {
from: outgoing.from,
message: outgoing.message,
})
.await
.unwrap();

// Give up execution so that the tasks could process messages.
sleep(Duration::from_millis(0)).await;
Expand All @@ -146,19 +173,19 @@ async fn message_dispatcher(txs: BTreeMap<Verifier, mpsc::Sender<MessageIn>>, rx
}
}

async fn run_nodes<P>(
sessions: Vec<Session<P, Signer, Verifier, Signature>>,
) -> Vec<SessionReport<P, Verifier, Signature>>
async fn run_nodes<P, SP>(sessions: Vec<Session<P, SP>>) -> Vec<SessionReport<P, SP>>
where
P: Protocol + Send + 'static,
P: 'static + Protocol + Send,
SP: 'static + SessionParameters,
P::Result: Send,
SP::Signer: Send,
{
let num_parties = sessions.len();

let (dispatcher_tx, dispatcher_rx) = mpsc::channel::<MessageOut>(100);
let (dispatcher_tx, dispatcher_rx) = mpsc::channel::<MessageOut<SP>>(100);

let channels = (0..num_parties).map(|_| mpsc::channel::<MessageIn>(100));
let (txs, rxs): (Vec<mpsc::Sender<MessageIn>>, Vec<mpsc::Receiver<MessageIn>>) = channels.unzip();
let channels = (0..num_parties).map(|_| mpsc::channel::<MessageIn<SP>>(100));
let (txs, rxs): (Vec<_>, Vec<_>) = channels.unzip();
let tx_map = sessions
.iter()
.map(|session| session.verifier())
Expand Down Expand Up @@ -204,10 +231,8 @@ async fn async_run() {
let inputs = Inputs {
all_ids: all_ids.clone(),
};
Session::<<Round1<Verifier> as Round<Verifier>>::Protocol, Signer, Verifier, Signature>::new::<
Round1<Verifier>,
>(&mut OsRng, session_id.clone(), signer, inputs)
.unwrap()
Session::<_, TestingSessionParams>::new::<Round1<Verifier>>(&mut OsRng, session_id.clone(), signer, inputs)
.unwrap()
})
.collect::<Vec<_>>();

Expand Down
3 changes: 1 addition & 2 deletions manul/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ categories = ["cryptography", "no-std"]

[dependencies]
serde = { version = "1", default-features = false, features = ["alloc", "serde_derive"] }
serde-encoded-bytes = { version = "0.1", default-features = false, features = ["base64"] }
serde-encoded-bytes = { version = "0.1", default-features = false, features = ["hex", "base64"] }
digest = { version = "0.10", default-features = false }
signature = { version = "2", default-features = false, features = ["digest", "rand_core"] }
rand_core = { version = "0.6.4", default-features = false }
Expand All @@ -22,7 +22,6 @@ rand = { version = "0.8", default-features = false, optional = true }

[dev-dependencies]
impls = "1"
sha3 = "0.10"
rand = { version = "0.8", default-features = false }
bincode = { version = "2.0.0-rc.3", default-features = false, features = ["alloc", "serde"] }
serde_asn1_der = "0.8"
Expand Down
8 changes: 3 additions & 5 deletions manul/benches/empty_rounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use manul::{
LocalError, Payload, Protocol, ProtocolError, ProtocolValidationError, ReceiveError, Round, RoundId,
},
session::{signature::Keypair, SessionId, SessionOutcome},
testing::{run_sync, Hasher, Signature, Signer, Verifier},
testing::{run_sync, Signer, TestingSessionParams, Verifier},
};
use rand_core::{CryptoRngCore, OsRng};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -39,8 +39,6 @@ impl Protocol for EmptyProtocol {
type ProtocolError = EmptyProtocolError;
type CorrectnessProof = ();

type Digest = Hasher;

fn serialize<T: Serialize>(value: T) -> Result<Box<[u8]>, LocalError> {
bincode::serde::encode_to_vec(value, bincode::config::standard())
.map(|vec| vec.into())
Expand Down Expand Up @@ -206,7 +204,7 @@ fn bench_empty_rounds(c: &mut Criterion) {
group.bench_function("25 nodes, 5 rounds, no echo", |b| {
b.iter(|| {
assert!(
run_sync::<EmptyRound<Verifier>, Signer, Verifier, Signature>(&mut OsRng, inputs_no_echo.clone())
run_sync::<EmptyRound<Verifier>, TestingSessionParams>(&mut OsRng, inputs_no_echo.clone())
.unwrap()
.values()
.all(|report| matches!(report.outcome, SessionOutcome::Result(_)))
Expand Down Expand Up @@ -236,7 +234,7 @@ fn bench_empty_rounds(c: &mut Criterion) {
group.bench_function("25 nodes, 5 rounds, echo each round", |b| {
b.iter(|| {
assert!(
run_sync::<EmptyRound<Verifier>, Signer, Verifier, Signature>(&mut OsRng, inputs_echo.clone())
run_sync::<EmptyRound<Verifier>, TestingSessionParams>(&mut OsRng, inputs_echo.clone())
.unwrap()
.values()
.all(|report| matches!(report.outcome, SessionOutcome::Result(_)))
Expand Down
6 changes: 0 additions & 6 deletions manul/src/protocol/round.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use alloc::{
};
use core::{any::Any, fmt::Debug};

use digest::Digest;
use rand_core::CryptoRngCore;
use serde::{Deserialize, Serialize};
use serde_encoded_bytes::{Base64, SliceLike};
Expand Down Expand Up @@ -255,11 +254,6 @@ pub trait Protocol: Debug + Sized {
/// It proves that the node did its job correctly, to be adjudicated by a third party.
type CorrectnessProof: Send + Serialize + for<'de> Deserialize<'de>;

/// The hasher used by this protocol.
///
/// This will be used to generate message signatures.
type Digest: Digest;

/// Serializes the given object into a bytestring.
fn serialize<T: Serialize>(value: T) -> Result<Box<[u8]>, LocalError>;

Expand Down
2 changes: 1 addition & 1 deletion manul/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ mod transcript;

pub use crate::protocol::{LocalError, RemoteError};
pub use message::MessageBundle;
pub use session::{CanFinalize, RoundAccumulator, RoundOutcome, Session, SessionId};
pub use session::{CanFinalize, RoundAccumulator, RoundOutcome, Session, SessionId, SessionParameters};
pub use transcript::{SessionOutcome, SessionReport};

pub(crate) use echo::EchoRoundError;
Expand Down
Loading

0 comments on commit 81ed1d7

Please sign in to comment.