From 19793d29b64b7d64db423532ff452f3972b01a86 Mon Sep 17 00:00:00 2001 From: Bogdan Opanchuk Date: Sun, 20 Oct 2024 18:17:16 -0700 Subject: [PATCH 1/2] Merge Signer/Verifier/Signature/Digest into SessionParameters --- CHANGELOG.md | 6 + example/src/simple.rs | 7 +- example/src/simple_malicious.rs | 8 +- example/tests/async.rs | 86 +++++++++----- manul/Cargo.toml | 1 - manul/benches/empty_rounds.rs | 8 +- manul/src/protocol/round.rs | 6 - manul/src/session.rs | 2 +- manul/src/session/echo.rs | 74 +++++------- manul/src/session/evidence.rs | 159 +++++++++++-------------- manul/src/session/message.rs | 91 ++++++++------ manul/src/session/session.rs | 204 +++++++++++++++++--------------- manul/src/session/transcript.rs | 56 ++++----- manul/src/testing.rs | 2 +- manul/src/testing/identity.rs | 13 ++ manul/src/testing/run_sync.rs | 69 ++++------- 16 files changed, 400 insertions(+), 392 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea08318..199c2d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,12 +5,18 @@ 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]) + + ### 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 diff --git a/example/src/simple.rs b/example/src/simple.rs index cffb808..51f1cfc 100644 --- a/example/src/simple.rs +++ b/example/src/simple.rs @@ -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)] @@ -73,8 +72,6 @@ impl Protocol for SimpleProtocol { type ProtocolError = SimpleProtocolError; type CorrectnessProof = (); - type Digest = Sha3_256; - fn serialize(value: T) -> Result, LocalError> { bincode::serde::encode_to_vec(value, bincode::config::standard()) .map(|vec| vec.into()) @@ -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; @@ -389,7 +386,7 @@ mod tests { .with_env_filter(EnvFilter::from_default_env()) .finish(); let reports = tracing::subscriber::with_default(my_subscriber, || { - run_sync::, Signer, Verifier, Signature>(&mut OsRng, inputs).unwrap() + run_sync::, TestingSessionParams>(&mut OsRng, inputs).unwrap() }); for (_id, report) in reports { diff --git a/example/src/simple_malicious.rs b/example/src/simple_malicious.rs index 46d38b5..e7e73da 100644 --- a/example/src/simple_malicious.rs +++ b/example/src/simple_malicious.rs @@ -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; @@ -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::, Signer, Verifier, Signature>(&mut OsRng, run_inputs).unwrap() + run_sync::, TestingSessionParams>(&mut OsRng, run_inputs).unwrap() }); let v0 = signers[0].verifying_key(); @@ -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::, Signer, Verifier, Signature>(&mut OsRng, run_inputs).unwrap() + run_sync::, TestingSessionParams>(&mut OsRng, run_inputs).unwrap() }); let v0 = signers[0].verifying_key(); @@ -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::, Signer, Verifier, Signature>(&mut OsRng, run_inputs).unwrap() + run_sync::, TestingSessionParams>(&mut OsRng, run_inputs).unwrap() }); let v0 = signers[0].verifying_key(); diff --git a/example/tests/async.rs b/example/tests/async.rs index 7b7951c..bf281ba 100644 --- a/example/tests/async.rs +++ b/example/tests/async.rs @@ -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; @@ -19,16 +20,25 @@ use tokio::{ use tracing::debug; use tracing_subscriber::{util::SubscriberInitExt, EnvFilter}; -type MessageOut = (Verifier, Verifier, MessageBundle); -type MessageIn = (Verifier, MessageBundle); +struct MessageOut { + from: SP::Verifier, + to: SP::Verifier, + message: MessageBundle, +} + +struct MessageIn { + from: SP::Verifier, + message: MessageBundle, +} -async fn run_session

( - tx: mpsc::Sender, - rx: mpsc::Receiver, - session: Session, -) -> Result, LocalError> +async fn run_session( + tx: mpsc::Sender>, + rx: mpsc::Receiver>, + session: Session, +) -> Result, LocalError> where - P: Protocol + 'static, + P: 'static + Protocol, + SP: 'static + SessionParameters, { let rng = &mut OsRng; @@ -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)?; @@ -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. @@ -114,9 +130,14 @@ where } } -async fn message_dispatcher(txs: BTreeMap>, rx: mpsc::Receiver) { +async fn message_dispatcher( + txs: BTreeMap>>, + rx: mpsc::Receiver>, +) where + SP: SessionParameters, +{ let mut rx = rx; - let mut messages = Vec::::new(); + let mut messages = Vec::>::new(); loop { let msg = match rx.recv().await { Some(msg) => msg, @@ -132,9 +153,15 @@ async fn message_dispatcher(txs: BTreeMap>, 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; @@ -146,19 +173,20 @@ async fn message_dispatcher(txs: BTreeMap>, rx } } -async fn run_nodes

