Skip to content

Commit

Permalink
Merge branch 'main' into josef/skipRoundLogic
Browse files Browse the repository at this point in the history
  • Loading branch information
romac committed Nov 24, 2023
2 parents f5a124b + 2a7862b commit a6a1281
Show file tree
Hide file tree
Showing 22 changed files with 1,065 additions and 610 deletions.
2 changes: 2 additions & 0 deletions Code/common/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ where
/// Build a new prevote vote by the validator with the given address,
/// for the value identified by the given value id, at the given round.
fn new_prevote(
height: Self::Height,
round: Round,
value_id: Option<ValueId<Self>>,
address: Self::Address,
Expand All @@ -48,6 +49,7 @@ where
/// Build a new precommit vote by the validator with the given address,
/// for the value identified by the given value id, at the given round.
fn new_precommit(
height: Self::Height,
round: Round,
value_id: Option<ValueId<Self>>,
address: Self::Address,
Expand Down
2 changes: 1 addition & 1 deletion Code/common/src/height.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ use core::fmt::Debug;
pub trait Height
where
// TODO: Require Copy as well?
Self: Clone + Debug + PartialEq + Eq + PartialOrd + Ord,
Self: Default + Clone + Debug + PartialEq + Eq + PartialOrd + Ord,
{
}
5 changes: 4 additions & 1 deletion Code/common/src/vote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,14 @@ where
Self: Clone + Debug + Eq,
Ctx: Context,
{
/// The height for which the vote is for.
fn height(&self) -> Ctx::Height;

/// The round for which the vote is for.
fn round(&self) -> Round;

/// Get a reference to the value being voted for.
fn value(&self) -> Option<&<Ctx::Value as Value>::Id>;
fn value(&self) -> &Option<<Ctx::Value as Value>::Id>;

/// Take ownership of the value being voted for.
fn take_value(self) -> Option<<Ctx::Value as Value>::Id>;
Expand Down
91 changes: 46 additions & 45 deletions Code/driver/src/driver.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use alloc::collections::BTreeMap;

use malachite_round::state_machine::RoundData;

use malachite_common::{
Expand All @@ -12,6 +10,7 @@ use malachite_round::state::State as RoundState;
use malachite_vote::keeper::Message as VoteMessage;
use malachite_vote::keeper::VoteKeeper;
use malachite_vote::Threshold;
use malachite_vote::ThresholdParams;

use crate::env::Env as DriverEnv;
use crate::event::Event;
Expand All @@ -32,13 +31,11 @@ where
pub env: Env,
pub proposer_selector: PSel,

pub height: Ctx::Height,
pub address: Ctx::Address,
pub validator_set: Ctx::ValidatorSet,

pub round: Round,
pub votes: VoteKeeper<Ctx>,
pub round_states: BTreeMap<Round, RoundState<Ctx>>,
pub round_state: RoundState<Ctx>,
}

impl<Ctx, Env, PSel> Driver<Ctx, Env, PSel>
Expand All @@ -51,27 +48,37 @@ where
ctx: Ctx,
env: Env,
proposer_selector: PSel,
height: Ctx::Height,
validator_set: Ctx::ValidatorSet,
address: Ctx::Address,
) -> Self {
let votes = VoteKeeper::new(validator_set.total_voting_power());
let votes = VoteKeeper::new(
validator_set.total_voting_power(),
ThresholdParams::default(), // TODO: Make this configurable
);

Self {
ctx,
env,
proposer_selector,
height,
address,
validator_set,
round: Round::NIL,
votes,
round_states: BTreeMap::new(),
round_state: RoundState::default(),
}
}

async fn get_value(&self, round: Round) -> Option<Ctx::Value> {
self.env.get_value(self.height.clone(), round).await
pub fn height(&self) -> &Ctx::Height {
&self.round_state.height
}

pub fn round(&self) -> Round {
self.round_state.round
}

async fn get_value(&self) -> Option<Ctx::Value> {
self.env
.get_value(self.height().clone(), self.round())
.await
}

pub async fn execute(&mut self, msg: Event<Ctx>) -> Result<Option<Message<Ctx>>, Error<Ctx>> {
Expand All @@ -81,11 +88,7 @@ where
};

let msg = match round_msg {
RoundMessage::NewRound(round) => {
// XXX: Check if there is an existing state?
assert!(self.round < round);
Message::NewRound(round)
}
RoundMessage::NewRound(round) => Message::NewRound(self.height().clone(), round),

RoundMessage::Proposal(proposal) => {
// sign the proposal
Expand All @@ -108,21 +111,27 @@ where
Ok(Some(msg))
}

async fn apply(&mut self, msg: Event<Ctx>) -> Result<Option<RoundMessage<Ctx>>, Error<Ctx>> {
match msg {
Event::NewRound(round) => self.apply_new_round(round).await,
async fn apply(&mut self, event: Event<Ctx>) -> Result<Option<RoundMessage<Ctx>>, Error<Ctx>> {
match event {
Event::NewRound(height, round) => self.apply_new_round(height, round).await,

Event::Proposal(proposal, validity) => {
Ok(self.apply_proposal(proposal, validity).await)
}

Event::Vote(signed_vote) => self.apply_vote(signed_vote),

Event::TimeoutElapsed(timeout) => Ok(self.apply_timeout(timeout)),
}
}

async fn apply_new_round(
&mut self,
height: Ctx::Height,
round: Round,
) -> Result<Option<RoundMessage<Ctx>>, Error<Ctx>> {
self.round_state = RoundState::new(height, round);

let proposer_address = self
.proposer_selector
.select_proposer(round, &self.validator_set);
Expand All @@ -136,7 +145,7 @@ where
// We are the proposer
// TODO: Schedule propose timeout

let Some(value) = self.get_value(round).await else {
let Some(value) = self.get_value().await else {
return Err(Error::NoValueToPropose);
};

Expand All @@ -145,11 +154,6 @@ where
RoundEvent::NewRound
};

assert!(self.round < round);
self.round_states
.insert(round, RoundState::default().new_round(round));
self.round = round;

Ok(self.apply_event(round, event))
}

Expand All @@ -159,23 +163,24 @@ where
validity: Validity,
) -> Option<RoundMessage<Ctx>> {
// Check that there is an ongoing round
let Some(round_state) = self.round_states.get(&self.round) else {
// TODO: Add logging
if self.round_state.round == Round::NIL {
return None;
};
}

// Only process the proposal if there is no other proposal
if round_state.proposal.is_some() {
if self.round_state.proposal.is_some() {
return None;
}

// Check that the proposal is for the current height and round
if self.height != proposal.height() || self.round != proposal.round() {
if self.round_state.height != proposal.height()
|| self.round_state.round != proposal.round()
{
return None;
}

// TODO: Document
if proposal.pol_round().is_defined() && proposal.pol_round() >= round_state.round {
if proposal.pol_round().is_defined() && proposal.pol_round() >= self.round_state.round {
return None;
}

Expand Down Expand Up @@ -233,11 +238,12 @@ where
));
}

let round = signed_vote.vote.round();
let vote_round = signed_vote.vote.round();
let current_round = self.round();

let Some(vote_msg) = self
.votes
.apply_vote(signed_vote.vote, validator.voting_power())
let Some(vote_msg) =
self.votes
.apply_vote(signed_vote.vote, validator.voting_power(), current_round)
else {
return Ok(None);
};
Expand All @@ -251,7 +257,7 @@ where
VoteMessage::SkipRound(r) => RoundEvent::SkipRound(r),
};

Ok(self.apply_event(round, round_event))
Ok(self.apply_event(vote_round, round_event))
}

fn apply_timeout(&mut self, timeout: Timeout) -> Option<RoundMessage<Ctx>> {
Expand All @@ -266,10 +272,9 @@ where

/// Apply the event, update the state.
fn apply_event(&mut self, round: Round, event: RoundEvent<Ctx>) -> Option<RoundMessage<Ctx>> {
// Get the round state, or create a new one
let round_state = self.round_states.remove(&round).unwrap_or_default();
let round_state = core::mem::take(&mut self.round_state);

let data = RoundData::new(round, &self.height, &self.address);
let data = RoundData::new(round, round_state.height.clone(), &self.address);

// Multiplex the event with the round state.
let mux_event = match event {
Expand All @@ -293,13 +298,9 @@ where
let transition = round_state.apply_event(&data, mux_event);

// Update state
self.round_states.insert(round, transition.next_state);
self.round_state = transition.next_state;

// Return message, if any
transition.message
}

pub fn round_state(&self, round: Round) -> Option<&RoundState<Ctx>> {
self.round_states.get(&round)
}
}
2 changes: 1 addition & 1 deletion Code/driver/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub enum Event<Ctx>
where
Ctx: Context,
{
NewRound(Round),
NewRound(Ctx::Height, Round),
Proposal(Ctx::Proposal, Validity),
Vote(SignedVote<Ctx>),
TimeoutElapsed(Timeout),
Expand Down
10 changes: 6 additions & 4 deletions Code/driver/src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ where
Vote(SignedVote<Ctx>),
Decide(Round, Ctx::Value),
ScheduleTimeout(Timeout),
NewRound(Round),
NewRound(Ctx::Height, Round),
}

// NOTE: We have to derive these instances manually, otherwise
Expand All @@ -26,7 +26,7 @@ impl<Ctx: Context> Clone for Message<Ctx> {
Message::Vote(signed_vote) => Message::Vote(signed_vote.clone()),
Message::Decide(round, value) => Message::Decide(*round, value.clone()),
Message::ScheduleTimeout(timeout) => Message::ScheduleTimeout(*timeout),
Message::NewRound(round) => Message::NewRound(*round),
Message::NewRound(height, round) => Message::NewRound(height.clone(), *round),
}
}
}
Expand All @@ -39,7 +39,7 @@ impl<Ctx: Context> fmt::Debug for Message<Ctx> {
Message::Vote(signed_vote) => write!(f, "Vote({:?})", signed_vote),
Message::Decide(round, value) => write!(f, "Decide({:?}, {:?})", round, value),
Message::ScheduleTimeout(timeout) => write!(f, "ScheduleTimeout({:?})", timeout),
Message::NewRound(round) => write!(f, "NewRound({:?})", round),
Message::NewRound(height, round) => write!(f, "NewRound({:?}, {:?})", height, round),
}
}
}
Expand All @@ -60,7 +60,9 @@ impl<Ctx: Context> PartialEq for Message<Ctx> {
(Message::ScheduleTimeout(timeout), Message::ScheduleTimeout(other_timeout)) => {
timeout == other_timeout
}
(Message::NewRound(round), Message::NewRound(other_round)) => round == other_round,
(Message::NewRound(height, round), Message::NewRound(other_height, other_round)) => {
height == other_height && round == other_round
}
_ => false,
}
}
Expand Down
18 changes: 14 additions & 4 deletions Code/round/src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,22 @@ impl<Ctx: Context> Message<Ctx> {
Message::Proposal(Ctx::new_proposal(height, round, value, pol_round))
}

