reth_storage_api/
block_id.rs1use crate::BlockHashReader;
2use alloy_eips::{BlockHashOrNumber, BlockId, BlockNumberOrTag};
3use alloy_primitives::{BlockNumber, B256};
4use reth_chainspec::ChainInfo;
5use reth_storage_errors::provider::{ProviderError, ProviderResult};
6
7#[auto_impl::auto_impl(&, Arc)]
12pub trait BlockNumReader: BlockHashReader + Send + Sync {
13 fn chain_info(&self) -> ProviderResult<ChainInfo>;
15
16 fn best_block_number(&self) -> ProviderResult<BlockNumber>;
18
19 fn last_block_number(&self) -> ProviderResult<BlockNumber>;
21
22 fn block_number(&self, hash: B256) -> ProviderResult<Option<BlockNumber>>;
24
25 fn convert_hash_or_number(&self, id: BlockHashOrNumber) -> ProviderResult<Option<BlockNumber>> {
28 match id {
29 BlockHashOrNumber::Hash(hash) => self.block_number(hash),
30 BlockHashOrNumber::Number(num) => Ok(Some(num)),
31 }
32 }
33
34 fn convert_number(&self, id: BlockHashOrNumber) -> ProviderResult<Option<B256>> {
37 match id {
38 BlockHashOrNumber::Hash(hash) => Ok(Some(hash)),
39 BlockHashOrNumber::Number(num) => self.block_hash(num),
40 }
41 }
42}
43
44#[auto_impl::auto_impl(&, Arc)]
54pub trait BlockIdReader: BlockNumReader + Send + Sync {
55 fn convert_block_number(&self, num: BlockNumberOrTag) -> ProviderResult<Option<BlockNumber>> {
57 let num = match num {
58 BlockNumberOrTag::Latest => self.best_block_number()?,
59 BlockNumberOrTag::Earliest => 0,
60 BlockNumberOrTag::Pending => {
61 return self
62 .pending_block_num_hash()
63 .map(|res_opt| res_opt.map(|num_hash| num_hash.number))
64 }
65 BlockNumberOrTag::Number(num) => num,
66 BlockNumberOrTag::Finalized => {
67 self.finalized_block_number()?.ok_or(ProviderError::FinalizedBlockNotFound)?
68 }
69 BlockNumberOrTag::Safe => {
70 self.safe_block_number()?.ok_or(ProviderError::SafeBlockNotFound)?
71 }
72 };
73 Ok(Some(num))
74 }
75
76 fn block_hash_for_id(&self, block_id: BlockId) -> ProviderResult<Option<B256>> {
78 match block_id {
79 BlockId::Hash(hash) => Ok(Some(hash.into())),
80 BlockId::Number(num) => match num {
81 BlockNumberOrTag::Latest => Ok(Some(self.chain_info()?.best_hash)),
82 BlockNumberOrTag::Pending => self
83 .pending_block_num_hash()
84 .map(|res_opt| res_opt.map(|num_hash| num_hash.hash)),
85 BlockNumberOrTag::Finalized => self.finalized_block_hash(),
86 BlockNumberOrTag::Safe => self.safe_block_hash(),
87 BlockNumberOrTag::Earliest => self.block_hash(0),
88 BlockNumberOrTag::Number(num) => self.block_hash(num),
89 },
90 }
91 }
92
93 fn block_number_for_id(&self, block_id: BlockId) -> ProviderResult<Option<BlockNumber>> {
95 match block_id {
96 BlockId::Hash(hash) => self.block_number(hash.into()),
97 BlockId::Number(num) => self.convert_block_number(num),
98 }
99 }
100
101 fn pending_block_num_hash(&self) -> ProviderResult<Option<alloy_eips::BlockNumHash>>;
103
104 fn safe_block_num_hash(&self) -> ProviderResult<Option<alloy_eips::BlockNumHash>>;
106
107 fn finalized_block_num_hash(&self) -> ProviderResult<Option<alloy_eips::BlockNumHash>>;
109
110 fn safe_block_number(&self) -> ProviderResult<Option<BlockNumber>> {
112 self.safe_block_num_hash().map(|res_opt| res_opt.map(|num_hash| num_hash.number))
113 }
114
115 fn finalized_block_number(&self) -> ProviderResult<Option<BlockNumber>> {
117 self.finalized_block_num_hash().map(|res_opt| res_opt.map(|num_hash| num_hash.number))
118 }
119
120 fn safe_block_hash(&self) -> ProviderResult<Option<B256>> {
122 self.safe_block_num_hash().map(|res_opt| res_opt.map(|num_hash| num_hash.hash))
123 }
124
125 fn finalized_block_hash(&self) -> ProviderResult<Option<B256>> {
127 self.finalized_block_num_hash().map(|res_opt| res_opt.map(|num_hash| num_hash.hash))
128 }
129}
130
131#[cfg(test)]
132fn _object_safe(_: Box<dyn BlockIdReader>) {}