feat: add header AT to provider (#13030)

Co-authored-by: Arsenii Kulikov <klkvrr@gmail.com>
This commit is contained in:
Matthias Seitz
2024-12-02 14:24:48 +01:00
committed by GitHub
parent 519a10ae99
commit 332cce1f9b
71 changed files with 669 additions and 434 deletions

View File

@ -24,6 +24,7 @@ reth-fs-util.workspace = true
reth-node-types.workspace = true
# eth
alloy-consensus.workspace = true
alloy-genesis.workspace = true
alloy-primitives.workspace = true

View File

@ -1,5 +1,6 @@
//! Reth genesis initialization utility functions.
use alloy_consensus::BlockHeader;
use alloy_genesis::GenesisAccount;
use alloy_primitives::{Address, B256, U256};
use reth_chainspec::EthChainSpec;
@ -8,7 +9,9 @@ use reth_config::config::EtlConfig;
use reth_db::tables;
use reth_db_api::{transaction::DbTxMut, DatabaseError};
use reth_etl::Collector;
use reth_primitives::{Account, Bytecode, GotExpected, Receipts, StaticFileSegment, StorageEntry};
use reth_primitives::{
Account, Bytecode, GotExpected, NodePrimitives, Receipts, StaticFileSegment, StorageEntry,
};
use reth_provider::{
errors::provider::ProviderResult, providers::StaticFileWriter, writer::UnifiedStorageWriter,
BlockHashReader, BlockNumReader, BundleStateInit, ChainSpecProvider, DBProvider,
@ -69,7 +72,10 @@ impl From<DatabaseError> for InitDatabaseError {
/// Write the genesis block if it has not already been written
pub fn init_genesis<PF>(factory: &PF) -> Result<B256, InitDatabaseError>
where
PF: DatabaseProviderFactory + StaticFileProviderFactory + ChainSpecProvider + BlockHashReader,
PF: DatabaseProviderFactory
+ StaticFileProviderFactory<Primitives: NodePrimitives<BlockHeader: Compact>>
+ ChainSpecProvider
+ BlockHashReader,
PF::ProviderRW: StaticFileProviderFactory<Primitives = PF::Primitives>
+ StageCheckpointWriter
+ HistoryWriter
@ -78,7 +84,7 @@ where
+ StateWriter
+ StateWriter
+ AsRef<PF::ProviderRW>,
PF::ChainSpec: EthChainSpec<Header = reth_primitives::Header>,
PF::ChainSpec: EthChainSpec<Header = <PF::Primitives as NodePrimitives>::BlockHeader>,
{
let chain = factory.chain_spec();
@ -307,15 +313,16 @@ pub fn insert_genesis_header<Provider, Spec>(
chain: &Spec,
) -> ProviderResult<()>
where
Provider: StaticFileProviderFactory + DBProvider<Tx: DbTxMut>,
Spec: EthChainSpec<Header = reth_primitives::Header>,
Provider: StaticFileProviderFactory<Primitives: NodePrimitives<BlockHeader: Compact>>
+ DBProvider<Tx: DbTxMut>,
Spec: EthChainSpec<Header = <Provider::Primitives as NodePrimitives>::BlockHeader>,
{
let (header, block_hash) = (chain.genesis_header(), chain.genesis_hash());
let static_file_provider = provider.static_file_provider();
match static_file_provider.block_hash(0) {
Ok(None) | Err(ProviderError::MissingStaticFileBlock(StaticFileSegment::Headers, 0)) => {
let (difficulty, hash) = (header.difficulty, block_hash);
let (difficulty, hash) = (header.difficulty(), block_hash);
let mut writer = static_file_provider.latest_writer(StaticFileSegment::Headers)?;
writer.append_header(header, difficulty, &hash)?;
}
@ -359,7 +366,7 @@ where
let expected_state_root = provider_rw
.header_by_number(block)?
.ok_or_else(|| ProviderError::HeaderNotFound(block.into()))?
.state_root;
.state_root();
// first line can be state root
let dump_state_root = parse_state_root(&mut reader)?;

View File

@ -25,7 +25,7 @@ use reth_db::{models::BlockNumberAddress, transaction::DbTx, Database};
use reth_db_api::models::{AccountBeforeTx, StoredBlockBodyIndices};
use reth_evm::ConfigureEvmEnv;
use reth_execution_types::ExecutionOutcome;
use reth_node_types::{BlockTy, NodeTypesWithDB, ReceiptTy, TxTy};
use reth_node_types::{BlockTy, HeaderTy, NodeTypesWithDB, ReceiptTy, TxTy};
use reth_primitives::{
Account, Block, BlockWithSenders, EthPrimitives, NodePrimitives, Receipt, SealedBlock,
SealedBlockFor, SealedBlockWithSenders, SealedHeader, StorageEntry, TransactionMeta,
@ -89,7 +89,10 @@ impl<N: ProviderNodeTypes> BlockchainProvider2<N> {
///
/// This returns a `ProviderResult` since it tries the retrieve the last finalized header from
/// `database`.
pub fn with_latest(storage: ProviderFactory<N>, latest: SealedHeader) -> ProviderResult<Self> {
pub fn with_latest(
storage: ProviderFactory<N>,
latest: SealedHeader<HeaderTy<N>>,
) -> ProviderResult<Self> {
let provider = storage.provider()?;
let finalized_header = provider
.last_finalized_block_number()?
@ -175,11 +178,13 @@ impl<N: ProviderNodeTypes> StaticFileProviderFactory for BlockchainProvider2<N>
}
impl<N: ProviderNodeTypes> HeaderProvider for BlockchainProvider2<N> {
fn header(&self, block_hash: &BlockHash) -> ProviderResult<Option<Header>> {
type Header = HeaderTy<N>;
fn header(&self, block_hash: &BlockHash) -> ProviderResult<Option<Self::Header>> {
self.consistent_provider()?.header(block_hash)
}
fn header_by_number(&self, num: BlockNumber) -> ProviderResult<Option<Header>> {
fn header_by_number(&self, num: BlockNumber) -> ProviderResult<Option<Self::Header>> {
self.consistent_provider()?.header_by_number(num)
}
@ -191,26 +196,32 @@ impl<N: ProviderNodeTypes> HeaderProvider for BlockchainProvider2<N> {
self.consistent_provider()?.header_td_by_number(number)
}
fn headers_range(&self, range: impl RangeBounds<BlockNumber>) -> ProviderResult<Vec<Header>> {
fn headers_range(
&self,
range: impl RangeBounds<BlockNumber>,
) -> ProviderResult<Vec<Self::Header>> {
self.consistent_provider()?.headers_range(range)
}
fn sealed_header(&self, number: BlockNumber) -> ProviderResult<Option<SealedHeader>> {
fn sealed_header(
&self,
number: BlockNumber,
) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
self.consistent_provider()?.sealed_header(number)
}
fn sealed_headers_range(
&self,
range: impl RangeBounds<BlockNumber>,
) -> ProviderResult<Vec<SealedHeader>> {
) -> ProviderResult<Vec<SealedHeader<Self::Header>>> {
self.consistent_provider()?.sealed_headers_range(range)
}
fn sealed_headers_while(
&self,
range: impl RangeBounds<BlockNumber>,
predicate: impl FnMut(&SealedHeader) -> bool,
) -> ProviderResult<Vec<SealedHeader>> {
predicate: impl FnMut(&SealedHeader<Self::Header>) -> bool,
) -> ProviderResult<Vec<SealedHeader<Self::Header>>> {
self.consistent_provider()?.sealed_headers_while(range, predicate)
}
}
@ -292,7 +303,7 @@ impl<N: ProviderNodeTypes> BlockReader for BlockchainProvider2<N> {
Ok(self.canonical_in_memory_state.pending_block_and_receipts())
}
fn ommers(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Vec<Header>>> {
fn ommers(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Vec<Self::Header>>> {
self.consistent_provider()?.ommers(id)
}
@ -470,7 +481,7 @@ impl<N: ProviderNodeTypes> StageCheckpointReader for BlockchainProvider2<N> {
}
}
impl<N: ProviderNodeTypes> EvmEnvProvider for BlockchainProvider2<N> {
impl<N: ProviderNodeTypes> EvmEnvProvider<HeaderTy<N>> for BlockchainProvider2<N> {
fn fill_env_at<EvmConfig>(
&self,
cfg: &mut CfgEnvWithHandlerCfg,
@ -479,7 +490,7 @@ impl<N: ProviderNodeTypes> EvmEnvProvider for BlockchainProvider2<N> {
evm_config: EvmConfig,
) -> ProviderResult<()>
where
EvmConfig: ConfigureEvmEnv<Header = Header>,
EvmConfig: ConfigureEvmEnv<Header = HeaderTy<N>>,
{
self.consistent_provider()?.fill_env_at(cfg, block_env, at, evm_config)
}
@ -488,11 +499,11 @@ impl<N: ProviderNodeTypes> EvmEnvProvider for BlockchainProvider2<N> {
&self,
cfg: &mut CfgEnvWithHandlerCfg,
block_env: &mut BlockEnv,
header: &Header,
header: &HeaderTy<N>,
evm_config: EvmConfig,
) -> ProviderResult<()>
where
EvmConfig: ConfigureEvmEnv<Header = Header>,
EvmConfig: ConfigureEvmEnv<Header = HeaderTy<N>>,
{
self.consistent_provider()?.fill_env_with_header(cfg, block_env, header, evm_config)
}
@ -504,7 +515,7 @@ impl<N: ProviderNodeTypes> EvmEnvProvider for BlockchainProvider2<N> {
evm_config: EvmConfig,
) -> ProviderResult<()>
where
EvmConfig: ConfigureEvmEnv<Header = Header>,
EvmConfig: ConfigureEvmEnv<Header = HeaderTy<N>>,
{
self.consistent_provider()?.fill_cfg_env_at(cfg, at, evm_config)
}
@ -512,11 +523,11 @@ impl<N: ProviderNodeTypes> EvmEnvProvider for BlockchainProvider2<N> {
fn fill_cfg_env_with_header<EvmConfig>(
&self,
cfg: &mut CfgEnvWithHandlerCfg,
header: &Header,
header: &HeaderTy<N>,
evm_config: EvmConfig,
) -> ProviderResult<()>
where
EvmConfig: ConfigureEvmEnv<Header = Header>,
EvmConfig: ConfigureEvmEnv<Header = HeaderTy<N>>,
{
self.consistent_provider()?.fill_cfg_env_with_header(cfg, header, evm_config)
}
@ -652,10 +663,9 @@ impl<N: ProviderNodeTypes> StateProviderFactory for BlockchainProvider2<N> {
}
}
impl<N: ProviderNodeTypes> CanonChainTracker for BlockchainProvider2<N>
where
Self: BlockReader,
{
impl<N: ProviderNodeTypes> CanonChainTracker for BlockchainProvider2<N> {
type Header = HeaderTy<N>;
fn on_forkchoice_update_received(&self, _update: &ForkchoiceState) {
// update timestamp
self.canonical_in_memory_state.on_forkchoice_update_received();
@ -673,15 +683,15 @@ where
self.canonical_in_memory_state.last_exchanged_transition_configuration_timestamp()
}
fn set_canonical_head(&self, header: SealedHeader) {
fn set_canonical_head(&self, header: SealedHeader<Self::Header>) {
self.canonical_in_memory_state.set_canonical_head(header);
}
fn set_safe(&self, header: SealedHeader) {
fn set_safe(&self, header: SealedHeader<Self::Header>) {
self.canonical_in_memory_state.set_safe(header);
}
fn set_finalized(&self, header: SealedHeader) {
fn set_finalized(&self, header: SealedHeader<Self::Header>) {
self.canonical_in_memory_state.set_finalized(header);
}
}
@ -694,26 +704,32 @@ where
self.consistent_provider()?.block_by_id(id)
}
fn header_by_number_or_tag(&self, id: BlockNumberOrTag) -> ProviderResult<Option<Header>> {
fn header_by_number_or_tag(
&self,
id: BlockNumberOrTag,
) -> ProviderResult<Option<Self::Header>> {
self.consistent_provider()?.header_by_number_or_tag(id)
}
fn sealed_header_by_number_or_tag(
&self,
id: BlockNumberOrTag,
) -> ProviderResult<Option<SealedHeader>> {
) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
self.consistent_provider()?.sealed_header_by_number_or_tag(id)
}
fn sealed_header_by_id(&self, id: BlockId) -> ProviderResult<Option<SealedHeader>> {
fn sealed_header_by_id(
&self,
id: BlockId,
) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
self.consistent_provider()?.sealed_header_by_id(id)
}
fn header_by_id(&self, id: BlockId) -> ProviderResult<Option<Header>> {
fn header_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Header>> {
self.consistent_provider()?.header_by_id(id)
}
fn ommers_by_id(&self, id: BlockId) -> ProviderResult<Option<Vec<Header>>> {
fn ommers_by_id(&self, id: BlockId) -> ProviderResult<Option<Vec<Self::Header>>> {
self.consistent_provider()?.ommers_by_id(id)
}
}
@ -727,12 +743,14 @@ impl<N: NodeTypesWithDB<Primitives = EthPrimitives>> CanonStateSubscriptions
}
impl<N: ProviderNodeTypes> ForkChoiceSubscriptions for BlockchainProvider2<N> {
fn subscribe_safe_block(&self) -> ForkChoiceNotifications {
type Header = HeaderTy<N>;
fn subscribe_safe_block(&self) -> ForkChoiceNotifications<Self::Header> {
let receiver = self.canonical_in_memory_state.subscribe_safe_block();
ForkChoiceNotifications(receiver)
}
fn subscribe_finalized_block(&self) -> ForkChoiceNotifications {
fn subscribe_finalized_block(&self) -> ForkChoiceNotifications<Self::Header> {
let receiver = self.canonical_in_memory_state.subscribe_finalized_block();
ForkChoiceNotifications(receiver)
}

View File

@ -6,7 +6,7 @@ use crate::{
StageCheckpointReader, StateReader, StaticFileProviderFactory, TransactionVariant,
TransactionsProvider, WithdrawalsProvider,
};
use alloy_consensus::Header;
use alloy_consensus::BlockHeader;
use alloy_eips::{
eip2718::Encodable2718,
eip4895::{Withdrawal, Withdrawals},
@ -19,7 +19,7 @@ use reth_db::models::BlockNumberAddress;
use reth_db_api::models::{AccountBeforeTx, StoredBlockBodyIndices};
use reth_evm::ConfigureEvmEnv;
use reth_execution_types::{BundleStateInit, ExecutionOutcome, RevertsInit};
use reth_node_types::{BlockTy, ReceiptTy, TxTy};
use reth_node_types::{BlockTy, HeaderTy, ReceiptTy, TxTy};
use reth_primitives::{
Account, BlockWithSenders, SealedBlockFor, SealedBlockWithSenders, SealedHeader, StorageEntry,
TransactionMeta,
@ -628,7 +628,9 @@ impl<N: ProviderNodeTypes> StaticFileProviderFactory for ConsistentProvider<N> {
}
impl<N: ProviderNodeTypes> HeaderProvider for ConsistentProvider<N> {
fn header(&self, block_hash: &BlockHash) -> ProviderResult<Option<Header>> {
type Header = HeaderTy<N>;
fn header(&self, block_hash: &BlockHash) -> ProviderResult<Option<Self::Header>> {
self.get_in_memory_or_storage_by_block(
(*block_hash).into(),
|db_provider| db_provider.header(block_hash),
@ -636,7 +638,7 @@ impl<N: ProviderNodeTypes> HeaderProvider for ConsistentProvider<N> {
)
}
fn header_by_number(&self, num: BlockNumber) -> ProviderResult<Option<Header>> {
fn header_by_number(&self, num: BlockNumber) -> ProviderResult<Option<Self::Header>> {
self.get_in_memory_or_storage_by_block(
num.into(),
|db_provider| db_provider.header_by_number(num),
@ -675,7 +677,10 @@ impl<N: ProviderNodeTypes> HeaderProvider for ConsistentProvider<N> {
self.storage_provider.header_td_by_number(number)
}
fn headers_range(&self, range: impl RangeBounds<BlockNumber>) -> ProviderResult<Vec<Header>> {
fn headers_range(
&self,
range: impl RangeBounds<BlockNumber>,
) -> ProviderResult<Vec<Self::Header>> {
self.get_in_memory_or_storage_by_block_range_while(
range,
|db_provider, range, _| db_provider.headers_range(range),
@ -684,7 +689,10 @@ impl<N: ProviderNodeTypes> HeaderProvider for ConsistentProvider<N> {
)
}
fn sealed_header(&self, number: BlockNumber) -> ProviderResult<Option<SealedHeader>> {
fn sealed_header(
&self,
number: BlockNumber,
) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
self.get_in_memory_or_storage_by_block(
number.into(),
|db_provider| db_provider.sealed_header(number),
@ -695,7 +703,7 @@ impl<N: ProviderNodeTypes> HeaderProvider for ConsistentProvider<N> {
fn sealed_headers_range(
&self,
range: impl RangeBounds<BlockNumber>,
) -> ProviderResult<Vec<SealedHeader>> {
) -> ProviderResult<Vec<SealedHeader<Self::Header>>> {
self.get_in_memory_or_storage_by_block_range_while(
range,
|db_provider, range, _| db_provider.sealed_headers_range(range),
@ -707,8 +715,8 @@ impl<N: ProviderNodeTypes> HeaderProvider for ConsistentProvider<N> {
fn sealed_headers_while(
&self,
range: impl RangeBounds<BlockNumber>,
predicate: impl FnMut(&SealedHeader) -> bool,
) -> ProviderResult<Vec<SealedHeader>> {
predicate: impl FnMut(&SealedHeader<Self::Header>) -> bool,
) -> ProviderResult<Vec<SealedHeader<Self::Header>>> {
self.get_in_memory_or_storage_by_block_range_while(
range,
|db_provider, range, predicate| db_provider.sealed_headers_while(range, predicate),
@ -832,7 +840,7 @@ impl<N: ProviderNodeTypes> BlockReader for ConsistentProvider<N> {
Ok(self.canonical_in_memory_state.pending_block_and_receipts())
}
fn ommers(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Vec<Header>>> {
fn ommers(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Vec<HeaderTy<N>>>> {
self.get_in_memory_or_storage_by_block(
id,
|db_provider| db_provider.ommers(id),
@ -868,7 +876,7 @@ impl<N: ProviderNodeTypes> BlockReader for ConsistentProvider<N> {
// Iterate from the lowest block in memory until our target block
for state in block_state.chain().collect::<Vec<_>>().into_iter().rev() {
let block_tx_count = state.block_ref().block.body.transactions().len() as u64;
if state.block_ref().block().number == number {
if state.block_ref().block().number() == number {
stored_indices.tx_count = block_tx_count;
} else {
stored_indices.first_tx_num += block_tx_count;
@ -1017,7 +1025,7 @@ impl<N: ProviderNodeTypes> TransactionsProvider for ConsistentProvider<N> {
self.get_in_memory_or_storage_by_tx(
id.into(),
|provider| provider.transaction_block(id),
|_, _, block_state| Ok(Some(block_state.block_ref().block().number)),
|_, _, block_state| Ok(Some(block_state.block_ref().block().number())),
)
}
@ -1222,7 +1230,7 @@ impl<N: ProviderNodeTypes> StageCheckpointReader for ConsistentProvider<N> {
}
}
impl<N: ProviderNodeTypes> EvmEnvProvider for ConsistentProvider<N> {
impl<N: ProviderNodeTypes> EvmEnvProvider<HeaderTy<N>> for ConsistentProvider<N> {
fn fill_env_at<EvmConfig>(
&self,
cfg: &mut CfgEnvWithHandlerCfg,
@ -1231,7 +1239,7 @@ impl<N: ProviderNodeTypes> EvmEnvProvider for ConsistentProvider<N> {
evm_config: EvmConfig,
) -> ProviderResult<()>
where
EvmConfig: ConfigureEvmEnv<Header = Header>,
EvmConfig: ConfigureEvmEnv<Header = HeaderTy<N>>,
{
let hash = self.convert_number(at)?.ok_or(ProviderError::HeaderNotFound(at))?;
let header = self.header(&hash)?.ok_or(ProviderError::HeaderNotFound(at))?;
@ -1242,15 +1250,15 @@ impl<N: ProviderNodeTypes> EvmEnvProvider for ConsistentProvider<N> {
&self,
cfg: &mut CfgEnvWithHandlerCfg,
block_env: &mut BlockEnv,
header: &Header,
header: &HeaderTy<N>,
evm_config: EvmConfig,
) -> ProviderResult<()>
where
EvmConfig: ConfigureEvmEnv<Header = Header>,
EvmConfig: ConfigureEvmEnv<Header = HeaderTy<N>>,
{
let total_difficulty = self
.header_td_by_number(header.number)?
.ok_or_else(|| ProviderError::HeaderNotFound(header.number.into()))?;
.header_td_by_number(header.number())?
.ok_or_else(|| ProviderError::HeaderNotFound(header.number().into()))?;
evm_config.fill_cfg_and_block_env(cfg, block_env, header, total_difficulty);
Ok(())
}
@ -1262,7 +1270,7 @@ impl<N: ProviderNodeTypes> EvmEnvProvider for ConsistentProvider<N> {
evm_config: EvmConfig,
) -> ProviderResult<()>
where
EvmConfig: ConfigureEvmEnv<Header = Header>,
EvmConfig: ConfigureEvmEnv<Header = HeaderTy<N>>,
{
let hash = self.convert_number(at)?.ok_or(ProviderError::HeaderNotFound(at))?;
let header = self.header(&hash)?.ok_or(ProviderError::HeaderNotFound(at))?;
@ -1272,15 +1280,15 @@ impl<N: ProviderNodeTypes> EvmEnvProvider for ConsistentProvider<N> {
fn fill_cfg_env_with_header<EvmConfig>(
&self,
cfg: &mut CfgEnvWithHandlerCfg,
header: &Header,
header: &HeaderTy<N>,
evm_config: EvmConfig,
) -> ProviderResult<()>
where
EvmConfig: ConfigureEvmEnv<Header = Header>,
EvmConfig: ConfigureEvmEnv<Header = HeaderTy<N>>,
{
let total_difficulty = self
.header_td_by_number(header.number)?
.ok_or_else(|| ProviderError::HeaderNotFound(header.number.into()))?;
.header_td_by_number(header.number())?
.ok_or_else(|| ProviderError::HeaderNotFound(header.number().into()))?;
evm_config.fill_cfg_env(cfg, header, total_difficulty);
Ok(())
}
@ -1326,7 +1334,7 @@ impl<N: ProviderNodeTypes> BlockReaderIdExt for ConsistentProvider<N> {
}
}
fn header_by_number_or_tag(&self, id: BlockNumberOrTag) -> ProviderResult<Option<Header>> {
fn header_by_number_or_tag(&self, id: BlockNumberOrTag) -> ProviderResult<Option<HeaderTy<N>>> {
Ok(match id {
BlockNumberOrTag::Latest => {
Some(self.canonical_in_memory_state.get_canonical_head().unseal())
@ -1347,7 +1355,7 @@ impl<N: ProviderNodeTypes> BlockReaderIdExt for ConsistentProvider<N> {
fn sealed_header_by_number_or_tag(
&self,
id: BlockNumberOrTag,
) -> ProviderResult<Option<SealedHeader>> {
) -> ProviderResult<Option<SealedHeader<HeaderTy<N>>>> {
match id {
BlockNumberOrTag::Latest => {
Ok(Some(self.canonical_in_memory_state.get_canonical_head()))
@ -1366,21 +1374,24 @@ impl<N: ProviderNodeTypes> BlockReaderIdExt for ConsistentProvider<N> {
}
}
fn sealed_header_by_id(&self, id: BlockId) -> ProviderResult<Option<SealedHeader>> {
fn sealed_header_by_id(
&self,
id: BlockId,
) -> ProviderResult<Option<SealedHeader<HeaderTy<N>>>> {
Ok(match id {
BlockId::Number(num) => self.sealed_header_by_number_or_tag(num)?,
BlockId::Hash(hash) => self.header(&hash.block_hash)?.map(SealedHeader::seal),
})
}
fn header_by_id(&self, id: BlockId) -> ProviderResult<Option<Header>> {
fn header_by_id(&self, id: BlockId) -> ProviderResult<Option<HeaderTy<N>>> {
Ok(match id {
BlockId::Number(num) => self.header_by_number_or_tag(num)?,
BlockId::Hash(hash) => self.header(&hash.block_hash)?,
})
}
fn ommers_by_id(&self, id: BlockId) -> ProviderResult<Option<Vec<Header>>> {
fn ommers_by_id(&self, id: BlockId) -> ProviderResult<Option<Vec<HeaderTy<N>>>> {
match id {
BlockId::Number(num) => self.ommers_by_number_or_tag(num),
BlockId::Hash(hash) => {

View File

@ -7,7 +7,6 @@ use crate::{
PruneCheckpointReader, StageCheckpointReader, StateProviderBox, StaticFileProviderFactory,
TransactionVariant, TransactionsProvider, WithdrawalsProvider,
};
use alloy_consensus::Header;
use alloy_eips::{
eip4895::{Withdrawal, Withdrawals},
BlockHashOrNumber,
@ -19,7 +18,7 @@ use reth_db::{init_db, mdbx::DatabaseArguments, DatabaseEnv};
use reth_db_api::{database::Database, models::StoredBlockBodyIndices};
use reth_errors::{RethError, RethResult};
use reth_evm::ConfigureEvmEnv;
use reth_node_types::{BlockTy, NodeTypesWithDB, ReceiptTy, TxTy};
use reth_node_types::{BlockTy, HeaderTy, NodeTypesWithDB, ReceiptTy, TxTy};
use reth_primitives::{
BlockWithSenders, SealedBlockFor, SealedBlockWithSenders, SealedHeader, StaticFileSegment,
TransactionMeta,
@ -228,21 +227,24 @@ impl<N: NodeTypesWithDB> StaticFileProviderFactory for ProviderFactory<N> {
}
impl<N: ProviderNodeTypes> HeaderSyncGapProvider for ProviderFactory<N> {
type Header = HeaderTy<N>;
fn sync_gap(
&self,
tip: watch::Receiver<B256>,
highest_uninterrupted_block: BlockNumber,
) -> ProviderResult<HeaderSyncGap> {
) -> ProviderResult<HeaderSyncGap<Self::Header>> {
self.provider()?.sync_gap(tip, highest_uninterrupted_block)
}
}
impl<N: ProviderNodeTypes> HeaderProvider for ProviderFactory<N> {
fn header(&self, block_hash: &BlockHash) -> ProviderResult<Option<Header>> {
type Header = HeaderTy<N>;
fn header(&self, block_hash: &BlockHash) -> ProviderResult<Option<Self::Header>> {
self.provider()?.header(block_hash)
}
fn header_by_number(&self, num: BlockNumber) -> ProviderResult<Option<Header>> {
fn header_by_number(&self, num: BlockNumber) -> ProviderResult<Option<Self::Header>> {
self.static_file_provider.get_with_static_file_or_database(
StaticFileSegment::Headers,
num,
@ -270,7 +272,10 @@ impl<N: ProviderNodeTypes> HeaderProvider for ProviderFactory<N> {
)
}
fn headers_range(&self, range: impl RangeBounds<BlockNumber>) -> ProviderResult<Vec<Header>> {
fn headers_range(
&self,
range: impl RangeBounds<BlockNumber>,
) -> ProviderResult<Vec<Self::Header>> {
self.static_file_provider.get_range_with_static_file_or_database(
StaticFileSegment::Headers,
to_range(range),
@ -280,7 +285,10 @@ impl<N: ProviderNodeTypes> HeaderProvider for ProviderFactory<N> {
)
}
fn sealed_header(&self, number: BlockNumber) -> ProviderResult<Option<SealedHeader>> {
fn sealed_header(
&self,
number: BlockNumber,
) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
self.static_file_provider.get_with_static_file_or_database(
StaticFileSegment::Headers,
number,
@ -292,15 +300,15 @@ impl<N: ProviderNodeTypes> HeaderProvider for ProviderFactory<N> {
fn sealed_headers_range(
&self,
range: impl RangeBounds<BlockNumber>,
) -> ProviderResult<Vec<SealedHeader>> {
) -> ProviderResult<Vec<SealedHeader<Self::Header>>> {
self.sealed_headers_while(range, |_| true)
}
fn sealed_headers_while(
&self,
range: impl RangeBounds<BlockNumber>,
predicate: impl FnMut(&SealedHeader) -> bool,
) -> ProviderResult<Vec<SealedHeader>> {
predicate: impl FnMut(&SealedHeader<Self::Header>) -> bool,
) -> ProviderResult<Vec<SealedHeader<Self::Header>>> {
self.static_file_provider.get_range_with_static_file_or_database(
StaticFileSegment::Headers,
to_range(range),
@ -385,7 +393,7 @@ impl<N: ProviderNodeTypes> BlockReader for ProviderFactory<N> {
self.provider()?.pending_block_and_receipts()
}
fn ommers(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Vec<Header>>> {
fn ommers(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Vec<Self::Header>>> {
self.provider()?.ommers(id)
}
@ -570,7 +578,7 @@ impl<N: ProviderNodeTypes> StageCheckpointReader for ProviderFactory<N> {
}
}
impl<N: ProviderNodeTypes> EvmEnvProvider for ProviderFactory<N> {
impl<N: ProviderNodeTypes> EvmEnvProvider<HeaderTy<N>> for ProviderFactory<N> {
fn fill_env_at<EvmConfig>(
&self,
cfg: &mut CfgEnvWithHandlerCfg,
@ -579,7 +587,7 @@ impl<N: ProviderNodeTypes> EvmEnvProvider for ProviderFactory<N> {
evm_config: EvmConfig,
) -> ProviderResult<()>
where
EvmConfig: ConfigureEvmEnv<Header = Header>,
EvmConfig: ConfigureEvmEnv<Header = HeaderTy<N>>,
{
self.provider()?.fill_env_at(cfg, block_env, at, evm_config)
}
@ -588,11 +596,11 @@ impl<N: ProviderNodeTypes> EvmEnvProvider for ProviderFactory<N> {
&self,
cfg: &mut CfgEnvWithHandlerCfg,
block_env: &mut BlockEnv,
header: &Header,
header: &HeaderTy<N>,
evm_config: EvmConfig,
) -> ProviderResult<()>
where
EvmConfig: ConfigureEvmEnv<Header = Header>,
EvmConfig: ConfigureEvmEnv<Header = HeaderTy<N>>,
{
self.provider()?.fill_env_with_header(cfg, block_env, header, evm_config)
}
@ -604,7 +612,7 @@ impl<N: ProviderNodeTypes> EvmEnvProvider for ProviderFactory<N> {
evm_config: EvmConfig,
) -> ProviderResult<()>
where
EvmConfig: ConfigureEvmEnv<Header = Header>,
EvmConfig: ConfigureEvmEnv<Header = HeaderTy<N>>,
{
self.provider()?.fill_cfg_env_at(cfg, at, evm_config)
}
@ -612,11 +620,11 @@ impl<N: ProviderNodeTypes> EvmEnvProvider for ProviderFactory<N> {
fn fill_cfg_env_with_header<EvmConfig>(
&self,
cfg: &mut CfgEnvWithHandlerCfg,
header: &Header,
header: &HeaderTy<N>,
evm_config: EvmConfig,
) -> ProviderResult<()>
where
EvmConfig: ConfigureEvmEnv<Header = Header>,
EvmConfig: ConfigureEvmEnv<Header = HeaderTy<N>>,
{
self.provider()?.fill_cfg_env_with_header(cfg, header, evm_config)
}

View File

@ -19,7 +19,7 @@ use crate::{
StorageLocation, StorageReader, StorageTrieWriter, TransactionVariant, TransactionsProvider,
TransactionsProviderExt, TrieWriter, WithdrawalsProvider,
};
use alloy_consensus::Header;
use alloy_consensus::{BlockHeader, Header};
use alloy_eips::{
eip2718::Encodable2718,
eip4895::{Withdrawal, Withdrawals},
@ -50,10 +50,11 @@ use reth_db_api::{
use reth_evm::ConfigureEvmEnv;
use reth_execution_types::{Chain, ExecutionOutcome};
use reth_network_p2p::headers::downloader::SyncTarget;
use reth_node_types::{BlockTy, BodyTy, NodeTypes, ReceiptTy, TxTy};
use reth_node_types::{BlockTy, BodyTy, HeaderTy, NodeTypes, ReceiptTy, TxTy};
use reth_primitives::{
Account, BlockExt, BlockWithSenders, Bytecode, GotExpected, SealedBlock, SealedBlockFor,
SealedBlockWithSenders, SealedHeader, StaticFileSegment, StorageEntry, TransactionMeta,
Account, BlockExt, BlockWithSenders, Bytecode, GotExpected, NodePrimitives, SealedBlock,
SealedBlockFor, SealedBlockWithSenders, SealedHeader, StaticFileSegment, StorageEntry,
TransactionMeta,
};
use reth_primitives_traits::{Block as _, BlockBody as _, SignedTransaction};
use reth_prune_types::{PruneCheckpoint, PruneModes, PruneSegment};
@ -326,7 +327,7 @@ impl<TX: DbTx + DbTxMut + 'static, N: NodeTypesForProvider> DatabaseProvider<TX,
let parent_state_root = self
.header_by_number(parent_number)?
.ok_or_else(|| ProviderError::HeaderNotFound(parent_number.into()))?
.state_root;
.state_root();
// state root should be always correct as we are reverting state.
// but for sake of double verification we will check it again.
@ -420,7 +421,11 @@ impl<TX: DbTx + 'static, N: NodeTypes> StateCommitmentProvider for DatabaseProvi
type StateCommitment = N::StateCommitment;
}
impl<Tx: DbTx + DbTxMut + 'static, N: NodeTypesForProvider + 'static> DatabaseProvider<Tx, N> {
impl<
Tx: DbTx + DbTxMut + 'static,
N: NodeTypesForProvider<Primitives: NodePrimitives<BlockHeader = Header>>,
> DatabaseProvider<Tx, N>
{
// TODO: uncomment below, once `reth debug_cmd` has been feature gated with dev.
// #[cfg(any(test, feature = "test-utils"))]
/// Inserts an historical block. **Used for setting up test environments**
@ -560,8 +565,7 @@ impl<TX: DbTx + 'static, N: NodeTypesForProvider> DatabaseProvider<TX, N> {
construct_block: BF,
) -> ProviderResult<Option<B>>
where
N::ChainSpec: EthereumHardforks,
H: AsRef<Header>,
H: AsRef<HeaderTy<N>>,
HF: FnOnce(BlockNumber) -> ProviderResult<Option<H>>,
BF: FnOnce(H, BodyTy<N>, Vec<Address>) -> ProviderResult<Option<B>>,
{
@ -610,8 +614,7 @@ impl<TX: DbTx + 'static, N: NodeTypesForProvider> DatabaseProvider<TX, N> {
mut assemble_block: F,
) -> ProviderResult<Vec<R>>
where
N::ChainSpec: EthereumHardforks,
H: AsRef<Header>,
H: AsRef<HeaderTy<N>>,
HF: FnOnce(RangeInclusive<BlockNumber>) -> ProviderResult<Vec<H>>,
F: FnMut(H, BodyTy<N>, Range<TxNumber>) -> ProviderResult<R>,
{
@ -634,7 +637,7 @@ impl<TX: DbTx + 'static, N: NodeTypesForProvider> DatabaseProvider<TX, N> {
// have enough information to return the block anyways, so
// we skip the block.
if let Some((_, block_body_indices)) =
block_body_cursor.seek_exact(header.as_ref().number)?
block_body_cursor.seek_exact(header.as_ref().number())?
{
let tx_range = block_body_indices.tx_num_range();
present_headers.push((header, tx_range));
@ -678,8 +681,7 @@ impl<TX: DbTx + 'static, N: NodeTypesForProvider> DatabaseProvider<TX, N> {
assemble_block: BF,
) -> ProviderResult<Vec<B>>
where
N::ChainSpec: EthereumHardforks,
H: AsRef<Header>,
H: AsRef<HeaderTy<N>>,
HF: Fn(RangeInclusive<BlockNumber>) -> ProviderResult<Vec<H>>,
BF: Fn(H, BodyTy<N>, Vec<Address>) -> ProviderResult<B>,
{
@ -943,12 +945,16 @@ impl<TX: DbTx, N: NodeTypes> ChangeSetReader for DatabaseProvider<TX, N> {
}
}
impl<TX: DbTx + 'static, N: NodeTypes> HeaderSyncGapProvider for DatabaseProvider<TX, N> {
impl<TX: DbTx + 'static, N: NodeTypesForProvider> HeaderSyncGapProvider
for DatabaseProvider<TX, N>
{
type Header = HeaderTy<N>;
fn sync_gap(
&self,
tip: watch::Receiver<B256>,
highest_uninterrupted_block: BlockNumber,
) -> ProviderResult<HeaderSyncGap> {
) -> ProviderResult<HeaderSyncGap<Self::Header>> {
let static_file_provider = self.static_file_provider();
// Make sure Headers static file is at the same height. If it's further, this
@ -987,10 +993,10 @@ impl<TX: DbTx + 'static, N: NodeTypes> HeaderSyncGapProvider for DatabaseProvide
}
}
impl<TX: DbTx + 'static, N: NodeTypes<ChainSpec: EthereumHardforks>> HeaderProvider
for DatabaseProvider<TX, N>
{
fn header(&self, block_hash: &BlockHash) -> ProviderResult<Option<Header>> {
impl<TX: DbTx + 'static, N: NodeTypesForProvider> HeaderProvider for DatabaseProvider<TX, N> {
type Header = HeaderTy<N>;
fn header(&self, block_hash: &BlockHash) -> ProviderResult<Option<Self::Header>> {
if let Some(num) = self.block_number(*block_hash)? {
Ok(self.header_by_number(num)?)
} else {
@ -998,12 +1004,12 @@ impl<TX: DbTx + 'static, N: NodeTypes<ChainSpec: EthereumHardforks>> HeaderProvi
}
}
fn header_by_number(&self, num: BlockNumber) -> ProviderResult<Option<Header>> {
fn header_by_number(&self, num: BlockNumber) -> ProviderResult<Option<Self::Header>> {
self.static_file_provider.get_with_static_file_or_database(
StaticFileSegment::Headers,
num,
|static_file| static_file.header_by_number(num),
|| Ok(self.tx.get::<tables::Headers>(num)?),
|| Ok(self.tx.get::<tables::Headers<Self::Header>>(num)?),
)
}
@ -1030,17 +1036,25 @@ impl<TX: DbTx + 'static, N: NodeTypes<ChainSpec: EthereumHardforks>> HeaderProvi
)
}
fn headers_range(&self, range: impl RangeBounds<BlockNumber>) -> ProviderResult<Vec<Header>> {
fn headers_range(
&self,
range: impl RangeBounds<BlockNumber>,
) -> ProviderResult<Vec<Self::Header>> {
self.static_file_provider.get_range_with_static_file_or_database(
StaticFileSegment::Headers,
to_range(range),
|static_file, range, _| static_file.headers_range(range),
|range, _| self.cursor_read_collect::<tables::Headers>(range).map_err(Into::into),
|range, _| {
self.cursor_read_collect::<tables::Headers<Self::Header>>(range).map_err(Into::into)
},
|_| true,
)
}
fn sealed_header(&self, number: BlockNumber) -> ProviderResult<Option<SealedHeader>> {
fn sealed_header(
&self,
number: BlockNumber,
) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
self.static_file_provider.get_with_static_file_or_database(
StaticFileSegment::Headers,
number,
@ -1061,15 +1075,17 @@ impl<TX: DbTx + 'static, N: NodeTypes<ChainSpec: EthereumHardforks>> HeaderProvi
fn sealed_headers_while(
&self,
range: impl RangeBounds<BlockNumber>,
predicate: impl FnMut(&SealedHeader) -> bool,
) -> ProviderResult<Vec<SealedHeader>> {
predicate: impl FnMut(&SealedHeader<Self::Header>) -> bool,
) -> ProviderResult<Vec<SealedHeader<Self::Header>>> {
self.static_file_provider.get_range_with_static_file_or_database(
StaticFileSegment::Headers,
to_range(range),
|static_file, range, predicate| static_file.sealed_headers_while(range, predicate),
|range, mut predicate| {
let mut headers = vec![];
for entry in self.tx.cursor_read::<tables::Headers>()?.walk_range(range)? {
for entry in
self.tx.cursor_read::<tables::Headers<Self::Header>>()?.walk_range(range)?
{
let (number, header) = entry?;
let hash = self
.block_hash(number)?
@ -1210,7 +1226,7 @@ impl<TX: DbTx + 'static, N: NodeTypesForProvider> BlockReader for DatabaseProvid
///
/// If the block is not found, this returns `None`.
/// If the block exists, but doesn't contain ommers, this returns `None`.
fn ommers(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Vec<Header>>> {
fn ommers(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Vec<Self::Header>>> {
if let Some(number) = self.convert_hash_or_number(id)? {
// If the Paris (Merge) hardfork block is known and block is after it, return empty
// ommers.
@ -1218,7 +1234,8 @@ impl<TX: DbTx + 'static, N: NodeTypesForProvider> BlockReader for DatabaseProvid
return Ok(Some(Vec::new()))
}
let ommers = self.tx.get::<tables::BlockOmmers>(number)?.map(|o| o.ommers);
let ommers =
self.tx.get::<tables::BlockOmmers<Self::Header>>(number)?.map(|o| o.ommers);
return Ok(ommers)
}
@ -1450,9 +1467,9 @@ impl<TX: DbTx + 'static, N: NodeTypesForProvider> TransactionsProvider for Datab
index,
block_hash,
block_number,
base_fee: header.base_fee_per_gas,
excess_blob_gas: header.excess_blob_gas,
timestamp: header.timestamp,
base_fee: header.base_fee_per_gas(),
excess_blob_gas: header.excess_blob_gas(),
timestamp: header.timestamp(),
};
return Ok(Some((transaction, meta)))
@ -1618,7 +1635,7 @@ impl<TX: DbTx + 'static, N: NodeTypes<ChainSpec: EthereumHardforks>> Withdrawals
}
}
impl<TX: DbTx + 'static, N: NodeTypes<ChainSpec: EthereumHardforks>> EvmEnvProvider
impl<TX: DbTx + 'static, N: NodeTypesForProvider> EvmEnvProvider<HeaderTy<N>>
for DatabaseProvider<TX, N>
{
fn fill_env_at<EvmConfig>(
@ -1629,7 +1646,7 @@ impl<TX: DbTx + 'static, N: NodeTypes<ChainSpec: EthereumHardforks>> EvmEnvProvi
evm_config: EvmConfig,
) -> ProviderResult<()>
where
EvmConfig: ConfigureEvmEnv<Header = Header>,
EvmConfig: ConfigureEvmEnv<Header = HeaderTy<N>>,
{
let hash = self.convert_number(at)?.ok_or(ProviderError::HeaderNotFound(at))?;
let header = self.header(&hash)?.ok_or(ProviderError::HeaderNotFound(at))?;
@ -1640,15 +1657,15 @@ impl<TX: DbTx + 'static, N: NodeTypes<ChainSpec: EthereumHardforks>> EvmEnvProvi
&self,
cfg: &mut CfgEnvWithHandlerCfg,
block_env: &mut BlockEnv,
header: &Header,
header: &HeaderTy<N>,
evm_config: EvmConfig,
) -> ProviderResult<()>
where
EvmConfig: ConfigureEvmEnv<Header = Header>,
EvmConfig: ConfigureEvmEnv<Header = HeaderTy<N>>,
{
let total_difficulty = self
.header_td_by_number(header.number)?
.ok_or_else(|| ProviderError::HeaderNotFound(header.number.into()))?;
.header_td_by_number(header.number())?
.ok_or_else(|| ProviderError::HeaderNotFound(header.number().into()))?;
evm_config.fill_cfg_and_block_env(cfg, block_env, header, total_difficulty);
Ok(())
}
@ -1660,7 +1677,7 @@ impl<TX: DbTx + 'static, N: NodeTypes<ChainSpec: EthereumHardforks>> EvmEnvProvi
evm_config: EvmConfig,
) -> ProviderResult<()>
where
EvmConfig: ConfigureEvmEnv<Header = Header>,
EvmConfig: ConfigureEvmEnv<Header = HeaderTy<N>>,
{
let hash = self.convert_number(at)?.ok_or(ProviderError::HeaderNotFound(at))?;
let header = self.header(&hash)?.ok_or(ProviderError::HeaderNotFound(at))?;
@ -1670,15 +1687,15 @@ impl<TX: DbTx + 'static, N: NodeTypes<ChainSpec: EthereumHardforks>> EvmEnvProvi
fn fill_cfg_env_with_header<EvmConfig>(
&self,
cfg: &mut CfgEnvWithHandlerCfg,
header: &Header,
header: &HeaderTy<N>,
evm_config: EvmConfig,
) -> ProviderResult<()>
where
EvmConfig: ConfigureEvmEnv<Header = Header>,
EvmConfig: ConfigureEvmEnv<Header = HeaderTy<N>>,
{
let total_difficulty = self
.header_td_by_number(header.number)?
.ok_or_else(|| ProviderError::HeaderNotFound(header.number.into()))?;
.header_td_by_number(header.number())?
.ok_or_else(|| ProviderError::HeaderNotFound(header.number().into()))?;
evm_config.fill_cfg_env(cfg, header, total_difficulty);
Ok(())
}
@ -2813,18 +2830,18 @@ impl<TX: DbTxMut + DbTx + 'static, N: NodeTypesForProvider + 'static> BlockWrite
block: SealedBlockWithSenders<Self::Block>,
write_to: StorageLocation,
) -> ProviderResult<StoredBlockBodyIndices> {
let block_number = block.number;
let block_number = block.number();
let mut durations_recorder = metrics::DurationsRecorder::default();
// total difficulty
let ttd = if block_number == 0 {
block.difficulty
block.difficulty()
} else {
let parent_block_number = block_number - 1;
let parent_ttd = self.header_td_by_number(parent_block_number)?.unwrap_or_default();
durations_recorder.record_relative(metrics::Action::GetParentTD);
parent_ttd + block.difficulty
parent_ttd + block.difficulty()
};
if write_to.database() {
@ -2832,7 +2849,8 @@ impl<TX: DbTxMut + DbTx + 'static, N: NodeTypesForProvider + 'static> BlockWrite
durations_recorder.record_relative(metrics::Action::InsertCanonicalHeaders);
// Put header with canonical hashes.
self.tx.put::<tables::Headers>(block_number, block.header.as_ref().clone())?;
self.tx
.put::<tables::Headers<HeaderTy<N>>>(block_number, block.header.as_ref().clone())?;
durations_recorder.record_relative(metrics::Action::InsertHeaders);
self.tx.put::<tables::HeaderTerminalDifficulties>(block_number, ttd.into())?;
@ -2979,7 +2997,7 @@ impl<TX: DbTxMut + DbTx + 'static, N: NodeTypesForProvider + 'static> BlockWrite
self.tx.delete::<tables::HeaderNumbers>(hash, None)?;
rev_headers.delete_current()?;
}
self.remove::<tables::Headers>(block + 1..)?;
self.remove::<tables::Headers<HeaderTy<N>>>(block + 1..)?;
self.remove::<tables::HeaderTerminalDifficulties>(block + 1..)?;
// First transaction to be removed
@ -3063,10 +3081,10 @@ impl<TX: DbTxMut + DbTx + 'static, N: NodeTypesForProvider + 'static> BlockWrite
return Ok(())
}
let first_number = blocks.first().unwrap().number;
let first_number = blocks.first().unwrap().number();
let last = blocks.last().unwrap();
let last_block_number = last.number;
let last_block_number = last.number();
let mut durations_recorder = metrics::DurationsRecorder::default();

View File

@ -1,6 +1,6 @@
use crate::{
AccountReader, BlockHashReader, BlockIdReader, BlockNumReader, BlockReader, BlockReaderIdExt,
BlockSource, BlockchainTreePendingStateProvider, CanonChainTracker, CanonStateNotifications,
BlockSource, BlockchainTreePendingStateProvider, CanonStateNotifications,
CanonStateSubscriptions, ChainSpecProvider, ChainStateBlockReader, ChangeSetReader,
DatabaseProviderFactory, EvmEnvProvider, FullExecutionDataProvider, HeaderProvider,
NodePrimitivesProvider, ProviderError, PruneCheckpointReader, ReceiptProvider,
@ -14,6 +14,7 @@ use alloy_eips::{
BlockHashOrNumber, BlockId, BlockNumHash, BlockNumberOrTag,
};
use alloy_primitives::{Address, BlockHash, BlockNumber, TxHash, TxNumber, B256, U256};
use alloy_rpc_types_engine::ForkchoiceState;
use reth_blockchain_tree_api::{
error::{CanonicalError, InsertBlockError},
BlockValidationKind, BlockchainTreeEngine, BlockchainTreeViewer, CanonicalOutcome,
@ -24,13 +25,16 @@ use reth_chainspec::{ChainInfo, EthereumHardforks};
use reth_db::table::Value;
use reth_db_api::models::{AccountBeforeTx, StoredBlockBodyIndices};
use reth_evm::ConfigureEvmEnv;
use reth_node_types::{BlockTy, FullNodePrimitives, NodeTypes, NodeTypesWithDB, ReceiptTy, TxTy};
use reth_node_types::{
BlockTy, FullNodePrimitives, HeaderTy, NodeTypes, NodeTypesWithDB, ReceiptTy, TxTy,
};
use reth_primitives::{
Account, BlockWithSenders, EthPrimitives, Receipt, SealedBlock, SealedBlockFor,
SealedBlockWithSenders, SealedHeader, TransactionMeta,
};
use reth_prune_types::{PruneCheckpoint, PruneSegment};
use reth_stages_types::{StageCheckpoint, StageId};
use reth_storage_api::CanonChainTracker;
use reth_storage_errors::provider::ProviderResult;
use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg};
use std::{
@ -61,7 +65,6 @@ mod bundle_state_provider;
pub use bundle_state_provider::BundleStateProvider;
mod consistent_view;
use alloy_rpc_types_engine::ForkchoiceState;
pub use consistent_view::{ConsistentDbView, ConsistentViewError};
mod blockchain_provider;
@ -77,11 +80,7 @@ where
Self: NodeTypes<
ChainSpec: EthereumHardforks,
Storage: ChainStorage<Self::Primitives>,
Primitives: FullNodePrimitives<
SignedTx: Value,
Receipt: Value,
BlockHeader = alloy_consensus::Header,
>,
Primitives: FullNodePrimitives<SignedTx: Value, Receipt: Value, BlockHeader: Value>,
>,
{
}
@ -90,11 +89,7 @@ impl<T> NodeTypesForProvider for T where
T: NodeTypes<
ChainSpec: EthereumHardforks,
Storage: ChainStorage<T::Primitives>,
Primitives: FullNodePrimitives<
SignedTx: Value,
Receipt: Value,
BlockHeader = alloy_consensus::Header,
>,
Primitives: FullNodePrimitives<SignedTx: Value, Receipt: Value, BlockHeader: Value>,
>
{
}
@ -151,7 +146,7 @@ impl<N: NodeTypesWithDB> BlockchainProvider<N> {
}
}
impl<N: ProviderNodeTypes> BlockchainProvider<N> {
impl<N: TreeNodeTypes> BlockchainProvider<N> {
/// Create new provider instance that wraps the database and the blockchain tree, using the
/// provided latest header to initialize the chain info tracker, alongside the finalized header
/// if it exists.
@ -261,7 +256,9 @@ impl<N: ProviderNodeTypes> StaticFileProviderFactory for BlockchainProvider<N> {
}
}
impl<N: ProviderNodeTypes> HeaderProvider for BlockchainProvider<N> {
impl<N: TreeNodeTypes> HeaderProvider for BlockchainProvider<N> {
type Header = Header;
fn header(&self, block_hash: &BlockHash) -> ProviderResult<Option<Header>> {
self.database.header(block_hash)
}
@ -593,7 +590,7 @@ impl<N: ProviderNodeTypes> StageCheckpointReader for BlockchainProvider<N> {
}
}
impl<N: ProviderNodeTypes> EvmEnvProvider for BlockchainProvider<N> {
impl<N: TreeNodeTypes> EvmEnvProvider for BlockchainProvider<N> {
fn fill_env_at<EvmConfig>(
&self,
cfg: &mut CfgEnvWithHandlerCfg,
@ -666,7 +663,7 @@ impl<N: ProviderNodeTypes> ChainSpecProvider for BlockchainProvider<N> {
}
}
impl<N: ProviderNodeTypes> StateProviderFactory for BlockchainProvider<N> {
impl<N: TreeNodeTypes> StateProviderFactory for BlockchainProvider<N> {
/// Storage provider for latest block
fn latest(&self) -> ProviderResult<StateProviderBox> {
trace!(target: "providers::blockchain", "Getting latest block state provider");
@ -840,10 +837,9 @@ impl<N: ProviderNodeTypes> BlockchainTreeViewer for BlockchainProvider<N> {
}
}
impl<N: ProviderNodeTypes> CanonChainTracker for BlockchainProvider<N>
where
Self: BlockReader,
{
impl<N: TreeNodeTypes> CanonChainTracker for BlockchainProvider<N> {
type Header = HeaderTy<N>;
fn on_forkchoice_update_received(&self, _update: &ForkchoiceState) {
// update timestamp
self.chain_info.on_forkchoice_update_received();
@ -874,10 +870,7 @@ where
}
}
impl<N: ProviderNodeTypes> BlockReaderIdExt for BlockchainProvider<N>
where
Self: BlockReader + ReceiptProviderIdExt,
{
impl<N: TreeNodeTypes> BlockReaderIdExt for BlockchainProvider<N> {
fn block_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Block>> {
match id {
BlockId::Number(num) => self.block_by_number_or_tag(num),
@ -896,7 +889,10 @@ where
}
}
fn header_by_number_or_tag(&self, id: BlockNumberOrTag) -> ProviderResult<Option<Header>> {
fn header_by_number_or_tag(
&self,
id: BlockNumberOrTag,
) -> ProviderResult<Option<Self::Header>> {
Ok(match id {
BlockNumberOrTag::Latest => Some(self.chain_info.get_canonical_head().unseal()),
BlockNumberOrTag::Finalized => {
@ -912,7 +908,7 @@ where
fn sealed_header_by_number_or_tag(
&self,
id: BlockNumberOrTag,
) -> ProviderResult<Option<SealedHeader>> {
) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
match id {
BlockNumberOrTag::Latest => Ok(Some(self.chain_info.get_canonical_head())),
BlockNumberOrTag::Finalized => Ok(self.chain_info.get_finalized_header()),
@ -927,21 +923,24 @@ where
}
}
fn sealed_header_by_id(&self, id: BlockId) -> ProviderResult<Option<SealedHeader>> {
fn sealed_header_by_id(
&self,
id: BlockId,
) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
Ok(match id {
BlockId::Number(num) => self.sealed_header_by_number_or_tag(num)?,
BlockId::Hash(hash) => self.header(&hash.block_hash)?.map(SealedHeader::seal),
})
}
fn header_by_id(&self, id: BlockId) -> ProviderResult<Option<Header>> {
fn header_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Header>> {
Ok(match id {
BlockId::Number(num) => self.header_by_number_or_tag(num)?,
BlockId::Hash(hash) => self.header(&hash.block_hash)?,
})
}
fn ommers_by_id(&self, id: BlockId) -> ProviderResult<Option<Vec<Header>>> {
fn ommers_by_id(&self, id: BlockId) -> ProviderResult<Option<Vec<Self::Header>>> {
match id {
BlockId::Number(num) => self.ommers_by_number_or_tag(num),
BlockId::Hash(hash) => {
@ -968,7 +967,9 @@ impl<N: ProviderNodeTypes> CanonStateSubscriptions for BlockchainProvider<N> {
}
}
impl<N: ProviderNodeTypes> ForkChoiceSubscriptions for BlockchainProvider<N> {
impl<N: TreeNodeTypes> ForkChoiceSubscriptions for BlockchainProvider<N> {
type Header = HeaderTy<N>;
fn subscribe_safe_block(&self) -> ForkChoiceNotifications {
let receiver = self.chain_info.subscribe_safe_block();
ForkChoiceNotifications(receiver)

View File

@ -6,7 +6,6 @@ use crate::{
to_range, BlockHashReader, BlockNumReader, HeaderProvider, ReceiptProvider,
TransactionsProvider,
};
use alloy_consensus::Header;
use alloy_eips::{eip2718::Encodable2718, BlockHashOrNumber};
use alloy_primitives::{Address, BlockHash, BlockNumber, TxHash, TxNumber, B256, U256};
use reth_chainspec::ChainInfo;
@ -15,7 +14,7 @@ use reth_db::{
BlockHashMask, HeaderMask, HeaderWithHashMask, ReceiptMask, StaticFileCursor,
TDWithHashMask, TotalDifficultyMask, TransactionMask,
},
table::Decompress,
table::{Decompress, Value},
};
use reth_node_types::NodePrimitives;
use reth_primitives::{transaction::recover_signers, SealedHeader, TransactionMeta};
@ -90,17 +89,19 @@ impl<'a, N: NodePrimitives> StaticFileJarProvider<'a, N> {
}
}
impl<N: NodePrimitives> HeaderProvider for StaticFileJarProvider<'_, N> {
fn header(&self, block_hash: &BlockHash) -> ProviderResult<Option<Header>> {
impl<N: NodePrimitives<BlockHeader: Value>> HeaderProvider for StaticFileJarProvider<'_, N> {
type Header = N::BlockHeader;
fn header(&self, block_hash: &BlockHash) -> ProviderResult<Option<Self::Header>> {
Ok(self
.cursor()?
.get_two::<HeaderWithHashMask<Header>>(block_hash.into())?
.get_two::<HeaderWithHashMask<Self::Header>>(block_hash.into())?
.filter(|(_, hash)| hash == block_hash)
.map(|(header, _)| header))
}
fn header_by_number(&self, num: BlockNumber) -> ProviderResult<Option<Header>> {
self.cursor()?.get_one::<HeaderMask<Header>>(num.into())
fn header_by_number(&self, num: BlockNumber) -> ProviderResult<Option<Self::Header>> {
self.cursor()?.get_one::<HeaderMask<Self::Header>>(num.into())
}
fn header_td(&self, block_hash: &BlockHash) -> ProviderResult<Option<U256>> {
@ -115,14 +116,17 @@ impl<N: NodePrimitives> HeaderProvider for StaticFileJarProvider<'_, N> {
Ok(self.cursor()?.get_one::<TotalDifficultyMask>(num.into())?.map(Into::into))
}
fn headers_range(&self, range: impl RangeBounds<BlockNumber>) -> ProviderResult<Vec<Header>> {
fn headers_range(
&self,
range: impl RangeBounds<BlockNumber>,
) -> ProviderResult<Vec<Self::Header>> {
let range = to_range(range);
let mut cursor = self.cursor()?;
let mut headers = Vec::with_capacity((range.end - range.start) as usize);
for num in range {
if let Some(header) = cursor.get_one::<HeaderMask<Header>>(num.into())? {
if let Some(header) = cursor.get_one::<HeaderMask<Self::Header>>(num.into())? {
headers.push(header);
}
}
@ -130,18 +134,21 @@ impl<N: NodePrimitives> HeaderProvider for StaticFileJarProvider<'_, N> {
Ok(headers)
}
fn sealed_header(&self, number: BlockNumber) -> ProviderResult<Option<SealedHeader>> {
fn sealed_header(
&self,
number: BlockNumber,
) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
Ok(self
.cursor()?
.get_two::<HeaderWithHashMask<Header>>(number.into())?
.get_two::<HeaderWithHashMask<Self::Header>>(number.into())?
.map(|(header, hash)| SealedHeader::new(header, hash)))
}
fn sealed_headers_while(
&self,
range: impl RangeBounds<BlockNumber>,
mut predicate: impl FnMut(&SealedHeader) -> bool,
) -> ProviderResult<Vec<SealedHeader>> {
mut predicate: impl FnMut(&SealedHeader<Self::Header>) -> bool,
) -> ProviderResult<Vec<SealedHeader<Self::Header>>> {
let range = to_range(range);
let mut cursor = self.cursor()?;
@ -149,7 +156,7 @@ impl<N: NodePrimitives> HeaderProvider for StaticFileJarProvider<'_, N> {
for number in range {
if let Some((header, hash)) =
cursor.get_two::<HeaderWithHashMask<Header>>(number.into())?
cursor.get_two::<HeaderWithHashMask<Self::Header>>(number.into())?
{
let sealed = SealedHeader::new(header, hash);
if !predicate(&sealed) {

View File

@ -1235,12 +1235,14 @@ impl<N: NodePrimitives> StaticFileWriter for StaticFileProvider<N> {
}
}
impl<N: NodePrimitives> HeaderProvider for StaticFileProvider<N> {
fn header(&self, block_hash: &BlockHash) -> ProviderResult<Option<Header>> {
impl<N: NodePrimitives<BlockHeader: Value>> HeaderProvider for StaticFileProvider<N> {
type Header = N::BlockHeader;
fn header(&self, block_hash: &BlockHash) -> ProviderResult<Option<Self::Header>> {
self.find_static_file(StaticFileSegment::Headers, |jar_provider| {
Ok(jar_provider
.cursor()?
.get_two::<HeaderWithHashMask<Header>>(block_hash.into())?
.get_two::<HeaderWithHashMask<Self::Header>>(block_hash.into())?
.and_then(|(header, hash)| {
if &hash == block_hash {
return Some(header)
@ -1250,7 +1252,7 @@ impl<N: NodePrimitives> HeaderProvider for StaticFileProvider<N> {
})
}
fn header_by_number(&self, num: BlockNumber) -> ProviderResult<Option<Header>> {
fn header_by_number(&self, num: BlockNumber) -> ProviderResult<Option<Self::Header>> {
self.get_segment_provider_from_block(StaticFileSegment::Headers, num, None)
.and_then(|provider| provider.header_by_number(num))
.or_else(|err| {
@ -1283,16 +1285,22 @@ impl<N: NodePrimitives> HeaderProvider for StaticFileProvider<N> {
})
}
fn headers_range(&self, range: impl RangeBounds<BlockNumber>) -> ProviderResult<Vec<Header>> {
fn headers_range(
&self,
range: impl RangeBounds<BlockNumber>,
) -> ProviderResult<Vec<Self::Header>> {
self.fetch_range_with_predicate(
StaticFileSegment::Headers,
to_range(range),
|cursor, number| cursor.get_one::<HeaderMask<Header>>(number.into()),
|cursor, number| cursor.get_one::<HeaderMask<Self::Header>>(number.into()),
|_| true,
)
}
fn sealed_header(&self, num: BlockNumber) -> ProviderResult<Option<SealedHeader>> {
fn sealed_header(
&self,
num: BlockNumber,
) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
self.get_segment_provider_from_block(StaticFileSegment::Headers, num, None)
.and_then(|provider| provider.sealed_header(num))
.or_else(|err| {
@ -1307,14 +1315,14 @@ impl<N: NodePrimitives> HeaderProvider for StaticFileProvider<N> {
fn sealed_headers_while(
&self,
range: impl RangeBounds<BlockNumber>,
predicate: impl FnMut(&SealedHeader) -> bool,
) -> ProviderResult<Vec<SealedHeader>> {
predicate: impl FnMut(&SealedHeader<Self::Header>) -> bool,
) -> ProviderResult<Vec<SealedHeader<Self::Header>>> {
self.fetch_range_with_predicate(
StaticFileSegment::Headers,
to_range(range),
|cursor, number| {
Ok(cursor
.get_two::<HeaderWithHashMask<Header>>(number.into())?
.get_two::<HeaderWithHashMask<Self::Header>>(number.into())?
.map(|(header, hash)| SealedHeader::new(header, hash)))
},
predicate,
@ -1385,8 +1393,8 @@ impl<N: NodePrimitives<SignedTx: Value + SignedTransaction, Receipt: Value>> Rec
}
}
impl<N: FullNodePrimitives<SignedTx: Value, Receipt: Value>> TransactionsProviderExt
for StaticFileProvider<N>
impl<N: FullNodePrimitives<SignedTx: Value, Receipt: Value, BlockHeader: Value>>
TransactionsProviderExt for StaticFileProvider<N>
{
fn transaction_hashes_by_range(
&self,
@ -1582,7 +1590,9 @@ impl<N: NodePrimitives> BlockNumReader for StaticFileProvider<N> {
}
}
impl<N: FullNodePrimitives<SignedTx: Value, Receipt: Value>> BlockReader for StaticFileProvider<N> {
impl<N: FullNodePrimitives<SignedTx: Value, Receipt: Value, BlockHeader: Value>> BlockReader
for StaticFileProvider<N>
{
type Block = N::Block;
fn find_block_by_hash(
@ -1618,7 +1628,7 @@ impl<N: FullNodePrimitives<SignedTx: Value, Receipt: Value>> BlockReader for Sta
Err(ProviderError::UnsupportedProvider)
}
fn ommers(&self, _id: BlockHashOrNumber) -> ProviderResult<Option<Vec<Header>>> {
fn ommers(&self, _id: BlockHashOrNumber) -> ProviderResult<Option<Vec<Self::Header>>> {
// Required data not present in static_files
Err(ProviderError::UnsupportedProvider)
}

View File

@ -2,7 +2,7 @@ use super::{
manager::StaticFileProviderInner, metrics::StaticFileProviderMetrics, StaticFileProvider,
};
use crate::providers::static_file::metrics::StaticFileProviderOperation;
use alloy_consensus::Header;
use alloy_consensus::BlockHeader;
use alloy_primitives::{BlockHash, BlockNumber, TxNumber, U256};
use parking_lot::{lock_api::RwLockWriteGuard, RawRwLock, RwLock};
use reth_codecs::Compact;
@ -526,16 +526,19 @@ impl<N: NodePrimitives> StaticFileProviderRW<N> {
/// Returns the current [`BlockNumber`] as seen in the static file.
pub fn append_header(
&mut self,
header: &Header,
header: &N::BlockHeader,
total_difficulty: U256,
hash: &BlockHash,
) -> ProviderResult<()> {
) -> ProviderResult<()>
where
N::BlockHeader: Compact,
{
let start = Instant::now();
self.ensure_no_queued_prune()?;
debug_assert!(self.writer.user_header().segment() == StaticFileSegment::Headers);
self.increment_block(header.number)?;
self.increment_block(header.number())?;
self.append_column(header)?;
self.append_column(CompactU256::from(total_difficulty))?;

View File

@ -179,6 +179,8 @@ impl DatabaseProviderFactory for MockEthProvider {
}
impl HeaderProvider for MockEthProvider {
type Header = Header;
fn header(&self, block_hash: &BlockHash) -> ProviderResult<Option<Header>> {
let lock = self.headers.lock();
Ok(lock.get(block_hash).cloned())

View File

@ -284,6 +284,8 @@ impl ReceiptProvider for NoopProvider {
impl ReceiptProviderIdExt for NoopProvider {}
impl HeaderProvider for NoopProvider {
type Header = Header;
fn header(&self, _block_hash: &BlockHash) -> ProviderResult<Option<Header>> {
Ok(None)
}
@ -586,6 +588,8 @@ impl CanonStateSubscriptions for NoopProvider {
}
impl ForkChoiceSubscriptions for NoopProvider {
type Header = Header;
fn subscribe_safe_block(&self) -> ForkChoiceNotifications {
let (_, rx) = watch::channel(None);
ForkChoiceNotifications(rx)

View File

@ -7,7 +7,7 @@ use crate::{
};
use reth_chain_state::{CanonStateSubscriptions, ForkChoiceSubscriptions};
use reth_chainspec::EthereumHardforks;
use reth_node_types::{BlockTy, NodeTypesWithDB, ReceiptTy, TxTy};
use reth_node_types::{BlockTy, HeaderTy, NodeTypesWithDB, ReceiptTy, TxTy};
use reth_storage_api::NodePrimitivesProvider;
/// Helper trait to unify all provider traits for simplicity.
@ -15,14 +15,18 @@ pub trait FullProvider<N: NodeTypesWithDB>:
DatabaseProviderFactory<DB = N::DB>
+ NodePrimitivesProvider<Primitives = N::Primitives>
+ StaticFileProviderFactory
+ BlockReaderIdExt<Transaction = TxTy<N>, Block = BlockTy<N>, Receipt = ReceiptTy<N>>
+ AccountReader
+ BlockReaderIdExt<
Transaction = TxTy<N>,
Block = BlockTy<N>,
Receipt = ReceiptTy<N>,
Header = HeaderTy<N>,
> + AccountReader
+ StateProviderFactory
+ EvmEnvProvider
+ ChainSpecProvider<ChainSpec = N::ChainSpec>
+ ChangeSetReader
+ CanonStateSubscriptions
+ ForkChoiceSubscriptions
+ ForkChoiceSubscriptions<Header = HeaderTy<N>>
+ StageCheckpointReader
+ Clone
+ Unpin
@ -34,14 +38,18 @@ impl<T, N: NodeTypesWithDB> FullProvider<N> for T where
T: DatabaseProviderFactory<DB = N::DB>
+ NodePrimitivesProvider<Primitives = N::Primitives>
+ StaticFileProviderFactory
+ BlockReaderIdExt<Transaction = TxTy<N>, Block = BlockTy<N>, Receipt = ReceiptTy<N>>
+ AccountReader
+ BlockReaderIdExt<
Transaction = TxTy<N>,
Block = BlockTy<N>,
Receipt = ReceiptTy<N>,
Header = HeaderTy<N>,
> + AccountReader
+ StateProviderFactory
+ EvmEnvProvider
+ ChainSpecProvider<ChainSpec = N::ChainSpec>
+ ChangeSetReader
+ CanonStateSubscriptions
+ ForkChoiceSubscriptions
+ ForkChoiceSubscriptions<Header = HeaderTy<N>>
+ StageCheckpointReader
+ Clone
+ Unpin

View File

@ -1,3 +1,4 @@
use alloy_consensus::{BlockHeader, Header};
use alloy_eips::BlockHashOrNumber;
use alloy_primitives::{BlockNumber, B256};
use reth_network_p2p::headers::downloader::SyncTarget;
@ -7,21 +8,21 @@ use tokio::sync::watch;
/// Represents a gap to sync: from `local_head` to `target`
#[derive(Clone, Debug)]
pub struct HeaderSyncGap {
pub struct HeaderSyncGap<H = Header> {
/// The local head block. Represents lower bound of sync range.
pub local_head: SealedHeader,
pub local_head: SealedHeader<H>,
/// The sync target. Represents upper bound of sync range.
pub target: SyncTarget,
}
impl HeaderSyncGap {
impl<H: BlockHeader> HeaderSyncGap<H> {
/// Returns `true` if the gap from the head to the target was closed
#[inline]
pub fn is_closed(&self) -> bool {
match self.target.tip() {
BlockHashOrNumber::Hash(hash) => self.local_head.hash() == hash,
BlockHashOrNumber::Number(num) => self.local_head.number == num,
BlockHashOrNumber::Number(num) => self.local_head.number() == num,
}
}
}
@ -29,6 +30,9 @@ impl HeaderSyncGap {
/// Client trait for determining the current headers sync gap.
#[auto_impl::auto_impl(&, Arc)]
pub trait HeaderSyncGapProvider: Send + Sync {
/// The header type.
type Header: Send + Sync;
/// Find a current sync gap for the headers depending on the last
/// uninterrupted block number. Last uninterrupted block represents the block number before
/// which there are no gaps. It's up to the caller to ensure that last uninterrupted block is
@ -37,5 +41,5 @@ pub trait HeaderSyncGapProvider: Send + Sync {
&self,
tip: watch::Receiver<B256>,
highest_uninterrupted_block: BlockNumber,
) -> ProviderResult<HeaderSyncGap>;
) -> ProviderResult<HeaderSyncGap<Self::Header>>;
}

View File

@ -2,7 +2,6 @@ use crate::{
BlockNumReader, HeaderProvider, ReceiptProvider, ReceiptProviderIdExt, TransactionVariant,
TransactionsProvider, WithdrawalsProvider,
};
use alloy_consensus::Header;
use alloy_eips::{BlockHashOrNumber, BlockId, BlockNumberOrTag};
use alloy_primitives::{BlockNumber, B256};
use reth_db_models::StoredBlockBodyIndices;
@ -57,6 +56,7 @@ pub trait BlockReader:
/// The block type this provider reads.
type Block: reth_primitives_traits::Block<
Body: reth_primitives_traits::BlockBody<Transaction = Self::Transaction>,
Header = Self::Header,
>;
/// Tries to find in the given block source.
@ -98,7 +98,7 @@ pub trait BlockReader:
/// Returns the ommers/uncle headers of the given block from the database.
///
/// Returns `None` if block is not found.
fn ommers(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Vec<Header>>>;
fn ommers(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Vec<Self::Header>>>;
/// Returns the block with matching hash from the database.
///
@ -187,7 +187,7 @@ impl<T: BlockReader> BlockReader for std::sync::Arc<T> {
) -> ProviderResult<Option<(SealedBlockFor<Self::Block>, Vec<Self::Receipt>)>> {
T::pending_block_and_receipts(self)
}
fn ommers(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Vec<Header>>> {
fn ommers(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Vec<Self::Header>>> {
T::ommers(self, id)
}
fn block_by_hash(&self, hash: B256) -> ProviderResult<Option<Self::Block>> {
@ -256,7 +256,7 @@ impl<T: BlockReader> BlockReader for &T {
) -> ProviderResult<Option<(SealedBlockFor<Self::Block>, Vec<Self::Receipt>)>> {
T::pending_block_and_receipts(self)
}
fn ommers(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Vec<Header>>> {
fn ommers(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Vec<Self::Header>>> {
T::ommers(self, id)
}
fn block_by_hash(&self, hash: B256) -> ProviderResult<Option<Self::Block>> {
@ -321,7 +321,7 @@ pub trait BlockReaderIdExt: BlockReader + ReceiptProviderIdExt {
///
/// Note: This returns a [`SealedHeader`] because it's expected that this is sealed by the
/// provider and the caller does not know the hash.
fn pending_header(&self) -> ProviderResult<Option<SealedHeader>> {
fn pending_header(&self) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
self.sealed_header_by_id(BlockNumberOrTag::Pending.into())
}
@ -329,7 +329,7 @@ pub trait BlockReaderIdExt: BlockReader + ReceiptProviderIdExt {
///
/// Note: This returns a [`SealedHeader`] because it's expected that this is sealed by the
/// provider and the caller does not know the hash.
fn latest_header(&self) -> ProviderResult<Option<SealedHeader>> {
fn latest_header(&self) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
self.sealed_header_by_id(BlockNumberOrTag::Latest.into())
}
@ -337,7 +337,7 @@ pub trait BlockReaderIdExt: BlockReader + ReceiptProviderIdExt {
///
/// Note: This returns a [`SealedHeader`] because it's expected that this is sealed by the
/// provider and the caller does not know the hash.
fn safe_header(&self) -> ProviderResult<Option<SealedHeader>> {
fn safe_header(&self) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
self.sealed_header_by_id(BlockNumberOrTag::Safe.into())
}
@ -345,7 +345,7 @@ pub trait BlockReaderIdExt: BlockReader + ReceiptProviderIdExt {
///
/// Note: This returns a [`SealedHeader`] because it's expected that this is sealed by the
/// provider and the caller does not know the hash.
fn finalized_header(&self) -> ProviderResult<Option<SealedHeader>> {
fn finalized_header(&self) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
self.sealed_header_by_id(BlockNumberOrTag::Finalized.into())
}
@ -378,7 +378,10 @@ pub trait BlockReaderIdExt: BlockReader + ReceiptProviderIdExt {
/// Returns the header with matching tag from the database
///
/// Returns `None` if header is not found.
fn header_by_number_or_tag(&self, id: BlockNumberOrTag) -> ProviderResult<Option<Header>> {
fn header_by_number_or_tag(
&self,
id: BlockNumberOrTag,
) -> ProviderResult<Option<Self::Header>> {
self.convert_block_number(id)?
.map_or_else(|| Ok(None), |num| self.header_by_hash_or_number(num.into()))
}
@ -389,7 +392,7 @@ pub trait BlockReaderIdExt: BlockReader + ReceiptProviderIdExt {
fn sealed_header_by_number_or_tag(
&self,
id: BlockNumberOrTag,
) -> ProviderResult<Option<SealedHeader>> {
) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
self.convert_block_number(id)?
.map_or_else(|| Ok(None), |num| self.header_by_hash_or_number(num.into()))?
.map_or_else(|| Ok(None), |h| Ok(Some(SealedHeader::seal(h))))
@ -398,22 +401,28 @@ pub trait BlockReaderIdExt: BlockReader + ReceiptProviderIdExt {
/// Returns the sealed header with the matching `BlockId` from the database.
///
/// Returns `None` if header is not found.
fn sealed_header_by_id(&self, id: BlockId) -> ProviderResult<Option<SealedHeader>>;
fn sealed_header_by_id(
&self,
id: BlockId,
) -> ProviderResult<Option<SealedHeader<Self::Header>>>;
/// Returns the header with the matching `BlockId` from the database.
///
/// Returns `None` if header is not found.
fn header_by_id(&self, id: BlockId) -> ProviderResult<Option<Header>>;
fn header_by_id(&self, id: BlockId) -> ProviderResult<Option<Self::Header>>;
/// Returns the ommers with the matching tag from the database.
fn ommers_by_number_or_tag(&self, id: BlockNumberOrTag) -> ProviderResult<Option<Vec<Header>>> {
fn ommers_by_number_or_tag(
&self,
id: BlockNumberOrTag,
) -> ProviderResult<Option<Vec<Self::Header>>> {
self.convert_block_number(id)?.map_or_else(|| Ok(None), |num| self.ommers(num.into()))
}
/// Returns the ommers with the matching `BlockId` from the database.
///
/// Returns `None` if block is not found.
fn ommers_by_id(&self, id: BlockId) -> ProviderResult<Option<Vec<Header>>>;
fn ommers_by_id(&self, id: BlockId) -> ProviderResult<Option<Vec<Self::Header>>>;
}
/// Functionality to read the last known chain blocks from the database.

View File

@ -4,6 +4,9 @@ use std::time::Instant;
/// A type that can track updates related to fork choice updates.
pub trait CanonChainTracker: Send + Sync {
/// The header type.
type Header: Send + Sync;
/// Notify the tracker about a received fork choice update.
fn on_forkchoice_update_received(&self, update: &ForkchoiceState);
@ -19,11 +22,11 @@ pub trait CanonChainTracker: Send + Sync {
fn last_exchanged_transition_configuration_timestamp(&self) -> Option<Instant>;
/// Sets the canonical head of the chain.
fn set_canonical_head(&self, header: SealedHeader);
fn set_canonical_head(&self, header: SealedHeader<Self::Header>);
/// Sets the safe block of the chain.
fn set_safe(&self, header: SealedHeader);
fn set_safe(&self, header: SealedHeader<Self::Header>);
/// Sets the finalized block of the chain.
fn set_finalized(&self, header: SealedHeader);
fn set_finalized(&self, header: SealedHeader<Self::Header>);
}

View File

@ -1,34 +1,40 @@
use alloy_consensus::Header;
use alloy_eips::BlockHashOrNumber;
use alloy_primitives::{BlockHash, BlockNumber, U256};
use reth_primitives::SealedHeader;
use reth_primitives_traits::BlockHeader;
use reth_storage_errors::provider::ProviderResult;
use std::ops::RangeBounds;
/// Client trait for fetching `Header` related data.
#[auto_impl::auto_impl(&, Arc)]
pub trait HeaderProvider: Send + Sync {
/// The header type this provider supports.
type Header: BlockHeader;
/// Check if block is known
fn is_known(&self, block_hash: &BlockHash) -> ProviderResult<bool> {
self.header(block_hash).map(|header| header.is_some())
}
/// Get header by block hash
fn header(&self, block_hash: &BlockHash) -> ProviderResult<Option<Header>>;
fn header(&self, block_hash: &BlockHash) -> ProviderResult<Option<Self::Header>>;
/// Retrieves the header sealed by the given block hash.
fn sealed_header_by_hash(&self, block_hash: BlockHash) -> ProviderResult<Option<SealedHeader>> {
fn sealed_header_by_hash(
&self,
block_hash: BlockHash,
) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
Ok(self.header(&block_hash)?.map(|header| SealedHeader::new(header, block_hash)))
}
/// Get header by block number
fn header_by_number(&self, num: u64) -> ProviderResult<Option<Header>>;
fn header_by_number(&self, num: u64) -> ProviderResult<Option<Self::Header>>;
/// Get header by block number or hash
fn header_by_hash_or_number(
&self,
hash_or_num: BlockHashOrNumber,
) -> ProviderResult<Option<Header>> {
) -> ProviderResult<Option<Self::Header>> {
match hash_or_num {
BlockHashOrNumber::Hash(hash) => self.header(&hash),
BlockHashOrNumber::Number(num) => self.header_by_number(num),
@ -42,16 +48,22 @@ pub trait HeaderProvider: Send + Sync {
fn header_td_by_number(&self, number: BlockNumber) -> ProviderResult<Option<U256>>;
/// Get headers in range of block numbers
fn headers_range(&self, range: impl RangeBounds<BlockNumber>) -> ProviderResult<Vec<Header>>;
fn headers_range(
&self,
range: impl RangeBounds<BlockNumber>,
) -> ProviderResult<Vec<Self::Header>>;
/// Get a single sealed header by block number.
fn sealed_header(&self, number: BlockNumber) -> ProviderResult<Option<SealedHeader>>;
fn sealed_header(
&self,
number: BlockNumber,
) -> ProviderResult<Option<SealedHeader<Self::Header>>>;
/// Get headers in range of block numbers.
fn sealed_headers_range(
&self,
range: impl RangeBounds<BlockNumber>,
) -> ProviderResult<Vec<SealedHeader>> {
) -> ProviderResult<Vec<SealedHeader<Self::Header>>> {
self.sealed_headers_while(range, |_| true)
}
@ -59,6 +71,6 @@ pub trait HeaderProvider: Send + Sync {
fn sealed_headers_while(
&self,
range: impl RangeBounds<BlockNumber>,
predicate: impl FnMut(&SealedHeader) -> bool,
) -> ProviderResult<Vec<SealedHeader>>;
predicate: impl FnMut(&SealedHeader<Self::Header>) -> bool,
) -> ProviderResult<Vec<SealedHeader<Self::Header>>>;
}