From d8f69bf48714ba34084d617f2e4dbb5a715fd730 Mon Sep 17 00:00:00 2001 From: Bogdan Opanchuk Date: Wed, 30 Oct 2024 12:08:23 -0700 Subject: [PATCH 1/4] Re-export `digest` along with `signature` --- CHANGELOG.md | 2 ++ manul/src/session.rs | 1 + 2 files changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5335d8a..9412bf4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `SerializableMap` wrapper for `BTreeMap` supporting more formats and providing some safety features. (#[32]) - `DirectMessage::assert_is_none()` and `verify_is_some()`, same for `EchoBroadcast`. Users can now check that a part of the round message (echo or direct) is `None` as expected, and make a verifiable evidence if it is not. ([#46]) +- Re-export `digest` from the `session` module. ([#56]) [#32]: https://github.com/entropyxyz/manul/pull/32 @@ -35,6 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [#41]: https://github.com/entropyxyz/manul/pull/41 [#46]: https://github.com/entropyxyz/manul/pull/46 [#47]: https://github.com/entropyxyz/manul/pull/47 +[#56]: https://github.com/entropyxyz/manul/pull/56 ## [0.0.1] - 2024-10-12 diff --git a/manul/src/session.rs b/manul/src/session.rs index 1763e5e..62dae7a 100644 --- a/manul/src/session.rs +++ b/manul/src/session.rs @@ -25,3 +25,4 @@ pub use wire_format::WireFormat; pub(crate) use echo::EchoRoundError; pub use signature; +pub use digest; From 0fc723b21522eebfca3fd809ebc45f7e9d817e05 Mon Sep 17 00:00:00 2001 From: Bogdan Opanchuk Date: Wed, 30 Oct 2024 11:44:04 -0700 Subject: [PATCH 2/4] Remove an unused MissingMessage --- manul/src/session/evidence.rs | 9 --------- manul/src/session/message.rs | 3 --- 2 files changed, 12 deletions(-) diff --git a/manul/src/session/evidence.rs b/manul/src/session/evidence.rs index 4a2e9a6..ef9206a 100644 --- a/manul/src/session/evidence.rs +++ b/manul/src/session/evidence.rs @@ -37,15 +37,6 @@ pub enum EvidenceError { InvalidEvidence(String), } -// Other nodes would send a signed message with the payload being either Some(...) or None. -// We expect the messages in the evidence only be the Some(...) ones, so if it's not the case, it's invalid evidence. -// It's hard to enforce statically since we have to keep the signed messages as they were created by remote nodes. -impl From for EvidenceError { - fn from(_error: MissingMessage) -> Self { - Self::InvalidEvidence("The signed message is missing the expected payload".into()) - } -} - impl From for EvidenceError { fn from(error: MessageVerificationError) -> Self { match error { diff --git a/manul/src/session/message.rs b/manul/src/session/message.rs index 210cfee..4f23edd 100644 --- a/manul/src/session/message.rs +++ b/manul/src/session/message.rs @@ -152,9 +152,6 @@ where } } -#[derive(Debug, Clone, Copy)] -pub(crate) struct MissingMessage; - #[derive(Debug, Clone)] pub struct VerifiedMessage { signature: SerializedSignature, From 6ba72bd4b35bc9febc01d9de098a8901bc08ad21 Mon Sep 17 00:00:00 2001 From: Bogdan Opanchuk Date: Wed, 30 Oct 2024 12:10:19 -0700 Subject: [PATCH 3/4] Rename MessageBundle to Message, and rename internal types accordingly --- CHANGELOG.md | 1 + examples/tests/async_runner.rs | 8 +-- manul/src/session.rs | 4 +- manul/src/session/echo.rs | 14 +++--- manul/src/session/evidence.rs | 42 ++++++++-------- manul/src/session/message.rs | 88 ++++++++++++++++----------------- manul/src/session/session.rs | 59 +++++++++++----------- manul/src/session/transcript.rs | 22 ++++----- manul/src/testing/run_sync.rs | 12 ++--- 9 files changed, 124 insertions(+), 126 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9412bf4..c6842f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `EchoBroadcast` and `DirectMessage` now use `ProtocolMessagePart` trait for their methods. ([#47]) - Added normal broadcasts support in addition to echo ones; signatures of `Round` methods changed accordingly; added `Round::make_normal_broadcast()`. ([#47]) - Serialization format is a part of `SessionParameters` now; `Round` and `Protocol` methods receive dynamic serializers/deserializers. ([#33]) +- Renamed `(Verified)MessageBundle` to `(Verified)Message`. ([#56]) ### Added diff --git a/examples/tests/async_runner.rs b/examples/tests/async_runner.rs index 53a1dcc..1c52472 100644 --- a/examples/tests/async_runner.rs +++ b/examples/tests/async_runner.rs @@ -5,8 +5,8 @@ use alloc::collections::{BTreeMap, BTreeSet}; use manul::{ protocol::Protocol, session::{ - signature::Keypair, CanFinalize, LocalError, MessageBundle, RoundOutcome, Session, SessionId, - SessionParameters, SessionReport, + signature::Keypair, CanFinalize, LocalError, Message, RoundOutcome, Session, SessionId, SessionParameters, + SessionReport, }, testing::{BinaryFormat, TestSessionParams, TestSigner}, }; @@ -23,12 +23,12 @@ use tracing_subscriber::{util::SubscriberInitExt, EnvFilter}; struct MessageOut { from: SP::Verifier, to: SP::Verifier, - message: MessageBundle, + message: Message, } struct MessageIn { from: SP::Verifier, - message: MessageBundle, + message: Message, } /// Runs a session. Simulates what each participating party would run as the protocol progresses. diff --git a/manul/src/session.rs b/manul/src/session.rs index 62dae7a..83791b8 100644 --- a/manul/src/session.rs +++ b/manul/src/session.rs @@ -17,12 +17,12 @@ mod wire_format; pub use crate::protocol::{LocalError, RemoteError}; pub use evidence::{Evidence, EvidenceError}; -pub use message::MessageBundle; +pub use message::{VerifiedMessage, Message}; pub use session::{CanFinalize, RoundAccumulator, RoundOutcome, Session, SessionId, SessionParameters}; pub use transcript::{SessionOutcome, SessionReport}; pub use wire_format::WireFormat; pub(crate) use echo::EchoRoundError; -pub use signature; pub use digest; +pub use signature; diff --git a/manul/src/session/echo.rs b/manul/src/session/echo.rs index 9e209ef..5bbd124 100644 --- a/manul/src/session/echo.rs +++ b/manul/src/session/echo.rs @@ -12,7 +12,7 @@ use serde::{Deserialize, Serialize}; use tracing::debug; use super::{ - message::{MessageVerificationError, SignedMessage}, + message::{MessageVerificationError, SignedMessagePart}, session::SessionParameters, LocalError, }; @@ -42,8 +42,8 @@ pub(crate) enum EchoRoundError { MismatchedBroadcasts { guilty_party: Id, error: MismatchedBroadcastsError, - we_received: SignedMessage, - echoed_to_us: SignedMessage, + we_received: SignedMessagePart, + echoed_to_us: SignedMessagePart, }, } @@ -68,7 +68,7 @@ pub(crate) enum MismatchedBroadcastsError { #[derive(Debug, Clone, Serialize, Deserialize)] pub(crate) struct EchoRoundMessage { - pub(super) echo_broadcasts: SerializableMap>, + pub(super) echo_broadcasts: SerializableMap>, } /// Each protocol round can contain one `EchoRound` with "echo messages" that are sent to all @@ -77,7 +77,7 @@ pub(crate) struct EchoRoundMessage { #[derive_where::derive_where(Debug)] pub struct EchoRound { verifier: SP::Verifier, - echo_broadcasts: BTreeMap>, + echo_broadcasts: BTreeMap>, destinations: BTreeSet, expected_echos: BTreeSet, main_round: Box>, @@ -92,8 +92,8 @@ where { pub fn new( verifier: SP::Verifier, - my_echo_broadcast: SignedMessage, - echo_broadcasts: BTreeMap>, + my_echo_broadcast: SignedMessagePart, + echo_broadcasts: BTreeMap>, main_round: Box>, payloads: BTreeMap, artifacts: BTreeMap, diff --git a/manul/src/session/evidence.rs b/manul/src/session/evidence.rs index ef9206a..c0fab32 100644 --- a/manul/src/session/evidence.rs +++ b/manul/src/session/evidence.rs @@ -10,7 +10,7 @@ use serde::{Deserialize, Serialize}; use super::{ echo::{EchoRound, EchoRoundError, EchoRoundMessage, MismatchedBroadcastsError}, - message::{MessageVerificationError, MissingMessage, SignedMessage}, + message::{MessageVerificationError, SignedMessagePart}, session::SessionParameters, transcript::Transcript, LocalError, @@ -89,9 +89,9 @@ where { pub(crate) fn new_protocol_error( verifier: &SP::Verifier, - echo_broadcast: SignedMessage, - normal_broadcast: SignedMessage, - direct_message: SignedMessage, + echo_broadcast: SignedMessagePart, + normal_broadcast: SignedMessagePart, + direct_message: SignedMessagePart, error: P::ProtocolError, transcript: &Transcript, ) -> Result { @@ -155,7 +155,7 @@ where pub(crate) fn new_echo_round_error( verifier: &SP::Verifier, - normal_broadcast: SignedMessage, + normal_broadcast: SignedMessagePart, error: EchoRoundError, ) -> Result { let description = format!("Echo round error: {}", error.description()); @@ -187,7 +187,7 @@ where pub(crate) fn new_invalid_direct_message( verifier: &SP::Verifier, - direct_message: SignedMessage, + direct_message: SignedMessagePart, error: DirectMessageError, ) -> Self { Self { @@ -202,7 +202,7 @@ where pub(crate) fn new_invalid_echo_broadcast( verifier: &SP::Verifier, - echo_broadcast: SignedMessage, + echo_broadcast: SignedMessagePart, error: EchoBroadcastError, ) -> Self { Self { @@ -217,7 +217,7 @@ where pub(crate) fn new_invalid_normal_broadcast( verifier: &SP::Verifier, - normal_broadcast: SignedMessage, + normal_broadcast: SignedMessagePart, error: NormalBroadcastError, ) -> Self { Self { @@ -271,7 +271,7 @@ enum EvidenceEnum { #[derive_where::derive_where(Debug)] #[derive(Clone, Serialize, Deserialize)] pub struct InvalidEchoPackEvidence { - normal_broadcast: SignedMessage, + normal_broadcast: SignedMessagePart, invalid_echo_sender: SP::Verifier, } @@ -315,8 +315,8 @@ where #[derive(Debug, Clone, Serialize, Deserialize)] pub struct MismatchedBroadcastsEvidence { error: MismatchedBroadcastsError, - we_received: SignedMessage, - echoed_to_us: SignedMessage, + we_received: SignedMessagePart, + echoed_to_us: SignedMessagePart, } impl MismatchedBroadcastsEvidence { @@ -351,7 +351,7 @@ impl MismatchedBroadcastsEvidence { #[derive_where::derive_where(Debug)] #[derive(Clone, Serialize, Deserialize)] pub struct InvalidDirectMessageEvidence { - direct_message: SignedMessage, + direct_message: SignedMessagePart, phantom: core::marker::PhantomData

, } @@ -381,7 +381,7 @@ where #[derive_where::derive_where(Debug)] #[derive(Clone, Serialize, Deserialize)] pub struct InvalidEchoBroadcastEvidence { - echo_broadcast: SignedMessage, + echo_broadcast: SignedMessagePart, phantom: core::marker::PhantomData

