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