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, ExecutionWitnessMode, HashedPostState, HashedStorage,
39    MultiProof, 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
407#[cfg(feature = "db-api")]
408impl<C: Send + Sync, N: NodePrimitives> StorageChangeSetReader for NoopProvider<C, N> {
409    fn storage_changeset(
410        &self,
411        _block_number: BlockNumber,
412    ) -> ProviderResult<
413        Vec<(reth_db_api::models::BlockNumberAddress, reth_primitives_traits::StorageEntry)>,
414    > {
415        Ok(Vec::default())
416    }
417
418    fn get_storage_before_block(
419        &self,
420        _block_number: BlockNumber,
421        _address: Address,
422        _storage_key: B256,
423    ) -> ProviderResult<Option<reth_primitives_traits::StorageEntry>> {
424        Ok(None)
425    }
426
427    fn storage_changesets_range(
428        &self,
429        _range: impl core::ops::RangeBounds<BlockNumber>,
430    ) -> ProviderResult<
431        Vec<(reth_db_api::models::BlockNumberAddress, reth_primitives_traits::StorageEntry)>,
432    > {
433        Ok(Vec::default())
434    }
435}
436
437impl<C: Send + Sync, N: NodePrimitives> StateRootProvider for NoopProvider<C, N> {
438    fn state_root(&self, _state: HashedPostState) -> ProviderResult<B256> {
439        Ok(B256::default())
440    }
441
442    fn state_root_from_nodes(&self, _input: TrieInput) -> ProviderResult<B256> {
443        Ok(B256::default())
444    }
445
446    fn state_root_with_updates(
447        &self,
448        _state: HashedPostState,
449    ) -> ProviderResult<(B256, TrieUpdates)> {
450        Ok((B256::default(), TrieUpdates::default()))
451    }
452
453    fn state_root_from_nodes_with_updates(
454        &self,
455        _input: TrieInput,
456    ) -> ProviderResult<(B256, TrieUpdates)> {
457        Ok((B256::default(), TrieUpdates::default()))
458    }
459}
460
461impl<C: Send + Sync, N: NodePrimitives> StorageRootProvider for NoopProvider<C, N> {
462    fn storage_root(
463        &self,
464        _address: Address,
465        _hashed_storage: HashedStorage,
466    ) -> ProviderResult<B256> {
467        Ok(B256::default())
468    }
469
470    fn storage_proof(
471        &self,
472        _address: Address,
473        slot: B256,
474        _hashed_storage: HashedStorage,
475    ) -> ProviderResult<StorageProof> {
476        Ok(StorageProof::new(slot))
477    }
478
479    fn storage_multiproof(
480        &self,
481        _address: Address,
482        _slots: &[B256],
483        _hashed_storage: HashedStorage,
484    ) -> ProviderResult<StorageMultiProof> {
485        Ok(StorageMultiProof::empty())
486    }
487}
488
489impl<C: Send + Sync, N: NodePrimitives> StateProofProvider for NoopProvider<C, N> {
490    fn proof(
491        &self,
492        _input: TrieInput,
493        address: Address,
494        _slots: &[B256],
495    ) -> ProviderResult<AccountProof> {
496        Ok(AccountProof::new(address))
497    }
498
499    fn multiproof(
500        &self,
501        _input: TrieInput,
502        _targets: MultiProofTargets,
503    ) -> ProviderResult<MultiProof> {
504        Ok(MultiProof::default())
505    }
506
507    fn witness(
508        &self,
509        _input: TrieInput,
510        _target: HashedPostState,
511        _mode: ExecutionWitnessMode,
512    ) -> ProviderResult<Vec<Bytes>> {
513        Ok(Vec::default())
514    }
515}
516
517impl<C: Send + Sync, N: NodePrimitives> HashedPostStateProvider for NoopProvider<C, N> {
518    fn hashed_post_state(&self, _bundle_state: &revm_database::BundleState) -> HashedPostState {
519        HashedPostState::default()
520    }
521}
522
523impl<C: Send + Sync, N: NodePrimitives> StateReader for NoopProvider<C, N> {
524    type Receipt = N::Receipt;
525
526    fn get_state(
527        &self,
528        _block: BlockNumber,
529    ) -> ProviderResult<Option<ExecutionOutcome<Self::Receipt>>> {
530        Ok(None)
531    }
532}
533
534impl<C: Send + Sync, N: NodePrimitives> StateProvider for NoopProvider<C, N> {
535    fn storage(
536        &self,
537        _account: Address,
538        _storage_key: StorageKey,
539    ) -> ProviderResult<Option<StorageValue>> {
540        Ok(None)
541    }
542}
543
544impl<C: Send + Sync, N: NodePrimitives> BytecodeReader for NoopProvider<C, N> {
545    fn bytecode_by_hash(&self, _code_hash: &B256) -> ProviderResult<Option<Bytecode>> {
546        Ok(None)
547    }
548}
549
550impl<C: Send + Sync + 'static, N: NodePrimitives> StateProviderFactory for NoopProvider<C, N> {
551    fn latest(&self) -> ProviderResult<StateProviderBox> {
552        Ok(Box::new(self.clone()))
553    }
554
555    fn state_by_block_number_or_tag(
556        &self,
557        number_or_tag: BlockNumberOrTag,
558    ) -> ProviderResult<StateProviderBox> {
559        match number_or_tag {
560            BlockNumberOrTag::Latest => self.latest(),
561            BlockNumberOrTag::Finalized => {
562                // we can only get the finalized state by hash, not by num
563                let hash =
564                    self.finalized_block_hash()?.ok_or(ProviderError::FinalizedBlockNotFound)?;
565
566                // only look at historical state
567                self.history_by_block_hash(hash)
568            }
569            BlockNumberOrTag::Safe => {
570                // we can only get the safe state by hash, not by num
571                let hash = self.safe_block_hash()?.ok_or(ProviderError::SafeBlockNotFound)?;
572
573                self.history_by_block_hash(hash)
574            }
575            BlockNumberOrTag::Earliest => {
576                self.history_by_block_number(self.earliest_block_number()?)
577            }
578            BlockNumberOrTag::Pending => self.pending(),
579            BlockNumberOrTag::Number(num) => self.history_by_block_number(num),
580        }
581    }
582
583    fn history_by_block_number(&self, _block: BlockNumber) -> ProviderResult<StateProviderBox> {
584        Ok(Box::new(self.clone()))
585    }
586
587    fn history_by_block_hash(&self, _block: BlockHash) -> ProviderResult<StateProviderBox> {
588        Ok(Box::new(self.clone()))
589    }
590
591    fn state_by_block_hash(&self, _block: BlockHash) -> ProviderResult<StateProviderBox> {
592        Ok(Box::new(self.clone()))
593    }
594
595    fn pending(&self) -> ProviderResult<StateProviderBox> {
596        Ok(Box::new(self.clone()))
597    }
598
599    fn pending_state_by_hash(&self, _block_hash: B256) -> ProviderResult<Option<StateProviderBox>> {
600        Ok(Some(Box::new(self.clone())))
601    }
602
603    fn maybe_pending(&self) -> ProviderResult<Option<StateProviderBox>> {
604        Ok(Some(Box::new(self.clone())))
605    }
606}
607
608impl<C: Send + Sync, N: NodePrimitives> StageCheckpointReader for NoopProvider<C, N> {
609    fn get_stage_checkpoint(&self, _id: StageId) -> ProviderResult<Option<StageCheckpoint>> {
610        Ok(None)
611    }
612
613    fn get_stage_checkpoint_progress(&self, _id: StageId) -> ProviderResult<Option<Vec<u8>>> {
614        Ok(None)
615    }
616
617    fn get_all_checkpoints(&self) -> ProviderResult<Vec<(String, StageCheckpoint)>> {
618        Ok(Vec::new())
619    }
620}
621
622impl<C: Send + Sync, N: NodePrimitives> PruneCheckpointReader for NoopProvider<C, N> {
623    fn get_prune_checkpoint(
624        &self,
625        _segment: PruneSegment,
626    ) -> ProviderResult<Option<PruneCheckpoint>> {
627        Ok(None)
628    }
629
630    fn get_prune_checkpoints(&self) -> ProviderResult<Vec<(PruneSegment, PruneCheckpoint)>> {
631        Ok(Vec::new())
632    }
633}
634
635impl<C: Send + Sync, N: NodePrimitives> NodePrimitivesProvider for NoopProvider<C, N> {
636    type Primitives = N;
637}
638
639impl<C: Send + Sync, N: Send + Sync> BlockBodyIndicesProvider for NoopProvider<C, N> {
640    fn block_body_indices(&self, _num: u64) -> ProviderResult<Option<StoredBlockBodyIndices>> {
641        Ok(None)
642    }
643
644    fn block_body_indices_range(
645        &self,
646        _range: RangeInclusive<BlockNumber>,
647    ) -> ProviderResult<Vec<StoredBlockBodyIndices>> {
648        Ok(Vec::new())
649    }
650}
651
652#[cfg(feature = "db-api")]
653impl<ChainSpec: Send + Sync, N: NodePrimitives> DBProvider for NoopProvider<ChainSpec, N> {
654    type Tx = TxMock;
655
656    fn tx_ref(&self) -> &Self::Tx {
657        &self.tx
658    }
659
660    fn tx_mut(&mut self) -> &mut Self::Tx {
661        &mut self.tx
662    }
663
664    fn into_tx(self) -> Self::Tx {
665        self.tx
666    }
667
668    fn prune_modes_ref(&self) -> &PruneModes {
669        &self.prune_modes
670    }
671
672    fn commit(self) -> ProviderResult<()> {
673        use reth_db_api::transaction::DbTx;
674
675        Ok(self.tx.commit()?)
676    }
677}
678
679#[cfg(feature = "db-api")]
680impl<ChainSpec: Send + Sync, N: NodePrimitives> DatabaseProviderFactory
681    for NoopProvider<ChainSpec, N>
682{
683    type DB = DatabaseMock;
684    type Provider = Self;
685    type ProviderRW = Self;
686
687    fn database_provider_ro(&self) -> ProviderResult<Self::Provider> {
688        Ok(self.clone())
689    }
690
691    fn database_provider_rw(&self) -> ProviderResult<Self::ProviderRW> {
692        Ok(self.clone())
693    }
694}
695
696#[cfg(feature = "db-api")]
697impl<ChainSpec: Send + Sync, N: Send + Sync> StorageSettingsCache for NoopProvider<ChainSpec, N> {
698    fn cached_storage_settings(&self) -> reth_db_api::models::StorageSettings {
699        reth_db_api::models::StorageSettings::default()
700    }
701
702    fn set_storage_settings_cache(&self, _settings: reth_db_api::models::StorageSettings) {}
703}