Skip to content

Commit

Permalink
Introduce HashedPostStateProvider (#45)
Browse files Browse the repository at this point in the history
* feat: introduce StateCommitment in StateProviders

* refactor: introduce StateCommimentProvider

* feat: introduce HashedPostStateProvider

* feat: HashedPostState from reverts

* lint: revm/test-utils feature propogation

* fix: add Send + Sync bound on introduced storage state api methods

* fix: add merge files

* fix lint

* fix lint

* fmt

* address PR feedback
  • Loading branch information
frisitano authored Dec 2, 2024
1 parent fbf8e9e commit 1996f4e
Show file tree
Hide file tree
Showing 48 changed files with 322 additions and 148 deletions.
5 changes: 1 addition & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions bin/reth/src/commands/debug_cmd/build_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,8 @@ impl<C: ChainSpecParser<ChainSpec = ChainSpec>> Command<C> {
let block_with_senders =
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 =
EthExecutorProvider::ethereum(provider_factory.chain_spec()).executor(db);

Expand All @@ -271,7 +272,7 @@ impl<C: ChainSpecParser<ChainSpec = ChainSpec>> Command<C> {
ExecutionOutcome::from((block_execution_output, block.number));
debug!(target: "reth::cli", ?execution_outcome, "Executed block");

let hashed_post_state = execution_outcome.hash_state_slow();
let hashed_post_state = state_provider.hashed_post_state(execution_outcome.state());
let (state_root, trie_updates) = StateRoot::overlay_root_with_updates(
provider_factory.provider()?.tx_ref(),
hashed_post_state.clone(),
Expand Down
10 changes: 6 additions & 4 deletions bin/reth/src/commands/debug_cmd/in_memory_merkle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ use reth_node_ethereum::EthExecutorProvider;
use reth_primitives::BlockExt;
use reth_provider::{
providers::ProviderNodeTypes, AccountExtReader, ChainSpecProvider, DatabaseProviderFactory,
HashingWriter, HeaderProvider, LatestStateProviderRef, OriginalValuesKnown, ProviderFactory,
StageCheckpointReader, StateWriter, StorageLocation, StorageReader,
HashedPostStateProvider, HashingWriter, HeaderProvider, LatestStateProviderRef,
OriginalValuesKnown, ProviderFactory, StageCheckpointReader, StateWriter, StorageLocation,
StorageReader,
};
use reth_revm::database::StateProviderDatabase;
use reth_stages::StageId;
Expand Down Expand Up @@ -142,7 +143,8 @@ impl<C: ChainSpecParser<ChainSpec = ChainSpec>> Command<C> {
)
.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);

Expand All @@ -164,7 +166,7 @@ impl<C: ChainSpecParser<ChainSpec = ChainSpec>> Command<C> {
// Unpacked `BundleState::state_root_slow` function
let (in_memory_state_root, in_memory_updates) = StateRoot::overlay_root_with_updates(
provider.tx_ref(),
execution_outcome.hash_state_slow(),
state_provider.hashed_post_state(execution_outcome.state()),
)?;

if in_memory_state_root == block.state_root {
Expand Down
13 changes: 9 additions & 4 deletions crates/blockchain-tree/src/blockchain_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ use reth_primitives::{
use reth_provider::{
BlockExecutionWriter, BlockNumReader, BlockWriter, CanonStateNotification,
CanonStateNotificationSender, CanonStateNotifications, ChainSpecProvider, ChainSplit,
ChainSplitTarget, DBProvider, DisplayBlocksChain, HeaderProvider, ProviderError,
StaticFileProviderFactory, StorageLocation,
ChainSplitTarget, DBProvider, DisplayBlocksChain, HashedPostStateProvider, HeaderProvider,
ProviderError, StaticFileProviderFactory, StorageLocation,
};
use reth_stages_api::{MetricEvent, MetricEventsSender};
use reth_storage_errors::provider::{ProviderResult, RootMismatch};
Expand Down Expand Up @@ -1215,7 +1215,7 @@ where
recorder: &mut MakeCanonicalDurationsRecorder,
) -> Result<(), CanonicalError> {
let (blocks, state, chain_trie_updates) = chain.into_inner();
let hashed_state = state.hash_state_slow();
let hashed_state = self.externals.provider_factory.hashed_post_state(state.state());
let prefix_sets = hashed_state.construct_prefix_sets().freeze();
let hashed_state_sorted = hashed_state.into_sorted();

Expand Down Expand Up @@ -1880,7 +1880,12 @@ mod tests {
);

let provider = tree.externals.provider_factory.provider().unwrap();
let prefix_sets = exec5.hash_state_slow().construct_prefix_sets().freeze();
let prefix_sets = tree
.externals
.provider_factory
.hashed_post_state(exec5.state())
.construct_prefix_sets()
.freeze();
let state_root =
StateRoot::from_tx(provider.tx_ref()).with_prefix_sets(prefix_sets).root().unwrap();
assert_eq!(state_root, block5.state_root);
Expand Down
11 changes: 5 additions & 6 deletions crates/blockchain-tree/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ use reth_execution_types::{Chain, ExecutionOutcome};
use reth_primitives::{GotExpected, SealedBlockWithSenders, SealedHeader};
use reth_provider::{
providers::{BundleStateProvider, ConsistentDbView, ProviderNodeTypes},
DBProvider, FullExecutionDataProvider, ProviderError, StateRootProvider,
TryIntoHistoricalStateProvider,
DBProvider, FullExecutionDataProvider, HashedPostStateProvider, ProviderError,
StateRootProvider, TryIntoHistoricalStateProvider,
};
use reth_trie::{updates::TrieUpdates, HashedPostState, TrieInput};
use reth_trie::{updates::TrieUpdates, TrieInput};
use reth_trie_parallel::root::ParallelStateRoot;
use std::{
collections::BTreeMap,
Expand Down Expand Up @@ -230,14 +230,13 @@ impl AppendableChain {
execution_outcome.extend(initial_execution_outcome.clone());
ParallelStateRoot::new(
consistent_view,
TrieInput::from_state(execution_outcome.hash_state_slow()),
TrieInput::from_state(provider.hashed_post_state(execution_outcome.state())),
)
.incremental_root_with_updates()
.map(|(root, updates)| (root, Some(updates)))
.map_err(ProviderError::from)?
} else {
let hashed_state =
HashedPostState::from_bundle_state(&initial_execution_outcome.state().state);
let hashed_state = provider.hashed_post_state(initial_execution_outcome.state());
let state_root = provider.state_root(hashed_state)?;
(state_root, None)
};
Expand Down
6 changes: 2 additions & 4 deletions crates/chain-state/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ reth-trie.workspace = true
alloy-eips.workspace = true
alloy-primitives.workspace = true
alloy-consensus.workspace = true
revm.workspace = true

# async
tokio = { workspace = true, default-features = false, features = ["sync", "macros"] }
Expand All @@ -44,25 +45,22 @@ pin-project.workspace = true
alloy-signer = { workspace = true, optional = true }
alloy-signer-local = { workspace = true, optional = true }
rand = { workspace = true, optional = true }
revm = { workspace = true, optional = true }

[dev-dependencies]
reth-testing-utils.workspace = true
alloy-signer.workspace = true
alloy-signer-local.workspace = true
alloy-consensus.workspace = true
rand.workspace = true
revm.workspace = true

[features]
test-utils = [
"alloy-signer",
"alloy-signer-local",
"rand",
"revm",
"reth-chainspec/test-utils",
"reth-primitives/test-utils",
"reth-primitives-traits/test-utils",
"reth-trie/test-utils",
"revm?/test-utils",
"revm/test-utils",
]
10 changes: 8 additions & 2 deletions crates/chain-state/src/in_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -949,8 +949,8 @@ mod tests {
use reth_errors::ProviderResult;
use reth_primitives::{Account, Bytecode, EthPrimitives, Receipt};
use reth_storage_api::{
AccountReader, BlockHashReader, StateProofProvider, StateProvider, StateRootProvider,
StorageRootProvider,
AccountReader, BlockHashReader, HashedPostStateProvider, StateProofProvider, StateProvider,
StateRootProvider, StorageRootProvider,
};
use reth_trie::{
AccountProof, HashedStorage, MultiProof, StorageMultiProof, StorageProof, TrieInput,
Expand Down Expand Up @@ -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 {
fn storage_root(
&self,
Expand Down
11 changes: 9 additions & 2 deletions crates/chain-state/src/memory_overlay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ use alloy_primitives::{
use reth_errors::ProviderResult;
use reth_primitives::{Account, Bytecode, NodePrimitives};
use reth_storage_api::{
AccountReader, BlockHashReader, StateProofProvider, StateProvider, StateRootProvider,
StorageRootProvider,
AccountReader, BlockHashReader, HashedPostStateProvider, StateProofProvider, StateProvider,
StateRootProvider, StorageRootProvider,
};
use reth_trie::{
updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof,
StorageMultiProof, TrieInput,
};
use revm::db::BundleState;
use std::sync::OnceLock;

/// A state provider that stores references to in-memory blocks along with their state as well as a
Expand Down Expand Up @@ -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 {
fn storage(
&self,
Expand Down
4 changes: 2 additions & 2 deletions crates/engine/invalid-block-hooks/src/witness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use reth_revm::{
use reth_rpc_api::DebugApiClient;
use reth_scroll_execution::FinalizeExecution;
use reth_tracing::tracing::warn;
use reth_trie::{updates::TrieUpdates, HashedPostState, HashedStorage};
use reth_trie::{updates::TrieUpdates, HashedStorage};
use serde::Serialize;
use std::{collections::HashMap, fmt::Debug, fs::File, io::Write, path::PathBuf};

Expand Down Expand Up @@ -127,7 +127,7 @@ where
//
// Note: We grab *all* accounts in the cache here, as the `BundleState` prunes
// referenced accounts + storage slots.
let mut hashed_state = HashedPostState::from_bundle_state(&bundle_state.state);
let mut hashed_state = db.database.hashed_post_state(&bundle_state);
for (address, account) in db.cache.accounts {
let hashed_address = keccak256(address);
#[cfg(feature = "scroll")]
Expand Down
10 changes: 6 additions & 4 deletions crates/engine/tree/src/tree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ use reth_primitives::{
};
use reth_provider::{
providers::ConsistentDbView, BlockReader, DatabaseProviderFactory, ExecutionOutcome,
ProviderError, StateProviderBox, StateProviderFactory, StateReader, StateRootProvider,
TransactionVariant,
HashedPostStateProvider, ProviderError, StateCommitmentProvider, StateProviderBox,
StateProviderFactory, StateReader, StateRootProvider, TransactionVariant,
};
use reth_revm::database::StateProviderDatabase;
use reth_stages_api::ControlFlow;
Expand Down Expand Up @@ -545,6 +545,8 @@ where
+ BlockReader<Block = reth_primitives::Block>
+ StateProviderFactory
+ StateReader<Receipt = reth_primitives::Receipt>
+ StateCommitmentProvider
+ HashedPostStateProvider
+ Clone
+ 'static,
<P as DatabaseProviderFactory>::Provider: BlockReader,
Expand Down Expand Up @@ -1561,7 +1563,7 @@ where
.provider
.get_state(block.number())?
.ok_or_else(|| ProviderError::StateForNumberNotFound(block.number()))?;
let hashed_state = execution_output.hash_state_slow();
let hashed_state = self.provider.hashed_post_state(execution_output.state());

Ok(Some(ExecutedBlock {
block: Arc::new(block),
Expand Down Expand Up @@ -2235,7 +2237,7 @@ where
return Err(err.into())
}

let hashed_state = HashedPostState::from_bundle_state(&output.state.state);
let hashed_state = self.provider.hashed_post_state(&output.state);

trace!(target: "engine::tree", block=?sealed_block.num_hash(), "Calculating block state root");
let root_time = Instant::now();
Expand Down
8 changes: 7 additions & 1 deletion crates/engine/tree/src/tree/root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use alloy_primitives::map::{HashMap, HashSet};
use reth_provider::{
providers::ConsistentDbView, BlockReader, DBProvider, DatabaseProviderFactory,
StateCommitmentProvider,
};
use reth_trie::{
proof::Proof, updates::TrieUpdates, HashedPostState, HashedStorage, MultiProof, Nibbles,
Expand Down Expand Up @@ -176,7 +177,12 @@ pub(crate) struct StateRootTask<Factory> {
#[allow(dead_code)]
impl<Factory> StateRootTask<Factory>
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
pub(crate) fn new(
Expand Down
3 changes: 1 addition & 2 deletions crates/engine/util/src/reorg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ use reth_revm::{
};
use reth_rpc_types_compat::engine::payload::block_to_payload;
use reth_scroll_execution::FinalizeExecution;
use reth_trie::HashedPostState;
use revm_primitives::{calc_excess_blob_gas, EVMError, EnvWithHandlerCfg};
use std::{
collections::VecDeque,
Expand Down Expand Up @@ -380,7 +379,7 @@ where
reorg_target.number,
Default::default(),
);
let hashed_state = HashedPostState::from_bundle_state(&outcome.state().state);
let hashed_state = state_provider.hashed_post_state(outcome.state());

let (blob_gas_used, excess_blob_gas) =
if chain_spec.is_cancun_active_at_timestamp(reorg_target.timestamp) {
Expand Down
1 change: 0 additions & 1 deletion crates/ethereum/payload/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ reth-basic-payload-builder.workspace = true
reth-evm.workspace = true
reth-evm-ethereum.workspace = true
reth-errors.workspace = true
reth-trie.workspace = true
reth-chain-state.workspace = true
reth-chainspec.workspace = true

Expand Down
3 changes: 1 addition & 2 deletions crates/ethereum/payload/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ use reth_transaction_pool::{
error::InvalidPoolTransactionError, noop::NoopTransactionPool, BestTransactions,
BestTransactionsAttributes, TransactionPool, ValidPoolTransaction,
};
use reth_trie::HashedPostState;
use revm::{
db::{states::bundle_state::BundleRetention, State},
primitives::{
Expand Down Expand Up @@ -392,7 +391,7 @@ where
let logs_bloom = execution_outcome.block_logs_bloom(block_number).expect("Number is in range");

// calculate the state root
let hashed_state = HashedPostState::from_bundle_state(&execution_outcome.state().state);
let hashed_state = db.database.db.hashed_post_state(execution_outcome.state());
let (state_root, trie_output) = {
db.database.inner().state_root_with_updates(hashed_state.clone()).inspect_err(|err| {
warn!(target: "payload_builder",
Expand Down
6 changes: 3 additions & 3 deletions crates/evm/execution-types/src/execution_outcome.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use alloy_eips::eip7685::Requests;
use alloy_primitives::{Address, BlockNumber, Bloom, Log, B256, U256};
use reth_primitives::{logs_bloom, Account, Bytecode, Receipts, StorageEntry};
use reth_primitives_traits::{receipt::ReceiptExt, Receipt};
use reth_trie::HashedPostState;
use reth_trie::{HashedPostState, KeyHasher};
use revm::{
db::{states::BundleState, BundleAccount},
primitives::AccountInfo,
Expand Down Expand Up @@ -166,8 +166,8 @@ impl<T> ExecutionOutcome<T> {

/// 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<KH: KeyHasher>(&self) -> HashedPostState {
HashedPostState::from_bundle_state::<KH>(&self.bundle.state)
}

/// Transform block number to the index of block.
Expand Down
2 changes: 1 addition & 1 deletion crates/net/eth-wire/src/capability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ pub fn shared_capability_offsets(
// highest wins, others are ignored
if shared_capabilities
.get(&peer_capability.name)
.map_or(true, |v| peer_capability.version > v.version)
.is_none_or(|v| peer_capability.version > v.version)
{
shared_capabilities.insert(
peer_capability.name.clone(),
Expand Down
Loading

0 comments on commit 1996f4e

Please sign in to comment.