Introduce HashedPostStateProvider (#12607)

Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
frisitano
2024-12-04 00:56:17 +08:00
committed by GitHub
parent e4c7fac9db
commit 886471d693
42 changed files with 318 additions and 137 deletions

5
Cargo.lock generated
View File

@ -7528,7 +7528,6 @@ dependencies = [
"reth-provider", "reth-provider",
"reth-revm", "reth-revm",
"reth-transaction-pool", "reth-transaction-pool",
"reth-trie",
"revm", "revm",
"tracing", "tracing",
] ]
@ -8449,7 +8448,6 @@ dependencies = [
"reth-revm", "reth-revm",
"reth-rpc-types-compat", "reth-rpc-types-compat",
"reth-transaction-pool", "reth-transaction-pool",
"reth-trie",
"revm", "revm",
"sha2 0.10.8", "sha2 0.10.8",
"thiserror 2.0.3", "thiserror 2.0.3",
@ -8861,7 +8859,6 @@ dependencies = [
"reth-tasks", "reth-tasks",
"reth-testing-utils", "reth-testing-utils",
"reth-transaction-pool", "reth-transaction-pool",
"reth-trie",
"revm", "revm",
"revm-inspectors", "revm-inspectors",
"revm-primitives", "revm-primitives",
@ -9041,7 +9038,6 @@ dependencies = [
"reth-rpc-types-compat", "reth-rpc-types-compat",
"reth-tasks", "reth-tasks",
"reth-transaction-pool", "reth-transaction-pool",
"reth-trie",
"reth-trie-common", "reth-trie-common",
"revm", "revm",
"revm-inspectors", "revm-inspectors",
@ -9292,6 +9288,7 @@ dependencies = [
"reth-storage-errors", "reth-storage-errors",
"reth-trie", "reth-trie",
"reth-trie-db", "reth-trie-db",
"revm",
] ]
[[package]] [[package]]

View File

@ -263,7 +263,8 @@ impl<C: ChainSpecParser<ChainSpec = ChainSpec>> Command<C> {
let block_with_senders = let block_with_senders =
SealedBlockWithSenders::<BlockTy<N>>::new(block.clone(), senders).unwrap(); SealedBlockWithSenders::<BlockTy<N>>::new(block.clone(), senders).unwrap();
let db = StateProviderDatabase::new(blockchain_db.latest()?); let state_provider = blockchain_db.latest()?;
let db = StateProviderDatabase::new(&state_provider);
let executor = let executor =
EthExecutorProvider::ethereum(provider_factory.chain_spec()).executor(db); EthExecutorProvider::ethereum(provider_factory.chain_spec()).executor(db);
@ -273,7 +274,7 @@ impl<C: ChainSpecParser<ChainSpec = ChainSpec>> Command<C> {
ExecutionOutcome::from((block_execution_output, block.number)); ExecutionOutcome::from((block_execution_output, block.number));
debug!(target: "reth::cli", ?execution_outcome, "Executed block"); debug!(target: "reth::cli", ?execution_outcome, "Executed block");
let hashed_post_state = execution_outcome.hash_state_slow(); let hashed_post_state = state_provider.hashed_post_state(execution_outcome.state());
let (state_root, trie_updates) = StateRoot::overlay_root_with_updates( let (state_root, trie_updates) = StateRoot::overlay_root_with_updates(
provider_factory.provider()?.tx_ref(), provider_factory.provider()?.tx_ref(),
hashed_post_state.clone(), hashed_post_state.clone(),

View File

@ -24,8 +24,9 @@ use reth_node_ethereum::EthExecutorProvider;
use reth_primitives::BlockExt; use reth_primitives::BlockExt;
use reth_provider::{ use reth_provider::{
providers::ProviderNodeTypes, AccountExtReader, ChainSpecProvider, DatabaseProviderFactory, providers::ProviderNodeTypes, AccountExtReader, ChainSpecProvider, DatabaseProviderFactory,
HashingWriter, HeaderProvider, LatestStateProviderRef, OriginalValuesKnown, ProviderFactory, HashedPostStateProvider, HashingWriter, HeaderProvider, LatestStateProviderRef,
StageCheckpointReader, StateWriter, StorageLocation, StorageReader, OriginalValuesKnown, ProviderFactory, StageCheckpointReader, StateWriter, StorageLocation,
StorageReader,
}; };
use reth_revm::database::StateProviderDatabase; use reth_revm::database::StateProviderDatabase;
use reth_stages::StageId; use reth_stages::StageId;
@ -143,7 +144,8 @@ impl<C: ChainSpecParser<ChainSpec = ChainSpec>> Command<C> {
) )
.await?; .await?;
let db = StateProviderDatabase::new(LatestStateProviderRef::new(&provider)); let state_provider = LatestStateProviderRef::new(&provider);
let db = StateProviderDatabase::new(&state_provider);
let executor = EthExecutorProvider::ethereum(provider_factory.chain_spec()).executor(db); let executor = EthExecutorProvider::ethereum(provider_factory.chain_spec()).executor(db);
@ -165,7 +167,7 @@ impl<C: ChainSpecParser<ChainSpec = ChainSpec>> Command<C> {
// Unpacked `BundleState::state_root_slow` function // Unpacked `BundleState::state_root_slow` function
let (in_memory_state_root, in_memory_updates) = StateRoot::overlay_root_with_updates( let (in_memory_state_root, in_memory_updates) = StateRoot::overlay_root_with_updates(
provider.tx_ref(), provider.tx_ref(),
execution_outcome.hash_state_slow(), state_provider.hashed_post_state(execution_outcome.state()),
)?; )?;
if in_memory_state_root == block.state_root { if in_memory_state_root == block.state_root {

View File

@ -24,8 +24,8 @@ use reth_primitives::{
use reth_provider::{ use reth_provider::{
BlockExecutionWriter, BlockNumReader, BlockWriter, CanonStateNotification, BlockExecutionWriter, BlockNumReader, BlockWriter, CanonStateNotification,
CanonStateNotificationSender, CanonStateNotifications, ChainSpecProvider, ChainSplit, CanonStateNotificationSender, CanonStateNotifications, ChainSpecProvider, ChainSplit,
ChainSplitTarget, DBProvider, DisplayBlocksChain, HeaderProvider, ProviderError, ChainSplitTarget, DBProvider, DisplayBlocksChain, HashedPostStateProvider, HeaderProvider,
StaticFileProviderFactory, StorageLocation, ProviderError, StaticFileProviderFactory, StorageLocation,
}; };
use reth_stages_api::{MetricEvent, MetricEventsSender}; use reth_stages_api::{MetricEvent, MetricEventsSender};
use reth_storage_errors::provider::{ProviderResult, RootMismatch}; use reth_storage_errors::provider::{ProviderResult, RootMismatch};
@ -1215,7 +1215,7 @@ where
recorder: &mut MakeCanonicalDurationsRecorder, recorder: &mut MakeCanonicalDurationsRecorder,
) -> Result<(), CanonicalError> { ) -> Result<(), CanonicalError> {
let (blocks, state, chain_trie_updates) = chain.into_inner(); let (blocks, state, chain_trie_updates) = chain.into_inner();
let hashed_state = state.hash_state_slow(); let hashed_state = self.externals.provider_factory.hashed_post_state(state.state());
let prefix_sets = hashed_state.construct_prefix_sets().freeze(); let prefix_sets = hashed_state.construct_prefix_sets().freeze();
let hashed_state_sorted = hashed_state.into_sorted(); let hashed_state_sorted = hashed_state.into_sorted();
@ -1885,7 +1885,12 @@ mod tests {
); );
let provider = tree.externals.provider_factory.provider().unwrap(); let provider = tree.externals.provider_factory.provider().unwrap();
let prefix_sets = exec5.hash_state_slow().construct_prefix_sets().freeze(); let prefix_sets = tree
.externals
.provider_factory
.hashed_post_state(exec5.state())
.construct_prefix_sets()
.freeze();
let state_root = let state_root =
StateRoot::from_tx(provider.tx_ref()).with_prefix_sets(prefix_sets).root().unwrap(); StateRoot::from_tx(provider.tx_ref()).with_prefix_sets(prefix_sets).root().unwrap();
assert_eq!(state_root, block5.state_root); assert_eq!(state_root, block5.state_root);

View File

@ -18,11 +18,11 @@ use reth_execution_types::{Chain, ExecutionOutcome};
use reth_primitives::{GotExpected, SealedBlockWithSenders, SealedHeader}; use reth_primitives::{GotExpected, SealedBlockWithSenders, SealedHeader};
use reth_provider::{ use reth_provider::{
providers::{BundleStateProvider, ConsistentDbView, TreeNodeTypes}, providers::{BundleStateProvider, ConsistentDbView, TreeNodeTypes},
DBProvider, FullExecutionDataProvider, ProviderError, StateRootProvider, DBProvider, FullExecutionDataProvider, HashedPostStateProvider, ProviderError,
TryIntoHistoricalStateProvider, StateRootProvider, TryIntoHistoricalStateProvider,
}; };
use reth_revm::database::StateProviderDatabase; use reth_revm::database::StateProviderDatabase;
use reth_trie::{updates::TrieUpdates, HashedPostState, TrieInput}; use reth_trie::{updates::TrieUpdates, TrieInput};
use reth_trie_parallel::root::ParallelStateRoot; use reth_trie_parallel::root::ParallelStateRoot;
use std::{ use std::{
collections::BTreeMap, collections::BTreeMap,
@ -228,14 +228,13 @@ impl AppendableChain {
execution_outcome.extend(initial_execution_outcome.clone()); execution_outcome.extend(initial_execution_outcome.clone());
ParallelStateRoot::new( ParallelStateRoot::new(
consistent_view, consistent_view,
TrieInput::from_state(execution_outcome.hash_state_slow()), TrieInput::from_state(provider.hashed_post_state(execution_outcome.state())),
) )
.incremental_root_with_updates() .incremental_root_with_updates()
.map(|(root, updates)| (root, Some(updates))) .map(|(root, updates)| (root, Some(updates)))
.map_err(ProviderError::from)? .map_err(ProviderError::from)?
} else { } else {
let hashed_state = let hashed_state = provider.hashed_post_state(initial_execution_outcome.state());
HashedPostState::from_bundle_state(&initial_execution_outcome.state().state);
let state_root = provider.state_root(hashed_state)?; let state_root = provider.state_root(hashed_state)?;
(state_root, None) (state_root, None)
}; };

View File

@ -26,6 +26,7 @@ reth-trie.workspace = true
alloy-eips.workspace = true alloy-eips.workspace = true
alloy-primitives.workspace = true alloy-primitives.workspace = true
alloy-consensus.workspace = true alloy-consensus.workspace = true
revm.workspace = true
# async # async
tokio = { workspace = true, default-features = false, features = ["sync", "macros"] } tokio = { workspace = true, default-features = false, features = ["sync", "macros"] }
@ -44,7 +45,6 @@ pin-project.workspace = true
alloy-signer = { workspace = true, optional = true } alloy-signer = { workspace = true, optional = true }
alloy-signer-local = { workspace = true, optional = true } alloy-signer-local = { workspace = true, optional = true }
rand = { workspace = true, optional = true } rand = { workspace = true, optional = true }
revm = { workspace = true, optional = true }
[dev-dependencies] [dev-dependencies]
reth-testing-utils.workspace = true reth-testing-utils.workspace = true
@ -52,17 +52,15 @@ alloy-signer.workspace = true
alloy-signer-local.workspace = true alloy-signer-local.workspace = true
alloy-consensus.workspace = true alloy-consensus.workspace = true
rand.workspace = true rand.workspace = true
revm.workspace = true
[features] [features]
test-utils = [ test-utils = [
"alloy-signer", "alloy-signer",
"alloy-signer-local", "alloy-signer-local",
"rand", "rand",
"revm",
"reth-chainspec/test-utils", "reth-chainspec/test-utils",
"reth-primitives/test-utils", "reth-primitives/test-utils",
"reth-primitives-traits/test-utils", "reth-primitives-traits/test-utils",
"reth-trie/test-utils", "reth-trie/test-utils",
"revm?/test-utils", "revm/test-utils",
] ]

View File

@ -949,8 +949,8 @@ mod tests {
use reth_errors::ProviderResult; use reth_errors::ProviderResult;
use reth_primitives::{Account, Bytecode, EthPrimitives, Receipt}; use reth_primitives::{Account, Bytecode, EthPrimitives, Receipt};
use reth_storage_api::{ use reth_storage_api::{
AccountReader, BlockHashReader, StateProofProvider, StateProvider, StateRootProvider, AccountReader, BlockHashReader, HashedPostStateProvider, StateProofProvider, StateProvider,
StorageRootProvider, StateRootProvider, StorageRootProvider,
}; };
use reth_trie::{ use reth_trie::{
AccountProof, HashedStorage, MultiProof, StorageMultiProof, StorageProof, TrieInput, AccountProof, HashedStorage, MultiProof, StorageMultiProof, StorageProof, TrieInput,
@ -1047,6 +1047,12 @@ mod tests {
} }
} }
impl HashedPostStateProvider for MockStateProvider {
fn hashed_post_state(&self, _bundle_state: &revm::db::BundleState) -> HashedPostState {
HashedPostState::default()
}
}
impl StorageRootProvider for MockStateProvider { impl StorageRootProvider for MockStateProvider {
fn storage_root( fn storage_root(
&self, &self,

View File

@ -8,13 +8,14 @@ use alloy_primitives::{
use reth_errors::ProviderResult; use reth_errors::ProviderResult;
use reth_primitives::{Account, Bytecode, NodePrimitives}; use reth_primitives::{Account, Bytecode, NodePrimitives};
use reth_storage_api::{ use reth_storage_api::{
AccountReader, BlockHashReader, StateProofProvider, StateProvider, StateRootProvider, AccountReader, BlockHashReader, HashedPostStateProvider, StateProofProvider, StateProvider,
StorageRootProvider, StateRootProvider, StorageRootProvider,
}; };
use reth_trie::{ use reth_trie::{
updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof,
StorageMultiProof, TrieInput, StorageMultiProof, TrieInput,
}; };
use revm::db::BundleState;
use std::sync::OnceLock; use std::sync::OnceLock;
/// A state provider that stores references to in-memory blocks along with their state as well as a /// A state provider that stores references to in-memory blocks along with their state as well as a
@ -218,6 +219,12 @@ macro_rules! impl_state_provider {
} }
} }
impl $($tokens)* HashedPostStateProvider for $type {
fn hashed_post_state(&self, bundle_state: &BundleState) -> HashedPostState {
self.historical.hashed_post_state(bundle_state)
}
}
impl $($tokens)* StateProvider for $type { impl $($tokens)* StateProvider for $type {
fn storage( fn storage(
&self, &self,

View File

@ -17,7 +17,7 @@ use reth_revm::{
}; };
use reth_rpc_api::DebugApiClient; use reth_rpc_api::DebugApiClient;
use reth_tracing::tracing::warn; use reth_tracing::tracing::warn;
use reth_trie::{updates::TrieUpdates, HashedPostState, HashedStorage}; use reth_trie::{updates::TrieUpdates, HashedStorage};
use serde::Serialize; use serde::Serialize;
use std::{collections::HashMap, fmt::Debug, fs::File, io::Write, path::PathBuf}; use std::{collections::HashMap, fmt::Debug, fs::File, io::Write, path::PathBuf};
@ -129,7 +129,7 @@ where
// //
// Note: We grab *all* accounts in the cache here, as the `BundleState` prunes // Note: We grab *all* accounts in the cache here, as the `BundleState` prunes
// referenced accounts + storage slots. // referenced accounts + storage slots.
let mut hashed_state = HashedPostState::from_bundle_state(&bundle_state.state); let mut hashed_state = db.database.hashed_post_state(&bundle_state);
for (address, account) in db.cache.accounts { for (address, account) in db.cache.accounts {
let hashed_address = keccak256(address); let hashed_address = keccak256(address);
hashed_state hashed_state

View File

@ -41,8 +41,8 @@ use reth_primitives::{
}; };
use reth_provider::{ use reth_provider::{
providers::ConsistentDbView, BlockReader, DatabaseProviderFactory, ExecutionOutcome, providers::ConsistentDbView, BlockReader, DatabaseProviderFactory, ExecutionOutcome,
ProviderError, StateProviderBox, StateProviderFactory, StateReader, StateRootProvider, HashedPostStateProvider, ProviderError, StateCommitmentProvider, StateProviderBox,
TransactionVariant, StateProviderFactory, StateReader, StateRootProvider, TransactionVariant,
}; };
use reth_revm::database::StateProviderDatabase; use reth_revm::database::StateProviderDatabase;
use reth_stages_api::ControlFlow; use reth_stages_api::ControlFlow;
@ -552,6 +552,8 @@ where
+ BlockReader<Block = N::Block, Header = N::BlockHeader> + BlockReader<Block = N::Block, Header = N::BlockHeader>
+ StateProviderFactory + StateProviderFactory
+ StateReader<Receipt = reth_primitives::Receipt> + StateReader<Receipt = reth_primitives::Receipt>
+ StateCommitmentProvider
+ HashedPostStateProvider
+ Clone + Clone
+ 'static, + 'static,
<P as DatabaseProviderFactory>::Provider: BlockReader, <P as DatabaseProviderFactory>::Provider: BlockReader,
@ -1568,7 +1570,7 @@ where
.provider .provider
.get_state(block.number())? .get_state(block.number())?
.ok_or_else(|| ProviderError::StateForNumberNotFound(block.number()))?; .ok_or_else(|| ProviderError::StateForNumberNotFound(block.number()))?;
let hashed_state = execution_output.hash_state_slow(); let hashed_state = self.provider.hashed_post_state(execution_output.state());
Ok(Some(ExecutedBlock { Ok(Some(ExecutedBlock {
block: Arc::new(block), block: Arc::new(block),
@ -2242,7 +2244,7 @@ where
return Err(err.into()) return Err(err.into())
} }
let hashed_state = HashedPostState::from_bundle_state(&output.state.state); let hashed_state = self.provider.hashed_post_state(&output.state);
trace!(target: "engine::tree", block=?sealed_block.num_hash(), "Calculating block state root"); trace!(target: "engine::tree", block=?sealed_block.num_hash(), "Calculating block state root");
let root_time = Instant::now(); let root_time = Instant::now();

View File

@ -3,6 +3,7 @@
use alloy_primitives::map::{HashMap, HashSet}; use alloy_primitives::map::{HashMap, HashSet};
use reth_provider::{ use reth_provider::{
providers::ConsistentDbView, BlockReader, DBProvider, DatabaseProviderFactory, providers::ConsistentDbView, BlockReader, DBProvider, DatabaseProviderFactory,
StateCommitmentProvider,
}; };
use reth_trie::{ use reth_trie::{
proof::Proof, updates::TrieUpdates, HashedPostState, HashedStorage, MultiProof, Nibbles, proof::Proof, updates::TrieUpdates, HashedPostState, HashedStorage, MultiProof, Nibbles,
@ -179,7 +180,12 @@ pub(crate) struct StateRootTask<Factory> {
#[allow(dead_code)] #[allow(dead_code)]
impl<Factory> StateRootTask<Factory> impl<Factory> StateRootTask<Factory>
where where
Factory: DatabaseProviderFactory<Provider: BlockReader> + Clone + Send + Sync + 'static, Factory: DatabaseProviderFactory<Provider: BlockReader>
+ StateCommitmentProvider
+ Clone
+ Send
+ Sync
+ 'static,
{ {
/// Creates a new state root task with the unified message channel /// Creates a new state root task with the unified message channel
pub(crate) fn new( pub(crate) fn new(

View File

@ -29,7 +29,6 @@ use reth_revm::{
DatabaseCommit, DatabaseCommit,
}; };
use reth_rpc_types_compat::engine::payload::block_to_payload; use reth_rpc_types_compat::engine::payload::block_to_payload;
use reth_trie::HashedPostState;
use revm_primitives::{calc_excess_blob_gas, EVMError, EnvWithHandlerCfg}; use revm_primitives::{calc_excess_blob_gas, EVMError, EnvWithHandlerCfg};
use std::{ use std::{
collections::VecDeque, collections::VecDeque,
@ -382,7 +381,7 @@ where
reorg_target.number, reorg_target.number,
Default::default(), Default::default(),
); );
let hashed_state = HashedPostState::from_bundle_state(&outcome.state().state); let hashed_state = state_provider.hashed_post_state(outcome.state());
let (blob_gas_used, excess_blob_gas) = let (blob_gas_used, excess_blob_gas) =
if chain_spec.is_cancun_active_at_timestamp(reorg_target.timestamp) { if chain_spec.is_cancun_active_at_timestamp(reorg_target.timestamp) {

View File

@ -25,7 +25,6 @@ reth-basic-payload-builder.workspace = true
reth-evm.workspace = true reth-evm.workspace = true
reth-evm-ethereum.workspace = true reth-evm-ethereum.workspace = true
reth-errors.workspace = true reth-errors.workspace = true
reth-trie.workspace = true
reth-chain-state.workspace = true reth-chain-state.workspace = true
reth-chainspec.workspace = true reth-chainspec.workspace = true

View File

@ -39,7 +39,6 @@ use reth_transaction_pool::{
error::InvalidPoolTransactionError, noop::NoopTransactionPool, BestTransactions, error::InvalidPoolTransactionError, noop::NoopTransactionPool, BestTransactions,
BestTransactionsAttributes, PoolTransaction, TransactionPool, ValidPoolTransaction, BestTransactionsAttributes, PoolTransaction, TransactionPool, ValidPoolTransaction,
}; };
use reth_trie::HashedPostState;
use revm::{ use revm::{
db::{states::bundle_state::BundleRetention, State}, db::{states::bundle_state::BundleRetention, State},
primitives::{ primitives::{
@ -413,7 +412,7 @@ where
let logs_bloom = execution_outcome.block_logs_bloom(block_number).expect("Number is in range"); let logs_bloom = execution_outcome.block_logs_bloom(block_number).expect("Number is in range");
// calculate the state root // calculate the state root
let hashed_state = HashedPostState::from_bundle_state(&execution_outcome.state().state); let hashed_state = db.database.db.hashed_post_state(execution_outcome.state());
let (state_root, trie_output) = { let (state_root, trie_output) = {
db.database.inner().state_root_with_updates(hashed_state.clone()).inspect_err(|err| { db.database.inner().state_root_with_updates(hashed_state.clone()).inspect_err(|err| {
warn!(target: "payload_builder", warn!(target: "payload_builder",

View File

@ -3,7 +3,7 @@ use alloy_eips::eip7685::Requests;
use alloy_primitives::{logs_bloom, Address, BlockNumber, Bloom, Log, B256, U256}; use alloy_primitives::{logs_bloom, Address, BlockNumber, Bloom, Log, B256, U256};
use reth_primitives::Receipts; use reth_primitives::Receipts;
use reth_primitives_traits::{receipt::ReceiptExt, Account, Bytecode, Receipt, StorageEntry}; use reth_primitives_traits::{receipt::ReceiptExt, Account, Bytecode, Receipt, StorageEntry};
use reth_trie::HashedPostState; use reth_trie::{HashedPostState, KeyHasher};
use revm::{ use revm::{
db::{states::BundleState, BundleAccount}, db::{states::BundleState, BundleAccount},
primitives::AccountInfo, primitives::AccountInfo,
@ -164,8 +164,8 @@ impl<T> ExecutionOutcome<T> {
/// Returns [`HashedPostState`] for this execution outcome. /// Returns [`HashedPostState`] for this execution outcome.
/// See [`HashedPostState::from_bundle_state`] for more info. /// See [`HashedPostState::from_bundle_state`] for more info.
pub fn hash_state_slow(&self) -> HashedPostState { pub fn hash_state_slow<KH: KeyHasher>(&self) -> HashedPostState {
HashedPostState::from_bundle_state(&self.bundle.state) HashedPostState::from_bundle_state::<KH>(&self.bundle.state)
} }
/// Transform block number to the index of block. /// Transform block number to the index of block.

View File

@ -26,7 +26,6 @@ reth-payload-builder-primitives.workspace = true
reth-payload-util.workspace = true reth-payload-util.workspace = true
reth-payload-primitives = { workspace = true, features = ["op"] } reth-payload-primitives = { workspace = true, features = ["op"] }
reth-basic-payload-builder.workspace = true reth-basic-payload-builder.workspace = true
reth-trie.workspace = true
reth-chain-state.workspace = true reth-chain-state.workspace = true
# op-reth # op-reth

View File

@ -22,12 +22,14 @@ use reth_primitives::{
proofs, transaction::SignedTransactionIntoRecoveredExt, Block, BlockBody, BlockExt, Receipt, proofs, transaction::SignedTransactionIntoRecoveredExt, Block, BlockBody, BlockExt, Receipt,
SealedHeader, TransactionSigned, TxType, SealedHeader, TransactionSigned, TxType,
}; };
use reth_provider::{ProviderError, StateProofProvider, StateProviderFactory, StateRootProvider}; use reth_provider::{
HashedPostStateProvider, ProviderError, StateProofProvider, StateProviderFactory,
StateRootProvider,
};
use reth_revm::database::StateProviderDatabase; use reth_revm::database::StateProviderDatabase;
use reth_transaction_pool::{ use reth_transaction_pool::{
noop::NoopTransactionPool, BestTransactionsAttributes, PoolTransaction, TransactionPool, noop::NoopTransactionPool, BestTransactionsAttributes, PoolTransaction, TransactionPool,
}; };
use reth_trie::HashedPostState;
use revm::{ use revm::{
db::{states::bundle_state::BundleRetention, State}, db::{states::bundle_state::BundleRetention, State},
primitives::{ primitives::{
@ -339,7 +341,7 @@ where
where where
EvmConfig: ConfigureEvm<Header = Header>, EvmConfig: ConfigureEvm<Header = Header>,
DB: Database<Error = ProviderError> + AsRef<P>, DB: Database<Error = ProviderError> + AsRef<P>,
P: StateRootProvider, P: StateRootProvider + HashedPostStateProvider,
{ {
let ExecutedPayload { info, withdrawals_root } = match self.execute(&mut state, &ctx)? { let ExecutedPayload { info, withdrawals_root } = match self.execute(&mut state, &ctx)? {
BuildOutcomeKind::Better { payload } | BuildOutcomeKind::Freeze(payload) => payload, BuildOutcomeKind::Better { payload } | BuildOutcomeKind::Freeze(payload) => payload,
@ -367,17 +369,16 @@ where
execution_outcome.block_logs_bloom(block_number).expect("Number is in range"); execution_outcome.block_logs_bloom(block_number).expect("Number is in range");
// // calculate the state root // // calculate the state root
let hashed_state = HashedPostState::from_bundle_state(&execution_outcome.state().state); let state_provider = state.database.as_ref();
let hashed_state = state_provider.hashed_post_state(execution_outcome.state());
let (state_root, trie_output) = { let (state_root, trie_output) = {
state.database.as_ref().state_root_with_updates(hashed_state.clone()).inspect_err( state_provider.state_root_with_updates(hashed_state.clone()).inspect_err(|err| {
|err| { warn!(target: "payload_builder",
warn!(target: "payload_builder", parent_header=%ctx.parent().hash(),
parent_header=%ctx.parent().hash(), %err,
%err, "failed to calculate state root for payload"
"failed to calculate state root for payload" );
); })?
},
)?
}; };
// create the block header // create the block header

View File

@ -6,13 +6,13 @@ use alloy_primitives::{
}; };
use reth_primitives::{Account, Bytecode}; use reth_primitives::{Account, Bytecode};
use reth_storage_api::{ use reth_storage_api::{
AccountReader, BlockHashReader, StateProofProvider, StateProvider, StateRootProvider, AccountReader, BlockHashReader, HashedPostStateProvider, StateProofProvider, StateProvider,
StorageRootProvider, StateRootProvider, StorageRootProvider,
}; };
use reth_storage_errors::provider::ProviderResult; use reth_storage_errors::provider::ProviderResult;
use reth_trie::{ use reth_trie::{
updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, KeccakKeyHasher,
StorageMultiProof, StorageProof, TrieInput, MultiProof, StorageMultiProof, StorageProof, TrieInput,
}; };
/// Mock state for testing /// Mock state for testing
@ -150,6 +150,12 @@ impl StateProofProvider for StateProviderTest {
} }
} }
impl HashedPostStateProvider for StateProviderTest {
fn hashed_post_state(&self, bundle_state: &revm::db::BundleState) -> HashedPostState {
HashedPostState::from_bundle_state::<KeccakKeyHasher>(bundle_state.state())
}
}
impl StateProvider for StateProviderTest { impl StateProvider for StateProviderTest {
fn storage( fn storage(
&self, &self,

View File

@ -30,7 +30,6 @@ reth-rpc-eth-types.workspace = true
reth-rpc-server-types.workspace = true reth-rpc-server-types.workspace = true
reth-network-api.workspace = true reth-network-api.workspace = true
reth-node-api.workspace = true reth-node-api.workspace = true
reth-trie.workspace = true
reth-trie-common = { workspace = true, features = ["eip1186"] } reth-trie-common = { workspace = true, features = ["eip1186"] }
# ethereum # ethereum

View File

@ -36,7 +36,6 @@ use reth_transaction_pool::{
error::InvalidPoolTransactionError, BestTransactionsAttributes, PoolTransaction, error::InvalidPoolTransactionError, BestTransactionsAttributes, PoolTransaction,
TransactionPool, TransactionPool,
}; };
use reth_trie::HashedPostState;
use revm::{db::states::bundle_state::BundleRetention, DatabaseCommit, State}; use revm::{db::states::bundle_state::BundleRetention, DatabaseCommit, State};
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use tokio::sync::Mutex; use tokio::sync::Mutex;
@ -427,7 +426,7 @@ pub trait LoadPendingBlock:
block_number, block_number,
Vec::new(), Vec::new(),
); );
let hashed_state = HashedPostState::from_bundle_state(&execution_outcome.state().state); let hashed_state = db.database.hashed_post_state(execution_outcome.state());
let receipts_root = self.receipts_root(&block_env, &execution_outcome, block_number); let receipts_root = self.receipts_root(&block_env, &execution_outcome, block_number);

View File

@ -8,7 +8,7 @@ use alloy_primitives::{
}; };
use reth_errors::ProviderResult; use reth_errors::ProviderResult;
use reth_revm::{database::StateProviderDatabase, db::CacheDB, DatabaseRef}; use reth_revm::{database::StateProviderDatabase, db::CacheDB, DatabaseRef};
use reth_storage_api::StateProvider; use reth_storage_api::{HashedPostStateProvider, StateProvider};
use reth_trie::HashedStorage; use reth_trie::HashedStorage;
use revm::Database; use revm::Database;
@ -139,6 +139,15 @@ impl reth_storage_api::BlockHashReader for StateProviderTraitObjWrapper<'_> {
} }
} }
impl HashedPostStateProvider for StateProviderTraitObjWrapper<'_> {
fn hashed_post_state(
&self,
bundle_state: &revm::db::BundleState,
) -> reth_trie::HashedPostState {
self.0.hashed_post_state(bundle_state)
}
}
impl StateProvider for StateProviderTraitObjWrapper<'_> { impl StateProvider for StateProviderTraitObjWrapper<'_> {
fn storage( fn storage(
&self, &self,

View File

@ -34,7 +34,6 @@ reth-evm.workspace = true
reth-rpc-eth-types.workspace = true reth-rpc-eth-types.workspace = true
reth-rpc-server-types.workspace = true reth-rpc-server-types.workspace = true
reth-network-types.workspace = true reth-network-types.workspace = true
reth-trie.workspace = true
reth-consensus.workspace = true reth-consensus.workspace = true
reth-payload-validator.workspace = true reth-payload-validator.workspace = true

View File

@ -25,7 +25,6 @@ use reth_revm::{cached::CachedReads, database::StateProviderDatabase};
use reth_rpc_api::BlockSubmissionValidationApiServer; use reth_rpc_api::BlockSubmissionValidationApiServer;
use reth_rpc_server_types::result::internal_rpc_err; use reth_rpc_server_types::result::internal_rpc_err;
use reth_tasks::TaskSpawner; use reth_tasks::TaskSpawner;
use reth_trie::HashedPostState;
use revm_primitives::{Address, B256, U256}; use revm_primitives::{Address, B256, U256};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{collections::HashSet, sync::Arc}; use std::{collections::HashSet, sync::Arc};
@ -186,7 +185,7 @@ where
self.ensure_payment(&block, &output, &message)?; self.ensure_payment(&block, &output, &message)?;
let state_root = let state_root =
state_provider.state_root(HashedPostState::from_bundle_state(&output.state.state))?; state_provider.state_root(state_provider.hashed_post_state(&output.state))?;
if state_root != block.state_root { if state_root != block.state_root {
return Err(ConsensusError::BodyStateRootDiff( return Err(ConsensusError::BodyStateRootDiff(

View File

@ -4,8 +4,8 @@ use crate::{
AccountReader, BlockHashReader, BlockIdReader, BlockNumReader, BlockReader, BlockReaderIdExt, AccountReader, BlockHashReader, BlockIdReader, BlockNumReader, BlockReader, BlockReaderIdExt,
BlockSource, CanonChainTracker, CanonStateNotifications, CanonStateSubscriptions, BlockSource, CanonChainTracker, CanonStateNotifications, CanonStateSubscriptions,
ChainSpecProvider, ChainStateBlockReader, ChangeSetReader, DatabaseProvider, ChainSpecProvider, ChainStateBlockReader, ChangeSetReader, DatabaseProvider,
DatabaseProviderFactory, EvmEnvProvider, FullProvider, HeaderProvider, ProviderError, DatabaseProviderFactory, EvmEnvProvider, FullProvider, HashedPostStateProvider, HeaderProvider,
ProviderFactory, PruneCheckpointReader, ReceiptProvider, ReceiptProviderIdExt, ProviderError, ProviderFactory, PruneCheckpointReader, ReceiptProvider, ReceiptProviderIdExt,
StageCheckpointReader, StateProviderBox, StateProviderFactory, StateReader, StageCheckpointReader, StateProviderBox, StateProviderFactory, StateReader,
StaticFileProviderFactory, TransactionVariant, TransactionsProvider, WithdrawalsProvider, StaticFileProviderFactory, TransactionVariant, TransactionsProvider, WithdrawalsProvider,
}; };
@ -34,9 +34,16 @@ use reth_primitives::{
use reth_primitives_traits::BlockBody as _; use reth_primitives_traits::BlockBody as _;
use reth_prune_types::{PruneCheckpoint, PruneSegment}; use reth_prune_types::{PruneCheckpoint, PruneSegment};
use reth_stages_types::{StageCheckpoint, StageId}; use reth_stages_types::{StageCheckpoint, StageId};
use reth_storage_api::{DBProvider, NodePrimitivesProvider, StorageChangeSetReader}; use reth_storage_api::{
DBProvider, NodePrimitivesProvider, StateCommitmentProvider, StorageChangeSetReader,
};
use reth_storage_errors::provider::ProviderResult; use reth_storage_errors::provider::ProviderResult;
use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg}; use reth_trie::HashedPostState;
use reth_trie_db::StateCommitment;
use revm::{
db::BundleState,
primitives::{BlockEnv, CfgEnvWithHandlerCfg},
};
use std::{ use std::{
ops::{Add, RangeBounds, RangeInclusive, Sub}, ops::{Add, RangeBounds, RangeInclusive, Sub},
sync::Arc, sync::Arc,
@ -171,6 +178,10 @@ impl<N: ProviderNodeTypes> DatabaseProviderFactory for BlockchainProvider2<N> {
} }
} }
impl<N: ProviderNodeTypes> StateCommitmentProvider for BlockchainProvider2<N> {
type StateCommitment = N::StateCommitment;
}
impl<N: ProviderNodeTypes> StaticFileProviderFactory for BlockchainProvider2<N> { impl<N: ProviderNodeTypes> StaticFileProviderFactory for BlockchainProvider2<N> {
fn static_file_provider(&self) -> StaticFileProvider<Self::Primitives> { fn static_file_provider(&self) -> StaticFileProvider<Self::Primitives> {
self.database.static_file_provider() self.database.static_file_provider()
@ -663,6 +674,14 @@ impl<N: ProviderNodeTypes> StateProviderFactory for BlockchainProvider2<N> {
} }
} }
impl<N: NodeTypesWithDB> HashedPostStateProvider for BlockchainProvider2<N> {
fn hashed_post_state(&self, bundle_state: &BundleState) -> HashedPostState {
HashedPostState::from_bundle_state::<<N::StateCommitment as StateCommitment>::KeyHasher>(
bundle_state.state(),
)
}
}
impl<N: ProviderNodeTypes> CanonChainTracker for BlockchainProvider2<N> { impl<N: ProviderNodeTypes> CanonChainTracker for BlockchainProvider2<N> {
type Header = HeaderTy<N>; type Header = HeaderTy<N>;

View File

@ -6,7 +6,7 @@ use alloy_primitives::{
Address, BlockNumber, Bytes, B256, Address, BlockNumber, Bytes, B256,
}; };
use reth_primitives::{Account, Bytecode}; 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_storage_errors::provider::ProviderResult;
use reth_trie::{ use reth_trie::{
updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof,
@ -87,7 +87,7 @@ impl<SP: StateProvider, EDP: ExecutionDataProvider> StateRootProvider
{ {
fn state_root(&self, hashed_state: HashedPostState) -> ProviderResult<B256> { fn state_root(&self, hashed_state: HashedPostState) -> ProviderResult<B256> {
let bundle_state = self.block_execution_data_provider.execution_outcome().state(); let bundle_state = self.block_execution_data_provider.execution_outcome().state();
let mut state = HashedPostState::from_bundle_state(&bundle_state.state); let mut state = self.hashed_post_state(bundle_state);
state.extend(hashed_state); state.extend(hashed_state);
self.state_provider.state_root(state) self.state_provider.state_root(state)
} }
@ -101,7 +101,7 @@ impl<SP: StateProvider, EDP: ExecutionDataProvider> StateRootProvider
hashed_state: HashedPostState, hashed_state: HashedPostState,
) -> ProviderResult<(B256, TrieUpdates)> { ) -> ProviderResult<(B256, TrieUpdates)> {
let bundle_state = self.block_execution_data_provider.execution_outcome().state(); let bundle_state = self.block_execution_data_provider.execution_outcome().state();
let mut state = HashedPostState::from_bundle_state(&bundle_state.state); let mut state = self.hashed_post_state(bundle_state);
state.extend(hashed_state); state.extend(hashed_state);
self.state_provider.state_root_with_updates(state) self.state_provider.state_root_with_updates(state)
} }
@ -111,7 +111,7 @@ impl<SP: StateProvider, EDP: ExecutionDataProvider> StateRootProvider
mut input: TrieInput, mut input: TrieInput,
) -> ProviderResult<(B256, TrieUpdates)> { ) -> ProviderResult<(B256, TrieUpdates)> {
let bundle_state = self.block_execution_data_provider.execution_outcome().state(); let bundle_state = self.block_execution_data_provider.execution_outcome().state();
input.prepend(HashedPostState::from_bundle_state(&bundle_state.state)); input.prepend(self.hashed_post_state(bundle_state));
self.state_provider.state_root_from_nodes_with_updates(input) self.state_provider.state_root_from_nodes_with_updates(input)
} }
} }
@ -162,7 +162,7 @@ impl<SP: StateProvider, EDP: ExecutionDataProvider> StateProofProvider
slots: &[B256], slots: &[B256],
) -> ProviderResult<AccountProof> { ) -> ProviderResult<AccountProof> {
let bundle_state = self.block_execution_data_provider.execution_outcome().state(); let bundle_state = self.block_execution_data_provider.execution_outcome().state();
input.prepend(HashedPostState::from_bundle_state(&bundle_state.state)); input.prepend(self.hashed_post_state(bundle_state));
self.state_provider.proof(input, address, slots) self.state_provider.proof(input, address, slots)
} }
@ -172,7 +172,7 @@ impl<SP: StateProvider, EDP: ExecutionDataProvider> StateProofProvider
targets: HashMap<B256, HashSet<B256>>, targets: HashMap<B256, HashSet<B256>>,
) -> ProviderResult<MultiProof> { ) -> ProviderResult<MultiProof> {
let bundle_state = self.block_execution_data_provider.execution_outcome().state(); let bundle_state = self.block_execution_data_provider.execution_outcome().state();
input.prepend(HashedPostState::from_bundle_state(&bundle_state.state)); input.prepend(self.hashed_post_state(bundle_state));
self.state_provider.multiproof(input, targets) self.state_provider.multiproof(input, targets)
} }
@ -182,11 +182,19 @@ impl<SP: StateProvider, EDP: ExecutionDataProvider> StateProofProvider
target: HashedPostState, target: HashedPostState,
) -> ProviderResult<HashMap<B256, Bytes>> { ) -> ProviderResult<HashMap<B256, Bytes>> {
let bundle_state = self.block_execution_data_provider.execution_outcome().state(); let bundle_state = self.block_execution_data_provider.execution_outcome().state();
input.prepend(HashedPostState::from_bundle_state(&bundle_state.state)); input.prepend(self.hashed_post_state(bundle_state));
self.state_provider.witness(input, target) self.state_provider.witness(input, target)
} }
} }
impl<SP: StateProvider, EDP: ExecutionDataProvider> HashedPostStateProvider
for BundleStateProvider<SP, EDP>
{
fn hashed_post_state(&self, bundle_state: &revm::db::BundleState) -> HashedPostState {
self.state_provider.hashed_post_state(bundle_state)
}
}
impl<SP: StateProvider, EDP: ExecutionDataProvider> StateProvider for BundleStateProvider<SP, EDP> { impl<SP: StateProvider, EDP: ExecutionDataProvider> StateProvider for BundleStateProvider<SP, EDP> {
fn storage( fn storage(
&self, &self,

View File

@ -2,11 +2,11 @@ use crate::{BlockNumReader, DatabaseProviderFactory, HeaderProvider};
use alloy_primitives::B256; use alloy_primitives::B256;
use reth_errors::ProviderError; use reth_errors::ProviderError;
use reth_primitives::GotExpected; use reth_primitives::GotExpected;
use reth_storage_api::{BlockReader, DBProvider}; use reth_storage_api::{BlockReader, DBProvider, StateCommitmentProvider};
use reth_storage_errors::provider::ProviderResult; use reth_storage_errors::provider::ProviderResult;
use reth_trie::HashedPostState; use reth_trie::HashedPostState;
use reth_trie_db::DatabaseHashedPostState; use reth_trie_db::{DatabaseHashedPostState, StateCommitment};
pub use reth_storage_errors::provider::ConsistentViewError; pub use reth_storage_errors::provider::ConsistentViewError;
@ -33,7 +33,7 @@ pub struct ConsistentDbView<Factory> {
impl<Factory> ConsistentDbView<Factory> impl<Factory> ConsistentDbView<Factory>
where where
Factory: DatabaseProviderFactory<Provider: BlockReader>, Factory: DatabaseProviderFactory<Provider: BlockReader> + StateCommitmentProvider,
{ {
/// Creates new consistent database view. /// Creates new consistent database view.
pub const fn new(factory: Factory, tip: Option<B256>) -> Self { pub const fn new(factory: Factory, tip: Option<B256>) -> Self {
@ -59,7 +59,9 @@ where
{ {
Ok(HashedPostState::default()) Ok(HashedPostState::default())
} else { } else {
Ok(HashedPostState::from_reverts(provider.tx_ref(), block_number + 1)?) Ok(HashedPostState::from_reverts::<
<Factory::StateCommitment as StateCommitment>::KeyHasher,
>(provider.tx_ref(), block_number + 1)?)
} }
} }

View File

@ -3,9 +3,9 @@ use crate::{
to_range, to_range,
traits::{BlockSource, ReceiptProvider}, traits::{BlockSource, ReceiptProvider},
BlockHashReader, BlockNumReader, BlockReader, ChainSpecProvider, DatabaseProviderFactory, BlockHashReader, BlockNumReader, BlockReader, ChainSpecProvider, DatabaseProviderFactory,
EvmEnvProvider, HeaderProvider, HeaderSyncGap, HeaderSyncGapProvider, ProviderError, EvmEnvProvider, HashedPostStateProvider, HeaderProvider, HeaderSyncGap, HeaderSyncGapProvider,
PruneCheckpointReader, StageCheckpointReader, StateProviderBox, StaticFileProviderFactory, ProviderError, PruneCheckpointReader, StageCheckpointReader, StateProviderBox,
TransactionVariant, TransactionsProvider, WithdrawalsProvider, StaticFileProviderFactory, TransactionVariant, TransactionsProvider, WithdrawalsProvider,
}; };
use alloy_eips::{ use alloy_eips::{
eip4895::{Withdrawal, Withdrawals}, eip4895::{Withdrawal, Withdrawals},
@ -25,9 +25,16 @@ use reth_primitives::{
}; };
use reth_prune_types::{PruneCheckpoint, PruneModes, PruneSegment}; use reth_prune_types::{PruneCheckpoint, PruneModes, PruneSegment};
use reth_stages_types::{StageCheckpoint, StageId}; use reth_stages_types::{StageCheckpoint, StageId};
use reth_storage_api::{NodePrimitivesProvider, TryIntoHistoricalStateProvider}; use reth_storage_api::{
NodePrimitivesProvider, StateCommitmentProvider, TryIntoHistoricalStateProvider,
};
use reth_storage_errors::provider::ProviderResult; use reth_storage_errors::provider::ProviderResult;
use revm::primitives::{BlockEnv, CfgEnvWithHandlerCfg}; use reth_trie::HashedPostState;
use reth_trie_db::StateCommitment;
use revm::{
db::BundleState,
primitives::{BlockEnv, CfgEnvWithHandlerCfg},
};
use std::{ use std::{
ops::{RangeBounds, RangeInclusive}, ops::{RangeBounds, RangeInclusive},
path::Path, path::Path,
@ -219,6 +226,10 @@ impl<N: ProviderNodeTypes> DatabaseProviderFactory for ProviderFactory<N> {
} }
} }
impl<N: NodeTypesWithDB> StateCommitmentProvider for ProviderFactory<N> {
type StateCommitment = N::StateCommitment;
}
impl<N: NodeTypesWithDB> StaticFileProviderFactory for ProviderFactory<N> { impl<N: NodeTypesWithDB> StaticFileProviderFactory for ProviderFactory<N> {
/// Returns static file provider /// Returns static file provider
fn static_file_provider(&self) -> StaticFileProvider<Self::Primitives> { fn static_file_provider(&self) -> StaticFileProvider<Self::Primitives> {
@ -651,6 +662,14 @@ impl<N: ProviderNodeTypes> PruneCheckpointReader for ProviderFactory<N> {
} }
} }
impl<N: ProviderNodeTypes> HashedPostStateProvider for ProviderFactory<N> {
fn hashed_post_state(&self, bundle_state: &BundleState) -> HashedPostState {
HashedPostState::from_bundle_state::<<N::StateCommitment as StateCommitment>::KeyHasher>(
bundle_state.state(),
)
}
}
impl<N: NodeTypesWithDB> Clone for ProviderFactory<N> { impl<N: NodeTypesWithDB> Clone for ProviderFactory<N> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
providers::state::macros::delegate_provider_impls, AccountReader, BlockHashReader, providers::state::macros::delegate_provider_impls, AccountReader, BlockHashReader,
ProviderError, StateProvider, StateRootProvider, HashedPostStateProvider, ProviderError, StateProvider, StateRootProvider,
}; };
use alloy_eips::merge::EPOCH_SLOTS; use alloy_eips::merge::EPOCH_SLOTS;
use alloy_primitives::{ use alloy_primitives::{
@ -28,7 +28,7 @@ use reth_trie::{
}; };
use reth_trie_db::{ use reth_trie_db::{
DatabaseHashedPostState, DatabaseHashedStorage, DatabaseProof, DatabaseStateRoot, DatabaseHashedPostState, DatabaseHashedStorage, DatabaseProof, DatabaseStateRoot,
DatabaseStorageProof, DatabaseStorageRoot, DatabaseTrieWitness, DatabaseStorageProof, DatabaseStorageRoot, DatabaseTrieWitness, StateCommitment,
}; };
use std::fmt::Debug; use std::fmt::Debug;
@ -136,7 +136,9 @@ impl<'b, Provider: DBProvider + BlockNumReader + StateCommitmentProvider>
); );
} }
Ok(HashedPostState::from_reverts(self.tx(), self.block_number)?) Ok(HashedPostState::from_reverts::<
<Provider::StateCommitment as StateCommitment>::KeyHasher,
>(self.tx(), self.block_number)?)
} }
/// Retrieve revert hashed storage for this history provider and target address. /// Retrieve revert hashed storage for this history provider and target address.
@ -394,6 +396,16 @@ impl<Provider: DBProvider + BlockNumReader + StateCommitmentProvider> StateProof
} }
} }
impl<Provider: StateCommitmentProvider> HashedPostStateProvider
for HistoricalStateProviderRef<'_, Provider>
{
fn hashed_post_state(&self, bundle_state: &revm::db::BundleState) -> HashedPostState {
HashedPostState::from_bundle_state::<
<Provider::StateCommitment as StateCommitment>::KeyHasher,
>(bundle_state.state())
}
}
impl<Provider: DBProvider + BlockNumReader + BlockHashReader + StateCommitmentProvider> impl<Provider: DBProvider + BlockNumReader + BlockHashReader + StateCommitmentProvider>
StateProvider for HistoricalStateProviderRef<'_, Provider> StateProvider for HistoricalStateProviderRef<'_, Provider>
{ {
@ -433,6 +445,12 @@ impl<Provider: DBProvider + BlockNumReader + BlockHashReader + StateCommitmentPr
} }
} }
impl<Provider: StateCommitmentProvider> StateCommitmentProvider
for HistoricalStateProviderRef<'_, Provider>
{
type StateCommitment = Provider::StateCommitment;
}
/// State provider for a given block number. /// State provider for a given block number.
/// For more detailed description, see [`HistoricalStateProviderRef`]. /// For more detailed description, see [`HistoricalStateProviderRef`].
#[derive(Debug)] #[derive(Debug)]
@ -482,6 +500,12 @@ impl<Provider: DBProvider + BlockNumReader + StateCommitmentProvider>
} }
} }
impl<Provider: StateCommitmentProvider> StateCommitmentProvider
for HistoricalStateProvider<Provider>
{
type StateCommitment = Provider::StateCommitment;
}
// Delegates all provider impls to [HistoricalStateProviderRef] // Delegates all provider impls to [HistoricalStateProviderRef]
delegate_provider_impls!(HistoricalStateProvider<Provider> where [Provider: DBProvider + BlockNumReader + BlockHashReader + StateCommitmentProvider]); delegate_provider_impls!(HistoricalStateProvider<Provider> where [Provider: DBProvider + BlockNumReader + BlockHashReader + StateCommitmentProvider]);

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
providers::state::macros::delegate_provider_impls, AccountReader, BlockHashReader, providers::state::macros::delegate_provider_impls, AccountReader, BlockHashReader,
StateProvider, StateRootProvider, HashedPostStateProvider, StateProvider, StateRootProvider,
}; };
use alloy_primitives::{ use alloy_primitives::{
map::{HashMap, HashSet}, map::{HashMap, HashSet},
@ -22,7 +22,7 @@ use reth_trie::{
}; };
use reth_trie_db::{ use reth_trie_db::{
DatabaseProof, DatabaseStateRoot, DatabaseStorageProof, DatabaseStorageRoot, DatabaseProof, DatabaseStateRoot, DatabaseStorageProof, DatabaseStorageRoot,
DatabaseTrieWitness, DatabaseTrieWitness, StateCommitment,
}; };
/// State provider over latest state that takes tx reference. /// State provider over latest state that takes tx reference.
@ -157,6 +157,16 @@ impl<Provider: DBProvider + StateCommitmentProvider> StateProofProvider
} }
} }
impl<Provider: DBProvider + StateCommitmentProvider> HashedPostStateProvider
for LatestStateProviderRef<'_, Provider>
{
fn hashed_post_state(&self, bundle_state: &revm::db::BundleState) -> HashedPostState {
HashedPostState::from_bundle_state::<
<Provider::StateCommitment as StateCommitment>::KeyHasher,
>(bundle_state.state())
}
}
impl<Provider: DBProvider + BlockHashReader + StateCommitmentProvider> StateProvider impl<Provider: DBProvider + BlockHashReader + StateCommitmentProvider> StateProvider
for LatestStateProviderRef<'_, Provider> for LatestStateProviderRef<'_, Provider>
{ {
@ -181,11 +191,17 @@ impl<Provider: DBProvider + BlockHashReader + StateCommitmentProvider> StateProv
} }
} }
impl<Provider: StateCommitmentProvider> StateCommitmentProvider
for LatestStateProviderRef<'_, Provider>
{
type StateCommitment = Provider::StateCommitment;
}
/// State provider for the latest state. /// State provider for the latest state.
#[derive(Debug)] #[derive(Debug)]
pub struct LatestStateProvider<Provider>(Provider); pub struct LatestStateProvider<Provider>(Provider);
impl<Provider: DBProvider> LatestStateProvider<Provider> { impl<Provider: DBProvider + StateCommitmentProvider> LatestStateProvider<Provider> {
/// Create new state provider /// Create new state provider
pub const fn new(db: Provider) -> Self { pub const fn new(db: Provider) -> Self {
Self(db) Self(db)
@ -198,6 +214,10 @@ impl<Provider: DBProvider> LatestStateProvider<Provider> {
} }
} }
impl<Provider: StateCommitmentProvider> StateCommitmentProvider for LatestStateProvider<Provider> {
type StateCommitment = Provider::StateCommitment;
}
// Delegates all provider impls to [LatestStateProviderRef] // Delegates all provider impls to [LatestStateProviderRef]
delegate_provider_impls!(LatestStateProvider<Provider> where [Provider: DBProvider + BlockHashReader + StateCommitmentProvider]); delegate_provider_impls!(LatestStateProvider<Provider> where [Provider: DBProvider + BlockHashReader + StateCommitmentProvider]);

View File

@ -57,6 +57,9 @@ macro_rules! delegate_provider_impls {
fn multiproof(&self, input: reth_trie::TrieInput, targets: alloy_primitives::map::HashMap<alloy_primitives::B256, alloy_primitives::map::HashSet<alloy_primitives::B256>>) -> reth_storage_errors::provider::ProviderResult<reth_trie::MultiProof>; fn multiproof(&self, input: reth_trie::TrieInput, targets: alloy_primitives::map::HashMap<alloy_primitives::B256, alloy_primitives::map::HashSet<alloy_primitives::B256>>) -> reth_storage_errors::provider::ProviderResult<reth_trie::MultiProof>;
fn witness(&self, input: reth_trie::TrieInput, target: reth_trie::HashedPostState) -> reth_storage_errors::provider::ProviderResult<alloy_primitives::map::HashMap<alloy_primitives::B256, alloy_primitives::Bytes>>; fn witness(&self, input: reth_trie::TrieInput, target: reth_trie::HashedPostState) -> reth_storage_errors::provider::ProviderResult<alloy_primitives::map::HashMap<alloy_primitives::B256, alloy_primitives::Bytes>>;
} }
HashedPostStateProvider $(where [$($generics)*])? {
fn hashed_post_state(&self, bundle_state: &revm::db::BundleState) -> reth_trie::HashedPostState;
}
); );
} }
} }

View File

@ -29,7 +29,8 @@ use reth_primitives::{
use reth_primitives_traits::SignedTransaction; use reth_primitives_traits::SignedTransaction;
use reth_stages_types::{StageCheckpoint, StageId}; use reth_stages_types::{StageCheckpoint, StageId};
use reth_storage_api::{ use reth_storage_api::{
DatabaseProviderFactory, StageCheckpointReader, StateProofProvider, StorageRootProvider, DatabaseProviderFactory, HashedPostStateProvider, StageCheckpointReader,
StateCommitmentProvider, StateProofProvider, StorageRootProvider,
}; };
use reth_storage_errors::provider::{ConsistentViewError, ProviderError, ProviderResult}; use reth_storage_errors::provider::{ConsistentViewError, ProviderError, ProviderResult};
use reth_trie::{ use reth_trie::{
@ -164,6 +165,10 @@ impl NodeTypes for MockNode {
type Storage = EthStorage; type Storage = EthStorage;
} }
impl StateCommitmentProvider for MockEthProvider {
type StateCommitment = <MockNode as NodeTypes>::StateCommitment;
}
impl DatabaseProviderFactory for MockEthProvider { impl DatabaseProviderFactory for MockEthProvider {
type DB = DatabaseMock; type DB = DatabaseMock;
type Provider = DatabaseProvider<TxMock, MockNode>; type Provider = DatabaseProvider<TxMock, MockNode>;
@ -682,6 +687,12 @@ impl StateProofProvider for MockEthProvider {
} }
} }
impl HashedPostStateProvider for MockEthProvider {
fn hashed_post_state(&self, _state: &revm::db::BundleState) -> HashedPostState {
HashedPostState::default()
}
}
impl StateProvider for MockEthProvider { impl StateProvider for MockEthProvider {
fn storage( fn storage(
&self, &self,

View File

@ -27,7 +27,9 @@ use reth_primitives::{
}; };
use reth_prune_types::{PruneCheckpoint, PruneSegment}; use reth_prune_types::{PruneCheckpoint, PruneSegment};
use reth_stages_types::{StageCheckpoint, StageId}; use reth_stages_types::{StageCheckpoint, StageId};
use reth_storage_api::{NodePrimitivesProvider, StateProofProvider, StorageRootProvider}; use reth_storage_api::{
HashedPostStateProvider, NodePrimitivesProvider, StateProofProvider, StorageRootProvider,
};
use reth_storage_errors::provider::ProviderResult; use reth_storage_errors::provider::ProviderResult;
use reth_trie::{ use reth_trie::{
updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, TrieInput, updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, TrieInput,
@ -413,6 +415,12 @@ impl StateProofProvider for NoopProvider {
} }
} }
impl HashedPostStateProvider for NoopProvider {
fn hashed_post_state(&self, _bundle_state: &revm::db::BundleState) -> HashedPostState {
HashedPostState::default()
}
}
impl StateProvider for NoopProvider { impl StateProvider for NoopProvider {
fn storage( fn storage(
&self, &self,

View File

@ -234,7 +234,7 @@ mod tests {
}; };
use reth_execution_types::ExecutionOutcome; use reth_execution_types::ExecutionOutcome;
use reth_primitives::{Account, Receipt, Receipts, StorageEntry}; use reth_primitives::{Account, Receipt, Receipts, StorageEntry};
use reth_storage_api::DatabaseProviderFactory; use reth_storage_api::{DatabaseProviderFactory, HashedPostStateProvider};
use reth_trie::{ use reth_trie::{
test_utils::{state_root, storage_root_prehashed}, test_utils::{state_root, storage_root_prehashed},
HashedPostState, HashedStorage, StateRoot, StorageRoot, HashedPostState, HashedStorage, StateRoot, StorageRoot,
@ -1118,13 +1118,7 @@ mod tests {
assert_eq!( assert_eq!(
StateRoot::overlay_root( StateRoot::overlay_root(
tx, tx,
ExecutionOutcome::<Receipt>::new( provider_factory.hashed_post_state(&state.bundle_state)
state.bundle_state.clone(),
Receipts::default(),
0,
Vec::new()
)
.hash_state_slow(),
) )
.unwrap(), .unwrap(),
state_root(expected.clone().into_iter().map(|(address, (account, storage))| ( state_root(expected.clone().into_iter().map(|(address, (account, storage))| (

View File

@ -25,6 +25,7 @@ reth-storage-errors.workspace = true
reth-trie.workspace = true reth-trie.workspace = true
reth-trie-db.workspace = true reth-trie-db.workspace = true
reth-db.workspace = true reth-db.workspace = true
revm.workspace = true
# ethereum # ethereum
alloy-eips.workspace = true alloy-eips.workspace = true

View File

@ -2,9 +2,9 @@
use crate::{ use crate::{
AccountReader, BlockHashReader, BlockIdReader, BlockNumReader, BlockReader, BlockReaderIdExt, AccountReader, BlockHashReader, BlockIdReader, BlockNumReader, BlockReader, BlockReaderIdExt,
BlockSource, ChangeSetReader, HeaderProvider, NodePrimitivesProvider, PruneCheckpointReader, BlockSource, ChangeSetReader, HashedPostStateProvider, HeaderProvider, NodePrimitivesProvider,
ReceiptProvider, ReceiptProviderIdExt, StageCheckpointReader, StateProofProvider, PruneCheckpointReader, ReceiptProvider, ReceiptProviderIdExt, StageCheckpointReader,
StateProvider, StateRootProvider, StorageRootProvider, TransactionVariant, StateProofProvider, StateProvider, StateRootProvider, StorageRootProvider, TransactionVariant,
TransactionsProvider, WithdrawalsProvider, TransactionsProvider, WithdrawalsProvider,
}; };
use alloy_eips::{ use alloy_eips::{
@ -456,6 +456,12 @@ impl<C: Send + Sync, N: NodePrimitives> StateProofProvider for NoopProvider<C, N
} }
} }
impl<C: Send + Sync, N: NodePrimitives> HashedPostStateProvider for NoopProvider<C, N> {
fn hashed_post_state(&self, _bundle_state: &revm::db::BundleState) -> HashedPostState {
HashedPostState::default()
}
}
impl<C: Send + Sync, N: NodePrimitives> StateProvider for NoopProvider<C, N> { impl<C: Send + Sync, N: NodePrimitives> StateProvider for NoopProvider<C, N> {
fn storage( fn storage(
&self, &self,

View File

@ -8,7 +8,9 @@ use alloy_primitives::{Address, BlockHash, BlockNumber, StorageKey, StorageValue
use auto_impl::auto_impl; use auto_impl::auto_impl;
use reth_primitives::Bytecode; use reth_primitives::Bytecode;
use reth_storage_errors::provider::ProviderResult; use reth_storage_errors::provider::ProviderResult;
use reth_trie::HashedPostState;
use reth_trie_db::StateCommitment; use reth_trie_db::StateCommitment;
use revm::db::states::BundleState;
/// Type alias of boxed [`StateProvider`]. /// Type alias of boxed [`StateProvider`].
pub type StateProviderBox = Box<dyn StateProvider>; pub type StateProviderBox = Box<dyn StateProvider>;
@ -21,6 +23,7 @@ pub trait StateProvider:
+ StateRootProvider + StateRootProvider
+ StorageRootProvider + StorageRootProvider
+ StateProofProvider + StateProofProvider
+ HashedPostStateProvider
+ Send + Send
+ Sync + Sync
{ {
@ -83,11 +86,18 @@ pub trait StateProvider:
} }
/// Trait implemented for database providers that can provide the [`StateCommitment`] type. /// Trait implemented for database providers that can provide the [`StateCommitment`] type.
pub trait StateCommitmentProvider { pub trait StateCommitmentProvider: Send + Sync {
/// The [`StateCommitment`] type that can be used to perform state commitment operations. /// The [`StateCommitment`] type that can be used to perform state commitment operations.
type StateCommitment: StateCommitment; type StateCommitment: StateCommitment;
} }
/// Trait that provides the hashed state from various sources.
#[auto_impl(&, Arc, Box)]
pub trait HashedPostStateProvider: Send + Sync {
/// Returns the `HashedPostState` of the provided [`BundleState`].
fn hashed_post_state(&self, bundle_state: &BundleState) -> HashedPostState;
}
/// Trait implemented for database providers that can be converted into a historical state provider. /// Trait implemented for database providers that can be converted into a historical state provider.
pub trait TryIntoHistoricalStateProvider { pub trait TryIntoHistoricalStateProvider {
/// Returns a historical [`StateProvider`] indexed by the given historic block number. /// Returns a historical [`StateProvider`] indexed by the given historic block number.

View File

@ -1,4 +1,4 @@
use alloy_primitives::{keccak256, BlockNumber, B256}; use alloy_primitives::{BlockNumber, B256};
use derive_more::Deref; use derive_more::Deref;
use reth_db::tables; use reth_db::tables;
use reth_db_api::{ use reth_db_api::{
@ -10,25 +10,34 @@ use reth_db_api::{
use reth_primitives::StorageEntry; use reth_primitives::StorageEntry;
use reth_trie::{ use reth_trie::{
prefix_set::{PrefixSetMut, TriePrefixSets}, prefix_set::{PrefixSetMut, TriePrefixSets},
Nibbles, KeyHasher, Nibbles,
}; };
use std::{ use std::{
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
marker::PhantomData,
ops::RangeInclusive, ops::RangeInclusive,
}; };
/// A wrapper around a database transaction that loads prefix sets within a given block range. /// A wrapper around a database transaction that loads prefix sets within a given block range.
#[derive(Deref, Debug)] #[derive(Debug)]
pub struct PrefixSetLoader<'a, TX>(&'a TX); pub struct PrefixSetLoader<'a, TX, KH>(&'a TX, PhantomData<KH>);
impl<'a, TX> PrefixSetLoader<'a, TX> { impl<'a, TX, KH> PrefixSetLoader<'a, TX, KH> {
/// Create a new loader. /// Create a new loader.
pub const fn new(tx: &'a TX) -> Self { pub const fn new(tx: &'a TX) -> Self {
Self(tx) Self(tx, PhantomData)
} }
} }
impl<TX: DbTx> PrefixSetLoader<'_, TX> { impl<TX, KH> Deref for PrefixSetLoader<'_, TX, KH> {
type Target = TX;
fn deref(&self) -> &Self::Target {
self.0
}
}
impl<TX: DbTx, KH: KeyHasher> PrefixSetLoader<'_, TX, KH> {
/// Load all account and storage changes for the given block range. /// Load all account and storage changes for the given block range.
pub fn load(self, range: RangeInclusive<BlockNumber>) -> Result<TriePrefixSets, DatabaseError> { pub fn load(self, range: RangeInclusive<BlockNumber>) -> Result<TriePrefixSets, DatabaseError> {
// Initialize prefix sets. // Initialize prefix sets.
@ -41,7 +50,7 @@ impl<TX: DbTx> PrefixSetLoader<'_, TX> {
let mut account_hashed_state_cursor = self.cursor_read::<tables::HashedAccounts>()?; let mut account_hashed_state_cursor = self.cursor_read::<tables::HashedAccounts>()?;
for account_entry in account_changeset_cursor.walk_range(range.clone())? { for account_entry in account_changeset_cursor.walk_range(range.clone())? {
let (_, AccountBeforeTx { address, .. }) = account_entry?; let (_, AccountBeforeTx { address, .. }) = account_entry?;
let hashed_address = keccak256(address); let hashed_address = KH::hash_key(address);
account_prefix_set.insert(Nibbles::unpack(hashed_address)); account_prefix_set.insert(Nibbles::unpack(hashed_address));
if account_hashed_state_cursor.seek_exact(hashed_address)?.is_none() { if account_hashed_state_cursor.seek_exact(hashed_address)?.is_none() {
@ -55,12 +64,12 @@ impl<TX: DbTx> PrefixSetLoader<'_, TX> {
let storage_range = BlockNumberAddress::range(range); let storage_range = BlockNumberAddress::range(range);
for storage_entry in storage_cursor.walk_range(storage_range)? { for storage_entry in storage_cursor.walk_range(storage_range)? {
let (BlockNumberAddress((_, address)), StorageEntry { key, .. }) = storage_entry?; let (BlockNumberAddress((_, address)), StorageEntry { key, .. }) = storage_entry?;
let hashed_address = keccak256(address); let hashed_address = KH::hash_key(address);
account_prefix_set.insert(Nibbles::unpack(hashed_address)); account_prefix_set.insert(Nibbles::unpack(hashed_address));
storage_prefix_sets storage_prefix_sets
.entry(hashed_address) .entry(hashed_address)
.or_default() .or_default()
.insert(Nibbles::unpack(keccak256(key))); .insert(Nibbles::unpack(KH::hash_key(key)));
} }
Ok(TriePrefixSets { Ok(TriePrefixSets {

View File

@ -1,5 +1,5 @@
use crate::{DatabaseHashedCursorFactory, DatabaseTrieCursorFactory, PrefixSetLoader}; 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::tables;
use reth_db_api::{ use reth_db_api::{
cursor::DbCursorRO, cursor::DbCursorRO,
@ -10,7 +10,8 @@ use reth_execution_errors::StateRootError;
use reth_storage_errors::db::DatabaseError; use reth_storage_errors::db::DatabaseError;
use reth_trie::{ use reth_trie::{
hashed_cursor::HashedPostStateCursorFactory, trie_cursor::InMemoryTrieCursorFactory, hashed_cursor::HashedPostStateCursorFactory, trie_cursor::InMemoryTrieCursorFactory,
updates::TrieUpdates, HashedPostState, HashedStorage, StateRoot, StateRootProgress, TrieInput, updates::TrieUpdates, HashedPostState, HashedStorage, KeccakKeyHasher, KeyHasher, StateRoot,
StateRootProgress, TrieInput,
}; };
use std::{collections::HashMap, ops::RangeInclusive}; use std::{collections::HashMap, ops::RangeInclusive};
use tracing::debug; use tracing::debug;
@ -122,7 +123,7 @@ pub trait DatabaseStateRoot<'a, TX>: Sized {
pub trait DatabaseHashedPostState<TX>: Sized { pub trait DatabaseHashedPostState<TX>: Sized {
/// Initializes [`HashedPostState`] from reverts. Iterates over state reverts from the specified /// 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. /// block up to the current tip and aggregates them into hashed state in reverse.
fn from_reverts(tx: &TX, from: BlockNumber) -> Result<Self, DatabaseError>; fn from_reverts<KH: KeyHasher>(tx: &TX, from: BlockNumber) -> Result<Self, DatabaseError>;
} }
impl<'a, TX: DbTx> DatabaseStateRoot<'a, TX> impl<'a, TX: DbTx> DatabaseStateRoot<'a, TX>
@ -136,7 +137,7 @@ impl<'a, TX: DbTx> DatabaseStateRoot<'a, TX>
tx: &'a TX, tx: &'a TX,
range: RangeInclusive<BlockNumber>, range: RangeInclusive<BlockNumber>,
) -> Result<Self, StateRootError> { ) -> Result<Self, StateRootError> {
let loaded_prefix_sets = PrefixSetLoader::new(tx).load(range)?; let loaded_prefix_sets = PrefixSetLoader::<_, KeccakKeyHasher>::new(tx).load(range)?;
Ok(Self::from_tx(tx).with_prefix_sets(loaded_prefix_sets)) Ok(Self::from_tx(tx).with_prefix_sets(loaded_prefix_sets))
} }
@ -216,7 +217,7 @@ impl<'a, TX: DbTx> DatabaseStateRoot<'a, TX>
} }
impl<TX: DbTx> DatabaseHashedPostState<TX> for HashedPostState { impl<TX: DbTx> DatabaseHashedPostState<TX> for HashedPostState {
fn from_reverts(tx: &TX, from: BlockNumber) -> Result<Self, DatabaseError> { fn from_reverts<KH: KeyHasher>(tx: &TX, from: BlockNumber) -> Result<Self, DatabaseError> {
// Iterate over account changesets and record value before first occurring account change. // Iterate over account changesets and record value before first occurring account change.
let mut accounts = HashMap::new(); let mut accounts = HashMap::new();
let mut account_changesets_cursor = tx.cursor_read::<tables::AccountChangeSets>()?; let mut account_changesets_cursor = tx.cursor_read::<tables::AccountChangeSets>()?;
@ -237,19 +238,19 @@ impl<TX: DbTx> DatabaseHashedPostState<TX> for HashedPostState {
} }
let hashed_accounts = 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 let hashed_storages = storages
.into_iter() .into_iter()
.map(|(address, storage)| { .map(|(address, storage)| {
( (
keccak256(address), KH::hash_key(address),
HashedStorage::from_iter( HashedStorage::from_iter(
// The `wiped` flag indicates only whether previous storage entries // 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 // should be looked up in db or not. For reverts it's a noop since all
// wiped changes had been written as storage reverts. // wiped changes had been written as storage reverts.
false, false,
storage.into_iter().map(|(slot, value)| (keccak256(slot), value)), storage.into_iter().map(|(slot, value)| (KH::hash_key(slot), value)),
), ),
) )
}) })
@ -265,6 +266,7 @@ mod tests {
use alloy_primitives::{hex, map::HashMap, Address, U256}; use alloy_primitives::{hex, map::HashMap, Address, U256};
use reth_db::test_utils::create_test_rw_db; use reth_db::test_utils::create_test_rw_db;
use reth_db_api::database::Database; use reth_db_api::database::Database;
use reth_trie::KeccakKeyHasher;
use revm::{db::BundleState, primitives::AccountInfo}; use revm::{db::BundleState, primitives::AccountInfo};
#[test] #[test]
@ -285,7 +287,7 @@ mod tests {
.build(); .build();
assert_eq!(bundle_state.reverts.len(), 1); assert_eq!(bundle_state.reverts.len(), 1);
let post_state = HashedPostState::from_bundle_state(&bundle_state.state); let post_state = HashedPostState::from_bundle_state::<KeccakKeyHasher>(&bundle_state.state);
assert_eq!(post_state.accounts.len(), 2); assert_eq!(post_state.accounts.len(), 2);
assert_eq!(post_state.storages.len(), 2); assert_eq!(post_state.storages.len(), 2);

View File

@ -9,6 +9,7 @@ use reth_db::DatabaseError;
use reth_execution_errors::StorageRootError; use reth_execution_errors::StorageRootError;
use reth_provider::{ use reth_provider::{
providers::ConsistentDbView, BlockReader, DBProvider, DatabaseProviderFactory, ProviderError, providers::ConsistentDbView, BlockReader, DBProvider, DatabaseProviderFactory, ProviderError,
StateCommitmentProvider,
}; };
use reth_trie::{ use reth_trie::{
hashed_cursor::{HashedCursorFactory, HashedPostStateCursorFactory}, hashed_cursor::{HashedCursorFactory, HashedPostStateCursorFactory},
@ -53,7 +54,12 @@ impl<Factory> ParallelProof<Factory> {
impl<Factory> ParallelProof<Factory> impl<Factory> ParallelProof<Factory>
where where
Factory: DatabaseProviderFactory<Provider: BlockReader> + Clone + Send + Sync + 'static, Factory: DatabaseProviderFactory<Provider: BlockReader>
+ StateCommitmentProvider
+ Clone
+ Send
+ Sync
+ 'static,
{ {
/// Generate a state multiproof according to specified targets. /// Generate a state multiproof according to specified targets.
pub fn multiproof( pub fn multiproof(

View File

@ -8,6 +8,7 @@ use reth_db::DatabaseError;
use reth_execution_errors::StorageRootError; use reth_execution_errors::StorageRootError;
use reth_provider::{ use reth_provider::{
providers::ConsistentDbView, BlockReader, DBProvider, DatabaseProviderFactory, ProviderError, providers::ConsistentDbView, BlockReader, DBProvider, DatabaseProviderFactory, ProviderError,
StateCommitmentProvider,
}; };
use reth_trie::{ use reth_trie::{
hashed_cursor::{HashedCursorFactory, HashedPostStateCursorFactory}, hashed_cursor::{HashedCursorFactory, HashedPostStateCursorFactory},
@ -58,7 +59,12 @@ impl<Factory> ParallelStateRoot<Factory> {
impl<Factory> ParallelStateRoot<Factory> impl<Factory> ParallelStateRoot<Factory>
where where
Factory: DatabaseProviderFactory<Provider: BlockReader> + Clone + Send + Sync + 'static, Factory: DatabaseProviderFactory<Provider: BlockReader>
+ StateCommitmentProvider
+ Clone
+ Send
+ Sync
+ 'static,
{ {
/// Calculate incremental state root in parallel. /// Calculate incremental state root in parallel.
pub fn incremental_root(self) -> Result<B256, ParallelStateRootError> { pub fn incremental_root(self) -> Result<B256, ParallelStateRootError> {

View File

@ -2,7 +2,7 @@
use alloy_primitives::{keccak256, map::HashMap, Address, B256, U256}; use alloy_primitives::{keccak256, map::HashMap, Address, B256, U256};
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
use proptest::{prelude::*, strategy::ValueTree, test_runner::TestRunner}; 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}; use revm::db::{states::BundleBuilder, BundleAccount};
pub fn hash_post_state(c: &mut Criterion) { pub fn hash_post_state(c: &mut Criterion) {
@ -19,7 +19,7 @@ pub fn hash_post_state(c: &mut Criterion) {
// parallel // parallel
group.bench_function(BenchmarkId::new("parallel hashing", size), |b| { group.bench_function(BenchmarkId::new("parallel hashing", size), |b| {
b.iter(|| HashedPostState::from_bundle_state(&state)) b.iter(|| HashedPostState::from_bundle_state::<KeccakKeyHasher>(&state))
}); });
} }
} }

View File

@ -10,6 +10,7 @@ use alloy_primitives::{
use itertools::Itertools; use itertools::Itertools;
use rayon::prelude::{IntoParallelIterator, ParallelIterator}; use rayon::prelude::{IntoParallelIterator, ParallelIterator};
use reth_primitives::Account; use reth_primitives::Account;
use reth_trie_common::KeyHasher;
use revm::db::{states::CacheAccount, AccountStatus, BundleAccount}; use revm::db::{states::CacheAccount, AccountStatus, BundleAccount};
use std::borrow::Cow; use std::borrow::Cow;
@ -26,13 +27,13 @@ impl HashedPostState {
/// Initialize [`HashedPostState`] from bundle state. /// Initialize [`HashedPostState`] from bundle state.
/// Hashes all changed accounts and storage entries that are currently stored in the bundle /// Hashes all changed accounts and storage entries that are currently stored in the bundle
/// state. /// state.
pub fn from_bundle_state<'a>( pub fn from_bundle_state<'a, KH: KeyHasher>(
state: impl IntoParallelIterator<Item = (&'a Address, &'a BundleAccount)>, state: impl IntoParallelIterator<Item = (&'a Address, &'a BundleAccount)>,
) -> Self { ) -> Self {
let hashed = state let hashed = state
.into_par_iter() .into_par_iter()
.map(|(address, account)| { .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_account = account.info.clone().map(Into::into);
let hashed_storage = HashedStorage::from_plain_storage( let hashed_storage = HashedStorage::from_plain_storage(
account.status, account.status,
@ -53,13 +54,13 @@ impl HashedPostState {
/// Initialize [`HashedPostState`] from cached state. /// Initialize [`HashedPostState`] from cached state.
/// Hashes all changed accounts and storage entries that are currently stored in cache. /// 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<Item = (&'a Address, &'a CacheAccount)>, state: impl IntoParallelIterator<Item = (&'a Address, &'a CacheAccount)>,
) -> Self { ) -> Self {
let hashed = state let hashed = state
.into_par_iter() .into_par_iter()
.map(|(address, account)| { .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_account = account.account.as_ref().map(|a| a.info.clone().into());
let hashed_storage = HashedStorage::from_plain_storage( let hashed_storage = HashedStorage::from_plain_storage(
account.status, account.status,
@ -354,6 +355,7 @@ impl HashedStorageSorted {
mod tests { mod tests {
use super::*; use super::*;
use alloy_primitives::Bytes; use alloy_primitives::Bytes;
use reth_trie_common::KeccakKeyHasher;
use revm::{ use revm::{
db::{ db::{
states::{plain_account::PlainStorage, StorageSlot}, states::{plain_account::PlainStorage, StorageSlot},
@ -467,7 +469,7 @@ mod tests {
let state = vec![(&address, &account)]; let state = vec![(&address, &account)];
// Convert the bundle state into a hashed post state. // Convert the bundle state into a hashed post state.
let hashed_state = HashedPostState::from_bundle_state(state); let hashed_state = HashedPostState::from_bundle_state::<KeccakKeyHasher>(state);
// Validate the hashed post state. // Validate the hashed post state.
assert_eq!(hashed_state.accounts.len(), 1); assert_eq!(hashed_state.accounts.len(), 1);
@ -506,7 +508,7 @@ mod tests {
let state = vec![(&address, &account)]; let state = vec![(&address, &account)];
// Convert the cache state into a hashed post state. // Convert the cache state into a hashed post state.
let hashed_state = HashedPostState::from_cache_state(state); let hashed_state = HashedPostState::from_cache_state::<KeccakKeyHasher>(state);
// Validate the hashed post state. // Validate the hashed post state.
assert_eq!(hashed_state.accounts.len(), 1); assert_eq!(hashed_state.accounts.len(), 1);