reth_storage_api/
block_id.rsuse crate::BlockHashReader;
use alloy_eips::{BlockHashOrNumber, BlockId, BlockNumberOrTag};
use alloy_primitives::{BlockNumber, B256};
use reth_chainspec::ChainInfo;
use reth_storage_errors::provider::{ProviderError, ProviderResult};
#[auto_impl::auto_impl(&, Arc)]
pub trait BlockNumReader: BlockHashReader + Send + Sync {
fn chain_info(&self) -> ProviderResult<ChainInfo>;
fn best_block_number(&self) -> ProviderResult<BlockNumber>;
fn last_block_number(&self) -> ProviderResult<BlockNumber>;
fn block_number(&self, hash: B256) -> ProviderResult<Option<BlockNumber>>;
fn convert_hash_or_number(&self, id: BlockHashOrNumber) -> ProviderResult<Option<BlockNumber>> {
match id {
BlockHashOrNumber::Hash(hash) => self.block_number(hash),
BlockHashOrNumber::Number(num) => Ok(Some(num)),
}
}
fn convert_number(&self, id: BlockHashOrNumber) -> ProviderResult<Option<B256>> {
match id {
BlockHashOrNumber::Hash(hash) => Ok(Some(hash)),
BlockHashOrNumber::Number(num) => self.block_hash(num),
}
}
}
#[auto_impl::auto_impl(&, Arc)]
pub trait BlockIdReader: BlockNumReader + Send + Sync {
fn convert_block_number(&self, num: BlockNumberOrTag) -> ProviderResult<Option<BlockNumber>> {
let num = match num {
BlockNumberOrTag::Latest => self.best_block_number()?,
BlockNumberOrTag::Earliest => 0,
BlockNumberOrTag::Pending => {
return self
.pending_block_num_hash()
.map(|res_opt| res_opt.map(|num_hash| num_hash.number))
}
BlockNumberOrTag::Number(num) => num,
BlockNumberOrTag::Finalized => {
self.finalized_block_number()?.ok_or(ProviderError::FinalizedBlockNotFound)?
}
BlockNumberOrTag::Safe => {
self.safe_block_number()?.ok_or(ProviderError::SafeBlockNotFound)?
}
};
Ok(Some(num))
}
fn block_hash_for_id(&self, block_id: BlockId) -> ProviderResult<Option<B256>> {
match block_id {
BlockId::Hash(hash) => Ok(Some(hash.into())),
BlockId::Number(num) => match num {
BlockNumberOrTag::Latest => Ok(Some(self.chain_info()?.best_hash)),
BlockNumberOrTag::Pending => self
.pending_block_num_hash()
.map(|res_opt| res_opt.map(|num_hash| num_hash.hash)),
BlockNumberOrTag::Finalized => self.finalized_block_hash(),
BlockNumberOrTag::Safe => self.safe_block_hash(),
BlockNumberOrTag::Earliest => self.block_hash(0),
BlockNumberOrTag::Number(num) => self.block_hash(num),
},
}
}
fn block_number_for_id(&self, block_id: BlockId) -> ProviderResult<Option<BlockNumber>> {
match block_id {
BlockId::Hash(hash) => self.block_number(hash.into()),
BlockId::Number(num) => self.convert_block_number(num),
}
}
fn pending_block_num_hash(&self) -> ProviderResult<Option<alloy_eips::BlockNumHash>>;
fn safe_block_num_hash(&self) -> ProviderResult<Option<alloy_eips::BlockNumHash>>;
fn finalized_block_num_hash(&self) -> ProviderResult<Option<alloy_eips::BlockNumHash>>;
fn safe_block_number(&self) -> ProviderResult<Option<BlockNumber>> {
self.safe_block_num_hash().map(|res_opt| res_opt.map(|num_hash| num_hash.number))
}
fn finalized_block_number(&self) -> ProviderResult<Option<BlockNumber>> {
self.finalized_block_num_hash().map(|res_opt| res_opt.map(|num_hash| num_hash.number))
}
fn safe_block_hash(&self) -> ProviderResult<Option<B256>> {
self.safe_block_num_hash().map(|res_opt| res_opt.map(|num_hash| num_hash.hash))
}
fn finalized_block_hash(&self) -> ProviderResult<Option<B256>> {
self.finalized_block_num_hash().map(|res_opt| res_opt.map(|num_hash| num_hash.hash))
}
}
#[cfg(test)]
fn _object_safe(_: Box<dyn BlockIdReader>) {}