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, 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#[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::none(),
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::none(),
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 transaction_block(&self, _id: TxNumber) -> ProviderResult<Option<BlockNumber>> {
276 Ok(None)
277 }
278
279 fn transactions_by_block(
280 &self,
281 _block_id: BlockHashOrNumber,
282 ) -> ProviderResult<Option<Vec<Self::Transaction>>> {
283 Ok(None)
284 }
285
286 fn transactions_by_block_range(
287 &self,
288 _range: impl RangeBounds<BlockNumber>,
289 ) -> ProviderResult<Vec<Vec<Self::Transaction>>> {
290 Ok(Vec::default())
291 }
292
293 fn transactions_by_tx_range(
294 &self,
295 _range: impl RangeBounds<TxNumber>,
296 ) -> ProviderResult<Vec<Self::Transaction>> {
297 Ok(Vec::default())
298 }
299
300 fn senders_by_tx_range(
301 &self,
302 _range: impl RangeBounds<TxNumber>,
303 ) -> ProviderResult<Vec<Address>> {
304 Ok(Vec::default())
305 }
306
307 fn transaction_sender(&self, _id: TxNumber) -> ProviderResult<Option<Address>> {
308 Ok(None)
309 }
310}
311
312impl<C: Send + Sync, N: NodePrimitives> ReceiptProvider for NoopProvider<C, N> {
313 type Receipt = N::Receipt;
314
315 fn receipt(&self, _id: TxNumber) -> ProviderResult<Option<Self::Receipt>> {
316 Ok(None)
317 }
318
319 fn receipt_by_hash(&self, _hash: TxHash) -> ProviderResult<Option<Self::Receipt>> {
320 Ok(None)
321 }
322
323 fn receipts_by_block(
324 &self,
325 _block: BlockHashOrNumber,
326 ) -> ProviderResult<Option<Vec<Self::Receipt>>> {
327 Ok(None)
328 }
329
330 fn receipts_by_tx_range(
331 &self,
332 _range: impl RangeBounds<TxNumber>,
333 ) -> ProviderResult<Vec<Self::Receipt>> {
334 Ok(Vec::new())
335 }
336
337 fn receipts_by_block_range(
338 &self,
339 _block_range: RangeInclusive<BlockNumber>,
340 ) -> ProviderResult<Vec<Vec<Self::Receipt>>> {
341 Ok(Vec::new())
342 }
343}
344
345impl<C: Send + Sync, N: NodePrimitives> ReceiptProviderIdExt for NoopProvider<C, N> {}
346
347impl<C: Send + Sync, N: NodePrimitives> HeaderProvider for NoopProvider<C, N> {
348 type Header = N::BlockHeader;
349
350 fn header(&self, _block_hash: BlockHash) -> ProviderResult<Option<Self::Header>> {
351 Ok(None)
352 }
353
354 fn header_by_number(&self, _num: u64) -> ProviderResult<Option<Self::Header>> {
355 Ok(None)
356 }
357
358 fn header_td(&self, _hash: BlockHash) -> ProviderResult<Option<U256>> {
359 Ok(None)
360 }
361
362 fn header_td_by_number(&self, _number: BlockNumber) -> ProviderResult<Option<U256>> {
363 Ok(None)
364 }
365
366 fn headers_range(
367 &self,
368 _range: impl RangeBounds<BlockNumber>,
369 ) -> ProviderResult<Vec<Self::Header>> {
370 Ok(Vec::new())
371 }
372
373 fn sealed_header(
374 &self,
375 _number: BlockNumber,
376 ) -> ProviderResult<Option<SealedHeader<Self::Header>>> {
377 Ok(None)
378 }
379
380 fn sealed_headers_while(
381 &self,
382 _range: impl RangeBounds<BlockNumber>,
383 _predicate: impl FnMut(&SealedHeader<Self::Header>) -> bool,
384 ) -> ProviderResult<Vec<SealedHeader<Self::Header>>> {
385 Ok(Vec::new())
386 }
387}
388
389impl<C: Send + Sync, N: NodePrimitives> AccountReader for NoopProvider<C, N> {
390 fn basic_account(&self, _address: &Address) -> ProviderResult<Option<Account>> {
391 Ok(None)
392 }
393}
394
395impl<C: Send + Sync, N: NodePrimitives> ChangeSetReader for NoopProvider<C, N> {
396 fn account_block_changeset(
397 &self,
398 _block_number: BlockNumber,
399 ) -> ProviderResult<Vec<AccountBeforeTx>> {
400 Ok(Vec::default())
401 }
402
403 fn get_account_before_block(
404 &self,
405 _block_number: BlockNumber,
406 _address: Address,
407 ) -> ProviderResult<Option<AccountBeforeTx>> {
408 Ok(None)
409 }
410}
411
412impl<C: Send + Sync, N: NodePrimitives> StateRootProvider for NoopProvider<C, N> {
413 fn state_root(&self, _state: HashedPostState) -> ProviderResult<B256> {
414 Ok(B256::default())
415 }
416
417 fn state_root_from_nodes(&self, _input: TrieInput) -> ProviderResult<B256> {
418 Ok(B256::default())
419 }
420
421 fn state_root_with_updates(
422 &self,
423 _state: HashedPostState,
424 ) -> ProviderResult<(B256, TrieUpdates)> {
425 Ok((B256::default(), TrieUpdates::default()))
426 }
427
428 fn state_root_from_nodes_with_updates(
429 &self,
430 _input: TrieInput,
431 ) -> ProviderResult<(B256, TrieUpdates)> {
432 Ok((B256::default(), TrieUpdates::default()))
433 }
434}
435
436impl<C: Send + Sync, N: NodePrimitives> StorageRootProvider for NoopProvider<C, N> {
437 fn storage_root(
438 &self,
439 _address: Address,
440 _hashed_storage: HashedStorage,
441 ) -> ProviderResult<B256> {
442 Ok(B256::default())
443 }
444
445 fn storage_proof(
446 &self,
447 _address: Address,
448 slot: B256,
449 _hashed_storage: HashedStorage,
450 ) -> ProviderResult<StorageProof> {
451 Ok(StorageProof::new(slot))
452 }
453
454 fn storage_multiproof(
455 &self,
456 _address: Address,
457 _slots: &[B256],
458 _hashed_storage: HashedStorage,
459 ) -> ProviderResult<StorageMultiProof> {
460 Ok(StorageMultiProof::empty())
461 }
462}
463
464impl<C: Send + Sync, N: NodePrimitives> StateProofProvider for NoopProvider<C, N> {
465 fn proof(
466 &self,
467 _input: TrieInput,
468 address: Address,
469 _slots: &[B256],
470 ) -> ProviderResult<AccountProof> {
471 Ok(AccountProof::new(address))
472 }
473
474 fn multiproof(
475 &self,
476 _input: TrieInput,
477 _targets: MultiProofTargets,
478 ) -> ProviderResult<MultiProof> {
479 Ok(MultiProof::default())
480 }
481
482 fn witness(&self, _input: TrieInput, _target: HashedPostState) -> ProviderResult<Vec<Bytes>> {
483 Ok(Vec::default())
484 }
485}
486
487impl<C: Send + Sync, N: NodePrimitives> HashedPostStateProvider for NoopProvider<C, N> {
488 fn hashed_post_state(&self, _bundle_state: &revm_database::BundleState) -> HashedPostState {
489 HashedPostState::default()
490 }
491}
492
493impl<C: Send + Sync, N: NodePrimitives> StateReader for NoopProvider<C, N> {
494 type Receipt = N::Receipt;
495
496 fn get_state(
497 &self,
498 _block: BlockNumber,
499 ) -> ProviderResult<Option<ExecutionOutcome<Self::Receipt>>> {
500 Ok(None)
501 }
502}
503
504impl<C: Send + Sync, N: NodePrimitives> StateProvider for NoopProvider<C, N> {
505 fn storage(
506 &self,
507 _account: Address,
508 _storage_key: StorageKey,
509 ) -> ProviderResult<Option<StorageValue>> {
510 Ok(None)
511 }
512}
513
514impl<C: Send + Sync, N: NodePrimitives> BytecodeReader for NoopProvider<C, N> {
515 fn bytecode_by_hash(&self, _code_hash: &B256) -> ProviderResult<Option<Bytecode>> {
516 Ok(None)
517 }
518}
519
520impl<C: Send + Sync + 'static, N: NodePrimitives> StateProviderFactory for NoopProvider<C, N> {
521 fn latest(&self) -> ProviderResult<StateProviderBox> {
522 Ok(Box::new(self.clone()))
523 }
524
525 fn state_by_block_number_or_tag(
526 &self,
527 number_or_tag: BlockNumberOrTag,
528 ) -> ProviderResult<StateProviderBox> {
529 match number_or_tag {
530 BlockNumberOrTag::Latest => self.latest(),
531 BlockNumberOrTag::Finalized => {
532 let hash =
534 self.finalized_block_hash()?.ok_or(ProviderError::FinalizedBlockNotFound)?;
535
536 self.history_by_block_hash(hash)
538 }
539 BlockNumberOrTag::Safe => {
540 let hash = self.safe_block_hash()?.ok_or(ProviderError::SafeBlockNotFound)?;
542
543 self.history_by_block_hash(hash)
544 }
545 BlockNumberOrTag::Earliest => {
546 self.history_by_block_number(self.earliest_block_number()?)
547 }
548 BlockNumberOrTag::Pending => self.pending(),
549 BlockNumberOrTag::Number(num) => self.history_by_block_number(num),
550 }
551 }
552
553 fn history_by_block_number(&self, _block: BlockNumber) -> ProviderResult<StateProviderBox> {
554 Ok(Box::new(self.clone()))
555 }
556
557 fn history_by_block_hash(&self, _block: BlockHash) -> ProviderResult<StateProviderBox> {
558 Ok(Box::new(self.clone()))
559 }
560
561 fn state_by_block_hash(&self, _block: BlockHash) -> ProviderResult<StateProviderBox> {
562 Ok(Box::new(self.clone()))
563 }
564
565 fn pending(&self) -> ProviderResult<StateProviderBox> {
566 Ok(Box::new(self.clone()))
567 }
568
569 fn pending_state_by_hash(&self, _block_hash: B256) -> ProviderResult<Option<StateProviderBox>> {
570 Ok(Some(Box::new(self.clone())))
571 }
572
573 fn maybe_pending(&self) -> ProviderResult<Option<StateProviderBox>> {
574 Ok(Some(Box::new(self.clone())))
575 }
576}
577
578impl<C: Send + Sync, N: NodePrimitives> StageCheckpointReader for NoopProvider<C, N> {
579 fn get_stage_checkpoint(&self, _id: StageId) -> ProviderResult<Option<StageCheckpoint>> {
580 Ok(None)
581 }
582
583 fn get_stage_checkpoint_progress(&self, _id: StageId) -> ProviderResult<Option<Vec<u8>>> {
584 Ok(None)
585 }
586
587 fn get_all_checkpoints(&self) -> ProviderResult<Vec<(String, StageCheckpoint)>> {
588 Ok(Vec::new())
589 }
590}
591
592impl<C: Send + Sync, N: NodePrimitives> PruneCheckpointReader for NoopProvider<C, N> {
593 fn get_prune_checkpoint(
594 &self,
595 _segment: PruneSegment,
596 ) -> ProviderResult<Option<PruneCheckpoint>> {
597 Ok(None)
598 }
599
600 fn get_prune_checkpoints(&self) -> ProviderResult<Vec<(PruneSegment, PruneCheckpoint)>> {
601 Ok(Vec::new())
602 }
603}
604
605impl<C: Send + Sync, N: NodePrimitives> NodePrimitivesProvider for NoopProvider<C, N> {
606 type Primitives = N;
607}
608
609impl<C: Send + Sync, N: Send + Sync> BlockBodyIndicesProvider for NoopProvider<C, N> {
610 fn block_body_indices(&self, _num: u64) -> ProviderResult<Option<StoredBlockBodyIndices>> {
611 Ok(None)
612 }
613
614 fn block_body_indices_range(
615 &self,
616 _range: RangeInclusive<BlockNumber>,
617 ) -> ProviderResult<Vec<StoredBlockBodyIndices>> {
618 Ok(Vec::new())
619 }
620}
621
622#[cfg(feature = "db-api")]
623impl<ChainSpec: Send + Sync, N: NodePrimitives> DBProvider for NoopProvider<ChainSpec, N> {
624 type Tx = TxMock;
625
626 fn tx_ref(&self) -> &Self::Tx {
627 &self.tx
628 }
629
630 fn tx_mut(&mut self) -> &mut Self::Tx {
631 &mut self.tx
632 }
633
634 fn into_tx(self) -> Self::Tx {
635 self.tx
636 }
637
638 fn prune_modes_ref(&self) -> &PruneModes {
639 &self.prune_modes
640 }
641
642 fn commit(self) -> ProviderResult<bool> {
643 use reth_db_api::transaction::DbTx;
644
645 Ok(self.tx.commit()?)
646 }
647}
648
649#[cfg(feature = "db-api")]
650impl<ChainSpec: Send + Sync, N: NodePrimitives> DatabaseProviderFactory
651 for NoopProvider<ChainSpec, N>
652{
653 type DB = DatabaseMock;
654 type Provider = Self;
655 type ProviderRW = Self;
656
657 fn database_provider_ro(&self) -> ProviderResult<Self::Provider> {
658 Ok(self.clone())
659 }
660
661 fn database_provider_rw(&self) -> ProviderResult<Self::ProviderRW> {
662 Ok(self.clone())
663 }
664}