Skip to content

Commit ac3b58a

Browse files
apollo_consensus: move height from SHC to SM
1 parent 5f39c90 commit ac3b58a

File tree

3 files changed

+34
-22
lines changed

3 files changed

+34
-22
lines changed

crates/apollo_consensus/src/single_height_consensus.rs

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,6 @@ impl ShcTask {
133133
/// SHC is not a top level task, it is called directly and returns values (doesn't directly run sub
134134
/// tasks). SHC does have side effects, such as sending messages to the network via the context.
135135
pub(crate) struct SingleHeightConsensus {
136-
height: BlockNumber,
137136
validators: Vec<ValidatorId>,
138137
timeouts: TimeoutsConfig,
139138
state_machine: StateMachine,
@@ -156,9 +155,8 @@ impl SingleHeightConsensus {
156155
// TODO(matan): Use actual weights, not just `len`.
157156
let n_validators =
158157
u64::try_from(validators.len()).expect("Should have way less than u64::MAX validators");
159-
let state_machine = StateMachine::new(id, n_validators, is_observer, quorum_type);
158+
let state_machine = StateMachine::new(height, id, n_validators, is_observer, quorum_type);
160159
Self {
161-
height,
162160
validators,
163161
timeouts,
164162
state_machine,
@@ -179,13 +177,14 @@ impl SingleHeightConsensus {
179177
&mut self,
180178
context: &mut ContextT,
181179
) -> Result<ShcReturn, ConsensusError> {
182-
context.set_height_and_round(self.height, self.state_machine.round()).await;
183-
let leader_fn = |round: Round| -> ValidatorId { context.proposer(self.height, round) };
180+
let height = self.state_machine.height();
181+
context.set_height_and_round(height, self.state_machine.round()).await;
182+
let leader_fn = |round: Round| -> ValidatorId { context.proposer(height, round) };
184183
let events = self.state_machine.start(&leader_fn);
185184
let ret = self.handle_state_machine_events(context, events).await;
186185
// Defensive programming. We don't expect the height and round to have changed from the
187186
// start of this method.
188-
context.set_height_and_round(self.height, self.state_machine.round()).await;
187+
context.set_height_and_round(height, self.state_machine.round()).await;
189188
ret
190189
}
191190

@@ -199,11 +198,12 @@ impl SingleHeightConsensus {
199198
p2p_messages_receiver: mpsc::Receiver<ContextT::ProposalPart>,
200199
) -> Result<ShcReturn, ConsensusError> {
201200
debug!("Received {init:?}");
202-
let proposer_id = context.proposer(self.height, init.round);
203-
if init.height != self.height {
204-
warn!("Invalid proposal height: expected {:?}, got {:?}", self.height, init.height);
201+
let height = self.state_machine.height();
202+
if init.height != height {
203+
warn!("Invalid proposal height: expected {:?}, got {:?}", height, init.height);
205204
return Ok(ShcReturn::Tasks(Vec::new()));
206205
}
206+
let proposer_id = context.proposer(height, init.round);
207207
if init.proposer != proposer_id {
208208
warn!("Invalid proposer: expected {:?}, got {:?}", proposer_id, init.proposer);
209209
return Ok(ShcReturn::Tasks(Vec::new()));
@@ -223,7 +223,7 @@ impl SingleHeightConsensus {
223223
// twice in parallel. This could be caused by a network repeat or a malicious spam attack.
224224
proposal_entry.insert(None);
225225
let block_receiver = context.validate_proposal(init, timeout, p2p_messages_receiver).await;
226-
context.set_height_and_round(self.height, self.state_machine.round()).await;
226+
context.set_height_and_round(height, self.state_machine.round()).await;
227227
Ok(ShcReturn::Tasks(vec![ShcTask::ValidateProposal(init, block_receiver)]))
228228
}
229229

@@ -275,8 +275,8 @@ impl SingleHeightConsensus {
275275
)]))
276276
}
277277
StateMachineEvent::Proposal(proposal_id, round, valid_round) => {
278-
let leader_fn =
279-
|round: Round| -> ValidatorId { context.proposer(self.height, round) };
278+
let height = self.state_machine.height();
279+
let leader_fn = |round: Round| -> ValidatorId { context.proposer(height, round) };
280280
debug!(
281281
proposer = %leader_fn(round),
282282
%round,
@@ -314,14 +314,14 @@ impl SingleHeightConsensus {
314314
"State machine should not progress while awaiting proposal"
315315
);
316316
debug!(%round, proposal_commitment = ?proposal_id, "Built proposal.");
317-
let leader_fn =
318-
|round: Round| -> ValidatorId { context.proposer(self.height, round) };
317+
let height = self.state_machine.height();
318+
let leader_fn = |round: Round| -> ValidatorId { context.proposer(height, round) };
319319
let sm_events = self.state_machine.handle_event(event, &leader_fn);
320320
self.handle_state_machine_events(context, sm_events).await
321321
}
322322
_ => unimplemented!("Unexpected event: {:?}", event),
323323
};
324-
context.set_height_and_round(self.height, self.state_machine.round()).await;
324+
context.set_height_and_round(self.state_machine.height(), self.state_machine.round()).await;
325325
ret
326326
}
327327

@@ -330,7 +330,8 @@ impl SingleHeightConsensus {
330330
context: &mut ContextT,
331331
event: StateMachineEvent,
332332
) -> Result<ShcReturn, ConsensusError> {
333-
let leader_fn = |round: Round| -> ValidatorId { context.proposer(self.height, round) };
333+
let height = self.state_machine.height();
334+
let leader_fn = |round: Round| -> ValidatorId { context.proposer(height, round) };
334335
let sm_events = self.state_machine.handle_event(event, &leader_fn);
335336
self.handle_state_machine_events(context, sm_events).await
336337
}
@@ -376,10 +377,11 @@ impl SingleHeightConsensus {
376377
}
377378
}
378379
info!("Accepting {:?}", vote);
379-
let leader_fn = |round: Round| -> ValidatorId { context.proposer(self.height, round) };
380+
let height = self.state_machine.height();
381+
let leader_fn = |round: Round| -> ValidatorId { context.proposer(height, round) };
380382
let sm_events = self.state_machine.handle_event(sm_vote, &leader_fn);
381383
let ret = self.handle_state_machine_events(context, sm_events).await;
382-
context.set_height_and_round(self.height, self.state_machine.round()).await;
384+
context.set_height_and_round(height, self.state_machine.round()).await;
383385
ret
384386
}
385387

