Skip to content

Commit

Permalink
Merge pull request #72 from fjarri/remove-correctness-proof
Browse files Browse the repository at this point in the history
Remove `CorrectnessProof`
  • Loading branch information
fjarri authored Nov 19, 2024
2 parents 963d36e + 699ddab commit 6bec7fc
Show file tree
Hide file tree
Showing 14 changed files with 75 additions and 178 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Entry points are now stateful; combinator API reworked accordingly. ([#68])
- `run_sync()` now returns an `ExecutionResult` object. ([#71])
- `testing` module and feature renamed to `dev` to avoid confusion with tests. ([#71])
- Correctness proofs are removed from the API. Consequently, `FinalizeError` is removed, and `Round::finalize()` returns a `Result<..., LocalError>`) ([#72])


### Added
Expand Down Expand Up @@ -63,6 +64,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[#67]: https://github.com/entropyxyz/manul/pull/67
[#68]: https://github.com/entropyxyz/manul/pull/68
[#71]: https://github.com/entropyxyz/manul/pull/71
[#72]: https://github.com/entropyxyz/manul/pull/72


## [0.0.1] - 2024-10-12
Expand Down
16 changes: 5 additions & 11 deletions examples/src/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ impl ProtocolError for SimpleProtocolError {
impl Protocol for SimpleProtocol {
type Result = u8;
type ProtocolError = SimpleProtocolError;
type CorrectnessProof = ();

fn verify_direct_message_is_invalid(
deserializer: &Deserializer,
Expand Down Expand Up @@ -275,7 +274,7 @@ impl<Id: PartyId> Round<Id> for Round1<Id> {
_rng: &mut impl CryptoRngCore,
payloads: BTreeMap<Id, Payload>,
_artifacts: BTreeMap<Id, Artifact>,
) -> Result<FinalizeOutcome<Id, Self::Protocol>, FinalizeError<Self::Protocol>> {
) -> Result<FinalizeOutcome<Id, Self::Protocol>, LocalError> {
debug!(
"{:?}: finalizing with messages from {:?}",
self.context.id,
Expand Down Expand Up @@ -378,7 +377,7 @@ impl<Id: PartyId> Round<Id> for Round2<Id> {
_rng: &mut impl CryptoRngCore,
payloads: BTreeMap<Id, Payload>,
_artifacts: BTreeMap<Id, Artifact>,
) -> Result<FinalizeOutcome<Id, Self::Protocol>, FinalizeError<Self::Protocol>> {
) -> Result<FinalizeOutcome<Id, Self::Protocol>, LocalError> {
debug!(
"{:?}: finalizing with messages from {:?}",
self.context.id,
Expand All @@ -388,16 +387,11 @@ impl<Id: PartyId> Round<Id> for Round2<Id> {
let typed_payloads = payloads
.into_values()
.map(|payload| payload.try_to_typed::<Round1Payload>())
.collect::<Result<Vec<_>, _>>()
.map_err(FinalizeError::Local)?;
.collect::<Result<Vec<_>, _>>()?;
let sum = self.context.ids_to_positions[&self.context.id]
+ typed_payloads.iter().map(|payload| payload.x).sum::<u8>();

if sum != self.round1_sum {
return Err(FinalizeError::Unattributable(()));
}

Ok(FinalizeOutcome::Result(sum))
Ok(FinalizeOutcome::Result(sum + self.round1_sum))
}

fn expecting_messages_from(&self) -> &BTreeSet<Id> {
Expand Down Expand Up @@ -435,7 +429,7 @@ mod tests {
.unwrap();

for (_id, result) in results {
assert_eq!(result, 3); // 0 + 1 + 2
assert_eq!(result, 6); // (0 + 1 + 2) * 2
}
}
}
2 changes: 1 addition & 1 deletion examples/src/simple_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ mod tests {
.unwrap();

for (_id, result) in results {
assert_eq!(result, 3); // 0 + 1 + 2
assert_eq!(result, 6); // (0 + 1 + 2) * 2
}
}
}
8 changes: 3 additions & 5 deletions manul/benches/empty_rounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ use criterion::{criterion_group, criterion_main, Criterion};
use manul::{
dev::{run_sync, BinaryFormat, TestSessionParams, TestSigner},
protocol::{
Artifact, BoxedRound, Deserializer, DirectMessage, EchoBroadcast, EntryPoint, FinalizeError, FinalizeOutcome,
LocalError, NormalBroadcast, PartyId, Payload, Protocol, ProtocolMessagePart, ReceiveError, Round, RoundId,
Serializer,
Artifact, BoxedRound, Deserializer, DirectMessage, EchoBroadcast, EntryPoint, FinalizeOutcome, LocalError,
NormalBroadcast, PartyId, Payload, Protocol, ProtocolMessagePart, ReceiveError, Round, RoundId, Serializer,
},
session::signature::Keypair,
};
Expand All @@ -22,7 +21,6 @@ pub struct EmptyProtocol;
impl Protocol for EmptyProtocol {
type Result = ();
type ProtocolError = ();
type CorrectnessProof = ();
}

#[derive(Debug)]
Expand Down Expand Up @@ -133,7 +131,7 @@ impl<Id: PartyId> Round<Id> for EmptyRound<Id> {
_rng: &mut impl CryptoRngCore,
payloads: BTreeMap<Id, Payload>,
artifacts: BTreeMap<Id, Artifact>,
) -> Result<FinalizeOutcome<Id, Self::Protocol>, FinalizeError<Self::Protocol>> {
) -> Result<FinalizeOutcome<Id, Self::Protocol>, LocalError> {
for payload in payloads.into_values() {
let _payload = payload.try_to_typed::<Round1Payload>()?;
}
Expand Down
71 changes: 13 additions & 58 deletions manul/src/combinators/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,49 +221,12 @@ where
}
}

/// The correctness proof type for the chained protocol.
#[derive_where::derive_where(Debug, Clone)]
#[derive(Serialize, Deserialize)]
#[serde(bound(serialize = "
<C::Protocol1 as Protocol>::CorrectnessProof: Serialize,
<C::Protocol2 as Protocol>::CorrectnessProof: Serialize,
"))]
#[serde(bound(deserialize = "
<C::Protocol1 as Protocol>::CorrectnessProof: for<'x> Deserialize<'x>,
<C::Protocol2 as Protocol>::CorrectnessProof: for<'x> Deserialize<'x>,
"))]
pub enum ChainedCorrectnessProof<C>
where
C: ChainedProtocol,
{
/// A correctness proof from the first protocol.
Protocol1(<C::Protocol1 as Protocol>::CorrectnessProof),
/// A correctness proof from the second protocol.
Protocol2(<C::Protocol2 as Protocol>::CorrectnessProof),
}

impl<C> ChainedCorrectnessProof<C>
where
C: ChainedProtocol,
{
fn from_protocol1(proof: <C::Protocol1 as Protocol>::CorrectnessProof) -> Self {
Self::Protocol1(proof)
}

fn from_protocol2(proof: <C::Protocol2 as Protocol>::CorrectnessProof) -> Self {
Self::Protocol2(proof)
}
}

impl<C> CorrectnessProof for ChainedCorrectnessProof<C> where C: ChainedProtocol {}

impl<C> Protocol for C
where
C: ChainedProtocol,
{
type Result = <C::Protocol2 as Protocol>::Result;
type ProtocolError = ChainedProtocolError<C>;
type CorrectnessProof = ChainedCorrectnessProof<C>;
}

/// A trait defining how the entry point for the whole chained protocol
Expand Down Expand Up @@ -504,15 +467,15 @@ where
rng: &mut dyn CryptoRngCore,
payloads: BTreeMap<Id, Payload>,
artifacts: BTreeMap<Id, Artifact>,
) -> Result<FinalizeOutcome<Id, Self::Protocol>, FinalizeError<Self::Protocol>> {
) -> Result<FinalizeOutcome<Id, Self::Protocol>, LocalError> {
match self.state {
ChainState::Protocol1 {
id,
round,
transition,
shared_randomness,
} => match round.into_boxed().finalize(rng, payloads, artifacts) {
Ok(FinalizeOutcome::Result(result)) => {
} => 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)?;
Expand All @@ -523,32 +486,24 @@ where
},
)))
}
Ok(FinalizeOutcome::AnotherRound(round)) => Ok(FinalizeOutcome::AnotherRound(
BoxedRound::new_object_safe(ChainedRound::<Id, T> {
FinalizeOutcome::AnotherRound(round) => Ok(FinalizeOutcome::AnotherRound(BoxedRound::new_object_safe(
ChainedRound::<Id, T> {
state: ChainState::Protocol1 {
id,
shared_randomness,
round,
transition,
},
}),
)),
Err(FinalizeError::Local(err)) => Err(FinalizeError::Local(err)),
Err(FinalizeError::Unattributable(proof)) => Err(FinalizeError::Unattributable(
ChainedCorrectnessProof::from_protocol1(proof),
)),
},
))),
},
ChainState::Protocol2(round) => match round.into_boxed().finalize(rng, payloads, artifacts) {
Ok(FinalizeOutcome::Result(result)) => Ok(FinalizeOutcome::Result(result)),
Ok(FinalizeOutcome::AnotherRound(round)) => Ok(FinalizeOutcome::AnotherRound(
BoxedRound::new_object_safe(ChainedRound::<Id, T> {
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::<Id, T> {
state: ChainState::Protocol2(round),
}),
)),
Err(FinalizeError::Local(err)) => Err(FinalizeError::Local(err)),
Err(FinalizeError::Unattributable(proof)) => Err(FinalizeError::Unattributable(
ChainedCorrectnessProof::from_protocol2(proof),
)),
},
))),
},
}
}
Expand Down
12 changes: 5 additions & 7 deletions manul/src/combinators/misbehave.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ use rand_core::CryptoRngCore;

use crate::protocol::{
Artifact, BoxedRng, BoxedRound, Deserializer, DirectMessage, EchoBroadcast, EchoRoundParticipation, EntryPoint,
FinalizeError, FinalizeOutcome, LocalError, NormalBroadcast, ObjectSafeRound, PartyId, Payload, ReceiveError,
RoundId, Serializer,
FinalizeOutcome, LocalError, NormalBroadcast, ObjectSafeRound, PartyId, Payload, ReceiveError, RoundId, Serializer,
};

/// A trait describing required properties for a behavior type.
Expand Down Expand Up @@ -294,16 +293,15 @@ where
rng: &mut dyn CryptoRngCore,
payloads: BTreeMap<Id, Payload>,
artifacts: BTreeMap<Id, Artifact>,
) -> Result<FinalizeOutcome<Id, Self::Protocol>, FinalizeError<Self::Protocol>> {
match self.round.into_boxed().finalize(rng, payloads, artifacts) {
Ok(FinalizeOutcome::Result(result)) => Ok(FinalizeOutcome::Result(result)),
Ok(FinalizeOutcome::AnotherRound(round)) => {
) -> Result<FinalizeOutcome<Id, Self::Protocol>, LocalError> {
match self.round.into_boxed().finalize(rng, payloads, artifacts)? {
FinalizeOutcome::Result(result) => Ok(FinalizeOutcome::Result(result)),
FinalizeOutcome::AnotherRound(round) => {
Ok(FinalizeOutcome::AnotherRound(BoxedRound::new_object_safe(Self {
round,
behavior: self.behavior,
})))
}
Err(err) => Err(err),
}
}
}
6 changes: 3 additions & 3 deletions manul/src/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ mod round;
mod serialization;

pub use errors::{
DeserializationError, DirectMessageError, EchoBroadcastError, FinalizeError, LocalError, MessageValidationError,
DeserializationError, DirectMessageError, EchoBroadcastError, LocalError, MessageValidationError,
NormalBroadcastError, ProtocolValidationError, ReceiveError, RemoteError,
};
pub use message::{DirectMessage, EchoBroadcast, NormalBroadcast, ProtocolMessagePart};
pub use object_safe::BoxedRound;
pub use round::{
Artifact, CorrectnessProof, EchoRoundParticipation, EntryPoint, FinalizeOutcome, PartyId, Payload, Protocol,
ProtocolError, Round, RoundId,
Artifact, EchoRoundParticipation, EntryPoint, FinalizeOutcome, PartyId, Payload, Protocol, ProtocolError, Round,
RoundId,
};
pub use serialization::{Deserializer, Serializer};

Expand Down
15 changes: 0 additions & 15 deletions manul/src/protocol/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,21 +151,6 @@ where
}
}

/// An error that can occur during [`Round::finalize`](`super::Round::finalize`).
#[derive(Debug)]
pub enum FinalizeError<P: Protocol> {
/// A local error, usually indicating a bug in the implementation.
Local(LocalError),
/// An unattributable error, with an attached proof that this node performed its duties correctly.
Unattributable(P::CorrectnessProof),
}

impl<P: Protocol> From<LocalError> for FinalizeError<P> {
fn from(error: LocalError) -> Self {
Self::Local(error)
}
}

/// An error that can occur during the validation of an evidence of an invalid message.
#[derive(Debug, Clone)]
pub enum MessageValidationError {
Expand Down
6 changes: 3 additions & 3 deletions manul/src/protocol/object_safe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use core::{fmt::Debug, marker::PhantomData};
use rand_core::{CryptoRng, CryptoRngCore, RngCore};

use super::{
errors::{FinalizeError, LocalError, ReceiveError},
errors::{LocalError, ReceiveError},
message::{DirectMessage, EchoBroadcast, NormalBroadcast},
round::{Artifact, EchoRoundParticipation, FinalizeOutcome, PartyId, Payload, Protocol, Round, RoundId},
serialization::{Deserializer, Serializer},
Expand Down Expand Up @@ -91,7 +91,7 @@ pub(crate) trait ObjectSafeRound<Id: PartyId>: 'static + Debug + Send + Sync {
rng: &mut dyn CryptoRngCore,
payloads: BTreeMap<Id, Payload>,
artifacts: BTreeMap<Id, Artifact>,
) -> Result<FinalizeOutcome<Id, Self::Protocol>, FinalizeError<Self::Protocol>>;
) -> Result<FinalizeOutcome<Id, Self::Protocol>, LocalError>;

/// Returns the type ID of the implementing type.
fn get_type_id(&self) -> core::any::TypeId {
Expand Down Expand Up @@ -207,7 +207,7 @@ where
rng: &mut dyn CryptoRngCore,
payloads: BTreeMap<Id, Payload>,
artifacts: BTreeMap<Id, Artifact>,
) -> Result<FinalizeOutcome<Id, Self::Protocol>, FinalizeError<Self::Protocol>> {
) -> Result<FinalizeOutcome<Id, Self::Protocol>, LocalError> {
let mut boxed_rng = BoxedRng(rng);
self.round.finalize(&mut boxed_rng, payloads, artifacts)
}
Expand Down
21 changes: 2 additions & 19 deletions manul/src/protocol/round.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use serde::{Deserialize, Serialize};
use tinyvec::TinyVec;

use super::{
errors::{FinalizeError, LocalError, MessageValidationError, ProtocolValidationError, ReceiveError},
errors::{LocalError, MessageValidationError, ProtocolValidationError, ReceiveError},
message::{DirectMessage, EchoBroadcast, NormalBroadcast, ProtocolMessagePart},
object_safe::BoxedRound,
serialization::{Deserializer, Serializer},
Expand Down Expand Up @@ -134,11 +134,6 @@ pub trait Protocol: 'static {
/// An object of this type will be returned when a provable error happens during [`Round::receive_message`].
type ProtocolError: ProtocolError;

/// An object of this type will be returned when an unattributable error happens during [`Round::finalize`].
///
/// It proves that the node did its job correctly, to be adjudicated by a third party.
type CorrectnessProof: CorrectnessProof;

/// Returns `Ok(())` if the given direct message cannot be deserialized
/// assuming it is a direct message from the round `round_id`.
///
Expand Down Expand Up @@ -271,18 +266,6 @@ impl ProtocolError for () {
}
}

/// Describes unattributable errors originating during protocol execution.
///
/// In the situations where no specific message can be blamed for an error,
/// each node must generate a correctness proof proving that they performed their duties correctly,
/// and the collection of proofs is verified by a third party.
/// One of the proofs will necessarily be missing or invalid.
pub trait CorrectnessProof: Debug + Clone + Send + Serialize + for<'de> Deserialize<'de> {}

// A convenience implementation for protocols that don't define any errors.
// Have to do it for `()`, since `!` is unstable.
impl CorrectnessProof for () {}

/// Message payload created in [`Round::receive_message`].
#[derive(Debug)]
pub struct Payload(pub Box<dyn Any + Send + Sync>);
Expand Down Expand Up @@ -510,5 +493,5 @@ pub trait Round<Id: PartyId>: 'static + Debug + Send + Sync {
rng: &mut impl CryptoRngCore,
payloads: BTreeMap<Id, Payload>,
artifacts: BTreeMap<Id, Artifact>,
) -> Result<FinalizeOutcome<Id, Self::Protocol>, FinalizeError<Self::Protocol>>;
) -> Result<FinalizeOutcome<Id, Self::Protocol>, LocalError>;
}
7 changes: 3 additions & 4 deletions manul/src/session/echo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ use super::{
};
use crate::{
protocol::{
Artifact, BoxedRound, Deserializer, DirectMessage, EchoBroadcast, FinalizeError, FinalizeOutcome,
MessageValidationError, NormalBroadcast, Payload, Protocol, ProtocolMessagePart, ReceiveError, Round, RoundId,
Serializer,
Artifact, BoxedRound, Deserializer, DirectMessage, EchoBroadcast, FinalizeOutcome, MessageValidationError,
NormalBroadcast, Payload, Protocol, ProtocolMessagePart, ReceiveError, Round, RoundId, Serializer,
},
utils::SerializableMap,
};
Expand Down Expand Up @@ -286,7 +285,7 @@ where
rng: &mut impl CryptoRngCore,
_payloads: BTreeMap<SP::Verifier, Payload>,
_artifacts: BTreeMap<SP::Verifier, Artifact>,
) -> Result<FinalizeOutcome<SP::Verifier, Self::Protocol>, FinalizeError<Self::Protocol>> {
) -> Result<FinalizeOutcome<SP::Verifier, Self::Protocol>, LocalError> {
self.main_round
.into_boxed()
.finalize(rng, self.payloads, self.artifacts)
Expand Down
Loading

0 comments on commit 6bec7fc

Please sign in to comment.