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