reth_chain_state/
in_memory.rs

1//! Types for tracking the canonical chain state in memory.
2
3use 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::HashMap, BlockNumber, TxHash, B256};
10use parking_lot::RwLock;
11use reth_chainspec::ChainInfo;
12use reth_ethereum_primitives::EthPrimitives;
13use reth_execution_types::{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, TrieInputSorted};
21use std::{collections::BTreeMap, ops::Deref, sync::Arc, time::Instant};
22use tokio::sync::{broadcast, watch};
23
24/// Size of the broadcast channel used to notify canonical state events.
25const CANON_STATE_NOTIFICATION_CHANNEL_SIZE: usize = 256;
26
27/// Metrics for the in-memory state.
28#[derive(Metrics)]
29#[metrics(scope = "blockchain_tree.in_mem_state")]
30pub(crate) struct InMemoryStateMetrics {
31    /// The block number of the earliest block in the in-memory state.
32    pub(crate) earliest_block: Gauge,
33    /// The block number of the latest block in the in-memory state.
34    pub(crate) latest_block: Gauge,
35    /// The number of blocks in the in-memory state.
36    pub(crate) num_blocks: Gauge,
37}
38
39/// Container type for in memory state data of the canonical chain.
40///
41/// This tracks blocks and their state that haven't been persisted to disk yet but are part of the
42/// canonical chain that can be traced back to a canonical block on disk.
43///
44/// # Locking behavior on state updates
45///
46/// All update calls must acquire all locks at once before modifying state to ensure the internal
47/// state remains consistent. This prevents readers from observing partially updated state where
48/// the numbers and blocks maps are out of sync.
49/// Update functions ensure that the numbers write lock is always acquired first, because lookup by
50/// numbers first read the numbers map and then the blocks map.
51/// By acquiring the numbers lock first, we ensure that read-only lookups don't deadlock updates.
52/// This holds, because only lookup by number functions need to acquire the numbers lock first to
53/// get the block hash.
54#[derive(Debug, Default)]
55pub(crate) struct InMemoryState<N: NodePrimitives = EthPrimitives> {
56    /// All canonical blocks that are not on disk yet.
57    blocks: RwLock<HashMap<B256, Arc<BlockState<N>>>>,
58    /// Mapping of block numbers to block hashes.
59    numbers: RwLock<BTreeMap<u64, B256>>,
60    /// The pending block that has not yet been made canonical.
61    pending: watch::Sender<Option<BlockState<N>>>,
62    /// Metrics for the in-memory state.
63    metrics: InMemoryStateMetrics,
64}
65
66impl<N: NodePrimitives> InMemoryState<N> {
67    pub(crate) fn new(
68        blocks: HashMap<B256, 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    /// Update the metrics for the in-memory state.
84    ///
85    /// # Locking behavior
86    ///
87    /// This tries to acquire a read lock. Drop any write locks before calling this.
88    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    /// Returns the state for a given block hash.
106    pub(crate) fn state_by_hash(&self, hash: B256) -> Option<Arc<BlockState<N>>> {
107        self.blocks.read().get(&hash).cloned()
108    }
109
110    /// Returns the state for a given block number.
111    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    /// Returns the hash for a specific block number
117    pub(crate) fn hash_by_number(&self, number: u64) -> Option<B256> {
118        self.numbers.read().get(&number).copied()
119    }
120
121    /// Returns the current chain head state.
122    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    /// Returns the pending state corresponding to the current head plus one,
128    /// from the payload received in newPayload that does not have a FCU yet.
129    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/// Inner type to provide in memory state. It includes a chain tracker to be
140/// advanced internally by the tree.
141#[derive(Debug)]
142pub(crate) struct CanonicalInMemoryStateInner<N: NodePrimitives> {
143    /// Tracks certain chain information, such as the canonical head, safe head, and finalized
144    /// head.
145    pub(crate) chain_info_tracker: ChainInfoTracker<N>,
146    /// Tracks blocks at the tip of the chain that have not been persisted to disk yet.
147    pub(crate) in_memory_state: InMemoryState<N>,
148    /// A broadcast stream that emits events when the canonical chain is updated.
149    pub(crate) canon_state_notification_sender: CanonStateNotificationSender<N>,
150}
151
152impl<N: NodePrimitives> CanonicalInMemoryStateInner<N> {
153    /// Clears all entries in the in memory state.
154    fn clear(&self) {
155        {
156            // acquire locks, starting with the numbers lock
157            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/// This type is responsible for providing the blocks, receipts, and state for
173/// all canonical blocks not on disk yet and keeps track of the block range that
174/// is in memory.
175#[derive(Debug, Clone)]
176pub struct CanonicalInMemoryState<N: NodePrimitives = EthPrimitives> {
177    pub(crate) inner: Arc<CanonicalInMemoryStateInner<N>>,
178}
179
180impl<N: NodePrimitives> CanonicalInMemoryState<N> {
181    /// Create a new in-memory state with the given blocks, numbers, pending state, and optional
182    /// finalized header.
183    pub fn new(
184        blocks: HashMap<B256, 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    /// Create an empty state.
208    pub fn empty() -> Self {
209        Self::new(HashMap::default(), BTreeMap::new(), None, None, None)
210    }
211
212    /// Create a new in memory state with the given local head and finalized header
213    /// if it exists.
214    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    /// Returns the block hash corresponding to the given number.
233    pub fn hash_by_number(&self, number: u64) -> Option<B256> {
234        self.inner.in_memory_state.hash_by_number(number)
235    }
236
237    /// Returns the header corresponding to the given hash.
238    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    /// Clears all entries in the in memory state.
244    pub fn clear_state(&self) {
245        self.inner.clear()
246    }
247
248    /// Updates the pending block with the given block.
249    ///
250    /// Note: This assumes that the parent block of the pending block is canonical.
251    pub fn set_pending_block(&self, pending: ExecutedBlock<N>) {
252        // fetch the state of the pending block's parent block
253        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    /// Append new blocks to the in memory state.
262    ///
263    /// This removes all reorged blocks and appends the new blocks to the tracked chain and connects
264    /// them to their parent blocks.
265    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            // acquire locks, starting with the numbers lock
272            let mut numbers = self.inner.in_memory_state.numbers.write();
273            let mut blocks = self.inner.in_memory_state.blocks.write();
274
275            // we first remove the blocks from the reorged chain
276            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            // insert the new blocks
284            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                // append new blocks
291                blocks.insert(hash, Arc::new(block_state));
292                numbers.insert(number, hash);
293            }
294
295            // remove the pending state
296            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    /// Update the in memory state with the given chain update.
304    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    /// Removes blocks from the in memory state that are persisted to the given height.
316    ///
317    /// This will update the links between blocks and remove all blocks that are [..
318    /// `persisted_height`].
319    pub fn remove_persisted_blocks(&self, persisted_num_hash: BlockNumHash) {
320        // if the persisted hash is not in the canonical in memory state, do nothing, because it
321        // means canonical blocks were not actually persisted.
322        //
323        // This can happen if the persistence task takes a long time, while a reorg is happening.
324        {
325            if self.inner.in_memory_state.blocks.read().get(&persisted_num_hash.hash).is_none() {
326                // do nothing
327                return
328            }
329        }
330
331        {
332            // acquire locks, starting with the numbers lock
333            let mut numbers = self.inner.in_memory_state.numbers.write();
334            let mut blocks = self.inner.in_memory_state.blocks.write();
335
336            let BlockNumHash { number: persisted_height, hash: _ } = persisted_num_hash;
337
338            // clear all numbers
339            numbers.clear();
340
341            // drain all blocks and only keep the ones that are not persisted (below the persisted
342            // height)
343            let mut old_blocks = blocks
344                .drain()
345                .filter(|(_, b)| b.block_ref().recovered_block().number() > persisted_height)
346                .map(|(_, b)| b.block.clone())
347                .collect::<Vec<_>>();
348
349            // sort the blocks by number so we can insert them back in natural order (low -> high)
350            old_blocks.sort_unstable_by_key(|block| block.recovered_block().number());
351
352            // re-insert the blocks in natural order and connect them to their parent blocks
353            for block in old_blocks {
354                let parent = blocks.get(&block.recovered_block().parent_hash()).cloned();
355                let block_state = BlockState::with_parent(block, parent);
356                let hash = block_state.hash();
357                let number = block_state.number();
358
359                // append new blocks
360                blocks.insert(hash, Arc::new(block_state));
361                numbers.insert(number, hash);
362            }
363
364            // also shift the pending state if it exists
365            self.inner.in_memory_state.pending.send_modify(|p| {
366                if let Some(p) = p.as_mut() {
367                    p.parent = blocks.get(&p.block_ref().recovered_block().parent_hash()).cloned();
368                }
369            });
370        }
371        self.inner.in_memory_state.update_metrics();
372    }
373
374    /// Returns in memory state corresponding the given hash.
375    pub fn state_by_hash(&self, hash: B256) -> Option<Arc<BlockState<N>>> {
376        self.inner.in_memory_state.state_by_hash(hash)
377    }
378
379    /// Returns in memory state corresponding the block number.
380    pub fn state_by_number(&self, number: u64) -> Option<Arc<BlockState<N>>> {
381        self.inner.in_memory_state.state_by_number(number)
382    }
383
384    /// Returns the in memory head state.
385    pub fn head_state(&self) -> Option<Arc<BlockState<N>>> {
386        self.inner.in_memory_state.head_state()
387    }
388
389    /// Returns the in memory pending state.
390    pub fn pending_state(&self) -> Option<BlockState<N>> {
391        self.inner.in_memory_state.pending_state()
392    }
393
394    /// Returns the in memory pending `BlockNumHash`.
395    pub fn pending_block_num_hash(&self) -> Option<BlockNumHash> {
396        self.inner
397            .in_memory_state
398            .pending_state()
399            .map(|state| BlockNumHash { number: state.number(), hash: state.hash() })
400    }
401
402    /// Returns the current `ChainInfo`.
403    pub fn chain_info(&self) -> ChainInfo {
404        self.inner.chain_info_tracker.chain_info()
405    }
406
407    /// Returns the latest canonical block number.
408    pub fn get_canonical_block_number(&self) -> u64 {
409        self.inner.chain_info_tracker.get_canonical_block_number()
410    }
411
412    /// Returns the `BlockNumHash` of the safe head.
413    pub fn get_safe_num_hash(&self) -> Option<BlockNumHash> {
414        self.inner.chain_info_tracker.get_safe_num_hash()
415    }
416
417    /// Returns the `BlockNumHash` of the finalized head.
418    pub fn get_finalized_num_hash(&self) -> Option<BlockNumHash> {
419        self.inner.chain_info_tracker.get_finalized_num_hash()
420    }
421
422    /// Hook for new fork choice update.
423    pub fn on_forkchoice_update_received(&self) {
424        self.inner.chain_info_tracker.on_forkchoice_update_received();
425    }
426
427    /// Returns the timestamp of the last received update.
428    pub fn last_received_update_timestamp(&self) -> Option<Instant> {
429        self.inner.chain_info_tracker.last_forkchoice_update_received_at()
430    }
431
432    /// Canonical head setter.
433    pub fn set_canonical_head(&self, header: SealedHeader<N::BlockHeader>) {
434        self.inner.chain_info_tracker.set_canonical_head(header);
435    }
436
437    /// Safe head setter.
438    pub fn set_safe(&self, header: SealedHeader<N::BlockHeader>) {
439        self.inner.chain_info_tracker.set_safe(header);
440    }
441
442    /// Finalized head setter.
443    pub fn set_finalized(&self, header: SealedHeader<N::BlockHeader>) {
444        self.inner.chain_info_tracker.set_finalized(header);
445    }
446
447    /// Canonical head getter.
448    pub fn get_canonical_head(&self) -> SealedHeader<N::BlockHeader> {
449        self.inner.chain_info_tracker.get_canonical_head()
450    }
451
452    /// Finalized header getter.
453    pub fn get_finalized_header(&self) -> Option<SealedHeader<N::BlockHeader>> {
454        self.inner.chain_info_tracker.get_finalized_header()
455    }
456
457    /// Safe header getter.
458    pub fn get_safe_header(&self) -> Option<SealedHeader<N::BlockHeader>> {
459        self.inner.chain_info_tracker.get_safe_header()
460    }
461
462    /// Returns the `SealedHeader` corresponding to the pending state.
463    pub fn pending_sealed_header(&self) -> Option<SealedHeader<N::BlockHeader>> {
464        self.pending_state().map(|h| h.block_ref().recovered_block().clone_sealed_header())
465    }
466
467    /// Returns the `Header` corresponding to the pending state.
468    pub fn pending_header(&self) -> Option<N::BlockHeader> {
469        self.pending_sealed_header().map(|sealed_header| sealed_header.unseal())
470    }
471
472    /// Returns the `SealedBlock` corresponding to the pending state.
473    pub fn pending_block(&self) -> Option<SealedBlock<N::Block>> {
474        self.pending_state()
475            .map(|block_state| block_state.block_ref().recovered_block().sealed_block().clone())
476    }
477
478    /// Returns the `RecoveredBlock` corresponding to the pending state.
479    pub fn pending_recovered_block(&self) -> Option<RecoveredBlock<N::Block>>
480    where
481        N::SignedTx: SignedTransaction,
482    {
483        self.pending_state().map(|block_state| block_state.block_ref().recovered_block().clone())
484    }
485
486    /// Returns a tuple with the `SealedBlock` corresponding to the pending
487    /// state and a vector of its `Receipt`s.
488    pub fn pending_block_and_receipts(&self) -> Option<PendingBlockAndReceipts<N>> {
489        self.pending_state().map(|block_state| {
490            (
491                block_state.block_ref().recovered_block().clone(),
492                block_state.executed_block_receipts(),
493            )
494        })
495    }
496
497    /// Subscribe to new blocks events.
498    pub fn subscribe_canon_state(&self) -> CanonStateNotifications<N> {
499        self.inner.canon_state_notification_sender.subscribe()
500    }
501
502    /// Subscribe to new safe block events.
503    pub fn subscribe_safe_block(&self) -> watch::Receiver<Option<SealedHeader<N::BlockHeader>>> {
504        self.inner.chain_info_tracker.subscribe_safe_block()
505    }
506
507    /// Subscribe to new finalized block events.
508    pub fn subscribe_finalized_block(
509        &self,
510    ) -> watch::Receiver<Option<SealedHeader<N::BlockHeader>>> {
511        self.inner.chain_info_tracker.subscribe_finalized_block()
512    }
513
514    /// Attempts to send a new [`CanonStateNotification`] to all active Receiver handles.
515    pub fn notify_canon_state(&self, event: CanonStateNotification<N>) {
516        self.inner.canon_state_notification_sender.send(event).ok();
517    }
518
519    /// Return state provider with reference to in-memory blocks that overlay database state.
520    ///
521    /// This merges the state of all blocks that are part of the chain that the requested block is
522    /// the head of. This includes all blocks that connect back to the canonical block on disk.
523    pub fn state_provider(
524        &self,
525        hash: B256,
526        historical: StateProviderBox,
527    ) -> MemoryOverlayStateProvider<N> {
528        let in_memory = if let Some(state) = self.state_by_hash(hash) {
529            state.chain().map(|block_state| block_state.block()).collect()
530        } else {
531            Vec::new()
532        };
533
534        MemoryOverlayStateProvider::new(historical, in_memory)
535    }
536
537    /// Returns an iterator over all __canonical blocks__ in the in-memory state, from newest to
538    /// oldest (highest to lowest).
539    ///
540    /// This iterator contains a snapshot of the in-memory state at the time of the call.
541    pub fn canonical_chain(&self) -> impl Iterator<Item = Arc<BlockState<N>>> {
542        self.inner.in_memory_state.head_state().into_iter().flat_map(|head| head.iter())
543    }
544
545    /// Returns [`SignedTransaction`] type for the given `TxHash` if found.
546    pub fn transaction_by_hash(&self, hash: TxHash) -> Option<N::SignedTx> {
547        for block_state in self.canonical_chain() {
548            if let Some(tx) =
549                block_state.block_ref().recovered_block().body().transaction_by_hash(&hash)
550            {
551                return Some(tx.clone())
552            }
553        }
554        None
555    }
556
557    /// Returns a tuple with [`SignedTransaction`] type and [`TransactionMeta`] for the
558    /// given [`TxHash`] if found.
559    pub fn transaction_by_hash_with_meta(
560        &self,
561        tx_hash: TxHash,
562    ) -> Option<(N::SignedTx, TransactionMeta)> {
563        for block_state in self.canonical_chain() {
564            if let Some(indexed) = block_state.find_indexed(tx_hash) {
565                return Some((indexed.tx().clone(), indexed.meta()));
566            }
567        }
568        None
569    }
570}
571
572/// State after applying the given block, this block is part of the canonical chain that partially
573/// stored in memory and can be traced back to a canonical block on disk.
574#[derive(Debug, Clone)]
575pub struct BlockState<N: NodePrimitives = EthPrimitives> {
576    /// The executed block that determines the state after this block has been executed.
577    block: ExecutedBlock<N>,
578    /// The block's parent block if it exists.
579    parent: Option<Arc<Self>>,
580}
581
582impl<N: NodePrimitives> PartialEq for BlockState<N> {
583    fn eq(&self, other: &Self) -> bool {
584        self.block == other.block && self.parent == other.parent
585    }
586}
587
588impl<N: NodePrimitives> BlockState<N> {
589    /// [`BlockState`] constructor.
590    pub const fn new(block: ExecutedBlock<N>) -> Self {
591        Self { block, parent: None }
592    }
593
594    /// [`BlockState`] constructor with parent.
595    pub const fn with_parent(block: ExecutedBlock<N>, parent: Option<Arc<Self>>) -> Self {
596        Self { block, parent }
597    }
598
599    /// Returns the hash and block of the on disk block this state can be traced back to.
600    pub fn anchor(&self) -> BlockNumHash {
601        let mut current = self;
602        while let Some(parent) = &current.parent {
603            current = parent;
604        }
605        current.block.recovered_block().parent_num_hash()
606    }
607
608    /// Returns the executed block that determines the state.
609    pub fn block(&self) -> ExecutedBlock<N> {
610        self.block.clone()
611    }
612
613    /// Returns a reference to the executed block that determines the state.
614    pub const fn block_ref(&self) -> &ExecutedBlock<N> {
615        &self.block
616    }
617
618    /// Returns the hash of executed block that determines the state.
619    pub fn hash(&self) -> B256 {
620        self.block.recovered_block().hash()
621    }
622
623    /// Returns the block number of executed block that determines the state.
624    pub fn number(&self) -> u64 {
625        self.block.recovered_block().number()
626    }
627
628    /// Returns the state root after applying the executed block that determines
629    /// the state.
630    pub fn state_root(&self) -> B256 {
631        self.block.recovered_block().state_root()
632    }
633
634    /// Returns the `Receipts` of executed block that determines the state.
635    pub fn receipts(&self) -> &Vec<Vec<N::Receipt>> {
636        &self.block.execution_outcome().receipts
637    }
638
639    /// Returns a vector of `Receipt` of executed block that determines the state.
640    /// We assume that the `Receipts` in the executed block `ExecutionOutcome`
641    /// has only one element corresponding to the executed block associated to
642    /// the state.
643    ///
644    /// This clones the vector of receipts. To avoid it, use [`Self::executed_block_receipts_ref`].
645    pub fn executed_block_receipts(&self) -> Vec<N::Receipt> {
646        let receipts = self.receipts();
647
648        debug_assert!(
649            receipts.len() <= 1,
650            "Expected at most one block's worth of receipts, found {}",
651            receipts.len()
652        );
653
654        receipts.first().cloned().unwrap_or_default()
655    }
656
657    /// Returns a slice of `Receipt` of executed block that determines the state.
658    /// We assume that the `Receipts` in the executed block `ExecutionOutcome`
659    /// has only one element corresponding to the executed block associated to
660    /// the state.
661    pub fn executed_block_receipts_ref(&self) -> &[N::Receipt] {
662        let receipts = self.receipts();
663
664        debug_assert!(
665            receipts.len() <= 1,
666            "Expected at most one block's worth of receipts, found {}",
667            receipts.len()
668        );
669
670        receipts.first().map(|receipts| receipts.deref()).unwrap_or_default()
671    }
672
673    /// Returns an iterator over __parent__ `BlockStates`.
674    ///
675    /// The block state order is newest to oldest (highest to lowest):
676    /// `[5,4,3,2,1]`
677    ///
678    /// Note: This does not include self.
679    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    /// Returns a vector of `BlockStates` representing the entire in memory chain.
684    /// The block state order in the output vector is newest to oldest (highest to lowest),
685    /// including self as the first element.
686    pub fn chain(&self) -> impl Iterator<Item = &Self> {
687        std::iter::successors(Some(self), |state| state.parent.as_deref())
688    }
689
690    /// Appends the parent chain of this [`BlockState`] to the given vector.
691    ///
692    /// Parents are appended in order from newest to oldest (highest to lowest).
693    /// This does not include self, only the parent states.
694    ///
695    /// This is a convenience method equivalent to `chain.extend(self.parent_state_chain())`.
696    pub fn append_parent_chain<'a>(&'a self, chain: &mut Vec<&'a Self>) {
697        chain.extend(self.parent_state_chain());
698    }
699
700    /// Returns an iterator over the atomically captured chain of in memory blocks.
701    ///
702    /// This yields the blocks from newest to oldest (highest to lowest).
703    pub fn iter(self: Arc<Self>) -> impl Iterator<Item = Arc<Self>> {
704        std::iter::successors(Some(self), |state| state.parent.clone())
705    }
706
707    /// Return state provider with reference to in-memory blocks that overlay database state.
708    ///
709    /// This merges the state of all blocks that are part of the chain that the this block is
710    /// the head of. This includes all blocks that connect back to the canonical block on disk.
711    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    /// Tries to find a block by [`BlockHashOrNumber`] in the chain ending at this block.
718    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    /// Tries to find a transaction by [`TxHash`] in the chain ending at this block.
726    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    /// Tries to find a transaction with meta by [`TxHash`] in the chain ending at this block.
733    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    /// Finds a transaction by hash and returns it with its index and block context.
743    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/// Represents an executed block stored in-memory.
749#[derive(Clone, Debug)]
750pub struct ExecutedBlock<N: NodePrimitives = EthPrimitives> {
751    /// Recovered Block
752    pub recovered_block: Arc<RecoveredBlock<N::Block>>,
753    /// Block's execution outcome.
754    pub execution_output: Arc<ExecutionOutcome<N::Receipt>>,
755    /// Deferred trie data produced by execution.
756    ///
757    /// This allows deferring the computation of the trie data which can be expensive.
758    /// The data can be populated asynchronously after the block was validated.
759    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: Default::default(),
767            trie_data: DeferredTrieData::ready(ComputedTrieData::default()),
768        }
769    }
770}
771
772impl<N: NodePrimitives> PartialEq for ExecutedBlock<N> {
773    fn eq(&self, other: &Self) -> bool {
774        // Trie data is computed asynchronously and doesn't define block identity.
775        self.recovered_block == other.recovered_block &&
776            self.execution_output == other.execution_output
777    }
778}
779
780impl<N: NodePrimitives> ExecutedBlock<N> {
781    /// Create a new [`ExecutedBlock`] with already-computed trie data.
782    ///
783    /// Use this constructor when trie data is available immediately (e.g., sequencers,
784    /// payload builders). This is the safe default path.
785    pub fn new(
786        recovered_block: Arc<RecoveredBlock<N::Block>>,
787        execution_output: Arc<ExecutionOutcome<N::Receipt>>,
788        trie_data: ComputedTrieData,
789    ) -> Self {
790        Self { recovered_block, execution_output, trie_data: DeferredTrieData::ready(trie_data) }
791    }
792
793    /// Create a new [`ExecutedBlock`] with deferred trie data.
794    ///
795    /// This is useful if the trie data is populated somewhere else, e.g. asynchronously
796    /// after the block was validated.
797    ///
798    /// The [`DeferredTrieData`] handle allows expensive trie operations (sorting hashed state,
799    /// sorting trie updates, and building the accumulated trie input overlay) to be performed
800    /// outside the critical validation path. This can improve latency for time-sensitive
801    /// operations like block validation.
802    ///
803    /// If the data hasn't been populated when [`Self::trie_data()`] is called, computation
804    /// occurs synchronously from stored inputs, so there is no blocking or deadlock risk.
805    ///
806    /// Use [`Self::new()`] instead when trie data is already computed and available immediately.
807    pub const fn with_deferred_trie_data(
808        recovered_block: Arc<RecoveredBlock<N::Block>>,
809        execution_output: Arc<ExecutionOutcome<N::Receipt>>,
810        trie_data: DeferredTrieData,
811    ) -> Self {
812        Self { recovered_block, execution_output, trie_data }
813    }
814
815    /// Returns a reference to an inner [`SealedBlock`]
816    #[inline]
817    pub fn sealed_block(&self) -> &SealedBlock<N::Block> {
818        self.recovered_block.sealed_block()
819    }
820
821    /// Returns a reference to [`RecoveredBlock`]
822    #[inline]
823    pub fn recovered_block(&self) -> &RecoveredBlock<N::Block> {
824        &self.recovered_block
825    }
826
827    /// Returns a reference to the block's execution outcome
828    #[inline]
829    pub fn execution_outcome(&self) -> &ExecutionOutcome<N::Receipt> {
830        &self.execution_output
831    }
832
833    /// Returns the trie data, computing it synchronously if not already cached.
834    ///
835    /// Uses `OnceLock::get_or_init` internally:
836    /// - If already computed: returns cached result immediately
837    /// - If not computed: first caller computes, others wait for that result
838    #[inline]
839    #[tracing::instrument(level = "debug", target = "engine::tree", name = "trie_data", skip_all)]
840    pub fn trie_data(&self) -> ComputedTrieData {
841        self.trie_data.wait_cloned()
842    }
843
844    /// Returns a clone of the deferred trie data handle.
845    ///
846    /// A handle is a lightweight reference that can be passed to descendants without
847    /// forcing trie data to be computed immediately. The actual work runs when
848    /// `wait_cloned()` is called by a consumer (e.g. when merging overlays).
849    #[inline]
850    pub fn trie_data_handle(&self) -> DeferredTrieData {
851        self.trie_data.clone()
852    }
853
854    /// Returns the hashed state result of the execution outcome.
855    ///
856    /// May compute trie data synchronously if the deferred task hasn't completed.
857    #[inline]
858    pub fn hashed_state(&self) -> Arc<HashedPostStateSorted> {
859        self.trie_data().hashed_state
860    }
861
862    /// Returns the trie updates resulting from the execution outcome.
863    ///
864    /// May compute trie data synchronously if the deferred task hasn't completed.
865    #[inline]
866    pub fn trie_updates(&self) -> Arc<TrieUpdatesSorted> {
867        self.trie_data().trie_updates
868    }
869
870    /// Returns the trie input anchored to the persisted ancestor.
871    ///
872    /// May compute trie data synchronously if the deferred task hasn't completed.
873    #[inline]
874    pub fn trie_input(&self) -> Option<Arc<TrieInputSorted>> {
875        self.trie_data().trie_input().cloned()
876    }
877
878    /// Returns the anchor hash of the trie input, if present.
879    #[inline]
880    pub fn anchor_hash(&self) -> Option<B256> {
881        self.trie_data().anchor_hash()
882    }
883
884    /// Returns a [`BlockNumber`] of the block.
885    #[inline]
886    pub fn block_number(&self) -> BlockNumber {
887        self.recovered_block.header().number()
888    }
889}
890
891/// Non-empty chain of blocks.
892#[derive(Debug)]
893pub enum NewCanonicalChain<N: NodePrimitives = EthPrimitives> {
894    /// A simple append to the current canonical head
895    Commit {
896        /// all blocks that lead back to the canonical head
897        new: Vec<ExecutedBlock<N>>,
898    },
899    /// A reorged chain consists of two chains that trace back to a shared ancestor block at which
900    /// point they diverge.
901    Reorg {
902        /// All blocks of the _new_ chain
903        new: Vec<ExecutedBlock<N>>,
904        /// All blocks of the _old_ chain
905        old: Vec<ExecutedBlock<N>>,
906    },
907}
908
909impl<N: NodePrimitives<SignedTx: SignedTransaction>> NewCanonicalChain<N> {
910    /// Returns the length of the new chain.
911    pub const fn new_block_count(&self) -> usize {
912        match self {
913            Self::Commit { new } | Self::Reorg { new, .. } => new.len(),
914        }
915    }
916
917    /// Returns the length of the reorged chain.
918    pub const fn reorged_block_count(&self) -> usize {
919        match self {
920            Self::Commit { .. } => 0,
921            Self::Reorg { old, .. } => old.len(),
922        }
923    }
924
925    /// Converts the new chain into a notification that will be emitted to listeners
926    pub fn to_chain_notification(&self) -> CanonStateNotification<N> {
927        match self {
928            Self::Commit { new } => {
929                let new = Arc::new(new.iter().fold(Chain::default(), |mut chain, exec| {
930                    chain.append_block(
931                        exec.recovered_block().clone(),
932                        exec.execution_outcome().clone(),
933                    );
934                    chain
935                }));
936                CanonStateNotification::Commit { new }
937            }
938            Self::Reorg { new, old } => {
939                let new = Arc::new(new.iter().fold(Chain::default(), |mut chain, exec| {
940                    chain.append_block(
941                        exec.recovered_block().clone(),
942                        exec.execution_outcome().clone(),
943                    );
944                    chain
945                }));
946                let old = Arc::new(old.iter().fold(Chain::default(), |mut chain, exec| {
947                    chain.append_block(
948                        exec.recovered_block().clone(),
949                        exec.execution_outcome().clone(),
950                    );
951                    chain
952                }));
953                CanonStateNotification::Reorg { new, old }
954            }
955        }
956    }
957
958    /// Returns the new tip of the chain.
959    ///
960    /// Returns the new tip for [`Self::Reorg`] and [`Self::Commit`] variants which commit at least
961    /// 1 new block.
962    pub fn tip(&self) -> &SealedBlock<N::Block> {
963        match self {
964            Self::Commit { new } | Self::Reorg { new, .. } => {
965                new.last().expect("non empty blocks").recovered_block()
966            }
967        }
968    }
969}
970
971#[cfg(test)]
972mod tests {
973    use super::*;
974    use crate::test_utils::TestBlockBuilder;
975    use alloy_eips::eip7685::Requests;
976    use alloy_primitives::{Address, BlockNumber, Bytes, StorageKey, StorageValue};
977    use rand::Rng;
978    use reth_errors::ProviderResult;
979    use reth_ethereum_primitives::{EthPrimitives, Receipt};
980    use reth_primitives_traits::{Account, Bytecode};
981    use reth_storage_api::{
982        AccountReader, BlockHashReader, BytecodeReader, HashedPostStateProvider,
983        StateProofProvider, StateProvider, StateRootProvider, StorageRootProvider,
984    };
985    use reth_trie::{
986        updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof,
987        MultiProofTargets, StorageMultiProof, StorageProof, TrieInput,
988    };
989
990    fn create_mock_state(
991        test_block_builder: &mut TestBlockBuilder<EthPrimitives>,
992        block_number: u64,
993        parent_hash: B256,
994    ) -> BlockState {
995        BlockState::new(
996            test_block_builder.get_executed_block_with_number(block_number, parent_hash),
997        )
998    }
999
1000    fn create_mock_state_chain(
1001        test_block_builder: &mut TestBlockBuilder<EthPrimitives>,
1002        num_blocks: u64,
1003    ) -> Vec<BlockState> {
1004        let mut chain = Vec::with_capacity(num_blocks as usize);
1005        let mut parent_hash = B256::random();
1006        let mut parent_state: Option<BlockState> = None;
1007
1008        for i in 1..=num_blocks {
1009            let mut state = create_mock_state(test_block_builder, i, parent_hash);
1010            if let Some(parent) = parent_state {
1011                state.parent = Some(Arc::new(parent));
1012            }
1013            parent_hash = state.hash();
1014            parent_state = Some(state.clone());
1015            chain.push(state);
1016        }
1017
1018        chain
1019    }
1020
1021    struct MockStateProvider;
1022
1023    impl StateProvider for MockStateProvider {
1024        fn storage(
1025            &self,
1026            _address: Address,
1027            _storage_key: StorageKey,
1028        ) -> ProviderResult<Option<StorageValue>> {
1029            Ok(None)
1030        }
1031    }
1032
1033    impl BytecodeReader for MockStateProvider {
1034        fn bytecode_by_hash(&self, _code_hash: &B256) -> ProviderResult<Option<Bytecode>> {
1035            Ok(None)
1036        }
1037    }
1038
1039    impl BlockHashReader for MockStateProvider {
1040        fn block_hash(&self, _number: BlockNumber) -> ProviderResult<Option<B256>> {
1041            Ok(None)
1042        }
1043
1044        fn canonical_hashes_range(
1045            &self,
1046            _start: BlockNumber,
1047            _end: BlockNumber,
1048        ) -> ProviderResult<Vec<B256>> {
1049            Ok(vec![])
1050        }
1051    }
1052
1053    impl AccountReader for MockStateProvider {
1054        fn basic_account(&self, _address: &Address) -> ProviderResult<Option<Account>> {
1055            Ok(None)
1056        }
1057    }
1058
1059    impl StateRootProvider for MockStateProvider {
1060        fn state_root(&self, _hashed_state: HashedPostState) -> ProviderResult<B256> {
1061            Ok(B256::random())
1062        }
1063
1064        fn state_root_from_nodes(&self, _input: TrieInput) -> ProviderResult<B256> {
1065            Ok(B256::random())
1066        }
1067
1068        fn state_root_with_updates(
1069            &self,
1070            _hashed_state: HashedPostState,
1071        ) -> ProviderResult<(B256, TrieUpdates)> {
1072            Ok((B256::random(), TrieUpdates::default()))
1073        }
1074
1075        fn state_root_from_nodes_with_updates(
1076            &self,
1077            _input: TrieInput,
1078        ) -> ProviderResult<(B256, TrieUpdates)> {
1079            Ok((B256::random(), TrieUpdates::default()))
1080        }
1081    }
1082
1083    impl HashedPostStateProvider for MockStateProvider {
1084        fn hashed_post_state(&self, _bundle_state: &revm_database::BundleState) -> HashedPostState {
1085            HashedPostState::default()
1086        }
1087    }
1088
1089    impl StorageRootProvider for MockStateProvider {
1090        fn storage_root(
1091            &self,
1092            _address: Address,
1093            _hashed_storage: HashedStorage,
1094        ) -> ProviderResult<B256> {
1095            Ok(B256::random())
1096        }
1097
1098        fn storage_proof(
1099            &self,
1100            _address: Address,
1101            slot: B256,
1102            _hashed_storage: HashedStorage,
1103        ) -> ProviderResult<StorageProof> {
1104            Ok(StorageProof::new(slot))
1105        }
1106
1107        fn storage_multiproof(
1108            &self,
1109            _address: Address,
1110            _slots: &[B256],
1111            _hashed_storage: HashedStorage,
1112        ) -> ProviderResult<StorageMultiProof> {
1113            Ok(StorageMultiProof::empty())
1114        }
1115    }
1116
1117    impl StateProofProvider for MockStateProvider {
1118        fn proof(
1119            &self,
1120            _input: TrieInput,
1121            _address: Address,
1122            _slots: &[B256],
1123        ) -> ProviderResult<AccountProof> {
1124            Ok(AccountProof::new(Address::random()))
1125        }
1126
1127        fn multiproof(
1128            &self,
1129            _input: TrieInput,
1130            _targets: MultiProofTargets,
1131        ) -> ProviderResult<MultiProof> {
1132            Ok(MultiProof::default())
1133        }
1134
1135        fn witness(
1136            &self,
1137            _input: TrieInput,
1138            _target: HashedPostState,
1139        ) -> ProviderResult<Vec<Bytes>> {
1140            Ok(Vec::default())
1141        }
1142    }
1143
1144    #[test]
1145    fn test_in_memory_state_impl_state_by_hash() {
1146        let mut state_by_hash = HashMap::default();
1147        let number = rand::rng().random::<u64>();
1148        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1149        let state = Arc::new(create_mock_state(&mut test_block_builder, number, B256::random()));
1150        state_by_hash.insert(state.hash(), state.clone());
1151
1152        let in_memory_state = InMemoryState::new(state_by_hash, BTreeMap::new(), None);
1153
1154        assert_eq!(in_memory_state.state_by_hash(state.hash()), Some(state));
1155        assert_eq!(in_memory_state.state_by_hash(B256::random()), None);
1156    }
1157
1158    #[test]
1159    fn test_in_memory_state_impl_state_by_number() {
1160        let mut state_by_hash = HashMap::default();
1161        let mut hash_by_number = BTreeMap::new();
1162
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        let hash = state.hash();
1167
1168        state_by_hash.insert(hash, state.clone());
1169        hash_by_number.insert(number, hash);
1170
1171        let in_memory_state = InMemoryState::new(state_by_hash, hash_by_number, None);
1172
1173        assert_eq!(in_memory_state.state_by_number(number), Some(state));
1174        assert_eq!(in_memory_state.state_by_number(number + 1), None);
1175    }
1176
1177    #[test]
1178    fn test_in_memory_state_impl_head_state() {
1179        let mut state_by_hash = HashMap::default();
1180        let mut hash_by_number = BTreeMap::new();
1181        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1182        let state1 = Arc::new(create_mock_state(&mut test_block_builder, 1, B256::random()));
1183        let hash1 = state1.hash();
1184        let state2 = Arc::new(create_mock_state(&mut test_block_builder, 2, hash1));
1185        let hash2 = state2.hash();
1186        hash_by_number.insert(1, hash1);
1187        hash_by_number.insert(2, hash2);
1188        state_by_hash.insert(hash1, state1);
1189        state_by_hash.insert(hash2, state2);
1190
1191        let in_memory_state = InMemoryState::new(state_by_hash, hash_by_number, None);
1192        let head_state = in_memory_state.head_state().unwrap();
1193
1194        assert_eq!(head_state.hash(), hash2);
1195        assert_eq!(head_state.number(), 2);
1196    }
1197
1198    #[test]
1199    fn test_in_memory_state_impl_pending_state() {
1200        let pending_number = rand::rng().random::<u64>();
1201        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1202        let pending_state =
1203            create_mock_state(&mut test_block_builder, pending_number, B256::random());
1204        let pending_hash = pending_state.hash();
1205
1206        let in_memory_state =
1207            InMemoryState::new(HashMap::default(), BTreeMap::new(), Some(pending_state));
1208
1209        let result = in_memory_state.pending_state();
1210        assert!(result.is_some());
1211        let actual_pending_state = result.unwrap();
1212        assert_eq!(actual_pending_state.block.recovered_block().hash(), pending_hash);
1213        assert_eq!(actual_pending_state.block.recovered_block().number, pending_number);
1214    }
1215
1216    #[test]
1217    fn test_in_memory_state_impl_no_pending_state() {
1218        let in_memory_state: InMemoryState =
1219            InMemoryState::new(HashMap::default(), BTreeMap::new(), None);
1220
1221        assert_eq!(in_memory_state.pending_state(), None);
1222    }
1223
1224    #[test]
1225    fn test_state() {
1226        let number = rand::rng().random::<u64>();
1227        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1228        let block = test_block_builder.get_executed_block_with_number(number, B256::random());
1229
1230        let state = BlockState::new(block.clone());
1231
1232        assert_eq!(state.block(), block);
1233        assert_eq!(state.hash(), block.recovered_block().hash());
1234        assert_eq!(state.number(), number);
1235        assert_eq!(state.state_root(), block.recovered_block().state_root);
1236    }
1237
1238    #[test]
1239    fn test_state_receipts() {
1240        let receipts = vec![vec![Receipt::default()]];
1241        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1242        let block =
1243            test_block_builder.get_executed_block_with_receipts(receipts.clone(), B256::random());
1244
1245        let state = BlockState::new(block);
1246
1247        assert_eq!(state.receipts(), &receipts);
1248    }
1249
1250    #[test]
1251    fn test_in_memory_state_chain_update() {
1252        let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1253        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1254        let block1 = test_block_builder.get_executed_block_with_number(0, B256::random());
1255        let block2 = test_block_builder.get_executed_block_with_number(0, B256::random());
1256        let chain = NewCanonicalChain::Commit { new: vec![block1.clone()] };
1257        state.update_chain(chain);
1258        assert_eq!(
1259            state.head_state().unwrap().block_ref().recovered_block().hash(),
1260            block1.recovered_block().hash()
1261        );
1262        assert_eq!(
1263            state.state_by_number(0).unwrap().block_ref().recovered_block().hash(),
1264            block1.recovered_block().hash()
1265        );
1266
1267        let chain = NewCanonicalChain::Reorg { new: vec![block2.clone()], old: vec![block1] };
1268        state.update_chain(chain);
1269        assert_eq!(
1270            state.head_state().unwrap().block_ref().recovered_block().hash(),
1271            block2.recovered_block().hash()
1272        );
1273        assert_eq!(
1274            state.state_by_number(0).unwrap().block_ref().recovered_block().hash(),
1275            block2.recovered_block().hash()
1276        );
1277
1278        assert_eq!(state.inner.in_memory_state.block_count(), 1);
1279    }
1280
1281    #[test]
1282    fn test_in_memory_state_set_pending_block() {
1283        let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1284        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1285
1286        // First random block
1287        let block1 = test_block_builder.get_executed_block_with_number(0, B256::random());
1288
1289        // Second block with parent hash of the first block
1290        let block2 =
1291            test_block_builder.get_executed_block_with_number(1, block1.recovered_block().hash());
1292
1293        // Commit the two blocks
1294        let chain = NewCanonicalChain::Commit { new: vec![block1.clone(), block2.clone()] };
1295        state.update_chain(chain);
1296
1297        // Assert that the pending state is None before setting it
1298        assert!(state.pending_state().is_none());
1299
1300        // Set the pending block
1301        state.set_pending_block(block2.clone());
1302
1303        // Check the pending state
1304        assert_eq!(
1305            state.pending_state().unwrap(),
1306            BlockState::with_parent(block2.clone(), Some(Arc::new(BlockState::new(block1))))
1307        );
1308
1309        // Check the pending block
1310        assert_eq!(state.pending_block().unwrap(), block2.recovered_block().sealed_block().clone());
1311
1312        // Check the pending block number and hash
1313        assert_eq!(
1314            state.pending_block_num_hash().unwrap(),
1315            BlockNumHash { number: 1, hash: block2.recovered_block().hash() }
1316        );
1317
1318        // Check the pending header
1319        assert_eq!(state.pending_header().unwrap(), block2.recovered_block().header().clone());
1320
1321        // Check the pending sealed header
1322        assert_eq!(
1323            state.pending_sealed_header().unwrap(),
1324            block2.recovered_block().clone_sealed_header()
1325        );
1326
1327        // Check the pending block with senders
1328        assert_eq!(state.pending_recovered_block().unwrap(), block2.recovered_block().clone());
1329
1330        // Check the pending block and receipts
1331        assert_eq!(
1332            state.pending_block_and_receipts().unwrap(),
1333            (block2.recovered_block().clone(), vec![])
1334        );
1335    }
1336
1337    #[test]
1338    fn test_canonical_in_memory_state_state_provider() {
1339        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1340        let block1 = test_block_builder.get_executed_block_with_number(1, B256::random());
1341        let block2 =
1342            test_block_builder.get_executed_block_with_number(2, block1.recovered_block().hash());
1343        let block3 =
1344            test_block_builder.get_executed_block_with_number(3, block2.recovered_block().hash());
1345
1346        let state1 = Arc::new(BlockState::new(block1.clone()));
1347        let state2 = Arc::new(BlockState::with_parent(block2.clone(), Some(state1.clone())));
1348        let state3 = Arc::new(BlockState::with_parent(block3.clone(), Some(state2.clone())));
1349
1350        let mut blocks = HashMap::default();
1351        blocks.insert(block1.recovered_block().hash(), state1);
1352        blocks.insert(block2.recovered_block().hash(), state2);
1353        blocks.insert(block3.recovered_block().hash(), state3);
1354
1355        let mut numbers = BTreeMap::new();
1356        numbers.insert(1, block1.recovered_block().hash());
1357        numbers.insert(2, block2.recovered_block().hash());
1358        numbers.insert(3, block3.recovered_block().hash());
1359
1360        let canonical_state = CanonicalInMemoryState::new(blocks, numbers, None, None, None);
1361
1362        let historical: StateProviderBox = Box::new(MockStateProvider);
1363
1364        let overlay_provider =
1365            canonical_state.state_provider(block3.recovered_block().hash(), historical);
1366
1367        assert_eq!(overlay_provider.in_memory.len(), 3);
1368        assert_eq!(overlay_provider.in_memory[0].recovered_block().number, 3);
1369        assert_eq!(overlay_provider.in_memory[1].recovered_block().number, 2);
1370        assert_eq!(overlay_provider.in_memory[2].recovered_block().number, 1);
1371
1372        assert_eq!(
1373            overlay_provider.in_memory[0].recovered_block().parent_hash,
1374            overlay_provider.in_memory[1].recovered_block().hash()
1375        );
1376        assert_eq!(
1377            overlay_provider.in_memory[1].recovered_block().parent_hash,
1378            overlay_provider.in_memory[2].recovered_block().hash()
1379        );
1380
1381        let unknown_hash = B256::random();
1382        let empty_overlay_provider =
1383            canonical_state.state_provider(unknown_hash, Box::new(MockStateProvider));
1384        assert_eq!(empty_overlay_provider.in_memory.len(), 0);
1385    }
1386
1387    #[test]
1388    fn test_canonical_in_memory_state_canonical_chain_empty() {
1389        let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1390        assert!(state.canonical_chain().next().is_none());
1391    }
1392
1393    #[test]
1394    fn test_canonical_in_memory_state_canonical_chain_single_block() {
1395        let block = TestBlockBuilder::eth().get_executed_block_with_number(1, B256::random());
1396        let hash = block.recovered_block().hash();
1397        let mut blocks = HashMap::default();
1398        blocks.insert(hash, Arc::new(BlockState::new(block)));
1399        let mut numbers = BTreeMap::new();
1400        numbers.insert(1, hash);
1401
1402        let state = CanonicalInMemoryState::new(blocks, numbers, None, None, None);
1403        let chain: Vec<_> = state.canonical_chain().collect();
1404
1405        assert_eq!(chain.len(), 1);
1406        assert_eq!(chain[0].number(), 1);
1407        assert_eq!(chain[0].hash(), hash);
1408    }
1409
1410    #[test]
1411    fn test_canonical_in_memory_state_canonical_chain_multiple_blocks() {
1412        let mut parent_hash = B256::random();
1413        let mut block_builder = TestBlockBuilder::eth();
1414        let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1415
1416        for i in 1..=3 {
1417            let block = block_builder.get_executed_block_with_number(i, parent_hash);
1418            let hash = block.recovered_block().hash();
1419            state.update_blocks(Some(block), None);
1420            parent_hash = hash;
1421        }
1422
1423        let chain: Vec<_> = state.canonical_chain().collect();
1424
1425        assert_eq!(chain.len(), 3);
1426        assert_eq!(chain[0].number(), 3);
1427        assert_eq!(chain[1].number(), 2);
1428        assert_eq!(chain[2].number(), 1);
1429    }
1430
1431    // ensures the pending block is not part of the canonical chain
1432    #[test]
1433    fn test_canonical_in_memory_state_canonical_chain_with_pending_block() {
1434        let mut parent_hash = B256::random();
1435        let mut block_builder = TestBlockBuilder::<EthPrimitives>::eth();
1436        let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1437
1438        for i in 1..=2 {
1439            let block = block_builder.get_executed_block_with_number(i, parent_hash);
1440            let hash = block.recovered_block().hash();
1441            state.update_blocks(Some(block), None);
1442            parent_hash = hash;
1443        }
1444
1445        let pending_block = block_builder.get_executed_block_with_number(3, parent_hash);
1446        state.set_pending_block(pending_block);
1447        let chain: Vec<_> = state.canonical_chain().collect();
1448
1449        assert_eq!(chain.len(), 2);
1450        assert_eq!(chain[0].number(), 2);
1451        assert_eq!(chain[1].number(), 1);
1452    }
1453
1454    #[test]
1455    fn test_block_state_parent_blocks() {
1456        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1457        let chain = create_mock_state_chain(&mut test_block_builder, 4);
1458
1459        let parents: Vec<_> = chain[3].parent_state_chain().collect();
1460        assert_eq!(parents.len(), 3);
1461        assert_eq!(parents[0].block().recovered_block().number, 3);
1462        assert_eq!(parents[1].block().recovered_block().number, 2);
1463        assert_eq!(parents[2].block().recovered_block().number, 1);
1464
1465        let parents: Vec<_> = chain[2].parent_state_chain().collect();
1466        assert_eq!(parents.len(), 2);
1467        assert_eq!(parents[0].block().recovered_block().number, 2);
1468        assert_eq!(parents[1].block().recovered_block().number, 1);
1469
1470        let parents: Vec<_> = chain[0].parent_state_chain().collect();
1471        assert_eq!(parents.len(), 0);
1472    }
1473
1474    #[test]
1475    fn test_block_state_single_block_state_chain() {
1476        let single_block_number = 1;
1477        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1478        let single_block =
1479            create_mock_state(&mut test_block_builder, single_block_number, B256::random());
1480        let single_block_hash = single_block.block().recovered_block().hash();
1481
1482        let parents: Vec<_> = single_block.parent_state_chain().collect();
1483        assert_eq!(parents.len(), 0);
1484
1485        let block_state_chain = single_block.chain().collect::<Vec<_>>();
1486        assert_eq!(block_state_chain.len(), 1);
1487        assert_eq!(block_state_chain[0].block().recovered_block().number, single_block_number);
1488        assert_eq!(block_state_chain[0].block().recovered_block().hash(), single_block_hash);
1489    }
1490
1491    #[test]
1492    fn test_block_state_chain() {
1493        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1494        let chain = create_mock_state_chain(&mut test_block_builder, 3);
1495
1496        let block_state_chain = chain[2].chain().collect::<Vec<_>>();
1497        assert_eq!(block_state_chain.len(), 3);
1498        assert_eq!(block_state_chain[0].block().recovered_block().number, 3);
1499        assert_eq!(block_state_chain[1].block().recovered_block().number, 2);
1500        assert_eq!(block_state_chain[2].block().recovered_block().number, 1);
1501
1502        let block_state_chain = chain[1].chain().collect::<Vec<_>>();
1503        assert_eq!(block_state_chain.len(), 2);
1504        assert_eq!(block_state_chain[0].block().recovered_block().number, 2);
1505        assert_eq!(block_state_chain[1].block().recovered_block().number, 1);
1506
1507        let block_state_chain = chain[0].chain().collect::<Vec<_>>();
1508        assert_eq!(block_state_chain.len(), 1);
1509        assert_eq!(block_state_chain[0].block().recovered_block().number, 1);
1510    }
1511
1512    #[test]
1513    fn test_to_chain_notification() {
1514        // Generate 4 blocks
1515        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1516        let block0 = test_block_builder.get_executed_block_with_number(0, B256::random());
1517        let block1 =
1518            test_block_builder.get_executed_block_with_number(1, block0.recovered_block.hash());
1519        let block1a =
1520            test_block_builder.get_executed_block_with_number(1, block0.recovered_block.hash());
1521        let block2 =
1522            test_block_builder.get_executed_block_with_number(2, block1.recovered_block.hash());
1523        let block2a =
1524            test_block_builder.get_executed_block_with_number(2, block1.recovered_block.hash());
1525
1526        let sample_execution_outcome = ExecutionOutcome {
1527            receipts: vec![vec![], vec![]],
1528            requests: vec![Requests::default(), Requests::default()],
1529            ..Default::default()
1530        };
1531
1532        // Test commit notification
1533        let chain_commit = NewCanonicalChain::Commit { new: vec![block0.clone(), block1.clone()] };
1534
1535        assert_eq!(
1536            chain_commit.to_chain_notification(),
1537            CanonStateNotification::Commit {
1538                new: Arc::new(Chain::new(
1539                    vec![block0.recovered_block().clone(), block1.recovered_block().clone()],
1540                    sample_execution_outcome.clone(),
1541                    None
1542                ))
1543            }
1544        );
1545
1546        // Test reorg notification
1547        let chain_reorg = NewCanonicalChain::Reorg {
1548            new: vec![block1a.clone(), block2a.clone()],
1549            old: vec![block1.clone(), block2.clone()],
1550        };
1551
1552        assert_eq!(
1553            chain_reorg.to_chain_notification(),
1554            CanonStateNotification::Reorg {
1555                old: Arc::new(Chain::new(
1556                    vec![block1.recovered_block().clone(), block2.recovered_block().clone()],
1557                    sample_execution_outcome.clone(),
1558                    None
1559                )),
1560                new: Arc::new(Chain::new(
1561                    vec![block1a.recovered_block().clone(), block2a.recovered_block().clone()],
1562                    sample_execution_outcome,
1563                    None
1564                ))
1565            }
1566        );
1567    }
1568}