From feaaac75a5bacde6f74b3b4a266965805ca6a40e Mon Sep 17 00:00:00 2001 From: Marcio Diaz Date: Wed, 8 May 2019 12:59:52 +0200 Subject: [PATCH 01/21] feat: add length of hash when voted --- src/round.rs | 14 ++++++++++++++ src/voter/voting_round.rs | 10 ++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/round.rs b/src/round.rs index 16d2e1dd..f26e9e51 100644 --- a/src/round.rs +++ b/src/round.rs @@ -98,6 +98,7 @@ impl VoteMultiplicity { struct VoteTracker { votes: HashMap>, current_weight: u64, + voted_at: Option, } /// Result of adding a vote. @@ -111,6 +112,7 @@ impl VoteTracker VoteTracker { votes: HashMap::new(), current_weight: 0, + voted_at: None, } } @@ -674,6 +676,18 @@ impl Round where pub fn precommits(&self) -> Vec<(Id, Precommit, Signature)> { self.precommit.votes() } + + /// Return all imported prevotes. + pub fn set_prevote_idx(&mut self, idx: usize) -> bool { + self.prevote.voted_at = Some(idx); + true + } + + /// Return all imported precommits. + pub fn set_precommit_idx(&mut self, idx: usize) -> bool { + self.precommit.voted_at = Some(idx); + true + } } #[cfg(test)] diff --git a/src/voter/voting_round.rs b/src/voter/voting_round.rs index da226b32..d93c85fe 100644 --- a/src/voter/voting_round.rs +++ b/src/voter/voting_round.rs @@ -201,6 +201,16 @@ impl> VotingRound where self.votes.voters() } + /// Get the best block finalized in this round. + pub(super) fn set_precommit_idx(&mut self, idx: usize) -> bool { + self.votes.set_precommit_idx(idx) + } + + /// Get the best block finalized in this round. + pub(super) fn set_prevote_idx(&mut self, idx: usize) -> bool { + self.votes.set_prevote_idx(idx) + } + /// Get the best block finalized in this round. pub(super) fn finalized(&self) -> Option<&(H, N)> { self.votes.finalized() From 75ec15b0f52eed27542116a3c242e8a3f0824221 Mon Sep 17 00:00:00 2001 From: Marcio Diaz Date: Wed, 8 May 2019 12:59:52 +0200 Subject: [PATCH 02/21] feat: add length of hash when voted --- src/round.rs | 16 ++++++++++++++++ src/voter/voting_round.rs | 2 ++ 2 files changed, 18 insertions(+) diff --git a/src/round.rs b/src/round.rs index 16d2e1dd..352af770 100644 --- a/src/round.rs +++ b/src/round.rs @@ -98,6 +98,7 @@ impl VoteMultiplicity { struct VoteTracker { votes: HashMap>, current_weight: u64, + voted_at: Option, } /// Result of adding a vote. @@ -111,6 +112,7 @@ impl VoteTracker VoteTracker { votes: HashMap::new(), current_weight: 0, + voted_at: None, } } @@ -674,6 +676,20 @@ impl Round where pub fn precommits(&self) -> Vec<(Id, Precommit, Signature)> { self.precommit.votes() } + + /// Save the len of prevotes received at the moment of prevoting. + pub fn set_prevote_idx(&mut self) -> bool { + self.prevote.voted_at = Some(self.prevote.votes().len()); + println!("set prevote idx to {:?}", self.prevote.voted_at); + true + } + + /// Save the len of precommits received at the moment of precommiting. + pub fn set_precommit_idx(&mut self) -> bool { + self.precommit.voted_at = Some(self.precommit.votes().len()); + println!("set precommit idx to {:?}", self.precommit.voted_at); + true + } } #[cfg(test)] diff --git a/src/voter/voting_round.rs b/src/voter/voting_round.rs index da226b32..daa4eacb 100644 --- a/src/voter/voting_round.rs +++ b/src/voter/voting_round.rs @@ -370,6 +370,7 @@ impl> VotingRound where if let Some(prevote) = self.construct_prevote(last_round_state)? { debug!(target: "afg", "Casting prevote for round {}", self.votes.number()); self.env.prevoted(self.round_number(), prevote.clone())?; + self.votes.set_prevote_idx(); self.outgoing.push(Message::Prevote(prevote)); } } @@ -421,6 +422,7 @@ impl> VotingRound where if self.voting.is_active() { debug!(target: "afg", "Casting precommit for round {}", self.votes.number()); let precommit = self.construct_precommit(); + self.votes.set_precommit_idx(); self.env.precommitted(self.round_number(), precommit.clone())?; self.outgoing.push(Message::Precommit(precommit)); } From 2e9ade6dc4d7f159191391a7a6ac76aa8a442917 Mon Sep 17 00:00:00 2001 From: Marcio Diaz Date: Wed, 8 May 2019 16:42:05 +0200 Subject: [PATCH 03/21] feat: add HistoricalVotes struct --- src/round.rs | 14 ++++++++++++-- src/voter/mod.rs | 4 ++-- src/voter/voting_round.rs | 18 +++++++++++++++--- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/round.rs b/src/round.rs index 352af770..5fcd7863 100644 --- a/src/round.rs +++ b/src/round.rs @@ -677,19 +677,29 @@ impl Round where self.precommit.votes() } - /// Save the len of prevotes received at the moment of prevoting. + /// Set the length of prevotes received at the moment of prevoting. pub fn set_prevote_idx(&mut self) -> bool { self.prevote.voted_at = Some(self.prevote.votes().len()); println!("set prevote idx to {:?}", self.prevote.voted_at); true } - /// Save the len of precommits received at the moment of precommiting. + /// Set the length of precommits received at the moment of precommiting. pub fn set_precommit_idx(&mut self) -> bool { self.precommit.voted_at = Some(self.precommit.votes().len()); println!("set precommit idx to {:?}", self.precommit.voted_at); true } + + /// Get the length of prevotes received at the moment of prevoting. + pub fn prevote_idx(&self) -> Option { + self.prevote.voted_at + } + + /// Get the length of precommits received at the moment of precommiting. + pub fn precommit_idx(&self) -> Option { + self.precommit.voted_at + } } #[cfg(test)] diff --git a/src/voter/mod.rs b/src/voter/mod.rs index d30c3bb1..970b40c2 100644 --- a/src/voter/mod.rs +++ b/src/voter/mod.rs @@ -40,7 +40,7 @@ use crate::{ }; use crate::voter_set::VoterSet; use past_rounds::PastRounds; -use voting_round::{VotingRound, State as VotingRoundState}; +use voting_round::{VotingRound, State as VotingRoundState, HistoricalVotes}; mod past_rounds; mod voting_round; @@ -101,7 +101,7 @@ pub trait Environment: Chain { round: u64, state: RoundState, base: (H, N), - votes: Vec>, + votes: HistoricalVotes>, ) -> Result<(), Self::Error>; /// Called when a block should be finalized. diff --git a/src/voter/voting_round.rs b/src/voter/voting_round.rs index daa4eacb..493ad4ff 100644 --- a/src/voter/voting_round.rs +++ b/src/voter/voting_round.rs @@ -95,6 +95,12 @@ impl Voting { } } +pub struct HistoricalVotes { + seen: Vec, + prevote_idx: Option, + precommit_idx: Option, +} + impl> VotingRound where H: Hash + Clone + Eq + Ord + ::std::fmt::Debug, N: Copy + BlockNumberOps + ::std::fmt::Debug, @@ -256,7 +262,7 @@ impl> VotingRound where } /// Return all imported votes for the round (prevotes and precommits). - pub(super) fn votes(&self) -> Vec> { + pub(super) fn votes(&self) -> HistoricalVotes> { let prevotes = self.votes.prevotes().into_iter().map(|(id, prevote, signature)| { SignedMessage { id, @@ -273,7 +279,13 @@ impl> VotingRound where } }); - prevotes.chain(precommits).collect() + let prevotes_len = prevotes.len(); + + HistoricalVotes { + seen: prevotes.chain(precommits).collect(), + prevote_idx: self.votes.prevote_idx(), + precommit_idx: self.votes.precommit_idx().map(|idx| idx + prevotes_len), + } } fn process_incoming(&mut self) -> Result<(), E::Error> { @@ -422,8 +434,8 @@ impl> VotingRound where if self.voting.is_active() { debug!(target: "afg", "Casting precommit for round {}", self.votes.number()); let precommit = self.construct_precommit(); - self.votes.set_precommit_idx(); self.env.precommitted(self.round_number(), precommit.clone())?; + self.votes.set_precommit_idx(); self.outgoing.push(Message::Precommit(precommit)); } self.state = Some(State::Precommitted); From c1ac719c76f31570ed7a0e1ecd10f863849043ee Mon Sep 17 00:00:00 2001 From: Marcio Diaz Date: Thu, 9 May 2019 20:09:02 +0200 Subject: [PATCH 04/21] fix: seen is more interleaved now, not sure if enough --- src/voter/voting_round.rs | 46 +++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/src/voter/voting_round.rs b/src/voter/voting_round.rs index b5f0bf6b..ddac1501 100644 --- a/src/voter/voting_round.rs +++ b/src/voter/voting_round.rs @@ -48,13 +48,14 @@ impl std::fmt::Debug for State { } /// Logic for a voter on a specific round. -pub(super) struct VotingRound> where +pub(super) struct VotingRound, M> where H: Hash + Clone + Eq + Ord + ::std::fmt::Debug, N: Copy + BlockNumberOps + ::std::fmt::Debug, { env: Arc, voting: Voting, votes: Round, + historical_votes: HistoricalVotes, incoming: E::In, outgoing: Buffered, state: Option>, // state machine driving votes. @@ -101,7 +102,7 @@ pub struct HistoricalVotes { precommit_idx: Option, } -impl> VotingRound where +impl, M> VotingRound where H: Hash + Clone + Eq + Ord + ::std::fmt::Debug, N: Copy + BlockNumberOps + ::std::fmt::Debug, { @@ -113,7 +114,7 @@ impl> VotingRound where last_round_state: Option>, finalized_sender: UnboundedSender<(H, N, u64, Commit)>, env: Arc, - ) -> VotingRound { + ) -> VotingRound { let round_data = env.round_data(round_number); let round_params = crate::round::RoundParams { voters, @@ -138,6 +139,11 @@ impl> VotingRound where VotingRound { votes, voting, + historical_votes: HistoricalVotes { + seen: Vec::new(), + prevote_idx: None, + precommit_idx: None, + }, incoming: round_data.incoming, outgoing: Buffered::new(round_data.outgoing), state: Some( @@ -273,28 +279,46 @@ impl> VotingRound where /// Return all imported votes for the round (prevotes and precommits). pub(super) fn votes(&self) -> HistoricalVotes> { - let prevotes = self.votes.prevotes().into_iter().map(|(id, prevote, signature)| { + let prevotes_before_prevote = self.votes.prevotes().into_iter().map(|(id, prevote, signature)| { SignedMessage { id, signature, message: Message::Prevote(prevote), } - }); + }).collect(); - let precommits = self.votes.precommits().into_iter().map(|(id, precommit, signature)| { + let precommits_before_prevote = self.votes.precommits().into_iter().map(|(id, precommit, signature)| { SignedMessage { id, signature, message: Message::Precommit(precommit), } - }); + }).collect(); + + // Indices when prevoted. + let (pv_pv_len, pv_pc_len) = self.votes.prevoted_indices().unwrap_or_default(); + + // Indices when precommited. + let (pc_pv_len, pc_pc_len) = self.votes.precommited_indices().unwrap_or_default(); + + let prevotes_before_precommit = prevotes_before_prevote.split_off(pv_pv_len); + let prevotes_after_precommit = prevotes_before_precommit.split_off(pc_pv_len - pv_pv_len); + + let precommits_before_precommit = precommits_before_prevote.split_off(pv_pc_len); + let precommits_after_precommit = precommits_before_precommit.split_off(pc_pc_len - pv_pc_len); - let prevotes_len = prevotes.len(); + let prevote_idx = prevotes_before_prevote.len() + precommits_before_prevote.len(); + let precommit_idx = prevote_idx + prevotes_before_precommit.len() + precommits_before_precommit.len(); HistoricalVotes { - seen: prevotes.chain(precommits).collect(), - prevote_idx: self.votes.prevote_idx(), - precommit_idx: self.votes.precommit_idx().map(|idx| idx + prevotes_len), + seen: prevotes_before_prevote + .chain(precommits_before_prevote) + .chain(prevotes_before_precommit) + .chain(precommits_before_precommit) + .chain(prevotes_after_precommit) + .chain(precommits_after_precommit).collect(), + prevote_idx, + precommit_idx, } } From b174a92ac1794c139ebaa6ab9ed1a78f55520e89 Mon Sep 17 00:00:00 2001 From: Marcio Diaz Date: Thu, 9 May 2019 20:46:16 +0200 Subject: [PATCH 05/21] fix: compiles --- src/round.rs | 36 ++++++++++++++-------------- src/voter/voting_round.rs | 50 +++++++++++++-------------------------- 2 files changed, 35 insertions(+), 51 deletions(-) diff --git a/src/round.rs b/src/round.rs index df90b8a3..724597ad 100644 --- a/src/round.rs +++ b/src/round.rs @@ -98,7 +98,6 @@ impl VoteMultiplicity { struct VoteTracker { votes: HashMap>, current_weight: u64, - voted_at: Option, } /// Result of adding a vote. @@ -112,7 +111,6 @@ impl VoteTracker VoteTracker { votes: HashMap::new(), current_weight: 0, - voted_at: None, } } @@ -225,6 +223,8 @@ pub struct Round { graph: VoteGraph, // DAG of blocks which have been voted on. prevote: VoteTracker, Signature>, // tracks prevotes that have been counted precommit: VoteTracker, Signature>, // tracks precommits + prevoted_indices: Option<(usize, usize)>, + precommited_indices: Option<(usize, usize)>, round_number: u64, voters: VoterSet, total_weight: u64, @@ -276,6 +276,8 @@ impl Round where graph: VoteGraph::new(base_hash, base_number), prevote: VoteTracker::new(), precommit: VoteTracker::new(), + prevoted_indices: None, + precommited_indices: None, bitfield_context: BitfieldContext::new(n_validators), prevote_ghost: None, precommit_ghost: None, @@ -677,28 +679,26 @@ impl Round where self.precommit.votes() } - /// Set the length of prevotes received at the moment of prevoting. - pub fn set_prevote_idx(&mut self) -> bool { - self.prevote.voted_at = Some(self.prevote.votes().len()); - println!("set prevote idx to {:?}", self.prevote.voted_at); - true + /// Set the length of prevotes and precommits received at the moment of prevoting. + pub fn set_prevoted_indices(&mut self) { + self.prevoted_indices = Some((self.prevote.votes().len(), self.precommit.votes().len())); + println!("set prevoted indices to {:?}", self.prevoted_indices) } - /// Set the length of precommits received at the moment of precommiting. - pub fn set_precommit_idx(&mut self) -> bool { - self.precommit.voted_at = Some(self.precommit.votes().len()); - println!("set precommit idx to {:?}", self.precommit.voted_at); - true + /// Set the length of prevotes and precommits received at the moment of precommiting. + pub fn set_precommited_indices(&mut self) { + self.precommited_indices = Some((self.prevote.votes().len(), self.precommit.votes().len())); + println!("set precommited indices to {:?}", self.precommited_indices) } - /// Get the length of prevotes received at the moment of prevoting. - pub fn prevote_idx(&self) -> Option { - self.prevote.voted_at + /// Get the length of prevotes and precommits received at the moment of prevoting. + pub fn prevoted_indices(&self) -> Option<(usize, usize)> { + self.prevoted_indices } - /// Get the length of precommits received at the moment of precommiting. - pub fn precommit_idx(&self) -> Option { - self.precommit.voted_at + /// Get the length of prevotes and precommits received at the moment of precommiting. + pub fn precommited_indices(&self) -> Option<(usize, usize)> { + self.precommited_indices } } diff --git a/src/voter/voting_round.rs b/src/voter/voting_round.rs index ddac1501..5426ee04 100644 --- a/src/voter/voting_round.rs +++ b/src/voter/voting_round.rs @@ -48,14 +48,13 @@ impl std::fmt::Debug for State { } /// Logic for a voter on a specific round. -pub(super) struct VotingRound, M> where +pub(super) struct VotingRound> where H: Hash + Clone + Eq + Ord + ::std::fmt::Debug, N: Copy + BlockNumberOps + ::std::fmt::Debug, { env: Arc, voting: Voting, votes: Round, - historical_votes: HistoricalVotes, incoming: E::In, outgoing: Buffered, state: Option>, // state machine driving votes. @@ -98,11 +97,11 @@ impl Voting { pub struct HistoricalVotes { seen: Vec, - prevote_idx: Option, - precommit_idx: Option, + prevote_idx: usize, + precommit_idx: usize, } -impl, M> VotingRound where +impl> VotingRound where H: Hash + Clone + Eq + Ord + ::std::fmt::Debug, N: Copy + BlockNumberOps + ::std::fmt::Debug, { @@ -114,7 +113,7 @@ impl, M> VotingRound where last_round_state: Option>, finalized_sender: UnboundedSender<(H, N, u64, Commit)>, env: Arc, - ) -> VotingRound { + ) -> VotingRound { let round_data = env.round_data(round_number); let round_params = crate::round::RoundParams { voters, @@ -139,11 +138,6 @@ impl, M> VotingRound where VotingRound { votes, voting, - historical_votes: HistoricalVotes { - seen: Vec::new(), - prevote_idx: None, - precommit_idx: None, - }, incoming: round_data.incoming, outgoing: Buffered::new(round_data.outgoing), state: Some( @@ -213,16 +207,6 @@ impl, M> VotingRound where self.votes.voters() } - /// Get the best block finalized in this round. - pub(super) fn set_precommit_idx(&mut self, idx: usize) -> bool { - self.votes.set_precommit_idx(idx) - } - - /// Get the best block finalized in this round. - pub(super) fn set_prevote_idx(&mut self, idx: usize) -> bool { - self.votes.set_prevote_idx(idx) - } - /// Get the best block finalized in this round. pub(super) fn finalized(&self) -> Option<&(H, N)> { self.votes.finalized() @@ -279,7 +263,7 @@ impl, M> VotingRound where /// Return all imported votes for the round (prevotes and precommits). pub(super) fn votes(&self) -> HistoricalVotes> { - let prevotes_before_prevote = self.votes.prevotes().into_iter().map(|(id, prevote, signature)| { + let mut prevotes_before_prevote: Vec<_> = self.votes.prevotes().into_iter().map(|(id, prevote, signature)| { SignedMessage { id, signature, @@ -287,7 +271,7 @@ impl, M> VotingRound where } }).collect(); - let precommits_before_prevote = self.votes.precommits().into_iter().map(|(id, precommit, signature)| { + let mut precommits_before_prevote: Vec<_> = self.votes.precommits().into_iter().map(|(id, precommit, signature)| { SignedMessage { id, signature, @@ -301,22 +285,22 @@ impl, M> VotingRound where // Indices when precommited. let (pc_pv_len, pc_pc_len) = self.votes.precommited_indices().unwrap_or_default(); - let prevotes_before_precommit = prevotes_before_prevote.split_off(pv_pv_len); + let mut prevotes_before_precommit = prevotes_before_prevote.split_off(pv_pv_len); let prevotes_after_precommit = prevotes_before_precommit.split_off(pc_pv_len - pv_pv_len); - let precommits_before_precommit = precommits_before_prevote.split_off(pv_pc_len); + let mut precommits_before_precommit = precommits_before_prevote.split_off(pv_pc_len); let precommits_after_precommit = precommits_before_precommit.split_off(pc_pc_len - pv_pc_len); let prevote_idx = prevotes_before_prevote.len() + precommits_before_prevote.len(); let precommit_idx = prevote_idx + prevotes_before_precommit.len() + precommits_before_precommit.len(); HistoricalVotes { - seen: prevotes_before_prevote - .chain(precommits_before_prevote) - .chain(prevotes_before_precommit) - .chain(precommits_before_precommit) - .chain(prevotes_after_precommit) - .chain(precommits_after_precommit).collect(), + seen: prevotes_before_prevote.into_iter() + .chain(precommits_before_prevote.into_iter()) + .chain(prevotes_before_precommit.into_iter()) + .chain(precommits_before_precommit.into_iter()) + .chain(prevotes_after_precommit.into_iter()) + .chain(precommits_after_precommit.into_iter()).collect(), prevote_idx, precommit_idx, } @@ -416,7 +400,7 @@ impl, M> VotingRound where if let Some(prevote) = self.construct_prevote(last_round_state)? { debug!(target: "afg", "Casting prevote for round {}", self.votes.number()); self.env.prevoted(self.round_number(), prevote.clone())?; - self.votes.set_prevote_idx(); + self.votes.set_prevoted_indices(); self.outgoing.push(Message::Prevote(prevote)); } } @@ -469,7 +453,7 @@ impl, M> VotingRound where debug!(target: "afg", "Casting precommit for round {}", self.votes.number()); let precommit = self.construct_precommit(); self.env.precommitted(self.round_number(), precommit.clone())?; - self.votes.set_precommit_idx(); + self.votes.set_precommited_indices(); self.outgoing.push(Message::Precommit(precommit)); } self.state = Some(State::Precommitted); From 8674ae1bfd8322b8af32223de2c3bffac9ecf92a Mon Sep 17 00:00:00 2001 From: Marcio Diaz Date: Thu, 9 May 2019 21:11:59 +0200 Subject: [PATCH 06/21] fix: test compiles --- src/lib.rs | 9 +++++++++ src/testing.rs | 6 ++---- src/voter/mod.rs | 4 ++-- src/voter/voting_round.rs | 7 +------ 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 063299cb..636c6d50 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -478,6 +478,15 @@ pub fn process_commit_validation_result( } } +/// Historical votes seen in a round. +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "derive-codec", derive(Encode, Decode))] +pub struct HistoricalVotes { + seen: Vec, + prevote_idx: usize, + precommit_idx: usize, +} + #[cfg(test)] mod tests { use super::threshold; diff --git a/src/testing.rs b/src/testing.rs index 4d987603..dd286c53 100644 --- a/src/testing.rs +++ b/src/testing.rs @@ -24,7 +24,7 @@ use tokio::timer::Delay; use parking_lot::Mutex; use futures::prelude::*; use futures::sync::mpsc::{self, UnboundedReceiver, UnboundedSender}; -use super::{Chain, Commit, Error, Equivocation, Message, Prevote, Precommit, PrimaryPropose, SignedMessage}; +use super::{Chain, Commit, Error, Equivocation, Message, Prevote, Precommit, PrimaryPropose, SignedMessage, HistoricalVotes}; pub const GENESIS_HASH: &str = "genesis"; const NULL_HASH: &str = "NULL"; @@ -53,8 +53,6 @@ impl DummyChain { } pub fn push_blocks(&mut self, mut parent: &'static str, blocks: &[&'static str]) { - use std::cmp::Ord; - if blocks.is_empty() { return } let base_number = self.inner.get(parent).unwrap().number + 1; @@ -218,7 +216,7 @@ impl crate::voter::Environment<&'static str, u32> for Environment { _round: u64, _state: RoundState<&'static str, u32>, _base: (&'static str, u32), - _votes: Vec>, + _votes: HistoricalVotes>, ) -> Result<(), Error> { Ok(()) } diff --git a/src/voter/mod.rs b/src/voter/mod.rs index 970b40c2..7aff9b89 100644 --- a/src/voter/mod.rs +++ b/src/voter/mod.rs @@ -36,11 +36,11 @@ use std::sync::Arc; use crate::round::State as RoundState; use crate::{ Chain, Commit, CompactCommit, Equivocation, Message, Prevote, Precommit, PrimaryPropose, - SignedMessage, BlockNumberOps, validate_commit, CommitValidationResult + SignedMessage, BlockNumberOps, validate_commit, CommitValidationResult, HistoricalVotes, }; use crate::voter_set::VoterSet; use past_rounds::PastRounds; -use voting_round::{VotingRound, State as VotingRoundState, HistoricalVotes}; +use voting_round::{VotingRound, State as VotingRoundState}; mod past_rounds; mod voting_round; diff --git a/src/voter/voting_round.rs b/src/voter/voting_round.rs index 5426ee04..9e470a39 100644 --- a/src/voter/voting_round.rs +++ b/src/voter/voting_round.rs @@ -24,6 +24,7 @@ use crate::round::{Round, State as RoundState}; use crate::{ Commit, Message, Prevote, Precommit, PrimaryPropose, SignedMessage, SignedPrecommit, BlockNumberOps, validate_commit, ImportResult, + HistoricalVotes, }; use crate::voter_set::VoterSet; use super::{Environment, Buffered}; @@ -95,12 +96,6 @@ impl Voting { } } -pub struct HistoricalVotes { - seen: Vec, - prevote_idx: usize, - precommit_idx: usize, -} - impl> VotingRound where H: Hash + Clone + Eq + Ord + ::std::fmt::Debug, N: Copy + BlockNumberOps + ::std::fmt::Debug, From 00c48c8e43b45ac7c3bd9f6030cb50050afac674 Mon Sep 17 00:00:00 2001 From: Marcio Diaz Date: Fri, 10 May 2019 11:43:06 +0200 Subject: [PATCH 07/21] fix: add index to votes in VoteTracker, since votes() doesn't return sorted votes --- src/round.rs | 60 +++++++++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/src/round.rs b/src/round.rs index 724597ad..91f690f6 100644 --- a/src/round.rs +++ b/src/round.rs @@ -77,17 +77,17 @@ impl AddAssign for VoteWeight { // votes from a single validator enum VoteMultiplicity { // validator voted once. - Single(Vote, Signature), + Single(Vote, Signature, usize), // validator equivocated at least once. - Equivocated((Vote, Signature), (Vote, Signature)), + Equivocated((Vote, Signature, usize), (Vote, Signature, usize)), } impl VoteMultiplicity { fn contains(&self, vote: &Vote, signature: &Signature) -> bool { match self { - VoteMultiplicity::Single(v, s) => + VoteMultiplicity::Single(v, s, _) => v == vote && s == signature, - VoteMultiplicity::Equivocated((v1, s1), (v2, s2)) => { + VoteMultiplicity::Equivocated((v1, s1, _), (v2, s2, _)) => { v1 == vote && s1 == signature || v2 == vote && s2 == signature }, @@ -98,6 +98,7 @@ impl VoteMultiplicity { struct VoteTracker { votes: HashMap>, current_weight: u64, + num_votes: usize, } /// Result of adding a vote. @@ -111,6 +112,7 @@ impl VoteTracker VoteTracker { votes: HashMap::new(), current_weight: 0, + num_votes: 0, } } @@ -130,7 +132,9 @@ impl VoteTracker match self.votes.entry(id) { Entry::Vacant(vacant) => { self.current_weight += weight; - let multiplicity = vacant.insert(VoteMultiplicity::Single(vote, signature)); + let multiplicity = vacant.insert(VoteMultiplicity::Single(vote, signature, self.num_votes)); + self.num_votes += 1; + return AddVoteResult { multiplicity: Some(multiplicity), duplicated: false, @@ -143,8 +147,11 @@ impl VoteTracker // import, but ignore further equivocations. let new_val = match *occupied.get_mut() { - VoteMultiplicity::Single(ref v, ref s) => - Some(VoteMultiplicity::Equivocated((v.clone(), s.clone()), (vote, signature))), + VoteMultiplicity::Single(ref v, ref s, n) => + Some(VoteMultiplicity::Equivocated( + (v.clone(), s.clone(), n), + (vote, signature, self.num_votes) + )), VoteMultiplicity::Equivocated(_, _) => { return AddVoteResult { multiplicity: None, duplicated: false } } @@ -152,6 +159,7 @@ impl VoteTracker if let Some(new_val) = new_val { *occupied.get_mut() = new_val; + self.num_votes += 1; } AddVoteResult { @@ -168,12 +176,12 @@ impl VoteTracker for (id, vote) in self.votes.iter() { match vote { - VoteMultiplicity::Single(v, s) => { - votes.push((id.clone(), v.clone(), s.clone())) + VoteMultiplicity::Single(v, s, n) => { + votes.insert(*n, (id.clone(), v.clone(), s.clone())); }, - VoteMultiplicity::Equivocated((v1, s1), (v2, s2)) => { - votes.push((id.clone(), v1.clone(), s1.clone())); - votes.push((id.clone(), v2.clone(), s2.clone())); + VoteMultiplicity::Equivocated((v1, s1, n1), (v2, s2, n2)) => { + votes.insert(*n1, (id.clone(), v1.clone(), s1.clone())); + votes.insert(*n2, (id.clone(), v2.clone(), s2.clone())); }, } } @@ -323,7 +331,7 @@ impl Round where let round_number = self.round_number; match multiplicity { - VoteMultiplicity::Single(ref vote, _) => { + VoteMultiplicity::Single(vote, _, _) => { let vote_weight = VoteWeight { bitfield: self.bitfield_context.prevote_bitfield(info) .expect("info is instantiated from same voter set as context; qed"), @@ -338,7 +346,7 @@ impl Round where None } - VoteMultiplicity::Equivocated(ref first, ref second) => { + VoteMultiplicity::Equivocated((fst_vote, fst_sig, _), (snd_vote, snd_sig, _)) => { // mark the equivocator as such. no need to "undo" the first vote. self.bitfield_context.equivocated_prevote(info) .expect("info is instantiated from same voter set as bitfield; qed"); @@ -346,8 +354,8 @@ impl Round where Some(Equivocation { round_number, identity: signer, - first: first.clone(), - second: second.clone(), + first: (fst_vote.clone(), fst_sig.clone()), + second: (snd_vote.clone(), snd_sig.clone()), }) } } @@ -400,7 +408,7 @@ impl Round where let round_number = self.round_number; match multiplicity { - VoteMultiplicity::Single(ref vote, _) => { + VoteMultiplicity::Single(vote, _, _) => { let vote_weight = VoteWeight { bitfield: self.bitfield_context.precommit_bitfield(info) .expect("info is instantiated from same voter set as context; qed"), @@ -415,7 +423,7 @@ impl Round where None } - VoteMultiplicity::Equivocated(ref first, ref second) => { + VoteMultiplicity::Equivocated((fst_vote, fst_sig, _), (snd_vote, snd_sig, _)) => { // mark the equivocator as such. no need to "undo" the first vote. self.bitfield_context.equivocated_precommit(info) .expect("info is instantiated from same voter set as bitfield; qed"); @@ -423,8 +431,8 @@ impl Round where Some(Equivocation { round_number, identity: signer, - first: first.clone(), - second: second.clone(), + first: (fst_vote.clone(), fst_sig.clone()), + second: (snd_vote.clone(), snd_sig.clone()), }) } } @@ -476,8 +484,8 @@ impl Round where type Item = (V, S); fn next(&mut self) -> Option<(V, S)> { - match *self.multiplicity { - VoteMultiplicity::Single(ref v, ref s) => { + match self.multiplicity { + VoteMultiplicity::Single(v, s, _) => { if self.yielded == 0 { self.yielded += 1; Some((v.clone(), s.clone())) @@ -485,10 +493,10 @@ impl Round where None } } - VoteMultiplicity::Equivocated(ref a, ref b) => { + VoteMultiplicity::Equivocated((fst_vote, fst_sig, _), (snd_vote, snd_sig, _)) => { let res = match self.yielded { - 0 => Some(a.clone()), - 1 => Some(b.clone()), + 0 => Some((fst_vote.clone(), fst_sig.clone())), + 1 => Some((snd_vote.clone(), snd_sig.clone())), _ => None, }; @@ -502,7 +510,7 @@ impl Round where let (f_hash, _f_num) = self.finalized.clone()?; let find_valid_precommits = self.precommit.votes.iter() .filter(move |&(_id, ref multiplicity)| { - if let VoteMultiplicity::Single(ref v, _) = *multiplicity { + if let VoteMultiplicity::Single(v, _, _) = *multiplicity { // if there is a single vote from this voter, we only include it // if it branches off of the target. chain.is_equal_or_descendent_of(f_hash.clone(), v.target_hash.clone()) From 70197e3c4964b0c7ee3f35f7395710bcb2e9e11a Mon Sep 17 00:00:00 2001 From: Marcio Diaz Date: Fri, 10 May 2019 11:52:36 +0200 Subject: [PATCH 08/21] fix: indices --- src/round.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/round.rs b/src/round.rs index 91f690f6..32b4151f 100644 --- a/src/round.rs +++ b/src/round.rs @@ -689,13 +689,13 @@ impl Round where /// Set the length of prevotes and precommits received at the moment of prevoting. pub fn set_prevoted_indices(&mut self) { - self.prevoted_indices = Some((self.prevote.votes().len(), self.precommit.votes().len())); + self.prevoted_indices = Some((self.prevote.num_votes, self.precommit.num_votes)); println!("set prevoted indices to {:?}", self.prevoted_indices) } /// Set the length of prevotes and precommits received at the moment of precommiting. pub fn set_precommited_indices(&mut self) { - self.precommited_indices = Some((self.prevote.votes().len(), self.precommit.votes().len())); + self.precommited_indices = Some((self.prevote.num_votes, self.precommit.num_votes)); println!("set precommited indices to {:?}", self.precommited_indices) } From 72bb3d15ab6fa944fb1f9bfc5b2f9377c5b4a483 Mon Sep 17 00:00:00 2001 From: Marcio Diaz Date: Fri, 10 May 2019 12:04:47 +0200 Subject: [PATCH 09/21] chore: add note about performance --- src/round.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/round.rs b/src/round.rs index 32b4151f..8ce7d534 100644 --- a/src/round.rs +++ b/src/round.rs @@ -173,7 +173,8 @@ impl VoteTracker // Returns all imported votes. fn votes(&self) -> Vec<(Id, Vote, Signature)> { let mut votes = Vec::new(); - + // TODO: I think it should be faster to initialized votes to default values + // and then do votes[n] = (). But i need to find the default... for (id, vote) in self.votes.iter() { match vote { VoteMultiplicity::Single(v, s, n) => { From 0d6d721e4eae50dfab666b3f57ad999563e1ee6e Mon Sep 17 00:00:00 2001 From: Marcio Diaz Date: Fri, 10 May 2019 14:03:03 +0200 Subject: [PATCH 10/21] fix: ok, I'll just duplicate votes for now --- src/lib.rs | 8 +++---- src/round.rs | 47 +++++++++++++++++++++--------------- src/voter/mod.rs | 4 ++-- src/voter/voting_round.rs | 50 +++++++++++++-------------------------- 4 files changed, 50 insertions(+), 59 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 636c6d50..7e3e98c9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -481,10 +481,10 @@ pub fn process_commit_validation_result( /// Historical votes seen in a round. #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "derive-codec", derive(Encode, Decode))] -pub struct HistoricalVotes { - seen: Vec, - prevote_idx: usize, - precommit_idx: usize, +pub struct HistoricalVotes { + seen: Vec>, + prevote_idx: Option, + precommit_idx: Option, } #[cfg(test)] diff --git a/src/round.rs b/src/round.rs index 8ce7d534..463b1e66 100644 --- a/src/round.rs +++ b/src/round.rs @@ -22,7 +22,7 @@ use crate::bitfield::{Shared as BitfieldContext, Bitfield}; use crate::vote_graph::VoteGraph; use crate::voter_set::VoterSet; -use super::{Equivocation, Prevote, Precommit, Chain, BlockNumberOps}; +use super::{Equivocation, Prevote, Precommit, Chain, BlockNumberOps, HistoricalVotes, Message}; #[derive(Hash, Eq, PartialEq)] struct Address; @@ -232,8 +232,7 @@ pub struct Round { graph: VoteGraph, // DAG of blocks which have been voted on. prevote: VoteTracker, Signature>, // tracks prevotes that have been counted precommit: VoteTracker, Signature>, // tracks precommits - prevoted_indices: Option<(usize, usize)>, - precommited_indices: Option<(usize, usize)>, + historical_votes: HistoricalVotes, round_number: u64, voters: VoterSet, total_weight: u64, @@ -285,8 +284,11 @@ impl Round where graph: VoteGraph::new(base_hash, base_number), prevote: VoteTracker::new(), precommit: VoteTracker::new(), - prevoted_indices: None, - precommited_indices: None, + historical_votes: HistoricalVotes { + seen: Vec::new(), + prevote_idx: None, + precommit_idx: None, + }, bitfield_context: BitfieldContext::new(n_validators), prevote_ghost: None, precommit_ghost: None, @@ -345,6 +347,8 @@ impl Round where chain, )?; + self.historical_votes.seen.push(Message::Prevote(vote.clone())); + None } VoteMultiplicity::Equivocated((fst_vote, fst_sig, _), (snd_vote, snd_sig, _)) => { @@ -422,6 +426,8 @@ impl Round where chain, )?; + self.historical_votes.seen.push(Message::Precommit(vote.clone())); + None } VoteMultiplicity::Equivocated((fst_vote, fst_sig, _), (snd_vote, snd_sig, _)) => { @@ -688,26 +694,29 @@ impl Round where self.precommit.votes() } - /// Set the length of prevotes and precommits received at the moment of prevoting. - pub fn set_prevoted_indices(&mut self) { - self.prevoted_indices = Some((self.prevote.num_votes, self.precommit.num_votes)); - println!("set prevoted indices to {:?}", self.prevoted_indices) + /// Return all imported votes (prevotes and precommits) ordered. + pub fn historical_votes(&self) -> &HistoricalVotes { + &self.historical_votes + } + + /// Set the number of prevotes and precommits received at the moment of prevoting. + pub fn set_prevoted_index(&mut self) { + self.historical_votes.prevote_idx = Some(self.historical_votes.seen.len()) } - /// Set the length of prevotes and precommits received at the moment of precommiting. - pub fn set_precommited_indices(&mut self) { - self.precommited_indices = Some((self.prevote.num_votes, self.precommit.num_votes)); - println!("set precommited indices to {:?}", self.precommited_indices) + /// Set the number of prevotes and precommits received at the moment of precommiting. + pub fn set_precommited_index(&mut self) { + self.historical_votes.precommit_idx = Some(self.historical_votes.seen.len()) } - /// Get the length of prevotes and precommits received at the moment of prevoting. - pub fn prevoted_indices(&self) -> Option<(usize, usize)> { - self.prevoted_indices + /// Get the number of prevotes and precommits received at the moment of prevoting. + pub fn prevoted_index(&self) -> Option { + self.historical_votes.prevote_idx } - /// Get the length of prevotes and precommits received at the moment of precommiting. - pub fn precommited_indices(&self) -> Option<(usize, usize)> { - self.precommited_indices + /// Get the number of prevotes and precommits received at the moment of precommiting. + pub fn precommited_index(&self) -> Option { + self.historical_votes.precommit_idx } } diff --git a/src/voter/mod.rs b/src/voter/mod.rs index 7aff9b89..cc8f8df7 100644 --- a/src/voter/mod.rs +++ b/src/voter/mod.rs @@ -36,7 +36,7 @@ use std::sync::Arc; use crate::round::State as RoundState; use crate::{ Chain, Commit, CompactCommit, Equivocation, Message, Prevote, Precommit, PrimaryPropose, - SignedMessage, BlockNumberOps, validate_commit, CommitValidationResult, HistoricalVotes, + SignedMessage, BlockNumberOps, validate_commit, CommitValidationResult, }; use crate::voter_set::VoterSet; use past_rounds::PastRounds; @@ -101,7 +101,7 @@ pub trait Environment: Chain { round: u64, state: RoundState, base: (H, N), - votes: HistoricalVotes>, + votes: Vec>, ) -> Result<(), Self::Error>; /// Called when a block should be finalized. diff --git a/src/voter/voting_round.rs b/src/voter/voting_round.rs index 9e470a39..165c9668 100644 --- a/src/voter/voting_round.rs +++ b/src/voter/voting_round.rs @@ -256,49 +256,31 @@ impl> VotingRound where self.best_finalized.as_ref() } - /// Return all imported votes for the round (prevotes and precommits). - pub(super) fn votes(&self) -> HistoricalVotes> { - let mut prevotes_before_prevote: Vec<_> = self.votes.prevotes().into_iter().map(|(id, prevote, signature)| { + /// Return all imported votes for the round (prevotes and precommits) unordered. + pub(super) fn votes(&self) -> Vec> { + let prevotes = self.votes.prevotes().into_iter().map(|(id, prevote, signature)| { SignedMessage { id, signature, message: Message::Prevote(prevote), } - }).collect(); + }); - let mut precommits_before_prevote: Vec<_> = self.votes.precommits().into_iter().map(|(id, precommit, signature)| { + let precommits = self.votes.precommits().into_iter().map(|(id, precommit, signature)| { SignedMessage { id, signature, message: Message::Precommit(precommit), } - }).collect(); - - // Indices when prevoted. - let (pv_pv_len, pv_pc_len) = self.votes.prevoted_indices().unwrap_or_default(); - - // Indices when precommited. - let (pc_pv_len, pc_pc_len) = self.votes.precommited_indices().unwrap_or_default(); - - let mut prevotes_before_precommit = prevotes_before_prevote.split_off(pv_pv_len); - let prevotes_after_precommit = prevotes_before_precommit.split_off(pc_pv_len - pv_pv_len); - - let mut precommits_before_precommit = precommits_before_prevote.split_off(pv_pc_len); - let precommits_after_precommit = precommits_before_precommit.split_off(pc_pc_len - pv_pc_len); - - let prevote_idx = prevotes_before_prevote.len() + precommits_before_prevote.len(); - let precommit_idx = prevote_idx + prevotes_before_precommit.len() + precommits_before_precommit.len(); - - HistoricalVotes { - seen: prevotes_before_prevote.into_iter() - .chain(precommits_before_prevote.into_iter()) - .chain(prevotes_before_precommit.into_iter()) - .chain(precommits_before_precommit.into_iter()) - .chain(prevotes_after_precommit.into_iter()) - .chain(precommits_after_precommit.into_iter()).collect(), - prevote_idx, - precommit_idx, - } + }); + + prevotes.chain(precommits).collect() + } + + /// Return all imported votes for the round (prevotes and precommits) ordered + /// and indicating at which indices we voted. + pub(super) fn historical_votes(&self) -> &HistoricalVotes { + self.votes.historical_votes() } fn process_incoming(&mut self) -> Result<(), E::Error> { @@ -395,7 +377,7 @@ impl> VotingRound where if let Some(prevote) = self.construct_prevote(last_round_state)? { debug!(target: "afg", "Casting prevote for round {}", self.votes.number()); self.env.prevoted(self.round_number(), prevote.clone())?; - self.votes.set_prevoted_indices(); + self.votes.set_prevoted_index(); self.outgoing.push(Message::Prevote(prevote)); } } @@ -448,7 +430,7 @@ impl> VotingRound where debug!(target: "afg", "Casting precommit for round {}", self.votes.number()); let precommit = self.construct_precommit(); self.env.precommitted(self.round_number(), precommit.clone())?; - self.votes.set_precommited_indices(); + self.votes.set_precommited_index(); self.outgoing.push(Message::Precommit(precommit)); } self.state = Some(State::Precommitted); From 3d0f81be18a15917292d79c5c65c1f0bd0f5c4a8 Mon Sep 17 00:00:00 2001 From: Marcio Diaz Date: Fri, 10 May 2019 17:48:45 +0200 Subject: [PATCH 11/21] fix: add new --- src/lib.rs | 10 ++++++++++ src/round.rs | 6 +----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 7e3e98c9..ab7044f6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -487,6 +487,16 @@ pub struct HistoricalVotes { precommit_idx: Option, } +impl HistoricalVotes { + pub fn new() -> Self { + HistoricalVotes { + seen: Vec::new(), + prevote_idx: None, + precommit_idx: None, + } + } +} + #[cfg(test)] mod tests { use super::threshold; diff --git a/src/round.rs b/src/round.rs index 463b1e66..7e6c3f35 100644 --- a/src/round.rs +++ b/src/round.rs @@ -284,11 +284,7 @@ impl Round where graph: VoteGraph::new(base_hash, base_number), prevote: VoteTracker::new(), precommit: VoteTracker::new(), - historical_votes: HistoricalVotes { - seen: Vec::new(), - prevote_idx: None, - precommit_idx: None, - }, + historical_votes: HistoricalVotes::new(), bitfield_context: BitfieldContext::new(n_validators), prevote_ghost: None, precommit_ghost: None, From 0060027f4a19071c56f3fcc7afeb77dde0b2e020 Mon Sep 17 00:00:00 2001 From: Marcio Diaz Date: Fri, 10 May 2019 17:50:19 +0200 Subject: [PATCH 12/21] fix: test compiles --- src/testing.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/testing.rs b/src/testing.rs index dd286c53..53fd1725 100644 --- a/src/testing.rs +++ b/src/testing.rs @@ -24,7 +24,7 @@ use tokio::timer::Delay; use parking_lot::Mutex; use futures::prelude::*; use futures::sync::mpsc::{self, UnboundedReceiver, UnboundedSender}; -use super::{Chain, Commit, Error, Equivocation, Message, Prevote, Precommit, PrimaryPropose, SignedMessage, HistoricalVotes}; +use super::{Chain, Commit, Error, Equivocation, Message, Prevote, Precommit, PrimaryPropose, SignedMessage}; pub const GENESIS_HASH: &str = "genesis"; const NULL_HASH: &str = "NULL"; @@ -216,7 +216,7 @@ impl crate::voter::Environment<&'static str, u32> for Environment { _round: u64, _state: RoundState<&'static str, u32>, _base: (&'static str, u32), - _votes: HistoricalVotes>, + _votes: Vec>, ) -> Result<(), Error> { Ok(()) } From c2c8b1cd8208e68d3f04de9da3dd06e62f7113f9 Mon Sep 17 00:00:00 2001 From: Marcio Diaz Date: Fri, 10 May 2019 18:12:52 +0200 Subject: [PATCH 13/21] fix: add some methods, clean --- src/lib.rs | 12 +++++++ src/round.rs | 66 ++++++++++++++++++--------------------- src/voter/mod.rs | 2 +- src/voter/voting_round.rs | 4 +-- 4 files changed, 46 insertions(+), 38 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index ab7044f6..0d35cfd5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -495,6 +495,18 @@ impl HistoricalVotes { precommit_idx: None, } } + + pub fn seen(&self) -> &Vec> { + &self.seen + } + + pub fn prevote_idx(&self) -> Option { + self.prevote_idx + } + + pub fn precommit_idx(&self) -> Option { + self.precommit_idx + } } #[cfg(test)] diff --git a/src/round.rs b/src/round.rs index 7e6c3f35..c4a06e2f 100644 --- a/src/round.rs +++ b/src/round.rs @@ -77,17 +77,17 @@ impl AddAssign for VoteWeight { // votes from a single validator enum VoteMultiplicity { // validator voted once. - Single(Vote, Signature, usize), + Single(Vote, Signature), // validator equivocated at least once. - Equivocated((Vote, Signature, usize), (Vote, Signature, usize)), + Equivocated((Vote, Signature), (Vote, Signature)), } impl VoteMultiplicity { fn contains(&self, vote: &Vote, signature: &Signature) -> bool { match self { - VoteMultiplicity::Single(v, s, _) => + VoteMultiplicity::Single(v, s) => v == vote && s == signature, - VoteMultiplicity::Equivocated((v1, s1, _), (v2, s2, _)) => { + VoteMultiplicity::Equivocated((v1, s1), (v2, s2)) => { v1 == vote && s1 == signature || v2 == vote && s2 == signature }, @@ -98,7 +98,6 @@ impl VoteMultiplicity { struct VoteTracker { votes: HashMap>, current_weight: u64, - num_votes: usize, } /// Result of adding a vote. @@ -112,7 +111,6 @@ impl VoteTracker VoteTracker { votes: HashMap::new(), current_weight: 0, - num_votes: 0, } } @@ -132,8 +130,7 @@ impl VoteTracker match self.votes.entry(id) { Entry::Vacant(vacant) => { self.current_weight += weight; - let multiplicity = vacant.insert(VoteMultiplicity::Single(vote, signature, self.num_votes)); - self.num_votes += 1; + let multiplicity = vacant.insert(VoteMultiplicity::Single(vote, signature)); return AddVoteResult { multiplicity: Some(multiplicity), @@ -147,11 +144,8 @@ impl VoteTracker // import, but ignore further equivocations. let new_val = match *occupied.get_mut() { - VoteMultiplicity::Single(ref v, ref s, n) => - Some(VoteMultiplicity::Equivocated( - (v.clone(), s.clone(), n), - (vote, signature, self.num_votes) - )), + VoteMultiplicity::Single(ref v, ref s) => + Some(VoteMultiplicity::Equivocated((v.clone(), s.clone()), (vote, signature))), VoteMultiplicity::Equivocated(_, _) => { return AddVoteResult { multiplicity: None, duplicated: false } } @@ -159,7 +153,6 @@ impl VoteTracker if let Some(new_val) = new_val { *occupied.get_mut() = new_val; - self.num_votes += 1; } AddVoteResult { @@ -173,16 +166,15 @@ impl VoteTracker // Returns all imported votes. fn votes(&self) -> Vec<(Id, Vote, Signature)> { let mut votes = Vec::new(); - // TODO: I think it should be faster to initialized votes to default values - // and then do votes[n] = (). But i need to find the default... + for (id, vote) in self.votes.iter() { match vote { - VoteMultiplicity::Single(v, s, n) => { - votes.insert(*n, (id.clone(), v.clone(), s.clone())); + VoteMultiplicity::Single(v, s) => { + votes.push((id.clone(), v.clone(), s.clone())) }, - VoteMultiplicity::Equivocated((v1, s1, n1), (v2, s2, n2)) => { - votes.insert(*n1, (id.clone(), v1.clone(), s1.clone())); - votes.insert(*n2, (id.clone(), v2.clone(), s2.clone())); + VoteMultiplicity::Equivocated((v1, s1), (v2, s2)) => { + votes.push((id.clone(), v1.clone(), s1.clone())); + votes.push((id.clone(), v2.clone(), s2.clone())); }, } } @@ -330,7 +322,7 @@ impl Round where let round_number = self.round_number; match multiplicity { - VoteMultiplicity::Single(vote, _, _) => { + VoteMultiplicity::Single(ref vote, _) => { let vote_weight = VoteWeight { bitfield: self.bitfield_context.prevote_bitfield(info) .expect("info is instantiated from same voter set as context; qed"), @@ -347,7 +339,7 @@ impl Round where None } - VoteMultiplicity::Equivocated((fst_vote, fst_sig, _), (snd_vote, snd_sig, _)) => { + VoteMultiplicity::Equivocated(ref first, ref second) => { // mark the equivocator as such. no need to "undo" the first vote. self.bitfield_context.equivocated_prevote(info) .expect("info is instantiated from same voter set as bitfield; qed"); @@ -355,8 +347,8 @@ impl Round where Some(Equivocation { round_number, identity: signer, - first: (fst_vote.clone(), fst_sig.clone()), - second: (snd_vote.clone(), snd_sig.clone()), + first: first.clone(), + second: second.clone(), }) } } @@ -409,7 +401,7 @@ impl Round where let round_number = self.round_number; match multiplicity { - VoteMultiplicity::Single(vote, _, _) => { + VoteMultiplicity::Single(ref vote, _) => { let vote_weight = VoteWeight { bitfield: self.bitfield_context.precommit_bitfield(info) .expect("info is instantiated from same voter set as context; qed"), @@ -426,7 +418,7 @@ impl Round where None } - VoteMultiplicity::Equivocated((fst_vote, fst_sig, _), (snd_vote, snd_sig, _)) => { + VoteMultiplicity::Equivocated(ref first, ref second) => { // mark the equivocator as such. no need to "undo" the first vote. self.bitfield_context.equivocated_precommit(info) .expect("info is instantiated from same voter set as bitfield; qed"); @@ -434,8 +426,8 @@ impl Round where Some(Equivocation { round_number, identity: signer, - first: (fst_vote.clone(), fst_sig.clone()), - second: (snd_vote.clone(), snd_sig.clone()), + first: first.clone(), + second: second.clone(), }) } } @@ -488,7 +480,7 @@ impl Round where fn next(&mut self) -> Option<(V, S)> { match self.multiplicity { - VoteMultiplicity::Single(v, s, _) => { + VoteMultiplicity::Single(ref v, ref s) => { if self.yielded == 0 { self.yielded += 1; Some((v.clone(), s.clone())) @@ -496,10 +488,10 @@ impl Round where None } } - VoteMultiplicity::Equivocated((fst_vote, fst_sig, _), (snd_vote, snd_sig, _)) => { + VoteMultiplicity::Equivocated(ref a, ref b) => { let res = match self.yielded { - 0 => Some((fst_vote.clone(), fst_sig.clone())), - 1 => Some((snd_vote.clone(), snd_sig.clone())), + 0 => Some(a.clone()), + 1 => Some(b.clone()), _ => None, }; @@ -513,7 +505,7 @@ impl Round where let (f_hash, _f_num) = self.finalized.clone()?; let find_valid_precommits = self.precommit.votes.iter() .filter(move |&(_id, ref multiplicity)| { - if let VoteMultiplicity::Single(v, _, _) = *multiplicity { + if let VoteMultiplicity::Single(ref v, _) = *multiplicity { // if there is a single vote from this voter, we only include it // if it branches off of the target. chain.is_equal_or_descendent_of(f_hash.clone(), v.target_hash.clone()) @@ -690,27 +682,31 @@ impl Round where self.precommit.votes() } - /// Return all imported votes (prevotes and precommits) ordered. + /// Return all votes (prevotes and precommits) by importing order. pub fn historical_votes(&self) -> &HistoricalVotes { &self.historical_votes } /// Set the number of prevotes and precommits received at the moment of prevoting. + /// It should be called inmediatly after prevoting. pub fn set_prevoted_index(&mut self) { self.historical_votes.prevote_idx = Some(self.historical_votes.seen.len()) } /// Set the number of prevotes and precommits received at the moment of precommiting. + /// It should be called inmediatly after precommiting. pub fn set_precommited_index(&mut self) { self.historical_votes.precommit_idx = Some(self.historical_votes.seen.len()) } /// Get the number of prevotes and precommits received at the moment of prevoting. + /// Returns None if the prevote wasn't realized. pub fn prevoted_index(&self) -> Option { self.historical_votes.prevote_idx } /// Get the number of prevotes and precommits received at the moment of precommiting. + /// Returns None if the precommit wasn't realized. pub fn precommited_index(&self) -> Option { self.historical_votes.precommit_idx } diff --git a/src/voter/mod.rs b/src/voter/mod.rs index cc8f8df7..d30c3bb1 100644 --- a/src/voter/mod.rs +++ b/src/voter/mod.rs @@ -36,7 +36,7 @@ use std::sync::Arc; use crate::round::State as RoundState; use crate::{ Chain, Commit, CompactCommit, Equivocation, Message, Prevote, Precommit, PrimaryPropose, - SignedMessage, BlockNumberOps, validate_commit, CommitValidationResult, + SignedMessage, BlockNumberOps, validate_commit, CommitValidationResult }; use crate::voter_set::VoterSet; use past_rounds::PastRounds; diff --git a/src/voter/voting_round.rs b/src/voter/voting_round.rs index 165c9668..0b2f91a0 100644 --- a/src/voter/voting_round.rs +++ b/src/voter/voting_round.rs @@ -277,8 +277,8 @@ impl> VotingRound where prevotes.chain(precommits).collect() } - /// Return all imported votes for the round (prevotes and precommits) ordered - /// and indicating at which indices we voted. + /// Return all votes for the round (prevotes and precommits) + /// sorted by importing order and indicating at which indices we voted. pub(super) fn historical_votes(&self) -> &HistoricalVotes { self.votes.historical_votes() } From 4411de9f913b7a9d74bc2847c459ed7b53ede06c Mon Sep 17 00:00:00 2001 From: Marcio Diaz Date: Mon, 13 May 2019 10:48:40 +0200 Subject: [PATCH 14/21] fix: pass HistoricalVotes to completed() --- src/voter/mod.rs | 8 ++++---- src/voter/voting_round.rs | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/voter/mod.rs b/src/voter/mod.rs index d30c3bb1..4a28be47 100644 --- a/src/voter/mod.rs +++ b/src/voter/mod.rs @@ -36,7 +36,7 @@ use std::sync::Arc; use crate::round::State as RoundState; use crate::{ Chain, Commit, CompactCommit, Equivocation, Message, Prevote, Precommit, PrimaryPropose, - SignedMessage, BlockNumberOps, validate_commit, CommitValidationResult + SignedMessage, BlockNumberOps, validate_commit, CommitValidationResult, HistoricalVotes, }; use crate::voter_set::VoterSet; use past_rounds::PastRounds; @@ -101,7 +101,7 @@ pub trait Environment: Chain { round: u64, state: RoundState, base: (H, N), - votes: Vec>, + votes: &HistoricalVotes, ) -> Result<(), Self::Error>; /// Called when a block should be finalized. @@ -662,7 +662,7 @@ impl, GlobalIn, GlobalOut> Voter, GlobalIn, GlobalOut> Voter> VotingRound where prevotes.chain(precommits).collect() } - /// Return all votes for the round (prevotes and precommits) - /// sorted by importing order and indicating at which indices we voted. + /// Return all votes for the round (prevotes and precommits), + /// sorted by imported order and indicating the indices where we voted. pub(super) fn historical_votes(&self) -> &HistoricalVotes { self.votes.historical_votes() } From 5d5a86afd8f1a2a758bf7d513020ae65c927ecb2 Mon Sep 17 00:00:00 2001 From: Marcio Diaz Date: Mon, 13 May 2019 12:00:28 +0200 Subject: [PATCH 15/21] fix: test --- src/testing.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/testing.rs b/src/testing.rs index 53fd1725..2243a6d1 100644 --- a/src/testing.rs +++ b/src/testing.rs @@ -24,7 +24,7 @@ use tokio::timer::Delay; use parking_lot::Mutex; use futures::prelude::*; use futures::sync::mpsc::{self, UnboundedReceiver, UnboundedSender}; -use super::{Chain, Commit, Error, Equivocation, Message, Prevote, Precommit, PrimaryPropose, SignedMessage}; +use super::{Chain, Commit, Error, Equivocation, Message, Prevote, Precommit, PrimaryPropose, SignedMessage, HistoricalVotes}; pub const GENESIS_HASH: &str = "genesis"; const NULL_HASH: &str = "NULL"; @@ -216,7 +216,7 @@ impl crate::voter::Environment<&'static str, u32> for Environment { _round: u64, _state: RoundState<&'static str, u32>, _base: (&'static str, u32), - _votes: Vec>, + _votes: &HistoricalVotes<&'static str, u32>, ) -> Result<(), Error> { Ok(()) } From 296fd185294f5d8d44460cdcd34823d76d8a2905 Mon Sep 17 00:00:00 2001 From: Marcio Diaz Date: Mon, 13 May 2019 16:10:07 +0200 Subject: [PATCH 16/21] fix: add signatures, remove votes(), add equivocations --- src/lib.rs | 8 ++++---- src/round.rs | 29 ++++++++++++++++++++++------- src/testing.rs | 2 +- src/voter/mod.rs | 2 +- src/voter/voting_round.rs | 23 +---------------------- 5 files changed, 29 insertions(+), 35 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 0d35cfd5..9801f4f8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -481,13 +481,13 @@ pub fn process_commit_validation_result( /// Historical votes seen in a round. #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "derive-codec", derive(Encode, Decode))] -pub struct HistoricalVotes { - seen: Vec>, +pub struct HistoricalVotes { + seen: Vec>, prevote_idx: Option, precommit_idx: Option, } -impl HistoricalVotes { +impl HistoricalVotes { pub fn new() -> Self { HistoricalVotes { seen: Vec::new(), @@ -496,7 +496,7 @@ impl HistoricalVotes { } } - pub fn seen(&self) -> &Vec> { + pub fn seen(&self) -> &Vec> { &self.seen } diff --git a/src/round.rs b/src/round.rs index c4a06e2f..9c6b41e4 100644 --- a/src/round.rs +++ b/src/round.rs @@ -22,7 +22,7 @@ use crate::bitfield::{Shared as BitfieldContext, Bitfield}; use crate::vote_graph::VoteGraph; use crate::voter_set::VoterSet; -use super::{Equivocation, Prevote, Precommit, Chain, BlockNumberOps, HistoricalVotes, Message}; +use super::{Equivocation, Prevote, Precommit, Chain, BlockNumberOps, HistoricalVotes, Message, SignedMessage}; #[derive(Hash, Eq, PartialEq)] struct Address; @@ -224,7 +224,7 @@ pub struct Round { graph: VoteGraph, // DAG of blocks which have been voted on. prevote: VoteTracker, Signature>, // tracks prevotes that have been counted precommit: VoteTracker, Signature>, // tracks precommits - historical_votes: HistoricalVotes, + historical_votes: HistoricalVotes, round_number: u64, voters: VoterSet, total_weight: u64, @@ -312,7 +312,7 @@ impl Round where let weight = info.weight(); let equivocation = { - let multiplicity = match self.prevote.add_vote(signer.clone(), vote, signature, weight) { + let multiplicity = match self.prevote.add_vote(signer.clone(), vote.clone(), signature.clone(), weight) { AddVoteResult { multiplicity: Some(m), .. } => m, AddVoteResult { duplicated, .. } => { import_result.duplicated = duplicated; @@ -335,7 +335,10 @@ impl Round where chain, )?; - self.historical_votes.seen.push(Message::Prevote(vote.clone())); + // Push the vote into HistoricalVotes. + let message = Message::Prevote(vote.clone()); + let signed_message = SignedMessage { id: signer.clone(), signature, message }; + self.historical_votes.seen.push(signed_message); None } @@ -344,6 +347,11 @@ impl Round where self.bitfield_context.equivocated_prevote(info) .expect("info is instantiated from same voter set as bitfield; qed"); + // Push the vote into HistoricalVotes. + let message = Message::Prevote(vote); + let signed_message = SignedMessage { id: signer.clone(), signature, message }; + self.historical_votes.seen.push(signed_message); + Some(Equivocation { round_number, identity: signer, @@ -391,7 +399,7 @@ impl Round where let weight = info.weight(); let equivocation = { - let multiplicity = match self.precommit.add_vote(signer.clone(), vote, signature, weight) { + let multiplicity = match self.precommit.add_vote(signer.clone(), vote.clone(), signature.clone(), weight) { AddVoteResult { multiplicity: Some(m), .. } => m, AddVoteResult { duplicated, .. } => { import_result.duplicated = duplicated; @@ -414,7 +422,9 @@ impl Round where chain, )?; - self.historical_votes.seen.push(Message::Precommit(vote.clone())); + let message = Message::Precommit(vote.clone()); + let signed_message = SignedMessage { id: signer.clone(), signature, message }; + self.historical_votes.seen.push(signed_message); None } @@ -423,6 +433,11 @@ impl Round where self.bitfield_context.equivocated_precommit(info) .expect("info is instantiated from same voter set as bitfield; qed"); + // Push the vote into HistoricalVotes. + let message = Message::Precommit(vote); + let signed_message = SignedMessage { id: signer.clone(), signature, message }; + self.historical_votes.seen.push(signed_message); + Some(Equivocation { round_number, identity: signer, @@ -683,7 +698,7 @@ impl Round where } /// Return all votes (prevotes and precommits) by importing order. - pub fn historical_votes(&self) -> &HistoricalVotes { + pub fn historical_votes(&self) -> &HistoricalVotes { &self.historical_votes } diff --git a/src/testing.rs b/src/testing.rs index 2243a6d1..886c1883 100644 --- a/src/testing.rs +++ b/src/testing.rs @@ -216,7 +216,7 @@ impl crate::voter::Environment<&'static str, u32> for Environment { _round: u64, _state: RoundState<&'static str, u32>, _base: (&'static str, u32), - _votes: &HistoricalVotes<&'static str, u32>, + _votes: &HistoricalVotes<&'static str, u32, Self::Signature, Self::Id>, ) -> Result<(), Error> { Ok(()) } diff --git a/src/voter/mod.rs b/src/voter/mod.rs index 4a28be47..66da7523 100644 --- a/src/voter/mod.rs +++ b/src/voter/mod.rs @@ -101,7 +101,7 @@ pub trait Environment: Chain { round: u64, state: RoundState, base: (H, N), - votes: &HistoricalVotes, + votes: &HistoricalVotes, ) -> Result<(), Self::Error>; /// Called when a block should be finalized. diff --git a/src/voter/voting_round.rs b/src/voter/voting_round.rs index 1d6bce32..383cf6ce 100644 --- a/src/voter/voting_round.rs +++ b/src/voter/voting_round.rs @@ -256,30 +256,9 @@ impl> VotingRound where self.best_finalized.as_ref() } - /// Return all imported votes for the round (prevotes and precommits) unordered. - pub(super) fn votes(&self) -> Vec> { - let prevotes = self.votes.prevotes().into_iter().map(|(id, prevote, signature)| { - SignedMessage { - id, - signature, - message: Message::Prevote(prevote), - } - }); - - let precommits = self.votes.precommits().into_iter().map(|(id, precommit, signature)| { - SignedMessage { - id, - signature, - message: Message::Precommit(precommit), - } - }); - - prevotes.chain(precommits).collect() - } - /// Return all votes for the round (prevotes and precommits), /// sorted by imported order and indicating the indices where we voted. - pub(super) fn historical_votes(&self) -> &HistoricalVotes { + pub(super) fn historical_votes(&self) -> &HistoricalVotes { self.votes.historical_votes() } From 404186ce64d4596fdb3dae40f0dd78a9efd02b09 Mon Sep 17 00:00:00 2001 From: Marcio Diaz Date: Mon, 13 May 2019 17:32:34 +0200 Subject: [PATCH 17/21] fix: add new_with_votes --- src/lib.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 9801f4f8..f1b89c01 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -496,6 +496,14 @@ impl HistoricalVotes { } } + pub fn new_with_votes(seen: Vec>) -> Self { + HistoricalVotes { + seen, + prevote_idx: None, + precommit_idx: None, + } + } + pub fn seen(&self) -> &Vec> { &self.seen } From 0e104ace599f91ec5f2b2be1a57a0bd9e0c7d1e2 Mon Sep 17 00:00:00 2001 From: Marcio Diaz Date: Tue, 14 May 2019 09:24:22 +0200 Subject: [PATCH 18/21] chore: add some doc comments --- src/lib.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index f1b89c01..7940003b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -488,6 +488,7 @@ pub struct HistoricalVotes { } impl HistoricalVotes { + /// Creates a new HistoricalVotes. pub fn new() -> Self { HistoricalVotes { seen: Vec::new(), @@ -496,6 +497,7 @@ impl HistoricalVotes { } } + /// Creates a new HistoricalVotes initialized with messages in `seen`. pub fn new_with_votes(seen: Vec>) -> Self { HistoricalVotes { seen, @@ -504,14 +506,19 @@ impl HistoricalVotes { } } + /// Returns the messages seen so far. pub fn seen(&self) -> &Vec> { &self.seen } + /// Returns the number of messages seen before prevoting. + /// Returns None in case we didn't prevote yet. pub fn prevote_idx(&self) -> Option { self.prevote_idx } + /// Returns the number of messages seen before precommiting. + /// Returns None in case we didn't precommit yet. pub fn precommit_idx(&self) -> Option { self.precommit_idx } From f234092705093fea85381811001c72f4a22a71e2 Mon Sep 17 00:00:00 2001 From: Marcio Diaz Date: Tue, 14 May 2019 11:39:50 +0200 Subject: [PATCH 19/21] add test --- src/lib.rs | 39 ++++++++++++++++------ src/round.rs | 93 ++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 116 insertions(+), 16 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 7940003b..84e89a2e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -488,7 +488,7 @@ pub struct HistoricalVotes { } impl HistoricalVotes { - /// Creates a new HistoricalVotes. + /// Create a new HistoricalVotes. pub fn new() -> Self { HistoricalVotes { seen: Vec::new(), @@ -497,31 +497,50 @@ impl HistoricalVotes { } } - /// Creates a new HistoricalVotes initialized with messages in `seen`. - pub fn new_with_votes(seen: Vec>) -> Self { + /// Create a new HistoricalVotes initialized from the parameters. + pub fn new_with( + seen: Vec>, + prevote_idx: Option, + precommit_idx: Option + ) -> Self { HistoricalVotes { seen, - prevote_idx: None, - precommit_idx: None, + prevote_idx, + precommit_idx, } } - /// Returns the messages seen so far. + /// Push a vote into the list. + pub fn push_vote(&mut self, msg: SignedMessage) { + self.seen.push(msg) + } + + /// Return the messages seen so far. pub fn seen(&self) -> &Vec> { &self.seen } - /// Returns the number of messages seen before prevoting. - /// Returns None in case we didn't prevote yet. + /// Return the number of messages seen before prevoting. + /// None in case we didn't prevote yet. pub fn prevote_idx(&self) -> Option { self.prevote_idx } - /// Returns the number of messages seen before precommiting. - /// Returns None in case we didn't precommit yet. + /// Return the number of messages seen before precommiting. + /// None in case we didn't precommit yet. pub fn precommit_idx(&self) -> Option { self.precommit_idx } + + /// Set the number of messages seen before prevoting. + pub fn set_prevoted_idx(&mut self) { + self.prevote_idx = Some(self.seen.len()) + } + + /// Set the number of messages seen before precommiting. + pub fn set_precommited_idx(&mut self) { + self.precommit_idx = Some(self.seen.len()) + } } #[cfg(test)] diff --git a/src/round.rs b/src/round.rs index 9c6b41e4..696670c8 100644 --- a/src/round.rs +++ b/src/round.rs @@ -338,7 +338,7 @@ impl Round where // Push the vote into HistoricalVotes. let message = Message::Prevote(vote.clone()); let signed_message = SignedMessage { id: signer.clone(), signature, message }; - self.historical_votes.seen.push(signed_message); + self.historical_votes.push_vote(signed_message); None } @@ -350,7 +350,7 @@ impl Round where // Push the vote into HistoricalVotes. let message = Message::Prevote(vote); let signed_message = SignedMessage { id: signer.clone(), signature, message }; - self.historical_votes.seen.push(signed_message); + self.historical_votes.push_vote(signed_message); Some(Equivocation { round_number, @@ -424,7 +424,7 @@ impl Round where let message = Message::Precommit(vote.clone()); let signed_message = SignedMessage { id: signer.clone(), signature, message }; - self.historical_votes.seen.push(signed_message); + self.historical_votes.push_vote(signed_message); None } @@ -436,7 +436,7 @@ impl Round where // Push the vote into HistoricalVotes. let message = Message::Precommit(vote); let signed_message = SignedMessage { id: signer.clone(), signature, message }; - self.historical_votes.seen.push(signed_message); + self.historical_votes.push_vote(signed_message); Some(Equivocation { round_number, @@ -705,13 +705,13 @@ impl Round where /// Set the number of prevotes and precommits received at the moment of prevoting. /// It should be called inmediatly after prevoting. pub fn set_prevoted_index(&mut self) { - self.historical_votes.prevote_idx = Some(self.historical_votes.seen.len()) + self.historical_votes.set_prevoted_idx() } /// Set the number of prevotes and precommits received at the moment of precommiting. /// It should be called inmediatly after precommiting. pub fn set_precommited_index(&mut self) { - self.historical_votes.precommit_idx = Some(self.historical_votes.seen.len()) + self.historical_votes.set_precommited_idx() } /// Get the number of prevotes and precommits received at the moment of prevoting. @@ -947,4 +947,85 @@ mod tests { // adding an extra vote by 5 doesn't increase the count. assert_eq!(vote_weight, TotalWeight { prevote: 1 + 5 + 2 + 3, precommit: 0 }); } + + #[test] + fn historical_votes_works() { + let mut chain = DummyChain::new(); + chain.push_blocks(GENESIS_HASH, &["A", "B", "C", "D", "E", "F"]); + chain.push_blocks("E", &["EA", "EB", "EC", "ED"]); + chain.push_blocks("F", &["FA", "FB", "FC"]); + + let mut round = Round::new(RoundParams { + round_number: 1, + voters: voters(), + base: ("C", 4), + }); + + round.import_prevote( + &chain, + Prevote::new("FC", 10), + "Alice", + Signature("Alice"), + ).unwrap(); + + round.set_prevoted_index(); + + round.import_prevote( + &chain, + Prevote::new("EA", 7), + "Eve", + Signature("Eve"), + ).unwrap(); + + round.import_precommit( + &chain, + Precommit::new("EA", 7), + "Eve", + Signature("Eve"), + ).unwrap(); + + round.import_prevote( + &chain, + Prevote::new("EC", 10), + "Alice", + Signature("Alice"), + ).unwrap(); + + round.set_precommited_index(); + + assert_eq!(round.historical_votes(), &HistoricalVotes::new_with( + vec![ + SignedMessage { + message: Message::Prevote( + Prevote { target_hash: "FC", target_number: 10 } + ), + signature: Signature("Alice"), + id: "Alice" + }, + SignedMessage { + message: Message::Prevote( + Prevote { target_hash: "EA", target_number: 7 } + ), + signature: Signature("Eve"), + id: "Eve" + }, + SignedMessage { + message: Message::Precommit( + Precommit { target_hash: "EA", target_number: 7 } + ), + signature: Signature("Eve"), + id: "Eve" + }, + SignedMessage { + message: Message::Precommit( + Precommit { target_hash: "EC", target_number: 10 } + ), + signature: Signature("Alice"), + id: "Alice" + }, + ], + Some(1), + Some(4), + )); + } } From 448c697c101dbf8c896fccc55a6132d25a5094da Mon Sep 17 00:00:00 2001 From: Marcio Diaz Date: Tue, 14 May 2019 12:00:31 +0200 Subject: [PATCH 20/21] fix test --- src/round.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/round.rs b/src/round.rs index 696670c8..6bf605bb 100644 --- a/src/round.rs +++ b/src/round.rs @@ -1017,8 +1017,8 @@ mod tests { id: "Eve" }, SignedMessage { - message: Message::Precommit( - Precommit { target_hash: "EC", target_number: 10 } + message: Message::Prevote( + Prevote { target_hash: "EC", target_number: 10 } ), signature: Signature("Alice"), id: "Alice" From 29a62dcdfc21de111e679b112fde9e2fa45dbc65 Mon Sep 17 00:00:00 2001 From: Marcio Diaz Date: Tue, 14 May 2019 14:01:36 +0200 Subject: [PATCH 21/21] fix: remove unnecesary clones --- src/round.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/round.rs b/src/round.rs index 6bf605bb..e5b1bc29 100644 --- a/src/round.rs +++ b/src/round.rs @@ -322,22 +322,22 @@ impl Round where let round_number = self.round_number; match multiplicity { - VoteMultiplicity::Single(ref vote, _) => { + VoteMultiplicity::Single(single_vote, _) => { let vote_weight = VoteWeight { bitfield: self.bitfield_context.prevote_bitfield(info) .expect("info is instantiated from same voter set as context; qed"), }; self.graph.insert( - vote.target_hash.clone(), - vote.target_number, + single_vote.target_hash.clone(), + single_vote.target_number, vote_weight, chain, )?; // Push the vote into HistoricalVotes. - let message = Message::Prevote(vote.clone()); - let signed_message = SignedMessage { id: signer.clone(), signature, message }; + let message = Message::Prevote(vote); + let signed_message = SignedMessage { id: signer, signature, message }; self.historical_votes.push_vote(signed_message); None @@ -409,25 +409,25 @@ impl Round where let round_number = self.round_number; match multiplicity { - VoteMultiplicity::Single(ref vote, _) => { + VoteMultiplicity::Single(single_vote, _) => { let vote_weight = VoteWeight { bitfield: self.bitfield_context.precommit_bitfield(info) .expect("info is instantiated from same voter set as context; qed"), }; self.graph.insert( - vote.target_hash.clone(), - vote.target_number, + single_vote.target_hash.clone(), + single_vote.target_number, vote_weight, chain, )?; - let message = Message::Precommit(vote.clone()); - let signed_message = SignedMessage { id: signer.clone(), signature, message }; + let message = Message::Precommit(vote); + let signed_message = SignedMessage { id: signer, signature, message }; self.historical_votes.push_vote(signed_message); None - } + }, VoteMultiplicity::Equivocated(ref first, ref second) => { // mark the equivocator as such. no need to "undo" the first vote. self.bitfield_context.equivocated_precommit(info) @@ -444,7 +444,7 @@ impl Round where first: first.clone(), second: second.clone(), }) - } + }, } };