-
Notifications
You must be signed in to change notification settings - Fork 1
Protocol combinators #60
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
Changes from all commits
aed78d0
a9e6d4d
24fb8ad
3f7eafa
be30e0d
e8ff740
f5d5bd7
891bd04
600cf85
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
extern crate alloc; | ||
|
||
pub mod simple; | ||
pub mod simple_chain; | ||
dvdplm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
#[cfg(test)] | ||
mod simple_malicious; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -149,14 +149,15 @@ struct Round1Payload { | |
x: u8, | ||
} | ||
|
||
impl<Id: PartyId> FirstRound<Id> for Round1<Id> { | ||
impl<Id: PartyId> EntryPoint<Id> for Round1<Id> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Naming ideas:
Can you elaborate a bit on why "FirstRound" is a bad name? I kind of liked it because it's very descriptive. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It was logical when There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will be especially true if we make it stateful (see the note in the PR description). |
||
type Inputs = Inputs<Id>; | ||
type Protocol = SimpleProtocol; | ||
fn new( | ||
_rng: &mut impl CryptoRngCore, | ||
_shared_randomness: &[u8], | ||
id: Id, | ||
inputs: Self::Inputs, | ||
) -> Result<Self, LocalError> { | ||
) -> Result<BoxedRound<Id, Self::Protocol>, LocalError> { | ||
// Just some numbers associated with IDs to use in the dummy protocol. | ||
// They will be the same on each node since IDs are ordered. | ||
let ids_to_positions = inputs | ||
|
@@ -169,13 +170,13 @@ impl<Id: PartyId> FirstRound<Id> for Round1<Id> { | |
let mut ids = inputs.all_ids; | ||
ids.remove(&id); | ||
|
||
Ok(Self { | ||
Ok(BoxedRound::new_dynamic(Self { | ||
context: Context { | ||
id, | ||
other_ids: ids, | ||
ids_to_positions, | ||
}, | ||
}) | ||
})) | ||
} | ||
} | ||
|
||
|
@@ -228,14 +229,15 @@ impl<Id: PartyId> Round<Id> for Round1<Id> { | |
_rng: &mut impl CryptoRngCore, | ||
serializer: &Serializer, | ||
destination: &Id, | ||
) -> Result<DirectMessage, LocalError> { | ||
) -> Result<(DirectMessage, Option<Artifact>), LocalError> { | ||
debug!("{:?}: making direct message for {:?}", self.context.id, destination); | ||
|
||
let message = Round1Message { | ||
my_position: self.context.ids_to_positions[&self.context.id], | ||
your_position: self.context.ids_to_positions[destination], | ||
}; | ||
DirectMessage::new(serializer, message) | ||
let dm = DirectMessage::new(serializer, message)?; | ||
Ok((dm, None)) | ||
} | ||
|
||
fn receive_message( | ||
|
@@ -281,11 +283,11 @@ impl<Id: PartyId> Round<Id> for Round1<Id> { | |
let sum = self.context.ids_to_positions[&self.context.id] | ||
+ typed_payloads.iter().map(|payload| payload.x).sum::<u8>(); | ||
|
||
let round2 = Round2 { | ||
let round2 = BoxedRound::new_dynamic(Round2 { | ||
round1_sum: sum, | ||
context: self.context, | ||
}; | ||
Ok(FinalizeOutcome::another_round(round2)) | ||
}); | ||
Ok(FinalizeOutcome::AnotherRound(round2)) | ||
} | ||
|
||
fn expecting_messages_from(&self) -> &BTreeSet<Id> { | ||
|
@@ -325,14 +327,15 @@ impl<Id: PartyId> Round<Id> for Round2<Id> { | |
_rng: &mut impl CryptoRngCore, | ||
serializer: &Serializer, | ||
destination: &Id, | ||
) -> Result<DirectMessage, LocalError> { | ||
) -> Result<(DirectMessage, Option<Artifact>), LocalError> { | ||
debug!("{:?}: making direct message for {:?}", self.context.id, destination); | ||
|
||
let message = Round2Message { | ||
my_position: self.context.ids_to_positions[&self.context.id], | ||
your_position: self.context.ids_to_positions[destination], | ||
}; | ||
DirectMessage::new(serializer, message) | ||
let dm = DirectMessage::new(serializer, message)?; | ||
Ok((dm, None)) | ||
} | ||
|
||
fn receive_message( | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
use core::fmt::Debug; | ||
|
||
use manul::{ | ||
combinators::chain::{Chained, ChainedEntryPoint}, | ||
protocol::PartyId, | ||
}; | ||
|
||
use super::simple::{Inputs, Round1}; | ||
|
||
pub struct ChainedSimple; | ||
dvdplm marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
#[derive(Debug)] | ||
pub struct NewInputs<Id>(Inputs<Id>); | ||
|
||
impl<'a, Id: PartyId> From<&'a NewInputs<Id>> for Inputs<Id> { | ||
fn from(source: &'a NewInputs<Id>) -> Self { | ||
source.0.clone() | ||
} | ||
} | ||
|
||
impl<Id: PartyId> From<(NewInputs<Id>, u8)> for Inputs<Id> { | ||
fn from(source: (NewInputs<Id>, u8)) -> Self { | ||
let (inputs, _result) = source; | ||
inputs.0 | ||
} | ||
} | ||
|
||
impl<Id: PartyId> Chained<Id> for ChainedSimple { | ||
type Inputs = NewInputs<Id>; | ||
type EntryPoint1 = Round1<Id>; | ||
type EntryPoint2 = Round1<Id>; | ||
} | ||
|
||
pub type DoubleSimpleEntryPoint<Id> = ChainedEntryPoint<Id, ChainedSimple>; | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use alloc::collections::BTreeSet; | ||
|
||
use manul::{ | ||
session::{signature::Keypair, SessionOutcome}, | ||
testing::{run_sync, BinaryFormat, TestSessionParams, TestSigner, TestVerifier}, | ||
}; | ||
use rand_core::OsRng; | ||
use tracing_subscriber::EnvFilter; | ||
|
||
use super::{DoubleSimpleEntryPoint, NewInputs}; | ||
use crate::simple::Inputs; | ||
|
||
#[test] | ||
fn round() { | ||
let signers = (0..3).map(TestSigner::new).collect::<Vec<_>>(); | ||
let all_ids = signers | ||
.iter() | ||
.map(|signer| signer.verifying_key()) | ||
.collect::<BTreeSet<_>>(); | ||
let inputs = signers | ||
.into_iter() | ||
.map(|signer| { | ||
( | ||
signer, | ||
NewInputs(Inputs { | ||
all_ids: all_ids.clone(), | ||
}), | ||
) | ||
}) | ||
.collect::<Vec<_>>(); | ||
|
||
let my_subscriber = tracing_subscriber::fmt() | ||
.with_env_filter(EnvFilter::from_default_env()) | ||
.finish(); | ||
let reports = tracing::subscriber::with_default(my_subscriber, || { | ||
run_sync::<DoubleSimpleEntryPoint<TestVerifier>, TestSessionParams<BinaryFormat>>(&mut OsRng, inputs) | ||
.unwrap() | ||
}); | ||
|
||
for (_id, report) in reports { | ||
if let SessionOutcome::Result(result) = report.outcome { | ||
assert_eq!(result, 3); // 0 + 1 + 2 | ||
} else { | ||
panic!("Session did not finish successfully"); | ||
} | ||
} | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.