feat: Genericise stateless_validation API so that it is not fixed to Eth types (#16328)

Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
kevaundray
2025-05-21 16:36:31 +01:00
committed by GitHub
parent 73fd146267
commit 3bf1110403
4 changed files with 25 additions and 15 deletions

1
Cargo.lock generated
View File

@@ -10036,7 +10036,6 @@ dependencies = [
"reth-ethereum-consensus",
"reth-ethereum-primitives",
"reth-evm",
"reth-evm-ethereum",
"reth-primitives-traits",
"reth-revm",
"reth-trie-common",

View File

@@ -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

View File

@@ -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<ChainSpec, E>(
current_block: Block,
witness: ExecutionWitness,
chain_spec: Arc<ChainSpec>,
) -> Result<B256, StatelessValidationError> {
evm_config: E,
) -> Result<B256, StatelessValidationError>
where
ChainSpec: Send + Sync + EthChainSpec + EthereumHardforks + Debug,
E: ConfigureEvm<Primitives = EthPrimitives> + 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(&current_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<ChainSpec>(
chain_spec: Arc<ChainSpec>,
block: &RecoveredBlock<Block>,
) -> Result<(), StatelessValidationError> {
) -> Result<(), StatelessValidationError>
where
ChainSpec: Send + Sync + EthChainSpec + EthereumHardforks + Debug,
{
let consensus = EthBeaconConsensus::new(chain_spec);
consensus.validate_header(block.sealed_header())?;

View File

@@ -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(())