Skip to content

Commit

Permalink
Merge branch 'romac/rust-state-machine' into romac/complete-vote-keeper
Browse files Browse the repository at this point in the history
  • Loading branch information
romac committed Nov 7, 2023
2 parents 9daf55d + f53355f commit ede3908
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 110 deletions.
1 change: 1 addition & 0 deletions Code/common/src/round.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub enum Round {
impl Round {
/// The initial, zero round.
pub const INITIAL: Round = Round::new(0);
pub const NIL: Round = Round::new(-1);

/// Create a new round.
///
Expand Down
2 changes: 1 addition & 1 deletion Code/common/src/validator_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ where
fn total_voting_power(&self) -> VotingPower;

/// The proposer in the validator set.
fn get_proposer(&self) -> Ctx::Validator;
fn get_proposer(&self) -> &Ctx::Validator;

/// Get the validator with the given public key.
fn get_by_public_key(&self, public_key: &PublicKey<Ctx>) -> Option<&Ctx::Validator>;
Expand Down
47 changes: 35 additions & 12 deletions Code/consensus/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ where
private_key: Secret<PrivateKey<Ctx>>,
address: Ctx::Address,
validator_set: Ctx::ValidatorSet,
round: Round,
pub round: Round,
votes: VoteKeeper<Ctx>,
round_states: BTreeMap<Round, RoundState<Ctx>>,
}
Expand All @@ -50,6 +50,7 @@ where
Vote(SignedVote<Ctx>),
Decide(Round, Ctx::Value),
ScheduleTimeout(Timeout),
NewRound(Round),
}

impl<Ctx> Executor<Ctx>
Expand All @@ -69,7 +70,7 @@ where
private_key: Secret::new(private_key),
address,
validator_set,
round: Round::INITIAL,
round: Round::NIL,
votes,
round_states: BTreeMap::new(),
}
Expand All @@ -88,13 +89,9 @@ where

match round_msg {
RoundMessage::NewRound(round) => {
// TODO: check if we are the proposer

// XXX: Check if there is an existing state?
self.round_states
.insert(round, RoundState::default().new_round(round));

None
assert!(self.round < round);
Some(Message::NewRound(round))
}

RoundMessage::Proposal(proposal) => {
Expand Down Expand Up @@ -137,12 +134,16 @@ where
RoundEvent::NewRound
};

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

self.apply_event(round, event)
}

fn apply_proposal(&mut self, proposal: Ctx::Proposal) -> Option<RoundMessage<Ctx>> {
// TODO: Check for invalid proposal
let event = RoundEvent::Proposal(proposal.clone());

// Check that there is an ongoing round
let Some(round_state) = self.round_states.get(&self.round) else {
Expand Down Expand Up @@ -172,7 +173,9 @@ where
Round::Nil => {
// Is it possible to get +2/3 prevotes before the proposal?
// Do we wait for our own prevote to check the threshold?
self.apply_event(proposal.round(), event)
let round = proposal.round();
let event = RoundEvent::Proposal(proposal);
self.apply_event(round, event)
}
Round::Some(_)
if self.votes.is_threshold_met(
Expand All @@ -181,7 +184,9 @@ where
Threshold::Value(proposal.value().id()),
) =>
{
self.apply_event(proposal.round(), event)
let round = proposal.round();
let event = RoundEvent::Proposal(proposal);
self.apply_event(round, event)
}
_ => None,
}
Expand Down Expand Up @@ -233,8 +238,26 @@ where

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

// Multiplex the event with the round state.
let mux_event = match event {
RoundEvent::PolkaValue(value_id) => match round_state.proposal {
Some(ref proposal) if proposal.value().id() == value_id => {
RoundEvent::ProposalAndPolkaCurrent(proposal.clone())
}
_ => RoundEvent::PolkaAny,
},
RoundEvent::PrecommitValue(value_id) => match round_state.proposal {
Some(ref proposal) if proposal.value().id() == value_id => {
RoundEvent::ProposalAndPrecommitValue(proposal.clone())
}
_ => RoundEvent::PrecommitAny,
},

_ => event,
};

// Apply the event to the round state machine
let transition = round_state.apply_event(&data, event);
let transition = round_state.apply_event(&data, mux_event);

// Update state
self.round_states.insert(round, transition.next_state);
Expand Down
29 changes: 16 additions & 13 deletions Code/round/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,20 @@ pub enum Event<Ctx>
where
Ctx: Context,
{
NewRound, // Start a new round, not as proposer.
NewRoundProposer(Ctx::Value), // Start a new round and propose the Value.
Proposal(Ctx::Proposal), // Receive a proposal with possible polka round.
ProposalInvalid, // Receive an invalid proposal.
PolkaAny, // Receive +2/3 prevotes for anything.
PolkaNil, // Receive +2/3 prevotes for nil.
PolkaValue(ValueId<Ctx>), // Receive +2/3 prevotes for Value.
PrecommitAny, // Receive +2/3 precommits for anything.
PrecommitValue(ValueId<Ctx>), // Receive +2/3 precommits for Value.
SkipRound(Round), // Receive +1/3 votes from a higher round, skip to that round
TimeoutPropose, // Timeout waiting for proposal.
TimeoutPrevote, // Timeout waiting for prevotes.
TimeoutPrecommit, // Timeout waiting for precommits.
NewRound, // Start a new round, not as proposer.L20
NewRoundProposer(Ctx::Value), // Start a new round and propose the Value.L14
Proposal(Ctx::Proposal), // Receive a proposal. L22 + L23 (valid)
ProposalAndPolkaPrevious(Ctx::Proposal), // Recieved a proposal and a polka value from a previous round. L28 + L29 (valid)
ProposalInvalid, // Receive an invalid proposal. L26 + L32 (invalid)
PolkaValue(ValueId<Ctx>), // Receive +2/3 prevotes for valueId. L44
PolkaAny, // Receive +2/3 prevotes for anything. L34
PolkaNil, // Receive +2/3 prevotes for nil. L44
ProposalAndPolkaCurrent(Ctx::Proposal), // Receive +2/3 prevotes for Value in current round. L36
PrecommitAny, // Receive +2/3 precommits for anything. L47
ProposalAndPrecommitValue(Ctx::Proposal), // Receive +2/3 precommits for Value. L49
PrecommitValue(ValueId<Ctx>), // Receive +2/3 precommits for ValueId. L51
SkipRound(Round), // Receive +1/3 messages from a higher round. OneCorrectProcessInHigherRound, L55
TimeoutPropose, // Timeout waiting for proposal. L57
TimeoutPrevote, // Timeout waiting for prevotes. L61
TimeoutPrecommit, // Timeout waiting for precommits. L65
}
17 changes: 1 addition & 16 deletions Code/round/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,25 +76,10 @@ where
..self
}
}

pub fn next_step(self) -> Self {
let step = match self.step {
Step::NewRound => Step::Propose,
Step::Propose => Step::Prevote,
Step::Prevote => Step::Precommit,
_ => self.step,
};

pub fn with_step(self, step: Step) -> Self {
Self { step, ..self }
}

pub fn commit_step(self) -> Self {
Self {
step: Step::Commit,
..self
}
}

pub fn set_locked(self, value: Ctx::Value) -> Self {
Self {
locked: Some(RoundValue::new(value, self.round)),
Expand Down
Loading

0 comments on commit ede3908

Please sign in to comment.