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: ExecutedBlockWithTrieUpdates<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 = ExecutedBlockWithTrieUpdates<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: ExecutedBlockWithTrieUpdates<N>,
572    /// The block's parent block if it exists.
573    parent: Option<Arc<BlockState<N>>>,
574}
575
576impl<N: NodePrimitives> BlockState<N> {
577    /// [`BlockState`] constructor.
578    pub const fn new(block: ExecutedBlockWithTrieUpdates<N>) -> Self {
579        Self { block, parent: None }
580    }
581
582    /// [`BlockState`] constructor with parent.
583    pub const fn with_parent(
584        block: ExecutedBlockWithTrieUpdates<N>,
585        parent: Option<Arc<Self>>,
586    ) -> Self {
587        Self { block, parent }
588    }
589
590    /// Returns the hash and block of the on disk block this state can be traced back to.
591    pub fn anchor(&self) -> BlockNumHash {
592        let mut current = self;
593        while let Some(parent) = &current.parent {
594            current = parent;
595        }
596        current.block.recovered_block().parent_num_hash()
597    }
598
599    /// Returns the executed block that determines the state.
600    pub fn block(&self) -> ExecutedBlockWithTrieUpdates<N> {
601        self.block.clone()
602    }
603
604    /// Returns a reference to the executed block that determines the state.
605    pub const fn block_ref(&self) -> &ExecutedBlockWithTrieUpdates<N> {
606        &self.block
607    }
608
609    /// Returns the hash of executed block that determines the state.
610    pub fn hash(&self) -> B256 {
611        self.block.recovered_block().hash()
612    }
613
614    /// Returns the block number of executed block that determines the state.
615    pub fn number(&self) -> u64 {
616        self.block.recovered_block().number()
617    }
618
619    /// Returns the state root after applying the executed block that determines
620    /// the state.
621    pub fn state_root(&self) -> B256 {
622        self.block.recovered_block().state_root()
623    }
624
625    /// Returns the `Receipts` of executed block that determines the state.
626    pub fn receipts(&self) -> &Vec<Vec<N::Receipt>> {
627        &self.block.execution_outcome().receipts
628    }
629
630    /// Returns a vector of `Receipt` of executed block that determines the state.
631    /// We assume that the `Receipts` in the executed block `ExecutionOutcome`
632    /// has only one element corresponding to the executed block associated to
633    /// the state.
634    pub fn executed_block_receipts(&self) -> Vec<N::Receipt> {
635        let receipts = self.receipts();
636
637        debug_assert!(
638            receipts.len() <= 1,
639            "Expected at most one block's worth of receipts, found {}",
640            receipts.len()
641        );
642
643        receipts.first().cloned().unwrap_or_default()
644    }
645
646    /// Returns a vector of __parent__ `BlockStates`.
647    ///
648    /// The block state order in the output vector is newest to oldest (highest to lowest):
649    /// `[5,4,3,2,1]`
650    ///
651    /// Note: This does not include self.
652    pub fn parent_state_chain(&self) -> Vec<&Self> {
653        let mut parents = Vec::new();
654        let mut current = self.parent.as_deref();
655
656        while let Some(parent) = current {
657            parents.push(parent);
658            current = parent.parent.as_deref();
659        }
660
661        parents
662    }
663
664    /// Returns a vector of `BlockStates` representing the entire in memory chain.
665    /// The block state order in the output vector is newest to oldest (highest to lowest),
666    /// including self as the first element.
667    pub fn chain(&self) -> impl Iterator<Item = &Self> {
668        std::iter::successors(Some(self), |state| state.parent.as_deref())
669    }
670
671    /// Appends the parent chain of this [`BlockState`] to the given vector.
672    pub fn append_parent_chain<'a>(&'a self, chain: &mut Vec<&'a Self>) {
673        chain.extend(self.parent_state_chain());
674    }
675
676    /// Returns an iterator over the atomically captured chain of in memory blocks.
677    ///
678    /// This yields the blocks from newest to oldest (highest to lowest).
679    pub fn iter(self: Arc<Self>) -> impl Iterator<Item = Arc<Self>> {
680        std::iter::successors(Some(self), |state| state.parent.clone())
681    }
682
683    /// Return state provider with reference to in-memory blocks that overlay database state.
684    ///
685    /// This merges the state of all blocks that are part of the chain that the this block is
686    /// the head of. This includes all blocks that connect back to the canonical block on disk.
687    pub fn state_provider(&self, historical: StateProviderBox) -> MemoryOverlayStateProvider<N> {
688        let in_memory = self.chain().map(|block_state| block_state.block()).collect();
689
690        MemoryOverlayStateProvider::new(historical, in_memory)
691    }
692
693    /// Tries to find a block by [`BlockHashOrNumber`] in the chain ending at this block.
694    pub fn block_on_chain(&self, hash_or_num: BlockHashOrNumber) -> Option<&Self> {
695        self.chain().find(|block| match hash_or_num {
696            BlockHashOrNumber::Hash(hash) => block.hash() == hash,
697            BlockHashOrNumber::Number(number) => block.number() == number,
698        })
699    }
700
701    /// Tries to find a transaction by [`TxHash`] in the chain ending at this block.
702    pub fn transaction_on_chain(&self, hash: TxHash) -> Option<N::SignedTx> {
703        self.chain().find_map(|block_state| {
704            block_state.block_ref().recovered_block().body().transaction_by_hash(&hash).cloned()
705        })
706    }
707
708    /// Tries to find a transaction with meta by [`TxHash`] in the chain ending at this block.
709    pub fn transaction_meta_on_chain(
710        &self,
711        tx_hash: TxHash,
712    ) -> Option<(N::SignedTx, TransactionMeta)> {
713        self.chain().find_map(|block_state| {
714            block_state.find_indexed(tx_hash).map(|indexed| (indexed.tx().clone(), indexed.meta()))
715        })
716    }
717
718    /// Finds a transaction by hash and returns it with its index and block context.
719    pub fn find_indexed(&self, tx_hash: TxHash) -> Option<IndexedTx<'_, N::Block>> {
720        self.block_ref().recovered_block().find_indexed(tx_hash)
721    }
722}
723
724/// Represents an executed block stored in-memory.
725#[derive(Clone, Debug, PartialEq, Eq)]
726pub struct ExecutedBlock<N: NodePrimitives = EthPrimitives> {
727    /// Recovered Block
728    pub recovered_block: Arc<RecoveredBlock<N::Block>>,
729    /// Block's execution outcome.
730    pub execution_output: Arc<ExecutionOutcome<N::Receipt>>,
731    /// Block's hashed state.
732    pub hashed_state: Arc<HashedPostState>,
733}
734
735impl<N: NodePrimitives> Default for ExecutedBlock<N> {
736    fn default() -> Self {
737        Self {
738            recovered_block: Default::default(),
739            execution_output: Default::default(),
740            hashed_state: 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 [`BlockNumber`] of the block.
771    #[inline]
772    pub fn block_number(&self) -> BlockNumber {
773        self.recovered_block.header().number()
774    }
775}
776
777/// Trie updates that result from calculating the state root for the block.
778#[derive(Debug, Clone, PartialEq, Eq)]
779pub enum ExecutedTrieUpdates {
780    /// Trie updates present. State root was calculated, and the trie updates can be applied to the
781    /// database.
782    Present(Arc<TrieUpdates>),
783    /// Trie updates missing. State root was calculated, but the trie updates cannot be applied to
784    /// the current database state. To apply the updates, the state root must be recalculated, and
785    /// new trie updates must be generated.
786    ///
787    /// This can happen when processing fork chain blocks that are building on top of the
788    /// historical database state. Since we don't store the historical trie state, we cannot
789    /// generate the trie updates for it.
790    Missing,
791}
792
793impl ExecutedTrieUpdates {
794    /// Creates a [`ExecutedTrieUpdates`] with present but empty trie updates.
795    pub fn empty() -> Self {
796        Self::Present(Arc::default())
797    }
798
799    /// Sets the trie updates to the provided value as present.
800    pub fn set_present(&mut self, updates: Arc<TrieUpdates>) {
801        *self = Self::Present(updates);
802    }
803
804    /// Takes the present trie updates, leaving the state as missing.
805    pub fn take_present(&mut self) -> Option<Arc<TrieUpdates>> {
806        match self {
807            Self::Present(updates) => {
808                let updates = core::mem::take(updates);
809                *self = Self::Missing;
810                Some(updates)
811            }
812            Self::Missing => None,
813        }
814    }
815
816    /// Returns a reference to the trie updates if present.
817    #[allow(clippy::missing_const_for_fn)] // false positive
818    pub fn as_ref(&self) -> Option<&TrieUpdates> {
819        match self {
820            Self::Present(updates) => Some(updates),
821            Self::Missing => None,
822        }
823    }
824
825    /// Returns `true` if the trie updates are present.
826    pub const fn is_present(&self) -> bool {
827        matches!(self, Self::Present(_))
828    }
829
830    /// Returns `true` if the trie updates are missing.
831    pub const fn is_missing(&self) -> bool {
832        matches!(self, Self::Missing)
833    }
834}
835
836/// An [`ExecutedBlock`] with its [`TrieUpdates`].
837///
838/// We store it as separate type because [`TrieUpdates`] are only available for blocks stored in
839/// memory and can't be obtained for canonical persisted blocks.
840#[derive(
841    Clone, Debug, PartialEq, Eq, derive_more::Deref, derive_more::DerefMut, derive_more::Into,
842)]
843pub struct ExecutedBlockWithTrieUpdates<N: NodePrimitives = EthPrimitives> {
844    /// Inner [`ExecutedBlock`].
845    #[deref]
846    #[deref_mut]
847    #[into]
848    pub block: ExecutedBlock<N>,
849    /// Trie updates that result from calculating the state root for the block.
850    ///
851    /// If [`ExecutedTrieUpdates::Missing`], the trie updates should be computed when persisting
852    /// the block **on top of the canonical parent**.
853    pub trie: ExecutedTrieUpdates,
854}
855
856impl<N: NodePrimitives> ExecutedBlockWithTrieUpdates<N> {
857    /// [`ExecutedBlock`] constructor.
858    pub const fn new(
859        recovered_block: Arc<RecoveredBlock<N::Block>>,
860        execution_output: Arc<ExecutionOutcome<N::Receipt>>,
861        hashed_state: Arc<HashedPostState>,
862        trie: ExecutedTrieUpdates,
863    ) -> Self {
864        Self { block: ExecutedBlock { recovered_block, execution_output, hashed_state }, trie }
865    }
866
867    /// Returns a reference to the trie updates for the block, if present.
868    #[inline]
869    pub fn trie_updates(&self) -> Option<&TrieUpdates> {
870        self.trie.as_ref()
871    }
872
873    /// Converts the value into [`SealedBlock`].
874    pub fn into_sealed_block(self) -> SealedBlock<N::Block> {
875        let block = Arc::unwrap_or_clone(self.block.recovered_block);
876        block.into_sealed_block()
877    }
878}
879
880/// Non-empty chain of blocks.
881#[derive(Debug)]
882pub enum NewCanonicalChain<N: NodePrimitives = EthPrimitives> {
883    /// A simple append to the current canonical head
884    Commit {
885        /// all blocks that lead back to the canonical head
886        new: Vec<ExecutedBlockWithTrieUpdates<N>>,
887    },
888    /// A reorged chain consists of two chains that trace back to a shared ancestor block at which
889    /// point they diverge.
890    Reorg {
891        /// All blocks of the _new_ chain
892        new: Vec<ExecutedBlockWithTrieUpdates<N>>,
893        /// All blocks of the _old_ chain
894        ///
895        /// These are not [`ExecutedBlockWithTrieUpdates`] because we don't always have the trie
896        /// updates for the old canonical chain. For example, in case of node being restarted right
897        /// before the reorg [`TrieUpdates`] can't be fetched from database.
898        old: Vec<ExecutedBlock<N>>,
899    },
900}
901
902impl<N: NodePrimitives<SignedTx: SignedTransaction>> NewCanonicalChain<N> {
903    /// Returns the length of the new chain.
904    pub const fn new_block_count(&self) -> usize {
905        match self {
906            Self::Commit { new } | Self::Reorg { new, .. } => new.len(),
907        }
908    }
909
910    /// Returns the length of the reorged chain.
911    pub const fn reorged_block_count(&self) -> usize {
912        match self {
913            Self::Commit { .. } => 0,
914            Self::Reorg { old, .. } => old.len(),
915        }
916    }
917
918    /// Converts the new chain into a notification that will be emitted to listeners
919    pub fn to_chain_notification(&self) -> CanonStateNotification<N> {
920        match self {
921            Self::Commit { new } => {
922                let new = Arc::new(new.iter().fold(Chain::default(), |mut chain, exec| {
923                    chain.append_block(
924                        exec.recovered_block().clone(),
925                        exec.execution_outcome().clone(),
926                    );
927                    chain
928                }));
929                CanonStateNotification::Commit { new }
930            }
931            Self::Reorg { new, old } => {
932                let new = Arc::new(new.iter().fold(Chain::default(), |mut chain, exec| {
933                    chain.append_block(
934                        exec.recovered_block().clone(),
935                        exec.execution_outcome().clone(),
936                    );
937                    chain
938                }));
939                let old = Arc::new(old.iter().fold(Chain::default(), |mut chain, exec| {
940                    chain.append_block(
941                        exec.recovered_block().clone(),
942                        exec.execution_outcome().clone(),
943                    );
944                    chain
945                }));
946                CanonStateNotification::Reorg { new, old }
947            }
948        }
949    }
950
951    /// Returns the new tip of the chain.
952    ///
953    /// Returns the new tip for [`Self::Reorg`] and [`Self::Commit`] variants which commit at least
954    /// 1 new block.
955    pub fn tip(&self) -> &SealedBlock<N::Block> {
956        match self {
957            Self::Commit { new } | Self::Reorg { new, .. } => {
958                new.last().expect("non empty blocks").recovered_block()
959            }
960        }
961    }
962}
963
964#[cfg(test)]
965mod tests {
966    use super::*;
967    use crate::test_utils::TestBlockBuilder;
968    use alloy_eips::eip7685::Requests;
969    use alloy_primitives::{Address, BlockNumber, Bytes, StorageKey, StorageValue};
970    use rand::Rng;
971    use reth_errors::ProviderResult;
972    use reth_ethereum_primitives::{EthPrimitives, Receipt};
973    use reth_primitives_traits::{Account, Bytecode};
974    use reth_storage_api::{
975        AccountReader, BlockHashReader, BytecodeReader, HashedPostStateProvider,
976        StateProofProvider, StateProvider, StateRootProvider, StorageRootProvider,
977    };
978    use reth_trie::{
979        AccountProof, HashedStorage, MultiProof, MultiProofTargets, StorageMultiProof,
980        StorageProof, TrieInput,
981    };
982
983    fn create_mock_state(
984        test_block_builder: &mut TestBlockBuilder<EthPrimitives>,
985        block_number: u64,
986        parent_hash: B256,
987    ) -> BlockState {
988        BlockState::new(
989            test_block_builder.get_executed_block_with_number(block_number, parent_hash),
990        )
991    }
992
993    fn create_mock_state_chain(
994        test_block_builder: &mut TestBlockBuilder<EthPrimitives>,
995        num_blocks: u64,
996    ) -> Vec<BlockState> {
997        let mut chain = Vec::with_capacity(num_blocks as usize);
998        let mut parent_hash = B256::random();
999        let mut parent_state: Option<BlockState> = None;
1000
1001        for i in 1..=num_blocks {
1002            let mut state = create_mock_state(test_block_builder, i, parent_hash);
1003            if let Some(parent) = parent_state {
1004                state.parent = Some(Arc::new(parent));
1005            }
1006            parent_hash = state.hash();
1007            parent_state = Some(state.clone());
1008            chain.push(state);
1009        }
1010
1011        chain
1012    }
1013
1014    struct MockStateProvider;
1015
1016    impl StateProvider for MockStateProvider {
1017        fn storage(
1018            &self,
1019            _address: Address,
1020            _storage_key: StorageKey,
1021        ) -> ProviderResult<Option<StorageValue>> {
1022            Ok(None)
1023        }
1024    }
1025
1026    impl BytecodeReader for MockStateProvider {
1027        fn bytecode_by_hash(&self, _code_hash: &B256) -> ProviderResult<Option<Bytecode>> {
1028            Ok(None)
1029        }
1030    }
1031
1032    impl BlockHashReader for MockStateProvider {
1033        fn block_hash(&self, _number: BlockNumber) -> ProviderResult<Option<B256>> {
1034            Ok(None)
1035        }
1036
1037        fn canonical_hashes_range(
1038            &self,
1039            _start: BlockNumber,
1040            _end: BlockNumber,
1041        ) -> ProviderResult<Vec<B256>> {
1042            Ok(vec![])
1043        }
1044    }
1045
1046    impl AccountReader for MockStateProvider {
1047        fn basic_account(&self, _address: &Address) -> ProviderResult<Option<Account>> {
1048            Ok(None)
1049        }
1050    }
1051
1052    impl StateRootProvider for MockStateProvider {
1053        fn state_root(&self, _hashed_state: HashedPostState) -> ProviderResult<B256> {
1054            Ok(B256::random())
1055        }
1056
1057        fn state_root_from_nodes(&self, _input: TrieInput) -> ProviderResult<B256> {
1058            Ok(B256::random())
1059        }
1060
1061        fn state_root_with_updates(
1062            &self,
1063            _hashed_state: HashedPostState,
1064        ) -> ProviderResult<(B256, TrieUpdates)> {
1065            Ok((B256::random(), TrieUpdates::default()))
1066        }
1067
1068        fn state_root_from_nodes_with_updates(
1069            &self,
1070            _input: TrieInput,
1071        ) -> ProviderResult<(B256, TrieUpdates)> {
1072            Ok((B256::random(), TrieUpdates::default()))
1073        }
1074    }
1075
1076    impl HashedPostStateProvider for MockStateProvider {
1077        fn hashed_post_state(&self, _bundle_state: &revm_database::BundleState) -> HashedPostState {
1078            HashedPostState::default()
1079        }
1080    }
1081
1082    impl StorageRootProvider for MockStateProvider {
1083        fn storage_root(
1084            &self,
1085            _address: Address,
1086            _hashed_storage: HashedStorage,
1087        ) -> ProviderResult<B256> {
1088            Ok(B256::random())
1089        }
1090
1091        fn storage_proof(
1092            &self,
1093            _address: Address,
1094            slot: B256,
1095            _hashed_storage: HashedStorage,
1096        ) -> ProviderResult<StorageProof> {
1097            Ok(StorageProof::new(slot))
1098        }
1099
1100        fn storage_multiproof(
1101            &self,
1102            _address: Address,
1103            _slots: &[B256],
1104            _hashed_storage: HashedStorage,
1105        ) -> ProviderResult<StorageMultiProof> {
1106            Ok(StorageMultiProof::empty())
1107        }
1108    }
1109
1110    impl StateProofProvider for MockStateProvider {
1111        fn proof(
1112            &self,
1113            _input: TrieInput,
1114            _address: Address,
1115            _slots: &[B256],
1116        ) -> ProviderResult<AccountProof> {
1117            Ok(AccountProof::new(Address::random()))
1118        }
1119
1120        fn multiproof(
1121            &self,
1122            _input: TrieInput,
1123            _targets: MultiProofTargets,
1124        ) -> ProviderResult<MultiProof> {
1125            Ok(MultiProof::default())
1126        }
1127
1128        fn witness(
1129            &self,
1130            _input: TrieInput,
1131            _target: HashedPostState,
1132        ) -> ProviderResult<Vec<Bytes>> {
1133            Ok(Vec::default())
1134        }
1135    }
1136
1137    #[test]
1138    fn test_in_memory_state_impl_state_by_hash() {
1139        let mut state_by_hash = HashMap::default();
1140        let number = rand::rng().random::<u64>();
1141        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1142        let state = Arc::new(create_mock_state(&mut test_block_builder, number, B256::random()));
1143        state_by_hash.insert(state.hash(), state.clone());
1144
1145        let in_memory_state = InMemoryState::new(state_by_hash, BTreeMap::new(), None);
1146
1147        assert_eq!(in_memory_state.state_by_hash(state.hash()), Some(state));
1148        assert_eq!(in_memory_state.state_by_hash(B256::random()), None);
1149    }
1150
1151    #[test]
1152    fn test_in_memory_state_impl_state_by_number() {
1153        let mut state_by_hash = HashMap::default();
1154        let mut hash_by_number = BTreeMap::new();
1155
1156        let number = rand::rng().random::<u64>();
1157        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1158        let state = Arc::new(create_mock_state(&mut test_block_builder, number, B256::random()));
1159        let hash = state.hash();
1160
1161        state_by_hash.insert(hash, state.clone());
1162        hash_by_number.insert(number, hash);
1163
1164        let in_memory_state = InMemoryState::new(state_by_hash, hash_by_number, None);
1165
1166        assert_eq!(in_memory_state.state_by_number(number), Some(state));
1167        assert_eq!(in_memory_state.state_by_number(number + 1), None);
1168    }
1169
1170    #[test]
1171    fn test_in_memory_state_impl_head_state() {
1172        let mut state_by_hash = HashMap::default();
1173        let mut hash_by_number = BTreeMap::new();
1174        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1175        let state1 = Arc::new(create_mock_state(&mut test_block_builder, 1, B256::random()));
1176        let hash1 = state1.hash();
1177        let state2 = Arc::new(create_mock_state(&mut test_block_builder, 2, hash1));
1178        let hash2 = state2.hash();
1179        hash_by_number.insert(1, hash1);
1180        hash_by_number.insert(2, hash2);
1181        state_by_hash.insert(hash1, state1);
1182        state_by_hash.insert(hash2, state2);
1183
1184        let in_memory_state = InMemoryState::new(state_by_hash, hash_by_number, None);
1185        let head_state = in_memory_state.head_state().unwrap();
1186
1187        assert_eq!(head_state.hash(), hash2);
1188        assert_eq!(head_state.number(), 2);
1189    }
1190
1191    #[test]
1192    fn test_in_memory_state_impl_pending_state() {
1193        let pending_number = rand::rng().random::<u64>();
1194        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1195        let pending_state =
1196            create_mock_state(&mut test_block_builder, pending_number, B256::random());
1197        let pending_hash = pending_state.hash();
1198
1199        let in_memory_state =
1200            InMemoryState::new(HashMap::default(), BTreeMap::new(), Some(pending_state));
1201
1202        let result = in_memory_state.pending_state();
1203        assert!(result.is_some());
1204        let actual_pending_state = result.unwrap();
1205        assert_eq!(actual_pending_state.block.recovered_block().hash(), pending_hash);
1206        assert_eq!(actual_pending_state.block.recovered_block().number, pending_number);
1207    }
1208
1209    #[test]
1210    fn test_in_memory_state_impl_no_pending_state() {
1211        let in_memory_state: InMemoryState =
1212            InMemoryState::new(HashMap::default(), BTreeMap::new(), None);
1213
1214        assert_eq!(in_memory_state.pending_state(), None);
1215    }
1216
1217    #[test]
1218    fn test_state() {
1219        let number = rand::rng().random::<u64>();
1220        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1221        let block = test_block_builder.get_executed_block_with_number(number, B256::random());
1222
1223        let state = BlockState::new(block.clone());
1224
1225        assert_eq!(state.block(), block);
1226        assert_eq!(state.hash(), block.recovered_block().hash());
1227        assert_eq!(state.number(), number);
1228        assert_eq!(state.state_root(), block.recovered_block().state_root);
1229    }
1230
1231    #[test]
1232    fn test_state_receipts() {
1233        let receipts = vec![vec![Receipt::default()]];
1234        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1235        let block =
1236            test_block_builder.get_executed_block_with_receipts(receipts.clone(), B256::random());
1237
1238        let state = BlockState::new(block);
1239
1240        assert_eq!(state.receipts(), &receipts);
1241    }
1242
1243    #[test]
1244    fn test_in_memory_state_chain_update() {
1245        let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1246        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1247        let block1 = test_block_builder.get_executed_block_with_number(0, B256::random());
1248        let block2 = test_block_builder.get_executed_block_with_number(0, B256::random());
1249        let chain = NewCanonicalChain::Commit { new: vec![block1.clone()] };
1250        state.update_chain(chain);
1251        assert_eq!(
1252            state.head_state().unwrap().block_ref().recovered_block().hash(),
1253            block1.recovered_block().hash()
1254        );
1255        assert_eq!(
1256            state.state_by_number(0).unwrap().block_ref().recovered_block().hash(),
1257            block1.recovered_block().hash()
1258        );
1259
1260        let chain = NewCanonicalChain::Reorg { new: vec![block2.clone()], old: vec![block1.block] };
1261        state.update_chain(chain);
1262        assert_eq!(
1263            state.head_state().unwrap().block_ref().recovered_block().hash(),
1264            block2.recovered_block().hash()
1265        );
1266        assert_eq!(
1267            state.state_by_number(0).unwrap().block_ref().recovered_block().hash(),
1268            block2.recovered_block().hash()
1269        );
1270
1271        assert_eq!(state.inner.in_memory_state.block_count(), 1);
1272    }
1273
1274    #[test]
1275    fn test_in_memory_state_set_pending_block() {
1276        let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1277        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1278
1279        // First random block
1280        let block1 = test_block_builder.get_executed_block_with_number(0, B256::random());
1281
1282        // Second block with parent hash of the first block
1283        let block2 =
1284            test_block_builder.get_executed_block_with_number(1, block1.recovered_block().hash());
1285
1286        // Commit the two blocks
1287        let chain = NewCanonicalChain::Commit { new: vec![block1.clone(), block2.clone()] };
1288        state.update_chain(chain);
1289
1290        // Assert that the pending state is None before setting it
1291        assert!(state.pending_state().is_none());
1292
1293        // Set the pending block
1294        state.set_pending_block(block2.clone());
1295
1296        // Check the pending state
1297        assert_eq!(
1298            state.pending_state().unwrap(),
1299            BlockState::with_parent(block2.clone(), Some(Arc::new(BlockState::new(block1))))
1300        );
1301
1302        // Check the pending block
1303        assert_eq!(state.pending_block().unwrap(), block2.recovered_block().sealed_block().clone());
1304
1305        // Check the pending block number and hash
1306        assert_eq!(
1307            state.pending_block_num_hash().unwrap(),
1308            BlockNumHash { number: 1, hash: block2.recovered_block().hash() }
1309        );
1310
1311        // Check the pending header
1312        assert_eq!(state.pending_header().unwrap(), block2.recovered_block().header().clone());
1313
1314        // Check the pending sealed header
1315        assert_eq!(
1316            state.pending_sealed_header().unwrap(),
1317            block2.recovered_block().clone_sealed_header()
1318        );
1319
1320        // Check the pending block with senders
1321        assert_eq!(state.pending_recovered_block().unwrap(), block2.recovered_block().clone());
1322
1323        // Check the pending block and receipts
1324        assert_eq!(
1325            state.pending_block_and_receipts().unwrap(),
1326            (block2.recovered_block().clone(), vec![])
1327        );
1328    }
1329
1330    #[test]
1331    fn test_canonical_in_memory_state_state_provider() {
1332        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1333        let block1 = test_block_builder.get_executed_block_with_number(1, B256::random());
1334        let block2 =
1335            test_block_builder.get_executed_block_with_number(2, block1.recovered_block().hash());
1336        let block3 =
1337            test_block_builder.get_executed_block_with_number(3, block2.recovered_block().hash());
1338
1339        let state1 = Arc::new(BlockState::new(block1.clone()));
1340        let state2 = Arc::new(BlockState::with_parent(block2.clone(), Some(state1.clone())));
1341        let state3 = Arc::new(BlockState::with_parent(block3.clone(), Some(state2.clone())));
1342
1343        let mut blocks = HashMap::default();
1344        blocks.insert(block1.recovered_block().hash(), state1);
1345        blocks.insert(block2.recovered_block().hash(), state2);
1346        blocks.insert(block3.recovered_block().hash(), state3);
1347
1348        let mut numbers = BTreeMap::new();
1349        numbers.insert(1, block1.recovered_block().hash());
1350        numbers.insert(2, block2.recovered_block().hash());
1351        numbers.insert(3, block3.recovered_block().hash());
1352
1353        let canonical_state = CanonicalInMemoryState::new(blocks, numbers, None, None, None);
1354
1355        let historical: StateProviderBox = Box::new(MockStateProvider);
1356
1357        let overlay_provider =
1358            canonical_state.state_provider(block3.recovered_block().hash(), historical);
1359
1360        assert_eq!(overlay_provider.in_memory.len(), 3);
1361        assert_eq!(overlay_provider.in_memory[0].recovered_block().number, 3);
1362        assert_eq!(overlay_provider.in_memory[1].recovered_block().number, 2);
1363        assert_eq!(overlay_provider.in_memory[2].recovered_block().number, 1);
1364
1365        assert_eq!(
1366            overlay_provider.in_memory[0].recovered_block().parent_hash,
1367            overlay_provider.in_memory[1].recovered_block().hash()
1368        );
1369        assert_eq!(
1370            overlay_provider.in_memory[1].recovered_block().parent_hash,
1371            overlay_provider.in_memory[2].recovered_block().hash()
1372        );
1373
1374        let unknown_hash = B256::random();
1375        let empty_overlay_provider =
1376            canonical_state.state_provider(unknown_hash, Box::new(MockStateProvider));
1377        assert_eq!(empty_overlay_provider.in_memory.len(), 0);
1378    }
1379
1380    #[test]
1381    fn test_canonical_in_memory_state_canonical_chain_empty() {
1382        let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1383        let chain: Vec<_> = state.canonical_chain().collect();
1384        assert!(chain.is_empty());
1385    }
1386
1387    #[test]
1388    fn test_canonical_in_memory_state_canonical_chain_single_block() {
1389        let block = TestBlockBuilder::eth().get_executed_block_with_number(1, B256::random());
1390        let hash = block.recovered_block().hash();
1391        let mut blocks = HashMap::default();
1392        blocks.insert(hash, Arc::new(BlockState::new(block)));
1393        let mut numbers = BTreeMap::new();
1394        numbers.insert(1, hash);
1395
1396        let state = CanonicalInMemoryState::new(blocks, numbers, None, None, None);
1397        let chain: Vec<_> = state.canonical_chain().collect();
1398
1399        assert_eq!(chain.len(), 1);
1400        assert_eq!(chain[0].number(), 1);
1401        assert_eq!(chain[0].hash(), hash);
1402    }
1403
1404    #[test]
1405    fn test_canonical_in_memory_state_canonical_chain_multiple_blocks() {
1406        let mut parent_hash = B256::random();
1407        let mut block_builder = TestBlockBuilder::eth();
1408        let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1409
1410        for i in 1..=3 {
1411            let block = block_builder.get_executed_block_with_number(i, parent_hash);
1412            let hash = block.recovered_block().hash();
1413            state.update_blocks(Some(block), None);
1414            parent_hash = hash;
1415        }
1416
1417        let chain: Vec<_> = state.canonical_chain().collect();
1418
1419        assert_eq!(chain.len(), 3);
1420        assert_eq!(chain[0].number(), 3);
1421        assert_eq!(chain[1].number(), 2);
1422        assert_eq!(chain[2].number(), 1);
1423    }
1424
1425    // ensures the pending block is not part of the canonical chain
1426    #[test]
1427    fn test_canonical_in_memory_state_canonical_chain_with_pending_block() {
1428        let mut parent_hash = B256::random();
1429        let mut block_builder = TestBlockBuilder::<EthPrimitives>::eth();
1430        let state: CanonicalInMemoryState = CanonicalInMemoryState::empty();
1431
1432        for i in 1..=2 {
1433            let block = block_builder.get_executed_block_with_number(i, parent_hash);
1434            let hash = block.recovered_block().hash();
1435            state.update_blocks(Some(block), None);
1436            parent_hash = hash;
1437        }
1438
1439        let pending_block = block_builder.get_executed_block_with_number(3, parent_hash);
1440        state.set_pending_block(pending_block);
1441        let chain: Vec<_> = state.canonical_chain().collect();
1442
1443        assert_eq!(chain.len(), 2);
1444        assert_eq!(chain[0].number(), 2);
1445        assert_eq!(chain[1].number(), 1);
1446    }
1447
1448    #[test]
1449    fn test_block_state_parent_blocks() {
1450        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1451        let chain = create_mock_state_chain(&mut test_block_builder, 4);
1452
1453        let parents = chain[3].parent_state_chain();
1454        assert_eq!(parents.len(), 3);
1455        assert_eq!(parents[0].block().recovered_block().number, 3);
1456        assert_eq!(parents[1].block().recovered_block().number, 2);
1457        assert_eq!(parents[2].block().recovered_block().number, 1);
1458
1459        let parents = chain[2].parent_state_chain();
1460        assert_eq!(parents.len(), 2);
1461        assert_eq!(parents[0].block().recovered_block().number, 2);
1462        assert_eq!(parents[1].block().recovered_block().number, 1);
1463
1464        let parents = chain[0].parent_state_chain();
1465        assert_eq!(parents.len(), 0);
1466    }
1467
1468    #[test]
1469    fn test_block_state_single_block_state_chain() {
1470        let single_block_number = 1;
1471        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1472        let single_block =
1473            create_mock_state(&mut test_block_builder, single_block_number, B256::random());
1474        let single_block_hash = single_block.block().recovered_block().hash();
1475
1476        let parents = single_block.parent_state_chain();
1477        assert_eq!(parents.len(), 0);
1478
1479        let block_state_chain = single_block.chain().collect::<Vec<_>>();
1480        assert_eq!(block_state_chain.len(), 1);
1481        assert_eq!(block_state_chain[0].block().recovered_block().number, single_block_number);
1482        assert_eq!(block_state_chain[0].block().recovered_block().hash(), single_block_hash);
1483    }
1484
1485    #[test]
1486    fn test_block_state_chain() {
1487        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1488        let chain = create_mock_state_chain(&mut test_block_builder, 3);
1489
1490        let block_state_chain = chain[2].chain().collect::<Vec<_>>();
1491        assert_eq!(block_state_chain.len(), 3);
1492        assert_eq!(block_state_chain[0].block().recovered_block().number, 3);
1493        assert_eq!(block_state_chain[1].block().recovered_block().number, 2);
1494        assert_eq!(block_state_chain[2].block().recovered_block().number, 1);
1495
1496        let block_state_chain = chain[1].chain().collect::<Vec<_>>();
1497        assert_eq!(block_state_chain.len(), 2);
1498        assert_eq!(block_state_chain[0].block().recovered_block().number, 2);
1499        assert_eq!(block_state_chain[1].block().recovered_block().number, 1);
1500
1501        let block_state_chain = chain[0].chain().collect::<Vec<_>>();
1502        assert_eq!(block_state_chain.len(), 1);
1503        assert_eq!(block_state_chain[0].block().recovered_block().number, 1);
1504    }
1505
1506    #[test]
1507    fn test_to_chain_notification() {
1508        // Generate 4 blocks
1509        let mut test_block_builder: TestBlockBuilder = TestBlockBuilder::default();
1510        let block0 = test_block_builder.get_executed_block_with_number(0, B256::random());
1511        let block1 =
1512            test_block_builder.get_executed_block_with_number(1, block0.recovered_block.hash());
1513        let block1a =
1514            test_block_builder.get_executed_block_with_number(1, block0.recovered_block.hash());
1515        let block2 =
1516            test_block_builder.get_executed_block_with_number(2, block1.recovered_block.hash());
1517        let block2a =
1518            test_block_builder.get_executed_block_with_number(2, block1.recovered_block.hash());
1519
1520        let sample_execution_outcome = ExecutionOutcome {
1521            receipts: vec![vec![], vec![]],
1522            requests: vec![Requests::default(), Requests::default()],
1523            ..Default::default()
1524        };
1525
1526        // Test commit notification
1527        let chain_commit = NewCanonicalChain::Commit { new: vec![block0.clone(), block1.clone()] };
1528
1529        assert_eq!(
1530            chain_commit.to_chain_notification(),
1531            CanonStateNotification::Commit {
1532                new: Arc::new(Chain::new(
1533                    vec![block0.recovered_block().clone(), block1.recovered_block().clone()],
1534                    sample_execution_outcome.clone(),
1535                    None
1536                ))
1537            }
1538        );
1539
1540        // Test reorg notification
1541        let chain_reorg = NewCanonicalChain::Reorg {
1542            new: vec![block1a.clone(), block2a.clone()],
1543            old: vec![block1.block.clone(), block2.block.clone()],
1544        };
1545
1546        assert_eq!(
1547            chain_reorg.to_chain_notification(),
1548            CanonStateNotification::Reorg {
1549                old: Arc::new(Chain::new(
1550                    vec![block1.recovered_block().clone(), block2.recovered_block().clone()],
1551                    sample_execution_outcome.clone(),
1552                    None
1553                )),
1554                new: Arc::new(Chain::new(
1555                    vec![block1a.recovered_block().clone(), block2a.recovered_block().clone()],
1556                    sample_execution_outcome,
1557                    None
1558                ))
1559            }
1560        );
1561    }
1562}