Skip to content
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

feat(driver): Use an async Client #56

Merged
merged 1 commit into from
Nov 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading