From 871cbc73cb204b7db60a344687c2fe4314d9e1f7 Mon Sep 17 00:00:00 2001 From: frisitano Date: Fri, 18 Oct 2024 02:25:26 +0800 Subject: [PATCH] feat: introduce StateCommitment in StateProviders --- .../commands/debug_cmd/in_memory_merkle.rs | 9 +- bin/reth/src/commands/debug_cmd/merkle.rs | 12 +- crates/exex/exex/src/backfill/test_utils.rs | 15 +- crates/stages/stages/benches/criterion.rs | 10 +- crates/stages/stages/benches/setup/mod.rs | 20 +- crates/stages/stages/src/stages/execution.rs | 17 +- .../stages/src/stages/hashing_account.rs | 3 +- crates/stages/stages/src/test_utils/runner.rs | 10 +- .../src/providers/blockchain_provider.rs | 10 +- .../provider/src/providers/database/mod.rs | 18 +- .../src/providers/database/provider.rs | 235 +++++++++++------- .../src/providers/state/historical.rs | 120 +++++---- .../provider/src/providers/state/latest.rs | 39 +-- .../storage/provider/src/test_utils/blocks.rs | 5 +- .../storage/provider/src/test_utils/mock.rs | 5 +- crates/storage/storage-api/src/state.rs | 7 + crates/trie/db/tests/trie.rs | 8 +- 17 files changed, 342 insertions(+), 201 deletions(-) diff --git a/bin/reth/src/commands/debug_cmd/in_memory_merkle.rs b/bin/reth/src/commands/debug_cmd/in_memory_merkle.rs index 51851c0b0ad2..81c84819af62 100644 --- a/bin/reth/src/commands/debug_cmd/in_memory_merkle.rs +++ b/bin/reth/src/commands/debug_cmd/in_memory_merkle.rs @@ -22,8 +22,8 @@ use reth_node_ethereum::EthExecutorProvider; use reth_primitives::BlockHashOrNumber; use reth_provider::{ writer::UnifiedStorageWriter, AccountExtReader, ChainSpecProvider, HashingWriter, - HeaderProvider, LatestStateProviderRef, OriginalValuesKnown, ProviderFactory, - StageCheckpointReader, StateWriter, StaticFileProviderFactory, StorageReader, + HeaderProvider, OriginalValuesKnown, ProviderFactory, StageCheckpointReader, StateWriter, + StorageReader, ToLatestStateProviderRef, }; use reth_revm::database::StateProviderDatabase; use reth_stages::StageId; @@ -131,10 +131,7 @@ impl> Command { ) .await?; - let db = StateProviderDatabase::new(LatestStateProviderRef::new( - provider.tx_ref(), - provider_factory.static_file_provider(), - )); + let db = StateProviderDatabase::new(provider.latest()); let executor = EthExecutorProvider::ethereum(provider_factory.chain_spec()).executor(db); diff --git a/bin/reth/src/commands/debug_cmd/merkle.rs b/bin/reth/src/commands/debug_cmd/merkle.rs index 8e02a52eaf07..9923321ae1c0 100644 --- a/bin/reth/src/commands/debug_cmd/merkle.rs +++ b/bin/reth/src/commands/debug_cmd/merkle.rs @@ -21,8 +21,8 @@ use reth_node_ethereum::EthExecutorProvider; use reth_primitives::BlockHashOrNumber; use reth_provider::{ writer::UnifiedStorageWriter, BlockNumReader, BlockWriter, ChainSpecProvider, - DatabaseProviderFactory, HeaderProvider, LatestStateProviderRef, OriginalValuesKnown, - ProviderError, ProviderFactory, StateWriter, StaticFileProviderFactory, + DatabaseProviderFactory, HeaderProvider, OriginalValuesKnown, ProviderError, ProviderFactory, + StateWriter, ToLatestStateProviderRef, }; use reth_revm::database::StateProviderDatabase; use reth_stages::{ @@ -152,12 +152,8 @@ impl> Command { provider_rw.insert_block(sealed_block.clone())?; td += sealed_block.difficulty; - let mut executor = executor_provider.batch_executor(StateProviderDatabase::new( - LatestStateProviderRef::new( - provider_rw.tx_ref(), - provider_rw.static_file_provider().clone(), - ), - )); + let mut executor = + executor_provider.batch_executor(StateProviderDatabase::new(provider_rw.latest())); executor.execute_and_verify_one((&sealed_block.clone().unseal(), td).into())?; let execution_outcome = executor.finalize(); diff --git a/crates/exex/exex/src/backfill/test_utils.rs b/crates/exex/exex/src/backfill/test_utils.rs index 1c793975c755..f01afa75398d 100644 --- a/crates/exex/exex/src/backfill/test_utils.rs +++ b/crates/exex/exex/src/backfill/test_utils.rs @@ -14,8 +14,8 @@ use reth_primitives::{ SealedBlockWithSenders, Transaction, }; use reth_provider::{ - providers::ProviderNodeTypes, BlockWriter as _, ExecutionOutcome, LatestStateProviderRef, - ProviderFactory, StaticFileProviderFactory, + providers::ProviderNodeTypes, BlockWriter as _, ExecutionOutcome, ProviderFactory, + ToLatestStateProviderRef, }; use reth_revm::database::StateProviderDatabase; use reth_testing_utils::generators::sign_tx_with_key_pair; @@ -64,10 +64,7 @@ where // Execute the block to produce a block execution output let mut block_execution_output = EthExecutorProvider::ethereum(chain_spec) - .executor(StateProviderDatabase::new(LatestStateProviderRef::new( - provider.tx_ref(), - provider.static_file_provider(), - ))) + .executor(StateProviderDatabase::new(provider.latest())) .execute(BlockExecutionInput { block, total_difficulty: U256::ZERO })?; block_execution_output.state.reverts.sort(); @@ -192,10 +189,8 @@ where let provider = provider_factory.provider()?; - let executor = - EthExecutorProvider::ethereum(chain_spec).batch_executor(StateProviderDatabase::new( - LatestStateProviderRef::new(provider.tx_ref(), provider.static_file_provider()), - )); + let executor = EthExecutorProvider::ethereum(chain_spec) + .batch_executor(StateProviderDatabase::new(provider.latest())); let mut execution_outcome = executor.execute_and_verify_batch(vec![ (&block1, U256::ZERO).into(), diff --git a/crates/stages/stages/benches/criterion.rs b/crates/stages/stages/benches/criterion.rs index 7519d81a3622..9d40f52908a1 100644 --- a/crates/stages/stages/benches/criterion.rs +++ b/crates/stages/stages/benches/criterion.rs @@ -14,6 +14,7 @@ use reth_stages::{ StageCheckpoint, }; use reth_stages_api::{ExecInput, Stage, StageExt, UnwindInput}; +use reth_trie_db::MerklePatriciaTrie; use std::ops::RangeInclusive; use tokio::runtime::Runtime; @@ -148,7 +149,14 @@ fn measure_stage( block_interval: RangeInclusive, label: String, ) where - S: Clone + Stage as Database>::TXMut, ChainSpec>>, + S: Clone + + Stage< + DatabaseProvider< + as Database>::TXMut, + ChainSpec, + MerklePatriciaTrie, + >, + >, F: Fn(S, &TestStageDB, StageRange), { let stage_range = ( diff --git a/crates/stages/stages/benches/setup/mod.rs b/crates/stages/stages/benches/setup/mod.rs index 4812fb13c39a..bbb3e29096f9 100644 --- a/crates/stages/stages/benches/setup/mod.rs +++ b/crates/stages/stages/benches/setup/mod.rs @@ -26,12 +26,19 @@ mod constants; mod account_hashing; pub use account_hashing::*; use reth_stages_api::{ExecInput, Stage, UnwindInput}; -use reth_trie_db::DatabaseStateRoot; +use reth_trie_db::{DatabaseStateRoot, MerklePatriciaTrie}; pub(crate) type StageRange = (ExecInput, UnwindInput); pub(crate) fn stage_unwind< - S: Clone + Stage as Database>::TXMut, ChainSpec>>, + S: Clone + + Stage< + DatabaseProvider< + as Database>::TXMut, + ChainSpec, + MerklePatriciaTrie, + >, + >, >( stage: S, db: &TestStageDB, @@ -63,7 +70,14 @@ pub(crate) fn stage_unwind< pub(crate) fn unwind_hashes(stage: S, db: &TestStageDB, range: StageRange) where - S: Clone + Stage as Database>::TXMut, ChainSpec>>, + S: Clone + + Stage< + DatabaseProvider< + as Database>::TXMut, + ChainSpec, + MerklePatriciaTrie, + >, + >, { let (input, unwind) = range; diff --git a/crates/stages/stages/src/stages/execution.rs b/crates/stages/stages/src/stages/execution.rs index 7bb6ebc59e09..3a6e16a3396e 100644 --- a/crates/stages/stages/src/stages/execution.rs +++ b/crates/stages/stages/src/stages/execution.rs @@ -15,8 +15,8 @@ use reth_primitives_traits::format_gas_throughput; use reth_provider::{ providers::{StaticFileProvider, StaticFileProviderRWRefMut, StaticFileWriter}, writer::UnifiedStorageWriter, - BlockReader, DBProvider, HeaderProvider, LatestStateProviderRef, OriginalValuesKnown, - ProviderError, StateChangeWriter, StateWriter, StaticFileProviderFactory, StatsReader, + BlockReader, DBProvider, HeaderProvider, OriginalValuesKnown, ProviderError, StateChangeWriter, + StateWriter, StaticFileProviderFactory, StatsReader, ToLatestStateProviderRef, TransactionVariant, }; use reth_prune_types::PruneModes; @@ -174,8 +174,12 @@ impl ExecutionStage { impl Stage for ExecutionStage where E: BlockExecutorProvider, - Provider: - DBProvider + BlockReader + StaticFileProviderFactory + StatsReader + StateChangeWriter, + Provider: DBProvider + + BlockReader + + StaticFileProviderFactory + + StatsReader + + StateChangeWriter + + ToLatestStateProviderRef, for<'a> UnifiedStorageWriter<'a, Provider, StaticFileProviderRWRefMut<'a>>: StateWriter, { /// Return the id of the stage @@ -219,10 +223,7 @@ where None }; - let db = StateProviderDatabase(LatestStateProviderRef::new( - provider.tx_ref(), - provider.static_file_provider(), - )); + let db = StateProviderDatabase(provider.latest()); let mut executor = self.executor_provider.batch_executor(db); executor.set_tip(max_block); executor.set_prune_modes(prune_modes); diff --git a/crates/stages/stages/src/stages/hashing_account.rs b/crates/stages/stages/src/stages/hashing_account.rs index 14afb37d81db..0087eae3e99c 100644 --- a/crates/stages/stages/src/stages/hashing_account.rs +++ b/crates/stages/stages/src/stages/hashing_account.rs @@ -61,8 +61,9 @@ impl AccountHashingStage { pub fn seed< Tx: DbTx + DbTxMut + 'static, Spec: Send + Sync + 'static + reth_chainspec::EthereumHardforks, + SC: Send + Sync + 'static, >( - provider: &reth_provider::DatabaseProvider, + provider: &reth_provider::DatabaseProvider, opts: SeedOpts, ) -> Result, StageError> { use alloy_primitives::U256; diff --git a/crates/stages/stages/src/test_utils/runner.rs b/crates/stages/stages/src/test_utils/runner.rs index 26f245c1304d..b5f91e8664b5 100644 --- a/crates/stages/stages/src/test_utils/runner.rs +++ b/crates/stages/stages/src/test_utils/runner.rs @@ -6,6 +6,7 @@ use reth_stages_api::{ ExecInput, ExecOutput, Stage, StageError, StageExt, UnwindInput, UnwindOutput, }; use reth_storage_errors::db::DatabaseError; +use reth_trie_db::MerklePatriciaTrie; use tokio::sync::oneshot; #[derive(thiserror::Error, Debug)] @@ -20,8 +21,13 @@ pub(crate) enum TestRunnerError { /// A generic test runner for stages. pub(crate) trait StageTestRunner { - type S: Stage as Database>::TXMut, ChainSpec>> - + 'static; + type S: Stage< + DatabaseProvider< + as Database>::TXMut, + ChainSpec, + MerklePatriciaTrie, + >, + > + 'static; /// Return a reference to the database. fn db(&self) -> &TestStageDB; diff --git a/crates/storage/provider/src/providers/blockchain_provider.rs b/crates/storage/provider/src/providers/blockchain_provider.rs index 9e6f32b33a3b..6e39a3697b30 100644 --- a/crates/storage/provider/src/providers/blockchain_provider.rs +++ b/crates/storage/provider/src/providers/blockchain_provider.rs @@ -302,7 +302,7 @@ impl BlockchainProvider2 { ) -> ProviderResult> where F: FnOnce( - &DatabaseProviderRO, + &DatabaseProviderRO, RangeInclusive, &mut P, ) -> ProviderResult>, @@ -418,7 +418,7 @@ impl BlockchainProvider2 { ) -> ProviderResult> where S: FnOnce( - DatabaseProviderRO, + DatabaseProviderRO, RangeInclusive, ) -> ProviderResult>, M: Fn(RangeInclusive, Arc) -> ProviderResult>, @@ -516,7 +516,9 @@ impl BlockchainProvider2 { fetch_from_block_state: M, ) -> ProviderResult> where - S: FnOnce(DatabaseProviderRO) -> ProviderResult>, + S: FnOnce( + DatabaseProviderRO, + ) -> ProviderResult>, M: Fn(usize, TxNumber, Arc) -> ProviderResult>, { // Order of instantiation matters. More information on: @@ -585,7 +587,7 @@ impl BlockchainProvider2 { fetch_from_block_state: M, ) -> ProviderResult where - S: FnOnce(DatabaseProviderRO) -> ProviderResult, + S: FnOnce(DatabaseProviderRO) -> ProviderResult, M: Fn(Arc) -> ProviderResult, { let block_state = match id { diff --git a/crates/storage/provider/src/providers/database/mod.rs b/crates/storage/provider/src/providers/database/mod.rs index 520b514527b2..62e04c2cf651 100644 --- a/crates/storage/provider/src/providers/database/mod.rs +++ b/crates/storage/provider/src/providers/database/mod.rs @@ -130,7 +130,9 @@ impl ProviderFactory { /// This sets the [`PruneModes`] to [`None`], because they should only be relevant for writing /// data. #[track_caller] - pub fn provider(&self) -> ProviderResult> { + pub fn provider( + &self, + ) -> ProviderResult> { Ok(DatabaseProvider::new( self.db.tx()?, self.chain_spec.clone(), @@ -144,7 +146,9 @@ impl ProviderFactory { /// [`BlockHashReader`]. This may fail if the inner read/write database transaction fails to /// open. #[track_caller] - pub fn provider_rw(&self) -> ProviderResult> { + pub fn provider_rw( + &self, + ) -> ProviderResult> { Ok(DatabaseProviderRW(DatabaseProvider::new_rw( self.db.tx_mut()?, self.chain_spec.clone(), @@ -157,7 +161,10 @@ impl ProviderFactory { #[track_caller] pub fn latest(&self) -> ProviderResult { trace!(target: "providers::db", "Returning latest state provider"); - Ok(Box::new(LatestStateProvider::new(self.db.tx()?, self.static_file_provider()))) + Ok(Box::new(LatestStateProvider::<_, N::StateCommitment>::new( + self.db.tx()?, + self.static_file_provider(), + ))) } /// Storage provider for state at that given block @@ -186,8 +193,9 @@ impl ProviderFactory { impl DatabaseProviderFactory for ProviderFactory { type DB = N::DB; - type Provider = DatabaseProvider<::TX, N::ChainSpec>; - type ProviderRW = DatabaseProvider<::TXMut, N::ChainSpec>; + type Provider = DatabaseProvider<::TX, N::ChainSpec, N::StateCommitment>; + type ProviderRW = + DatabaseProvider<::TXMut, N::ChainSpec, N::StateCommitment>; fn database_provider_ro(&self) -> ProviderResult { self.provider() diff --git a/crates/storage/provider/src/providers/database/provider.rs b/crates/storage/provider/src/providers/database/provider.rs index 8140700fabac..1c3042d5e4a6 100644 --- a/crates/storage/provider/src/providers/database/provider.rs +++ b/crates/storage/provider/src/providers/database/provider.rs @@ -13,8 +13,9 @@ use crate::{ LatestStateProvider, LatestStateProviderRef, OriginalValuesKnown, ProviderError, PruneCheckpointReader, PruneCheckpointWriter, RequestsProvider, RevertsInit, StageCheckpointReader, StateChangeWriter, StateProviderBox, StateReader, StateWriter, - StaticFileProviderFactory, StatsReader, StorageReader, StorageTrieWriter, TransactionVariant, - TransactionsProvider, TransactionsProviderExt, TrieWriter, WithdrawalsProvider, + StaticFileProviderFactory, StatsReader, StorageReader, StorageTrieWriter, + ToLatestStateProviderRef, TransactionVariant, TransactionsProvider, TransactionsProviderExt, + TrieWriter, WithdrawalsProvider, }; use alloy_eips::BlockHashOrNumber; use alloy_primitives::{keccak256, Address, BlockHash, BlockNumber, TxHash, TxNumber, B256, U256}; @@ -54,7 +55,7 @@ use reth_trie::{ updates::{StorageTrieUpdates, TrieUpdates}, HashedPostStateSorted, Nibbles, StateRoot, StoredNibbles, }; -use reth_trie_db::{DatabaseStateRoot, DatabaseStorageTrieCursor}; +use reth_trie_db::{DatabaseStateRoot, DatabaseStorageTrieCursor, StateCommitment}; use revm::{ db::states::{PlainStateReverts, PlainStorageChangeset, PlainStorageRevert, StateChangeset}, primitives::{BlockEnv, CfgEnvWithHandlerCfg}, @@ -63,6 +64,7 @@ use std::{ cmp::Ordering, collections::{hash_map, BTreeMap, BTreeSet, HashMap, HashSet}, fmt::Debug, + marker::PhantomData, ops::{Bound, Deref, DerefMut, Range, RangeBounds, RangeInclusive}, sync::{mpsc, Arc}, time::{Duration, Instant}, @@ -71,40 +73,40 @@ use tokio::sync::watch; use tracing::{debug, error, trace, warn}; /// A [`DatabaseProvider`] that holds a read-only database transaction. -pub type DatabaseProviderRO = DatabaseProvider<::TX, Spec>; +pub type DatabaseProviderRO = DatabaseProvider<::TX, Spec, SC>; /// A [`DatabaseProvider`] that holds a read-write database transaction. /// /// Ideally this would be an alias type. However, there's some weird compiler error (), that forces us to wrap this in a struct instead. /// Once that issue is solved, we can probably revert back to being an alias type. #[derive(Debug)] -pub struct DatabaseProviderRW( - pub DatabaseProvider<::TXMut, Spec>, +pub struct DatabaseProviderRW( + pub DatabaseProvider<::TXMut, Spec, SC>, ); -impl Deref for DatabaseProviderRW { - type Target = DatabaseProvider<::TXMut, Spec>; +impl Deref for DatabaseProviderRW { + type Target = DatabaseProvider<::TXMut, Spec, SC>; fn deref(&self) -> &Self::Target { &self.0 } } -impl DerefMut for DatabaseProviderRW { +impl DerefMut for DatabaseProviderRW { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } -impl AsRef::TXMut, Spec>> - for DatabaseProviderRW +impl AsRef::TXMut, Spec, SC>> + for DatabaseProviderRW { - fn as_ref(&self) -> &DatabaseProvider<::TXMut, Spec> { + fn as_ref(&self) -> &DatabaseProvider<::TXMut, Spec, SC> { &self.0 } } -impl DatabaseProviderRW { +impl DatabaseProviderRW { /// Commit database transaction and static file if it exists. pub fn commit(self) -> ProviderResult { self.0.commit() @@ -116,10 +118,10 @@ impl DatabaseProviderRW { } } -impl From> - for DatabaseProvider<::TXMut, Spec> +impl From> + for DatabaseProvider<::TXMut, Spec, SC> { - fn from(provider: DatabaseProviderRW) -> Self { + fn from(provider: DatabaseProviderRW) -> Self { provider.0 } } @@ -127,7 +129,7 @@ impl From> /// A provider struct that fetches data from the database. /// Wrapper around [`DbTx`] and [`DbTxMut`]. Example: [`HeaderProvider`] [`BlockHashReader`] #[derive(Debug)] -pub struct DatabaseProvider { +pub struct DatabaseProvider { /// Database transaction. tx: TX, /// Chain spec @@ -136,22 +138,18 @@ pub struct DatabaseProvider { static_file_provider: StaticFileProvider, /// Pruning configuration prune_modes: PruneModes, + /// Marker to associate the `StateCommitment` type with this provider. + _marker: std::marker::PhantomData, } -impl DatabaseProvider { +impl DatabaseProvider { /// Returns reference to prune modes. pub const fn prune_modes_ref(&self) -> &PruneModes { &self.prune_modes } } -impl DatabaseProvider { - /// State provider for latest block - pub fn latest<'a>(&'a self) -> ProviderResult> { - trace!(target: "providers::db", "Returning latest state provider"); - Ok(Box::new(LatestStateProviderRef::new(&self.tx, self.static_file_provider.clone()))) - } - +impl DatabaseProvider { /// Storage provider for state at that given block hash pub fn history_by_block_hash<'a>( &'a self, @@ -162,7 +160,7 @@ impl DatabaseProvider { if block_number == self.best_block_number().unwrap_or_default() && block_number == self.last_block_number().unwrap_or_default() { - return Ok(Box::new(LatestStateProviderRef::new( + return Ok(Box::new(LatestStateProviderRef::<'_, _, SC>::new( &self.tx, self.static_file_provider.clone(), ))) @@ -176,7 +174,7 @@ impl DatabaseProvider { let storage_history_prune_checkpoint = self.get_prune_checkpoint(PruneSegment::StorageHistory)?; - let mut state_provider = HistoricalStateProviderRef::new( + let mut state_provider = HistoricalStateProviderRef::<'_, _, SC>::new( &self.tx, block_number, self.static_file_provider.clone(), @@ -203,15 +201,15 @@ impl DatabaseProvider { } } -impl StaticFileProviderFactory for DatabaseProvider { +impl StaticFileProviderFactory for DatabaseProvider { /// Returns a static file provider fn static_file_provider(&self) -> StaticFileProvider { self.static_file_provider.clone() } } -impl ChainSpecProvider - for DatabaseProvider +impl ChainSpecProvider + for DatabaseProvider { type ChainSpec = Spec; @@ -220,7 +218,7 @@ impl ChainSpecProvider } } -impl DatabaseProvider { +impl DatabaseProvider { /// Creates a provider with an inner read-write transaction. pub const fn new_rw( tx: TX, @@ -228,18 +226,18 @@ impl DatabaseProvider { static_file_provider: StaticFileProvider, prune_modes: PruneModes, ) -> Self { - Self { tx, chain_spec, static_file_provider, prune_modes } + Self { tx, chain_spec, static_file_provider, prune_modes, _marker: PhantomData } } } -impl AsRef for DatabaseProvider { +impl AsRef for DatabaseProvider { fn as_ref(&self) -> &Self { self } } -impl TryIntoHistoricalStateProvider - for DatabaseProvider +impl TryIntoHistoricalStateProvider + for DatabaseProvider { fn try_into_history_at_block( self, @@ -248,7 +246,10 @@ impl TryIntoHistoricalStateProvider if block_number == self.best_block_number().unwrap_or_default() && block_number == self.last_block_number().unwrap_or_default() { - return Ok(Box::new(LatestStateProvider::new(self.tx, self.static_file_provider))) + return Ok(Box::new(LatestStateProvider::<_, SC>::new( + self.tx, + self.static_file_provider, + ))) } // +1 as the changeset that we want is the one that was applied after this block. @@ -260,7 +261,7 @@ impl TryIntoHistoricalStateProvider self.get_prune_checkpoint(PruneSegment::StorageHistory)?; let mut state_provider = - HistoricalStateProvider::new(self.tx, block_number, self.static_file_provider); + HistoricalStateProvider::<_, SC>::new(self.tx, block_number, self.static_file_provider); // If we pruned account or storage history, we can't return state on every historical block. // Instead, we should cap it at the latest prune checkpoint for corresponding prune segment. @@ -283,8 +284,24 @@ impl TryIntoHistoricalStateProvider } } -impl - DatabaseProvider +impl ToLatestStateProviderRef + for DatabaseProvider +{ + /// State provider for latest block + fn latest<'a>(&'a self) -> Box { + trace!(target: "providers::db", "Returning latest state provider"); + Box::new(LatestStateProviderRef::<'_, _, SC>::new( + &self.tx, + self.static_file_provider.clone(), + )) + } +} + +impl< + Tx: DbTx + DbTxMut + 'static, + Spec: Send + Sync + EthereumHardforks + 'static, + SC: Send + Sync + 'static, + > DatabaseProvider { // TODO: uncomment below, once `reth debug_cmd` has been feature gated with dev. // #[cfg(any(test, feature = "test-utils"))] @@ -366,7 +383,7 @@ where Ok(Vec::new()) } -impl DatabaseProvider { +impl DatabaseProvider { /// Creates a provider with an inner read-only transaction. pub const fn new( tx: TX, @@ -374,7 +391,7 @@ impl DatabaseProvider { static_file_provider: StaticFileProvider, prune_modes: PruneModes, ) -> Self { - Self { tx, chain_spec, static_file_provider, prune_modes } + Self { tx, chain_spec, static_file_provider, prune_modes, _marker: PhantomData } } /// Consume `DbTx` or `DbTxMut`. @@ -1037,7 +1054,7 @@ impl DatabaseProvider { } } -impl DatabaseProvider { +impl DatabaseProvider { /// Commit database transaction. pub fn commit(self) -> ProviderResult { Ok(self.tx.commit()?) @@ -1423,13 +1440,17 @@ impl DatabaseProvider { } } -impl AccountReader for DatabaseProvider { +impl AccountReader + for DatabaseProvider +{ fn basic_account(&self, address: Address) -> ProviderResult> { Ok(self.tx.get::(address)?) } } -impl AccountExtReader for DatabaseProvider { +impl AccountExtReader + for DatabaseProvider +{ fn changed_accounts_with_range( &self, range: impl RangeBounds, @@ -1473,7 +1494,9 @@ impl AccountExtReader for DatabaseProvider StorageChangeSetReader for DatabaseProvider { +impl StorageChangeSetReader + for DatabaseProvider +{ fn storage_changeset( &self, block_number: BlockNumber, @@ -1488,7 +1511,9 @@ impl StorageChangeSetReader for DatabaseProvider ChangeSetReader for DatabaseProvider { +impl ChangeSetReader + for DatabaseProvider +{ fn account_block_changeset( &self, block_number: BlockNumber, @@ -1505,7 +1530,9 @@ impl ChangeSetReader for DatabaseProvider } } -impl HeaderSyncGapProvider for DatabaseProvider { +impl HeaderSyncGapProvider + for DatabaseProvider +{ fn sync_gap( &self, tip: watch::Receiver, @@ -1549,8 +1576,8 @@ impl HeaderSyncGapProvider for DatabaseProvider HeaderProvider - for DatabaseProvider +impl HeaderProvider + for DatabaseProvider { fn header(&self, block_hash: &BlockHash) -> ProviderResult> { if let Some(num) = self.block_number(*block_hash)? { @@ -1649,7 +1676,9 @@ impl HeaderProvider } } -impl BlockHashReader for DatabaseProvider { +impl BlockHashReader + for DatabaseProvider +{ fn block_hash(&self, number: u64) -> ProviderResult> { self.static_file_provider.get_with_static_file_or_database( StaticFileSegment::Headers, @@ -1676,7 +1705,9 @@ impl BlockHashReader for DatabaseProvider } } -impl BlockNumReader for DatabaseProvider { +impl BlockNumReader + for DatabaseProvider +{ fn chain_info(&self) -> ProviderResult { let best_number = self.best_block_number()?; let best_hash = self.block_hash(best_number)?.unwrap_or_default(); @@ -1707,7 +1738,9 @@ impl BlockNumReader for DatabaseProvider } } -impl BlockReader for DatabaseProvider { +impl BlockReader + for DatabaseProvider +{ fn find_block_by_hash(&self, hash: B256, source: BlockSource) -> ProviderResult> { if source.is_canonical() { self.block(hash.into()) @@ -1892,8 +1925,8 @@ impl BlockReader for DatabasePr } } -impl TransactionsProviderExt - for DatabaseProvider +impl TransactionsProviderExt + for DatabaseProvider { /// Recovers transaction hashes by walking through `Transactions` table and /// calculating them in a parallel manner. Returned unsorted. @@ -1962,8 +1995,8 @@ impl TransactionsProviderExt } // Calculates the hash of the given transaction -impl TransactionsProvider - for DatabaseProvider +impl TransactionsProvider + for DatabaseProvider { fn transaction_id(&self, tx_hash: TxHash) -> ProviderResult> { Ok(self.tx.get::(tx_hash)?) @@ -2122,8 +2155,8 @@ impl TransactionsProvider } } -impl ReceiptProvider - for DatabaseProvider +impl ReceiptProvider + for DatabaseProvider { fn receipt(&self, id: TxNumber) -> ProviderResult> { self.static_file_provider.get_with_static_file_or_database( @@ -2170,8 +2203,8 @@ impl ReceiptProvider } } -impl WithdrawalsProvider - for DatabaseProvider +impl WithdrawalsProvider + for DatabaseProvider { fn withdrawals_by_block( &self, @@ -2200,8 +2233,8 @@ impl WithdrawalsProvider } } -impl RequestsProvider - for DatabaseProvider +impl RequestsProvider + for DatabaseProvider { fn requests_by_block( &self, @@ -2218,8 +2251,8 @@ impl RequestsProvider } } -impl EvmEnvProvider - for DatabaseProvider +impl EvmEnvProvider + for DatabaseProvider { fn fill_env_at( &self, @@ -2284,7 +2317,9 @@ impl EvmEnvProvider } } -impl StageCheckpointReader for DatabaseProvider { +impl StageCheckpointReader + for DatabaseProvider +{ fn get_stage_checkpoint(&self, id: StageId) -> ProviderResult> { Ok(self.tx.get::(id.to_string())?) } @@ -2303,7 +2338,9 @@ impl StageCheckpointReader for DatabaseProvider StageCheckpointWriter for DatabaseProvider { +impl StageCheckpointWriter + for DatabaseProvider +{ /// Save stage checkpoint. fn save_stage_checkpoint( &self, @@ -2344,7 +2381,9 @@ impl StageCheckpointWriter for DatabaseProvider< } } -impl StorageReader for DatabaseProvider { +impl StorageReader + for DatabaseProvider +{ fn plain_state_storages( &self, addresses_with_keys: impl IntoIterator)>, @@ -2407,7 +2446,9 @@ impl StorageReader for DatabaseProvider { } } -impl StateChangeWriter for DatabaseProvider { +impl StateChangeWriter + for DatabaseProvider +{ fn write_state_reverts( &self, reverts: PlainStateReverts, @@ -2784,7 +2825,9 @@ impl StateChangeWriter for DatabaseProvid } } -impl TrieWriter for DatabaseProvider { +impl TrieWriter + for DatabaseProvider +{ /// Writes trie updates. Returns the number of entries modified. fn write_trie_updates(&self, trie_updates: &TrieUpdates) -> ProviderResult { if trie_updates.is_empty() { @@ -2834,7 +2877,9 @@ impl TrieWriter for DatabaseProvider StorageTrieWriter for DatabaseProvider { +impl StorageTrieWriter + for DatabaseProvider +{ /// Writes storage trie updates from the given storage trie map. First sorts the storage trie /// updates by the hashed address, writing in sorted order. fn write_storage_trie_updates( @@ -2871,7 +2916,9 @@ impl StorageTrieWriter for DatabaseProvid } } -impl HashingWriter for DatabaseProvider { +impl HashingWriter + for DatabaseProvider +{ fn unwind_account_hashing( &self, range: RangeInclusive, @@ -3077,7 +3124,9 @@ impl HashingWriter for DatabaseProvider HistoryWriter for DatabaseProvider { +impl HistoryWriter + for DatabaseProvider +{ fn unwind_account_history_indices( &self, range: RangeInclusive, @@ -3193,8 +3242,8 @@ impl HistoryWriter for DatabaseProvider BlockExecutionReader - for DatabaseProvider +impl BlockExecutionReader + for DatabaseProvider { fn get_block_and_execution_range( &self, @@ -3210,14 +3259,17 @@ impl BlockExecutionReader } } -impl StateReader for DatabaseProvider { +impl StateReader for DatabaseProvider { fn get_state(&self, block: BlockNumber) -> ProviderResult> { self.get_state(block..=block) } } -impl - BlockExecutionWriter for DatabaseProvider +impl< + TX: DbTxMut + DbTx + 'static, + Spec: Send + Sync + EthereumHardforks + 'static, + SC: Send + Sync + 'static, + > BlockExecutionWriter for DatabaseProvider { fn take_block_and_execution_range( &self, @@ -3396,8 +3448,11 @@ impl BlockWriter - for DatabaseProvider +impl< + TX: DbTxMut + DbTx + 'static, + Spec: Send + Sync + EthereumHardforks + 'static, + SC: Send + Sync + 'static, + > BlockWriter for DatabaseProvider { /// Inserts the block into the database, always modifying the following tables: /// * [`CanonicalHeaders`](tables::CanonicalHeaders) @@ -3615,7 +3670,9 @@ impl PruneCheckpointReader for DatabaseProvider { +impl PruneCheckpointReader + for DatabaseProvider +{ fn get_prune_checkpoint( &self, segment: PruneSegment, @@ -3632,7 +3689,9 @@ impl PruneCheckpointReader for DatabaseProvider PruneCheckpointWriter for DatabaseProvider { +impl PruneCheckpointWriter + for DatabaseProvider +{ fn save_prune_checkpoint( &self, segment: PruneSegment, @@ -3642,7 +3701,7 @@ impl PruneCheckpointWriter for DatabaseProvider< } } -impl StatsReader for DatabaseProvider { +impl StatsReader for DatabaseProvider { fn count_entries(&self) -> ProviderResult { let db_entries = self.tx.entries::()?; let static_file_entries = match self.static_file_provider.count_entries::() { @@ -3655,7 +3714,9 @@ impl StatsReader for DatabaseProvider { } } -impl ChainStateBlockReader for DatabaseProvider { +impl ChainStateBlockReader + for DatabaseProvider +{ fn last_finalized_block_number(&self) -> ProviderResult> { let mut finalized_blocks = self .tx @@ -3681,7 +3742,9 @@ impl ChainStateBlockReader for DatabaseProvider ChainStateBlockWriter for DatabaseProvider { +impl ChainStateBlockWriter + for DatabaseProvider +{ fn save_finalized_block_number(&self, block_number: BlockNumber) -> ProviderResult<()> { Ok(self .tx @@ -3695,7 +3758,9 @@ impl ChainStateBlockWriter for DatabaseProvider< } } -impl DBProvider for DatabaseProvider { +impl DBProvider + for DatabaseProvider +{ type Tx = TX; fn tx_ref(&self) -> &Self::Tx { diff --git a/crates/storage/provider/src/providers/state/historical.rs b/crates/storage/provider/src/providers/state/historical.rs index 640041e0801f..967343a9763c 100644 --- a/crates/storage/provider/src/providers/state/historical.rs +++ b/crates/storage/provider/src/providers/state/historical.rs @@ -24,9 +24,9 @@ use reth_trie::{ }; use reth_trie_db::{ DatabaseHashedPostState, DatabaseHashedStorage, DatabaseProof, DatabaseStateRoot, - DatabaseStorageProof, DatabaseStorageRoot, DatabaseTrieWitness, + DatabaseStorageProof, DatabaseStorageRoot, DatabaseTrieWitness, StateCommitment, }; -use std::fmt::Debug; +use std::{fmt::Debug, marker::PhantomData}; /// State provider for a given block number which takes a tx reference. /// @@ -40,7 +40,7 @@ use std::fmt::Debug; /// - [`tables::AccountChangeSets`] /// - [`tables::StorageChangeSets`] #[derive(Debug)] -pub struct HistoricalStateProviderRef<'b, TX: DbTx> { +pub struct HistoricalStateProviderRef<'b, TX: DbTx, SC: StateCommitment> { /// Transaction tx: &'b TX, /// Block number is main index for the history state of accounts and storages. @@ -49,6 +49,8 @@ pub struct HistoricalStateProviderRef<'b, TX: DbTx> { lowest_available_blocks: LowestAvailableBlocks, /// Static File provider static_file_provider: StaticFileProvider, + /// Marker to associate the `StateCommitment` type with this provider. + _marker: PhantomData, } #[derive(Debug, Eq, PartialEq)] @@ -59,14 +61,20 @@ pub enum HistoryInfo { MaybeInPlainState, } -impl<'b, TX: DbTx> HistoricalStateProviderRef<'b, TX> { +impl<'b, TX: DbTx, SC: StateCommitment> HistoricalStateProviderRef<'b, TX, SC> { /// Create new `StateProvider` for historical block number pub fn new( tx: &'b TX, block_number: BlockNumber, static_file_provider: StaticFileProvider, ) -> Self { - Self { tx, block_number, lowest_available_blocks: Default::default(), static_file_provider } + Self { + tx, + block_number, + lowest_available_blocks: Default::default(), + static_file_provider, + _marker: PhantomData, + } } /// Create new `StateProvider` for historical block number and lowest block numbers at which @@ -77,7 +85,13 @@ impl<'b, TX: DbTx> HistoricalStateProviderRef<'b, TX> { lowest_available_blocks: LowestAvailableBlocks, static_file_provider: StaticFileProvider, ) -> Self { - Self { tx, block_number, lowest_available_blocks, static_file_provider } + Self { + tx, + block_number, + lowest_available_blocks, + static_file_provider, + _marker: PhantomData, + } } /// Lookup an account in the `AccountsHistory` table @@ -247,7 +261,7 @@ impl<'b, TX: DbTx> HistoricalStateProviderRef<'b, TX> { } } -impl AccountReader for HistoricalStateProviderRef<'_, TX> { +impl AccountReader for HistoricalStateProviderRef<'_, TX, SC> { /// Get basic account information. fn basic_account(&self, address: Address) -> ProviderResult> { match self.account_history_lookup(address)? { @@ -269,7 +283,7 @@ impl AccountReader for HistoricalStateProviderRef<'_, TX> { } } -impl BlockHashReader for HistoricalStateProviderRef<'_, TX> { +impl BlockHashReader for HistoricalStateProviderRef<'_, TX, SC> { /// Get block hash by number. fn block_hash(&self, number: u64) -> ProviderResult> { self.static_file_provider.get_with_static_file_or_database( @@ -305,7 +319,7 @@ impl BlockHashReader for HistoricalStateProviderRef<'_, TX> { } } -impl StateRootProvider for HistoricalStateProviderRef<'_, TX> { +impl StateRootProvider for HistoricalStateProviderRef<'_, TX, SC> { fn state_root(&self, hashed_state: HashedPostState) -> ProviderResult { let mut revert_state = self.revert_state()?; revert_state.extend(hashed_state); @@ -339,7 +353,7 @@ impl StateRootProvider for HistoricalStateProviderRef<'_, TX> { } } -impl StorageRootProvider for HistoricalStateProviderRef<'_, TX> { +impl StorageRootProvider for HistoricalStateProviderRef<'_, TX, SC> { fn storage_root( &self, address: Address, @@ -364,7 +378,7 @@ impl StorageRootProvider for HistoricalStateProviderRef<'_, TX> { } } -impl StateProofProvider for HistoricalStateProviderRef<'_, TX> { +impl StateProofProvider for HistoricalStateProviderRef<'_, TX, SC> { /// Get account and storage proofs. fn proof( &self, @@ -396,7 +410,7 @@ impl StateProofProvider for HistoricalStateProviderRef<'_, TX> { } } -impl StateProvider for HistoricalStateProviderRef<'_, TX> { +impl StateProvider for HistoricalStateProviderRef<'_, TX, SC> { /// Get storage. fn storage( &self, @@ -436,7 +450,7 @@ impl StateProvider for HistoricalStateProviderRef<'_, TX> { /// State provider for a given block number. /// For more detailed description, see [`HistoricalStateProviderRef`]. #[derive(Debug)] -pub struct HistoricalStateProvider { +pub struct HistoricalStateProvider { /// Database transaction tx: TX, /// State at the block number is the main indexer of the state. @@ -445,16 +459,24 @@ pub struct HistoricalStateProvider { lowest_available_blocks: LowestAvailableBlocks, /// Static File provider static_file_provider: StaticFileProvider, + /// Marker to associate the `StateCommitment` type with this provider. + _marker: PhantomData, } -impl HistoricalStateProvider { +impl HistoricalStateProvider { /// Create new `StateProvider` for historical block number pub fn new( tx: TX, block_number: BlockNumber, static_file_provider: StaticFileProvider, ) -> Self { - Self { tx, block_number, lowest_available_blocks: Default::default(), static_file_provider } + Self { + tx, + block_number, + lowest_available_blocks: Default::default(), + static_file_provider, + _marker: PhantomData, + } } /// Set the lowest block number at which the account history is available. @@ -477,7 +499,7 @@ impl HistoricalStateProvider { /// Returns a new provider that takes the `TX` as reference #[inline(always)] - fn as_ref(&self) -> HistoricalStateProviderRef<'_, TX> { + fn as_ref(&self) -> HistoricalStateProviderRef<'_, TX, SC> { HistoricalStateProviderRef::new_with_lowest_available_blocks( &self.tx, self.block_number, @@ -488,7 +510,7 @@ impl HistoricalStateProvider { } // Delegates all provider impls to [HistoricalStateProviderRef] -delegate_provider_impls!(HistoricalStateProvider where [TX: DbTx]); +delegate_provider_impls!(HistoricalStateProvider where [TX: DbTx, SC: StateCommitment]); /// Lowest blocks at which different parts of the state are available. /// They may be [Some] if pruning is enabled. @@ -534,6 +556,18 @@ mod tests { }; use reth_primitives::{Account, StorageEntry}; use reth_storage_errors::provider::ProviderError; + use reth_trie_db::{MerklePatriciaTrie, StateCommitment}; + + type TestHistoricalStateProviderRefRO<'a> = HistoricalStateProviderRef< + 'a, + reth_db::mdbx::tx::Tx, + MerklePatriciaTrie, + >; + type TestHistoricalStateProviderRefRW<'a> = HistoricalStateProviderRef< + 'a, + reth_db::mdbx::tx::Tx, + MerklePatriciaTrie, + >; const ADDRESS: Address = address!("0000000000000000000000000000000000000001"); const HIGHER_ADDRESS: Address = address!("0000000000000000000000000000000000000005"); @@ -541,8 +575,8 @@ mod tests { const fn assert_state_provider() {} #[allow(dead_code)] - const fn assert_historical_state_provider() { - assert_state_provider::>(); + const fn assert_historical_state_provider() { + assert_state_provider::>(); } #[test] @@ -613,58 +647,58 @@ mod tests { // run assert_eq!( - HistoricalStateProviderRef::new(&tx, 1, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 1, static_file_provider.clone()) .basic_account(ADDRESS), Ok(None) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 2, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 2, static_file_provider.clone()) .basic_account(ADDRESS), Ok(Some(acc_at3)) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 3, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 3, static_file_provider.clone()) .basic_account(ADDRESS), Ok(Some(acc_at3)) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 4, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 4, static_file_provider.clone()) .basic_account(ADDRESS), Ok(Some(acc_at7)) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 7, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 7, static_file_provider.clone()) .basic_account(ADDRESS), Ok(Some(acc_at7)) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 9, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 9, static_file_provider.clone()) .basic_account(ADDRESS), Ok(Some(acc_at10)) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 10, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 10, static_file_provider.clone()) .basic_account(ADDRESS), Ok(Some(acc_at10)) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 11, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 11, static_file_provider.clone()) .basic_account(ADDRESS), Ok(Some(acc_at15)) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 16, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 16, static_file_provider.clone()) .basic_account(ADDRESS), Ok(Some(acc_plain)) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 1, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 1, static_file_provider.clone()) .basic_account(HIGHER_ADDRESS), Ok(None) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 1000, static_file_provider) + TestHistoricalStateProviderRefRO::new(&tx, 1000, static_file_provider) .basic_account(HIGHER_ADDRESS), Ok(Some(higher_acc_plain)) ); @@ -725,52 +759,52 @@ mod tests { // run assert_eq!( - HistoricalStateProviderRef::new(&tx, 0, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 0, static_file_provider.clone()) .storage(ADDRESS, STORAGE), Ok(None) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 3, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 3, static_file_provider.clone()) .storage(ADDRESS, STORAGE), Ok(Some(U256::ZERO)) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 4, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 4, static_file_provider.clone()) .storage(ADDRESS, STORAGE), Ok(Some(entry_at7.value)) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 7, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 7, static_file_provider.clone()) .storage(ADDRESS, STORAGE), Ok(Some(entry_at7.value)) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 9, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 9, static_file_provider.clone()) .storage(ADDRESS, STORAGE), Ok(Some(entry_at10.value)) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 10, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 10, static_file_provider.clone()) .storage(ADDRESS, STORAGE), Ok(Some(entry_at10.value)) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 11, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 11, static_file_provider.clone()) .storage(ADDRESS, STORAGE), Ok(Some(entry_at15.value)) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 16, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 16, static_file_provider.clone()) .storage(ADDRESS, STORAGE), Ok(Some(entry_plain.value)) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 1, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 1, static_file_provider.clone()) .storage(HIGHER_ADDRESS, STORAGE), Ok(None) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 1000, static_file_provider) + TestHistoricalStateProviderRefRO::new(&tx, 1000, static_file_provider) .storage(HIGHER_ADDRESS, STORAGE), Ok(Some(higher_entry_plain.value)) ); @@ -784,7 +818,7 @@ mod tests { // provider block_number < lowest available block number, // i.e. state at provider block is pruned - let provider = HistoricalStateProviderRef::new_with_lowest_available_blocks( + let provider = TestHistoricalStateProviderRefRW::new_with_lowest_available_blocks( &tx, 2, LowestAvailableBlocks { @@ -804,7 +838,7 @@ mod tests { // provider block_number == lowest available block number, // i.e. state at provider block is available - let provider = HistoricalStateProviderRef::new_with_lowest_available_blocks( + let provider = TestHistoricalStateProviderRefRW::new_with_lowest_available_blocks( &tx, 2, LowestAvailableBlocks { @@ -821,7 +855,7 @@ mod tests { // provider block_number == lowest available block number, // i.e. state at provider block is available - let provider = HistoricalStateProviderRef::new_with_lowest_available_blocks( + let provider = TestHistoricalStateProviderRefRW::new_with_lowest_available_blocks( &tx, 2, LowestAvailableBlocks { diff --git a/crates/storage/provider/src/providers/state/latest.rs b/crates/storage/provider/src/providers/state/latest.rs index fdcbfc4937fe..1299db28b911 100644 --- a/crates/storage/provider/src/providers/state/latest.rs +++ b/crates/storage/provider/src/providers/state/latest.rs @@ -22,33 +22,36 @@ use reth_trie::{ }; use reth_trie_db::{ DatabaseProof, DatabaseStateRoot, DatabaseStorageProof, DatabaseStorageRoot, - DatabaseTrieWitness, + DatabaseTrieWitness, StateCommitment, }; +use std::marker::PhantomData; /// State provider over latest state that takes tx reference. #[derive(Debug)] -pub struct LatestStateProviderRef<'b, TX: DbTx> { +pub struct LatestStateProviderRef<'b, TX: DbTx, SC: StateCommitment> { /// database transaction tx: &'b TX, /// Static File provider static_file_provider: StaticFileProvider, + /// Marker to associate the `StateCommitment` type with this provider. + _marker: PhantomData, } -impl<'b, TX: DbTx> LatestStateProviderRef<'b, TX> { +impl<'b, TX: DbTx, SC: StateCommitment> LatestStateProviderRef<'b, TX, SC> { /// Create new state provider pub const fn new(tx: &'b TX, static_file_provider: StaticFileProvider) -> Self { - Self { tx, static_file_provider } + Self { tx, static_file_provider, _marker: PhantomData } } } -impl AccountReader for LatestStateProviderRef<'_, TX> { +impl AccountReader for LatestStateProviderRef<'_, TX, SC> { /// Get basic account information. fn basic_account(&self, address: Address) -> ProviderResult> { self.tx.get::(address).map_err(Into::into) } } -impl BlockHashReader for LatestStateProviderRef<'_, TX> { +impl BlockHashReader for LatestStateProviderRef<'_, TX, SC> { /// Get block hash by number. fn block_hash(&self, number: u64) -> ProviderResult> { self.static_file_provider.get_with_static_file_or_database( @@ -84,7 +87,7 @@ impl BlockHashReader for LatestStateProviderRef<'_, TX> { } } -impl StateRootProvider for LatestStateProviderRef<'_, TX> { +impl StateRootProvider for LatestStateProviderRef<'_, TX, SC> { fn state_root(&self, hashed_state: HashedPostState) -> ProviderResult { StateRoot::overlay_root(self.tx, hashed_state) .map_err(|err| ProviderError::Database(err.into())) @@ -112,7 +115,7 @@ impl StateRootProvider for LatestStateProviderRef<'_, TX> { } } -impl StorageRootProvider for LatestStateProviderRef<'_, TX> { +impl StorageRootProvider for LatestStateProviderRef<'_, TX, SC> { fn storage_root( &self, address: Address, @@ -133,7 +136,7 @@ impl StorageRootProvider for LatestStateProviderRef<'_, TX> { } } -impl StateProofProvider for LatestStateProviderRef<'_, TX> { +impl StateProofProvider for LatestStateProviderRef<'_, TX, SC> { fn proof( &self, input: TrieInput, @@ -161,7 +164,7 @@ impl StateProofProvider for LatestStateProviderRef<'_, TX> { } } -impl StateProvider for LatestStateProviderRef<'_, TX> { +impl StateProvider for LatestStateProviderRef<'_, TX, SC> { /// Get storage. fn storage( &self, @@ -185,28 +188,30 @@ impl StateProvider for LatestStateProviderRef<'_, TX> { /// State provider for the latest state. #[derive(Debug)] -pub struct LatestStateProvider { +pub struct LatestStateProvider { /// database transaction db: TX, /// Static File provider static_file_provider: StaticFileProvider, + /// Marker to associate the `StateCommitment` type with this provider. + _marker: PhantomData, } -impl LatestStateProvider { +impl LatestStateProvider { /// Create new state provider pub const fn new(db: TX, static_file_provider: StaticFileProvider) -> Self { - Self { db, static_file_provider } + Self { db, static_file_provider, _marker: PhantomData } } /// Returns a new provider that takes the `TX` as reference #[inline(always)] - fn as_ref(&self) -> LatestStateProviderRef<'_, TX> { + fn as_ref(&self) -> LatestStateProviderRef<'_, TX, SC> { LatestStateProviderRef::new(&self.db, self.static_file_provider.clone()) } } // Delegates all provider impls to [LatestStateProviderRef] -delegate_provider_impls!(LatestStateProvider where [TX: DbTx]); +delegate_provider_impls!(LatestStateProvider where [TX: DbTx, SC: StateCommitment]); #[cfg(test)] mod tests { @@ -214,7 +219,7 @@ mod tests { const fn assert_state_provider() {} #[allow(dead_code)] - const fn assert_latest_state_provider() { - assert_state_provider::>(); + const fn assert_latest_state_provider() { + assert_state_provider::>(); } } diff --git a/crates/storage/provider/src/test_utils/blocks.rs b/crates/storage/provider/src/test_utils/blocks.rs index 57e111d674ba..6f45dce63245 100644 --- a/crates/storage/provider/src/test_utils/blocks.rs +++ b/crates/storage/provider/src/test_utils/blocks.rs @@ -13,12 +13,13 @@ use reth_primitives::{ Signature, Transaction, TransactionSigned, TxType, Withdrawal, Withdrawals, }; use reth_trie::root::{state_root_unhashed, storage_root_unhashed}; +use reth_trie_db::StateCommitment; use revm::{db::BundleState, primitives::AccountInfo}; use std::{str::FromStr, sync::LazyLock}; /// Assert genesis block -pub fn assert_genesis_block( - provider: &DatabaseProviderRW, +pub fn assert_genesis_block( + provider: &DatabaseProviderRW, g: SealedBlock, ) { let n = g.number; diff --git a/crates/storage/provider/src/test_utils/mock.rs b/crates/storage/provider/src/test_utils/mock.rs index c7c94b939ac3..d99093ac80a5 100644 --- a/crates/storage/provider/src/test_utils/mock.rs +++ b/crates/storage/provider/src/test_utils/mock.rs @@ -34,6 +34,7 @@ use reth_trie::{ updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, StorageProof, TrieInput, }; +use reth_trie_db::MerklePatriciaTrie; use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg}; use std::{ collections::BTreeMap, @@ -152,8 +153,8 @@ impl MockEthProvider { impl DatabaseProviderFactory for MockEthProvider { type DB = DatabaseMock; - type Provider = DatabaseProvider; - type ProviderRW = DatabaseProvider; + type Provider = DatabaseProvider; + type ProviderRW = DatabaseProvider; fn database_provider_ro(&self) -> ProviderResult { Err(ConsistentViewError::Syncing { best_block: GotExpected::new(0, 0) }.into()) diff --git a/crates/storage/storage-api/src/state.rs b/crates/storage/storage-api/src/state.rs index 9a3b855ff14d..1bbcd614e77e 100644 --- a/crates/storage/storage-api/src/state.rs +++ b/crates/storage/storage-api/src/state.rs @@ -90,6 +90,13 @@ pub trait TryIntoHistoricalStateProvider { ) -> ProviderResult; } +/// Trait implemented for database providers that can be converted into a latest state provider +/// reference. +pub trait ToLatestStateProviderRef { + /// Returns a [`StateProvider`] for the latest state. + fn latest<'a>(&'a self) -> Box; +} + /// Light wrapper that returns `StateProvider` implementations that correspond to the given /// `BlockNumber`, the latest state, or the pending state. /// diff --git a/crates/trie/db/tests/trie.rs b/crates/trie/db/tests/trie.rs index f5823404c899..fffcf224d86c 100644 --- a/crates/trie/db/tests/trie.rs +++ b/crates/trie/db/tests/trie.rs @@ -693,8 +693,8 @@ fn storage_trie_around_extension_node() { assert_trie_updates(updates.storage_nodes_ref()); } -fn extension_node_storage_trie( - tx: &DatabaseProviderRW>, Spec>, +fn extension_node_storage_trie( + tx: &DatabaseProviderRW>, Spec, SC>, hashed_address: B256, ) -> (B256, StorageTrieUpdates) { let value = U256::from(1); @@ -721,8 +721,8 @@ fn extension_node_storage_trie( (root, trie_updates) } -fn extension_node_trie( - tx: &DatabaseProviderRW>, Spec>, +fn extension_node_trie( + tx: &DatabaseProviderRW>, Spec, SC>, ) -> B256 { let a = Account { nonce: 0, balance: U256::from(1u64), bytecode_hash: Some(B256::random()) }; let val = encode_account(a, None);