ab_client_api/lib.rs
1//! Client API
2
3#![expect(incomplete_features, reason = "generic_const_exprs")]
4// TODO: This feature is not actually used in this crate, but is added as a workaround for
5// https://github.com/rust-lang/rust/issues/141492
6#![feature(generic_const_exprs)]
7
8use ab_core_primitives::block::owned::GenericOwnedBlock;
9use ab_core_primitives::block::{BlockNumber, BlockRoot};
10use ab_merkle_tree::mmr::MerkleMountainRange;
11use rclite::Arc;
12
13// TODO: This is a workaround for https://github.com/rust-lang/rust/issues/139866 that allows the
14// code to compile. Constant 4294967295 is hardcoded here and below for compilation to succeed.
15const _: () = {
16 assert!(u32::MAX == 4294967295);
17};
18
19/// Type alias for Merkle Mountain Range with block roots.
20///
21/// NOTE: `u32` is smaller than `BlockNumber`'s internal `u64` but will be sufficient for a long
22/// time and substantially decrease the size of the data structure.
23pub type BlockMerkleMountainRange = MerkleMountainRange<4294967295>;
24
25// TODO: Probably move it elsewhere
26/// Origin
27#[derive(Debug, PartialEq, Eq, Clone, Copy)]
28pub enum BlockOrigin {
29 /// Created locally
30 Local,
31 /// Received during the sync process
32 Sync,
33 /// Broadcast on the network during normal operation (not sync)
34 Broadcast,
35}
36
37/// Error for [`ChainInfoWrite::persist_block()`]
38#[derive(Debug, thiserror::Error)]
39pub enum PersistBlockError {
40 // TODO
41}
42
43// TODO: Split this into different more narrow traits
44/// Chain info
45pub trait ChainInfo<Block>: Clone + Send + Sync + 'static
46where
47 Block: GenericOwnedBlock,
48{
49 /// Best block root
50 fn best_root(&self) -> BlockRoot;
51
52 // TODO: Uncomment if/when necessary
53 // /// Find root of ancestor block number for descendant block root
54 // fn ancestor_root(
55 // &self,
56 // ancestor_block_number: BlockNumber,
57 // descendant_block_root: &BlockRoot,
58 // ) -> Option<BlockRoot>;
59
60 /// Best block header
61 fn best_header(&self) -> Block::Header;
62
63 /// Get header of ancestor block number for descendant block root
64 fn ancestor_header(
65 &self,
66 ancestor_block_number: BlockNumber,
67 descendant_block_root: &BlockRoot,
68 ) -> Option<Block::Header>;
69
70 /// Block header
71 fn header(&self, block_root: &BlockRoot) -> Option<Block::Header>;
72
73 /// Merkle Mountain Range with block
74 fn mmr_with_block(&self, block_root: &BlockRoot) -> Option<Arc<BlockMerkleMountainRange>>;
75}
76
77/// [`ChainInfo`] extension for writing information
78pub trait ChainInfoWrite<Block>: ChainInfo<Block>
79where
80 Block: GenericOwnedBlock,
81{
82 /// Persist newly imported block
83 fn persist_block(
84 &self,
85 block: Block,
86 mmr_with_block: Arc<BlockMerkleMountainRange>,
87 ) -> impl Future<Output = Result<(), PersistBlockError>> + Send;
88}
89
90/// Chain sync status
91pub trait ChainSyncStatus: Clone + Send + Sync + 'static {
92 /// Block number that the sync process is targeting right now.
93 ///
94 /// Can be zero if not syncing actively.
95 fn target_block_number(&self) -> BlockNumber;
96
97 /// Returns `true` if the chain is currently syncing
98 fn is_syncing(&self) -> bool;
99
100 /// Returns `true` if the node is currently offline
101 fn is_offline(&self) -> bool;
102}