( - sessions: Vec>, -) -> Vec> +async fn run_nodes(sessions: Vec>) -> Vec> 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::(100); + let (dispatcher_tx, dispatcher_rx) = mpsc::channel::>(100); - let channels = (0..num_parties).map(|_| mpsc::channel::(100)); - let (txs, rxs): (Vec>, Vec>) = channels.unzip(); + let channels = (0..num_parties).map(|_| mpsc::channel::>(100)); + #[allow(clippy::type_complexity)] + let (txs, rxs): (Vec>>, Vec>>) = channels.unzip(); let tx_map = sessions .iter() .map(|session| session.verifier()) @@ -204,10 +232,8 @@ async fn async_run() { let inputs = Inputs { all_ids: all_ids.clone(), }; - Session::< as Round>::Protocol, Signer, Verifier, Signature>::new::< - Round1, - >(&mut OsRng, session_id.clone(), signer, inputs) - .unwrap() + Session::<_, TestingSessionParams>::new::>(&mut OsRng, session_id.clone(), signer, inputs) + .unwrap() }) .collect::>(); diff --git a/manul/Cargo.toml b/manul/Cargo.toml index fbe7eb9..3ef62d9 100644 --- a/manul/Cargo.toml +++ b/manul/Cargo.toml @@ -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" diff --git a/manul/benches/empty_rounds.rs b/manul/benches/empty_rounds.rs index 6c43882..f0612b2 100644 --- a/manul/benches/empty_rounds.rs +++ b/manul/benches/empty_rounds.rs @@ -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}; @@ -39,8 +39,6 @@ impl Protocol for EmptyProtocol { type ProtocolError = EmptyProtocolError; type CorrectnessProof = (); - type Digest = Hasher; - fn serialize(value: T) -> Result, LocalError> { bincode::serde::encode_to_vec(value, bincode::config::standard()) .map(|vec| vec.into()) @@ -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::, Signer, Verifier, Signature>(&mut OsRng, inputs_no_echo.clone()) + run_sync::, TestingSessionParams>(&mut OsRng, inputs_no_echo.clone()) .unwrap() .values() .all(|report| matches!(report.outcome, SessionOutcome::Result(_))) @@ -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::, Signer, Verifier, Signature>(&mut OsRng, inputs_echo.clone()) + run_sync::, TestingSessionParams>(&mut OsRng, inputs_echo.clone()) .unwrap() .values() .all(|report| matches!(report.outcome, SessionOutcome::Result(_))) diff --git a/manul/src/protocol/round.rs b/manul/src/protocol/round.rs index ccab7a1..0103b4d 100644 --- a/manul/src/protocol/round.rs +++ b/manul/src/protocol/round.rs @@ -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}; @@ -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(value: T) -> Result, LocalError>; diff --git a/manul/src/session.rs b/manul/src/session.rs index d03cb5d..44f4cf8 100644 --- a/manul/src/session.rs +++ b/manul/src/session.rs @@ -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; diff --git a/manul/src/session/echo.rs b/manul/src/session/echo.rs index 7b5c8dc..9922f5e 100644 --- a/manul/src/session/echo.rs +++ b/manul/src/session/echo.rs @@ -8,11 +8,11 @@ use core::fmt::Debug; use rand_core::CryptoRngCore; use serde::{Deserialize, Serialize}; -use signature::DigestVerifier; use tracing::debug; use super::{ message::{MessageVerificationError, SignedMessage}, + session::SessionParameters, LocalError, }; use crate::{ @@ -30,32 +30,32 @@ pub(crate) enum EchoRoundError { } #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct EchoRoundMessage { - pub(crate) echo_messages: SerializableMap>, +pub struct EchoRoundMessage { + pub(crate) echo_messages: SerializableMap>, } -pub struct EchoRound { - verifier: Id, - echo_messages: BTreeMap>, - destinations: BTreeSet, - expected_echos: BTreeSet, - main_round: Box>, - payloads: BTreeMap, - artifacts: BTreeMap, +pub struct EchoRound { + verifier: SP::Verifier, + echo_messages: BTreeMap>, + destinations: BTreeSet, + expected_echos: BTreeSet, + main_round: Box>, + payloads: BTreeMap, + artifacts: BTreeMap, } -impl EchoRound +impl EchoRound where P: Protocol, - Id: Debug + Clone + Ord, + SP: SessionParameters, { pub fn new( - verifier: Id, - my_echo_message: SignedMessage, - echo_messages: BTreeMap>, - main_round: Box>, - payloads: BTreeMap, - artifacts: BTreeMap, + verifier: SP::Verifier, + my_echo_message: SignedMessage, + echo_messages: BTreeMap>, + main_round: Box>, + payloads: BTreeMap, + artifacts: BTreeMap, ) -> Self { let destinations = echo_messages.keys().cloned().collect::>(); @@ -79,20 +79,10 @@ where } } -impl Round for EchoRound +impl Round for EchoRound where P: 'static + Protocol, - Id: 'static - + Debug - + Clone - + Ord - + Serialize - + for<'de> Deserialize<'de> - + Eq - + Send - + Sync - + DigestVerifier, - S: 'static + Debug + Clone + Serialize + for<'de> Deserialize<'de> + Eq + Send + Sync, + SP: 'static + SessionParameters, { type Protocol = P; @@ -104,14 +94,14 @@ where self.main_round.possible_next_rounds() } - fn message_destinations(&self) -> &BTreeSet { + fn message_destinations(&self) -> &BTreeSet { &self.destinations } fn make_direct_message( &self, _rng: &mut impl CryptoRngCore, - destination: &Id, + destination: &SP::Verifier, ) -> Result<(DirectMessage, Artifact), LocalError> { debug!("{:?}: making echo round message for {:?}", self.verifier, destination); @@ -124,27 +114,27 @@ where ))); } - let message = EchoRoundMessage { + let message = EchoRoundMessage:: { echo_messages: echo_messages.into(), }; let dm = DirectMessage::new::(&message)?; Ok((dm, Artifact::empty())) } - fn expecting_messages_from(&self) -> &BTreeSet { + fn expecting_messages_from(&self) -> &BTreeSet { &self.destinations } fn receive_message( &self, _rng: &mut impl CryptoRngCore, - from: &Id, + from: &SP::Verifier, _echo_broadcast: Option, direct_message: DirectMessage, - ) -> Result> { + ) -> Result> { debug!("{:?}: received an echo message from {:?}", self.verifier, from); - let message = direct_message.deserialize::>()?; + let message = direct_message.deserialize::>()?; // Check that the received message contains entries from `destinations` sans `from` // It is an unprovable fault. @@ -191,7 +181,7 @@ where continue; } - let verified_echo = match echo.clone().verify::(sender) { + let verified_echo = match echo.clone().verify::(sender) { Ok(echo) => echo, Err(MessageVerificationError::Local(error)) => return Err(error.into()), // This means `from` sent us an incorrectly signed message. @@ -220,9 +210,9 @@ where fn finalize( self, rng: &mut impl CryptoRngCore, - _payloads: BTreeMap, - _artifacts: BTreeMap, - ) -> Result, FinalizeError> { + _payloads: BTreeMap, + _artifacts: BTreeMap, + ) -> Result, FinalizeError> { self.main_round.finalize(rng, self.payloads, self.artifacts) } } diff --git a/manul/src/session/evidence.rs b/manul/src/session/evidence.rs index 786cdb0..2b12510 100644 --- a/manul/src/session/evidence.rs +++ b/manul/src/session/evidence.rs @@ -2,11 +2,11 @@ use alloc::{collections::BTreeMap, format, string::String, vec::Vec}; use core::fmt::Debug; use serde::{Deserialize, Serialize}; -use signature::DigestVerifier; use super::{ echo::{EchoRoundError, EchoRoundMessage}, message::{MessageVerificationError, SignedMessage}, + session::SessionParameters, transcript::Transcript, LocalError, }; @@ -58,24 +58,23 @@ impl From for EvidenceError { } #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Evidence { - guilty_party: Verifier, +pub struct Evidence { + guilty_party: SP::Verifier, description: String, - evidence: EvidenceEnum, + evidence: EvidenceEnum, } -impl Evidence +impl Evidence where P: Protocol, - Verifier: Debug + Clone + Ord + for<'de> Deserialize<'de> + DigestVerifier, - S: Debug + Clone + for<'de> Deserialize<'de>, + SP: SessionParameters, { pub(crate) fn new_protocol_error( - verifier: &Verifier, - echo_broadcast: Option>, - direct_message: SignedMessage, + verifier: &SP::Verifier, + echo_broadcast: Option>, + direct_message: SignedMessage, error: P::ProtocolError, - transcript: &Transcript, + transcript: &Transcript, ) -> Result { let echo_broadcasts = error .required_echo_broadcasts() @@ -124,10 +123,10 @@ where } pub(crate) fn new_echo_round_error( - verifier: &Verifier, - direct_message: SignedMessage, - error: EchoRoundError, - transcript: &Transcript, + verifier: &SP::Verifier, + direct_message: SignedMessage, + error: EchoRoundError, + transcript: &Transcript, ) -> Result { let description = format!("{:?}", error); match error { @@ -149,7 +148,7 @@ where let deserialized = direct_message .payload() - .deserialize::>() + .deserialize::>() .map_err(|error| { LocalError::new(format!("Failed to deserialize the given direct message: {:?}", error)) })?; @@ -173,8 +172,8 @@ where } pub(crate) fn new_invalid_direct_message( - verifier: &Verifier, - direct_message: SignedMessage, + verifier: &SP::Verifier, + direct_message: SignedMessage, error: DirectMessageError, ) -> Self { Self { @@ -188,8 +187,8 @@ where } pub(crate) fn new_invalid_echo_broadcast( - verifier: &Verifier, - echo_broadcast: SignedMessage, + verifier: &SP::Verifier, + echo_broadcast: SignedMessage, error: EchoBroadcastError, ) -> Self { Self { @@ -202,7 +201,7 @@ where } } - pub fn guilty_party(&self) -> &Verifier { + pub fn guilty_party(&self) -> &SP::Verifier { &self.guilty_party } @@ -210,7 +209,7 @@ where &self.description } - pub fn verify(&self, party: &Verifier) -> Result<(), EvidenceError> { + pub fn verify(&self, party: &SP::Verifier) -> Result<(), EvidenceError> { match &self.evidence { EvidenceEnum::Protocol(evidence) => evidence.verify(party), EvidenceEnum::InvalidDirectMessage(evidence) => evidence.verify(party), @@ -222,30 +221,29 @@ where } #[derive(Debug, Clone, Serialize, Deserialize)] -enum EvidenceEnum { - Protocol(ProtocolEvidence), - InvalidDirectMessage(InvalidDirectMessageEvidence), - InvalidEchoBroadcast(InvalidEchoBroadcastEvidence), - InvalidEchoPack(InvalidEchoPackEvidence), - MismatchedBroadcasts(MismatchedBroadcastsEvidence), +enum EvidenceEnum { + Protocol(ProtocolEvidence), + InvalidDirectMessage(InvalidDirectMessageEvidence), + InvalidEchoBroadcast(InvalidEchoBroadcastEvidence), + InvalidEchoPack(InvalidEchoPackEvidence), + MismatchedBroadcasts(MismatchedBroadcastsEvidence), } #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct InvalidEchoPackEvidence { - direct_message: SignedMessage, - invalid_echo_sender: Verifier, +pub struct InvalidEchoPackEvidence { + direct_message: SignedMessage, + invalid_echo_sender: SP::Verifier, phantom: core::marker::PhantomData