@@ -466,7 +468,7 @@ impl SingleHeightConsensus {
466468
// TODO(Matan): Figure out how to handle failed proposal building. I believe this should be
467469
// handled by applying timeoutPropose when we are the leader.
468470
let init = ProposalInit {
469-
height: self.height,
471+
height: self.state_machine.height(),
470472
round,
471473
proposer: self.state_machine.validator_id(),
472474
valid_round: None,
@@ -506,7 +508,7 @@ impl SingleHeightConsensus {
506508
let old = self.proposals.insert(round, Some(proposal_id));
507509
assert!(old.is_none(), "There should be no proposal for round {round}.");
508510
let init = ProposalInit {
509-
height: self.height,
511+
height: self.state_machine.height(),
510512
round,
511513
proposer: self.state_machine.validator_id(),
512514
valid_round: Some(valid_round),
@@ -541,7 +543,7 @@ impl SingleHeightConsensus {
541543
};
542544
let vote = Vote {
543545
vote_type,
544-
height: self.height.0,
546+
height: self.state_machine.height().0,
545547
round,
546548
proposal_commitment: proposal_id,
547549
voter: self.state_machine.validator_id(),

crates/apollo_consensus/src/state_machine.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ mod state_machine_test;
1010
use std::collections::{HashMap, HashSet, VecDeque};
1111

1212
use serde::{Deserialize, Serialize};
13+
use starknet_api::block::BlockNumber;
1314
use tracing::{debug, info, trace, warn};
1415

1516
use crate::metrics::{
@@ -66,6 +67,7 @@ pub(crate) enum Step {
6667
/// Each height is begun with a call to `start`, with no further calls to it.
6768
#[derive(Serialize, Deserialize)]
6869
pub(crate) struct StateMachine {
70+
height: BlockNumber,
6971
id: ValidatorId,
7072
round: Round,
7173
step: Step,
@@ -92,12 +94,14 @@ pub(crate) struct StateMachine {
9294
impl StateMachine {
9395
/// total_weight - the total voting weight of all validators for this height.
9496
pub(crate) fn new(
97+
height: BlockNumber,
9598
id: ValidatorId,
9699
total_weight: u64,
97100
is_observer: bool,
98101
quorum_type: QuorumType,
99102
) -> Self {
100103
Self {
104+
height,
101105
id,
102106
round: 0,
103107
step: Step::Propose,
@@ -136,6 +140,10 @@ impl StateMachine {
136140
self.id
137141
}
138142

143+
pub(crate) fn height(&self) -> BlockNumber {
144+
self.height
145+
}
146+
139147
/// Starts the state machine, effectively calling `StartRound(0)` from the paper. This is
140148
/// needed to trigger the first leader to propose.
141149
/// See [`GetProposal`](StateMachineEvent::GetProposal)

crates/apollo_consensus/src/state_machine_test.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::collections::VecDeque;
22

33
use apollo_protobuf::consensus::DEFAULT_VALIDATOR_ID;
44
use lazy_static::lazy_static;
5+
use starknet_api::block::BlockNumber;
56
use starknet_types_core::felt::Felt;
67
use test_case::test_case;
78

@@ -17,6 +18,7 @@ lazy_static! {
1718

1819
const PROPOSAL_ID: Option<ProposalCommitment> = Some(ProposalCommitment(Felt::ONE));
1920
const ROUND: Round = 0;
21+
const HEIGHT: BlockNumber = BlockNumber(0);
2022

2123
struct TestWrapper<LeaderFn: Fn(Round) -> ValidatorId> {
2224
state_machine: StateMachine,
@@ -33,7 +35,7 @@ impl<LeaderFn: Fn(Round) -> ValidatorId> TestWrapper<LeaderFn> {
3335
quorum_type: QuorumType,
3436
) -> Self {
3537
Self {
36-
state_machine: StateMachine::new(id, total_weight, is_observer, quorum_type),
38+
state_machine: StateMachine::new(HEIGHT, id, total_weight, is_observer, quorum_type),
3739
leader_fn,
3840
events: VecDeque::new(),
3941
}

0 commit comments

Comments
 (0)