From 51fa6bbe910854f508f32db2832007504f92f374 Mon Sep 17 00:00:00 2001 From: frisitano Date: Sat, 16 Nov 2024 19:10:50 +0800 Subject: [PATCH 01/15] feat: introduce StateCommitment in StateProviders --- .../commands/debug_cmd/in_memory_merkle.rs | 8 +- bin/reth/src/commands/debug_cmd/merkle.rs | 11 +- crates/exex/exex/src/backfill/test_utils.rs | 6 +- crates/stages/stages/src/stages/execution.rs | 12 +- .../provider/src/providers/consistent.rs | 12 +- .../provider/src/providers/database/mod.rs | 4 +- .../src/providers/database/provider.rs | 41 +++--- .../src/providers/state/historical.rs | 122 +++++++++++------- .../provider/src/providers/state/latest.rs | 49 ++++--- crates/storage/storage-api/src/state.rs | 7 + 10 files changed, 162 insertions(+), 110 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 d5bb8a87b22e..ef186ca050e1 100644 --- a/bin/reth/src/commands/debug_cmd/in_memory_merkle.rs +++ b/bin/reth/src/commands/debug_cmd/in_memory_merkle.rs @@ -22,9 +22,9 @@ use reth_network_api::NetworkInfo; use reth_node_api::{NodeTypesWithDB, NodeTypesWithEngine}; use reth_node_ethereum::EthExecutorProvider; use reth_provider::{ - writer::UnifiedStorageWriter, AccountExtReader, ChainSpecProvider, HashingWriter, - HeaderProvider, LatestStateProviderRef, OriginalValuesKnown, ProviderFactory, - StageCheckpointReader, StateWriter, StorageReader, + writer::UnifiedStorageWriter, AccountExtReader, AsLatestStateProviderRef, ChainSpecProvider, + HashingWriter, HeaderProvider, OriginalValuesKnown, ProviderFactory, StageCheckpointReader, + StateWriter, StorageReader, }; use reth_revm::database::StateProviderDatabase; use reth_stages::StageId; @@ -133,7 +133,7 @@ impl> Command { ) .await?; - let db = StateProviderDatabase::new(LatestStateProviderRef::new(&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 9c77c70abc74..4128b982ca24 100644 --- a/bin/reth/src/commands/debug_cmd/merkle.rs +++ b/bin/reth/src/commands/debug_cmd/merkle.rs @@ -20,9 +20,9 @@ use reth_network_p2p::full_block::FullBlockClient; use reth_node_api::{NodeTypesWithDB, NodeTypesWithEngine}; use reth_node_ethereum::EthExecutorProvider; use reth_provider::{ - writer::UnifiedStorageWriter, BlockNumReader, BlockWriter, ChainSpecProvider, - DatabaseProviderFactory, HeaderProvider, LatestStateProviderRef, OriginalValuesKnown, - ProviderError, ProviderFactory, StateWriter, + writer::UnifiedStorageWriter, AsLatestStateProviderRef, BlockNumReader, BlockWriter, + ChainSpecProvider, DatabaseProviderFactory, HeaderProvider, OriginalValuesKnown, ProviderError, + ProviderFactory, StateWriter, }; use reth_revm::database::StateProviderDatabase; use reth_stages::{ @@ -152,9 +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), - )); + 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 80af408c5c8f..222f9dc1d0d2 100644 --- a/crates/exex/exex/src/backfill/test_utils.rs +++ b/crates/exex/exex/src/backfill/test_utils.rs @@ -13,7 +13,7 @@ use reth_primitives::{ Block, BlockBody, BlockWithSenders, Receipt, SealedBlockWithSenders, Transaction, }; use reth_provider::{ - providers::ProviderNodeTypes, BlockWriter as _, ExecutionOutcome, LatestStateProviderRef, + providers::ProviderNodeTypes, AsLatestStateProviderRef, BlockWriter as _, ExecutionOutcome, ProviderFactory, }; use reth_revm::database::StateProviderDatabase; @@ -63,7 +63,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))) + .executor(StateProviderDatabase::new(provider.latest())) .execute(BlockExecutionInput { block, total_difficulty: U256::ZERO })?; block_execution_output.state.reverts.sort(); @@ -189,7 +189,7 @@ where let provider = provider_factory.provider()?; let executor = EthExecutorProvider::ethereum(chain_spec) - .batch_executor(StateProviderDatabase::new(LatestStateProviderRef::new(&provider))); + .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/src/stages/execution.rs b/crates/stages/stages/src/stages/execution.rs index 16234ad483f7..7c6d41bd536f 100644 --- a/crates/stages/stages/src/stages/execution.rs +++ b/crates/stages/stages/src/stages/execution.rs @@ -16,7 +16,7 @@ use reth_primitives_traits::{format_gas_throughput, NodePrimitives}; use reth_provider::{ providers::{StaticFileProvider, StaticFileProviderRWRefMut, StaticFileWriter}, writer::UnifiedStorageWriter, - BlockHashReader, BlockReader, DBProvider, HeaderProvider, LatestStateProviderRef, + AsLatestStateProviderRef, BlockHashReader, BlockReader, DBProvider, HeaderProvider, OriginalValuesKnown, ProviderError, StateChangeWriter, StateWriter, StaticFileProviderFactory, StatsReader, TransactionVariant, }; @@ -46,8 +46,9 @@ use tracing::*; /// - [`tables::BlockBodyIndices`] to get tx number /// - [`tables::Transactions`] to execute /// -/// For state access [`LatestStateProviderRef`] provides us latest state and history state -/// For latest most recent state [`LatestStateProviderRef`] would need (Used for execution Stage): +/// For state access [`reth_provider::LatestStateProviderRef`] provides us latest state and history +/// state For latest most recent state [`reth_provider::LatestStateProviderRef`] would need (Used +/// for execution Stage): /// - [`tables::PlainAccountState`] /// - [`tables::Bytecodes`] /// - [`tables::PlainStorageState`] @@ -180,7 +181,8 @@ where + StaticFileProviderFactory + StatsReader + StateChangeWriter - + BlockHashReader, + + BlockHashReader + + AsLatestStateProviderRef, for<'a> UnifiedStorageWriter<'a, Provider, StaticFileProviderRWRefMut<'a, Provider::Primitives>>: StateWriter, { @@ -225,7 +227,7 @@ where None }; - let db = StateProviderDatabase(LatestStateProviderRef::new(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/storage/provider/src/providers/consistent.rs b/crates/storage/provider/src/providers/consistent.rs index 3b2599f49991..a5980bcd7d48 100644 --- a/crates/storage/provider/src/providers/consistent.rs +++ b/crates/storage/provider/src/providers/consistent.rs @@ -1,10 +1,10 @@ use super::{DatabaseProviderRO, ProviderFactory, ProviderNodeTypes}; use crate::{ - providers::StaticFileProvider, AccountReader, BlockHashReader, BlockIdReader, BlockNumReader, - BlockReader, BlockReaderIdExt, BlockSource, ChainSpecProvider, ChangeSetReader, EvmEnvProvider, - HeaderProvider, ProviderError, PruneCheckpointReader, ReceiptProvider, ReceiptProviderIdExt, - StageCheckpointReader, StateReader, StaticFileProviderFactory, TransactionVariant, - TransactionsProvider, WithdrawalsProvider, + providers::StaticFileProvider, AccountReader, AsLatestStateProviderRef, BlockHashReader, + BlockIdReader, BlockNumReader, BlockReader, BlockReaderIdExt, BlockSource, ChainSpecProvider, + ChangeSetReader, EvmEnvProvider, HeaderProvider, ProviderError, PruneCheckpointReader, + ReceiptProvider, ReceiptProviderIdExt, StageCheckpointReader, StateReader, + StaticFileProviderFactory, TransactionVariant, TransactionsProvider, WithdrawalsProvider, }; use alloy_consensus::Header; use alloy_eips::{ @@ -109,7 +109,7 @@ impl ConsistentProvider { Ok(self.block_state_provider_ref(state)?.boxed()) } else { trace!(target: "providers::blockchain", "Using database state for latest state provider"); - self.storage_provider.latest() + Ok(self.storage_provider.latest()) } } diff --git a/crates/storage/provider/src/providers/database/mod.rs b/crates/storage/provider/src/providers/database/mod.rs index 94c83bbb4422..14fc6f765f63 100644 --- a/crates/storage/provider/src/providers/database/mod.rs +++ b/crates/storage/provider/src/providers/database/mod.rs @@ -160,7 +160,9 @@ impl ProviderFactory { #[track_caller] pub fn latest(&self) -> ProviderResult { trace!(target: "providers::db", "Returning latest state provider"); - Ok(Box::new(LatestStateProvider::new(self.database_provider_ro()?))) + Ok(Box::new(LatestStateProvider::<_, N::StateCommitment>::new( + self.database_provider_ro()?, + ))) } /// Storage provider for state at that given block diff --git a/crates/storage/provider/src/providers/database/provider.rs b/crates/storage/provider/src/providers/database/provider.rs index b93112e70843..94b57c2113e4 100644 --- a/crates/storage/provider/src/providers/database/provider.rs +++ b/crates/storage/provider/src/providers/database/provider.rs @@ -6,14 +6,15 @@ use crate::{ AccountExtReader, BlockSource, ChangeSetReader, ReceiptProvider, StageCheckpointWriter, }, writer::UnifiedStorageWriter, - AccountReader, BlockExecutionWriter, BlockHashReader, BlockNumReader, BlockReader, BlockWriter, - BundleStateInit, ChainStateBlockReader, ChainStateBlockWriter, DBProvider, EvmEnvProvider, - HashingWriter, HeaderProvider, HeaderSyncGap, HeaderSyncGapProvider, HistoricalStateProvider, - HistoricalStateProviderRef, HistoryWriter, LatestStateProvider, LatestStateProviderRef, - OriginalValuesKnown, ProviderError, PruneCheckpointReader, PruneCheckpointWriter, RevertsInit, - StageCheckpointReader, StateChangeWriter, StateProviderBox, StateReader, StateWriter, - StaticFileProviderFactory, StatsReader, StorageReader, StorageTrieWriter, TransactionVariant, - TransactionsProvider, TransactionsProviderExt, TrieWriter, WithdrawalsProvider, + AccountReader, AsLatestStateProviderRef, BlockExecutionWriter, BlockHashReader, BlockNumReader, + BlockReader, BlockWriter, BundleStateInit, ChainStateBlockReader, ChainStateBlockWriter, + DBProvider, EvmEnvProvider, HashingWriter, HeaderProvider, HeaderSyncGap, + HeaderSyncGapProvider, HistoricalStateProvider, HistoricalStateProviderRef, HistoryWriter, + LatestStateProvider, LatestStateProviderRef, OriginalValuesKnown, ProviderError, + PruneCheckpointReader, PruneCheckpointWriter, RevertsInit, StageCheckpointReader, + StateChangeWriter, StateProviderBox, StateReader, StateWriter, StaticFileProviderFactory, + StatsReader, StorageReader, StorageTrieWriter, TransactionVariant, TransactionsProvider, + TransactionsProviderExt, TrieWriter, WithdrawalsProvider, }; use alloy_consensus::Header; use alloy_eips::{ @@ -148,12 +149,6 @@ impl DatabaseProvider { } 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))) - } - /// Storage provider for state at that given block hash pub fn history_by_block_hash<'a>( &'a self, @@ -164,7 +159,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(self))) + return Ok(Box::new(LatestStateProviderRef::<'_, _, N::StateCommitment>::new(self))) } // +1 as the changeset that we want is the one that was applied after this block. @@ -175,7 +170,8 @@ impl DatabaseProvider { let storage_history_prune_checkpoint = self.get_prune_checkpoint(PruneSegment::StorageHistory)?; - let mut state_provider = HistoricalStateProviderRef::new(self, block_number); + let mut state_provider = + HistoricalStateProviderRef::<'_, _, N::StateCommitment>::new(self, block_number); // 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. @@ -243,7 +239,7 @@ impl TryIntoHistoricalStateProvider for Databa 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))) + return Ok(Box::new(LatestStateProvider::<_, N::StateCommitment>::new(self))) } // +1 as the changeset that we want is the one that was applied after this block. @@ -254,7 +250,8 @@ impl TryIntoHistoricalStateProvider for Databa let storage_history_prune_checkpoint = self.get_prune_checkpoint(PruneSegment::StorageHistory)?; - let mut state_provider = HistoricalStateProvider::new(self, block_number); + let mut state_provider = + HistoricalStateProvider::<_, N::StateCommitment>::new(self, block_number); // 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. @@ -277,6 +274,14 @@ impl TryIntoHistoricalStateProvider for Databa } } +impl AsLatestStateProviderRef for DatabaseProvider { + /// State provider for latest state + fn latest<'a>(&'a self) -> Box { + trace!(target: "providers::db", "Returning latest state provider"); + Box::new(LatestStateProviderRef::<'_, _, N::StateCommitment>::new(self)) + } +} + impl + 'static> DatabaseProvider { diff --git a/crates/storage/provider/src/providers/state/historical.rs b/crates/storage/provider/src/providers/state/historical.rs index 29ba70e2049e..2cc912af9791 100644 --- a/crates/storage/provider/src/providers/state/historical.rs +++ b/crates/storage/provider/src/providers/state/historical.rs @@ -27,7 +27,7 @@ use reth_trie_db::{ DatabaseHashedPostState, DatabaseHashedStorage, DatabaseProof, DatabaseStateRoot, DatabaseStorageProof, DatabaseStorageRoot, DatabaseTrieWitness, }; -use std::fmt::Debug; +use std::{fmt::Debug, marker::PhantomData}; /// State provider for a given block number which takes a tx reference. /// @@ -41,13 +41,15 @@ use std::fmt::Debug; /// - [`tables::AccountChangeSets`] /// - [`tables::StorageChangeSets`] #[derive(Debug)] -pub struct HistoricalStateProviderRef<'b, Provider> { +pub struct HistoricalStateProviderRef<'b, Provider, SC> { /// Database provider provider: &'b Provider, /// Block number is main index for the history state of accounts and storages. block_number: BlockNumber, /// Lowest blocks at which different parts of the state are available. lowest_available_blocks: LowestAvailableBlocks, + /// Marker to associate the `StateCommitment` type with this provider. + _marker: PhantomData, } #[derive(Debug, Eq, PartialEq)] @@ -58,10 +60,15 @@ pub enum HistoryInfo { MaybeInPlainState, } -impl<'b, Provider: DBProvider + BlockNumReader> HistoricalStateProviderRef<'b, Provider> { +impl<'b, Provider: DBProvider + BlockNumReader, SC> HistoricalStateProviderRef<'b, Provider, SC> { /// Create new `StateProvider` for historical block number pub fn new(provider: &'b Provider, block_number: BlockNumber) -> Self { - Self { provider, block_number, lowest_available_blocks: Default::default() } + Self { + provider, + block_number, + lowest_available_blocks: Default::default(), + _marker: PhantomData, + } } /// Create new `StateProvider` for historical block number and lowest block numbers at which @@ -71,7 +78,7 @@ impl<'b, Provider: DBProvider + BlockNumReader> HistoricalStateProviderRef<'b, P block_number: BlockNumber, lowest_available_blocks: LowestAvailableBlocks, ) -> Self { - Self { provider, block_number, lowest_available_blocks } + Self { provider, block_number, lowest_available_blocks, _marker: PhantomData } } /// Lookup an account in the `AccountsHistory` table @@ -233,14 +240,14 @@ impl<'b, Provider: DBProvider + BlockNumReader> HistoricalStateProviderRef<'b, P } } -impl HistoricalStateProviderRef<'_, Provider> { +impl HistoricalStateProviderRef<'_, Provider, SC> { fn tx(&self) -> &Provider::Tx { self.provider.tx_ref() } } -impl AccountReader - for HistoricalStateProviderRef<'_, Provider> +impl AccountReader + for HistoricalStateProviderRef<'_, Provider, SC> { /// Get basic account information. fn basic_account(&self, address: Address) -> ProviderResult> { @@ -263,8 +270,8 @@ impl AccountReader } } -impl BlockHashReader - for HistoricalStateProviderRef<'_, Provider> +impl BlockHashReader + for HistoricalStateProviderRef<'_, Provider, SC> { /// Get block hash by number. fn block_hash(&self, number: u64) -> ProviderResult> { @@ -280,8 +287,8 @@ impl BlockHashReader } } -impl StateRootProvider - for HistoricalStateProviderRef<'_, Provider> +impl StateRootProvider + for HistoricalStateProviderRef<'_, Provider, SC> { fn state_root(&self, hashed_state: HashedPostState) -> ProviderResult { let mut revert_state = self.revert_state()?; @@ -316,8 +323,8 @@ impl StateRootProvider } } -impl StorageRootProvider - for HistoricalStateProviderRef<'_, Provider> +impl StorageRootProvider + for HistoricalStateProviderRef<'_, Provider, SC> { fn storage_root( &self, @@ -343,8 +350,8 @@ impl StorageRootProvider } } -impl StateProofProvider - for HistoricalStateProviderRef<'_, Provider> +impl StateProofProvider + for HistoricalStateProviderRef<'_, Provider, SC> { /// Get account and storage proofs. fn proof( @@ -377,8 +384,8 @@ impl StateProofProvider } } -impl StateProvider - for HistoricalStateProviderRef<'_, Provider> +impl StateProvider + for HistoricalStateProviderRef<'_, Provider, SC> { /// Get storage. fn storage( @@ -419,19 +426,26 @@ impl StateProvider /// State provider for a given block number. /// For more detailed description, see [`HistoricalStateProviderRef`]. #[derive(Debug)] -pub struct HistoricalStateProvider { +pub struct HistoricalStateProvider { /// Database provider. provider: Provider, /// State at the block number is the main indexer of the state. block_number: BlockNumber, /// Lowest blocks at which different parts of the state are available. lowest_available_blocks: LowestAvailableBlocks, + /// 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(provider: Provider, block_number: BlockNumber) -> Self { - Self { provider, block_number, lowest_available_blocks: Default::default() } + Self { + provider, + block_number, + lowest_available_blocks: Default::default(), + _marker: PhantomData, + } } /// Set the lowest block number at which the account history is available. @@ -454,7 +468,7 @@ impl HistoricalStateProvider { /// Returns a new provider that takes the `TX` as reference #[inline(always)] - const fn as_ref(&self) -> HistoricalStateProviderRef<'_, Provider> { + const fn as_ref(&self) -> HistoricalStateProviderRef<'_, Provider, SC> { HistoricalStateProviderRef::new_with_lowest_available_blocks( &self.provider, self.block_number, @@ -464,7 +478,7 @@ impl HistoricalStateProvider { } // Delegates all provider impls to [HistoricalStateProviderRef] -delegate_provider_impls!(HistoricalStateProvider where [Provider: DBProvider + BlockNumReader + BlockHashReader]); +delegate_provider_impls!(HistoricalStateProvider where [Provider: DBProvider + BlockNumReader + BlockHashReader, SC: Send + Sync]); /// Lowest blocks at which different parts of the state are available. /// They may be [Some] if pruning is enabled. @@ -510,6 +524,10 @@ mod tests { use reth_primitives::{Account, StorageEntry}; use reth_storage_api::{BlockHashReader, BlockNumReader, DBProvider, DatabaseProviderFactory}; use reth_storage_errors::provider::ProviderError; + use reth_trie_db::MerklePatriciaTrie; + + type TestHistoricalStateProviderRef<'a, TX> = + HistoricalStateProviderRef<'a, TX, MerklePatriciaTrie>; const ADDRESS: Address = address!("0000000000000000000000000000000000000001"); const HIGHER_ADDRESS: Address = address!("0000000000000000000000000000000000000005"); @@ -517,8 +535,11 @@ 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< + T: DBProvider + BlockNumReader + BlockHashReader, + SC: Send + Sync, + >() { + assert_state_provider::>(); } #[test] @@ -587,43 +608,46 @@ mod tests { let db = factory.provider().unwrap(); // run - assert_eq!(HistoricalStateProviderRef::new(&db, 1).basic_account(ADDRESS), Ok(None)); + assert_eq!(TestHistoricalStateProviderRef::new(&db, 1).basic_account(ADDRESS), Ok(None)); assert_eq!( - HistoricalStateProviderRef::new(&db, 2).basic_account(ADDRESS), + TestHistoricalStateProviderRef::new(&db, 2).basic_account(ADDRESS), Ok(Some(acc_at3)) ); assert_eq!( - HistoricalStateProviderRef::new(&db, 3).basic_account(ADDRESS), + TestHistoricalStateProviderRef::new(&db, 3).basic_account(ADDRESS), Ok(Some(acc_at3)) ); assert_eq!( - HistoricalStateProviderRef::new(&db, 4).basic_account(ADDRESS), + TestHistoricalStateProviderRef::new(&db, 4).basic_account(ADDRESS), Ok(Some(acc_at7)) ); assert_eq!( - HistoricalStateProviderRef::new(&db, 7).basic_account(ADDRESS), + TestHistoricalStateProviderRef::new(&db, 7).basic_account(ADDRESS), Ok(Some(acc_at7)) ); assert_eq!( - HistoricalStateProviderRef::new(&db, 9).basic_account(ADDRESS), + TestHistoricalStateProviderRef::new(&db, 9).basic_account(ADDRESS), Ok(Some(acc_at10)) ); assert_eq!( - HistoricalStateProviderRef::new(&db, 10).basic_account(ADDRESS), + TestHistoricalStateProviderRef::new(&db, 10).basic_account(ADDRESS), Ok(Some(acc_at10)) ); assert_eq!( - HistoricalStateProviderRef::new(&db, 11).basic_account(ADDRESS), + TestHistoricalStateProviderRef::new(&db, 11).basic_account(ADDRESS), Ok(Some(acc_at15)) ); assert_eq!( - HistoricalStateProviderRef::new(&db, 16).basic_account(ADDRESS), + TestHistoricalStateProviderRef::new(&db, 16).basic_account(ADDRESS), Ok(Some(acc_plain)) ); - assert_eq!(HistoricalStateProviderRef::new(&db, 1).basic_account(HIGHER_ADDRESS), Ok(None)); assert_eq!( - HistoricalStateProviderRef::new(&db, 1000).basic_account(HIGHER_ADDRESS), + TestHistoricalStateProviderRef::new(&db, 1).basic_account(HIGHER_ADDRESS), + Ok(None) + ); + assert_eq!( + TestHistoricalStateProviderRef::new(&db, 1000).basic_account(HIGHER_ADDRESS), Ok(Some(higher_acc_plain)) ); } @@ -681,41 +705,41 @@ mod tests { let db = factory.provider().unwrap(); // run - assert_eq!(HistoricalStateProviderRef::new(&db, 0).storage(ADDRESS, STORAGE), Ok(None)); + assert_eq!(TestHistoricalStateProviderRef::new(&db, 0).storage(ADDRESS, STORAGE), Ok(None)); assert_eq!( - HistoricalStateProviderRef::new(&db, 3).storage(ADDRESS, STORAGE), + TestHistoricalStateProviderRef::new(&db, 3).storage(ADDRESS, STORAGE), Ok(Some(U256::ZERO)) ); assert_eq!( - HistoricalStateProviderRef::new(&db, 4).storage(ADDRESS, STORAGE), + TestHistoricalStateProviderRef::new(&db, 4).storage(ADDRESS, STORAGE), Ok(Some(entry_at7.value)) ); assert_eq!( - HistoricalStateProviderRef::new(&db, 7).storage(ADDRESS, STORAGE), + TestHistoricalStateProviderRef::new(&db, 7).storage(ADDRESS, STORAGE), Ok(Some(entry_at7.value)) ); assert_eq!( - HistoricalStateProviderRef::new(&db, 9).storage(ADDRESS, STORAGE), + TestHistoricalStateProviderRef::new(&db, 9).storage(ADDRESS, STORAGE), Ok(Some(entry_at10.value)) ); assert_eq!( - HistoricalStateProviderRef::new(&db, 10).storage(ADDRESS, STORAGE), + TestHistoricalStateProviderRef::new(&db, 10).storage(ADDRESS, STORAGE), Ok(Some(entry_at10.value)) ); assert_eq!( - HistoricalStateProviderRef::new(&db, 11).storage(ADDRESS, STORAGE), + TestHistoricalStateProviderRef::new(&db, 11).storage(ADDRESS, STORAGE), Ok(Some(entry_at15.value)) ); assert_eq!( - HistoricalStateProviderRef::new(&db, 16).storage(ADDRESS, STORAGE), + TestHistoricalStateProviderRef::new(&db, 16).storage(ADDRESS, STORAGE), Ok(Some(entry_plain.value)) ); assert_eq!( - HistoricalStateProviderRef::new(&db, 1).storage(HIGHER_ADDRESS, STORAGE), + TestHistoricalStateProviderRef::new(&db, 1).storage(HIGHER_ADDRESS, STORAGE), Ok(None) ); assert_eq!( - HistoricalStateProviderRef::new(&db, 1000).storage(HIGHER_ADDRESS, STORAGE), + TestHistoricalStateProviderRef::new(&db, 1000).storage(HIGHER_ADDRESS, STORAGE), Ok(Some(higher_entry_plain.value)) ); } @@ -727,7 +751,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 = TestHistoricalStateProviderRef::new_with_lowest_available_blocks( &db, 2, LowestAvailableBlocks { @@ -746,7 +770,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 = TestHistoricalStateProviderRef::new_with_lowest_available_blocks( &db, 2, LowestAvailableBlocks { @@ -762,7 +786,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 = TestHistoricalStateProviderRef::new_with_lowest_available_blocks( &db, 2, LowestAvailableBlocks { diff --git a/crates/storage/provider/src/providers/state/latest.rs b/crates/storage/provider/src/providers/state/latest.rs index 297217acece7..bec5aa5e3ac6 100644 --- a/crates/storage/provider/src/providers/state/latest.rs +++ b/crates/storage/provider/src/providers/state/latest.rs @@ -1,3 +1,5 @@ +use std::marker::PhantomData; + use crate::{ providers::state::macros::delegate_provider_impls, AccountReader, BlockHashReader, StateProvider, StateRootProvider, @@ -24,14 +26,15 @@ use reth_trie_db::{ /// State provider over latest state that takes tx reference. /// -/// Wraps a [`DBProvider`] to get access to database. +/// Wraps a [`DBProvider`] to get access to database and [`reth_trie_db::StateCommitment`] +/// (`PhantomData`) to get access to state commitment operations. #[derive(Debug)] -pub struct LatestStateProviderRef<'b, Provider>(&'b Provider); +pub struct LatestStateProviderRef<'b, Provider, SC>(&'b Provider, PhantomData); -impl<'b, Provider: DBProvider> LatestStateProviderRef<'b, Provider> { +impl<'b, Provider: DBProvider, SC> LatestStateProviderRef<'b, Provider, SC> { /// Create new state provider pub const fn new(provider: &'b Provider) -> Self { - Self(provider) + Self(provider, PhantomData) } fn tx(&self) -> &Provider::Tx { @@ -39,14 +42,18 @@ impl<'b, Provider: DBProvider> LatestStateProviderRef<'b, Provider> { } } -impl AccountReader for LatestStateProviderRef<'_, Provider> { +impl AccountReader + for LatestStateProviderRef<'_, Provider, SC> +{ /// Get basic account information. fn basic_account(&self, address: Address) -> ProviderResult> { self.tx().get::(address).map_err(Into::into) } } -impl BlockHashReader for LatestStateProviderRef<'_, Provider> { +impl BlockHashReader + for LatestStateProviderRef<'_, Provider, SC> +{ /// Get block hash by number. fn block_hash(&self, number: u64) -> ProviderResult> { self.0.block_hash(number) @@ -61,7 +68,9 @@ impl BlockHashReader for LatestStateProviderRef<'_, P } } -impl StateRootProvider for LatestStateProviderRef<'_, Provider> { +impl StateRootProvider + for LatestStateProviderRef<'_, Provider, SC> +{ fn state_root(&self, hashed_state: HashedPostState) -> ProviderResult { StateRoot::overlay_root(self.tx(), hashed_state) .map_err(|err| ProviderError::Database(err.into())) @@ -89,7 +98,9 @@ impl StateRootProvider for LatestStateProviderRef<'_, Prov } } -impl StorageRootProvider for LatestStateProviderRef<'_, Provider> { +impl StorageRootProvider + for LatestStateProviderRef<'_, Provider, SC> +{ fn storage_root( &self, address: Address, @@ -110,7 +121,9 @@ impl StorageRootProvider for LatestStateProviderRef<'_, Pr } } -impl StateProofProvider for LatestStateProviderRef<'_, Provider> { +impl StateProofProvider + for LatestStateProviderRef<'_, Provider, SC> +{ fn proof( &self, input: TrieInput, @@ -138,8 +151,8 @@ impl StateProofProvider for LatestStateProviderRef<'_, Pro } } -impl StateProvider - for LatestStateProviderRef<'_, Provider> +impl StateProvider + for LatestStateProviderRef<'_, Provider, SC> { /// Get storage. fn storage( @@ -164,23 +177,23 @@ impl StateProvider /// State provider for the latest state. #[derive(Debug)] -pub struct LatestStateProvider(Provider); +pub struct LatestStateProvider(Provider, PhantomData); -impl LatestStateProvider { +impl LatestStateProvider { /// Create new state provider pub const fn new(db: Provider) -> Self { - Self(db) + Self(db, PhantomData) } /// Returns a new provider that takes the `TX` as reference #[inline(always)] - const fn as_ref(&self) -> LatestStateProviderRef<'_, Provider> { + const fn as_ref(&self) -> LatestStateProviderRef<'_, Provider, SC> { LatestStateProviderRef::new(&self.0) } } // Delegates all provider impls to [LatestStateProviderRef] -delegate_provider_impls!(LatestStateProvider where [Provider: DBProvider + BlockHashReader]); +delegate_provider_impls!(LatestStateProvider where [Provider: DBProvider + BlockHashReader, SC: Send + Sync]); #[cfg(test)] mod tests { @@ -188,7 +201,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/storage-api/src/state.rs b/crates/storage/storage-api/src/state.rs index d37940f04787..6c9e82cfba3b 100644 --- a/crates/storage/storage-api/src/state.rs +++ b/crates/storage/storage-api/src/state.rs @@ -91,6 +91,13 @@ pub trait TryIntoHistoricalStateProvider { ) -> ProviderResult; } +/// Trait implemented for database providers that can be converted into a latest state provider +/// reference. +pub trait AsLatestStateProviderRef { + /// 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. /// From 52426dbce689ea4595881023834c32166a17959f Mon Sep 17 00:00:00 2001 From: frisitano Date: Wed, 20 Nov 2024 12:57:08 +0800 Subject: [PATCH 02/15] refactor: introduce StateCommimentProvider --- Cargo.lock | 1 + .../commands/debug_cmd/in_memory_merkle.rs | 8 +- bin/reth/src/commands/debug_cmd/merkle.rs | 11 +- crates/exex/exex/src/backfill/test_utils.rs | 6 +- crates/stages/stages/src/stages/execution.rs | 15 +- .../provider/src/providers/consistent.rs | 10 +- .../provider/src/providers/database/mod.rs | 4 +- .../src/providers/database/provider.rs | 42 +++--- .../src/providers/state/historical.rs | 133 ++++++++---------- .../provider/src/providers/state/latest.rs | 55 ++++---- crates/storage/storage-api/Cargo.toml | 1 + crates/storage/storage-api/src/state.rs | 14 +- 12 files changed, 142 insertions(+), 158 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 973ad4718720..f1fb2f89eeaa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9183,6 +9183,7 @@ dependencies = [ "reth-stages-types", "reth-storage-errors", "reth-trie", + "reth-trie-db", ] [[package]] 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 ef186ca050e1..d5bb8a87b22e 100644 --- a/bin/reth/src/commands/debug_cmd/in_memory_merkle.rs +++ b/bin/reth/src/commands/debug_cmd/in_memory_merkle.rs @@ -22,9 +22,9 @@ use reth_network_api::NetworkInfo; use reth_node_api::{NodeTypesWithDB, NodeTypesWithEngine}; use reth_node_ethereum::EthExecutorProvider; use reth_provider::{ - writer::UnifiedStorageWriter, AccountExtReader, AsLatestStateProviderRef, ChainSpecProvider, - HashingWriter, HeaderProvider, OriginalValuesKnown, ProviderFactory, StageCheckpointReader, - StateWriter, StorageReader, + writer::UnifiedStorageWriter, AccountExtReader, ChainSpecProvider, HashingWriter, + HeaderProvider, LatestStateProviderRef, OriginalValuesKnown, ProviderFactory, + StageCheckpointReader, StateWriter, StorageReader, }; use reth_revm::database::StateProviderDatabase; use reth_stages::StageId; @@ -133,7 +133,7 @@ impl> Command { ) .await?; - let db = StateProviderDatabase::new(provider.latest()); + let db = StateProviderDatabase::new(LatestStateProviderRef::new(&provider)); 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 4128b982ca24..9c77c70abc74 100644 --- a/bin/reth/src/commands/debug_cmd/merkle.rs +++ b/bin/reth/src/commands/debug_cmd/merkle.rs @@ -20,9 +20,9 @@ use reth_network_p2p::full_block::FullBlockClient; use reth_node_api::{NodeTypesWithDB, NodeTypesWithEngine}; use reth_node_ethereum::EthExecutorProvider; use reth_provider::{ - writer::UnifiedStorageWriter, AsLatestStateProviderRef, BlockNumReader, BlockWriter, - ChainSpecProvider, DatabaseProviderFactory, HeaderProvider, OriginalValuesKnown, ProviderError, - ProviderFactory, StateWriter, + writer::UnifiedStorageWriter, BlockNumReader, BlockWriter, ChainSpecProvider, + DatabaseProviderFactory, HeaderProvider, LatestStateProviderRef, OriginalValuesKnown, + ProviderError, ProviderFactory, StateWriter, }; use reth_revm::database::StateProviderDatabase; use reth_stages::{ @@ -152,8 +152,9 @@ impl> Command { provider_rw.insert_block(sealed_block.clone())?; td += sealed_block.difficulty; - let mut executor = - executor_provider.batch_executor(StateProviderDatabase::new(provider_rw.latest())); + let mut executor = executor_provider.batch_executor(StateProviderDatabase::new( + LatestStateProviderRef::new(&provider_rw), + )); 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 222f9dc1d0d2..80af408c5c8f 100644 --- a/crates/exex/exex/src/backfill/test_utils.rs +++ b/crates/exex/exex/src/backfill/test_utils.rs @@ -13,7 +13,7 @@ use reth_primitives::{ Block, BlockBody, BlockWithSenders, Receipt, SealedBlockWithSenders, Transaction, }; use reth_provider::{ - providers::ProviderNodeTypes, AsLatestStateProviderRef, BlockWriter as _, ExecutionOutcome, + providers::ProviderNodeTypes, BlockWriter as _, ExecutionOutcome, LatestStateProviderRef, ProviderFactory, }; use reth_revm::database::StateProviderDatabase; @@ -63,7 +63,7 @@ where // Execute the block to produce a block execution output let mut block_execution_output = EthExecutorProvider::ethereum(chain_spec) - .executor(StateProviderDatabase::new(provider.latest())) + .executor(StateProviderDatabase::new(LatestStateProviderRef::new(&provider))) .execute(BlockExecutionInput { block, total_difficulty: U256::ZERO })?; block_execution_output.state.reverts.sort(); @@ -189,7 +189,7 @@ where let provider = provider_factory.provider()?; let executor = EthExecutorProvider::ethereum(chain_spec) - .batch_executor(StateProviderDatabase::new(provider.latest())); + .batch_executor(StateProviderDatabase::new(LatestStateProviderRef::new(&provider))); let mut execution_outcome = executor.execute_and_verify_batch(vec![ (&block1, U256::ZERO).into(), diff --git a/crates/stages/stages/src/stages/execution.rs b/crates/stages/stages/src/stages/execution.rs index 7c6d41bd536f..c8bcc8ae389a 100644 --- a/crates/stages/stages/src/stages/execution.rs +++ b/crates/stages/stages/src/stages/execution.rs @@ -16,9 +16,9 @@ use reth_primitives_traits::{format_gas_throughput, NodePrimitives}; use reth_provider::{ providers::{StaticFileProvider, StaticFileProviderRWRefMut, StaticFileWriter}, writer::UnifiedStorageWriter, - AsLatestStateProviderRef, BlockHashReader, BlockReader, DBProvider, HeaderProvider, - OriginalValuesKnown, ProviderError, StateChangeWriter, StateWriter, StaticFileProviderFactory, - StatsReader, TransactionVariant, + BlockHashReader, BlockReader, DBProvider, HeaderProvider, LatestStateProviderRef, + OriginalValuesKnown, ProviderError, StateChangeWriter, StateCommitmentProvider, StateWriter, + StaticFileProviderFactory, StatsReader, TransactionVariant, }; use reth_prune_types::PruneModes; use reth_revm::database::StateProviderDatabase; @@ -46,9 +46,8 @@ use tracing::*; /// - [`tables::BlockBodyIndices`] to get tx number /// - [`tables::Transactions`] to execute /// -/// For state access [`reth_provider::LatestStateProviderRef`] provides us latest state and history -/// state For latest most recent state [`reth_provider::LatestStateProviderRef`] would need (Used -/// for execution Stage): +/// For state access [`LatestStateProviderRef`] provides us latest state and history state +/// For latest most recent state [`LatestStateProviderRef`] would need (Used for execution Stage): /// - [`tables::PlainAccountState`] /// - [`tables::Bytecodes`] /// - [`tables::PlainStorageState`] @@ -182,7 +181,7 @@ where + StatsReader + StateChangeWriter + BlockHashReader - + AsLatestStateProviderRef, + + StateCommitmentProvider, for<'a> UnifiedStorageWriter<'a, Provider, StaticFileProviderRWRefMut<'a, Provider::Primitives>>: StateWriter, { @@ -227,7 +226,7 @@ where None }; - let db = StateProviderDatabase(provider.latest()); + let db = StateProviderDatabase(LatestStateProviderRef::new(provider)); let mut executor = self.executor_provider.batch_executor(db); executor.set_tip(max_block); executor.set_prune_modes(prune_modes); diff --git a/crates/storage/provider/src/providers/consistent.rs b/crates/storage/provider/src/providers/consistent.rs index a5980bcd7d48..7702504ced4a 100644 --- a/crates/storage/provider/src/providers/consistent.rs +++ b/crates/storage/provider/src/providers/consistent.rs @@ -1,10 +1,10 @@ use super::{DatabaseProviderRO, ProviderFactory, ProviderNodeTypes}; use crate::{ - providers::StaticFileProvider, AccountReader, AsLatestStateProviderRef, BlockHashReader, - BlockIdReader, BlockNumReader, BlockReader, BlockReaderIdExt, BlockSource, ChainSpecProvider, - ChangeSetReader, EvmEnvProvider, HeaderProvider, ProviderError, PruneCheckpointReader, - ReceiptProvider, ReceiptProviderIdExt, StageCheckpointReader, StateReader, - StaticFileProviderFactory, TransactionVariant, TransactionsProvider, WithdrawalsProvider, + providers::StaticFileProvider, AccountReader, BlockHashReader, BlockIdReader, BlockNumReader, + BlockReader, BlockReaderIdExt, BlockSource, ChainSpecProvider, ChangeSetReader, EvmEnvProvider, + HeaderProvider, ProviderError, PruneCheckpointReader, ReceiptProvider, ReceiptProviderIdExt, + StageCheckpointReader, StateReader, StaticFileProviderFactory, TransactionVariant, + TransactionsProvider, WithdrawalsProvider, }; use alloy_consensus::Header; use alloy_eips::{ diff --git a/crates/storage/provider/src/providers/database/mod.rs b/crates/storage/provider/src/providers/database/mod.rs index 14fc6f765f63..94c83bbb4422 100644 --- a/crates/storage/provider/src/providers/database/mod.rs +++ b/crates/storage/provider/src/providers/database/mod.rs @@ -160,9 +160,7 @@ impl ProviderFactory { #[track_caller] pub fn latest(&self) -> ProviderResult { trace!(target: "providers::db", "Returning latest state provider"); - Ok(Box::new(LatestStateProvider::<_, N::StateCommitment>::new( - self.database_provider_ro()?, - ))) + Ok(Box::new(LatestStateProvider::new(self.database_provider_ro()?))) } /// Storage provider for state at that given block diff --git a/crates/storage/provider/src/providers/database/provider.rs b/crates/storage/provider/src/providers/database/provider.rs index 94b57c2113e4..ab5ed783e898 100644 --- a/crates/storage/provider/src/providers/database/provider.rs +++ b/crates/storage/provider/src/providers/database/provider.rs @@ -6,15 +6,15 @@ use crate::{ AccountExtReader, BlockSource, ChangeSetReader, ReceiptProvider, StageCheckpointWriter, }, writer::UnifiedStorageWriter, - AccountReader, AsLatestStateProviderRef, BlockExecutionWriter, BlockHashReader, BlockNumReader, - BlockReader, BlockWriter, BundleStateInit, ChainStateBlockReader, ChainStateBlockWriter, - DBProvider, EvmEnvProvider, HashingWriter, HeaderProvider, HeaderSyncGap, - HeaderSyncGapProvider, HistoricalStateProvider, HistoricalStateProviderRef, HistoryWriter, - LatestStateProvider, LatestStateProviderRef, OriginalValuesKnown, ProviderError, - PruneCheckpointReader, PruneCheckpointWriter, RevertsInit, StageCheckpointReader, - StateChangeWriter, StateProviderBox, StateReader, StateWriter, StaticFileProviderFactory, - StatsReader, StorageReader, StorageTrieWriter, TransactionVariant, TransactionsProvider, - TransactionsProviderExt, TrieWriter, WithdrawalsProvider, + AccountReader, BlockExecutionWriter, BlockHashReader, BlockNumReader, BlockReader, BlockWriter, + BundleStateInit, ChainStateBlockReader, ChainStateBlockWriter, DBProvider, EvmEnvProvider, + HashingWriter, HeaderProvider, HeaderSyncGap, HeaderSyncGapProvider, HistoricalStateProvider, + HistoricalStateProviderRef, HistoryWriter, LatestStateProvider, LatestStateProviderRef, + OriginalValuesKnown, ProviderError, PruneCheckpointReader, PruneCheckpointWriter, RevertsInit, + StageCheckpointReader, StateChangeWriter, StateCommitmentProvider, StateProviderBox, + StateReader, StateWriter, StaticFileProviderFactory, StatsReader, StorageReader, + StorageTrieWriter, TransactionVariant, TransactionsProvider, TransactionsProviderExt, + TrieWriter, WithdrawalsProvider, }; use alloy_consensus::Header; use alloy_eips::{ @@ -149,6 +149,12 @@ impl DatabaseProvider { } impl DatabaseProvider { + /// State provider for latest state + pub fn latest<'a>(&'a self) -> Box { + trace!(target: "providers::db", "Returning latest state provider"); + Box::new(LatestStateProviderRef::new(self)) + } + /// Storage provider for state at that given block hash pub fn history_by_block_hash<'a>( &'a self, @@ -159,7 +165,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::<'_, _, N::StateCommitment>::new(self))) + return Ok(Box::new(LatestStateProviderRef::new(self))) } // +1 as the changeset that we want is the one that was applied after this block. @@ -170,8 +176,7 @@ impl DatabaseProvider { let storage_history_prune_checkpoint = self.get_prune_checkpoint(PruneSegment::StorageHistory)?; - let mut state_provider = - HistoricalStateProviderRef::<'_, _, N::StateCommitment>::new(self, block_number); + let mut state_provider = HistoricalStateProviderRef::new(self, block_number); // 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. @@ -239,7 +244,7 @@ impl TryIntoHistoricalStateProvider for Databa if block_number == self.best_block_number().unwrap_or_default() && block_number == self.last_block_number().unwrap_or_default() { - return Ok(Box::new(LatestStateProvider::<_, N::StateCommitment>::new(self))) + return Ok(Box::new(LatestStateProvider::new(self))) } // +1 as the changeset that we want is the one that was applied after this block. @@ -250,8 +255,7 @@ impl TryIntoHistoricalStateProvider for Databa let storage_history_prune_checkpoint = self.get_prune_checkpoint(PruneSegment::StorageHistory)?; - let mut state_provider = - HistoricalStateProvider::<_, N::StateCommitment>::new(self, block_number); + let mut state_provider = HistoricalStateProvider::new(self, block_number); // 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. @@ -274,12 +278,8 @@ impl TryIntoHistoricalStateProvider for Databa } } -impl AsLatestStateProviderRef for DatabaseProvider { - /// State provider for latest state - fn latest<'a>(&'a self) -> Box { - trace!(target: "providers::db", "Returning latest state provider"); - Box::new(LatestStateProviderRef::<'_, _, N::StateCommitment>::new(self)) - } +impl StateCommitmentProvider for DatabaseProvider { + type StateCommitment = N::StateCommitment; } impl + 'static> diff --git a/crates/storage/provider/src/providers/state/historical.rs b/crates/storage/provider/src/providers/state/historical.rs index 2cc912af9791..a70fe9ac203b 100644 --- a/crates/storage/provider/src/providers/state/historical.rs +++ b/crates/storage/provider/src/providers/state/historical.rs @@ -15,7 +15,9 @@ use reth_db_api::{ transaction::DbTx, }; use reth_primitives::{Account, Bytecode}; -use reth_storage_api::{BlockNumReader, DBProvider, StateProofProvider, StorageRootProvider}; +use reth_storage_api::{ + BlockNumReader, DBProvider, StateCommitmentProvider, StateProofProvider, StorageRootProvider, +}; use reth_storage_errors::provider::ProviderResult; use reth_trie::{ proof::{Proof, StorageProof}, @@ -27,7 +29,7 @@ use reth_trie_db::{ DatabaseHashedPostState, DatabaseHashedStorage, DatabaseProof, DatabaseStateRoot, DatabaseStorageProof, DatabaseStorageRoot, DatabaseTrieWitness, }; -use std::{fmt::Debug, marker::PhantomData}; +use std::fmt::Debug; /// State provider for a given block number which takes a tx reference. /// @@ -41,15 +43,13 @@ use std::{fmt::Debug, marker::PhantomData}; /// - [`tables::AccountChangeSets`] /// - [`tables::StorageChangeSets`] #[derive(Debug)] -pub struct HistoricalStateProviderRef<'b, Provider, SC> { +pub struct HistoricalStateProviderRef<'b, Provider> { /// Database provider provider: &'b Provider, /// Block number is main index for the history state of accounts and storages. block_number: BlockNumber, /// Lowest blocks at which different parts of the state are available. lowest_available_blocks: LowestAvailableBlocks, - /// Marker to associate the `StateCommitment` type with this provider. - _marker: PhantomData, } #[derive(Debug, Eq, PartialEq)] @@ -60,15 +60,12 @@ pub enum HistoryInfo { MaybeInPlainState, } -impl<'b, Provider: DBProvider + BlockNumReader, SC> HistoricalStateProviderRef<'b, Provider, SC> { +impl<'b, Provider: DBProvider + BlockNumReader + StateCommitmentProvider> + HistoricalStateProviderRef<'b, Provider> +{ /// Create new `StateProvider` for historical block number pub fn new(provider: &'b Provider, block_number: BlockNumber) -> Self { - Self { - provider, - block_number, - lowest_available_blocks: Default::default(), - _marker: PhantomData, - } + Self { provider, block_number, lowest_available_blocks: Default::default() } } /// Create new `StateProvider` for historical block number and lowest block numbers at which @@ -78,7 +75,7 @@ impl<'b, Provider: DBProvider + BlockNumReader, SC> HistoricalStateProviderRef<' block_number: BlockNumber, lowest_available_blocks: LowestAvailableBlocks, ) -> Self { - Self { provider, block_number, lowest_available_blocks, _marker: PhantomData } + Self { provider, block_number, lowest_available_blocks } } /// Lookup an account in the `AccountsHistory` table @@ -240,14 +237,14 @@ impl<'b, Provider: DBProvider + BlockNumReader, SC> HistoricalStateProviderRef<' } } -impl HistoricalStateProviderRef<'_, Provider, SC> { +impl HistoricalStateProviderRef<'_, Provider> { fn tx(&self) -> &Provider::Tx { self.provider.tx_ref() } } -impl AccountReader - for HistoricalStateProviderRef<'_, Provider, SC> +impl AccountReader + for HistoricalStateProviderRef<'_, Provider> { /// Get basic account information. fn basic_account(&self, address: Address) -> ProviderResult> { @@ -270,8 +267,8 @@ impl AccountReader } } -impl BlockHashReader - for HistoricalStateProviderRef<'_, Provider, SC> +impl BlockHashReader + for HistoricalStateProviderRef<'_, Provider> { /// Get block hash by number. fn block_hash(&self, number: u64) -> ProviderResult> { @@ -287,8 +284,8 @@ impl B } } -impl StateRootProvider - for HistoricalStateProviderRef<'_, Provider, SC> +impl StateRootProvider + for HistoricalStateProviderRef<'_, Provider> { fn state_root(&self, hashed_state: HashedPostState) -> ProviderResult { let mut revert_state = self.revert_state()?; @@ -323,8 +320,8 @@ impl StateRootProvider } } -impl StorageRootProvider - for HistoricalStateProviderRef<'_, Provider, SC> +impl StorageRootProvider + for HistoricalStateProviderRef<'_, Provider> { fn storage_root( &self, @@ -350,8 +347,8 @@ impl StorageRootProvider } } -impl StateProofProvider - for HistoricalStateProviderRef<'_, Provider, SC> +impl StateProofProvider + for HistoricalStateProviderRef<'_, Provider> { /// Get account and storage proofs. fn proof( @@ -384,8 +381,8 @@ impl StateProofProvider } } -impl StateProvider - for HistoricalStateProviderRef<'_, Provider, SC> +impl + StateProvider for HistoricalStateProviderRef<'_, Provider> { /// Get storage. fn storage( @@ -426,26 +423,21 @@ impl S /// State provider for a given block number. /// For more detailed description, see [`HistoricalStateProviderRef`]. #[derive(Debug)] -pub struct HistoricalStateProvider { +pub struct HistoricalStateProvider { /// Database provider. provider: Provider, /// State at the block number is the main indexer of the state. block_number: BlockNumber, /// Lowest blocks at which different parts of the state are available. lowest_available_blocks: LowestAvailableBlocks, - /// 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(provider: Provider, block_number: BlockNumber) -> Self { - Self { - provider, - block_number, - lowest_available_blocks: Default::default(), - _marker: PhantomData, - } + Self { provider, block_number, lowest_available_blocks: Default::default() } } /// Set the lowest block number at which the account history is available. @@ -468,7 +460,7 @@ impl HistoricalStateProvider HistoricalStateProviderRef<'_, Provider, SC> { + const fn as_ref(&self) -> HistoricalStateProviderRef<'_, Provider> { HistoricalStateProviderRef::new_with_lowest_available_blocks( &self.provider, self.block_number, @@ -478,7 +470,7 @@ impl HistoricalStateProvider where [Provider: DBProvider + BlockNumReader + BlockHashReader, SC: Send + Sync]); +delegate_provider_impls!(HistoricalStateProvider where [Provider: DBProvider + BlockNumReader + BlockHashReader + StateCommitmentProvider]); /// Lowest blocks at which different parts of the state are available. /// They may be [Some] if pruning is enabled. @@ -522,12 +514,11 @@ mod tests { transaction::{DbTx, DbTxMut}, }; use reth_primitives::{Account, StorageEntry}; - use reth_storage_api::{BlockHashReader, BlockNumReader, DBProvider, DatabaseProviderFactory}; + use reth_storage_api::{ + BlockHashReader, BlockNumReader, DBProvider, DatabaseProviderFactory, + StateCommitmentProvider, + }; use reth_storage_errors::provider::ProviderError; - use reth_trie_db::MerklePatriciaTrie; - - type TestHistoricalStateProviderRef<'a, TX> = - HistoricalStateProviderRef<'a, TX, MerklePatriciaTrie>; const ADDRESS: Address = address!("0000000000000000000000000000000000000001"); const HIGHER_ADDRESS: Address = address!("0000000000000000000000000000000000000005"); @@ -536,10 +527,9 @@ mod tests { const fn assert_state_provider() {} #[allow(dead_code)] const fn assert_historical_state_provider< - T: DBProvider + BlockNumReader + BlockHashReader, - SC: Send + Sync, + T: DBProvider + BlockNumReader + BlockHashReader + StateCommitmentProvider, >() { - assert_state_provider::>(); + assert_state_provider::>(); } #[test] @@ -608,46 +598,43 @@ mod tests { let db = factory.provider().unwrap(); // run - assert_eq!(TestHistoricalStateProviderRef::new(&db, 1).basic_account(ADDRESS), Ok(None)); + assert_eq!(HistoricalStateProviderRef::new(&db, 1).basic_account(ADDRESS), Ok(None)); assert_eq!( - TestHistoricalStateProviderRef::new(&db, 2).basic_account(ADDRESS), + HistoricalStateProviderRef::new(&db, 2).basic_account(ADDRESS), Ok(Some(acc_at3)) ); assert_eq!( - TestHistoricalStateProviderRef::new(&db, 3).basic_account(ADDRESS), + HistoricalStateProviderRef::new(&db, 3).basic_account(ADDRESS), Ok(Some(acc_at3)) ); assert_eq!( - TestHistoricalStateProviderRef::new(&db, 4).basic_account(ADDRESS), + HistoricalStateProviderRef::new(&db, 4).basic_account(ADDRESS), Ok(Some(acc_at7)) ); assert_eq!( - TestHistoricalStateProviderRef::new(&db, 7).basic_account(ADDRESS), + HistoricalStateProviderRef::new(&db, 7).basic_account(ADDRESS), Ok(Some(acc_at7)) ); assert_eq!( - TestHistoricalStateProviderRef::new(&db, 9).basic_account(ADDRESS), + HistoricalStateProviderRef::new(&db, 9).basic_account(ADDRESS), Ok(Some(acc_at10)) ); assert_eq!( - TestHistoricalStateProviderRef::new(&db, 10).basic_account(ADDRESS), + HistoricalStateProviderRef::new(&db, 10).basic_account(ADDRESS), Ok(Some(acc_at10)) ); assert_eq!( - TestHistoricalStateProviderRef::new(&db, 11).basic_account(ADDRESS), + HistoricalStateProviderRef::new(&db, 11).basic_account(ADDRESS), Ok(Some(acc_at15)) ); assert_eq!( - TestHistoricalStateProviderRef::new(&db, 16).basic_account(ADDRESS), + HistoricalStateProviderRef::new(&db, 16).basic_account(ADDRESS), Ok(Some(acc_plain)) ); + assert_eq!(HistoricalStateProviderRef::new(&db, 1).basic_account(HIGHER_ADDRESS), Ok(None)); assert_eq!( - TestHistoricalStateProviderRef::new(&db, 1).basic_account(HIGHER_ADDRESS), - Ok(None) - ); - assert_eq!( - TestHistoricalStateProviderRef::new(&db, 1000).basic_account(HIGHER_ADDRESS), + HistoricalStateProviderRef::new(&db, 1000).basic_account(HIGHER_ADDRESS), Ok(Some(higher_acc_plain)) ); } @@ -705,41 +692,41 @@ mod tests { let db = factory.provider().unwrap(); // run - assert_eq!(TestHistoricalStateProviderRef::new(&db, 0).storage(ADDRESS, STORAGE), Ok(None)); + assert_eq!(HistoricalStateProviderRef::new(&db, 0).storage(ADDRESS, STORAGE), Ok(None)); assert_eq!( - TestHistoricalStateProviderRef::new(&db, 3).storage(ADDRESS, STORAGE), + HistoricalStateProviderRef::new(&db, 3).storage(ADDRESS, STORAGE), Ok(Some(U256::ZERO)) ); assert_eq!( - TestHistoricalStateProviderRef::new(&db, 4).storage(ADDRESS, STORAGE), + HistoricalStateProviderRef::new(&db, 4).storage(ADDRESS, STORAGE), Ok(Some(entry_at7.value)) ); assert_eq!( - TestHistoricalStateProviderRef::new(&db, 7).storage(ADDRESS, STORAGE), + HistoricalStateProviderRef::new(&db, 7).storage(ADDRESS, STORAGE), Ok(Some(entry_at7.value)) ); assert_eq!( - TestHistoricalStateProviderRef::new(&db, 9).storage(ADDRESS, STORAGE), + HistoricalStateProviderRef::new(&db, 9).storage(ADDRESS, STORAGE), Ok(Some(entry_at10.value)) ); assert_eq!( - TestHistoricalStateProviderRef::new(&db, 10).storage(ADDRESS, STORAGE), + HistoricalStateProviderRef::new(&db, 10).storage(ADDRESS, STORAGE), Ok(Some(entry_at10.value)) ); assert_eq!( - TestHistoricalStateProviderRef::new(&db, 11).storage(ADDRESS, STORAGE), + HistoricalStateProviderRef::new(&db, 11).storage(ADDRESS, STORAGE), Ok(Some(entry_at15.value)) ); assert_eq!( - TestHistoricalStateProviderRef::new(&db, 16).storage(ADDRESS, STORAGE), + HistoricalStateProviderRef::new(&db, 16).storage(ADDRESS, STORAGE), Ok(Some(entry_plain.value)) ); assert_eq!( - TestHistoricalStateProviderRef::new(&db, 1).storage(HIGHER_ADDRESS, STORAGE), + HistoricalStateProviderRef::new(&db, 1).storage(HIGHER_ADDRESS, STORAGE), Ok(None) ); assert_eq!( - TestHistoricalStateProviderRef::new(&db, 1000).storage(HIGHER_ADDRESS, STORAGE), + HistoricalStateProviderRef::new(&db, 1000).storage(HIGHER_ADDRESS, STORAGE), Ok(Some(higher_entry_plain.value)) ); } @@ -751,7 +738,7 @@ mod tests { // provider block_number < lowest available block number, // i.e. state at provider block is pruned - let provider = TestHistoricalStateProviderRef::new_with_lowest_available_blocks( + let provider = HistoricalStateProviderRef::new_with_lowest_available_blocks( &db, 2, LowestAvailableBlocks { @@ -770,7 +757,7 @@ mod tests { // provider block_number == lowest available block number, // i.e. state at provider block is available - let provider = TestHistoricalStateProviderRef::new_with_lowest_available_blocks( + let provider = HistoricalStateProviderRef::new_with_lowest_available_blocks( &db, 2, LowestAvailableBlocks { @@ -786,7 +773,7 @@ mod tests { // provider block_number == lowest available block number, // i.e. state at provider block is available - let provider = TestHistoricalStateProviderRef::new_with_lowest_available_blocks( + let provider = HistoricalStateProviderRef::new_with_lowest_available_blocks( &db, 2, LowestAvailableBlocks { diff --git a/crates/storage/provider/src/providers/state/latest.rs b/crates/storage/provider/src/providers/state/latest.rs index bec5aa5e3ac6..ab70d759b992 100644 --- a/crates/storage/provider/src/providers/state/latest.rs +++ b/crates/storage/provider/src/providers/state/latest.rs @@ -1,5 +1,3 @@ -use std::marker::PhantomData; - use crate::{ providers::state::macros::delegate_provider_impls, AccountReader, BlockHashReader, StateProvider, StateRootProvider, @@ -11,7 +9,9 @@ use alloy_primitives::{ use reth_db::tables; use reth_db_api::{cursor::DbDupCursorRO, transaction::DbTx}; use reth_primitives::{Account, Bytecode}; -use reth_storage_api::{DBProvider, StateProofProvider, StorageRootProvider}; +use reth_storage_api::{ + DBProvider, StateCommitmentProvider, StateProofProvider, StorageRootProvider, +}; use reth_storage_errors::provider::{ProviderError, ProviderResult}; use reth_trie::{ proof::{Proof, StorageProof}, @@ -26,15 +26,14 @@ use reth_trie_db::{ /// State provider over latest state that takes tx reference. /// -/// Wraps a [`DBProvider`] to get access to database and [`reth_trie_db::StateCommitment`] -/// (`PhantomData`) to get access to state commitment operations. +/// Wraps a [`DBProvider`] to get access to database. #[derive(Debug)] -pub struct LatestStateProviderRef<'b, Provider, SC>(&'b Provider, PhantomData); +pub struct LatestStateProviderRef<'b, Provider>(&'b Provider); -impl<'b, Provider: DBProvider, SC> LatestStateProviderRef<'b, Provider, SC> { +impl<'b, Provider: DBProvider> LatestStateProviderRef<'b, Provider> { /// Create new state provider pub const fn new(provider: &'b Provider) -> Self { - Self(provider, PhantomData) + Self(provider) } fn tx(&self) -> &Provider::Tx { @@ -42,18 +41,14 @@ impl<'b, Provider: DBProvider, SC> LatestStateProviderRef<'b, Provider, SC> { } } -impl AccountReader - for LatestStateProviderRef<'_, Provider, SC> -{ +impl AccountReader for LatestStateProviderRef<'_, Provider> { /// Get basic account information. fn basic_account(&self, address: Address) -> ProviderResult> { self.tx().get::(address).map_err(Into::into) } } -impl BlockHashReader - for LatestStateProviderRef<'_, Provider, SC> -{ +impl BlockHashReader for LatestStateProviderRef<'_, Provider> { /// Get block hash by number. fn block_hash(&self, number: u64) -> ProviderResult> { self.0.block_hash(number) @@ -68,8 +63,8 @@ impl BlockHashReader } } -impl StateRootProvider - for LatestStateProviderRef<'_, Provider, SC> +impl StateRootProvider + for LatestStateProviderRef<'_, Provider> { fn state_root(&self, hashed_state: HashedPostState) -> ProviderResult { StateRoot::overlay_root(self.tx(), hashed_state) @@ -98,8 +93,8 @@ impl StateRootProvider } } -impl StorageRootProvider - for LatestStateProviderRef<'_, Provider, SC> +impl StorageRootProvider + for LatestStateProviderRef<'_, Provider> { fn storage_root( &self, @@ -121,8 +116,8 @@ impl StorageRootProvider } } -impl StateProofProvider - for LatestStateProviderRef<'_, Provider, SC> +impl StateProofProvider + for LatestStateProviderRef<'_, Provider> { fn proof( &self, @@ -151,8 +146,8 @@ impl StateProofProvider } } -impl StateProvider - for LatestStateProviderRef<'_, Provider, SC> +impl StateProvider + for LatestStateProviderRef<'_, Provider> { /// Get storage. fn storage( @@ -177,23 +172,23 @@ impl StateProvider /// State provider for the latest state. #[derive(Debug)] -pub struct LatestStateProvider(Provider, PhantomData); +pub struct LatestStateProvider(Provider); -impl LatestStateProvider { +impl LatestStateProvider { /// Create new state provider pub const fn new(db: Provider) -> Self { - Self(db, PhantomData) + Self(db) } /// Returns a new provider that takes the `TX` as reference #[inline(always)] - const fn as_ref(&self) -> LatestStateProviderRef<'_, Provider, SC> { + const fn as_ref(&self) -> LatestStateProviderRef<'_, Provider> { LatestStateProviderRef::new(&self.0) } } // Delegates all provider impls to [LatestStateProviderRef] -delegate_provider_impls!(LatestStateProvider where [Provider: DBProvider + BlockHashReader, SC: Send + Sync]); +delegate_provider_impls!(LatestStateProvider where [Provider: DBProvider + BlockHashReader + StateCommitmentProvider]); #[cfg(test)] mod tests { @@ -201,7 +196,9 @@ 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< + T: DBProvider + BlockHashReader + StateCommitmentProvider, + >() { + assert_state_provider::>(); } } diff --git a/crates/storage/storage-api/Cargo.toml b/crates/storage/storage-api/Cargo.toml index 2b13f6332f87..88e35c18f8c6 100644 --- a/crates/storage/storage-api/Cargo.toml +++ b/crates/storage/storage-api/Cargo.toml @@ -22,6 +22,7 @@ reth-prune-types.workspace = true reth-stages-types.workspace = true reth-storage-errors.workspace = true reth-trie.workspace = true +reth-trie-db.workspace = true reth-db.workspace = true # ethereum diff --git a/crates/storage/storage-api/src/state.rs b/crates/storage/storage-api/src/state.rs index 6c9e82cfba3b..49db24a9bb93 100644 --- a/crates/storage/storage-api/src/state.rs +++ b/crates/storage/storage-api/src/state.rs @@ -9,6 +9,7 @@ use auto_impl::auto_impl; use reth_execution_types::ExecutionOutcome; use reth_primitives::Bytecode; use reth_storage_errors::provider::{ProviderError, ProviderResult}; +use reth_trie_db::StateCommitment; /// Type alias of boxed [`StateProvider`]. pub type StateProviderBox = Box; @@ -82,6 +83,12 @@ pub trait StateProvider: } } +/// Trait implemented for database providers that can provide the [`StateCommitment`] type. +pub trait StateCommitmentProvider { + /// The [`StateCommitment`] type that can be used to perform state commitment operations. + type StateCommitment: StateCommitment; +} + /// Trait implemented for database providers that can be converted into a historical state provider. pub trait TryIntoHistoricalStateProvider { /// Returns a historical [`StateProvider`] indexed by the given historic block number. @@ -91,13 +98,6 @@ pub trait TryIntoHistoricalStateProvider { ) -> ProviderResult; } -/// Trait implemented for database providers that can be converted into a latest state provider -/// reference. -pub trait AsLatestStateProviderRef { - /// 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. /// From 10af3b1a82d8a9a5874c5970d761342d676afcde Mon Sep 17 00:00:00 2001 From: frisitano Date: Mon, 25 Nov 2024 13:17:23 +0800 Subject: [PATCH 03/15] feat: introduce HashedPostStateProvider --- Cargo.lock | 5 +-- .../src/commands/debug_cmd/build_block.rs | 5 +-- .../commands/debug_cmd/in_memory_merkle.rs | 10 +++--- crates/blockchain-tree/src/blockchain_tree.rs | 11 +++++-- crates/blockchain-tree/src/chain.rs | 11 +++---- crates/chain-state/Cargo.toml | 4 +-- crates/chain-state/src/in_memory.rs | 10 ++++-- crates/chain-state/src/memory_overlay.rs | 11 +++++-- .../engine/invalid-block-hooks/src/witness.rs | 4 +-- crates/engine/tree/src/tree/mod.rs | 16 +++++++--- crates/engine/util/src/reorg.rs | 3 +- crates/ethereum/payload/Cargo.toml | 1 - crates/ethereum/payload/src/lib.rs | 3 +- .../execution-types/src/execution_outcome.rs | 6 ++-- crates/optimism/payload/Cargo.toml | 1 - crates/optimism/payload/src/builder.rs | 27 ++++++++-------- crates/revm/src/test_utils.rs | 14 +++++--- crates/rpc/rpc-eth-api/Cargo.toml | 1 - .../rpc-eth-api/src/helpers/pending_block.rs | 3 +- crates/rpc/rpc-eth-types/src/cache/db.rs | 11 ++++++- crates/rpc/rpc/Cargo.toml | 1 - crates/rpc/rpc/src/validation.rs | 3 +- .../src/providers/blockchain_provider.rs | 19 +++++++++-- .../src/providers/bundle_state_provider.rs | 22 +++++++++---- .../provider/src/providers/database/mod.rs | 21 +++++++++--- .../src/providers/state/historical.rs | 26 +++++++++++++-- .../provider/src/providers/state/latest.rs | 26 +++++++++++++-- .../provider/src/providers/state/macros.rs | 3 ++ .../storage/provider/src/test_utils/mock.rs | 9 +++++- .../storage/provider/src/test_utils/noop.rs | 8 ++++- crates/storage/provider/src/writer/mod.rs | 10 ++---- crates/storage/storage-api/Cargo.toml | 1 + crates/storage/storage-api/src/state.rs | 10 ++++++ crates/trie/db/src/prefix_set.rs | 32 +++++++++++++------ crates/trie/db/src/state.rs | 8 +++-- crates/trie/trie/benches/hash_post_state.rs | 4 +-- crates/trie/trie/src/state.rs | 14 ++++---- 37 files changed, 258 insertions(+), 116 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2e8fc217e4b0..f70aff6e1454 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7457,7 +7457,6 @@ dependencies = [ "reth-provider", "reth-revm", "reth-transaction-pool", - "reth-trie", "revm", "tracing", ] @@ -8367,7 +8366,6 @@ dependencies = [ "reth-revm", "reth-rpc-types-compat", "reth-transaction-pool", - "reth-trie", "revm", "sha2 0.10.8", "thiserror 1.0.69", @@ -8771,7 +8769,6 @@ dependencies = [ "reth-tasks", "reth-testing-utils", "reth-transaction-pool", - "reth-trie", "revm", "revm-inspectors", "revm-primitives", @@ -8951,7 +8948,6 @@ dependencies = [ "reth-rpc-types-compat", "reth-tasks", "reth-transaction-pool", - "reth-trie", "revm", "revm-inspectors", "revm-primitives", @@ -9200,6 +9196,7 @@ dependencies = [ "reth-storage-errors", "reth-trie", "reth-trie-db", + "revm", ] [[package]] diff --git a/bin/reth/src/commands/debug_cmd/build_block.rs b/bin/reth/src/commands/debug_cmd/build_block.rs index adb2c83b1b2f..4a950f56cf79 100644 --- a/bin/reth/src/commands/debug_cmd/build_block.rs +++ b/bin/reth/src/commands/debug_cmd/build_block.rs @@ -261,7 +261,8 @@ impl> Command { let block_with_senders = SealedBlockWithSenders::new(block.clone(), senders).unwrap(); - let db = StateProviderDatabase::new(blockchain_db.latest()?); + let state_provider = blockchain_db.latest()?; + let db = StateProviderDatabase::new(&state_provider); let executor = EthExecutorProvider::ethereum(provider_factory.chain_spec()).executor(db); @@ -271,7 +272,7 @@ impl> Command { ExecutionOutcome::from((block_execution_output, block.number)); debug!(target: "reth::cli", ?execution_outcome, "Executed block"); - let hashed_post_state = execution_outcome.hash_state_slow(); + let hashed_post_state = state_provider.hashed_post_state(execution_outcome.state()); let (state_root, trie_updates) = StateRoot::overlay_root_with_updates( provider_factory.provider()?.tx_ref(), hashed_post_state.clone(), 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 ce5f318632e5..c7a05ace3ebf 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,9 @@ use reth_network_api::NetworkInfo; use reth_node_ethereum::EthExecutorProvider; use reth_provider::{ providers::ProviderNodeTypes, writer::UnifiedStorageWriter, AccountExtReader, - ChainSpecProvider, HashingWriter, HeaderProvider, LatestStateProviderRef, OriginalValuesKnown, - ProviderFactory, StageCheckpointReader, StateWriter, StorageReader, + ChainSpecProvider, HashedPostStateProvider, HashingWriter, HeaderProvider, + LatestStateProviderRef, OriginalValuesKnown, ProviderFactory, StageCheckpointReader, + StateWriter, StorageReader, }; use reth_revm::database::StateProviderDatabase; use reth_stages::StageId; @@ -132,7 +133,8 @@ impl> Command { ) .await?; - let db = StateProviderDatabase::new(LatestStateProviderRef::new(&provider)); + let state_provider = LatestStateProviderRef::new(&provider); + let db = StateProviderDatabase::new(&state_provider); let executor = EthExecutorProvider::ethereum(provider_factory.chain_spec()).executor(db); @@ -154,7 +156,7 @@ impl> Command { // Unpacked `BundleState::state_root_slow` function let (in_memory_state_root, in_memory_updates) = StateRoot::overlay_root_with_updates( provider.tx_ref(), - execution_outcome.hash_state_slow(), + state_provider.hashed_post_state(execution_outcome.state()), )?; if in_memory_state_root == block.state_root { diff --git a/crates/blockchain-tree/src/blockchain_tree.rs b/crates/blockchain-tree/src/blockchain_tree.rs index 1a8a390e99dc..661eaa67ee8c 100644 --- a/crates/blockchain-tree/src/blockchain_tree.rs +++ b/crates/blockchain-tree/src/blockchain_tree.rs @@ -24,7 +24,7 @@ use reth_provider::{ providers::ProviderNodeTypes, BlockExecutionWriter, BlockNumReader, BlockWriter, CanonStateNotification, CanonStateNotificationSender, CanonStateNotifications, ChainSpecProvider, ChainSplit, ChainSplitTarget, DBProvider, DisplayBlocksChain, - HeaderProvider, ProviderError, StaticFileProviderFactory, + HashedPostStateProvider, HeaderProvider, ProviderError, StaticFileProviderFactory, }; use reth_stages_api::{MetricEvent, MetricEventsSender}; use reth_storage_errors::provider::{ProviderResult, RootMismatch}; @@ -1214,7 +1214,7 @@ where recorder: &mut MakeCanonicalDurationsRecorder, ) -> Result<(), CanonicalError> { let (blocks, state, chain_trie_updates) = chain.into_inner(); - let hashed_state = state.hash_state_slow(); + let hashed_state = self.externals.provider_factory.hashed_post_state(state.state()); let prefix_sets = hashed_state.construct_prefix_sets().freeze(); let hashed_state_sorted = hashed_state.into_sorted(); @@ -1869,7 +1869,12 @@ mod tests { ); let provider = tree.externals.provider_factory.provider().unwrap(); - let prefix_sets = exec5.hash_state_slow().construct_prefix_sets().freeze(); + let prefix_sets = tree + .externals + .provider_factory + .hashed_post_state(exec5.state()) + .construct_prefix_sets() + .freeze(); let state_root = StateRoot::from_tx(provider.tx_ref()).with_prefix_sets(prefix_sets).root().unwrap(); assert_eq!(state_root, block5.state_root); diff --git a/crates/blockchain-tree/src/chain.rs b/crates/blockchain-tree/src/chain.rs index 6ac39c316702..a73d87f3a445 100644 --- a/crates/blockchain-tree/src/chain.rs +++ b/crates/blockchain-tree/src/chain.rs @@ -18,11 +18,11 @@ use reth_execution_types::{Chain, ExecutionOutcome}; use reth_primitives::{GotExpected, SealedBlockWithSenders, SealedHeader}; use reth_provider::{ providers::{BundleStateProvider, ConsistentDbView, ProviderNodeTypes}, - DBProvider, FullExecutionDataProvider, ProviderError, StateRootProvider, - TryIntoHistoricalStateProvider, + DBProvider, FullExecutionDataProvider, HashedPostStateProvider, ProviderError, + StateRootProvider, TryIntoHistoricalStateProvider, }; use reth_revm::database::StateProviderDatabase; -use reth_trie::{updates::TrieUpdates, HashedPostState, TrieInput}; +use reth_trie::{updates::TrieUpdates, TrieInput}; use reth_trie_parallel::root::ParallelStateRoot; use std::{ collections::BTreeMap, @@ -228,14 +228,13 @@ impl AppendableChain { execution_outcome.extend(initial_execution_outcome.clone()); ParallelStateRoot::new( consistent_view, - TrieInput::from_state(execution_outcome.hash_state_slow()), + TrieInput::from_state(provider.hashed_post_state(execution_outcome.state())), ) .incremental_root_with_updates() .map(|(root, updates)| (root, Some(updates))) .map_err(ProviderError::from)? } else { - let hashed_state = - HashedPostState::from_bundle_state(&initial_execution_outcome.state().state); + let hashed_state = provider.hashed_post_state(initial_execution_outcome.state()); let state_root = provider.state_root(hashed_state)?; (state_root, None) }; diff --git a/crates/chain-state/Cargo.toml b/crates/chain-state/Cargo.toml index ff62b76e5dfb..7d6d503a7060 100644 --- a/crates/chain-state/Cargo.toml +++ b/crates/chain-state/Cargo.toml @@ -25,6 +25,7 @@ reth-trie.workspace = true alloy-eips.workspace = true alloy-primitives.workspace = true alloy-consensus.workspace = true +revm.workspace = true # async tokio = { workspace = true, default-features = false, features = ["sync", "macros"] } @@ -44,7 +45,6 @@ pin-project.workspace = true alloy-signer = { workspace = true, optional = true } alloy-signer-local = { workspace = true, optional = true } rand = { workspace = true, optional = true } -revm = { workspace = true, optional = true } [dev-dependencies] reth-testing-utils.workspace = true @@ -59,9 +59,7 @@ test-utils = [ "alloy-signer", "alloy-signer-local", "rand", - "revm", "reth-chainspec/test-utils", "reth-primitives/test-utils", "reth-trie/test-utils", - "revm?/test-utils", ] diff --git a/crates/chain-state/src/in_memory.rs b/crates/chain-state/src/in_memory.rs index e07eaeaa5d9e..9320ff64107b 100644 --- a/crates/chain-state/src/in_memory.rs +++ b/crates/chain-state/src/in_memory.rs @@ -919,8 +919,8 @@ mod tests { use reth_errors::ProviderResult; use reth_primitives::{Account, Bytecode, EthPrimitives, Receipt}; use reth_storage_api::{ - AccountReader, BlockHashReader, StateProofProvider, StateProvider, StateRootProvider, - StorageRootProvider, + AccountReader, BlockHashReader, HashedPostStateProvider, StateProofProvider, StateProvider, + StateRootProvider, StorageRootProvider, }; use reth_trie::{AccountProof, HashedStorage, MultiProof, StorageProof, TrieInput}; @@ -1015,6 +1015,12 @@ mod tests { } } + impl HashedPostStateProvider for MockStateProvider { + fn hashed_post_state(&self, _bundle_state: &revm::db::BundleState) -> HashedPostState { + HashedPostState::default() + } + } + impl StorageRootProvider for MockStateProvider { fn storage_root( &self, diff --git a/crates/chain-state/src/memory_overlay.rs b/crates/chain-state/src/memory_overlay.rs index 88cd411d38b2..92ae409991da 100644 --- a/crates/chain-state/src/memory_overlay.rs +++ b/crates/chain-state/src/memory_overlay.rs @@ -7,12 +7,13 @@ use alloy_primitives::{ use reth_errors::ProviderResult; use reth_primitives::{Account, Bytecode, NodePrimitives}; use reth_storage_api::{ - AccountReader, BlockHashReader, StateProofProvider, StateProvider, StateRootProvider, - StorageRootProvider, + AccountReader, BlockHashReader, HashedPostStateProvider, StateProofProvider, StateProvider, + StateRootProvider, StorageRootProvider, }; use reth_trie::{ updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, TrieInput, }; +use revm::db::BundleState; use std::sync::OnceLock; /// A state provider that stores references to in-memory blocks along with their state as well as a @@ -202,6 +203,12 @@ macro_rules! impl_state_provider { } } + impl $($tokens)* HashedPostStateProvider for $type { + fn hashed_post_state(&self, bundle_state: &BundleState) -> HashedPostState { + self.historical.hashed_post_state(bundle_state) + } + } + impl $($tokens)* StateProvider for $type { fn storage( &self, diff --git a/crates/engine/invalid-block-hooks/src/witness.rs b/crates/engine/invalid-block-hooks/src/witness.rs index 4e92411ea128..0daf3a64911e 100644 --- a/crates/engine/invalid-block-hooks/src/witness.rs +++ b/crates/engine/invalid-block-hooks/src/witness.rs @@ -20,7 +20,7 @@ use reth_revm::{ }; use reth_rpc_api::DebugApiClient; use reth_tracing::tracing::warn; -use reth_trie::{updates::TrieUpdates, HashedPostState, HashedStorage}; +use reth_trie::{updates::TrieUpdates, HashedStorage}; use serde::Serialize; /// Generates a witness for the given block and saves it to a file. @@ -130,7 +130,7 @@ where // // Note: We grab *all* accounts in the cache here, as the `BundleState` prunes // referenced accounts + storage slots. - let mut hashed_state = HashedPostState::from_bundle_state(&bundle_state.state); + let mut hashed_state = db.database.hashed_post_state(&bundle_state); for (address, account) in db.cache.accounts { let hashed_address = keccak256(address); hashed_state diff --git a/crates/engine/tree/src/tree/mod.rs b/crates/engine/tree/src/tree/mod.rs index 39843377684c..4bfa0e20ee76 100644 --- a/crates/engine/tree/src/tree/mod.rs +++ b/crates/engine/tree/src/tree/mod.rs @@ -39,8 +39,8 @@ use reth_payload_validator::ExecutionPayloadValidator; use reth_primitives::{Block, GotExpected, SealedBlock, SealedBlockWithSenders, SealedHeader}; use reth_provider::{ providers::ConsistentDbView, BlockReader, DatabaseProviderFactory, ExecutionOutcome, - ProviderError, StateProviderBox, StateProviderFactory, StateReader, StateRootProvider, - TransactionVariant, + HashedPostStateProvider, ProviderError, StateProviderBox, StateProviderFactory, StateReader, + StateRootProvider, TransactionVariant, }; use reth_revm::database::StateProviderDatabase; use reth_stages_api::ControlFlow; @@ -536,7 +536,13 @@ impl std::fmt::Debug impl EngineApiTreeHandler where - P: DatabaseProviderFactory + BlockReader + StateProviderFactory + StateReader + Clone + 'static, + P: DatabaseProviderFactory + + BlockReader + + StateProviderFactory + + StateReader + + HashedPostStateProvider + + Clone + + 'static,

