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