reth_storage_api/
noop.rs

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