, } @@ -411,7 +411,7 @@ where #[derive_where::derive_where(Debug)] #[derive(Clone, Serialize, Deserialize)] pub struct InvalidNormalBroadcastEvidence { - normal_broadcast: SignedMessage, + normal_broadcast: SignedMessagePart, phantom: core::marker::PhantomData

, } @@ -445,13 +445,13 @@ where #[derive(Clone, Serialize, Deserialize)] struct ProtocolEvidence { error: P::ProtocolError, - direct_message: SignedMessage, - echo_broadcast: SignedMessage, - normal_broadcast: SignedMessage, - direct_messages: SerializableMap>, - echo_broadcasts: SerializableMap>, - normal_broadcasts: SerializableMap>, - combined_echos: SerializableMap>, + direct_message: SignedMessagePart, + echo_broadcast: SignedMessagePart, + normal_broadcast: SignedMessagePart, + direct_messages: SerializableMap>, + echo_broadcasts: SerializableMap>, + normal_broadcasts: SerializableMap>, + combined_echos: SerializableMap>, } impl

ProtocolEvidence

diff --git a/manul/src/session/message.rs b/manul/src/session/message.rs index 4f23edd..e25fe66 100644 --- a/manul/src/session/message.rs +++ b/manul/src/session/message.rs @@ -44,7 +44,7 @@ pub(crate) enum MessageVerificationError { } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub(crate) struct SignedMessage { +pub(crate) struct SignedMessagePart { signature: SerializedSignature, message_with_metadata: MessageWithMetadata, } @@ -84,7 +84,7 @@ impl MessageWithMetadata { SP: SessionParameters, { let digest = - SP::Digest::new_with_prefix(b"SignedMessage").chain_update(SP::WireFormat::serialize(&self.metadata)?); + SP::Digest::new_with_prefix(b"SignedMessagePart").chain_update(SP::WireFormat::serialize(&self.metadata)?); let digest = match self.message.maybe_message().as_ref() { None => digest.chain_update([0u8]), @@ -95,7 +95,7 @@ impl MessageWithMetadata { } } -impl SignedMessage +impl SignedMessagePart where M: ProtocolMessagePart, { @@ -129,7 +129,7 @@ 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 SP: SessionParameters, { @@ -142,7 +142,7 @@ where .deserialize::() .map_err(|_| MessageVerificationError::InvalidSignature)?; if verifier.verify_digest(digest, &signature).is_ok() { - Ok(VerifiedMessage { + Ok(VerifiedMessagePart { signature: self.signature, message_with_metadata: self.message_with_metadata, }) @@ -153,12 +153,12 @@ where } #[derive(Debug, Clone)] -pub struct VerifiedMessage { +pub struct VerifiedMessagePart { signature: SerializedSignature, message_with_metadata: MessageWithMetadata, } -impl VerifiedMessage { +impl VerifiedMessagePart { pub(crate) fn metadata(&self) -> &MessageMetadata { &self.message_with_metadata.metadata } @@ -167,27 +167,23 @@ impl VerifiedMessage { &self.message_with_metadata.message } - pub fn into_unverified(self) -> SignedMessage { - SignedMessage { + pub fn into_unverified(self) -> SignedMessagePart { + SignedMessagePart { signature: self.signature, message_with_metadata: self.message_with_metadata, } } } -/// A message bundle destined for another node. -/// -/// During message pre-processing, a `MessageBundle` transitions to a `CheckedMessageBundle`. -/// -/// Note that this is already signed. +/// A signed message destined for another node. #[derive(Clone, Debug)] -pub struct MessageBundle { - direct_message: SignedMessage, - echo_broadcast: SignedMessage, - normal_broadcast: SignedMessage, +pub struct Message { + direct_message: SignedMessagePart, + echo_broadcast: SignedMessagePart, + normal_broadcast: SignedMessagePart, } -impl MessageBundle { +impl Message { #[allow(clippy::too_many_arguments)] pub(crate) fn new( rng: &mut impl CryptoRngCore, @@ -195,13 +191,13 @@ impl MessageBundle { session_id: &SessionId, round_id: RoundId, direct_message: DirectMessage, - echo_broadcast: SignedMessage, - normal_broadcast: SignedMessage, + echo_broadcast: SignedMessagePart, + normal_broadcast: SignedMessagePart, ) -> Result where SP: SessionParameters, { - let direct_message = SignedMessage::new::(rng, signer, session_id, round_id, direct_message)?; + let direct_message = SignedMessagePart::new::(rng, signer, session_id, round_id, direct_message)?; Ok(Self { direct_message, echo_broadcast, @@ -209,7 +205,7 @@ impl MessageBundle { }) } - pub(crate) fn unify_metadata(self) -> Option { + pub(crate) fn unify_metadata(self) -> Option { if self.echo_broadcast.metadata() != self.direct_message.metadata() { return None; } @@ -219,7 +215,7 @@ impl MessageBundle { } let metadata = self.direct_message.message_with_metadata.metadata.clone(); - Some(CheckedMessageBundle { + Some(CheckedMessage { metadata, direct_message: self.direct_message, echo_broadcast: self.echo_broadcast, @@ -228,24 +224,24 @@ impl MessageBundle { } } -/// A `CheckedMessageBundle` is like a [`MessageBundle`] but where we have checked that the metadata +/// A `CheckedMessage` is like a [`Message`] but where we have checked that the metadata /// (i.e. SessionId and RoundId) from the Echo message (if any) matches with that of the /// [`DirectMessage`]. -/// `CheckedMessageBundle`s can transition to [`VerifiedMessageBundle`]. +/// `CheckedMessage`s can transition to [`VerifiedMessage`]. #[derive(Clone, Debug)] -pub(crate) struct CheckedMessageBundle { +pub(crate) struct CheckedMessage { metadata: MessageMetadata, - direct_message: SignedMessage, - echo_broadcast: SignedMessage, - normal_broadcast: SignedMessage, + direct_message: SignedMessagePart, + echo_broadcast: SignedMessagePart, + normal_broadcast: SignedMessagePart, } -impl CheckedMessageBundle { +impl CheckedMessage { 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 SP: SessionParameters, { @@ -253,7 +249,7 @@ impl CheckedMessageBundle { let echo_broadcast = self.echo_broadcast.verify::(verifier)?; let normal_broadcast = self.normal_broadcast.verify::(verifier)?; - Ok(VerifiedMessageBundle { + Ok(VerifiedMessage { from: verifier.clone(), metadata: self.metadata, direct_message, @@ -263,20 +259,22 @@ impl CheckedMessageBundle { } } -/// A `VerifiedMessageBundle` is the final evolution of a [`MessageBundle`]. At this point in the -/// process, the [`DirectMessage`] and an eventual [`EchoBroadcast`] have been fully checked and the -/// signature on the [`SignedMessage`] from the original [`MessageBundle`] successfully verified. +// A `VerifiedMessage` is the final evolution of a [`Message`]. At this point in the +// process, the [`DirectMessage`] and an eventual [`EchoBroadcast`] have been fully checked and the +// signatures of message parts (direct, broadcast etc) from the original [`Message`] successfully verified. + +/// A [`Message`] that had its metadata and signatures verified. #[derive_where::derive_where(Debug)] #[derive(Clone)] -pub struct VerifiedMessageBundle { +pub struct VerifiedMessage { from: SP::Verifier, metadata: MessageMetadata, - direct_message: VerifiedMessage, - echo_broadcast: VerifiedMessage, - normal_broadcast: VerifiedMessage, + direct_message: VerifiedMessagePart, + echo_broadcast: VerifiedMessagePart, + normal_broadcast: VerifiedMessagePart, } -impl VerifiedMessageBundle +impl VerifiedMessage where SP: SessionParameters, { @@ -300,14 +298,14 @@ where self.normal_broadcast.payload() } - /// Split the `VerifiedMessageBundle` into its signed constituent parts: + /// Split the `VerifiedMessage` into its signed constituent parts: /// the echo broadcast and the direct message. pub(crate) fn into_parts( self, ) -> ( - SignedMessage, - SignedMessage, - SignedMessage, + SignedMessagePart, + SignedMessagePart, + SignedMessagePart, ) { let direct_message = self.direct_message.into_unverified(); let echo_broadcast = self.echo_broadcast.into_unverified(); diff --git a/manul/src/session/session.rs b/manul/src/session/session.rs index 04d9fdc..b1a084b 100644 --- a/manul/src/session/session.rs +++ b/manul/src/session/session.rs @@ -16,7 +16,7 @@ use tracing::{debug, trace}; use super::{ echo::EchoRound, evidence::Evidence, - message::{MessageBundle, MessageVerificationError, SignedMessage, VerifiedMessageBundle}, + message::{Message, MessageVerificationError, SignedMessagePart, VerifiedMessage}, transcript::{SessionOutcome, SessionReport, Transcript}, wire_format::WireFormat, LocalError, RemoteError, @@ -114,8 +114,8 @@ pub struct Session { deserializer: Deserializer, round: Box>, message_destinations: BTreeSet, - echo_broadcast: SignedMessage, - normal_broadcast: SignedMessage, + echo_broadcast: SignedMessagePart, + normal_broadcast: SignedMessagePart, possible_next_rounds: BTreeSet, transcript: Transcript, } @@ -130,7 +130,7 @@ pub enum RoundOutcome { /// The session object for the new round. session: Session, /// The messages intended for the new round cached during the previous round. - cached_messages: Vec>, + cached_messages: Vec>, }, } @@ -181,10 +181,10 @@ where let verifier = signer.verifying_key(); let echo = round.make_echo_broadcast(rng, &serializer)?; - let echo_broadcast = SignedMessage::new::(rng, &signer, &session_id, round.id(), echo)?; + let echo_broadcast = SignedMessagePart::new::(rng, &signer, &session_id, round.id(), echo)?; let normal = round.make_normal_broadcast(rng, &serializer)?; - let normal_broadcast = SignedMessage::new::(rng, &signer, &session_id, round.id(), normal)?; + let normal_broadcast = SignedMessagePart::new::(rng, &signer, &session_id, round.id(), normal)?; let message_destinations = round.message_destinations().clone(); @@ -231,12 +231,12 @@ where &self, rng: &mut impl CryptoRngCore, destination: &SP::Verifier, - ) -> Result<(MessageBundle, ProcessedArtifact), LocalError> { + ) -> Result<(Message, ProcessedArtifact), LocalError> { let (direct_message, artifact) = self.round .make_direct_message_with_artifact(rng, &self.serializer, destination)?; - let bundle = MessageBundle::new::( + let message = Message::new::( rng, &self.signer, &self.session_id, @@ -246,13 +246,12 @@ where self.normal_broadcast.clone(), )?; - Ok(( - bundle, - ProcessedArtifact { - destination: destination.clone(), - artifact, - }, - )) + let processed_artifact = ProcessedArtifact { + destination: destination.clone(), + artifact, + }; + + Ok((message, processed_artifact)) } /// Adds the artifact from [`make_message`](`Self::make_message`) to the accumulator. @@ -286,8 +285,8 @@ where &self, accum: &mut RoundAccumulator, from: &SP::Verifier, - message: MessageBundle, - ) -> Result>, LocalError> { + message: Message, + ) -> Result>, LocalError> { // Quick preliminary checks, before we proceed with more expensive verification let key = self.verifier(); if self.transcript.is_banned(from) || accum.is_banned(from) { @@ -382,7 +381,7 @@ where pub fn process_message( &self, rng: &mut impl CryptoRngCore, - message: VerifiedMessageBundle, + message: VerifiedMessage, ) -> ProcessedMessage { let processed = self.round.receive_message( rng, @@ -545,10 +544,10 @@ pub struct RoundAccumulator { processing: BTreeSet, payloads: BTreeMap, artifacts: BTreeMap, - cached: BTreeMap>>, - echo_broadcasts: BTreeMap>, - normal_broadcasts: BTreeMap>, - direct_messages: BTreeMap>, + cached: BTreeMap>>, + echo_broadcasts: BTreeMap>, + normal_broadcasts: BTreeMap>, + direct_messages: BTreeMap>, provable_errors: BTreeMap>, unprovable_errors: BTreeMap, } @@ -626,7 +625,7 @@ where } } - fn mark_processing(&mut self, message: &VerifiedMessageBundle) -> Result<(), LocalError> { + fn mark_processing(&mut self, message: &VerifiedMessage) -> Result<(), LocalError> { if !self.processing.insert(message.from().clone()) { Err(LocalError::new(format!( "A message from {:?} is already marked as being processed", @@ -733,7 +732,7 @@ where } } - fn cache_message(&mut self, message: VerifiedMessageBundle) -> Result<(), LocalError> { + fn cache_message(&mut self, message: VerifiedMessage) -> Result<(), LocalError> { let from = message.from().clone(); let round_id = message.metadata().round_id(); let cached = self.cached.entry(from.clone()).or_default(); @@ -755,14 +754,14 @@ pub struct ProcessedArtifact { #[derive(Debug)] pub struct ProcessedMessage { - message: VerifiedMessageBundle, + message: VerifiedMessage, processed: Result>, } fn filter_messages( - messages: BTreeMap>>, + messages: BTreeMap>>, round_id: RoundId, -) -> Vec> { +) -> Vec> { messages .into_values() .filter_map(|mut messages| messages.remove(&round_id)) @@ -776,7 +775,7 @@ mod tests { use impls::impls; use serde::{Deserialize, Serialize}; - use super::{MessageBundle, ProcessedArtifact, ProcessedMessage, Session, VerifiedMessageBundle}; + use super::{Message, ProcessedArtifact, ProcessedMessage, Session, VerifiedMessage}; use crate::{ protocol::{ Deserializer, DirectMessage, EchoBroadcast, NormalBroadcast, Protocol, ProtocolError, @@ -836,9 +835,9 @@ mod tests { assert!(impls!(Session: Sync)); // These objects are sent to/from message processing tasks - assert!(impls!(MessageBundle: Send)); + assert!(impls!(Message: Send)); assert!(impls!(ProcessedArtifact: Send)); - assert!(impls!(VerifiedMessageBundle: Send)); + assert!(impls!(VerifiedMessage: Send)); assert!(impls!(ProcessedMessage: Send)); } } diff --git a/manul/src/session/transcript.rs b/manul/src/session/transcript.rs index edb2c18..a1d2cfe 100644 --- a/manul/src/session/transcript.rs +++ b/manul/src/session/transcript.rs @@ -4,14 +4,14 @@ use alloc::{ }; use core::fmt::Debug; -use super::{evidence::Evidence, message::SignedMessage, session::SessionParameters, LocalError, RemoteError}; +use super::{evidence::Evidence, message::SignedMessagePart, session::SessionParameters, LocalError, RemoteError}; use crate::protocol::{DirectMessage, EchoBroadcast, NormalBroadcast, Protocol, RoundId}; #[derive(Debug)] pub(crate) struct Transcript { - echo_broadcasts: BTreeMap>>, - normal_broadcasts: BTreeMap>>, - direct_messages: BTreeMap>>, + echo_broadcasts: BTreeMap>>, + normal_broadcasts: BTreeMap>>, + direct_messages: BTreeMap>>, provable_errors: BTreeMap>, unprovable_errors: BTreeMap, missing_messages: BTreeMap>, @@ -37,9 +37,9 @@ where pub fn update( self, round_id: RoundId, - echo_broadcasts: BTreeMap>, - normal_broadcasts: BTreeMap>, - direct_messages: BTreeMap>, + echo_broadcasts: BTreeMap>, + normal_broadcasts: BTreeMap>, + direct_messages: BTreeMap>, provable_errors: BTreeMap>, unprovable_errors: BTreeMap, missing_messages: BTreeSet, @@ -116,7 +116,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:?}")))? @@ -129,7 +129,7 @@ where &self, round_id: RoundId, from: &SP::Verifier, - ) -> Result, LocalError> { + ) -> Result, LocalError> { self.normal_broadcasts .get(&round_id) .ok_or_else(|| LocalError::new(format!("No normal broadcasts registered for {round_id:?}")))? @@ -142,7 +142,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:?}")))? @@ -158,7 +158,7 @@ where 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 4a45f69..9cd08de 100644 --- a/manul/src/testing/run_sync.rs +++ b/manul/src/testing/run_sync.rs @@ -8,7 +8,7 @@ use tracing::debug; use crate::{ protocol::{FirstRound, Protocol}, session::{ - CanFinalize, LocalError, MessageBundle, RoundAccumulator, RoundOutcome, Session, SessionId, SessionParameters, + CanFinalize, LocalError, Message, RoundAccumulator, RoundOutcome, Session, SessionId, SessionParameters, SessionReport, }, }; @@ -21,10 +21,10 @@ enum State { Finished(SessionReport), } -struct Message { +struct RoundMessage { from: SP::Verifier, to: SP::Verifier, - message: MessageBundle, + message: Message, } #[allow(clippy::type_complexity)] @@ -32,7 +32,7 @@ fn propagate( rng: &mut impl CryptoRngCore, session: Session, accum: RoundAccumulator, -) -> Result<(State, Vec>), LocalError> +) -> Result<(State, Vec>), LocalError> where P: 'static + Protocol, SP: 'static + SessionParameters, @@ -74,7 +74,7 @@ where let destinations = session.message_destinations(); for destination in destinations { let (message, artifact) = session.make_message(rng, destination)?; - messages.push(Message { + messages.push(RoundMessage { from: session.verifier().clone(), to: destination.clone(), message, @@ -110,7 +110,7 @@ where let destinations = session.message_destinations(); for destination in destinations { let (message, artifact) = session.make_message(rng, destination)?; - messages.push(Message { + messages.push(RoundMessage { from: session.verifier().clone(), to: destination.clone(), message, From fed74b138a5e56d32a533055029c78c9661f9aff Mon Sep 17 00:00:00 2001 From: Bogdan Opanchuk Date: Wed, 30 Oct 2024 12:03:58 -0700 Subject: [PATCH 4/4] Make `Message` and `VerifiedMessage` generic over `Verifier` --- CHANGELOG.md | 3 ++- examples/tests/async_runner.rs | 4 ++-- manul/src/session.rs | 2 +- manul/src/session/message.rs | 31 +++++++++++++++++++------------ manul/src/session/session.rs | 31 ++++++++++++++++--------------- manul/src/testing/run_sync.rs | 2 +- 6 files changed, 41 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c6842f7..191bd9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `EchoBroadcast` and `DirectMessage` now use `ProtocolMessagePart` trait for their methods. ([#47]) - Added normal broadcasts support in addition to echo ones; signatures of `Round` methods changed accordingly; added `Round::make_normal_broadcast()`. ([#47]) - Serialization format is a part of `SessionParameters` now; `Round` and `Protocol` methods receive dynamic serializers/deserializers. ([#33]) -- Renamed `(Verified)MessageBundle` to `(Verified)Message`. ([#56]) +- Renamed `(Verified)MessageBundle` to `(Verified)Message`. Both are now generic over `Verifier`. ([#56]) ### Added @@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `SerializableMap` wrapper for `BTreeMap` supporting more formats and providing some safety features. (#[32]) - `DirectMessage::assert_is_none()` and `verify_is_some()`, same for `EchoBroadcast`. Users can now check that a part of the round message (echo or direct) is `None` as expected, and make a verifiable evidence if it is not. ([#46]) - Re-export `digest` from the `session` module. ([#56]) +- Added `Message::destination()`. ([#56]) [#32]: https://github.com/entropyxyz/manul/pull/32 diff --git a/examples/tests/async_runner.rs b/examples/tests/async_runner.rs index 1c52472..008ee82 100644 --- a/examples/tests/async_runner.rs +++ b/examples/tests/async_runner.rs @@ -23,12 +23,12 @@ use tracing_subscriber::{util::SubscriberInitExt, EnvFilter}; struct MessageOut { from: SP::Verifier, to: SP::Verifier, - message: Message, + message: Message, } struct MessageIn { from: SP::Verifier, - message: Message, + message: Message, } /// Runs a session. Simulates what each participating party would run as the protocol progresses. diff --git a/manul/src/session.rs b/manul/src/session.rs index 83791b8..3710d96 100644 --- a/manul/src/session.rs +++ b/manul/src/session.rs @@ -17,7 +17,7 @@ mod wire_format; pub use crate::protocol::{LocalError, RemoteError}; pub use evidence::{Evidence, EvidenceError}; -pub use message::{VerifiedMessage, Message}; +pub use message::{Message, VerifiedMessage}; pub use session::{CanFinalize, RoundAccumulator, RoundOutcome, Session, SessionId, SessionParameters}; pub use transcript::{SessionOutcome, SessionReport}; pub use wire_format::WireFormat; diff --git a/manul/src/session/message.rs b/manul/src/session/message.rs index e25fe66..51dbc55 100644 --- a/manul/src/session/message.rs +++ b/manul/src/session/message.rs @@ -177,19 +177,24 @@ impl VerifiedMessagePart { /// A signed message destined for another node. #[derive(Clone, Debug)] -pub struct Message { +pub struct Message { + destination: Verifier, direct_message: SignedMessagePart, echo_broadcast: SignedMessagePart, normal_broadcast: SignedMessagePart, } -impl Message { +impl Message +where + Verifier: Clone, +{ #[allow(clippy::too_many_arguments)] pub(crate) fn new( rng: &mut impl CryptoRngCore, signer: &SP::Signer, session_id: &SessionId, round_id: RoundId, + destination: &Verifier, direct_message: DirectMessage, echo_broadcast: SignedMessagePart, normal_broadcast: SignedMessagePart, @@ -199,12 +204,18 @@ impl Message { { let direct_message = SignedMessagePart::new::(rng, signer, session_id, round_id, direct_message)?; Ok(Self { + destination: destination.clone(), direct_message, echo_broadcast, normal_broadcast, }) } + /// The verifier of the party this message is intended for. + pub fn destination(&self) -> &Verifier { + &self.destination + } + pub(crate) fn unify_metadata(self) -> Option { if self.echo_broadcast.metadata() != self.direct_message.metadata() { return None; @@ -241,7 +252,7 @@ impl CheckedMessage { &self.metadata } - pub fn verify(self, verifier: &SP::Verifier) -> Result, MessageVerificationError> + pub fn verify(self, verifier: &SP::Verifier) -> Result, MessageVerificationError> where SP: SessionParameters, { @@ -264,25 +275,21 @@ impl CheckedMessage { // signatures of message parts (direct, broadcast etc) from the original [`Message`] successfully verified. /// A [`Message`] that had its metadata and signatures verified. -#[derive_where::derive_where(Debug)] -#[derive(Clone)] -pub struct VerifiedMessage { - from: SP::Verifier, +#[derive(Debug, Clone)] +pub struct VerifiedMessage { + from: Verifier, metadata: MessageMetadata, direct_message: VerifiedMessagePart, echo_broadcast: VerifiedMessagePart, normal_broadcast: VerifiedMessagePart, } -impl VerifiedMessage -where - SP: SessionParameters, -{ +impl VerifiedMessage { pub(crate) fn metadata(&self) -> &MessageMetadata { &self.metadata } - pub(crate) fn from(&self) -> &SP::Verifier { + pub(crate) fn from(&self) -> &Verifier { &self.from } diff --git a/manul/src/session/session.rs b/manul/src/session/session.rs index b1a084b..210e0b7 100644 --- a/manul/src/session/session.rs +++ b/manul/src/session/session.rs @@ -130,7 +130,7 @@ pub enum RoundOutcome { /// The session object for the new round. session: Session, /// The messages intended for the new round cached during the previous round. - cached_messages: Vec>, + cached_messages: Vec>, }, } @@ -231,7 +231,7 @@ where &self, rng: &mut impl CryptoRngCore, destination: &SP::Verifier, - ) -> Result<(Message, ProcessedArtifact), LocalError> { + ) -> Result<(Message, ProcessedArtifact), LocalError> { let (direct_message, artifact) = self.round .make_direct_message_with_artifact(rng, &self.serializer, destination)?; @@ -241,6 +241,7 @@ where &self.signer, &self.session_id, self.round.id(), + destination, direct_message, self.echo_broadcast.clone(), self.normal_broadcast.clone(), @@ -285,8 +286,8 @@ where &self, accum: &mut RoundAccumulator, from: &SP::Verifier, - message: Message, - ) -> Result>, LocalError> { + message: Message, + ) -> Result>, LocalError> { // Quick preliminary checks, before we proceed with more expensive verification let key = self.verifier(); if self.transcript.is_banned(from) || accum.is_banned(from) { @@ -381,7 +382,7 @@ where pub fn process_message( &self, rng: &mut impl CryptoRngCore, - message: VerifiedMessage, + message: VerifiedMessage, ) -> ProcessedMessage { let processed = self.round.receive_message( rng, @@ -544,7 +545,7 @@ pub struct RoundAccumulator { processing: BTreeSet, payloads: BTreeMap, artifacts: BTreeMap, - cached: BTreeMap>>, + cached: BTreeMap>>, echo_broadcasts: BTreeMap>, normal_broadcasts: BTreeMap>, direct_messages: BTreeMap>, @@ -625,7 +626,7 @@ where } } - fn mark_processing(&mut self, message: &VerifiedMessage) -> Result<(), LocalError> { + fn mark_processing(&mut self, message: &VerifiedMessage) -> Result<(), LocalError> { if !self.processing.insert(message.from().clone()) { Err(LocalError::new(format!( "A message from {:?} is already marked as being processed", @@ -732,7 +733,7 @@ where } } - fn cache_message(&mut self, message: VerifiedMessage) -> Result<(), LocalError> { + fn cache_message(&mut self, message: VerifiedMessage) -> Result<(), LocalError> { let from = message.from().clone(); let round_id = message.metadata().round_id(); let cached = self.cached.entry(from.clone()).or_default(); @@ -754,14 +755,14 @@ pub struct ProcessedArtifact { #[derive(Debug)] pub struct ProcessedMessage { - message: VerifiedMessage, + message: VerifiedMessage, 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)) @@ -781,7 +782,7 @@ mod tests { Deserializer, DirectMessage, EchoBroadcast, NormalBroadcast, Protocol, ProtocolError, ProtocolValidationError, RoundId, }, - testing::{BinaryFormat, TestSessionParams}, + testing::{BinaryFormat, TestSessionParams, TestVerifier}, }; #[test] @@ -835,9 +836,9 @@ mod tests { assert!(impls!(Session: Sync)); // These objects are sent to/from message processing tasks - assert!(impls!(Message: Send)); + assert!(impls!(Message: Send)); assert!(impls!(ProcessedArtifact: Send)); - assert!(impls!(VerifiedMessage: Send)); + assert!(impls!(VerifiedMessage: Send)); assert!(impls!(ProcessedMessage: Send)); } } diff --git a/manul/src/testing/run_sync.rs b/manul/src/testing/run_sync.rs index 9cd08de..1ca8669 100644 --- a/manul/src/testing/run_sync.rs +++ b/manul/src/testing/run_sync.rs @@ -24,7 +24,7 @@ enum State { struct RoundMessage { from: SP::Verifier, to: SP::Verifier, - message: Message, + message: Message, } #[allow(clippy::type_complexity)]