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]
857 pub fn trie_data_handle(&self) -> DeferredTrieData {
858 self.trie_data.clone()
859 }
860
861 #[inline]
865 pub fn hashed_state(&self) -> Arc<HashedPostStateSorted> {
866 self.trie_data().hashed_state
867 }
868
869 #[inline]
873 pub fn trie_updates(&self) -> Arc<TrieUpdatesSorted> {
874 self.trie_data().trie_updates
875 }
876
877 #[inline]
879 pub fn block_number(&self) -> BlockNumber {
880 self.recovered_block.header().number()
881 }
882}
883
884#[derive(Debug)]
886pub enum NewCanonicalChain<N: NodePrimitives = EthPrimitives> {
887 Commit {
889 new: Vec<ExecutedBlock<N>>,
891 },
892 Reorg {
895 new: Vec<ExecutedBlock<N>>,
897 old: Vec<ExecutedBlock<N>>,
899 },
900}
901
902impl<N: NodePrimitives<SignedTx: SignedTransaction>> NewCanonicalChain<N> {
903 pub const fn new_block_count(&self) -> usize {
905 match self {
906 Self::Commit { new } | Self::Reorg { new, .. } => new.len(),
907 }
908 }
909
910 pub const fn reorged_block_count(&self) -> usize {
912 match self {
913 Self::Commit { .. } => 0,
914 Self::Reorg { old, .. } => old.len(),
915 }
916 }
917
918 pub fn to_chain_notification(&self) -> CanonStateNotification<N> {
920 match self {
921 Self::Commit { new } => {
922 CanonStateNotification::Commit { new: Arc::new(Self::blocks_to_chain(new)) }
923 }
924 Self::Reorg { new, old } => CanonStateNotification::Reorg {
925 new: Arc::new(Self::blocks_to_chain(new)),
926 old: Arc::new(Self::blocks_to_chain(old)),
927 },
928 }
929 }
930
931 fn blocks_to_chain(blocks: &[ExecutedBlock<N>]) -> Chain<N> {
933 match blocks {
934 [] => Chain::default(),
935 [first, rest @ ..] => {
936 let trie_data_handle = first.trie_data_handle();
937 let mut chain = Chain::from_block(
938 first.recovered_block().clone(),
939 ExecutionOutcome::from((
940 first.execution_outcome().clone(),
941 first.block_number(),
942 )),
943 LazyTrieData::deferred(move || {
944 let trie_data = trie_data_handle.wait_cloned();
945 SortedTrieData {
946 hashed_state: trie_data.hashed_state,
947 trie_updates: trie_data.trie_updates,
948 }
949 }),
950 );
951 for exec in rest {
952 let trie_data_handle = exec.trie_data_handle();
953 chain.append_block(
954 exec.recovered_block().clone(),
955 ExecutionOutcome::from((
956 exec.execution_outcome().clone(),
957 exec.block_number(),
958 )),
959 LazyTrieData::deferred(move || {
960 let trie_data = trie_data_handle.wait_cloned();
961 SortedTrieData {
962 hashed_state: trie_data.hashed_state,
963 trie_updates: trie_data.trie_updates,
964 }
965 }),
966 );
967 }
968 chain
969 }
970 }
971 }
972
973 pub fn tip(&self) -> &RecoveredBlock<N::Block> {
978 match self {
979 Self::Commit { new } | Self::Reorg { new, .. } => {
980 new.last().expect("non empty blocks").recovered_block()
981 }
982 }
983 }
984}
985
986#[cfg(test)]
987mod tests {
988 use super::*;
989 use crate::test_utils::TestBlockBuilder;
990 use alloy_eips::eip7685::Requests;
991 use alloy_primitives::{Address, BlockNumber, Bytes, StorageKey, StorageValue};
992 use rand::Rng;
993 use reth_errors::ProviderResult;
994 use reth_ethereum_primitives::{EthPrimitives, Receipt};
995 use reth_primitives_traits::{Account, Bytecode};
996 use reth_storage_api::{
997 AccountReader, BlockHashReader, BytecodeReader, HashedPostStateProvider,
998 StateProofProvider, StateProvider, StateRootProvider, StorageRootProvider,
999 };
1000 use reth_trie::{
1001 updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof,
1002 MultiProofTargets, StorageMultiProof, StorageProof, TrieInput,
1003 };
1004
1005 fn create_mock_state(
1006 test_block_builder: &mut TestBlockBuilder<EthPrimitives>,
1007 block_number: u64,
1008 parent_hash: B256,
1009 ) -> BlockState {
1010 BlockState::new(
1011 test_block_builder.get_executed_block_with_number(block_number, parent_hash),
1012 )
1013 }
1014
1015 fn create_mock_state_chain(
1016 test_block_builder: &mut TestBlockBuilder<EthPrimitives>,
1017 num_blocks: u64,
1018 ) -> Vec<BlockState> {
1019 let mut chain = Vec::with_capacity(num_blocks as usize);
1020 let mut parent_hash = B256::random();
1021 let mut parent_state: Option<BlockState> = None;
1022
1023 for i in 1..=num_blocks {
1024 let mut state = create_mock_state(test_block_builder, i, parent_hash);
1025 if let Some(parent) = parent_state {
1026 state.parent = Some(Arc::new(parent));
1027 }
1028 parent_hash = state.hash();
1029 parent_state = Some(state.clone());
1030 chain.push(state);
1031 }
1032
1033 chain
1034 }
1035
1036 struct MockStateProvider;
1037
1038 impl StateProvider for MockStateProvider {
1039 fn storage(
1040 &self,
1041 _address: Address,
1042 _storage_key: StorageKey,
1043 ) -> ProviderResult<Option<StorageValue>> {
1044 Ok(None)
1045 }
1046 }
1047
1048 impl BytecodeReader for MockStateProvider {
1049 fn bytecode_by_hash(&self, _code_hash: &B256) -> ProviderResult<Option<Bytecode>> {
1050 Ok(None)
1051 }
1052 }
1053
1054 impl BlockHashReader for MockStateProvider {
1055 fn block_hash(&self, _number: BlockNumber) -> ProviderResult<Option<B256>> {
1056 Ok(None)
1057 }
1058
1059 fn canonical_hashes_range(
1060 &self,
1061 _start: BlockNumber,
1062 _end: BlockNumber,
1063 ) -> ProviderResult<Vec<B256>> {
1064 Ok(vec![])
1065 }
1066 }
1067
1068 impl AccountReader for MockStateProvider {
1069 fn basic_account(&self, _address: &Address) -> ProviderResult<Option<Account>> {
1070 Ok(None)
1071 }
1072 }
1073
1074 impl StateRootProvider for MockStateProvider {
1075 fn state_root(&self, _hashed_state: HashedPostState) -> ProviderResult<B256> {
1076 Ok(B256::random())
1077 }
1078
1079 fn state_root_from_nodes(&self, _input: TrieInput) -> ProviderResult<B256> {
1080 Ok(B256::random())
1081 }
1082
1083 fn state_root_with_updates(
1084 &self,
1085 _hashed_state: HashedPostState,
1086 ) -> ProviderResult<(B256, TrieUpdates)> {
1087 Ok((B256::random(), TrieUpdates::default()))
1088 }
1089
1090 fn state_root_from_nodes_with_updates(
1091 &self,
1092 _input: TrieInput,
1093 ) -> ProviderResult<(B256, TrieUpdates)> {
1094 Ok((B256::random(), TrieUpdates::default()))
1095 }
1096 }
1097
1098 impl HashedPostStateProvider for MockStateProvider {
1099 fn hashed_post_state(&self, _bundle_state: &revm_database::BundleState) -> HashedPostState {
1100 HashedPostState::default()
1101 }
1102 }
1103
1104 impl StorageRootProvider for MockStateProvider {
1105 fn storage_root(
1106 &self,
1107 _address: Address,
1108 _hashed_storage: HashedStorage,
1109 ) -> ProviderResult<B256> {
1110 Ok(B256::random())
1111 }
1112
1113 fn storage_proof(
1114 &self,
1115 _address: Address,
1116 slot: B256,
1117 _hashed_storage: HashedStorage,
1118 ) -> ProviderResult<StorageProof> {
1119 Ok(StorageProof::new(slot))
1120 }
1121
1122 fn storage_multiproof(
1123 &self,
1124 _address: Address,
1125 _slots: &[B256],
1126 _hashed_storage: HashedStorage,
1127 ) -> ProviderResult<StorageMultiProof> {
1128 Ok(StorageMultiProof::empty())
1129 }
1130 }
1131
1132 impl StateProofProvider for MockStateProvider {
1133 fn proof(
1134 &self,
1135 _input: TrieInput,
1136 _address: Address,
1137 _slots: &[B256],
1138 ) -> ProviderResult<AccountProof> {
1139 Ok(AccountProof::new(Address::random()))
1140 }
1141
1142 fn multiproof(
1143 &self,
1144 _input: TrieInput,
1145 _targets: MultiProofTargets,
1146 ) -> ProviderResult<MultiProof> {
1147 Ok(MultiProof::default())
1148 }
1149
1150 fn witness(
1151 &self,
1152 _input: TrieInput,
1153 _target: HashedPostState,
1154 _mode: reth_trie::ExecutionWitnessMode,
1155 ) -> ProviderResult<Vec<Bytes>> {
1156 Ok(Vec::default())
1157 }
1158 }
1159
1160 #[test]
1161 fn test_in_memory_state_impl_state_by_hash() {
1162 let mut state_by_hash = B256Map::default();
1163 let number = rand::rng().random::<u64>();
1164 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1165 let state = Arc::new(create_mock_state(&mut test_block_builder, number, B256::random()));
1166 state_by_hash.insert(state.hash(), state.clone());
1167
1168 let in_memory_state = InMemoryState::new(state_by_hash, BTreeMap::new(), None);
1169
1170 assert_eq!(in_memory_state.state_by_hash(state.hash()), Some(state));
1171 assert_eq!(in_memory_state.state_by_hash(B256::random()), None);
1172 }
1173
1174 #[test]
1175 fn test_in_memory_state_impl_state_by_number() {
1176 let mut state_by_hash = B256Map::default();
1177 let mut hash_by_number = BTreeMap::new();
1178
1179 let number = rand::rng().random::<u64>();
1180 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1181 let state = Arc::new(create_mock_state(&mut test_block_builder, number, B256::random()));
1182 let hash = state.hash();
1183
1184 state_by_hash.insert(hash, state.clone());
1185 hash_by_number.insert(number, hash);
1186
1187 let in_memory_state = InMemoryState::new(state_by_hash, hash_by_number, None);
1188
1189 assert_eq!(in_memory_state.state_by_number(number), Some(state));
1190 assert_eq!(in_memory_state.state_by_number(number + 1), None);
1191 }
1192
1193 #[test]
1194 fn test_in_memory_state_impl_head_state() {
1195 let mut state_by_hash = B256Map::default();
1196 let mut hash_by_number = BTreeMap::new();
1197 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1198 let state1 = Arc::new(create_mock_state(&mut test_block_builder, 1, B256::random()));
1199 let hash1 = state1.hash();
1200 let state2 = Arc::new(create_mock_state(&mut test_block_builder, 2, hash1));
1201 let hash2 = state2.hash();
1202 hash_by_number.insert(1, hash1);
1203 hash_by_number.insert(2, hash2);
1204 state_by_hash.insert(hash1, state1);
1205 state_by_hash.insert(hash2, state2);
1206
1207 let in_memory_state = InMemoryState::new(state_by_hash, hash_by_number, None);
1208 let head_state = in_memory_state.head_state().unwrap();
1209
1210 assert_eq!(head_state.hash(), hash2);
1211 assert_eq!(head_state.number(), 2);
1212 }
1213
1214 #[test]
1215 fn test_in_memory_state_impl_pending_state() {
1216 let pending_number = rand::rng().random::<u64>();
1217 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1218 let pending_state =
1219 create_mock_state(&mut test_block_builder, pending_number, B256::random());
1220 let pending_hash = pending_state.hash();
1221
1222 let in_memory_state =
1223 InMemoryState::new(B256Map::default(), BTreeMap::new(), Some(pending_state));
1224
1225 let result = in_memory_state.pending_state();
1226 assert!(result.is_some());
1227 let actual_pending_state = result.unwrap();
1228 assert_eq!(actual_pending_state.block.recovered_block().hash(), pending_hash);
1229 assert_eq!(actual_pending_state.block.recovered_block().number, pending_number);
1230 }
1231
1232 #[test]
1233 fn test_in_memory_state_impl_no_pending_state() {
1234 let in_memory_state: InMemoryState =
1235 InMemoryState::new(B256Map::default(), BTreeMap::new(), None);
1236
1237 assert_eq!(in_memory_state.pending_state(), None);
1238 }
1239
1240 #[test]
1241 fn test_state() {
1242 let number = rand::rng().random::<u64>();
1243 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1244 let block = test_block_builder.get_executed_block_with_number(number, B256::random());
1245
1246 let state = BlockState::new(block.clone());
1247
1248 assert_eq!(state.block(), block);
1249 assert_eq!(state.hash(), block.recovered_block().hash());
1250 assert_eq!(state.number(), number);
1251 assert_eq!(state.state_root(), block.recovered_block().state_root);
1252 }
1253
1254 #[test]
1255 fn test_state_receipts() {
1256 let receipts = vec![vec![Receipt::default()]];
1257 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1258 let block =
1259 test_block_builder.get_executed_block_with_receipts(receipts.clone(), B256::random());
1260
1261 let state = BlockState::new(block);
1262
1263 assert_eq!(state.receipts(), receipts.first().unwrap());
1264 }
1265
1266 #[test]
1267 fn test_in_memory_state_chain_update() {
1268 let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1269 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1270 let block1 = test_block_builder.get_executed_block_with_number(0, B256::random());
1271 let block2 = test_block_builder.get_executed_block_with_number(0, B256::random());
1272 let chain = NewCanonicalChain::Commit { new: vec![block1.clone()] };
1273 state.update_chain(chain);
1274 assert_eq!(
1275 state.head_state().unwrap().block_ref().recovered_block().hash(),
1276 block1.recovered_block().hash()
1277 );
1278 assert_eq!(
1279 state.state_by_number(0).unwrap().block_ref().recovered_block().hash(),
1280 block1.recovered_block().hash()
1281 );
1282
1283 let chain = NewCanonicalChain::Reorg { new: vec![block2.clone()], old: vec![block1] };
1284 state.update_chain(chain);
1285 assert_eq!(
1286 state.head_state().unwrap().block_ref().recovered_block().hash(),
1287 block2.recovered_block().hash()
1288 );
1289 assert_eq!(
1290 state.state_by_number(0).unwrap().block_ref().recovered_block().hash(),
1291 block2.recovered_block().hash()
1292 );
1293
1294 assert_eq!(state.inner.in_memory_state.block_count(), 1);
1295 }
1296
1297 #[test]
1298 fn test_in_memory_state_set_pending_block() {
1299 let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1300 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1301
1302 let block1 = test_block_builder.get_executed_block_with_number(0, B256::random());
1304
1305 let block2 =
1307 test_block_builder.get_executed_block_with_number(1, block1.recovered_block().hash());
1308
1309 let chain = NewCanonicalChain::Commit { new: vec![block1.clone(), block2.clone()] };
1311 state.update_chain(chain);
1312
1313 assert!(state.pending_state().is_none());
1315
1316 state.set_pending_block(block2.clone());
1318
1319 assert_eq!(
1321 state.pending_state().unwrap(),
1322 BlockState::with_parent(block2.clone(), Some(Arc::new(BlockState::new(block1))))
1323 );
1324
1325 assert_eq!(state.pending_block().unwrap(), block2.recovered_block().sealed_block().clone());
1327
1328 assert_eq!(
1330 state.pending_block_num_hash().unwrap(),
1331 BlockNumHash { number: 1, hash: block2.recovered_block().hash() }
1332 );
1333
1334 assert_eq!(state.pending_header().unwrap(), block2.recovered_block().header().clone());
1336
1337 assert_eq!(
1339 state.pending_sealed_header().unwrap(),
1340 block2.recovered_block().clone_sealed_header()
1341 );
1342
1343 assert_eq!(state.pending_recovered_block().unwrap(), block2.recovered_block().clone());
1345
1346 assert_eq!(
1348 state.pending_block_and_receipts().unwrap(),
1349 (block2.recovered_block().clone(), vec![])
1350 );
1351 }
1352
1353 #[test]
1354 fn test_canonical_in_memory_state_state_provider() {
1355 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1356 let block1 = test_block_builder.get_executed_block_with_number(1, B256::random());
1357 let block2 =
1358 test_block_builder.get_executed_block_with_number(2, block1.recovered_block().hash());
1359 let block3 =
1360 test_block_builder.get_executed_block_with_number(3, block2.recovered_block().hash());
1361
1362 let state1 = Arc::new(BlockState::new(block1.clone()));
1363 let state2 = Arc::new(BlockState::with_parent(block2.clone(), Some(state1.clone())));
1364 let state3 = Arc::new(BlockState::with_parent(block3.clone(), Some(state2.clone())));
1365
1366 let mut blocks = B256Map::default();
1367 blocks.insert(block1.recovered_block().hash(), state1);
1368 blocks.insert(block2.recovered_block().hash(), state2);
1369 blocks.insert(block3.recovered_block().hash(), state3);
1370
1371 let mut numbers = BTreeMap::new();
1372 numbers.insert(1, block1.recovered_block().hash());
1373 numbers.insert(2, block2.recovered_block().hash());
1374 numbers.insert(3, block3.recovered_block().hash());
1375
1376 let canonical_state = CanonicalInMemoryState::new(blocks, numbers, None, None, None);
1377
1378 let historical: StateProviderBox = Box::new(MockStateProvider);
1379
1380 let overlay_provider =
1381 canonical_state.state_provider(block3.recovered_block().hash(), historical);
1382
1383 assert_eq!(overlay_provider.in_memory.len(), 3);
1384 assert_eq!(overlay_provider.in_memory[0].recovered_block().number, 3);
1385 assert_eq!(overlay_provider.in_memory[1].recovered_block().number, 2);
1386 assert_eq!(overlay_provider.in_memory[2].recovered_block().number, 1);
1387
1388 assert_eq!(
1389 overlay_provider.in_memory[0].recovered_block().parent_hash,
1390 overlay_provider.in_memory[1].recovered_block().hash()
1391 );
1392 assert_eq!(
1393 overlay_provider.in_memory[1].recovered_block().parent_hash,
1394 overlay_provider.in_memory[2].recovered_block().hash()
1395 );
1396
1397 let unknown_hash = B256::random();
1398 let empty_overlay_provider =
1399 canonical_state.state_provider(unknown_hash, Box::new(MockStateProvider));
1400 assert_eq!(empty_overlay_provider.in_memory.len(), 0);
1401 }
1402
1403 #[test]
1404 fn test_canonical_in_memory_state_canonical_chain_empty() {
1405 let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1406 assert!(state.canonical_chain().next().is_none());
1407 }
1408
1409 #[test]
1410 fn test_canonical_in_memory_state_canonical_chain_single_block() {
1411 let block = TestBlockBuilder::eth().get_executed_block_with_number(1, B256::random());
1412 let hash = block.recovered_block().hash();
1413 let mut blocks = B256Map::default();
1414 blocks.insert(hash, Arc::new(BlockState::new(block)));
1415 let mut numbers = BTreeMap::new();
1416 numbers.insert(1, hash);
1417
1418 let state = CanonicalInMemoryState::new(blocks, numbers, None, None, None);
1419 let chain: Vec<_> = state.canonical_chain().collect();
1420
1421 assert_eq!(chain.len(), 1);
1422 assert_eq!(chain[0].number(), 1);
1423 assert_eq!(chain[0].hash(), hash);
1424 }
1425
1426 #[test]
1427 fn test_canonical_in_memory_state_canonical_chain_multiple_blocks() {
1428 let mut parent_hash = B256::random();
1429 let mut block_builder = TestBlockBuilder::eth();
1430 let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1431
1432 for i in 1..=3 {
1433 let block = block_builder.get_executed_block_with_number(i, parent_hash);
1434 let hash = block.recovered_block().hash();
1435 state.update_blocks(Some(block), None);
1436 parent_hash = hash;
1437 }
1438
1439 let chain: Vec<_> = state.canonical_chain().collect();
1440
1441 assert_eq!(chain.len(), 3);
1442 assert_eq!(chain[0].number(), 3);
1443 assert_eq!(chain[1].number(), 2);
1444 assert_eq!(chain[2].number(), 1);
1445 }
1446
1447 #[test]
1449 fn test_canonical_in_memory_state_canonical_chain_with_pending_block() {
1450 let mut parent_hash = B256::random();
1451 let mut block_builder = TestBlockBuilder::<EthPrimitives>::eth();
1452 let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1453
1454 for i in 1..=2 {
1455 let block = block_builder.get_executed_block_with_number(i, parent_hash);
1456 let hash = block.recovered_block().hash();
1457 state.update_blocks(Some(block), None);
1458 parent_hash = hash;
1459 }
1460
1461 let pending_block = block_builder.get_executed_block_with_number(3, parent_hash);
1462 state.set_pending_block(pending_block);
1463 let chain: Vec<_> = state.canonical_chain().collect();
1464
1465 assert_eq!(chain.len(), 2);
1466 assert_eq!(chain[0].number(), 2);
1467 assert_eq!(chain[1].number(), 1);
1468 }
1469
1470 #[test]
1471 fn test_block_state_parent_blocks() {
1472 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1473 let chain = create_mock_state_chain(&mut test_block_builder, 4);
1474
1475 let parents: Vec<_> = chain[3].parent_state_chain().collect();
1476 assert_eq!(parents.len(), 3);
1477 assert_eq!(parents[0].block().recovered_block().number, 3);
1478 assert_eq!(parents[1].block().recovered_block().number, 2);
1479 assert_eq!(parents[2].block().recovered_block().number, 1);
1480
1481 let parents: Vec<_> = chain[2].parent_state_chain().collect();
1482 assert_eq!(parents.len(), 2);
1483 assert_eq!(parents[0].block().recovered_block().number, 2);
1484 assert_eq!(parents[1].block().recovered_block().number, 1);
1485
1486 assert_eq!(chain[0].parent_state_chain().count(), 0);
1487 }
1488
1489 #[test]
1490 fn test_block_state_single_block_state_chain() {
1491 let single_block_number = 1;
1492 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1493 let single_block =
1494 create_mock_state(&mut test_block_builder, single_block_number, B256::random());
1495 let single_block_hash = single_block.block().recovered_block().hash();
1496
1497 assert_eq!(single_block.parent_state_chain().count(), 0);
1498
1499 let block_state_chain = single_block.chain().collect::<Vec<_>>();
1500 assert_eq!(block_state_chain.len(), 1);
1501 assert_eq!(block_state_chain[0].block().recovered_block().number, single_block_number);
1502 assert_eq!(block_state_chain[0].block().recovered_block().hash(), single_block_hash);
1503 }
1504
1505 #[test]
1506 fn test_block_state_chain() {
1507 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1508 let chain = create_mock_state_chain(&mut test_block_builder, 3);
1509
1510 let block_state_chain = chain[2].chain().collect::<Vec<_>>();
1511 assert_eq!(block_state_chain.len(), 3);
1512 assert_eq!(block_state_chain[0].block().recovered_block().number, 3);
1513 assert_eq!(block_state_chain[1].block().recovered_block().number, 2);
1514 assert_eq!(block_state_chain[2].block().recovered_block().number, 1);
1515
1516 let block_state_chain = chain[1].chain().collect::<Vec<_>>();
1517 assert_eq!(block_state_chain.len(), 2);
1518 assert_eq!(block_state_chain[0].block().recovered_block().number, 2);
1519 assert_eq!(block_state_chain[1].block().recovered_block().number, 1);
1520
1521 let block_state_chain = chain[0].chain().collect::<Vec<_>>();
1522 assert_eq!(block_state_chain.len(), 1);
1523 assert_eq!(block_state_chain[0].block().recovered_block().number, 1);
1524 }
1525
1526 #[test]
1527 fn test_to_chain_notification() {
1528 let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1530 let block0 = test_block_builder.get_executed_block_with_number(0, B256::random());
1531 let block1 =
1532 test_block_builder.get_executed_block_with_number(1, block0.recovered_block.hash());
1533 let block1a =
1534 test_block_builder.get_executed_block_with_number(1, block0.recovered_block.hash());
1535 let block2 =
1536 test_block_builder.get_executed_block_with_number(2, block1.recovered_block.hash());
1537 let block2a =
1538 test_block_builder.get_executed_block_with_number(2, block1.recovered_block.hash());
1539
1540 let chain_commit = NewCanonicalChain::Commit { new: vec![block0.clone(), block1.clone()] };
1542
1543 let mut expected_trie_data = BTreeMap::new();
1545 expected_trie_data
1546 .insert(0, LazyTrieData::ready(block0.hashed_state(), block0.trie_updates()));
1547 expected_trie_data
1548 .insert(1, LazyTrieData::ready(block1.hashed_state(), block1.trie_updates()));
1549
1550 let commit_execution_outcome = ExecutionOutcome {
1552 receipts: vec![vec![], vec![]],
1553 requests: vec![Requests::default(), Requests::default()],
1554 first_block: 0,
1555 ..Default::default()
1556 };
1557
1558 assert_eq!(
1559 chain_commit.to_chain_notification(),
1560 CanonStateNotification::Commit {
1561 new: Arc::new(Chain::new(
1562 vec![block0.recovered_block().clone(), block1.recovered_block().clone()],
1563 commit_execution_outcome,
1564 expected_trie_data,
1565 ))
1566 }
1567 );
1568
1569 let chain_reorg = NewCanonicalChain::Reorg {
1571 new: vec![block1a.clone(), block2a.clone()],
1572 old: vec![block1.clone(), block2.clone()],
1573 };
1574
1575 let mut old_trie_data = BTreeMap::new();
1577 old_trie_data.insert(1, LazyTrieData::ready(block1.hashed_state(), block1.trie_updates()));
1578 old_trie_data.insert(2, LazyTrieData::ready(block2.hashed_state(), block2.trie_updates()));
1579
1580 let mut new_trie_data = BTreeMap::new();
1582 new_trie_data
1583 .insert(1, LazyTrieData::ready(block1a.hashed_state(), block1a.trie_updates()));
1584 new_trie_data
1585 .insert(2, LazyTrieData::ready(block2a.hashed_state(), block2a.trie_updates()));
1586
1587 let reorg_execution_outcome = ExecutionOutcome {
1590 receipts: vec![vec![], vec![]],
1591 requests: vec![Requests::default(), Requests::default()],
1592 first_block: 1,
1593 ..Default::default()
1594 };
1595
1596 assert_eq!(
1597 chain_reorg.to_chain_notification(),
1598 CanonStateNotification::Reorg {
1599 old: Arc::new(Chain::new(
1600 vec![block1.recovered_block().clone(), block2.recovered_block().clone()],
1601 reorg_execution_outcome.clone(),
1602 old_trie_data,
1603 )),
1604 new: Arc::new(Chain::new(
1605 vec![block1a.recovered_block().clone(), block2a.recovered_block().clone()],
1606 reorg_execution_outcome,
1607 new_trie_data,
1608 ))
1609 }
1610 );
1611 }
1612}