Skip to main content

reth_chain_state/
in_memory.rs

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