mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
chore: remove BatchExecutor (#14453)
This commit is contained in:
@ -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",
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user