Skip to main content

reth_storage_api/
noop.rs

1//! Various noop implementations for traits.
2
3use crate::{
4    AccountReader, BlockBodyIndicesProvider, BlockHashReader, BlockIdReader, BlockNumReader,
5    BlockReader, BlockReaderIdExt, BlockSource, BytecodeReader, ChangeSetReader,
6    HashedPostStateProvider, HeaderProvider, NodePrimitivesProvider, PruneCheckpointReader,
7    ReceiptProvider, ReceiptProviderIdExt, StageCheckpointReader, StateProofProvider,
8    StateProvider, StateProviderBox, StateProviderFactory, StateReader, StateRootProvider,
9    StorageRootProvider, TransactionVariant, TransactionsProvider,
10};
11
12#[cfg(feature = "db-api")]
13use crate::{DBProvider, DatabaseProviderFactory, StorageChangeSetReader, StorageSettingsCache};
14use alloc::{boxed::Box, string::String, sync::Arc, vec::Vec};
15use alloy_consensus::transaction::TransactionMeta;
16use alloy_eips::{BlockHashOrNumber, BlockId, BlockNumberOrTag};
17use alloy_primitives::{
18    Address, BlockHash, BlockNumber, Bytes, StorageKey, StorageValue, TxHash, TxNumber, B256,
19};
20use core::{
21    fmt::Debug,
22    marker::PhantomData,
23    ops::{RangeBounds, RangeInclusive},
24};
25use reth_chainspec::{ChainInfo, ChainSpecProvider, EthChainSpec, MAINNET};
26#[cfg(feature = "db-api")]
27use reth_db_api::mock::{DatabaseMock, TxMock};
28use reth_db_models::{AccountBeforeTx, StoredBlockBodyIndices};
29use reth_ethereum_primitives::EthPrimitives;
30use reth_execution_types::ExecutionOutcome;
31use reth_primitives_traits::{Account, Bytecode, NodePrimitives, RecoveredBlock, SealedHeader};
32#[cfg(feature = "db-api")]
33use reth_prune_types::PruneModes;
34use reth_prune_types::{PruneCheckpoint, PruneSegment};
35use reth_stages_types::{StageCheckpoint, StageId};
36use reth_storage_errors::provider::{ProviderError, ProviderResult};
37use reth_trie_common::{
38    updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof,
39    MultiProofTargets, StorageMultiProof, StorageProof, TrieInput,
40};
41
42/// Supports various api interfaces for testing purposes.
43#[derive(Debug)]
44#[non_exhaustive]
45pub struct NoopProvider<ChainSpec = reth_chainspec::ChainSpec, N = EthPrimitives> {
46    chain_spec: Arc<ChainSpec>,
47    #[cfg(feature = "db-api")]
48    tx: TxMock,
49    #[cfg(feature = "db-api")]
50    prune_modes: PruneModes,
51    _phantom: PhantomData<N>,
52}
53
54impl<ChainSpec, N> NoopProvider<ChainSpec, N> {
55    /// Create a new instance for specific primitive types.
56    pub fn new(chain_spec: Arc<ChainSpec>) -> Self {
57        Self {
58            chain_spec,
59            #[cfg(feature = "db-api")]
60            tx: TxMock::default(),
61            #[cfg(feature = "db-api")]
62            prune_modes: PruneModes::default(),
63            _phantom: Default::default(),
64        }
65    }
66}
67
68impl<ChainSpec> NoopProvider<ChainSpec> {
69    /// Create a new instance of the `NoopBlockReader`.
70    pub fn eth(chain_spec: Arc<ChainSpec>) -> Self {
71        Self {
72            chain_spec,
73            #[cfg(feature = "db-api")]
74            tx: TxMock::default(),
75            #[cfg(feature = "db-api")]
76            prune_modes: PruneModes::default(),
77            _phantom: Default::default(),
78        }
79    }
80}
81
82impl NoopProvider {
83    /// Create a new instance of the [`NoopProvider`] with the mainnet chain spec.
84    pub fn mainnet() -> Self {
85        Self::eth(MAINNET.clone())
86    }
87}
88
89impl Default for NoopProvider {
90    fn default() -> Self {
91        Self::mainnet()
92    }
93}
94
95impl<ChainSpec, N> Clone for NoopProvider<ChainSpec, N> {
96    fn clone(&self) -> Self {
97        Self {
98            chain_spec: Arc::clone(&self.chain_spec),
99            #[cfg(feature = "db-api")]
100            tx: self.tx.clone(),
101            #[cfg(feature = "db-api")]
102            prune_modes: self.prune_modes.clone(),
103            _phantom: Default::default(),
104        }
105    }
106}
107
108/// Noop implementation for testing purposes
109impl<ChainSpec: Send + Sync, N: Send + Sync> BlockHashReader for NoopProvider<ChainSpec, N> {
110    fn block_hash(&self, _number: u64) -> ProviderResult<Option<B256>> {
111        Ok(None)
112    }
113
114    fn canonical_hashes_range(
115        &self,
116        _start: BlockNumber,
117        _end: BlockNumber,
118    ) -> ProviderResult<Vec<B256>> {
119        Ok(Vec::new())
120    }
121}
122
123impl<ChainSpec: Send + Sync, N: Send + Sync> BlockNumReader for NoopProvider<ChainSpec, N> {
124    fn chain_info(&self) -> ProviderResult<ChainInfo> {
125        Ok(ChainInfo::default())
126    }
127
128    fn best_block_number(&self) -> ProviderResult<BlockNumber> {
129        Ok(0)
130    }
131
132    fn last_block_number(&self) -> ProviderResult<BlockNumber> {
133        Ok(0)
134    }
135
136    fn block_number(&self, _hash: B256) -> ProviderResult<Option<BlockNumber>> {
137        Ok(None)
138    }
139}
140
141impl<ChainSpec: EthChainSpec + 'static, N: Debug + Send + Sync + 'static> ChainSpecProvider
142    for NoopProvider<ChainSpec, N>
143{
144    type ChainSpec = ChainSpec;
145
146    fn chain_spec(&self) -> Arc<Self::ChainSpec> {
147        self.chain_spec.clone()
148    }
149}
150
151impl<C: Send + Sync, N: NodePrimitives> BlockIdReader for NoopProvider<C, N> {
152    fn pending_block_num_hash(&self) -> ProviderResult<Option<alloy_eips::BlockNumHash>> {
153        Ok(None)
154    }
155
156    fn safe_block_num_hash(&self) -> ProviderResult<Option<alloy_eips::BlockNumHash>> {
157        Ok(None)
158    }
159
160    fn finalized_block_num_hash(&self) -> ProviderResult<Option<alloy_eips::BlockNumHash>> {
161        Ok(None)
162    }
163}
164
165impl<C: Send + Sync, N: NodePrimitives> BlockReaderIdExt for NoopProvider<C, N> {
166    fn block_by_id(&self, _id: BlockId) -> ProviderResult<Option<N::Block>> {
167        Ok(None)
168    }
169
170    fn sealed_header_by_id(
171        &self,
172        _id: BlockId,
173    ) -> ProviderResult<Option<SealedHeader<N::BlockHeader>>> {
174        Ok(None)
175    }
176
177    fn header_by_id(&self, _id: BlockId) -> ProviderResult<Option<N::BlockHeader>> {
178        Ok(None)
179    }
180}
181
182impl<C: Send + Sync, N: NodePrimitives> BlockReader for NoopProvider<C, N> {
183    type Block = N::Block;
184
185    fn find_block_by_hash(
186        &self,
187        _hash: B256,
188        _source: BlockSource,
189    ) -> ProviderResult<Option<Self::Block>> {
190        Ok(None)
191    }
192
193    fn block(&self, _id: BlockHashOrNumber) -> ProviderResult<Option<Self::Block>> {
194        Ok(None)
195    }
196
197    fn pending_block(&self) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
198        Ok(None)
199    }
200
201    fn pending_block_and_receipts(
202        &self,
203    ) -> ProviderResult<Option<(RecoveredBlock<Self::Block>, Vec<Self::Receipt>)>> {
204        Ok(None)
205    }
206
207    fn recovered_block(
208        &self,
209        _id: BlockHashOrNumber,
210        _transaction_kind: TransactionVariant,
211    ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
212        Ok(None)
213    }
214
215    fn sealed_block_with_senders(
216        &self,
217        _id: BlockHashOrNumber,
218        _transaction_kind: TransactionVariant,
219    ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
220        Ok(None)
221    }
222
223    fn block_range(&self, _range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Self::Block>> {
224        Ok(Vec::new())
225    }
226
227    fn block_with_senders_range(
228        &self,
229        _range: RangeInclusive<BlockNumber>,
230    ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
231        Ok(Vec::new())
232    }
233
234    fn recovered_block_range(
235        &self,
236        _range: RangeInclusive<BlockNumber>,
237    ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
238        Ok(Vec::new())
239    }
240
241    fn block_by_transaction_id(&self, _id: TxNumber) -> ProviderResult<Option<BlockNumber>> {
242        Ok(None)
243    }
244}
245
246impl<C: Send + Sync, N: NodePrimitives> TransactionsProvider for NoopProvider<C, N> {
247    type Transaction = N::SignedTx;
248
249    fn transaction_id(&self, _tx_hash: TxHash) -> ProviderResult<Option<TxNumber>> {
250        Ok(None)
251    }
252
253    fn transaction_by_id(&self, _id: TxNumber) -> ProviderResult<Option<Self::Transaction>> {
254        Ok(None)
255    }
256
257    fn transaction_by_id_unhashed(
258        &self,
259        _id: TxNumber,
260    ) -> ProviderResult<Option<Self::Transaction>> {
261        Ok(None)
262    }
263
264    fn transaction_by_hash(&self, _hash: TxHash) -> ProviderResult<Option<Self::Transaction>> {
265        Ok(None)
266    }
267
268    fn transaction_by_hash_with_meta(
269        &self,
270        _hash: TxHash,
271    ) -> ProviderResult<Option<(Self::Transaction, TransactionMeta)>> {
272        Ok(None)
273    }
274
275    fn transactions_by_block(
276        &self,
277        _block_id: BlockHashOrNumber,
278    ) -> ProviderResult<Option<Vec<Self::Transaction>>> {
279        Ok(None)
280    }
281
282    fn transactions_by_block_range(
283        &self,
284        _range: impl RangeBounds<BlockNumber>,
285    ) -> ProviderResult<Vec<Vec<Self::Transaction>>> {
286        Ok(Vec::default())
287    }
288
289    fn transactions_by_tx_range(
290        &self,
291        _range: impl RangeBounds<TxNumber>,
292    ) -> ProviderResult<Vec<Self::Transaction>> {
293        Ok(Vec::default())
294    }
295
296    fn senders_by_tx_range(
297        &self,
298        _range: impl RangeBounds<TxNumber>,
299    ) -> ProviderResult<Vec<Address>> {
300        Ok(Vec::default())
301    }
302
303    fn transaction_sender(&self, _id: TxNumber) -> ProviderResult<Option<Address>> {
304        Ok(None)
305    }
306}
307
308impl<C: Send + Sync, N: NodePrimitives> ReceiptProvider for NoopProvider<C, N> {
309    type Receipt = N::Receipt;
310
311    fn receipt(&self, _id: TxNumber) -> ProviderResult<Option<Self::Receipt>> {
312        Ok(None)
313    }
314
315    fn receipt_by_hash(&self, _hash: TxHash) -> ProviderResult<Option<Self::Receipt>> {
316        Ok(None)
317    }
318
319    fn receipts_by_block(
320        &self,
321        _block: BlockHashOrNumber,
322    ) -> ProviderResult<Option<Vec<Self::Receipt>>> {
323        Ok(None)
324    }
325
326    fn receipts_by_tx_range(
327        &self,
328        _range: impl RangeBounds<TxNumber>,
329    ) -> ProviderResult<Vec<Self::Receipt>> {
330        Ok(Vec::new())
331    }
332
333    fn receipts_by_block_range(
334        &self,
335        _block_range: RangeInclusive<BlockNumber>,
336    ) -> ProviderResult<Vec<Vec<Self::Receipt>>> {
337        Ok(Vec::new())
338    }
339}
340
341impl<C: Send + Sync, N: NodePrimitives> ReceiptProviderIdExt for NoopProvider<C, N> {}
342
343impl<C: Send + Sync, N: NodePrimitives> HeaderProvider for NoopProvider<C, N> {
344    type Header = N::BlockHeader;
345
346    fn header(&self, _block_hash: BlockHash) -> ProviderResult<Option<Self::Header>> {
347        Ok(None)
348    }
349
350    fn header_by_number(&self, _num: u64) -> ProviderResult<Option<Self::Header>> {
351        Ok(None)
352    }
353
354    fn headers_range(
355        &self,
356        _range: impl RangeBounds<BlockNumber>,
357    ) -> ProviderResult<Vec<Self::Header>> {
358        Ok(Vec::new())
359    }
360
361    fn sealed_header(
362        &self,
363        _number: BlockNumber,
364    ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
365        Ok(None)
366    }
367
368    fn sealed_headers_while(
369        &self,
370        _range: impl RangeBounds<BlockNumber>,
371        _predicate: impl FnMut(&SealedHeader<Self::Header>) -> bool,
372    ) -> ProviderResult<Vec<SealedHeader<Self::Header>>> {
373        Ok(Vec::new())
374    }
375}
376
377impl<C: Send + Sync, N: NodePrimitives> AccountReader for NoopProvider<C, N> {
378    fn basic_account(&self, _address: &Address) -> ProviderResult<Option<Account>> {
379        Ok(None)
380    }
381}
382
383impl<C: Send + Sync, N: NodePrimitives> ChangeSetReader for NoopProvider<C, N> {
384    fn account_block_changeset(
385        &self,
386        _block_number: BlockNumber,
387    ) -> ProviderResult<Vec<AccountBeforeTx>> {
388        Ok(Vec::default())
389    }
390
391    fn get_account_before_block(
392        &self,
393        _block_number: BlockNumber,
394        _address: Address,
395    ) -> ProviderResult<Option<AccountBeforeTx>> {
396        Ok(None)
397    }
398
399    fn account_changesets_range(
400        &self,
401        _range: impl core::ops::RangeBounds<BlockNumber>,
402    ) -> ProviderResult<Vec<(BlockNumber, AccountBeforeTx)>> {
403        Ok(Vec::default())
404    }
405
406    fn account_changeset_count(&self) -> ProviderResult<usize> {
407        Ok(0)
408    }
409}
410
411#[cfg(feature = "db-api")]
412impl<C: Send + Sync, N: NodePrimitives> StorageChangeSetReader for NoopProvider<C, N> {
413    fn storage_changeset(
414        &self,
415        _block_number: BlockNumber,
416    ) -> ProviderResult<
417        Vec<(reth_db_api::models::BlockNumberAddress, reth_primitives_traits::StorageEntry)>,
418    > {
419        Ok(Vec::default())
420    }
421
422    fn get_storage_before_block(
423        &self,
424        _block_number: BlockNumber,
425        _address: Address,
426        _storage_key: B256,
427    ) -> ProviderResult<Option<reth_primitives_traits::StorageEntry>> {
428        Ok(None)
429    }
430
431    fn storage_changesets_range(
432        &self,
433        _range: impl core::ops::RangeBounds<BlockNumber>,
434    ) -> ProviderResult<
435        Vec<(reth_db_api::models::BlockNumberAddress, reth_primitives_traits::StorageEntry)>,
436    > {
437        Ok(Vec::default())
438    }
439
440    fn storage_changeset_count(&self) -> ProviderResult<usize> {
441        Ok(0)
442    }
443}
444
445impl<C: Send + Sync, N: NodePrimitives> StateRootProvider for NoopProvider<C, N> {
446    fn state_root(&self, _state: HashedPostState) -> ProviderResult<B256> {
447        Ok(B256::default())
448    }
449
450    fn state_root_from_nodes(&self, _input: TrieInput) -> ProviderResult<B256> {
451        Ok(B256::default())
452    }
453
454    fn state_root_with_updates(
455        &self,
456        _state: HashedPostState,
457    ) -> ProviderResult<(B256, TrieUpdates)> {
458        Ok((B256::default(), TrieUpdates::default()))
459    }
460
461    fn state_root_from_nodes_with_updates(
462        &self,
463        _input: TrieInput,
464    ) -> ProviderResult<(B256, TrieUpdates)> {
465        Ok((B256::default(), TrieUpdates::default()))
466    }
467}
468
469impl<C: Send + Sync, N: NodePrimitives> StorageRootProvider for NoopProvider<C, N> {
470    fn storage_root(
471        &self,
472        _address: Address,
473        _hashed_storage: HashedStorage,
474    ) -> ProviderResult<B256> {
475        Ok(B256::default())
476    }
477
478    fn storage_proof(
479        &self,
480        _address: Address,
481        slot: B256,
482        _hashed_storage: HashedStorage,
483    ) -> ProviderResult<StorageProof> {
484        Ok(StorageProof::new(slot))
485    }
486
487    fn storage_multiproof(
488        &self,
489        _address: Address,
490        _slots: &[B256],
491        _hashed_storage: HashedStorage,
492    ) -> ProviderResult<StorageMultiProof> {
493        Ok(StorageMultiProof::empty())
494    }
495}
496
497impl<C: Send + Sync, N: NodePrimitives> StateProofProvider for NoopProvider<C, N> {
498    fn proof(
499        &self,
500        _input: TrieInput,
501        address: Address,
502        _slots: &[B256],
503    ) -> ProviderResult<AccountProof> {
504        Ok(AccountProof::new(address))
505    }
506
507    fn multiproof(
508        &self,
509        _input: TrieInput,
510        _targets: MultiProofTargets,
511    ) -> ProviderResult<MultiProof> {
512        Ok(MultiProof::default())
513    }
514
515    fn witness(&self, _input: TrieInput, _target: HashedPostState) -> ProviderResult<Vec<Bytes>> {
516        Ok(Vec::default())
517    }
518}
519
520impl<C: Send + Sync, N: NodePrimitives> HashedPostStateProvider for NoopProvider<C, N> {
521    fn hashed_post_state(&self, _bundle_state: &revm_database::BundleState) -> HashedPostState {
522        HashedPostState::default()
523    }
524}
525
526impl<C: Send + Sync, N: NodePrimitives> StateReader for NoopProvider<C, N> {
527    type Receipt = N::Receipt;
528
529    fn get_state(
530        &self,
531        _block: BlockNumber,
532    ) -> ProviderResult<Option<ExecutionOutcome<Self::Receipt>>> {
533        Ok(None)
534    }
535}
536
537impl<C: Send + Sync, N: NodePrimitives> StateProvider for NoopProvider<C, N> {
538    fn storage(
539        &self,
540        _account: Address,
541        _storage_key: StorageKey,
542    ) -> ProviderResult<Option<StorageValue>> {
543        Ok(None)
544    }
545}
546
547impl<C: Send + Sync, N: NodePrimitives> BytecodeReader for NoopProvider<C, N> {
548    fn bytecode_by_hash(&self, _code_hash: &B256) -> ProviderResult<Option<Bytecode>> {
549        Ok(None)
550    }
551}
552
553impl<C: Send + Sync + 'static, N: NodePrimitives> StateProviderFactory for NoopProvider<C, N> {
554    fn latest(&self) -> ProviderResult<StateProviderBox> {
555        Ok(Box::new(self.clone()))
556    }
557
558    fn state_by_block_number_or_tag(
559        &self,
560        number_or_tag: BlockNumberOrTag,
561    ) -> ProviderResult<StateProviderBox> {
562        match number_or_tag {
563            BlockNumberOrTag::Latest => self.latest(),
564            BlockNumberOrTag::Finalized => {
565                // we can only get the finalized state by hash, not by num
566                let hash =
567                    self.finalized_block_hash()?.ok_or(ProviderError::FinalizedBlockNotFound)?;
568
569                // only look at historical state
570                self.history_by_block_hash(hash)
571            }
572            BlockNumberOrTag::Safe => {
573                // we can only get the safe state by hash, not by num
574                let hash = self.safe_block_hash()?.ok_or(ProviderError::SafeBlockNotFound)?;
575
576                self.history_by_block_hash(hash)
577            }
578            BlockNumberOrTag::Earliest => {
579                self.history_by_block_number(self.earliest_block_number()?)
580            }
581            BlockNumberOrTag::Pending => self.pending(),
582            BlockNumberOrTag::Number(num) => self.history_by_block_number(num),
583        }
584    }
585
586    fn history_by_block_number(&self, _block: BlockNumber) -> ProviderResult<StateProviderBox> {
587        Ok(Box::new(self.clone()))
588    }
589
590    fn history_by_block_hash(&self, _block: BlockHash) -> ProviderResult<StateProviderBox> {
591        Ok(Box::new(self.clone()))
592    }
593
594    fn state_by_block_hash(&self, _block: BlockHash) -> ProviderResult<StateProviderBox> {
595        Ok(Box::new(self.clone()))
596    }
597
598    fn pending(&self) -> ProviderResult<StateProviderBox> {
599        Ok(Box::new(self.clone()))
600    }
601
602    fn pending_state_by_hash(&self, _block_hash: B256) -> ProviderResult<Option<StateProviderBox>> {
603        Ok(Some(Box::new(self.clone())))
604    }
605
606    fn maybe_pending(&self) -> ProviderResult<Option<StateProviderBox>> {
607        Ok(Some(Box::new(self.clone())))
608    }
609}
610
611impl<C: Send + Sync, N: NodePrimitives> StageCheckpointReader for NoopProvider<C, N> {
612    fn get_stage_checkpoint(&self, _id: StageId) -> ProviderResult<Option<StageCheckpoint>> {
613        Ok(None)
614    }
615
616    fn get_stage_checkpoint_progress(&self, _id: StageId) -> ProviderResult<Option<Vec<u8>>> {
617        Ok(None)
618    }
619
620    fn get_all_checkpoints(&self) -> ProviderResult<Vec<(String, StageCheckpoint)>> {
621        Ok(Vec::new())
622    }
623}
624
625impl<C: Send + Sync, N: NodePrimitives> PruneCheckpointReader for NoopProvider<C, N> {
626    fn get_prune_checkpoint(
627        &self,
628        _segment: PruneSegment,
629    ) -> ProviderResult<Option<PruneCheckpoint>> {
630        Ok(None)
631    }
632
633    fn get_prune_checkpoints(&self) -> ProviderResult<Vec<(PruneSegment, PruneCheckpoint)>> {
634        Ok(Vec::new())
635    }
636}
637
638impl<C: Send + Sync, N: NodePrimitives> NodePrimitivesProvider for NoopProvider<C, N> {
639    type Primitives = N;
640}
641
642impl<C: Send + Sync, N: Send + Sync> BlockBodyIndicesProvider for NoopProvider<C, N> {
643    fn block_body_indices(&self, _num: u64) -> ProviderResult<Option<StoredBlockBodyIndices>> {
644        Ok(None)
645    }
646
647    fn block_body_indices_range(
648        &self,
649        _range: RangeInclusive<BlockNumber>,
650    ) -> ProviderResult<Vec<StoredBlockBodyIndices>> {
651        Ok(Vec::new())
652    }
653}
654
655#[cfg(feature = "db-api")]
656impl<ChainSpec: Send + Sync, N: NodePrimitives> DBProvider for NoopProvider<ChainSpec, N> {
657    type Tx = TxMock;
658
659    fn tx_ref(&self) -> &Self::Tx {
660        &self.tx
661    }
662
663    fn tx_mut(&mut self) -> &mut Self::Tx {
664        &mut self.tx
665    }
666
667    fn into_tx(self) -> Self::Tx {
668        self.tx
669    }
670
671    fn prune_modes_ref(&self) -> &PruneModes {
672        &self.prune_modes
673    }
674
675    fn commit(self) -> ProviderResult<()> {
676        use reth_db_api::transaction::DbTx;
677
678        Ok(self.tx.commit()?)
679    }
680}
681
682#[cfg(feature = "db-api")]
683impl<ChainSpec: Send + Sync, N: NodePrimitives> DatabaseProviderFactory
684    for NoopProvider<ChainSpec, N>
685{
686    type DB = DatabaseMock;
687    type Provider = Self;
688    type ProviderRW = Self;
689
690    fn database_provider_ro(&self) -> ProviderResult<Self::Provider> {
691        Ok(self.clone())
692    }
693
694    fn database_provider_rw(&self) -> ProviderResult<Self::ProviderRW> {
695        Ok(self.clone())
696    }
697}
698
699#[cfg(feature = "db-api")]
700impl<ChainSpec: Send + Sync, N: Send + Sync> StorageSettingsCache for NoopProvider<ChainSpec, N> {
701    fn cached_storage_settings(&self) -> reth_db_api::models::StorageSettings {
702        reth_db_api::models::StorageSettings::default()
703    }
704
705    fn set_storage_settings_cache(&self, _settings: reth_db_api::models::StorageSettings) {}
706}