Skip to content

Commit

Permalink
Merge pull request #79 from fjarri/api-adjustment
Browse files Browse the repository at this point in the history
API adjustments for CGGMP'24
  • Loading branch information
fjarri authored Jan 1, 2025
2 parents 8ee47c9 + c0cd439 commit c6a8972
Show file tree
Hide file tree
Showing 20 changed files with 646 additions and 474 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `Combinator`/`CombinatorEntryPoint` removed in favor of a single `ChainedMarker` trait. ([#76])
- The `combined_echos` argument to `ProtocolError::verify_messages_constitute_error()` now has a mapping of id to echo instead of just a vector of echos. ([#76])
- `ProtocolError::verify_messages_constitute_error()` now takes messages and mapping of messages by value. ([#76])
- Removed `ProtocolError::description()`, using `Display` impl instead. ([#79])
- Added `ProtocolError::AssociatedData` type, and a corresponding argument to `ProtocolError::verify_messages_constitute_error()` and `Evidence::verify()`. ([#79])
- Message parts in `Round::receive_message()` and `ProtocolError::verify_messages_constitute_error()` are bundled in `ProtocolMessage`. ([#79])
- `RoundId`s are passed by reference in public methods since they are not `Copy`. ([#79])
- Using a single `ProtocolError::required_messages()` instead of multiple methods. ([#79])
- `Protocol::verify_*_is_invalid()` are now mandatory to implement. ([#79])


### Added

- `impl From<NormalBroadcastError> for ProtocolValidationError` (to match what already exists for other messages). ([#77])
- Exposed `dev::ExecutionResult`. ([#79])
- `NoProtocolErrors` stub type to indicate that the protocol does not generate any provable errors. ([#79])


[#75]: https://github.com/entropyxyz/manul/pull/75
[#76]: https://github.com/entropyxyz/manul/pull/76
[#77]: https://github.com/entropyxyz/manul/pull/77
[#79]: https://github.com/entropyxyz/manul/pull/79


## [0.1.0] - 2024-11-19
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ serde = "1"
sha3 = "0.10"
rand_core = "0.6"
tracing = "0.1"
displaydoc = "0.2"

[dev-dependencies]
tokio = { version = "1", features = ["rt", "sync", "time", "macros"] }
Expand Down
104 changes: 49 additions & 55 deletions examples/src/simple.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
use alloc::{
collections::{BTreeMap, BTreeSet},
format,
string::String,
};
use alloc::collections::{BTreeMap, BTreeSet};
use core::fmt::Debug;

use manul::protocol::{
Artifact, BoxedRound, Deserializer, DirectMessage, EchoBroadcast, EntryPoint, FinalizeOutcome, LocalError,
MessageValidationError, NormalBroadcast, PartyId, Payload, Protocol, ProtocolError, ProtocolMessagePart,
ProtocolValidationError, ReceiveError, Round, RoundId, Serializer,
MessageValidationError, NormalBroadcast, PartyId, Payload, Protocol, ProtocolError, ProtocolMessage,
ProtocolMessagePart, ProtocolValidationError, ReceiveError, RequiredMessageParts, RequiredMessages, Round, RoundId,
Serializer,
};
use rand_core::CryptoRngCore;
use serde::{Deserialize, Serialize};
Expand All @@ -17,36 +14,28 @@ use tracing::debug;
#[derive(Debug)]
pub struct SimpleProtocol;

#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(displaydoc::Display, Debug, Clone, Serialize, Deserialize)]
/// An example error.
pub enum SimpleProtocolError {
/// Invalid position in Round 1.
Round1InvalidPosition,
/// Invalid position in Round 2.
Round2InvalidPosition,
}

impl<Id> ProtocolError<Id> for SimpleProtocolError {
fn description(&self) -> String {
format!("{:?}", self)
}
type AssociatedData = ();

fn required_direct_messages(&self) -> BTreeSet<RoundId> {
fn required_messages(&self) -> RequiredMessages {
match self {
Self::Round1InvalidPosition => BTreeSet::new(),
Self::Round2InvalidPosition => [RoundId::new(1)].into(),
}
}

fn required_echo_broadcasts(&self) -> BTreeSet<RoundId> {
BTreeSet::new()
}

fn required_normal_broadcasts(&self) -> BTreeSet<RoundId> {
BTreeSet::new()
}

fn required_combined_echos(&self) -> BTreeSet<RoundId> {
match self {
Self::Round1InvalidPosition => BTreeSet::new(),
Self::Round2InvalidPosition => [RoundId::new(1)].into(),
Self::Round1InvalidPosition => {
RequiredMessages::new(RequiredMessageParts::direct_message_only(), None, None)
}
Self::Round2InvalidPosition => RequiredMessages::new(
RequiredMessageParts::direct_message_only(),
Some([(RoundId::new(1), RequiredMessageParts::direct_message_only())].into()),
Some([RoundId::new(1)].into()),
),
}
}

Expand All @@ -55,22 +44,19 @@ impl<Id> ProtocolError<Id> for SimpleProtocolError {
deserializer: &Deserializer,
_guilty_party: &Id,
_shared_randomness: &[u8],
_echo_broadcast: EchoBroadcast,
_normal_broadcast: NormalBroadcast,
direct_message: DirectMessage,
_echo_broadcasts: BTreeMap<RoundId, EchoBroadcast>,
_normal_broadcasts: BTreeMap<RoundId, NormalBroadcast>,
_direct_messages: BTreeMap<RoundId, DirectMessage>,
_associated_data: &Self::AssociatedData,
message: ProtocolMessage,
_previous_messages: BTreeMap<RoundId, ProtocolMessage>,
combined_echos: BTreeMap<RoundId, BTreeMap<Id, EchoBroadcast>>,
) -> Result<(), ProtocolValidationError> {
match self {
SimpleProtocolError::Round1InvalidPosition => {
let _message = direct_message.deserialize::<Round1Message>(deserializer)?;
let _message = message.direct_message.deserialize::<Round1Message>(deserializer)?;
// Message contents would be checked here
Ok(())
}
SimpleProtocolError::Round2InvalidPosition => {
let _r1_message = direct_message.deserialize::<Round1Message>(deserializer)?;
let _r1_message = message.direct_message.deserialize::<Round1Message>(deserializer)?;
let r1_echos_serialized = combined_echos
.get(&RoundId::new(1))
.ok_or_else(|| LocalError::new("Could not find combined echos for Round 1"))?;
Expand All @@ -94,27 +80,39 @@ impl<Id> Protocol<Id> for SimpleProtocol {

fn verify_direct_message_is_invalid(
deserializer: &Deserializer,
round_id: RoundId,
round_id: &RoundId,
message: &DirectMessage,
) -> Result<(), MessageValidationError> {
match round_id {
r if r == RoundId::new(1) => message.verify_is_not::<Round1Message>(deserializer),
r if r == RoundId::new(2) => message.verify_is_not::<Round2Message>(deserializer),
r if r == &RoundId::new(1) => message.verify_is_not::<Round1Message>(deserializer),
r if r == &RoundId::new(2) => message.verify_is_not::<Round2Message>(deserializer),
_ => Err(MessageValidationError::InvalidEvidence("Invalid round number".into())),
}
}

fn verify_echo_broadcast_is_invalid(
deserializer: &Deserializer,
round_id: RoundId,
round_id: &RoundId,
message: &EchoBroadcast,
) -> Result<(), MessageValidationError> {
match round_id {
r if r == RoundId::new(1) => message.verify_is_some(),
r if r == RoundId::new(2) => message.verify_is_not::<Round2Message>(deserializer),
r if r == &RoundId::new(1) => message.verify_is_some(),
r if r == &RoundId::new(2) => message.verify_is_not::<Round2Message>(deserializer),
_ => Err(MessageValidationError::InvalidEvidence("Invalid round number".into())),
}
}

fn verify_normal_broadcast_is_invalid(
_deserializer: &Deserializer,
round_id: &RoundId,
message: &NormalBroadcast,
) -> Result<(), MessageValidationError> {
if round_id == &RoundId::new(1) || round_id == &RoundId::new(2) {
message.verify_is_some()
} else {
Err(MessageValidationError::InvalidEvidence("Invalid round number".into()))
}
}
}

#[derive(Debug)]
Expand Down Expand Up @@ -256,15 +254,13 @@ impl<Id: PartyId> Round<Id> for Round1<Id> {
_rng: &mut impl CryptoRngCore,
deserializer: &Deserializer,
from: &Id,
echo_broadcast: EchoBroadcast,
normal_broadcast: NormalBroadcast,
direct_message: DirectMessage,
message: ProtocolMessage,
) -> Result<Payload, ReceiveError<Id, Self::Protocol>> {
debug!("{:?}: receiving message from {:?}", self.context.id, from);

let _echo = echo_broadcast.deserialize::<Round1Echo>(deserializer)?;
let _normal = normal_broadcast.deserialize::<Round1Broadcast>(deserializer)?;
let message = direct_message.deserialize::<Round1Message>(deserializer)?;
let _echo = message.echo_broadcast.deserialize::<Round1Echo>(deserializer)?;
let _normal = message.normal_broadcast.deserialize::<Round1Broadcast>(deserializer)?;
let message = message.direct_message.deserialize::<Round1Message>(deserializer)?;

debug!("{:?}: received message: {:?}", self.context.id, message);

Expand Down Expand Up @@ -358,16 +354,14 @@ impl<Id: PartyId> Round<Id> for Round2<Id> {
_rng: &mut impl CryptoRngCore,
deserializer: &Deserializer,
from: &Id,
echo_broadcast: EchoBroadcast,
normal_broadcast: NormalBroadcast,
direct_message: DirectMessage,
message: ProtocolMessage,
) -> Result<Payload, ReceiveError<Id, Self::Protocol>> {
debug!("{:?}: receiving message from {:?}", self.context.id, from);

echo_broadcast.assert_is_none()?;
normal_broadcast.assert_is_none()?;
message.echo_broadcast.assert_is_none()?;
message.normal_broadcast.assert_is_none()?;

let message = direct_message.deserialize::<Round1Message>(deserializer)?;
let message = message.direct_message.deserialize::<Round1Message>(deserializer)?;

debug!("{:?}: received message: {:?}", self.context.id, message);

Expand Down
12 changes: 6 additions & 6 deletions examples/src/simple_malicious.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ fn serialized_garbage() {
let report1 = reports.remove(&v1).unwrap();
let report2 = reports.remove(&v2).unwrap();

assert!(report1.provable_errors[&v0].verify().is_ok());
assert!(report2.provable_errors[&v0].verify().is_ok());
assert!(report1.provable_errors[&v0].verify(&()).is_ok());
assert!(report2.provable_errors[&v0].verify(&()).is_ok());
}

#[test]
Expand Down Expand Up @@ -145,8 +145,8 @@ fn attributable_failure() {
let report1 = reports.remove(&v1).unwrap();
let report2 = reports.remove(&v2).unwrap();

assert!(report1.provable_errors[&v0].verify().is_ok());
assert!(report2.provable_errors[&v0].verify().is_ok());
assert!(report1.provable_errors[&v0].verify(&()).is_ok());
assert!(report2.provable_errors[&v0].verify(&()).is_ok());
}

#[test]
Expand Down Expand Up @@ -184,6 +184,6 @@ fn attributable_failure_round2() {
let report1 = reports.remove(&v1).unwrap();
let report2 = reports.remove(&v2).unwrap();

assert!(report1.provable_errors[&v0].verify().is_ok());
assert!(report2.provable_errors[&v0].verify().is_ok());
assert!(report1.provable_errors[&v0].verify(&()).is_ok());
assert!(report2.provable_errors[&v0].verify(&()).is_ok());
}
45 changes: 36 additions & 9 deletions manul/benches/empty_rounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ use manul::{
dev::{run_sync, BinaryFormat, TestSessionParams, TestSigner},
protocol::{
Artifact, BoxedRound, Deserializer, DirectMessage, EchoBroadcast, EntryPoint, FinalizeOutcome, LocalError,
NormalBroadcast, PartyId, Payload, Protocol, ProtocolMessagePart, ReceiveError, Round, RoundId, Serializer,
MessageValidationError, NoProtocolErrors, NormalBroadcast, PartyId, Payload, Protocol, ProtocolMessage,
ProtocolMessagePart, ReceiveError, Round, RoundId, Serializer,
},
signature::Keypair,
};
Expand All @@ -20,7 +21,31 @@ pub struct EmptyProtocol;

impl<Id> Protocol<Id> for EmptyProtocol {
type Result = ();
type ProtocolError = ();
type ProtocolError = NoProtocolErrors;

fn verify_direct_message_is_invalid(
_deserializer: &Deserializer,
_round_id: &RoundId,
_message: &DirectMessage,
) -> Result<(), MessageValidationError> {
unimplemented!()
}

fn verify_echo_broadcast_is_invalid(
_deserializer: &Deserializer,
_round_id: &RoundId,
_message: &EchoBroadcast,
) -> Result<(), MessageValidationError> {
unimplemented!()
}

fn verify_normal_broadcast_is_invalid(
_deserializer: &Deserializer,
_round_id: &RoundId,
_message: &NormalBroadcast,
) -> Result<(), MessageValidationError> {
unimplemented!()
}
}

#[derive(Debug)]
Expand Down Expand Up @@ -112,17 +137,19 @@ impl<Id: PartyId> Round<Id> for EmptyRound<Id> {
_rng: &mut impl CryptoRngCore,
deserializer: &Deserializer,
_from: &Id,
echo_broadcast: EchoBroadcast,
normal_broadcast: NormalBroadcast,
direct_message: DirectMessage,
message: ProtocolMessage,
) -> Result<Payload, ReceiveError<Id, Self::Protocol>> {
if self.inputs.echo {
let _echo_broadcast = echo_broadcast.deserialize::<Round1EchoBroadcast>(deserializer)?;
let _echo_broadcast = message
.echo_broadcast
.deserialize::<Round1EchoBroadcast>(deserializer)?;
} else {
echo_broadcast.assert_is_none()?;
message.echo_broadcast.assert_is_none()?;
}
normal_broadcast.assert_is_none()?;
let _direct_message = direct_message.deserialize::<Round1DirectMessage>(deserializer)?;
message.normal_broadcast.assert_is_none()?;
let _direct_message = message
.direct_message
.deserialize::<Round1DirectMessage>(deserializer)?;
Ok(Payload::new(Round1Payload))
}

Expand Down
Loading

0 comments on commit c6a8972

Please sign in to comment.