mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-04-30 03:01:58 -04:00
Compare commits
2 Commits
push
...
alexey/exe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc59318e70 | ||
|
|
0585c84ca8 |
@@ -13,7 +13,7 @@ workspace = true
|
||||
[dependencies]
|
||||
# reth
|
||||
reth-chain-state.workspace = true
|
||||
reth-chainspec = { workspace = true, optional = true }
|
||||
reth-chainspec.workspace = true
|
||||
reth-consensus.workspace = true
|
||||
reth-db.workspace = true
|
||||
reth-engine-primitives = { workspace = true, features = ["std"] }
|
||||
@@ -79,7 +79,6 @@ reth-tracing = { workspace = true, optional = true }
|
||||
# reth
|
||||
reth-evm-ethereum = { workspace = true, features = ["test-utils"] }
|
||||
reth-chain-state = { workspace = true, features = ["test-utils"] }
|
||||
reth-chainspec.workspace = true
|
||||
reth-db-common.workspace = true
|
||||
reth-ethereum-consensus.workspace = true
|
||||
metrics-util = { workspace = true, features = ["debugging"] }
|
||||
|
||||
@@ -9,7 +9,7 @@ use alloy_primitives::{Address, B256};
|
||||
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
|
||||
use proptest::test_runner::TestRunner;
|
||||
use rand::Rng;
|
||||
use reth_chainspec::ChainSpec;
|
||||
use reth_chainspec::{ChainSpec, MAINNET};
|
||||
use reth_db_common::init::init_genesis;
|
||||
use reth_engine_tree::tree::{
|
||||
executor::WorkloadExecutor, precompile_cache::PrecompileCacheMap, PayloadProcessor,
|
||||
@@ -220,6 +220,7 @@ fn bench_state_root(c: &mut Criterion) {
|
||||
EthEvmConfig::new(factory.chain_spec()),
|
||||
&TreeConfig::default(),
|
||||
PrecompileCacheMap::default(),
|
||||
MAINNET.clone(),
|
||||
);
|
||||
let provider = BlockchainProvider::new(factory).unwrap();
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ use reth_trie::{
|
||||
updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof,
|
||||
MultiProofTargets, StorageMultiProof, StorageProof, TrieInput,
|
||||
};
|
||||
use revm_primitives::map::DefaultHashBuilder;
|
||||
use revm_primitives::{hardfork::SpecId, map::DefaultHashBuilder};
|
||||
use std::{sync::Arc, time::Duration};
|
||||
use tracing::{debug_span, instrument, trace};
|
||||
|
||||
@@ -442,7 +442,11 @@ impl ExecutionCache {
|
||||
///
|
||||
/// Returns an error if the state updates are inconsistent and should be discarded.
|
||||
#[instrument(level = "debug", target = "engine::caching", skip_all)]
|
||||
pub(crate) fn insert_state(&self, state_updates: &BundleState) -> Result<(), ()> {
|
||||
pub(crate) fn insert_state(
|
||||
&self,
|
||||
state_updates: &BundleState,
|
||||
spec: &SpecId,
|
||||
) -> Result<(), ()> {
|
||||
let _enter =
|
||||
debug_span!(target: "engine::tree", "contracts", len = state_updates.contracts.len())
|
||||
.entered();
|
||||
@@ -467,8 +471,13 @@ impl ExecutionCache {
|
||||
continue
|
||||
}
|
||||
|
||||
// If the account was destroyed, invalidate from the account / storage caches
|
||||
if account.was_destroyed() {
|
||||
// If the account was destroyed, invalidate from the account / storage caches.
|
||||
//
|
||||
// Post-cancun when EIP-6780 is live, an account can be destroyed only when it's created
|
||||
// in the same transaction. This guarantees that we will not have such accounts
|
||||
// and storage slots in our cache, because Revm doesn't go through the
|
||||
// Database for freshly created accounts. Hence we can safely ignore invalidating them.
|
||||
if account.was_destroyed() && !spec.is_enabled_in(revm_primitives::hardfork::CANCUN) {
|
||||
// Invalidate the account cache entry if destroyed
|
||||
self.account_cache.invalidate(addr);
|
||||
|
||||
|
||||
@@ -23,13 +23,14 @@ use multiproof::{SparseTrieUpdate, *};
|
||||
use parking_lot::RwLock;
|
||||
use prewarm::PrewarmMetrics;
|
||||
use rayon::prelude::*;
|
||||
use reth_chainspec::EthereumHardforks;
|
||||
use reth_evm::{
|
||||
execute::{ExecutableTxFor, WithTxEnv},
|
||||
ConfigureEvm, EvmEnvFor, ExecutableTxIterator, ExecutableTxTuple, OnStateHook, SpecFor,
|
||||
TxEnvFor,
|
||||
};
|
||||
use reth_execution_types::ExecutionOutcome;
|
||||
use reth_primitives_traits::NodePrimitives;
|
||||
use reth_primitives_traits::{HeaderTy, NodePrimitives};
|
||||
use reth_provider::{BlockReader, DatabaseProviderROFactory, StateProviderFactory, StateReader};
|
||||
use reth_revm::{db::BundleState, state::EvmState};
|
||||
use reth_trie::{hashed_cursor::HashedCursorFactory, trie_cursor::TrieCursorFactory};
|
||||
@@ -42,6 +43,7 @@ use reth_trie_sparse::{
|
||||
ClearedSparseStateTrie, SparseStateTrie, SparseTrie,
|
||||
};
|
||||
use reth_trie_sparse_parallel::{ParallelSparseTrie, ParallelismThresholds};
|
||||
use revm_primitives::hardfork::SpecId;
|
||||
use std::{
|
||||
collections::BTreeMap,
|
||||
sync::{
|
||||
@@ -102,7 +104,7 @@ type IteratorPayloadHandle<Evm, I, N> = PayloadHandle<
|
||||
|
||||
/// Entrypoint for executing the payload.
|
||||
#[derive(Debug)]
|
||||
pub struct PayloadProcessor<Evm>
|
||||
pub struct PayloadProcessor<Evm, C>
|
||||
where
|
||||
Evm: ConfigureEvm,
|
||||
{
|
||||
@@ -118,6 +120,7 @@ where
|
||||
disable_transaction_prewarming: bool,
|
||||
/// Whether state cache should be disable
|
||||
disable_state_cache: bool,
|
||||
chain_spec: Arc<C>,
|
||||
/// Determines how to configure the evm for execution.
|
||||
evm_config: Evm,
|
||||
/// Whether precompile cache should be disabled.
|
||||
@@ -137,7 +140,7 @@ where
|
||||
prewarm_max_concurrency: usize,
|
||||
}
|
||||
|
||||
impl<N, Evm> PayloadProcessor<Evm>
|
||||
impl<N, Evm, C> PayloadProcessor<Evm, C>
|
||||
where
|
||||
N: NodePrimitives,
|
||||
Evm: ConfigureEvm<Primitives = N>,
|
||||
@@ -153,6 +156,7 @@ where
|
||||
evm_config: Evm,
|
||||
config: &TreeConfig,
|
||||
precompile_cache_map: PrecompileCacheMap<SpecFor<Evm>>,
|
||||
chain_spec: Arc<C>,
|
||||
) -> Self {
|
||||
Self {
|
||||
executor,
|
||||
@@ -160,6 +164,7 @@ where
|
||||
trie_metrics: Default::default(),
|
||||
cross_block_cache_size: config.cross_block_cache_size(),
|
||||
disable_transaction_prewarming: config.disable_prewarming(),
|
||||
chain_spec,
|
||||
evm_config,
|
||||
disable_state_cache: config.disable_state_cache(),
|
||||
precompile_cache_disabled: config.precompile_cache_disabled(),
|
||||
@@ -171,10 +176,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<N, Evm> PayloadProcessor<Evm>
|
||||
impl<N, Evm, C> PayloadProcessor<Evm, C>
|
||||
where
|
||||
N: NodePrimitives,
|
||||
Evm: ConfigureEvm<Primitives = N> + 'static,
|
||||
C: EthereumHardforks,
|
||||
{
|
||||
/// Spawns all background tasks and returns a handle connected to the tasks.
|
||||
///
|
||||
@@ -540,6 +546,7 @@ where
|
||||
/// hitting the database, maintaining performance consistency.
|
||||
pub(crate) fn on_inserted_executed_block(
|
||||
&self,
|
||||
header: &HeaderTy<N>,
|
||||
block_with_parent: BlockWithParent,
|
||||
bundle_state: &BundleState,
|
||||
) {
|
||||
@@ -566,7 +573,7 @@ where
|
||||
|
||||
// Insert the block's bundle state into cache
|
||||
let new_cache = SavedCache::new(block_with_parent.block.hash, caches, cache_metrics);
|
||||
if new_cache.cache().insert_state(bundle_state).is_err() {
|
||||
if new_cache.cache().insert_state(bundle_state, &alloy_evm::spec(&self.chain_spec, header)).is_err() {
|
||||
*cached = None;
|
||||
debug!(target: "engine::caching", "cleared execution cache on update error");
|
||||
return;
|
||||
@@ -809,6 +816,8 @@ pub struct ExecutionEnv<Evm: ConfigureEvm> {
|
||||
pub hash: B256,
|
||||
/// Hash of the parent block.
|
||||
pub parent_hash: B256,
|
||||
/// Spec id associated with the EVM for the block being executed.
|
||||
pub spec_id: SpecId,
|
||||
}
|
||||
|
||||
impl<Evm: ConfigureEvm> Default for ExecutionEnv<Evm>
|
||||
@@ -820,6 +829,7 @@ where
|
||||
evm_env: Default::default(),
|
||||
hash: Default::default(),
|
||||
parent_hash: Default::default(),
|
||||
spec_id: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -835,10 +845,11 @@ mod tests {
|
||||
precompile_cache::PrecompileCacheMap,
|
||||
StateProviderBuilder, TreeConfig,
|
||||
};
|
||||
use alloy_consensus::Header;
|
||||
use alloy_eips::eip1898::{BlockNumHash, BlockWithParent};
|
||||
use alloy_evm::block::StateChangeSource;
|
||||
use rand::Rng;
|
||||
use reth_chainspec::ChainSpec;
|
||||
use reth_chainspec::{ChainSpec, MAINNET};
|
||||
use reth_db_common::init::init_genesis;
|
||||
use reth_ethereum_primitives::TransactionSigned;
|
||||
use reth_evm::OnStateHook;
|
||||
@@ -934,13 +945,14 @@ mod tests {
|
||||
EthEvmConfig::new(Arc::new(ChainSpec::default())),
|
||||
&TreeConfig::default(),
|
||||
PrecompileCacheMap::default(),
|
||||
MAINNET.clone(),
|
||||
);
|
||||
|
||||
let parent_hash = B256::from([1u8; 32]);
|
||||
let block_hash = B256::from([10u8; 32]);
|
||||
let header = Header::default();
|
||||
let block_hash = header.hash_slow();
|
||||
let block_with_parent = BlockWithParent {
|
||||
block: BlockNumHash { hash: block_hash, number: 1 },
|
||||
parent: parent_hash,
|
||||
block: BlockNumHash { hash: block_hash, number: header.number },
|
||||
parent: header.parent_hash,
|
||||
};
|
||||
let bundle_state = BundleState::default();
|
||||
|
||||
@@ -948,7 +960,7 @@ mod tests {
|
||||
assert!(payload_processor.execution_cache.get_cache_for(block_hash).is_none());
|
||||
|
||||
// Update cache with inserted block
|
||||
payload_processor.on_inserted_executed_block(block_with_parent, &bundle_state);
|
||||
payload_processor.on_inserted_executed_block(&header, block_with_parent, &bundle_state);
|
||||
|
||||
// Cache should now exist for the block hash
|
||||
let cached = payload_processor.execution_cache.get_cache_for(block_hash);
|
||||
@@ -963,24 +975,27 @@ mod tests {
|
||||
EthEvmConfig::new(Arc::new(ChainSpec::default())),
|
||||
&TreeConfig::default(),
|
||||
PrecompileCacheMap::default(),
|
||||
MAINNET.clone(),
|
||||
);
|
||||
|
||||
// Setup: populate cache with block 1
|
||||
let block1_hash = B256::from([1u8; 32]);
|
||||
let header1 = Header { number: 1, ..Default::default() };
|
||||
let block1_hash = header1.hash_slow();
|
||||
payload_processor
|
||||
.execution_cache
|
||||
.update_with_guard(|slot| *slot = Some(make_saved_cache(block1_hash)));
|
||||
|
||||
// Try to insert block 3 with wrong parent (should skip and keep block 1's cache)
|
||||
let wrong_parent = B256::from([99u8; 32]);
|
||||
let block3_hash = B256::from([3u8; 32]);
|
||||
let header3 =
|
||||
Header { parent_hash: B256::from([99u8; 32]), number: 3, ..Default::default() };
|
||||
let block3_hash = header3.hash_slow();
|
||||
let block_with_parent = BlockWithParent {
|
||||
block: BlockNumHash { hash: block3_hash, number: 3 },
|
||||
parent: wrong_parent,
|
||||
block: BlockNumHash { hash: block3_hash, number: header3.number },
|
||||
parent: header3.parent_hash,
|
||||
};
|
||||
let bundle_state = BundleState::default();
|
||||
|
||||
payload_processor.on_inserted_executed_block(block_with_parent, &bundle_state);
|
||||
payload_processor.on_inserted_executed_block(&header3, block_with_parent, &bundle_state);
|
||||
|
||||
// Cache should still be for block 1 (unchanged)
|
||||
let cached = payload_processor.execution_cache.get_cache_for(block1_hash);
|
||||
@@ -1096,6 +1111,7 @@ mod tests {
|
||||
EthEvmConfig::new(factory.chain_spec()),
|
||||
&TreeConfig::default(),
|
||||
PrecompileCacheMap::default(),
|
||||
MAINNET.clone(),
|
||||
);
|
||||
|
||||
let provider_factory = BlockchainProvider::new(factory).unwrap();
|
||||
|
||||
@@ -265,7 +265,8 @@ where
|
||||
|
||||
// Insert state into cache while holding the lock
|
||||
// Access the BundleState through the shared ExecutionOutcome
|
||||
if new_cache.cache().insert_state(execution_outcome.state()).is_err() {
|
||||
if new_cache.cache().insert_state(execution_outcome.state(), &env.spec_id).is_err()
|
||||
{
|
||||
// Clear the cache on error to prevent having a polluted cache
|
||||
*cached = None;
|
||||
debug!(target: "engine::caching", "cleared execution cache on update error");
|
||||
|
||||
@@ -14,9 +14,10 @@ use alloy_consensus::transaction::Either;
|
||||
use alloy_eip7928::BlockAccessList;
|
||||
use alloy_eips::{eip1898::BlockWithParent, NumHash};
|
||||
use alloy_evm::Evm;
|
||||
use alloy_primitives::B256;
|
||||
use alloy_primitives::{BlockTimestamp, B256};
|
||||
use rayon::prelude::*;
|
||||
use reth_chain_state::{CanonicalInMemoryState, DeferredTrieData, ExecutedBlock};
|
||||
use reth_chainspec::EthereumHardforks;
|
||||
use reth_consensus::{ConsensusError, FullConsensus};
|
||||
use reth_engine_primitives::{
|
||||
ConfigureEngineEvm, ExecutableTxIterator, ExecutionPayload, InvalidBlockHook, PayloadValidator,
|
||||
@@ -34,7 +35,7 @@ use reth_primitives_traits::{
|
||||
SealedHeader, SignerRecoverable,
|
||||
};
|
||||
use reth_provider::{
|
||||
providers::OverlayStateProviderFactory, BlockExecutionOutput, BlockReader,
|
||||
providers::OverlayStateProviderFactory, BlockExecutionOutput, BlockReader, ChainSpecProvider,
|
||||
DatabaseProviderFactory, DatabaseProviderROFactory, ExecutionOutcome, HashedPostStateProvider,
|
||||
ProviderError, PruneCheckpointReader, StageCheckpointReader, StateProvider,
|
||||
StateProviderFactory, StateReader, TrieReader,
|
||||
@@ -108,6 +109,7 @@ impl<'a, N: NodePrimitives> TreeCtx<'a, N> {
|
||||
pub struct BasicEngineValidator<P, Evm, V>
|
||||
where
|
||||
Evm: ConfigureEvm,
|
||||
P: ChainSpecProvider<ChainSpec: EthereumHardforks>,
|
||||
{
|
||||
/// Provider for database access.
|
||||
provider: P,
|
||||
@@ -118,7 +120,7 @@ where
|
||||
/// Configuration for the tree.
|
||||
config: TreeConfig,
|
||||
/// Payload processor for state root computation.
|
||||
payload_processor: PayloadProcessor<Evm>,
|
||||
payload_processor: PayloadProcessor<Evm, P::ChainSpec>,
|
||||
/// Precompile cache map.
|
||||
precompile_cache_map: PrecompileCacheMap<SpecFor<Evm>>,
|
||||
/// Precompile cache metrics.
|
||||
@@ -141,6 +143,7 @@ where
|
||||
+ StateProviderFactory
|
||||
+ StateReader
|
||||
+ HashedPostStateProvider
|
||||
+ ChainSpecProvider<ChainSpec: EthereumHardforks>
|
||||
+ Clone
|
||||
+ 'static,
|
||||
Evm: ConfigureEvm<Primitives = N> + 'static,
|
||||
@@ -161,6 +164,7 @@ where
|
||||
evm_config.clone(),
|
||||
&config,
|
||||
precompile_cache_map.clone(),
|
||||
provider.chain_spec(),
|
||||
);
|
||||
Self {
|
||||
provider,
|
||||
@@ -390,7 +394,14 @@ where
|
||||
.in_scope(|| self.evm_env_for(&input))
|
||||
.map_err(NewPayloadError::other)?;
|
||||
|
||||
let env = ExecutionEnv { evm_env, hash: input.hash(), parent_hash: input.parent_hash() };
|
||||
let spec_id = alloy_evm::spec_by_timestamp_and_block_number(
|
||||
&provider_builder.provider_factory.chain_spec(),
|
||||
input.timestamp(),
|
||||
input.num_hash().number,
|
||||
);
|
||||
|
||||
let env =
|
||||
ExecutionEnv { evm_env, hash: input.hash(), parent_hash: input.parent_hash(), spec_id };
|
||||
|
||||
// Plan the strategy used for state root computation.
|
||||
let strategy = self.plan_state_root_computation();
|
||||
@@ -1185,6 +1196,7 @@ where
|
||||
+ StateProviderFactory
|
||||
+ StateReader
|
||||
+ HashedPostStateProvider
|
||||
+ ChainSpecProvider<ChainSpec: EthereumHardforks>
|
||||
+ Clone
|
||||
+ 'static,
|
||||
N: NodePrimitives,
|
||||
@@ -1226,6 +1238,7 @@ where
|
||||
|
||||
fn on_inserted_executed_block(&self, block: ExecutedBlock<N>) {
|
||||
self.payload_processor.on_inserted_executed_block(
|
||||
block.recovered_block.header(),
|
||||
block.recovered_block.block_with_parent(),
|
||||
block.execution_output.state(),
|
||||
);
|
||||
@@ -1258,6 +1271,14 @@ impl<T: PayloadTypes> BlockOrPayload<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the timestamp of the block.
|
||||
pub fn timestamp(&self) -> BlockTimestamp {
|
||||
match self {
|
||||
Self::Payload(payload) => payload.timestamp(),
|
||||
Self::Block(block) => block.timestamp(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the parent hash of the block.
|
||||
pub fn parent_hash(&self) -> B256 {
|
||||
match self {
|
||||
|
||||
@@ -1319,6 +1319,7 @@ where
|
||||
impl<Node, EV> EngineValidatorBuilder<Node> for BasicEngineValidatorBuilder<EV>
|
||||
where
|
||||
Node: FullNodeComponents<
|
||||
Types: NodeTypes<ChainSpec: EthereumHardforks>,
|
||||
Evm: ConfigureEngineEvm<
|
||||
<<Node::Types as NodeTypes>::Payload as PayloadTypes>::ExecutionData,
|
||||
>,
|
||||
|
||||
Reference in New Issue
Block a user