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, MemoryOverlayStateProvider,
6};
7use alloy_consensus::{transaction::TransactionMeta, BlockHeader};
8use alloy_eips::{BlockHashOrNumber, BlockNumHash};
9use alloy_primitives::{map::HashMap, BlockNumber, TxHash, B256};
10use parking_lot::RwLock;
11use reth_chainspec::ChainInfo;
12use reth_ethereum_primitives::EthPrimitives;
13use reth_execution_types::{Chain, ExecutionOutcome};
14use reth_metrics::{metrics::Gauge, Metrics};
15use reth_primitives_traits::{
16    BlockBody as _, IndexedTx, NodePrimitives, RecoveredBlock, SealedBlock, SealedHeader,
17    SignedTransaction,
18};
19use reth_storage_api::StateProviderBox;
20use reth_trie::{updates::TrieUpdates, HashedPostState};
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<HashMap<B256, Arc<BlockState<N>>>>,
58    /// Mapping of block numbers to block hashes.
59    numbers: RwLock<BTreeMap<u64, B256>>,
60    /// The pending block that has not yet been made canonical.
61    pending: watch::Sender<Option<BlockState<N>>>,
62    /// Metrics for the in-memory state.
63    metrics: InMemoryStateMetrics,
64}
65
66impl<N: NodePrimitives> InMemoryState<N> {
67    pub(crate) fn new(
68        blocks: HashMap<B256, Arc<BlockState<N>>>,
69        numbers: BTreeMap<u64, B256>,
70        pending: Option<BlockState<N>>,
71    ) -> Self {
72        let (pending, _) = watch::channel(pending);
73        let this = Self {
74            blocks: RwLock::new(blocks),
75            numbers: RwLock::new(numbers),
76            pending,
77            metrics: Default::default(),
78        };
79        this.update_metrics();
80        this
81    }
82
83    /// Update the metrics for the in-memory state.
84    ///
85    /// # Locking behavior
86    ///
87    /// This tries to acquire a read lock. Drop any write locks before calling this.
88    pub(crate) fn update_metrics(&self) {
89        let numbers = self.numbers.read();
90        if let Some((earliest_block_number, _)) = numbers.first_key_value() {
91            self.metrics.earliest_block.set(*earliest_block_number as f64);
92        }
93        if let Some((latest_block_number, _)) = numbers.last_key_value() {
94            self.metrics.latest_block.set(*latest_block_number as f64);
95        }
96        self.metrics.num_blocks.set(numbers.len() as f64);
97    }
98
99    /// Returns the state for a given block hash.
100    pub(crate) fn state_by_hash(&self, hash: B256) -> Option<Arc<BlockState<N>>> {
101        self.blocks.read().get(&hash).cloned()
102    }
103
104    /// Returns the state for a given block number.
105    pub(crate) fn state_by_number(&self, number: u64) -> Option<Arc<BlockState<N>>> {
106        let hash = self.hash_by_number(number)?;
107        self.state_by_hash(hash)
108    }
109
110    /// Returns the hash for a specific block number
111    pub(crate) fn hash_by_number(&self, number: u64) -> Option<B256> {
112        self.numbers.read().get(&number).copied()
113    }
114
115    /// Returns the current chain head state.
116    pub(crate) fn head_state(&self) -> Option<Arc<BlockState<N>>> {
117        let hash = *self.numbers.read().last_key_value()?.1;
118        self.state_by_hash(hash)
119    }
120
121    /// Returns the pending state corresponding to the current head plus one,
122    /// from the payload received in newPayload that does not have a FCU yet.
123    pub(crate) fn pending_state(&self) -> Option<BlockState<N>> {
124        self.pending.borrow().clone()
125    }
126
127    #[cfg(test)]
128    fn block_count(&self) -> usize {
129        self.blocks.read().len()
130    }
131}
132
133/// Inner type to provide in memory state. It includes a chain tracker to be
134/// advanced internally by the tree.
135#[derive(Debug)]
136pub(crate) struct CanonicalInMemoryStateInner<N: NodePrimitives> {
137    /// Tracks certain chain information, such as the canonical head, safe head, and finalized
138    /// head.
139    pub(crate) chain_info_tracker: ChainInfoTracker<N>,
140    /// Tracks blocks at the tip of the chain that have not been persisted to disk yet.
141    pub(crate) in_memory_state: InMemoryState<N>,
142    /// A broadcast stream that emits events when the canonical chain is updated.
143    pub(crate) canon_state_notification_sender: CanonStateNotificationSender<N>,
144}
145
146impl<N: NodePrimitives> CanonicalInMemoryStateInner<N> {
147    /// Clears all entries in the in memory state.
148    fn clear(&self) {
149        {
150            // acquire locks, starting with the numbers lock
151            let mut numbers = self.in_memory_state.numbers.write();
152            let mut blocks = self.in_memory_state.blocks.write();
153            numbers.clear();
154            blocks.clear();
155            self.in_memory_state.pending.send_modify(|p| {
156                p.take();
157            });
158        }
159        self.in_memory_state.update_metrics();
160    }
161}
162
163type PendingBlockAndReceipts<N> =
164    (RecoveredBlock<<N as NodePrimitives>::Block>, Vec<reth_primitives_traits::ReceiptTy<N>>);
165
166/// This type is responsible for providing the blocks, receipts, and state for
167/// all canonical blocks not on disk yet and keeps track of the block range that
168/// is in memory.
169#[derive(Debug, Clone)]
170pub struct CanonicalInMemoryState<N: NodePrimitives = EthPrimitives> {
171    pub(crate) inner: Arc<CanonicalInMemoryStateInner<N>>,
172}
173
174impl<N: NodePrimitives> CanonicalInMemoryState<N> {
175    /// Create a new in-memory state with the given blocks, numbers, pending state, and optional
176    /// finalized header.
177    pub fn new(
178        blocks: HashMap<B256, Arc<BlockState<N>>>,
179        numbers: BTreeMap<u64, B256>,
180        pending: Option<BlockState<N>>,
181        finalized: Option<SealedHeader<N::BlockHeader>>,
182        safe: Option<SealedHeader<N::BlockHeader>>,
183    ) -> Self {
184        let in_memory_state = InMemoryState::new(blocks, numbers, pending);
185        let header = in_memory_state.head_state().map_or_else(SealedHeader::default, |state| {
186            state.block_ref().recovered_block().clone_sealed_header()
187        });
188        let chain_info_tracker = ChainInfoTracker::new(header, finalized, safe);
189        let (canon_state_notification_sender, _) =
190            broadcast::channel(CANON_STATE_NOTIFICATION_CHANNEL_SIZE);
191
192        Self {
193            inner: Arc::new(CanonicalInMemoryStateInner {
194                chain_info_tracker,
195                in_memory_state,
196                canon_state_notification_sender,
197            }),
198        }
199    }
200
201    /// Create an empty state.
202    pub fn empty() -> Self {
203        Self::new(HashMap::default(), BTreeMap::new(), None, None, None)
204    }
205
206    /// Create a new in memory state with the given local head and finalized header
207    /// if it exists.
208    pub fn with_head(
209        head: SealedHeader<N::BlockHeader>,
210        finalized: Option<SealedHeader<N::BlockHeader>>,
211        safe: Option<SealedHeader<N::BlockHeader>>,
212    ) -> Self {
213        let chain_info_tracker = ChainInfoTracker::new(head, finalized, safe);
214        let in_memory_state = InMemoryState::default();
215        let (canon_state_notification_sender, _) =
216            broadcast::channel(CANON_STATE_NOTIFICATION_CHANNEL_SIZE);
217        let inner = CanonicalInMemoryStateInner {
218            chain_info_tracker,
219            in_memory_state,
220            canon_state_notification_sender,
221        };
222
223        Self { inner: Arc::new(inner) }
224    }
225
226    /// Returns the block hash corresponding to the given number.
227    pub fn hash_by_number(&self, number: u64) -> Option<B256> {
228        self.inner.in_memory_state.hash_by_number(number)
229    }
230
231    /// Returns the header corresponding to the given hash.
232    pub fn header_by_hash(&self, hash: B256) -> Option<SealedHeader<N::BlockHeader>> {
233        self.state_by_hash(hash)
234            .map(|block| block.block_ref().recovered_block().clone_sealed_header())
235    }
236
237    /// Clears all entries in the in memory state.
238    pub fn clear_state(&self) {
239        self.inner.clear()
240    }
241
242    /// Updates the pending block with the given block.
243    ///
244    /// Note: This assumes that the parent block of the pending block is canonical.
245    pub fn set_pending_block(&self, pending: ExecutedBlock<N>) {
246        // fetch the state of the pending block's parent block
247        let parent = self.state_by_hash(pending.recovered_block().parent_hash());
248        let pending = BlockState::with_parent(pending, parent);
249        self.inner.in_memory_state.pending.send_modify(|p| {
250            p.replace(pending);
251        });
252        self.inner.in_memory_state.update_metrics();
253    }
254
255    /// Append new blocks to the in memory state.
256    ///
257    /// This removes all reorged blocks and appends the new blocks to the tracked chain and connects
258    /// them to their parent blocks.
259    fn update_blocks<I, R>(&self, new_blocks: I, reorged: R)
260    where
261        I: IntoIterator<Item = ExecutedBlock<N>>,
262        R: IntoIterator<Item = ExecutedBlock<N>>,
263    {
264        {
265            // acquire locks, starting with the numbers lock
266            let mut numbers = self.inner.in_memory_state.numbers.write();
267            let mut blocks = self.inner.in_memory_state.blocks.write();
268
269            // we first remove the blocks from the reorged chain
270            for block in reorged {
271                let hash = block.recovered_block().hash();
272                let number = block.recovered_block().number();
273                blocks.remove(&hash);
274                numbers.remove(&number);
275            }
276
277            // insert the new blocks
278            for block in new_blocks {
279                let parent = blocks.get(&block.recovered_block().parent_hash()).cloned();
280                let block_state = BlockState::with_parent(block, parent);
281                let hash = block_state.hash();
282                let number = block_state.number();
283
284                // append new blocks
285                blocks.insert(hash, Arc::new(block_state));
286                numbers.insert(number, hash);
287            }
288
289            // remove the pending state
290            self.inner.in_memory_state.pending.send_modify(|p| {
291                p.take();
292            });
293        }
294        self.inner.in_memory_state.update_metrics();
295    }
296
297    /// Update the in memory state with the given chain update.
298    pub fn update_chain(&self, new_chain: NewCanonicalChain<N>) {
299        match new_chain {
300            NewCanonicalChain::Commit { new } => {
301                self.update_blocks(new, vec![]);
302            }
303            NewCanonicalChain::Reorg { new, old } => {
304                self.update_blocks(new, old);
305            }
306        }
307    }
308
309    /// Removes blocks from the in memory state that are persisted to the given height.
310    ///
311    /// This will update the links between blocks and remove all blocks that are [..
312    /// `persisted_height`].
313    pub fn remove_persisted_blocks(&self, persisted_num_hash: BlockNumHash) {
314        // if the persisted hash is not in the canonical in memory state, do nothing, because it
315        // means canonical blocks were not actually persisted.
316        //
317        // This can happen if the persistence task takes a long time, while a reorg is happening.
318        {
319            if self.inner.in_memory_state.blocks.read().get(&persisted_num_hash.hash).is_none() {
320                // do nothing
321                return
322            }
323        }
324
325        {
326            // acquire locks, starting with the numbers lock
327            let mut numbers = self.inner.in_memory_state.numbers.write();
328            let mut blocks = self.inner.in_memory_state.blocks.write();
329
330            let BlockNumHash { number: persisted_height, hash: _ } = persisted_num_hash;
331
332            // clear all numbers
333            numbers.clear();
334
335            // drain all blocks and only keep the ones that are not persisted (below the persisted
336            // height)
337            let mut old_blocks = blocks
338                .drain()
339                .filter(|(_, b)| b.block_ref().recovered_block().number() > persisted_height)
340                .map(|(_, b)| b.block.clone())
341                .collect::<Vec<_>>();
342
343            // sort the blocks by number so we can insert them back in natural order (low -> high)
344            old_blocks.sort_unstable_by_key(|block| block.recovered_block().number());
345
346            // re-insert the blocks in natural order and connect them to their parent blocks
347            for block in old_blocks {
348                let parent = blocks.get(&block.recovered_block().parent_hash()).cloned();
349                let block_state = BlockState::with_parent(block, parent);
350                let hash = block_state.hash();
351                let number = block_state.number();
352
353                // append new blocks
354                blocks.insert(hash, Arc::new(block_state));
355                numbers.insert(number, hash);
356            }
357
358            // also shift the pending state if it exists
359            self.inner.in_memory_state.pending.send_modify(|p| {
360                if let Some(p) = p.as_mut() {
361                    p.parent = blocks.get(&p.block_ref().recovered_block().parent_hash()).cloned();
362                }
363            });
364        }
365        self.inner.in_memory_state.update_metrics();
366    }
367
368    /// Returns in memory state corresponding the given hash.
369    pub fn state_by_hash(&self, hash: B256) -> Option<Arc<BlockState<N>>> {
370        self.inner.in_memory_state.state_by_hash(hash)
371    }
372
373    /// Returns in memory state corresponding the block number.
374    pub fn state_by_number(&self, number: u64) -> Option<Arc<BlockState<N>>> {
375        self.inner.in_memory_state.state_by_number(number)
376    }
377
378    /// Returns the in memory head state.
379    pub fn head_state(&self) -> Option<Arc<BlockState<N>>> {
380        self.inner.in_memory_state.head_state()
381    }
382
383    /// Returns the in memory pending state.
384    pub fn pending_state(&self) -> Option<BlockState<N>> {
385        self.inner.in_memory_state.pending_state()
386    }
387
388    /// Returns the in memory pending `BlockNumHash`.
389    pub fn pending_block_num_hash(&self) -> Option<BlockNumHash> {
390        self.inner
391            .in_memory_state
392            .pending_state()
393            .map(|state| BlockNumHash { number: state.number(), hash: state.hash() })
394    }
395
396    /// Returns the current `ChainInfo`.
397    pub fn chain_info(&self) -> ChainInfo {
398        self.inner.chain_info_tracker.chain_info()
399    }
400
401    /// Returns the latest canonical block number.
402    pub fn get_canonical_block_number(&self) -> u64 {
403        self.inner.chain_info_tracker.get_canonical_block_number()
404    }
405
406    /// Returns the `BlockNumHash` of the safe head.
407    pub fn get_safe_num_hash(&self) -> Option<BlockNumHash> {
408        self.inner.chain_info_tracker.get_safe_num_hash()
409    }
410
411    /// Returns the `BlockNumHash` of the finalized head.
412    pub fn get_finalized_num_hash(&self) -> Option<BlockNumHash> {
413        self.inner.chain_info_tracker.get_finalized_num_hash()
414    }
415
416    /// Hook for new fork choice update.
417    pub fn on_forkchoice_update_received(&self) {
418        self.inner.chain_info_tracker.on_forkchoice_update_received();
419    }
420
421    /// Returns the timestamp of the last received update.
422    pub fn last_received_update_timestamp(&self) -> Option<Instant> {
423        self.inner.chain_info_tracker.last_forkchoice_update_received_at()
424    }
425
426    /// Canonical head setter.
427    pub fn set_canonical_head(&self, header: SealedHeader<N::BlockHeader>) {
428        self.inner.chain_info_tracker.set_canonical_head(header);
429    }
430
431    /// Safe head setter.
432    pub fn set_safe(&self, header: SealedHeader<N::BlockHeader>) {
433        self.inner.chain_info_tracker.set_safe(header);
434    }
435
436    /// Finalized head setter.
437    pub fn set_finalized(&self, header: SealedHeader<N::BlockHeader>) {
438        self.inner.chain_info_tracker.set_finalized(header);
439    }
440
441    /// Canonical head getter.
442    pub fn get_canonical_head(&self) -> SealedHeader<N::BlockHeader> {
443        self.inner.chain_info_tracker.get_canonical_head()
444    }
445
446    /// Finalized header getter.
447    pub fn get_finalized_header(&self) -> Option<SealedHeader<N::BlockHeader>> {
448        self.inner.chain_info_tracker.get_finalized_header()
449    }
450
451    /// Safe header getter.
452    pub fn get_safe_header(&self) -> Option<SealedHeader<N::BlockHeader>> {
453        self.inner.chain_info_tracker.get_safe_header()
454    }
455
456    /// Returns the `SealedHeader` corresponding to the pending state.
457    pub fn pending_sealed_header(&self) -> Option<SealedHeader<N::BlockHeader>> {
458        self.pending_state().map(|h| h.block_ref().recovered_block().clone_sealed_header())
459    }
460
461    /// Returns the `Header` corresponding to the pending state.
462    pub fn pending_header(&self) -> Option<N::BlockHeader> {
463        self.pending_sealed_header().map(|sealed_header| sealed_header.unseal())
464    }
465
466    /// Returns the `SealedBlock` corresponding to the pending state.
467    pub fn pending_block(&self) -> Option<SealedBlock<N::Block>> {
468        self.pending_state()
469            .map(|block_state| block_state.block_ref().recovered_block().sealed_block().clone())
470    }
471
472    /// Returns the `RecoveredBlock` corresponding to the pending state.
473    pub fn pending_recovered_block(&self) -> Option<RecoveredBlock<N::Block>>
474    where
475        N::SignedTx: SignedTransaction,
476    {
477        self.pending_state().map(|block_state| block_state.block_ref().recovered_block().clone())
478    }
479
480    /// Returns a tuple with the `SealedBlock` corresponding to the pending
481    /// state and a vector of its `Receipt`s.
482    pub fn pending_block_and_receipts(&self) -> Option<PendingBlockAndReceipts<N>> {
483        self.pending_state().map(|block_state| {
484            (
485                block_state.block_ref().recovered_block().clone(),
486                block_state.executed_block_receipts(),
487            )
488        })
489    }
490
491    /// Subscribe to new blocks events.
492    pub fn subscribe_canon_state(&self) -> CanonStateNotifications<N> {
493        self.inner.canon_state_notification_sender.subscribe()
494    }
495
496    /// Subscribe to new safe block events.
497    pub fn subscribe_safe_block(&self) -> watch::Receiver<Option<SealedHeader<N::BlockHeader>>> {
498        self.inner.chain_info_tracker.subscribe_safe_block()
499    }
500
501    /// Subscribe to new finalized block events.
502    pub fn subscribe_finalized_block(
503        &self,
504    ) -> watch::Receiver<Option<SealedHeader<N::BlockHeader>>> {
505        self.inner.chain_info_tracker.subscribe_finalized_block()
506    }
507
508    /// Attempts to send a new [`CanonStateNotification`] to all active Receiver handles.
509    pub fn notify_canon_state(&self, event: CanonStateNotification<N>) {
510        self.inner.canon_state_notification_sender.send(event).ok();
511    }
512
513    /// Return state provider with reference to in-memory blocks that overlay database state.
514    ///
515    /// This merges the state of all blocks that are part of the chain that the requested block is
516    /// the head of. This includes all blocks that connect back to the canonical block on disk.
517    pub fn state_provider(
518        &self,
519        hash: B256,
520        historical: StateProviderBox,
521    ) -> MemoryOverlayStateProvider<N> {
522        let in_memory = if let Some(state) = self.state_by_hash(hash) {
523            state.chain().map(|block_state| block_state.block()).collect()
524        } else {
525            Vec::new()
526        };
527
528        MemoryOverlayStateProvider::new(historical, in_memory)
529    }
530
531    /// Returns an iterator over all __canonical blocks__ in the in-memory state, from newest to
532    /// oldest (highest to lowest).
533    ///
534    /// This iterator contains a snapshot of the in-memory state at the time of the call.
535    pub fn canonical_chain(&self) -> impl Iterator<Item = Arc<BlockState<N>>> {
536        self.inner.in_memory_state.head_state().into_iter().flat_map(|head| head.iter())
537    }
538
539    /// Returns [`SignedTransaction`] type for the given `TxHash` if found.
540    pub fn transaction_by_hash(&self, hash: TxHash) -> Option<N::SignedTx> {
541        for block_state in self.canonical_chain() {
542            if let Some(tx) =
543                block_state.block_ref().recovered_block().body().transaction_by_hash(&hash)
544            {
545                return Some(tx.clone())
546            }
547        }
548        None
549    }
550
551    /// Returns a tuple with [`SignedTransaction`] type and [`TransactionMeta`] for the
552    /// given [`TxHash`] if found.
553    pub fn transaction_by_hash_with_meta(
554        &self,
555        tx_hash: TxHash,
556    ) -> Option<(N::SignedTx, TransactionMeta)> {
557        for block_state in self.canonical_chain() {
558            if let Some(indexed) = block_state.find_indexed(tx_hash) {
559                return Some((indexed.tx().clone(), indexed.meta()));
560            }
561        }
562        None
563    }
564}
565
566/// State after applying the given block, this block is part of the canonical chain that partially
567/// stored in memory and can be traced back to a canonical block on disk.
568#[derive(Debug, PartialEq, Eq, Clone)]
569pub struct BlockState<N: NodePrimitives = EthPrimitives> {
570    /// The executed block that determines the state after this block has been executed.
571    block: ExecutedBlock<N>,
572    /// The block's parent block if it exists.
573    parent: Option<Arc<Self>>,
574}
575
576impl<N: NodePrimitives> BlockState<N> {
577    /// [`BlockState`] constructor.
578    pub const fn new(block: ExecutedBlock<N>) -> Self {
579        Self { block, parent: None }
580    }
581
582    /// [`BlockState`] constructor with parent.
583    pub const fn with_parent(block: ExecutedBlock<N>, parent: Option<Arc<Self>>) -> Self {
584        Self { block, parent }
585    }
586
587    /// Returns the hash and block of the on disk block this state can be traced back to.
588    pub fn anchor(&self) -> BlockNumHash {
589        let mut current = self;
590        while let Some(parent) = &current.parent {
591            current = parent;
592        }
593        current.block.recovered_block().parent_num_hash()
594    }
595
596    /// Returns the executed block that determines the state.
597    pub fn block(&self) -> ExecutedBlock<N> {
598        self.block.clone()
599    }
600
601    /// Returns a reference to the executed block that determines the state.
602    pub const fn block_ref(&self) -> &ExecutedBlock<N> {
603        &self.block
604    }
605
606    /// Returns the hash of executed block that determines the state.
607    pub fn hash(&self) -> B256 {
608        self.block.recovered_block().hash()
609    }
610
611    /// Returns the block number of executed block that determines the state.
612    pub fn number(&self) -> u64 {
613        self.block.recovered_block().number()
614    }
615
616    /// Returns the state root after applying the executed block that determines
617    /// the state.
618    pub fn state_root(&self) -> B256 {
619        self.block.recovered_block().state_root()
620    }
621
622    /// Returns the `Receipts` of executed block that determines the state.
623    pub fn receipts(&self) -> &Vec<Vec<N::Receipt>> {
624        &self.block.execution_outcome().receipts
625    }
626
627    /// Returns a vector of `Receipt` of executed block that determines the state.
628    /// We assume that the `Receipts` in the executed block `ExecutionOutcome`
629    /// has only one element corresponding to the executed block associated to
630    /// the state.
631    pub fn executed_block_receipts(&self) -> Vec<N::Receipt> {
632        let receipts = self.receipts();
633
634        debug_assert!(
635            receipts.len() <= 1,
636            "Expected at most one block's worth of receipts, found {}",
637            receipts.len()
638        );
639
640        receipts.first().cloned().unwrap_or_default()
641    }
642
643    /// Returns a vector of __parent__ `BlockStates`.
644    ///
645    /// The block state order in the output vector is newest to oldest (highest to lowest):
646    /// `[5,4,3,2,1]`
647    ///
648    /// Note: This does not include self.
649    pub fn parent_state_chain(&self) -> Vec<&Self> {
650        let mut parents = Vec::new();
651        let mut current = self.parent.as_deref();
652
653        while let Some(parent) = current {
654            parents.push(parent);
655            current = parent.parent.as_deref();
656        }
657
658        parents
659    }
660
661    /// Returns a vector of `BlockStates` representing the entire in memory chain.
662    /// The block state order in the output vector is newest to oldest (highest to lowest),
663    /// including self as the first element.
664    pub fn chain(&self) -> impl Iterator<Item = &Self> {
665        std::iter::successors(Some(self), |state| state.parent.as_deref())
666    }
667
668    /// Appends the parent chain of this [`BlockState`] to the given vector.
669    pub fn append_parent_chain<'a>(&'a self, chain: &mut Vec<&'a Self>) {
670        chain.extend(self.parent_state_chain());
671    }
672
673    /// Returns an iterator over the atomically captured chain of in memory blocks.
674    ///
675    /// This yields the blocks from newest to oldest (highest to lowest).
676    pub fn iter(self: Arc<Self>) -> impl Iterator<Item = Arc<Self>> {
677        std::iter::successors(Some(self), |state| state.parent.clone())
678    }
679
680    /// Return state provider with reference to in-memory blocks that overlay database state.
681    ///
682    /// This merges the state of all blocks that are part of the chain that the this block is
683    /// the head of. This includes all blocks that connect back to the canonical block on disk.
684    pub fn state_provider(&self, historical: StateProviderBox) -> MemoryOverlayStateProvider<N> {
685        let in_memory = self.chain().map(|block_state| block_state.block()).collect();
686
687        MemoryOverlayStateProvider::new(historical, in_memory)
688    }
689
690    /// Tries to find a block by [`BlockHashOrNumber`] in the chain ending at this block.
691    pub fn block_on_chain(&self, hash_or_num: BlockHashOrNumber) -> Option<&Self> {
692        self.chain().find(|block| match hash_or_num {
693            BlockHashOrNumber::Hash(hash) => block.hash() == hash,
694            BlockHashOrNumber::Number(number) => block.number() == number,
695        })
696    }
697
698    /// Tries to find a transaction by [`TxHash`] in the chain ending at this block.
699    pub fn transaction_on_chain(&self, hash: TxHash) -> Option<N::SignedTx> {
700        self.chain().find_map(|block_state| {
701            block_state.block_ref().recovered_block().body().transaction_by_hash(&hash).cloned()
702        })
703    }
704
705    /// Tries to find a transaction with meta by [`TxHash`] in the chain ending at this block.
706    pub fn transaction_meta_on_chain(
707        &self,
708        tx_hash: TxHash,
709    ) -> Option<(N::SignedTx, TransactionMeta)> {
710        self.chain().find_map(|block_state| {
711            block_state.find_indexed(tx_hash).map(|indexed| (indexed.tx().clone(), indexed.meta()))
712        })
713    }
714
715    /// Finds a transaction by hash and returns it with its index and block context.
716    pub fn find_indexed(&self, tx_hash: TxHash) -> Option<IndexedTx<'_, N::Block>> {
717        self.block_ref().recovered_block().find_indexed(tx_hash)
718    }
719}
720
721/// Represents an executed block stored in-memory.
722#[derive(Clone, Debug, PartialEq, Eq)]
723pub struct ExecutedBlock<N: NodePrimitives = EthPrimitives> {
724    /// Recovered Block
725    pub recovered_block: Arc<RecoveredBlock<N::Block>>,
726    /// Block's execution outcome.
727    pub execution_output: Arc<ExecutionOutcome<N::Receipt>>,
728    /// Block's hashed state.
729    pub hashed_state: Arc<HashedPostState>,
730    /// Trie updates that result from calculating the state root for the block.
731    pub trie_updates: Arc<TrieUpdates>,
732}
733
734impl<N: NodePrimitives> Default for ExecutedBlock<N> {
735    fn default() -> Self {
736        Self {
737            recovered_block: Default::default(),
738            execution_output: Default::default(),
739            hashed_state: Default::default(),
740            trie_updates: Default::default(),
741        }
742    }
743}
744
745impl<N: NodePrimitives> ExecutedBlock<N> {
746    /// Returns a reference to an inner [`SealedBlock`]
747    #[inline]
748    pub fn sealed_block(&self) -> &SealedBlock<N::Block> {
749        self.recovered_block.sealed_block()
750    }
751
752    /// Returns a reference to [`RecoveredBlock`]
753    #[inline]
754    pub fn recovered_block(&self) -> &RecoveredBlock<N::Block> {
755        &self.recovered_block
756    }
757
758    /// Returns a reference to the block's execution outcome
759    #[inline]
760    pub fn execution_outcome(&self) -> &ExecutionOutcome<N::Receipt> {
761        &self.execution_output
762    }
763
764    /// Returns a reference to the hashed state result of the execution outcome
765    #[inline]
766    pub fn hashed_state(&self) -> &HashedPostState {
767        &self.hashed_state
768    }
769
770    /// Returns a reference to the trie updates resulting from the execution outcome
771    #[inline]
772    pub fn trie_updates(&self) -> &TrieUpdates {
773        &self.trie_updates
774    }
775
776    /// Returns a [`BlockNumber`] of the block.
777    #[inline]
778    pub fn block_number(&self) -> BlockNumber {
779        self.recovered_block.header().number()
780    }
781}
782
783/// Non-empty chain of blocks.
784#[derive(Debug)]
785pub enum NewCanonicalChain<N: NodePrimitives = EthPrimitives> {
786    /// A simple append to the current canonical head
787    Commit {
788        /// all blocks that lead back to the canonical head
789        new: Vec<ExecutedBlock<N>>,
790    },
791    /// A reorged chain consists of two chains that trace back to a shared ancestor block at which
792    /// point they diverge.
793    Reorg {
794        /// All blocks of the _new_ chain
795        new: Vec<ExecutedBlock<N>>,
796        /// All blocks of the _old_ chain
797        old: Vec<ExecutedBlock<N>>,
798    },
799}
800
801impl<N: NodePrimitives<SignedTx: SignedTransaction>> NewCanonicalChain<N> {
802    /// Returns the length of the new chain.
803    pub const fn new_block_count(&self) -> usize {
804        match self {
805            Self::Commit { new } | Self::Reorg { new, .. } => new.len(),
806        }
807    }
808
809    /// Returns the length of the reorged chain.
810    pub const fn reorged_block_count(&self) -> usize {
811        match self {
812            Self::Commit { .. } => 0,
813            Self::Reorg { old, .. } => old.len(),
814        }
815    }
816
817    /// Converts the new chain into a notification that will be emitted to listeners
818    pub fn to_chain_notification(&self) -> CanonStateNotification<N> {
819        match self {
820            Self::Commit { new } => {
821                let new = Arc::new(new.iter().fold(Chain::default(), |mut chain, exec| {
822                    chain.append_block(
823                        exec.recovered_block().clone(),
824                        exec.execution_outcome().clone(),
825                    );
826                    chain
827                }));
828                CanonStateNotification::Commit { new }
829            }
830            Self::Reorg { new, old } => {
831                let new = Arc::new(new.iter().fold(Chain::default(), |mut chain, exec| {
832                    chain.append_block(
833                        exec.recovered_block().clone(),
834                        exec.execution_outcome().clone(),
835                    );
836                    chain
837                }));
838                let old = Arc::new(old.iter().fold(Chain::default(), |mut chain, exec| {
839                    chain.append_block(
840                        exec.recovered_block().clone(),
841                        exec.execution_outcome().clone(),
842                    );
843                    chain
844                }));
845                CanonStateNotification::Reorg { new, old }
846            }
847        }
848    }
849
850    /// Returns the new tip of the chain.
851    ///
852    /// Returns the new tip for [`Self::Reorg`] and [`Self::Commit`] variants which commit at least
853    /// 1 new block.
854    pub fn tip(&self) -> &SealedBlock<N::Block> {
855        match self {
856            Self::Commit { new } | Self::Reorg { new, .. } => {
857                new.last().expect("non empty blocks").recovered_block()
858            }
859        }
860    }
861}
862
863#[cfg(test)]
864mod tests {
865    use super::*;
866    use crate::test_utils::TestBlockBuilder;
867    use alloy_eips::eip7685::Requests;
868    use alloy_primitives::{Address, BlockNumber, Bytes, StorageKey, StorageValue};
869    use rand::Rng;
870    use reth_errors::ProviderResult;
871    use reth_ethereum_primitives::{EthPrimitives, Receipt};
872    use reth_primitives_traits::{Account, Bytecode};
873    use reth_storage_api::{
874        AccountReader, BlockHashReader, BytecodeReader, HashedPostStateProvider,
875        StateProofProvider, StateProvider, StateRootProvider, StorageRootProvider,
876    };
877    use reth_trie::{
878        AccountProof, HashedStorage, MultiProof, MultiProofTargets, StorageMultiProof,
879        StorageProof, TrieInput,
880    };
881
882    fn create_mock_state(
883        test_block_builder: &mut TestBlockBuilder<EthPrimitives>,
884        block_number: u64,
885        parent_hash: B256,
886    ) -> BlockState {
887        BlockState::new(
888            test_block_builder.get_executed_block_with_number(block_number, parent_hash),
889        )
890    }
891
892    fn create_mock_state_chain(
893        test_block_builder: &mut TestBlockBuilder<EthPrimitives>,
894        num_blocks: u64,
895    ) -> Vec<BlockState> {
896        let mut chain = Vec::with_capacity(num_blocks as usize);
897        let mut parent_hash = B256::random();
898        let mut parent_state: Option<BlockState> = None;
899
900        for i in 1..=num_blocks {
901            let mut state = create_mock_state(test_block_builder, i, parent_hash);
902            if let Some(parent) = parent_state {
903                state.parent = Some(Arc::new(parent));
904            }
905            parent_hash = state.hash();
906            parent_state = Some(state.clone());
907            chain.push(state);
908        }
909
910        chain
911    }
912
913    struct MockStateProvider;
914
915    impl StateProvider for MockStateProvider {
916        fn storage(
917            &self,
918            _address: Address,
919            _storage_key: StorageKey,
920        ) -> ProviderResult<Option<StorageValue>> {
921            Ok(None)
922        }
923    }
924
925    impl BytecodeReader for MockStateProvider {
926        fn bytecode_by_hash(&self, _code_hash: &B256) -> ProviderResult<Option<Bytecode>> {
927            Ok(None)
928        }
929    }
930
931    impl BlockHashReader for MockStateProvider {
932        fn block_hash(&self, _number: BlockNumber) -> ProviderResult<Option<B256>> {
933            Ok(None)
934        }
935
936        fn canonical_hashes_range(
937            &self,
938            _start: BlockNumber,
939            _end: BlockNumber,
940        ) -> ProviderResult<Vec<B256>> {
941            Ok(vec![])
942        }
943    }
944
945    impl AccountReader for MockStateProvider {
946        fn basic_account(&self, _address: &Address) -> ProviderResult<Option<Account>> {
947            Ok(None)
948        }
949    }
950
951    impl StateRootProvider for MockStateProvider {
952        fn state_root(&self, _hashed_state: HashedPostState) -> ProviderResult<B256> {
953            Ok(B256::random())
954        }
955
956        fn state_root_from_nodes(&self, _input: TrieInput) -> ProviderResult<B256> {
957            Ok(B256::random())
958        }
959
960        fn state_root_with_updates(
961            &self,
962            _hashed_state: HashedPostState,
963        ) -> ProviderResult<(B256, TrieUpdates)> {
964            Ok((B256::random(), TrieUpdates::default()))
965        }
966
967        fn state_root_from_nodes_with_updates(
968            &self,
969            _input: TrieInput,
970        ) -> ProviderResult<(B256, TrieUpdates)> {
971            Ok((B256::random(), TrieUpdates::default()))
972        }
973    }
974
975    impl HashedPostStateProvider for MockStateProvider {
976        fn hashed_post_state(&self, _bundle_state: &revm_database::BundleState) -> HashedPostState {
977            HashedPostState::default()
978        }
979    }
980
981    impl StorageRootProvider for MockStateProvider {
982        fn storage_root(
983            &self,
984            _address: Address,
985            _hashed_storage: HashedStorage,
986        ) -> ProviderResult<B256> {
987            Ok(B256::random())
988        }
989
990        fn storage_proof(
991            &self,
992            _address: Address,
993            slot: B256,
994            _hashed_storage: HashedStorage,
995        ) -> ProviderResult<StorageProof> {
996            Ok(StorageProof::new(slot))
997        }
998
999        fn storage_multiproof(
1000            &self,
1001            _address: Address,
1002            _slots: &[B256],
1003            _hashed_storage: HashedStorage,
1004        ) -> ProviderResult<StorageMultiProof> {
1005            Ok(StorageMultiProof::empty())
1006        }
1007    }
1008
1009    impl StateProofProvider for MockStateProvider {
1010        fn proof(
1011            &self,
1012            _input: TrieInput,
1013            _address: Address,
1014            _slots: &[B256],
1015        ) -> ProviderResult<AccountProof> {
1016            Ok(AccountProof::new(Address::random()))
1017        }
1018
1019        fn multiproof(
1020            &self,
1021            _input: TrieInput,
1022            _targets: MultiProofTargets,
1023        ) -> ProviderResult<MultiProof> {
1024            Ok(MultiProof::default())
1025        }
1026
1027        fn witness(
1028            &self,
1029            _input: TrieInput,
1030            _target: HashedPostState,
1031        ) -> ProviderResult<Vec<Bytes>> {
1032            Ok(Vec::default())
1033        }
1034    }
1035
1036    #[test]
1037    fn test_in_memory_state_impl_state_by_hash() {
1038        let mut state_by_hash = HashMap::default();
1039        let number = rand::rng().random::<u64>();
1040        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1041        let state = Arc::new(create_mock_state(&mut test_block_builder, number, B256::random()));
1042        state_by_hash.insert(state.hash(), state.clone());
1043
1044        let in_memory_state = InMemoryState::new(state_by_hash, BTreeMap::new(), None);
1045
1046        assert_eq!(in_memory_state.state_by_hash(state.hash()), Some(state));
1047        assert_eq!(in_memory_state.state_by_hash(B256::random()), None);
1048    }
1049
1050    #[test]
1051    fn test_in_memory_state_impl_state_by_number() {
1052        let mut state_by_hash = HashMap::default();
1053        let mut hash_by_number = BTreeMap::new();
1054
1055        let number = rand::rng().random::<u64>();
1056        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1057        let state = Arc::new(create_mock_state(&mut test_block_builder, number, B256::random()));
1058        let hash = state.hash();
1059
1060        state_by_hash.insert(hash, state.clone());
1061        hash_by_number.insert(number, hash);
1062
1063        let in_memory_state = InMemoryState::new(state_by_hash, hash_by_number, None);
1064
1065        assert_eq!(in_memory_state.state_by_number(number), Some(state));
1066        assert_eq!(in_memory_state.state_by_number(number + 1), None);
1067    }
1068
1069    #[test]
1070    fn test_in_memory_state_impl_head_state() {
1071        let mut state_by_hash = HashMap::default();
1072        let mut hash_by_number = BTreeMap::new();
1073        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1074        let state1 = Arc::new(create_mock_state(&mut test_block_builder, 1, B256::random()));
1075        let hash1 = state1.hash();
1076        let state2 = Arc::new(create_mock_state(&mut test_block_builder, 2, hash1));
1077        let hash2 = state2.hash();
1078        hash_by_number.insert(1, hash1);
1079        hash_by_number.insert(2, hash2);
1080        state_by_hash.insert(hash1, state1);
1081        state_by_hash.insert(hash2, state2);
1082
1083        let in_memory_state = InMemoryState::new(state_by_hash, hash_by_number, None);
1084        let head_state = in_memory_state.head_state().unwrap();
1085
1086        assert_eq!(head_state.hash(), hash2);
1087        assert_eq!(head_state.number(), 2);
1088    }
1089
1090    #[test]
1091    fn test_in_memory_state_impl_pending_state() {
1092        let pending_number = rand::rng().random::<u64>();
1093        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1094        let pending_state =
1095            create_mock_state(&mut test_block_builder, pending_number, B256::random());
1096        let pending_hash = pending_state.hash();
1097
1098        let in_memory_state =
1099            InMemoryState::new(HashMap::default(), BTreeMap::new(), Some(pending_state));
1100
1101        let result = in_memory_state.pending_state();
1102        assert!(result.is_some());
1103        let actual_pending_state = result.unwrap();
1104        assert_eq!(actual_pending_state.block.recovered_block().hash(), pending_hash);
1105        assert_eq!(actual_pending_state.block.recovered_block().number, pending_number);
1106    }
1107
1108    #[test]
1109    fn test_in_memory_state_impl_no_pending_state() {
1110        let in_memory_state: InMemoryState =
1111            InMemoryState::new(HashMap::default(), BTreeMap::new(), None);
1112
1113        assert_eq!(in_memory_state.pending_state(), None);
1114    }
1115
1116    #[test]
1117    fn test_state() {
1118        let number = rand::rng().random::<u64>();
1119        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1120        let block = test_block_builder.get_executed_block_with_number(number, B256::random());
1121
1122        let state = BlockState::new(block.clone());
1123
1124        assert_eq!(state.block(), block);
1125        assert_eq!(state.hash(), block.recovered_block().hash());
1126        assert_eq!(state.number(), number);
1127        assert_eq!(state.state_root(), block.recovered_block().state_root);
1128    }
1129
1130    #[test]
1131    fn test_state_receipts() {
1132        let receipts = vec![vec![Receipt::default()]];
1133        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1134        let block =
1135            test_block_builder.get_executed_block_with_receipts(receipts.clone(), B256::random());
1136
1137        let state = BlockState::new(block);
1138
1139        assert_eq!(state.receipts(), &receipts);
1140    }
1141
1142    #[test]
1143    fn test_in_memory_state_chain_update() {
1144        let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1145        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1146        let block1 = test_block_builder.get_executed_block_with_number(0, B256::random());
1147        let block2 = test_block_builder.get_executed_block_with_number(0, B256::random());
1148        let chain = NewCanonicalChain::Commit { new: vec![block1.clone()] };
1149        state.update_chain(chain);
1150        assert_eq!(
1151            state.head_state().unwrap().block_ref().recovered_block().hash(),
1152            block1.recovered_block().hash()
1153        );
1154        assert_eq!(
1155            state.state_by_number(0).unwrap().block_ref().recovered_block().hash(),
1156            block1.recovered_block().hash()
1157        );
1158
1159        let chain = NewCanonicalChain::Reorg { new: vec![block2.clone()], old: vec![block1] };
1160        state.update_chain(chain);
1161        assert_eq!(
1162            state.head_state().unwrap().block_ref().recovered_block().hash(),
1163            block2.recovered_block().hash()
1164        );
1165        assert_eq!(
1166            state.state_by_number(0).unwrap().block_ref().recovered_block().hash(),
1167            block2.recovered_block().hash()
1168        );
1169
1170        assert_eq!(state.inner.in_memory_state.block_count(), 1);
1171    }
1172
1173    #[test]
1174    fn test_in_memory_state_set_pending_block() {
1175        let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1176        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1177
1178        // First random block
1179        let block1 = test_block_builder.get_executed_block_with_number(0, B256::random());
1180
1181        // Second block with parent hash of the first block
1182        let block2 =
1183            test_block_builder.get_executed_block_with_number(1, block1.recovered_block().hash());
1184
1185        // Commit the two blocks
1186        let chain = NewCanonicalChain::Commit { new: vec![block1.clone(), block2.clone()] };
1187        state.update_chain(chain);
1188
1189        // Assert that the pending state is None before setting it
1190        assert!(state.pending_state().is_none());
1191
1192        // Set the pending block
1193        state.set_pending_block(block2.clone());
1194
1195        // Check the pending state
1196        assert_eq!(
1197            state.pending_state().unwrap(),
1198            BlockState::with_parent(block2.clone(), Some(Arc::new(BlockState::new(block1))))
1199        );
1200
1201        // Check the pending block
1202        assert_eq!(state.pending_block().unwrap(), block2.recovered_block().sealed_block().clone());
1203
1204        // Check the pending block number and hash
1205        assert_eq!(
1206            state.pending_block_num_hash().unwrap(),
1207            BlockNumHash { number: 1, hash: block2.recovered_block().hash() }
1208        );
1209
1210        // Check the pending header
1211        assert_eq!(state.pending_header().unwrap(), block2.recovered_block().header().clone());
1212
1213        // Check the pending sealed header
1214        assert_eq!(
1215            state.pending_sealed_header().unwrap(),
1216            block2.recovered_block().clone_sealed_header()
1217        );
1218
1219        // Check the pending block with senders
1220        assert_eq!(state.pending_recovered_block().unwrap(), block2.recovered_block().clone());
1221
1222        // Check the pending block and receipts
1223        assert_eq!(
1224            state.pending_block_and_receipts().unwrap(),
1225            (block2.recovered_block().clone(), vec![])
1226        );
1227    }
1228
1229    #[test]
1230    fn test_canonical_in_memory_state_state_provider() {
1231        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1232        let block1 = test_block_builder.get_executed_block_with_number(1, B256::random());
1233        let block2 =
1234            test_block_builder.get_executed_block_with_number(2, block1.recovered_block().hash());
1235        let block3 =
1236            test_block_builder.get_executed_block_with_number(3, block2.recovered_block().hash());
1237
1238        let state1 = Arc::new(BlockState::new(block1.clone()));
1239        let state2 = Arc::new(BlockState::with_parent(block2.clone(), Some(state1.clone())));
1240        let state3 = Arc::new(BlockState::with_parent(block3.clone(), Some(state2.clone())));
1241
1242        let mut blocks = HashMap::default();
1243        blocks.insert(block1.recovered_block().hash(), state1);
1244        blocks.insert(block2.recovered_block().hash(), state2);
1245        blocks.insert(block3.recovered_block().hash(), state3);
1246
1247        let mut numbers = BTreeMap::new();
1248        numbers.insert(1, block1.recovered_block().hash());
1249        numbers.insert(2, block2.recovered_block().hash());
1250        numbers.insert(3, block3.recovered_block().hash());
1251
1252        let canonical_state = CanonicalInMemoryState::new(blocks, numbers, None, None, None);
1253
1254        let historical: StateProviderBox = Box::new(MockStateProvider);
1255
1256        let overlay_provider =
1257            canonical_state.state_provider(block3.recovered_block().hash(), historical);
1258
1259        assert_eq!(overlay_provider.in_memory.len(), 3);
1260        assert_eq!(overlay_provider.in_memory[0].recovered_block().number, 3);
1261        assert_eq!(overlay_provider.in_memory[1].recovered_block().number, 2);
1262        assert_eq!(overlay_provider.in_memory[2].recovered_block().number, 1);
1263
1264        assert_eq!(
1265            overlay_provider.in_memory[0].recovered_block().parent_hash,
1266            overlay_provider.in_memory[1].recovered_block().hash()
1267        );
1268        assert_eq!(
1269            overlay_provider.in_memory[1].recovered_block().parent_hash,
1270            overlay_provider.in_memory[2].recovered_block().hash()
1271        );
1272
1273        let unknown_hash = B256::random();
1274        let empty_overlay_provider =
1275            canonical_state.state_provider(unknown_hash, Box::new(MockStateProvider));
1276        assert_eq!(empty_overlay_provider.in_memory.len(), 0);
1277    }
1278
1279    #[test]
1280    fn test_canonical_in_memory_state_canonical_chain_empty() {
1281        let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1282        assert!(state.canonical_chain().next().is_none());
1283    }
1284
1285    #[test]
1286    fn test_canonical_in_memory_state_canonical_chain_single_block() {
1287        let block = TestBlockBuilder::eth().get_executed_block_with_number(1, B256::random());
1288        let hash = block.recovered_block().hash();
1289        let mut blocks = HashMap::default();
1290        blocks.insert(hash, Arc::new(BlockState::new(block)));
1291        let mut numbers = BTreeMap::new();
1292        numbers.insert(1, hash);
1293
1294        let state = CanonicalInMemoryState::new(blocks, numbers, None, None, None);
1295        let chain: Vec<_> = state.canonical_chain().collect();
1296
1297        assert_eq!(chain.len(), 1);
1298        assert_eq!(chain[0].number(), 1);
1299        assert_eq!(chain[0].hash(), hash);
1300    }
1301
1302    #[test]
1303    fn test_canonical_in_memory_state_canonical_chain_multiple_blocks() {
1304        let mut parent_hash = B256::random();
1305        let mut block_builder = TestBlockBuilder::eth();
1306        let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1307
1308        for i in 1..=3 {
1309            let block = block_builder.get_executed_block_with_number(i, parent_hash);
1310            let hash = block.recovered_block().hash();
1311            state.update_blocks(Some(block), None);
1312            parent_hash = hash;
1313        }
1314
1315        let chain: Vec<_> = state.canonical_chain().collect();
1316
1317        assert_eq!(chain.len(), 3);
1318        assert_eq!(chain[0].number(), 3);
1319        assert_eq!(chain[1].number(), 2);
1320        assert_eq!(chain[2].number(), 1);
1321    }
1322
1323    // ensures the pending block is not part of the canonical chain
1324    #[test]
1325    fn test_canonical_in_memory_state_canonical_chain_with_pending_block() {
1326        let mut parent_hash = B256::random();
1327        let mut block_builder = TestBlockBuilder::<EthPrimitives>::eth();
1328        let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1329
1330        for i in 1..=2 {
1331            let block = block_builder.get_executed_block_with_number(i, parent_hash);
1332            let hash = block.recovered_block().hash();
1333            state.update_blocks(Some(block), None);
1334            parent_hash = hash;
1335        }
1336
1337        let pending_block = block_builder.get_executed_block_with_number(3, parent_hash);
1338        state.set_pending_block(pending_block);
1339        let chain: Vec<_> = state.canonical_chain().collect();
1340
1341        assert_eq!(chain.len(), 2);
1342        assert_eq!(chain[0].number(), 2);
1343        assert_eq!(chain[1].number(), 1);
1344    }
1345
1346    #[test]
1347    fn test_block_state_parent_blocks() {
1348        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1349        let chain = create_mock_state_chain(&mut test_block_builder, 4);
1350
1351        let parents = chain[3].parent_state_chain();
1352        assert_eq!(parents.len(), 3);
1353        assert_eq!(parents[0].block().recovered_block().number, 3);
1354        assert_eq!(parents[1].block().recovered_block().number, 2);
1355        assert_eq!(parents[2].block().recovered_block().number, 1);
1356
1357        let parents = chain[2].parent_state_chain();
1358        assert_eq!(parents.len(), 2);
1359        assert_eq!(parents[0].block().recovered_block().number, 2);
1360        assert_eq!(parents[1].block().recovered_block().number, 1);
1361
1362        let parents = chain[0].parent_state_chain();
1363        assert_eq!(parents.len(), 0);
1364    }
1365
1366    #[test]
1367    fn test_block_state_single_block_state_chain() {
1368        let single_block_number = 1;
1369        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1370        let single_block =
1371            create_mock_state(&mut test_block_builder, single_block_number, B256::random());
1372        let single_block_hash = single_block.block().recovered_block().hash();
1373
1374        let parents = single_block.parent_state_chain();
1375        assert_eq!(parents.len(), 0);
1376
1377        let block_state_chain = single_block.chain().collect::<Vec<_>>();
1378        assert_eq!(block_state_chain.len(), 1);
1379        assert_eq!(block_state_chain[0].block().recovered_block().number, single_block_number);
1380        assert_eq!(block_state_chain[0].block().recovered_block().hash(), single_block_hash);
1381    }
1382
1383    #[test]
1384    fn test_block_state_chain() {
1385        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1386        let chain = create_mock_state_chain(&mut test_block_builder, 3);
1387
1388        let block_state_chain = chain[2].chain().collect::<Vec<_>>();
1389        assert_eq!(block_state_chain.len(), 3);
1390        assert_eq!(block_state_chain[0].block().recovered_block().number, 3);
1391        assert_eq!(block_state_chain[1].block().recovered_block().number, 2);
1392        assert_eq!(block_state_chain[2].block().recovered_block().number, 1);
1393
1394        let block_state_chain = chain[1].chain().collect::<Vec<_>>();
1395        assert_eq!(block_state_chain.len(), 2);
1396        assert_eq!(block_state_chain[0].block().recovered_block().number, 2);
1397        assert_eq!(block_state_chain[1].block().recovered_block().number, 1);
1398
1399        let block_state_chain = chain[0].chain().collect::<Vec<_>>();
1400        assert_eq!(block_state_chain.len(), 1);
1401        assert_eq!(block_state_chain[0].block().recovered_block().number, 1);
1402    }
1403
1404    #[test]
1405    fn test_to_chain_notification() {
1406        // Generate 4 blocks
1407        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1408        let block0 = test_block_builder.get_executed_block_with_number(0, B256::random());
1409        let block1 =
1410            test_block_builder.get_executed_block_with_number(1, block0.recovered_block.hash());
1411        let block1a =
1412            test_block_builder.get_executed_block_with_number(1, block0.recovered_block.hash());
1413        let block2 =
1414            test_block_builder.get_executed_block_with_number(2, block1.recovered_block.hash());
1415        let block2a =
1416            test_block_builder.get_executed_block_with_number(2, block1.recovered_block.hash());
1417
1418        let sample_execution_outcome = ExecutionOutcome {
1419            receipts: vec![vec![], vec![]],
1420            requests: vec![Requests::default(), Requests::default()],
1421            ..Default::default()
1422        };
1423
1424        // Test commit notification
1425        let chain_commit = NewCanonicalChain::Commit { new: vec![block0.clone(), block1.clone()] };
1426
1427        assert_eq!(
1428            chain_commit.to_chain_notification(),
1429            CanonStateNotification::Commit {
1430                new: Arc::new(Chain::new(
1431                    vec![block0.recovered_block().clone(), block1.recovered_block().clone()],
1432                    sample_execution_outcome.clone(),
1433                    None
1434                ))
1435            }
1436        );
1437
1438        // Test reorg notification
1439        let chain_reorg = NewCanonicalChain::Reorg {
1440            new: vec![block1a.clone(), block2a.clone()],
1441            old: vec![block1.clone(), block2.clone()],
1442        };
1443
1444        assert_eq!(
1445            chain_reorg.to_chain_notification(),
1446            CanonStateNotification::Reorg {
1447                old: Arc::new(Chain::new(
1448                    vec![block1.recovered_block().clone(), block2.recovered_block().clone()],
1449                    sample_execution_outcome.clone(),
1450                    None
1451                )),
1452                new: Arc::new(Chain::new(
1453                    vec![block1a.recovered_block().clone(), block2a.recovered_block().clone()],
1454                    sample_execution_outcome,
1455                    None
1456                ))
1457            }
1458        );
1459    }
1460}