Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DatabaseState abstraction #11786

Closed
wants to merge 13 commits into from
13 changes: 3 additions & 10 deletions Cargo.lock

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

2 changes: 0 additions & 2 deletions bin/reth/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ reth-payload-primitives.workspace = true
reth-payload-validator.workspace = true
reth-basic-payload-builder.workspace = true
reth-static-file.workspace = true
reth-trie = { workspace = true, features = ["metrics"] }
reth-trie-db = { workspace = true, features = ["metrics"] }
reth-node-api.workspace = true
reth-node-core.workspace = true
reth-ethereum-payload-builder.workspace = true
Expand Down
15 changes: 7 additions & 8 deletions bin/reth/src/commands/debug_cmd/build_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,15 @@ use reth_primitives::{
};
use reth_provider::{
providers::BlockchainProvider, BlockHashReader, BlockReader, BlockWriter, ChainSpecProvider,
ProviderFactory, StageCheckpointReader, StateProviderFactory,
HashedPostStateProvider, ProviderFactory, StageCheckpointReader, StateProviderFactory,
StateRootProvider,
};
use reth_revm::{database::StateProviderDatabase, primitives::EnvKzgSettings};
use reth_stages::StageId;
use reth_transaction_pool::{
blobstore::InMemoryBlobStore, BlobStore, EthPooledTransaction, PoolConfig, TransactionOrigin,
TransactionPool, TransactionValidationTaskExecutor,
};
use reth_trie::StateRoot;
use reth_trie_db::DatabaseStateRoot;
use std::{path::PathBuf, str::FromStr, sync::Arc};
use tracing::*;

Expand Down Expand Up @@ -266,11 +265,11 @@ 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 (state_root, trie_updates) = StateRoot::overlay_root_with_updates(
provider_factory.provider()?.tx_ref(),
hashed_post_state.clone(),
)?;
let provider = provider_factory.provider()?;
let hashed_post_state =
provider.hashed_post_state_from_bundle_state(&execution_outcome.bundle);
let (state_root, trie_updates, _) =
provider.state_root_from_post_state_with_updates(hashed_post_state.clone())?;

if state_root != block_with_senders.state_root {
eyre::bail!(
Expand Down
29 changes: 11 additions & 18 deletions bin/reth/src/commands/debug_cmd/in_memory_merkle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,13 @@ 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, ChainSpecProvider, HashedPostStateProvider,
HashingWriter, HeaderProvider, OriginalValuesKnown, ProviderFactory, StageCheckpointReader,
StateRootProvider, StateWriter, StorageReader, ToLatestStateProviderRef,
};
use reth_revm::database::StateProviderDatabase;
use reth_stages::StageId;
use reth_tasks::TaskExecutor;
use reth_trie::StateRoot;
use reth_trie_db::DatabaseStateRoot;
use std::{path::PathBuf, sync::Arc};
use tracing::*;

Expand Down Expand Up @@ -131,10 +129,7 @@ impl<C: ChainSpecParser<ChainSpec = ChainSpec>> Command<C> {
)
.await?;

let db = StateProviderDatabase::new(LatestStateProviderRef::new(
provider.tx_ref(),
provider_factory.static_file_provider(),
));
let db = StateProviderDatabase::new(provider.latest_ref());

let executor = EthExecutorProvider::ethereum(provider_factory.chain_spec()).executor(db);

Expand All @@ -152,16 +147,16 @@ impl<C: ChainSpecParser<ChainSpec = ChainSpec>> Command<C> {
.into(),
)?;
let execution_outcome = ExecutionOutcome::from((block_execution_output, block.number));
let hashed_post_state =
provider.hashed_post_state_from_bundle_state(&execution_outcome.bundle);

// 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(),
)?;
let (in_memory_state_root, in_memory_updates, _) =
provider.state_root_from_post_state_with_updates(hashed_post_state)?;

if in_memory_state_root == block.state_root {
info!(target: "reth::cli", state_root = ?in_memory_state_root, "Computed in-memory state root matches");
return Ok(())
return Ok(());
}

