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};
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, U256,
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::none(),
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::none(),
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
242impl<C: Send + Sync, N: NodePrimitives> TransactionsProvider for NoopProvider<C, N> {
243    type Transaction = N::SignedTx;
244
245    fn transaction_id(&self, _tx_hash: TxHash) -> ProviderResult<Option<TxNumber>> {
246        Ok(None)
247    }
248
249    fn transaction_by_id(&self, _id: TxNumber) -> ProviderResult<Option<Self::Transaction>> {
250        Ok(None)
251    }
252
253    fn transaction_by_id_unhashed(
254        &self,
255        _id: TxNumber,
256    ) -> ProviderResult<Option<Self::Transaction>> {
257        Ok(None)
258    }
259
260    fn transaction_by_hash(&self, _hash: TxHash) -> ProviderResult<Option<Self::Transaction>> {
261        Ok(None)
262    }
263
264    fn transaction_by_hash_with_meta(
265        &self,
266        _hash: TxHash,
267    ) -> ProviderResult<Option<(Self::Transaction, TransactionMeta)>> {
268        Ok(None)
269    }
270
271    fn transaction_block(&self, _id: TxNumber) -> ProviderResult<Option<BlockNumber>> {
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 header_td(&self, _hash: &BlockHash) -> ProviderResult<Option<U256>> {
355        Ok(None)
356    }
357
358    fn header_td_by_number(&self, _number: BlockNumber) -> ProviderResult<Option<U256>> {
359        Ok(None)
360    }
361
362    fn headers_range(
363        &self,
364        _range: impl RangeBounds<BlockNumber>,
365    ) -> ProviderResult<Vec<Self::Header>> {
366        Ok(Vec::new())
367    }
368
369    fn sealed_header(
370        &self,
371        _number: BlockNumber,
372    ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
373        Ok(None)
374    }
375
376    fn sealed_headers_while(
377        &self,
378        _range: impl RangeBounds<BlockNumber>,
379        _predicate: impl FnMut(&SealedHeader<Self::Header>) -> bool,
380    ) -> ProviderResult<Vec<SealedHeader<Self::Header>>> {
381        Ok(Vec::new())
382    }
383}
384
385impl<C: Send + Sync, N: NodePrimitives> AccountReader for NoopProvider<C, N> {
386    fn basic_account(&self, _address: &Address) -> ProviderResult<Option<Account>> {
387        Ok(None)
388    }
389}
390
391impl<C: Send + Sync, N: NodePrimitives> ChangeSetReader for NoopProvider<C, N> {
392    fn account_block_changeset(
393        &self,
394        _block_number: BlockNumber,
395    ) -> ProviderResult<Vec<AccountBeforeTx>> {
396        Ok(Vec::default())
397    }
398}
399
400impl<C: Send + Sync, N: NodePrimitives> StateRootProvider for NoopProvider<C, N> {
401    fn state_root(&self, _state: HashedPostState) -> ProviderResult<B256> {
402        Ok(B256::default())
403    }
404
405    fn state_root_from_nodes(&self, _input: TrieInput) -> ProviderResult<B256> {
406        Ok(B256::default())
407    }
408
409    fn state_root_with_updates(
410        &self,
411        _state: HashedPostState,
412    ) -> ProviderResult<(B256, TrieUpdates)> {
413        Ok((B256::default(), TrieUpdates::default()))
414    }
415
416    fn state_root_from_nodes_with_updates(
417        &self,
418        _input: TrieInput,
419    ) -> ProviderResult<(B256, TrieUpdates)> {
420        Ok((B256::default(), TrieUpdates::default()))
421    }
422}
423
424impl<C: Send + Sync, N: NodePrimitives> StorageRootProvider for NoopProvider<C, N> {
425    fn storage_root(
426        &self,
427        _address: Address,
428        _hashed_storage: HashedStorage,
429    ) -> ProviderResult<B256> {
430        Ok(B256::default())
431    }
432
433    fn storage_proof(
434        &self,
435        _address: Address,
436        slot: B256,
437        _hashed_storage: HashedStorage,
438    ) -> ProviderResult<StorageProof> {
439        Ok(StorageProof::new(slot))
440    }
441
442    fn storage_multiproof(
443        &self,
444        _address: Address,
445        _slots: &[B256],
446        _hashed_storage: HashedStorage,
447    ) -> ProviderResult<StorageMultiProof> {
448        Ok(StorageMultiProof::empty())
449    }
450}
451
452impl<C: Send + Sync, N: NodePrimitives> StateProofProvider for NoopProvider<C, N> {
453    fn proof(
454        &self,
455        _input: TrieInput,
456        address: Address,
457        _slots: &[B256],
458    ) -> ProviderResult<AccountProof> {
459        Ok(AccountProof::new(address))
460    }
461
462    fn multiproof(
463        &self,
464        _input: TrieInput,
465        _targets: MultiProofTargets,
466    ) -> ProviderResult<MultiProof> {
467        Ok(MultiProof::default())
468    }
469
470    fn witness(&self, _input: TrieInput, _target: HashedPostState) -> ProviderResult<Vec<Bytes>> {
471        Ok(Vec::default())
472    }
473}
474
475impl<C: Send + Sync, N: NodePrimitives> HashedPostStateProvider for NoopProvider<C, N> {
476    fn hashed_post_state(&self, _bundle_state: &revm_database::BundleState) -> HashedPostState {
477        HashedPostState::default()
478    }
479}
480
481impl<C: Send + Sync, N: NodePrimitives> StateReader for NoopProvider<C, N> {
482    type Receipt = N::Receipt;
483
484    fn get_state(
485        &self,
486        _block: BlockNumber,
487    ) -> ProviderResult<Option<ExecutionOutcome<Self::Receipt>>> {
488        Ok(None)
489    }
490}
491
492impl<C: Send + Sync, N: NodePrimitives> StateProvider for NoopProvider<C, N> {
493    fn storage(
494        &self,
495        _account: Address,
496        _storage_key: StorageKey,
497    ) -> ProviderResult<Option<StorageValue>> {
498        Ok(None)
499    }
500}
501
502impl<C: Send + Sync, N: NodePrimitives> BytecodeReader for NoopProvider<C, N> {
503    fn bytecode_by_hash(&self, _code_hash: &B256) -> ProviderResult<Option<Bytecode>> {
504        Ok(None)
505    }
506}
507
508impl<C: Send + Sync + 'static, N: NodePrimitives> StateProviderFactory for NoopProvider<C, N> {
509    fn latest(&self) -> ProviderResult<StateProviderBox> {
510        Ok(Box::new(self.clone()))
511    }
512
513    fn state_by_block_number_or_tag(
514        &self,
515        number_or_tag: BlockNumberOrTag,
516    ) -> ProviderResult<StateProviderBox> {
517        match number_or_tag {
518            BlockNumberOrTag::Latest => self.latest(),
519            BlockNumberOrTag::Finalized => {
520                // we can only get the finalized state by hash, not by num
521                let hash =
522                    self.finalized_block_hash()?.ok_or(ProviderError::FinalizedBlockNotFound)?;
523
524                // only look at historical state
525                self.history_by_block_hash(hash)
526            }
527            BlockNumberOrTag::Safe => {
528                // we can only get the safe state by hash, not by num
529                let hash = self.safe_block_hash()?.ok_or(ProviderError::SafeBlockNotFound)?;
530
531                self.history_by_block_hash(hash)
532            }
533            BlockNumberOrTag::Earliest => {
534                self.history_by_block_number(self.earliest_block_number()?)
535            }
536            BlockNumberOrTag::Pending => self.pending(),
537            BlockNumberOrTag::Number(num) => self.history_by_block_number(num),
538        }
539    }
540
541    fn history_by_block_number(&self, _block: BlockNumber) -> ProviderResult<StateProviderBox> {
542        Ok(Box::new(self.clone()))
543    }
544
545    fn history_by_block_hash(&self, _block: BlockHash) -> ProviderResult<StateProviderBox> {
546        Ok(Box::new(self.clone()))
547    }
548
549    fn state_by_block_hash(&self, _block: BlockHash) -> ProviderResult<StateProviderBox> {
550        Ok(Box::new(self.clone()))
551    }
552
553    fn pending(&self) -> ProviderResult<StateProviderBox> {
554        Ok(Box::new(self.clone()))
555    }
556
557    fn pending_state_by_hash(&self, _block_hash: B256) -> ProviderResult<Option<StateProviderBox>> {
558        Ok(Some(Box::new(self.clone())))
559    }
560}
561
562impl<C: Send + Sync, N: NodePrimitives> StageCheckpointReader for NoopProvider<C, N> {
563    fn get_stage_checkpoint(&self, _id: StageId) -> ProviderResult<Option<StageCheckpoint>> {
564        Ok(None)
565    }
566
567    fn get_stage_checkpoint_progress(&self, _id: StageId) -> ProviderResult<Option<Vec<u8>>> {
568        Ok(None)
569    }
570
571    fn get_all_checkpoints(&self) -> ProviderResult<Vec<(String, StageCheckpoint)>> {
572        Ok(Vec::new())
573    }
574}
575
576impl<C: Send + Sync, N: NodePrimitives> PruneCheckpointReader for NoopProvider<C, N> {
577    fn get_prune_checkpoint(
578        &self,
579        _segment: PruneSegment,
580    ) -> ProviderResult<Option<PruneCheckpoint>> {
581        Ok(None)
582    }
583
584    fn get_prune_checkpoints(&self) -> ProviderResult<Vec<(PruneSegment, PruneCheckpoint)>> {
585        Ok(Vec::new())
586    }
587}
588
589impl<C: Send + Sync, N: NodePrimitives> NodePrimitivesProvider for NoopProvider<C, N> {
590    type Primitives = N;
591}
592
593impl<C: Send + Sync, N: Send + Sync> BlockBodyIndicesProvider for NoopProvider<C, N> {
594    fn block_body_indices(&self, _num: u64) -> ProviderResult<Option<StoredBlockBodyIndices>> {
595        Ok(None)
596    }
597
598    fn block_body_indices_range(
599        &self,
600        _range: RangeInclusive<BlockNumber>,
601    ) -> ProviderResult<Vec<StoredBlockBodyIndices>> {
602        Ok(Vec::new())
603    }
604}
605
606#[cfg(feature = "db-api")]
607impl<ChainSpec: Send + Sync, N: NodePrimitives> DBProvider for NoopProvider<ChainSpec, N> {
608    type Tx = TxMock;
609
610    fn tx_ref(&self) -> &Self::Tx {
611        &self.tx
612    }
613
614    fn tx_mut(&mut self) -> &mut Self::Tx {
615        &mut self.tx
616    }
617
618    fn into_tx(self) -> Self::Tx {
619        self.tx
620    }
621
622    fn prune_modes_ref(&self) -> &PruneModes {
623        &self.prune_modes
624    }
625}
626
627#[cfg(feature = "db-api")]
628impl<ChainSpec: Send + Sync, N: NodePrimitives> DatabaseProviderFactory
629    for NoopProvider<ChainSpec, N>
630{
631    type DB = DatabaseMock;
632    type Provider = Self;
633    type ProviderRW = Self;
634
635    fn database_provider_ro(&self) -> ProviderResult<Self::Provider> {
636        Ok(self.clone())
637    }
638
639    fn database_provider_rw(&self) -> ProviderResult<Self::ProviderRW> {
640        Ok(self.clone())
641    }
642}