Skip to main content

hotmint_storage/
block_store.rs

1use hotmint_consensus::store::BlockStore;
2use hotmint_types::{Block, BlockHash, Height, QuorumCertificate};
3use tracing::debug;
4use vsdb::MapxOrd;
5
6/// Persistent block store backed by vsdb
7pub struct VsdbBlockStore {
8    by_hash: MapxOrd<[u8; 32], Block>,
9    by_height: MapxOrd<u64, [u8; 32]>,
10    commit_qcs: MapxOrd<u64, QuorumCertificate>,
11}
12
13impl VsdbBlockStore {
14    pub fn new() -> Self {
15        let mut store = Self {
16            by_hash: MapxOrd::new(),
17            by_height: MapxOrd::new(),
18            commit_qcs: MapxOrd::new(),
19        };
20        let genesis = Block::genesis();
21        store.put_block(genesis);
22        store
23    }
24
25    pub fn contains(&self, hash: &BlockHash) -> bool {
26        self.by_hash.contains_key(&hash.0)
27    }
28
29    pub fn flush(&self) {
30        vsdb::vsdb_flush();
31    }
32}
33
34impl Default for VsdbBlockStore {
35    fn default() -> Self {
36        Self::new()
37    }
38}
39
40impl BlockStore for VsdbBlockStore {
41    fn put_block(&mut self, block: Block) {
42        debug!(height = block.height.as_u64(), hash = %block.hash, "storing block to vsdb");
43        self.by_height.insert(&block.height.as_u64(), &block.hash.0);
44        self.by_hash.insert(&block.hash.0, &block);
45    }
46
47    fn get_block(&self, hash: &BlockHash) -> Option<Block> {
48        self.by_hash.get(&hash.0)
49    }
50
51    fn get_block_by_height(&self, h: Height) -> Option<Block> {
52        self.by_height
53            .get(&h.as_u64())
54            .and_then(|hash_bytes| self.by_hash.get(&hash_bytes))
55    }
56
57    fn get_blocks_in_range(&self, from: Height, to: Height) -> Vec<Block> {
58        self.by_height
59            .range(from.as_u64()..=to.as_u64())
60            .filter_map(|(_, hash_bytes)| self.by_hash.get(&hash_bytes))
61            .collect()
62    }
63
64    fn tip_height(&self) -> Height {
65        self.by_height
66            .last()
67            .map(|(h, _)| Height(h))
68            .unwrap_or(Height::GENESIS)
69    }
70
71    fn put_commit_qc(&mut self, height: Height, qc: QuorumCertificate) {
72        self.commit_qcs.insert(&height.as_u64(), &qc);
73    }
74
75    fn get_commit_qc(&self, height: Height) -> Option<QuorumCertificate> {
76        self.commit_qcs.get(&height.as_u64())
77    }
78
79    fn flush(&self) {
80        vsdb::vsdb_flush();
81    }
82}