1#![feature(const_block_items)]
4#![expect(incomplete_features, reason = "generic_const_exprs")]
5#![feature(generic_const_exprs)]
8
9use ab_aligned_buffer::SharedAlignedBuffer;
10use ab_core_primitives::address::Address;
11use ab_core_primitives::block::owned::{GenericOwnedBlock, OwnedBeaconChainBlock};
12use ab_core_primitives::block::{BlockNumber, BlockRoot};
13use ab_core_primitives::segments::{
14 LocalSegmentIndex, SegmentHeader, SegmentIndex, SegmentRoot, SuperSegmentHeader,
15 SuperSegmentIndex,
16};
17use ab_core_primitives::shard::ShardIndex;
18use ab_merkle_tree::mmr::MerkleMountainRange;
19use rclite::Arc;
20use std::io;
21use std::sync::Arc as StdArc;
22
23#[expect(clippy::assertions_on_constants, reason = "Intentional documentation")]
26#[expect(clippy::eq_op, reason = "Intentional documentation")]
27const {
28 assert!(u32::MAX == 4294967295);
29}
30
31pub type BlockMerkleMountainRange = MerkleMountainRange<4294967295>;
38
39#[derive(Debug, Clone)]
41pub struct ContractSlotState {
42 pub owner: Address,
44 pub contract: Address,
46 pub contents: SharedAlignedBuffer,
48}
49
50#[derive(Debug, Clone)]
52pub struct BlockDetails {
53 pub mmr_with_block: Arc<BlockMerkleMountainRange>,
55 pub system_contract_states: StdArc<[ContractSlotState]>,
57}
58
59#[derive(Debug, Clone)]
62pub enum BlockOrigin {
63 LocalBlockBuilder {
66 block_details: BlockDetails,
68 },
69 Sync,
71 Broadcast,
73}
74
75#[derive(Debug, Clone, Copy, PartialEq, Eq)]
77pub struct ShardSegmentRoot {
78 pub shard_index: ShardIndex,
80 pub segment_index: LocalSegmentIndex,
82 pub segment_root: SegmentRoot,
84}
85
86#[derive(Debug, thiserror::Error)]
88pub enum ReadBlockError {
89 #[error("Unknown block root")]
91 UnknownBlockRoot,
92 #[error("Failed to decode the block")]
94 FailedToDecode,
95 #[error("Storage item read error")]
97 StorageItemReadError {
98 #[from]
100 error: io::Error,
101 },
102}
103
104#[derive(Debug, thiserror::Error)]
106pub enum PersistBlockError {
107 #[error("Missing parent")]
109 MissingParent,
110 #[error("Block is outside the acceptable range")]
112 OutsideAcceptableRange,
113 #[error("Storage item write error")]
115 StorageItemWriteError {
116 #[from]
118 error: io::Error,
119 },
120}
121
122#[derive(Debug, thiserror::Error)]
124pub enum PersistSegmentHeadersError {
125 #[error(
127 "Segment index {local_segment_index} must strictly follow last segment index \
128 {last_local_segment_index}, can't store segment header"
129 )]
130 MustFollowLastSegmentIndex {
131 local_segment_index: LocalSegmentIndex,
133 last_local_segment_index: LocalSegmentIndex,
135 },
136 #[error("First segment index must be zero, found {local_segment_index}")]
138 FirstSegmentIndexZero {
139 local_segment_index: LocalSegmentIndex,
141 },
142 #[error("Storage item write error")]
144 StorageItemWriteError {
145 #[from]
147 error: io::Error,
148 },
149}
150
151#[derive(Debug, thiserror::Error)]
153pub enum ShardSegmentRootsError {
154 #[error("Block {block_number} is missing")]
156 BlockMissing {
157 block_number: BlockNumber,
159 },
160}
161
162#[derive(Debug, thiserror::Error)]
164pub enum PersistSuperSegmentHeadersError {
165 #[error(
168 "Super segment index {super_segment_index} must strictly follow last super segment index \
169 {last_super_segment_index}, can't store super segment header"
170 )]
171 MustFollowLastSegmentIndex {
172 super_segment_index: SuperSegmentIndex,
174 last_super_segment_index: SuperSegmentIndex,
176 },
177 #[error("First super segment index must be zero, found {super_segment_index}")]
179 FirstSegmentIndexZero {
180 super_segment_index: SuperSegmentIndex,
182 },
183 #[error("Storage item write error")]
185 StorageItemWriteError {
186 #[from]
188 error: io::Error,
189 },
190}
191
192pub trait ChainInfo<Block>: Clone + Send + Sync + 'static
204where
205 Block: GenericOwnedBlock,
206{
207 fn best_root(&self) -> BlockRoot;
209
210 fn best_header(&self) -> Block::Header;
220
221 fn best_header_with_details(&self) -> (Block::Header, BlockDetails);
223
224 fn ancestor_header(
226 &self,
227 ancestor_block_number: BlockNumber,
228 descendant_block_root: &BlockRoot,
229 ) -> Option<Block::Header>;
230
231 fn header(&self, block_root: &BlockRoot) -> Option<Block::Header>;
233
234 fn header_with_details(&self, block_root: &BlockRoot) -> Option<(Block::Header, BlockDetails)>;
236
237 fn block(
238 &self,
239 block_root: &BlockRoot,
240 ) -> impl Future<Output = Result<Block, ReadBlockError>> + Send;
241
242 fn last_segment_header(&self) -> Option<SegmentHeader>;
244
245 fn get_segment_header(&self, segment_index: LocalSegmentIndex) -> Option<SegmentHeader>;
247
248 fn segment_headers_for_block(&self, block_number: BlockNumber) -> Vec<SegmentHeader>;
250}
251
252pub trait ChainInfoWrite<Block>: ChainInfo<Block>
254where
255 Block: GenericOwnedBlock,
256{
257 fn persist_block(
259 &self,
260 block: Block,
261 block_details: BlockDetails,
262 ) -> impl Future<Output = Result<(), PersistBlockError>> + Send;
263
264 fn persist_segment_headers(
268 &self,
269 segment_headers: Vec<SegmentHeader>,
270 ) -> impl Future<Output = Result<(), PersistSegmentHeadersError>> + Send;
271}
272
273pub trait BeaconChainInfo: ChainInfo<OwnedBeaconChainBlock> {
275 fn shard_segment_roots(
280 &self,
281 block_number: BlockNumber,
282 ) -> Result<StdArc<[ShardSegmentRoot]>, ShardSegmentRootsError>;
283
284 fn last_super_segment_header(&self) -> Option<SuperSegmentHeader>;
286
287 fn previous_super_segment_header(
292 &self,
293 target_block_number: BlockNumber,
294 ) -> Option<SuperSegmentHeader>;
295
296 fn get_super_segment_header(
298 &self,
299 super_segment_index: SuperSegmentIndex,
300 ) -> Option<SuperSegmentHeader>;
301
302 fn get_super_segment_header_for_segment_index(
304 &self,
305 segment_index: SegmentIndex,
306 ) -> Option<SuperSegmentHeader>;
307}
308
309pub trait BeaconChainInfoWrite: BeaconChainInfo + ChainInfoWrite<OwnedBeaconChainBlock> {
311 #[must_use]
315 fn persist_super_segment_header(
316 &self,
317 super_segment_header: SuperSegmentHeader,
318 ) -> impl Future<Output = Result<bool, PersistSuperSegmentHeadersError>> + Send;
319
320 fn persist_super_segment_headers(
324 &self,
325 super_segment_headers: Vec<SuperSegmentHeader>,
326 ) -> impl Future<Output = Result<(), PersistSuperSegmentHeadersError>> + Send;
327}
328
329pub trait ChainSyncStatus: Clone + Send + Sync + 'static {
331 fn target_block_number(&self) -> BlockNumber;
335
336 fn is_syncing(&self) -> bool;
338
339 fn is_offline(&self) -> bool;
341}