From 44914dfe7b7de28549a27abbdeaf298b23cf0a27 Mon Sep 17 00:00:00 2001 From: Bogdan Opanchuk Date: Sun, 16 Feb 2025 15:25:21 -0800 Subject: [PATCH 1/8] Bump serde-encoded-bytes to 0.2 --- Cargo.lock | 8 ++++---- manul/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6e68fae..308c07a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -119,9 +119,9 @@ dependencies = [ [[package]] name = "base64" -version = "0.21.7" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "block-buffer" @@ -881,9 +881,9 @@ dependencies = [ [[package]] name = "serde-encoded-bytes" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec007ca0e3db940a5409d65780b6bd0202cbea68800861ae876b80655ee8e24b" +checksum = "41015be3fac3ea5ca130f052836e50662c574547baca4d482e69e834f266e8d5" dependencies = [ "base64", "hex", diff --git a/manul/Cargo.toml b/manul/Cargo.toml index 39a4d9d..82ded49 100644 --- a/manul/Cargo.toml +++ b/manul/Cargo.toml @@ -13,7 +13,7 @@ categories = ["cryptography", "no-std"] [dependencies] serde = { version = "1", default-features = false, features = ["alloc", "serde_derive"] } erased-serde = { version = "0.4", default-features = false, features = ["alloc"] } -serde-encoded-bytes = { version = "0.1", default-features = false, features = ["hex", "base64"] } +serde-encoded-bytes = { version = "0.2", 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 } From 1650aae26d9ee90b7cd99d0675704ce25e6fa97c Mon Sep 17 00:00:00 2001 From: Bogdan Opanchuk Date: Wed, 19 Feb 2025 00:07:29 -0800 Subject: [PATCH 2/8] Rename `Payload::try_to_typed()` and `Artifact::try_to_typed()` to `downcast()` --- CHANGELOG.md | 2 ++ examples/src/simple.rs | 4 ++-- manul/benches/async_session.rs | 4 ++-- manul/benches/empty_rounds.rs | 4 ++-- manul/src/protocol/round.rs | 4 ++-- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d92da09..c6c53a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Removed `Send` bound on `ProtocolError`. ([#92]) - Merged `Round::id()`, `possible_next_rounds()` and `may_produce_result()` into `transition_info()`. ([#93]) - Merged `Round::message_destinations()`, `expecting_messages_from()` and `echo_round_participation()` into `communication_info()`. ([#93]) +- Renamed `Payload::try_to_typed()` and `Artifact::try_to_typed()` to `downcast()`. ([#94]) ### Added @@ -64,6 +65,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [#91]: https://github.com/entropyxyz/manul/pull/91 [#92]: https://github.com/entropyxyz/manul/pull/92 [#93]: https://github.com/entropyxyz/manul/pull/93 +[#94]: https://github.com/entropyxyz/manul/pull/94 ## [0.1.0] - 2024-11-19 diff --git a/examples/src/simple.rs b/examples/src/simple.rs index ed52bfb..50e9d4e 100644 --- a/examples/src/simple.rs +++ b/examples/src/simple.rs @@ -283,7 +283,7 @@ impl Round for Round1 { let typed_payloads = payloads .into_values() - .map(|payload| payload.try_to_typed::()) + .map(|payload| payload.downcast::()) .collect::, _>>()?; let sum = self.context.ids_to_positions[&self.context.id] + typed_payloads.iter().map(|payload| payload.x).sum::(); @@ -371,7 +371,7 @@ impl Round for Round2 { let typed_payloads = payloads .into_values() - .map(|payload| payload.try_to_typed::()) + .map(|payload| payload.downcast::()) .collect::, _>>()?; let sum = self.context.ids_to_positions[&self.context.id] + typed_payloads.iter().map(|payload| payload.x).sum::(); diff --git a/manul/benches/async_session.rs b/manul/benches/async_session.rs index e6d39a6..ee7bc62 100644 --- a/manul/benches/async_session.rs +++ b/manul/benches/async_session.rs @@ -169,10 +169,10 @@ impl Round for EmptyRound { artifacts: BTreeMap, ) -> Result, LocalError> { for payload in payloads.into_values() { - let _payload = payload.try_to_typed::()?; + let _payload = payload.downcast::()?; } for artifact in artifacts.into_values() { - let _artifact = artifact.try_to_typed::()?; + let _artifact = artifact.downcast::()?; } if self.round_counter == self.inputs.rounds_num { diff --git a/manul/benches/empty_rounds.rs b/manul/benches/empty_rounds.rs index 0703c26..3495f7e 100644 --- a/manul/benches/empty_rounds.rs +++ b/manul/benches/empty_rounds.rs @@ -156,10 +156,10 @@ impl Round for EmptyRound { artifacts: BTreeMap, ) -> Result, LocalError> { for payload in payloads.into_values() { - let _payload = payload.try_to_typed::()?; + let _payload = payload.downcast::()?; } for artifact in artifacts.into_values() { - let _artifact = artifact.try_to_typed::()?; + let _artifact = artifact.downcast::()?; } if self.round_counter == self.inputs.rounds_num { diff --git a/manul/src/protocol/round.rs b/manul/src/protocol/round.rs index e535136..99d2da5 100644 --- a/manul/src/protocol/round.rs +++ b/manul/src/protocol/round.rs @@ -279,7 +279,7 @@ impl Payload { /// Attempts to downcast back to the concrete type. /// /// Would be normally called in [`Round::finalize`]. - pub fn try_to_typed(self) -> Result { + pub fn downcast(self) -> Result { Ok(*(self .0 .downcast::() @@ -302,7 +302,7 @@ impl Artifact { /// Attempts to downcast back to the concrete type. /// /// Would be normally called in [`Round::finalize`]. - pub fn try_to_typed(self) -> Result { + pub fn downcast(self) -> Result { Ok(*(self .0 .downcast::() From cc42aebaa83ec9ddab6ccb59470ad536bae650f1 Mon Sep 17 00:00:00 2001 From: Bogdan Opanchuk Date: Sun, 16 Feb 2025 15:52:49 -0800 Subject: [PATCH 3/8] Fix a comment in `Payload::empty()` --- manul/src/protocol/round.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manul/src/protocol/round.rs b/manul/src/protocol/round.rs index 99d2da5..f32c1ef 100644 --- a/manul/src/protocol/round.rs +++ b/manul/src/protocol/round.rs @@ -271,7 +271,7 @@ impl Payload { /// Creates an empty payload. /// - /// Use it in [`Round::receive_message`] if it does not need to create artifacts. + /// Use it in [`Round::receive_message`] if it does not need to create payloads. pub fn empty() -> Self { Self::new(()) } From 10fed4d3e1f8f8ce5e06fd40aac6d56bb63b1ad0 Mon Sep 17 00:00:00 2001 From: Bogdan Opanchuk Date: Wed, 19 Feb 2025 00:08:24 -0800 Subject: [PATCH 4/8] Use `dyn CryptoRngCore` in `Round` methods --- CHANGELOG.md | 1 + examples/src/simple.rs | 14 +++++----- examples/src/simple_malicious.rs | 2 +- manul/benches/async_session.rs | 8 +++--- manul/benches/empty_rounds.rs | 8 +++--- manul/src/combinators/chain.rs | 12 ++++----- manul/src/combinators/misbehave.rs | 42 +++++++++--------------------- manul/src/protocol.rs | 2 +- manul/src/protocol/object_safe.rs | 36 ++++--------------------- manul/src/protocol/round.rs | 10 +++---- manul/src/session/echo.rs | 4 +-- manul/src/tests/partial_echo.rs | 6 ++--- 12 files changed, 50 insertions(+), 95 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c6c53a0..bba1907 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Merged `Round::id()`, `possible_next_rounds()` and `may_produce_result()` into `transition_info()`. ([#93]) - Merged `Round::message_destinations()`, `expecting_messages_from()` and `echo_round_participation()` into `communication_info()`. ([#93]) - Renamed `Payload::try_to_typed()` and `Artifact::try_to_typed()` to `downcast()`. ([#94]) +- `Round` methods take `dyn CryptoRngCore` instead of `impl CryptoRngCore`. ([#94]) ### Added diff --git a/examples/src/simple.rs b/examples/src/simple.rs index 50e9d4e..642d558 100644 --- a/examples/src/simple.rs +++ b/examples/src/simple.rs @@ -166,7 +166,7 @@ impl EntryPoint for SimpleProtocolEntryPoint { fn make_round( self, - _rng: &mut impl CryptoRngCore, + _rng: &mut dyn CryptoRngCore, _shared_randomness: &[u8], id: &Id, ) -> Result, LocalError> { @@ -205,7 +205,7 @@ impl Round for Round1 { fn make_normal_broadcast( &self, - _rng: &mut impl CryptoRngCore, + _rng: &mut dyn CryptoRngCore, serializer: &Serializer, ) -> Result { debug!("{:?}: making normal broadcast", self.context.id); @@ -220,7 +220,7 @@ impl Round for Round1 { fn make_echo_broadcast( &self, - _rng: &mut impl CryptoRngCore, + _rng: &mut dyn CryptoRngCore, serializer: &Serializer, ) -> Result { debug!("{:?}: making echo broadcast", self.context.id); @@ -234,7 +234,7 @@ impl Round for Round1 { fn make_direct_message( &self, - _rng: &mut impl CryptoRngCore, + _rng: &mut dyn CryptoRngCore, serializer: &Serializer, destination: &Id, ) -> Result<(DirectMessage, Option), LocalError> { @@ -271,7 +271,7 @@ impl Round for Round1 { fn finalize( self, - _rng: &mut impl CryptoRngCore, + _rng: &mut dyn CryptoRngCore, payloads: BTreeMap, _artifacts: BTreeMap, ) -> Result, LocalError> { @@ -321,7 +321,7 @@ impl Round for Round2 { fn make_direct_message( &self, - _rng: &mut impl CryptoRngCore, + _rng: &mut dyn CryptoRngCore, serializer: &Serializer, destination: &Id, ) -> Result<(DirectMessage, Option), LocalError> { @@ -359,7 +359,7 @@ impl Round for Round2 { fn finalize( self, - _rng: &mut impl CryptoRngCore, + _rng: &mut dyn CryptoRngCore, payloads: BTreeMap, _artifacts: BTreeMap, ) -> Result, LocalError> { diff --git a/examples/src/simple_malicious.rs b/examples/src/simple_malicious.rs index a4bfbef..71e5220 100644 --- a/examples/src/simple_malicious.rs +++ b/examples/src/simple_malicious.rs @@ -28,7 +28,7 @@ impl Misbehaving for MaliciousLogic { type EntryPoint = SimpleProtocolEntryPoint; fn modify_direct_message( - _rng: &mut impl CryptoRngCore, + _rng: &mut dyn CryptoRngCore, round: &BoxedRound>::Protocol>, behavior: &Behavior, serializer: &Serializer, diff --git a/manul/benches/async_session.rs b/manul/benches/async_session.rs index ee7bc62..93728bc 100644 --- a/manul/benches/async_session.rs +++ b/manul/benches/async_session.rs @@ -91,7 +91,7 @@ impl EntryPoint for Inputs { fn make_round( self, - _rng: &mut impl CryptoRngCore, + _rng: &mut dyn CryptoRngCore, _shared_randomness: &[u8], _id: &Id, ) -> Result, LocalError> { @@ -119,7 +119,7 @@ impl Round for EmptyRound { fn make_echo_broadcast( &self, - _rng: &mut impl CryptoRngCore, + _rng: &mut dyn CryptoRngCore, serializer: &Serializer, ) -> Result { if self.inputs.echo { @@ -131,7 +131,7 @@ impl Round for EmptyRound { fn make_direct_message( &self, - _rng: &mut impl CryptoRngCore, + _rng: &mut dyn CryptoRngCore, serializer: &Serializer, _destination: &Id, ) -> Result<(DirectMessage, Option), LocalError> { @@ -164,7 +164,7 @@ impl Round for EmptyRound { fn finalize( self, - _rng: &mut impl CryptoRngCore, + _rng: &mut dyn CryptoRngCore, payloads: BTreeMap, artifacts: BTreeMap, ) -> Result, LocalError> { diff --git a/manul/benches/empty_rounds.rs b/manul/benches/empty_rounds.rs index 3495f7e..2b938e1 100644 --- a/manul/benches/empty_rounds.rs +++ b/manul/benches/empty_rounds.rs @@ -80,7 +80,7 @@ impl EntryPoint for Inputs { fn make_round( self, - _rng: &mut impl CryptoRngCore, + _rng: &mut dyn CryptoRngCore, _shared_randomness: &[u8], _id: &Id, ) -> Result, LocalError> { @@ -108,7 +108,7 @@ impl Round for EmptyRound { fn make_echo_broadcast( &self, - _rng: &mut impl CryptoRngCore, + _rng: &mut dyn CryptoRngCore, serializer: &Serializer, ) -> Result { if self.inputs.echo { @@ -120,7 +120,7 @@ impl Round for EmptyRound { fn make_direct_message( &self, - _rng: &mut impl CryptoRngCore, + _rng: &mut dyn CryptoRngCore, serializer: &Serializer, _destination: &Id, ) -> Result<(DirectMessage, Option), LocalError> { @@ -151,7 +151,7 @@ impl Round for EmptyRound { fn finalize( self, - _rng: &mut impl CryptoRngCore, + _rng: &mut dyn CryptoRngCore, payloads: BTreeMap, artifacts: BTreeMap, ) -> Result, LocalError> { diff --git a/manul/src/combinators/chain.rs b/manul/src/combinators/chain.rs index d3ee435..a38d98e 100644 --- a/manul/src/combinators/chain.rs +++ b/manul/src/combinators/chain.rs @@ -56,10 +56,9 @@ use rand_core::CryptoRngCore; use serde::{Deserialize, Serialize}; use crate::protocol::{ - Artifact, BoxedRng, BoxedRound, CommunicationInfo, Deserializer, DirectMessage, EchoBroadcast, EntryPoint, - FinalizeOutcome, LocalError, MessageValidationError, NormalBroadcast, ObjectSafeRound, PartyId, Payload, Protocol, - ProtocolError, ProtocolMessage, ProtocolValidationError, ReceiveError, RequiredMessages, RoundId, Serializer, - TransitionInfo, + Artifact, BoxedRound, CommunicationInfo, Deserializer, DirectMessage, EchoBroadcast, EntryPoint, FinalizeOutcome, + LocalError, MessageValidationError, NormalBroadcast, ObjectSafeRound, PartyId, Payload, Protocol, ProtocolError, + ProtocolMessage, ProtocolValidationError, ReceiveError, RequiredMessages, RoundId, Serializer, TransitionInfo, }; /// A marker trait that is used to disambiguate blanket trait implementations for [`Protocol`] and [`EntryPoint`]. @@ -299,7 +298,7 @@ where fn make_round( self, - rng: &mut impl CryptoRngCore, + rng: &mut dyn CryptoRngCore, shared_randomness: &[u8], id: &Id, ) -> Result, LocalError> { @@ -446,9 +445,8 @@ where shared_randomness, } => match round.into_boxed().finalize(rng, payloads, artifacts)? { FinalizeOutcome::Result(result) => { - let mut boxed_rng = BoxedRng(rng); let entry_point2 = transition.make_entry_point2(result); - let round = entry_point2.make_round(&mut boxed_rng, &shared_randomness, &id)?; + let round = entry_point2.make_round(rng, &shared_randomness, &id)?; Ok(FinalizeOutcome::AnotherRound(BoxedRound::new_object_safe( ChainedRound:: { diff --git a/manul/src/combinators/misbehave.rs b/manul/src/combinators/misbehave.rs index 5bfe276..a436244 100644 --- a/manul/src/combinators/misbehave.rs +++ b/manul/src/combinators/misbehave.rs @@ -29,9 +29,9 @@ use core::fmt::Debug; use rand_core::CryptoRngCore; use crate::protocol::{ - Artifact, BoxedRng, BoxedRound, CommunicationInfo, Deserializer, DirectMessage, EchoBroadcast, EntryPoint, - FinalizeOutcome, LocalError, NormalBroadcast, ObjectSafeRound, PartyId, Payload, Protocol, ProtocolMessage, - ReceiveError, RoundId, Serializer, TransitionInfo, + Artifact, BoxedRound, CommunicationInfo, Deserializer, DirectMessage, EchoBroadcast, EntryPoint, FinalizeOutcome, + LocalError, NormalBroadcast, ObjectSafeRound, PartyId, Payload, Protocol, ProtocolMessage, ReceiveError, RoundId, + Serializer, TransitionInfo, }; /// A trait describing required properties for a behavior type. @@ -56,7 +56,7 @@ where /// The default implementation passes through the original message. #[allow(unused_variables)] fn modify_echo_broadcast( - rng: &mut impl CryptoRngCore, + rng: &mut dyn CryptoRngCore, round: &BoxedRound>::Protocol>, behavior: &B, serializer: &Serializer, @@ -72,7 +72,7 @@ where /// The default implementation passes through the original message. #[allow(unused_variables)] fn modify_normal_broadcast( - rng: &mut impl CryptoRngCore, + rng: &mut dyn CryptoRngCore, round: &BoxedRound>::Protocol>, behavior: &B, serializer: &Serializer, @@ -88,7 +88,7 @@ where /// The default implementation passes through the original message. #[allow(unused_variables, clippy::too_many_arguments)] fn modify_direct_message( - rng: &mut impl CryptoRngCore, + rng: &mut dyn CryptoRngCore, round: &BoxedRound>::Protocol>, behavior: &B, serializer: &Serializer, @@ -109,7 +109,7 @@ where /// in which case the existing `finalize()` will not be called. #[allow(unused_variables)] fn override_finalize( - rng: &mut impl CryptoRngCore, + rng: &mut dyn CryptoRngCore, round: BoxedRound>::Protocol>, behavior: &B, payloads: BTreeMap, @@ -179,7 +179,7 @@ where fn make_round( self, - rng: &mut impl CryptoRngCore, + rng: &mut dyn CryptoRngCore, shared_randomness: &[u8], id: &Id, ) -> Result, LocalError> { @@ -250,9 +250,8 @@ where .as_ref() .make_direct_message(rng, serializer, deserializer, destination)?; if let Some(behavior) = self.behavior.as_ref() { - let mut boxed_rng = BoxedRng(rng); M::modify_direct_message( - &mut boxed_rng, + rng, &self.round, behavior, serializer, @@ -274,15 +273,7 @@ where ) -> Result { let echo_broadcast = self.round.as_ref().make_echo_broadcast(rng, serializer, deserializer)?; if let Some(behavior) = self.behavior.as_ref() { - let mut boxed_rng = BoxedRng(rng); - M::modify_echo_broadcast( - &mut boxed_rng, - &self.round, - behavior, - serializer, - deserializer, - echo_broadcast, - ) + M::modify_echo_broadcast(rng, &self.round, behavior, serializer, deserializer, echo_broadcast) } else { Ok(echo_broadcast) } @@ -299,15 +290,7 @@ where .as_ref() .make_normal_broadcast(rng, serializer, deserializer)?; if let Some(behavior) = self.behavior.as_ref() { - let mut boxed_rng = BoxedRng(rng); - M::modify_normal_broadcast( - &mut boxed_rng, - &self.round, - behavior, - serializer, - deserializer, - normal_broadcast, - ) + M::modify_normal_broadcast(rng, &self.round, behavior, serializer, deserializer, normal_broadcast) } else { Ok(normal_broadcast) } @@ -329,8 +312,7 @@ where artifacts: BTreeMap, ) -> Result, LocalError> { let (round, payloads, artifacts) = if let Some(behavior) = self.behavior.as_ref() { - let mut boxed_rng = BoxedRng(rng); - let result = M::override_finalize(&mut boxed_rng, self.round, behavior, payloads, artifacts)?; + let result = M::override_finalize(rng, self.round, behavior, payloads, artifacts)?; match result { FinalizeOverride::UseDefault { round, diff --git a/manul/src/protocol.rs b/manul/src/protocol.rs index 48e2858..be2c010 100644 --- a/manul/src/protocol.rs +++ b/manul/src/protocol.rs @@ -33,4 +33,4 @@ pub use serialization::{Deserializer, Serializer}; pub(crate) use errors::ReceiveErrorType; pub(crate) use message::ProtocolMessagePartHashable; -pub(crate) use object_safe::{BoxedRng, ObjectSafeRound}; +pub(crate) use object_safe::ObjectSafeRound; diff --git a/manul/src/protocol/object_safe.rs b/manul/src/protocol/object_safe.rs index 9a7c384..2caa535 100644 --- a/manul/src/protocol/object_safe.rs +++ b/manul/src/protocol/object_safe.rs @@ -1,7 +1,7 @@ use alloc::{boxed::Box, collections::BTreeMap, format}; use core::{fmt::Debug, marker::PhantomData}; -use rand_core::{CryptoRng, CryptoRngCore, RngCore}; +use rand_core::CryptoRngCore; use super::{ errors::{LocalError, ReceiveError}, @@ -11,28 +11,6 @@ use super::{ serialization::{Deserializer, Serializer}, }; -/// Since object-safe trait methods cannot take `impl CryptoRngCore` arguments, -/// this structure wraps the dynamic object and exposes a `CryptoRngCore` interface, -/// to be passed to statically typed round methods. -pub(crate) struct BoxedRng<'a>(pub(crate) &'a mut dyn CryptoRngCore); - -impl CryptoRng for BoxedRng<'_> {} - -impl RngCore for BoxedRng<'_> { - fn next_u32(&mut self) -> u32 { - self.0.next_u32() - } - fn next_u64(&mut self) -> u64 { - self.0.next_u64() - } - fn fill_bytes(&mut self, dest: &mut [u8]) { - self.0.fill_bytes(dest) - } - fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> { - self.0.try_fill_bytes(dest) - } -} - // Since we want `Round` methods to take `&mut impl CryptoRngCore` arguments // (which is what all cryptographic libraries generally take), it cannot be object-safe. // Thus we have to add this crate-private object-safe layer on top of `Round`. @@ -127,8 +105,7 @@ where #[allow(unused_variables)] deserializer: &Deserializer, destination: &Id, ) -> Result<(DirectMessage, Option), LocalError> { - let mut boxed_rng = BoxedRng(rng); - self.round.make_direct_message(&mut boxed_rng, serializer, destination) + self.round.make_direct_message(rng, serializer, destination) } fn make_echo_broadcast( @@ -137,8 +114,7 @@ where serializer: &Serializer, #[allow(unused_variables)] deserializer: &Deserializer, ) -> Result { - let mut boxed_rng = BoxedRng(rng); - self.round.make_echo_broadcast(&mut boxed_rng, serializer) + self.round.make_echo_broadcast(rng, serializer) } fn make_normal_broadcast( @@ -147,8 +123,7 @@ where serializer: &Serializer, #[allow(unused_variables)] deserializer: &Deserializer, ) -> Result { - let mut boxed_rng = BoxedRng(rng); - self.round.make_normal_broadcast(&mut boxed_rng, serializer) + self.round.make_normal_broadcast(rng, serializer) } fn receive_message( @@ -166,8 +141,7 @@ where payloads: BTreeMap, artifacts: BTreeMap, ) -> Result, LocalError> { - let mut boxed_rng = BoxedRng(rng); - self.round.finalize(&mut boxed_rng, payloads, artifacts) + self.round.finalize(rng, payloads, artifacts) } } diff --git a/manul/src/protocol/round.rs b/manul/src/protocol/round.rs index f32c1ef..56bc471 100644 --- a/manul/src/protocol/round.rs +++ b/manul/src/protocol/round.rs @@ -327,7 +327,7 @@ pub trait EntryPoint { /// `id` is the ID of this node. fn make_round( self, - rng: &mut impl CryptoRngCore, + rng: &mut dyn CryptoRngCore, shared_randomness: &[u8], id: &Id, ) -> Result, LocalError>; @@ -389,7 +389,7 @@ pub trait Round: 'static + Debug + Send + Sync { /// These should be put in an [`Artifact`] and will be available at the time of [`finalize`](`Self::finalize`). fn make_direct_message( &self, - #[allow(unused_variables)] rng: &mut impl CryptoRngCore, + #[allow(unused_variables)] rng: &mut dyn CryptoRngCore, #[allow(unused_variables)] serializer: &Serializer, #[allow(unused_variables)] destination: &Id, ) -> Result<(DirectMessage, Option), LocalError> { @@ -406,7 +406,7 @@ pub trait Round: 'static + Debug + Send + Sync { /// if an evidence of malicious behavior has to be constructed. fn make_echo_broadcast( &self, - #[allow(unused_variables)] rng: &mut impl CryptoRngCore, + #[allow(unused_variables)] rng: &mut dyn CryptoRngCore, #[allow(unused_variables)] serializer: &Serializer, ) -> Result { Ok(EchoBroadcast::none()) @@ -421,7 +421,7 @@ pub trait Round: 'static + Debug + Send + Sync { /// without any confirmation required. fn make_normal_broadcast( &self, - #[allow(unused_variables)] rng: &mut impl CryptoRngCore, + #[allow(unused_variables)] rng: &mut dyn CryptoRngCore, #[allow(unused_variables)] serializer: &Serializer, ) -> Result { Ok(NormalBroadcast::none()) @@ -445,7 +445,7 @@ pub trait Round: 'static + Debug + Send + Sync { /// [`make_direct_message`](`Self::make_direct_message`). fn finalize( self, - rng: &mut impl CryptoRngCore, + rng: &mut dyn CryptoRngCore, payloads: BTreeMap, artifacts: BTreeMap, ) -> Result, LocalError>; diff --git a/manul/src/session/echo.rs b/manul/src/session/echo.rs index 568322d..241564e 100644 --- a/manul/src/session/echo.rs +++ b/manul/src/session/echo.rs @@ -153,7 +153,7 @@ where fn make_normal_broadcast( &self, - _rng: &mut impl CryptoRngCore, + _rng: &mut dyn CryptoRngCore, serializer: &Serializer, ) -> Result { debug!("{:?}: making an echo round message", self.verifier); @@ -268,7 +268,7 @@ where fn finalize( self, - rng: &mut impl CryptoRngCore, + rng: &mut dyn CryptoRngCore, _payloads: BTreeMap, _artifacts: BTreeMap, ) -> Result, LocalError> { diff --git a/manul/src/tests/partial_echo.rs b/manul/src/tests/partial_echo.rs index b7e07f5..48e24aa 100644 --- a/manul/src/tests/partial_echo.rs +++ b/manul/src/tests/partial_echo.rs @@ -78,7 +78,7 @@ impl Deserialize<'de>> EntryPoint for Inp fn make_round( self, - _rng: &mut impl CryptoRngCore, + _rng: &mut dyn CryptoRngCore, _shared_randomness: &[u8], _id: &Id, ) -> Result, LocalError> { @@ -103,7 +103,7 @@ impl Deserialize<'de>> Round for Round1 Result { if self.inputs.message_destinations.is_empty() { @@ -140,7 +140,7 @@ impl Deserialize<'de>> Round for Round1, _artifacts: BTreeMap, ) -> Result, LocalError> { From 4758d64ae2b589a294e96a516b24dd4c3287643e Mon Sep 17 00:00:00 2001 From: Bogdan Opanchuk Date: Wed, 19 Feb 2025 00:09:46 -0800 Subject: [PATCH 5/8] Make `Round` dyn safe --- CHANGELOG.md | 1 + examples/src/simple.rs | 58 ++++----- examples/src/simple_malicious.rs | 12 +- manul/benches/async_session.rs | 30 ++--- manul/benches/empty_rounds.rs | 30 ++--- manul/src/combinators/chain.rs | 102 +++++++-------- manul/src/combinators/misbehave.rs | 57 ++++----- manul/src/protocol.rs | 3 +- manul/src/protocol/message.rs | 19 +-- manul/src/protocol/object_safe.rs | 191 +++------------------------- manul/src/protocol/round.rs | 29 +++-- manul/src/protocol/serialization.rs | 59 ++++----- manul/src/session/echo.rs | 21 ++- manul/src/session/evidence.rs | 45 +++---- manul/src/session/session.rs | 71 ++++------- manul/src/tests/partial_echo.rs | 22 ++-- 16 files changed, 260 insertions(+), 490 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bba1907..1266c35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Merged `Round::message_destinations()`, `expecting_messages_from()` and `echo_round_participation()` into `communication_info()`. ([#93]) - Renamed `Payload::try_to_typed()` and `Artifact::try_to_typed()` to `downcast()`. ([#94]) - `Round` methods take `dyn CryptoRngCore` instead of `impl CryptoRngCore`. ([#94]) +- `Round` is now dyn-safe. `serializer` and `deserializer` arguments to `Round` and related traits are merged into `format`. `Round::finalize()` takes `self: Box`. ([#94]) ### Added diff --git a/examples/src/simple.rs b/examples/src/simple.rs index 642d558..8517f7b 100644 --- a/examples/src/simple.rs +++ b/examples/src/simple.rs @@ -2,10 +2,10 @@ use alloc::collections::{BTreeMap, BTreeSet}; use core::fmt::Debug; use manul::protocol::{ - Artifact, BoxedRound, CommunicationInfo, Deserializer, DirectMessage, EchoBroadcast, EntryPoint, FinalizeOutcome, + Artifact, BoxedFormat, BoxedRound, CommunicationInfo, DirectMessage, EchoBroadcast, EntryPoint, FinalizeOutcome, LocalError, MessageValidationError, NormalBroadcast, PartyId, Payload, Protocol, ProtocolError, ProtocolMessage, ProtocolMessagePart, ProtocolValidationError, ReceiveError, RequiredMessageParts, RequiredMessages, Round, RoundId, - Serializer, TransitionInfo, + TransitionInfo, }; use rand_core::CryptoRngCore; use serde::{Deserialize, Serialize}; @@ -39,7 +39,7 @@ impl ProtocolError for SimpleProtocolError { fn verify_messages_constitute_error( &self, - deserializer: &Deserializer, + format: &BoxedFormat, _guilty_party: &Id, _shared_randomness: &[u8], _associated_data: &Self::AssociatedData, @@ -49,12 +49,12 @@ impl ProtocolError for SimpleProtocolError { ) -> Result<(), ProtocolValidationError> { match self { SimpleProtocolError::Round1InvalidPosition => { - let _message = message.direct_message.deserialize::(deserializer)?; + let _message = message.direct_message.deserialize::(format)?; // Message contents would be checked here Ok(()) } SimpleProtocolError::Round2InvalidPosition => { - let _r1_message = message.direct_message.deserialize::(deserializer)?; + let _r1_message = message.direct_message.deserialize::(format)?; let r1_echos_serialized = combined_echos .get(&1.into()) .ok_or_else(|| LocalError::new("Could not find combined echos for Round 1"))?; @@ -62,7 +62,7 @@ impl ProtocolError for SimpleProtocolError { // Deserialize the echos let _r1_echos = r1_echos_serialized .iter() - .map(|(_id, echo)| echo.deserialize::(deserializer)) + .map(|(_id, echo)| echo.deserialize::(format)) .collect::, _>>()?; // Message contents would be checked here @@ -77,36 +77,36 @@ impl Protocol for SimpleProtocol { type ProtocolError = SimpleProtocolError; fn verify_direct_message_is_invalid( - deserializer: &Deserializer, + format: &BoxedFormat, round_id: &RoundId, message: &DirectMessage, ) -> Result<(), MessageValidationError> { match round_id { - r if r == &1 => message.verify_is_not::(deserializer), - r if r == &2 => message.verify_is_not::(deserializer), + r if r == &1 => message.verify_is_not::(format), + r if r == &2 => message.verify_is_not::(format), _ => Err(MessageValidationError::InvalidEvidence("Invalid round number".into())), } } fn verify_echo_broadcast_is_invalid( - deserializer: &Deserializer, + format: &BoxedFormat, round_id: &RoundId, message: &EchoBroadcast, ) -> Result<(), MessageValidationError> { match round_id { - r if r == &1 => message.verify_is_not::(deserializer), + r if r == &1 => message.verify_is_not::(format), r if r == &2 => message.verify_is_some(), _ => Err(MessageValidationError::InvalidEvidence("Invalid round number".into())), } } fn verify_normal_broadcast_is_invalid( - deserializer: &Deserializer, + format: &BoxedFormat, round_id: &RoundId, message: &NormalBroadcast, ) -> Result<(), MessageValidationError> { match round_id { - r if r == &1 => message.verify_is_not::(deserializer), + r if r == &1 => message.verify_is_not::(format), r if r == &2 => message.verify_is_some(), _ => Err(MessageValidationError::InvalidEvidence("Invalid round number".into())), } @@ -206,7 +206,7 @@ impl Round for Round1 { fn make_normal_broadcast( &self, _rng: &mut dyn CryptoRngCore, - serializer: &Serializer, + format: &BoxedFormat, ) -> Result { debug!("{:?}: making normal broadcast", self.context.id); @@ -215,13 +215,13 @@ impl Round for Round1 { my_position: self.context.ids_to_positions[&self.context.id], }; - NormalBroadcast::new(serializer, message) + NormalBroadcast::new(format, message) } fn make_echo_broadcast( &self, _rng: &mut dyn CryptoRngCore, - serializer: &Serializer, + format: &BoxedFormat, ) -> Result { debug!("{:?}: making echo broadcast", self.context.id); @@ -229,13 +229,13 @@ impl Round for Round1 { my_position: self.context.ids_to_positions[&self.context.id], }; - EchoBroadcast::new(serializer, message) + EchoBroadcast::new(format, message) } fn make_direct_message( &self, _rng: &mut dyn CryptoRngCore, - serializer: &Serializer, + format: &BoxedFormat, destination: &Id, ) -> Result<(DirectMessage, Option), LocalError> { debug!("{:?}: making direct message for {:?}", self.context.id, destination); @@ -244,21 +244,21 @@ impl Round for Round1 { my_position: self.context.ids_to_positions[&self.context.id], your_position: self.context.ids_to_positions[destination], }; - let dm = DirectMessage::new(serializer, message)?; + let dm = DirectMessage::new(format, message)?; Ok((dm, None)) } fn receive_message( &self, - deserializer: &Deserializer, + format: &BoxedFormat, from: &Id, message: ProtocolMessage, ) -> Result> { debug!("{:?}: receiving message from {:?}", self.context.id, from); - let _echo = message.echo_broadcast.deserialize::(deserializer)?; - let _normal = message.normal_broadcast.deserialize::(deserializer)?; - let message = message.direct_message.deserialize::(deserializer)?; + let _echo = message.echo_broadcast.deserialize::(format)?; + let _normal = message.normal_broadcast.deserialize::(format)?; + let message = message.direct_message.deserialize::(format)?; debug!("{:?}: received message: {:?}", self.context.id, message); @@ -270,7 +270,7 @@ impl Round for Round1 { } fn finalize( - self, + self: Box, _rng: &mut dyn CryptoRngCore, payloads: BTreeMap, _artifacts: BTreeMap, @@ -322,7 +322,7 @@ impl Round for Round2 { fn make_direct_message( &self, _rng: &mut dyn CryptoRngCore, - serializer: &Serializer, + format: &BoxedFormat, destination: &Id, ) -> Result<(DirectMessage, Option), LocalError> { debug!("{:?}: making direct message for {:?}", self.context.id, destination); @@ -331,13 +331,13 @@ impl Round for Round2 { my_position: self.context.ids_to_positions[&self.context.id], your_position: self.context.ids_to_positions[destination], }; - let dm = DirectMessage::new(serializer, message)?; + let dm = DirectMessage::new(format, message)?; Ok((dm, None)) } fn receive_message( &self, - deserializer: &Deserializer, + format: &BoxedFormat, from: &Id, message: ProtocolMessage, ) -> Result> { @@ -346,7 +346,7 @@ impl Round for Round2 { message.echo_broadcast.assert_is_none()?; message.normal_broadcast.assert_is_none()?; - let message = message.direct_message.deserialize::(deserializer)?; + let message = message.direct_message.deserialize::(format)?; debug!("{:?}: received message: {:?}", self.context.id, message); @@ -358,7 +358,7 @@ impl Round for Round2 { } fn finalize( - self, + self: Box, _rng: &mut dyn CryptoRngCore, payloads: BTreeMap, _artifacts: BTreeMap, diff --git a/examples/src/simple_malicious.rs b/examples/src/simple_malicious.rs index 71e5220..90e82d1 100644 --- a/examples/src/simple_malicious.rs +++ b/examples/src/simple_malicious.rs @@ -5,8 +5,7 @@ use manul::{ combinators::misbehave::{Misbehaving, MisbehavingEntryPoint}, dev::{run_sync, BinaryFormat, TestSessionParams, TestSigner}, protocol::{ - Artifact, BoxedRound, Deserializer, DirectMessage, EntryPoint, LocalError, PartyId, ProtocolMessagePart, - Serializer, + Artifact, BoxedFormat, BoxedRound, DirectMessage, EntryPoint, LocalError, PartyId, ProtocolMessagePart, }, signature::Keypair, }; @@ -31,22 +30,21 @@ impl Misbehaving for MaliciousLogic { _rng: &mut dyn CryptoRngCore, round: &BoxedRound>::Protocol>, behavior: &Behavior, - serializer: &Serializer, - _deserializer: &Deserializer, + format: &BoxedFormat, _destination: &Id, direct_message: DirectMessage, artifact: Option, ) -> Result<(DirectMessage, Option), LocalError> { let dm = if round.id() == 1 { match behavior { - Behavior::SerializedGarbage => DirectMessage::new(serializer, [99u8])?, + Behavior::SerializedGarbage => DirectMessage::new(format, [99u8])?, Behavior::AttributableFailure => { let round1 = round.downcast_ref::>()?; let message = Round1Message { my_position: round1.context.ids_to_positions[&round1.context.id], your_position: round1.context.ids_to_positions[&round1.context.id], }; - DirectMessage::new(serializer, message)? + DirectMessage::new(format, message)? } _ => direct_message, } @@ -58,7 +56,7 @@ impl Misbehaving for MaliciousLogic { my_position: round2.context.ids_to_positions[&round2.context.id], your_position: round2.context.ids_to_positions[&round2.context.id], }; - DirectMessage::new(serializer, message)? + DirectMessage::new(format, message)? } _ => direct_message, } diff --git a/manul/benches/async_session.rs b/manul/benches/async_session.rs index 93728bc..18aa142 100644 --- a/manul/benches/async_session.rs +++ b/manul/benches/async_session.rs @@ -8,9 +8,9 @@ use criterion::{criterion_group, criterion_main, Criterion}; use manul::{ dev::{tokio::run_async, BinaryFormat, TestSessionParams, TestSigner}, protocol::{ - Artifact, BoxedRound, CommunicationInfo, Deserializer, DirectMessage, EchoBroadcast, EntryPoint, + Artifact, BoxedFormat, BoxedRound, CommunicationInfo, DirectMessage, EchoBroadcast, EntryPoint, FinalizeOutcome, LocalError, MessageValidationError, NoProtocolErrors, NormalBroadcast, PartyId, Payload, - Protocol, ProtocolMessage, ProtocolMessagePart, ReceiveError, Round, RoundId, Serializer, TransitionInfo, + Protocol, ProtocolMessage, ProtocolMessagePart, ReceiveError, Round, RoundId, TransitionInfo, }, signature::Keypair, }; @@ -35,7 +35,7 @@ impl Protocol for EmptyProtocol { type ProtocolError = NoProtocolErrors; fn verify_direct_message_is_invalid( - _deserializer: &Deserializer, + _format: &BoxedFormat, _round_id: &RoundId, _message: &DirectMessage, ) -> Result<(), MessageValidationError> { @@ -43,7 +43,7 @@ impl Protocol for EmptyProtocol { } fn verify_echo_broadcast_is_invalid( - _deserializer: &Deserializer, + _format: &BoxedFormat, _round_id: &RoundId, _message: &EchoBroadcast, ) -> Result<(), MessageValidationError> { @@ -51,7 +51,7 @@ impl Protocol for EmptyProtocol { } fn verify_normal_broadcast_is_invalid( - _deserializer: &Deserializer, + _format: &BoxedFormat, _round_id: &RoundId, _message: &NormalBroadcast, ) -> Result<(), MessageValidationError> { @@ -120,10 +120,10 @@ impl Round for EmptyRound { fn make_echo_broadcast( &self, _rng: &mut dyn CryptoRngCore, - serializer: &Serializer, + format: &BoxedFormat, ) -> Result { if self.inputs.echo { - EchoBroadcast::new(serializer, Round1EchoBroadcast) + EchoBroadcast::new(format, Round1EchoBroadcast) } else { Ok(EchoBroadcast::none()) } @@ -132,38 +132,34 @@ impl Round for EmptyRound { fn make_direct_message( &self, _rng: &mut dyn CryptoRngCore, - serializer: &Serializer, + format: &BoxedFormat, _destination: &Id, ) -> Result<(DirectMessage, Option), LocalError> { - let dm = DirectMessage::new(serializer, Round1DirectMessage(do_work(self.round_counter + 2)))?; + let dm = DirectMessage::new(format, Round1DirectMessage(do_work(self.round_counter + 2)))?; let artifact = Artifact::new(Round1Artifact); Ok((dm, Some(artifact))) } fn receive_message( &self, - deserializer: &Deserializer, + format: &BoxedFormat, _from: &Id, message: ProtocolMessage, ) -> Result> { //std::thread::sleep(std::time::Duration::from_secs_f64(0.001)); if self.inputs.echo { - let _echo_broadcast = message - .echo_broadcast - .deserialize::(deserializer)?; + let _echo_broadcast = message.echo_broadcast.deserialize::(format)?; } else { message.echo_broadcast.assert_is_none()?; } message.normal_broadcast.assert_is_none()?; - let direct_message = message - .direct_message - .deserialize::(deserializer)?; + let direct_message = message.direct_message.deserialize::(format)?; assert!(direct_message.0 == do_work(self.round_counter + 2)); Ok(Payload::new(Round1Payload)) } fn finalize( - self, + self: Box, _rng: &mut dyn CryptoRngCore, payloads: BTreeMap, artifacts: BTreeMap, diff --git a/manul/benches/empty_rounds.rs b/manul/benches/empty_rounds.rs index 2b938e1..4607fc7 100644 --- a/manul/benches/empty_rounds.rs +++ b/manul/benches/empty_rounds.rs @@ -7,9 +7,9 @@ use criterion::{criterion_group, criterion_main, Criterion}; use manul::{ dev::{run_sync, BinaryFormat, TestSessionParams, TestSigner}, protocol::{ - Artifact, BoxedRound, CommunicationInfo, Deserializer, DirectMessage, EchoBroadcast, EntryPoint, + Artifact, BoxedFormat, BoxedRound, CommunicationInfo, DirectMessage, EchoBroadcast, EntryPoint, FinalizeOutcome, LocalError, MessageValidationError, NoProtocolErrors, NormalBroadcast, PartyId, Payload, - Protocol, ProtocolMessage, ProtocolMessagePart, ReceiveError, Round, RoundId, Serializer, TransitionInfo, + Protocol, ProtocolMessage, ProtocolMessagePart, ReceiveError, Round, RoundId, TransitionInfo, }, signature::Keypair, }; @@ -24,7 +24,7 @@ impl Protocol for EmptyProtocol { type ProtocolError = NoProtocolErrors; fn verify_direct_message_is_invalid( - _deserializer: &Deserializer, + _format: &BoxedFormat, _round_id: &RoundId, _message: &DirectMessage, ) -> Result<(), MessageValidationError> { @@ -32,7 +32,7 @@ impl Protocol for EmptyProtocol { } fn verify_echo_broadcast_is_invalid( - _deserializer: &Deserializer, + _format: &BoxedFormat, _round_id: &RoundId, _message: &EchoBroadcast, ) -> Result<(), MessageValidationError> { @@ -40,7 +40,7 @@ impl Protocol for EmptyProtocol { } fn verify_normal_broadcast_is_invalid( - _deserializer: &Deserializer, + _format: &BoxedFormat, _round_id: &RoundId, _message: &NormalBroadcast, ) -> Result<(), MessageValidationError> { @@ -109,10 +109,10 @@ impl Round for EmptyRound { fn make_echo_broadcast( &self, _rng: &mut dyn CryptoRngCore, - serializer: &Serializer, + format: &BoxedFormat, ) -> Result { if self.inputs.echo { - EchoBroadcast::new(serializer, Round1EchoBroadcast) + EchoBroadcast::new(format, Round1EchoBroadcast) } else { Ok(EchoBroadcast::none()) } @@ -121,36 +121,32 @@ impl Round for EmptyRound { fn make_direct_message( &self, _rng: &mut dyn CryptoRngCore, - serializer: &Serializer, + format: &BoxedFormat, _destination: &Id, ) -> Result<(DirectMessage, Option), LocalError> { - let dm = DirectMessage::new(serializer, Round1DirectMessage)?; + let dm = DirectMessage::new(format, Round1DirectMessage)?; let artifact = Artifact::new(Round1Artifact); Ok((dm, Some(artifact))) } fn receive_message( &self, - deserializer: &Deserializer, + format: &BoxedFormat, _from: &Id, message: ProtocolMessage, ) -> Result> { if self.inputs.echo { - let _echo_broadcast = message - .echo_broadcast - .deserialize::(deserializer)?; + let _echo_broadcast = message.echo_broadcast.deserialize::(format)?; } else { message.echo_broadcast.assert_is_none()?; } message.normal_broadcast.assert_is_none()?; - let _direct_message = message - .direct_message - .deserialize::(deserializer)?; + let _direct_message = message.direct_message.deserialize::(format)?; Ok(Payload::new(Round1Payload)) } fn finalize( - self, + self: Box, _rng: &mut dyn CryptoRngCore, payloads: BTreeMap, artifacts: BTreeMap, diff --git a/manul/src/combinators/chain.rs b/manul/src/combinators/chain.rs index a38d98e..948cfa9 100644 --- a/manul/src/combinators/chain.rs +++ b/manul/src/combinators/chain.rs @@ -56,9 +56,9 @@ use rand_core::CryptoRngCore; use serde::{Deserialize, Serialize}; use crate::protocol::{ - Artifact, BoxedRound, CommunicationInfo, Deserializer, DirectMessage, EchoBroadcast, EntryPoint, FinalizeOutcome, - LocalError, MessageValidationError, NormalBroadcast, ObjectSafeRound, PartyId, Payload, Protocol, ProtocolError, - ProtocolMessage, ProtocolValidationError, ReceiveError, RequiredMessages, RoundId, Serializer, TransitionInfo, + Artifact, BoxedFormat, BoxedRound, CommunicationInfo, DirectMessage, EchoBroadcast, EntryPoint, FinalizeOutcome, + LocalError, MessageValidationError, NormalBroadcast, PartyId, Payload, Protocol, ProtocolError, ProtocolMessage, + ProtocolValidationError, ReceiveError, RequiredMessages, Round, RoundId, TransitionInfo, }; /// A marker trait that is used to disambiguate blanket trait implementations for [`Protocol`] and [`EntryPoint`]. @@ -167,7 +167,7 @@ where #[allow(clippy::too_many_arguments)] fn verify_messages_constitute_error( &self, - deserializer: &Deserializer, + format: &BoxedFormat, guilty_party: &Id, shared_randomness: &[u8], associated_data: &Self::AssociatedData, @@ -186,7 +186,7 @@ where match self { Self::Protocol1(err) => err.verify_messages_constitute_error( - deserializer, + format, guilty_party, shared_randomness, &associated_data.protocol1, @@ -195,7 +195,7 @@ where combined_echos, ), Self::Protocol2(err) => err.verify_messages_constitute_error( - deserializer, + format, guilty_party, shared_randomness, &associated_data.protocol2, @@ -216,41 +216,41 @@ where type ProtocolError = ChainedProtocolError; fn verify_direct_message_is_invalid( - deserializer: &Deserializer, + format: &BoxedFormat, round_id: &RoundId, message: &DirectMessage, ) -> Result<(), MessageValidationError> { let (group, round_id) = round_id.split_group()?; if group == 1 { - C::Protocol1::verify_direct_message_is_invalid(deserializer, &round_id, message) + C::Protocol1::verify_direct_message_is_invalid(format, &round_id, message) } else { - C::Protocol2::verify_direct_message_is_invalid(deserializer, &round_id, message) + C::Protocol2::verify_direct_message_is_invalid(format, &round_id, message) } } fn verify_echo_broadcast_is_invalid( - deserializer: &Deserializer, + format: &BoxedFormat, round_id: &RoundId, message: &EchoBroadcast, ) -> Result<(), MessageValidationError> { let (group, round_id) = round_id.split_group()?; if group == 1 { - C::Protocol1::verify_echo_broadcast_is_invalid(deserializer, &round_id, message) + C::Protocol1::verify_echo_broadcast_is_invalid(format, &round_id, message) } else { - C::Protocol2::verify_echo_broadcast_is_invalid(deserializer, &round_id, message) + C::Protocol2::verify_echo_broadcast_is_invalid(format, &round_id, message) } } fn verify_normal_broadcast_is_invalid( - deserializer: &Deserializer, + format: &BoxedFormat, round_id: &RoundId, message: &NormalBroadcast, ) -> Result<(), MessageValidationError> { let (group, round_id) = round_id.split_group()?; if group == 1 { - C::Protocol1::verify_normal_broadcast_is_invalid(deserializer, &round_id, message) + C::Protocol1::verify_normal_broadcast_is_invalid(format, &round_id, message) } else { - C::Protocol2::verify_normal_broadcast_is_invalid(deserializer, &round_id, message) + C::Protocol2::verify_normal_broadcast_is_invalid(format, &round_id, message) } } } @@ -312,7 +312,7 @@ where round, }, }; - Ok(BoxedRound::new_object_safe(chained_round)) + Ok(BoxedRound::new_dynamic(chained_round)) } } @@ -340,7 +340,7 @@ where Protocol2(BoxedRound>::Protocol2>), } -impl ObjectSafeRound for ChainedRound +impl Round for ChainedRound where Id: PartyId, T: ChainedJoin, @@ -371,60 +371,49 @@ where fn make_direct_message( &self, rng: &mut dyn CryptoRngCore, - serializer: &Serializer, - deserializer: &Deserializer, + format: &BoxedFormat, destination: &Id, ) -> Result<(DirectMessage, Option), LocalError> { match &self.state { - ChainState::Protocol1 { round, .. } => { - round - .as_ref() - .make_direct_message(rng, serializer, deserializer, destination) - } - ChainState::Protocol2(round) => { - round - .as_ref() - .make_direct_message(rng, serializer, deserializer, destination) - } + ChainState::Protocol1 { round, .. } => round.as_ref().make_direct_message(rng, format, destination), + ChainState::Protocol2(round) => round.as_ref().make_direct_message(rng, format, destination), } } fn make_echo_broadcast( &self, rng: &mut dyn CryptoRngCore, - serializer: &Serializer, - deserializer: &Deserializer, + format: &BoxedFormat, ) -> Result { match &self.state { - ChainState::Protocol1 { round, .. } => round.as_ref().make_echo_broadcast(rng, serializer, deserializer), - ChainState::Protocol2(round) => round.as_ref().make_echo_broadcast(rng, serializer, deserializer), + ChainState::Protocol1 { round, .. } => round.as_ref().make_echo_broadcast(rng, format), + ChainState::Protocol2(round) => round.as_ref().make_echo_broadcast(rng, format), } } fn make_normal_broadcast( &self, rng: &mut dyn CryptoRngCore, - serializer: &Serializer, - deserializer: &Deserializer, + format: &BoxedFormat, ) -> Result { match &self.state { - ChainState::Protocol1 { round, .. } => round.as_ref().make_normal_broadcast(rng, serializer, deserializer), - ChainState::Protocol2(round) => round.as_ref().make_normal_broadcast(rng, serializer, deserializer), + ChainState::Protocol1 { round, .. } => round.as_ref().make_normal_broadcast(rng, format), + ChainState::Protocol2(round) => round.as_ref().make_normal_broadcast(rng, format), } } fn receive_message( &self, - deserializer: &Deserializer, + format: &BoxedFormat, from: &Id, message: ProtocolMessage, ) -> Result> { match &self.state { - ChainState::Protocol1 { round, .. } => match round.as_ref().receive_message(deserializer, from, message) { + ChainState::Protocol1 { round, .. } => match round.as_ref().receive_message(format, from, message) { Ok(payload) => Ok(payload), Err(err) => Err(err.map(ChainedProtocolError::from_protocol1)), }, - ChainState::Protocol2(round) => match round.as_ref().receive_message(deserializer, from, message) { + ChainState::Protocol2(round) => match round.as_ref().receive_message(format, from, message) { Ok(payload) => Ok(payload), Err(err) => Err(err.map(ChainedProtocolError::from_protocol2)), }, @@ -448,30 +437,37 @@ where let entry_point2 = transition.make_entry_point2(result); let round = entry_point2.make_round(rng, &shared_randomness, &id)?; - Ok(FinalizeOutcome::AnotherRound(BoxedRound::new_object_safe( - ChainedRound:: { - state: ChainState::Protocol2(round), - }, - ))) + Ok(FinalizeOutcome::AnotherRound(BoxedRound::new_dynamic(ChainedRound::< + Id, + T, + > { + state: ChainState::Protocol2(round), + }))) } - FinalizeOutcome::AnotherRound(round) => Ok(FinalizeOutcome::AnotherRound(BoxedRound::new_object_safe( - ChainedRound:: { + FinalizeOutcome::AnotherRound(round) => { + Ok(FinalizeOutcome::AnotherRound(BoxedRound::new_dynamic(ChainedRound::< + Id, + T, + > { state: ChainState::Protocol1 { id, shared_randomness, round, transition, }, - }, - ))), + }))) + } }, ChainState::Protocol2(round) => match round.into_boxed().finalize(rng, payloads, artifacts)? { FinalizeOutcome::Result(result) => Ok(FinalizeOutcome::Result(result)), - FinalizeOutcome::AnotherRound(round) => Ok(FinalizeOutcome::AnotherRound(BoxedRound::new_object_safe( - ChainedRound:: { + FinalizeOutcome::AnotherRound(round) => { + Ok(FinalizeOutcome::AnotherRound(BoxedRound::new_dynamic(ChainedRound::< + Id, + T, + > { state: ChainState::Protocol2(round), - }, - ))), + }))) + } }, } } diff --git a/manul/src/combinators/misbehave.rs b/manul/src/combinators/misbehave.rs index a436244..a578d21 100644 --- a/manul/src/combinators/misbehave.rs +++ b/manul/src/combinators/misbehave.rs @@ -29,9 +29,9 @@ use core::fmt::Debug; use rand_core::CryptoRngCore; use crate::protocol::{ - Artifact, BoxedRound, CommunicationInfo, Deserializer, DirectMessage, EchoBroadcast, EntryPoint, FinalizeOutcome, - LocalError, NormalBroadcast, ObjectSafeRound, PartyId, Payload, Protocol, ProtocolMessage, ReceiveError, RoundId, - Serializer, TransitionInfo, + Artifact, BoxedFormat, BoxedRound, CommunicationInfo, DirectMessage, EchoBroadcast, EntryPoint, FinalizeOutcome, + LocalError, NormalBroadcast, PartyId, Payload, Protocol, ProtocolMessage, ReceiveError, Round, RoundId, + TransitionInfo, }; /// A trait describing required properties for a behavior type. @@ -59,8 +59,7 @@ where rng: &mut dyn CryptoRngCore, round: &BoxedRound>::Protocol>, behavior: &B, - serializer: &Serializer, - deserializer: &Deserializer, + format: &BoxedFormat, echo_broadcast: EchoBroadcast, ) -> Result { Ok(echo_broadcast) @@ -75,8 +74,7 @@ where rng: &mut dyn CryptoRngCore, round: &BoxedRound>::Protocol>, behavior: &B, - serializer: &Serializer, - deserializer: &Deserializer, + format: &BoxedFormat, normal_broadcast: NormalBroadcast, ) -> Result { Ok(normal_broadcast) @@ -91,8 +89,7 @@ where rng: &mut dyn CryptoRngCore, round: &BoxedRound>::Protocol>, behavior: &B, - serializer: &Serializer, - deserializer: &Deserializer, + format: &BoxedFormat, destination: &Id, direct_message: DirectMessage, artifact: Option, @@ -184,7 +181,7 @@ where id: &Id, ) -> Result, LocalError> { let round = self.entry_point.make_round(rng, shared_randomness, id)?; - Ok(BoxedRound::new_object_safe(MisbehavingRound:: { + Ok(BoxedRound::new_dynamic(MisbehavingRound:: { round, behavior: self.behavior, })) @@ -210,19 +207,19 @@ where { /// Wraps the outcome of the underlying Round into the MisbehavingRound structure. fn map_outcome( - outcome: FinalizeOutcome>::Protocol>, + outcome: FinalizeOutcome>::Protocol>, behavior: Option, - ) -> FinalizeOutcome>::Protocol> { + ) -> FinalizeOutcome>::Protocol> { match outcome { FinalizeOutcome::Result(result) => FinalizeOutcome::Result(result), FinalizeOutcome::AnotherRound(round) => { - FinalizeOutcome::AnotherRound(BoxedRound::new_object_safe(Self { round, behavior })) + FinalizeOutcome::AnotherRound(BoxedRound::new_dynamic(Self { round, behavior })) } } } } -impl ObjectSafeRound for MisbehavingRound +impl Round for MisbehavingRound where Id: PartyId, B: Behavior, @@ -241,21 +238,16 @@ where fn make_direct_message( &self, rng: &mut dyn CryptoRngCore, - serializer: &Serializer, - deserializer: &Deserializer, + format: &BoxedFormat, destination: &Id, ) -> Result<(DirectMessage, Option), LocalError> { - let (direct_message, artifact) = - self.round - .as_ref() - .make_direct_message(rng, serializer, deserializer, destination)?; + let (direct_message, artifact) = self.round.as_ref().make_direct_message(rng, format, destination)?; if let Some(behavior) = self.behavior.as_ref() { M::modify_direct_message( rng, &self.round, behavior, - serializer, - deserializer, + format, destination, direct_message, artifact, @@ -268,12 +260,11 @@ where fn make_echo_broadcast( &self, rng: &mut dyn CryptoRngCore, - serializer: &Serializer, - deserializer: &Deserializer, + format: &BoxedFormat, ) -> Result { - let echo_broadcast = self.round.as_ref().make_echo_broadcast(rng, serializer, deserializer)?; + let echo_broadcast = self.round.as_ref().make_echo_broadcast(rng, format)?; if let Some(behavior) = self.behavior.as_ref() { - M::modify_echo_broadcast(rng, &self.round, behavior, serializer, deserializer, echo_broadcast) + M::modify_echo_broadcast(rng, &self.round, behavior, format, echo_broadcast) } else { Ok(echo_broadcast) } @@ -282,15 +273,11 @@ where fn make_normal_broadcast( &self, rng: &mut dyn CryptoRngCore, - serializer: &Serializer, - deserializer: &Deserializer, + format: &BoxedFormat, ) -> Result { - let normal_broadcast = self - .round - .as_ref() - .make_normal_broadcast(rng, serializer, deserializer)?; + let normal_broadcast = self.round.as_ref().make_normal_broadcast(rng, format)?; if let Some(behavior) = self.behavior.as_ref() { - M::modify_normal_broadcast(rng, &self.round, behavior, serializer, deserializer, normal_broadcast) + M::modify_normal_broadcast(rng, &self.round, behavior, format, normal_broadcast) } else { Ok(normal_broadcast) } @@ -298,11 +285,11 @@ where fn receive_message( &self, - deserializer: &Deserializer, + format: &BoxedFormat, from: &Id, message: ProtocolMessage, ) -> Result> { - self.round.as_ref().receive_message(deserializer, from, message) + self.round.as_ref().receive_message(format, from, message) } fn finalize( diff --git a/manul/src/protocol.rs b/manul/src/protocol.rs index be2c010..9381b77 100644 --- a/manul/src/protocol.rs +++ b/manul/src/protocol.rs @@ -29,8 +29,7 @@ pub use round::{ Payload, Protocol, ProtocolError, RequiredMessageParts, RequiredMessages, Round, }; pub use round_id::{RoundId, TransitionInfo}; -pub use serialization::{Deserializer, Serializer}; +pub use serialization::BoxedFormat; pub(crate) use errors::ReceiveErrorType; pub(crate) use message::ProtocolMessagePartHashable; -pub(crate) use object_safe::ObjectSafeRound; diff --git a/manul/src/protocol/message.rs b/manul/src/protocol/message.rs index 02d5027..8c9e9f8 100644 --- a/manul/src/protocol/message.rs +++ b/manul/src/protocol/message.rs @@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize}; use super::{ errors::{DirectMessageError, EchoBroadcastError, LocalError, MessageValidationError, NormalBroadcastError}, - Deserializer, Serializer, + BoxedFormat, }; mod private { @@ -50,11 +50,11 @@ pub trait ProtocolMessagePart: ProtocolMessageWrapper { } /// Creates a new serialized message. - fn new(serializer: &Serializer, message: T) -> Result + fn new(format: &BoxedFormat, message: T) -> Result where T: 'static + Serialize, { - let payload = MessagePayload(serializer.serialize(message)?); + let payload = MessagePayload(format.serialize(message)?); Ok(Self::new_inner(Some(payload))) } @@ -79,11 +79,8 @@ pub trait ProtocolMessagePart: ProtocolMessageWrapper { /// This is intended to be used in the implementations of /// [`Protocol::verify_direct_message_is_invalid`](`crate::protocol::Protocol::verify_direct_message_is_invalid`) or /// [`Protocol::verify_echo_broadcast_is_invalid`](`crate::protocol::Protocol::verify_echo_broadcast_is_invalid`). - fn verify_is_not<'de, T: Deserialize<'de>>( - &'de self, - deserializer: &Deserializer, - ) -> Result<(), MessageValidationError> { - if self.deserialize::(deserializer).is_err() { + fn verify_is_not<'de, T: Deserialize<'de>>(&'de self, format: &BoxedFormat) -> Result<(), MessageValidationError> { + if self.deserialize::(format).is_err() { Ok(()) } else { Err(MessageValidationError::InvalidEvidence( @@ -108,7 +105,7 @@ pub trait ProtocolMessagePart: ProtocolMessageWrapper { } /// Deserializes the message into `T`. - fn deserialize<'de, T>(&'de self, deserializer: &Deserializer) -> Result + fn deserialize<'de, T>(&'de self, format: &BoxedFormat) -> Result where T: Deserialize<'de>, { @@ -116,9 +113,7 @@ pub trait ProtocolMessagePart: ProtocolMessageWrapper { .maybe_message() .as_ref() .ok_or_else(|| "The payload is `None` and cannot be deserialized".into())?; - deserializer - .deserialize(&payload.0) - .map_err(|err| err.to_string().into()) + format.deserialize(&payload.0).map_err(|err| err.to_string().into()) } } diff --git a/manul/src/protocol/object_safe.rs b/manul/src/protocol/object_safe.rs index 2caa535..989064f 100644 --- a/manul/src/protocol/object_safe.rs +++ b/manul/src/protocol/object_safe.rs @@ -1,197 +1,40 @@ -use alloc::{boxed::Box, collections::BTreeMap, format}; -use core::{fmt::Debug, marker::PhantomData}; - -use rand_core::CryptoRngCore; +use alloc::{boxed::Box, format}; use super::{ - errors::{LocalError, ReceiveError}, - message::{DirectMessage, EchoBroadcast, NormalBroadcast, ProtocolMessage}, - round::{Artifact, CommunicationInfo, FinalizeOutcome, PartyId, Payload, Protocol, Round}, - round_id::{RoundId, TransitionInfo}, - serialization::{Deserializer, Serializer}, + errors::LocalError, + round::{PartyId, Protocol, Round}, + round_id::RoundId, }; -// Since we want `Round` methods to take `&mut impl CryptoRngCore` arguments -// (which is what all cryptographic libraries generally take), it cannot be object-safe. -// Thus we have to add this crate-private object-safe layer on top of `Round`. -pub(crate) trait ObjectSafeRound: 'static + Debug + Send + Sync { - type Protocol: Protocol; - - fn transition_info(&self) -> TransitionInfo; - - fn communication_info(&self) -> CommunicationInfo; - - fn make_direct_message( - &self, - rng: &mut dyn CryptoRngCore, - serializer: &Serializer, - deserializer: &Deserializer, - destination: &Id, - ) -> Result<(DirectMessage, Option), LocalError>; - - fn make_echo_broadcast( - &self, - rng: &mut dyn CryptoRngCore, - serializer: &Serializer, - deserializer: &Deserializer, - ) -> Result; - - fn make_normal_broadcast( - &self, - rng: &mut dyn CryptoRngCore, - serializer: &Serializer, - deserializer: &Deserializer, - ) -> Result; - - fn receive_message( - &self, - deserializer: &Deserializer, - from: &Id, - message: ProtocolMessage, - ) -> Result>; - - fn finalize( - self: Box, - rng: &mut dyn CryptoRngCore, - payloads: BTreeMap, - artifacts: BTreeMap, - ) -> Result, LocalError>; - - /// Returns the type ID of the implementing type. - fn get_type_id(&self) -> core::any::TypeId { - core::any::TypeId::of::() - } -} - -// The `fn(Id)` bit is so that `ObjectSafeRoundWrapper` didn't require a bound on `Id` to be `Send + Sync`. -#[derive(Debug)] -pub(crate) struct ObjectSafeRoundWrapper { - round: R, - phantom: PhantomData, -} - -impl ObjectSafeRoundWrapper -where - Id: PartyId, - R: Round, -{ - pub fn new(round: R) -> Self { - Self { - round, - phantom: PhantomData, - } - } -} - -impl ObjectSafeRound for ObjectSafeRoundWrapper -where - Id: PartyId, - R: Round, -{ - type Protocol = >::Protocol; - - fn transition_info(&self) -> TransitionInfo { - self.round.transition_info() - } - - fn communication_info(&self) -> CommunicationInfo { - self.round.communication_info() - } - - fn make_direct_message( - &self, - rng: &mut dyn CryptoRngCore, - serializer: &Serializer, - #[allow(unused_variables)] deserializer: &Deserializer, - destination: &Id, - ) -> Result<(DirectMessage, Option), LocalError> { - self.round.make_direct_message(rng, serializer, destination) - } - - fn make_echo_broadcast( - &self, - rng: &mut dyn CryptoRngCore, - serializer: &Serializer, - #[allow(unused_variables)] deserializer: &Deserializer, - ) -> Result { - self.round.make_echo_broadcast(rng, serializer) - } - - fn make_normal_broadcast( - &self, - rng: &mut dyn CryptoRngCore, - serializer: &Serializer, - #[allow(unused_variables)] deserializer: &Deserializer, - ) -> Result { - self.round.make_normal_broadcast(rng, serializer) - } - - fn receive_message( - &self, - deserializer: &Deserializer, - from: &Id, - message: ProtocolMessage, - ) -> Result> { - self.round.receive_message(deserializer, from, message) - } - - fn finalize( - self: Box, - rng: &mut dyn CryptoRngCore, - payloads: BTreeMap, - artifacts: BTreeMap, - ) -> Result, LocalError> { - self.round.finalize(rng, payloads, artifacts) - } -} - -// We do not want to expose `ObjectSafeRound` to the user, so it is hidden in a struct. /// A wrapped new round that may be returned by [`Round::finalize`] /// or [`EntryPoint::make_round`](`crate::protocol::EntryPoint::make_round`). #[derive_where::derive_where(Debug)] -pub struct BoxedRound> { - wrapped: bool, - round: Box>, -} +pub struct BoxedRound>(Box>); impl> BoxedRound { /// Wraps an object implementing the dynamic round trait ([`Round`](`crate::protocol::Round`)). pub fn new_dynamic>(round: R) -> Self { - Self { - wrapped: true, - round: Box::new(ObjectSafeRoundWrapper::new(round)), - } - } - - pub(crate) fn new_object_safe>(round: R) -> Self { - Self { - wrapped: false, - round: Box::new(round), - } + Self(Box::new(round)) } - pub(crate) fn as_ref(&self) -> &dyn ObjectSafeRound { - self.round.as_ref() + pub(crate) fn as_ref(&self) -> &dyn Round { + self.0.as_ref() } - pub(crate) fn into_boxed(self) -> Box> { - self.round + pub(crate) fn into_boxed(self) -> Box> { + self.0 } fn boxed_type_is(&self) -> bool { - core::any::TypeId::of::() == self.round.get_type_id() + core::any::TypeId::of::() == self.0.get_type_id() } /// Attempts to extract an object of a concrete type, preserving the original on failure. pub fn try_downcast>(self) -> Result { - if self.wrapped && self.boxed_type_is::>() { + if self.boxed_type_is::() { // Safety: This is safe since we just checked that we are casting to the correct type. - let boxed_downcast = unsafe { - Box::>::from_raw( - Box::into_raw(self.round) as *mut ObjectSafeRoundWrapper - ) - }; - Ok(boxed_downcast.round) + let boxed_downcast = unsafe { Box::::from_raw(Box::into_raw(self.0) as *mut T) }; + Ok(*boxed_downcast) } else { Err(self) } @@ -209,8 +52,8 @@ impl> BoxedRound { /// /// Fails if the wrapped type is not `T`. pub fn downcast_ref>(&self) -> Result<&T, LocalError> { - if self.wrapped && self.boxed_type_is::>() { - let ptr: *const dyn ObjectSafeRound = self.round.as_ref(); + if self.boxed_type_is::() { + let ptr: *const dyn Round = self.0.as_ref(); // Safety: This is safe since we just checked that we are casting to the correct type. Ok(unsafe { &*(ptr as *const T) }) } else { @@ -226,6 +69,6 @@ impl> BoxedRound { // This constructs a new `TransitionInfo` object, so calling this method inside `Session` // has mild performance drawbacks. // This is mostly exposed for the sake of users writing `Misbehave` impls for testing. - self.round.transition_info().id() + self.0.transition_info().id() } } diff --git a/manul/src/protocol/round.rs b/manul/src/protocol/round.rs index 56bc471..40a9977 100644 --- a/manul/src/protocol/round.rs +++ b/manul/src/protocol/round.rs @@ -16,7 +16,7 @@ use super::{ message::{DirectMessage, EchoBroadcast, NormalBroadcast, ProtocolMessage, ProtocolMessagePart}, object_safe::BoxedRound, round_id::{RoundId, TransitionInfo}, - serialization::{Deserializer, Serializer}, + serialization::BoxedFormat, }; /// Describes what other parties this rounds sends messages to, and what other parties it expects messages from. @@ -79,7 +79,7 @@ pub trait Protocol: 'static { /// Normally one would use [`ProtocolMessagePart::verify_is_not`] and [`ProtocolMessagePart::verify_is_some`] /// when implementing this. fn verify_direct_message_is_invalid( - deserializer: &Deserializer, + format: &BoxedFormat, round_id: &RoundId, message: &DirectMessage, ) -> Result<(), MessageValidationError>; @@ -90,7 +90,7 @@ pub trait Protocol: 'static { /// Normally one would use [`ProtocolMessagePart::verify_is_not`] and [`ProtocolMessagePart::verify_is_some`] /// when implementing this. fn verify_echo_broadcast_is_invalid( - deserializer: &Deserializer, + format: &BoxedFormat, round_id: &RoundId, message: &EchoBroadcast, ) -> Result<(), MessageValidationError>; @@ -101,7 +101,7 @@ pub trait Protocol: 'static { /// Normally one would use [`ProtocolMessagePart::verify_is_not`] and [`ProtocolMessagePart::verify_is_some`] /// when implementing this. fn verify_normal_broadcast_is_invalid( - deserializer: &Deserializer, + format: &BoxedFormat, round_id: &RoundId, message: &NormalBroadcast, ) -> Result<(), MessageValidationError>; @@ -222,7 +222,7 @@ pub trait ProtocolError: Display + Debug + Clone + Serialize + for<'de> Dese #[allow(clippy::too_many_arguments)] fn verify_messages_constitute_error( &self, - deserializer: &Deserializer, + format: &BoxedFormat, guilty_party: &Id, shared_randomness: &[u8], associated_data: &Self::AssociatedData, @@ -245,7 +245,7 @@ impl ProtocolError for NoProtocolErrors { fn verify_messages_constitute_error( &self, - _deserializer: &Deserializer, + _format: &BoxedFormat, _guilty_party: &Id, _shared_randomness: &[u8], _associated_data: &Self::AssociatedData, @@ -390,7 +390,7 @@ pub trait Round: 'static + Debug + Send + Sync { fn make_direct_message( &self, #[allow(unused_variables)] rng: &mut dyn CryptoRngCore, - #[allow(unused_variables)] serializer: &Serializer, + #[allow(unused_variables)] format: &BoxedFormat, #[allow(unused_variables)] destination: &Id, ) -> Result<(DirectMessage, Option), LocalError> { Ok((DirectMessage::none(), None)) @@ -407,7 +407,7 @@ pub trait Round: 'static + Debug + Send + Sync { fn make_echo_broadcast( &self, #[allow(unused_variables)] rng: &mut dyn CryptoRngCore, - #[allow(unused_variables)] serializer: &Serializer, + #[allow(unused_variables)] format: &BoxedFormat, ) -> Result { Ok(EchoBroadcast::none()) } @@ -422,7 +422,7 @@ pub trait Round: 'static + Debug + Send + Sync { fn make_normal_broadcast( &self, #[allow(unused_variables)] rng: &mut dyn CryptoRngCore, - #[allow(unused_variables)] serializer: &Serializer, + #[allow(unused_variables)] format: &BoxedFormat, ) -> Result { Ok(NormalBroadcast::none()) } @@ -433,7 +433,7 @@ pub trait Round: 'static + Debug + Send + Sync { /// it has already been done by the execution layer. fn receive_message( &self, - deserializer: &Deserializer, + format: &BoxedFormat, from: &Id, message: ProtocolMessage, ) -> Result>; @@ -444,9 +444,16 @@ pub trait Round: 'static + Debug + Send + Sync { /// and `artifacts` are the ones previously generated by /// [`make_direct_message`](`Self::make_direct_message`). fn finalize( - self, + self: Box, rng: &mut dyn CryptoRngCore, payloads: BTreeMap, artifacts: BTreeMap, ) -> Result, LocalError>; + + /// Returns the type ID of the implementing type. + /// + /// **Warning:** replacing the blanket implementation may lead to bugs. + fn get_type_id(&self) -> core::any::TypeId { + core::any::TypeId::of::() + } } diff --git a/manul/src/protocol/serialization.rs b/manul/src/protocol/serialization.rs index 9dfd1fe..b855fcb 100644 --- a/manul/src/protocol/serialization.rs +++ b/manul/src/protocol/serialization.rs @@ -6,8 +6,6 @@ use serde::{Deserialize, Serialize}; use super::errors::{DeserializationError, LocalError}; use crate::session::WireFormat; -// Serialization - trait ObjectSafeSerializer: Debug { fn serialize(&self, value: Box) -> Result, LocalError>; } @@ -22,27 +20,6 @@ impl ObjectSafeSerializer for SerializerWrapper { } } -/// A serializer for protocol messages. -#[derive(Debug)] -pub struct Serializer(Box); - -impl Serializer { - pub(crate) fn new() -> Self { - Self(Box::new(SerializerWrapper::(PhantomData))) - } - - /// Serializes a `serde`-serializable object. - pub fn serialize(&self, value: T) -> Result, LocalError> - where - T: 'static + Serialize, - { - let boxed_value: Box = Box::new(value); - self.0.serialize(boxed_value) - } -} - -// Deserialization - // `fn(F)` makes the type `Send` + `Sync` even if `F` isn't. #[derive(Debug)] struct DeserializerFactoryWrapper(PhantomData); @@ -61,24 +38,36 @@ where } } -/// A deserializer for protocol messages. +/// A serializer/deserializer for protocol messages. #[derive(Debug)] -pub struct Deserializer(Box); +pub struct BoxedFormat { + serializer: Box, + deserializer_factory: Box, +} -impl Deserializer { - pub(crate) fn new() -> Self +impl BoxedFormat { + pub(crate) fn new() -> Self { + Self { + serializer: Box::new(SerializerWrapper::(PhantomData)), + deserializer_factory: Box::new(DeserializerFactoryWrapper::(PhantomData)), + } + } + + /// Serializes a `serde`-serializable object. + pub(crate) fn serialize(&self, value: T) -> Result, LocalError> where - F: WireFormat, + T: 'static + Serialize, { - Self(Box::new(DeserializerFactoryWrapper::(PhantomData))) + let boxed_value: Box = Box::new(value); + self.serializer.serialize(boxed_value) } /// Deserializes a `serde`-deserializable object. - pub fn deserialize<'de, T>(&self, bytes: &'de [u8]) -> Result + pub(crate) fn deserialize<'de, T>(&self, bytes: &'de [u8]) -> Result where T: Deserialize<'de>, { - let mut deserializer = self.0.make_erased_deserializer(bytes); + let mut deserializer = self.deserializer_factory.make_erased_deserializer(bytes); erased_serde::deserialize::(&mut deserializer) .map_err(|err| DeserializationError::new(format!("Deserialization error: {err:?}"))) } @@ -88,13 +77,11 @@ impl Deserializer { mod tests { use impls::impls; - use super::{Deserializer, Serializer}; + use super::BoxedFormat; #[test] fn test_concurrency_bounds() { - assert!(impls!(Serializer: Send)); - assert!(impls!(Serializer: Sync)); - assert!(impls!(Deserializer: Send)); - assert!(impls!(Deserializer: Sync)); + assert!(impls!(BoxedFormat: Send)); + assert!(impls!(BoxedFormat: Sync)); } } diff --git a/manul/src/session/echo.rs b/manul/src/session/echo.rs index 241564e..5930bd4 100644 --- a/manul/src/session/echo.rs +++ b/manul/src/session/echo.rs @@ -1,4 +1,5 @@ use alloc::{ + boxed::Box, collections::{BTreeMap, BTreeSet}, format, string::String, @@ -17,9 +18,9 @@ use super::{ }; use crate::{ protocol::{ - Artifact, BoxedRound, CommunicationInfo, Deserializer, DirectMessage, EchoBroadcast, EchoRoundParticipation, + Artifact, BoxedFormat, BoxedRound, CommunicationInfo, DirectMessage, EchoBroadcast, EchoRoundParticipation, FinalizeOutcome, MessageValidationError, NormalBroadcast, Payload, Protocol, ProtocolMessage, - ProtocolMessagePart, ReceiveError, Round, Serializer, TransitionInfo, + ProtocolMessagePart, ReceiveError, Round, TransitionInfo, }, utils::SerializableMap, }; @@ -121,10 +122,10 @@ where } pub fn verify_normal_broadcast_is_invalid( - deserializer: &Deserializer, + format: &BoxedFormat, message: &NormalBroadcast, ) -> Result<(), MessageValidationError> { - message.verify_is_not::>(deserializer) + message.verify_is_not::>(format) } } @@ -154,7 +155,7 @@ where fn make_normal_broadcast( &self, _rng: &mut dyn CryptoRngCore, - serializer: &Serializer, + format: &BoxedFormat, ) -> Result { debug!("{:?}: making an echo round message", self.verifier); @@ -174,12 +175,12 @@ where .into(); let message = EchoRoundMessage:: { message_hashes }; - NormalBroadcast::new(serializer, message) + NormalBroadcast::new(format, message) } fn receive_message( &self, - deserializer: &Deserializer, + format: &BoxedFormat, from: &SP::Verifier, message: ProtocolMessage, ) -> Result> { @@ -188,9 +189,7 @@ where message.echo_broadcast.assert_is_none()?; message.direct_message.assert_is_none()?; - let message = message - .normal_broadcast - .deserialize::>(deserializer)?; + let message = message.normal_broadcast.deserialize::>(format)?; // Check that the received message contains entries from `expected_echos`. // It is an unprovable fault. @@ -267,7 +266,7 @@ where } fn finalize( - self, + self: Box, rng: &mut dyn CryptoRngCore, _payloads: BTreeMap, _artifacts: BTreeMap, diff --git a/manul/src/session/evidence.rs b/manul/src/session/evidence.rs index a7d23bb..5bfd148 100644 --- a/manul/src/session/evidence.rs +++ b/manul/src/session/evidence.rs @@ -16,7 +16,7 @@ use super::{ }; use crate::{ protocol::{ - Deserializer, DirectMessage, DirectMessageError, EchoBroadcast, EchoBroadcastError, MessageValidationError, + BoxedFormat, DirectMessage, DirectMessageError, EchoBroadcast, EchoBroadcastError, MessageValidationError, NormalBroadcast, NormalBroadcastError, Protocol, ProtocolError, ProtocolMessage, ProtocolMessagePart, ProtocolMessagePartHashable, ProtocolValidationError, RoundId, }, @@ -247,17 +247,13 @@ where &self, associated_data: &>::AssociatedData, ) -> Result<(), EvidenceError> { - let deserializer = Deserializer::new::(); + let format = BoxedFormat::new::(); match &self.evidence { - EvidenceEnum::Protocol(evidence) => { - evidence.verify::(&self.guilty_party, &deserializer, associated_data) - } - EvidenceEnum::InvalidDirectMessage(evidence) => evidence.verify::(&self.guilty_party, &deserializer), - EvidenceEnum::InvalidEchoBroadcast(evidence) => evidence.verify::(&self.guilty_party, &deserializer), - EvidenceEnum::InvalidNormalBroadcast(evidence) => { - evidence.verify::(&self.guilty_party, &deserializer) - } - EvidenceEnum::InvalidEchoPack(evidence) => evidence.verify(&self.guilty_party, &deserializer), + EvidenceEnum::Protocol(evidence) => evidence.verify::(&self.guilty_party, &format, associated_data), + EvidenceEnum::InvalidDirectMessage(evidence) => evidence.verify::(&self.guilty_party, &format), + EvidenceEnum::InvalidEchoBroadcast(evidence) => evidence.verify::(&self.guilty_party, &format), + EvidenceEnum::InvalidNormalBroadcast(evidence) => evidence.verify::(&self.guilty_party, &format), + EvidenceEnum::InvalidEchoPack(evidence) => evidence.verify(&self.guilty_party, &format), EvidenceEnum::MismatchedBroadcasts(evidence) => evidence.verify::(&self.guilty_party), } } @@ -285,9 +281,9 @@ impl InvalidEchoPackEvidence where SP: SessionParameters, { - fn verify(&self, verifier: &SP::Verifier, deserializer: &Deserializer) -> Result<(), EvidenceError> { + fn verify(&self, verifier: &SP::Verifier, format: &BoxedFormat) -> Result<(), EvidenceError> { let verified = self.normal_broadcast.clone().verify::(verifier)?; - let deserialized = verified.payload().deserialize::>(deserializer)?; + let deserialized = verified.payload().deserialize::>(format)?; let invalid_echo = deserialized .message_hashes .get(&self.invalid_echo_sender) @@ -346,7 +342,7 @@ impl MismatchedBroadcastsEvidence { pub struct InvalidDirectMessageEvidence(SignedMessagePart); impl InvalidDirectMessageEvidence { - fn verify(&self, verifier: &SP::Verifier, deserializer: &Deserializer) -> Result<(), EvidenceError> + fn verify(&self, verifier: &SP::Verifier, format: &BoxedFormat) -> Result<(), EvidenceError> where P: Protocol, SP: SessionParameters, @@ -358,7 +354,7 @@ impl InvalidDirectMessageEvidence { Ok(EchoRound::::verify_direct_message_is_invalid(payload)?) } else { Ok(P::verify_direct_message_is_invalid( - deserializer, + format, self.0.metadata().round_id(), payload, )?) @@ -370,7 +366,7 @@ impl InvalidDirectMessageEvidence { pub struct InvalidEchoBroadcastEvidence(SignedMessagePart); impl InvalidEchoBroadcastEvidence { - fn verify(&self, verifier: &SP::Verifier, deserializer: &Deserializer) -> Result<(), EvidenceError> + fn verify(&self, verifier: &SP::Verifier, format: &BoxedFormat) -> Result<(), EvidenceError> where P: Protocol, SP: SessionParameters, @@ -382,7 +378,7 @@ impl InvalidEchoBroadcastEvidence { Ok(EchoRound::::verify_echo_broadcast_is_invalid(payload)?) } else { Ok(P::verify_echo_broadcast_is_invalid( - deserializer, + format, self.0.metadata().round_id(), payload, )?) @@ -394,7 +390,7 @@ impl InvalidEchoBroadcastEvidence { pub struct InvalidNormalBroadcastEvidence(SignedMessagePart); impl InvalidNormalBroadcastEvidence { - fn verify(&self, verifier: &SP::Verifier, deserializer: &Deserializer) -> Result<(), EvidenceError> + fn verify(&self, verifier: &SP::Verifier, format: &BoxedFormat) -> Result<(), EvidenceError> where P: Protocol, SP: SessionParameters, @@ -403,13 +399,10 @@ impl InvalidNormalBroadcastEvidence { let payload = verified_normal_broadcast.payload(); if self.0.metadata().round_id().is_echo() { - Ok(EchoRound::::verify_normal_broadcast_is_invalid( - deserializer, - payload, - )?) + Ok(EchoRound::::verify_normal_broadcast_is_invalid(format, payload)?) } else { Ok(P::verify_normal_broadcast_is_invalid( - deserializer, + format, self.0.metadata().round_id(), payload, )?) @@ -487,7 +480,7 @@ where fn verify( &self, verifier: &SP::Verifier, - deserializer: &Deserializer, + format: &BoxedFormat, associated_data: &>::AssociatedData, ) -> Result<(), EvidenceError> where @@ -535,7 +528,7 @@ where let verified_echo_hashes = echo_hashes.clone().verify::(verifier)?; let echo_round_payload = verified_echo_hashes .payload() - .deserialize::>(deserializer)?; + .deserialize::>(format)?; let signed_echo_broadcasts = self .other_echo_broadcasts @@ -602,7 +595,7 @@ where } Ok(self.error.verify_messages_constitute_error( - deserializer, + format, verifier, session_id.as_ref(), associated_data, diff --git a/manul/src/session/session.rs b/manul/src/session/session.rs index eec696b..1f0ec2c 100644 --- a/manul/src/session/session.rs +++ b/manul/src/session/session.rs @@ -23,9 +23,9 @@ use super::{ LocalError, RemoteError, }; use crate::protocol::{ - Artifact, BoxedRound, CommunicationInfo, Deserializer, DirectMessage, EchoBroadcast, EchoRoundParticipation, + Artifact, BoxedFormat, BoxedRound, CommunicationInfo, DirectMessage, EchoBroadcast, EchoRoundParticipation, EntryPoint, FinalizeOutcome, NormalBroadcast, PartyId, Payload, Protocol, ProtocolMessage, ProtocolMessagePart, - ReceiveError, ReceiveErrorType, RoundId, Serializer, TransitionInfo, + ReceiveError, ReceiveErrorType, RoundId, TransitionInfo, }; /// A set of types needed to execute a session. @@ -111,8 +111,7 @@ pub struct Session, SP: SessionParameters> { session_id: SessionId, signer: SP::Signer, verifier: SP::Verifier, - serializer: Serializer, - deserializer: Deserializer, + format: BoxedFormat, round: BoxedRound, communication_info: CommunicationInfo, echo_round_info: Option>, @@ -152,25 +151,15 @@ where EP: EntryPoint, { let first_round = entry_point.make_round(rng, session_id.as_ref(), &signer.verifying_key())?; - let serializer = Serializer::new::(); - let deserializer = Deserializer::new::(); - Self::new_for_next_round( - rng, - session_id, - signer, - serializer, - deserializer, - first_round, - Transcript::new(), - ) + let format = BoxedFormat::new::(); + Self::new_for_next_round(rng, session_id, signer, format, first_round, Transcript::new()) } fn new_for_next_round( rng: &mut impl CryptoRngCore, session_id: SessionId, signer: SP::Signer, - serializer: Serializer, - deserializer: Deserializer, + format: BoxedFormat, round: BoxedRound, transcript: Transcript, ) -> Result { @@ -178,10 +167,10 @@ where let transition_info = round.as_ref().transition_info(); - let echo = round.as_ref().make_echo_broadcast(rng, &serializer, &deserializer)?; + let echo = round.as_ref().make_echo_broadcast(rng, &format)?; let echo_broadcast = SignedMessagePart::new::(rng, &signer, &session_id, &transition_info.id(), echo)?; - let normal = round.as_ref().make_normal_broadcast(rng, &serializer, &deserializer)?; + let normal = round.as_ref().make_normal_broadcast(rng, &format)?; let normal_broadcast = SignedMessagePart::new::(rng, &signer, &session_id, &transition_info.id(), normal)?; let communication_info = round.as_ref().communication_info(); @@ -214,8 +203,7 @@ where session_id, signer, verifier, - serializer, - deserializer, + format, round, echo_broadcast, normal_broadcast, @@ -249,10 +237,10 @@ where rng: &mut impl CryptoRngCore, destination: &SP::Verifier, ) -> Result<(Message, ProcessedArtifact), LocalError> { - let (direct_message, artifact) = - self.round - .as_ref() - .make_direct_message(rng, &self.serializer, &self.deserializer, destination)?; + let (direct_message, artifact) = self + .round + .as_ref() + .make_direct_message(rng, &self.format, destination)?; let message = Message::new::( rng, @@ -408,7 +396,7 @@ where let processed = self .round .as_ref() - .receive_message(&self.deserializer, message.from(), protocol_message); + .receive_message(&self.format, message.from(), protocol_message); // We could filter out and return a possible `LocalError` at this stage, // but it's no harm in delaying it until `ProcessedMessage` is added to the accumulator. ProcessedMessage { message, processed } @@ -497,15 +485,8 @@ where accum.artifacts, )); let cached_messages = filter_messages(accum.cached, &round.id()); - let session = Session::new_for_next_round( - rng, - self.session_id, - self.signer, - self.serializer, - self.deserializer, - round, - transcript, - )?; + let session = + Session::new_for_next_round(rng, self.session_id, self.signer, self.format, round, transcript)?; return Ok(RoundOutcome::AnotherRound { session, cached_messages, @@ -533,15 +514,8 @@ where .filter(|message| !transcript.is_banned(message.from())) .collect::>(); - let session = Session::new_for_next_round( - rng, - self.session_id, - self.signer, - self.serializer, - self.deserializer, - round, - transcript, - )?; + let session = + Session::new_for_next_round(rng, self.session_id, self.signer, self.format, round, transcript)?; Ok(RoundOutcome::AnotherRound { cached_messages, session, @@ -839,8 +813,7 @@ mod tests { use impls::impls; use super::{ - Deserializer, Message, ProcessedArtifact, ProcessedMessage, RoundId, Session, SessionParameters, - VerifiedMessage, + BoxedFormat, Message, ProcessedArtifact, ProcessedMessage, RoundId, Session, SessionParameters, VerifiedMessage, }; use crate::{ dev::{BinaryFormat, TestSessionParams, TestVerifier}, @@ -866,7 +839,7 @@ mod tests { type ProtocolError = NoProtocolErrors; fn verify_direct_message_is_invalid( - _deserializer: &Deserializer, + _format: &BoxedFormat, _round_id: &RoundId, _message: &DirectMessage, ) -> Result<(), MessageValidationError> { @@ -874,7 +847,7 @@ mod tests { } fn verify_echo_broadcast_is_invalid( - _deserializer: &Deserializer, + _format: &BoxedFormat, _round_id: &RoundId, _message: &EchoBroadcast, ) -> Result<(), MessageValidationError> { @@ -882,7 +855,7 @@ mod tests { } fn verify_normal_broadcast_is_invalid( - _deserializer: &Deserializer, + _format: &BoxedFormat, _round_id: &RoundId, _message: &NormalBroadcast, ) -> Result<(), MessageValidationError> { diff --git a/manul/src/tests/partial_echo.rs b/manul/src/tests/partial_echo.rs index 48e24aa..82e1bb5 100644 --- a/manul/src/tests/partial_echo.rs +++ b/manul/src/tests/partial_echo.rs @@ -1,4 +1,5 @@ use alloc::{ + boxed::Box, collections::{BTreeMap, BTreeSet}, vec, vec::Vec, @@ -11,10 +12,9 @@ use serde::{Deserialize, Serialize}; use crate::{ dev::{run_sync, BinaryFormat, TestSessionParams, TestSigner, TestVerifier}, protocol::{ - Artifact, BoxedRound, CommunicationInfo, Deserializer, DirectMessage, EchoBroadcast, EchoRoundParticipation, + Artifact, BoxedFormat, BoxedRound, CommunicationInfo, DirectMessage, EchoBroadcast, EchoRoundParticipation, EntryPoint, FinalizeOutcome, LocalError, MessageValidationError, NoProtocolErrors, NormalBroadcast, PartyId, - Payload, Protocol, ProtocolMessage, ProtocolMessagePart, ReceiveError, Round, RoundId, Serializer, - TransitionInfo, + Payload, Protocol, ProtocolMessage, ProtocolMessagePart, ReceiveError, Round, RoundId, TransitionInfo, }, signature::Keypair, }; @@ -27,7 +27,7 @@ impl Protocol for PartialEchoProtocol { type ProtocolError = NoProtocolErrors; fn verify_direct_message_is_invalid( - _deserializer: &Deserializer, + _format: &BoxedFormat, _round_id: &RoundId, _message: &DirectMessage, ) -> Result<(), MessageValidationError> { @@ -35,7 +35,7 @@ impl Protocol for PartialEchoProtocol { } fn verify_echo_broadcast_is_invalid( - _deserializer: &Deserializer, + _format: &BoxedFormat, _round_id: &RoundId, _message: &EchoBroadcast, ) -> Result<(), MessageValidationError> { @@ -43,7 +43,7 @@ impl Protocol for PartialEchoProtocol { } fn verify_normal_broadcast_is_invalid( - _deserializer: &Deserializer, + _format: &BoxedFormat, _round_id: &RoundId, _message: &NormalBroadcast, ) -> Result<(), MessageValidationError> { @@ -104,13 +104,13 @@ impl Deserialize<'de>> Round for Round1 Result { if self.inputs.message_destinations.is_empty() { Ok(EchoBroadcast::none()) } else { EchoBroadcast::new( - serializer, + format, Round1Echo { sender: self.inputs.id.clone(), }, @@ -120,7 +120,7 @@ impl Deserialize<'de>> Round for Round1 Result> { @@ -130,7 +130,7 @@ impl Deserialize<'de>> Round for Round1>(deserializer)?; + let echo = message.echo_broadcast.deserialize::>(format)?; assert_eq!(&echo.sender, from); assert!(self.inputs.expecting_messages_from.contains(from)); } @@ -139,7 +139,7 @@ impl Deserialize<'de>> Round for Round1, _rng: &mut dyn CryptoRngCore, _payloads: BTreeMap, _artifacts: BTreeMap, From c82fe5fed27a5c931d955064f588e814cb1da1de Mon Sep 17 00:00:00 2001 From: Bogdan Opanchuk Date: Tue, 18 Feb 2025 16:08:40 -0800 Subject: [PATCH 6/8] Rename `protocol::object_safe` to `boxed_round` --- manul/src/protocol.rs | 4 ++-- manul/src/protocol/{object_safe.rs => boxed_round.rs} | 0 manul/src/protocol/round.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename manul/src/protocol/{object_safe.rs => boxed_round.rs} (100%) diff --git a/manul/src/protocol.rs b/manul/src/protocol.rs index 9381b77..2d77694 100644 --- a/manul/src/protocol.rs +++ b/manul/src/protocol.rs @@ -11,19 +11,19 @@ to be executed by a [`Session`](`crate::session::Session`). For more details, see the documentation of the mentioned traits. */ +mod boxed_round; mod errors; mod message; -mod object_safe; mod round; mod round_id; mod serialization; +pub use boxed_round::BoxedRound; pub use errors::{ DeserializationError, DirectMessageError, EchoBroadcastError, LocalError, MessageValidationError, NormalBroadcastError, ProtocolValidationError, ReceiveError, RemoteError, }; pub use message::{DirectMessage, EchoBroadcast, NormalBroadcast, ProtocolMessage, ProtocolMessagePart}; -pub use object_safe::BoxedRound; pub use round::{ Artifact, CommunicationInfo, EchoRoundParticipation, EntryPoint, FinalizeOutcome, NoProtocolErrors, PartyId, Payload, Protocol, ProtocolError, RequiredMessageParts, RequiredMessages, Round, diff --git a/manul/src/protocol/object_safe.rs b/manul/src/protocol/boxed_round.rs similarity index 100% rename from manul/src/protocol/object_safe.rs rename to manul/src/protocol/boxed_round.rs diff --git a/manul/src/protocol/round.rs b/manul/src/protocol/round.rs index 40a9977..f93c108 100644 --- a/manul/src/protocol/round.rs +++ b/manul/src/protocol/round.rs @@ -12,9 +12,9 @@ use rand_core::CryptoRngCore; use serde::{Deserialize, Serialize}; use super::{ + boxed_round::BoxedRound, errors::{LocalError, MessageValidationError, ProtocolValidationError, ReceiveError}, message::{DirectMessage, EchoBroadcast, NormalBroadcast, ProtocolMessage, ProtocolMessagePart}, - object_safe::BoxedRound, round_id::{RoundId, TransitionInfo}, serialization::BoxedFormat, }; From 309f98e2cacd3233c1d97167f8f229ba52b62ec8 Mon Sep 17 00:00:00 2001 From: Bogdan Opanchuk Date: Tue, 18 Feb 2025 22:13:38 -0800 Subject: [PATCH 7/8] Hide `get_type_id()` from the public API --- manul/src/protocol/round.rs | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/manul/src/protocol/round.rs b/manul/src/protocol/round.rs index f93c108..0e79477 100644 --- a/manul/src/protocol/round.rs +++ b/manul/src/protocol/round.rs @@ -357,6 +357,20 @@ pub enum EchoRoundParticipation { }, } +mod sealed { + /// A dyn safe trait to get the type's ID. + pub trait DynTypeId: 'static { + /// Returns the type ID of the implementing type. + fn get_type_id(&self) -> core::any::TypeId { + core::any::TypeId::of::() + } + } + + impl DynTypeId for T {} +} + +use sealed::DynTypeId; + /** A type representing a single round of a protocol. @@ -366,7 +380,7 @@ The way a round will be used by an external caller: - process received messages from other nodes (by calling [`receive_message`](`Self::receive_message`)); - attempt to finalize (by calling [`finalize`](`Self::finalize`)) to produce the next round, or return a result. */ -pub trait Round: 'static + Debug + Send + Sync { +pub trait Round: 'static + Debug + Send + Sync + DynTypeId { /// The protocol this round is a part of. type Protocol: Protocol; @@ -449,11 +463,4 @@ pub trait Round: 'static + Debug + Send + Sync { payloads: BTreeMap, artifacts: BTreeMap, ) -> Result, LocalError>; - - /// Returns the type ID of the implementing type. - /// - /// **Warning:** replacing the blanket implementation may lead to bugs. - fn get_type_id(&self) -> core::any::TypeId { - core::any::TypeId::of::() - } } From 59fa85b343c679fc4ca8603ecd18d25b61612c22 Mon Sep 17 00:00:00 2001 From: Bogdan Opanchuk Date: Thu, 20 Feb 2025 11:47:51 -0800 Subject: [PATCH 8/8] rename `protocol::serialization` to `boxed_format` --- manul/src/protocol.rs | 4 ++-- manul/src/protocol/{serialization.rs => boxed_format.rs} | 0 manul/src/protocol/round.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename manul/src/protocol/{serialization.rs => boxed_format.rs} (100%) diff --git a/manul/src/protocol.rs b/manul/src/protocol.rs index 2d77694..975fc15 100644 --- a/manul/src/protocol.rs +++ b/manul/src/protocol.rs @@ -11,13 +11,14 @@ to be executed by a [`Session`](`crate::session::Session`). For more details, see the documentation of the mentioned traits. */ +mod boxed_format; mod boxed_round; mod errors; mod message; mod round; mod round_id; -mod serialization; +pub use boxed_format::BoxedFormat; pub use boxed_round::BoxedRound; pub use errors::{ DeserializationError, DirectMessageError, EchoBroadcastError, LocalError, MessageValidationError, @@ -29,7 +30,6 @@ pub use round::{ Payload, Protocol, ProtocolError, RequiredMessageParts, RequiredMessages, Round, }; pub use round_id::{RoundId, TransitionInfo}; -pub use serialization::BoxedFormat; pub(crate) use errors::ReceiveErrorType; pub(crate) use message::ProtocolMessagePartHashable; diff --git a/manul/src/protocol/serialization.rs b/manul/src/protocol/boxed_format.rs similarity index 100% rename from manul/src/protocol/serialization.rs rename to manul/src/protocol/boxed_format.rs diff --git a/manul/src/protocol/round.rs b/manul/src/protocol/round.rs index 0e79477..edb21fe 100644 --- a/manul/src/protocol/round.rs +++ b/manul/src/protocol/round.rs @@ -12,11 +12,11 @@ use rand_core::CryptoRngCore; use serde::{Deserialize, Serialize}; use super::{ + boxed_format::BoxedFormat, boxed_round::BoxedRound, errors::{LocalError, MessageValidationError, ProtocolValidationError, ReceiveError}, message::{DirectMessage, EchoBroadcast, NormalBroadcast, ProtocolMessage, ProtocolMessagePart}, round_id::{RoundId, TransitionInfo}, - serialization::BoxedFormat, }; /// Describes what other parties this rounds sends messages to, and what other parties it expects messages from.