tycho_core/block_strider/
state.rs

1use std::sync::Mutex;
2
3use tycho_block_util::block::ShardHeights;
4use tycho_types::models::BlockId;
5
6use crate::storage::CoreStorage;
7
8#[derive(Debug, Clone, Copy)]
9pub struct CommitMasterBlock<'a> {
10    pub block_id: &'a BlockId,
11    pub is_key_block: bool,
12    pub shard_heights: &'a ShardHeights,
13}
14
15#[derive(Debug, Clone, Copy)]
16pub struct CommitShardBlock<'a> {
17    pub block_id: &'a BlockId,
18}
19
20pub trait BlockStriderState: Send + Sync + 'static {
21    fn load_last_mc_block_id(&self) -> BlockId;
22
23    fn is_committed(&self, block_id: &BlockId) -> bool;
24
25    fn commit_master(&self, ctx: CommitMasterBlock<'_>);
26    fn commit_shard(&self, ctx: CommitShardBlock<'_>);
27}
28
29pub struct PersistentBlockStriderState {
30    zerostate_id: BlockId,
31    storage: CoreStorage,
32}
33
34impl PersistentBlockStriderState {
35    pub fn new(zerostate_id: BlockId, storage: CoreStorage) -> Self {
36        Self {
37            zerostate_id,
38            storage,
39        }
40    }
41}
42
43impl BlockStriderState for PersistentBlockStriderState {
44    fn load_last_mc_block_id(&self) -> BlockId {
45        match self.storage.node_state().load_last_mc_block_id() {
46            Some(block_id) => block_id,
47            None => self.zerostate_id,
48        }
49    }
50
51    fn is_committed(&self, block_id: &BlockId) -> bool {
52        if block_id.is_masterchain() {
53            let last_mc = self.load_last_mc_block_id();
54            last_mc.seqno >= block_id.seqno
55        } else {
56            match self.storage.block_handle_storage().load_handle(block_id) {
57                Some(handle) => handle.is_committed(),
58                None => false,
59            }
60        }
61    }
62
63    fn commit_master(&self, ctx: CommitMasterBlock<'_>) {
64        assert!(ctx.block_id.is_masterchain());
65        self.storage
66            .node_state()
67            .store_last_mc_block_id(ctx.block_id);
68    }
69
70    fn commit_shard(&self, ctx: CommitShardBlock<'_>) {
71        assert!(!ctx.block_id.is_masterchain());
72
73        let handles = self.storage.block_handle_storage();
74        if let Some(handle) = handles.load_handle(ctx.block_id) {
75            handles.set_block_committed(&handle);
76        } else {
77            tracing::warn!(
78                block_id = %ctx.block_id,
79                "committing shard block without a block handle",
80            );
81        }
82    }
83}
84
85pub struct TempBlockStriderState {
86    top_blocks: Mutex<(BlockId, ShardHeights)>,
87}
88
89impl TempBlockStriderState {
90    pub fn new(mc_block_id: BlockId, shard_heights: ShardHeights) -> Self {
91        Self {
92            top_blocks: Mutex::new((mc_block_id, shard_heights)),
93        }
94    }
95}
96
97impl BlockStriderState for TempBlockStriderState {
98    fn load_last_mc_block_id(&self) -> BlockId {
99        self.top_blocks.lock().unwrap().0
100    }
101
102    fn is_committed(&self, block_id: &BlockId) -> bool {
103        let commited = self.top_blocks.lock().unwrap();
104        let (mc_block_id, shard_heights) = &*commited;
105        if block_id.is_masterchain() {
106            block_id.seqno <= mc_block_id.seqno
107        } else {
108            shard_heights.contains_ext(block_id, |top_block, seqno| seqno <= top_block)
109        }
110    }
111
112    fn commit_master(&self, ctx: CommitMasterBlock<'_>) {
113        assert!(ctx.block_id.is_masterchain());
114        let mut commited = self.top_blocks.lock().unwrap();
115        if commited.0.seqno < ctx.block_id.seqno {
116            *commited = (*ctx.block_id, ctx.shard_heights.clone());
117        }
118    }
119
120    fn commit_shard(&self, ctx: CommitShardBlock<'_>) {
121        assert!(!ctx.block_id.is_masterchain());
122        // TODO: Update shard height
123    }
124}