From 3bf1110403043a8bb8b52199d9a620d7bd1b78a4 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Wed, 21 May 2025 16:36:31 +0100 Subject: [PATCH] feat: Genericise `stateless_validation` API so that it is not fixed to `Eth` types (#16328) Co-authored-by: Matthias Seitz --- Cargo.lock | 1 - crates/stateless/Cargo.toml | 1 - crates/stateless/src/validation.rs | 27 ++++++++++++------- testing/ef-tests/src/cases/blockchain_test.rs | 11 +++++--- 4 files changed, 25 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1c3a4ca401..c4a7107201 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10036,7 +10036,6 @@ dependencies = [ "reth-ethereum-consensus", "reth-ethereum-primitives", "reth-evm", - "reth-evm-ethereum", "reth-primitives-traits", "reth-revm", "reth-trie-common", diff --git a/crates/stateless/Cargo.toml b/crates/stateless/Cargo.toml index d452521aa1..ef0315c0ad 100644 --- a/crates/stateless/Cargo.toml +++ b/crates/stateless/Cargo.toml @@ -25,7 +25,6 @@ reth-primitives-traits.workspace = true reth-ethereum-primitives.workspace = true reth-errors.workspace = true reth-evm.workspace = true -reth-evm-ethereum.workspace = true reth-revm.workspace = true reth-trie-common.workspace = true reth-trie-sparse.workspace = true diff --git a/crates/stateless/src/validation.rs b/crates/stateless/src/validation.rs index b51cc1cc3f..d73c4d54c0 100644 --- a/crates/stateless/src/validation.rs +++ b/crates/stateless/src/validation.rs @@ -2,6 +2,7 @@ use crate::{witness_db::WitnessDatabase, ExecutionWitness}; use alloc::{ boxed::Box, collections::BTreeMap, + fmt::Debug, string::{String, ToString}, sync::Arc, vec::Vec, @@ -9,13 +10,12 @@ use alloc::{ use alloy_consensus::{BlockHeader, Header}; use alloy_primitives::{keccak256, map::B256Map, B256}; use alloy_rlp::Decodable; -use reth_chainspec::ChainSpec; +use reth_chainspec::{EthChainSpec, EthereumHardforks}; use reth_consensus::{Consensus, HeaderValidator}; use reth_errors::ConsensusError; use reth_ethereum_consensus::{validate_block_post_execution, EthBeaconConsensus}; -use reth_ethereum_primitives::Block; +use reth_ethereum_primitives::{Block, EthPrimitives}; use reth_evm::{execute::Executor, ConfigureEvm}; -use reth_evm_ethereum::execute::EthExecutorProvider; use reth_primitives_traits::{block::error::BlockRecoveryError, Block as _, RecoveredBlock}; use reth_revm::state::Bytecode; use reth_trie_common::{HashedPostState, KeccakKeyHasher}; @@ -110,7 +110,7 @@ pub enum StatelessValidationError { /// from `ancestor_headers`. Verifies the provided [`ExecutionWitness`] against this root using /// [`verify_execution_witness`]. /// -/// 3. **Chain Verification:** The code currently does not verify the [`ChainSpec`] and expects a +/// 3. **Chain Verification:** The code currently does not verify the [`EthChainSpec`] and expects a /// higher level function to assert that this is correct by, for example, asserting that it is /// equal to the Ethereum Mainnet `ChainSpec` or asserting against the genesis hash that this /// `ChainSpec` defines. @@ -126,11 +126,16 @@ pub enum StatelessValidationError { /// /// If all steps succeed the function returns `Some` containing the hash of the validated /// `current_block`. -pub fn stateless_validation( +pub fn stateless_validation( current_block: Block, witness: ExecutionWitness, chain_spec: Arc, -) -> Result { + evm_config: E, +) -> Result +where + ChainSpec: Send + Sync + EthChainSpec + EthereumHardforks + Debug, + E: ConfigureEvm + Clone + 'static, +{ let current_block = current_block .try_into_recovered() .map_err(|err| StatelessValidationError::SignerRecovery(Box::new(err)))?; @@ -172,8 +177,7 @@ pub fn stateless_validation( let db = WitnessDatabase::new(&sparse_trie, bytecode, ancestor_hashes); // Execute the block - let basic_block_executor = EthExecutorProvider::ethereum(chain_spec.clone()); - let executor = basic_block_executor.batch_executor(db); + let executor = evm_config.executor(db); let output = executor .execute(¤t_block) .map_err(|e| StatelessValidationError::StatelessExecutionFailed(e.to_string()))?; @@ -216,10 +220,13 @@ pub fn stateless_validation( /// /// This function acts as a preliminary validation before executing and validating the state /// transition function. -fn validate_block_consensus( +fn validate_block_consensus( chain_spec: Arc, block: &RecoveredBlock, -) -> Result<(), StatelessValidationError> { +) -> Result<(), StatelessValidationError> +where + ChainSpec: Send + Sync + EthChainSpec + EthereumHardforks + Debug, +{ let consensus = EthBeaconConsensus::new(chain_spec); consensus.validate_header(block.sealed_header())?; diff --git a/testing/ef-tests/src/cases/blockchain_test.rs b/testing/ef-tests/src/cases/blockchain_test.rs index 10032e5db8..0a79f3fbe2 100644 --- a/testing/ef-tests/src/cases/blockchain_test.rs +++ b/testing/ef-tests/src/cases/blockchain_test.rs @@ -12,7 +12,7 @@ use reth_db_common::init::{insert_genesis_hashes, insert_genesis_history, insert use reth_ethereum_consensus::{validate_block_post_execution, EthBeaconConsensus}; use reth_ethereum_primitives::Block; use reth_evm::{execute::Executor, ConfigureEvm}; -use reth_evm_ethereum::execute::EthExecutorProvider; +use reth_evm_ethereum::{execute::EthExecutorProvider, EthEvmConfig}; use reth_primitives_traits::{RecoveredBlock, SealedBlock}; use reth_provider::{ test_utils::create_test_provider_factory_with_chain_spec, BlockWriter, DatabaseProviderFactory, @@ -319,8 +319,13 @@ fn run_case(case: &BlockchainTest) -> Result<(), Error> { // Now validate using the stateless client if everything else passes for (block, execution_witness) in program_inputs { - stateless_validation(block.into_block(), execution_witness, chain_spec.clone()) - .expect("stateless validation failed"); + stateless_validation( + block.into_block(), + execution_witness, + chain_spec.clone(), + EthEvmConfig::new(chain_spec.clone()), + ) + .expect("stateless validation failed"); } Ok(())