From e4e01f8f838ce76eb2f98800883c7383dae3c653 Mon Sep 17 00:00:00 2001 From: Federico Gimenez Date: Tue, 18 Feb 2025 17:51:58 +0100 Subject: [PATCH] test(engine): enable state root task in engine unit tests --- crates/engine/local/src/service.rs | 7 +- crates/engine/service/src/service.rs | 7 +- crates/engine/tree/src/tree/config.rs | 17 ++ crates/engine/tree/src/tree/mod.rs | 188 ++++++++++++------ crates/engine/tree/src/tree/root.rs | 104 ++++++++++ .../storage/provider/src/test_utils/mock.rs | 58 ++++-- 6 files changed, 308 insertions(+), 73 deletions(-) diff --git a/crates/engine/local/src/service.rs b/crates/engine/local/src/service.rs index dd6a644acb8b..5c55812b1dff 100644 --- a/crates/engine/local/src/service.rs +++ b/crates/engine/local/src/service.rs @@ -27,7 +27,7 @@ use reth_engine_tree::{ RequestHandlerEvent, }, persistence::PersistenceHandle, - tree::{EngineApiTreeHandler, InvalidBlockHook, TreeConfig}, + tree::{root::BasicStateRootTaskFactory, EngineApiTreeHandler, InvalidBlockHook, TreeConfig}, }; use reth_evm::{execute::BlockExecutorProvider, ConfigureEvm}; use reth_node_types::{BlockTy, HeaderTy, TxTy}; @@ -95,8 +95,10 @@ where PersistenceHandle::::spawn_service(provider, pruner, sync_metrics_tx); let canonical_in_memory_state = blockchain_db.canonical_in_memory_state(); + let state_root_task_factory = BasicStateRootTaskFactory::new(); + let (to_tree_tx, from_tree) = - EngineApiTreeHandler::::spawn_new( + EngineApiTreeHandler::::spawn_new( blockchain_db.clone(), executor_factory, consensus, @@ -108,6 +110,7 @@ where invalid_block_hook, engine_kind, evm_config, + state_root_task_factory, ); let handler = EngineApiRequestHandler::new(to_tree_tx, from_tree); diff --git a/crates/engine/service/src/service.rs b/crates/engine/service/src/service.rs index f6b791e744c0..917e1f50332d 100644 --- a/crates/engine/service/src/service.rs +++ b/crates/engine/service/src/service.rs @@ -8,7 +8,7 @@ use reth_engine_tree::{ download::BasicBlockDownloader, engine::{EngineApiKind, EngineApiRequest, EngineApiRequestHandler, EngineHandler}, persistence::PersistenceHandle, - tree::{EngineApiTreeHandler, InvalidBlockHook, TreeConfig}, + tree::{root::BasicStateRootTaskFactory, EngineApiTreeHandler, InvalidBlockHook, TreeConfig}, }; pub use reth_engine_tree::{ chain::{ChainEvent, ChainOrchestrator}, @@ -105,8 +105,10 @@ where let canonical_in_memory_state = blockchain_db.canonical_in_memory_state(); + let state_root_task_factory = BasicStateRootTaskFactory::new(); + let (to_tree_tx, from_tree) = - EngineApiTreeHandler::::spawn_new( + EngineApiTreeHandler::::spawn_new( blockchain_db, executor_factory, consensus, @@ -118,6 +120,7 @@ where invalid_block_hook, engine_kind, evm_config, + state_root_task_factory, ); let engine_handler = EngineApiRequestHandler::new(to_tree_tx, from_tree); diff --git a/crates/engine/tree/src/tree/config.rs b/crates/engine/tree/src/tree/config.rs index f7b4667966eb..e0d2620c1ce9 100644 --- a/crates/engine/tree/src/tree/config.rs +++ b/crates/engine/tree/src/tree/config.rs @@ -1,5 +1,6 @@ //! Engine tree configuration. +use crate::tree::root::has_enough_parallelism; use alloy_eips::merge::EPOCH_SLOTS; /// The largest gap for which the tree will be used for sync. See docs for `pipeline_run_threshold` @@ -53,6 +54,8 @@ pub struct TreeConfig { use_caching_and_prewarming: bool, /// Cross-block cache size in bytes. cross_block_cache_size: u64, + /// Wether the host has enough parallelism to run state root task. + has_enough_parallelism: bool, } impl Default for TreeConfig { @@ -67,6 +70,7 @@ impl Default for TreeConfig { always_compare_trie_updates: false, use_caching_and_prewarming: false, cross_block_cache_size: DEFAULT_CROSS_BLOCK_CACHE_SIZE, + has_enough_parallelism: has_enough_parallelism(), } } } @@ -84,6 +88,7 @@ impl TreeConfig { always_compare_trie_updates: bool, use_caching_and_prewarming: bool, cross_block_cache_size: u64, + has_enough_parallelism: bool, ) -> Self { Self { persistence_threshold, @@ -95,6 +100,7 @@ impl TreeConfig { always_compare_trie_updates, use_caching_and_prewarming, cross_block_cache_size, + has_enough_parallelism, } } @@ -211,4 +217,15 @@ impl TreeConfig { self.cross_block_cache_size = cross_block_cache_size; self } + + /// Setter for has enough parallelism. + pub const fn with_has_enough_parallelism(mut self, has_enough_parallelism: bool) -> Self { + self.has_enough_parallelism = has_enough_parallelism; + self + } + + /// Wether or not to use state root task + pub(crate) fn use_state_root_task(&self) -> bool { + self.has_enough_parallelism && !self.legacy_state_root + } } diff --git a/crates/engine/tree/src/tree/mod.rs b/crates/engine/tree/src/tree/mod.rs index f78f3cd2efd6..3a694dc0cc5c 100644 --- a/crates/engine/tree/src/tree/mod.rs +++ b/crates/engine/tree/src/tree/mod.rs @@ -3,10 +3,6 @@ use crate::{ chain::FromOrchestrator, engine::{DownloadRequest, EngineApiEvent, EngineApiKind, EngineApiRequest, FromEngine}, persistence::PersistenceHandle, - tree::{ - cached_state::{CachedStateMetrics, CachedStateProvider, ProviderCacheBuilder}, - metrics::EngineApiMetrics, - }, }; use alloy_consensus::{transaction::Recovered, BlockHeader}; use alloy_eips::BlockNumHash; @@ -18,9 +14,11 @@ use alloy_primitives::{ use alloy_rpc_types_engine::{ ForkchoiceState, PayloadStatus, PayloadStatusEnum, PayloadValidationError, }; -use cached_state::{ProviderCaches, SavedCache}; +use cached_state::{ + CachedStateMetrics, CachedStateProvider, ProviderCacheBuilder, ProviderCaches, SavedCache, +}; use error::{InsertBlockError, InsertBlockErrorKind, InsertBlockFatalError}; -use metrics::PrewarmThreadMetrics; +use metrics::{EngineApiMetrics, PrewarmThreadMetrics}; use persistence_state::CurrentPersistenceAction; use reth_chain_state::{ CanonicalInMemoryState, ExecutedBlock, ExecutedBlockWithTrieUpdates, @@ -59,7 +57,8 @@ use reth_trie::{ use reth_trie_db::DatabaseTrieCursorFactory; use reth_trie_parallel::root::{ParallelStateRoot, ParallelStateRootError}; use root::{ - StateRootComputeOutcome, StateRootConfig, StateRootHandle, StateRootMessage, StateRootTask, + StateRootComputeHandle, StateRootComputeOutcome, StateRootConfig, StateRootMessage, + StateRootTaskFactory, StateRootTaskRunner, }; use std::{ cmp::Ordering, @@ -556,10 +555,11 @@ pub enum TreeAction { /// /// This type is responsible for processing engine API requests, maintaining the canonical state and /// emitting events. -pub struct EngineApiTreeHandler +pub struct EngineApiTreeHandler where N: NodePrimitives, T: EngineTypes, + F: StateRootTaskFactory

, { provider: P, executor_provider: E, @@ -603,14 +603,15 @@ where engine_kind: EngineApiKind, /// The most recent cache used for execution. most_recent_cache: Option, - /// Thread pool used for the state root task and prewarming - thread_pool: Arc, + /// Factory for state root tasks. + state_root_task_factory: F, } -impl std::fmt::Debug - for EngineApiTreeHandler +impl std::fmt::Debug + for EngineApiTreeHandler where N: NodePrimitives, + F: StateRootTaskFactory

, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("EngineApiTreeHandler") @@ -634,7 +635,7 @@ where } } -impl EngineApiTreeHandler +impl EngineApiTreeHandler where N: NodePrimitives, P: DatabaseProviderFactory @@ -651,6 +652,7 @@ where C: ConfigureEvm

, T: EngineTypes, V: EngineValidator, + F: StateRootTaskFactory

, { /// Creates a new [`EngineApiTreeHandler`]. #[expect(clippy::too_many_arguments)] @@ -668,19 +670,10 @@ where config: TreeConfig, engine_kind: EngineApiKind, evm_config: C, + state_root_task_factory: F, ) -> Self { let (incoming_tx, incoming) = std::sync::mpsc::channel(); - let num_threads = root::rayon_thread_pool_size(); - - let thread_pool = Arc::new( - rayon::ThreadPoolBuilder::new() - .num_threads(num_threads) - .thread_name(|i| format!("srt-worker-{}", i)) - .build() - .expect("Failed to create proof worker thread pool"), - ); - Self { provider, executor_provider, @@ -701,7 +694,7 @@ where invalid_block_hook: Box::new(NoopInvalidBlockHook), engine_kind, most_recent_cache: None, - thread_pool, + state_root_task_factory, } } @@ -728,6 +721,7 @@ where invalid_block_hook: Box>, kind: EngineApiKind, evm_config: C, + state_root_task_factory: F, ) -> (Sender, N::Block>>, UnboundedReceiver>) { let best_block_number = provider.best_block_number().unwrap_or(0); @@ -760,6 +754,7 @@ where config, kind, evm_config, + state_root_task_factory, ); task.set_invalid_block_hook(invalid_block_hook); let incoming = task.incoming_tx.clone(); @@ -2431,11 +2426,8 @@ where // Atomic bool for letting the prewarm tasks know when to stop let cancel_execution = ManualCancel::default(); - let use_legacy_state_root = - self.config.legacy_state_root() || !root::has_enough_parallelism(); - let (state_root_handle, state_root_task_config, state_root_sender, state_hook) = - if is_descendant_of_persisting_blocks && !use_legacy_state_root { + if is_descendant_of_persisting_blocks && self.config.use_state_root_task() { let consistent_view = ConsistentDbView::new_with_latest_tip(self.provider.clone())?; // Compute trie input @@ -2462,9 +2454,9 @@ where .set(config_elapsed.as_secs_f64()); let state_root_task = - StateRootTask::new(state_root_config.clone(), self.thread_pool.clone()); + self.state_root_task_factory.create_task(state_root_config.clone()); let state_root_sender = state_root_task.state_root_message_sender(); - let state_hook = Box::new(state_root_task.state_hook()) as Box; + let state_hook = state_root_task.state_hook() as Box; ( Some(state_root_task.spawn()), Some(state_root_config), @@ -2560,7 +2552,21 @@ where // a different database transaction per thread and it might end up with a // different view of the database. let (state_root, trie_output, root_elapsed) = if is_descendant_of_persisting_blocks { - if use_legacy_state_root { + if self.config.use_state_root_task() { + let state_root_handle = state_root_handle + .expect("state root handle must exist if legacy_state_root is false"); + let state_root_config = state_root_task_config.expect("task config is present"); + + // Handle state root result from task using handle + self.handle_state_root_result( + state_root_handle, + state_root_config, + block.sealed_block(), + &hashed_state, + &state_provider, + root_time, + )? + } else { match self.compute_state_root_parallel(block.header().parent_hash(), &hashed_state) { Ok(result) => { @@ -2580,20 +2586,6 @@ where } Err(error) => return Err(InsertBlockErrorKind::Other(Box::new(error))), } - } else { - let state_root_handle = state_root_handle - .expect("state root handle must exist if legacy_state_root is false"); - let state_root_config = state_root_task_config.expect("task config is present"); - - // Handle state root result from task using handle - self.handle_state_root_result( - state_root_handle, - state_root_config, - block.sealed_block(), - &hashed_state, - &state_provider, - root_time, - )? } } else { debug!(target: "engine::tree", block=?block_num_hash, ?is_descendant_of_persisting_blocks, "Failed to compute state root in parallel"); @@ -2744,7 +2736,7 @@ where let evm_config = self.evm_config.clone(); // spawn task executing the individual tx - self.thread_pool.spawn(move || { + self.state_root_task_factory.thread_pool().spawn(move || { let thread_start = Instant::now(); let in_progress = task_finished.read().unwrap(); @@ -2894,11 +2886,11 @@ where )) } - /// Waits for the result on the input [`StateRootHandle`], and handles it, falling back to + /// Waits for the result on the input state root handle, and handles it, falling back to /// the hash builder-based state root calculation if it fails. fn handle_state_root_result( &self, - state_root_handle: StateRootHandle, + state_root_handle: ::ResultHandle, state_root_task_config: StateRootConfig

, sealed_block: &SealedBlock, hashed_state: &HashedPostState, @@ -3235,7 +3227,10 @@ pub enum InsertPayloadOk { #[cfg(test)] mod tests { - use super::*; + use super::{ + root::{StateRootComputeHandle, StateRootTaskRunner}, + *, + }; use crate::persistence::PersistenceAction; use alloy_consensus::Header; use alloy_primitives::Bytes; @@ -3251,11 +3246,12 @@ mod tests { use reth_ethereum_consensus::EthBeaconConsensus; use reth_ethereum_engine_primitives::{EthEngineTypes, EthereumEngineValidator}; use reth_ethereum_primitives::{Block, EthPrimitives}; - use reth_evm::test_utils::MockExecutorProvider; + use reth_evm::{system_calls::StateChangeSource, test_utils::MockExecutorProvider}; use reth_evm_ethereum::EthEvmConfig; use reth_primitives_traits::Block as _; use reth_provider::test_utils::MockEthProvider; use reth_trie::{updates::TrieUpdates, HashedPostState}; + use revm_state::EvmState; use std::{ str::FromStr, sync::mpsc::{channel, Sender}, @@ -3316,6 +3312,78 @@ mod tests { } } + struct MockStateRootHandle { + root: B256, + } + + impl StateRootComputeHandle for MockStateRootHandle { + fn wait_for_result(self) -> Result { + Ok(StateRootComputeOutcome { + state_root: (self.root, TrieUpdates::default()), + total_time: Duration::from_secs(0), + time_from_last_update: Duration::from_secs(0), + }) + } + } + + struct MockStateRootTask { + root: B256, + } + + impl MockStateRootTask { + fn new(root: B256) -> Self { + Self { root } + } + } + + impl StateRootTaskRunner for MockStateRootTask { + type ResultHandle = MockStateRootHandle; + + fn spawn(self) -> Self::ResultHandle { + MockStateRootHandle { root: self.root } + } + + fn state_hook(&self) -> Box { + Box::new(move |_: StateChangeSource, _: &EvmState| {}) + } + + fn state_root_message_sender(&self) -> Sender { + let (tx, _rx) = channel(); + tx + } + } + + struct MockStateRootTaskFactory { + roots: Vec, + thread_pool: Arc, + } + + impl MockStateRootTaskFactory { + fn new() -> Self { + let num_threads = root::rayon_thread_pool_size(); + let thread_pool = + Arc::new(rayon::ThreadPoolBuilder::new().num_threads(num_threads).build().unwrap()); + + Self { roots: Vec::new(), thread_pool } + } + + fn add_state_root(&mut self, root: B256) { + self.roots.push(root); + } + } + + impl StateRootTaskFactory for MockStateRootTaskFactory { + type Runner = MockStateRootTask; + + fn create_task(&mut self, _config: StateRootConfig) -> Self::Runner { + MockStateRootTask::new(self.roots.pop().unwrap()) + } + + fn thread_pool(&self) -> Arc { + self.thread_pool.clone() + } + } + struct TestHarness { tree: EngineApiTreeHandler< EthPrimitives, @@ -3324,6 +3392,7 @@ mod tests { EthEngineTypes, EthereumEngineValidator, EthEvmConfig, + MockStateRootTaskFactory, >, to_tree_tx: Sender, Block>>, from_tree_rx: UnboundedReceiver, @@ -3356,6 +3425,11 @@ mod tests { let consensus = Arc::new(EthBeaconConsensus::new(chain_spec.clone())); let provider = MockEthProvider::default(); + let mut block_builder = + TestBlockBuilder::default().with_chain_spec((*chain_spec).clone()); + let genesis_block = block_builder.get_executed_block_with_number(0, B256::random()); + provider.add_block(B256::default(), genesis_block.into_sealed_block().clone_block()); + let executor_provider = MockExecutorProvider::default(); let payload_validator = EthereumEngineValidator::new(chain_spec.clone()); @@ -3370,7 +3444,9 @@ mod tests { let (to_payload_service, _payload_command_rx) = unbounded_channel(); let payload_builder = PayloadBuilderHandle::new(to_payload_service); - let evm_config = EthEvmConfig::new(chain_spec.clone()); + let evm_config = EthEvmConfig::new(chain_spec); + + let state_root_task_factory = MockStateRootTaskFactory::new(); let tree = EngineApiTreeHandler::new( provider.clone(), @@ -3383,13 +3459,13 @@ mod tests { persistence_handle, PersistenceState::default(), payload_builder, - // TODO: fix tests for state root task https://github.com/paradigmxyz/reth/issues/14376 - TreeConfig::default().with_legacy_state_root(true), + // always assume enough parallelism for tests + TreeConfig::default().with_has_enough_parallelism(true), EngineApiKind::Ethereum, evm_config, + state_root_task_factory, ); - let block_builder = TestBlockBuilder::default().with_chain_spec((*chain_spec).clone()); Self { to_tree_tx: tree.incoming_tx.clone(), tree, @@ -3463,7 +3539,7 @@ mod tests { ) -> Result> { let execution_outcome = self.block_builder.get_execution_outcome(block.clone()); self.extend_execution_outcome([execution_outcome]); - self.tree.provider.add_state_root(block.state_root); + self.tree.state_root_task_factory.add_state_root(block.state_root); self.tree.insert_block(block) } @@ -3666,7 +3742,7 @@ mod tests { } else { block.state_root }; - self.tree.provider.add_state_root(state_root); + self.tree.state_root_task_factory.add_state_root(state_root); execution_outcomes.push(execution_outcome); } self.extend_execution_outcome(execution_outcomes); diff --git a/crates/engine/tree/src/tree/root.rs b/crates/engine/tree/src/tree/root.rs index 206992f558c0..cc715ccdf4f9 100644 --- a/crates/engine/tree/src/tree/root.rs +++ b/crates/engine/tree/src/tree/root.rs @@ -499,6 +499,110 @@ struct StateRootTaskMetrics { pub state_root_iterations_histogram: Histogram, } +/// Result provided by a state root calculation +pub trait StateRootComputeHandle: Send + 'static { + /// Waits for the state root calculation to complete and returns the result. + fn wait_for_result(self) -> Result; +} + +impl StateRootComputeHandle for StateRootHandle { + fn wait_for_result(self) -> Result { + self.wait_for_result() + } +} + +/// Public interface of the state root task. +pub trait StateRootTaskRunner: Send + 'static { + /// Type of state root result returned by this runner + type ResultHandle: StateRootComputeHandle; + + /// Spawns the state root task and returns a handle to await its result. + fn spawn(self) -> Self::ResultHandle; + + /// Returns a state hook that can be used to send state updates to this task. + fn state_hook(&self) -> Box; + + /// Returns a [`StateRootMessage`] sender. + fn state_root_message_sender(&self) -> Sender; +} + +impl StateRootTaskRunner for StateRootTask +where + Factory: + DatabaseProviderFactory + StateCommitmentProvider + Clone + 'static, +{ + type ResultHandle = StateRootHandle; + + fn spawn(self) -> StateRootHandle { + self.spawn() + } + + fn state_hook(&self) -> Box { + Box::new(self.state_hook()) + } + + fn state_root_message_sender(&self) -> Sender { + self.state_root_message_sender() + } +} + +/// Factory trait for creating state root task runners. +pub trait StateRootTaskFactory: Send + 'static { + /// The type of task runner this factory creates. + type Runner: StateRootTaskRunner; + + /// Creates a new state root task runner. + fn create_task(&mut self, config: StateRootConfig) -> Self::Runner; + + /// Creates a new state root task runner. + fn thread_pool(&self) -> Arc; +} + +/// Factory for creating real state root tasks. +#[derive(Debug)] +pub struct BasicStateRootTaskFactory { + /// Thread pool used for parallel proof generation. + thread_pool: Arc, +} + +impl BasicStateRootTaskFactory { + /// Creates a new factory. + pub fn new() -> Self { + let num_threads = rayon_thread_pool_size(); + let thread_pool = Arc::new( + rayon::ThreadPoolBuilder::new() + .num_threads(num_threads) + .thread_name(|i| format!("srt-worker-{}", i)) + .build() + .expect("Failed to create proof worker thread pool"), + ); + + Self { thread_pool } + } +} + +impl Default for BasicStateRootTaskFactory { + fn default() -> Self { + Self::new() + } +} + +impl StateRootTaskFactory for BasicStateRootTaskFactory +where + Provider: + DatabaseProviderFactory + StateCommitmentProvider + Clone + 'static, +{ + type Runner = StateRootTask; + + fn create_task(&mut self, config: StateRootConfig) -> Self::Runner { + StateRootTask::new(config, self.thread_pool.clone()) + } + + fn thread_pool(&self) -> Arc { + self.thread_pool.clone() + } +} + /// Standalone task that receives a transaction state stream and updates relevant /// data structures to calculate state root. /// diff --git a/crates/storage/provider/src/test_utils/mock.rs b/crates/storage/provider/src/test_utils/mock.rs index 873a60806b45..24049834523a 100644 --- a/crates/storage/provider/src/test_utils/mock.rs +++ b/crates/storage/provider/src/test_utils/mock.rs @@ -1,9 +1,9 @@ use crate::{ traits::{BlockSource, ReceiptProvider}, AccountReader, BlockHashReader, BlockIdReader, BlockNumReader, BlockReader, BlockReaderIdExt, - ChainSpecProvider, ChangeSetReader, DatabaseProvider, EthStorage, HeaderProvider, - ReceiptProviderIdExt, StateProvider, StateProviderBox, StateProviderFactory, StateReader, - StateRootProvider, TransactionVariant, TransactionsProvider, WithdrawalsProvider, + ChainSpecProvider, ChangeSetReader, EthStorage, HeaderProvider, ReceiptProviderIdExt, + StateProvider, StateProviderBox, StateProviderFactory, StateReader, StateRootProvider, + TransactionVariant, TransactionsProvider, WithdrawalsProvider, }; use alloy_consensus::{ constants::EMPTY_ROOT_HASH, transaction::TransactionMeta, Header, Transaction, @@ -23,16 +23,18 @@ use reth_db_api::{ use reth_execution_types::ExecutionOutcome; use reth_node_types::NodeTypes; use reth_primitives::{ - Account, Block, Bytecode, EthPrimitives, GotExpected, Receipt, RecoveredBlock, SealedBlock, - SealedHeader, TransactionSigned, + Account, Block, Bytecode, EthPrimitives, Receipt, RecoveredBlock, SealedBlock, SealedHeader, + TransactionSigned, }; use reth_primitives_traits::SignedTransaction; +use reth_prune_types::PruneModes; use reth_stages_types::{StageCheckpoint, StageId}; use reth_storage_api::{ - BlockBodyIndicesProvider, DatabaseProviderFactory, HashedPostStateProvider, OmmersProvider, - StageCheckpointReader, StateCommitmentProvider, StateProofProvider, StorageRootProvider, + BlockBodyIndicesProvider, DBProvider, DatabaseProviderFactory, HashedPostStateProvider, + OmmersProvider, StageCheckpointReader, StateCommitmentProvider, StateProofProvider, + StorageRootProvider, }; -use reth_storage_errors::provider::{ConsistentViewError, ProviderError, ProviderResult}; +use reth_storage_errors::provider::{ProviderError, ProviderResult}; use reth_trie::{ updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof, MultiProofTargets, StorageMultiProof, StorageProof, TrieInput, @@ -57,6 +59,8 @@ pub struct MockEthProvider, /// Local state roots pub state_roots: Arc>>, + tx: TxMock, + prune_modes: Arc, } impl Clone for MockEthProvider { @@ -67,6 +71,8 @@ impl Clone for MockEthProvider { accounts: self.accounts.clone(), chain_spec: self.chain_spec.clone(), state_roots: self.state_roots.clone(), + tx: self.tx.clone(), + prune_modes: self.prune_modes.clone(), } } } @@ -80,6 +86,8 @@ impl MockEthProvider { accounts: Default::default(), chain_spec: Arc::new(reth_chainspec::ChainSpecBuilder::mainnet().build()), state_roots: Default::default(), + tx: Default::default(), + prune_modes: Default::default(), } } } @@ -136,6 +144,8 @@ impl MockEthProvider { accounts: self.accounts, chain_spec: Arc::new(chain_spec), state_roots: self.state_roots, + tx: self.tx, + prune_modes: self.prune_modes, } } } @@ -200,19 +210,41 @@ impl StateCommitmentProvider type StateCommitment = ::StateCommitment; } -impl DatabaseProviderFactory +impl DatabaseProviderFactory for MockEthProvider { type DB = DatabaseMock; - type Provider = DatabaseProvider; - type ProviderRW = DatabaseProvider; + type Provider = Self; + type ProviderRW = Self; fn database_provider_ro(&self) -> ProviderResult { - Err(ConsistentViewError::Syncing { best_block: GotExpected::new(0, 0) }.into()) + Ok(self.clone()) } fn database_provider_rw(&self) -> ProviderResult { - Err(ConsistentViewError::Syncing { best_block: GotExpected::new(0, 0) }.into()) + Ok(self.clone()) + } +} + +impl DBProvider + for MockEthProvider +{ + type Tx = TxMock; + + fn tx_ref(&self) -> &Self::Tx { + &self.tx + } + + fn tx_mut(&mut self) -> &mut Self::Tx { + &mut self.tx + } + + fn into_tx(self) -> Self::Tx { + self.tx + } + + fn prune_modes_ref(&self) -> &PruneModes { + &self.prune_modes } }