Skip to content

Commit

Permalink
code: Events and SM improvements (#19)
Browse files Browse the repository at this point in the history
* Event name changes and other small fixes

* Add event multiplexing in executor and fix tests

* Fix formatting

* Fix executor handling of new round

* Fix executor initialization

* Add test step for NewRound, fix precommit for nil quorum to emit PrecommitAny

* Review comments

* Remove dead code

---------

Co-authored-by: Anca Zamfir <[email protected]>
  • Loading branch information
romac and ancazamfir committed Nov 8, 2023
1 parent 709798b commit 643a84e
Show file tree
Hide file tree
Showing 9 changed files with 149 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
40 changes: 30 additions & 10 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 @@ -64,7 +65,7 @@ where
) -> Self {
let votes = VoteKeeper::new(
height.clone(),
Round::INITIAL,
Round::NIL,
validator_set.total_voting_power(),
);

Expand All @@ -73,7 +74,7 @@ where
private_key: Secret::new(private_key),
address,
validator_set,
round: Round::INITIAL,
round: Round::NIL,
votes,
round_states: BTreeMap::new(),
}
Expand All @@ -92,13 +93,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 @@ -141,6 +138,11 @@ 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)
}

Expand Down Expand Up @@ -239,8 +241,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.
RoundSkip, // Receive +1/3 votes from a higher 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
RoundSkip, // 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 643a84e

Please sign in to comment.