chore: remove BatchExecutor (#14453)

This commit is contained in:
Arsenii Kulikov
2025-02-12 19:56:42 +04:00
committed by GitHub
parent 1970a4425b
commit 4f73e1a47e
8 changed files with 9 additions and 320 deletions

View File

@ -150,9 +150,6 @@ impl InsertBlockErrorKind {
BlockExecutionError::Validation(err) => {
Ok(InsertBlockValidationError::Validation(err))
}
BlockExecutionError::Consensus(err) => {
Ok(InsertBlockValidationError::Consensus(err))
}
// these are internal errors, not caused by an invalid block
BlockExecutionError::Internal(error) => {
Err(InsertBlockFatalError::BlockExecutionError(error))

View File

@ -12,7 +12,6 @@ workspace = true
[dependencies]
# reth
reth-consensus.workspace = true
reth-storage-errors.workspace = true
alloy-primitives.workspace = true
@ -25,7 +24,6 @@ thiserror.workspace = true
[features]
default = ["std"]
std = [
"reth-consensus/std",
"alloy-eips/std",
"alloy-primitives/std",
"alloy-rlp/std",

View File

@ -17,7 +17,6 @@ use alloc::{
};
use alloy_eips::BlockNumHash;
use alloy_primitives::B256;
use reth_consensus::ConsensusError;
use reth_storage_errors::provider::ProviderError;
use thiserror::Error;
@ -109,9 +108,6 @@ pub enum BlockExecutionError {
/// Validation error, transparently wrapping [`BlockValidationError`]
#[error(transparent)]
Validation(#[from] BlockValidationError),
/// Consensus error, transparently wrapping [`ConsensusError`]
#[error(transparent)]
Consensus(#[from] ConsensusError),
/// Internal, i.e. non consensus or validation related Block Executor Errors
#[error(transparent)]
Internal(#[from] InternalBlockExecutionError),

View File

@ -1,7 +1,7 @@
//! Helper type that represents one of two possible executor types
use crate::{
execute::{BatchExecutor, BlockExecutorProvider, Executor},
execute::{BlockExecutorProvider, Executor},
system_calls::OnStateHook,
Database,
};
@ -20,8 +20,6 @@ where
type Executor<DB: Database> = Either<A::Executor<DB>, B::Executor<DB>>;
type BatchExecutor<DB: Database> = Either<A::BatchExecutor<DB>, B::BatchExecutor<DB>>;
fn executor<DB>(&self, db: DB) -> Self::Executor<DB>
where
DB: Database,
@ -31,16 +29,6 @@ where
Self::Right(b) => Either::Right(b.executor(db)),
}
}
fn batch_executor<DB>(&self, db: DB) -> Self::BatchExecutor<DB>
where
DB: Database,
{
match self {
Self::Left(a) => Either::Left(a.batch_executor(db)),
Self::Right(b) => Either::Right(b.batch_executor(db)),
}
}
}
impl<A, B, DB> Executor<DB> for Either<A, B>
@ -116,35 +104,3 @@ where
}
}
}
impl<A, B, DB> BatchExecutor<DB> for Either<A, B>
where
A: BatchExecutor<DB>,
B: for<'a> BatchExecutor<DB, Input<'a> = A::Input<'a>, Output = A::Output, Error = A::Error>,
DB: Database,
{
type Input<'a> = A::Input<'a>;
type Output = A::Output;
type Error = A::Error;
fn execute_and_verify_one(&mut self, input: Self::Input<'_>) -> Result<(), Self::Error> {
match self {
Self::Left(a) => a.execute_and_verify_one(input),
Self::Right(b) => b.execute_and_verify_one(input),
}
}
fn finalize(self) -> Self::Output {
match self {
Self::Left(a) => a.finalize(),
Self::Right(b) => b.finalize(),
}
}
fn size_hint(&self) -> Option<usize> {
match self {
Self::Left(a) => a.size_hint(),
Self::Right(b) => b.size_hint(),
}
}
}

View File

@ -9,7 +9,7 @@ use reth_execution_types::BlockExecutionResult;
pub use reth_execution_types::{BlockExecutionOutput, ExecutionOutcome};
pub use reth_storage_errors::provider::ProviderError;
use crate::{batch::BlockBatchRecord, system_calls::OnStateHook, Database};
use crate::{system_calls::OnStateHook, Database};
use alloc::{boxed::Box, vec::Vec};
use alloy_eips::eip7685::Requests;
use alloy_primitives::{
@ -21,10 +21,8 @@ use reth_primitives::{NodePrimitives, Receipt, RecoveredBlock};
use revm::db::{states::bundle_state::BundleRetention, State};
use revm_primitives::{Account, AccountStatus, EvmState};
/// A general purpose executor trait that executes an input (e.g. block) and produces an output
/// (e.g. state changes and receipts).
///
/// This executor does not validate the output, see [`BatchExecutor`] for that.
/// A type that knows how to execute a block. It is assumed to operate on a
/// [`crate::Evm`] internally and use [`State`] as database.
pub trait Executor<DB: Database>: Sized {
/// The primitive types used by the executor.
type Primitives: NodePrimitives;
@ -50,8 +48,7 @@ pub trait Executor<DB: Database>: Sized {
/// Consumes the type and executes the block.
///
/// # Note
/// Execution happens without any validation of the output. To validate the output, use the
/// [`BatchExecutor`].
/// Execution happens without any validation of the output.
///
/// # Returns
/// The output of the block execution.
@ -130,56 +127,6 @@ pub trait Executor<DB: Database>: Sized {
fn size_hint(&self) -> usize;
}
/// A general purpose executor that can execute multiple inputs in sequence, validate the outputs,
/// and keep track of the state over the entire batch.
pub trait BatchExecutor<DB> {
/// The input type for the executor.
type Input<'a>;
/// The output type for the executor.
type Output;
/// The error type returned by the executor.
type Error;
/// Executes the next block in the batch, verifies the output and updates the state internally.
fn execute_and_verify_one(&mut self, input: Self::Input<'_>) -> Result<(), Self::Error>;
/// Executes multiple inputs in the batch, verifies the output, and updates the state
/// internally.
///
/// This method is a convenience function for calling [`BatchExecutor::execute_and_verify_one`]
/// for each input.
fn execute_and_verify_many<'a, I>(&mut self, inputs: I) -> Result<(), Self::Error>
where
I: IntoIterator<Item = Self::Input<'a>>,
{
for input in inputs {
self.execute_and_verify_one(input)?;
}
Ok(())
}
/// Executes the entire batch, verifies the output, and returns the final state.
///
/// This method is a convenience function for calling [`BatchExecutor::execute_and_verify_many`]
/// and [`BatchExecutor::finalize`].
fn execute_and_verify_batch<'a, I>(mut self, batch: I) -> Result<Self::Output, Self::Error>
where
I: IntoIterator<Item = Self::Input<'a>>,
Self: Sized,
{
self.execute_and_verify_many(batch)?;
Ok(self.finalize())
}
/// Finishes the batch and return the final state.
fn finalize(self) -> Self::Output;
/// The size hint of the batch's tracked state size.
///
/// This is used to optimize DB commits depending on the size of the state.
fn size_hint(&self) -> Option<usize>;
}
/// A type that can create a new executor for block execution.
pub trait BlockExecutorProvider: Send + Sync + Clone + Unpin + 'static {
/// Receipt type.
@ -202,28 +149,12 @@ pub trait BlockExecutorProvider: Send + Sync + Clone + Unpin + 'static {
Error = BlockExecutionError,
>;
/// An executor that can execute a batch of blocks given a database.
type BatchExecutor<DB: Database>: for<'a> BatchExecutor<
DB,
Input<'a> = &'a RecoveredBlock<<Self::Primitives as NodePrimitives>::Block>,
Output = ExecutionOutcome<<Self::Primitives as NodePrimitives>::Receipt>,
Error = BlockExecutionError,
>;
/// Creates a new executor for single block execution.
///
/// This is used to execute a single block and get the changed state.
fn executor<DB>(&self, db: DB) -> Self::Executor<DB>
where
DB: Database;
/// Creates a new batch executor with the given database and pruning modes.
///
/// Batch executor is used to execute multiple blocks in sequence and keep track of the state
/// during historical sync which involves executing multiple blocks in sequence.
fn batch_executor<DB>(&self, db: DB) -> Self::BatchExecutor<DB>
where
DB: Database;
}
/// Helper type for the output of executing a block.
@ -336,8 +267,6 @@ where
type Executor<DB: Database> = BasicBlockExecutor<F::Strategy<DB>>;
type BatchExecutor<DB: Database> = BasicBatchExecutor<F::Strategy<DB>>;
fn executor<DB>(&self, db: DB) -> Self::Executor<DB>
where
DB: Database,
@ -345,15 +274,6 @@ where
let strategy = self.strategy_factory.create_strategy(db);
BasicBlockExecutor::new(strategy)
}
fn batch_executor<DB>(&self, db: DB) -> Self::BatchExecutor<DB>
where
DB: Database,
{
let strategy = self.strategy_factory.create_strategy(db);
let batch_record = BlockBatchRecord::default();
BasicBatchExecutor::new(strategy, batch_record)
}
}
/// A generic block executor that uses a [`BlockExecutionStrategy`] to
@ -416,77 +336,6 @@ where
}
}
/// A generic batch executor that uses a [`BlockExecutionStrategy`] to
/// execute batches.
#[allow(missing_debug_implementations)]
pub struct BasicBatchExecutor<S>
where
S: BlockExecutionStrategy,
{
/// Batch execution strategy.
pub(crate) strategy: S,
/// Keeps track of batch execution receipts and requests.
pub(crate) batch_record: BlockBatchRecord<<S::Primitives as NodePrimitives>::Receipt>,
}
impl<S> BasicBatchExecutor<S>
where
S: BlockExecutionStrategy,
{
/// Creates a new `BasicBatchExecutor` with the given strategy.
pub const fn new(
strategy: S,
batch_record: BlockBatchRecord<<S::Primitives as NodePrimitives>::Receipt>,
) -> Self {
Self { strategy, batch_record }
}
}
impl<S, DB> BatchExecutor<DB> for BasicBatchExecutor<S>
where
S: BlockExecutionStrategy<DB = DB, Error = BlockExecutionError>,
DB: Database,
{
type Input<'a> = &'a RecoveredBlock<<S::Primitives as NodePrimitives>::Block>;
type Output = ExecutionOutcome<<S::Primitives as NodePrimitives>::Receipt>;
type Error = BlockExecutionError;
fn execute_and_verify_one(&mut self, block: Self::Input<'_>) -> Result<(), Self::Error> {
if self.batch_record.first_block().is_none() {
self.batch_record.set_first_block(block.header().number());
}
self.strategy.apply_pre_execution_changes(block)?;
let ExecuteOutput { receipts, .. } = self.strategy.execute_transactions(block)?;
let requests = self.strategy.apply_post_execution_changes(block, &receipts)?;
self.strategy.validate_block_post_execution(block, &receipts, &requests)?;
self.strategy.state_mut().merge_transitions(BundleRetention::Reverts);
// store receipts in the set
self.batch_record.save_receipts(receipts);
// store requests in the set
self.batch_record.save_requests(requests);
Ok(())
}
fn finalize(mut self) -> Self::Output {
ExecutionOutcome::new(
self.strategy.state_mut().take_bundle(),
self.batch_record.take_receipts(),
self.batch_record.first_block().unwrap_or_default(),
self.batch_record.take_requests(),
)
}
fn size_hint(&self) -> Option<usize> {
Some(self.strategy.state_ref().bundle_state.size_hint())
}
}
/// Creates an `EvmState` from a map of balance increments and the current state
/// to load accounts from. No balance increment is done in the function.
/// Zero balance increments are ignored and won't create state entries.
@ -540,7 +389,6 @@ mod tests {
impl BlockExecutorProvider for TestExecutorProvider {
type Primitives = EthPrimitives;
type Executor<DB: Database> = TestExecutor<DB>;
type BatchExecutor<DB: Database> = TestExecutor<DB>;
fn executor<DB>(&self, _db: DB) -> Self::Executor<DB>
where
@ -548,13 +396,6 @@ mod tests {
{
TestExecutor(PhantomData)
}
fn batch_executor<DB>(&self, _db: DB) -> Self::BatchExecutor<DB>
where
DB: Database,
{
TestExecutor(PhantomData)
}
}
struct TestExecutor<DB>(PhantomData<DB>);
@ -591,24 +432,6 @@ mod tests {
}
}
impl<DB> BatchExecutor<DB> for TestExecutor<DB> {
type Input<'a> = &'a RecoveredBlock<reth_primitives::Block>;
type Output = ExecutionOutcome;
type Error = BlockExecutionError;
fn execute_and_verify_one(&mut self, _input: Self::Input<'_>) -> Result<(), Self::Error> {
Ok(())
}
fn finalize(self) -> Self::Output {
todo!()
}
fn size_hint(&self) -> Option<usize> {
None
}
}
struct TestExecutorStrategy<DB, EvmConfig> {
// chain spec and evm config here only to illustrate how the strategy
// factory can use them in a real use case.

View File

@ -1,11 +1,11 @@
//! A no operation block executor implementation.
use reth_execution_errors::BlockExecutionError;
use reth_execution_types::{BlockExecutionResult, ExecutionOutcome};
use reth_execution_types::BlockExecutionResult;
use reth_primitives::{NodePrimitives, RecoveredBlock};
use crate::{
execute::{BatchExecutor, BlockExecutorProvider, Executor},
execute::{BlockExecutorProvider, Executor},
system_calls::OnStateHook,
Database,
};
@ -22,21 +22,12 @@ impl<P: NodePrimitives> BlockExecutorProvider for NoopBlockExecutorProvider<P> {
type Executor<DB: Database> = Self;
type BatchExecutor<DB: Database> = Self;
fn executor<DB>(&self, _: DB) -> Self::Executor<DB>
where
DB: Database,
{
Self::default()
}
fn batch_executor<DB>(&self, _: DB) -> Self::BatchExecutor<DB>
where
DB: Database,
{
Self::default()
}
}
impl<DB: Database, P: NodePrimitives> Executor<DB> for NoopBlockExecutorProvider<P> {
@ -70,21 +61,3 @@ impl<DB: Database, P: NodePrimitives> Executor<DB> for NoopBlockExecutorProvider
0
}
}
impl<DB, P: NodePrimitives> BatchExecutor<DB> for NoopBlockExecutorProvider<P> {
type Input<'a> = &'a RecoveredBlock<P::Block>;
type Output = ExecutionOutcome<P::Receipt>;
type Error = BlockExecutionError;
fn execute_and_verify_one(&mut self, _: Self::Input<'_>) -> Result<(), Self::Error> {
Err(BlockExecutionError::msg(UNAVAILABLE_FOR_NOOP))
}
fn finalize(self) -> Self::Output {
unreachable!()
}
fn size_hint(&self) -> Option<usize> {
None
}
}

View File

@ -2,8 +2,8 @@
use crate::{
execute::{
BasicBatchExecutor, BasicBlockExecutor, BatchExecutor, BlockExecutionOutput,
BlockExecutionStrategy, BlockExecutorProvider, Executor,
BasicBlockExecutor, BlockExecutionOutput, BlockExecutionStrategy, BlockExecutorProvider,
Executor,
},
system_calls::OnStateHook,
Database,
@ -34,21 +34,12 @@ impl BlockExecutorProvider for MockExecutorProvider {
type Executor<DB: Database> = Self;
type BatchExecutor<DB: Database> = Self;
fn executor<DB>(&self, _: DB) -> Self::Executor<DB>
where
DB: Database,
{
self.clone()
}
fn batch_executor<DB>(&self, _: DB) -> Self::BatchExecutor<DB>
where
DB: Database,
{
self.clone()
}
}
impl<DB: Database> Executor<DB> for MockExecutorProvider {
@ -132,24 +123,6 @@ impl<DB: Database> Executor<DB> for MockExecutorProvider {
}
}
impl<DB> BatchExecutor<DB> for MockExecutorProvider {
type Input<'a> = &'a RecoveredBlock<reth_primitives::Block>;
type Output = ExecutionOutcome;
type Error = BlockExecutionError;
fn execute_and_verify_one(&mut self, _: Self::Input<'_>) -> Result<(), Self::Error> {
Ok(())
}
fn finalize(self) -> Self::Output {
self.exec_results.lock().pop().unwrap()
}
fn size_hint(&self) -> Option<usize> {
None
}
}
impl<S> BasicBlockExecutor<S>
where
S: BlockExecutionStrategy,
@ -170,29 +143,3 @@ where
f(self.strategy.state_mut())
}
}
impl<S> BasicBatchExecutor<S>
where
S: BlockExecutionStrategy,
{
/// Provides safe read access to the state
pub fn with_state<F, R>(&self, f: F) -> R
where
F: FnOnce(&State<S::DB>) -> R,
{
f(self.strategy.state_ref())
}
/// Provides safe write access to the state
pub fn with_state_mut<F, R>(&mut self, f: F) -> R
where
F: FnOnce(&mut State<S::DB>) -> R,
{
f(self.strategy.state_mut())
}
/// Accessor for batch executor receipts.
pub const fn receipts(&self) -> &Vec<Vec<<S::Primitives as NodePrimitives>::Receipt>> {
self.batch_record.receipts()
}
}