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