::Provider: BlockReader, E: BlockExecutorProvider, T: EngineTypes, @@ -1541,7 +1547,7 @@ where .provider .get_state(block.number)? .ok_or_else(|| ProviderError::StateForNumberNotFound(block.number))?; - let hashed_state = execution_output.hash_state_slow(); + let hashed_state = self.provider.hashed_post_state(execution_output.state()); Ok(Some(ExecutedBlock { block: Arc::new(block), @@ -2215,7 +2221,7 @@ where return Err(err.into()) } - let hashed_state = HashedPostState::from_bundle_state(&output.state.state); + let hashed_state = self.provider.hashed_post_state(&output.state); trace!(target: "engine::tree", block=?sealed_block.num_hash(), "Calculating block state root"); let root_time = Instant::now(); diff --git a/crates/engine/util/src/reorg.rs b/crates/engine/util/src/reorg.rs index ec69bbd00241..96bf4f252970 100644 --- a/crates/engine/util/src/reorg.rs +++ b/crates/engine/util/src/reorg.rs @@ -26,7 +26,6 @@ use reth_revm::{ DatabaseCommit, }; use reth_rpc_types_compat::engine::payload::block_to_payload; -use reth_trie::HashedPostState; use revm_primitives::{ calc_excess_blob_gas, BlockEnv, CfgEnvWithHandlerCfg, EVMError, EnvWithHandlerCfg, }; @@ -383,7 +382,7 @@ where reorg_target.number, Default::default(), ); - let hashed_state = HashedPostState::from_bundle_state(&outcome.state().state); + let hashed_state = state_provider.hashed_post_state(outcome.state()); let (blob_gas_used, excess_blob_gas) = if chain_spec.is_cancun_active_at_timestamp(reorg_target.timestamp) { diff --git a/crates/ethereum/payload/Cargo.toml b/crates/ethereum/payload/Cargo.toml index 4e0880d1d153..b01f4c5bc74f 100644 --- a/crates/ethereum/payload/Cargo.toml +++ b/crates/ethereum/payload/Cargo.toml @@ -25,7 +25,6 @@ reth-basic-payload-builder.workspace = true reth-evm.workspace = true reth-evm-ethereum.workspace = true reth-errors.workspace = true -reth-trie.workspace = true reth-chain-state.workspace = true reth-chainspec.workspace = true diff --git a/crates/ethereum/payload/src/lib.rs b/crates/ethereum/payload/src/lib.rs index 4ec1e212c8d5..41b3317bc134 100644 --- a/crates/ethereum/payload/src/lib.rs +++ b/crates/ethereum/payload/src/lib.rs @@ -35,7 +35,6 @@ use reth_transaction_pool::{ noop::NoopTransactionPool, BestTransactions, BestTransactionsAttributes, TransactionPool, ValidPoolTransaction, }; -use reth_trie::HashedPostState; use revm::{ db::{states::bundle_state::BundleRetention, State}, primitives::{ @@ -375,7 +374,7 @@ where let logs_bloom = execution_outcome.block_logs_bloom(block_number).expect("Number is in range"); // calculate the state root - let hashed_state = HashedPostState::from_bundle_state(&execution_outcome.state().state); + let hashed_state = db.database.db.hashed_post_state(execution_outcome.state()); let (state_root, trie_output) = { db.database.inner().state_root_with_updates(hashed_state.clone()).inspect_err(|err| { warn!(target: "payload_builder", diff --git a/crates/evm/execution-types/src/execution_outcome.rs b/crates/evm/execution-types/src/execution_outcome.rs index 412269ace9cd..82cc1d20c247 100644 --- a/crates/evm/execution-types/src/execution_outcome.rs +++ b/crates/evm/execution-types/src/execution_outcome.rs @@ -4,7 +4,7 @@ use alloy_eips::eip7685::Requests; use alloy_primitives::{Address, BlockNumber, Bloom, Log, B256, U256}; use reth_primitives::{logs_bloom, Account, Bytecode, Receipts, StorageEntry}; use reth_primitives_traits::{receipt::ReceiptExt, Receipt}; -use reth_trie::HashedPostState; +use reth_trie::{HashedPostState, KeyHasher}; use revm::{ db::{states::BundleState, BundleAccount}, primitives::AccountInfo, @@ -166,8 +166,8 @@ impl ExecutionOutcome { /// Returns [`HashedPostState`] for this execution outcome. /// See [`HashedPostState::from_bundle_state`] for more info. - pub fn hash_state_slow(&self) -> HashedPostState { - HashedPostState::from_bundle_state(&self.bundle.state) + pub fn hash_state_slow(&self) -> HashedPostState { + HashedPostState::from_bundle_state::(&self.bundle.state) } /// Transform block number to the index of block. diff --git a/crates/optimism/payload/Cargo.toml b/crates/optimism/payload/Cargo.toml index 7f47da7e2360..1c4f855b6aa2 100644 --- a/crates/optimism/payload/Cargo.toml +++ b/crates/optimism/payload/Cargo.toml @@ -26,7 +26,6 @@ reth-payload-builder-primitives.workspace = true reth-payload-util.workspace = true reth-payload-primitives = { workspace = true, features = ["op"] } reth-basic-payload-builder.workspace = true -reth-trie.workspace = true reth-chain-state.workspace = true # op-reth diff --git a/crates/optimism/payload/src/builder.rs b/crates/optimism/payload/src/builder.rs index 3644d8f71a54..0d90681e6ff3 100644 --- a/crates/optimism/payload/src/builder.rs +++ b/crates/optimism/payload/src/builder.rs @@ -19,12 +19,14 @@ use reth_payload_builder_primitives::PayloadBuilderError; use reth_payload_primitives::PayloadBuilderAttributes; use reth_payload_util::PayloadTransactions; use reth_primitives::{proofs, Block, BlockBody, Receipt, SealedHeader, TransactionSigned, TxType}; -use reth_provider::{ProviderError, StateProofProvider, StateProviderFactory, StateRootProvider}; +use reth_provider::{ + HashedPostStateProvider, ProviderError, StateProofProvider, StateProviderFactory, + StateRootProvider, +}; use reth_revm::database::StateProviderDatabase; use reth_transaction_pool::{ noop::NoopTransactionPool, BestTransactionsAttributes, TransactionPool, }; -use reth_trie::HashedPostState; use revm::{ db::{states::bundle_state::BundleRetention, State}, primitives::{ @@ -336,7 +338,7 @@ where where EvmConfig: ConfigureEvm

, DB: Database + AsRef

, - P: StateRootProvider, + P: StateRootProvider + HashedPostStateProvider, { let ExecutedPayload { info, @@ -367,17 +369,16 @@ where execution_outcome.block_logs_bloom(block_number).expect("Number is in range"); // // calculate the state root - let hashed_state = HashedPostState::from_bundle_state(&execution_outcome.state().state); + let state_provider = state.database.as_ref(); + let hashed_state = state_provider.hashed_post_state(execution_outcome.state()); let (state_root, trie_output) = { - state.database.as_ref().state_root_with_updates(hashed_state.clone()).inspect_err( - |err| { - warn!(target: "payload_builder", - parent_header=%ctx.parent().hash(), - %err, - "failed to calculate state root for payload" - ); - }, - )? + state_provider.state_root_with_updates(hashed_state.clone()).inspect_err(|err| { + warn!(target: "payload_builder", + parent_header=%ctx.parent().hash(), + %err, + "failed to calculate state root for payload" + ); + })? }; // create the block header diff --git a/crates/revm/src/test_utils.rs b/crates/revm/src/test_utils.rs index 813997c72d11..23705dda0e1d 100644 --- a/crates/revm/src/test_utils.rs +++ b/crates/revm/src/test_utils.rs @@ -6,13 +6,13 @@ use alloy_primitives::{ }; use reth_primitives::{Account, Bytecode}; use reth_storage_api::{ - AccountReader, BlockHashReader, StateProofProvider, StateProvider, StateRootProvider, - StorageRootProvider, + AccountReader, BlockHashReader, HashedPostStateProvider, StateProofProvider, StateProvider, + StateRootProvider, StorageRootProvider, }; use reth_storage_errors::provider::ProviderResult; use reth_trie::{ - updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, StorageProof, - TrieInput, + updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, KeccakKeyHasher, + MultiProof, StorageProof, TrieInput, }; /// Mock state for testing @@ -141,6 +141,12 @@ impl StateProofProvider for StateProviderTest { } } +impl HashedPostStateProvider for StateProviderTest { + fn hashed_post_state(&self, bundle_state: &revm::db::BundleState) -> HashedPostState { + HashedPostState::from_bundle_state::(bundle_state.state()) + } +} + impl StateProvider for StateProviderTest { fn storage( &self, diff --git a/crates/rpc/rpc-eth-api/Cargo.toml b/crates/rpc/rpc-eth-api/Cargo.toml index e4b1b28074f0..ba13943923f8 100644 --- a/crates/rpc/rpc-eth-api/Cargo.toml +++ b/crates/rpc/rpc-eth-api/Cargo.toml @@ -29,7 +29,6 @@ reth-execution-types.workspace = true reth-rpc-eth-types.workspace = true reth-rpc-server-types.workspace = true reth-network-api.workspace = true -reth-trie.workspace = true reth-node-api.workspace = true # ethereum diff --git a/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs b/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs index 548f9101023d..b697c6870c5a 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs @@ -33,7 +33,6 @@ use reth_revm::{ }; use reth_rpc_eth_types::{EthApiError, PendingBlock, PendingBlockEnv, PendingBlockEnvOrigin}; use reth_transaction_pool::{BestTransactionsAttributes, TransactionPool}; -use reth_trie::HashedPostState; use revm::{db::states::bundle_state::BundleRetention, DatabaseCommit, State}; use std::time::{Duration, Instant}; use tokio::sync::Mutex; @@ -389,7 +388,7 @@ pub trait LoadPendingBlock: block_number, Vec::new(), ); - let hashed_state = HashedPostState::from_bundle_state(&execution_outcome.state().state); + let hashed_state = db.database.hashed_post_state(execution_outcome.state()); let receipts_root = self.receipts_root(&block_env, &execution_outcome, block_number); diff --git a/crates/rpc/rpc-eth-types/src/cache/db.rs b/crates/rpc/rpc-eth-types/src/cache/db.rs index 50fd4b04625f..de61f308fd6c 100644 --- a/crates/rpc/rpc-eth-types/src/cache/db.rs +++ b/crates/rpc/rpc-eth-types/src/cache/db.rs @@ -8,7 +8,7 @@ use alloy_primitives::{ }; use reth_errors::ProviderResult; use reth_revm::{database::StateProviderDatabase, db::CacheDB, DatabaseRef}; -use reth_storage_api::StateProvider; +use reth_storage_api::{HashedPostStateProvider, StateProvider}; use reth_trie::HashedStorage; use revm::Database; @@ -130,6 +130,15 @@ impl reth_storage_api::BlockHashReader for StateProviderTraitObjWrapper<'_> { } } +impl HashedPostStateProvider for StateProviderTraitObjWrapper<'_> { + fn hashed_post_state( + &self, + bundle_state: &revm::db::BundleState, + ) -> reth_trie::HashedPostState { + self.0.hashed_post_state(bundle_state) + } +} + impl StateProvider for StateProviderTraitObjWrapper<'_> { fn storage( &self, diff --git a/crates/rpc/rpc/Cargo.toml b/crates/rpc/rpc/Cargo.toml index 5418cd1eb3a7..d4aef0536030 100644 --- a/crates/rpc/rpc/Cargo.toml +++ b/crates/rpc/rpc/Cargo.toml @@ -33,7 +33,6 @@ reth-evm.workspace = true reth-rpc-eth-types.workspace = true reth-rpc-server-types.workspace = true reth-network-types.workspace = true -reth-trie.workspace = true reth-consensus.workspace = true reth-payload-validator.workspace = true diff --git a/crates/rpc/rpc/src/validation.rs b/crates/rpc/rpc/src/validation.rs index b997dec1e015..bd8ee5486643 100644 --- a/crates/rpc/rpc/src/validation.rs +++ b/crates/rpc/rpc/src/validation.rs @@ -24,7 +24,6 @@ use reth_revm::{cached::CachedReads, database::StateProviderDatabase}; use reth_rpc_api::BlockSubmissionValidationApiServer; use reth_rpc_eth_types::EthApiError; use reth_rpc_server_types::{result::internal_rpc_err, ToRpcResult}; -use reth_trie::HashedPostState; use revm_primitives::{Address, B256, U256}; use serde::{Deserialize, Serialize}; use std::{collections::HashSet, sync::Arc}; @@ -178,7 +177,7 @@ where self.ensure_payment(&block, &output, &message)?; let state_root = - state_provider.state_root(HashedPostState::from_bundle_state(&output.state.state))?; + state_provider.state_root(state_provider.hashed_post_state(&output.state))?; if state_root != block.state_root { return Err(ConsensusError::BodyStateRootDiff( diff --git a/crates/storage/provider/src/providers/blockchain_provider.rs b/crates/storage/provider/src/providers/blockchain_provider.rs index 083e7fb596b6..1df7db0e4599 100644 --- a/crates/storage/provider/src/providers/blockchain_provider.rs +++ b/crates/storage/provider/src/providers/blockchain_provider.rs @@ -4,8 +4,8 @@ use crate::{ AccountReader, BlockHashReader, BlockIdReader, BlockNumReader, BlockReader, BlockReaderIdExt, BlockSource, CanonChainTracker, CanonStateNotifications, CanonStateSubscriptions, ChainSpecProvider, ChainStateBlockReader, ChangeSetReader, DatabaseProvider, - DatabaseProviderFactory, EvmEnvProvider, FullProvider, HeaderProvider, ProviderError, - ProviderFactory, PruneCheckpointReader, ReceiptProvider, ReceiptProviderIdExt, + DatabaseProviderFactory, EvmEnvProvider, FullProvider, HashedPostStateProvider, HeaderProvider, + ProviderError, ProviderFactory, PruneCheckpointReader, ReceiptProvider, ReceiptProviderIdExt, StageCheckpointReader, StateProviderBox, StateProviderFactory, StateReader, StaticFileProviderFactory, TransactionVariant, TransactionsProvider, WithdrawalsProvider, }; @@ -34,7 +34,12 @@ use reth_prune_types::{PruneCheckpoint, PruneSegment}; use reth_stages_types::{StageCheckpoint, StageId}; use reth_storage_api::{DBProvider, StorageChangeSetReader}; use reth_storage_errors::provider::ProviderResult; -use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg}; +use reth_trie::HashedPostState; +use reth_trie_db::StateCommitment; +use revm::{ + db::BundleState, + primitives::{BlockEnv, CfgEnvWithHandlerCfg}, +}; use std::{ ops::{Add, RangeBounds, RangeInclusive, Sub}, sync::Arc, @@ -631,6 +636,14 @@ impl StateProviderFactory for BlockchainProvider2 { } } +impl HashedPostStateProvider for BlockchainProvider2 { + fn hashed_post_state(&self, bundle_state: &BundleState) -> HashedPostState { + HashedPostState::from_bundle_state::<::KeyHasher>( + bundle_state.state(), + ) + } +} + impl CanonChainTracker for BlockchainProvider2 where Self: BlockReader, diff --git a/crates/storage/provider/src/providers/bundle_state_provider.rs b/crates/storage/provider/src/providers/bundle_state_provider.rs index be6549033cde..a7a102bc5c41 100644 --- a/crates/storage/provider/src/providers/bundle_state_provider.rs +++ b/crates/storage/provider/src/providers/bundle_state_provider.rs @@ -6,7 +6,7 @@ use alloy_primitives::{ Address, BlockNumber, Bytes, B256, }; use reth_primitives::{Account, Bytecode}; -use reth_storage_api::{StateProofProvider, StorageRootProvider}; +use reth_storage_api::{HashedPostStateProvider, StateProofProvider, StorageRootProvider}; use reth_storage_errors::provider::ProviderResult; use reth_trie::{ updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, TrieInput, @@ -86,7 +86,7 @@ impl StateRootProvider { fn state_root(&self, hashed_state: HashedPostState) -> ProviderResult { let bundle_state = self.block_execution_data_provider.execution_outcome().state(); - let mut state = HashedPostState::from_bundle_state(&bundle_state.state); + let mut state = self.hashed_post_state(bundle_state); state.extend(hashed_state); self.state_provider.state_root(state) } @@ -100,7 +100,7 @@ impl StateRootProvider hashed_state: HashedPostState, ) -> ProviderResult<(B256, TrieUpdates)> { let bundle_state = self.block_execution_data_provider.execution_outcome().state(); - let mut state = HashedPostState::from_bundle_state(&bundle_state.state); + let mut state = self.hashed_post_state(bundle_state); state.extend(hashed_state); self.state_provider.state_root_with_updates(state) } @@ -110,7 +110,7 @@ impl StateRootProvider mut input: TrieInput, ) -> ProviderResult<(B256, TrieUpdates)> { let bundle_state = self.block_execution_data_provider.execution_outcome().state(); - input.prepend(HashedPostState::from_bundle_state(&bundle_state.state)); + input.prepend(self.hashed_post_state(bundle_state)); self.state_provider.state_root_from_nodes_with_updates(input) } } @@ -150,7 +150,7 @@ impl StateProofProvider slots: &[B256], ) -> ProviderResult { let bundle_state = self.block_execution_data_provider.execution_outcome().state(); - input.prepend(HashedPostState::from_bundle_state(&bundle_state.state)); + input.prepend(self.hashed_post_state(bundle_state)); self.state_provider.proof(input, address, slots) } @@ -160,7 +160,7 @@ impl StateProofProvider targets: HashMap>, ) -> ProviderResult { let bundle_state = self.block_execution_data_provider.execution_outcome().state(); - input.prepend(HashedPostState::from_bundle_state(&bundle_state.state)); + input.prepend(self.hashed_post_state(bundle_state)); self.state_provider.multiproof(input, targets) } @@ -170,11 +170,19 @@ impl StateProofProvider target: HashedPostState, ) -> ProviderResult> { let bundle_state = self.block_execution_data_provider.execution_outcome().state(); - input.prepend(HashedPostState::from_bundle_state(&bundle_state.state)); + input.prepend(self.hashed_post_state(bundle_state)); self.state_provider.witness(input, target) } } +impl HashedPostStateProvider + for BundleStateProvider +{ + fn hashed_post_state(&self, bundle_state: &revm::db::BundleState) -> HashedPostState { + self.state_provider.hashed_post_state(bundle_state) + } +} + impl StateProvider for BundleStateProvider { fn storage( &self, diff --git a/crates/storage/provider/src/providers/database/mod.rs b/crates/storage/provider/src/providers/database/mod.rs index a64bb2578dd6..094a3369ee1b 100644 --- a/crates/storage/provider/src/providers/database/mod.rs +++ b/crates/storage/provider/src/providers/database/mod.rs @@ -3,9 +3,9 @@ use crate::{ to_range, traits::{BlockSource, ReceiptProvider}, BlockHashReader, BlockNumReader, BlockReader, ChainSpecProvider, DatabaseProviderFactory, - EvmEnvProvider, HeaderProvider, HeaderSyncGap, HeaderSyncGapProvider, ProviderError, - PruneCheckpointReader, StageCheckpointReader, StateProviderBox, StaticFileProviderFactory, - TransactionVariant, TransactionsProvider, WithdrawalsProvider, + EvmEnvProvider, HashedPostStateProvider, HeaderProvider, HeaderSyncGap, HeaderSyncGapProvider, + ProviderError, PruneCheckpointReader, StageCheckpointReader, StateProviderBox, + StaticFileProviderFactory, TransactionVariant, TransactionsProvider, WithdrawalsProvider, }; use alloy_consensus::Header; use alloy_eips::{ @@ -28,7 +28,12 @@ use reth_prune_types::{PruneCheckpoint, PruneModes, PruneSegment}; use reth_stages_types::{StageCheckpoint, StageId}; use reth_storage_api::TryIntoHistoricalStateProvider; use reth_storage_errors::provider::ProviderResult; -use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg}; +use reth_trie::HashedPostState; +use reth_trie_db::StateCommitment; +use revm::{ + db::BundleState, + primitives::{BlockEnv, CfgEnvWithHandlerCfg}, +}; use std::{ ops::{RangeBounds, RangeInclusive}, path::Path, @@ -625,6 +630,14 @@ impl PruneCheckpointReader for ProviderFactory { } } +impl HashedPostStateProvider for ProviderFactory { + fn hashed_post_state(&self, bundle_state: &BundleState) -> HashedPostState { + HashedPostState::from_bundle_state::<::KeyHasher>( + bundle_state.state(), + ) + } +} + impl Clone for ProviderFactory { fn clone(&self) -> Self { Self { diff --git a/crates/storage/provider/src/providers/state/historical.rs b/crates/storage/provider/src/providers/state/historical.rs index a70fe9ac203b..e4594d3ddda9 100644 --- a/crates/storage/provider/src/providers/state/historical.rs +++ b/crates/storage/provider/src/providers/state/historical.rs @@ -1,6 +1,6 @@ use crate::{ providers::state::macros::delegate_provider_impls, AccountReader, BlockHashReader, - ProviderError, StateProvider, StateRootProvider, + HashedPostStateProvider, ProviderError, StateProvider, StateRootProvider, }; use alloy_eips::merge::EPOCH_SLOTS; use alloy_primitives::{ @@ -27,7 +27,7 @@ use reth_trie::{ }; use reth_trie_db::{ DatabaseHashedPostState, DatabaseHashedStorage, DatabaseProof, DatabaseStateRoot, - DatabaseStorageProof, DatabaseStorageRoot, DatabaseTrieWitness, + DatabaseStorageProof, DatabaseStorageRoot, DatabaseTrieWitness, StateCommitment, }; use std::fmt::Debug; @@ -381,6 +381,16 @@ impl StateProof } } +impl HashedPostStateProvider + for HistoricalStateProviderRef<'_, Provider> +{ + fn hashed_post_state(&self, bundle_state: &revm::db::BundleState) -> HashedPostState { + HashedPostState::from_bundle_state::< + ::KeyHasher, + >(bundle_state.state()) + } +} + impl StateProvider for HistoricalStateProviderRef<'_, Provider> { @@ -420,6 +430,12 @@ impl StateCommitmentProvider + for HistoricalStateProviderRef<'_, Provider> +{ + type StateCommitment = Provider::StateCommitment; +} + /// State provider for a given block number. /// For more detailed description, see [`HistoricalStateProviderRef`]. #[derive(Debug)] @@ -469,6 +485,12 @@ impl } } +impl StateCommitmentProvider + for HistoricalStateProvider +{ + type StateCommitment = Provider::StateCommitment; +} + // Delegates all provider impls to [HistoricalStateProviderRef] delegate_provider_impls!(HistoricalStateProvider where [Provider: DBProvider + BlockNumReader + BlockHashReader + StateCommitmentProvider]); diff --git a/crates/storage/provider/src/providers/state/latest.rs b/crates/storage/provider/src/providers/state/latest.rs index ab70d759b992..825817357ca9 100644 --- a/crates/storage/provider/src/providers/state/latest.rs +++ b/crates/storage/provider/src/providers/state/latest.rs @@ -1,6 +1,6 @@ use crate::{ providers::state::macros::delegate_provider_impls, AccountReader, BlockHashReader, - StateProvider, StateRootProvider, + HashedPostStateProvider, StateProvider, StateRootProvider, }; use alloy_primitives::{ map::{HashMap, HashSet}, @@ -21,7 +21,7 @@ use reth_trie::{ }; use reth_trie_db::{ DatabaseProof, DatabaseStateRoot, DatabaseStorageProof, DatabaseStorageRoot, - DatabaseTrieWitness, + DatabaseTrieWitness, StateCommitment, }; /// State provider over latest state that takes tx reference. @@ -146,6 +146,16 @@ impl StateProofProvider } } +impl HashedPostStateProvider + for LatestStateProviderRef<'_, Provider> +{ + fn hashed_post_state(&self, bundle_state: &revm::db::BundleState) -> HashedPostState { + HashedPostState::from_bundle_state::< + ::KeyHasher, + >(bundle_state.state()) + } +} + impl StateProvider for LatestStateProviderRef<'_, Provider> { @@ -170,11 +180,17 @@ impl StateProv } } +impl StateCommitmentProvider + for LatestStateProviderRef<'_, Provider> +{ + type StateCommitment = Provider::StateCommitment; +} + /// State provider for the latest state. #[derive(Debug)] pub struct LatestStateProvider(Provider); -impl LatestStateProvider { +impl LatestStateProvider { /// Create new state provider pub const fn new(db: Provider) -> Self { Self(db) @@ -187,6 +203,10 @@ impl LatestStateProvider { } } +impl StateCommitmentProvider for LatestStateProvider { + type StateCommitment = Provider::StateCommitment; +} + // Delegates all provider impls to [LatestStateProviderRef] delegate_provider_impls!(LatestStateProvider where [Provider: DBProvider + BlockHashReader + StateCommitmentProvider]); diff --git a/crates/storage/provider/src/providers/state/macros.rs b/crates/storage/provider/src/providers/state/macros.rs index b90924354c43..860407923573 100644 --- a/crates/storage/provider/src/providers/state/macros.rs +++ b/crates/storage/provider/src/providers/state/macros.rs @@ -56,6 +56,9 @@ macro_rules! delegate_provider_impls { fn multiproof(&self, input: reth_trie::TrieInput, targets: alloy_primitives::map::HashMap>) -> reth_storage_errors::provider::ProviderResult; fn witness(&self, input: reth_trie::TrieInput, target: reth_trie::HashedPostState) -> reth_storage_errors::provider::ProviderResult>; } + HashedPostStateProvider $(where [$($generics)*])? { + fn hashed_post_state(&self, bundle_state: &revm::db::BundleState) -> reth_trie::HashedPostState; + } ); } } diff --git a/crates/storage/provider/src/test_utils/mock.rs b/crates/storage/provider/src/test_utils/mock.rs index 43bb1e809422..1c1e933dc89b 100644 --- a/crates/storage/provider/src/test_utils/mock.rs +++ b/crates/storage/provider/src/test_utils/mock.rs @@ -29,7 +29,8 @@ use reth_primitives::{ }; use reth_stages_types::{StageCheckpoint, StageId}; use reth_storage_api::{ - DatabaseProviderFactory, StageCheckpointReader, StateProofProvider, StorageRootProvider, + DatabaseProviderFactory, HashedPostStateProvider, StageCheckpointReader, StateProofProvider, + StorageRootProvider, }; use reth_storage_errors::provider::{ConsistentViewError, ProviderError, ProviderResult}; use reth_trie::{ @@ -668,6 +669,12 @@ impl StateProofProvider for MockEthProvider { } } +impl HashedPostStateProvider for MockEthProvider { + fn hashed_post_state(&self, _state: &revm::db::BundleState) -> HashedPostState { + HashedPostState::default() + } +} + impl StateProvider for MockEthProvider { fn storage( &self, diff --git a/crates/storage/provider/src/test_utils/noop.rs b/crates/storage/provider/src/test_utils/noop.rs index d12539a2c27f..949adc86bcaf 100644 --- a/crates/storage/provider/src/test_utils/noop.rs +++ b/crates/storage/provider/src/test_utils/noop.rs @@ -27,7 +27,7 @@ use reth_primitives::{ }; use reth_prune_types::{PruneCheckpoint, PruneSegment}; use reth_stages_types::{StageCheckpoint, StageId}; -use reth_storage_api::{StateProofProvider, StorageRootProvider}; +use reth_storage_api::{HashedPostStateProvider, StateProofProvider, StorageRootProvider}; use reth_storage_errors::provider::ProviderResult; use reth_trie::{ updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, TrieInput, @@ -397,6 +397,12 @@ impl StateProofProvider for NoopProvider { } } +impl HashedPostStateProvider for NoopProvider { + fn hashed_post_state(&self, _bundle_state: &revm::db::BundleState) -> HashedPostState { + HashedPostState::default() + } +} + impl StateProvider for NoopProvider { fn storage( &self, diff --git a/crates/storage/provider/src/writer/mod.rs b/crates/storage/provider/src/writer/mod.rs index 17dea5a6d51f..43c192f55326 100644 --- a/crates/storage/provider/src/writer/mod.rs +++ b/crates/storage/provider/src/writer/mod.rs @@ -557,7 +557,7 @@ mod tests { transaction::{DbTx, DbTxMut}, }; use reth_primitives::{Account, Receipt, Receipts, StorageEntry}; - use reth_storage_api::DatabaseProviderFactory; + use reth_storage_api::{DatabaseProviderFactory, HashedPostStateProvider}; use reth_trie::{ test_utils::{state_root, storage_root_prehashed}, HashedPostState, HashedStorage, StateRoot, StorageRoot, @@ -1447,13 +1447,7 @@ mod tests { assert_eq!( StateRoot::overlay_root( tx, - ExecutionOutcome::::new( - state.bundle_state.clone(), - Receipts::default(), - 0, - Vec::new() - ) - .hash_state_slow(), + provider_factory.hashed_post_state(&state.bundle_state) ) .unwrap(), state_root(expected.clone().into_iter().map(|(address, (account, storage))| ( diff --git a/crates/storage/storage-api/Cargo.toml b/crates/storage/storage-api/Cargo.toml index ba2ccf1b1573..7ebff976d135 100644 --- a/crates/storage/storage-api/Cargo.toml +++ b/crates/storage/storage-api/Cargo.toml @@ -25,6 +25,7 @@ reth-storage-errors.workspace = true reth-trie.workspace = true reth-trie-db.workspace = true reth-db.workspace = true +revm.workspace = true # ethereum alloy-eips.workspace = true diff --git a/crates/storage/storage-api/src/state.rs b/crates/storage/storage-api/src/state.rs index 49db24a9bb93..98af854b2498 100644 --- a/crates/storage/storage-api/src/state.rs +++ b/crates/storage/storage-api/src/state.rs @@ -9,7 +9,9 @@ use auto_impl::auto_impl; use reth_execution_types::ExecutionOutcome; use reth_primitives::Bytecode; use reth_storage_errors::provider::{ProviderError, ProviderResult}; +use reth_trie::HashedPostState; use reth_trie_db::StateCommitment; +use revm::db::states::BundleState; /// Type alias of boxed [`StateProvider`]. pub type StateProviderBox = Box; @@ -22,6 +24,7 @@ pub trait StateProvider: + StateRootProvider + StorageRootProvider + StateProofProvider + + HashedPostStateProvider + Send + Sync { @@ -89,6 +92,13 @@ pub trait StateCommitmentProvider { type StateCommitment: StateCommitment; } +/// Trait that provides the hashed state from various sources. +#[auto_impl(&, Arc, Box)] +pub trait HashedPostStateProvider { + /// Returns the `HashedPostState` of the provided [`BundleState`]. + fn hashed_post_state(&self, bundle_state: &BundleState) -> HashedPostState; +} + /// Trait implemented for database providers that can be converted into a historical state provider. pub trait TryIntoHistoricalStateProvider { /// Returns a historical [`StateProvider`] indexed by the given historic block number. diff --git a/crates/trie/db/src/prefix_set.rs b/crates/trie/db/src/prefix_set.rs index cd50503bc703..b8cb380ff0ee 100644 --- a/crates/trie/db/src/prefix_set.rs +++ b/crates/trie/db/src/prefix_set.rs @@ -1,4 +1,4 @@ -use alloy_primitives::{keccak256, BlockNumber, B256}; +use alloy_primitives::{BlockNumber, B256}; use derive_more::Deref; use reth_db::tables; use reth_db_api::{ @@ -8,25 +8,37 @@ use reth_db_api::{ DatabaseError, }; use reth_primitives::StorageEntry; -use reth_trie::prefix_set::{PrefixSetMut, TriePrefixSets}; +use reth_trie::{ + prefix_set::{PrefixSetMut, TriePrefixSets}, + KeyHasher, +}; use reth_trie_common::Nibbles; use std::{ collections::{HashMap, HashSet}, + marker::PhantomData, ops::RangeInclusive, }; /// A wrapper around a database transaction that loads prefix sets within a given block range. -#[derive(Deref, Debug)] -pub struct PrefixSetLoader<'a, TX>(&'a TX); +#[derive(Debug)] +pub struct PrefixSetLoader<'a, TX, KH>(&'a TX, PhantomData); -impl<'a, TX> PrefixSetLoader<'a, TX> { +impl<'a, TX, KH> PrefixSetLoader<'a, TX, KH> { /// Create a new loader. pub const fn new(tx: &'a TX) -> Self { - Self(tx) + Self(tx, PhantomData) + } +} + +impl Deref for PrefixSetLoader<'_, TX, KH> { + type Target = TX; + + fn deref(&self) -> &Self::Target { + self.0 } } -impl PrefixSetLoader<'_, TX> { +impl PrefixSetLoader<'_, TX, KH> { /// Load all account and storage changes for the given block range. pub fn load(self, range: RangeInclusive) -> Result { // Initialize prefix sets. @@ -39,7 +51,7 @@ impl PrefixSetLoader<'_, TX> { let mut account_hashed_state_cursor = self.cursor_read::()?; for account_entry in account_changeset_cursor.walk_range(range.clone())? { let (_, AccountBeforeTx { address, .. }) = account_entry?; - let hashed_address = keccak256(address); + let hashed_address = KH::hash_key(address); account_prefix_set.insert(Nibbles::unpack(hashed_address)); if account_hashed_state_cursor.seek_exact(hashed_address)?.is_none() { @@ -53,12 +65,12 @@ impl PrefixSetLoader<'_, TX> { let storage_range = BlockNumberAddress::range(range); for storage_entry in storage_cursor.walk_range(storage_range)? { let (BlockNumberAddress((_, address)), StorageEntry { key, .. }) = storage_entry?; - let hashed_address = keccak256(address); + let hashed_address = KH::hash_key(address); account_prefix_set.insert(Nibbles::unpack(hashed_address)); storage_prefix_sets .entry(hashed_address) .or_default() - .insert(Nibbles::unpack(keccak256(key))); + .insert(Nibbles::unpack(KH::hash_key(key))); } Ok(TriePrefixSets { diff --git a/crates/trie/db/src/state.rs b/crates/trie/db/src/state.rs index 6e2cea5051d0..5f77b0b916c4 100644 --- a/crates/trie/db/src/state.rs +++ b/crates/trie/db/src/state.rs @@ -10,7 +10,8 @@ use reth_execution_errors::StateRootError; use reth_storage_errors::db::DatabaseError; use reth_trie::{ hashed_cursor::HashedPostStateCursorFactory, trie_cursor::InMemoryTrieCursorFactory, - updates::TrieUpdates, HashedPostState, HashedStorage, StateRoot, StateRootProgress, TrieInput, + updates::TrieUpdates, HashedPostState, HashedStorage, KeccakKeyHasher, StateRoot, + StateRootProgress, TrieInput, }; use std::{collections::HashMap, ops::RangeInclusive}; use tracing::debug; @@ -136,7 +137,7 @@ impl<'a, TX: DbTx> DatabaseStateRoot<'a, TX> tx: &'a TX, range: RangeInclusive, ) -> Result { - let loaded_prefix_sets = PrefixSetLoader::new(tx).load(range)?; + let loaded_prefix_sets = PrefixSetLoader::<_, KeccakKeyHasher>::new(tx).load(range)?; Ok(Self::from_tx(tx).with_prefix_sets(loaded_prefix_sets)) } @@ -265,6 +266,7 @@ mod tests { use alloy_primitives::{hex, map::HashMap, Address, U256}; use reth_db::test_utils::create_test_rw_db; use reth_db_api::database::Database; + use reth_trie::KeccakKeyHasher; use revm::{db::BundleState, primitives::AccountInfo}; #[test] @@ -285,7 +287,7 @@ mod tests { .build(); assert_eq!(bundle_state.reverts.len(), 1); - let post_state = HashedPostState::from_bundle_state(&bundle_state.state); + let post_state = HashedPostState::from_bundle_state::(&bundle_state.state); assert_eq!(post_state.accounts.len(), 2); assert_eq!(post_state.storages.len(), 2); diff --git a/crates/trie/trie/benches/hash_post_state.rs b/crates/trie/trie/benches/hash_post_state.rs index 6e913ef78a3c..7111a785f469 100644 --- a/crates/trie/trie/benches/hash_post_state.rs +++ b/crates/trie/trie/benches/hash_post_state.rs @@ -2,7 +2,7 @@ use alloy_primitives::{keccak256, map::HashMap, Address, B256, U256}; use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; use proptest::{prelude::*, strategy::ValueTree, test_runner::TestRunner}; -use reth_trie::{HashedPostState, HashedStorage}; +use reth_trie::{HashedPostState, HashedStorage, KeccakKeyHasher}; use revm::db::{states::BundleBuilder, BundleAccount}; pub fn hash_post_state(c: &mut Criterion) { @@ -19,7 +19,7 @@ pub fn hash_post_state(c: &mut Criterion) { // parallel group.bench_function(BenchmarkId::new("parallel hashing", size), |b| { - b.iter(|| HashedPostState::from_bundle_state(&state)) + b.iter(|| HashedPostState::from_bundle_state::(&state)) }); } } diff --git a/crates/trie/trie/src/state.rs b/crates/trie/trie/src/state.rs index eca126744e96..66a6af5a3a70 100644 --- a/crates/trie/trie/src/state.rs +++ b/crates/trie/trie/src/state.rs @@ -6,6 +6,7 @@ use alloy_primitives::{keccak256, Address, B256, U256}; use itertools::Itertools; use rayon::prelude::{IntoParallelIterator, ParallelIterator}; use reth_primitives::Account; +use reth_trie_common::KeyHasher; use revm::db::{states::CacheAccount, AccountStatus, BundleAccount}; use std::{ borrow::Cow, @@ -25,13 +26,13 @@ impl HashedPostState { /// Initialize [`HashedPostState`] from bundle state. /// Hashes all changed accounts and storage entries that are currently stored in the bundle /// state. - pub fn from_bundle_state<'a>( + pub fn from_bundle_state<'a, KH: KeyHasher>( state: impl IntoParallelIterator, ) -> Self { let hashed = state .into_par_iter() .map(|(address, account)| { - let hashed_address = keccak256(address); + let hashed_address = KH::hash_key(address); let hashed_account = account.info.clone().map(Into::into); let hashed_storage = HashedStorage::from_plain_storage( account.status, @@ -52,13 +53,13 @@ impl HashedPostState { /// Initialize [`HashedPostState`] from cached state. /// Hashes all changed accounts and storage entries that are currently stored in cache. - pub fn from_cache_state<'a>( + pub fn from_cache_state<'a, KH: KeyHasher>( state: impl IntoParallelIterator, ) -> Self { let hashed = state .into_par_iter() .map(|(address, account)| { - let hashed_address = keccak256(address); + let hashed_address = KH::hash_key(address); let hashed_account = account.account.as_ref().map(|a| a.info.clone().into()); let hashed_storage = HashedStorage::from_plain_storage( account.status, @@ -349,6 +350,7 @@ impl HashedStorageSorted { mod tests { use super::*; use alloy_primitives::Bytes; + use reth_trie_common::KeccakKeyHasher; use revm::{ db::{ states::{plain_account::PlainStorage, StorageSlot}, @@ -462,7 +464,7 @@ mod tests { let state = vec![(&address, &account)]; // Convert the bundle state into a hashed post state. - let hashed_state = HashedPostState::from_bundle_state(state); + let hashed_state = HashedPostState::from_bundle_state::(state); // Validate the hashed post state. assert_eq!(hashed_state.accounts.len(), 1); @@ -501,7 +503,7 @@ mod tests { let state = vec![(&address, &account)]; // Convert the cache state into a hashed post state. - let hashed_state = HashedPostState::from_cache_state(state); + let hashed_state = HashedPostState::from_cache_state::(state); // Validate the hashed post state. assert_eq!(hashed_state.accounts.len(), 1); From 500f8c25f1a5e56eaa90dd822076c0bf469bb5c5 Mon Sep 17 00:00:00 2001 From: frisitano Date: Mon, 25 Nov 2024 14:38:25 +0800 Subject: [PATCH 04/15] feat: HashedPostState from reverts --- crates/engine/tree/src/tree/mod.rs | 5 +++-- .../provider/src/providers/blockchain_provider.rs | 6 +++++- .../provider/src/providers/consistent_view.rs | 10 ++++++---- .../storage/provider/src/providers/database/mod.rs | 6 +++++- .../provider/src/providers/state/historical.rs | 4 +++- crates/storage/provider/src/test_utils/mock.rs | 8 ++++++-- crates/trie/db/src/state.rs | 14 +++++++------- crates/trie/parallel/src/proof.rs | 8 +++++++- crates/trie/parallel/src/root.rs | 8 +++++++- 9 files changed, 49 insertions(+), 20 deletions(-) diff --git a/crates/engine/tree/src/tree/mod.rs b/crates/engine/tree/src/tree/mod.rs index 4bfa0e20ee76..8263f2edc438 100644 --- a/crates/engine/tree/src/tree/mod.rs +++ b/crates/engine/tree/src/tree/mod.rs @@ -39,8 +39,8 @@ use reth_payload_validator::ExecutionPayloadValidator; use reth_primitives::{Block, GotExpected, SealedBlock, SealedBlockWithSenders, SealedHeader}; use reth_provider::{ providers::ConsistentDbView, BlockReader, DatabaseProviderFactory, ExecutionOutcome, - HashedPostStateProvider, ProviderError, StateProviderBox, StateProviderFactory, StateReader, - StateRootProvider, TransactionVariant, + HashedPostStateProvider, ProviderError, StateCommitmentProvider, StateProviderBox, + StateProviderFactory, StateReader, StateRootProvider, TransactionVariant, }; use reth_revm::database::StateProviderDatabase; use reth_stages_api::ControlFlow; @@ -540,6 +540,7 @@ where + BlockReader + StateProviderFactory + StateReader + + StateCommitmentProvider + HashedPostStateProvider + Clone + 'static, diff --git a/crates/storage/provider/src/providers/blockchain_provider.rs b/crates/storage/provider/src/providers/blockchain_provider.rs index 14a25dba6472..6ac09376292b 100644 --- a/crates/storage/provider/src/providers/blockchain_provider.rs +++ b/crates/storage/provider/src/providers/blockchain_provider.rs @@ -32,7 +32,7 @@ use reth_primitives::{ }; use reth_prune_types::{PruneCheckpoint, PruneSegment}; use reth_stages_types::{StageCheckpoint, StageId}; -use reth_storage_api::{DBProvider, StorageChangeSetReader}; +use reth_storage_api::{DBProvider, StateCommitmentProvider, StorageChangeSetReader}; use reth_storage_errors::provider::ProviderResult; use reth_trie::HashedPostState; use reth_trie_db::StateCommitment; @@ -167,6 +167,10 @@ impl DatabaseProviderFactory for BlockchainProvider2 { } } +impl StateCommitmentProvider for BlockchainProvider2 { + type StateCommitment = N::StateCommitment; +} + impl StaticFileProviderFactory for BlockchainProvider2 { type Primitives = N::Primitives; diff --git a/crates/storage/provider/src/providers/consistent_view.rs b/crates/storage/provider/src/providers/consistent_view.rs index 4640f4603354..479537f120cc 100644 --- a/crates/storage/provider/src/providers/consistent_view.rs +++ b/crates/storage/provider/src/providers/consistent_view.rs @@ -2,11 +2,11 @@ use crate::{BlockNumReader, DatabaseProviderFactory, HeaderProvider}; use alloy_primitives::B256; use reth_errors::ProviderError; use reth_primitives::GotExpected; -use reth_storage_api::{BlockReader, DBProvider}; +use reth_storage_api::{BlockReader, DBProvider, StateCommitmentProvider}; use reth_storage_errors::provider::ProviderResult; use reth_trie::HashedPostState; -use reth_trie_db::DatabaseHashedPostState; +use reth_trie_db::{DatabaseHashedPostState, StateCommitment}; pub use reth_storage_errors::provider::ConsistentViewError; @@ -33,7 +33,7 @@ pub struct ConsistentDbView { impl ConsistentDbView where - Factory: DatabaseProviderFactory, + Factory: DatabaseProviderFactory + StateCommitmentProvider, { /// Creates new consistent database view. pub const fn new(factory: Factory, tip: Option) -> Self { @@ -59,7 +59,9 @@ where { Ok(HashedPostState::default()) } else { - Ok(HashedPostState::from_reverts(provider.tx_ref(), block_number + 1)?) + Ok(HashedPostState::from_reverts::< + ::KeyHasher, + >(provider.tx_ref(), block_number + 1)?) } } diff --git a/crates/storage/provider/src/providers/database/mod.rs b/crates/storage/provider/src/providers/database/mod.rs index 13fbb77582e6..d620c92edab0 100644 --- a/crates/storage/provider/src/providers/database/mod.rs +++ b/crates/storage/provider/src/providers/database/mod.rs @@ -26,7 +26,7 @@ use reth_primitives::{ }; use reth_prune_types::{PruneCheckpoint, PruneModes, PruneSegment}; use reth_stages_types::{StageCheckpoint, StageId}; -use reth_storage_api::TryIntoHistoricalStateProvider; +use reth_storage_api::{StateCommitmentProvider, TryIntoHistoricalStateProvider}; use reth_storage_errors::provider::ProviderResult; use reth_trie::HashedPostState; use reth_trie_db::StateCommitment; @@ -221,6 +221,10 @@ impl DatabaseProviderFactory for ProviderFactory { } } +impl StateCommitmentProvider for ProviderFactory { + type StateCommitment = N::StateCommitment; +} + impl StaticFileProviderFactory for ProviderFactory { type Primitives = N::Primitives; diff --git a/crates/storage/provider/src/providers/state/historical.rs b/crates/storage/provider/src/providers/state/historical.rs index e4594d3ddda9..ddc52c721e91 100644 --- a/crates/storage/provider/src/providers/state/historical.rs +++ b/crates/storage/provider/src/providers/state/historical.rs @@ -135,7 +135,9 @@ impl<'b, Provider: DBProvider + BlockNumReader + StateCommitmentProvider> ); } - Ok(HashedPostState::from_reverts(self.tx(), self.block_number)?) + Ok(HashedPostState::from_reverts::< + ::KeyHasher, + >(self.tx(), self.block_number)?) } /// Retrieve revert hashed storage for this history provider and target address. diff --git a/crates/storage/provider/src/test_utils/mock.rs b/crates/storage/provider/src/test_utils/mock.rs index d2536b0e63a1..0df3a8988e82 100644 --- a/crates/storage/provider/src/test_utils/mock.rs +++ b/crates/storage/provider/src/test_utils/mock.rs @@ -28,8 +28,8 @@ use reth_primitives::{ }; use reth_stages_types::{StageCheckpoint, StageId}; use reth_storage_api::{ - DatabaseProviderFactory, HashedPostStateProvider, StageCheckpointReader, StateProofProvider, - StorageRootProvider, + DatabaseProviderFactory, HashedPostStateProvider, StageCheckpointReader, + StateCommitmentProvider, StateProofProvider, StorageRootProvider, }; use reth_storage_errors::provider::{ConsistentViewError, ProviderError, ProviderResult}; use reth_trie::{ @@ -164,6 +164,10 @@ impl NodeTypes for MockNode { type Storage = EthStorage; } +impl StateCommitmentProvider for MockEthProvider { + type StateCommitment = ::StateCommitment; +} + impl DatabaseProviderFactory for MockEthProvider { type DB = DatabaseMock; type Provider = DatabaseProvider; diff --git a/crates/trie/db/src/state.rs b/crates/trie/db/src/state.rs index 5f77b0b916c4..5aaf3ebe5b0f 100644 --- a/crates/trie/db/src/state.rs +++ b/crates/trie/db/src/state.rs @@ -1,5 +1,5 @@ use crate::{DatabaseHashedCursorFactory, DatabaseTrieCursorFactory, PrefixSetLoader}; -use alloy_primitives::{keccak256, Address, BlockNumber, B256, U256}; +use alloy_primitives::{Address, BlockNumber, B256, U256}; use reth_db::tables; use reth_db_api::{ cursor::DbCursorRO, @@ -10,7 +10,7 @@ use reth_execution_errors::StateRootError; use reth_storage_errors::db::DatabaseError; use reth_trie::{ hashed_cursor::HashedPostStateCursorFactory, trie_cursor::InMemoryTrieCursorFactory, - updates::TrieUpdates, HashedPostState, HashedStorage, KeccakKeyHasher, StateRoot, + updates::TrieUpdates, HashedPostState, HashedStorage, KeccakKeyHasher, KeyHasher, StateRoot, StateRootProgress, TrieInput, }; use std::{collections::HashMap, ops::RangeInclusive}; @@ -123,7 +123,7 @@ pub trait DatabaseStateRoot<'a, TX>: Sized { pub trait DatabaseHashedPostState: Sized { /// Initializes [`HashedPostState`] from reverts. Iterates over state reverts from the specified /// block up to the current tip and aggregates them into hashed state in reverse. - fn from_reverts(tx: &TX, from: BlockNumber) -> Result; + fn from_reverts(tx: &TX, from: BlockNumber) -> Result; } impl<'a, TX: DbTx> DatabaseStateRoot<'a, TX> @@ -217,7 +217,7 @@ impl<'a, TX: DbTx> DatabaseStateRoot<'a, TX> } impl DatabaseHashedPostState for HashedPostState { - fn from_reverts(tx: &TX, from: BlockNumber) -> Result { + fn from_reverts(tx: &TX, from: BlockNumber) -> Result { // Iterate over account changesets and record value before first occurring account change. let mut accounts = HashMap::new(); let mut account_changesets_cursor = tx.cursor_read::()?; @@ -238,19 +238,19 @@ impl DatabaseHashedPostState for HashedPostState { } let hashed_accounts = - accounts.into_iter().map(|(address, info)| (keccak256(address), info)).collect(); + accounts.into_iter().map(|(address, info)| (KH::hash_key(address), info)).collect(); let hashed_storages = storages .into_iter() .map(|(address, storage)| { ( - keccak256(address), + KH::hash_key(address), HashedStorage::from_iter( // The `wiped` flag indicates only whether previous storage entries // should be looked up in db or not. For reverts it's a noop since all // wiped changes had been written as storage reverts. false, - storage.into_iter().map(|(slot, value)| (keccak256(slot), value)), + storage.into_iter().map(|(slot, value)| (KH::hash_key(slot), value)), ), ) }) diff --git a/crates/trie/parallel/src/proof.rs b/crates/trie/parallel/src/proof.rs index dcb1a0231dd1..d0a31738ef9d 100644 --- a/crates/trie/parallel/src/proof.rs +++ b/crates/trie/parallel/src/proof.rs @@ -9,6 +9,7 @@ use reth_db::DatabaseError; use reth_execution_errors::StorageRootError; use reth_provider::{ providers::ConsistentDbView, BlockReader, DBProvider, DatabaseProviderFactory, ProviderError, + StateCommitmentProvider, }; use reth_trie::{ hashed_cursor::{HashedCursorFactory, HashedPostStateCursorFactory}, @@ -53,7 +54,12 @@ impl ParallelProof { impl ParallelProof where - Factory: DatabaseProviderFactory + Clone + Send + Sync + 'static, + Factory: DatabaseProviderFactory + + StateCommitmentProvider + + Clone + + Send + + Sync + + 'static, { /// Generate a state multiproof according to specified targets. pub fn multiproof( diff --git a/crates/trie/parallel/src/root.rs b/crates/trie/parallel/src/root.rs index 7a316d8b15fb..8b75a1225c6d 100644 --- a/crates/trie/parallel/src/root.rs +++ b/crates/trie/parallel/src/root.rs @@ -7,6 +7,7 @@ use itertools::Itertools; use reth_execution_errors::StorageRootError; use reth_provider::{ providers::ConsistentDbView, BlockReader, DBProvider, DatabaseProviderFactory, ProviderError, + StateCommitmentProvider, }; use reth_trie::{ hashed_cursor::{HashedCursorFactory, HashedPostStateCursorFactory}, @@ -57,7 +58,12 @@ impl ParallelStateRoot { impl ParallelStateRoot where - Factory: DatabaseProviderFactory + Clone + Send + Sync + 'static, + Factory: DatabaseProviderFactory + + StateCommitmentProvider + + Clone + + Send + + Sync + + 'static, { /// Calculate incremental state root in parallel. pub fn incremental_root(self) -> Result { From 8b24bc32efdaa6602edccd1971832fbdbe736a60 Mon Sep 17 00:00:00 2001 From: frisitano Date: Mon, 25 Nov 2024 15:31:07 +0800 Subject: [PATCH 05/15] feat: introduce HashedStorageProvider --- crates/chain-state/src/in_memory.rs | 11 +++++++-- crates/chain-state/src/memory_overlay.rs | 12 +++++++--- crates/revm/src/test_utils.rs | 10 ++++++-- crates/rpc/rpc-eth-types/src/cache/db.rs | 8 ++++++- .../src/providers/bundle_state_provider.rs | 19 +++++++++------ .../src/providers/state/historical.rs | 13 ++++++++++- .../provider/src/providers/state/latest.rs | 13 ++++++++++- .../provider/src/providers/state/macros.rs | 3 +++ .../storage/provider/src/test_utils/mock.rs | 8 ++++++- .../storage/provider/src/test_utils/noop.rs | 10 +++++++- crates/storage/storage-api/src/state.rs | 5 ++-- crates/storage/storage-api/src/storage.rs | 9 ++++++++ crates/trie/trie/src/state.rs | 23 ++++++++++++++----- 13 files changed, 117 insertions(+), 27 deletions(-) diff --git a/crates/chain-state/src/in_memory.rs b/crates/chain-state/src/in_memory.rs index d6e885ad2bc4..c88b86896553 100644 --- a/crates/chain-state/src/in_memory.rs +++ b/crates/chain-state/src/in_memory.rs @@ -919,10 +919,11 @@ mod tests { use reth_errors::ProviderResult; use reth_primitives::{Account, Bytecode, EthPrimitives, Receipt}; use reth_storage_api::{ - AccountReader, BlockHashReader, HashedPostStateProvider, StateProofProvider, StateProvider, - StateRootProvider, StorageRootProvider, + AccountReader, BlockHashReader, HashedPostStateProvider, HashedStorageProvider, + StateProofProvider, StateProvider, StateRootProvider, StorageRootProvider, }; use reth_trie::{AccountProof, HashedStorage, MultiProof, StorageProof, TrieInput}; + use revm::db::BundleAccount; fn create_mock_state( test_block_builder: &mut TestBlockBuilder, @@ -1021,6 +1022,12 @@ mod tests { } } + impl HashedStorageProvider for MockStateProvider { + fn hashed_storage(&self, _account: &BundleAccount) -> HashedStorage { + HashedStorage::default() + } + } + impl StorageRootProvider for MockStateProvider { fn storage_root( &self, diff --git a/crates/chain-state/src/memory_overlay.rs b/crates/chain-state/src/memory_overlay.rs index 92ae409991da..4c160b037ee8 100644 --- a/crates/chain-state/src/memory_overlay.rs +++ b/crates/chain-state/src/memory_overlay.rs @@ -7,13 +7,13 @@ use alloy_primitives::{ use reth_errors::ProviderResult; use reth_primitives::{Account, Bytecode, NodePrimitives}; use reth_storage_api::{ - AccountReader, BlockHashReader, HashedPostStateProvider, StateProofProvider, StateProvider, - StateRootProvider, StorageRootProvider, + AccountReader, BlockHashReader, HashedPostStateProvider, HashedStorageProvider, + StateProofProvider, StateProvider, StateRootProvider, StorageRootProvider, }; use reth_trie::{ updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, TrieInput, }; -use revm::db::BundleState; +use revm::db::{BundleAccount, BundleState}; use std::sync::OnceLock; /// A state provider that stores references to in-memory blocks along with their state as well as a @@ -209,6 +209,12 @@ macro_rules! impl_state_provider { } } + impl $($tokens)* HashedStorageProvider for $type { + fn hashed_storage(&self, account: &BundleAccount) -> HashedStorage { + self.historical.hashed_storage(account) + } + } + impl $($tokens)* StateProvider for $type { fn storage( &self, diff --git a/crates/revm/src/test_utils.rs b/crates/revm/src/test_utils.rs index 23705dda0e1d..5057ff828220 100644 --- a/crates/revm/src/test_utils.rs +++ b/crates/revm/src/test_utils.rs @@ -6,8 +6,8 @@ use alloy_primitives::{ }; use reth_primitives::{Account, Bytecode}; use reth_storage_api::{ - AccountReader, BlockHashReader, HashedPostStateProvider, StateProofProvider, StateProvider, - StateRootProvider, StorageRootProvider, + AccountReader, BlockHashReader, HashedPostStateProvider, HashedStorageProvider, + StateProofProvider, StateProvider, StateRootProvider, StorageRootProvider, }; use reth_storage_errors::provider::ProviderResult; use reth_trie::{ @@ -147,6 +147,12 @@ impl HashedPostStateProvider for StateProviderTest { } } +impl HashedStorageProvider for StateProviderTest { + fn hashed_storage(&self, account: &revm::db::BundleAccount) -> HashedStorage { + HashedStorage::from_bundle_account::(account) + } +} + impl StateProvider for StateProviderTest { fn storage( &self, diff --git a/crates/rpc/rpc-eth-types/src/cache/db.rs b/crates/rpc/rpc-eth-types/src/cache/db.rs index de61f308fd6c..ce99a0af8a60 100644 --- a/crates/rpc/rpc-eth-types/src/cache/db.rs +++ b/crates/rpc/rpc-eth-types/src/cache/db.rs @@ -8,7 +8,7 @@ use alloy_primitives::{ }; use reth_errors::ProviderResult; use reth_revm::{database::StateProviderDatabase, db::CacheDB, DatabaseRef}; -use reth_storage_api::{HashedPostStateProvider, StateProvider}; +use reth_storage_api::{HashedPostStateProvider, HashedStorageProvider, StateProvider}; use reth_trie::HashedStorage; use revm::Database; @@ -139,6 +139,12 @@ impl HashedPostStateProvider for StateProviderTraitObjWrapper<'_> { } } +impl HashedStorageProvider for StateProviderTraitObjWrapper<'_> { + fn hashed_storage(&self, account: &revm::db::BundleAccount) -> HashedStorage { + self.0.hashed_storage(account) + } +} + impl StateProvider for StateProviderTraitObjWrapper<'_> { fn storage( &self, diff --git a/crates/storage/provider/src/providers/bundle_state_provider.rs b/crates/storage/provider/src/providers/bundle_state_provider.rs index a7a102bc5c41..8db8f3753378 100644 --- a/crates/storage/provider/src/providers/bundle_state_provider.rs +++ b/crates/storage/provider/src/providers/bundle_state_provider.rs @@ -6,7 +6,9 @@ use alloy_primitives::{ Address, BlockNumber, Bytes, B256, }; use reth_primitives::{Account, Bytecode}; -use reth_storage_api::{HashedPostStateProvider, StateProofProvider, StorageRootProvider}; +use reth_storage_api::{ + HashedPostStateProvider, HashedStorageProvider, StateProofProvider, StorageRootProvider, +}; use reth_storage_errors::provider::ProviderResult; use reth_trie::{ updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, TrieInput, @@ -37,12 +39,7 @@ impl BundleStateProvider let bundle_state = self.block_execution_data_provider.execution_outcome().state(); bundle_state .account(&address) - .map(|account| { - HashedStorage::from_plain_storage( - account.status, - account.storage.iter().map(|(slot, value)| (slot, &value.present_value)), - ) - }) + .map(|account| self.state_provider.hashed_storage(account)) .unwrap_or_default() } } @@ -183,6 +180,14 @@ impl HashedPostStateProvider } } +impl HashedStorageProvider + for BundleStateProvider +{ + fn hashed_storage(&self, account: &revm::db::BundleAccount) -> HashedStorage { + self.state_provider.hashed_storage(account) + } +} + impl StateProvider for BundleStateProvider { fn storage( &self, diff --git a/crates/storage/provider/src/providers/state/historical.rs b/crates/storage/provider/src/providers/state/historical.rs index ddc52c721e91..a06246176f01 100644 --- a/crates/storage/provider/src/providers/state/historical.rs +++ b/crates/storage/provider/src/providers/state/historical.rs @@ -16,7 +16,8 @@ use reth_db_api::{ }; use reth_primitives::{Account, Bytecode}; use reth_storage_api::{ - BlockNumReader, DBProvider, StateCommitmentProvider, StateProofProvider, StorageRootProvider, + BlockNumReader, DBProvider, HashedStorageProvider, StateCommitmentProvider, StateProofProvider, + StorageRootProvider, }; use reth_storage_errors::provider::ProviderResult; use reth_trie::{ @@ -393,6 +394,16 @@ impl HashedPostStateProvider } } +impl HashedStorageProvider + for HistoricalStateProviderRef<'_, Provider> +{ + fn hashed_storage(&self, account: &revm::db::BundleAccount) -> HashedStorage { + HashedStorage::from_bundle_account::< + ::KeyHasher, + >(account) + } +} + impl StateProvider for HistoricalStateProviderRef<'_, Provider> { diff --git a/crates/storage/provider/src/providers/state/latest.rs b/crates/storage/provider/src/providers/state/latest.rs index 825817357ca9..e920ac5a7c73 100644 --- a/crates/storage/provider/src/providers/state/latest.rs +++ b/crates/storage/provider/src/providers/state/latest.rs @@ -10,7 +10,8 @@ use reth_db::tables; use reth_db_api::{cursor::DbDupCursorRO, transaction::DbTx}; use reth_primitives::{Account, Bytecode}; use reth_storage_api::{ - DBProvider, StateCommitmentProvider, StateProofProvider, StorageRootProvider, + DBProvider, HashedStorageProvider, StateCommitmentProvider, StateProofProvider, + StorageRootProvider, }; use reth_storage_errors::provider::{ProviderError, ProviderResult}; use reth_trie::{ @@ -156,6 +157,16 @@ impl HashedPostStateProvider } } +impl HashedStorageProvider + for LatestStateProviderRef<'_, Provider> +{ + fn hashed_storage<'a>(&self, account: &revm::db::BundleAccount) -> HashedStorage { + HashedStorage::from_bundle_account::< + ::KeyHasher, + >(account) + } +} + impl StateProvider for LatestStateProviderRef<'_, Provider> { diff --git a/crates/storage/provider/src/providers/state/macros.rs b/crates/storage/provider/src/providers/state/macros.rs index 860407923573..d83dc3b292da 100644 --- a/crates/storage/provider/src/providers/state/macros.rs +++ b/crates/storage/provider/src/providers/state/macros.rs @@ -59,6 +59,9 @@ macro_rules! delegate_provider_impls { HashedPostStateProvider $(where [$($generics)*])? { fn hashed_post_state(&self, bundle_state: &revm::db::BundleState) -> reth_trie::HashedPostState; } + HashedStorageProvider $(where [$($generics)*])? { + fn hashed_storage(&self, bundle_state: &revm::db::BundleAccount) -> reth_trie::HashedStorage; + } ); } } diff --git a/crates/storage/provider/src/test_utils/mock.rs b/crates/storage/provider/src/test_utils/mock.rs index 0df3a8988e82..f4412387e2cf 100644 --- a/crates/storage/provider/src/test_utils/mock.rs +++ b/crates/storage/provider/src/test_utils/mock.rs @@ -28,7 +28,7 @@ use reth_primitives::{ }; use reth_stages_types::{StageCheckpoint, StageId}; use reth_storage_api::{ - DatabaseProviderFactory, HashedPostStateProvider, StageCheckpointReader, + DatabaseProviderFactory, HashedPostStateProvider, HashedStorageProvider, StageCheckpointReader, StateCommitmentProvider, StateProofProvider, StorageRootProvider, }; use reth_storage_errors::provider::{ConsistentViewError, ProviderError, ProviderResult}; @@ -677,6 +677,12 @@ impl HashedPostStateProvider for MockEthProvider { } } +impl HashedStorageProvider for MockEthProvider { + fn hashed_storage(&self, _account: &revm::db::BundleAccount) -> HashedStorage { + HashedStorage::default() + } +} + impl StateProvider for MockEthProvider { fn storage( &self, diff --git a/crates/storage/provider/src/test_utils/noop.rs b/crates/storage/provider/src/test_utils/noop.rs index f97d403cb1f7..2269b1cb8fae 100644 --- a/crates/storage/provider/src/test_utils/noop.rs +++ b/crates/storage/provider/src/test_utils/noop.rs @@ -27,7 +27,9 @@ use reth_primitives::{ }; use reth_prune_types::{PruneCheckpoint, PruneSegment}; use reth_stages_types::{StageCheckpoint, StageId}; -use reth_storage_api::{HashedPostStateProvider, StateProofProvider, StorageRootProvider}; +use reth_storage_api::{ + HashedPostStateProvider, HashedStorageProvider, StateProofProvider, StorageRootProvider, +}; use reth_storage_errors::provider::ProviderResult; use reth_trie::{ updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, TrieInput, @@ -405,6 +407,12 @@ impl HashedPostStateProvider for NoopProvider { } } +impl HashedStorageProvider for NoopProvider { + fn hashed_storage(&self, _account: &revm::db::BundleAccount) -> HashedStorage { + HashedStorage::default() + } +} + impl StateProvider for NoopProvider { fn storage( &self, diff --git a/crates/storage/storage-api/src/state.rs b/crates/storage/storage-api/src/state.rs index 9b0134607c34..2f52a42d4519 100644 --- a/crates/storage/storage-api/src/state.rs +++ b/crates/storage/storage-api/src/state.rs @@ -1,6 +1,6 @@ use super::{ - AccountReader, BlockHashReader, BlockIdReader, StateProofProvider, StateRootProvider, - StorageRootProvider, + AccountReader, BlockHashReader, BlockIdReader, HashedStorageProvider, StateProofProvider, + StateRootProvider, StorageRootProvider, }; use alloy_consensus::constants::KECCAK_EMPTY; use alloy_eips::{BlockId, BlockNumberOrTag}; @@ -24,6 +24,7 @@ pub trait StateProvider: + StorageRootProvider + StateProofProvider + HashedPostStateProvider + + HashedStorageProvider + Send + Sync { diff --git a/crates/storage/storage-api/src/storage.rs b/crates/storage/storage-api/src/storage.rs index e1443347e4bb..3e3fd92eaefe 100644 --- a/crates/storage/storage-api/src/storage.rs +++ b/crates/storage/storage-api/src/storage.rs @@ -2,6 +2,8 @@ use alloy_primitives::{Address, BlockNumber, B256}; use reth_db_api::models::BlockNumberAddress; use reth_primitives::StorageEntry; use reth_storage_errors::provider::ProviderResult; +use reth_trie::HashedStorage; +use revm::db::BundleAccount; use std::{ collections::{BTreeMap, BTreeSet}, ops::RangeInclusive, @@ -41,3 +43,10 @@ pub trait StorageChangeSetReader: Send + Sync { block_number: BlockNumber, ) -> ProviderResult>; } + +/// Provider of [`HashedStorage`] +#[auto_impl::auto_impl(&, Arc, Box)] +pub trait HashedStorageProvider: Send + Sync { + /// Construct [`HashedStorage`] from the provided [`BundleAccount`]. + fn hashed_storage(&self, account: &BundleAccount) -> HashedStorage; +} diff --git a/crates/trie/trie/src/state.rs b/crates/trie/trie/src/state.rs index 66a6af5a3a70..6307358163f1 100644 --- a/crates/trie/trie/src/state.rs +++ b/crates/trie/trie/src/state.rs @@ -2,7 +2,7 @@ use crate::{ prefix_set::{PrefixSetMut, TriePrefixSetsMut}, Nibbles, }; -use alloy_primitives::{keccak256, Address, B256, U256}; +use alloy_primitives::{Address, B256, U256}; use itertools::Itertools; use rayon::prelude::{IntoParallelIterator, ParallelIterator}; use reth_primitives::Account; @@ -34,7 +34,7 @@ impl HashedPostState { .map(|(address, account)| { let hashed_address = KH::hash_key(address); let hashed_account = account.info.clone().map(Into::into); - let hashed_storage = HashedStorage::from_plain_storage( + let hashed_storage = HashedStorage::from_plain_storage::( account.status, account.storage.iter().map(|(slot, value)| (slot, &value.present_value)), ); @@ -61,7 +61,7 @@ impl HashedPostState { .map(|(address, account)| { let hashed_address = KH::hash_key(address); let hashed_account = account.account.as_ref().map(|a| a.info.clone().into()); - let hashed_storage = HashedStorage::from_plain_storage( + let hashed_storage = HashedStorage::from_plain_storage::( account.status, account.account.as_ref().map(|a| a.storage.iter()).into_iter().flatten(), ); @@ -219,14 +219,25 @@ impl HashedStorage { Self { wiped, storage: HashMap::from_iter(iter) } } + /// Create a new hashed storage from the provided [`BundleAccount`] + /// + /// This function will use the present value of the storage slots in the account to create the + /// hashed storage. + pub fn from_bundle_account(account: &BundleAccount) -> Self { + Self::from_plain_storage::( + account.status, + account.storage.iter().map(|(slot, value)| (slot, &value.present_value)), + ) + } + /// Create new hashed storage from account status and plain storage. - pub fn from_plain_storage<'a>( + pub fn from_plain_storage<'a, KH: KeyHasher>( status: AccountStatus, storage: impl IntoIterator, ) -> Self { Self::from_iter( status.was_destroyed(), - storage.into_iter().map(|(key, value)| (keccak256(B256::from(*key)), *value)), + storage.into_iter().map(|(key, value)| (KH::hash_key(B256::from(*key)), *value)), ) } @@ -349,7 +360,7 @@ impl HashedStorageSorted { #[cfg(test)] mod tests { use super::*; - use alloy_primitives::Bytes; + use alloy_primitives::{keccak256, Bytes}; use reth_trie_common::KeccakKeyHasher; use revm::{ db::{ From 0e79635cc265ab6788cdf4af9dab557970cedfda Mon Sep 17 00:00:00 2001 From: frisitano Date: Mon, 25 Nov 2024 15:34:24 +0800 Subject: [PATCH 06/15] lint: revm/test-utils feature propogation --- crates/chain-state/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/chain-state/Cargo.toml b/crates/chain-state/Cargo.toml index 7d6d503a7060..7f05d8475cc0 100644 --- a/crates/chain-state/Cargo.toml +++ b/crates/chain-state/Cargo.toml @@ -52,7 +52,6 @@ alloy-signer.workspace = true alloy-signer-local.workspace = true alloy-consensus.workspace = true rand.workspace = true -revm.workspace = true [features] test-utils = [ @@ -62,4 +61,5 @@ test-utils = [ "reth-chainspec/test-utils", "reth-primitives/test-utils", "reth-trie/test-utils", + "revm/test-utils", ] From 593587e691763a71cf678e3501e0092caaaef7ed Mon Sep 17 00:00:00 2001 From: frisitano Date: Mon, 25 Nov 2024 15:40:50 +0800 Subject: [PATCH 07/15] fix: add Send + Sync bound on introduced storage state api methods --- crates/storage/storage-api/src/state.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/storage/storage-api/src/state.rs b/crates/storage/storage-api/src/state.rs index 9b0134607c34..dc53319f4c5f 100644 --- a/crates/storage/storage-api/src/state.rs +++ b/crates/storage/storage-api/src/state.rs @@ -86,14 +86,14 @@ pub trait StateProvider: } /// Trait implemented for database providers that can provide the [`StateCommitment`] type. -pub trait StateCommitmentProvider { +pub trait StateCommitmentProvider: Send + Sync { /// The [`StateCommitment`] type that can be used to perform state commitment operations. type StateCommitment: StateCommitment; } /// Trait that provides the hashed state from various sources. #[auto_impl(&, Arc, Box)] -pub trait HashedPostStateProvider { +pub trait HashedPostStateProvider: Send + Sync { /// Returns the `HashedPostState` of the provided [`BundleState`]. fn hashed_post_state(&self, bundle_state: &BundleState) -> HashedPostState; } From dbeb344bc0c4ea4395c4342e3d905d944553fc45 Mon Sep 17 00:00:00 2001 From: frisitano Date: Mon, 25 Nov 2024 17:19:37 +0800 Subject: [PATCH 08/15] feat: introduce KeyHasherProvider --- crates/chain-state/src/in_memory.rs | 14 ++++++- crates/chain-state/src/memory_overlay.rs | 13 ++++-- .../engine/invalid-block-hooks/src/witness.rs | 11 +++-- crates/revm/src/test_utils.rs | 10 ++++- crates/rpc/rpc-eth-types/src/cache/db.rs | 10 ++++- crates/rpc/rpc-eth-types/src/simulate.rs | 8 ++-- .../stages/src/stages/hashing_account.rs | 25 +++++++++--- .../stages/src/stages/hashing_storage.rs | 25 +++++++++--- .../src/providers/bundle_state_provider.rs | 11 ++++- .../src/providers/database/provider.rs | 40 ++++++++++++------- .../src/providers/state/historical.rs | 17 ++++++-- .../provider/src/providers/state/latest.rs | 13 ++++-- .../provider/src/providers/state/macros.rs | 3 ++ .../storage/provider/src/test_utils/mock.rs | 10 ++++- .../storage/provider/src/test_utils/noop.rs | 9 ++++- crates/storage/storage-api/src/state.rs | 8 ++++ 16 files changed, 172 insertions(+), 55 deletions(-) diff --git a/crates/chain-state/src/in_memory.rs b/crates/chain-state/src/in_memory.rs index c88b86896553..95c327980b04 100644 --- a/crates/chain-state/src/in_memory.rs +++ b/crates/chain-state/src/in_memory.rs @@ -920,9 +920,13 @@ mod tests { use reth_primitives::{Account, Bytecode, EthPrimitives, Receipt}; use reth_storage_api::{ AccountReader, BlockHashReader, HashedPostStateProvider, HashedStorageProvider, - StateProofProvider, StateProvider, StateRootProvider, StorageRootProvider, + KeyHasherProvider, StateProofProvider, StateProvider, StateRootProvider, + StorageRootProvider, + }; + use reth_trie::{ + AccountProof, HashedStorage, KeccakKeyHasher, KeyHasher, MultiProof, StorageProof, + TrieInput, }; - use reth_trie::{AccountProof, HashedStorage, MultiProof, StorageProof, TrieInput}; use revm::db::BundleAccount; fn create_mock_state( @@ -1028,6 +1032,12 @@ mod tests { } } + impl KeyHasherProvider for MockStateProvider { + fn hash_key(&self, bytes: &[u8]) -> B256 { + KeccakKeyHasher::hash_key(bytes) + } + } + impl StorageRootProvider for MockStateProvider { fn storage_root( &self, diff --git a/crates/chain-state/src/memory_overlay.rs b/crates/chain-state/src/memory_overlay.rs index 4c160b037ee8..05e761f99980 100644 --- a/crates/chain-state/src/memory_overlay.rs +++ b/crates/chain-state/src/memory_overlay.rs @@ -1,6 +1,5 @@ use super::ExecutedBlock; use alloy_primitives::{ - keccak256, map::{HashMap, HashSet}, Address, BlockNumber, Bytes, StorageKey, StorageValue, B256, }; @@ -8,7 +7,7 @@ use reth_errors::ProviderResult; use reth_primitives::{Account, Bytecode, NodePrimitives}; use reth_storage_api::{ AccountReader, BlockHashReader, HashedPostStateProvider, HashedStorageProvider, - StateProofProvider, StateProvider, StateRootProvider, StorageRootProvider, + KeyHasherProvider, StateProofProvider, StateProvider, StateRootProvider, StorageRootProvider, }; use reth_trie::{ updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, TrieInput, @@ -150,7 +149,7 @@ macro_rules! impl_state_provider { fn storage_root(&self, address: Address, storage: HashedStorage) -> ProviderResult { let state = &self.trie_state().state; let mut hashed_storage = - state.storages.get(&keccak256(address)).cloned().unwrap_or_default(); + state.storages.get(&self.hash_key(address.as_ref())).cloned().unwrap_or_default(); hashed_storage.extend(&storage); self.historical.storage_root(address, hashed_storage) } @@ -164,7 +163,7 @@ macro_rules! impl_state_provider { ) -> ProviderResult { let state = &self.trie_state().state; let mut hashed_storage = - state.storages.get(&keccak256(address)).cloned().unwrap_or_default(); + state.storages.get(&self.hash_key(address.as_ref())).cloned().unwrap_or_default(); hashed_storage.extend(&storage); self.historical.storage_proof(address, slot, hashed_storage) } @@ -215,6 +214,12 @@ macro_rules! impl_state_provider { } } + impl $($tokens)* KeyHasherProvider for $type { + fn hash_key(&self, bytes: &[u8]) -> B256 { + self.historical.hash_key(bytes) + } + } + impl $($tokens)* StateProvider for $type { fn storage( &self, diff --git a/crates/engine/invalid-block-hooks/src/witness.rs b/crates/engine/invalid-block-hooks/src/witness.rs index 0daf3a64911e..acb3351afa6f 100644 --- a/crates/engine/invalid-block-hooks/src/witness.rs +++ b/crates/engine/invalid-block-hooks/src/witness.rs @@ -1,7 +1,7 @@ use std::{collections::HashMap, fmt::Debug, fs::File, io::Write, path::PathBuf}; use alloy_consensus::Header; -use alloy_primitives::{keccak256, B256, U256}; +use alloy_primitives::{B256, U256}; use alloy_rpc_types_debug::ExecutionWitness; use eyre::OptionExt; use pretty_assertions::Comparison; @@ -68,10 +68,9 @@ where // TODO(alexey): unify with `DebugApi::debug_execution_witness` // Setup database. + let provider = self.provider.state_by_block_hash(parent_header.hash())?; let mut db = StateBuilder::new() - .with_database(StateProviderDatabase::new( - self.provider.state_by_block_hash(parent_header.hash())?, - )) + .with_database(StateProviderDatabase::new(&provider)) .with_bundle_update() .build(); @@ -132,7 +131,7 @@ where // referenced accounts + storage slots. let mut hashed_state = db.database.hashed_post_state(&bundle_state); for (address, account) in db.cache.accounts { - let hashed_address = keccak256(address); + let hashed_address = provider.hash_key(address.as_ref()); hashed_state .accounts .insert(hashed_address, account.account.as_ref().map(|a| a.info.clone().into())); @@ -147,7 +146,7 @@ where for (slot, value) in account.storage { let slot = B256::from(slot); - let hashed_slot = keccak256(slot); + let hashed_slot = provider.hash_key(slot.as_ref()); storage.storage.insert(hashed_slot, value); state_preimages.insert(hashed_slot, alloy_rlp::encode(slot).into()); diff --git a/crates/revm/src/test_utils.rs b/crates/revm/src/test_utils.rs index 5057ff828220..6beb61c2cd59 100644 --- a/crates/revm/src/test_utils.rs +++ b/crates/revm/src/test_utils.rs @@ -7,11 +7,11 @@ use alloy_primitives::{ use reth_primitives::{Account, Bytecode}; use reth_storage_api::{ AccountReader, BlockHashReader, HashedPostStateProvider, HashedStorageProvider, - StateProofProvider, StateProvider, StateRootProvider, StorageRootProvider, + KeyHasherProvider, StateProofProvider, StateProvider, StateRootProvider, StorageRootProvider, }; use reth_storage_errors::provider::ProviderResult; use reth_trie::{ - updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, KeccakKeyHasher, + updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, KeccakKeyHasher, KeyHasher, MultiProof, StorageProof, TrieInput, }; @@ -153,6 +153,12 @@ impl HashedStorageProvider for StateProviderTest { } } +impl KeyHasherProvider for StateProviderTest { + fn hash_key(&self, bytes: &[u8]) -> B256 { + KeccakKeyHasher::hash_key(bytes) + } +} + impl StateProvider for StateProviderTest { fn storage( &self, diff --git a/crates/rpc/rpc-eth-types/src/cache/db.rs b/crates/rpc/rpc-eth-types/src/cache/db.rs index ce99a0af8a60..34da3b562c61 100644 --- a/crates/rpc/rpc-eth-types/src/cache/db.rs +++ b/crates/rpc/rpc-eth-types/src/cache/db.rs @@ -8,7 +8,9 @@ use alloy_primitives::{ }; use reth_errors::ProviderResult; use reth_revm::{database::StateProviderDatabase, db::CacheDB, DatabaseRef}; -use reth_storage_api::{HashedPostStateProvider, HashedStorageProvider, StateProvider}; +use reth_storage_api::{ + HashedPostStateProvider, HashedStorageProvider, KeyHasherProvider, StateProvider, +}; use reth_trie::HashedStorage; use revm::Database; @@ -145,6 +147,12 @@ impl HashedStorageProvider for StateProviderTraitObjWrapper<'_> { } } +impl KeyHasherProvider for StateProviderTraitObjWrapper<'_> { + fn hash_key(&self, bytes: &[u8]) -> B256 { + self.0.hash_key(bytes) + } +} + impl StateProvider for StateProviderTraitObjWrapper<'_> { fn storage( &self, diff --git a/crates/rpc/rpc-eth-types/src/simulate.rs b/crates/rpc/rpc-eth-types/src/simulate.rs index 5a0daa1b42f0..58a695b7533e 100644 --- a/crates/rpc/rpc-eth-types/src/simulate.rs +++ b/crates/rpc/rpc-eth-types/src/simulate.rs @@ -15,10 +15,10 @@ use reth_primitives::{ use reth_revm::database::StateProviderDatabase; use reth_rpc_server_types::result::rpc_err; use reth_rpc_types_compat::{block::from_block, TransactionCompat}; -use reth_storage_api::StateRootProvider; +use reth_storage_api::{KeyHasherProvider, StateRootProvider}; use reth_trie::{HashedPostState, HashedStorage}; use revm::{db::CacheDB, Database}; -use revm_primitives::{keccak256, Address, BlockEnv, Bytes, ExecutionResult, TxKind, B256, U256}; +use revm_primitives::{Address, BlockEnv, Bytes, ExecutionResult, TxKind, B256, U256}; use crate::{ cache::db::StateProviderTraitObjWrapper, @@ -231,7 +231,7 @@ pub fn build_block>( let mut hashed_state = HashedPostState::default(); for (address, account) in &db.accounts { - let hashed_address = keccak256(address); + let hashed_address = db.db.hash_key(address.as_ref()); hashed_state.accounts.insert(hashed_address, Some(account.info.clone().into())); let storage = hashed_state @@ -241,7 +241,7 @@ pub fn build_block>( for (slot, value) in &account.storage { let slot = B256::from(*slot); - let hashed_slot = keccak256(slot); + let hashed_slot = db.db.hash_key(slot.as_ref()); storage.storage.insert(hashed_slot, *value); } } diff --git a/crates/stages/stages/src/stages/hashing_account.rs b/crates/stages/stages/src/stages/hashing_account.rs index e6b1e548455f..581b98b3a683 100644 --- a/crates/stages/stages/src/stages/hashing_account.rs +++ b/crates/stages/stages/src/stages/hashing_account.rs @@ -1,4 +1,4 @@ -use alloy_primitives::{keccak256, B256}; +use alloy_primitives::B256; use itertools::Itertools; use reth_config::config::{EtlConfig, HashingConfig}; use reth_db::{tables, RawKey, RawTable, RawValue}; @@ -8,12 +8,16 @@ use reth_db_api::{ }; use reth_etl::Collector; use reth_primitives::Account; -use reth_provider::{AccountExtReader, DBProvider, HashingWriter, StatsReader}; +use reth_provider::{ + AccountExtReader, DBProvider, HashingWriter, StateCommitmentProvider, StatsReader, +}; use reth_stages_api::{ AccountHashingCheckpoint, EntitiesCheckpoint, ExecInput, ExecOutput, Stage, StageCheckpoint, StageError, StageId, UnwindInput, UnwindOutput, }; use reth_storage_errors::provider::ProviderResult; +use reth_trie::KeyHasher; +use reth_trie_db::StateCommitment; use std::{ fmt::Debug, ops::{Range, RangeInclusive}, @@ -131,7 +135,11 @@ impl Default for AccountHashingStage { impl Stage for AccountHashingStage where - Provider: DBProvider + HashingWriter + AccountExtReader + StatsReader, + Provider: DBProvider + + HashingWriter + + AccountExtReader + + StatsReader + + StateCommitmentProvider, { /// Return the id of the stage fn id(&self) -> StageId { @@ -172,7 +180,14 @@ where rayon::spawn(move || { for (address, account) in chunk { let address = address.key().unwrap(); - let _ = tx.send((RawKey::new(keccak256(address)), account)); + let _ = tx.send(( + RawKey::new( + <::KeyHasher as KeyHasher>::hash_key( + address, + ), + ), + account, + )); } }); @@ -299,7 +314,7 @@ mod tests { stage_test_suite_ext, ExecuteStageTestRunner, StageTestRunner, TestRunnerError, UnwindStageTestRunner, }; - use alloy_primitives::U256; + use alloy_primitives::{keccak256, U256}; use assert_matches::assert_matches; use reth_primitives::Account; use reth_provider::providers::StaticFileWriter; diff --git a/crates/stages/stages/src/stages/hashing_storage.rs b/crates/stages/stages/src/stages/hashing_storage.rs index dcabbe83ee64..3208113140ee 100644 --- a/crates/stages/stages/src/stages/hashing_storage.rs +++ b/crates/stages/stages/src/stages/hashing_storage.rs @@ -1,4 +1,4 @@ -use alloy_primitives::{bytes::BufMut, keccak256, B256}; +use alloy_primitives::{bytes::BufMut, B256}; use itertools::Itertools; use reth_config::config::{EtlConfig, HashingConfig}; use reth_db::tables; @@ -10,12 +10,16 @@ use reth_db_api::{ }; use reth_etl::Collector; use reth_primitives::StorageEntry; -use reth_provider::{DBProvider, HashingWriter, StatsReader, StorageReader}; +use reth_provider::{ + DBProvider, HashingWriter, StateCommitmentProvider, StatsReader, StorageReader, +}; use reth_stages_api::{ EntitiesCheckpoint, ExecInput, ExecOutput, Stage, StageCheckpoint, StageError, StageId, StorageHashingCheckpoint, UnwindInput, UnwindOutput, }; use reth_storage_errors::provider::ProviderResult; +use reth_trie::KeyHasher; +use reth_trie_db::StateCommitment; use std::{ fmt::Debug, sync::mpsc::{self, Receiver}, @@ -64,7 +68,11 @@ impl Default for StorageHashingStage { impl Stage for StorageHashingStage where - Provider: DBProvider + StorageReader + HashingWriter + StatsReader, + Provider: DBProvider + + StorageReader + + HashingWriter + + StatsReader + + StateCommitmentProvider, { /// Return the id of the stage fn id(&self) -> StageId { @@ -103,8 +111,13 @@ where rayon::spawn(move || { for (address, slot) in chunk { let mut addr_key = Vec::with_capacity(64); - addr_key.put_slice(keccak256(address).as_slice()); - addr_key.put_slice(keccak256(slot.key).as_slice()); + addr_key.put_slice( + <::KeyHasher as KeyHasher>::hash_key( + address, + ) + .as_slice(), + ); + addr_key.put_slice(<::KeyHasher as KeyHasher>::hash_key(slot.key).as_slice()); let _ = tx.send((addr_key, CompactU256::from(slot.value))); } }); @@ -212,7 +225,7 @@ mod tests { stage_test_suite_ext, ExecuteStageTestRunner, StageTestRunner, TestRunnerError, TestStageDB, UnwindStageTestRunner, }; - use alloy_primitives::{Address, U256}; + use alloy_primitives::{keccak256, Address, U256}; use assert_matches::assert_matches; use rand::Rng; use reth_db_api::{ diff --git a/crates/storage/provider/src/providers/bundle_state_provider.rs b/crates/storage/provider/src/providers/bundle_state_provider.rs index 8db8f3753378..1b1bc12e8cd7 100644 --- a/crates/storage/provider/src/providers/bundle_state_provider.rs +++ b/crates/storage/provider/src/providers/bundle_state_provider.rs @@ -7,7 +7,8 @@ use alloy_primitives::{ }; use reth_primitives::{Account, Bytecode}; use reth_storage_api::{ - HashedPostStateProvider, HashedStorageProvider, StateProofProvider, StorageRootProvider, + HashedPostStateProvider, HashedStorageProvider, KeyHasherProvider, StateProofProvider, + StorageRootProvider, }; use reth_storage_errors::provider::ProviderResult; use reth_trie::{ @@ -188,6 +189,14 @@ impl HashedStorageProvider } } +impl KeyHasherProvider + for BundleStateProvider +{ + fn hash_key(&self, bytes: &[u8]) -> B256 { + self.state_provider.hash_key(bytes) + } +} + impl StateProvider for BundleStateProvider { fn storage( &self, diff --git a/crates/storage/provider/src/providers/database/provider.rs b/crates/storage/provider/src/providers/database/provider.rs index cdf07361389b..9d84a2dd5ddd 100644 --- a/crates/storage/provider/src/providers/database/provider.rs +++ b/crates/storage/provider/src/providers/database/provider.rs @@ -14,12 +14,12 @@ use crate::{ BlockReader, BlockWriter, BundleStateInit, ChainStateBlockReader, ChainStateBlockWriter, DBProvider, EvmEnvProvider, HashingWriter, HeaderProvider, HeaderSyncGap, HeaderSyncGapProvider, HistoricalStateProvider, HistoricalStateProviderRef, HistoryWriter, - LatestStateProvider, LatestStateProviderRef, OriginalValuesKnown, ProviderError, - PruneCheckpointReader, PruneCheckpointWriter, RevertsInit, StageCheckpointReader, - StateChangeWriter, StateCommitmentProvider, StateProviderBox, StateReader, StateWriter, - StaticFileProviderFactory, StatsReader, StorageLocation, StorageReader, StorageTrieWriter, - TransactionVariant, TransactionsProvider, TransactionsProviderExt, TrieWriter, - WithdrawalsProvider, + KeyHasherProvider, LatestStateProvider, LatestStateProviderRef, OriginalValuesKnown, + ProviderError, PruneCheckpointReader, PruneCheckpointWriter, RevertsInit, + StageCheckpointReader, StateChangeWriter, StateCommitmentProvider, StateProviderBox, + StateReader, StateWriter, StaticFileProviderFactory, StatsReader, StorageLocation, + StorageReader, StorageTrieWriter, TransactionVariant, TransactionsProvider, + TransactionsProviderExt, TrieWriter, WithdrawalsProvider, }; use alloy_consensus::Header; use alloy_eips::{ @@ -61,9 +61,9 @@ use reth_storage_errors::provider::{ProviderResult, RootMismatch}; use reth_trie::{ prefix_set::{PrefixSet, PrefixSetMut, TriePrefixSets}, updates::{StorageTrieUpdates, TrieUpdates}, - HashedPostStateSorted, Nibbles, StateRoot, StoredNibbles, + HashedPostStateSorted, KeyHasher, 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}, @@ -379,6 +379,12 @@ impl StateCommitmentProvider for DatabaseProvi type StateCommitment = N::StateCommitment; } +impl KeyHasherProvider for DatabaseProvider { + fn hash_key(&self, bytes: &[u8]) -> B256 { + <::KeyHasher as KeyHasher>::hash_key(bytes) + } +} + impl DatabaseProvider { // TODO: uncomment below, once `reth debug_cmd` has been feature gated with dev. // #[cfg(any(test, feature = "test-utils"))] @@ -2348,7 +2354,7 @@ impl HashingWriter for DatabaseProvi // changes are applied in the correct order. let hashed_accounts = changesets .into_iter() - .map(|(_, e)| (keccak256(e.address), e.info)) + .map(|(_, e)| (self.hash_key(e.address.as_ref()), e.info)) .collect::>() .into_iter() .rev() @@ -2384,8 +2390,10 @@ impl HashingWriter for DatabaseProvi changesets: impl IntoIterator)>, ) -> ProviderResult>> { let mut hashed_accounts_cursor = self.tx.cursor_write::()?; - let hashed_accounts = - changesets.into_iter().map(|(ad, ac)| (keccak256(ad), ac)).collect::>(); + let hashed_accounts = changesets + .into_iter() + .map(|(ad, ac)| (self.hash_key(ad.as_ref()), ac)) + .collect::>(); for (hashed_address, account) in &hashed_accounts { if let Some(account) = account { hashed_accounts_cursor.upsert(*hashed_address, *account)?; @@ -2404,7 +2412,11 @@ impl HashingWriter for DatabaseProvi let mut hashed_storages = changesets .into_iter() .map(|(BlockNumberAddress((_, address)), storage_entry)| { - (keccak256(address), keccak256(storage_entry.key), storage_entry.value) + ( + self.hash_key(address.as_ref()), + self.hash_key(storage_entry.key.as_ref()), + storage_entry.value, + ) }) .collect::>(); hashed_storages.sort_by_key(|(ha, hk, _)| (*ha, *hk)); @@ -2451,10 +2463,10 @@ impl HashingWriter for DatabaseProvi let hashed_storages = storages.into_iter().fold(BTreeMap::new(), |mut map, (address, storage)| { let storage = storage.into_iter().fold(BTreeMap::new(), |mut map, entry| { - map.insert(keccak256(entry.key), entry.value); + map.insert(self.hash_key(entry.key.as_ref()), entry.value); map }); - map.insert(keccak256(address), storage); + map.insert(self.hash_key(address.as_ref()), storage); map }); diff --git a/crates/storage/provider/src/providers/state/historical.rs b/crates/storage/provider/src/providers/state/historical.rs index a06246176f01..659ec330d1ad 100644 --- a/crates/storage/provider/src/providers/state/historical.rs +++ b/crates/storage/provider/src/providers/state/historical.rs @@ -16,15 +16,16 @@ use reth_db_api::{ }; use reth_primitives::{Account, Bytecode}; use reth_storage_api::{ - BlockNumReader, DBProvider, HashedStorageProvider, StateCommitmentProvider, StateProofProvider, - StorageRootProvider, + BlockNumReader, DBProvider, HashedStorageProvider, KeyHasherProvider, StateCommitmentProvider, + StateProofProvider, StorageRootProvider, }; use reth_storage_errors::provider::ProviderResult; use reth_trie::{ proof::{Proof, StorageProof}, updates::TrieUpdates, witness::TrieWitness, - AccountProof, HashedPostState, HashedStorage, MultiProof, StateRoot, StorageRoot, TrieInput, + AccountProof, HashedPostState, HashedStorage, KeyHasher, MultiProof, StateRoot, StorageRoot, + TrieInput, }; use reth_trie_db::{ DatabaseHashedPostState, DatabaseHashedStorage, DatabaseProof, DatabaseStateRoot, @@ -394,7 +395,7 @@ impl HashedPostStateProvider } } -impl HashedStorageProvider +impl HashedStorageProvider for HistoricalStateProviderRef<'_, Provider> { fn hashed_storage(&self, account: &revm::db::BundleAccount) -> HashedStorage { @@ -404,6 +405,14 @@ impl HashedStorageProvider } } +impl KeyHasherProvider + for HistoricalStateProviderRef<'_, Provider> +{ + fn hash_key(&self, bytes: &[u8]) -> B256 { + <::KeyHasher as KeyHasher>::hash_key(bytes) + } +} + impl StateProvider for HistoricalStateProviderRef<'_, Provider> { diff --git a/crates/storage/provider/src/providers/state/latest.rs b/crates/storage/provider/src/providers/state/latest.rs index e920ac5a7c73..4bc0318a6123 100644 --- a/crates/storage/provider/src/providers/state/latest.rs +++ b/crates/storage/provider/src/providers/state/latest.rs @@ -10,15 +10,16 @@ use reth_db::tables; use reth_db_api::{cursor::DbDupCursorRO, transaction::DbTx}; use reth_primitives::{Account, Bytecode}; use reth_storage_api::{ - DBProvider, HashedStorageProvider, StateCommitmentProvider, StateProofProvider, - StorageRootProvider, + DBProvider, HashedStorageProvider, KeyHasherProvider, StateCommitmentProvider, + StateProofProvider, StorageRootProvider, }; use reth_storage_errors::provider::{ProviderError, ProviderResult}; use reth_trie::{ proof::{Proof, StorageProof}, updates::TrieUpdates, witness::TrieWitness, - AccountProof, HashedPostState, HashedStorage, MultiProof, StateRoot, StorageRoot, TrieInput, + AccountProof, HashedPostState, HashedStorage, KeyHasher, MultiProof, StateRoot, StorageRoot, + TrieInput, }; use reth_trie_db::{ DatabaseProof, DatabaseStateRoot, DatabaseStorageProof, DatabaseStorageRoot, @@ -167,6 +168,12 @@ impl HashedStorageProvider } } +impl KeyHasherProvider for LatestStateProviderRef<'_, Provider> { + fn hash_key(&self, bytes: &[u8]) -> B256 { + <::KeyHasher as KeyHasher>::hash_key(bytes) + } +} + impl StateProvider for LatestStateProviderRef<'_, Provider> { diff --git a/crates/storage/provider/src/providers/state/macros.rs b/crates/storage/provider/src/providers/state/macros.rs index d83dc3b292da..82ff634b1d9d 100644 --- a/crates/storage/provider/src/providers/state/macros.rs +++ b/crates/storage/provider/src/providers/state/macros.rs @@ -62,6 +62,9 @@ macro_rules! delegate_provider_impls { HashedStorageProvider $(where [$($generics)*])? { fn hashed_storage(&self, bundle_state: &revm::db::BundleAccount) -> reth_trie::HashedStorage; } + KeyHasherProvider $(where [$($generics)*])? { + fn hash_key(&self, bytes: &[u8]) -> alloy_primitives::B256; + } ); } } diff --git a/crates/storage/provider/src/test_utils/mock.rs b/crates/storage/provider/src/test_utils/mock.rs index f4412387e2cf..a52da1338699 100644 --- a/crates/storage/provider/src/test_utils/mock.rs +++ b/crates/storage/provider/src/test_utils/mock.rs @@ -28,8 +28,8 @@ use reth_primitives::{ }; use reth_stages_types::{StageCheckpoint, StageId}; use reth_storage_api::{ - DatabaseProviderFactory, HashedPostStateProvider, HashedStorageProvider, StageCheckpointReader, - StateCommitmentProvider, StateProofProvider, StorageRootProvider, + DatabaseProviderFactory, HashedPostStateProvider, HashedStorageProvider, KeyHasherProvider, + StageCheckpointReader, StateCommitmentProvider, StateProofProvider, StorageRootProvider, }; use reth_storage_errors::provider::{ConsistentViewError, ProviderError, ProviderResult}; use reth_trie::{ @@ -683,6 +683,12 @@ impl HashedStorageProvider for MockEthProvider { } } +impl KeyHasherProvider for MockEthProvider { + fn hash_key(&self, _bytes: &[u8]) -> B256 { + B256::default() + } +} + impl StateProvider for MockEthProvider { fn storage( &self, diff --git a/crates/storage/provider/src/test_utils/noop.rs b/crates/storage/provider/src/test_utils/noop.rs index 2269b1cb8fae..4ad60b864146 100644 --- a/crates/storage/provider/src/test_utils/noop.rs +++ b/crates/storage/provider/src/test_utils/noop.rs @@ -28,7 +28,8 @@ use reth_primitives::{ use reth_prune_types::{PruneCheckpoint, PruneSegment}; use reth_stages_types::{StageCheckpoint, StageId}; use reth_storage_api::{ - HashedPostStateProvider, HashedStorageProvider, StateProofProvider, StorageRootProvider, + HashedPostStateProvider, HashedStorageProvider, KeyHasherProvider, StateProofProvider, + StorageRootProvider, }; use reth_storage_errors::provider::ProviderResult; use reth_trie::{ @@ -413,6 +414,12 @@ impl HashedStorageProvider for NoopProvider { } } +impl KeyHasherProvider for NoopProvider { + fn hash_key(&self, _bytes: &[u8]) -> B256 { + B256::default() + } +} + impl StateProvider for NoopProvider { fn storage( &self, diff --git a/crates/storage/storage-api/src/state.rs b/crates/storage/storage-api/src/state.rs index 59b47221588e..859e73eb61e9 100644 --- a/crates/storage/storage-api/src/state.rs +++ b/crates/storage/storage-api/src/state.rs @@ -25,6 +25,7 @@ pub trait StateProvider: + StateProofProvider + HashedPostStateProvider + HashedStorageProvider + + KeyHasherProvider + Send + Sync { @@ -99,6 +100,13 @@ pub trait HashedPostStateProvider: Send + Sync { fn hashed_post_state(&self, bundle_state: &BundleState) -> HashedPostState; } +/// Trait that provides a method to hash bytes to produce a [`B256`] hash. +#[auto_impl(&, Arc, Box)] +pub trait KeyHasherProvider: Send + Sync { + /// Hashes the provided bytes into a 256-bit hash. + fn hash_key(&self, bytes: &[u8]) -> B256; +} + /// Trait implemented for database providers that can be converted into a historical state provider. pub trait TryIntoHistoricalStateProvider { /// Returns a historical [`StateProvider`] indexed by the given historic block number. From 8cfb70e47d66dc4c71bb576a7dcc5db4ff628192 Mon Sep 17 00:00:00 2001 From: frisitano Date: Mon, 2 Dec 2024 12:13:54 +0800 Subject: [PATCH 09/15] fix: add merge files --- Cargo.lock | 5 +---- crates/engine/tree/src/tree/root.rs | 8 +++++++- crates/rpc/rpc-eth-api/Cargo.toml | 1 - crates/rpc/rpc/Cargo.toml | 1 - crates/storage/provider/src/test_utils/noop.rs | 4 +++- crates/trie/db/src/prefix_set.rs | 3 +-- 6 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 62a5dce28980..b69aef5ab400 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7524,7 +7524,6 @@ dependencies = [ "reth-revm", "reth-scroll-revm", "reth-transaction-pool", - "reth-trie", "tracing", ] @@ -8451,7 +8450,6 @@ dependencies = [ "reth-rpc-types-compat", "reth-scroll-revm", "reth-transaction-pool", - "reth-trie", "sha2 0.10.8", "thiserror 1.0.69", "tracing", @@ -8864,7 +8862,6 @@ dependencies = [ "reth-tasks", "reth-testing-utils", "reth-transaction-pool", - "reth-trie", "revm-inspectors", "revm-primitives", "serde", @@ -9046,7 +9043,6 @@ dependencies = [ "reth-scroll-storage", "reth-tasks", "reth-transaction-pool", - "reth-trie", "revm-inspectors", "revm-primitives", "tokio", @@ -9350,6 +9346,7 @@ dependencies = [ "reth-primitives", "reth-primitives-traits", "reth-prune-types", + "reth-scroll-revm", "reth-stages-types", "reth-storage-errors", "reth-trie", diff --git a/crates/engine/tree/src/tree/root.rs b/crates/engine/tree/src/tree/root.rs index c760f479e711..05691a40ae53 100644 --- a/crates/engine/tree/src/tree/root.rs +++ b/crates/engine/tree/src/tree/root.rs @@ -3,6 +3,7 @@ use alloy_primitives::map::{HashMap, HashSet}; use reth_provider::{ providers::ConsistentDbView, BlockReader, DBProvider, DatabaseProviderFactory, + StateCommitmentProvider, }; use reth_trie::{ proof::Proof, updates::TrieUpdates, HashedPostState, HashedStorage, MultiProof, Nibbles, @@ -176,7 +177,12 @@ pub(crate) struct StateRootTask { #[allow(dead_code)] impl StateRootTask where - Factory: DatabaseProviderFactory + Clone + Send + Sync + 'static, + Factory: DatabaseProviderFactory + + StateCommitmentProvider + + Clone + + Send + + Sync + + 'static, { /// Creates a new state root task with the unified message channel pub(crate) fn new( diff --git a/crates/rpc/rpc-eth-api/Cargo.toml b/crates/rpc/rpc-eth-api/Cargo.toml index a72dc2fdfaf9..46a6d5136e95 100644 --- a/crates/rpc/rpc-eth-api/Cargo.toml +++ b/crates/rpc/rpc-eth-api/Cargo.toml @@ -65,7 +65,6 @@ tracing.workspace = true js-tracer = ["revm-inspectors/js-tracer", "reth-rpc-eth-types/js-tracer"] client = ["jsonrpsee/client", "jsonrpsee/async-client"] scroll = [ - "reth-trie/scroll", "reth-provider/scroll", "reth-execution-types/scroll", "reth-revm/scroll", diff --git a/crates/rpc/rpc/Cargo.toml b/crates/rpc/rpc/Cargo.toml index aadf682a1d5d..92ee311194e5 100644 --- a/crates/rpc/rpc/Cargo.toml +++ b/crates/rpc/rpc/Cargo.toml @@ -106,7 +106,6 @@ jsonrpsee = { workspace = true, features = ["client"] } [features] js-tracer = ["revm-inspectors/js-tracer", "reth-rpc-eth-types/js-tracer"] scroll = [ - "reth-trie/scroll", "reth-evm/scroll", "reth-rpc-eth-types/scroll", "reth-primitives/scroll", diff --git a/crates/storage/provider/src/test_utils/noop.rs b/crates/storage/provider/src/test_utils/noop.rs index 750fea7b33a8..cec243f71b3c 100644 --- a/crates/storage/provider/src/test_utils/noop.rs +++ b/crates/storage/provider/src/test_utils/noop.rs @@ -27,7 +27,9 @@ use reth_primitives::{ }; use reth_prune_types::{PruneCheckpoint, PruneSegment}; use reth_stages_types::{StageCheckpoint, StageId}; -use reth_storage_api::{NodePrimitivesProvider, StateProofProvider, StorageRootProvider}; +use reth_storage_api::{ + HashedPostStateProvider, NodePrimitivesProvider, StateProofProvider, StorageRootProvider, +}; use reth_storage_errors::provider::ProviderResult; use reth_trie::{ updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, TrieInput, diff --git a/crates/trie/db/src/prefix_set.rs b/crates/trie/db/src/prefix_set.rs index b8cb380ff0ee..95ff6d91f374 100644 --- a/crates/trie/db/src/prefix_set.rs +++ b/crates/trie/db/src/prefix_set.rs @@ -10,9 +10,8 @@ use reth_db_api::{ use reth_primitives::StorageEntry; use reth_trie::{ prefix_set::{PrefixSetMut, TriePrefixSets}, - KeyHasher, + KeyHasher, Nibbles, }; -use reth_trie_common::Nibbles; use std::{ collections::{HashMap, HashSet}, marker::PhantomData, From 534a90754febc885fe6a03bc27e0ff388e86e869 Mon Sep 17 00:00:00 2001 From: frisitano Date: Mon, 2 Dec 2024 12:58:56 +0800 Subject: [PATCH 10/15] fix lint --- crates/primitives-traits/src/account.rs | 2 +- crates/storage/provider/src/writer/mod.rs | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/crates/primitives-traits/src/account.rs b/crates/primitives-traits/src/account.rs index 03790dd982a8..27c03dc96b6e 100644 --- a/crates/primitives-traits/src/account.rs +++ b/crates/primitives-traits/src/account.rs @@ -58,7 +58,7 @@ impl Account { pub fn is_empty(&self) -> bool { self.nonce == 0 && self.balance.is_zero() && - self.bytecode_hash.map_or(true, |hash| hash == KECCAK_EMPTY) + self.bytecode_hash.is_none_or(|hash| hash == KECCAK_EMPTY) } /// Returns an account bytecode's hash. diff --git a/crates/storage/provider/src/writer/mod.rs b/crates/storage/provider/src/writer/mod.rs index dacb36ad77b2..ad54e9b2bdf8 100644 --- a/crates/storage/provider/src/writer/mod.rs +++ b/crates/storage/provider/src/writer/mod.rs @@ -1135,12 +1135,13 @@ mod tests { let mut state = State::builder().with_bundle_update().build(); let assert_state_root = |state: &State, expected: &PreState, msg| { + #[cfg(feature = "scroll")] + let bundle_state = &(state.bundle_state.clone(), &()).into(); + #[cfg(not(feature = "scroll"))] + let bundle_state = &state.bundle_state; assert_eq!( - StateRoot::overlay_root( - tx, - provider_factory.hashed_post_state(&state.bundle_state) - ) - .unwrap(), + StateRoot::overlay_root(tx, provider_factory.hashed_post_state(bundle_state)) + .unwrap(), state_root(expected.clone().into_iter().map(|(address, (account, storage))| ( address, (account, storage.into_iter()) From d2c9d32d4b40fa0683c8f843dfefec72ce79aaeb Mon Sep 17 00:00:00 2001 From: frisitano Date: Mon, 2 Dec 2024 13:14:14 +0800 Subject: [PATCH 11/15] fix lint --- crates/net/eth-wire/src/capability.rs | 3 +-- crates/revm/src/batch.rs | 2 +- crates/tracing/src/formatter.rs | 2 +- crates/transaction-pool/src/maintain.rs | 3 +-- crates/transaction-pool/src/pool/best.rs | 3 +-- crates/trie/trie/src/trie_cursor/subnode.rs | 6 ++---- 6 files changed, 7 insertions(+), 12 deletions(-) diff --git a/crates/net/eth-wire/src/capability.rs b/crates/net/eth-wire/src/capability.rs index 625971e0e7bd..06790c52c4a3 100644 --- a/crates/net/eth-wire/src/capability.rs +++ b/crates/net/eth-wire/src/capability.rs @@ -318,8 +318,7 @@ pub fn shared_capability_offsets( // If multiple versions are shared of the same (equal name) capability, the numerically // highest wins, others are ignored if shared_capabilities - .get(&peer_capability.name) - .map_or(true, |v| peer_capability.version > v.version) + .get(&peer_capability.name).is_none_or(|v| peer_capability.version > v.version) { shared_capabilities.insert( peer_capability.name.clone(), diff --git a/crates/revm/src/batch.rs b/crates/revm/src/batch.rs index 15ba049250f5..f55c3aeee259 100644 --- a/crates/revm/src/batch.rs +++ b/crates/revm/src/batch.rs @@ -102,7 +102,7 @@ impl BlockBatchRecord { /// Returns the [`BundleRetention`] for the given block based on the configured prune modes. pub fn bundle_retention(&self, block_number: BlockNumber) -> BundleRetention { - if self.tip.map_or(true, |tip| { + if self.tip.is_none_or(|tip| { !self .prune_modes .account_history diff --git a/crates/tracing/src/formatter.rs b/crates/tracing/src/formatter.rs index 1322377f1c9f..202a92136d26 100644 --- a/crates/tracing/src/formatter.rs +++ b/crates/tracing/src/formatter.rs @@ -54,7 +54,7 @@ impl LogFormat { .unwrap_or_else(|_| // If `RUST_LOG_TARGET` is not set, show target in logs only if the max enabled // level is higher than INFO (DEBUG, TRACE) - filter.max_level_hint().map_or(true, |max_level| max_level > tracing::Level::INFO)); + filter.max_level_hint().is_none_or(|max_level| max_level > tracing::Level::INFO)); match self { Self::Json => { diff --git a/crates/transaction-pool/src/maintain.rs b/crates/transaction-pool/src/maintain.rs index 02f218d4b098..7826a0e3406e 100644 --- a/crates/transaction-pool/src/maintain.rs +++ b/crates/transaction-pool/src/maintain.rs @@ -460,8 +460,7 @@ impl FinalizedBlockTracker { fn update(&mut self, finalized_block: Option) -> Option { let finalized = finalized_block?; self.last_finalized_block - .replace(finalized) - .map_or(true, |last| last < finalized) + .replace(finalized).is_none_or(|last| last < finalized) .then_some(finalized) } } diff --git a/crates/transaction-pool/src/pool/best.rs b/crates/transaction-pool/src/pool/best.rs index a4c91aae7268..284487e14a11 100644 --- a/crates/transaction-pool/src/pool/best.rs +++ b/crates/transaction-pool/src/pool/best.rs @@ -56,8 +56,7 @@ impl Iterator for BestTransactionsWithFees { // the transaction if best.transaction.max_fee_per_gas() >= self.base_fee as u128 && best.transaction - .max_fee_per_blob_gas() - .map_or(true, |fee| fee >= self.base_fee_per_blob_gas as u128) + .max_fee_per_blob_gas().is_none_or(|fee| fee >= self.base_fee_per_blob_gas as u128) { return Some(best); } diff --git a/crates/trie/trie/src/trie_cursor/subnode.rs b/crates/trie/trie/src/trie_cursor/subnode.rs index c928028eb157..c51b713d59a6 100644 --- a/crates/trie/trie/src/trie_cursor/subnode.rs +++ b/crates/trie/trie/src/trie_cursor/subnode.rs @@ -75,16 +75,14 @@ impl CursorSubNode { #[inline] pub fn state_flag(&self) -> bool { self.node - .as_ref() - .map_or(true, |node| self.nibble < 0 || node.state_mask.is_bit_set(self.nibble as u8)) + .as_ref().is_none_or(|node| self.nibble < 0 || node.state_mask.is_bit_set(self.nibble as u8)) } /// Returns `true` if the tree flag is set for the current nibble. #[inline] pub fn tree_flag(&self) -> bool { self.node - .as_ref() - .map_or(true, |node| self.nibble < 0 || node.tree_mask.is_bit_set(self.nibble as u8)) + .as_ref().is_none_or(|node| self.nibble < 0 || node.tree_mask.is_bit_set(self.nibble as u8)) } /// Returns `true` if the current nibble has a root hash. From 963eb212d619edd961b5e7e9e9279fa7271f5d87 Mon Sep 17 00:00:00 2001 From: frisitano Date: Mon, 2 Dec 2024 13:23:01 +0800 Subject: [PATCH 12/15] fmt --- crates/net/eth-wire/src/capability.rs | 3 ++- crates/transaction-pool/src/maintain.rs | 3 ++- crates/transaction-pool/src/pool/best.rs | 3 ++- crates/trie/trie/src/trie_cursor/subnode.rs | 6 ++++-- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/crates/net/eth-wire/src/capability.rs b/crates/net/eth-wire/src/capability.rs index 06790c52c4a3..8d969eac889b 100644 --- a/crates/net/eth-wire/src/capability.rs +++ b/crates/net/eth-wire/src/capability.rs @@ -318,7 +318,8 @@ pub fn shared_capability_offsets( // If multiple versions are shared of the same (equal name) capability, the numerically // highest wins, others are ignored if shared_capabilities - .get(&peer_capability.name).is_none_or(|v| peer_capability.version > v.version) + .get(&peer_capability.name) + .is_none_or(|v| peer_capability.version > v.version) { shared_capabilities.insert( peer_capability.name.clone(), diff --git a/crates/transaction-pool/src/maintain.rs b/crates/transaction-pool/src/maintain.rs index 7826a0e3406e..6763deb02e60 100644 --- a/crates/transaction-pool/src/maintain.rs +++ b/crates/transaction-pool/src/maintain.rs @@ -460,7 +460,8 @@ impl FinalizedBlockTracker { fn update(&mut self, finalized_block: Option) -> Option { let finalized = finalized_block?; self.last_finalized_block - .replace(finalized).is_none_or(|last| last < finalized) + .replace(finalized) + .is_none_or(|last| last < finalized) .then_some(finalized) } } diff --git a/crates/transaction-pool/src/pool/best.rs b/crates/transaction-pool/src/pool/best.rs index 284487e14a11..ed94bc676236 100644 --- a/crates/transaction-pool/src/pool/best.rs +++ b/crates/transaction-pool/src/pool/best.rs @@ -56,7 +56,8 @@ impl Iterator for BestTransactionsWithFees { // the transaction if best.transaction.max_fee_per_gas() >= self.base_fee as u128 && best.transaction - .max_fee_per_blob_gas().is_none_or(|fee| fee >= self.base_fee_per_blob_gas as u128) + .max_fee_per_blob_gas() + .is_none_or(|fee| fee >= self.base_fee_per_blob_gas as u128) { return Some(best); } diff --git a/crates/trie/trie/src/trie_cursor/subnode.rs b/crates/trie/trie/src/trie_cursor/subnode.rs index c51b713d59a6..457c1ba4685b 100644 --- a/crates/trie/trie/src/trie_cursor/subnode.rs +++ b/crates/trie/trie/src/trie_cursor/subnode.rs @@ -75,14 +75,16 @@ impl CursorSubNode { #[inline] pub fn state_flag(&self) -> bool { self.node - .as_ref().is_none_or(|node| self.nibble < 0 || node.state_mask.is_bit_set(self.nibble as u8)) + .as_ref() + .is_none_or(|node| self.nibble < 0 || node.state_mask.is_bit_set(self.nibble as u8)) } /// Returns `true` if the tree flag is set for the current nibble. #[inline] pub fn tree_flag(&self) -> bool { self.node - .as_ref().is_none_or(|node| self.nibble < 0 || node.tree_mask.is_bit_set(self.nibble as u8)) + .as_ref() + .is_none_or(|node| self.nibble < 0 || node.tree_mask.is_bit_set(self.nibble as u8)) } /// Returns `true` if the current nibble has a root hash. From 26621042b39398eb22a81e8b7dd1d69f4428393c Mon Sep 17 00:00:00 2001 From: frisitano Date: Mon, 2 Dec 2024 14:20:56 +0800 Subject: [PATCH 13/15] add KeyHasher generic to DatabaseHashedStorage::from_reverts trait --- .../provider/src/providers/state/historical.rs | 8 +++++++- crates/trie/db/src/storage.rs | 17 +++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/crates/storage/provider/src/providers/state/historical.rs b/crates/storage/provider/src/providers/state/historical.rs index bbbf4b949ed0..cba511aad03b 100644 --- a/crates/storage/provider/src/providers/state/historical.rs +++ b/crates/storage/provider/src/providers/state/historical.rs @@ -156,7 +156,13 @@ impl<'b, Provider: DBProvider + BlockNumReader + StateCommitmentProvider> ); } - Ok(HashedStorage::from_reverts(self.tx(), address, self.block_number)?) + Ok( + HashedStorage::from_reverts::<::KeyHasher>( + self.tx(), + address, + self.block_number, + )?, + ) } fn history_info( diff --git a/crates/trie/db/src/storage.rs b/crates/trie/db/src/storage.rs index 6a3bbe1b9651..c2aa04ee98ad 100644 --- a/crates/trie/db/src/storage.rs +++ b/crates/trie/db/src/storage.rs @@ -6,7 +6,8 @@ use reth_db::{cursor::DbCursorRO, models::BlockNumberAddress, tables, DatabaseEr use reth_db_api::transaction::DbTx; use reth_execution_errors::StorageRootError; use reth_trie::{ - hashed_cursor::HashedPostStateCursorFactory, HashedPostState, HashedStorage, StorageRoot, + hashed_cursor::HashedPostStateCursorFactory, HashedPostState, HashedStorage, KeyHasher, + StorageRoot, }; #[cfg(feature = "metrics")] @@ -32,7 +33,11 @@ pub trait DatabaseStorageRoot<'a, TX> { pub trait DatabaseHashedStorage: Sized { /// Initializes [`HashedStorage`] from reverts. Iterates over storage reverts from the specified /// block up to the current tip and aggregates them into hashed storage in reverse. - fn from_reverts(tx: &TX, address: Address, from: BlockNumber) -> Result; + fn from_reverts( + tx: &TX, + address: Address, + from: BlockNumber, + ) -> Result; } impl<'a, TX: DbTx> DatabaseStorageRoot<'a, TX> @@ -79,13 +84,17 @@ impl<'a, TX: DbTx> DatabaseStorageRoot<'a, TX> } impl DatabaseHashedStorage for HashedStorage { - fn from_reverts(tx: &TX, address: Address, from: BlockNumber) -> Result { + fn from_reverts( + tx: &TX, + address: Address, + from: BlockNumber, + ) -> Result { let mut storage = Self::new(false); let mut storage_changesets_cursor = tx.cursor_read::()?; for entry in storage_changesets_cursor.walk_range(BlockNumberAddress((from, address))..)? { let (BlockNumberAddress((_, storage_address)), storage_change) = entry?; if storage_address == address { - let hashed_slot = keccak256(storage_change.key); + let hashed_slot = KH::hash_key(storage_change.key); if let hash_map::Entry::Vacant(entry) = storage.storage.entry(hashed_slot) { entry.insert(storage_change.value); } From 893de64c3fd7f6f851d587d44ad48bf13293bcda Mon Sep 17 00:00:00 2001 From: frisitano Date: Mon, 2 Dec 2024 14:58:41 +0800 Subject: [PATCH 14/15] add merge files --- Cargo.lock | 8 ++++---- crates/chain-state/src/memory_overlay.rs | 2 +- crates/rpc/rpc-eth-types/src/simulate.rs | 1 - 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b69aef5ab400..8180e83e4069 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4606,9 +4606,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.165" +version = "0.2.167" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb4d3d38eab6c5239a362fa8bae48c03baf980a6e7079f063942d563ef3533e" +checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" [[package]] name = "libloading" @@ -4617,7 +4617,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -11354,7 +11354,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3637e734239e12ab152cd269302500bd063f37624ee210cd04b4936ed671f3b1" dependencies = [ "cc", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] diff --git a/crates/chain-state/src/memory_overlay.rs b/crates/chain-state/src/memory_overlay.rs index 4b5aea8ad8f3..b39c4e57b97d 100644 --- a/crates/chain-state/src/memory_overlay.rs +++ b/crates/chain-state/src/memory_overlay.rs @@ -179,7 +179,7 @@ macro_rules! impl_state_provider { ) -> ProviderResult { let state = &self.trie_state().state; let mut hashed_storage = - state.storages.get(&keccak256(address)).cloned().unwrap_or_default(); + state.storages.get(&self.hash_key(address.as_ref())).cloned().unwrap_or_default(); hashed_storage.extend(&storage); self.historical.storage_multiproof(address, slots, hashed_storage) } diff --git a/crates/rpc/rpc-eth-types/src/simulate.rs b/crates/rpc/rpc-eth-types/src/simulate.rs index f37b38d065f3..323253216e11 100644 --- a/crates/rpc/rpc-eth-types/src/simulate.rs +++ b/crates/rpc/rpc-eth-types/src/simulate.rs @@ -14,7 +14,6 @@ use reth_primitives::{ }; use reth_rpc_server_types::result::rpc_err; use reth_rpc_types_compat::{block::from_block, TransactionCompat}; -use reth_storage_api::{KeyHasherProvider, StateRootProvider}; use revm::Database; use revm_primitives::{Address, BlockEnv, Bytes, ExecutionResult, TxKind, B256, U256}; From e433cdc888da30a1c3521e4be6454249afefc17f Mon Sep 17 00:00:00 2001 From: frisitano Date: Wed, 4 Dec 2024 17:44:00 +0800 Subject: [PATCH 15/15] lint: minimise diff with upstream --- crates/rpc/rpc-eth-types/src/simulate.rs | 3 +-- crates/stages/stages/src/stages/execution.rs | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/crates/rpc/rpc-eth-types/src/simulate.rs b/crates/rpc/rpc-eth-types/src/simulate.rs index 323253216e11..a10b4afff9d7 100644 --- a/crates/rpc/rpc-eth-types/src/simulate.rs +++ b/crates/rpc/rpc-eth-types/src/simulate.rs @@ -233,8 +233,7 @@ pub fn build_block>( // let storage = hashed_state // .storages // .entry(hashed_address) - // .or_insert_with(|| - // HashedStorage::new(account.account_state.is_storage_cleared())); + // .or_insert_with(|| HashedStorage::new(account.account_state.is_storage_cleared())); // for (slot, value) in &account.storage { // let slot = B256::from(*slot); diff --git a/crates/stages/stages/src/stages/execution.rs b/crates/stages/stages/src/stages/execution.rs index 44a451e49b03..64f6d5accba1 100644 --- a/crates/stages/stages/src/stages/execution.rs +++ b/crates/stages/stages/src/stages/execution.rs @@ -262,8 +262,8 @@ where + StaticFileProviderFactory + StatsReader + BlockHashReader - + StateCommitmentProvider - + StateWriter, + + StateWriter + + StateCommitmentProvider, { /// Return the id of the stage fn id(&self) -> StageId {