From 5e6d44630132abc69b61029f50f3214f85fa8a74 Mon Sep 17 00:00:00 2001 From: Bogdan Opanchuk Date: Wed, 30 Oct 2024 14:04:36 -0700 Subject: [PATCH] Introduce PartyId to shorten the list of bounds we need to repeat every time --- CHANGELOG.md | 2 ++ examples/src/simple.rs | 6 +++--- examples/src/simple_malicious.rs | 14 +++++++------- manul/src/protocol.rs | 2 +- manul/src/protocol/object_safe.rs | 14 +++++++++----- manul/src/protocol/round.rs | 13 +++++++++---- manul/src/session/session.rs | 13 +++---------- manul/src/testing/macros.rs | 12 ++++++------ manul/src/testing/run_sync.rs | 8 ++++---- 9 files changed, 44 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c6e3baf..c203760 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 - `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]) +- `PartyId` trait alias for the combination of bounds needed for a party identifier. ([#59]) [#32]: https://github.com/entropyxyz/manul/pull/32 @@ -43,6 +44,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [#56]: https://github.com/entropyxyz/manul/pull/56 [#57]: https://github.com/entropyxyz/manul/pull/57 [#58]: https://github.com/entropyxyz/manul/pull/58 +[#59]: https://github.com/entropyxyz/manul/pull/59 ## [0.0.1] - 2024-10-12 diff --git a/examples/src/simple.rs b/examples/src/simple.rs index a687308..b947fac 100644 --- a/examples/src/simple.rs +++ b/examples/src/simple.rs @@ -149,7 +149,7 @@ struct Round1Payload { x: u8, } -impl FirstRound for Round1 { +impl FirstRound for Round1 { type Inputs = Inputs; fn new( _rng: &mut impl CryptoRngCore, @@ -179,7 +179,7 @@ impl FirstRound for Round1< } } -impl Round for Round1 { +impl Round for Round1 { type Protocol = SimpleProtocol; fn id(&self) -> RoundId { @@ -305,7 +305,7 @@ pub(crate) struct Round2Message { pub(crate) your_position: u8, } -impl Round for Round2 { +impl Round for Round2 { type Protocol = SimpleProtocol; fn id(&self) -> RoundId { diff --git a/examples/src/simple_malicious.rs b/examples/src/simple_malicious.rs index 176bf4d..1ed749d 100644 --- a/examples/src/simple_malicious.rs +++ b/examples/src/simple_malicious.rs @@ -3,8 +3,8 @@ use core::fmt::Debug; use manul::{ protocol::{ - Artifact, DirectMessage, FinalizeError, FinalizeOutcome, FirstRound, LocalError, Payload, ProtocolMessagePart, - Round, Serializer, + Artifact, DirectMessage, FinalizeError, FinalizeOutcome, FirstRound, LocalError, PartyId, Payload, + ProtocolMessagePart, Round, Serializer, }, session::signature::Keypair, testing::{ @@ -36,7 +36,7 @@ struct MaliciousRound1 { behavior: Behavior, } -impl RoundWrapper for MaliciousRound1 { +impl RoundWrapper for MaliciousRound1 { type InnerRound = Round1; fn inner_round_ref(&self) -> &Self::InnerRound { &self.round @@ -46,7 +46,7 @@ impl RoundWrapper for Malic } } -impl FirstRound for MaliciousRound1 { +impl FirstRound for MaliciousRound1 { type Inputs = MaliciousInputs; fn new( rng: &mut impl CryptoRngCore, @@ -62,7 +62,7 @@ impl FirstRound for Malicio } } -impl RoundOverride for MaliciousRound1 { +impl RoundOverride for MaliciousRound1 { fn make_direct_message( &self, rng: &mut impl CryptoRngCore, @@ -115,7 +115,7 @@ struct MaliciousRound2 { behavior: Behavior, } -impl RoundWrapper for MaliciousRound2 { +impl RoundWrapper for MaliciousRound2 { type InnerRound = Round2; fn inner_round_ref(&self) -> &Self::InnerRound { &self.round @@ -125,7 +125,7 @@ impl RoundWrapper for Malic } } -impl RoundOverride for MaliciousRound2 { +impl RoundOverride for MaliciousRound2 { fn make_direct_message( &self, rng: &mut impl CryptoRngCore, diff --git a/manul/src/protocol.rs b/manul/src/protocol.rs index b0b421f..0e53744 100644 --- a/manul/src/protocol.rs +++ b/manul/src/protocol.rs @@ -23,7 +23,7 @@ pub use errors::{ }; pub use message::{DirectMessage, EchoBroadcast, NormalBroadcast, ProtocolMessagePart}; pub use round::{ - AnotherRound, Artifact, FinalizeOutcome, FirstRound, Payload, Protocol, ProtocolError, Round, RoundId, + AnotherRound, Artifact, FinalizeOutcome, FirstRound, PartyId, Payload, Protocol, ProtocolError, Round, RoundId, }; pub use serialization::{Deserializer, Serializer}; diff --git a/manul/src/protocol/object_safe.rs b/manul/src/protocol/object_safe.rs index de07c8a..fd65f95 100644 --- a/manul/src/protocol/object_safe.rs +++ b/manul/src/protocol/object_safe.rs @@ -10,7 +10,7 @@ use rand_core::{CryptoRng, CryptoRngCore, RngCore}; use super::{ errors::{FinalizeError, LocalError, ReceiveError}, message::{DirectMessage, EchoBroadcast, NormalBroadcast}, - round::{Artifact, FinalizeOutcome, Payload, Protocol, Round, RoundId}, + round::{Artifact, FinalizeOutcome, PartyId, Payload, Protocol, Round, RoundId}, serialization::{Deserializer, Serializer}, }; @@ -39,7 +39,7 @@ impl RngCore for BoxedRng<'_> { // 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 { +pub(crate) trait ObjectSafeRound: 'static + Debug + Send + Sync { type Protocol: Protocol; fn id(&self) -> RoundId; @@ -98,7 +98,11 @@ pub(crate) struct ObjectSafeRoundWrapper { phantom: PhantomData Id>, } -impl> ObjectSafeRoundWrapper { +impl ObjectSafeRoundWrapper +where + Id: PartyId, + R: Round, +{ pub fn new(round: R) -> Self { Self { round, @@ -109,7 +113,7 @@ impl> ObjectSafeRoundWrapper { impl ObjectSafeRound for ObjectSafeRoundWrapper where - Id: 'static + Debug, + Id: PartyId, R: Round, { type Protocol = >::Protocol; @@ -203,7 +207,7 @@ where // so we have to provide this workaround. impl dyn ObjectSafeRound where - Id: 'static, + Id: PartyId, P: Protocol, { pub fn try_downcast>(self: Box) -> Result> { diff --git a/manul/src/protocol/round.rs b/manul/src/protocol/round.rs index 68a0353..e2f113b 100644 --- a/manul/src/protocol/round.rs +++ b/manul/src/protocol/round.rs @@ -28,7 +28,7 @@ pub enum FinalizeOutcome { impl FinalizeOutcome where - Id: 'static + Debug, + Id: PartyId, P: Protocol, { /// A helper method to create an [`AnotherRound`](`Self::AnotherRound`) variant. @@ -44,7 +44,7 @@ pub struct AnotherRound(Box AnotherRound where - Id: 'static + Debug, + Id: PartyId, P: Protocol, { /// Wraps an object implementing [`Round`]. @@ -301,7 +301,7 @@ impl Artifact { /// /// This is a round that can be created directly; /// all the others are only reachable throud [`Round::finalize`] by the execution layer. -pub trait FirstRound: Round + Sized { +pub trait FirstRound: Round + Sized { /// Additional inputs for the protocol (besides the mandatory ones in [`new`](`Self::new`)). type Inputs; @@ -317,6 +317,11 @@ pub trait FirstRound: Round + Sized { ) -> Result; } +/// A trait alias for the combination of traits needed for a party identifier. +pub trait PartyId: 'static + Debug + Clone + Ord + Send + Sync {} + +impl PartyId for T where T: 'static + Debug + Clone + Ord + Send + Sync {} + /** A type representing a single round of a protocol. @@ -326,7 +331,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 { /// The protocol this round is a part of. type Protocol: Protocol; diff --git a/manul/src/session/session.rs b/manul/src/session/session.rs index 96621ae..5c1845e 100644 --- a/manul/src/session/session.rs +++ b/manul/src/session/session.rs @@ -24,8 +24,8 @@ use super::{ }; use crate::protocol::{ Artifact, Deserializer, DirectMessage, EchoBroadcast, FinalizeError, FinalizeOutcome, FirstRound, NormalBroadcast, - ObjectSafeRound, ObjectSafeRoundWrapper, Payload, Protocol, ProtocolMessagePart, ReceiveError, ReceiveErrorType, - Round, RoundId, Serializer, + ObjectSafeRound, ObjectSafeRoundWrapper, PartyId, Payload, Protocol, ProtocolMessagePart, ReceiveError, + ReceiveErrorType, Round, RoundId, Serializer, }; /// A set of types needed to execute a session. @@ -40,14 +40,7 @@ pub trait SessionParameters: 'static { type Digest: Digest; /// The verifier type, which will also serve as a node identifier. - type Verifier: Debug - + Clone - + Ord - + DigestVerifier - + Serialize - + for<'de> Deserialize<'de> - + Send - + Sync; + type Verifier: PartyId + DigestVerifier + Serialize + for<'de> Deserialize<'de>; /// The signature type corresponding to [`Signer`](`Self::Signer`) and [`Verifier`](`Self::Verifier`). type Signature: Serialize + for<'de> Deserialize<'de>; diff --git a/manul/src/testing/macros.rs b/manul/src/testing/macros.rs index 2b411c5..d9c5d70 100644 --- a/manul/src/testing/macros.rs +++ b/manul/src/testing/macros.rs @@ -3,12 +3,12 @@ use alloc::collections::BTreeMap; use rand_core::CryptoRngCore; use crate::protocol::{ - Artifact, DirectMessage, EchoBroadcast, FinalizeError, FinalizeOutcome, LocalError, NormalBroadcast, Payload, - Round, Serializer, + Artifact, DirectMessage, EchoBroadcast, FinalizeError, FinalizeOutcome, LocalError, NormalBroadcast, PartyId, + Payload, Round, Serializer, }; /// A trait defining a wrapper around an existing type implementing [`Round`]. -pub trait RoundWrapper: 'static + Sized + Send + Sync { +pub trait RoundWrapper: 'static + Sized + Send + Sync { /// The inner round type. type InnerRound: Round; @@ -24,7 +24,7 @@ pub trait RoundWrapper: 'static + Sized + Send + Sync { /// Intended to be used with the [`round_override`] macro to generate the [`Round`] implementation. /// /// The blanket implementations delegate to the methods of the wrapped round. -pub trait RoundOverride: RoundWrapper { +pub trait RoundOverride: RoundWrapper { /// An override for [`Round::make_direct_message_with_artifact`]. fn make_direct_message_with_artifact( &self, @@ -90,8 +90,8 @@ macro_rules! round_override { ($round: ident) => { impl Round for $round where - Id: Debug, - $round: RoundOverride, + Id: $crate::protocol::PartyId, + $round: $crate::testing::RoundOverride, { type Protocol = <<$round as $crate::testing::RoundWrapper>::InnerRound as $crate::protocol::Round>::Protocol; diff --git a/manul/src/testing/run_sync.rs b/manul/src/testing/run_sync.rs index b14301f..83d24bc 100644 --- a/manul/src/testing/run_sync.rs +++ b/manul/src/testing/run_sync.rs @@ -34,8 +34,8 @@ fn propagate( accum: RoundAccumulator, ) -> Result<(State, Vec>), LocalError> where - P: 'static + Protocol, - SP: 'static + SessionParameters, + P: Protocol, + SP: SessionParameters, { let mut messages = Vec::new(); @@ -94,8 +94,8 @@ pub fn run_sync( inputs: Vec<(SP::Signer, R::Inputs)>, ) -> Result>, LocalError> where - R: 'static + FirstRound, - SP: 'static + SessionParameters, + R: FirstRound, + SP: SessionParameters, { let session_id = SessionId::random::(rng);