Skip to main content

hotmint_consensus/
state.rs

1use hotmint_types::{
2    DoubleCertificate, Height, QuorumCertificate, ValidatorId, ValidatorSet, ViewNumber,
3};
4
5/// Role of the validator in the current view
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum ViewRole {
8    Leader,
9    Replica,
10}
11
12/// Step within a view (state machine progression)
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub enum ViewStep {
15    Entered,
16    WaitingForStatus,
17    Proposed,
18    WaitingForProposal,
19    Voted,
20    CollectingVotes,
21    Prepared,
22    SentVote2,
23    Done,
24}
25
26/// Mutable consensus state for a single validator
27pub struct ConsensusState {
28    pub validator_id: ValidatorId,
29    pub validator_set: ValidatorSet,
30    pub current_view: ViewNumber,
31    pub role: ViewRole,
32    pub step: ViewStep,
33    pub locked_qc: Option<QuorumCertificate>,
34    pub highest_double_cert: Option<DoubleCertificate>,
35    pub highest_qc: Option<QuorumCertificate>,
36    pub last_committed_height: Height,
37}
38
39impl ConsensusState {
40    pub fn new(validator_id: ValidatorId, validator_set: ValidatorSet) -> Self {
41        Self {
42            validator_id,
43            validator_set,
44            current_view: ViewNumber::GENESIS,
45            role: ViewRole::Replica,
46            step: ViewStep::Entered,
47            locked_qc: None,
48            highest_double_cert: None,
49            highest_qc: None,
50            last_committed_height: Height::GENESIS,
51        }
52    }
53
54    pub fn is_leader(&self) -> bool {
55        self.role == ViewRole::Leader
56    }
57
58    pub fn update_highest_qc(&mut self, qc: &QuorumCertificate) {
59        let dominated = self.highest_qc.as_ref().is_none_or(|h| qc.view > h.view);
60        if dominated {
61            self.highest_qc = Some(qc.clone());
62        }
63    }
64
65    pub fn update_locked_qc(&mut self, qc: &QuorumCertificate) {
66        let dominated = self.locked_qc.as_ref().is_none_or(|h| qc.view > h.view);
67        if dominated {
68            self.locked_qc = Some(qc.clone());
69        }
70    }
71}