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, SegmentRoot, SuperSegmentHeader, SuperSegmentIndex,
15};
16use ab_core_primitives::shard::ShardIndex;
17use ab_merkle_tree::mmr::MerkleMountainRange;
18use rclite::Arc;
19use std::io;
20use std::sync::Arc as StdArc;
21
22#[expect(clippy::assertions_on_constants, reason = "Intentional documentation")]
25#[expect(clippy::eq_op, reason = "Intentional documentation")]
26const {
27 assert!(u32::MAX == 4294967295);
28}
29
30pub type BlockMerkleMountainRange = MerkleMountainRange<4294967295>;
37
38#[derive(Debug, Clone)]
40pub struct ContractSlotState {
41 pub owner: Address,
43 pub contract: Address,
45 pub contents: SharedAlignedBuffer,
47}
48
49#[derive(Debug, Clone)]
51pub struct BlockDetails {
52 pub mmr_with_block: Arc<BlockMerkleMountainRange>,
54 pub system_contract_states: StdArc<[ContractSlotState]>,
56}
57
58#[derive(Debug, Clone)]
61pub enum BlockOrigin {
62 LocalBlockBuilder {
65 block_details: BlockDetails,
67 },
68 Sync,
70 Broadcast,
72}
73
74#[derive(Debug, Clone, Copy, PartialEq, Eq)]
76pub struct ShardSegmentRoot {
77 pub shard_index: ShardIndex,
79 pub segment_index: LocalSegmentIndex,
81 pub segment_root: SegmentRoot,
83}
84
85#[derive(Debug, thiserror::Error)]
87pub enum ReadBlockError {
88 #[error("Unknown block root")]
90 UnknownBlockRoot,
91 #[error("Failed to decode the block")]
93 FailedToDecode,
94 #[error("Storage item read error")]
96 StorageItemReadError {
97 #[from]
99 error: io::Error,
100 },
101}
102
103#[derive(Debug, thiserror::Error)]
105pub enum PersistBlockError {
106 #[error("Missing parent")]
108 MissingParent,
109 #[error("Block is outside the acceptable range")]
111 OutsideAcceptableRange,
112 #[error("Storage item write error")]
114 StorageItemWriteError {
115 #[from]
117 error: io::Error,
118 },
119}
120
121#[derive(Debug, thiserror::Error)]
123pub enum PersistSegmentHeadersError {
124 #[error(
126 "Segment index {local_segment_index} must strictly follow last segment index \
127 {last_local_segment_index}, can't store segment header"
128 )]
129 MustFollowLastSegmentIndex {
130 local_segment_index: LocalSegmentIndex,
132 last_local_segment_index: LocalSegmentIndex,
134 },
135 #[error("First segment index must be zero, found {local_segment_index}")]
137 FirstSegmentIndexZero {
138 local_segment_index: LocalSegmentIndex,
140 },
141 #[error("Storage item write error")]
143 StorageItemWriteError {
144 #[from]
146 error: io::Error,
147 },
148}
149
150#[derive(Debug, thiserror::Error)]
152pub enum ShardSegmentRootsError {
153 #[error("Block {block_number} is missing")]
155 BlockMissing {
156 block_number: BlockNumber,
158 },
159}
160
161#[derive(Debug, thiserror::Error)]
163pub enum PersistSuperSegmentHeadersError {
164 #[error(
167 "Super segment index {super_segment_index} must strictly follow last super segment index \
168 {last_super_segment_index}, can't store super segment header"
169 )]
170 MustFollowLastSegmentIndex {
171 super_segment_index: SuperSegmentIndex,
173 last_super_segment_index: SuperSegmentIndex,
175 },
176 #[error("First super segment index must be zero, found {super_segment_index}")]
178 FirstSegmentIndexZero {
179 super_segment_index: SuperSegmentIndex,
181 },
182 #[error("Storage item write error")]
184 StorageItemWriteError {
185 #[from]
187 error: io::Error,
188 },
189}
190
191pub trait ChainInfo<Block>: Clone + Send + Sync + 'static
203where
204 Block: GenericOwnedBlock,
205{
206 fn best_root(&self) -> BlockRoot;
208
209 fn best_header(&self) -> Block::Header;
219
220 fn best_header_with_details(&self) -> (Block::Header, BlockDetails);
222
223 fn ancestor_header(
225 &self,
226 ancestor_block_number: BlockNumber,
227 descendant_block_root: &BlockRoot,
228 ) -> Option<Block::Header>;
229
230 fn header(&self, block_root: &BlockRoot) -> Option<Block::Header>;
232
233 fn header_with_details(&self, block_root: &BlockRoot) -> Option<(Block::Header, BlockDetails)>;
235
236 fn block(
237 &self,
238 block_root: &BlockRoot,
239 ) -> impl Future<Output = Result<Block, ReadBlockError>> + Send;
240
241 fn last_segment_header(&self) -> Option<SegmentHeader>;
243
244 fn get_segment_header(&self, segment_index: LocalSegmentIndex) -> Option<SegmentHeader>;
246
247 fn segment_headers_for_block(&self, block_number: BlockNumber) -> Vec<SegmentHeader>;
249}
250
251pub trait ChainInfoWrite<Block>: ChainInfo<Block>
253where
254 Block: GenericOwnedBlock,
255{
256 fn persist_block(
258 &self,
259 block: Block,
260 block_details: BlockDetails,
261 ) -> impl Future<Output = Result<(), PersistBlockError>> + Send;
262
263 fn persist_segment_headers(
267 &self,
268 segment_headers: Vec<SegmentHeader>,
269 ) -> impl Future<Output = Result<(), PersistSegmentHeadersError>> + Send;
270}
271
272pub trait BeaconChainInfo: ChainInfo<OwnedBeaconChainBlock> {
274 fn shard_segment_roots(
279 &self,
280 block_number: BlockNumber,
281 ) -> Result<StdArc<[ShardSegmentRoot]>, ShardSegmentRootsError>;
282
283 fn last_super_segment_header(&self) -> Option<SuperSegmentHeader>;
285
286 fn previous_super_segment_header(
291 &self,
292 target_block_number: BlockNumber,
293 ) -> Option<SuperSegmentHeader>;
294
295 fn get_super_segment_header(
297 &self,
298 super_segment_index: SuperSegmentIndex,
299 ) -> Option<SuperSegmentHeader>;
300}
301
302pub trait BeaconChainInfoWrite: BeaconChainInfo + ChainInfoWrite<OwnedBeaconChainBlock> {
304 #[must_use]
308 fn persist_super_segment_header(
309 &self,
310 super_segment_header: SuperSegmentHeader,
311 ) -> impl Future<Output = Result<bool, PersistSuperSegmentHeadersError>> + Send;
312
313 fn persist_super_segment_headers(
317 &self,
318 super_segment_headers: Vec<SuperSegmentHeader>,
319 ) -> impl Future<Output = Result<(), PersistSuperSegmentHeadersError>> + Send;
320}
321
322pub trait ChainSyncStatus: Clone + Send + Sync + 'static {
324 fn target_block_number(&self) -> BlockNumber;
328
329 fn is_syncing(&self) -> bool;
331
332 fn is_offline(&self) -> bool;
334}