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