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