Skip to content

Commit

Permalink
Add a wrapping type for run_sync() output
Browse files Browse the repository at this point in the history
  • Loading branch information
fjarri committed Nov 15, 2024
1 parent 1d431ce commit 355a5b5
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 27 deletions.
9 changes: 6 additions & 3 deletions examples/src/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,10 +429,13 @@ mod tests {
.map(|signer| (signer, SimpleProtocolEntryPoint::new(all_ids.clone())))
.collect::<Vec<_>>();

let reports = run_sync_with_tracing::<_, TestSessionParams<BinaryFormat>>(&mut OsRng, entry_points).unwrap();
let results = run_sync_with_tracing::<_, TestSessionParams<BinaryFormat>>(&mut OsRng, entry_points)
.unwrap()
.results()
.unwrap();

for (_id, report) in reports {
assert_eq!(report.result().unwrap(), 3); // 0 + 1 + 2
for (_id, result) in results {
assert_eq!(result, 3); // 0 + 1 + 2
}
}
}
9 changes: 6 additions & 3 deletions examples/src/simple_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,13 @@ mod tests {
.map(|signer| (signer, DoubleSimpleEntryPoint::new(all_ids.clone())))
.collect::<Vec<_>>();

let reports = run_sync_with_tracing::<_, TestSessionParams<BinaryFormat>>(&mut OsRng, entry_points).unwrap();
let results = run_sync_with_tracing::<_, TestSessionParams<BinaryFormat>>(&mut OsRng, entry_points)
.unwrap()
.results()
.unwrap();

for (_id, report) in reports {
assert_eq!(report.result().unwrap(), 3); // 0 + 1 + 2
for (_id, result) in results {
assert_eq!(result, 3); // 0 + 1 + 2
}
}
}
12 changes: 9 additions & 3 deletions examples/src/simple_malicious.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,9 @@ fn serialized_garbage() {
})
.collect::<Vec<_>>();

let mut reports = run_sync_with_tracing::<_, TestSessionParams<BinaryFormat>>(&mut OsRng, entry_points).unwrap();
let mut reports = run_sync_with_tracing::<_, TestSessionParams<BinaryFormat>>(&mut OsRng, entry_points)
.unwrap()
.reports;

let v0 = signers[0].verifying_key();
let v1 = signers[1].verifying_key();
Expand Down Expand Up @@ -130,7 +132,9 @@ fn attributable_failure() {
})
.collect::<Vec<_>>();

let mut reports = run_sync_with_tracing::<_, TestSessionParams<BinaryFormat>>(&mut OsRng, entry_points).unwrap();
let mut reports = run_sync_with_tracing::<_, TestSessionParams<BinaryFormat>>(&mut OsRng, entry_points)
.unwrap()
.reports;

let v0 = signers[0].verifying_key();
let v1 = signers[1].verifying_key();
Expand Down Expand Up @@ -167,7 +171,9 @@ fn attributable_failure_round2() {
})
.collect::<Vec<_>>();

let mut reports = run_sync_with_tracing::<_, TestSessionParams<BinaryFormat>>(&mut OsRng, entry_points).unwrap();
let mut reports = run_sync_with_tracing::<_, TestSessionParams<BinaryFormat>>(&mut OsRng, entry_points)
.unwrap()
.reports;

let v0 = signers[0].verifying_key();
let v1 = signers[1].verifying_key();
Expand Down
8 changes: 4 additions & 4 deletions manul/benches/empty_rounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,8 @@ fn bench_empty_rounds(c: &mut Criterion) {
assert!(
run_sync::<_, TestSessionParams<BinaryFormat>>(&mut OsRng, entry_points_no_echo.clone())
.unwrap()
.into_values()
.all(|report| report.result().is_some())
.results()
.is_ok()
)
})
});
Expand Down Expand Up @@ -225,8 +225,8 @@ fn bench_empty_rounds(c: &mut Criterion) {
assert!(
run_sync::<_, TestSessionParams<BinaryFormat>>(&mut OsRng, entry_points_echo.clone())
.unwrap()
.into_values()
.all(|report| report.result().is_some())
.results()
.is_ok()
);
})
});
Expand Down
44 changes: 44 additions & 0 deletions manul/src/session/transcript.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use alloc::{
collections::{btree_map::Entry, BTreeMap, BTreeSet},
format,
string::String,
vec::Vec,
};
use core::fmt::Debug;

Expand Down Expand Up @@ -183,6 +185,21 @@ pub enum SessionOutcome<P: Protocol> {
Terminated,
}

impl<P> SessionOutcome<P>
where
P: Protocol,
{
/// Returns a brief description of the outcome.
pub fn brief(&self) -> String {
match self {
Self::Result(result) => format!("Success ({result:?})"),
Self::NotEnoughMessages => "Not enough messages to finalize, terminated".into(),
Self::Terminated => "Terminated by the user".into(),
Self::StalledWithProof(_) => "Unattributable failure during finalization".into(),
}
}
}

