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