Skip to main content

hotmint_storage/
consensus_state.rs

1use hotmint_types::{Height, QuorumCertificate, ViewNumber};
2use serde::{Deserialize, Serialize};
3use vsdb::MapxOrd;
4
5/// Key constants for the consensus state KV store
6const KEY_CURRENT_VIEW: u64 = 1;
7const KEY_LOCKED_QC: u64 = 2;
8const KEY_HIGHEST_QC: u64 = 3;
9const KEY_LAST_COMMITTED_HEIGHT: u64 = 4;
10
11/// Persisted consensus state fields (serialized as a single blob per key)
12#[derive(Debug, Clone, Serialize, Deserialize)]
13enum StateValue {
14    View(ViewNumber),
15    Height(Height),
16    Qc(QuorumCertificate),
17}
18
19/// Persistent consensus state store backed by vsdb
20pub struct PersistentConsensusState {
21    store: MapxOrd<u64, StateValue>,
22}
23
24impl PersistentConsensusState {
25    pub fn new() -> Self {
26        Self {
27            store: MapxOrd::new(),
28        }
29    }
30
31    pub fn save_current_view(&mut self, view: ViewNumber) {
32        self.store
33            .insert(&KEY_CURRENT_VIEW, &StateValue::View(view));
34    }
35
36    pub fn load_current_view(&self) -> Option<ViewNumber> {
37        self.store.get(&KEY_CURRENT_VIEW).and_then(|v| match v {
38            StateValue::View(view) => Some(view),
39            _ => None,
40        })
41    }
42
43    pub fn save_locked_qc(&mut self, qc: &QuorumCertificate) {
44        self.store
45            .insert(&KEY_LOCKED_QC, &StateValue::Qc(qc.clone()));
46    }
47
48    pub fn load_locked_qc(&self) -> Option<QuorumCertificate> {
49        self.store.get(&KEY_LOCKED_QC).and_then(|v| match v {
50            StateValue::Qc(qc) => Some(qc),
51            _ => None,
52        })
53    }
54
55    pub fn save_highest_qc(&mut self, qc: &QuorumCertificate) {
56        self.store
57            .insert(&KEY_HIGHEST_QC, &StateValue::Qc(qc.clone()));
58    }
59
60    pub fn load_highest_qc(&self) -> Option<QuorumCertificate> {
61        self.store.get(&KEY_HIGHEST_QC).and_then(|v| match v {
62            StateValue::Qc(qc) => Some(qc),
63            _ => None,
64        })
65    }
66
67    pub fn save_last_committed_height(&mut self, height: Height) {
68        self.store
69            .insert(&KEY_LAST_COMMITTED_HEIGHT, &StateValue::Height(height));
70    }
71
72    pub fn load_last_committed_height(&self) -> Option<Height> {
73        self.store
74            .get(&KEY_LAST_COMMITTED_HEIGHT)
75            .and_then(|v| match v {
76                StateValue::Height(h) => Some(h),
77                _ => None,
78            })
79    }
80
81    pub fn flush(&self) {
82        vsdb::vsdb_flush();
83    }
84}
85
86impl Default for PersistentConsensusState {
87    fn default() -> Self {
88        Self::new()
89    }
90}