Skip to content

Commit

Permalink
Use an async Client (#56)
Browse files Browse the repository at this point in the history
  • Loading branch information
romac authored Nov 10, 2023
1 parent 19b65d3 commit 1ec7a94
Show file tree
Hide file tree
Showing 8 changed files with 39 additions and 23 deletions.
2 changes: 2 additions & 0 deletions Code/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ license = "Apache-2.0"
publish = false

[workspace.dependencies]
async-trait = "0.1"
futures = "0.3"
ed25519-consensus = "2.1.0"
rand = { version = "0.8.5", features = ["std_rng"] }
secrecy = "0.8.0"
Expand Down
3 changes: 2 additions & 1 deletion Code/driver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ malachite-common = { version = "0.1.0", path = "../common" }
malachite-round = { version = "0.1.0", path = "../round" }
malachite-vote = { version = "0.1.0", path = "../vote" }

secrecy.workspace = true
async-trait.workspace = true
secrecy.workspace = true
7 changes: 5 additions & 2 deletions Code/driver/src/client.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
use async_trait::async_trait;

use malachite_common::Context;

/// Client for use by the [`Driver`](crate::Driver) to ask
/// for a value to propose and validate proposals.
#[async_trait]
pub trait Client<Ctx>
where
Ctx: Context,
{
/// Get the value to propose.
fn get_value(&self) -> Ctx::Value;
async fn get_value(&self) -> Ctx::Value;

/// Validate a proposal.
fn validate_proposal(&self, proposal: &Ctx::Proposal) -> bool;
async fn validate_proposal(&self, proposal: &Ctx::Proposal) -> bool;
}
28 changes: 14 additions & 14 deletions Code/driver/src/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use crate::event::Event;
use crate::message::Message;
use crate::ProposerSelector;

/// Driver for the state machine of the Malachite consensus engine.
/// Driver for the state machine of the Malachite consensus engine at a given height.
#[derive(Clone, Debug)]
pub struct Driver<Ctx, Client, PSel>
where
Expand Down Expand Up @@ -73,16 +73,16 @@ where
}
}

