//! Helpers for testing. use crate::{ execute::{ BasicBatchExecutor, BasicBlockExecutor, BatchExecutor, BlockExecutionOutput, BlockExecutionStrategy, BlockExecutorProvider, Executor, }, system_calls::OnStateHook, }; use alloy_eips::eip7685::Requests; use alloy_primitives::BlockNumber; use parking_lot::Mutex; use reth_execution_errors::BlockExecutionError; use reth_execution_types::ExecutionOutcome; use reth_primitives::{BlockWithSenders, EthPrimitives, NodePrimitives, Receipt, Receipts}; use reth_prune_types::PruneModes; use reth_storage_errors::provider::ProviderError; use revm::State; use revm_primitives::db::Database; use std::{fmt::Display, sync::Arc}; /// A [`BlockExecutorProvider`] that returns mocked execution results. #[derive(Clone, Debug, Default)] pub struct MockExecutorProvider { exec_results: Arc>>, } impl MockExecutorProvider { /// Extend the mocked execution results pub fn extend(&self, results: impl IntoIterator>) { self.exec_results.lock().extend(results.into_iter().map(Into::into)); } } impl BlockExecutorProvider for MockExecutorProvider { type Primitives = EthPrimitives; type Executor + Display>> = Self; type BatchExecutor + Display>> = Self; fn executor(&self, _: DB) -> Self::Executor where DB: Database + Display>, { self.clone() } fn batch_executor(&self, _: DB) -> Self::BatchExecutor where DB: Database + Display>, { self.clone() } } impl Executor for MockExecutorProvider { type Input<'a> = &'a BlockWithSenders; type Output = BlockExecutionOutput; type Error = BlockExecutionError; fn execute(self, _: Self::Input<'_>) -> Result { let ExecutionOutcome { bundle, receipts, requests, first_block: _ } = self.exec_results.lock().pop().unwrap(); Ok(BlockExecutionOutput { state: bundle, receipts: receipts.into_iter().flatten().flatten().collect(), requests: requests.into_iter().fold(Requests::default(), |mut reqs, req| { reqs.extend(req); reqs }), gas_used: 0, }) } fn execute_with_state_closure( self, input: Self::Input<'_>, _: F, ) -> Result where F: FnMut(&State), { >::execute(self, input) } fn execute_with_state_hook( self, input: Self::Input<'_>, _: F, ) -> Result where F: OnStateHook, { >::execute(self, input) } } impl BatchExecutor for MockExecutorProvider { type Input<'a> = &'a BlockWithSenders; 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 set_tip(&mut self, _: BlockNumber) {} fn set_prune_modes(&mut self, _: PruneModes) {} fn size_hint(&self) -> Option { None } } impl BasicBlockExecutor where S: BlockExecutionStrategy, { /// Provides safe read access to the state pub fn with_state(&self, f: F) -> R where F: FnOnce(&State) -> R, { f(self.strategy.state_ref()) } /// Provides safe write access to the state pub fn with_state_mut(&mut self, f: F) -> R where F: FnOnce(&mut State) -> R, { f(self.strategy.state_mut()) } } impl BasicBatchExecutor where S: BlockExecutionStrategy, { /// Provides safe read access to the state pub fn with_state(&self, f: F) -> R where F: FnOnce(&State) -> R, { f(self.strategy.state_ref()) } /// Provides safe write access to the state pub fn with_state_mut(&mut self, f: F) -> R where F: FnOnce(&mut State) -> R, { f(self.strategy.state_mut()) } /// Accessor for batch executor receipts. pub const fn receipts(&self) -> &Receipts<::Receipt> { self.batch_record.receipts() } }