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

Merge Signer/Verifier/Signature/Digest into SessionParameters #36

Merged
merged 2 commits into from
Oct 21, 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
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
Loading