From fa2211ccf26d2f779f135af5ba301d6e36fde28d Mon Sep 17 00:00:00 2001 From: Romain Ruetschi Date: Fri, 3 Nov 2023 17:31:21 +0100 Subject: [PATCH] Add `Client` for getting a value and validate a proposal --- Code/consensus/src/executor.rs | 52 ++++++++++++++++++--------- Code/test/src/client.rs | 24 +++++++++++++ Code/test/src/lib.rs | 2 ++ Code/test/tests/consensus_executor.rs | 12 ++++--- 4 files changed, 68 insertions(+), 22 deletions(-) create mode 100644 Code/test/src/client.rs diff --git a/Code/consensus/src/executor.rs b/Code/consensus/src/executor.rs index 46e2b0769..ee422fdfe 100644 --- a/Code/consensus/src/executor.rs +++ b/Code/consensus/src/executor.rs @@ -27,11 +27,32 @@ where TimeoutElapsed(Timeout), } +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum Message +where + Ctx: Context, +{ + Propose(Ctx::Proposal), + Vote(SignedVote), + Decide(Round, Ctx::Value), + ScheduleTimeout(Timeout), +} + +pub trait Client +where + Ctx: Context, +{ + fn get_value(&self) -> Ctx::Value; + fn validate_proposal(&self, proposal: &Ctx::Proposal) -> bool; +} + #[derive(Clone, Debug)] -pub struct Executor +pub struct Executor where Ctx: Context, + Client: self::Client, { + client: Client, height: Ctx::Height, private_key: Secret>, address: Ctx::Address, @@ -41,22 +62,13 @@ where round_states: BTreeMap>, } -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum Message -where - Ctx: Context, -{ - Propose(Ctx::Proposal), - Vote(SignedVote), - Decide(Round, Ctx::Value), - ScheduleTimeout(Timeout), -} - -impl Executor +impl Executor where Ctx: Context, + Client: self::Client, { pub fn new( + client: Client, height: Ctx::Height, validator_set: Ctx::ValidatorSet, private_key: PrivateKey, @@ -69,6 +81,7 @@ where ); Self { + client, height, private_key: Secret::new(private_key), address, @@ -79,9 +92,12 @@ where } } - pub fn get_value(&self) -> Ctx::Value { - // TODO - add external interface to get the value - Ctx::DUMMY_VALUE + fn get_value(&self) -> Ctx::Value { + self.client.get_value() + } + + fn validate_proposal(&self, proposal: &Ctx::Proposal) -> bool { + self.client.validate_proposal(proposal) } pub fn execute(&mut self, msg: Event) -> Option> { @@ -145,7 +161,9 @@ where } fn apply_proposal(&mut self, proposal: Ctx::Proposal) -> Option> { - // TODO: Check for invalid proposal + if !self.validate_proposal(&proposal) { + todo!("invalid proposal"); + } // Check that there is an ongoing round let Some(round_state) = self.round_states.get(&self.round) else { diff --git a/Code/test/src/client.rs b/Code/test/src/client.rs new file mode 100644 index 000000000..4e05c2345 --- /dev/null +++ b/Code/test/src/client.rs @@ -0,0 +1,24 @@ +use malachite_consensus::executor::Client; + +use crate::{Proposal, TestContext, Value}; + +pub struct TestClient { + pub value: Value, + pub is_valid: fn(&Proposal) -> bool, +} + +impl TestClient { + pub fn new(value: Value, is_valid: fn(&Proposal) -> bool) -> Self { + Self { value, is_valid } + } +} + +impl Client for TestClient { + fn get_value(&self) -> Value { + self.value.clone() + } + + fn validate_proposal(&self, proposal: &Proposal) -> bool { + (self.is_valid)(proposal) + } +} diff --git a/Code/test/src/lib.rs b/Code/test/src/lib.rs index c39e1682a..fc979bccb 100644 --- a/Code/test/src/lib.rs +++ b/Code/test/src/lib.rs @@ -1,6 +1,7 @@ #![forbid(unsafe_code)] #![deny(trivial_casts, trivial_numeric_casts)] +mod client; mod context; mod height; mod proposal; @@ -9,6 +10,7 @@ mod validator_set; mod value; mod vote; +pub use crate::client::*; pub use crate::context::*; pub use crate::height::*; pub use crate::proposal::*; diff --git a/Code/test/tests/consensus_executor.rs b/Code/test/tests/consensus_executor.rs index e89afb9b2..e4cfa4155 100644 --- a/Code/test/tests/consensus_executor.rs +++ b/Code/test/tests/consensus_executor.rs @@ -3,7 +3,7 @@ use malachite_consensus::executor::{Event, Executor, Message}; use malachite_round::state::{RoundValue, State, Step}; use malachite_test::{ - Address, Height, PrivateKey, Proposal, TestContext, Validator, ValidatorSet, Vote, + Address, Height, PrivateKey, Proposal, TestClient, TestContext, Validator, ValidatorSet, Vote, }; use rand::rngs::StdRng; use rand::SeedableRng; @@ -46,8 +46,8 @@ fn executor_steps_proposer() { let (my_sk, my_addr) = (sk1, addr1); let vs = ValidatorSet::new(vec![v1, v2.clone(), v3.clone()]); - - let mut executor = Executor::new(Height::new(1), vs, my_sk.clone(), my_addr); + let client = TestClient::new(value.clone(), |_| true); + let mut executor = Executor::new(client, Height::new(1), vs, my_sk.clone(), my_addr); let proposal = Proposal::new(Height::new(1), Round::new(0), value.clone(), Round::new(-1)); @@ -228,7 +228,8 @@ fn executor_steps_not_proposer() { let (my_sk, my_addr) = (sk2, addr2); let vs = ValidatorSet::new(vec![v1.clone(), v2.clone(), v3.clone()]); - let mut executor = Executor::new(Height::new(1), vs, my_sk.clone(), my_addr); + let client = TestClient::new(value.clone(), |_| true); + let mut executor = Executor::new(client, Height::new(1), vs, my_sk.clone(), my_addr); let proposal = Proposal::new(Height::new(1), Round::new(0), value.clone(), Round::new(-1)); @@ -409,7 +410,8 @@ fn executor_steps_not_proposer_timeout() { let (my_sk, my_addr) = (sk2, addr2); let vs = ValidatorSet::new(vec![v1.clone(), v2.clone(), v3.clone()]); - let mut executor = Executor::new(Height::new(1), vs, my_sk.clone(), my_addr); + let client = TestClient::new(value.clone(), |_| true); + let mut executor = Executor::new(client, Height::new(1), vs, my_sk.clone(), my_addr); let steps = vec![ // Start round 0, we are not the proposer