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