Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various evidence-related fixes #54

Merged
merged 5 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion examples/src/simple.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use alloc::collections::{BTreeMap, BTreeSet};
use alloc::{
collections::{BTreeMap, BTreeSet},
format,
string::String,
};
use core::fmt::Debug;

use manul::protocol::*;
Expand All @@ -15,6 +19,10 @@ pub enum SimpleProtocolError {
}

impl ProtocolError for SimpleProtocolError {
fn description(&self) -> String {
format!("{:?}", self)
}

fn required_direct_messages(&self) -> BTreeSet<RoundId> {
match self {
Self::Round1InvalidPosition => BTreeSet::new(),
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 @@ -188,8 +188,8 @@ fn serialized_garbage() {
let report1 = reports.remove(&v1).unwrap();
let report2 = reports.remove(&v2).unwrap();

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

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

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

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

assert!(report1.provable_errors[&v0].verify(&v0).is_ok());
assert!(report2.provable_errors[&v0].verify(&v0).is_ok());
assert!(report1.provable_errors[&v0].verify().is_ok());
assert!(report2.provable_errors[&v0].verify().is_ok());
}
8 changes: 7 additions & 1 deletion manul/benches/empty_rounds.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
extern crate alloc;

use alloc::collections::{BTreeMap, BTreeSet};
use alloc::{
collections::{BTreeMap, BTreeSet},
string::String,
};
use core::fmt::Debug;

use criterion::{criterion_group, criterion_main, Criterion};
Expand All @@ -23,6 +26,9 @@ pub struct EmptyProtocol;
pub struct EmptyProtocolError;

impl ProtocolError for EmptyProtocolError {
fn description(&self) -> String {
unimplemented!()
}
fn verify_messages_constitute_error(
&self,
_deserializer: &Deserializer,
Expand Down
14 changes: 13 additions & 1 deletion manul/src/protocol/round.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use alloc::{
boxed::Box,
collections::{BTreeMap, BTreeSet},
format,
string::String,
vec::Vec,
};
use core::{any::Any, fmt::Debug};
Expand Down Expand Up @@ -84,6 +85,11 @@ impl RoundId {
}
}

/// Returns `true` if this is an ID of an echo broadcast round.
pub(crate) fn is_echo(&self) -> bool {
self.is_echo
}

/// Returns the identifier of the echo round corresponding to the given non-echo round.
///
/// Panics if `self` is already an echo round identifier.
Expand Down Expand Up @@ -116,7 +122,7 @@ impl RoundId {
}

/// A distributed protocol.
pub trait Protocol: 'static + Sized {
pub trait Protocol: 'static {
/// The successful result of an execution of this protocol.
type Result: Debug;

Expand Down Expand Up @@ -161,6 +167,7 @@ pub trait Protocol: 'static + Sized {
///
/// Normally one would use [`EchoBroadcast::verify_is_not`] when implementing this.
fn verify_normal_broadcast_is_invalid(
#[allow(unused_variables)] deserializer: &Deserializer,
round_id: RoundId,
#[allow(unused_variables)] message: &NormalBroadcast,
) -> Result<(), MessageValidationError> {
Expand All @@ -175,6 +182,11 @@ pub trait Protocol: 'static + Sized {
/// Provable here means that we can create an evidence object entirely of messages signed by some party,
/// which, in combination, prove the party's malicious actions.
pub trait ProtocolError: Debug + Clone + Send {
/// A description of the error that will be included in the generated evidence.
///
/// Make it short and informative.
fn description(&self) -> String;

/// The rounds direct messages from which are required to prove malicious behavior for this error.
///
/// **Note:** Should not include the round where the error happened.
Expand Down
1 change: 1 addition & 0 deletions manul/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ mod transcript;
mod wire_format;

pub use crate::protocol::{LocalError, RemoteError};
pub use evidence::{Evidence, EvidenceError};
pub use message::MessageBundle;
pub use session::{CanFinalize, RoundAccumulator, RoundOutcome, Session, SessionId, SessionParameters};
pub use transcript::{SessionOutcome, SessionReport};
Expand Down
38 changes: 35 additions & 3 deletions manul/src/session/echo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use alloc::{
boxed::Box,
collections::{BTreeMap, BTreeSet},
format,
string::String,
vec::Vec,
};
use core::fmt::Debug;
Expand All @@ -17,8 +18,9 @@ use super::{
};
use crate::{
protocol::{
Artifact, Deserializer, DirectMessage, EchoBroadcast, FinalizeError, FinalizeOutcome, NormalBroadcast,
ObjectSafeRound, Payload, Protocol, ProtocolMessagePart, ReceiveError, Round, RoundId, Serializer,
Artifact, Deserializer, DirectMessage, EchoBroadcast, FinalizeError, FinalizeOutcome, MessageValidationError,
NormalBroadcast, ObjectSafeRound, Payload, Protocol, ProtocolMessagePart, ReceiveError, Round, RoundId,
Serializer,
},
utils::SerializableMap,
};
Expand All @@ -45,6 +47,17 @@ pub(crate) enum EchoRoundError<Id> {
},
}

impl<Id> EchoRoundError<Id> {
pub(crate) fn description(&self) -> String {
match self {
Self::InvalidEcho(_) => "Invalid message received among the ones echoed".into(),
Self::MismatchedBroadcasts { .. } => {
"The echoed message is different from the originally received one".into()
}
}
}
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub(crate) enum MismatchedBroadcastsError {
/// The originally received message and the echoed one had different payloads.
Expand All @@ -55,7 +68,7 @@ pub(crate) enum MismatchedBroadcastsError {

#[derive(Debug, Clone, Serialize, Deserialize)]
pub(crate) struct EchoRoundMessage<SP: SessionParameters> {
pub(crate) echo_broadcasts: SerializableMap<SP::Verifier, SignedMessage<EchoBroadcast>>,
pub(super) echo_broadcasts: SerializableMap<SP::Verifier, SignedMessage<EchoBroadcast>>,
}

/// Each protocol round can contain one `EchoRound` with "echo messages" that are sent to all
Expand Down Expand Up @@ -105,6 +118,25 @@ where
artifacts,
}
}

// Since the echo round doesn't have its own `Protocol`, these methods live here.

pub fn verify_direct_message_is_invalid(message: &DirectMessage) -> Result<(), MessageValidationError> {
// We don't send any direct messages in the echo round
message.verify_is_some()
}

pub fn verify_echo_broadcast_is_invalid(message: &EchoBroadcast) -> Result<(), MessageValidationError> {
// We don't send any echo broadcasts in the echo round
message.verify_is_some()
}

pub fn verify_normal_broadcast_is_invalid(
deserializer: &Deserializer,
message: &NormalBroadcast,
) -> Result<(), MessageValidationError> {
message.verify_is_not::<EchoRoundMessage<SP>>(deserializer)
}
}

impl<P, SP> Round<SP::Verifier> for EchoRound<P, SP>
Expand Down
Loading
Loading