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}