From d3db6416c433e51c5f2b61c9c1c74e6df6391580 Mon Sep 17 00:00:00 2001 From: frisitano Date: Fri, 18 Oct 2024 20:09:29 +0800 Subject: [PATCH] feat: introduce HashedPostStateProvider --- Cargo.lock | 4 --- .../src/commands/debug_cmd/build_block.rs | 5 +-- .../commands/debug_cmd/in_memory_merkle.rs | 8 ++--- crates/blockchain-tree/src/blockchain_tree.rs | 14 +++++--- crates/blockchain-tree/src/chain.rs | 16 +++++++--- crates/chain-state/src/in_memory.rs | 20 ++++++++++-- crates/chain-state/src/memory_overlay.rs | 20 ++++++++++-- crates/consensus/auto-seal/Cargo.toml | 1 - crates/consensus/auto-seal/src/lib.rs | 3 +- .../engine/invalid-block-hooks/src/witness.rs | 4 +-- crates/engine/tree/src/tree/mod.rs | 19 +++++++---- crates/engine/util/src/reorg.rs | 3 +- crates/ethereum/payload/Cargo.toml | 1 - crates/ethereum/payload/src/lib.rs | 23 +++++++------ .../execution-types/src/execution_outcome.rs | 6 ++-- crates/evm/execution-types/src/lib.rs | 3 ++ crates/optimism/payload/Cargo.toml | 1 - crates/optimism/payload/src/builder.rs | 22 +++++++------ crates/revm/src/test_utils.rs | 22 ++++++++++--- crates/rpc/rpc-eth-api/Cargo.toml | 1 - .../rpc-eth-api/src/helpers/pending_block.rs | 7 ++-- crates/rpc/rpc-eth-types/src/cache/db.rs | 16 ++++++++++ .../src/providers/blockchain_provider.rs | 18 ++++++++++- .../src/providers/bundle_state_provider.rs | 32 +++++++++++++++---- .../provider/src/providers/consistent_view.rs | 7 ++-- .../provider/src/providers/database/mod.rs | 26 ++++++++++++++- .../src/providers/database/provider.rs | 29 +++++++++++++++-- .../src/providers/state/historical.rs | 22 +++++++++++-- .../provider/src/providers/state/latest.rs | 22 +++++++++++-- .../provider/src/providers/state/macros.rs | 4 +++ .../storage/provider/src/test_utils/mock.rs | 23 +++++++++++-- .../storage/provider/src/test_utils/noop.rs | 18 ++++++++++- crates/storage/provider/src/writer/mod.rs | 4 +-- crates/storage/storage-api/src/state.rs | 17 +++++++++- crates/trie/db/src/state.rs | 18 ++++++----- crates/trie/parallel/src/parallel_root.rs | 9 ++++-- crates/trie/trie/benches/hash_post_state.rs | 4 +-- crates/trie/trie/src/state.rs | 16 ++++++---- 38 files changed, 372 insertions(+), 116 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fc07aed94ca2..60dc918df378 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6329,7 +6329,6 @@ dependencies = [ "reth-stages-api", "reth-tokio-util", "reth-transaction-pool", - "reth-trie", "revm-primitives", "tokio", "tokio-stream", @@ -7337,7 +7336,6 @@ dependencies = [ "reth-provider", "reth-revm", "reth-transaction-pool", - "reth-trie", "revm", "revm-primitives", "tracing", @@ -8224,7 +8222,6 @@ dependencies = [ "reth-revm", "reth-rpc-types-compat", "reth-transaction-pool", - "reth-trie", "revm", "revm-primitives", "sha2 0.10.8", @@ -8767,7 +8764,6 @@ dependencies = [ "reth-rpc-types-compat", "reth-tasks", "reth-transaction-pool", - "reth-trie", "revm", "revm-inspectors", "revm-primitives", diff --git a/bin/reth/src/commands/debug_cmd/build_block.rs b/bin/reth/src/commands/debug_cmd/build_block.rs index 455d8356aff9..1940ae1e83b8 100644 --- a/bin/reth/src/commands/debug_cmd/build_block.rs +++ b/bin/reth/src/commands/debug_cmd/build_block.rs @@ -31,7 +31,7 @@ use reth_primitives::{ }; use reth_provider::{ providers::BlockchainProvider, BlockHashReader, BlockReader, BlockWriter, ChainSpecProvider, - ProviderFactory, StageCheckpointReader, StateProviderFactory, + HashedPostStateProvider, ProviderFactory, StageCheckpointReader, StateProviderFactory, }; use reth_revm::{database::StateProviderDatabase, primitives::EnvKzgSettings}; use reth_stages::StageId; @@ -266,7 +266,8 @@ 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 = + provider_factory.hashed_post_state_from_bundle_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 81c84819af62..5cb3562d0e1c 100644 --- a/bin/reth/src/commands/debug_cmd/in_memory_merkle.rs +++ b/bin/reth/src/commands/debug_cmd/in_memory_merkle.rs @@ -21,9 +21,9 @@ use reth_node_api::{NodeTypesWithDB, NodeTypesWithEngine}; use reth_node_ethereum::EthExecutorProvider; use reth_primitives::BlockHashOrNumber; use reth_provider::{ - writer::UnifiedStorageWriter, AccountExtReader, ChainSpecProvider, HashingWriter, - HeaderProvider, OriginalValuesKnown, ProviderFactory, StageCheckpointReader, StateWriter, - StorageReader, ToLatestStateProviderRef, + writer::UnifiedStorageWriter, AccountExtReader, ChainSpecProvider, HashedPostStateProvider, + HashingWriter, HeaderProvider, OriginalValuesKnown, ProviderFactory, StageCheckpointReader, + StateWriter, StorageReader, ToLatestStateProviderRef, }; use reth_revm::database::StateProviderDatabase; use reth_stages::StageId; @@ -153,7 +153,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(), + provider.hashed_post_state_from_bundle_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 71a58aa56288..475d800feb29 100644 --- a/crates/blockchain-tree/src/blockchain_tree.rs +++ b/crates/blockchain-tree/src/blockchain_tree.rs @@ -23,8 +23,8 @@ use reth_primitives::{ use reth_provider::{ providers::ProviderNodeTypes, BlockExecutionWriter, BlockNumReader, BlockWriter, CanonStateNotification, CanonStateNotificationSender, CanonStateNotifications, - ChainSpecProvider, ChainSplit, ChainSplitTarget, DisplayBlocksChain, HeaderProvider, - ProviderError, StaticFileProviderFactory, + ChainSpecProvider, ChainSplit, ChainSplitTarget, DisplayBlocksChain, HashedPostStateProvider, + HeaderProvider, ProviderError, StaticFileProviderFactory, }; use reth_stages_api::{MetricEvent, MetricEventsSender}; use reth_storage_errors::provider::{ProviderResult, RootMismatch}; @@ -1216,7 +1216,8 @@ 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_from_bundle_state(state.state()); let prefix_sets = hashed_state.construct_prefix_sets().freeze(); let hashed_state_sorted = hashed_state.into_sorted(); @@ -1875,7 +1876,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_from_bundle_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 393e525d5ae2..db350e0185b2 100644 --- a/crates/blockchain-tree/src/chain.rs +++ b/crates/blockchain-tree/src/chain.rs @@ -18,10 +18,11 @@ use reth_execution_types::{Chain, ExecutionOutcome}; use reth_primitives::{GotExpected, SealedBlockWithSenders, SealedHeader}; use reth_provider::{ providers::{BundleStateProvider, ConsistentDbView, ProviderNodeTypes}, - FullExecutionDataProvider, ProviderError, StateRootProvider, TryIntoHistoricalStateProvider, + 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::parallel_root::ParallelStateRoot; use std::{ collections::BTreeMap, @@ -227,14 +228,19 @@ impl AppendableChain { execution_outcome.extend(initial_execution_outcome.clone()); ParallelStateRoot::new( consistent_view, - TrieInput::from_state(execution_outcome.hash_state_slow()), + TrieInput::from_state( + externals + .provider_factory + .hashed_post_state_from_bundle_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 = externals + .provider_factory + .hashed_post_state_from_bundle_state(initial_execution_outcome.state()); let state_root = provider.state_root(hashed_state)?; (state_root, None) }; diff --git a/crates/chain-state/src/in_memory.rs b/crates/chain-state/src/in_memory.rs index f157da5ff450..195d2b5fbf67 100644 --- a/crates/chain-state/src/in_memory.rs +++ b/crates/chain-state/src/in_memory.rs @@ -870,8 +870,8 @@ mod tests { use reth_errors::ProviderResult; use reth_primitives::{Account, Bytecode, Receipt, Requests}; 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}; @@ -1012,6 +1012,22 @@ mod tests { } } + impl HashedPostStateProvider for MockStateProvider { + fn hashed_post_state_from_bundle_state( + &self, + _bundle_state: &reth_execution_types::BundleState, + ) -> HashedPostState { + HashedPostState::default() + } + + fn hashed_post_state_from_reverts( + &self, + _block_number: BlockNumber, + ) -> ProviderResult { + Ok(HashedPostState::default()) + } + } + #[test] fn test_in_memory_state_impl_state_by_hash() { let mut state_by_hash = HashMap::default(); diff --git a/crates/chain-state/src/memory_overlay.rs b/crates/chain-state/src/memory_overlay.rs index eb125dad115e..b19ae8508be9 100644 --- a/crates/chain-state/src/memory_overlay.rs +++ b/crates/chain-state/src/memory_overlay.rs @@ -7,8 +7,8 @@ use alloy_primitives::{ use reth_errors::ProviderResult; use reth_primitives::{Account, Bytecode}; use reth_storage_api::{ - AccountReader, BlockHashReader, StateProofProvider, StateProvider, StateProviderBox, - StateRootProvider, StorageRootProvider, + AccountReader, BlockHashReader, HashedPostStateProvider, StateProofProvider, StateProvider, + StateProviderBox, StateRootProvider, StorageRootProvider, }; use reth_trie::{ updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, TrieInput, @@ -188,6 +188,22 @@ impl StateProofProvider for MemoryOverlayStateProvider { } } +impl HashedPostStateProvider for MemoryOverlayStateProvider { + fn hashed_post_state_from_bundle_state( + &self, + bundle_state: &reth_execution_types::BundleState, + ) -> HashedPostState { + self.historical.hashed_post_state_from_bundle_state(bundle_state) + } + + fn hashed_post_state_from_reverts( + &self, + block_number: BlockNumber, + ) -> ProviderResult { + self.historical.hashed_post_state_from_reverts(block_number) + } +} + impl StateProvider for MemoryOverlayStateProvider { fn storage( &self, diff --git a/crates/consensus/auto-seal/Cargo.toml b/crates/consensus/auto-seal/Cargo.toml index b4b281230336..74ee7447d231 100644 --- a/crates/consensus/auto-seal/Cargo.toml +++ b/crates/consensus/auto-seal/Cargo.toml @@ -28,7 +28,6 @@ reth-engine-primitives.workspace = true reth-consensus.workspace = true reth-network-peers.workspace = true reth-tokio-util.workspace = true -reth-trie.workspace = true # ethereum alloy-primitives.workspace = true diff --git a/crates/consensus/auto-seal/src/lib.rs b/crates/consensus/auto-seal/src/lib.rs index 261227f1074e..7b4d0acc0b40 100644 --- a/crates/consensus/auto-seal/src/lib.rs +++ b/crates/consensus/auto-seal/src/lib.rs @@ -31,7 +31,6 @@ use reth_primitives::{ use reth_provider::{BlockReaderIdExt, StateProviderFactory, StateRootProvider}; use reth_revm::database::StateProviderDatabase; use reth_transaction_pool::TransactionPool; -use reth_trie::HashedPostState; use revm_primitives::calc_excess_blob_gas; use std::{ collections::HashMap, @@ -383,7 +382,7 @@ impl StorageInner { executor.executor(&mut db).execute((&block, U256::ZERO).into())?; let gas_used = block_execution_output.gas_used; let execution_outcome = ExecutionOutcome::from((block_execution_output, block.number)); - let hashed_state = HashedPostState::from_bundle_state(&execution_outcome.state().state); + let hashed_state = db.0.hashed_post_state_from_bundle_state(execution_outcome.state()); // todo(onbjerg): we should not pass requests around as this is building a block, which // means we need to extract the requests from the execution output and compute the requests diff --git a/crates/engine/invalid-block-hooks/src/witness.rs b/crates/engine/invalid-block-hooks/src/witness.rs index bb227e304198..6ea682970e55 100644 --- a/crates/engine/invalid-block-hooks/src/witness.rs +++ b/crates/engine/invalid-block-hooks/src/witness.rs @@ -18,7 +18,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. @@ -128,7 +128,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_from_bundle_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 3eadbbd522db..aeaf25289762 100644 --- a/crates/engine/tree/src/tree/mod.rs +++ b/crates/engine/tree/src/tree/mod.rs @@ -37,8 +37,8 @@ use reth_primitives::{ }; 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; @@ -531,8 +531,14 @@ impl std::fmt::Debug impl EngineApiTreeHandler where - P: DatabaseProviderFactory + BlockReader + StateProviderFactory + StateReader + Clone + 'static, -

::Provider: BlockReader, + P: DatabaseProviderFactory + + BlockReader + + StateProviderFactory + + StateReader + + HashedPostStateProvider + + Clone + + 'static, +

::Provider: BlockReader + HashedPostStateProvider, E: BlockExecutorProvider, T: EngineTypes, Spec: Send + Sync + EthereumHardforks + 'static, @@ -1530,7 +1536,8 @@ 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_from_bundle_state(execution_output.state()); Ok(Some(ExecutedBlock { block: Arc::new(block), @@ -2194,7 +2201,7 @@ where return Err(err.into()) } - let hashed_state = HashedPostState::from_bundle_state(&output.state.state); + let hashed_state = self.provider.hashed_post_state_from_bundle_state(&output.state); trace!(target: "engine::tree", block=?BlockNumHash::new(block_number, block_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 abfa23a57b32..1c52d944b53d 100644 --- a/crates/engine/util/src/reorg.rs +++ b/crates/engine/util/src/reorg.rs @@ -22,7 +22,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, }; @@ -365,7 +364,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_from_bundle_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 ce37a4f8ea4f..721a99f049d9 100644 --- a/crates/ethereum/payload/Cargo.toml +++ b/crates/ethereum/payload/Cargo.toml @@ -24,7 +24,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 dcf54fc02489..36652a1c098b 100644 --- a/crates/ethereum/payload/src/lib.rs +++ b/crates/ethereum/payload/src/lib.rs @@ -34,7 +34,6 @@ 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::{EVMError, EnvWithHandlerCfg, InvalidTransaction, ResultAndState}, @@ -353,16 +352,20 @@ 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 (state_root, trie_output) = { + + let (state_root, trie_output, hashed_state) = { let state_provider = db.database.0.inner.borrow_mut(); - state_provider.db.state_root_with_updates(hashed_state.clone()).inspect_err(|err| { - warn!(target: "payload_builder", - parent_hash=%parent_block.hash(), - %err, - "failed to calculate state root for payload" - ); - })? + let hashed_state = + state_provider.db.hashed_post_state_from_bundle_state(execution_outcome.state()); + let (state_root, trie_output) = + state_provider.db.state_root_with_updates(hashed_state.clone()).inspect_err(|err| { + warn!(target: "payload_builder", + parent_hash=%parent_block.hash(), + %err, + "failed to calculate state root for payload" + ); + })?; + (state_root, trie_output, hashed_state) }; // create the block header diff --git a/crates/evm/execution-types/src/execution_outcome.rs b/crates/evm/execution-types/src/execution_outcome.rs index 08ddf9e4167b..c58411fcdded 100644 --- a/crates/evm/execution-types/src/execution_outcome.rs +++ b/crates/evm/execution-types/src/execution_outcome.rs @@ -1,7 +1,7 @@ use crate::BlockExecutionOutput; use alloy_primitives::{Address, BlockNumber, Bloom, Log, B256, U256}; use reth_primitives::{logs_bloom, Account, Bytecode, Receipt, Receipts, Requests, StorageEntry}; -use reth_trie::HashedPostState; +use reth_trie::{HashedPostState, KeyHasher}; use revm::{ db::{states::BundleState, BundleAccount}, primitives::AccountInfo, @@ -162,8 +162,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/evm/execution-types/src/lib.rs b/crates/evm/execution-types/src/lib.rs index f98ebfe73a5f..c5adafecb1da 100644 --- a/crates/evm/execution-types/src/lib.rs +++ b/crates/evm/execution-types/src/lib.rs @@ -19,6 +19,9 @@ pub use execute::*; mod execution_outcome; pub use execution_outcome::*; +// Re-export commonly used execution types from `revm`. +pub use revm::db::{BundleAccount, BundleState}; + /// Bincode-compatible serde implementations for commonly used types for (EVM) block execution. /// /// `bincode` crate doesn't work with optionally serializable serde fields, but some of the diff --git a/crates/optimism/payload/Cargo.toml b/crates/optimism/payload/Cargo.toml index 46cc82edb6ce..4f7db968ecff 100644 --- a/crates/optimism/payload/Cargo.toml +++ b/crates/optimism/payload/Cargo.toml @@ -24,7 +24,6 @@ reth-execution-types.workspace = true reth-payload-builder.workspace = true reth-payload-primitives.workspace = true 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 e590635f524e..c4cf45b9e3b4 100644 --- a/crates/optimism/payload/src/builder.rs +++ b/crates/optimism/payload/src/builder.rs @@ -24,7 +24,6 @@ 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::{EVMError, EnvWithHandlerCfg, InvalidTransaction, ResultAndState}, @@ -451,16 +450,19 @@ 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 (state_root, trie_output) = { + let (state_root, trie_output, hashed_state) = { let state_provider = db.database.0.inner.borrow_mut(); - state_provider.db.state_root_with_updates(hashed_state.clone()).inspect_err(|err| { - warn!(target: "payload_builder", - parent_hash=%parent_block.hash(), - %err, - "failed to calculate state root for payload" - ); - })? + let hashed_state = + state_provider.db.hashed_post_state_from_bundle_state(execution_outcome.state()); + let (state_root, trie_output) = + state_provider.db.state_root_with_updates(hashed_state.clone()).inspect_err(|err| { + warn!(target: "payload_builder", + parent_hash=%parent_block.hash(), + %err, + "failed to calculate state root for payload" + ); + })?; + (state_root, trie_output, hashed_state) }; // create the block header diff --git a/crates/revm/src/test_utils.rs b/crates/revm/src/test_utils.rs index 813997c72d11..f15398a81cfa 100644 --- a/crates/revm/src/test_utils.rs +++ b/crates/revm/src/test_utils.rs @@ -6,14 +6,15 @@ 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, }; +use revm::db::BundleState; /// Mock state for testing #[derive(Debug, Default, Clone, Eq, PartialEq)] @@ -141,6 +142,19 @@ impl StateProofProvider for StateProviderTest { } } +impl HashedPostStateProvider for StateProviderTest { + fn hashed_post_state_from_bundle_state(&self, bundle_state: &BundleState) -> HashedPostState { + HashedPostState::from_bundle_state::(&bundle_state.state) + } + + fn hashed_post_state_from_reverts( + &self, + _block_number: BlockNumber, + ) -> ProviderResult { + unimplemented!("reverts are not supported") + } +} + 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 9d0f6cfd83d6..2044fe132678 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 # ethereum alloy-eips.workspace = true 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 832cf17055a5..78187b3e2c5b 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs @@ -31,7 +31,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 tokio::sync::Mutex; use tracing::debug; @@ -398,7 +397,10 @@ pub trait LoadPendingBlock: EthApiTypes { block_number, Vec::new(), ); - let hashed_state = HashedPostState::from_bundle_state(&execution_outcome.state().state); + + let state_provider = &db.database; + let hashed_state = + state_provider.hashed_post_state_from_bundle_state(execution_outcome.state()); let receipts_root = self.receipts_root(&block_env, &execution_outcome, block_number); @@ -406,7 +408,6 @@ pub trait LoadPendingBlock: EthApiTypes { execution_outcome.block_logs_bloom(block_number).expect("Block is present"); // calculate the state root - let state_provider = &db.database; let state_root = state_provider.state_root(hashed_state).map_err(Self::Error::from_eth_err)?; diff --git a/crates/rpc/rpc-eth-types/src/cache/db.rs b/crates/rpc/rpc-eth-types/src/cache/db.rs index 7422dcfb8a7b..fafa9fe7d721 100644 --- a/crates/rpc/rpc-eth-types/src/cache/db.rs +++ b/crates/rpc/rpc-eth-types/src/cache/db.rs @@ -130,6 +130,22 @@ impl reth_storage_api::BlockHashReader for StateProviderTraitObjWrapper<'_> { } } +impl reth_storage_api::HashedPostStateProvider for StateProviderTraitObjWrapper<'_> { + fn hashed_post_state_from_bundle_state( + &self, + bundle_state: &reth_execution_types::BundleState, + ) -> reth_trie::HashedPostState { + self.0.hashed_post_state_from_bundle_state(bundle_state) + } + + fn hashed_post_state_from_reverts( + &self, + block_number: alloy_primitives::BlockNumber, + ) -> ProviderResult { + self.0.hashed_post_state_from_reverts(block_number) + } +} + impl StateProvider for StateProviderTraitObjWrapper<'_> { fn account_balance( &self, diff --git a/crates/storage/provider/src/providers/blockchain_provider.rs b/crates/storage/provider/src/providers/blockchain_provider.rs index 6e39a3697b30..0be97cc67008 100644 --- a/crates/storage/provider/src/providers/blockchain_provider.rs +++ b/crates/storage/provider/src/providers/blockchain_provider.rs @@ -27,7 +27,7 @@ use reth_primitives::{ }; use reth_prune_types::{PruneCheckpoint, PruneSegment}; use reth_stages_types::{StageCheckpoint, StageId}; -use reth_storage_api::StorageChangeSetReader; +use reth_storage_api::{HashedPostStateProvider, StorageChangeSetReader}; use reth_storage_errors::provider::ProviderResult; use revm::{ db::states::PlainStorageRevert, @@ -1707,6 +1707,22 @@ impl StateReader for BlockchainProvider2 { } } +impl HashedPostStateProvider for BlockchainProvider2 { + fn hashed_post_state_from_bundle_state( + &self, + bundle_state: &reth_execution_types::BundleState, + ) -> reth_trie::HashedPostState { + self.database.hashed_post_state_from_bundle_state(bundle_state) + } + + fn hashed_post_state_from_reverts( + &self, + block_number: BlockNumber, + ) -> ProviderResult { + self.database.hashed_post_state_from_reverts(block_number) + } +} + #[cfg(test)] mod tests { use std::{ diff --git a/crates/storage/provider/src/providers/bundle_state_provider.rs b/crates/storage/provider/src/providers/bundle_state_provider.rs index be6549033cde..8c45a0133093 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.state_provider.hashed_post_state_from_bundle_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.state_provider.hashed_post_state_from_bundle_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.state_provider.hashed_post_state_from_bundle_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.state_provider.hashed_post_state_from_bundle_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.state_provider.hashed_post_state_from_bundle_state(bundle_state)); self.state_provider.multiproof(input, targets) } @@ -170,11 +170,29 @@ 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.state_provider.hashed_post_state_from_bundle_state(bundle_state)); self.state_provider.witness(input, target) } } +impl HashedPostStateProvider + for BundleStateProvider +{ + fn hashed_post_state_from_bundle_state( + &self, + bundle_state: &reth_execution_types::BundleState, + ) -> HashedPostState { + self.state_provider.hashed_post_state_from_bundle_state(bundle_state) + } + + fn hashed_post_state_from_reverts( + &self, + block_number: BlockNumber, + ) -> ProviderResult { + self.state_provider.hashed_post_state_from_reverts(block_number) + } +} + impl StateProvider for BundleStateProvider { fn storage( &self, diff --git a/crates/storage/provider/src/providers/consistent_view.rs b/crates/storage/provider/src/providers/consistent_view.rs index 4640f4603354..330b3abba3cd 100644 --- a/crates/storage/provider/src/providers/consistent_view.rs +++ b/crates/storage/provider/src/providers/consistent_view.rs @@ -2,11 +2,10 @@ 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, HashedPostStateProvider}; use reth_storage_errors::provider::ProviderResult; use reth_trie::HashedPostState; -use reth_trie_db::DatabaseHashedPostState; pub use reth_storage_errors::provider::ConsistentViewError; @@ -33,7 +32,7 @@ pub struct ConsistentDbView { impl ConsistentDbView where - Factory: DatabaseProviderFactory, + Factory: DatabaseProviderFactory, { /// Creates new consistent database view. pub const fn new(factory: Factory, tip: Option) -> Self { @@ -59,7 +58,7 @@ where { Ok(HashedPostState::default()) } else { - Ok(HashedPostState::from_reverts(provider.tx_ref(), block_number + 1)?) + Ok(provider.hashed_post_state_from_reverts(block_number + 1)?) } } diff --git a/crates/storage/provider/src/providers/database/mod.rs b/crates/storage/provider/src/providers/database/mod.rs index 62e04c2cf651..62a5829258b3 100644 --- a/crates/storage/provider/src/providers/database/mod.rs +++ b/crates/storage/provider/src/providers/database/mod.rs @@ -23,8 +23,10 @@ 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::{HashedPostStateProvider, TryIntoHistoricalStateProvider}; use reth_storage_errors::provider::ProviderResult; +use reth_trie::HashedPostState; +use reth_trie_db::{DatabaseHashedPostState, StateCommitment}; use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg}; use std::{ ops::{RangeBounds, RangeInclusive}, @@ -623,6 +625,28 @@ impl PruneCheckpointReader for ProviderFactory { } } +impl HashedPostStateProvider for ProviderFactory { + fn hashed_post_state_from_bundle_state( + &self, + bundle_state: &reth_execution_types::BundleState, + ) -> reth_trie::HashedPostState { + HashedPostState::from_bundle_state::<::KeyHasher>( + &bundle_state.state, + ) + } + + fn hashed_post_state_from_reverts( + &self, + block_number: BlockNumber, + ) -> ProviderResult { + HashedPostState::from_reverts::<::KeyHasher>( + &self.db.tx().map_err(Into::::into)?, + block_number, + ) + .map_err(Into::into) + } +} + impl Clone for ProviderFactory { fn clone(&self) -> Self { Self { diff --git a/crates/storage/provider/src/providers/database/provider.rs b/crates/storage/provider/src/providers/database/provider.rs index 1c3042d5e4a6..aa9fe269e0e6 100644 --- a/crates/storage/provider/src/providers/database/provider.rs +++ b/crates/storage/provider/src/providers/database/provider.rs @@ -48,14 +48,18 @@ use reth_primitives::{ }; use reth_prune_types::{PruneCheckpoint, PruneModes, PruneSegment}; use reth_stages_types::{StageCheckpoint, StageId}; -use reth_storage_api::{StateProvider, StorageChangeSetReader, TryIntoHistoricalStateProvider}; +use reth_storage_api::{ + HashedPostStateProvider, StateProvider, StorageChangeSetReader, TryIntoHistoricalStateProvider, +}; use reth_storage_errors::provider::{ProviderResult, RootMismatch}; use reth_trie::{ prefix_set::{PrefixSet, PrefixSetMut, TriePrefixSets}, updates::{StorageTrieUpdates, TrieUpdates}, - HashedPostStateSorted, Nibbles, StateRoot, StoredNibbles, + HashedPostState, HashedPostStateSorted, Nibbles, StateRoot, StoredNibbles, +}; +use reth_trie_db::{ + DatabaseHashedPostState, DatabaseStateRoot, DatabaseStorageTrieCursor, StateCommitment, }; -use reth_trie_db::{DatabaseStateRoot, DatabaseStorageTrieCursor, StateCommitment}; use revm::{ db::states::{PlainStateReverts, PlainStorageChangeset, PlainStorageRevert, StateChangeset}, primitives::{BlockEnv, CfgEnvWithHandlerCfg}, @@ -3758,6 +3762,25 @@ impl ChainStateBlockWriter } } +impl HashedPostStateProvider + for DatabaseProvider +{ + fn hashed_post_state_from_bundle_state( + &self, + bundle_state: &reth_execution_types::BundleState, + ) -> reth_trie::HashedPostState { + HashedPostState::from_bundle_state::(&bundle_state.state) + } + + fn hashed_post_state_from_reverts( + &self, + block_number: BlockNumber, + ) -> ProviderResult { + HashedPostState::from_reverts::(self.tx_ref(), block_number) + .map_err(Into::into) + } +} + impl DBProvider for DatabaseProvider { diff --git a/crates/storage/provider/src/providers/state/historical.rs b/crates/storage/provider/src/providers/state/historical.rs index 967343a9763c..6f5ee4403e5f 100644 --- a/crates/storage/provider/src/providers/state/historical.rs +++ b/crates/storage/provider/src/providers/state/historical.rs @@ -14,7 +14,7 @@ use reth_db_api::{ transaction::DbTx, }; use reth_primitives::{constants::EPOCH_SLOTS, Account, Bytecode, StaticFileSegment}; -use reth_storage_api::{StateProofProvider, StorageRootProvider}; +use reth_storage_api::{HashedPostStateProvider, StateProofProvider, StorageRootProvider}; use reth_storage_errors::provider::ProviderResult; use reth_trie::{ proof::{Proof, StorageProof}, @@ -159,7 +159,7 @@ impl<'b, TX: DbTx, SC: StateCommitment> HistoricalStateProviderRef<'b, TX, SC> { ); } - Ok(HashedPostState::from_reverts(self.tx, self.block_number)?) + Ok(HashedPostState::from_reverts::(self.tx, self.block_number)?) } /// Retrieve revert hashed storage for this history provider and target address. @@ -410,6 +410,24 @@ impl StateProofProvider for HistoricalStateProvid } } +impl HashedPostStateProvider + for HistoricalStateProviderRef<'_, TX, SC> +{ + fn hashed_post_state_from_bundle_state( + &self, + bundle_state: &reth_execution_types::BundleState, + ) -> HashedPostState { + HashedPostState::from_bundle_state::(&bundle_state.state) + } + + fn hashed_post_state_from_reverts( + &self, + block_number: BlockNumber, + ) -> ProviderResult { + HashedPostState::from_reverts::(self.tx, block_number).map_err(Into::into) + } +} + impl StateProvider for HistoricalStateProviderRef<'_, TX, SC> { /// Get storage. fn storage( diff --git a/crates/storage/provider/src/providers/state/latest.rs b/crates/storage/provider/src/providers/state/latest.rs index 1299db28b911..f20f00954fab 100644 --- a/crates/storage/provider/src/providers/state/latest.rs +++ b/crates/storage/provider/src/providers/state/latest.rs @@ -12,7 +12,7 @@ use reth_db_api::{ transaction::DbTx, }; use reth_primitives::{Account, Bytecode, StaticFileSegment}; -use reth_storage_api::{StateProofProvider, StorageRootProvider}; +use reth_storage_api::{HashedPostStateProvider, StateProofProvider, StorageRootProvider}; use reth_storage_errors::provider::{ProviderError, ProviderResult}; use reth_trie::{ proof::{Proof, StorageProof}, @@ -21,8 +21,8 @@ use reth_trie::{ AccountProof, HashedPostState, HashedStorage, MultiProof, StateRoot, StorageRoot, TrieInput, }; use reth_trie_db::{ - DatabaseProof, DatabaseStateRoot, DatabaseStorageProof, DatabaseStorageRoot, - DatabaseTrieWitness, StateCommitment, + DatabaseHashedPostState, DatabaseProof, DatabaseStateRoot, DatabaseStorageProof, + DatabaseStorageRoot, DatabaseTrieWitness, StateCommitment, }; use std::marker::PhantomData; @@ -164,6 +164,22 @@ impl StateProofProvider for LatestStateProviderRe } } +impl HashedPostStateProvider for LatestStateProviderRef<'_, TX, SC> { + fn hashed_post_state_from_bundle_state( + &self, + bundle_state: &reth_execution_types::BundleState, + ) -> HashedPostState { + HashedPostState::from_bundle_state::(&bundle_state.state) + } + + fn hashed_post_state_from_reverts( + &self, + block_number: BlockNumber, + ) -> ProviderResult { + HashedPostState::from_reverts::(self.tx, block_number).map_err(Into::into) + } +} + impl StateProvider for LatestStateProviderRef<'_, TX, SC> { /// Get storage. fn storage( diff --git a/crates/storage/provider/src/providers/state/macros.rs b/crates/storage/provider/src/providers/state/macros.rs index b90924354c43..424565340b11 100644 --- a/crates/storage/provider/src/providers/state/macros.rs +++ b/crates/storage/provider/src/providers/state/macros.rs @@ -56,6 +56,10 @@ 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_from_reverts(&self, block_number: alloy_primitives::BlockNumber) -> reth_storage_errors::provider::ProviderResult; + fn hashed_post_state_from_bundle_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 d99093ac80a5..479b075deced 100644 --- a/crates/storage/provider/src/test_utils/mock.rs +++ b/crates/storage/provider/src/test_utils/mock.rs @@ -27,12 +27,13 @@ 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::{ - updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, StorageProof, - TrieInput, + updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, KeccakKeyHasher, + MultiProof, StorageProof, TrieInput, }; use reth_trie_db::MerklePatriciaTrie; use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg}; @@ -670,6 +671,22 @@ impl StateProofProvider for MockEthProvider { } } +impl HashedPostStateProvider for MockEthProvider { + fn hashed_post_state_from_bundle_state( + &self, + bundle_state: &reth_execution_types::BundleState, + ) -> HashedPostState { + HashedPostState::from_bundle_state::(&bundle_state.state) + } + + fn hashed_post_state_from_reverts( + &self, + _block_number: BlockNumber, + ) -> ProviderResult { + unimplemented!("hashed_post_state_from_reverts not supported for MockEthProvider") + } +} + 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 0a205389c9b6..dd4091a2c07e 100644 --- a/crates/storage/provider/src/test_utils/noop.rs +++ b/crates/storage/provider/src/test_utils/noop.rs @@ -24,7 +24,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, @@ -394,6 +394,22 @@ impl StateProofProvider for NoopProvider { } } +impl HashedPostStateProvider for NoopProvider { + fn hashed_post_state_from_bundle_state( + &self, + _bundle_state: &reth_execution_types::BundleState, + ) -> HashedPostState { + HashedPostState::default() + } + + fn hashed_post_state_from_reverts( + &self, + _block_number: BlockNumber, + ) -> ProviderResult { + Ok(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 5b16b2da4e5a..562f77788735 100644 --- a/crates/storage/provider/src/writer/mod.rs +++ b/crates/storage/provider/src/writer/mod.rs @@ -555,7 +555,7 @@ mod tests { use reth_storage_api::DatabaseProviderFactory; use reth_trie::{ test_utils::{state_root, storage_root_prehashed}, - HashedPostState, HashedStorage, StateRoot, StorageRoot, + HashedPostState, HashedStorage, KeccakKeyHasher, StateRoot, StorageRoot, }; use reth_trie_db::{DatabaseStateRoot, DatabaseStorageRoot}; use revm::{ @@ -1447,7 +1447,7 @@ mod tests { 0, Vec::new() ) - .hash_state_slow(), + .hash_state_slow::(), ) .unwrap(), state_root(expected.clone().into_iter().map(|(address, (account, storage))| ( diff --git a/crates/storage/storage-api/src/state.rs b/crates/storage/storage-api/src/state.rs index 1bbcd614e77e..f2eebdaed548 100644 --- a/crates/storage/storage-api/src/state.rs +++ b/crates/storage/storage-api/src/state.rs @@ -5,9 +5,10 @@ use super::{ use alloy_eips::{BlockId, BlockNumHash, BlockNumberOrTag}; use alloy_primitives::{Address, BlockHash, BlockNumber, StorageKey, StorageValue, B256, U256}; use auto_impl::auto_impl; -use reth_execution_types::ExecutionOutcome; +use reth_execution_types::{BundleState, ExecutionOutcome}; use reth_primitives::{Bytecode, KECCAK_EMPTY}; use reth_storage_errors::provider::{ProviderError, ProviderResult}; +use reth_trie::HashedPostState; /// Type alias of boxed [`StateProvider`]. pub type StateProviderBox = Box; @@ -20,6 +21,7 @@ pub trait StateProvider: + StateRootProvider + StorageRootProvider + StateProofProvider + + HashedPostStateProvider + Send + Sync { @@ -174,6 +176,19 @@ pub trait StateProviderFactory: BlockIdReader + Send + Sync { fn pending_state_by_hash(&self, block_hash: B256) -> ProviderResult>; } +/// Trait that provides the hashed state from various sources. +#[auto_impl::auto_impl(&, Box, Arc)] +pub trait HashedPostStateProvider { + /// Returns the `HashedPostState` of the provided `BundleState`. + fn hashed_post_state_from_bundle_state(&self, bundle_state: &BundleState) -> HashedPostState; + + /// Returns the `HashedPostState` for the given block number. + fn hashed_post_state_from_reverts( + &self, + block_number: BlockNumber, + ) -> ProviderResult; +} + /// Blockchain trait provider that gives access to the blockchain state that is not yet committed /// (pending). pub trait BlockchainTreePendingStateProvider: Send + Sync { diff --git a/crates/trie/db/src/state.rs b/crates/trie/db/src/state.rs index 4d46183dfda4..0a1aa5fbce95 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, @@ -11,7 +11,8 @@ use reth_primitives::Account; 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, KeyHasher, StateRoot, StateRootProgress, + TrieInput, }; use std::{ collections::{hash_map, HashMap}, @@ -126,7 +127,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> @@ -220,7 +221,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::>::default(); let mut account_changesets_cursor = tx.cursor_read::()?; @@ -245,19 +246,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)), ), ) }) @@ -274,6 +275,7 @@ mod tests { use reth_db::test_utils::create_test_rw_db; use reth_db_api::database::Database; use reth_primitives::revm_primitives::AccountInfo; + use reth_trie::KeccakKeyHasher; use revm::db::BundleState; #[test] @@ -294,7 +296,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/parallel/src/parallel_root.rs b/crates/trie/parallel/src/parallel_root.rs index e432b91062ca..3ac976b5ca98 100644 --- a/crates/trie/parallel/src/parallel_root.rs +++ b/crates/trie/parallel/src/parallel_root.rs @@ -6,7 +6,8 @@ use alloy_rlp::{BufMut, Encodable}; use itertools::Itertools; use reth_execution_errors::StorageRootError; use reth_provider::{ - providers::ConsistentDbView, BlockReader, DBProvider, DatabaseProviderFactory, ProviderError, + providers::ConsistentDbView, BlockReader, DBProvider, DatabaseProviderFactory, + HashedPostStateProvider, ProviderError, }; use reth_trie::{ hashed_cursor::{HashedCursorFactory, HashedPostStateCursorFactory}, @@ -57,7 +58,11 @@ impl ParallelStateRoot { impl ParallelStateRoot where - Factory: DatabaseProviderFactory + Clone + Send + Sync + 'static, + Factory: DatabaseProviderFactory + + Clone + + Send + + Sync + + 'static, { /// Calculate incremental state root in parallel. pub fn incremental_root(self) -> Result { 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 2af48dfff798..c53d2fd71aa8 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, @@ -347,7 +348,8 @@ impl HashedStorageSorted { #[cfg(test)] mod tests { - use alloy_primitives::Bytes; + use alloy_primitives::{keccak256, Bytes}; + use reth_trie_common::KeccakKeyHasher; use revm::{ db::{ states::{plain_account::PlainStorage, StorageSlot}, @@ -463,7 +465,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); @@ -502,7 +504,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);