/// The report of a session execution.
#[derive(Debug)]
pub struct SessionReport<P: Protocol, SP: SessionParameters> {
Expand Down Expand Up @@ -217,4 +234,31 @@ where
_ => None,
}
}

/// Returns a brief description of report.
pub fn brief(&self) -> String {
let provable_errors = self
.provable_errors
.iter()
.map(|(id, evidence)| format!(" {:?}: {}", id, evidence.description()))
.collect::<Vec<_>>();
let unprovable_errors = self
.unprovable_errors
.iter()
.map(|(id, error)| format!(" {:?}: {}", id, error))
.collect::<Vec<_>>();
let missing_messages = self
.missing_messages
.iter()
.map(|(id, parties)| format!(" {:?}: {:?}", id, parties))
.collect::<Vec<_>>();

format!(
"Result: {}\nProvable errors:\n{}\nUnprovable errors:\n{}\nMissing_messages:\n{}",
self.outcome.brief(),
provable_errors.join("\n"),
unprovable_errors.join("\n"),
missing_messages.join("\n")
)
}
}
53 changes: 43 additions & 10 deletions manul/src/testing/run_sync.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use alloc::{collections::BTreeMap, vec::Vec};
use alloc::{collections::BTreeMap, format, string::String, vec::Vec};

use rand::Rng;
use rand_core::CryptoRngCore;
Expand All @@ -9,8 +9,8 @@ use tracing_subscriber::EnvFilter;
use crate::{
protocol::{EntryPoint, Protocol},
session::{
CanFinalize, LocalError, Message, RoundAccumulator, RoundOutcome, Session, SessionId, SessionParameters,
SessionReport,
CanFinalize, LocalError, Message, RoundAccumulator, RoundOutcome, Session, SessionId, SessionOutcome,
SessionParameters, SessionReport,
},
};

Expand Down Expand Up @@ -93,7 +93,7 @@ where
pub fn run_sync<EP, SP>(
rng: &mut impl CryptoRngCore,
entry_points: Vec<(SP::Signer, EP)>,
) -> Result<BTreeMap<SP::Verifier, SessionReport<EP::Protocol, SP>>, LocalError>
) -> Result<ExecutionResult<EP::Protocol, SP>, LocalError>
where
EP: EntryPoint<SP::Verifier>,
SP: SessionParameters,
Expand Down Expand Up @@ -156,25 +156,24 @@ where
}
}

let mut outcomes = BTreeMap::new();
let mut reports = BTreeMap::new();
for (verifier, state) in states {
let outcome = match state {
let report = match state {
State::InProgress { session, accum } => session.terminate(accum)?,
State::Finished(report) => report,
};
outcomes.insert(verifier, outcome);
reports.insert(verifier, report);
}

Ok(outcomes)
Ok(ExecutionResult { reports })
}

/// Same as [`run_sync()`], but enables a [`tracing`] subscriber that prints the tracing events to stdout,
/// taking options from the environment variable `RUST_LOG` (see [`mod@tracing_subscriber::fmt`] for details).
#[allow(clippy::type_complexity)]
pub fn run_sync_with_tracing<EP, SP>(
rng: &mut impl CryptoRngCore,
entry_points: Vec<(SP::Signer, EP)>,
) -> Result<BTreeMap<SP::Verifier, SessionReport<EP::Protocol, SP>>, LocalError>
) -> Result<ExecutionResult<EP::Protocol, SP>, LocalError>
where
EP: EntryPoint<SP::Verifier>,
SP: SessionParameters,
Expand All @@ -185,3 +184,37 @@ where
.finish();
tracing::subscriber::with_default(subscriber, || run_sync::<EP, SP>(rng, entry_points))
}

/// The result of a protocol execution on a set of nodes.
#[derive(Debug)]
pub struct ExecutionResult<P: Protocol, SP: SessionParameters> {
pub reports: BTreeMap<SP::Verifier, SessionReport<P, SP>>,
}

impl<P, SP> ExecutionResult<P, SP>
where
P: Protocol,
SP: SessionParameters,
{
pub fn results(self) -> Result<BTreeMap<SP::Verifier, P::Result>, String> {
let mut report_strings = Vec::new();
let mut results = BTreeMap::new();

for (id, report) in self.reports.into_iter() {
match report.outcome {
SessionOutcome::Result(result) => {
results.insert(id, result);
}
_ => {
report_strings.push(format!("Id: {:?}\n{}", id, report.brief()));
}
}
}

if report_strings.is_empty() {
Ok(results)
} else {
Err(report_strings.join("\n"))
}
}
}
8 changes: 4 additions & 4 deletions manul/src/tests/partial_echo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,8 @@ fn partial_echo() {

let entry_points = vec![node0, node1, node2, node3, node4];

let reports = run_sync_with_tracing::<_, TestSessionParams<BinaryFormat>>(&mut OsRng, entry_points).unwrap();
for (_id, report) in reports {
assert!(report.result().is_some());
}
let _results = run_sync_with_tracing::<_, TestSessionParams<BinaryFormat>>(&mut OsRng, entry_points)
.unwrap()
.results()
.unwrap();
}

0 comments on commit 355a5b5

Please sign in to comment.