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 std::io;
16use triomphe::Arc;
17
18const MAX_U32_AS_U64: u64 = u64::from(u32::MAX);
19pub type BlockMerkleMountainRange = MerkleMountainRange<MAX_U32_AS_U64>;
24
25#[derive(Debug, Clone)]
27pub struct ContractSlotState {
28 pub owner: Address,
30 pub contract: Address,
32 pub contents: SharedAlignedBuffer,
34}
35
36#[derive(Debug, Clone)]
38pub struct BlockDetails {
39 pub mmr_with_block: Arc<BlockMerkleMountainRange>,
41 pub system_contract_states: Arc<[ContractSlotState]>,
43}
44
45#[derive(Debug, Clone)]
48pub enum BlockOrigin {
49 LocalBlockBuilder {
52 block_details: BlockDetails,
54 },
55 Sync,
57 Broadcast,
59}
60
61#[derive(Debug, Clone, Copy, PartialEq, Eq)]
63pub struct ShardSegmentRoot {
64 pub shard_index: ShardIndex,
66 pub segment_index: LocalSegmentIndex,
68 pub segment_root: SegmentRoot,
70}
71
72#[derive(Debug, thiserror::Error)]
74pub enum ReadBlockError {
75 #[error("Unknown block root")]
77 UnknownBlockRoot,
78 #[error("Failed to decode the block")]
80 FailedToDecode,
81 #[error("Storage item read error")]
83 StorageItemReadError {
84 #[from]
86 error: io::Error,
87 },
88}
89
90#[derive(Debug, thiserror::Error)]
92pub enum PersistBlockError {
93 #[error("Missing parent")]
95 MissingParent,
96 #[error("Block is outside the acceptable range")]
98 OutsideAcceptableRange,
99 #[error("Storage item write error")]
101 StorageItemWriteError {
102 #[from]
104 error: io::Error,
105 },
106}
107
108#[derive(Debug, thiserror::Error)]
110pub enum PersistSegmentHeadersError {
111 #[error(
113 "Segment index {local_segment_index} must strictly follow last segment index \
114 {last_local_segment_index}, can't store segment header"
115 )]
116 MustFollowLastSegmentIndex {
117 local_segment_index: LocalSegmentIndex,
119 last_local_segment_index: LocalSegmentIndex,
121 },
122 #[error("First segment index must be zero, found {local_segment_index}")]
124 FirstSegmentIndexZero {
125 local_segment_index: LocalSegmentIndex,
127 },
128 #[error("Storage item write error")]
130 StorageItemWriteError {
131 #[from]
133 error: io::Error,
134 },
135}
136
137#[derive(Debug, thiserror::Error)]
139pub enum ShardSegmentRootsError {
140 #[error("Block {block_number} is missing")]
142 BlockMissing {
143 block_number: BlockNumber,
145 },
146}
147
148#[derive(Debug, thiserror::Error)]
150pub enum PersistSuperSegmentHeadersError {
151 #[error(
154 "Super segment index {super_segment_index} must strictly follow last super segment index \
155 {last_super_segment_index}, can't store super segment header"
156 )]
157 MustFollowLastSegmentIndex {
158 super_segment_index: SuperSegmentIndex,
160 last_super_segment_index: SuperSegmentIndex,
162 },
163 #[error("First super segment index must be zero, found {super_segment_index}")]
165 FirstSegmentIndexZero {
166 super_segment_index: SuperSegmentIndex,
168 },
169 #[error("Storage item write error")]
171 StorageItemWriteError {
172 #[from]
174 error: io::Error,
175 },
176}
177
178pub trait ChainInfo<Block>: Clone + Send + Sync + 'static
190where
191 Block: GenericOwnedBlock,
192{
193 fn best_root(&self) -> BlockRoot;
195
196 fn best_header(&self) -> Block::Header;
206
207 fn best_header_with_details(&self) -> (Block::Header, BlockDetails);
209
210 fn ancestor_header(
212 &self,
213 ancestor_block_number: BlockNumber,
214 descendant_block_root: &BlockRoot,
215 ) -> Option<Block::Header>;
216
217 fn header(&self, block_root: &BlockRoot) -> Option<Block::Header>;
219
220 fn header_with_details(&self, block_root: &BlockRoot) -> Option<(Block::Header, BlockDetails)>;
222
223 fn block(
224 &self,
225 block_root: &BlockRoot,
226 ) -> impl Future<Output = Result<Block, ReadBlockError>> + Send;
227
228 fn last_segment_header(&self) -> Option<SegmentHeader>;
230
231 fn get_segment_header(&self, segment_index: LocalSegmentIndex) -> Option<SegmentHeader>;
233
234 fn segment_headers_for_block(&self, block_number: BlockNumber) -> Vec<SegmentHeader>;
236}
237
238pub trait ChainInfoWrite<Block>: ChainInfo<Block>
240where
241 Block: GenericOwnedBlock,
242{
243 fn persist_block(
245 &self,
246 block: Block,
247 block_details: BlockDetails,
248 ) -> impl Future<Output = Result<(), PersistBlockError>> + Send;
249
250 fn persist_segment_headers(
254 &self,
255 segment_headers: Vec<SegmentHeader>,
256 ) -> impl Future<Output = Result<(), PersistSegmentHeadersError>> + Send;
257}
258
259pub trait BeaconChainInfo: ChainInfo<OwnedBeaconChainBlock> {
261 fn shard_segment_roots(
266 &self,
267 block_number: BlockNumber,
268 ) -> Result<Arc<[ShardSegmentRoot]>, ShardSegmentRootsError>;
269
270 fn last_super_segment_header(&self) -> Option<SuperSegmentHeader>;
272
273 fn previous_super_segment_header(
278 &self,
279 block_number: BlockNumber,
280 ) -> Option<SuperSegmentHeader>;
281
282 fn get_super_segment_header(
284 &self,
285 super_segment_index: SuperSegmentIndex,
286 ) -> Option<SuperSegmentHeader>;
287
288 fn get_super_segment_header_for_segment_index(
290 &self,
291 segment_index: SegmentIndex,
292 ) -> Option<SuperSegmentHeader>;
293}
294
295pub trait BeaconChainInfoWrite: BeaconChainInfo + ChainInfoWrite<OwnedBeaconChainBlock> {
297 fn persist_super_segment_header(
301 &self,
302 super_segment_header: SuperSegmentHeader,
303 ) -> impl Future<Output = Result<bool, PersistSuperSegmentHeadersError>> + Send;
304
305 fn persist_super_segment_headers(
309 &self,
310 super_segment_headers: Vec<SuperSegmentHeader>,
311 ) -> impl Future<Output = Result<(), PersistSuperSegmentHeadersError>> + Send;
312}
313
314pub trait ChainSyncStatus: Clone + Send + Sync + 'static {
316 fn target_block_number(&self) -> BlockNumber;
320
321 fn is_syncing(&self) -> bool;
323
324 fn is_offline(&self) -> bool;
326}