diff --git a/substrate/candidate-agreement/src/bft/accumulator.rs b/substrate/candidate-agreement/src/bft/accumulator.rs index e457bef859..8999a9f29b 100644 --- a/substrate/candidate-agreement/src/bft/accumulator.rs +++ b/substrate/candidate-agreement/src/bft/accumulator.rs @@ -23,8 +23,8 @@ use std::hash::Hash; use super::{Message, LocalizedMessage}; /// Justification for some state at a given round. -#[derive(PartialEq, Eq, Debug, Clone)] -pub struct Justification { +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct UncheckedJustification { /// The round. pub round_number: usize, /// The digest prepared for. @@ -33,36 +33,61 @@ pub struct Justification { pub signatures: Vec, } -impl Justification { +impl UncheckedJustification { /// Fails if there are duplicate signatures or invalid. /// /// Provide a closure for checking whether the signature is valid on a /// digest. /// - /// The closure should return true iff the round number, digest, and signature + /// The closure should returns a checked justification iff the round number, digest, and signature /// represent a valid message and the signer was authorized to issue /// it. /// /// The `check_message` closure may vary based on context. - pub fn check(&self, threshold: usize, check_message: F) -> bool + pub fn check(self, threshold: usize, mut check_message: F) + -> Result, Self> where - F: Fn(usize, &D, &S) -> Option, + F: FnMut(usize, &D, &S) -> Option, V: Hash + Eq, { - let mut voted = HashSet::new(); + let checks_out = { + let mut checks_out = || { + let mut voted = HashSet::new(); - for signature in &self.signatures { - match check_message(self.round_number, &self.digest, signature) { - None => return false, - Some(v) => { - if !voted.insert(v) { - return false; + for signature in &self.signatures { + match check_message(self.round_number, &self.digest, signature) { + None => return false, + Some(v) => { + if !voted.insert(v) { + return false; + } + } } } - } - } - voted.len() >= threshold + voted.len() >= threshold + }; + + checks_out() + }; + + if checks_out { + Ok(Justification(self)) + } else { + Err(self) + } + } +} + +/// A checked justification. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Justification(UncheckedJustification); + +impl ::std::ops::Deref for Justification { + type Target = UncheckedJustification; + + fn deref(&self) -> &Self::Target { + &self.0 } } @@ -228,11 +253,11 @@ impl Accumulator Accumulator