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