Skip to main content

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::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
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<B256Map<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: 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    /// 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: 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    /// Create an empty state.
208    pub fn empty() -> Self {
209        Self::new(B256Map::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        self.set_persisted(persisted_num_hash);
321        // if the persisted hash is not in the canonical in memory state, do nothing, because it
322        // means canonical blocks were not actually persisted.
323        //
324        // This can happen if the persistence task takes a long time, while a reorg is happening.
325        {
326            if self.inner.in_memory_state.blocks.read().get(&persisted_num_hash.hash).is_none() {
327                // do nothing
328                return
329            }
330        }
331
332        {
333            // acquire locks, starting with the numbers lock
334            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            // clear all numbers
340            numbers.clear();
341
342            // drain all blocks and only keep the ones that are not persisted (below the persisted
343            // height)
344            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            // sort the blocks by number so we can insert them back in natural order (low -> high)
351            old_blocks.sort_unstable_by_key(|block| block.recovered_block().number());
352
353            // re-insert the blocks in natural order and connect them to their parent blocks
354            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                // append new blocks
361                blocks.insert(hash, Arc::new(block_state));
362                numbers.insert(number, hash);
363            }
364
365            // also shift the pending state if it exists
366            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    /// Returns in memory state corresponding the given hash.
376    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    /// Returns in memory state corresponding the block number.
381    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    /// Returns the in memory head state.
386    pub fn head_state(&self) -> Option<Arc<BlockState<N>>> {
387        self.inner.in_memory_state.head_state()
388    }
389
390    /// Returns the in memory pending state.
391    pub fn pending_state(&self) -> Option<BlockState<N>> {
392        self.inner.in_memory_state.pending_state()
393    }
394
395    /// Returns the in memory pending `BlockNumHash`.
396    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    /// Returns the current `ChainInfo`.
404    pub fn chain_info(&self) -> ChainInfo {
405        self.inner.chain_info_tracker.chain_info()
406    }
407
408    /// Returns the latest canonical block number.
409    pub fn get_canonical_block_number(&self) -> u64 {
410        self.inner.chain_info_tracker.get_canonical_block_number()
411    }
412
413    /// Returns the `BlockNumHash` of the safe head.
414    pub fn get_safe_num_hash(&self) -> Option<BlockNumHash> {
415        self.inner.chain_info_tracker.get_safe_num_hash()
416    }
417
418    /// Returns the `BlockNumHash` of the finalized head.
419    pub fn get_finalized_num_hash(&self) -> Option<BlockNumHash> {
420        self.inner.chain_info_tracker.get_finalized_num_hash()
421    }
422
423    /// Hook for new fork choice update.
424    pub fn on_forkchoice_update_received(&self) {
425        self.inner.chain_info_tracker.on_forkchoice_update_received();
426    }
427
428    /// Returns the timestamp of the last received update.
429    pub fn last_received_update_timestamp(&self) -> Option<Instant> {
430        self.inner.chain_info_tracker.last_forkchoice_update_received_at()
431    }
432
433    /// Canonical head setter.
434    pub fn set_canonical_head(&self, header: SealedHeader<N::BlockHeader>) {
435        self.inner.chain_info_tracker.set_canonical_head(header);
436    }
437
438    /// Safe head setter.
439    pub fn set_safe(&self, header: SealedHeader<N::BlockHeader>) {
440        self.inner.chain_info_tracker.set_safe(header);
441    }
442
443    /// Finalized head setter.
444    pub fn set_finalized(&self, header: SealedHeader<N::BlockHeader>) {
445        self.inner.chain_info_tracker.set_finalized(header);
446    }
447
448    /// Persisted block setter.
449    pub fn set_persisted(&self, num_hash: BlockNumHash) {
450        self.inner.chain_info_tracker.set_persisted(num_hash);
451    }
452
453    /// Canonical head getter.
454    pub fn get_canonical_head(&self) -> SealedHeader<N::BlockHeader> {
455        self.inner.chain_info_tracker.get_canonical_head()
456    }
457
458    /// Finalized header getter.
459    pub fn get_finalized_header(&self) -> Option<SealedHeader<N::BlockHeader>> {
460        self.inner.chain_info_tracker.get_finalized_header()
461    }
462
463    /// Safe header getter.
464    pub fn get_safe_header(&self) -> Option<SealedHeader<N::BlockHeader>> {
465        self.inner.chain_info_tracker.get_safe_header()
466    }
467
468    /// Persisted block `BlockNumHash` getter.
469    pub fn get_persisted_num_hash(&self) -> Option<BlockNumHash> {
470        self.inner.chain_info_tracker.get_persisted_num_hash()
471    }
472
473    /// Returns the `SealedHeader` corresponding to the pending state.
474    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    /// Returns the `Header` corresponding to the pending state.
479    pub fn pending_header(&self) -> Option<N::BlockHeader> {
480        self.pending_sealed_header().map(|sealed_header| sealed_header.unseal())
481    }
482
483    /// Returns the `SealedBlock` corresponding to the pending state.
484    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    /// Returns the `RecoveredBlock` corresponding to the pending state.
490    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    /// Returns a tuple with the `SealedBlock` corresponding to the pending
498    /// state and a vector of its `Receipt`s.
499    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    /// Subscribe to new blocks events.
509    pub fn subscribe_canon_state(&self) -> CanonStateNotifications<N> {
510        self.inner.canon_state_notification_sender.subscribe()
511    }
512
513    /// Subscribe to new safe block events.
514    pub fn subscribe_safe_block(&self) -> watch::Receiver<Option<SealedHeader<N::BlockHeader>>> {
515        self.inner.chain_info_tracker.subscribe_safe_block()
516    }
517
518    /// Subscribe to new finalized block events.
519    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    /// Subscribe to new persisted block events.
526    pub fn subscribe_persisted_block(&self) -> watch::Receiver<Option<BlockNumHash>> {
527        self.inner.chain_info_tracker.subscribe_persisted_block()
528    }
529
530    /// Attempts to send a new [`CanonStateNotification`] to all active Receiver handles.
531    pub fn notify_canon_state(&self, event: CanonStateNotification<N>) {
532        self.inner.canon_state_notification_sender.send(event).ok();
533    }
534
535    /// Return state provider with reference to in-memory blocks that overlay database state.
536    ///
537    /// This merges the state of all blocks that are part of the chain that the requested block is
538    /// the head of. This includes all blocks that connect back to the canonical block on disk.
539    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    /// Returns an iterator over all __canonical blocks__ in the in-memory state, from newest to
554    /// oldest (highest to lowest).
555    ///
556    /// This iterator contains a snapshot of the in-memory state at the time of the call.
557    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    /// Returns [`SignedTransaction`] type for the given `TxHash` if found.
562    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    /// Returns a tuple with [`SignedTransaction`] type and [`TransactionMeta`] for the
574    /// given [`TxHash`] if found.
575    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/// State after applying the given block, this block is part of the canonical chain that partially
589/// stored in memory and can be traced back to a canonical block on disk.
590#[derive(Debug, Clone)]
591pub struct BlockState<N: NodePrimitives = EthPrimitives> {
592    /// The executed block that determines the state after this block has been executed.
593    block: ExecutedBlock<N>,
594    /// The block's parent block if it exists.
595    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    /// [`BlockState`] constructor.
606    pub const fn new(block: ExecutedBlock<N>) -> Self {
607        Self { block, parent: None }
608    }
609
610    /// [`BlockState`] constructor with parent.
611    pub const fn with_parent(block: ExecutedBlock<N>, parent: Option<Arc<Self>>) -> Self {
612        Self { block, parent }
613    }
614
615    /// Returns the hash and block of the on disk block this state can be traced back to.
616    pub fn anchor(&self) -> BlockNumHash {
617        let mut current = self;
618        while let Some(parent) = &current.parent {
619            current = parent;
620        }
621        current.block.recovered_block().parent_num_hash()
622    }
623
624    /// Returns the executed block that determines the state.
625    pub fn block(&self) -> ExecutedBlock<N> {
626        self.block.clone()
627    }
628
629    /// Returns a reference to the executed block that determines the state.
630    pub const fn block_ref(&self) -> &ExecutedBlock<N> {
631        &self.block
632    }
633
634    /// Returns the hash of executed block that determines the state.
635    pub fn hash(&self) -> B256 {
636        self.block.recovered_block().hash()
637    }
638
639    /// Returns the block number of executed block that determines the state.
640    pub fn number(&self) -> u64 {
641        self.block.recovered_block().number()
642    }
643
644    /// Returns the state root after applying the executed block that determines
645    /// the state.
646    pub fn state_root(&self) -> B256 {
647        self.block.recovered_block().state_root()
648    }
649
650    /// Returns the `Receipts` of executed block that determines the state.
651    pub fn receipts(&self) -> &Vec<N::Receipt> {
652        &self.block.execution_outcome().receipts
653    }
654
655    /// Returns a vector of `Receipt` of executed block that determines the state.
656    /// We assume that the `Receipts` in the executed block `ExecutionOutcome`
657    /// has only one element corresponding to the executed block associated to
658    /// the state.
659    ///
660    /// This clones the vector of receipts. To avoid it, use [`Self::executed_block_receipts_ref`].
661    pub fn executed_block_receipts(&self) -> Vec<N::Receipt> {
662        self.receipts().clone()
663    }
664
665    /// Returns a slice of `Receipt` of executed block that determines the state.
666    /// We assume that the `Receipts` in the executed block `ExecutionOutcome`
667    /// has only one element corresponding to the executed block associated to
668    /// the state.
669    pub fn executed_block_receipts_ref(&self) -> &[N::Receipt] {
670        self.receipts()
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<BlockExecutionOutput<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: 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        // Trie data is computed asynchronously and doesn't define block identity.
783        self.recovered_block == other.recovered_block &&
784            self.execution_output == other.execution_output
785    }
786}
787
788impl<N: NodePrimitives> ExecutedBlock<N> {
789    /// Create a new [`ExecutedBlock`] with already-computed trie data.
790    ///
791    /// Use this constructor when trie data is available immediately (e.g., sequencers,
792    /// payload builders). This is the safe default path.
793    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    /// Create a new [`ExecutedBlock`] with deferred trie data.
802    ///
803    /// This is useful if the trie data is populated somewhere else, e.g. asynchronously
804    /// after the block was validated.
805    ///
806    /// The [`DeferredTrieData`] handle allows expensive trie operations (sorting hashed state and
807    /// trie updates) to be performed outside the critical validation path by a background task.
808    /// This can improve latency for time-sensitive operations like block validation.
809    ///
810    /// If the data hasn't been populated when [`Self::trie_data()`] is called, the caller waits
811    /// for the background task to publish it.
812    ///
813    /// Use [`Self::new()`] instead when trie data is already computed and available immediately.
814    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    /// Returns a reference to an inner [`SealedBlock`]
823    #[inline]
824    pub fn sealed_block(&self) -> &SealedBlock<N::Block> {
825        self.recovered_block.sealed_block()
826    }
827
828    /// Returns a reference to [`RecoveredBlock`]
829    #[inline]
830    pub fn recovered_block(&self) -> &RecoveredBlock<N::Block> {
831        &self.recovered_block
832    }
833
834    /// Returns a reference to the block's execution outcome
835    #[inline]
836    pub fn execution_outcome(&self) -> &BlockExecutionOutput<N::Receipt> {
837        &self.execution_output
838    }
839
840    /// Returns the trie data, waiting for the background task if not already cached.
841    ///
842    /// Uses `OnceLock::get_or_init` internally:
843    /// - If already computed: returns cached result immediately
844    /// - If not computed: first caller waits for the publishing task, others wait for that result
845    #[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    /// Returns a clone of the deferred trie data handle.
852    ///
853    /// A handle is a lightweight reference that can be passed to descendants without
854    /// forcing trie data to be observed immediately. The actual work runs in the background task.
855    #[inline]
856    pub fn trie_data_handle(&self) -> DeferredTrieData {
857        self.trie_data.clone()
858    }
859
860    /// Returns the hashed state result of the execution outcome.
861    ///
862    /// May wait for trie data if the deferred task hasn't completed.
863    #[inline]
864    pub fn hashed_state(&self) -> Arc<HashedPostStateSorted> {
865        self.trie_data().hashed_state
866    }
867
868    /// Returns the trie updates resulting from the execution outcome.
869    ///
870    /// May wait for trie data if the deferred task hasn't completed.
871    #[inline]
872    pub fn trie_updates(&self) -> Arc<TrieUpdatesSorted> {
873        self.trie_data().trie_updates
874    }
875
876    /// Returns a [`BlockNumber`] of the block.
877    #[inline]
878    pub fn block_number(&self) -> BlockNumber {
879        self.recovered_block.header().number()
880    }
881}
882
883/// Non-empty chain of blocks.
884#[derive(Debug)]
885pub enum NewCanonicalChain<N: NodePrimitives = EthPrimitives> {
886    /// A simple append to the current canonical head
887    Commit {
888        /// all blocks that lead back to the canonical head
889        new: Vec<ExecutedBlock<N>>,
890    },
891    /// A reorged chain consists of two chains that trace back to a shared ancestor block at which
892    /// point they diverge.
893    Reorg {
894        /// All blocks of the _new_ chain
895        new: Vec<ExecutedBlock<N>>,
896        /// All blocks of the _old_ chain
897        old: Vec<ExecutedBlock<N>>,
898    },
899}
900
901impl<N: NodePrimitives<SignedTx: SignedTransaction>> NewCanonicalChain<N> {
902    /// Returns the length of the new chain.
903    pub const fn new_block_count(&self) -> usize {
904        match self {
905            Self::Commit { new } | Self::Reorg { new, .. } => new.len(),
906        }
907    }
908
909    /// Returns the length of the reorged chain.
910    pub const fn reorged_block_count(&self) -> usize {
911        match self {
912            Self::Commit { .. } => 0,
913            Self::Reorg { old, .. } => old.len(),
914        }
915    }
916
917    /// Converts the new chain into a notification that will be emitted to listeners
918    pub fn to_chain_notification(&self) -> CanonStateNotification<N> {
919        match self {
920            Self::Commit { new } => {
921                CanonStateNotification::Commit { new: Arc::new(Self::blocks_to_chain(new)) }
922            }
923            Self::Reorg { new, old } => CanonStateNotification::Reorg {
924                new: Arc::new(Self::blocks_to_chain(new)),
925                old: Arc::new(Self::blocks_to_chain(old)),
926            },
927        }
928    }
929
930    /// Converts a slice of executed blocks into a [`Chain`].
931    fn blocks_to_chain(blocks: &[ExecutedBlock<N>]) -> Chain<N> {
932        match blocks {
933            [] => Chain::default(),
934            [first, rest @ ..] => {
935                let trie_data_handle = first.trie_data_handle();
936                let mut chain = Chain::from_block(
937                    first.recovered_block().clone(),
938                    ExecutionOutcome::from((
939                        first.execution_outcome().clone(),
940                        first.block_number(),
941                    )),
942                    LazyTrieData::deferred(move || {
943                        let trie_data = trie_data_handle.wait_cloned();
944                        SortedTrieData {
945                            hashed_state: trie_data.hashed_state,
946                            trie_updates: trie_data.trie_updates,
947                        }
948                    }),
949                );
950                for exec in rest {
951                    let trie_data_handle = exec.trie_data_handle();
952                    chain.append_block(
953                        exec.recovered_block().clone(),
954                        ExecutionOutcome::from((
955                            exec.execution_outcome().clone(),
956                            exec.block_number(),
957                        )),
958                        LazyTrieData::deferred(move || {
959                            let trie_data = trie_data_handle.wait_cloned();
960                            SortedTrieData {
961                                hashed_state: trie_data.hashed_state,
962                                trie_updates: trie_data.trie_updates,
963                            }
964                        }),
965                    );
966                }
967                chain
968            }
969        }
970    }
971
972    /// Returns the new tip of the chain.
973    ///
974    /// Returns the new tip for [`Self::Reorg`] and [`Self::Commit`] variants which commit at least
975    /// 1 new block.
976    pub fn tip(&self) -> &RecoveredBlock<N::Block> {
977        match self {
978            Self::Commit { new } | Self::Reorg { new, .. } => {
979                new.last().expect("non empty blocks").recovered_block()
980            }
981        }
982    }
983}
984
985#[cfg(test)]
986mod tests {
987    use super::*;
988    use crate::test_utils::TestBlockBuilder;
989    use alloy_eips::eip7685::Requests;
990    use alloy_primitives::{Address, BlockNumber, Bytes, StorageKey, StorageValue};
991    use rand::Rng;
992    use reth_errors::ProviderResult;
993    use reth_ethereum_primitives::{EthPrimitives, Receipt};
994    use reth_primitives_traits::{Account, Bytecode};
995    use reth_storage_api::{
996        AccountReader, BlockHashReader, BytecodeReader, HashedPostStateProvider,
997        StateProofProvider, StateProvider, StateRootProvider, StorageRootProvider,
998    };
999    use reth_trie::{
1000        updates::TrieUpdates, AccountProof, HashedPostState, HashedStorage, MultiProof,
1001        MultiProofTargets, StorageMultiProof, StorageProof, TrieInput,
1002    };
1003
1004    fn create_mock_state(
1005        test_block_builder: &mut TestBlockBuilder<EthPrimitives>,
1006        block_number: u64,
1007        parent_hash: B256,
1008    ) -> BlockState {
1009        BlockState::new(
1010            test_block_builder.get_executed_block_with_number(block_number, parent_hash),
1011        )
1012    }
1013
1014    fn create_mock_state_chain(
1015        test_block_builder: &mut TestBlockBuilder<EthPrimitives>,
1016        num_blocks: u64,
1017    ) -> Vec<BlockState> {
1018        let mut chain = Vec::with_capacity(num_blocks as usize);
1019        let mut parent_hash = B256::random();
1020        let mut parent_state: Option<BlockState> = None;
1021
1022        for i in 1..=num_blocks {
1023            let mut state = create_mock_state(test_block_builder, i, parent_hash);
1024            if let Some(parent) = parent_state {
1025                state.parent = Some(Arc::new(parent));
1026            }
1027            parent_hash = state.hash();
1028            parent_state = Some(state.clone());
1029            chain.push(state);
1030        }
1031
1032        chain
1033    }
1034
1035    struct MockStateProvider;
1036
1037    impl StateProvider for MockStateProvider {
1038        fn storage(
1039            &self,
1040            _address: Address,
1041            _storage_key: StorageKey,
1042        ) -> ProviderResult<Option<StorageValue>> {
1043            Ok(None)
1044        }
1045    }
1046
1047    impl BytecodeReader for MockStateProvider {
1048        fn bytecode_by_hash(&self, _code_hash: &B256) -> ProviderResult<Option<Bytecode>> {
1049            Ok(None)
1050        }
1051    }
1052
1053    impl BlockHashReader for MockStateProvider {
1054        fn block_hash(&self, _number: BlockNumber) -> ProviderResult<Option<B256>> {
1055            Ok(None)
1056        }
1057
1058        fn canonical_hashes_range(
1059            &self,
1060            _start: BlockNumber,
1061            _end: BlockNumber,
1062        ) -> ProviderResult<Vec<B256>> {
1063            Ok(vec![])
1064        }
1065    }
1066
1067    impl AccountReader for MockStateProvider {
1068        fn basic_account(&self, _address: &Address) -> ProviderResult<Option<Account>> {
1069            Ok(None)
1070        }
1071    }
1072
1073    impl StateRootProvider for MockStateProvider {
1074        fn state_root(&self, _hashed_state: HashedPostState) -> ProviderResult<B256> {
1075            Ok(B256::random())
1076        }
1077
1078        fn state_root_from_nodes(&self, _input: TrieInput) -> ProviderResult<B256> {
1079            Ok(B256::random())
1080        }
1081
1082        fn state_root_with_updates(
1083            &self,
1084            _hashed_state: HashedPostState,
1085        ) -> ProviderResult<(B256, TrieUpdates)> {
1086            Ok((B256::random(), TrieUpdates::default()))
1087        }
1088
1089        fn state_root_from_nodes_with_updates(
1090            &self,
1091            _input: TrieInput,
1092        ) -> ProviderResult<(B256, TrieUpdates)> {
1093            Ok((B256::random(), TrieUpdates::default()))
1094        }
1095    }
1096
1097    impl HashedPostStateProvider for MockStateProvider {
1098        fn hashed_post_state(&self, _bundle_state: &revm_database::BundleState) -> HashedPostState {
1099            HashedPostState::default()
1100        }
1101    }
1102
1103    impl StorageRootProvider for MockStateProvider {
1104        fn storage_root(
1105            &self,
1106            _address: Address,
1107            _hashed_storage: HashedStorage,
1108        ) -> ProviderResult<B256> {
1109            Ok(B256::random())
1110        }
1111
1112        fn storage_proof(
1113            &self,
1114            _address: Address,
1115            slot: B256,
1116            _hashed_storage: HashedStorage,
1117        ) -> ProviderResult<StorageProof> {
1118            Ok(StorageProof::new(slot))
1119        }
1120
1121        fn storage_multiproof(
1122            &self,
1123            _address: Address,
1124            _slots: &[B256],
1125            _hashed_storage: HashedStorage,
1126        ) -> ProviderResult<StorageMultiProof> {
1127            Ok(StorageMultiProof::empty())
1128        }
1129    }
1130
1131    impl StateProofProvider for MockStateProvider {
1132        fn proof(
1133            &self,
1134            _input: TrieInput,
1135            _address: Address,
1136            _slots: &[B256],
1137        ) -> ProviderResult<AccountProof> {
1138            Ok(AccountProof::new(Address::random()))
1139        }
1140
1141        fn multiproof(
1142            &self,
1143            _input: TrieInput,
1144            _targets: MultiProofTargets,
1145        ) -> ProviderResult<MultiProof> {
1146            Ok(MultiProof::default())
1147        }
1148
1149        fn witness(
1150            &self,
1151            _input: TrieInput,
1152            _target: HashedPostState,
1153            _mode: reth_trie::ExecutionWitnessMode,
1154        ) -> ProviderResult<Vec<Bytes>> {
1155            Ok(Vec::default())
1156        }
1157    }
1158
1159    #[test]
1160    fn test_in_memory_state_impl_state_by_hash() {
1161        let mut state_by_hash = B256Map::default();
1162        let number = rand::rng().random::<u64>();
1163        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1164        let state = Arc::new(create_mock_state(&mut test_block_builder, number, B256::random()));
1165        state_by_hash.insert(state.hash(), state.clone());
1166
1167        let in_memory_state = InMemoryState::new(state_by_hash, BTreeMap::new(), None);
1168
1169        assert_eq!(in_memory_state.state_by_hash(state.hash()), Some(state));
1170        assert_eq!(in_memory_state.state_by_hash(B256::random()), None);
1171    }
1172
1173    #[test]
1174    fn test_in_memory_state_impl_state_by_number() {
1175        let mut state_by_hash = B256Map::default();
1176        let mut hash_by_number = BTreeMap::new();
1177
1178        let number = rand::rng().random::<u64>();
1179        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1180        let state = Arc::new(create_mock_state(&mut test_block_builder, number, B256::random()));
1181        let hash = state.hash();
1182
1183        state_by_hash.insert(hash, state.clone());
1184        hash_by_number.insert(number, hash);
1185
1186        let in_memory_state = InMemoryState::new(state_by_hash, hash_by_number, None);
1187
1188        assert_eq!(in_memory_state.state_by_number(number), Some(state));
1189        assert_eq!(in_memory_state.state_by_number(number + 1), None);
1190    }
1191
1192    #[test]
1193    fn test_in_memory_state_impl_head_state() {
1194        let mut state_by_hash = B256Map::default();
1195        let mut hash_by_number = BTreeMap::new();
1196        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1197        let state1 = Arc::new(create_mock_state(&mut test_block_builder, 1, B256::random()));
1198        let hash1 = state1.hash();
1199        let state2 = Arc::new(create_mock_state(&mut test_block_builder, 2, hash1));
1200        let hash2 = state2.hash();
1201        hash_by_number.insert(1, hash1);
1202        hash_by_number.insert(2, hash2);
1203        state_by_hash.insert(hash1, state1);
1204        state_by_hash.insert(hash2, state2);
1205
1206        let in_memory_state = InMemoryState::new(state_by_hash, hash_by_number, None);
1207        let head_state = in_memory_state.head_state().unwrap();
1208
1209        assert_eq!(head_state.hash(), hash2);
1210        assert_eq!(head_state.number(), 2);
1211    }
1212
1213    #[test]
1214    fn test_in_memory_state_impl_pending_state() {
1215        let pending_number = rand::rng().random::<u64>();
1216        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1217        let pending_state =
1218            create_mock_state(&mut test_block_builder, pending_number, B256::random());
1219        let pending_hash = pending_state.hash();
1220
1221        let in_memory_state =
1222            InMemoryState::new(B256Map::default(), BTreeMap::new(), Some(pending_state));
1223
1224        let result = in_memory_state.pending_state();
1225        assert!(result.is_some());
1226        let actual_pending_state = result.unwrap();
1227        assert_eq!(actual_pending_state.block.recovered_block().hash(), pending_hash);
1228        assert_eq!(actual_pending_state.block.recovered_block().number, pending_number);
1229    }
1230
1231    #[test]
1232    fn test_in_memory_state_impl_no_pending_state() {
1233        let in_memory_state: InMemoryState =
1234            InMemoryState::new(B256Map::default(), BTreeMap::new(), None);
1235
1236        assert_eq!(in_memory_state.pending_state(), None);
1237    }
1238
1239    #[test]
1240    fn test_state() {
1241        let number = rand::rng().random::<u64>();
1242        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1243        let block = test_block_builder.get_executed_block_with_number(number, B256::random());
1244
1245        let state = BlockState::new(block.clone());
1246
1247        assert_eq!(state.block(), block);
1248        assert_eq!(state.hash(), block.recovered_block().hash());
1249        assert_eq!(state.number(), number);
1250        assert_eq!(state.state_root(), block.recovered_block().state_root);
1251    }
1252
1253    #[test]
1254    fn test_state_receipts() {
1255        let receipts = vec![vec![Receipt::default()]];
1256        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1257        let block =
1258            test_block_builder.get_executed_block_with_receipts(receipts.clone(), B256::random());
1259
1260        let state = BlockState::new(block);
1261
1262        assert_eq!(state.receipts(), receipts.first().unwrap());
1263    }
1264
1265    #[test]
1266    fn test_in_memory_state_chain_update() {
1267        let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1268        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1269        let block1 = test_block_builder.get_executed_block_with_number(0, B256::random());
1270        let block2 = test_block_builder.get_executed_block_with_number(0, B256::random());
1271        let chain = NewCanonicalChain::Commit { new: vec![block1.clone()] };
1272        state.update_chain(chain);
1273        assert_eq!(
1274            state.head_state().unwrap().block_ref().recovered_block().hash(),
1275            block1.recovered_block().hash()
1276        );
1277        assert_eq!(
1278            state.state_by_number(0).unwrap().block_ref().recovered_block().hash(),
1279            block1.recovered_block().hash()
1280        );
1281
1282        let chain = NewCanonicalChain::Reorg { new: vec![block2.clone()], old: vec![block1] };
1283        state.update_chain(chain);
1284        assert_eq!(
1285            state.head_state().unwrap().block_ref().recovered_block().hash(),
1286            block2.recovered_block().hash()
1287        );
1288        assert_eq!(
1289            state.state_by_number(0).unwrap().block_ref().recovered_block().hash(),
1290            block2.recovered_block().hash()
1291        );
1292
1293        assert_eq!(state.inner.in_memory_state.block_count(), 1);
1294    }
1295
1296    #[test]
1297    fn test_in_memory_state_set_pending_block() {
1298        let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1299        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1300
1301        // First random block
1302        let block1 = test_block_builder.get_executed_block_with_number(0, B256::random());
1303
1304        // Second block with parent hash of the first block
1305        let block2 =
1306            test_block_builder.get_executed_block_with_number(1, block1.recovered_block().hash());
1307
1308        // Commit the two blocks
1309        let chain = NewCanonicalChain::Commit { new: vec![block1.clone(), block2.clone()] };
1310        state.update_chain(chain);
1311
1312        // Assert that the pending state is None before setting it
1313        assert!(state.pending_state().is_none());
1314
1315        // Set the pending block
1316        state.set_pending_block(block2.clone());
1317
1318        // Check the pending state
1319        assert_eq!(
1320            state.pending_state().unwrap(),
1321            BlockState::with_parent(block2.clone(), Some(Arc::new(BlockState::new(block1))))
1322        );
1323
1324        // Check the pending block
1325        assert_eq!(state.pending_block().unwrap(), block2.recovered_block().sealed_block().clone());
1326
1327        // Check the pending block number and hash
1328        assert_eq!(
1329            state.pending_block_num_hash().unwrap(),
1330            BlockNumHash { number: 1, hash: block2.recovered_block().hash() }
1331        );
1332
1333        // Check the pending header
1334        assert_eq!(state.pending_header().unwrap(), block2.recovered_block().header().clone());
1335
1336        // Check the pending sealed header
1337        assert_eq!(
1338            state.pending_sealed_header().unwrap(),
1339            block2.recovered_block().clone_sealed_header()
1340        );
1341
1342        // Check the pending block with senders
1343        assert_eq!(state.pending_recovered_block().unwrap(), block2.recovered_block().clone());
1344
1345        // Check the pending block and receipts
1346        assert_eq!(
1347            state.pending_block_and_receipts().unwrap(),
1348            (block2.recovered_block().clone(), vec![])
1349        );
1350    }
1351
1352    #[test]
1353    fn test_canonical_in_memory_state_state_provider() {
1354        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1355        let block1 = test_block_builder.get_executed_block_with_number(1, B256::random());
1356        let block2 =
1357            test_block_builder.get_executed_block_with_number(2, block1.recovered_block().hash());
1358        let block3 =
1359            test_block_builder.get_executed_block_with_number(3, block2.recovered_block().hash());
1360
1361        let state1 = Arc::new(BlockState::new(block1.clone()));
1362        let state2 = Arc::new(BlockState::with_parent(block2.clone(), Some(state1.clone())));
1363        let state3 = Arc::new(BlockState::with_parent(block3.clone(), Some(state2.clone())));
1364
1365        let mut blocks = B256Map::default();
1366        blocks.insert(block1.recovered_block().hash(), state1);
1367        blocks.insert(block2.recovered_block().hash(), state2);
1368        blocks.insert(block3.recovered_block().hash(), state3);
1369
1370        let mut numbers = BTreeMap::new();
1371        numbers.insert(1, block1.recovered_block().hash());
1372        numbers.insert(2, block2.recovered_block().hash());
1373        numbers.insert(3, block3.recovered_block().hash());
1374
1375        let canonical_state = CanonicalInMemoryState::new(blocks, numbers, None, None, None);
1376
1377        let historical: StateProviderBox = Box::new(MockStateProvider);
1378
1379        let overlay_provider =
1380            canonical_state.state_provider(block3.recovered_block().hash(), historical);
1381
1382        assert_eq!(overlay_provider.in_memory.len(), 3);
1383        assert_eq!(overlay_provider.in_memory[0].recovered_block().number, 3);
1384        assert_eq!(overlay_provider.in_memory[1].recovered_block().number, 2);
1385        assert_eq!(overlay_provider.in_memory[2].recovered_block().number, 1);
1386
1387        assert_eq!(
1388            overlay_provider.in_memory[0].recovered_block().parent_hash,
1389            overlay_provider.in_memory[1].recovered_block().hash()
1390        );
1391        assert_eq!(
1392            overlay_provider.in_memory[1].recovered_block().parent_hash,
1393            overlay_provider.in_memory[2].recovered_block().hash()
1394        );
1395
1396        let unknown_hash = B256::random();
1397        let empty_overlay_provider =
1398            canonical_state.state_provider(unknown_hash, Box::new(MockStateProvider));
1399        assert_eq!(empty_overlay_provider.in_memory.len(), 0);
1400    }
1401
1402    #[test]
1403    fn test_canonical_in_memory_state_canonical_chain_empty() {
1404        let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1405        assert!(state.canonical_chain().next().is_none());
1406    }
1407
1408    #[test]
1409    fn test_canonical_in_memory_state_canonical_chain_single_block() {
1410        let block = TestBlockBuilder::eth().get_executed_block_with_number(1, B256::random());
1411        let hash = block.recovered_block().hash();
1412        let mut blocks = B256Map::default();
1413        blocks.insert(hash, Arc::new(BlockState::new(block)));
1414        let mut numbers = BTreeMap::new();
1415        numbers.insert(1, hash);
1416
1417        let state = CanonicalInMemoryState::new(blocks, numbers, None, None, None);
1418        let chain: Vec<_> = state.canonical_chain().collect();
1419
1420        assert_eq!(chain.len(), 1);
1421        assert_eq!(chain[0].number(), 1);
1422        assert_eq!(chain[0].hash(), hash);
1423    }
1424
1425    #[test]
1426    fn test_canonical_in_memory_state_canonical_chain_multiple_blocks() {
1427        let mut parent_hash = B256::random();
1428        let mut block_builder = TestBlockBuilder::eth();
1429        let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1430
1431        for i in 1..=3 {
1432            let block = block_builder.get_executed_block_with_number(i, parent_hash);
1433            let hash = block.recovered_block().hash();
1434            state.update_blocks(Some(block), None);
1435            parent_hash = hash;
1436        }
1437
1438        let chain: Vec<_> = state.canonical_chain().collect();
1439
1440        assert_eq!(chain.len(), 3);
1441        assert_eq!(chain[0].number(), 3);
1442        assert_eq!(chain[1].number(), 2);
1443        assert_eq!(chain[2].number(), 1);
1444    }
1445
1446    // ensures the pending block is not part of the canonical chain
1447    #[test]
1448    fn test_canonical_in_memory_state_canonical_chain_with_pending_block() {
1449        let mut parent_hash = B256::random();
1450        let mut block_builder = TestBlockBuilder::<EthPrimitives>::eth();
1451        let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1452
1453        for i in 1..=2 {
1454            let block = block_builder.get_executed_block_with_number(i, parent_hash);
1455            let hash = block.recovered_block().hash();
1456            state.update_blocks(Some(block), None);
1457            parent_hash = hash;
1458        }
1459
1460        let pending_block = block_builder.get_executed_block_with_number(3, parent_hash);
1461        state.set_pending_block(pending_block);
1462        let chain: Vec<_> = state.canonical_chain().collect();
1463
1464        assert_eq!(chain.len(), 2);
1465        assert_eq!(chain[0].number(), 2);
1466        assert_eq!(chain[1].number(), 1);
1467    }
1468
1469    #[test]
1470    fn test_block_state_parent_blocks() {
1471        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1472        let chain = create_mock_state_chain(&mut test_block_builder, 4);
1473
1474        let parents: Vec<_> = chain[3].parent_state_chain().collect();
1475        assert_eq!(parents.len(), 3);
1476        assert_eq!(parents[0].block().recovered_block().number, 3);
1477        assert_eq!(parents[1].block().recovered_block().number, 2);
1478        assert_eq!(parents[2].block().recovered_block().number, 1);
1479
1480        let parents: Vec<_> = chain[2].parent_state_chain().collect();
1481        assert_eq!(parents.len(), 2);
1482        assert_eq!(parents[0].block().recovered_block().number, 2);
1483        assert_eq!(parents[1].block().recovered_block().number, 1);
1484
1485        assert_eq!(chain[0].parent_state_chain().count(), 0);
1486    }
1487
1488    #[test]
1489    fn test_block_state_single_block_state_chain() {
1490        let single_block_number = 1;
1491        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1492        let single_block =
1493            create_mock_state(&mut test_block_builder, single_block_number, B256::random());
1494        let single_block_hash = single_block.block().recovered_block().hash();
1495
1496        assert_eq!(single_block.parent_state_chain().count(), 0);
1497
1498        let block_state_chain = single_block.chain().collect::<Vec<_>>();
1499        assert_eq!(block_state_chain.len(), 1);
1500        assert_eq!(block_state_chain[0].block().recovered_block().number, single_block_number);
1501        assert_eq!(block_state_chain[0].block().recovered_block().hash(), single_block_hash);
1502    }
1503
1504    #[test]
1505    fn test_block_state_chain() {
1506        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1507        let chain = create_mock_state_chain(&mut test_block_builder, 3);
1508
1509        let block_state_chain = chain[2].chain().collect::<Vec<_>>();
1510        assert_eq!(block_state_chain.len(), 3);
1511        assert_eq!(block_state_chain[0].block().recovered_block().number, 3);
1512        assert_eq!(block_state_chain[1].block().recovered_block().number, 2);
1513        assert_eq!(block_state_chain[2].block().recovered_block().number, 1);
1514
1515        let block_state_chain = chain[1].chain().collect::<Vec<_>>();
1516        assert_eq!(block_state_chain.len(), 2);
1517        assert_eq!(block_state_chain[0].block().recovered_block().number, 2);
1518        assert_eq!(block_state_chain[1].block().recovered_block().number, 1);
1519
1520        let block_state_chain = chain[0].chain().collect::<Vec<_>>();
1521        assert_eq!(block_state_chain.len(), 1);
1522        assert_eq!(block_state_chain[0].block().recovered_block().number, 1);
1523    }
1524
1525    #[test]
1526    fn test_to_chain_notification() {
1527        // Generate 4 blocks
1528        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1529        let block0 = test_block_builder.get_executed_block_with_number(0, B256::random());
1530        let block1 =
1531            test_block_builder.get_executed_block_with_number(1, block0.recovered_block.hash());
1532        let block1a =
1533            test_block_builder.get_executed_block_with_number(1, block0.recovered_block.hash());
1534        let block2 =
1535            test_block_builder.get_executed_block_with_number(2, block1.recovered_block.hash());
1536        let block2a =
1537            test_block_builder.get_executed_block_with_number(2, block1.recovered_block.hash());
1538
1539        // Test commit notification
1540        let chain_commit = NewCanonicalChain::Commit { new: vec![block0.clone(), block1.clone()] };
1541
1542        // Build expected trie data map
1543        let mut expected_trie_data = BTreeMap::new();
1544        expected_trie_data
1545            .insert(0, LazyTrieData::ready(block0.hashed_state(), block0.trie_updates()));
1546        expected_trie_data
1547            .insert(1, LazyTrieData::ready(block1.hashed_state(), block1.trie_updates()));
1548
1549        // Build expected execution outcome (first_block matches first block number)
1550        let commit_execution_outcome = ExecutionOutcome {
1551            receipts: vec![vec![], vec![]],
1552            requests: vec![Requests::default(), Requests::default()],
1553            first_block: 0,
1554            ..Default::default()
1555        };
1556
1557        assert_eq!(
1558            chain_commit.to_chain_notification(),
1559            CanonStateNotification::Commit {
1560                new: Arc::new(Chain::new(
1561                    vec![block0.recovered_block().clone(), block1.recovered_block().clone()],
1562                    commit_execution_outcome,
1563                    expected_trie_data,
1564                ))
1565            }
1566        );
1567
1568        // Test reorg notification
1569        let chain_reorg = NewCanonicalChain::Reorg {
1570            new: vec![block1a.clone(), block2a.clone()],
1571            old: vec![block1.clone(), block2.clone()],
1572        };
1573
1574        // Build expected trie data for old chain
1575        let mut old_trie_data = BTreeMap::new();
1576        old_trie_data.insert(1, LazyTrieData::ready(block1.hashed_state(), block1.trie_updates()));
1577        old_trie_data.insert(2, LazyTrieData::ready(block2.hashed_state(), block2.trie_updates()));
1578
1579        // Build expected trie data for new chain
1580        let mut new_trie_data = BTreeMap::new();
1581        new_trie_data
1582            .insert(1, LazyTrieData::ready(block1a.hashed_state(), block1a.trie_updates()));
1583        new_trie_data
1584            .insert(2, LazyTrieData::ready(block2a.hashed_state(), block2a.trie_updates()));
1585
1586        // Build expected execution outcome for reorg chains (first_block matches first block
1587        // number)
1588        let reorg_execution_outcome = ExecutionOutcome {
1589            receipts: vec![vec![], vec![]],
1590            requests: vec![Requests::default(), Requests::default()],
1591            first_block: 1,
1592            ..Default::default()
1593        };
1594
1595        assert_eq!(
1596            chain_reorg.to_chain_notification(),
1597            CanonStateNotification::Reorg {
1598                old: Arc::new(Chain::new(
1599                    vec![block1.recovered_block().clone(), block2.recovered_block().clone()],
1600                    reorg_execution_outcome.clone(),
1601                    old_trie_data,
1602                )),
1603                new: Arc::new(Chain::new(
1604                    vec![block1a.recovered_block().clone(), block2a.recovered_block().clone()],
1605                    reorg_execution_outcome,
1606                    new_trie_data,
1607                ))
1608            }
1609        );
1610    }
1611}