tycho_core/block_strider/
state.rs1use 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 }
124}