From dc16623bded0157285f4d19fcd356219f2924202 Mon Sep 17 00:00:00 2001 From: Adi Seredinschi Date: Tue, 24 Oct 2023 16:50:30 -0400 Subject: [PATCH 1/5] Renamed Threshold::Init to Unreached. Reorded the enum variants. Nits & comments. --- Code/vote/src/count.rs | 41 +++++++++++++++++++++-------------------- Code/vote/src/keeper.rs | 10 +++++----- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/Code/vote/src/count.rs b/Code/vote/src/count.rs index 32e7310f6..5b66ac0c8 100644 --- a/Code/vote/src/count.rs +++ b/Code/vote/src/count.rs @@ -88,11 +88,11 @@ impl VoteCount { } // No quorum - Threshold::Init + Threshold::Unreached } pub fn check_threshold(&self, threshold: Threshold) -> bool { match threshold { - Threshold::Init => false, + Threshold::Unreached => false, Threshold::Any => self.values_weights.highest_weighted_value().is_some(), Threshold::Nil => self.nil > 0, Threshold::Value(value) => self.values_weights.value_weights.contains_key(&value), @@ -104,20 +104,21 @@ impl VoteCount { // Round votes //------------------------------------------------------------------------- -// Thresh represents the different quorum thresholds. +// Threshold represents the different quorum thresholds. #[derive(Clone, Debug, PartialEq, Eq)] pub enum Threshold { - /// No quorum - Init, // no quorum - /// Qorum of votes but not for the same value - Any, - /// Quorum for nil - Nil, - /// Quorum for a value + /// No quorum was reached + Unreached, + /// Quorum reached for a specific value Value(Arc), + /// Quorum reached for a nil value + /// This happens eg if the proposer missed their time to send proposal + Nil, + /// Qorum of votes reached but for multiple different values, including nil + Any, } -/// Returns whether or note `value > (2/3)*total`. +/// Returns whether or not `value > (2/3)*total`. pub fn is_quorum(value: Weight, total: Weight) -> bool { 3 * value > 2 * total } @@ -139,11 +140,11 @@ mod tests { // add a vote for nil. nothing changes. let vote = Vote::new_prevote(Round::new(0), None, Address::new(1)); let thresh = round_votes.add_vote(vote.clone(), 1); - assert_eq!(thresh, Threshold::Init); + assert_eq!(thresh, Threshold::Unreached); // add it again, nothing changes. let thresh = round_votes.add_vote(vote.clone(), 1); - assert_eq!(thresh, Threshold::Init); + assert_eq!(thresh, Threshold::Unreached); // add it again, get Nil let thresh = round_votes.add_vote(vote.clone(), 1); @@ -162,11 +163,11 @@ mod tests { // add a vote. nothing changes. let vote = Vote::new_prevote(Round::new(0), val, Address::new(1)); let thresh = round_votes.add_vote(vote.clone(), weight); - assert_eq!(thresh, Threshold::Init); + assert_eq!(thresh, Threshold::Unreached); // add it again, nothing changes. let thresh = round_votes.add_vote(vote.clone(), weight); - assert_eq!(thresh, Threshold::Init); + assert_eq!(thresh, Threshold::Unreached); // add a vote for nil, get Thresh::Any let vote_nil = Vote::new_prevote(Round::new(0), None, Address::new(2)); @@ -191,25 +192,25 @@ mod tests { // add a vote for v1. nothing changes. let vote1 = Vote::new_precommit(Round::new(0), val1, Address::new(1)); let thresh = round_votes.add_vote(vote1.clone(), 1); - assert_eq!(thresh, Threshold::Init); + assert_eq!(thresh, Threshold::Unreached); // add a vote for v2. nothing changes. let vote2 = Vote::new_precommit(Round::new(0), val2, Address::new(2)); let thresh = round_votes.add_vote(vote2.clone(), 1); - assert_eq!(thresh, Threshold::Init); + assert_eq!(thresh, Threshold::Unreached); // add a vote for nil. nothing changes. let vote_nil = Vote::new_precommit(Round::new(0), None, Address::new(3)); let thresh = round_votes.add_vote(vote_nil.clone(), 1); - assert_eq!(thresh, Threshold::Init); + assert_eq!(thresh, Threshold::Unreached); // add a vote for v1. nothing changes let thresh = round_votes.add_vote(vote1.clone(), 1); - assert_eq!(thresh, Threshold::Init); + assert_eq!(thresh, Threshold::Unreached); // add a vote for v2. nothing changes let thresh = round_votes.add_vote(vote2.clone(), 1); - assert_eq!(thresh, Threshold::Init); + assert_eq!(thresh, Threshold::Unreached); // add a big vote for v2. get Value(v2) let thresh = round_votes.add_vote(vote2.clone(), 10); diff --git a/Code/vote/src/keeper.rs b/Code/vote/src/keeper.rs index d24a5b778..d1d4b6f99 100644 --- a/Code/vote/src/keeper.rs +++ b/Code/vote/src/keeper.rs @@ -62,15 +62,15 @@ impl VoteKeeper { /// Map a vote type and a threshold to a state machine event. fn to_event(typ: VoteType, threshold: Threshold) -> Option { match (typ, threshold) { - (_, Threshold::Init) => None, + (_, Threshold::Unreached) => None, - (VoteType::Prevote, Threshold::Any) => Some(Event::PolkaAny), - (VoteType::Prevote, Threshold::Nil) => Some(Event::PolkaNil), (VoteType::Prevote, Threshold::Value(v)) => Some(Event::PolkaValue(*v.as_ref())), + (VoteType::Prevote, Threshold::Nil) => Some(Event::PolkaNil), + (VoteType::Prevote, Threshold::Any) => Some(Event::PolkaAny), - (VoteType::Precommit, Threshold::Any) => Some(Event::PrecommitAny), - (VoteType::Precommit, Threshold::Nil) => None, (VoteType::Precommit, Threshold::Value(v)) => Some(Event::PrecommitValue(*v.as_ref())), + (VoteType::Precommit, Threshold::Nil) => None, + (VoteType::Precommit, Threshold::Any) => Some(Event::PrecommitAny), } } } From 559b1f790fb32de1a0c357c310d5748f762127a6 Mon Sep 17 00:00:00 2001 From: Adi Seredinschi Date: Tue, 24 Oct 2023 19:18:56 -0400 Subject: [PATCH 2/5] Fixes for the cumulative weights --- .idea/.gitignore | 8 ++++++++ .idea/malachite.iml | 8 ++++++++ .idea/modules.xml | 8 ++++++++ .idea/vcs.xml | 6 ++++++ Code/vote/src/count.rs | 33 ++++++++++++++++++++++----------- 5 files changed, 52 insertions(+), 11 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/malachite.iml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 000000000..13566b81b --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/malachite.iml b/.idea/malachite.iml new file mode 100644 index 000000000..610219404 --- /dev/null +++ b/.idea/malachite.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 000000000..e6a1b3d5a --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 000000000..35eb1ddfb --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Code/vote/src/count.rs b/Code/vote/src/count.rs index 5b66ac0c8..cc498e32b 100644 --- a/Code/vote/src/count.rs +++ b/Code/vote/src/count.rs @@ -25,12 +25,12 @@ impl ValuesWeights { *entry } - /// Return the value with the highest weight and said weight, if any. - pub fn highest_weighted_value(&self) -> Option<(&ValueId, Weight)> { + /// Return the cumulative weight associated with all the values. + /// Returns None if there are no weights associated with any value. + pub fn cumulative_weights(&self) -> Option { self.value_weights .iter() - .max_by_key(|(_, weight)| *weight) - .map(|(value, weight)| (value.as_ref(), *weight)) + .fold(None, |mac, (_, w)| mac.map(|acc| acc + w)) } } @@ -63,6 +63,8 @@ impl VoteCount { /// Add vote to internal counters and return the highest threshold. pub fn add_vote(&mut self, vote: Vote, weight: Weight) -> Threshold { + // Note: The ordering among these if clauses is important + // We first check if there is a quorum for a specific value if let Some(value) = vote.value { let value = Arc::new(value); let new_weight = self.values_weights.add_weight(value.clone(), weight); @@ -80,24 +82,33 @@ impl VoteCount { } } - // Check if we have a quorum for any value, using the highest weighted value, if any. - if let Some((_max_value, max_weight)) = self.values_weights.highest_weighted_value() { - if is_quorum(max_weight + self.nil, self.total) { - return Threshold::Any; - } + // Check if we have a quorum for all values and for nil votes, + if self.is_quorum_any() { + return Threshold::Any; } - // No quorum + // No quorum was reached Threshold::Unreached } + pub fn check_threshold(&self, threshold: Threshold) -> bool { match threshold { Threshold::Unreached => false, - Threshold::Any => self.values_weights.highest_weighted_value().is_some(), + Threshold::Any => self.is_quorum_any(), Threshold::Nil => self.nil > 0, Threshold::Value(value) => self.values_weights.value_weights.contains_key(&value), } } + + // Checks if the cumulative weight associated to all votes and nil is enough for a quorum + fn is_quorum_any(&self) -> bool { + if let Some(cm_weight) = self.values_weights.cumulative_weights() { + if is_quorum(cm_weight + self.nil, self.total) { + return true; + } + } + false + } } //------------------------------------------------------------------------- From 1e08e97ad5ed4d7b2115938a107e0efb1bab67b7 Mon Sep 17 00:00:00 2001 From: Adi Seredinschi Date: Tue, 24 Oct 2023 19:20:58 -0400 Subject: [PATCH 3/5] Removes useless files --- .idea/.gitignore | 8 -------- .idea/malachite.iml | 8 -------- .idea/modules.xml | 8 -------- .idea/vcs.xml | 6 ------ 4 files changed, 30 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/malachite.iml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 13566b81b..000000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/.idea/malachite.iml b/.idea/malachite.iml deleted file mode 100644 index 610219404..000000000 --- a/.idea/malachite.iml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index e6a1b3d5a..000000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1ddfb..000000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file From b5f59db9157df73ea9d9dad1af4d0461017a3ce7 Mon Sep 17 00:00:00 2001 From: Adi Seredinschi Date: Tue, 24 Oct 2023 19:21:37 -0400 Subject: [PATCH 4/5] IDEA related fluff --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 5166e1ec1..82eea37e6 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,7 @@ Cargo.lock # Code coverage artifacts lcov.info + + +# IDEA related fluff +.idea From 4cdd50b6710235f5bbc9b4463f88d34e9011159c Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Wed, 25 Oct 2023 19:15:28 +0200 Subject: [PATCH 5/5] Formatting --- Code/vote/src/count.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/vote/src/count.rs b/Code/vote/src/count.rs index cc498e32b..616a62fe0 100644 --- a/Code/vote/src/count.rs +++ b/Code/vote/src/count.rs @@ -104,7 +104,7 @@ impl VoteCount { fn is_quorum_any(&self) -> bool { if let Some(cm_weight) = self.values_weights.cumulative_weights() { if is_quorum(cm_weight + self.nil, self.total) { - return true; + return true; } } false