1#![feature(const_convert, const_trait_impl)]
4
5use ab_aligned_buffer::SharedAlignedBuffer;
6use ab_core_primitives::address::Address;
7use ab_core_primitives::block::owned::{GenericOwnedBlock, OwnedBeaconChainBlock};
8use ab_core_primitives::block::{BlockNumber, BlockRoot};
9use ab_core_primitives::segments::{
10 LocalSegmentIndex, SegmentHeader, SegmentIndex, SegmentRoot, SuperSegmentHeader,
11 SuperSegmentIndex,
12};
13use ab_core_primitives::shard::ShardIndex;
14use ab_merkle_tree::mmr::MerkleMountainRange;
15use rclite::Arc;
16use std::io;
17use std::sync::Arc as StdArc;
18
19const MAX_U32_AS_U64: u64 = u64::from(u32::MAX);
20pub type BlockMerkleMountainRange = MerkleMountainRange<MAX_U32_AS_U64>;
25
26#[derive(Debug, Clone)]
28pub struct ContractSlotState {
29 pub owner: Address,
31 pub contract: Address,
33 pub contents: SharedAlignedBuffer,
35}
36
37#[derive(Debug, Clone)]
39pub struct BlockDetails {
40 pub mmr_with_block: Arc<BlockMerkleMountainRange>,
42 pub system_contract_states: StdArc<[ContractSlotState]>,
44}
45
46#[derive(Debug, Clone)]
49pub enum BlockOrigin {
50 LocalBlockBuilder {
53 block_details: BlockDetails,
55 },
56 Sync,
58 Broadcast,
60}
61
62#[derive(Debug, Clone, Copy, PartialEq, Eq)]
64pub struct ShardSegmentRoot {
65 pub shard_index: ShardIndex,
67 pub segment_index: LocalSegmentIndex,
69 pub segment_root: SegmentRoot,
71}
72
73#[derive(Debug, thiserror::Error)]
75pub enum ReadBlockError {
76 #[error("Unknown block root")]
78 UnknownBlockRoot,
79 #[error("Failed to decode the block")]
81 FailedToDecode,
82 #[error("Storage item read error")]
84 StorageItemReadError {
85 #[from]
87 error: io::Error,
88 },
89}
90
91#[derive(Debug, thiserror::Error)]
93pub enum PersistBlockError {
94 #[error("Missing parent")]
96 MissingParent,
97 #[error("Block is outside the acceptable range")]
99 OutsideAcceptableRange,
100 #[error("Storage item write error")]
102 StorageItemWriteError {
103 #[from]
105 error: io::Error,
106 },
107}
108
109#[derive(Debug, thiserror::Error)]
111pub enum PersistSegmentHeadersError {
112 #[error(
114 "Segment index {local_segment_index} must strictly follow last segment index \
115 {last_local_segment_index}, can't store segment header"
116 )]
117 MustFollowLastSegmentIndex {
118 local_segment_index: LocalSegmentIndex,
120 last_local_segment_index: LocalSegmentIndex,
122 },
123 #[error("First segment index must be zero, found {local_segment_index}")]
125 FirstSegmentIndexZero {
126 local_segment_index: LocalSegmentIndex,
128 },
129 #[error("Storage item write error")]
131 StorageItemWriteError {
132 #[from]
134 error: io::Error,
135 },
136}
137
138#[derive(Debug, thiserror::Error)]
140pub enum ShardSegmentRootsError {
141 #[error("Block {block_number} is missing")]
143 BlockMissing {
144 block_number: BlockNumber,
146 },
147}
148
149#[derive(Debug, thiserror::Error)]
151pub enum PersistSuperSegmentHeadersError {
152 #[error(
155 "Super segment index {super_segment_index} must strictly follow last super segment index \
156 {last_super_segment_index}, can't store super segment header"
157 )]
158 MustFollowLastSegmentIndex {
159 super_segment_index: SuperSegmentIndex,
161 last_super_segment_index: SuperSegmentIndex,
163 },
164 #[error("First super segment index must be zero, found {super_segment_index}")]
166 FirstSegmentIndexZero {
167 super_segment_index: SuperSegmentIndex,
169 },
170 #[error("Storage item write error")]
172 StorageItemWriteError {
173 #[from]
175 error: io::Error,
176 },
177}
178
179pub trait ChainInfo<Block>: Clone + Send + Sync + 'static
191where
192 Block: GenericOwnedBlock,
193{
194 fn best_root(&self) -> BlockRoot;
196
197 fn best_header(&self) -> Block::Header;
207
208 fn best_header_with_details(&self) -> (Block::Header, BlockDetails);
210
211 fn ancestor_header(
213 &self,
214 ancestor_block_number: BlockNumber,
215 descendant_block_root: &BlockRoot,
216 ) -> Option<Block::Header>;
217
218 fn header(&self, block_root: &BlockRoot) -> Option<Block::Header>;
220
221 fn header_with_details(&self, block_root: &BlockRoot) -> Option<(Block::Header, BlockDetails)>;
223
224 fn block(
225 &self,
226 block_root: &BlockRoot,
227 ) -> impl Future<Output = Result<Block, ReadBlockError>> + Send;
228
229 fn last_segment_header(&self) -> Option<SegmentHeader>;
231
232 fn get_segment_header(&self, segment_index: LocalSegmentIndex) -> Option<SegmentHeader>;
234
235 fn segment_headers_for_block(&self, block_number: BlockNumber) -> Vec<SegmentHeader>;
237}
238
239pub trait ChainInfoWrite<Block>: ChainInfo<Block>
241where
242 Block: GenericOwnedBlock,
243{
244 fn persist_block(
246 &self,
247 block: Block,
248 block_details: BlockDetails,
249 ) -> impl Future<Output = Result<(), PersistBlockError>> + Send;
250
251 fn persist_segment_headers(
255 &self,
256 segment_headers: Vec<SegmentHeader>,
257 ) -> impl Future<Output = Result<(), PersistSegmentHeadersError>> + Send;
258}
259
260pub trait BeaconChainInfo: ChainInfo<OwnedBeaconChainBlock> {
262 fn shard_segment_roots(
267 &self,
268 block_number: BlockNumber,
269 ) -> Result<StdArc<[ShardSegmentRoot]>, ShardSegmentRootsError>;
270
271 fn last_super_segment_header(&self) -> Option<SuperSegmentHeader>;
273
274 fn previous_super_segment_header(
279 &self,
280 block_number: BlockNumber,
281 ) -> Option<SuperSegmentHeader>;
282
283 fn get_super_segment_header(
285 &self,
286 super_segment_index: SuperSegmentIndex,
287 ) -> Option<SuperSegmentHeader>;
288
289 fn get_super_segment_header_for_segment_index(
291 &self,
292 segment_index: SegmentIndex,
293 ) -> Option<SuperSegmentHeader>;
294}
295
296pub trait BeaconChainInfoWrite: BeaconChainInfo + ChainInfoWrite<OwnedBeaconChainBlock> {
298 #[must_use]
302 fn persist_super_segment_header(
303 &self,
304 super_segment_header: SuperSegmentHeader,
305 ) -> impl Future<Output = Result<bool, PersistSuperSegmentHeadersError>> + Send;
306
307 fn persist_super_segment_headers(
311 &self,
312 super_segment_headers: Vec<SuperSegmentHeader>,
313 ) -> impl Future<Output = Result<(), PersistSuperSegmentHeadersError>> + Send;
314}
315
316pub trait ChainSyncStatus: Clone + Send + Sync + 'static {
318 fn target_block_number(&self) -> BlockNumber;
322
323 fn is_syncing(&self) -> bool;
325
326 fn is_offline(&self) -> bool;
328}