pub fn prevote(round: Round, value_id: Option<ValueId<Ctx>>, address: Ctx::Address) -> Self {
Message::Vote(Ctx::new_prevote(round, value_id, address))
pub fn prevote(
height: Ctx::Height,
round: Round,
value_id: Option<ValueId<Ctx>>,
address: Ctx::Address,
) -> Self {
Message::Vote(Ctx::new_prevote(height, round, value_id, address))
}

pub fn precommit(round: Round, value_id: Option<ValueId<Ctx>>, address: Ctx::Address) -> Self {
Message::Vote(Ctx::new_precommit(round, value_id, address))
pub fn precommit(
height: Ctx::Height,
round: Round,
value_id: Option<ValueId<Ctx>>,
address: Ctx::Address,
) -> Self {
Message::Vote(Ctx::new_precommit(height, round, value_id, address))
}

pub fn schedule_timeout(round: Round, step: TimeoutStep) -> Self {
Expand Down
16 changes: 6 additions & 10 deletions Code/round/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pub struct State<Ctx>
where
Ctx: Context,
{
pub height: Ctx::Height,
pub round: Round,
pub step: Step,
pub proposal: Option<Ctx::Proposal>,
Expand All @@ -45,23 +46,17 @@ impl<Ctx> State<Ctx>
where
Ctx: Context,
{
pub fn new() -> Self {
pub fn new(height: Ctx::Height, round: Round) -> Self {
Self {
round: Round::INITIAL,
height,
round,
step: Step::NewRound,
proposal: None,
locked: None,
valid: None,
}
}

pub fn new_round(self, round: Round) -> Self {
Self {
round,
step: Step::NewRound,
..self
}
}
pub fn with_step(self, step: Step) -> Self {
Self { step, ..self }
}
Expand Down Expand Up @@ -94,7 +89,7 @@ where
Ctx: Context,
{
fn default() -> Self {
Self::new()
Self::new(Ctx::Height::default(), Round::NIL)
}
}

Expand All @@ -105,6 +100,7 @@ where
#[cfg_attr(coverage_nightly, coverage(off))]
fn clone(&self) -> Self {
Self {
height: self.height.clone(),
round: self.round,
step: self.step,
proposal: self.proposal.clone(),
Expand Down
Loading

0 comments on commit a6a1281

Please sign in to comment.