diff --git a/Code/consensus/src/executor.rs b/Code/consensus/src/executor.rs index e8a14e96e..9cbb3ef93 100644 --- a/Code/consensus/src/executor.rs +++ b/Code/consensus/src/executor.rs @@ -11,9 +11,20 @@ use malachite_round::events::Event as RoundEvent; use malachite_round::message::Message as RoundMessage; use malachite_round::state::State as RoundState; use malachite_vote::count::Threshold; +use malachite_vote::keeper::Message as VoteMessage; use malachite_vote::keeper::VoteKeeper; -use crate::message::Message; +/// Messages that can be received and broadcast by the consensus executor. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum Event +where + C: Consensus, +{ + NewRound(Round), + Proposal(C::Proposal), + Vote(SignedVote), + Timeout(Timeout), +} #[derive(Clone, Debug)] pub struct Executor @@ -29,7 +40,7 @@ where } #[derive(Clone, Debug, PartialEq, Eq)] -pub enum Output +pub enum Message where C: Consensus, { @@ -65,7 +76,7 @@ where C::DUMMY_VALUE } - pub fn execute(&mut self, msg: Message) -> Option> { + pub fn execute(&mut self, msg: Event) -> Option> { let round_msg = match self.apply(msg) { Some(msg) => msg, None => return None, @@ -83,7 +94,7 @@ where RoundMessage::Proposal(proposal) => { // sign the proposal - Some(Output::Propose(proposal)) + Some(Message::Propose(proposal)) } RoundMessage::Vote(vote) => { @@ -96,24 +107,24 @@ where let signature = C::sign_vote(&vote, self.key.expose_secret()); let signed_vote = SignedVote::new(vote, address, signature); - Some(Output::Vote(signed_vote)) + Some(Message::Vote(signed_vote)) } - RoundMessage::Timeout(timeout) => Some(Output::SetTimeout(timeout)), + RoundMessage::Timeout(timeout) => Some(Message::SetTimeout(timeout)), RoundMessage::Decision(value) => { // TODO: update the state - Some(Output::Decide(value.round, value.value)) + Some(Message::Decide(value.round, value.value)) } } } - fn apply(&mut self, msg: Message) -> Option> { + fn apply(&mut self, msg: Event) -> Option> { match msg { - Message::NewRound(round) => self.apply_new_round(round), - Message::Proposal(proposal) => self.apply_proposal(proposal), - Message::Vote(signed_vote) => self.apply_vote(signed_vote), - Message::Timeout(timeout) => self.apply_timeout(timeout), + Event::NewRound(round) => self.apply_new_round(round), + Event::Proposal(proposal) => self.apply_proposal(proposal), + Event::Vote(signed_vote) => self.apply_vote(signed_vote), + Event::Timeout(timeout) => self.apply_timeout(timeout), } } @@ -188,11 +199,19 @@ where let round = signed_vote.vote.round(); - let event = self + let vote_msg = self .votes .apply_vote(signed_vote.vote, validator.voting_power())?; - self.apply_event(round, event) + let round_event = match vote_msg { + VoteMessage::PolkaAny => RoundEvent::PolkaAny, + VoteMessage::PolkaNil => RoundEvent::PolkaNil, + VoteMessage::PolkaValue(v) => RoundEvent::PolkaValue(v), + VoteMessage::PrecommitAny => RoundEvent::PrecommitAny, + VoteMessage::PrecommitValue(v) => RoundEvent::PrecommitValue(v), + }; + + self.apply_event(round, round_event) } fn apply_timeout(&mut self, timeout: Timeout) -> Option> { diff --git a/Code/consensus/src/lib.rs b/Code/consensus/src/lib.rs index 8c9bb9172..9f5b7756d 100644 --- a/Code/consensus/src/lib.rs +++ b/Code/consensus/src/lib.rs @@ -11,4 +11,3 @@ #![cfg_attr(not(test), deny(clippy::unwrap_used, clippy::panic))] pub mod executor; -pub mod message; diff --git a/Code/consensus/src/message.rs b/Code/consensus/src/message.rs deleted file mode 100644 index a82aa0de3..000000000 --- a/Code/consensus/src/message.rs +++ /dev/null @@ -1,13 +0,0 @@ -use malachite_common::{Consensus, Round, SignedVote, Timeout}; - -/// Messages that can be received and broadcast by the consensus executor. -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum Message -where - C: Consensus, -{ - NewRound(Round), - Proposal(C::Proposal), - Vote(SignedVote), - Timeout(Timeout), -} diff --git a/Code/test/tests/consensus_executor.rs b/Code/test/tests/consensus_executor.rs index 5dac360da..a18bb8fa0 100644 --- a/Code/test/tests/consensus_executor.rs +++ b/Code/test/tests/consensus_executor.rs @@ -1,6 +1,5 @@ use malachite_common::{Consensus, Round, Timeout}; -use malachite_consensus::executor::{Executor, Output}; -use malachite_consensus::message::Message; +use malachite_consensus::executor::{Event, Executor, Message}; use malachite_round::state::{RoundValue, State, Step}; use malachite_test::{Height, PrivateKey, Proposal, TestConsensus, Validator, ValidatorSet, Vote}; @@ -9,17 +8,17 @@ use rand::SeedableRng; struct TestStep { desc: &'static str, - input_message: Option>, - expected_output: Option>, + input_event: Option>, + expected_output: Option>, new_state: State, } -fn to_input_msg(output: Output) -> Option> { +fn to_input_msg(output: Message) -> Option> { match output { - Output::Propose(p) => Some(Message::Proposal(p)), - Output::Vote(v) => Some(Message::Vote(v)), - Output::Decide(_, _) => None, - Output::SetTimeout(_) => None, + Message::Propose(p) => Some(Event::Proposal(p)), + Message::Vote(v) => Some(Event::Vote(v)), + Message::Decide(_, _) => None, + Message::SetTimeout(_) => None, } } @@ -49,8 +48,8 @@ fn executor_steps_proposer() { let steps = vec![ TestStep { desc: "Start round 0, we are proposer, propose value", - input_message: Some(Message::NewRound(Round::new(0))), - expected_output: Some(Output::Propose(proposal.clone())), + input_event: Some(Event::NewRound(Round::new(0))), + expected_output: Some(Message::Propose(proposal.clone())), new_state: State { height: Height::new(1), round: Round::new(0), @@ -62,8 +61,8 @@ fn executor_steps_proposer() { }, TestStep { desc: "Receive our own proposal, prevote for it (v1)", - input_message: None, - expected_output: Some(Output::Vote( + input_event: None, + expected_output: Some(Message::Vote( Vote::new_prevote(Round::new(0), Some(value_id)).signed(&my_sk), )), new_state: State { @@ -77,7 +76,7 @@ fn executor_steps_proposer() { }, TestStep { desc: "Receive our own prevote v1", - input_message: None, + input_event: None, expected_output: None, new_state: State { height: Height::new(1), @@ -90,7 +89,7 @@ fn executor_steps_proposer() { }, TestStep { desc: "v2 prevotes for our proposal", - input_message: Some(Message::Vote( + input_event: Some(Event::Vote( Vote::new_prevote(Round::new(0), Some(value_id)).signed(&sk2), )), expected_output: None, @@ -105,10 +104,10 @@ fn executor_steps_proposer() { }, TestStep { desc: "v3 prevotes for our proposal, we get +2/3 prevotes, precommit for it (v1)", - input_message: Some(Message::Vote( + input_event: Some(Event::Vote( Vote::new_prevote(Round::new(0), Some(value_id)).signed(&sk3), )), - expected_output: Some(Output::Vote( + expected_output: Some(Message::Vote( Vote::new_precommit(Round::new(0), Some(value_id)).signed(&my_sk), )), new_state: State { @@ -128,7 +127,7 @@ fn executor_steps_proposer() { }, TestStep { desc: "v1 receives its own precommit", - input_message: None, + input_event: None, expected_output: None, new_state: State { height: Height::new(1), @@ -147,7 +146,7 @@ fn executor_steps_proposer() { }, TestStep { desc: "v2 precommits for our proposal", - input_message: Some(Message::Vote( + input_event: Some(Event::Vote( Vote::new_precommit(Round::new(0), Some(value_id)).signed(&sk2), )), expected_output: None, @@ -168,10 +167,10 @@ fn executor_steps_proposer() { }, TestStep { desc: "v3 precommits for our proposal, we get +2/3 precommits, decide it (v1)", - input_message: Some(Message::Vote( + input_event: Some(Event::Vote( Vote::new_precommit(Round::new(0), Some(value_id)).signed(&sk2), )), - expected_output: Some(Output::Decide(Round::new(0), value.clone())), + expected_output: Some(Message::Decide(Round::new(0), value.clone())), new_state: State { height: Height::new(1), round: Round::new(0), @@ -195,7 +194,7 @@ fn executor_steps_proposer() { println!("Step: {}", step.desc); let execute_message = step - .input_message + .input_event .unwrap_or_else(|| previous_message.unwrap()); let output = executor.execute(execute_message); @@ -234,8 +233,8 @@ fn executor_steps_not_proposer() { let steps = vec![ TestStep { desc: "Start round 0, we are not the proposer", - input_message: Some(Message::NewRound(Round::new(0))), - expected_output: Some(Output::SetTimeout(Timeout::propose(Round::new(0)))), + input_event: Some(Event::NewRound(Round::new(0))), + expected_output: Some(Message::SetTimeout(Timeout::propose(Round::new(0)))), new_state: State { height: Height::new(1), round: Round::new(0), @@ -247,8 +246,8 @@ fn executor_steps_not_proposer() { }, TestStep { desc: "Receive a proposal, prevote for it (v2)", - input_message: Some(Message::Proposal(proposal.clone())), - expected_output: Some(Output::Vote( + input_event: Some(Event::Proposal(proposal.clone())), + expected_output: Some(Message::Vote( Vote::new_prevote(Round::new(0), Some(value_id)).signed(my_sk), )), new_state: State { @@ -262,7 +261,7 @@ fn executor_steps_not_proposer() { }, TestStep { desc: "Receive our own prevote", - input_message: None, + input_event: None, expected_output: None, new_state: State { height: Height::new(1), @@ -275,7 +274,7 @@ fn executor_steps_not_proposer() { }, TestStep { desc: "v2 prevotes for its own proposal", - input_message: Some(Message::Vote( + input_event: Some(Event::Vote( Vote::new_prevote(Round::new(0), Some(value_id)).signed(&sk2), )), expected_output: None, @@ -290,10 +289,10 @@ fn executor_steps_not_proposer() { }, TestStep { desc: "v3 prevotes for v2's proposal, it gets +2/3 prevotes, precommit for it (v2)", - input_message: Some(Message::Vote( + input_event: Some(Event::Vote( Vote::new_prevote(Round::new(0), Some(value_id)).signed(&sk3), )), - expected_output: Some(Output::Vote( + expected_output: Some(Message::Vote( Vote::new_precommit(Round::new(0), Some(value_id)).signed(my_sk), )), new_state: State { @@ -313,7 +312,7 @@ fn executor_steps_not_proposer() { }, TestStep { desc: "we receive our own precommit", - input_message: None, + input_event: None, expected_output: None, new_state: State { height: Height::new(1), @@ -332,7 +331,7 @@ fn executor_steps_not_proposer() { }, TestStep { desc: "v1 precommits its proposal", - input_message: Some(Message::Vote( + input_event: Some(Event::Vote( Vote::new_precommit(Round::new(0), Some(value_id)).signed(&sk1), )), expected_output: None, @@ -353,10 +352,10 @@ fn executor_steps_not_proposer() { }, TestStep { desc: "v3 precommits for v1's proposal, it gets +2/3 precommits, decide it", - input_message: Some(Message::Vote( + input_event: Some(Event::Vote( Vote::new_precommit(Round::new(0), Some(value_id)).signed(&sk3), )), - expected_output: Some(Output::Decide(Round::new(0), value.clone())), + expected_output: Some(Message::Decide(Round::new(0), value.clone())), new_state: State { height: Height::new(1), round: Round::new(0), @@ -380,7 +379,7 @@ fn executor_steps_not_proposer() { println!("Step: {}", step.desc); let execute_message = step - .input_message + .input_event .unwrap_or_else(|| previous_message.unwrap()); let output = executor.execute(execute_message); @@ -418,8 +417,8 @@ fn executor_steps_not_proposer_timeout() { // Start round 0, we are not the proposer TestStep { desc: "Start round 0, we are not the proposer", - input_message: Some(Message::NewRound(Round::new(0))), - expected_output: Some(Output::SetTimeout(Timeout::propose(Round::new(0)))), + input_event: Some(Event::NewRound(Round::new(0))), + expected_output: Some(Message::SetTimeout(Timeout::propose(Round::new(0)))), new_state: State { height: Height::new(1), round: Round::new(0), @@ -432,8 +431,8 @@ fn executor_steps_not_proposer_timeout() { // Receive a propose timeout, prevote for nil (v1) TestStep { desc: "Receive a propose timeout, prevote for nil (v1)", - input_message: Some(Message::Timeout(Timeout::propose(Round::new(0)))), - expected_output: Some(Output::Vote( + input_event: Some(Event::Timeout(Timeout::propose(Round::new(0)))), + expected_output: Some(Message::Vote( Vote::new_prevote(Round::new(0), None).signed(&my_sk), )), new_state: State { @@ -448,7 +447,7 @@ fn executor_steps_not_proposer_timeout() { // Receive our own prevote v1 TestStep { desc: "Receive our own prevote v1", - input_message: None, + input_event: None, expected_output: None, new_state: State { height: Height::new(1), @@ -462,7 +461,7 @@ fn executor_steps_not_proposer_timeout() { // v2 prevotes for its own proposal TestStep { desc: "v2 prevotes for its own proposal", - input_message: Some(Message::Vote( + input_event: Some(Event::Vote( Vote::new_prevote(Round::new(0), Some(value_id)).signed(&sk1), )), expected_output: None, @@ -478,10 +477,10 @@ fn executor_steps_not_proposer_timeout() { // v3 prevotes for nil, it gets +2/3 prevotes, precommit for it (v1) TestStep { desc: "v3 prevotes for nil, it gets +2/3 prevotes, precommit for it (v1)", - input_message: Some(Message::Vote( + input_event: Some(Event::Vote( Vote::new_prevote(Round::new(0), None).signed(&sk3), )), - expected_output: Some(Output::Vote( + expected_output: Some(Message::Vote( Vote::new_precommit(Round::new(0), None).signed(&my_sk), )), new_state: State { @@ -496,7 +495,7 @@ fn executor_steps_not_proposer_timeout() { // v1 receives its own precommit TestStep { desc: "v1 receives its own precommit", - input_message: None, + input_event: None, expected_output: None, new_state: State { height: Height::new(1), @@ -510,7 +509,7 @@ fn executor_steps_not_proposer_timeout() { // v2 precommits its proposal TestStep { desc: "v2 precommits its proposal", - input_message: Some(Message::Vote( + input_event: Some(Event::Vote( Vote::new_precommit(Round::new(0), Some(value_id)).signed(&sk1), )), expected_output: None, @@ -526,7 +525,7 @@ fn executor_steps_not_proposer_timeout() { // v3 precommits for nil TestStep { desc: "v3 precommits for nil", - input_message: Some(Message::Vote( + input_event: Some(Event::Vote( Vote::new_precommit(Round::new(0), None).signed(&sk3), )), expected_output: None, @@ -542,7 +541,7 @@ fn executor_steps_not_proposer_timeout() { // we receive a precommit timeout, start a new round TestStep { desc: "we receive a precommit timeout, start a new round", - input_message: Some(Message::Timeout(Timeout::precommit(Round::new(0)))), + input_event: Some(Event::Timeout(Timeout::precommit(Round::new(0)))), expected_output: None, new_state: State { height: Height::new(1), @@ -561,7 +560,7 @@ fn executor_steps_not_proposer_timeout() { println!("Step: {}", step.desc); let execute_message = step - .input_message + .input_event .unwrap_or_else(|| previous_message.unwrap()); let output = executor.execute(execute_message); diff --git a/Code/test/tests/vote_keeper.rs b/Code/test/tests/vote_keeper.rs index ed976b9e5..c8947c030 100644 --- a/Code/test/tests/vote_keeper.rs +++ b/Code/test/tests/vote_keeper.rs @@ -1,6 +1,5 @@ use malachite_common::Round; -use malachite_round::events::Event; -use malachite_vote::keeper::VoteKeeper; +use malachite_vote::keeper::{Message, VoteKeeper}; use malachite_test::{Height, TestConsensus, ValueId, Vote}; @@ -10,14 +9,14 @@ fn prevote_apply_nil() { let vote = Vote::new_prevote(Round::new(0), None); - let event = keeper.apply_vote(vote.clone(), 1); - assert_eq!(event, None); + let msg = keeper.apply_vote(vote.clone(), 1); + assert_eq!(msg, None); - let event = keeper.apply_vote(vote.clone(), 1); - assert_eq!(event, None); + let msg = keeper.apply_vote(vote.clone(), 1); + assert_eq!(msg, None); - let event = keeper.apply_vote(vote, 1); - assert_eq!(event, Some(Event::PolkaNil)); + let msg = keeper.apply_vote(vote, 1); + assert_eq!(msg, Some(Message::PolkaNil)); } #[test] @@ -26,14 +25,14 @@ fn precommit_apply_nil() { let vote = Vote::new_precommit(Round::new(0), None); - let event = keeper.apply_vote(vote.clone(), 1); - assert_eq!(event, None); + let msg = keeper.apply_vote(vote.clone(), 1); + assert_eq!(msg, None); - let event = keeper.apply_vote(vote.clone(), 1); - assert_eq!(event, None); + let msg = keeper.apply_vote(vote.clone(), 1); + assert_eq!(msg, None); - let event = keeper.apply_vote(vote, 1); - assert_eq!(event, None); + let msg = keeper.apply_vote(vote, 1); + assert_eq!(msg, None); } #[test] @@ -44,18 +43,18 @@ fn prevote_apply_single_value() { let val = Some(v); let vote = Vote::new_prevote(Round::new(0), val); - let event = keeper.apply_vote(vote.clone(), 1); - assert_eq!(event, None); + let msg = keeper.apply_vote(vote.clone(), 1); + assert_eq!(msg, None); - let event = keeper.apply_vote(vote.clone(), 1); - assert_eq!(event, None); + let msg = keeper.apply_vote(vote.clone(), 1); + assert_eq!(msg, None); let vote_nil = Vote::new_prevote(Round::new(0), None); - let event = keeper.apply_vote(vote_nil, 1); - assert_eq!(event, Some(Event::PolkaAny)); + let msg = keeper.apply_vote(vote_nil, 1); + assert_eq!(msg, Some(Message::PolkaAny)); - let event = keeper.apply_vote(vote, 1); - assert_eq!(event, Some(Event::PolkaValue(v))); + let msg = keeper.apply_vote(vote, 1); + assert_eq!(msg, Some(Message::PolkaValue(v))); } #[test] @@ -66,16 +65,16 @@ fn precommit_apply_single_value() { let val = Some(v); let vote = Vote::new_precommit(Round::new(0), val); - let event = keeper.apply_vote(vote.clone(), 1); - assert_eq!(event, None); + let msg = keeper.apply_vote(vote.clone(), 1); + assert_eq!(msg, None); - let event = keeper.apply_vote(vote.clone(), 1); - assert_eq!(event, None); + let msg = keeper.apply_vote(vote.clone(), 1); + assert_eq!(msg, None); let vote_nil = Vote::new_precommit(Round::new(0), None); - let event = keeper.apply_vote(vote_nil, 1); - assert_eq!(event, Some(Event::PrecommitAny)); + let msg = keeper.apply_vote(vote_nil, 1); + assert_eq!(msg, Some(Message::PrecommitAny)); - let event = keeper.apply_vote(vote, 1); - assert_eq!(event, Some(Event::PrecommitValue(v))); + let msg = keeper.apply_vote(vote, 1); + assert_eq!(msg, Some(Message::PrecommitValue(v))); } diff --git a/Code/vote/Cargo.toml b/Code/vote/Cargo.toml index 782235c1d..64d9e4306 100644 --- a/Code/vote/Cargo.toml +++ b/Code/vote/Cargo.toml @@ -6,4 +6,3 @@ publish = false [dependencies] malachite-common = { version = "0.1.0", path = "../common" } -malachite-round = { version = "0.1.0", path = "../round" } diff --git a/Code/vote/src/keeper.rs b/Code/vote/src/keeper.rs index 5299361f5..7c244017b 100644 --- a/Code/vote/src/keeper.rs +++ b/Code/vote/src/keeper.rs @@ -1,14 +1,23 @@ use alloc::collections::BTreeMap; use malachite_common::{Consensus, Round, ValueId, Vote, VoteType}; -use malachite_round::events::Event; use crate::{ count::{Threshold, Weight}, RoundVotes, }; -/// Keeps track of votes and emits events when thresholds are reached. +/// Messages emitted by the vote keeper +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum Message { + PolkaAny, + PolkaNil, + PolkaValue(Value), + PrecommitAny, + PrecommitValue(Value), +} + +/// Keeps track of votes and emits messages when thresholds are reached. #[derive(Clone, Debug)] pub struct VoteKeeper where @@ -36,7 +45,7 @@ where } /// Apply a vote with a given weight, potentially triggering an event. - pub fn apply_vote(&mut self, vote: C::Vote, weight: Weight) -> Option> { + pub fn apply_vote(&mut self, vote: C::Vote, weight: Weight) -> Option>> { let round = self.rounds.entry(vote.round()).or_insert_with(|| { RoundVotes::new(self.height.clone(), vote.round(), self.total_weight) }); @@ -44,7 +53,7 @@ where let vote_type = vote.vote_type(); let threshold = round.add_vote(vote, weight); - Self::to_event(vote_type, threshold) + Self::to_message(vote_type, threshold) } /// Check if a threshold is met, ie. if we have a quorum for that threshold. @@ -66,17 +75,17 @@ where } /// Map a vote type and a threshold to a state machine event. - fn to_event(typ: VoteType, threshold: Threshold>) -> Option> { + fn to_message(typ: VoteType, threshold: Threshold>) -> Option>> { match (typ, threshold) { (_, Threshold::Init) => None, - (VoteType::Prevote, Threshold::Any) => Some(Event::PolkaAny), - (VoteType::Prevote, Threshold::Nil) => Some(Event::PolkaNil), - (VoteType::Prevote, Threshold::Value(v)) => Some(Event::PolkaValue(v)), + (VoteType::Prevote, Threshold::Any) => Some(Message::PolkaAny), + (VoteType::Prevote, Threshold::Nil) => Some(Message::PolkaNil), + (VoteType::Prevote, Threshold::Value(v)) => Some(Message::PolkaValue(v)), - (VoteType::Precommit, Threshold::Any) => Some(Event::PrecommitAny), + (VoteType::Precommit, Threshold::Any) => Some(Message::PrecommitAny), (VoteType::Precommit, Threshold::Nil) => None, - (VoteType::Precommit, Threshold::Value(v)) => Some(Event::PrecommitValue(v)), + (VoteType::Precommit, Threshold::Value(v)) => Some(Message::PrecommitValue(v)), } } }