diff --git a/crates/stages/stages/src/stages/mod.rs b/crates/stages/stages/src/stages/mod.rs index 9d7cc685a7ef..955d0d01e5e3 100644 --- a/crates/stages/stages/src/stages/mod.rs +++ b/crates/stages/stages/src/stages/mod.rs @@ -60,8 +60,9 @@ mod tests { use reth_provider::{ providers::{StaticFileProvider, StaticFileWriter}, test_utils::MockNodeTypesWithDB, - AccountExtReader, BlockReader, DatabaseProviderFactory, ProviderFactory, ProviderResult, - ReceiptProvider, StageCheckpointWriter, StaticFileProviderFactory, StorageReader, + AccountExtReader, BlockBodyIndicesProvider, DatabaseProviderFactory, ProviderFactory, + ProviderResult, ReceiptProvider, StageCheckpointWriter, StaticFileProviderFactory, + StorageReader, }; use reth_prune_types::{PruneMode, PruneModes}; use reth_stages_api::{ diff --git a/crates/stages/stages/src/stages/sender_recovery.rs b/crates/stages/stages/src/stages/sender_recovery.rs index 2dcce61b90d0..833246b1b020 100644 --- a/crates/stages/stages/src/stages/sender_recovery.rs +++ b/crates/stages/stages/src/stages/sender_recovery.rs @@ -376,8 +376,8 @@ mod tests { use reth_primitives::{SealedBlock, TransactionSigned}; use reth_primitives_traits::SignedTransaction; use reth_provider::{ - providers::StaticFileWriter, DatabaseProviderFactory, PruneCheckpointWriter, - StaticFileProviderFactory, TransactionsProvider, + providers::StaticFileWriter, BlockBodyIndicesProvider, DatabaseProviderFactory, + PruneCheckpointWriter, StaticFileProviderFactory, TransactionsProvider, }; use reth_prune_types::{PruneCheckpoint, PruneMode}; use reth_stages_api::StageUnitCheckpoint; diff --git a/crates/stages/stages/src/stages/tx_lookup.rs b/crates/stages/stages/src/stages/tx_lookup.rs index fab10b0f9535..90f577360980 100644 --- a/crates/stages/stages/src/stages/tx_lookup.rs +++ b/crates/stages/stages/src/stages/tx_lookup.rs @@ -257,7 +257,8 @@ mod tests { use assert_matches::assert_matches; use reth_primitives::SealedBlock; use reth_provider::{ - providers::StaticFileWriter, DatabaseProviderFactory, StaticFileProviderFactory, + providers::StaticFileWriter, BlockBodyIndicesProvider, DatabaseProviderFactory, + StaticFileProviderFactory, }; use reth_stages_api::StageUnitCheckpoint; use reth_testing_utils::generators::{ diff --git a/crates/storage/provider/src/providers/blockchain_provider.rs b/crates/storage/provider/src/providers/blockchain_provider.rs index 7d5399897894..14cb8108d692 100644 --- a/crates/storage/provider/src/providers/blockchain_provider.rs +++ b/crates/storage/provider/src/providers/blockchain_provider.rs @@ -35,8 +35,8 @@ use reth_primitives_traits::BlockBody as _; use reth_prune_types::{PruneCheckpoint, PruneSegment}; use reth_stages_types::{StageCheckpoint, StageId}; use reth_storage_api::{ - DBProvider, NodePrimitivesProvider, OmmersProvider, StateCommitmentProvider, - StorageChangeSetReader, + BlockBodyIndicesProvider, DBProvider, NodePrimitivesProvider, OmmersProvider, + StateCommitmentProvider, StorageChangeSetReader, }; use reth_storage_errors::provider::ProviderResult; use reth_trie::HashedPostState; @@ -315,13 +315,6 @@ impl BlockReader for BlockchainProvider2 { Ok(self.canonical_in_memory_state.pending_block_and_receipts()) } - fn block_body_indices( - &self, - number: BlockNumber, - ) -> ProviderResult> { - self.consistent_provider()?.block_body_indices(number) - } - /// Returns the block with senders with matching number or hash from database. /// /// **NOTE: If [`TransactionVariant::NoHash`] is provided then the transactions have invalid @@ -481,6 +474,15 @@ impl OmmersProvider for BlockchainProvider2 { } } +impl BlockBodyIndicesProvider for BlockchainProvider2 { + fn block_body_indices( + &self, + number: BlockNumber, + ) -> ProviderResult> { + self.consistent_provider()?.block_body_indices(number) + } +} + impl StageCheckpointReader for BlockchainProvider2 { fn get_stage_checkpoint(&self, id: StageId) -> ProviderResult> { self.consistent_provider()?.get_stage_checkpoint(id) @@ -817,10 +819,10 @@ mod tests { use reth_primitives::{BlockExt, Receipt, SealedBlock, StaticFileSegment}; use reth_primitives_traits::{BlockBody as _, SignedTransaction}; use reth_storage_api::{ - BlockHashReader, BlockIdReader, BlockNumReader, BlockReader, BlockReaderIdExt, BlockSource, - ChangeSetReader, DatabaseProviderFactory, HeaderProvider, OmmersProvider, ReceiptProvider, - ReceiptProviderIdExt, StateProviderFactory, TransactionVariant, TransactionsProvider, - WithdrawalsProvider, + BlockBodyIndicesProvider, BlockHashReader, BlockIdReader, BlockNumReader, BlockReader, + BlockReaderIdExt, BlockSource, ChangeSetReader, DatabaseProviderFactory, HeaderProvider, + OmmersProvider, ReceiptProvider, ReceiptProviderIdExt, StateProviderFactory, + TransactionVariant, TransactionsProvider, WithdrawalsProvider, }; use reth_testing_utils::generators::{ self, random_block, random_block_range, random_changeset_range, random_eoa_accounts, diff --git a/crates/storage/provider/src/providers/consistent.rs b/crates/storage/provider/src/providers/consistent.rs index 643bc2e38984..6d7529d2b4ac 100644 --- a/crates/storage/provider/src/providers/consistent.rs +++ b/crates/storage/provider/src/providers/consistent.rs @@ -28,8 +28,8 @@ use reth_primitives_traits::BlockBody; use reth_prune_types::{PruneCheckpoint, PruneSegment}; use reth_stages_types::{StageCheckpoint, StageId}; use reth_storage_api::{ - DatabaseProviderFactory, NodePrimitivesProvider, OmmersProvider, StateProvider, - StorageChangeSetReader, + BlockBodyIndicesProvider, DatabaseProviderFactory, NodePrimitivesProvider, OmmersProvider, + StateProvider, StorageChangeSetReader, }; use reth_storage_errors::provider::ProviderResult; use revm::{ @@ -841,40 +841,6 @@ impl BlockReader for ConsistentProvider { Ok(self.canonical_in_memory_state.pending_block_and_receipts()) } - fn block_body_indices( - &self, - number: BlockNumber, - ) -> ProviderResult> { - self.get_in_memory_or_storage_by_block( - number.into(), - |db_provider| db_provider.block_body_indices(number), - |block_state| { - // Find the last block indices on database - let last_storage_block_number = block_state.anchor().number; - let mut stored_indices = self - .storage_provider - .block_body_indices(last_storage_block_number)? - .ok_or(ProviderError::BlockBodyIndicesNotFound(last_storage_block_number))?; - - // Prepare our block indices - stored_indices.first_tx_num = stored_indices.next_tx_num(); - stored_indices.tx_count = 0; - - // Iterate from the lowest block in memory until our target block - for state in block_state.chain().collect::>().into_iter().rev() { - let block_tx_count = state.block_ref().block.body.transactions().len() as u64; - if state.block_ref().block().number() == number { - stored_indices.tx_count = block_tx_count; - } else { - stored_indices.first_tx_num += block_tx_count; - } - } - - Ok(Some(stored_indices)) - }, - ) - } - /// Returns the block with senders with matching number or hash from database. /// /// **NOTE: If [`TransactionVariant::NoHash`] is provided then the transactions have invalid @@ -1219,6 +1185,42 @@ impl OmmersProvider for ConsistentProvider { } } +impl BlockBodyIndicesProvider for ConsistentProvider { + fn block_body_indices( + &self, + number: BlockNumber, + ) -> ProviderResult> { + self.get_in_memory_or_storage_by_block( + number.into(), + |db_provider| db_provider.block_body_indices(number), + |block_state| { + // Find the last block indices on database + let last_storage_block_number = block_state.anchor().number; + let mut stored_indices = self + .storage_provider + .block_body_indices(last_storage_block_number)? + .ok_or(ProviderError::BlockBodyIndicesNotFound(last_storage_block_number))?; + + // Prepare our block indices + stored_indices.first_tx_num = stored_indices.next_tx_num(); + stored_indices.tx_count = 0; + + // Iterate from the lowest block in memory until our target block + for state in block_state.chain().collect::>().into_iter().rev() { + let block_tx_count = state.block_ref().block.body.transactions().len() as u64; + if state.block_ref().block().number() == number { + stored_indices.tx_count = block_tx_count; + } else { + stored_indices.first_tx_num += block_tx_count; + } + } + + Ok(Some(stored_indices)) + }, + ) + } +} + impl StageCheckpointReader for ConsistentProvider { fn get_stage_checkpoint(&self, id: StageId) -> ProviderResult> { self.storage_provider.get_stage_checkpoint(id) diff --git a/crates/storage/provider/src/providers/database/mod.rs b/crates/storage/provider/src/providers/database/mod.rs index a6195ff8181c..0241c432019d 100644 --- a/crates/storage/provider/src/providers/database/mod.rs +++ b/crates/storage/provider/src/providers/database/mod.rs @@ -26,7 +26,8 @@ use reth_primitives::{ use reth_prune_types::{PruneCheckpoint, PruneModes, PruneSegment}; use reth_stages_types::{StageCheckpoint, StageId}; use reth_storage_api::{ - NodePrimitivesProvider, OmmersProvider, StateCommitmentProvider, TryIntoHistoricalStateProvider, + BlockBodyIndicesProvider, NodePrimitivesProvider, OmmersProvider, StateCommitmentProvider, + TryIntoHistoricalStateProvider, }; use reth_storage_errors::provider::ProviderResult; use reth_trie::HashedPostState; @@ -404,13 +405,6 @@ impl BlockReader for ProviderFactory { self.provider()?.pending_block_and_receipts() } - fn block_body_indices( - &self, - number: BlockNumber, - ) -> ProviderResult> { - self.provider()?.block_body_indices(number) - } - fn block_with_senders( &self, id: BlockHashOrNumber, @@ -578,6 +572,15 @@ impl OmmersProvider for ProviderFactory { } } +impl BlockBodyIndicesProvider for ProviderFactory { + fn block_body_indices( + &self, + number: BlockNumber, + ) -> ProviderResult> { + self.provider()?.block_body_indices(number) + } +} + impl StageCheckpointReader for ProviderFactory { fn get_stage_checkpoint(&self, id: StageId) -> ProviderResult> { self.provider()?.get_stage_checkpoint(id) diff --git a/crates/storage/provider/src/providers/database/provider.rs b/crates/storage/provider/src/providers/database/provider.rs index f21773d12170..03ece42b6047 100644 --- a/crates/storage/provider/src/providers/database/provider.rs +++ b/crates/storage/provider/src/providers/database/provider.rs @@ -60,8 +60,8 @@ use reth_primitives_traits::{Block as _, BlockBody as _, SignedTransaction}; use reth_prune_types::{PruneCheckpoint, PruneModes, PruneSegment}; use reth_stages_types::{StageCheckpoint, StageId}; use reth_storage_api::{ - BlockBodyReader, NodePrimitivesProvider, OmmersProvider, StateProvider, StorageChangeSetReader, - TryIntoHistoricalStateProvider, + BlockBodyIndicesProvider, BlockBodyReader, NodePrimitivesProvider, OmmersProvider, + StateProvider, StorageChangeSetReader, TryIntoHistoricalStateProvider, }; use reth_storage_errors::provider::{ProviderResult, RootMismatch}; use reth_trie::{ @@ -1222,10 +1222,6 @@ impl BlockReader for DatabaseProvid Ok(None) } - fn block_body_indices(&self, num: u64) -> ProviderResult> { - Ok(self.tx.get::(num)?) - } - /// Returns the block with senders with matching number or hash from database. /// /// **NOTE: The transactions have invalid hashes, since they would need to be calculated on the @@ -1637,6 +1633,14 @@ impl OmmersProvider for DatabasePro } } +impl BlockBodyIndicesProvider + for DatabaseProvider +{ + fn block_body_indices(&self, num: u64) -> ProviderResult> { + Ok(self.tx.get::(num)?) + } +} + impl EvmEnvProvider> for DatabaseProvider { diff --git a/crates/storage/provider/src/providers/mod.rs b/crates/storage/provider/src/providers/mod.rs index 810d6b1c77ad..5a1568d0aca6 100644 --- a/crates/storage/provider/src/providers/mod.rs +++ b/crates/storage/provider/src/providers/mod.rs @@ -37,7 +37,7 @@ use reth_primitives::{ }; use reth_prune_types::{PruneCheckpoint, PruneSegment}; use reth_stages_types::{StageCheckpoint, StageId}; -use reth_storage_api::{CanonChainTracker, OmmersProvider}; +use reth_storage_api::{BlockBodyIndicesProvider, CanonChainTracker, OmmersProvider}; use reth_storage_errors::provider::ProviderResult; use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg}; use std::{ @@ -402,13 +402,6 @@ impl BlockReader for BlockchainProvider { Ok(self.tree.pending_block_and_receipts()) } - fn block_body_indices( - &self, - number: BlockNumber, - ) -> ProviderResult> { - self.database.block_body_indices(number) - } - /// Returns the block with senders with matching number or hash from database. /// /// **NOTE: If [`TransactionVariant::NoHash`] is provided then the transactions have invalid @@ -586,6 +579,15 @@ impl OmmersProvider for BlockchainProvider { } } +impl BlockBodyIndicesProvider for BlockchainProvider { + fn block_body_indices( + &self, + number: BlockNumber, + ) -> ProviderResult> { + self.database.block_body_indices(number) + } +} + impl StageCheckpointReader for BlockchainProvider { fn get_stage_checkpoint(&self, id: StageId) -> ProviderResult> { self.database.provider()?.get_stage_checkpoint(id) diff --git a/crates/storage/provider/src/providers/static_file/manager.rs b/crates/storage/provider/src/providers/static_file/manager.rs index 45f22f3780df..ab6b034fd98c 100644 --- a/crates/storage/provider/src/providers/static_file/manager.rs +++ b/crates/storage/provider/src/providers/static_file/manager.rs @@ -43,7 +43,7 @@ use reth_primitives::{ }; use reth_primitives_traits::SignedTransaction; use reth_stages_types::{PipelineTarget, StageId}; -use reth_storage_api::{DBProvider, OmmersProvider}; +use reth_storage_api::{BlockBodyIndicesProvider, DBProvider, OmmersProvider}; use reth_storage_errors::provider::{ProviderError, ProviderResult}; use std::{ collections::{hash_map::Entry, BTreeMap, HashMap}, @@ -1628,11 +1628,6 @@ impl> Err(ProviderError::UnsupportedProvider) } - fn block_body_indices(&self, _num: u64) -> ProviderResult> { - // Required data not present in static_files - Err(ProviderError::UnsupportedProvider) - } - fn block_with_senders( &self, _id: BlockHashOrNumber, @@ -1694,6 +1689,13 @@ impl> OmmersProvider for StaticFilePro } } +impl BlockBodyIndicesProvider for StaticFileProvider { + fn block_body_indices(&self, _num: u64) -> ProviderResult> { + // Required data not present in static_files + Err(ProviderError::UnsupportedProvider) + } +} + impl StatsReader for StaticFileProvider { fn count_entries(&self) -> ProviderResult { match T::NAME { diff --git a/crates/storage/provider/src/test_utils/mock.rs b/crates/storage/provider/src/test_utils/mock.rs index 7958c4a2d16b..69635a55f63e 100644 --- a/crates/storage/provider/src/test_utils/mock.rs +++ b/crates/storage/provider/src/test_utils/mock.rs @@ -29,8 +29,8 @@ use reth_primitives::{ use reth_primitives_traits::SignedTransaction; use reth_stages_types::{StageCheckpoint, StageId}; use reth_storage_api::{ - DatabaseProviderFactory, HashedPostStateProvider, OmmersProvider, StageCheckpointReader, - StateCommitmentProvider, StateProofProvider, StorageRootProvider, + BlockBodyIndicesProvider, DatabaseProviderFactory, HashedPostStateProvider, OmmersProvider, + StageCheckpointReader, StateCommitmentProvider, StateProofProvider, StorageRootProvider, }; use reth_storage_errors::provider::{ConsistentViewError, ProviderError, ProviderResult}; use reth_trie::{ @@ -510,10 +510,6 @@ impl BlockReader for MockEthProvider { Ok(None) } - fn block_body_indices(&self, _num: u64) -> ProviderResult> { - Ok(None) - } - fn block_with_senders( &self, _id: BlockHashOrNumber, @@ -796,6 +792,12 @@ impl OmmersProvider for MockEthProvider { } } +impl BlockBodyIndicesProvider for MockEthProvider { + fn block_body_indices(&self, _num: u64) -> ProviderResult> { + Ok(None) + } +} + impl ChangeSetReader for MockEthProvider { fn account_block_changeset( &self, diff --git a/crates/storage/storage-api/src/block.rs b/crates/storage/storage-api/src/block.rs index 794e399cae92..5e55042a76c4 100644 --- a/crates/storage/storage-api/src/block.rs +++ b/crates/storage/storage-api/src/block.rs @@ -1,10 +1,9 @@ use crate::{ - BlockNumReader, HeaderProvider, OmmersProvider, ReceiptProvider, ReceiptProviderIdExt, - TransactionVariant, TransactionsProvider, WithdrawalsProvider, + BlockBodyIndicesProvider, BlockNumReader, HeaderProvider, OmmersProvider, ReceiptProvider, + ReceiptProviderIdExt, TransactionVariant, TransactionsProvider, WithdrawalsProvider, }; use alloy_eips::{BlockHashOrNumber, BlockId, BlockNumberOrTag}; use alloy_primitives::{BlockNumber, B256}; -use reth_db_models::StoredBlockBodyIndices; use reth_primitives::{BlockWithSenders, SealedBlockFor, SealedBlockWithSenders, SealedHeader}; use reth_storage_errors::provider::ProviderResult; use std::ops::RangeInclusive; @@ -50,6 +49,7 @@ pub type ProviderBlock

=

::Block; pub trait BlockReader: BlockNumReader + HeaderProvider + + BlockBodyIndicesProvider + TransactionsProvider + ReceiptProvider + WithdrawalsProvider @@ -113,11 +113,6 @@ pub trait BlockReader: self.block(num.into()) } - /// Returns the block body indices with matching number from database. - /// - /// Returns `None` if block is not found. - fn block_body_indices(&self, num: u64) -> ProviderResult>; - /// Returns the block with senders with matching number or hash from database. /// /// Returns the block's transactions in the requested variant. @@ -192,9 +187,6 @@ impl BlockReader for std::sync::Arc { fn block_by_number(&self, num: u64) -> ProviderResult> { T::block_by_number(self, num) } - fn block_body_indices(&self, num: u64) -> ProviderResult> { - T::block_body_indices(self, num) - } fn block_with_senders( &self, id: BlockHashOrNumber, @@ -258,9 +250,6 @@ impl BlockReader for &T { fn block_by_number(&self, num: u64) -> ProviderResult> { T::block_by_number(self, num) } - fn block_body_indices(&self, num: u64) -> ProviderResult> { - T::block_body_indices(self, num) - } fn block_with_senders( &self, id: BlockHashOrNumber, diff --git a/crates/storage/storage-api/src/block_indices.rs b/crates/storage/storage-api/src/block_indices.rs new file mode 100644 index 000000000000..25c37bca8e2c --- /dev/null +++ b/crates/storage/storage-api/src/block_indices.rs @@ -0,0 +1,11 @@ +use reth_db_models::StoredBlockBodyIndices; +use reth_storage_errors::provider::ProviderResult; + +/// Client trait for fetching block body indices related data. +#[auto_impl::auto_impl(&, Arc)] +pub trait BlockBodyIndicesProvider: Send + Sync { + /// Returns the block body indices with matching number from database. + /// + /// Returns `None` if block is not found. + fn block_body_indices(&self, num: u64) -> ProviderResult>; +} diff --git a/crates/storage/storage-api/src/lib.rs b/crates/storage/storage-api/src/lib.rs index 3432c0d029bc..150d745e3bfe 100644 --- a/crates/storage/storage-api/src/lib.rs +++ b/crates/storage/storage-api/src/lib.rs @@ -76,3 +76,6 @@ pub use legacy::*; mod primitives; pub use primitives::*; + +mod block_indices; +pub use block_indices::*; diff --git a/crates/storage/storage-api/src/noop.rs b/crates/storage/storage-api/src/noop.rs index fe481d581ad4..e19776c7d964 100644 --- a/crates/storage/storage-api/src/noop.rs +++ b/crates/storage/storage-api/src/noop.rs @@ -1,12 +1,12 @@ //! Various noop implementations for traits. use crate::{ - AccountReader, BlockHashReader, BlockIdReader, BlockNumReader, BlockReader, BlockReaderIdExt, - BlockSource, ChangeSetReader, HashedPostStateProvider, HeaderProvider, NodePrimitivesProvider, - OmmersProvider, PruneCheckpointReader, ReceiptProvider, ReceiptProviderIdExt, - StageCheckpointReader, StateProofProvider, StateProvider, StateProviderBox, - StateProviderFactory, StateRootProvider, StorageRootProvider, TransactionVariant, - TransactionsProvider, WithdrawalsProvider, + AccountReader, BlockBodyIndicesProvider, BlockHashReader, BlockIdReader, BlockNumReader, + BlockReader, BlockReaderIdExt, BlockSource, ChangeSetReader, HashedPostStateProvider, + HeaderProvider, NodePrimitivesProvider, OmmersProvider, PruneCheckpointReader, ReceiptProvider, + ReceiptProviderIdExt, StageCheckpointReader, StateProofProvider, StateProvider, + StateProviderBox, StateProviderFactory, StateRootProvider, StorageRootProvider, + TransactionVariant, TransactionsProvider, WithdrawalsProvider, }; use alloy_eips::{ eip4895::{Withdrawal, Withdrawals}, @@ -185,10 +185,6 @@ impl BlockReader for NoopProvider { Ok(None) } - fn block_body_indices(&self, _num: u64) -> ProviderResult> { - Ok(None) - } - fn block_with_senders( &self, _id: BlockHashOrNumber, @@ -575,3 +571,9 @@ impl PruneCheckpointReader for NoopProvider NodePrimitivesProvider for NoopProvider { type Primitives = N; } + +impl BlockBodyIndicesProvider for NoopProvider { + fn block_body_indices(&self, _num: u64) -> ProviderResult> { + Ok(None) + } +}