let provider_rw = provider_factory.provider_rw()?;
Expand All @@ -182,10 +177,8 @@ impl<C: ChainSpecParser<ChainSpec = ChainSpec>> Command<C> {
let accounts = provider_rw.basic_accounts(account_lists)?;
provider_rw.insert_account_for_hashing(accounts)?;

let (state_root, incremental_trie_updates) = StateRoot::incremental_root_with_updates(
provider_rw.tx_ref(),
block.number..=block.number,
)?;
let (state_root, incremental_trie_updates) =
provider_rw.latest_ref().incremental_root_with_updates(block.number..=block.number)?;
if state_root != block.state_root {
eyre::bail!(
"Computed incremental state root mismatch. Expected: {:?}. Got: {:?}",
Expand Down
12 changes: 4 additions & 8 deletions bin/reth/src/commands/debug_cmd/merkle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ 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,
DatabaseProviderFactory, HeaderProvider, OriginalValuesKnown, ProviderError, ProviderFactory,
StateWriter, ToLatestStateProviderRef,
};
use reth_revm::database::StateProviderDatabase;
use reth_stages::{
Expand Down Expand Up @@ -152,12 +152,8 @@ impl<C: ChainSpecParser<ChainSpec = ChainSpec>> Command<C> {
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_ref()));
executor.execute_and_verify_one((&sealed_block.clone().unseal(), td).into())?;
let execution_outcome = executor.finalize();

Expand Down
1 change: 0 additions & 1 deletion crates/blockchain-tree/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ reth-provider.workspace = true
reth-execution-types.workspace = true
reth-stages-api.workspace = true
reth-trie = { workspace = true, features = ["metrics"] }
reth-trie-db = { workspace = true, features = ["metrics"] }
reth-trie-parallel.workspace = true
reth-network.workspace = true
reth-consensus.workspace = true
Expand Down
38 changes: 15 additions & 23 deletions crates/blockchain-tree/src/blockchain_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,11 @@ 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, StateRootProvider, StaticFileProviderFactory,
};
use reth_stages_api::{MetricEvent, MetricEventsSender};
use reth_storage_errors::provider::{ProviderResult, RootMismatch};
use reth_trie::{hashed_cursor::HashedPostStateCursorFactory, StateRoot};
use reth_trie_db::{DatabaseHashedCursorFactory, DatabaseStateRoot};
use std::{
collections::{btree_map::Entry, BTreeMap, HashSet},
sync::Arc,
Expand Down Expand Up @@ -1216,18 +1214,17 @@ where
recorder: &mut MakeCanonicalDurationsRecorder,
) -> Result<(), CanonicalError> {
let (blocks, state, chain_trie_updates) = chain.into_inner();
let hashed_state = state.hash_state_slow();
let prefix_sets = hashed_state.construct_prefix_sets().freeze();
let hashed_state_sorted = hashed_state.into_sorted();
let hashed_state =
self.externals.provider_factory.hashed_post_state_from_bundle_state(&state.bundle);

// Compute state root or retrieve cached trie updates before opening write transaction.
let block_hash_numbers =
blocks.iter().map(|(number, b)| (number, b.hash())).collect::<Vec<_>>();
let trie_updates = match chain_trie_updates {
let (trie_updates, hashed_state_sorted) = match chain_trie_updates {
Some(updates) => {
debug!(target: "blockchain_tree", blocks = ?block_hash_numbers, "Using cached trie updates");
self.metrics.trie_updates_insert_cached.increment(1);
updates
(updates, hashed_state.into_sorted())
}
None => {
debug!(target: "blockchain_tree", blocks = ?block_hash_numbers, "Recomputing state root for insert");
Expand All @@ -1238,14 +1235,8 @@ where
// State root calculation can take a while, and we're sure no write transaction
// will be open in parallel. See https://github.com/paradigmxyz/reth/issues/6168.
.disable_long_read_transaction_safety();
let (state_root, trie_updates) = StateRoot::from_tx(provider.tx_ref())
.with_hashed_cursor_factory(HashedPostStateCursorFactory::new(
DatabaseHashedCursorFactory::new(provider.tx_ref()),
&hashed_state_sorted,
))
.with_prefix_sets(prefix_sets)
.root_with_updates()
.map_err(Into::<BlockValidationError>::into)?;
let (state_root, trie_updates, hashed_state_sorted) =
provider.state_root_from_post_state_with_updates(hashed_state)?;
let tip = blocks.tip();
if state_root != tip.state_root {
return Err(ProviderError::StateRootMismatch(Box::new(RootMismatch {
Expand All @@ -1256,7 +1247,7 @@ where
.into())
}
self.metrics.trie_updates_insert_recomputed.increment(1);
trie_updates
(trie_updates, hashed_state_sorted)
}
};
recorder.record_relative(MakeCanonicalAction::RetrieveStateTrieUpdates);
Expand Down Expand Up @@ -1399,10 +1390,10 @@ mod tests {
blocks::BlockchainTestData, create_test_provider_factory_with_chain_spec,
MockNodeTypesWithDB,
},
ProviderFactory,
ProviderFactory, StateRootProvider,
};
use reth_stages_api::StageCheckpoint;
use reth_trie::{root::state_root_unhashed, StateRoot};
use reth_trie::{root::state_root_unhashed, TrieInput};
use std::collections::HashMap;

fn setup_externals(
Expand Down Expand Up @@ -1875,9 +1866,10 @@ mod tests {
);

let provider = tree.externals.provider_factory.provider().unwrap();
let prefix_sets = exec5.hash_state_slow().construct_prefix_sets().freeze();
let state_root =
StateRoot::from_tx(provider.tx_ref()).with_prefix_sets(prefix_sets).root().unwrap();
let prefix_sets =
provider.hashed_post_state_from_bundle_state(&exec5.bundle).construct_prefix_sets();
let state_root_input = TrieInput::new(Default::default(), Default::default(), prefix_sets);
let state_root = provider.state_root_from_nodes(state_root_input).unwrap();
assert_eq!(state_root, block5.state_root);
}

Expand Down
23 changes: 15 additions & 8 deletions crates/blockchain-tree/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@ use reth_execution_errors::BlockExecutionError;
use reth_execution_types::{Chain, ExecutionOutcome};
use reth_primitives::{GotExpected, SealedBlockWithSenders, SealedHeader};
use reth_provider::{
providers::{BundleStateProvider, ConsistentDbView, ProviderNodeTypes},
FullExecutionDataProvider, ProviderError, StateRootProvider, TryIntoHistoricalStateProvider,
providers::{ConsistentDbView, ProviderNodeTypes},
FullExecutionDataProvider, HashedPostStateProvider, ProviderError, ProviderFactory,
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,
Expand Down Expand Up @@ -201,7 +202,8 @@ impl AppendableChain {
.disable_long_read_transaction_safety()
.try_into_history_at_block(canonical_fork.number)?;

let provider = BundleStateProvider::new(state_provider, bundle_state_data_provider);
let provider =
ProviderFactory::<N>::bundle_state_provider(state_provider, bundle_state_data_provider);

let db = StateProviderDatabase::new(&provider);
let executor = externals.executor_factory.executor(db);
Expand All @@ -227,15 +229,20 @@ 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.bundle),
),
)
.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 state_root = provider.state_root(hashed_state)?;
let hashed_state = externals
.provider_factory
.hashed_post_state_from_bundle_state(&initial_execution_outcome.bundle);
let state_root = provider.state_root_from_post_state(hashed_state)?;
(state_root, None)
};
if block.state_root != state_root {
Expand Down
1 change: 1 addition & 0 deletions crates/chain-state/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ reth-metrics.workspace = true
reth-primitives.workspace = true
reth-storage-api.workspace = true
reth-trie.workspace = true
reth-revm.workspace = true

# ethereum
alloy-eips.workspace = true
Expand Down
Loading
Loading