-
Notifications
You must be signed in to change notification settings - Fork 46
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
Answer queries #65
Answer queries #65
Changes from all commits
feaaac7
75ec15b
2e9ade6
d055dad
c1ac719
b174a92
8674ae1
00c48c8
70197e3
72bb3d1
0d6d721
3d0f81b
0060027
c2c8b1c
4411de9
5d5a86a
296fd18
404186c
0e104ac
f234092
448c697
29a62dc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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, SignedMessage}; | ||
|
||
#[derive(Hash, Eq, PartialEq)] | ||
struct Address; | ||
|
@@ -131,6 +131,7 @@ impl<Id: Hash + Eq + Clone, Vote: Clone + Eq, Signature: Clone + Eq> VoteTracker | |
Entry::Vacant(vacant) => { | ||
self.current_weight += weight; | ||
let multiplicity = vacant.insert(VoteMultiplicity::Single(vote, signature)); | ||
|
||
return AddVoteResult { | ||
multiplicity: Some(multiplicity), | ||
duplicated: false, | ||
|
@@ -223,6 +224,7 @@ pub struct Round<Id: Hash + Eq, H: Hash + Eq, N, Signature> { | |
graph: VoteGraph<H, N, VoteWeight>, // DAG of blocks which have been voted on. | ||
prevote: VoteTracker<Id, Prevote<H, N>, Signature>, // tracks prevotes that have been counted | ||
precommit: VoteTracker<Id, Precommit<H, N>, Signature>, // tracks precommits | ||
historical_votes: HistoricalVotes<H, N, Signature, Id>, | ||
round_number: u64, | ||
voters: VoterSet<Id>, | ||
total_weight: u64, | ||
|
@@ -274,6 +276,7 @@ impl<Id, H, N, Signature> Round<Id, H, N, Signature> where | |
graph: VoteGraph::new(base_hash, base_number), | ||
prevote: VoteTracker::new(), | ||
precommit: VoteTracker::new(), | ||
historical_votes: HistoricalVotes::new(), | ||
bitfield_context: BitfieldContext::new(n_validators), | ||
prevote_ghost: None, | ||
precommit_ghost: None, | ||
|
@@ -309,7 +312,7 @@ impl<Id, H, N, Signature> Round<Id, H, N, Signature> 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; | ||
|
@@ -319,26 +322,36 @@ impl<Id, H, N, Signature> Round<Id, H, N, Signature> 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); | ||
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_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.push_vote(signed_message); | ||
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. Maybe only add if 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 is not needed since we early-exit after we've already seen an equivocation. |
||
|
||
Some(Equivocation { | ||
round_number, | ||
identity: signer, | ||
|
@@ -386,7 +399,7 @@ impl<Id, H, N, Signature> Round<Id, H, N, Signature> 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; | ||
|
@@ -396,33 +409,42 @@ impl<Id, H, N, Signature> Round<Id, H, N, Signature> 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); | ||
let signed_message = SignedMessage { id: signer, signature, message }; | ||
self.historical_votes.push_vote(signed_message); | ||
|
||
None | ||
} | ||
}, | ||
VoteMultiplicity::Equivocated(ref first, ref second) => { | ||
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. Same as above. |
||
// 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"); | ||
|
||
// Push the vote into HistoricalVotes. | ||
let message = Message::Precommit(vote); | ||
let signed_message = SignedMessage { id: signer.clone(), signature, message }; | ||
self.historical_votes.push_vote(signed_message); | ||
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. Same as above. |
||
|
||
Some(Equivocation { | ||
round_number, | ||
identity: signer, | ||
first: first.clone(), | ||
second: second.clone(), | ||
}) | ||
} | ||
}, | ||
} | ||
}; | ||
|
||
|
@@ -472,7 +494,7 @@ impl<Id, H, N, Signature> Round<Id, H, N, Signature> where | |
type Item = (V, S); | ||
|
||
fn next(&mut self) -> Option<(V, S)> { | ||
match *self.multiplicity { | ||
match self.multiplicity { | ||
VoteMultiplicity::Single(ref v, ref s) => { | ||
if self.yielded == 0 { | ||
self.yielded += 1; | ||
|
@@ -674,6 +696,35 @@ impl<Id, H, N, Signature> Round<Id, H, N, Signature> where | |
pub fn precommits(&self) -> Vec<(Id, Precommit<H, N>, Signature)> { | ||
self.precommit.votes() | ||
} | ||
|
||
/// Return all votes (prevotes and precommits) by importing order. | ||
pub fn historical_votes(&self) -> &HistoricalVotes<H, N, Signature, Id> { | ||
&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.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.set_precommited_idx() | ||
} | ||
|
||
/// 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<usize> { | ||
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<usize> { | ||
self.historical_votes.precommit_idx | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
|
@@ -896,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::Prevote( | ||
Prevote { target_hash: "EC", target_number: 10 } | ||
), | ||
signature: Signature("Alice"), | ||
id: "Alice" | ||
}, | ||
], | ||
Some(1), | ||
Some(4), | ||
)); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we need to store equivocated votes as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At the very least, the first equivocation of a type from a given voter
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.