1use crate::{
4 CanonStateNotification, CanonStateNotificationSender, CanonStateNotifications,
5 ChainInfoTracker, ComputedTrieData, DeferredTrieData, MemoryOverlayStateProvider,
6};
7use alloy_consensus::{transaction::TransactionMeta, BlockHeader};
8use alloy_eips::{BlockHashOrNumber, BlockNumHash};
9use alloy_primitives::{map::B256Map, BlockNumber, TxHash, B256};
10use parking_lot::RwLock;
11use reth_chainspec::ChainInfo;
12use reth_ethereum_primitives::EthPrimitives;
13use reth_execution_types::{BlockExecutionOutput, BlockExecutionResult, Chain, ExecutionOutcome};
14use reth_metrics::{metrics::Gauge, Metrics};
15use reth_primitives_traits::{
16 BlockBody as _, IndexedTx, NodePrimitives, RecoveredBlock, SealedBlock, SealedHeader,
17 SignedTransaction,
18};
19use reth_storage_api::StateProviderBox;
20use reth_trie::{
21 updates::TrieUpdatesSorted, HashedPostStateSorted, LazyTrieData, SortedTrieData,
22 TrieInputSorted,
23};
24use std::{collections::BTreeMap, sync::Arc, time::Instant};
25use tokio::sync::{broadcast, watch};
26
27const CANON_STATE_NOTIFICATION_CHANNEL_SIZE: usize = 256;
29
30#[derive(Metrics)]
32#[metrics(scope = "blockchain_tree.in_mem_state")]
33pub(crate) struct InMemoryStateMetrics {
34 pub(crate) earliest_block: Gauge,
36 pub(crate) latest_block: Gauge,
38 pub(crate) num_blocks: Gauge,
40}
41
42#[derive(Debug, Default)]
58pub(crate) struct InMemoryState<N: NodePrimitives = EthPrimitives> {
59 blocks: RwLock<B256Map<Arc<BlockState<N>>>>,
61 numbers: RwLock<BTreeMap<u64, B256>>,
63 pending: watch::Sender<Option<BlockState<N>>>,
65 metrics: InMemoryStateMetrics,
67}
68
69impl<N: NodePrimitives> InMemoryState<N> {
70 pub(crate) fn new(
71 blocks: B256Map<Arc<BlockState<N>>>,
72 numbers: BTreeMap<u64, B256>,
73 pending: Option<BlockState<N>>,
74 ) -> Self {
75 let (pending, _) = watch::channel(pending);
76 let this = Self {
77 blocks: RwLock::new(blocks),
78 numbers: RwLock::new(numbers),
79 pending,
80 metrics: Default::default(),
81 };
82 this.update_metrics();
83 this
84 }
85
86 pub(crate) fn update_metrics(&self) {
92 let (count, earliest, latest) = {
93 let numbers = self.numbers.read();
94 let count = numbers.len();
95 let earliest = numbers.first_key_value().map(|(number, _)| *number);
96 let latest = numbers.last_key_value().map(|(number, _)| *number);
97 (count, earliest, latest)
98 };
99 if let Some(earliest_block_number) = earliest {
100 self.metrics.earliest_block.set(earliest_block_number as f64);
101 }
102 if let Some(latest_block_number) = latest {
103 self.metrics.latest_block.set(latest_block_number as f64);
104 }
105 self.metrics.num_blocks.set(count as f64);
106 }
107
108 pub(crate) fn state_by_hash(&self, hash: B256) -> Option<Arc<BlockState<N>>> {
110 self.blocks.read().get(&hash).cloned()
111 }
112
113 pub(crate) fn state_by_number(&self, number: u64) -> Option<Arc<BlockState<N>>> {
115 let hash = self.hash_by_number(number)?;
116 self.state_by_hash(hash)
117 }
118
119 pub(crate) fn hash_by_number(&self, number: u64) -> Option<B256> {
121 self.numbers.read().get(&number).copied()
122 }
123
124 pub(crate) fn head_state(&self) -> Option<Arc<BlockState<N>>> {
126 let hash = *self.numbers.read().last_key_value()?.1;
127 self.state_by_hash(hash)
128 }
129
130 pub(crate) fn pending_state(&self) -> Option<BlockState<N>> {
133 self.pending.borrow().clone()
134 }
135
136 #[cfg(test)]
137 fn block_count(&self) -> usize {
138 self.blocks.read().len()
139 }
140}
141
142#[derive(Debug)]
145pub(crate) struct CanonicalInMemoryStateInner<N: NodePrimitives> {
146 pub(crate) chain_info_tracker: ChainInfoTracker<N>,
149 pub(crate) in_memory_state: InMemoryState<N>,
151 pub(crate) canon_state_notification_sender: CanonStateNotificationSender<N>,
153}
154
155impl<N: NodePrimitives> CanonicalInMemoryStateInner<N> {
156 fn clear(&self) {
158 {
159 let mut numbers = self.in_memory_state.numbers.write();
161 let mut blocks = self.in_memory_state.blocks.write();
162 numbers.clear();
163 blocks.clear();
164 self.in_memory_state.pending.send_modify(|p| {
165 p.take();
166 });
167 }
168 self.in_memory_state.update_metrics();
169 }
170}
171
172type PendingBlockAndReceipts<N> =
173 (RecoveredBlock<<N as NodePrimitives>::Block>, Vec<reth_primitives_traits::ReceiptTy<N>>);
174
175#[derive(Debug, Clone)]
179pub struct CanonicalInMemoryState<N: NodePrimitives = EthPrimitives> {
180 pub(crate) inner: Arc<CanonicalInMemoryStateInner<N>>,
181}
182
183impl<N: NodePrimitives> CanonicalInMemoryState<N> {
184 pub fn new(
187 blocks: B256Map<Arc<BlockState<N>>>,
188 numbers: BTreeMap<u64, B256>,
189 pending: Option<BlockState<N>>,
190 finalized: Option<SealedHeader<N::BlockHeader>>,
191 safe: Option<SealedHeader<N::BlockHeader>>,
192 ) -> Self {
193 let in_memory_state = InMemoryState::new(blocks, numbers, pending);
194 let header = in_memory_state.head_state().map_or_else(SealedHeader::default, |state| {
195 state.block_ref().recovered_block().clone_sealed_header()
196 });
197 let chain_info_tracker = ChainInfoTracker::new(header, finalized, safe);
198 let (canon_state_notification_sender, _) =
199 broadcast::channel(CANON_STATE_NOTIFICATION_CHANNEL_SIZE);
200
201 Self {
202 inner: Arc::new(CanonicalInMemoryStateInner {
203 chain_info_tracker,
204 in_memory_state,
205 canon_state_notification_sender,
206 }),
207 }
208 }
209
210 pub fn empty() -> Self {
212 Self::new(B256Map::default(), BTreeMap::new(), None, None, None)
213 }
214
215 pub fn with_head(
218 head: SealedHeader<N::BlockHeader>,
219 finalized: Option<SealedHeader<N::BlockHeader>>,
220 safe: Option<SealedHeader<N::BlockHeader>>,
221 ) -> Self {
222 let chain_info_tracker = ChainInfoTracker::new(head, finalized, safe);
223 let in_memory_state = InMemoryState::default();
224 let (canon_state_notification_sender, _) =
225 broadcast::channel(CANON_STATE_NOTIFICATION_CHANNEL_SIZE);
226 let inner = CanonicalInMemoryStateInner {
227 chain_info_tracker,
228 in_memory_state,
229 canon_state_notification_sender,
230 };
231
232 Self { inner: Arc::new(inner) }
233 }
234
235 pub fn hash_by_number(&self, number: u64) -> Option<B256> {
237 self.inner.in_memory_state.hash_by_number(number)
238 }
239
240 pub fn header_by_hash(&self, hash: B256) -> Option<SealedHeader<N::BlockHeader>> {
242 self.state_by_hash(hash)
243 .map(|block| block.block_ref().recovered_block().clone_sealed_header())
244 }
245
246 pub fn clear_state(&self) {
248 self.inner.clear()
249 }
250
251 pub fn set_pending_block(&self, pending: ExecutedBlock<N>) {
255 let parent = self.state_by_hash(pending.recovered_block().parent_hash());
257 let pending = BlockState::with_parent(pending, parent);
258 self.inner.in_memory_state.pending.send_modify(|p| {
259 p.replace(pending);
260 });
261 self.inner.in_memory_state.update_metrics();
262 }
263
264 fn update_blocks<I, R>(&self, new_blocks: I, reorged: R)
269 where
270 I: IntoIterator<Item = ExecutedBlock<N>>,
271 R: IntoIterator<Item = ExecutedBlock<N>>,
272 {
273 {
274 let mut numbers = self.inner.in_memory_state.numbers.write();
276 let mut blocks = self.inner.in_memory_state.blocks.write();
277
278 for block in reorged {
280 let hash = block.recovered_block().hash();
281 let number = block.recovered_block().number();
282 blocks.remove(&hash);
283 numbers.remove(&number);
284 }
285
286 for block in new_blocks {
288 let parent = blocks.get(&block.recovered_block().parent_hash()).cloned();
289 let block_state = BlockState::with_parent(block, parent);
290 let hash = block_state.hash();
291 let number = block_state.number();
292
293 blocks.insert(hash, Arc::new(block_state));
295 numbers.insert(number, hash);
296 }
297
298 self.inner.in_memory_state.pending.send_modify(|p| {
300 p.take();
301 });
302 }
303 self.inner.in_memory_state.update_metrics();
304 }
305
306 pub fn update_chain(&self, new_chain: NewCanonicalChain<N>) {
308 match new_chain {
309 NewCanonicalChain::Commit { new } => {
310 self.update_blocks(new, vec![]);
311 }
312 NewCanonicalChain::Reorg { new, old } => {
313 self.update_blocks(new, old);
314 }
315 }
316 }
317
318 pub fn remove_persisted_blocks(&self, persisted_num_hash: BlockNumHash) {
323 self.set_persisted(persisted_num_hash);
324 {
329 if self.inner.in_memory_state.blocks.read().get(&persisted_num_hash.hash).is_none() {
330 return
332 }
333 }
334
335 {
336 let mut numbers = self.inner.in_memory_state.numbers.write();
338 let mut blocks = self.inner.in_memory_state.blocks.write();
339
340 let BlockNumHash { number: persisted_height, hash: _ } = persisted_num_hash;
341
342 numbers.clear();
344
345 let mut old_blocks = blocks
348 .drain()
349 .filter(|(_, b)| b.block_ref().recovered_block().number() > persisted_height)
350 .map(|(_, b)| b.block.clone())
351 .collect::<Vec<_>>();
352
353 old_blocks.sort_unstable_by_key(|block| block.recovered_block().number());
355
356 for block in old_blocks {
358 let parent = blocks.get(&block.recovered_block().parent_hash()).cloned();
359 let block_state = BlockState::with_parent(block, parent);
360 let hash = block_state.hash();
361 let number = block_state.number();
362
363 blocks.insert(hash, Arc::new(block_state));
365 numbers.insert(number, hash);
366 }
367
368 self.inner.in_memory_state.pending.send_modify(|p| {
370 if let Some(p) = p.as_mut() {
371 p.parent = blocks.get(&p.block_ref().recovered_block().parent_hash()).cloned();
372 }
373 });
374 }
375 self.inner.in_memory_state.update_metrics();
376 }
377
378 pub fn state_by_hash(&self, hash: B256) -> Option<Arc<BlockState<N>>> {
380 self.inner.in_memory_state.state_by_hash(hash)
381 }
382
383 pub fn state_by_number(&self, number: u64) -> Option<Arc<BlockState<N>>> {
385 self.inner.in_memory_state.state_by_number(number)
386 }
387
388 pub fn head_state(&self) -> Option<Arc<BlockState<N>>> {
390 self.inner.in_memory_state.head_state()
391 }
392
393 pub fn pending_state(&self) -> Option<BlockState<N>> {
395 self.inner.in_memory_state.pending_state()
396 }
397
398 pub fn pending_block_num_hash(&self) -> Option<BlockNumHash> {
400 self.inner
401 .in_memory_state
402 .pending_state()
403 .map(|state| BlockNumHash { number: state.number(), hash: state.hash() })
404 }
405
406 pub fn chain_info(&self) -> ChainInfo {
408 self.inner.chain_info_tracker.chain_info()
409 }
410
411 pub fn get_canonical_block_number(&self) -> u64 {
413 self.inner.chain_info_tracker.get_canonical_block_number()
414 }
415
416 pub fn get_safe_num_hash(&self) -> Option<BlockNumHash> {
418 self.inner.chain_info_tracker.get_safe_num_hash()
419 }
420
421 pub fn get_finalized_num_hash(&self) -> Option<BlockNumHash> {
423 self.inner.chain_info_tracker.get_finalized_num_hash()
424 }
425
426 pub fn on_forkchoice_update_received(&self) {
428 self.inner.chain_info_tracker.on_forkchoice_update_received();
429 }
430
431 pub fn last_received_update_timestamp(&self) -> Option<Instant> {
433 self.inner.chain_info_tracker.last_forkchoice_update_received_at()
434 }
435
436 pub fn set_canonical_head(&self, header: SealedHeader<N::BlockHeader>) {
438 self.inner.chain_info_tracker.set_canonical_head(header);
439 }
440
441 pub fn set_safe(&self, header: SealedHeader<N::BlockHeader>) {
443 self.inner.chain_info_tracker.set_safe(header);
444 }
445
446 pub fn set_finalized(&self, header: SealedHeader<N::BlockHeader>) {
448 self.inner.chain_info_tracker.set_finalized(header);
449 }
450
451 pub fn set_persisted(&self, num_hash: BlockNumHash) {
453 self.inner.chain_info_tracker.set_persisted(num_hash);
454 }
455
456 pub fn get_canonical_head(&self) -> SealedHeader<N::BlockHeader> {
458 self.inner.chain_info_tracker.get_canonical_head()
459 }
460
461 pub fn get_finalized_header(&self) -> Option<SealedHeader<N::BlockHeader>> {
463 self.inner.chain_info_tracker.get_finalized_header()
464 }
465
466 pub fn get_safe_header(&self) -> Option<SealedHeader<N::BlockHeader>> {
468 self.inner.chain_info_tracker.get_safe_header()
469 }
470
471 pub fn get_persisted_num_hash(&self) -> Option<BlockNumHash> {
473 self.inner.chain_info_tracker.get_persisted_num_hash()
474 }
475
476 pub fn pending_sealed_header(&self) -> Option<SealedHeader<N::BlockHeader>> {
478 self.pending_state().map(|h| h.block_ref().recovered_block().clone_sealed_header())
479 }
480
481 pub fn pending_header(&self) -> Option<N::BlockHeader> {
483 self.pending_sealed_header().map(|sealed_header| sealed_header.unseal())
484 }
485
486 pub fn pending_block(&self) -> Option<SealedBlock<N::Block>> {
488 self.pending_state()
489 .map(|block_state| block_state.block_ref().recovered_block().sealed_block().clone())
490 }
491
492 pub fn pending_recovered_block(&self) -> Option<RecoveredBlock<N::Block>>
494 where
495 N::SignedTx: SignedTransaction,
496 {
497 self.pending_state().map(|block_state| block_state.block_ref().recovered_block().clone())
498 }
499
500 pub fn pending_block_and_receipts(&self) -> Option<PendingBlockAndReceipts<N>> {
503 self.pending_state().map(|block_state| {
504 (
505 block_state.block_ref().recovered_block().clone(),
506 block_state.executed_block_receipts(),
507 )
508 })
509 }
510
511 pub fn subscribe_canon_state(&self) -> CanonStateNotifications<N> {
513 self.inner.canon_state_notification_sender.subscribe()
514 }
515
516 pub fn subscribe_safe_block(&self) -> watch::Receiver<Option<SealedHeader<N::BlockHeader>>> {
518 self.inner.chain_info_tracker.subscribe_safe_block()
519 }
520
521 pub fn subscribe_finalized_block(
523 &self,
524 ) -> watch::Receiver<Option<SealedHeader<N::BlockHeader>>> {
525 self.inner.chain_info_tracker.subscribe_finalized_block()
526 }
527
528 pub fn subscribe_persisted_block(&self) -> watch::Receiver<Option<BlockNumHash>> {
530 self.inner.chain_info_tracker.subscribe_persisted_block()
531 }
532
533 pub fn notify_canon_state(&self, event: CanonStateNotification<N>) {
535 self.inner.canon_state_notification_sender.send(event).ok();
536 }
537
538 pub fn state_provider(
543 &self,
544 hash: B256,
545 historical: StateProviderBox,
546 ) -> MemoryOverlayStateProvider<N> {
547 let in_memory = if let Some(state) = self.state_by_hash(hash) {
548 state.chain().map(|block_state| block_state.block()).collect()
549 } else {
550 Vec::new()
551 };
552
553 MemoryOverlayStateProvider::new(historical, in_memory)
554 }
555
556 pub fn canonical_chain(&self) -> impl Iterator<Item = Arc<BlockState<N>>> {
561 self.inner.in_memory_state.head_state().into_iter().flat_map(|head| head.iter())
562 }
563
564 pub fn transaction_by_hash(&self, hash: TxHash) -> Option<N::SignedTx> {
566 for block_state in self.canonical_chain() {
567 if let Some(tx) =
568 block_state.block_ref().recovered_block().body().transaction_by_hash(&hash)
569 {
570 return Some(tx.clone())
571 }
572 }
573 None
574 }
575
576 pub fn transaction_by_hash_with_meta(
579 &self,
580 tx_hash: TxHash,
581 ) -> Option<(N::SignedTx, TransactionMeta)> {
582 for block_state in self.canonical_chain() {
583 if let Some(indexed) = block_state.find_indexed(tx_hash) {
584 return Some((indexed.tx().clone(), indexed.meta()));
585 }
586 }
587 None
588 }
589}
590
591#[derive(Debug, Clone)]
594pub struct BlockState<N: NodePrimitives = EthPrimitives> {
595 block: ExecutedBlock<N>,
597 parent: Option<Arc<Self>>,
599}
600
601impl<N: NodePrimitives> PartialEq for BlockState<N> {
602 fn eq(&self, other: &Self) -> bool {
603 self.block == other.block && self.parent == other.parent
604 }
605}
606
607impl<N: NodePrimitives> BlockState<N> {
608 pub const fn new(block: ExecutedBlock<N>) -> Self {
610 Self { block, parent: None }
611 }
612
613 pub const fn with_parent(block: ExecutedBlock<N>, parent: Option<Arc<Self>>) -> Self {
615 Self { block, parent }
616 }
617
618 pub fn anchor(&self) -> BlockNumHash {
620 let mut current = self;
621 while let Some(parent) = ¤t.parent {
622 current = parent;
623 }
624 current.block.recovered_block().parent_num_hash()
625 }
626
627 pub fn block(&self) -> ExecutedBlock<N> {
629 self.block.clone()
630 }
631
632 pub const fn block_ref(&self) -> &ExecutedBlock<N> {
634 &self.block
635 }
636
637 pub fn hash(&self) -> B256 {
639 self.block.recovered_block().hash()
640 }
641
642 pub fn number(&self) -> u64 {
644 self.block.recovered_block().number()
645 }
646
647 pub fn state_root(&self) -> B256 {
650 self.block.recovered_block().state_root()
651 }
652
653 pub fn receipts(&self) -> &Vec<N::Receipt> {
655 &self.block.execution_outcome().receipts
656 }
657
658 pub fn executed_block_receipts(&self) -> Vec<N::Receipt> {
665 self.receipts().clone()
666 }
667
668 pub fn executed_block_receipts_ref(&self) -> &[N::Receipt] {
673 self.receipts()
674 }
675
676 pub fn parent_state_chain(&self) -> impl Iterator<Item = &Self> + '_ {
683 std::iter::successors(self.parent.as_deref(), |state| state.parent.as_deref())
684 }
685
686 pub fn chain(&self) -> impl Iterator<Item = &Self> {
690 std::iter::successors(Some(self), |state| state.parent.as_deref())
691 }
692
693 pub fn append_parent_chain<'a>(&'a self, chain: &mut Vec<&'a Self>) {
700 chain.extend(self.parent_state_chain());
701 }
702
703 pub fn iter(self: Arc<Self>) -> impl Iterator<Item = Arc<Self>> {
707 std::iter::successors(Some(self), |state| state.parent.clone())
708 }
709
710 pub fn state_provider(&self, historical: StateProviderBox) -> MemoryOverlayStateProvider<N> {
715 let in_memory = self.chain().map(|block_state| block_state.block()).collect();
716
717 MemoryOverlayStateProvider::new(historical, in_memory)
718 }
719
720 pub fn block_on_chain(&self, hash_or_num: BlockHashOrNumber) -> Option<&Self> {
722 self.chain().find(|block| match hash_or_num {
723 BlockHashOrNumber::Hash(hash) => block.hash() == hash,
724 BlockHashOrNumber::Number(number) => block.number() == number,
725 })
726 }
727
728 pub fn transaction_on_chain(&self, hash: TxHash) -> Option<N::SignedTx> {
730 self.chain().find_map(|block_state| {
731 block_state.block_ref().recovered_block().body().transaction_by_hash(&hash).cloned()
732 })
733 }
734
735 pub fn transaction_meta_on_chain(
737 &self,
738 tx_hash: TxHash,
739 ) -> Option<(N::SignedTx, TransactionMeta)> {
740 self.chain().find_map(|block_state| {
741 block_state.find_indexed(tx_hash).map(|indexed| (indexed.tx().clone(), indexed.meta()))
742 })
743 }
744
745 pub fn find_indexed(&self, tx_hash: TxHash) -> Option<IndexedTx<'_, N::Block>> {
747 self.block_ref().recovered_block().find_indexed(tx_hash)
748 }
749}
750
751#[derive(Clone, Debug)]
753pub struct ExecutedBlock<N: NodePrimitives = EthPrimitives> {
754 pub recovered_block: Arc<RecoveredBlock<N::Block>>,
756 pub execution_output: Arc<BlockExecutionOutput<N::Receipt>>,
758 pub trie_data: DeferredTrieData,
763}
764
765impl<N: NodePrimitives> Default for ExecutedBlock<N> {
766 fn default() -> Self {
767 Self {
768 recovered_block: Default::default(),
769 execution_output: Arc::new(BlockExecutionOutput {
770 result: BlockExecutionResult {
771 receipts: Default::default(),
772 requests: Default::default(),
773 gas_used: 0,
774 blob_gas_used: 0,
775 },
776 state: Default::default(),
777 }),
778 trie_data: DeferredTrieData::ready(ComputedTrieData::default()),
779 }
780 }
781}
782
783impl<N: NodePrimitives> PartialEq for ExecutedBlock<N> {
784 fn eq(&self, other: &Self) -> bool {
785 self.recovered_block == other.recovered_block &&
787 self.execution_output == other.execution_output
788 }
789}
790
791impl<N: NodePrimitives> ExecutedBlock<N> {
792 pub fn new(
797 recovered_block: Arc<RecoveredBlock<N::Block>>,
798 execution_output: Arc<BlockExecutionOutput<N::Receipt>>,
799 trie_data: ComputedTrieData,
800 ) -> Self {
801 Self { recovered_block, execution_output, trie_data: DeferredTrieData::ready(trie_data) }
802 }
803
804 pub const fn with_deferred_trie_data(
819 recovered_block: Arc<RecoveredBlock<N::Block>>,
820 execution_output: Arc<BlockExecutionOutput<N::Receipt>>,
821 trie_data: DeferredTrieData,
822 ) -> Self {
823 Self { recovered_block, execution_output, trie_data }
824 }
825
826 #[inline]
828 pub fn sealed_block(&self) -> &SealedBlock<N::Block> {
829 self.recovered_block.sealed_block()
830 }
831
832 #[inline]
834 pub fn recovered_block(&self) -> &RecoveredBlock<N::Block> {
835 &self.recovered_block
836 }
837
838 #[inline]
840 pub fn execution_outcome(&self) -> &BlockExecutionOutput<N::Receipt> {
841 &self.execution_output
842 }
843
844 #[inline]
850 #[tracing::instrument(level = "debug", target = "engine::tree", name = "trie_data", skip_all)]
851 pub fn trie_data(&self) -> ComputedTrieData {
852 self.trie_data.wait_cloned()
853 }
854
855 #[inline]
861 pub fn trie_data_handle(&self) -> DeferredTrieData {
862 self.trie_data.clone()
863 }
864
865 #[inline]
869 pub fn hashed_state(&self) -> Arc<HashedPostStateSorted> {
870 self.trie_data().hashed_state
871 }
872
873 #[inline]
877 pub fn trie_updates(&self) -> Arc<TrieUpdatesSorted> {
878 self.trie_data().trie_updates
879 }
880
881 #[inline]
885 pub fn trie_input(&self) -> Option<Arc<TrieInputSorted>> {
886 self.trie_data().trie_input().cloned()
887 }
888
889 #[inline]
891 pub fn anchor_hash(&self) -> Option<B256> {
892 self.trie_data().anchor_hash()
893 }
894
895 #[inline]
897 pub fn block_number(&self) -> BlockNumber {
898 self.recovered_block.header().number()
899 }
900}
901
902#[derive(Debug)]
904pub enum NewCanonicalChain<N: NodePrimitives = EthPrimitives> {
905 Commit {
907 new: Vec<ExecutedBlock<N>>,
909 },
910 Reorg {
913 new: Vec<ExecutedBlock<N>>,
915 old: Vec<ExecutedBlock<N>>,
917 },
918}
919
920impl<N: NodePrimitives<SignedTx: SignedTransaction>> NewCanonicalChain<N> {
921 pub const fn new_block_count(&self) -> usize {
923 match self {
924 Self::Commit { new } | Self::Reorg { new, .. } => new.len(),
925 }
926 }
927
928 pub const fn reorged_block_count(&self) -> usize {
930 match self {
931 Self::Commit { .. } => 0,
932 Self::Reorg { old, .. } => old.len(),
933 }
934 }
935
936 pub fn to_chain_notification(&self) -> CanonStateNotification<N> {
938 match self {
939 Self::Commit { new } => {
940 CanonStateNotification::Commit { new: Arc::new(Self::blocks_to_chain(new)) }
941 }
942 Self::Reorg { new, old } => CanonStateNotification::Reorg {
943 new: Arc::new(Self::blocks_to_chain(new)),
944 old: Arc::new(Self::blocks_to_chain(old)),
945 },
946 }
947 }
948
949 fn blocks_to_chain(blocks: &[ExecutedBlock<N>]) -> Chain<N> {
951 match blocks {
952 [] => Chain::default(),
953 [first, rest @ ..] => {
954 let trie_data_handle = first.trie_data_handle();
955 let mut chain = Chain::from_block(
956 first.recovered_block().clone(),
957 ExecutionOutcome::from((
958 first.execution_outcome().clone(),
959 first.block_number(),
960 )),
961 LazyTrieData::deferred(move || {
962 let trie_data = trie_data_handle.wait_cloned();
963 SortedTrieData {
964 hashed_state: trie_data.hashed_state,
965 trie_updates: trie_data.trie_updates,
966 }
967 }),
968 );
969 for exec in rest {
970 let trie_data_handle = exec.trie_data_handle();
971 chain.append_block(
972 exec.recovered_block().clone(),
973 ExecutionOutcome::from((
974 exec.execution_outcome().clone(),
975 exec.block_number(),
976 )),
977 LazyTrieData::deferred(move || {
978 let trie_data = trie_data_handle.wait_cloned();
979 SortedTrieData {
980 hashed_state: trie_data.hashed_state,
981 trie_updates: trie_data.trie_updates,
982 }
983 }),
984 );
985 }
986 chain
987 }
988 }
989 }
990
991 pub fn tip(&self) -> &SealedBlock<N::Block> {
996 match self {
997 Self::Commit { new } | Self::Reorg { new, .. } => {
998 new.last().expect("non empty blocks").recovered_block()
999 }
1000 }
1001 }
1002}
1003
1004#[cfg(test)]
1005mod tests {
1006 use super::*;
1007 use crate::test_utils::TestBlockBuilder;
1008 use alloy_eips::eip7685::Requests;
1009 use alloy_primitives::{Address, BlockNumber, Bytes, StorageKey, StorageValue};
1010 use rand::Rng;
1011 use reth_errors::ProviderResult;
1012 use reth_ethereum_primitives::{EthPrimitives, Receipt};
1013 use reth_primitives_traits::{Account, Bytecode};
1014 use reth_storage_api::{
1015 AccountReader, BlockHashReader, BytecodeReader, HashedPostStateProvider,
1016 StateProofProvider, StateProvider, StateRootProvider, StorageRootProvider,
1017 };
1018 use reth_trie::{
1019 updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof,
1020 MultiProofTargets, StorageMultiProof, StorageProof, TrieInput,
1021 };
1022
1023 fn create_mock_state(
1024 test_block_builder: &mut TestBlockBuilder<EthPrimitives>,
1025 block_number: u64,
1026 parent_hash: B256,
1027 ) -> BlockState {
1028 BlockState::new(
1029 test_block_builder.get_executed_block_with_number(block_number, parent_hash),
1030 )
1031 }
1032
1033 fn create_mock_state_chain(
1034 test_block_builder: &mut TestBlockBuilder<EthPrimitives>,
1035 num_blocks: u64,
1036 ) -> Vec<BlockState> {
1037 let mut chain = Vec::with_capacity(num_blocks as usize);
1038 let mut parent_hash = B256::random();
1039 let mut parent_state: Option<BlockState> = None;
1040
1041 for i in 1..=num_blocks {
1042 let mut state = create_mock_state(test_block_builder, i, parent_hash);
1043 if let Some(parent) = parent_state {
1044 state.parent = Some(Arc::new(parent));
1045 }
1046 parent_hash = state.hash();
1047 parent_state = Some(state.clone());
1048 chain.push(state);
1049 }
1050
1051 chain
1052 }
1053
1054 struct MockStateProvider;
1055
1056 impl StateProvider for MockStateProvider {
1057 fn storage(
1058 &self,
1059 _address: Address,
1060 _storage_key: StorageKey,
1061 ) -> ProviderResult<Option<StorageValue>> {
1062 Ok(None)
1063 }
1064 }
1065
1066 impl BytecodeReader for MockStateProvider {
1067 fn bytecode_by_hash(&self, _code_hash: &B256) -> ProviderResult<Option<Bytecode>> {
1068 Ok(None)
1069 }
1070 }
1071
1072 impl BlockHashReader for MockStateProvider {
1073 fn block_hash(&self, _number: BlockNumber) -> ProviderResult<Option<B256>> {
1074 Ok(None)
1075 }
1076
1077 fn canonical_hashes_range(
1078 &self,
1079 _start: BlockNumber,
1080 _end: BlockNumber,
1081 ) -> ProviderResult<Vec<B256>> {
1082 Ok(vec![])
1083 }
1084 }
1085
1086 impl AccountReader for MockStateProvider {
1087 fn basic_account(&self, _address: &Address) -> ProviderResult<Option<Account>> {
1088 Ok(None)
1089 }
1090 }
1091
1092 impl StateRootProvider for MockStateProvider {
1093 fn state_root(&self, _hashed_state: HashedPostState) -> ProviderResult<B256> {
1094 Ok(B256::random())
1095 }
1096
1097 fn state_root_from_nodes(&self, _input: TrieInput) -> ProviderResult<B256> {
1098 Ok(B256::random())
1099 }
1100
1101 fn state_root_with_updates(
1102 &self,
1103 _hashed_state: HashedPostState,
1104 ) -> ProviderResult<(B256, TrieUpdates)> {
1105 Ok((B256::random(), TrieUpdates::default()))
1106 }
1107
1108 fn state_root_from_nodes_with_updates(
1109 &self,
1110 _input: TrieInput,
1111 ) -> ProviderResult<(B256, TrieUpdates)> {
1112 Ok((B256::random(), TrieUpdates::default()))
1113 }
1114 }
1115
1116 impl HashedPostStateProvider for MockStateProvider {
1117 fn hashed_post_state(&self, _bundle_state: &revm_database::BundleState) -> HashedPostState {
1118 HashedPostState::default()
1119 }
1120 }
1121
1122 impl StorageRootProvider for MockStateProvider {
1123 fn storage_root(
1124 &self,
1125 _address: Address,
1126 _hashed_storage: HashedStorage,
1127 ) -> ProviderResult<B256> {
1128 Ok(B256::random())
1129 }
1130
1131 fn storage_proof(
1132 &self,
1133 _address: Address,
1134 slot: B256,
1135 _hashed_storage: HashedStorage,
1136 ) -> ProviderResult<StorageProof> {
1137 Ok(StorageProof::new(slot))
1138 }
1139
1140 fn storage_multiproof(
1141 &self,
1142 _address: Address,
1143 _slots: &[B256],
1144 _hashed_storage: HashedStorage,
1145 ) -> ProviderResult<StorageMultiProof> {
1146 Ok(StorageMultiProof::empty())
1147 }
1148 }
1149
1150 impl StateProofProvider for MockStateProvider {
1151 fn proof(
1152 &self,
1153 _input: TrieInput,
1154 _address: Address,
1155 _slots: &[B256],
1156 ) -> ProviderResult<AccountProof> {
1157 Ok(AccountProof::new(Address::random()))
1158 }
1159
1160 fn multiproof(
1161 &self,
1162 _input: TrieInput,
1163 _targets: MultiProofTargets,
1164 ) -> ProviderResult<MultiProof> {
1165 Ok(MultiProof::default())
1166 }
1167
1168 fn witness(
1169 &self,
1170 _input: TrieInput,
1171 _target: HashedPostState,
1172 ) -> ProviderResult<Vec<Bytes>> {
1173 Ok(Vec::default())
1174 }
1175 }
1176
1177 #[test]
1178 fn test_in_memory_state_impl_state_by_hash() {
1179 let mut state_by_hash = B256Map::default();
1180 let number = rand::rng().random::<u64>();
1181 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1182 let state = Arc::new(create_mock_state(&mut test_block_builder, number, B256::random()));
1183 state_by_hash.insert(state.hash(), state.clone());
1184
1185 let in_memory_state = InMemoryState::new(state_by_hash, BTreeMap::new(), None);
1186
1187 assert_eq!(in_memory_state.state_by_hash(state.hash()), Some(state));
1188 assert_eq!(in_memory_state.state_by_hash(B256::random()), None);
1189 }
1190
1191 #[test]
1192 fn test_in_memory_state_impl_state_by_number() {
1193 let mut state_by_hash = B256Map::default();
1194 let mut hash_by_number = BTreeMap::new();
1195
1196 let number = rand::rng().random::<u64>();
1197 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1198 let state = Arc::new(create_mock_state(&mut test_block_builder, number, B256::random()));
1199 let hash = state.hash();
1200
1201 state_by_hash.insert(hash, state.clone());
1202 hash_by_number.insert(number, hash);
1203
1204 let in_memory_state = InMemoryState::new(state_by_hash, hash_by_number, None);
1205
1206 assert_eq!(in_memory_state.state_by_number(number), Some(state));
1207 assert_eq!(in_memory_state.state_by_number(number + 1), None);
1208 }
1209
1210 #[test]
1211 fn test_in_memory_state_impl_head_state() {
1212 let mut state_by_hash = B256Map::default();
1213 let mut hash_by_number = BTreeMap::new();
1214 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1215 let state1 = Arc::new(create_mock_state(&mut test_block_builder, 1, B256::random()));
1216 let hash1 = state1.hash();
1217 let state2 = Arc::new(create_mock_state(&mut test_block_builder, 2, hash1));
1218 let hash2 = state2.hash();
1219 hash_by_number.insert(1, hash1);
1220 hash_by_number.insert(2, hash2);
1221 state_by_hash.insert(hash1, state1);
1222 state_by_hash.insert(hash2, state2);
1223
1224 let in_memory_state = InMemoryState::new(state_by_hash, hash_by_number, None);
1225 let head_state = in_memory_state.head_state().unwrap();
1226
1227 assert_eq!(head_state.hash(), hash2);
1228 assert_eq!(head_state.number(), 2);
1229 }
1230
1231 #[test]
1232 fn test_in_memory_state_impl_pending_state() {
1233 let pending_number = rand::rng().random::<u64>();
1234 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1235 let pending_state =
1236 create_mock_state(&mut test_block_builder, pending_number, B256::random());
1237 let pending_hash = pending_state.hash();
1238
1239 let in_memory_state =
1240 InMemoryState::new(B256Map::default(), BTreeMap::new(), Some(pending_state));
1241
1242 let result = in_memory_state.pending_state();
1243 assert!(result.is_some());
1244 let actual_pending_state = result.unwrap();
1245 assert_eq!(actual_pending_state.block.recovered_block().hash(), pending_hash);
1246 assert_eq!(actual_pending_state.block.recovered_block().number, pending_number);
1247 }
1248
1249 #[test]
1250 fn test_in_memory_state_impl_no_pending_state() {
1251 let in_memory_state: InMemoryState =
1252 InMemoryState::new(B256Map::default(), BTreeMap::new(), None);
1253
1254 assert_eq!(in_memory_state.pending_state(), None);
1255 }
1256
1257 #[test]
1258 fn test_state() {
1259 let number = rand::rng().random::<u64>();
1260 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1261 let block = test_block_builder.get_executed_block_with_number(number, B256::random());
1262
1263 let state = BlockState::new(block.clone());
1264
1265 assert_eq!(state.block(), block);
1266 assert_eq!(state.hash(), block.recovered_block().hash());
1267 assert_eq!(state.number(), number);
1268 assert_eq!(state.state_root(), block.recovered_block().state_root);
1269 }
1270
1271 #[test]
1272 fn test_state_receipts() {
1273 let receipts = vec![vec![Receipt::default()]];
1274 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1275 let block =
1276 test_block_builder.get_executed_block_with_receipts(receipts.clone(), B256::random());
1277
1278 let state = BlockState::new(block);
1279
1280 assert_eq!(state.receipts(), receipts.first().unwrap());
1281 }
1282
1283 #[test]
1284 fn test_in_memory_state_chain_update() {
1285 let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1286 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1287 let block1 = test_block_builder.get_executed_block_with_number(0, B256::random());
1288 let block2 = test_block_builder.get_executed_block_with_number(0, B256::random());
1289 let chain = NewCanonicalChain::Commit { new: vec![block1.clone()] };
1290 state.update_chain(chain);
1291 assert_eq!(
1292 state.head_state().unwrap().block_ref().recovered_block().hash(),
1293 block1.recovered_block().hash()
1294 );
1295 assert_eq!(
1296 state.state_by_number(0).unwrap().block_ref().recovered_block().hash(),
1297 block1.recovered_block().hash()
1298 );
1299
1300 let chain = NewCanonicalChain::Reorg { new: vec![block2.clone()], old: vec![block1] };
1301 state.update_chain(chain);
1302 assert_eq!(
1303 state.head_state().unwrap().block_ref().recovered_block().hash(),
1304 block2.recovered_block().hash()
1305 );
1306 assert_eq!(
1307 state.state_by_number(0).unwrap().block_ref().recovered_block().hash(),
1308 block2.recovered_block().hash()
1309 );
1310
1311 assert_eq!(state.inner.in_memory_state.block_count(), 1);
1312 }
1313
1314 #[test]
1315 fn test_in_memory_state_set_pending_block() {
1316 let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1317 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1318
1319 let block1 = test_block_builder.get_executed_block_with_number(0, B256::random());
1321
1322 let block2 =
1324 test_block_builder.get_executed_block_with_number(1, block1.recovered_block().hash());
1325
1326 let chain = NewCanonicalChain::Commit { new: vec![block1.clone(), block2.clone()] };
1328 state.update_chain(chain);
1329
1330 assert!(state.pending_state().is_none());
1332
1333 state.set_pending_block(block2.clone());
1335
1336 assert_eq!(
1338 state.pending_state().unwrap(),
1339 BlockState::with_parent(block2.clone(), Some(Arc::new(BlockState::new(block1))))
1340 );
1341
1342 assert_eq!(state.pending_block().unwrap(), block2.recovered_block().sealed_block().clone());
1344
1345 assert_eq!(
1347 state.pending_block_num_hash().unwrap(),
1348 BlockNumHash { number: 1, hash: block2.recovered_block().hash() }
1349 );
1350
1351 assert_eq!(state.pending_header().unwrap(), block2.recovered_block().header().clone());
1353
1354 assert_eq!(
1356 state.pending_sealed_header().unwrap(),
1357 block2.recovered_block().clone_sealed_header()
1358 );
1359
1360 assert_eq!(state.pending_recovered_block().unwrap(), block2.recovered_block().clone());
1362
1363 assert_eq!(
1365 state.pending_block_and_receipts().unwrap(),
1366 (block2.recovered_block().clone(), vec![])
1367 );
1368 }
1369
1370 #[test]
1371 fn test_canonical_in_memory_state_state_provider() {
1372 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1373 let block1 = test_block_builder.get_executed_block_with_number(1, B256::random());
1374 let block2 =
1375 test_block_builder.get_executed_block_with_number(2, block1.recovered_block().hash());
1376 let block3 =
1377 test_block_builder.get_executed_block_with_number(3, block2.recovered_block().hash());
1378
1379 let state1 = Arc::new(BlockState::new(block1.clone()));
1380 let state2 = Arc::new(BlockState::with_parent(block2.clone(), Some(state1.clone())));
1381 let state3 = Arc::new(BlockState::with_parent(block3.clone(), Some(state2.clone())));
1382
1383 let mut blocks = B256Map::default();
1384 blocks.insert(block1.recovered_block().hash(), state1);
1385 blocks.insert(block2.recovered_block().hash(), state2);
1386 blocks.insert(block3.recovered_block().hash(), state3);
1387
1388 let mut numbers = BTreeMap::new();
1389 numbers.insert(1, block1.recovered_block().hash());
1390 numbers.insert(2, block2.recovered_block().hash());
1391 numbers.insert(3, block3.recovered_block().hash());
1392
1393 let canonical_state = CanonicalInMemoryState::new(blocks, numbers, None, None, None);
1394
1395 let historical: StateProviderBox = Box::new(MockStateProvider);
1396
1397 let overlay_provider =
1398 canonical_state.state_provider(block3.recovered_block().hash(), historical);
1399
1400 assert_eq!(overlay_provider.in_memory.len(), 3);
1401 assert_eq!(overlay_provider.in_memory[0].recovered_block().number, 3);
1402 assert_eq!(overlay_provider.in_memory[1].recovered_block().number, 2);
1403 assert_eq!(overlay_provider.in_memory[2].recovered_block().number, 1);
1404
1405 assert_eq!(
1406 overlay_provider.in_memory[0].recovered_block().parent_hash,
1407 overlay_provider.in_memory[1].recovered_block().hash()
1408 );
1409 assert_eq!(
1410 overlay_provider.in_memory[1].recovered_block().parent_hash,
1411 overlay_provider.in_memory[2].recovered_block().hash()
1412 );
1413
1414 let unknown_hash = B256::random();
1415 let empty_overlay_provider =
1416 canonical_state.state_provider(unknown_hash, Box::new(MockStateProvider));
1417 assert_eq!(empty_overlay_provider.in_memory.len(), 0);
1418 }
1419
1420 #[test]
1421 fn test_canonical_in_memory_state_canonical_chain_empty() {
1422 let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1423 assert!(state.canonical_chain().next().is_none());
1424 }
1425
1426 #[test]
1427 fn test_canonical_in_memory_state_canonical_chain_single_block() {
1428 let block = TestBlockBuilder::eth().get_executed_block_with_number(1, B256::random());
1429 let hash = block.recovered_block().hash();
1430 let mut blocks = B256Map::default();
1431 blocks.insert(hash, Arc::new(BlockState::new(block)));
1432 let mut numbers = BTreeMap::new();
1433 numbers.insert(1, hash);
1434
1435 let state = CanonicalInMemoryState::new(blocks, numbers, None, None, None);
1436 let chain: Vec<_> = state.canonical_chain().collect();
1437
1438 assert_eq!(chain.len(), 1);
1439 assert_eq!(chain[0].number(), 1);
1440 assert_eq!(chain[0].hash(), hash);
1441 }
1442
1443 #[test]
1444 fn test_canonical_in_memory_state_canonical_chain_multiple_blocks() {
1445 let mut parent_hash = B256::random();
1446 let mut block_builder = TestBlockBuilder::eth();
1447 let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1448
1449 for i in 1..=3 {
1450 let block = block_builder.get_executed_block_with_number(i, parent_hash);
1451 let hash = block.recovered_block().hash();
1452 state.update_blocks(Some(block), None);
1453 parent_hash = hash;
1454 }
1455
1456 let chain: Vec<_> = state.canonical_chain().collect();
1457
1458 assert_eq!(chain.len(), 3);
1459 assert_eq!(chain[0].number(), 3);
1460 assert_eq!(chain[1].number(), 2);
1461 assert_eq!(chain[2].number(), 1);
1462 }
1463
1464 #[test]
1466 fn test_canonical_in_memory_state_canonical_chain_with_pending_block() {
1467 let mut parent_hash = B256::random();
1468 let mut block_builder = TestBlockBuilder::<EthPrimitives>::eth();
1469 let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1470
1471 for i in 1..=2 {
1472 let block = block_builder.get_executed_block_with_number(i, parent_hash);
1473 let hash = block.recovered_block().hash();
1474 state.update_blocks(Some(block), None);
1475 parent_hash = hash;
1476 }
1477
1478 let pending_block = block_builder.get_executed_block_with_number(3, parent_hash);
1479 state.set_pending_block(pending_block);
1480 let chain: Vec<_> = state.canonical_chain().collect();
1481
1482 assert_eq!(chain.len(), 2);
1483 assert_eq!(chain[0].number(), 2);
1484 assert_eq!(chain[1].number(), 1);
1485 }
1486
1487 #[test]
1488 fn test_block_state_parent_blocks() {
1489 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1490 let chain = create_mock_state_chain(&mut test_block_builder, 4);
1491
1492 let parents: Vec<_> = chain[3].parent_state_chain().collect();
1493 assert_eq!(parents.len(), 3);
1494 assert_eq!(parents[0].block().recovered_block().number, 3);
1495 assert_eq!(parents[1].block().recovered_block().number, 2);
1496 assert_eq!(parents[2].block().recovered_block().number, 1);
1497
1498 let parents: Vec<_> = chain[2].parent_state_chain().collect();
1499 assert_eq!(parents.len(), 2);
1500 assert_eq!(parents[0].block().recovered_block().number, 2);
1501 assert_eq!(parents[1].block().recovered_block().number, 1);
1502
1503 assert_eq!(chain[0].parent_state_chain().count(), 0);
1504 }
1505
1506 #[test]
1507 fn test_block_state_single_block_state_chain() {
1508 let single_block_number = 1;
1509 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1510 let single_block =
1511 create_mock_state(&mut test_block_builder, single_block_number, B256::random());
1512 let single_block_hash = single_block.block().recovered_block().hash();
1513
1514 assert_eq!(single_block.parent_state_chain().count(), 0);
1515
1516 let block_state_chain = single_block.chain().collect::<Vec<_>>();
1517 assert_eq!(block_state_chain.len(), 1);
1518 assert_eq!(block_state_chain[0].block().recovered_block().number, single_block_number);
1519 assert_eq!(block_state_chain[0].block().recovered_block().hash(), single_block_hash);
1520 }
1521
1522 #[test]
1523 fn test_block_state_chain() {
1524 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1525 let chain = create_mock_state_chain(&mut test_block_builder, 3);
1526
1527 let block_state_chain = chain[2].chain().collect::<Vec<_>>();
1528 assert_eq!(block_state_chain.len(), 3);
1529 assert_eq!(block_state_chain[0].block().recovered_block().number, 3);
1530 assert_eq!(block_state_chain[1].block().recovered_block().number, 2);
1531 assert_eq!(block_state_chain[2].block().recovered_block().number, 1);
1532
1533 let block_state_chain = chain[1].chain().collect::<Vec<_>>();
1534 assert_eq!(block_state_chain.len(), 2);
1535 assert_eq!(block_state_chain[0].block().recovered_block().number, 2);
1536 assert_eq!(block_state_chain[1].block().recovered_block().number, 1);
1537
1538 let block_state_chain = chain[0].chain().collect::<Vec<_>>();
1539 assert_eq!(block_state_chain.len(), 1);
1540 assert_eq!(block_state_chain[0].block().recovered_block().number, 1);
1541 }
1542
1543 #[test]
1544 fn test_to_chain_notification() {
1545 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1547 let block0 = test_block_builder.get_executed_block_with_number(0, B256::random());
1548 let block1 =
1549 test_block_builder.get_executed_block_with_number(1, block0.recovered_block.hash());
1550 let block1a =
1551 test_block_builder.get_executed_block_with_number(1, block0.recovered_block.hash());
1552 let block2 =
1553 test_block_builder.get_executed_block_with_number(2, block1.recovered_block.hash());
1554 let block2a =
1555 test_block_builder.get_executed_block_with_number(2, block1.recovered_block.hash());
1556
1557 let chain_commit = NewCanonicalChain::Commit { new: vec![block0.clone(), block1.clone()] };
1559
1560 let mut expected_trie_data = BTreeMap::new();
1562 expected_trie_data
1563 .insert(0, LazyTrieData::ready(block0.hashed_state(), block0.trie_updates()));
1564 expected_trie_data
1565 .insert(1, LazyTrieData::ready(block1.hashed_state(), block1.trie_updates()));
1566
1567 let commit_execution_outcome = ExecutionOutcome {
1569 receipts: vec![vec![], vec![]],
1570 requests: vec![Requests::default(), Requests::default()],
1571 first_block: 0,
1572 ..Default::default()
1573 };
1574
1575 assert_eq!(
1576 chain_commit.to_chain_notification(),
1577 CanonStateNotification::Commit {
1578 new: Arc::new(Chain::new(
1579 vec![block0.recovered_block().clone(), block1.recovered_block().clone()],
1580 commit_execution_outcome,
1581 expected_trie_data,
1582 ))
1583 }
1584 );
1585
1586 let chain_reorg = NewCanonicalChain::Reorg {
1588 new: vec![block1a.clone(), block2a.clone()],
1589 old: vec![block1.clone(), block2.clone()],
1590 };
1591
1592 let mut old_trie_data = BTreeMap::new();
1594 old_trie_data.insert(1, LazyTrieData::ready(block1.hashed_state(), block1.trie_updates()));
1595 old_trie_data.insert(2, LazyTrieData::ready(block2.hashed_state(), block2.trie_updates()));
1596
1597 let mut new_trie_data = BTreeMap::new();
1599 new_trie_data
1600 .insert(1, LazyTrieData::ready(block1a.hashed_state(), block1a.trie_updates()));
1601 new_trie_data
1602 .insert(2, LazyTrieData::ready(block2a.hashed_state(), block2a.trie_updates()));
1603
1604 let reorg_execution_outcome = ExecutionOutcome {
1607 receipts: vec![vec![], vec![]],
1608 requests: vec![Requests::default(), Requests::default()],
1609 first_block: 1,
1610 ..Default::default()
1611 };
1612
1613 assert_eq!(
1614 chain_reorg.to_chain_notification(),
1615 CanonStateNotification::Reorg {
1616 old: Arc::new(Chain::new(
1617 vec![block1.recovered_block().clone(), block2.recovered_block().clone()],
1618 reorg_execution_outcome.clone(),
1619 old_trie_data,
1620 )),
1621 new: Arc::new(Chain::new(
1622 vec![block1a.recovered_block().clone(), block2a.recovered_block().clone()],
1623 reorg_execution_outcome,
1624 new_trie_data,
1625 ))
1626 }
1627 );
1628 }
1629}