diff --git a/Cargo.lock b/Cargo.lock index 27581ba3a800..d0a47eedc8cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6378,7 +6378,6 @@ dependencies = [ "reth-stages-api", "reth-tokio-util", "reth-transaction-pool", - "reth-trie", "revm-primitives", "tokio", "tokio-stream", @@ -7397,7 +7396,6 @@ dependencies = [ "reth-provider", "reth-revm", "reth-transaction-pool", - "reth-trie", "revm", "revm-primitives", "tracing", @@ -8284,7 +8282,6 @@ dependencies = [ "reth-revm", "reth-rpc-types-compat", "reth-transaction-pool", - "reth-trie", "revm", "sha2 0.10.8", "thiserror", @@ -8824,7 +8821,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 a2dfb5ab3eaa..c13c31531624 100644 --- a/bin/reth/src/commands/debug_cmd/build_block.rs +++ b/bin/reth/src/commands/debug_cmd/build_block.rs @@ -34,7 +34,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; @@ -270,7 +270,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 51851c0b0ad2..634a872b9577 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, LatestStateProviderRef, OriginalValuesKnown, ProviderFactory, - StageCheckpointReader, StateWriter, StaticFileProviderFactory, StorageReader, + writer::UnifiedStorageWriter, AccountExtReader, AsLatestStateProviderRef, ChainSpecProvider, + HashedPostStateProvider, HashingWriter, HeaderProvider, OriginalValuesKnown, ProviderFactory, + StageCheckpointReader, StateWriter, StorageReader, }; use reth_revm::database::StateProviderDatabase; use reth_stages::StageId; @@ -131,10 +131,7 @@ impl> Command { ) .await?; - let db = StateProviderDatabase::new(LatestStateProviderRef::new( - provider.tx_ref(), - provider_factory.static_file_provider(), - )); + let db = StateProviderDatabase::new(provider.latest()); let executor = EthExecutorProvider::ethereum(provider_factory.chain_spec()).executor(db); @@ -156,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/bin/reth/src/commands/debug_cmd/merkle.rs b/bin/reth/src/commands/debug_cmd/merkle.rs index 8e02a52eaf07..62b460ff1c04 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_node_api::{NodeTypesWithDB, NodeTypesWithEngine}; use reth_node_ethereum::EthExecutorProvider; use reth_primitives::BlockHashOrNumber; use reth_provider::{ - writer::UnifiedStorageWriter, BlockNumReader, BlockWriter, ChainSpecProvider, - DatabaseProviderFactory, HeaderProvider, LatestStateProviderRef, OriginalValuesKnown, - ProviderError, ProviderFactory, StateWriter, StaticFileProviderFactory, + writer::UnifiedStorageWriter, AsLatestStateProviderRef, BlockNumReader, BlockWriter, + ChainSpecProvider, DatabaseProviderFactory, HeaderProvider, OriginalValuesKnown, ProviderError, + ProviderFactory, StateWriter, }; use reth_revm::database::StateProviderDatabase; use reth_stages::{ @@ -152,12 +152,8 @@ impl> Command { provider_rw.insert_block(sealed_block.clone())?; td += sealed_block.difficulty; - let mut executor = executor_provider.batch_executor(StateProviderDatabase::new( - LatestStateProviderRef::new( - provider_rw.tx_ref(), - provider_rw.static_file_provider().clone(), - ), - )); + let mut executor = + executor_provider.batch_executor(StateProviderDatabase::new(provider_rw.latest())); executor.execute_and_verify_one((&sealed_block.clone().unseal(), td).into())?; let execution_outcome = executor.finalize(); diff --git a/crates/blockchain-tree/src/blockchain_tree.rs b/crates/blockchain-tree/src/blockchain_tree.rs index 4468d82052c8..172a9d8ffbb7 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}; @@ -1214,7 +1214,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(); @@ -1872,7 +1873,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 6bef197bea98..bd5447d248b8 100644 --- a/crates/chain-state/src/in_memory.rs +++ b/crates/chain-state/src/in_memory.rs @@ -918,8 +918,8 @@ mod tests { use reth_errors::ProviderResult; use reth_primitives::{Account, Bytecode, 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}; @@ -1060,6 +1060,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 ada0faee4907..5de2ded6e4bf 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, StateRootProvider, - StorageRootProvider, + AccountReader, BlockHashReader, HashedPostStateProvider, StateProofProvider, StateProvider, + StateRootProvider, StorageRootProvider, }; use reth_trie::{ updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, TrieInput, @@ -202,6 +202,22 @@ macro_rules! impl_state_provider { } } + impl $($tokens)* HashedPostStateProvider for $type { + 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 $($tokens)* StateProvider for $type { fn storage( &self, diff --git a/crates/consensus/auto-seal/Cargo.toml b/crates/consensus/auto-seal/Cargo.toml index f2bfb43bcced..00390323f73f 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-eips.workspace = true diff --git a/crates/consensus/auto-seal/src/lib.rs b/crates/consensus/auto-seal/src/lib.rs index 16299e19ba45..aac75b39f8e7 100644 --- a/crates/consensus/auto-seal/src/lib.rs +++ b/crates/consensus/auto-seal/src/lib.rs @@ -32,7 +32,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 416c4adb40f8..8b6018f17d26 100644 --- a/crates/engine/invalid-block-hooks/src/witness.rs +++ b/crates/engine/invalid-block-hooks/src/witness.rs @@ -19,7 +19,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. @@ -129,7 +129,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 bc070d87345e..750a6bc36df8 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; @@ -532,8 +532,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, @@ -1537,7 +1543,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), @@ -2202,7 +2209,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=?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 0d51d2dfab6f..293bbb792c27 100644 --- a/crates/engine/util/src/reorg.rs +++ b/crates/engine/util/src/reorg.rs @@ -24,7 +24,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, }; @@ -381,7 +380,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 443e837b2ed1..0205ba9312ac 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 8e188f890fd9..20b049f4bb4c 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::{EVMError, EnvWithHandlerCfg, InvalidTransaction, ResultAndState}, @@ -366,16 +365,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_header.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_header.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 026e6b37c42c..9b9d857102cc 100644 --- a/crates/evm/execution-types/src/execution_outcome.rs +++ b/crates/evm/execution-types/src/execution_outcome.rs @@ -2,7 +2,7 @@ use crate::BlockExecutionOutput; use alloy_eips::eip7685::Requests; use alloy_primitives::{Address, BlockNumber, Bloom, Log, B256, U256}; use reth_primitives::{logs_bloom, Account, Bytecode, Receipt, Receipts, StorageEntry}; -use reth_trie::HashedPostState; +use reth_trie::{HashedPostState, KeyHasher}; use revm::{ db::{states::BundleState, BundleAccount}, primitives::AccountInfo, @@ -163,8 +163,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/exex/exex/src/backfill/test_utils.rs b/crates/exex/exex/src/backfill/test_utils.rs index 0a8bde242457..243a01f5947a 100644 --- a/crates/exex/exex/src/backfill/test_utils.rs +++ b/crates/exex/exex/src/backfill/test_utils.rs @@ -13,8 +13,8 @@ use reth_primitives::{ Block, BlockBody, BlockWithSenders, Header, Receipt, SealedBlockWithSenders, Transaction, }; use reth_provider::{ - providers::ProviderNodeTypes, BlockWriter as _, ExecutionOutcome, LatestStateProviderRef, - ProviderFactory, StaticFileProviderFactory, + providers::ProviderNodeTypes, AsLatestStateProviderRef, BlockWriter as _, ExecutionOutcome, + ProviderFactory, }; use reth_revm::database::StateProviderDatabase; use reth_testing_utils::generators::sign_tx_with_key_pair; @@ -63,10 +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.tx_ref(), - provider.static_file_provider(), - ))) + .executor(StateProviderDatabase::new(provider.latest())) .execute(BlockExecutionInput { block, total_difficulty: U256::ZERO })?; block_execution_output.state.reverts.sort(); @@ -191,10 +188,8 @@ where let provider = provider_factory.provider()?; - let executor = - EthExecutorProvider::ethereum(chain_spec).batch_executor(StateProviderDatabase::new( - LatestStateProviderRef::new(provider.tx_ref(), provider.static_file_provider()), - )); + let executor = EthExecutorProvider::ethereum(chain_spec) + .batch_executor(StateProviderDatabase::new(provider.latest())); let mut execution_outcome = executor.execute_and_verify_batch(vec![ (&block1, U256::ZERO).into(), diff --git a/crates/optimism/payload/Cargo.toml b/crates/optimism/payload/Cargo.toml index 4b8e64f2dba3..cf4fe80547ed 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 0550adeaa8d5..4b71f9cb37b6 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}, @@ -445,16 +444,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_header=%parent_header.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_header=%parent_header.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 edfd57b201d9..6e32f29f9494 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 f2d1416139b8..570b39554803 100644 --- a/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs +++ b/crates/rpc/rpc-eth-api/src/helpers/pending_block.rs @@ -34,7 +34,6 @@ use reth_provider::{ use reth_revm::database::StateProviderDatabase; 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; @@ -391,7 +390,10 @@ pub trait LoadPendingBlock: 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); @@ -399,7 +401,6 @@ pub trait LoadPendingBlock: 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 627fd2b2df72..816247179209 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 storage( &self, diff --git a/crates/stages/stages/src/stages/execution.rs b/crates/stages/stages/src/stages/execution.rs index 47cd9d0445a2..d2135a2f1e23 100644 --- a/crates/stages/stages/src/stages/execution.rs +++ b/crates/stages/stages/src/stages/execution.rs @@ -15,7 +15,7 @@ use reth_primitives_traits::format_gas_throughput; use reth_provider::{ providers::{StaticFileProvider, StaticFileProviderRWRefMut, StaticFileWriter}, writer::UnifiedStorageWriter, - BlockReader, DBProvider, HeaderProvider, LatestStateProviderRef, OriginalValuesKnown, + AsLatestStateProviderRef, BlockReader, DBProvider, HeaderProvider, OriginalValuesKnown, ProviderError, StateChangeWriter, StateWriter, StaticFileProviderFactory, StatsReader, TransactionVariant, }; @@ -45,8 +45,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`] @@ -174,8 +175,12 @@ impl ExecutionStage { impl Stage for ExecutionStage where E: BlockExecutorProvider, - Provider: - DBProvider + BlockReader + StaticFileProviderFactory + StatsReader + StateChangeWriter, + Provider: DBProvider + + BlockReader + + StaticFileProviderFactory + + StatsReader + + StateChangeWriter + + AsLatestStateProviderRef, for<'a> UnifiedStorageWriter<'a, Provider, StaticFileProviderRWRefMut<'a>>: StateWriter, { /// Return the id of the stage @@ -219,10 +224,7 @@ where None }; - let db = StateProviderDatabase(LatestStateProviderRef::new( - provider.tx_ref(), - provider.static_file_provider(), - )); + let db = StateProviderDatabase(provider.latest()); let mut executor = self.executor_provider.batch_executor(db); executor.set_tip(max_block); executor.set_prune_modes(prune_modes); diff --git a/crates/storage/provider/src/providers/blockchain_provider.rs b/crates/storage/provider/src/providers/blockchain_provider.rs index 64a8a204a329..2f546f249f5c 100644 --- a/crates/storage/provider/src/providers/blockchain_provider.rs +++ b/crates/storage/provider/src/providers/blockchain_provider.rs @@ -29,7 +29,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, HashedPostStateProvider, StorageChangeSetReader}; use reth_storage_errors::provider::ProviderResult; use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg}; use std::{ @@ -750,6 +750,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.rs b/crates/storage/provider/src/providers/consistent.rs index e6ca1a919324..22e41ac07cb1 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_eips::{BlockHashOrNumber, BlockId, BlockNumHash, BlockNumberOrTag, HashOrNumber}; use alloy_primitives::{Address, BlockHash, BlockNumber, Sealable, TxHash, TxNumber, B256, U256}; @@ -106,7 +106,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/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 04a30ce90aaa..4f96e20de2ba 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}, @@ -157,7 +159,10 @@ impl ProviderFactory { #[track_caller] pub fn latest(&self) -> ProviderResult { trace!(target: "providers::db", "Returning latest state provider"); - Ok(Box::new(LatestStateProvider::new(self.db.tx()?, self.static_file_provider()))) + Ok(Box::new(LatestStateProvider::<_, N::StateCommitment>::new( + self.db.tx()?, + self.static_file_provider(), + ))) } /// Storage provider for state at that given block @@ -605,6 +610,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 81affa0d804f..a6c88a644f5f 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_eips::BlockHashOrNumber; use alloy_primitives::{keccak256, Address, BlockHash, BlockNumber, TxHash, TxNumber, B256, U256}; @@ -47,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}; use revm::{ db::states::{PlainStateReverts, PlainStorageChangeset, PlainStorageRevert, StateChangeset}, primitives::{BlockEnv, CfgEnvWithHandlerCfg}, @@ -146,12 +151,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.tx, self.static_file_provider.clone()))) - } - /// Storage provider for state at that given block hash pub fn history_by_block_hash<'a>( &'a self, @@ -162,7 +161,7 @@ impl DatabaseProvider { if block_number == self.best_block_number().unwrap_or_default() && block_number == self.last_block_number().unwrap_or_default() { - return Ok(Box::new(LatestStateProviderRef::new( + return Ok(Box::new(LatestStateProviderRef::<'_, _, N::StateCommitment>::new( &self.tx, self.static_file_provider.clone(), ))) @@ -176,7 +175,7 @@ impl DatabaseProvider { let storage_history_prune_checkpoint = self.get_prune_checkpoint(PruneSegment::StorageHistory)?; - let mut state_provider = HistoricalStateProviderRef::new( + let mut state_provider = HistoricalStateProviderRef::<'_, _, N::StateCommitment>::new( &self.tx, block_number, self.static_file_provider.clone(), @@ -246,7 +245,10 @@ 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.tx, self.static_file_provider))) + return Ok(Box::new(LatestStateProvider::<_, N::StateCommitment>::new( + self.tx, + self.static_file_provider, + ))) } // +1 as the changeset that we want is the one that was applied after this block. @@ -257,8 +259,11 @@ impl TryIntoHistoricalStateProvider for Databa let storage_history_prune_checkpoint = self.get_prune_checkpoint(PruneSegment::StorageHistory)?; - let mut state_provider = - HistoricalStateProvider::new(self.tx, block_number, self.static_file_provider); + let mut state_provider = HistoricalStateProvider::<_, N::StateCommitment>::new( + self.tx, + block_number, + self.static_file_provider, + ); // If we pruned account or storage history, we can't return state on every historical block. // Instead, we should cap it at the latest prune checkpoint for corresponding prune segment. @@ -281,6 +286,17 @@ impl TryIntoHistoricalStateProvider for Databa } } +impl AsLatestStateProviderRef for DatabaseProvider { + /// State provider for latest block + fn latest<'a>(&'a self) -> Box { + trace!(target: "providers::db", "Returning latest state provider"); + Box::new(LatestStateProviderRef::<'_, _, N::StateCommitment>::new( + &self.tx, + self.static_file_provider.clone(), + )) + } +} + impl + 'static> DatabaseProvider { @@ -3497,6 +3513,28 @@ impl ChainStateBlockWriter for DatabaseProvider HashedPostStateProvider for DatabaseProvider { + 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.tx_ref(), + block_number, + ) + .map_err(Into::into) + } +} + impl DBProvider for DatabaseProvider { type Tx = TX; diff --git a/crates/storage/provider/src/providers/state/historical.rs b/crates/storage/provider/src/providers/state/historical.rs index 56a1d057e704..48375e048d1a 100644 --- a/crates/storage/provider/src/providers/state/historical.rs +++ b/crates/storage/provider/src/providers/state/historical.rs @@ -15,7 +15,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::ProviderResult; use reth_trie::{ proof::{Proof, StorageProof}, @@ -25,9 +25,9 @@ use reth_trie::{ }; use reth_trie_db::{ DatabaseHashedPostState, DatabaseHashedStorage, DatabaseProof, DatabaseStateRoot, - DatabaseStorageProof, DatabaseStorageRoot, DatabaseTrieWitness, + DatabaseStorageProof, DatabaseStorageRoot, DatabaseTrieWitness, StateCommitment, }; -use std::fmt::Debug; +use std::{fmt::Debug, marker::PhantomData}; /// State provider for a given block number which takes a tx reference. /// @@ -41,7 +41,7 @@ use std::fmt::Debug; /// - [`tables::AccountChangeSets`] /// - [`tables::StorageChangeSets`] #[derive(Debug)] -pub struct HistoricalStateProviderRef<'b, TX: DbTx> { +pub struct HistoricalStateProviderRef<'b, TX: DbTx, SC> { /// Transaction tx: &'b TX, /// Block number is main index for the history state of accounts and storages. @@ -50,6 +50,8 @@ pub struct HistoricalStateProviderRef<'b, TX: DbTx> { lowest_available_blocks: LowestAvailableBlocks, /// Static File provider static_file_provider: StaticFileProvider, + /// Marker to associate the `StateCommitment` type with this provider. + _marker: PhantomData, } #[derive(Debug, Eq, PartialEq)] @@ -60,14 +62,20 @@ pub enum HistoryInfo { MaybeInPlainState, } -impl<'b, TX: DbTx> HistoricalStateProviderRef<'b, TX> { +impl<'b, TX: DbTx, SC: StateCommitment> HistoricalStateProviderRef<'b, TX, SC> { /// Create new `StateProvider` for historical block number pub fn new( tx: &'b TX, block_number: BlockNumber, static_file_provider: StaticFileProvider, ) -> Self { - Self { tx, block_number, lowest_available_blocks: Default::default(), static_file_provider } + Self { + tx, + block_number, + lowest_available_blocks: Default::default(), + static_file_provider, + _marker: PhantomData, + } } /// Create new `StateProvider` for historical block number and lowest block numbers at which @@ -78,7 +86,13 @@ impl<'b, TX: DbTx> HistoricalStateProviderRef<'b, TX> { lowest_available_blocks: LowestAvailableBlocks, static_file_provider: StaticFileProvider, ) -> Self { - Self { tx, block_number, lowest_available_blocks, static_file_provider } + Self { + tx, + block_number, + lowest_available_blocks, + static_file_provider, + _marker: PhantomData, + } } /// Lookup an account in the `AccountsHistory` table @@ -146,7 +160,7 @@ impl<'b, TX: DbTx> HistoricalStateProviderRef<'b, TX> { ); } - 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. @@ -248,7 +262,7 @@ impl<'b, TX: DbTx> HistoricalStateProviderRef<'b, TX> { } } -impl AccountReader for HistoricalStateProviderRef<'_, TX> { +impl AccountReader for HistoricalStateProviderRef<'_, TX, SC> { /// Get basic account information. fn basic_account(&self, address: Address) -> ProviderResult> { match self.account_history_lookup(address)? { @@ -270,7 +284,7 @@ impl AccountReader for HistoricalStateProviderRef<'_, TX> { } } -impl BlockHashReader for HistoricalStateProviderRef<'_, TX> { +impl BlockHashReader for HistoricalStateProviderRef<'_, TX, SC> { /// Get block hash by number. fn block_hash(&self, number: u64) -> ProviderResult> { self.static_file_provider.get_with_static_file_or_database( @@ -306,7 +320,7 @@ impl BlockHashReader for HistoricalStateProviderRef<'_, TX> { } } -impl StateRootProvider for HistoricalStateProviderRef<'_, TX> { +impl StateRootProvider for HistoricalStateProviderRef<'_, TX, SC> { fn state_root(&self, hashed_state: HashedPostState) -> ProviderResult { let mut revert_state = self.revert_state()?; revert_state.extend(hashed_state); @@ -340,7 +354,7 @@ impl StateRootProvider for HistoricalStateProviderRef<'_, TX> { } } -impl StorageRootProvider for HistoricalStateProviderRef<'_, TX> { +impl StorageRootProvider for HistoricalStateProviderRef<'_, TX, SC> { fn storage_root( &self, address: Address, @@ -365,7 +379,7 @@ impl StorageRootProvider for HistoricalStateProviderRef<'_, TX> { } } -impl StateProofProvider for HistoricalStateProviderRef<'_, TX> { +impl StateProofProvider for HistoricalStateProviderRef<'_, TX, SC> { /// Get account and storage proofs. fn proof( &self, @@ -397,7 +411,25 @@ impl StateProofProvider for HistoricalStateProviderRef<'_, TX> { } } -impl StateProvider for HistoricalStateProviderRef<'_, TX> { +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( &self, @@ -437,7 +469,7 @@ impl StateProvider for HistoricalStateProviderRef<'_, TX> { /// State provider for a given block number. /// For more detailed description, see [`HistoricalStateProviderRef`]. #[derive(Debug)] -pub struct HistoricalStateProvider { +pub struct HistoricalStateProvider { /// Database transaction tx: TX, /// State at the block number is the main indexer of the state. @@ -446,16 +478,24 @@ pub struct HistoricalStateProvider { lowest_available_blocks: LowestAvailableBlocks, /// Static File provider static_file_provider: StaticFileProvider, + /// Marker to associate the `StateCommitment` type with this provider. + _marker: PhantomData, } -impl HistoricalStateProvider { +impl HistoricalStateProvider { /// Create new `StateProvider` for historical block number pub fn new( tx: TX, block_number: BlockNumber, static_file_provider: StaticFileProvider, ) -> Self { - Self { tx, block_number, lowest_available_blocks: Default::default(), static_file_provider } + Self { + tx, + block_number, + lowest_available_blocks: Default::default(), + static_file_provider, + _marker: PhantomData, + } } /// Set the lowest block number at which the account history is available. @@ -478,7 +518,7 @@ impl HistoricalStateProvider { /// Returns a new provider that takes the `TX` as reference #[inline(always)] - fn as_ref(&self) -> HistoricalStateProviderRef<'_, TX> { + fn as_ref(&self) -> HistoricalStateProviderRef<'_, TX, SC> { HistoricalStateProviderRef::new_with_lowest_available_blocks( &self.tx, self.block_number, @@ -489,7 +529,7 @@ impl HistoricalStateProvider { } // Delegates all provider impls to [HistoricalStateProviderRef] -delegate_provider_impls!(HistoricalStateProvider where [TX: DbTx]); +delegate_provider_impls!(HistoricalStateProvider where [TX: DbTx, SC: StateCommitment]); /// Lowest blocks at which different parts of the state are available. /// They may be [Some] if pruning is enabled. @@ -535,6 +575,18 @@ mod tests { }; use reth_primitives::{Account, StorageEntry}; use reth_storage_errors::provider::ProviderError; + use reth_trie_db::{MerklePatriciaTrie, StateCommitment}; + + type TestHistoricalStateProviderRefRO<'a> = HistoricalStateProviderRef< + 'a, + reth_db::mdbx::tx::Tx, + MerklePatriciaTrie, + >; + type TestHistoricalStateProviderRefRW<'a> = HistoricalStateProviderRef< + 'a, + reth_db::mdbx::tx::Tx, + MerklePatriciaTrie, + >; const ADDRESS: Address = address!("0000000000000000000000000000000000000001"); const HIGHER_ADDRESS: Address = address!("0000000000000000000000000000000000000005"); @@ -542,8 +594,8 @@ mod tests { const fn assert_state_provider() {} #[allow(dead_code)] - const fn assert_historical_state_provider() { - assert_state_provider::>(); + const fn assert_historical_state_provider() { + assert_state_provider::>(); } #[test] @@ -614,58 +666,58 @@ mod tests { // run assert_eq!( - HistoricalStateProviderRef::new(&tx, 1, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 1, static_file_provider.clone()) .basic_account(ADDRESS), Ok(None) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 2, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 2, static_file_provider.clone()) .basic_account(ADDRESS), Ok(Some(acc_at3)) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 3, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 3, static_file_provider.clone()) .basic_account(ADDRESS), Ok(Some(acc_at3)) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 4, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 4, static_file_provider.clone()) .basic_account(ADDRESS), Ok(Some(acc_at7)) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 7, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 7, static_file_provider.clone()) .basic_account(ADDRESS), Ok(Some(acc_at7)) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 9, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 9, static_file_provider.clone()) .basic_account(ADDRESS), Ok(Some(acc_at10)) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 10, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 10, static_file_provider.clone()) .basic_account(ADDRESS), Ok(Some(acc_at10)) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 11, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 11, static_file_provider.clone()) .basic_account(ADDRESS), Ok(Some(acc_at15)) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 16, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 16, static_file_provider.clone()) .basic_account(ADDRESS), Ok(Some(acc_plain)) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 1, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 1, static_file_provider.clone()) .basic_account(HIGHER_ADDRESS), Ok(None) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 1000, static_file_provider) + TestHistoricalStateProviderRefRO::new(&tx, 1000, static_file_provider) .basic_account(HIGHER_ADDRESS), Ok(Some(higher_acc_plain)) ); @@ -726,52 +778,52 @@ mod tests { // run assert_eq!( - HistoricalStateProviderRef::new(&tx, 0, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 0, static_file_provider.clone()) .storage(ADDRESS, STORAGE), Ok(None) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 3, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 3, static_file_provider.clone()) .storage(ADDRESS, STORAGE), Ok(Some(U256::ZERO)) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 4, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 4, static_file_provider.clone()) .storage(ADDRESS, STORAGE), Ok(Some(entry_at7.value)) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 7, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 7, static_file_provider.clone()) .storage(ADDRESS, STORAGE), Ok(Some(entry_at7.value)) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 9, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 9, static_file_provider.clone()) .storage(ADDRESS, STORAGE), Ok(Some(entry_at10.value)) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 10, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 10, static_file_provider.clone()) .storage(ADDRESS, STORAGE), Ok(Some(entry_at10.value)) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 11, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 11, static_file_provider.clone()) .storage(ADDRESS, STORAGE), Ok(Some(entry_at15.value)) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 16, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 16, static_file_provider.clone()) .storage(ADDRESS, STORAGE), Ok(Some(entry_plain.value)) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 1, static_file_provider.clone()) + TestHistoricalStateProviderRefRO::new(&tx, 1, static_file_provider.clone()) .storage(HIGHER_ADDRESS, STORAGE), Ok(None) ); assert_eq!( - HistoricalStateProviderRef::new(&tx, 1000, static_file_provider) + TestHistoricalStateProviderRefRO::new(&tx, 1000, static_file_provider) .storage(HIGHER_ADDRESS, STORAGE), Ok(Some(higher_entry_plain.value)) ); @@ -785,7 +837,7 @@ mod tests { // provider block_number < lowest available block number, // i.e. state at provider block is pruned - let provider = HistoricalStateProviderRef::new_with_lowest_available_blocks( + let provider = TestHistoricalStateProviderRefRW::new_with_lowest_available_blocks( &tx, 2, LowestAvailableBlocks { @@ -805,7 +857,7 @@ mod tests { // provider block_number == lowest available block number, // i.e. state at provider block is available - let provider = HistoricalStateProviderRef::new_with_lowest_available_blocks( + let provider = TestHistoricalStateProviderRefRW::new_with_lowest_available_blocks( &tx, 2, LowestAvailableBlocks { @@ -822,7 +874,7 @@ mod tests { // provider block_number == lowest available block number, // i.e. state at provider block is available - let provider = HistoricalStateProviderRef::new_with_lowest_available_blocks( + let provider = TestHistoricalStateProviderRefRW::new_with_lowest_available_blocks( &tx, 2, LowestAvailableBlocks { diff --git a/crates/storage/provider/src/providers/state/latest.rs b/crates/storage/provider/src/providers/state/latest.rs index fdcbfc4937fe..34ea4644cd8d 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,34 +21,37 @@ use reth_trie::{ AccountProof, HashedPostState, HashedStorage, MultiProof, StateRoot, StorageRoot, TrieInput, }; use reth_trie_db::{ - DatabaseProof, DatabaseStateRoot, DatabaseStorageProof, DatabaseStorageRoot, - DatabaseTrieWitness, + DatabaseHashedPostState, DatabaseProof, DatabaseStateRoot, DatabaseStorageProof, + DatabaseStorageRoot, DatabaseTrieWitness, StateCommitment, }; +use std::marker::PhantomData; /// State provider over latest state that takes tx reference. #[derive(Debug)] -pub struct LatestStateProviderRef<'b, TX: DbTx> { +pub struct LatestStateProviderRef<'b, TX: DbTx, SC> { /// database transaction tx: &'b TX, /// Static File provider static_file_provider: StaticFileProvider, + /// Marker to associate the `StateCommitment` type with this provider. + _marker: PhantomData, } -impl<'b, TX: DbTx> LatestStateProviderRef<'b, TX> { +impl<'b, TX: DbTx, SC> LatestStateProviderRef<'b, TX, SC> { /// Create new state provider pub const fn new(tx: &'b TX, static_file_provider: StaticFileProvider) -> Self { - Self { tx, static_file_provider } + Self { tx, static_file_provider, _marker: PhantomData } } } -impl AccountReader for LatestStateProviderRef<'_, TX> { +impl AccountReader for LatestStateProviderRef<'_, TX, SC> { /// Get basic account information. fn basic_account(&self, address: Address) -> ProviderResult> { self.tx.get::(address).map_err(Into::into) } } -impl BlockHashReader for LatestStateProviderRef<'_, TX> { +impl BlockHashReader for LatestStateProviderRef<'_, TX, SC> { /// Get block hash by number. fn block_hash(&self, number: u64) -> ProviderResult> { self.static_file_provider.get_with_static_file_or_database( @@ -84,7 +87,7 @@ impl BlockHashReader for LatestStateProviderRef<'_, TX> { } } -impl StateRootProvider for LatestStateProviderRef<'_, TX> { +impl StateRootProvider for LatestStateProviderRef<'_, TX, SC> { fn state_root(&self, hashed_state: HashedPostState) -> ProviderResult { StateRoot::overlay_root(self.tx, hashed_state) .map_err(|err| ProviderError::Database(err.into())) @@ -112,7 +115,7 @@ impl StateRootProvider for LatestStateProviderRef<'_, TX> { } } -impl StorageRootProvider for LatestStateProviderRef<'_, TX> { +impl StorageRootProvider for LatestStateProviderRef<'_, TX, SC> { fn storage_root( &self, address: Address, @@ -133,7 +136,7 @@ impl StorageRootProvider for LatestStateProviderRef<'_, TX> { } } -impl StateProofProvider for LatestStateProviderRef<'_, TX> { +impl StateProofProvider for LatestStateProviderRef<'_, TX, SC> { fn proof( &self, input: TrieInput, @@ -161,7 +164,23 @@ impl StateProofProvider for LatestStateProviderRef<'_, TX> { } } -impl StateProvider for LatestStateProviderRef<'_, TX> { +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( &self, @@ -185,28 +204,30 @@ impl StateProvider for LatestStateProviderRef<'_, TX> { /// State provider for the latest state. #[derive(Debug)] -pub struct LatestStateProvider { +pub struct LatestStateProvider { /// database transaction db: TX, /// Static File provider static_file_provider: StaticFileProvider, + /// Marker to associate the `StateCommitment` type with this provider. + _marker: PhantomData, } -impl LatestStateProvider { +impl LatestStateProvider { /// Create new state provider pub const fn new(db: TX, static_file_provider: StaticFileProvider) -> Self { - Self { db, static_file_provider } + Self { db, static_file_provider, _marker: PhantomData } } /// Returns a new provider that takes the `TX` as reference #[inline(always)] - fn as_ref(&self) -> LatestStateProviderRef<'_, TX> { + fn as_ref(&self) -> LatestStateProviderRef<'_, TX, SC> { LatestStateProviderRef::new(&self.db, self.static_file_provider.clone()) } } // Delegates all provider impls to [LatestStateProviderRef] -delegate_provider_impls!(LatestStateProvider where [TX: DbTx]); +delegate_provider_impls!(LatestStateProvider where [TX: DbTx, SC: StateCommitment]); #[cfg(test)] mod tests { @@ -214,7 +235,7 @@ mod tests { const fn assert_state_provider() {} #[allow(dead_code)] - const fn assert_latest_state_provider() { - assert_state_provider::>(); + const fn assert_latest_state_provider() { + assert_state_provider::>(); } } diff --git a/crates/storage/provider/src/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 e2e08e61a86f..6a5d45875687 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}; @@ -680,6 +681,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 f6f7e185de63..e84bb0552b39 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 d37940f04787..8288aed96d82 100644 --- a/crates/storage/storage-api/src/state.rs +++ b/crates/storage/storage-api/src/state.rs @@ -6,9 +6,10 @@ use alloy_consensus::constants::KECCAK_EMPTY; 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; use reth_storage_errors::provider::{ProviderError, ProviderResult}; +use reth_trie::HashedPostState; /// Type alias of boxed [`StateProvider`]. pub type StateProviderBox = Box; @@ -21,6 +22,7 @@ pub trait StateProvider: + StateRootProvider + StorageRootProvider + StateProofProvider + + HashedPostStateProvider + Send + Sync { @@ -91,6 +93,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. /// @@ -168,6 +177,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);