1use crate::{
2 traits::{BlockSource, ReceiptProvider},
3 AccountReader, BlockHashReader, BlockIdReader, BlockNumReader, BlockReader, BlockReaderIdExt,
4 ChainSpecProvider, ChangeSetReader, EthStorage, HeaderProvider, ReceiptProviderIdExt,
5 StateProvider, StateProviderBox, StateProviderFactory, StateReader, StateRootProvider,
6 TransactionVariant, TransactionsProvider, WithdrawalsProvider,
7};
8use alloy_consensus::{
9 constants::EMPTY_ROOT_HASH, transaction::TransactionMeta, Header, Transaction,
10};
11use alloy_eips::{eip4895::Withdrawals, BlockHashOrNumber, BlockId, BlockNumberOrTag};
12use alloy_primitives::{
13 keccak256, map::HashMap, Address, BlockHash, BlockNumber, Bytes, StorageKey, StorageValue,
14 TxHash, TxNumber, B256, U256,
15};
16use parking_lot::Mutex;
17use reth_chain_state::{CanonStateNotifications, CanonStateSubscriptions};
18use reth_chainspec::{ChainInfo, EthChainSpec};
19use reth_db_api::{
20 mock::{DatabaseMock, TxMock},
21 models::{AccountBeforeTx, StoredBlockBodyIndices},
22};
23use reth_execution_types::ExecutionOutcome;
24use reth_node_types::NodeTypes;
25use reth_primitives::{
26 Account, Block, Bytecode, EthPrimitives, GotExpected, Receipt, RecoveredBlock, SealedBlock,
27 SealedHeader, TransactionSigned,
28};
29use reth_primitives_traits::SignedTransaction;
30use reth_prune_types::PruneModes;
31use reth_stages_types::{StageCheckpoint, StageId};
32use reth_storage_api::{
33 BlockBodyIndicesProvider, DBProvider, DatabaseProviderFactory, HashedPostStateProvider,
34 NodePrimitivesProvider, OmmersProvider, StageCheckpointReader, StateCommitmentProvider,
35 StateProofProvider, StorageRootProvider,
36};
37use reth_storage_errors::provider::{ConsistentViewError, ProviderError, ProviderResult};
38use reth_trie::{
39 updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof,
40 MultiProofTargets, StorageMultiProof, StorageProof, TrieInput,
41};
42use reth_trie_db::MerklePatriciaTrie;
43use std::{
44 collections::BTreeMap,
45 ops::{RangeBounds, RangeInclusive},
46 sync::Arc,
47};
48use tokio::sync::broadcast;
49
50#[derive(Debug)]
52pub struct MockEthProvider<T = TransactionSigned, ChainSpec = reth_chainspec::ChainSpec> {
53 pub blocks: Arc<Mutex<HashMap<B256, Block<T>>>>,
55 pub headers: Arc<Mutex<HashMap<B256, Header>>>,
57 pub accounts: Arc<Mutex<HashMap<Address, ExtendedAccount>>>,
59 pub chain_spec: Arc<ChainSpec>,
61 pub state_roots: Arc<Mutex<Vec<B256>>>,
63 tx: TxMock,
64 prune_modes: Arc<PruneModes>,
65}
66
67impl<T, ChainSpec> Clone for MockEthProvider<T, ChainSpec> {
68 fn clone(&self) -> Self {
69 Self {
70 blocks: self.blocks.clone(),
71 headers: self.headers.clone(),
72 accounts: self.accounts.clone(),
73 chain_spec: self.chain_spec.clone(),
74 state_roots: self.state_roots.clone(),
75 tx: self.tx.clone(),
76 prune_modes: self.prune_modes.clone(),
77 }
78 }
79}
80
81impl<T> MockEthProvider<T> {
82 pub fn new() -> Self {
84 Self {
85 blocks: Default::default(),
86 headers: Default::default(),
87 accounts: Default::default(),
88 chain_spec: Arc::new(reth_chainspec::ChainSpecBuilder::mainnet().build()),
89 state_roots: Default::default(),
90 tx: Default::default(),
91 prune_modes: Default::default(),
92 }
93 }
94}
95
96impl<T, ChainSpec> MockEthProvider<T, ChainSpec> {
97 pub fn add_block(&self, hash: B256, block: Block<T>) {
99 self.add_header(hash, block.header.clone());
100 self.blocks.lock().insert(hash, block);
101 }
102
103 pub fn extend_blocks(&self, iter: impl IntoIterator<Item = (B256, Block<T>)>) {
105 for (hash, block) in iter {
106 self.add_header(hash, block.header.clone());
107 self.add_block(hash, block)
108 }
109 }
110
111 pub fn add_header(&self, hash: B256, header: Header) {
113 self.headers.lock().insert(hash, header);
114 }
115
116 pub fn extend_headers(&self, iter: impl IntoIterator<Item = (B256, Header)>) {
118 for (hash, header) in iter {
119 self.add_header(hash, header)
120 }
121 }
122
123 pub fn add_account(&self, address: Address, account: ExtendedAccount) {
125 self.accounts.lock().insert(address, account);
126 }
127
128 pub fn extend_accounts(&self, iter: impl IntoIterator<Item = (Address, ExtendedAccount)>) {
130 for (address, account) in iter {
131 self.add_account(address, account)
132 }
133 }
134
135 pub fn add_state_root(&self, state_root: B256) {
137 self.state_roots.lock().push(state_root);
138 }
139
140 pub fn with_chain_spec<C>(self, chain_spec: C) -> MockEthProvider<T, C> {
142 MockEthProvider {
143 blocks: self.blocks,
144 headers: self.headers,
145 accounts: self.accounts,
146 chain_spec: Arc::new(chain_spec),
147 state_roots: self.state_roots,
148 tx: self.tx,
149 prune_modes: self.prune_modes,
150 }
151 }
152}
153
154impl Default for MockEthProvider {
155 fn default() -> Self {
156 Self::new()
157 }
158}
159
160#[derive(Debug, Clone)]
162pub struct ExtendedAccount {
163 account: Account,
164 bytecode: Option<Bytecode>,
165 storage: HashMap<StorageKey, StorageValue>,
166}
167
168impl ExtendedAccount {
169 pub fn new(nonce: u64, balance: U256) -> Self {
171 Self {
172 account: Account { nonce, balance, bytecode_hash: None },
173 bytecode: None,
174 storage: Default::default(),
175 }
176 }
177
178 pub fn with_bytecode(mut self, bytecode: Bytes) -> Self {
180 let hash = keccak256(&bytecode);
181 self.account.bytecode_hash = Some(hash);
182 self.bytecode = Some(Bytecode::new_raw(bytecode));
183 self
184 }
185
186 pub fn extend_storage(
189 mut self,
190 storage: impl IntoIterator<Item = (StorageKey, StorageValue)>,
191 ) -> Self {
192 self.storage.extend(storage);
193 self
194 }
195}
196
197#[derive(Debug)]
199pub struct MockNode;
200
201impl NodeTypes for MockNode {
202 type Primitives = EthPrimitives;
203 type ChainSpec = reth_chainspec::ChainSpec;
204 type StateCommitment = MerklePatriciaTrie;
205 type Storage = EthStorage;
206}
207
208impl<T: Transaction, ChainSpec: EthChainSpec> StateCommitmentProvider
209 for MockEthProvider<T, ChainSpec>
210{
211 type StateCommitment = <MockNode as NodeTypes>::StateCommitment;
212}
213
214impl<T: Transaction, ChainSpec: EthChainSpec + Clone + 'static> DatabaseProviderFactory
215 for MockEthProvider<T, ChainSpec>
216{
217 type DB = DatabaseMock;
218 type Provider = Self;
219 type ProviderRW = Self;
220
221 fn database_provider_ro(&self) -> ProviderResult<Self::Provider> {
222 Err(ConsistentViewError::Syncing { best_block: GotExpected::new(0, 0) }.into())
226 }
227
228 fn database_provider_rw(&self) -> ProviderResult<Self::ProviderRW> {
229 Err(ConsistentViewError::Syncing { best_block: GotExpected::new(0, 0) }.into())
233 }
234}
235
236impl<T: Transaction, ChainSpec: EthChainSpec + 'static> DBProvider
237 for MockEthProvider<T, ChainSpec>
238{
239 type Tx = TxMock;
240
241 fn tx_ref(&self) -> &Self::Tx {
242 &self.tx
243 }
244
245 fn tx_mut(&mut self) -> &mut Self::Tx {
246 &mut self.tx
247 }
248
249 fn into_tx(self) -> Self::Tx {
250 self.tx
251 }
252
253 fn prune_modes_ref(&self) -> &PruneModes {
254 &self.prune_modes
255 }
256}
257
258impl<T: Transaction, ChainSpec: EthChainSpec> HeaderProvider for MockEthProvider<T, ChainSpec> {
259 type Header = Header;
260
261 fn header(&self, block_hash: &BlockHash) -> ProviderResult<Option<Header>> {
262 let lock = self.headers.lock();
263 Ok(lock.get(block_hash).cloned())
264 }
265
266 fn header_by_number(&self, num: u64) -> ProviderResult<Option<Header>> {
267 let lock = self.headers.lock();
268 Ok(lock.values().find(|h| h.number == num).cloned())
269 }
270
271 fn header_td(&self, hash: &BlockHash) -> ProviderResult<Option<U256>> {
272 let lock = self.headers.lock();
273 Ok(lock.get(hash).map(|target| {
274 lock.values()
275 .filter(|h| h.number < target.number)
276 .fold(target.difficulty, |td, h| td + h.difficulty)
277 }))
278 }
279
280 fn header_td_by_number(&self, number: BlockNumber) -> ProviderResult<Option<U256>> {
281 let lock = self.headers.lock();
282 let sum = lock
283 .values()
284 .filter(|h| h.number <= number)
285 .fold(U256::ZERO, |td, h| td + h.difficulty);
286 Ok(Some(sum))
287 }
288
289 fn headers_range(&self, range: impl RangeBounds<BlockNumber>) -> ProviderResult<Vec<Header>> {
290 let lock = self.headers.lock();
291
292 let mut headers: Vec<_> =
293 lock.values().filter(|header| range.contains(&header.number)).cloned().collect();
294 headers.sort_by_key(|header| header.number);
295
296 Ok(headers)
297 }
298
299 fn sealed_header(&self, number: BlockNumber) -> ProviderResult<Option<SealedHeader>> {
300 Ok(self.header_by_number(number)?.map(SealedHeader::seal_slow))
301 }
302
303 fn sealed_headers_while(
304 &self,
305 range: impl RangeBounds<BlockNumber>,
306 mut predicate: impl FnMut(&SealedHeader) -> bool,
307 ) -> ProviderResult<Vec<SealedHeader>> {
308 Ok(self
309 .headers_range(range)?
310 .into_iter()
311 .map(SealedHeader::seal_slow)
312 .take_while(|h| predicate(h))
313 .collect())
314 }
315}
316
317impl<T: Transaction, ChainSpec: EthChainSpec + 'static> ChainSpecProvider
318 for MockEthProvider<T, ChainSpec>
319{
320 type ChainSpec = ChainSpec;
321
322 fn chain_spec(&self) -> Arc<ChainSpec> {
323 self.chain_spec.clone()
324 }
325}
326
327impl<T: SignedTransaction, ChainSpec: EthChainSpec> TransactionsProvider
328 for MockEthProvider<T, ChainSpec>
329{
330 type Transaction = T;
331
332 fn transaction_id(&self, tx_hash: TxHash) -> ProviderResult<Option<TxNumber>> {
333 let lock = self.blocks.lock();
334 let tx_number = lock
335 .values()
336 .flat_map(|block| &block.body.transactions)
337 .position(|tx| *tx.tx_hash() == tx_hash)
338 .map(|pos| pos as TxNumber);
339
340 Ok(tx_number)
341 }
342
343 fn transaction_by_id(&self, id: TxNumber) -> ProviderResult<Option<Self::Transaction>> {
344 let lock = self.blocks.lock();
345 let transaction =
346 lock.values().flat_map(|block| &block.body.transactions).nth(id as usize).cloned();
347
348 Ok(transaction)
349 }
350
351 fn transaction_by_id_unhashed(
352 &self,
353 id: TxNumber,
354 ) -> ProviderResult<Option<Self::Transaction>> {
355 let lock = self.blocks.lock();
356 let transaction =
357 lock.values().flat_map(|block| &block.body.transactions).nth(id as usize).cloned();
358
359 Ok(transaction)
360 }
361
362 fn transaction_by_hash(&self, hash: TxHash) -> ProviderResult<Option<Self::Transaction>> {
363 Ok(self.blocks.lock().iter().find_map(|(_, block)| {
364 block.body.transactions.iter().find(|tx| *tx.tx_hash() == hash).cloned()
365 }))
366 }
367
368 fn transaction_by_hash_with_meta(
369 &self,
370 hash: TxHash,
371 ) -> ProviderResult<Option<(Self::Transaction, TransactionMeta)>> {
372 let lock = self.blocks.lock();
373 for (block_hash, block) in lock.iter() {
374 for (index, tx) in block.body.transactions.iter().enumerate() {
375 if *tx.tx_hash() == hash {
376 let meta = TransactionMeta {
377 tx_hash: hash,
378 index: index as u64,
379 block_hash: *block_hash,
380 block_number: block.header.number,
381 base_fee: block.header.base_fee_per_gas,
382 excess_blob_gas: block.header.excess_blob_gas,
383 timestamp: block.header.timestamp,
384 };
385 return Ok(Some((tx.clone(), meta)))
386 }
387 }
388 }
389 Ok(None)
390 }
391
392 fn transaction_block(&self, id: TxNumber) -> ProviderResult<Option<BlockNumber>> {
393 let lock = self.blocks.lock();
394 let mut current_tx_number: TxNumber = 0;
395 for block in lock.values() {
396 if current_tx_number + (block.body.transactions.len() as TxNumber) > id {
397 return Ok(Some(block.header.number))
398 }
399 current_tx_number += block.body.transactions.len() as TxNumber;
400 }
401 Ok(None)
402 }
403
404 fn transactions_by_block(
405 &self,
406 id: BlockHashOrNumber,
407 ) -> ProviderResult<Option<Vec<Self::Transaction>>> {
408 Ok(self.block(id)?.map(|b| b.body.transactions))
409 }
410
411 fn transactions_by_block_range(
412 &self,
413 range: impl RangeBounds<alloy_primitives::BlockNumber>,
414 ) -> ProviderResult<Vec<Vec<Self::Transaction>>> {
415 let mut map = BTreeMap::new();
417 for (_, block) in self.blocks.lock().iter() {
418 if range.contains(&block.number) {
419 map.insert(block.number, block.body.transactions.clone());
420 }
421 }
422
423 Ok(map.into_values().collect())
424 }
425
426 fn transactions_by_tx_range(
427 &self,
428 range: impl RangeBounds<TxNumber>,
429 ) -> ProviderResult<Vec<Self::Transaction>> {
430 let lock = self.blocks.lock();
431 let transactions = lock
432 .values()
433 .flat_map(|block| &block.body.transactions)
434 .enumerate()
435 .filter(|&(tx_number, _)| range.contains(&(tx_number as TxNumber)))
436 .map(|(_, tx)| tx.clone())
437 .collect();
438
439 Ok(transactions)
440 }
441
442 fn senders_by_tx_range(
443 &self,
444 range: impl RangeBounds<TxNumber>,
445 ) -> ProviderResult<Vec<Address>> {
446 let lock = self.blocks.lock();
447 let transactions = lock
448 .values()
449 .flat_map(|block| &block.body.transactions)
450 .enumerate()
451 .filter_map(|(tx_number, tx)| {
452 if range.contains(&(tx_number as TxNumber)) {
453 tx.recover_signer().ok()
454 } else {
455 None
456 }
457 })
458 .collect();
459
460 Ok(transactions)
461 }
462
463 fn transaction_sender(&self, id: TxNumber) -> ProviderResult<Option<Address>> {
464 self.transaction_by_id(id).map(|tx_option| tx_option.map(|tx| tx.recover_signer().unwrap()))
465 }
466}
467
468impl<T: Transaction, ChainSpec: EthChainSpec> ReceiptProvider for MockEthProvider<T, ChainSpec> {
469 type Receipt = Receipt;
470
471 fn receipt(&self, _id: TxNumber) -> ProviderResult<Option<Receipt>> {
472 Ok(None)
473 }
474
475 fn receipt_by_hash(&self, _hash: TxHash) -> ProviderResult<Option<Receipt>> {
476 Ok(None)
477 }
478
479 fn receipts_by_block(&self, _block: BlockHashOrNumber) -> ProviderResult<Option<Vec<Receipt>>> {
480 Ok(None)
481 }
482
483 fn receipts_by_tx_range(
484 &self,
485 _range: impl RangeBounds<TxNumber>,
486 ) -> ProviderResult<Vec<Receipt>> {
487 Ok(vec![])
488 }
489}
490
491impl<T: Transaction, ChainSpec: EthChainSpec> ReceiptProviderIdExt
492 for MockEthProvider<T, ChainSpec>
493{
494}
495
496impl<T: Transaction, ChainSpec: EthChainSpec> BlockHashReader for MockEthProvider<T, ChainSpec> {
497 fn block_hash(&self, number: u64) -> ProviderResult<Option<B256>> {
498 let lock = self.blocks.lock();
499
500 let hash = lock.iter().find_map(|(hash, b)| (b.number == number).then_some(*hash));
501 Ok(hash)
502 }
503
504 fn canonical_hashes_range(
505 &self,
506 start: BlockNumber,
507 end: BlockNumber,
508 ) -> ProviderResult<Vec<B256>> {
509 let range = start..end;
510 let lock = self.blocks.lock();
511
512 let mut hashes: Vec<_> =
513 lock.iter().filter(|(_, block)| range.contains(&block.number)).collect();
514 hashes.sort_by_key(|(_, block)| block.number);
515
516 Ok(hashes.into_iter().map(|(hash, _)| *hash).collect())
517 }
518}
519
520impl<T: Transaction, ChainSpec: EthChainSpec> BlockNumReader for MockEthProvider<T, ChainSpec> {
521 fn chain_info(&self) -> ProviderResult<ChainInfo> {
522 let best_block_number = self.best_block_number()?;
523 let lock = self.headers.lock();
524
525 Ok(lock
526 .iter()
527 .find(|(_, header)| header.number == best_block_number)
528 .map(|(hash, header)| ChainInfo { best_hash: *hash, best_number: header.number })
529 .unwrap_or_default())
530 }
531
532 fn best_block_number(&self) -> ProviderResult<BlockNumber> {
533 let lock = self.headers.lock();
534 lock.iter()
535 .max_by_key(|h| h.1.number)
536 .map(|(_, header)| header.number)
537 .ok_or(ProviderError::BestBlockNotFound)
538 }
539
540 fn last_block_number(&self) -> ProviderResult<BlockNumber> {
541 self.best_block_number()
542 }
543
544 fn block_number(&self, hash: B256) -> ProviderResult<Option<alloy_primitives::BlockNumber>> {
545 let lock = self.blocks.lock();
546 let num = lock.iter().find_map(|(h, b)| (*h == hash).then_some(b.number));
547 Ok(num)
548 }
549}
550
551impl<T: Transaction, ChainSpec: EthChainSpec> BlockIdReader for MockEthProvider<T, ChainSpec> {
552 fn pending_block_num_hash(&self) -> ProviderResult<Option<alloy_eips::BlockNumHash>> {
553 Ok(None)
554 }
555
556 fn safe_block_num_hash(&self) -> ProviderResult<Option<alloy_eips::BlockNumHash>> {
557 Ok(None)
558 }
559
560 fn finalized_block_num_hash(&self) -> ProviderResult<Option<alloy_eips::BlockNumHash>> {
561 Ok(None)
562 }
563}
564
565impl<T: SignedTransaction, ChainSpec: EthChainSpec> BlockReader for MockEthProvider<T, ChainSpec> {
566 type Block = Block<T>;
567
568 fn find_block_by_hash(
569 &self,
570 hash: B256,
571 _source: BlockSource,
572 ) -> ProviderResult<Option<Self::Block>> {
573 self.block(hash.into())
574 }
575
576 fn block(&self, id: BlockHashOrNumber) -> ProviderResult<Option<Self::Block>> {
577 let lock = self.blocks.lock();
578 match id {
579 BlockHashOrNumber::Hash(hash) => Ok(lock.get(&hash).cloned()),
580 BlockHashOrNumber::Number(num) => Ok(lock.values().find(|b| b.number == num).cloned()),
581 }
582 }
583
584 fn pending_block(&self) -> ProviderResult<Option<SealedBlock<Self::Block>>> {
585 Ok(None)
586 }
587
588 fn pending_block_with_senders(&self) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
589 Ok(None)
590 }
591
592 fn pending_block_and_receipts(
593 &self,
594 ) -> ProviderResult<Option<(SealedBlock<Self::Block>, Vec<Receipt>)>> {
595 Ok(None)
596 }
597
598 fn recovered_block(
599 &self,
600 _id: BlockHashOrNumber,
601 _transaction_kind: TransactionVariant,
602 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
603 Ok(None)
604 }
605
606 fn sealed_block_with_senders(
607 &self,
608 _id: BlockHashOrNumber,
609 _transaction_kind: TransactionVariant,
610 ) -> ProviderResult<Option<RecoveredBlock<Self::Block>>> {
611 Ok(None)
612 }
613
614 fn block_range(&self, range: RangeInclusive<BlockNumber>) -> ProviderResult<Vec<Self::Block>> {
615 let lock = self.blocks.lock();
616
617 let mut blocks: Vec<_> =
618 lock.values().filter(|block| range.contains(&block.number)).cloned().collect();
619 blocks.sort_by_key(|block| block.number);
620
621 Ok(blocks)
622 }
623
624 fn block_with_senders_range(
625 &self,
626 _range: RangeInclusive<BlockNumber>,
627 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
628 Ok(vec![])
629 }
630
631 fn recovered_block_range(
632 &self,
633 _range: RangeInclusive<BlockNumber>,
634 ) -> ProviderResult<Vec<RecoveredBlock<Self::Block>>> {
635 Ok(vec![])
636 }
637}
638
639impl<T: SignedTransaction, ChainSpec: EthChainSpec> BlockReaderIdExt
640 for MockEthProvider<T, ChainSpec>
641{
642 fn block_by_id(&self, id: BlockId) -> ProviderResult<Option<Block<T>>> {
643 match id {
644 BlockId::Number(num) => self.block_by_number_or_tag(num),
645 BlockId::Hash(hash) => self.block_by_hash(hash.block_hash),
646 }
647 }
648
649 fn sealed_header_by_id(&self, id: BlockId) -> ProviderResult<Option<SealedHeader>> {
650 self.header_by_id(id)?.map_or_else(|| Ok(None), |h| Ok(Some(SealedHeader::seal_slow(h))))
651 }
652
653 fn header_by_id(&self, id: BlockId) -> ProviderResult<Option<Header>> {
654 match self.block_by_id(id)? {
655 None => Ok(None),
656 Some(block) => Ok(Some(block.header)),
657 }
658 }
659
660 fn ommers_by_id(&self, id: BlockId) -> ProviderResult<Option<Vec<Header>>> {
661 match id {
662 BlockId::Number(num) => self.ommers_by_number_or_tag(num),
663 BlockId::Hash(hash) => self.ommers(BlockHashOrNumber::Hash(hash.block_hash)),
664 }
665 }
666}
667
668impl<T: Transaction, ChainSpec: EthChainSpec> AccountReader for MockEthProvider<T, ChainSpec> {
669 fn basic_account(&self, address: &Address) -> ProviderResult<Option<Account>> {
670 Ok(self.accounts.lock().get(address).cloned().map(|a| a.account))
671 }
672}
673
674impl<T: Transaction, ChainSpec: EthChainSpec> StageCheckpointReader
675 for MockEthProvider<T, ChainSpec>
676{
677 fn get_stage_checkpoint(&self, _id: StageId) -> ProviderResult<Option<StageCheckpoint>> {
678 Ok(None)
679 }
680
681 fn get_stage_checkpoint_progress(&self, _id: StageId) -> ProviderResult<Option<Vec<u8>>> {
682 Ok(None)
683 }
684
685 fn get_all_checkpoints(&self) -> ProviderResult<Vec<(String, StageCheckpoint)>> {
686 Ok(vec![])
687 }
688}
689
690impl<T: Transaction, ChainSpec: EthChainSpec> StateRootProvider for MockEthProvider<T, ChainSpec> {
691 fn state_root(&self, _state: HashedPostState) -> ProviderResult<B256> {
692 Ok(self.state_roots.lock().pop().unwrap_or_default())
693 }
694
695 fn state_root_from_nodes(&self, _input: TrieInput) -> ProviderResult<B256> {
696 Ok(self.state_roots.lock().pop().unwrap_or_default())
697 }
698
699 fn state_root_with_updates(
700 &self,
701 _state: HashedPostState,
702 ) -> ProviderResult<(B256, TrieUpdates)> {
703 let state_root = self.state_roots.lock().pop().unwrap_or_default();
704 Ok((state_root, Default::default()))
705 }
706
707 fn state_root_from_nodes_with_updates(
708 &self,
709 _input: TrieInput,
710 ) -> ProviderResult<(B256, TrieUpdates)> {
711 let state_root = self.state_roots.lock().pop().unwrap_or_default();
712 Ok((state_root, Default::default()))
713 }
714}
715
716impl<T: Transaction, ChainSpec: EthChainSpec> StorageRootProvider
717 for MockEthProvider<T, ChainSpec>
718{
719 fn storage_root(
720 &self,
721 _address: Address,
722 _hashed_storage: HashedStorage,
723 ) -> ProviderResult<B256> {
724 Ok(EMPTY_ROOT_HASH)
725 }
726
727 fn storage_proof(
728 &self,
729 _address: Address,
730 slot: B256,
731 _hashed_storage: HashedStorage,
732 ) -> ProviderResult<reth_trie::StorageProof> {
733 Ok(StorageProof::new(slot))
734 }
735
736 fn storage_multiproof(
737 &self,
738 _address: Address,
739 _slots: &[B256],
740 _hashed_storage: HashedStorage,
741 ) -> ProviderResult<StorageMultiProof> {
742 Ok(StorageMultiProof::empty())
743 }
744}
745
746impl<T: Transaction, ChainSpec: EthChainSpec> StateProofProvider for MockEthProvider<T, ChainSpec> {
747 fn proof(
748 &self,
749 _input: TrieInput,
750 address: Address,
751 _slots: &[B256],
752 ) -> ProviderResult<AccountProof> {
753 Ok(AccountProof::new(address))
754 }
755
756 fn multiproof(
757 &self,
758 _input: TrieInput,
759 _targets: MultiProofTargets,
760 ) -> ProviderResult<MultiProof> {
761 Ok(MultiProof::default())
762 }
763
764 fn witness(&self, _input: TrieInput, _target: HashedPostState) -> ProviderResult<Vec<Bytes>> {
765 Ok(Vec::default())
766 }
767}
768
769impl<T: Transaction, ChainSpec: EthChainSpec + 'static> HashedPostStateProvider
770 for MockEthProvider<T, ChainSpec>
771{
772 fn hashed_post_state(&self, _state: &revm_database::BundleState) -> HashedPostState {
773 HashedPostState::default()
774 }
775}
776
777impl<T: Transaction, ChainSpec: EthChainSpec + 'static> StateProvider
778 for MockEthProvider<T, ChainSpec>
779{
780 fn storage(
781 &self,
782 account: Address,
783 storage_key: StorageKey,
784 ) -> ProviderResult<Option<StorageValue>> {
785 let lock = self.accounts.lock();
786 Ok(lock.get(&account).and_then(|account| account.storage.get(&storage_key)).copied())
787 }
788
789 fn bytecode_by_hash(&self, code_hash: &B256) -> ProviderResult<Option<Bytecode>> {
790 let lock = self.accounts.lock();
791 Ok(lock.values().find_map(|account| {
792 match (account.account.bytecode_hash.as_ref(), account.bytecode.as_ref()) {
793 (Some(bytecode_hash), Some(bytecode)) if bytecode_hash == code_hash => {
794 Some(bytecode.clone())
795 }
796 _ => None,
797 }
798 }))
799 }
800}
801
802impl<T: SignedTransaction, ChainSpec: EthChainSpec + 'static> StateProviderFactory
803 for MockEthProvider<T, ChainSpec>
804{
805 fn latest(&self) -> ProviderResult<StateProviderBox> {
806 Ok(Box::new(self.clone()))
807 }
808
809 fn state_by_block_number_or_tag(
810 &self,
811 number_or_tag: BlockNumberOrTag,
812 ) -> ProviderResult<StateProviderBox> {
813 match number_or_tag {
814 BlockNumberOrTag::Latest => self.latest(),
815 BlockNumberOrTag::Finalized => {
816 let hash =
818 self.finalized_block_hash()?.ok_or(ProviderError::FinalizedBlockNotFound)?;
819
820 self.history_by_block_hash(hash)
822 }
823 BlockNumberOrTag::Safe => {
824 let hash = self.safe_block_hash()?.ok_or(ProviderError::SafeBlockNotFound)?;
826
827 self.history_by_block_hash(hash)
828 }
829 BlockNumberOrTag::Earliest => self.history_by_block_number(0),
830 BlockNumberOrTag::Pending => self.pending(),
831 BlockNumberOrTag::Number(num) => self.history_by_block_number(num),
832 }
833 }
834
835 fn history_by_block_number(&self, _block: BlockNumber) -> ProviderResult<StateProviderBox> {
836 Ok(Box::new(self.clone()))
837 }
838
839 fn history_by_block_hash(&self, _block: BlockHash) -> ProviderResult<StateProviderBox> {
840 Ok(Box::new(self.clone()))
841 }
842
843 fn state_by_block_hash(&self, _block: BlockHash) -> ProviderResult<StateProviderBox> {
844 Ok(Box::new(self.clone()))
845 }
846
847 fn pending(&self) -> ProviderResult<StateProviderBox> {
848 Ok(Box::new(self.clone()))
849 }
850
851 fn pending_state_by_hash(&self, _block_hash: B256) -> ProviderResult<Option<StateProviderBox>> {
852 Ok(Some(Box::new(self.clone())))
853 }
854}
855
856impl<T: Transaction, ChainSpec: EthChainSpec> WithdrawalsProvider
857 for MockEthProvider<T, ChainSpec>
858{
859 fn withdrawals_by_block(
860 &self,
861 _id: BlockHashOrNumber,
862 _timestamp: u64,
863 ) -> ProviderResult<Option<Withdrawals>> {
864 Ok(None)
865 }
866}
867
868impl<T: Transaction, ChainSpec: EthChainSpec> OmmersProvider for MockEthProvider<T, ChainSpec> {
869 fn ommers(&self, _id: BlockHashOrNumber) -> ProviderResult<Option<Vec<Header>>> {
870 Ok(None)
871 }
872}
873
874impl<T: Transaction, ChainSpec: EthChainSpec> BlockBodyIndicesProvider
875 for MockEthProvider<T, ChainSpec>
876{
877 fn block_body_indices(&self, _num: u64) -> ProviderResult<Option<StoredBlockBodyIndices>> {
878 Ok(None)
879 }
880 fn block_body_indices_range(
881 &self,
882 _range: RangeInclusive<BlockNumber>,
883 ) -> ProviderResult<Vec<StoredBlockBodyIndices>> {
884 Ok(vec![])
885 }
886}
887
888impl<T: Transaction, ChainSpec: EthChainSpec> ChangeSetReader for MockEthProvider<T, ChainSpec> {
889 fn account_block_changeset(
890 &self,
891 _block_number: BlockNumber,
892 ) -> ProviderResult<Vec<AccountBeforeTx>> {
893 Ok(Vec::default())
894 }
895}
896
897impl<T: Transaction, ChainSpec: EthChainSpec> StateReader for MockEthProvider<T, ChainSpec> {
898 type Receipt = Receipt;
899
900 fn get_state(&self, _block: BlockNumber) -> ProviderResult<Option<ExecutionOutcome>> {
901 Ok(None)
902 }
903}
904
905impl<T: Transaction, ChainSpec: EthChainSpec> CanonStateSubscriptions
906 for MockEthProvider<T, ChainSpec>
907{
908 fn subscribe_to_canonical_state(&self) -> CanonStateNotifications<EthPrimitives> {
909 broadcast::channel(1).1
910 }
911}
912
913impl<T: Transaction, ChainSpec: EthChainSpec> NodePrimitivesProvider
914 for MockEthProvider<T, ChainSpec>
915{
916 type Primitives = EthPrimitives;
917}