fn get_value(&self) -> Ctx::Value {
self.client.get_value()
async fn get_value(&self) -> Ctx::Value {
self.client.get_value().await
}

fn validate_proposal(&self, proposal: &Ctx::Proposal) -> bool {
self.client.validate_proposal(proposal)
async fn validate_proposal(&self, proposal: &Ctx::Proposal) -> bool {
self.client.validate_proposal(proposal).await
}

pub fn execute(&mut self, msg: Event<Ctx>) -> Option<Message<Ctx>> {
let round_msg = match self.apply(msg) {
pub async fn execute(&mut self, msg: Event<Ctx>) -> Option<Message<Ctx>> {
let round_msg = match self.apply(msg).await {
Some(msg) => msg,
None => return None,
};
Expand Down Expand Up @@ -113,16 +113,16 @@ where
}
}

fn apply(&mut self, msg: Event<Ctx>) -> Option<RoundMessage<Ctx>> {
async fn apply(&mut self, msg: Event<Ctx>) -> Option<RoundMessage<Ctx>> {
match msg {
Event::NewRound(round) => self.apply_new_round(round),
Event::Proposal(proposal) => self.apply_proposal(proposal),
Event::NewRound(round) => self.apply_new_round(round).await,
Event::Proposal(proposal) => self.apply_proposal(proposal).await,
Event::Vote(signed_vote) => self.apply_vote(signed_vote),
Event::TimeoutElapsed(timeout) => self.apply_timeout(timeout),
}
}

fn apply_new_round(&mut self, round: Round) -> Option<RoundMessage<Ctx>> {
async fn apply_new_round(&mut self, round: Round) -> Option<RoundMessage<Ctx>> {
let proposer_address = self
.proposer_selector
.select_proposer(round, &self.validator_set);
Expand All @@ -134,7 +134,7 @@ where

// TODO: Write this check differently, maybe just based on the address
let event = if proposer.public_key() == &self.private_key.expose_secret().verifying_key() {
let value = self.get_value();
let value = self.get_value().await;
RoundEvent::NewRoundProposer(value)
} else {
RoundEvent::NewRound
Expand All @@ -148,7 +148,7 @@ where
self.apply_event(round, event)
}

fn apply_proposal(&mut self, proposal: Ctx::Proposal) -> Option<RoundMessage<Ctx>> {
async fn apply_proposal(&mut self, proposal: Ctx::Proposal) -> Option<RoundMessage<Ctx>> {
// Check that there is an ongoing round
let Some(round_state) = self.round_states.get(&self.round) else {
// TODO: Add logging
Expand All @@ -172,7 +172,7 @@ where

// TODO: Verify proposal signature (make some of these checks part of message validation)

let is_valid = self.validate_proposal(&proposal);
let is_valid = self.validate_proposal(&proposal).await;

match proposal.pol_round() {
Round::Nil => {
Expand Down
3 changes: 3 additions & 0 deletions Code/driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,6 @@ pub use driver::Driver;
pub use event::Event;
pub use message::Message;
pub use proposer::ProposerSelector;

// Re-export `#[async_trait]` macro for convenience.
pub use async_trait::async_trait;
3 changes: 3 additions & 0 deletions Code/test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ malachite-driver = { version = "0.1.0", path = "../driver" }
malachite-round = { version = "0.1.0", path = "../round" }
malachite-vote = { version = "0.1.0", path = "../vote" }

futures = { workspace = true, features = ["executor"] }

async-trait.workspace = true
ed25519-consensus.workspace = true
signature.workspace = true
rand.workspace = true
Expand Down
7 changes: 5 additions & 2 deletions Code/test/src/client.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use async_trait::async_trait;

use malachite_driver::Client;

use crate::{Proposal, TestContext, Value};
Expand All @@ -13,12 +15,13 @@ impl TestClient {
}
}

#[async_trait]
impl Client<TestContext> for TestClient {
fn get_value(&self) -> Value {
async fn get_value(&self) -> Value {
self.value.clone()
}

fn validate_proposal(&self, proposal: &Proposal) -> bool {
async fn validate_proposal(&self, proposal: &Proposal) -> bool {
(self.is_valid)(proposal)
}
}
9 changes: 5 additions & 4 deletions Code/test/tests/driver.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use futures::executor::block_on;
use malachite_common::{Context, Round, Timeout};
use malachite_driver::{Driver, Event, Message, ProposerSelector};
use malachite_round::state::{RoundValue, State, Step};
Expand Down Expand Up @@ -222,7 +223,7 @@ fn driver_steps_proposer() {
.input_event
.unwrap_or_else(|| previous_message.unwrap());

let output = driver.execute(execute_message);
let output = block_on(driver.execute(execute_message));
assert_eq!(output, step.expected_output, "expected output message");

assert_eq!(driver.round, step.expected_round, "expected round");
Expand Down Expand Up @@ -418,7 +419,7 @@ fn driver_steps_not_proposer_valid() {
.input_event
.unwrap_or_else(|| previous_message.unwrap());

let output = driver.execute(execute_message);
let output = block_on(driver.execute(execute_message));
assert_eq!(output, step.expected_output, "expected output message");

assert_eq!(driver.round, step.expected_round, "expected round");
Expand Down Expand Up @@ -560,7 +561,7 @@ fn driver_steps_not_proposer_invalid() {
.input_event
.unwrap_or_else(|| previous_message.unwrap());

let output = driver.execute(execute_message);
let output = block_on(driver.execute(execute_message));
assert_eq!(output, step.expected_output, "expected output");

assert_eq!(driver.round, step.expected_round, "expected round");
Expand Down Expand Up @@ -765,7 +766,7 @@ fn driver_steps_not_proposer_timeout_multiple_rounds() {
.input_event
.unwrap_or_else(|| previous_message.unwrap());

let output = driver.execute(execute_message);
let output = block_on(driver.execute(execute_message));
assert_eq!(output, step.expected_output, "expected output message");

assert_eq!(driver.round, step.expected_round, "expected round");
Expand Down

0 comments on commit 1ec7a94

Please sign in to comment.