, } -impl InvalidEchoPackEvidence +impl InvalidEchoPackEvidence where P: Protocol, - S: Clone + for<'de> Deserialize<'de>, - Verifier: Debug + Clone + Ord + DigestVerifier + for<'de> Deserialize<'de>, + SP: SessionParameters, { - fn verify(&self, verifier: &Verifier) -> Result<(), EvidenceError> { - let verified = self.direct_message.clone().verify::(verifier)?; - let deserialized = verified.payload().deserialize::>()?; + fn verify(&self, verifier: &SP::Verifier) -> Result<(), EvidenceError> { + let verified = self.direct_message.clone().verify::(verifier)?; + let deserialized = verified.payload().deserialize::>()?; let invalid_echo = deserialized .echo_messages .get(&self.invalid_echo_sender) @@ -256,7 +254,7 @@ where )) })?; - let verified_echo = match invalid_echo.clone().verify::(&self.invalid_echo_sender) { + let verified_echo = match invalid_echo.clone().verify::(&self.invalid_echo_sender) { Ok(echo) => echo, Err(MessageVerificationError::Local(error)) => return Err(EvidenceError::Local(error)), // The message was indeed incorrectly signed - fault proven @@ -276,23 +274,20 @@ where } #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct MismatchedBroadcastsEvidence { - we_received: SignedMessage, - echoed_to_us: SignedMessage, +pub struct MismatchedBroadcastsEvidence { + we_received: SignedMessage, + echoed_to_us: SignedMessage, phantom: core::marker::PhantomData

, } -impl MismatchedBroadcastsEvidence +impl MismatchedBroadcastsEvidence where P: Protocol, - S: Clone, + SP: SessionParameters, { - fn verify(&self, verifier: &Verifier) -> Result<(), EvidenceError> - where - Verifier: Debug + Clone + DigestVerifier, - { - let we_received = self.we_received.clone().verify::(verifier)?; - let echoed_to_us = self.echoed_to_us.clone().verify::(verifier)?; + fn verify(&self, verifier: &SP::Verifier) -> Result<(), EvidenceError> { + let we_received = self.we_received.clone().verify::(verifier)?; + let echoed_to_us = self.echoed_to_us.clone().verify::(verifier)?; if we_received.metadata() == echoed_to_us.metadata() && we_received.payload() != echoed_to_us.payload() { return Ok(()); @@ -305,21 +300,18 @@ where } #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct InvalidDirectMessageEvidence { - direct_message: SignedMessage, +pub struct InvalidDirectMessageEvidence { + direct_message: SignedMessage, phantom: core::marker::PhantomData

, } -impl InvalidDirectMessageEvidence +impl InvalidDirectMessageEvidence where P: Protocol, - S: Clone, + SP: SessionParameters, { - fn verify(&self, verifier: &Verifier) -> Result<(), EvidenceError> - where - Verifier: Debug + Clone + DigestVerifier, - { - let verified_direct_message = self.direct_message.clone().verify::(verifier)?; + fn verify(&self, verifier: &SP::Verifier) -> Result<(), EvidenceError> { + let verified_direct_message = self.direct_message.clone().verify::(verifier)?; Ok(P::verify_direct_message_is_invalid( self.direct_message.metadata().round_id(), verified_direct_message.payload(), @@ -328,21 +320,18 @@ where } #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct InvalidEchoBroadcastEvidence { - echo_broadcast: SignedMessage, +pub struct InvalidEchoBroadcastEvidence { + echo_broadcast: SignedMessage, phantom: core::marker::PhantomData

, } -impl InvalidEchoBroadcastEvidence +impl InvalidEchoBroadcastEvidence where P: Protocol, - S: Clone, + SP: SessionParameters, { - fn verify(&self, verifier: &Verifier) -> Result<(), EvidenceError> - where - Verifier: Debug + Clone + DigestVerifier, - { - let verified_echo_broadcast = self.echo_broadcast.clone().verify::(verifier)?; + fn verify(&self, verifier: &SP::Verifier) -> Result<(), EvidenceError> { + let verified_echo_broadcast = self.echo_broadcast.clone().verify::(verifier)?; Ok(P::verify_echo_broadcast_is_invalid( self.echo_broadcast.metadata().round_id(), verified_echo_broadcast.payload(), @@ -351,31 +340,28 @@ where } #[derive(Debug, Clone, Serialize, Deserialize)] -struct ProtocolEvidence { +struct ProtocolEvidence { error: P::ProtocolError, - direct_message: SignedMessage, - echo_broadcast: Option>, - direct_messages: SerializableMap>, - echo_broadcasts: SerializableMap>, - combined_echos: SerializableMap>, + direct_message: SignedMessage, + echo_broadcast: Option>, + direct_messages: SerializableMap>, + echo_broadcasts: SerializableMap>, + combined_echos: SerializableMap>, } -impl ProtocolEvidence +impl ProtocolEvidence where P: Protocol, - S: Clone + for<'de> Deserialize<'de>, + SP: SessionParameters, { - fn verify(&self, verifier: &Verifier) -> Result<(), EvidenceError> - where - Verifier: Debug + Clone + Ord + for<'de> Deserialize<'de> + DigestVerifier, - { + fn verify(&self, verifier: &SP::Verifier) -> Result<(), EvidenceError> { let session_id = self.direct_message.metadata().session_id(); - let verified_direct_message = self.direct_message.clone().verify::(verifier)?.payload().clone(); + let verified_direct_message = self.direct_message.clone().verify::(verifier)?.payload().clone(); let mut verified_direct_messages = BTreeMap::new(); for (round_id, direct_message) in self.direct_messages.iter() { - let verified_direct_message = direct_message.clone().verify::(verifier)?; + let verified_direct_message = direct_message.clone().verify::(verifier)?; let metadata = verified_direct_message.metadata(); if metadata.session_id() != session_id || metadata.round_id() != *round_id { return Err(EvidenceError::InvalidEvidence( @@ -392,14 +378,14 @@ where "Invalid attached message metadata".into(), )); } - Some(echo.clone().verify::(verifier)?.payload().clone()) + Some(echo.clone().verify::(verifier)?.payload().clone()) } else { None }; let mut verified_echo_broadcasts = BTreeMap::new(); for (round_id, echo_broadcast) in self.echo_broadcasts.iter() { - let verified_echo_broadcast = echo_broadcast.clone().verify::(verifier)?; + let verified_echo_broadcast = echo_broadcast.clone().verify::(verifier)?; let metadata = verified_echo_broadcast.metadata(); if metadata.session_id() != session_id || metadata.round_id() != *round_id { return Err(EvidenceError::InvalidEvidence( @@ -411,19 +397,18 @@ where let mut combined_echos = BTreeMap::new(); for (round_id, combined_echo) in self.combined_echos.iter() { - let verified_combined_echo = combined_echo.clone().verify::(verifier)?; + let verified_combined_echo = combined_echo.clone().verify::(verifier)?; let metadata = verified_combined_echo.metadata(); if metadata.session_id() != session_id || metadata.round_id().non_echo() != *round_id { return Err(EvidenceError::InvalidEvidence( "Invalid attached message metadata".into(), )); } - let echo_set = - DirectMessage::deserialize::>(verified_combined_echo.payload())?; + let echo_set = DirectMessage::deserialize::>(verified_combined_echo.payload())?; let mut verified_echo_set = Vec::new(); for (other_verifier, echo_broadcast) in echo_set.echo_messages.iter() { - let verified_echo_broadcast = echo_broadcast.clone().verify::(other_verifier)?; + let verified_echo_broadcast = echo_broadcast.clone().verify::(other_verifier)?; let metadata = verified_echo_broadcast.metadata(); if metadata.session_id() != session_id || metadata.round_id() != *round_id { return Err(EvidenceError::InvalidEvidence( diff --git a/manul/src/session/message.rs b/manul/src/session/message.rs index 2703fe3..7aede9a 100644 --- a/manul/src/session/message.rs +++ b/manul/src/session/message.rs @@ -5,7 +5,10 @@ use rand_core::CryptoRngCore; use serde::{Deserialize, Serialize}; use signature::{DigestVerifier, RandomizedDigestSigner}; -use super::{session::SessionId, LocalError}; +use super::{ + session::{SessionId, SessionParameters}, + LocalError, +}; use crate::protocol::{DirectMessage, EchoBroadcast, Protocol, RoundId}; #[derive(Debug, Clone)] @@ -53,20 +56,21 @@ impl SignedMessage where M: Serialize, { - pub fn new( + pub fn new( rng: &mut impl CryptoRngCore, - signer: &Signer, + signer: &SP::Signer, session_id: &SessionId, round_id: RoundId, message: M, ) -> Result where - Signer: RandomizedDigestSigner, + P: Protocol, + SP: SessionParameters, { let metadata = MessageMetadata::new(session_id, round_id); let message_with_metadata = MessageWithMetadata { metadata, message }; let message_bytes = P::serialize(&message_with_metadata)?; - let digest = P::Digest::new_with_prefix(b"SignedMessage").chain_update(message_bytes); + let digest = SP::Digest::new_with_prefix(b"SignedMessage").chain_update(message_bytes); let signature = signer .try_sign_digest_with_rng(rng, digest) .map_err(|err| LocalError::new(format!("Failed to sign: {:?}", err)))?; @@ -84,15 +88,16 @@ where &self.message_with_metadata.message } - pub(crate) fn verify( + pub(crate) fn verify( self, - verifier: &Verifier, + verifier: &SP::Verifier, ) -> Result, MessageVerificationError> where - Verifier: Clone + DigestVerifier, + P: Protocol, + SP: SessionParameters, { let message_bytes = P::serialize(&self.message_with_metadata).map_err(MessageVerificationError::Local)?; - let digest = P::Digest::new_with_prefix(b"SignedMessage").chain_update(message_bytes); + let digest = SP::Digest::new_with_prefix(b"SignedMessage").chain_update(message_bytes); if verifier.verify_digest(digest, &self.signature).is_ok() { Ok(VerifiedMessage { signature: self.signature, @@ -131,35 +136,34 @@ impl VerifiedMessage { /// /// Note that this is already signed. #[derive(Clone, Debug)] -pub struct MessageBundle { - direct_message: SignedMessage, - echo_broadcast: Option>, +pub struct MessageBundle { + direct_message: SignedMessage, + echo_broadcast: Option>, } -impl MessageBundle +impl MessageBundle where - S: PartialEq + Clone, + SP: SessionParameters, { - pub(crate) fn new( + pub(crate) fn new

( rng: &mut impl CryptoRngCore, - signer: &Signer, + signer: &SP::Signer, session_id: &SessionId, round_id: RoundId, direct_message: DirectMessage, - echo_broadcast: Option>, + echo_broadcast: Option>, ) -> Result where P: Protocol, - Signer: RandomizedDigestSigner, { - let direct_message = SignedMessage::new::(rng, signer, session_id, round_id, direct_message)?; + let direct_message = SignedMessage::new::(rng, signer, session_id, round_id, direct_message)?; Ok(Self { direct_message, echo_broadcast, }) } - pub(crate) fn unify_metadata(self) -> Option> { + pub(crate) fn unify_metadata(self) -> Option> { let metadata = self.direct_message.message_with_metadata.metadata.clone(); if !self .echo_broadcast @@ -179,28 +183,28 @@ where } #[derive(Clone, Debug)] -pub(crate) struct CheckedMessageBundle { +pub(crate) struct CheckedMessageBundle { metadata: MessageMetadata, - direct_message: SignedMessage, - echo_broadcast: Option>, + direct_message: SignedMessage, + echo_broadcast: Option>, } -impl CheckedMessageBundle { +impl CheckedMessageBundle +where + SP: SessionParameters, +{ pub fn metadata(&self) -> &MessageMetadata { &self.metadata } - pub fn verify( + pub fn verify( self, - verifier: &Verifier, - ) -> Result, MessageVerificationError> - where - Verifier: Clone + DigestVerifier, - { - let direct_message = self.direct_message.verify::(verifier)?; + verifier: &SP::Verifier, + ) -> Result, MessageVerificationError> { + let direct_message = self.direct_message.verify::(verifier)?; let echo_broadcast = self .echo_broadcast - .map(|echo| echo.verify::(verifier)) + .map(|echo| echo.verify::(verifier)) .transpose()?; Ok(VerifiedMessageBundle { from: verifier.clone(), @@ -212,19 +216,22 @@ impl CheckedMessageBundle { } #[derive(Clone, Debug)] -pub struct VerifiedMessageBundle { - from: Verifier, +pub struct VerifiedMessageBundle { + from: SP::Verifier, metadata: MessageMetadata, - direct_message: VerifiedMessage, - echo_broadcast: Option>, + direct_message: VerifiedMessage, + echo_broadcast: Option>, } -impl VerifiedMessageBundle { +impl VerifiedMessageBundle +where + SP: SessionParameters, +{ pub(crate) fn metadata(&self) -> &MessageMetadata { &self.metadata } - pub(crate) fn from(&self) -> &Verifier { + pub(crate) fn from(&self) -> &SP::Verifier { &self.from } @@ -232,7 +239,13 @@ impl VerifiedMessageBundle { self.direct_message.payload() } - pub(crate) fn into_unverified(self) -> (Option>, SignedMessage) { + #[allow(clippy::type_complexity)] + pub(crate) fn into_unverified( + self, + ) -> ( + Option>, + SignedMessage, + ) { let direct_message = self.direct_message.into_unverified(); let echo_broadcast = self.echo_broadcast.map(|echo| echo.into_unverified()); (echo_broadcast, direct_message) diff --git a/manul/src/session/session.rs b/manul/src/session/session.rs index 2ce1c51..7ec221d 100644 --- a/manul/src/session/session.rs +++ b/manul/src/session/session.rs @@ -6,6 +6,7 @@ use alloc::{ }; use core::fmt::Debug; +use digest::Digest; use rand_core::CryptoRngCore; use serde::{Deserialize, Serialize}; use serde_encoded_bytes::{Base64, SliceLike}; @@ -24,6 +25,33 @@ use crate::protocol::{ ObjectSafeRoundWrapper, Payload, Protocol, ReceiveError, ReceiveErrorType, Round, RoundId, }; +/// A set of types needed to execute a session. +/// +/// These will be generally determined by the user, depending on what signature type +/// is used in the network in which they are running the protocol. +pub trait SessionParameters { + /// The signer type. + type Signer: RandomizedDigestSigner + Keypair; + + /// The hash type that will be used to pre-hash message payloads before signing. + type Digest: Digest; + + /// The verifier type, which will also serve as a node identifier. + type Verifier: 'static + + Debug + + Clone + + Eq + + Ord + + DigestVerifier + + Serialize + + for<'de> Deserialize<'de> + + Send + + Sync; + + /// The signature type corresponding to [`Signer`] and [`Verifier`]. + type Signature: 'static + Debug + Clone + Eq + Serialize + for<'de> Deserialize<'de> + Send + Sync; +} + /// A session identifier shared between the parties. #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct SessionId(#[serde(with = "SliceLike::")] Box<[u8]>); @@ -55,55 +83,44 @@ impl AsRef<[u8]> for SessionId { /// An object encapsulating the currently active round, transport protocol, /// and the database of messages and errors from the previous rounds. -pub struct Session { +pub struct Session { session_id: SessionId, - signer: Signer, - verifier: Verifier, - round: Box>, - message_destinations: BTreeSet, - echo_message: Option>, + signer: SP::Signer, + verifier: SP::Verifier, + round: Box>, + message_destinations: BTreeSet, + echo_message: Option>, possible_next_rounds: BTreeSet, - transcript: Transcript, + transcript: Transcript, } /// Possible non-erroneous results of finalizing a round. -pub enum RoundOutcome { +pub enum RoundOutcome { /// The execution is finished. - Finished(SessionReport), + Finished(SessionReport), /// Transitioned to another round. AnotherRound { /// The session object for the new round. - session: Session, + session: Session, /// The messages intended for the new round cached during the previous round. - cached_messages: Vec>, + cached_messages: Vec>, }, } -impl Session +impl Session where - P: Protocol + 'static, - Signer: RandomizedDigestSigner + Keypair, - Verifier: Debug - + Clone - + Eq - + Ord - + DigestVerifier - + 'static - + Serialize - + for<'de> Deserialize<'de> - + Send - + Sync, - S: Debug + Clone + Eq + 'static + Serialize + for<'de> Deserialize<'de> + Send + Sync, + P: 'static + Protocol, + SP: 'static + SessionParameters, { /// Initializes a new session. pub fn new( rng: &mut impl CryptoRngCore, session_id: SessionId, - signer: Signer, + signer: SP::Signer, inputs: R::Inputs, ) -> Result where - R: FirstRound + Round + 'static, + R: FirstRound + Round + 'static, { let verifier = signer.verifying_key(); let first_round = Box::new(ObjectSafeRoundWrapper::new(R::new( @@ -118,15 +135,15 @@ where fn new_for_next_round( rng: &mut impl CryptoRngCore, session_id: SessionId, - signer: Signer, - round: Box>, - transcript: Transcript, + signer: SP::Signer, + round: Box>, + transcript: Transcript, ) -> Result { let verifier = signer.verifying_key(); let echo_message = round .make_echo_broadcast(rng) .transpose()? - .map(|echo| SignedMessage::new::(rng, &signer, &session_id, round.id(), echo)) + .map(|echo| SignedMessage::new::(rng, &signer, &session_id, round.id(), echo)) .transpose()?; let message_destinations = round.message_destinations().clone(); @@ -149,7 +166,7 @@ where } /// Returns the verifier corresponding to the session's signer. - pub fn verifier(&self) -> Verifier { + pub fn verifier(&self) -> SP::Verifier { self.verifier.clone() } @@ -159,7 +176,7 @@ where } /// Returns the set of message destinations for the current round. - pub fn message_destinations(&self) -> &BTreeSet { + pub fn message_destinations(&self) -> &BTreeSet { &self.message_destinations } @@ -169,11 +186,11 @@ where pub fn make_message( &self, rng: &mut impl CryptoRngCore, - destination: &Verifier, - ) -> Result<(MessageBundle, ProcessedArtifact), LocalError> { + destination: &SP::Verifier, + ) -> Result<(MessageBundle, ProcessedArtifact), LocalError> { let (direct_message, artifact) = self.round.make_direct_message(rng, destination)?; - let bundle = MessageBundle::new::( + let bundle = MessageBundle::new::

( rng, &self.signer, &self.session_id, @@ -194,8 +211,8 @@ where /// Adds the artifact from [`make_message`](`Self::make_message`) to the accumulator. pub fn add_artifact( &self, - accum: &mut RoundAccumulator, - processed: ProcessedArtifact, + accum: &mut RoundAccumulator, + processed: ProcessedArtifact, ) -> Result<(), LocalError> { accum.add_artifact(processed) } @@ -208,10 +225,10 @@ where /// Performs some preliminary checks on the message to verify its integrity. pub fn preprocess_message( &self, - accum: &mut RoundAccumulator, - from: &Verifier, - message: MessageBundle, - ) -> Result>, LocalError> { + accum: &mut RoundAccumulator, + from: &SP::Verifier, + message: MessageBundle, + ) -> Result>, LocalError> { // Quick preliminary checks, before we proceed with more expensive verification if self.transcript.is_banned(from) || accum.is_banned(from) { @@ -261,7 +278,7 @@ where // Verify the signature now - let verified_message = match checked_message.verify::(from) { + let verified_message = match checked_message.verify::

(from) { Ok(verified_message) => verified_message, Err(MessageVerificationError::InvalidSignature) => { accum.register_unprovable_error(from, RemoteError::new("Message verification failed"))?; @@ -299,8 +316,8 @@ where pub fn process_message( &self, rng: &mut impl CryptoRngCore, - message: VerifiedMessageBundle, - ) -> ProcessedMessage { + message: VerifiedMessageBundle, + ) -> ProcessedMessage { let processed = self.round.receive_message( rng, message.from(), @@ -315,22 +332,19 @@ where /// Adds a result of [`process_message`](`Self::process_message`) to the accumulator. pub fn add_processed_message( &self, - accum: &mut RoundAccumulator, - processed: ProcessedMessage, + accum: &mut RoundAccumulator, + processed: ProcessedMessage, ) -> Result<(), LocalError> { accum.add_processed_message(&self.transcript, processed) } /// Makes an accumulator for a new round. - pub fn make_accumulator(&self) -> RoundAccumulator { + pub fn make_accumulator(&self) -> RoundAccumulator { RoundAccumulator::new(self.round.expecting_messages_from()) } /// Terminates the session. - pub fn terminate( - self, - accum: RoundAccumulator, - ) -> Result, LocalError> { + pub fn terminate(self, accum: RoundAccumulator) -> Result, LocalError> { let round_id = self.round_id(); let transcript = self.transcript.update( round_id, @@ -347,8 +361,8 @@ where pub fn finalize_round( self, rng: &mut impl CryptoRngCore, - accum: RoundAccumulator, - ) -> Result, LocalError> { + accum: RoundAccumulator, + ) -> Result, LocalError> { let verifier = self.verifier().clone(); let round_id = self.round_id(); @@ -362,7 +376,7 @@ where )?; if let Some(echo_message) = self.echo_message { - let round = Box::new(ObjectSafeRoundWrapper::new(EchoRound::new( + let round = Box::new(ObjectSafeRoundWrapper::new(EchoRound::::new( verifier, echo_message, transcript.echo_broadcasts(round_id)?, @@ -418,7 +432,7 @@ where } /// Checks if the round can be finalized. - pub fn can_finalize(&self, accum: &RoundAccumulator) -> CanFinalize { + pub fn can_finalize(&self, accum: &RoundAccumulator) -> CanFinalize { accum.can_finalize() } } @@ -436,26 +450,25 @@ pub enum CanFinalize { } /// A mutable accumulator for collecting the results and errors from processing messages for a single round. -pub struct RoundAccumulator { - still_have_not_sent_messages: BTreeSet, - expecting_messages_from: BTreeSet, - processing: BTreeSet, - payloads: BTreeMap, - artifacts: BTreeMap, - cached: BTreeMap>>, - echo_broadcasts: BTreeMap>, - direct_messages: BTreeMap>, - provable_errors: BTreeMap>, - unprovable_errors: BTreeMap, +pub struct RoundAccumulator { + still_have_not_sent_messages: BTreeSet, + expecting_messages_from: BTreeSet, + processing: BTreeSet, + payloads: BTreeMap, + artifacts: BTreeMap, + cached: BTreeMap>>, + echo_broadcasts: BTreeMap>, + direct_messages: BTreeMap>, + provable_errors: BTreeMap>, + unprovable_errors: BTreeMap, } -impl RoundAccumulator +impl RoundAccumulator where P: Protocol, - Verifier: Debug + Clone + Ord + for<'de> Deserialize<'de> + DigestVerifier, - S: Debug + Clone + for<'de> Deserialize<'de>, + SP: SessionParameters, { - fn new(expecting_messages_from: &BTreeSet) -> Self { + fn new(expecting_messages_from: &BTreeSet) -> Self { Self { still_have_not_sent_messages: expecting_messages_from.clone(), expecting_messages_from: expecting_messages_from.clone(), @@ -484,15 +497,15 @@ where } } - fn is_banned(&self, from: &Verifier) -> bool { + fn is_banned(&self, from: &SP::Verifier) -> bool { self.provable_errors.contains_key(from) || self.unprovable_errors.contains_key(from) } - fn message_is_being_processed(&self, from: &Verifier) -> bool { + fn message_is_being_processed(&self, from: &SP::Verifier) -> bool { self.processing.contains(from) } - fn message_is_cached(&self, from: &Verifier, round_id: RoundId) -> bool { + fn message_is_cached(&self, from: &SP::Verifier, round_id: RoundId) -> bool { if let Some(entry) = self.cached.get(from) { entry.contains_key(&round_id) } else { @@ -500,7 +513,7 @@ where } } - fn register_unprovable_error(&mut self, from: &Verifier, error: RemoteError) -> Result<(), LocalError> { + fn register_unprovable_error(&mut self, from: &SP::Verifier, error: RemoteError) -> Result<(), LocalError> { if self.unprovable_errors.insert(from.clone(), error).is_some() { Err(LocalError::new(format!( "An unprovable error for {:?} is already registered", @@ -511,11 +524,7 @@ where } } - fn register_provable_error( - &mut self, - from: &Verifier, - evidence: Evidence, - ) -> Result<(), LocalError> { + fn register_provable_error(&mut self, from: &SP::Verifier, evidence: Evidence) -> Result<(), LocalError> { if self.provable_errors.insert(from.clone(), evidence).is_some() { Err(LocalError::new(format!( "A provable error for {:?} is already registered", @@ -526,7 +535,7 @@ where } } - fn mark_processing(&mut self, message: &VerifiedMessageBundle) -> Result<(), LocalError> { + fn mark_processing(&mut self, message: &VerifiedMessageBundle) -> Result<(), LocalError> { if !self.processing.insert(message.from().clone()) { Err(LocalError::new(format!( "A message from {:?} is already marked as being processed", @@ -537,7 +546,7 @@ where } } - fn add_artifact(&mut self, processed: ProcessedArtifact) -> Result<(), LocalError> { + fn add_artifact(&mut self, processed: ProcessedArtifact) -> Result<(), LocalError> { if self .artifacts .insert(processed.destination.clone(), processed.artifact) @@ -553,8 +562,8 @@ where fn add_processed_message( &mut self, - transcript: &Transcript, - processed: ProcessedMessage, + transcript: &Transcript, + processed: ProcessedMessage, ) -> Result<(), LocalError> { if self.payloads.contains_key(processed.message.from()) { return Err(LocalError::new(format!( @@ -616,7 +625,7 @@ where } } - fn cache_message(&mut self, message: VerifiedMessageBundle) -> Result<(), LocalError> { + fn cache_message(&mut self, message: VerifiedMessageBundle) -> Result<(), LocalError> { let from = message.from().clone(); let round_id = message.metadata().round_id(); let cached = self.cached.entry(from.clone()).or_default(); @@ -635,15 +644,15 @@ pub struct ProcessedArtifact { artifact: Artifact, } -pub struct ProcessedMessage { - message: VerifiedMessageBundle, - processed: Result>, +pub struct ProcessedMessage { + message: VerifiedMessageBundle, + processed: Result>, } -fn filter_messages( - messages: BTreeMap>>, +fn filter_messages( + messages: BTreeMap>>, round_id: RoundId, -) -> Vec> { +) -> Vec> { messages .into_values() .filter_map(|mut messages| messages.remove(&round_id)) @@ -663,7 +672,7 @@ mod tests { DeserializationError, DirectMessage, EchoBroadcast, LocalError, Protocol, ProtocolError, ProtocolValidationError, RoundId, }, - testing::{Hasher, Signature, Signer, Verifier}, + testing::{TestingSessionParams, Verifier}, }; #[test] @@ -699,7 +708,6 @@ mod tests { type Result = (); type ProtocolError = DummyProtocolError; type CorrectnessProof = (); - type Digest = Hasher; fn serialize(_: T) -> Result, LocalError> where T: Serialize, @@ -716,15 +724,15 @@ mod tests { // We need `Session` to be `Send` so that we send a `Session` object to a task // to run the loop there. - assert!(impls!(Session: Send)); + assert!(impls!(Session: Send)); // This is needed so that message processing offloaded to a task could use `&Session`. - assert!(impls!(Session: Sync)); + assert!(impls!(Session: Sync)); // These objects are sent to/from message processing tasks - assert!(impls!(MessageBundle: Send)); + assert!(impls!(MessageBundle: Send)); assert!(impls!(ProcessedArtifact: Send)); - assert!(impls!(VerifiedMessageBundle: Send)); - assert!(impls!(ProcessedMessage: Send)); + assert!(impls!(VerifiedMessageBundle: Send)); + assert!(impls!(ProcessedMessage: Send)); } } diff --git a/manul/src/session/transcript.rs b/manul/src/session/transcript.rs index c5df56c..9ed43a5 100644 --- a/manul/src/session/transcript.rs +++ b/manul/src/session/transcript.rs @@ -4,22 +4,22 @@ use alloc::{ }; use core::fmt::Debug; -use super::{evidence::Evidence, message::SignedMessage, LocalError, RemoteError}; +use super::{evidence::Evidence, message::SignedMessage, session::SessionParameters, LocalError, RemoteError}; use crate::protocol::{DirectMessage, EchoBroadcast, Protocol, RoundId}; -pub(crate) struct Transcript { - echo_broadcasts: BTreeMap>>, - direct_messages: BTreeMap>>, - provable_errors: BTreeMap>, - unprovable_errors: BTreeMap, - missing_messages: BTreeMap>, +#[allow(clippy::type_complexity)] +pub(crate) struct Transcript { + echo_broadcasts: BTreeMap>>, + direct_messages: BTreeMap>>, + provable_errors: BTreeMap>, + unprovable_errors: BTreeMap, + missing_messages: BTreeMap>, } -impl Transcript +impl Transcript where P: Protocol, - Verifier: Debug + Clone + Ord, - S: Clone, + SP: SessionParameters, { pub fn new() -> Self { Self { @@ -34,11 +34,11 @@ where pub fn update( self, round_id: RoundId, - echo_broadcasts: BTreeMap>, - direct_messages: BTreeMap>, - provable_errors: BTreeMap>, - unprovable_errors: BTreeMap, - missing_messages: BTreeSet, + echo_broadcasts: BTreeMap>, + direct_messages: BTreeMap>, + provable_errors: BTreeMap>, + unprovable_errors: BTreeMap, + missing_messages: BTreeSet, ) -> Result { let mut all_echo_broadcasts = self.echo_broadcasts; match all_echo_broadcasts.entry(round_id) { @@ -100,8 +100,8 @@ where pub fn get_echo_broadcast( &self, round_id: RoundId, - from: &Verifier, - ) -> Result, LocalError> { + from: &SP::Verifier, + ) -> Result, LocalError> { self.echo_broadcasts .get(&round_id) .ok_or_else(|| LocalError::new(format!("No echo broadcasts registered for {round_id:?}")))? @@ -113,8 +113,8 @@ where pub fn get_direct_message( &self, round_id: RoundId, - from: &Verifier, - ) -> Result, LocalError> { + from: &SP::Verifier, + ) -> Result, LocalError> { self.direct_messages .get(&round_id) .ok_or_else(|| LocalError::new(format!("No direct messages registered for {round_id:?}")))? @@ -123,14 +123,15 @@ where .ok_or_else(|| LocalError::new(format!("No direct messages registered for {from:?} in {round_id:?}"))) } - pub fn is_banned(&self, from: &Verifier) -> bool { + pub fn is_banned(&self, from: &SP::Verifier) -> bool { self.provable_errors.contains_key(from) || self.unprovable_errors.contains_key(from) } + #[allow(clippy::type_complexity)] pub fn echo_broadcasts( &self, round_id: RoundId, - ) -> Result>, LocalError> { + ) -> Result>, LocalError> { self.echo_broadcasts .get(&round_id) .cloned() @@ -153,22 +154,23 @@ pub enum SessionOutcome { } /// The report of a session execution. -pub struct SessionReport { +pub struct SessionReport { /// The session outcome. pub outcome: SessionOutcome

, /// The provable errors collected during the execution, as the evidences that can be published to prove them. - pub provable_errors: BTreeMap>, + pub provable_errors: BTreeMap>, /// The unprovable errors collected during the execution. - pub unprovable_errors: BTreeMap, + pub unprovable_errors: BTreeMap, /// The nodes that did not send their messages in time for the corresponding round. - pub missing_messages: BTreeMap>, + pub missing_messages: BTreeMap>, } -impl SessionReport +impl SessionReport where P: Protocol, + SP: SessionParameters, { - pub(crate) fn new(outcome: SessionOutcome

, transcript: Transcript) -> Self { + pub(crate) fn new(outcome: SessionOutcome

, transcript: Transcript) -> Self { Self { outcome, provable_errors: transcript.provable_errors, diff --git a/manul/src/testing.rs b/manul/src/testing.rs index f958aca..820bb10 100644 --- a/manul/src/testing.rs +++ b/manul/src/testing.rs @@ -6,6 +6,6 @@ mod identity; mod macros; mod run_sync; -pub use identity::{Hasher, Signature, Signer, Verifier}; +pub use identity::{Hasher, Signature, Signer, TestingSessionParams, Verifier}; pub use macros::{round_override, RoundOverride, RoundWrapper}; pub use run_sync::run_sync; diff --git a/manul/src/testing/identity.rs b/manul/src/testing/identity.rs index 49b7eb1..4220ca2 100644 --- a/manul/src/testing/identity.rs +++ b/manul/src/testing/identity.rs @@ -2,6 +2,8 @@ use digest::generic_array::typenum; use rand_core::CryptoRngCore; use serde::{Deserialize, Serialize}; +use crate::session::SessionParameters; + /// A simple signer for testing purposes. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub struct Signer(u8); @@ -85,6 +87,17 @@ impl digest::OutputSizeUser for Hasher { type OutputSize = typenum::U8; } +/// An implementation of [`SessionParameters`] using the testing signer/verifier types. +#[derive(Debug, Clone, Copy)] +pub struct TestingSessionParams; + +impl SessionParameters for TestingSessionParams { + type Signer = Signer; + type Verifier = Verifier; + type Signature = Signature; + type Digest = Hasher; +} + #[cfg(test)] mod tests { use impls::impls; diff --git a/manul/src/testing/run_sync.rs b/manul/src/testing/run_sync.rs index 63d623b..4691e0d 100644 --- a/manul/src/testing/run_sync.rs +++ b/manul/src/testing/run_sync.rs @@ -1,53 +1,41 @@ use alloc::{collections::BTreeMap, vec::Vec}; -use core::fmt::Debug; use rand::Rng; use rand_core::CryptoRngCore; -use serde::{Deserialize, Serialize}; -use signature::{DigestVerifier, Keypair, RandomizedDigestSigner}; +use signature::Keypair; use tracing::debug; use crate::{ protocol::{FirstRound, Protocol}, session::{ - CanFinalize, LocalError, MessageBundle, RoundAccumulator, RoundOutcome, Session, SessionId, SessionReport, + CanFinalize, LocalError, MessageBundle, RoundAccumulator, RoundOutcome, Session, SessionId, SessionParameters, + SessionReport, }, }; -enum State { +enum State { InProgress { - session: Session, - accum: RoundAccumulator, + session: Session, + accum: RoundAccumulator, }, - Finished(SessionReport), + Finished(SessionReport), } -struct Message { - from: Verifier, - to: Verifier, - message: MessageBundle, +struct Message { + from: SP::Verifier, + to: SP::Verifier, + message: MessageBundle, } #[allow(clippy::type_complexity)] -fn propagate( +fn propagate( rng: &mut impl CryptoRngCore, - session: Session, - accum: RoundAccumulator, -) -> Result<(State, Vec>), LocalError> + session: Session, + accum: RoundAccumulator, +) -> Result<(State, Vec>), LocalError> where - P: Protocol + 'static, - Signer: RandomizedDigestSigner + Keypair, - Verifier: Debug - + Clone - + Eq - + Ord - + DigestVerifier - + 'static - + Serialize - + for<'de> Deserialize<'de> - + Send - + Sync, - S: Debug + Clone + Eq + 'static + Serialize + for<'de> Deserialize<'de> + Send + Sync, + P: 'static + Protocol, + SP: 'static + SessionParameters, { let mut messages = Vec::new(); @@ -101,24 +89,13 @@ where /// Execute sessions for multiple nodes concurrently, given the the inputs /// for the first round `R` and the signer for each node. #[allow(clippy::type_complexity)] -pub fn run_sync( +pub fn run_sync( rng: &mut impl CryptoRngCore, - inputs: Vec<(Signer, R::Inputs)>, -) -> Result>, LocalError> + inputs: Vec<(SP::Signer, R::Inputs)>, +) -> Result>, LocalError> where - R: FirstRound + 'static, - Signer: RandomizedDigestSigner<::Digest, S> + Keypair, - Verifier: Debug - + Clone - + Eq - + Ord - + DigestVerifier<::Digest, S> - + 'static - + Serialize - + for<'de> Deserialize<'de> - + Send - + Sync, - S: Debug + Clone + Eq + 'static + Serialize + for<'de> Deserialize<'de> + Send + Sync, + R: 'static + FirstRound, + SP: 'static + SessionParameters, { let session_id = SessionId::random(rng); @@ -127,7 +104,7 @@ where for (signer, inputs) in inputs { let verifier = signer.verifying_key(); - let session = Session::::new::(rng, session_id.clone(), signer, inputs)?; + let session = Session::::new::(rng, session_id.clone(), signer, inputs)?; let mut accum = session.make_accumulator(); let destinations = session.message_destinations(); From 42e2d8baa5fdd29a3b28b7b27e9ee0b22ea60b46 Mon Sep 17 00:00:00 2001 From: Bogdan Opanchuk Date: Sun, 20 Oct 2024 14:58:59 -0700 Subject: [PATCH 2/2] Serialize the signature to avoid generics in MessageBundle --- CHANGELOG.md | 1 + example/tests/async.rs | 7 +-- manul/Cargo.toml | 2 +- manul/src/session/echo.rs | 8 +-- manul/src/session/evidence.rs | 86 +++++++++++++------------ manul/src/session/message.rs | 107 ++++++++++++++++++-------------- manul/src/session/session.rs | 16 ++--- manul/src/session/transcript.rs | 16 +++-- manul/src/testing/run_sync.rs | 2 +- 9 files changed, 132 insertions(+), 113 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 199c2d2..b37fc30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - `Session` is now generic over `SessionParameters` instead of a bunch of separate types. ([#36]) +- `MessageBundle` is not generic anymore. ([#36]) ### Added diff --git a/example/tests/async.rs b/example/tests/async.rs index bf281ba..9a95552 100644 --- a/example/tests/async.rs +++ b/example/tests/async.rs @@ -23,12 +23,12 @@ use tracing_subscriber::{util::SubscriberInitExt, EnvFilter}; struct MessageOut { from: SP::Verifier, to: SP::Verifier, - message: MessageBundle, + message: MessageBundle, } struct MessageIn { from: SP::Verifier, - message: MessageBundle, + message: MessageBundle, } async fn run_session( @@ -185,8 +185,7 @@ where let (dispatcher_tx, dispatcher_rx) = mpsc::channel::>(100); let channels = (0..num_parties).map(|_| mpsc::channel::>(100)); - #[allow(clippy::type_complexity)] - let (txs, rxs): (Vec>>, Vec>>) = channels.unzip(); + let (txs, rxs): (Vec<_>, Vec<_>) = channels.unzip(); let tx_map = sessions .iter() .map(|session| session.verifier()) diff --git a/manul/Cargo.toml b/manul/Cargo.toml index 3ef62d9..7f1c8f2 100644 --- a/manul/Cargo.toml +++ b/manul/Cargo.toml @@ -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 } diff --git a/manul/src/session/echo.rs b/manul/src/session/echo.rs index 9922f5e..e4aa132 100644 --- a/manul/src/session/echo.rs +++ b/manul/src/session/echo.rs @@ -31,12 +31,12 @@ pub(crate) enum EchoRoundError { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct EchoRoundMessage { - pub(crate) echo_messages: SerializableMap>, + pub(crate) echo_messages: SerializableMap>, } pub struct EchoRound { verifier: SP::Verifier, - echo_messages: BTreeMap>, + echo_messages: BTreeMap>, destinations: BTreeSet, expected_echos: BTreeSet, main_round: Box>, @@ -51,8 +51,8 @@ where { pub fn new( verifier: SP::Verifier, - my_echo_message: SignedMessage, - echo_messages: BTreeMap>, + my_echo_message: SignedMessage, + echo_messages: BTreeMap>, main_round: Box>, payloads: BTreeMap, artifacts: BTreeMap, diff --git a/manul/src/session/evidence.rs b/manul/src/session/evidence.rs index 2b12510..08dcca4 100644 --- a/manul/src/session/evidence.rs +++ b/manul/src/session/evidence.rs @@ -71,8 +71,8 @@ where { pub(crate) fn new_protocol_error( verifier: &SP::Verifier, - echo_broadcast: Option>, - direct_message: SignedMessage, + echo_broadcast: Option>, + direct_message: SignedMessage, error: P::ProtocolError, transcript: &Transcript, ) -> Result { @@ -124,7 +124,7 @@ where pub(crate) fn new_echo_round_error( verifier: &SP::Verifier, - direct_message: SignedMessage, + direct_message: SignedMessage, error: EchoRoundError, transcript: &Transcript, ) -> Result { @@ -173,7 +173,7 @@ where pub(crate) fn new_invalid_direct_message( verifier: &SP::Verifier, - direct_message: SignedMessage, + direct_message: SignedMessage, error: DirectMessageError, ) -> Self { Self { @@ -188,7 +188,7 @@ where pub(crate) fn new_invalid_echo_broadcast( verifier: &SP::Verifier, - echo_broadcast: SignedMessage, + echo_broadcast: SignedMessage, error: EchoBroadcastError, ) -> Self { Self { @@ -211,27 +211,27 @@ where pub fn verify(&self, party: &SP::Verifier) -> Result<(), EvidenceError> { match &self.evidence { - EvidenceEnum::Protocol(evidence) => evidence.verify(party), - EvidenceEnum::InvalidDirectMessage(evidence) => evidence.verify(party), - EvidenceEnum::InvalidEchoBroadcast(evidence) => evidence.verify(party), + EvidenceEnum::Protocol(evidence) => evidence.verify::(party), + EvidenceEnum::InvalidDirectMessage(evidence) => evidence.verify::(party), + EvidenceEnum::InvalidEchoBroadcast(evidence) => evidence.verify::(party), EvidenceEnum::InvalidEchoPack(evidence) => evidence.verify(party), - EvidenceEnum::MismatchedBroadcasts(evidence) => evidence.verify(party), + EvidenceEnum::MismatchedBroadcasts(evidence) => evidence.verify::(party), } } } #[derive(Debug, Clone, Serialize, Deserialize)] enum EvidenceEnum { - Protocol(ProtocolEvidence), - InvalidDirectMessage(InvalidDirectMessageEvidence), - InvalidEchoBroadcast(InvalidEchoBroadcastEvidence), + Protocol(ProtocolEvidence

), + InvalidDirectMessage(InvalidDirectMessageEvidence

), + InvalidEchoBroadcast(InvalidEchoBroadcastEvidence

), InvalidEchoPack(InvalidEchoPackEvidence), - MismatchedBroadcasts(MismatchedBroadcastsEvidence), + MismatchedBroadcasts(MismatchedBroadcastsEvidence

), } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct InvalidEchoPackEvidence { - direct_message: SignedMessage, + direct_message: SignedMessage, invalid_echo_sender: SP::Verifier, phantom: core::marker::PhantomData

, } @@ -274,18 +274,20 @@ where } #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct MismatchedBroadcastsEvidence { - we_received: SignedMessage, - echoed_to_us: SignedMessage, +pub struct MismatchedBroadcastsEvidence { + we_received: SignedMessage, + echoed_to_us: SignedMessage, phantom: core::marker::PhantomData

, } -impl MismatchedBroadcastsEvidence +impl

MismatchedBroadcastsEvidence

where P: Protocol, - SP: SessionParameters, { - fn verify(&self, verifier: &SP::Verifier) -> Result<(), EvidenceError> { + fn verify(&self, verifier: &SP::Verifier) -> Result<(), EvidenceError> + where + SP: SessionParameters, + { let we_received = self.we_received.clone().verify::(verifier)?; let echoed_to_us = self.echoed_to_us.clone().verify::(verifier)?; @@ -300,17 +302,19 @@ where } #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct InvalidDirectMessageEvidence { - direct_message: SignedMessage, +pub struct InvalidDirectMessageEvidence { + direct_message: SignedMessage, phantom: core::marker::PhantomData

, } -impl InvalidDirectMessageEvidence +impl

InvalidDirectMessageEvidence

where P: Protocol, - SP: SessionParameters, { - fn verify(&self, verifier: &SP::Verifier) -> Result<(), EvidenceError> { + fn verify(&self, verifier: &SP::Verifier) -> Result<(), EvidenceError> + where + SP: SessionParameters, + { let verified_direct_message = self.direct_message.clone().verify::(verifier)?; Ok(P::verify_direct_message_is_invalid( self.direct_message.metadata().round_id(), @@ -320,17 +324,19 @@ where } #[derive(Debug, Clone, Serialize, Deserialize)] -pub struct InvalidEchoBroadcastEvidence { - echo_broadcast: SignedMessage, +pub struct InvalidEchoBroadcastEvidence { + echo_broadcast: SignedMessage, phantom: core::marker::PhantomData

, } -impl InvalidEchoBroadcastEvidence +impl

InvalidEchoBroadcastEvidence

where P: Protocol, - SP: SessionParameters, { - fn verify(&self, verifier: &SP::Verifier) -> Result<(), EvidenceError> { + fn verify(&self, verifier: &SP::Verifier) -> Result<(), EvidenceError> + where + SP: SessionParameters, + { let verified_echo_broadcast = self.echo_broadcast.clone().verify::(verifier)?; Ok(P::verify_echo_broadcast_is_invalid( self.echo_broadcast.metadata().round_id(), @@ -340,21 +346,23 @@ where } #[derive(Debug, Clone, Serialize, Deserialize)] -struct ProtocolEvidence { +struct ProtocolEvidence { error: P::ProtocolError, - direct_message: SignedMessage, - echo_broadcast: Option>, - direct_messages: SerializableMap>, - echo_broadcasts: SerializableMap>, - combined_echos: SerializableMap>, + direct_message: SignedMessage, + echo_broadcast: Option>, + direct_messages: SerializableMap>, + echo_broadcasts: SerializableMap>, + combined_echos: SerializableMap>, } -impl ProtocolEvidence +impl

ProtocolEvidence

where P: Protocol, - SP: SessionParameters, { - fn verify(&self, verifier: &SP::Verifier) -> Result<(), EvidenceError> { + fn verify(&self, verifier: &SP::Verifier) -> Result<(), EvidenceError> + where + SP: SessionParameters, + { let session_id = self.direct_message.metadata().session_id(); let verified_direct_message = self.direct_message.clone().verify::(verifier)?.payload().clone(); diff --git a/manul/src/session/message.rs b/manul/src/session/message.rs index 7aede9a..47a42b9 100644 --- a/manul/src/session/message.rs +++ b/manul/src/session/message.rs @@ -1,15 +1,37 @@ -use alloc::format; +use alloc::{boxed::Box, format}; use digest::Digest; use rand_core::CryptoRngCore; use serde::{Deserialize, Serialize}; +use serde_encoded_bytes::{Hex, SliceLike}; use signature::{DigestVerifier, RandomizedDigestSigner}; use super::{ session::{SessionId, SessionParameters}, LocalError, }; -use crate::protocol::{DirectMessage, EchoBroadcast, Protocol, RoundId}; +use crate::protocol::{DeserializationError, DirectMessage, EchoBroadcast, Protocol, RoundId}; + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub(crate) struct SerializedSignature(#[serde(with = "SliceLike::")] Box<[u8]>); + +impl SerializedSignature { + pub fn new(signature: &SP::Signature) -> Result + where + P: Protocol, + SP: SessionParameters, + { + P::serialize(signature).map(Self) + } + + pub fn deserialize(&self) -> Result + where + P: Protocol, + SP: SessionParameters, + { + P::deserialize::(&self.0) + } +} #[derive(Debug, Clone)] pub(crate) enum MessageVerificationError { @@ -18,8 +40,8 @@ pub(crate) enum MessageVerificationError { } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub(crate) struct SignedMessage { - signature: S, +pub(crate) struct SignedMessage { + signature: SerializedSignature, message_with_metadata: MessageWithMetadata, } @@ -52,7 +74,7 @@ pub struct MessageWithMetadata { message: M, } -impl SignedMessage +impl SignedMessage where M: Serialize, { @@ -65,7 +87,7 @@ where ) -> Result where P: Protocol, - SP: SessionParameters, + SP: SessionParameters, { let metadata = MessageMetadata::new(session_id, round_id); let message_with_metadata = MessageWithMetadata { metadata, message }; @@ -75,7 +97,7 @@ where .try_sign_digest_with_rng(rng, digest) .map_err(|err| LocalError::new(format!("Failed to sign: {:?}", err)))?; Ok(Self { - signature, + signature: SerializedSignature::new::(&signature)?, message_with_metadata, }) } @@ -88,17 +110,18 @@ where &self.message_with_metadata.message } - pub(crate) fn verify( - self, - verifier: &SP::Verifier, - ) -> Result, MessageVerificationError> + pub(crate) fn verify(self, verifier: &SP::Verifier) -> Result, MessageVerificationError> where P: Protocol, - SP: SessionParameters, + SP: SessionParameters, { let message_bytes = P::serialize(&self.message_with_metadata).map_err(MessageVerificationError::Local)?; let digest = SP::Digest::new_with_prefix(b"SignedMessage").chain_update(message_bytes); - if verifier.verify_digest(digest, &self.signature).is_ok() { + let signature = self + .signature + .deserialize::() + .map_err(|_| MessageVerificationError::InvalidSignature)?; + if verifier.verify_digest(digest, &signature).is_ok() { Ok(VerifiedMessage { signature: self.signature, message_with_metadata: self.message_with_metadata, @@ -110,12 +133,12 @@ where } #[derive(Debug, Clone)] -pub struct VerifiedMessage { - signature: S, +pub struct VerifiedMessage { + signature: SerializedSignature, message_with_metadata: MessageWithMetadata, } -impl VerifiedMessage { +impl VerifiedMessage { pub(crate) fn metadata(&self) -> &MessageMetadata { &self.message_with_metadata.metadata } @@ -124,7 +147,7 @@ impl VerifiedMessage { &self.message_with_metadata.message } - pub fn into_unverified(self) -> SignedMessage { + pub fn into_unverified(self) -> SignedMessage { SignedMessage { signature: self.signature, message_with_metadata: self.message_with_metadata, @@ -136,25 +159,23 @@ impl VerifiedMessage { /// /// Note that this is already signed. #[derive(Clone, Debug)] -pub struct MessageBundle { - direct_message: SignedMessage, - echo_broadcast: Option>, +pub struct MessageBundle { + direct_message: SignedMessage, + echo_broadcast: Option>, } -impl MessageBundle -where - SP: SessionParameters, -{ - pub(crate) fn new

( +impl MessageBundle { + pub(crate) fn new( rng: &mut impl CryptoRngCore, signer: &SP::Signer, session_id: &SessionId, round_id: RoundId, direct_message: DirectMessage, - echo_broadcast: Option>, + echo_broadcast: Option>, ) -> Result where P: Protocol, + SP: SessionParameters, { let direct_message = SignedMessage::new::(rng, signer, session_id, round_id, direct_message)?; Ok(Self { @@ -163,7 +184,7 @@ where }) } - pub(crate) fn unify_metadata(self) -> Option> { + pub(crate) fn unify_metadata(self) -> Option { let metadata = self.direct_message.message_with_metadata.metadata.clone(); if !self .echo_broadcast @@ -183,24 +204,22 @@ where } #[derive(Clone, Debug)] -pub(crate) struct CheckedMessageBundle { +pub(crate) struct CheckedMessageBundle { metadata: MessageMetadata, - direct_message: SignedMessage, - echo_broadcast: Option>, + direct_message: SignedMessage, + echo_broadcast: Option>, } -impl CheckedMessageBundle -where - SP: SessionParameters, -{ +impl CheckedMessageBundle { pub fn metadata(&self) -> &MessageMetadata { &self.metadata } - pub fn verify( - self, - verifier: &SP::Verifier, - ) -> Result, MessageVerificationError> { + pub fn verify(self, verifier: &SP::Verifier) -> Result, MessageVerificationError> + where + P: Protocol, + SP: SessionParameters, + { let direct_message = self.direct_message.verify::(verifier)?; let echo_broadcast = self .echo_broadcast @@ -219,8 +238,8 @@ where pub struct VerifiedMessageBundle { from: SP::Verifier, metadata: MessageMetadata, - direct_message: VerifiedMessage, - echo_broadcast: Option>, + direct_message: VerifiedMessage, + echo_broadcast: Option>, } impl VerifiedMessageBundle @@ -239,13 +258,7 @@ where self.direct_message.payload() } - #[allow(clippy::type_complexity)] - pub(crate) fn into_unverified( - self, - ) -> ( - Option>, - SignedMessage, - ) { + pub(crate) fn into_unverified(self) -> (Option>, SignedMessage) { let direct_message = self.direct_message.into_unverified(); let echo_broadcast = self.echo_broadcast.map(|echo| echo.into_unverified()); (echo_broadcast, direct_message) diff --git a/manul/src/session/session.rs b/manul/src/session/session.rs index 7ec221d..b260918 100644 --- a/manul/src/session/session.rs +++ b/manul/src/session/session.rs @@ -89,7 +89,7 @@ pub struct Session { verifier: SP::Verifier, round: Box>, message_destinations: BTreeSet, - echo_message: Option>, + echo_message: Option>, possible_next_rounds: BTreeSet, transcript: Transcript, } @@ -187,10 +187,10 @@ where &self, rng: &mut impl CryptoRngCore, destination: &SP::Verifier, - ) -> Result<(MessageBundle, ProcessedArtifact), LocalError> { + ) -> Result<(MessageBundle, ProcessedArtifact), LocalError> { let (direct_message, artifact) = self.round.make_direct_message(rng, destination)?; - let bundle = MessageBundle::new::

( + let bundle = MessageBundle::new::( rng, &self.signer, &self.session_id, @@ -227,7 +227,7 @@ where &self, accum: &mut RoundAccumulator, from: &SP::Verifier, - message: MessageBundle, + message: MessageBundle, ) -> Result>, LocalError> { // Quick preliminary checks, before we proceed with more expensive verification @@ -278,7 +278,7 @@ where // Verify the signature now - let verified_message = match checked_message.verify::

(from) { + let verified_message = match checked_message.verify::(from) { Ok(verified_message) => verified_message, Err(MessageVerificationError::InvalidSignature) => { accum.register_unprovable_error(from, RemoteError::new("Message verification failed"))?; @@ -457,8 +457,8 @@ pub struct RoundAccumulator { payloads: BTreeMap, artifacts: BTreeMap, cached: BTreeMap>>, - echo_broadcasts: BTreeMap>, - direct_messages: BTreeMap>, + echo_broadcasts: BTreeMap>, + direct_messages: BTreeMap>, provable_errors: BTreeMap>, unprovable_errors: BTreeMap, } @@ -730,7 +730,7 @@ mod tests { assert!(impls!(Session: Sync)); // These objects are sent to/from message processing tasks - assert!(impls!(MessageBundle: Send)); + assert!(impls!(MessageBundle: Send)); assert!(impls!(ProcessedArtifact: Send)); assert!(impls!(VerifiedMessageBundle: Send)); assert!(impls!(ProcessedMessage: Send)); diff --git a/manul/src/session/transcript.rs b/manul/src/session/transcript.rs index 9ed43a5..a5b7d4f 100644 --- a/manul/src/session/transcript.rs +++ b/manul/src/session/transcript.rs @@ -7,10 +7,9 @@ use core::fmt::Debug; use super::{evidence::Evidence, message::SignedMessage, session::SessionParameters, LocalError, RemoteError}; use crate::protocol::{DirectMessage, EchoBroadcast, Protocol, RoundId}; -#[allow(clippy::type_complexity)] pub(crate) struct Transcript { - echo_broadcasts: BTreeMap>>, - direct_messages: BTreeMap>>, + echo_broadcasts: BTreeMap>>, + direct_messages: BTreeMap>>, provable_errors: BTreeMap>, unprovable_errors: BTreeMap, missing_messages: BTreeMap>, @@ -34,8 +33,8 @@ where pub fn update( self, round_id: RoundId, - echo_broadcasts: BTreeMap>, - direct_messages: BTreeMap>, + echo_broadcasts: BTreeMap>, + direct_messages: BTreeMap>, provable_errors: BTreeMap>, unprovable_errors: BTreeMap, missing_messages: BTreeSet, @@ -101,7 +100,7 @@ where &self, round_id: RoundId, from: &SP::Verifier, - ) -> Result, LocalError> { + ) -> Result, LocalError> { self.echo_broadcasts .get(&round_id) .ok_or_else(|| LocalError::new(format!("No echo broadcasts registered for {round_id:?}")))? @@ -114,7 +113,7 @@ where &self, round_id: RoundId, from: &SP::Verifier, - ) -> Result, LocalError> { + ) -> Result, LocalError> { self.direct_messages .get(&round_id) .ok_or_else(|| LocalError::new(format!("No direct messages registered for {round_id:?}")))? @@ -127,11 +126,10 @@ where self.provable_errors.contains_key(from) || self.unprovable_errors.contains_key(from) } - #[allow(clippy::type_complexity)] pub fn echo_broadcasts( &self, round_id: RoundId, - ) -> Result>, LocalError> { + ) -> Result>, LocalError> { self.echo_broadcasts .get(&round_id) .cloned() diff --git a/manul/src/testing/run_sync.rs b/manul/src/testing/run_sync.rs index 4691e0d..7d3a6cb 100644 --- a/manul/src/testing/run_sync.rs +++ b/manul/src/testing/run_sync.rs @@ -24,7 +24,7 @@ enum State { struct Message { from: SP::Verifier, to: SP::Verifier, - message: MessageBundle, + message: MessageBundle, } #[allow(clippy::type_complexity)]