reth_execution_types/
chain.rs

1//! Contains [Chain], a chain of blocks and their final state.
2
3use crate::ExecutionOutcome;
4use alloc::{borrow::Cow, collections::BTreeMap};
5use alloy_consensus::BlockHeader;
6use alloy_eips::{eip1898::ForkBlock, eip2718::Encodable2718, BlockNumHash};
7use alloy_primitives::{Address, BlockHash, BlockNumber, TxHash};
8use core::{fmt, ops::RangeInclusive};
9use reth_execution_errors::{BlockExecutionError, InternalBlockExecutionError};
10use reth_primitives::{
11    transaction::SignedTransactionIntoRecoveredExt, RecoveredTx, SealedBlockFor,
12    SealedBlockWithSenders, SealedHeader,
13};
14use reth_primitives_traits::{Block, BlockBody, NodePrimitives, SignedTransaction};
15use reth_trie::updates::TrieUpdates;
16use revm::db::BundleState;
17
18/// A chain of blocks and their final state.
19///
20/// The chain contains the state of accounts after execution of its blocks,
21/// changesets for those blocks (and their transactions), as well as the blocks themselves.
22///
23/// Used inside the `BlockchainTree`.
24///
25/// # Warning
26///
27/// A chain of blocks should not be empty.
28#[derive(Clone, Debug, PartialEq, Eq)]
29#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
30pub struct Chain<N: NodePrimitives = reth_primitives::EthPrimitives> {
31    /// All blocks in this chain.
32    blocks: BTreeMap<BlockNumber, SealedBlockWithSenders<N::Block>>,
33    /// The outcome of block execution for this chain.
34    ///
35    /// This field contains the state of all accounts after the execution of all blocks in this
36    /// chain, ranging from the [`Chain::first`] block to the [`Chain::tip`] block, inclusive.
37    ///
38    /// Additionally, it includes the individual state changes that led to the current state.
39    execution_outcome: ExecutionOutcome<N::Receipt>,
40    /// State trie updates after block is added to the chain.
41    /// NOTE: Currently, trie updates are present only for
42    /// single-block chains that extend the canonical chain.
43    trie_updates: Option<TrieUpdates>,
44}
45
46impl<N: NodePrimitives> Default for Chain<N> {
47    fn default() -> Self {
48        Self {
49            blocks: Default::default(),
50            execution_outcome: Default::default(),
51            trie_updates: Default::default(),
52        }
53    }
54}
55
56impl<N: NodePrimitives> Chain<N> {
57    /// Create new Chain from blocks and state.
58    ///
59    /// # Warning
60    ///
61    /// A chain of blocks should not be empty.
62    pub fn new(
63        blocks: impl IntoIterator<Item = SealedBlockWithSenders<N::Block>>,
64        execution_outcome: ExecutionOutcome<N::Receipt>,
65        trie_updates: Option<TrieUpdates>,
66    ) -> Self {
67        let blocks = blocks.into_iter().map(|b| (b.number(), b)).collect::<BTreeMap<_, _>>();
68        debug_assert!(!blocks.is_empty(), "Chain should have at least one block");
69
70        Self { blocks, execution_outcome, trie_updates }
71    }
72
73    /// Create new Chain from a single block and its state.
74    pub fn from_block(
75        block: SealedBlockWithSenders<N::Block>,
76        execution_outcome: ExecutionOutcome<N::Receipt>,
77        trie_updates: Option<TrieUpdates>,
78    ) -> Self {
79        Self::new([block], execution_outcome, trie_updates)
80    }
81
82    /// Get the blocks in this chain.
83    pub const fn blocks(&self) -> &BTreeMap<BlockNumber, SealedBlockWithSenders<N::Block>> {
84        &self.blocks
85    }
86
87    /// Consumes the type and only returns the blocks in this chain.
88    pub fn into_blocks(self) -> BTreeMap<BlockNumber, SealedBlockWithSenders<N::Block>> {
89        self.blocks
90    }
91
92    /// Returns an iterator over all headers in the block with increasing block numbers.
93    pub fn headers(&self) -> impl Iterator<Item = SealedHeader<N::BlockHeader>> + '_ {
94        self.blocks.values().map(|block| block.header.clone())
95    }
96
97    /// Get cached trie updates for this chain.
98    pub const fn trie_updates(&self) -> Option<&TrieUpdates> {
99        self.trie_updates.as_ref()
100    }
101
102    /// Remove cached trie updates for this chain.
103    pub fn clear_trie_updates(&mut self) {
104        self.trie_updates.take();
105    }
106
107    /// Get execution outcome of this chain
108    pub const fn execution_outcome(&self) -> &ExecutionOutcome<N::Receipt> {
109        &self.execution_outcome
110    }
111
112    /// Get mutable execution outcome of this chain
113    pub fn execution_outcome_mut(&mut self) -> &mut ExecutionOutcome<N::Receipt> {
114        &mut self.execution_outcome
115    }
116
117    /// Prepends the given state to the current state.
118    pub fn prepend_state(&mut self, state: BundleState) {
119        self.execution_outcome.prepend_state(state);
120        self.trie_updates.take(); // invalidate cached trie updates
121    }
122
123    /// Return true if chain is empty and has no blocks.
124    pub fn is_empty(&self) -> bool {
125        self.blocks.is_empty()
126    }
127
128    /// Return block number of the block hash.
129    pub fn block_number(&self, block_hash: BlockHash) -> Option<BlockNumber> {
130        self.blocks.iter().find_map(|(num, block)| (block.hash() == block_hash).then_some(*num))
131    }
132
133    /// Returns the block with matching hash.
134    pub fn block(&self, block_hash: BlockHash) -> Option<&SealedBlockFor<N::Block>> {
135        self.block_with_senders(block_hash).map(|block| &block.block)
136    }
137
138    /// Returns the block with matching hash.
139    pub fn block_with_senders(
140        &self,
141        block_hash: BlockHash,
142    ) -> Option<&SealedBlockWithSenders<N::Block>> {
143        self.blocks.iter().find_map(|(_num, block)| (block.hash() == block_hash).then_some(block))
144    }
145
146    /// Return execution outcome at the `block_number` or None if block is not known
147    pub fn execution_outcome_at_block(
148        &self,
149        block_number: BlockNumber,
150    ) -> Option<ExecutionOutcome<N::Receipt>> {
151        if self.tip().number() == block_number {
152            return Some(self.execution_outcome.clone())
153        }
154
155        if self.blocks.contains_key(&block_number) {
156            let mut execution_outcome = self.execution_outcome.clone();
157            execution_outcome.revert_to(block_number);
158            return Some(execution_outcome)
159        }
160        None
161    }
162
163    /// Destructure the chain into its inner components:
164    /// 1. The blocks contained in the chain.
165    /// 2. The execution outcome representing the final state.
166    /// 3. The optional trie updates.
167    pub fn into_inner(
168        self,
169    ) -> (ChainBlocks<'static, N::Block>, ExecutionOutcome<N::Receipt>, Option<TrieUpdates>) {
170        (ChainBlocks { blocks: Cow::Owned(self.blocks) }, self.execution_outcome, self.trie_updates)
171    }
172
173    /// Destructure the chain into its inner components:
174    /// 1. A reference to the blocks contained in the chain.
175    /// 2. A reference to the execution outcome representing the final state.
176    pub const fn inner(&self) -> (ChainBlocks<'_, N::Block>, &ExecutionOutcome<N::Receipt>) {
177        (ChainBlocks { blocks: Cow::Borrowed(&self.blocks) }, &self.execution_outcome)
178    }
179
180    /// Returns an iterator over all the receipts of the blocks in the chain.
181    pub fn block_receipts_iter(&self) -> impl Iterator<Item = &Vec<Option<N::Receipt>>> + '_ {
182        self.execution_outcome.receipts().iter()
183    }
184
185    /// Returns an iterator over all blocks in the chain with increasing block number.
186    pub fn blocks_iter(&self) -> impl Iterator<Item = &SealedBlockWithSenders<N::Block>> + '_ {
187        self.blocks().iter().map(|block| block.1)
188    }
189
190    /// Returns an iterator over all blocks and their receipts in the chain.
191    pub fn blocks_and_receipts(
192        &self,
193    ) -> impl Iterator<Item = (&SealedBlockWithSenders<N::Block>, &Vec<Option<N::Receipt>>)> + '_
194    {
195        self.blocks_iter().zip(self.block_receipts_iter())
196    }
197
198    /// Get the block at which this chain forked.
199    #[track_caller]
200    pub fn fork_block(&self) -> ForkBlock {
201        let first = self.first();
202        ForkBlock { number: first.number().saturating_sub(1), hash: first.parent_hash() }
203    }
204
205    /// Get the first block in this chain.
206    ///
207    /// # Panics
208    ///
209    /// If chain doesn't have any blocks.
210    #[track_caller]
211    pub fn first(&self) -> &SealedBlockWithSenders<N::Block> {
212        self.blocks.first_key_value().expect("Chain should have at least one block").1
213    }
214
215    /// Get the tip of the chain.
216    ///
217    /// # Panics
218    ///
219    /// If chain doesn't have any blocks.
220    #[track_caller]
221    pub fn tip(&self) -> &SealedBlockWithSenders<N::Block> {
222        self.blocks.last_key_value().expect("Chain should have at least one block").1
223    }
224
225    /// Returns length of the chain.
226    pub fn len(&self) -> usize {
227        self.blocks.len()
228    }
229
230    /// Returns the range of block numbers in the chain.
231    ///
232    /// # Panics
233    ///
234    /// If chain doesn't have any blocks.
235    pub fn range(&self) -> RangeInclusive<BlockNumber> {
236        self.first().number()..=self.tip().number()
237    }
238
239    /// Get all receipts for the given block.
240    pub fn receipts_by_block_hash(&self, block_hash: BlockHash) -> Option<Vec<&N::Receipt>> {
241        let num = self.block_number(block_hash)?;
242        self.execution_outcome.receipts_by_block(num).iter().map(Option::as_ref).collect()
243    }
244
245    /// Get all receipts with attachment.
246    ///
247    /// Attachment includes block number, block hash, transaction hash and transaction index.
248    pub fn receipts_with_attachment(&self) -> Vec<BlockReceipts<N::Receipt>>
249    where
250        N::SignedTx: Encodable2718,
251    {
252        let mut receipt_attach = Vec::with_capacity(self.blocks().len());
253        for ((block_num, block), receipts) in
254            self.blocks().iter().zip(self.execution_outcome.receipts().iter())
255        {
256            let mut tx_receipts = Vec::with_capacity(receipts.len());
257            for (tx, receipt) in block.body.transactions().iter().zip(receipts.iter()) {
258                tx_receipts.push((
259                    tx.trie_hash(),
260                    receipt.as_ref().expect("receipts have not been pruned").clone(),
261                ));
262            }
263            let block_num_hash = BlockNumHash::new(*block_num, block.hash());
264            receipt_attach.push(BlockReceipts { block: block_num_hash, tx_receipts });
265        }
266        receipt_attach
267    }
268
269    /// Append a single block with state to the chain.
270    /// This method assumes that blocks attachment to the chain has already been validated.
271    pub fn append_block(
272        &mut self,
273        block: SealedBlockWithSenders<N::Block>,
274        execution_outcome: ExecutionOutcome<N::Receipt>,
275    ) {
276        self.blocks.insert(block.number(), block);
277        self.execution_outcome.extend(execution_outcome);
278        self.trie_updates.take(); // reset
279    }
280
281    /// Merge two chains by appending the given chain into the current one.
282    ///
283    /// The state of accounts for this chain is set to the state of the newest chain.
284    pub fn append_chain(&mut self, other: Self) -> Result<(), BlockExecutionError> {
285        let chain_tip = self.tip();
286        let other_fork_block = other.fork_block();
287        if chain_tip.hash() != other_fork_block.hash {
288            return Err(InternalBlockExecutionError::AppendChainDoesntConnect {
289                chain_tip: Box::new(chain_tip.num_hash()),
290                other_chain_fork: Box::new(other_fork_block),
291            }
292            .into())
293        }
294
295        // Insert blocks from other chain
296        self.blocks.extend(other.blocks);
297        self.execution_outcome.extend(other.execution_outcome);
298        self.trie_updates.take(); // reset
299
300        Ok(())
301    }
302
303    /// Split this chain at the given block.
304    ///
305    /// The given block will be the last block in the first returned chain.
306    ///
307    /// If the given block is not found, [`ChainSplit::NoSplitPending`] is returned.
308    /// Split chain at the number or hash, block with given number will be included at first chain.
309    /// If any chain is empty (Does not have blocks) None will be returned.
310    ///
311    /// # Note
312    ///
313    /// The plain state is only found in the second chain, making it
314    /// impossible to perform any state reverts on the first chain.
315    ///
316    /// The second chain only contains the changes that were reverted on the first chain; however,
317    /// it retains the up to date state as if the chains were one, i.e. the second chain is an
318    /// extension of the first.
319    ///
320    /// # Panics
321    ///
322    /// If chain doesn't have any blocks.
323    #[track_caller]
324    pub fn split(mut self, split_at: ChainSplitTarget) -> ChainSplit<N> {
325        let chain_tip = *self.blocks.last_entry().expect("chain is never empty").key();
326        let block_number = match split_at {
327            ChainSplitTarget::Hash(block_hash) => {
328                let Some(block_number) = self.block_number(block_hash) else {
329                    return ChainSplit::NoSplitPending(self)
330                };
331                // If block number is same as tip whole chain is becoming canonical.
332                if block_number == chain_tip {
333                    return ChainSplit::NoSplitCanonical(self)
334                }
335                block_number
336            }
337            ChainSplitTarget::Number(block_number) => {
338                if block_number > chain_tip {
339                    return ChainSplit::NoSplitPending(self)
340                }
341                if block_number == chain_tip {
342                    return ChainSplit::NoSplitCanonical(self)
343                }
344                if block_number < *self.blocks.first_entry().expect("chain is never empty").key() {
345                    return ChainSplit::NoSplitPending(self)
346                }
347                block_number
348            }
349        };
350
351        let split_at = block_number + 1;
352        let higher_number_blocks = self.blocks.split_off(&split_at);
353
354        let execution_outcome = std::mem::take(&mut self.execution_outcome);
355        let (canonical_block_exec_outcome, pending_block_exec_outcome) =
356            execution_outcome.split_at(split_at);
357
358        // TODO: Currently, trie updates are reset on chain split.
359        // Add tests ensuring that it is valid to leave updates in the pending chain.
360        ChainSplit::Split {
361            canonical: Self {
362                execution_outcome: canonical_block_exec_outcome.expect("split in range"),
363                blocks: self.blocks,
364                trie_updates: None,
365            },
366            pending: Self {
367                execution_outcome: pending_block_exec_outcome,
368                blocks: higher_number_blocks,
369                trie_updates: None,
370            },
371        }
372    }
373}
374
375/// Wrapper type for `blocks` display in `Chain`
376#[derive(Debug)]
377pub struct DisplayBlocksChain<'a, B: reth_primitives_traits::Block>(
378    pub &'a BTreeMap<BlockNumber, SealedBlockWithSenders<B>>,
379);
380
381impl<B: reth_primitives_traits::Block> fmt::Display for DisplayBlocksChain<'_, B> {
382    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
383        let mut list = f.debug_list();
384        let mut values = self.0.values().map(|block| block.num_hash());
385        if values.len() <= 3 {
386            list.entries(values);
387        } else {
388            list.entry(&values.next().unwrap());
389            list.entry(&format_args!("..."));
390            list.entry(&values.next_back().unwrap());
391        }
392        list.finish()
393    }
394}
395
396/// All blocks in the chain
397#[derive(Clone, Debug, Default, PartialEq, Eq)]
398pub struct ChainBlocks<'a, B: Block> {
399    blocks: Cow<'a, BTreeMap<BlockNumber, SealedBlockWithSenders<B>>>,
400}
401
402impl<B: Block<Body: BlockBody<Transaction: SignedTransaction>>> ChainBlocks<'_, B> {
403    /// Creates a consuming iterator over all blocks in the chain with increasing block number.
404    ///
405    /// Note: this always yields at least one block.
406    #[inline]
407    pub fn into_blocks(self) -> impl Iterator<Item = SealedBlockWithSenders<B>> {
408        self.blocks.into_owned().into_values()
409    }
410
411    /// Creates an iterator over all blocks in the chain with increasing block number.
412    #[inline]
413    pub fn iter(&self) -> impl Iterator<Item = (&BlockNumber, &SealedBlockWithSenders<B>)> {
414        self.blocks.iter()
415    }
416
417    /// Get the tip of the chain.
418    ///
419    /// # Note
420    ///
421    /// Chains always have at least one block.
422    #[inline]
423    pub fn tip(&self) -> &SealedBlockWithSenders<B> {
424        self.blocks.last_key_value().expect("Chain should have at least one block").1
425    }
426
427    /// Get the _first_ block of the chain.
428    ///
429    /// # Note
430    ///
431    /// Chains always have at least one block.
432    #[inline]
433    pub fn first(&self) -> &SealedBlockWithSenders<B> {
434        self.blocks.first_key_value().expect("Chain should have at least one block").1
435    }
436
437    /// Returns an iterator over all transactions in the chain.
438    #[inline]
439    pub fn transactions(&self) -> impl Iterator<Item = &<B::Body as BlockBody>::Transaction> + '_ {
440        self.blocks.values().flat_map(|block| block.body.transactions().iter())
441    }
442
443    /// Returns an iterator over all transactions and their senders.
444    #[inline]
445    pub fn transactions_with_sender(
446        &self,
447    ) -> impl Iterator<Item = (&Address, &<B::Body as BlockBody>::Transaction)> + '_ {
448        self.blocks.values().flat_map(|block| block.transactions_with_sender())
449    }
450
451    /// Returns an iterator over all [`RecoveredTx`] in the blocks
452    ///
453    /// Note: This clones the transactions since it is assumed this is part of a shared [Chain].
454    #[inline]
455    pub fn transactions_ecrecovered(
456        &self,
457    ) -> impl Iterator<Item = RecoveredTx<<B::Body as BlockBody>::Transaction>> + '_ {
458        self.transactions_with_sender().map(|(signer, tx)| tx.clone().with_signer(*signer))
459    }
460
461    /// Returns an iterator over all transaction hashes in the block
462    #[inline]
463    pub fn transaction_hashes(&self) -> impl Iterator<Item = TxHash> + '_ {
464        self.blocks.values().flat_map(|block| block.transactions().iter().map(|tx| tx.trie_hash()))
465    }
466}
467
468impl<B: Block> IntoIterator for ChainBlocks<'_, B> {
469    type Item = (BlockNumber, SealedBlockWithSenders<B>);
470    type IntoIter = std::collections::btree_map::IntoIter<BlockNumber, SealedBlockWithSenders<B>>;
471
472    fn into_iter(self) -> Self::IntoIter {
473        #[allow(clippy::unnecessary_to_owned)]
474        self.blocks.into_owned().into_iter()
475    }
476}
477
478/// Used to hold receipts and their attachment.
479#[derive(Default, Clone, Debug, PartialEq, Eq)]
480pub struct BlockReceipts<T = reth_primitives::Receipt> {
481    /// Block identifier
482    pub block: BlockNumHash,
483    /// Transaction identifier and receipt.
484    pub tx_receipts: Vec<(TxHash, T)>,
485}
486
487/// The target block where the chain should be split.
488#[derive(Clone, Copy, Debug, PartialEq, Eq)]
489pub enum ChainSplitTarget {
490    /// Split at block number.
491    Number(BlockNumber),
492    /// Split at block hash.
493    Hash(BlockHash),
494}
495
496impl From<BlockNumber> for ChainSplitTarget {
497    fn from(number: BlockNumber) -> Self {
498        Self::Number(number)
499    }
500}
501
502impl From<BlockHash> for ChainSplitTarget {
503    fn from(hash: BlockHash) -> Self {
504        Self::Hash(hash)
505    }
506}
507
508/// Result of a split chain.
509#[derive(Clone, Debug, PartialEq, Eq)]
510pub enum ChainSplit<N: NodePrimitives = reth_primitives::EthPrimitives> {
511    /// Chain is not split. Pending chain is returned.
512    /// Given block split is higher than last block.
513    /// Or in case of split by hash when hash is unknown.
514    NoSplitPending(Chain<N>),
515    /// Chain is not split. Canonical chain is returned.
516    /// Given block split is lower than first block.
517    NoSplitCanonical(Chain<N>),
518    /// Chain is split into two: `[canonical]` and `[pending]`
519    /// The target of this chain split [`ChainSplitTarget`] belongs to the `canonical` chain.
520    Split {
521        /// Contains lower block numbers that are considered canonicalized. It ends with
522        /// the [`ChainSplitTarget`] block. The state of this chain is now empty and no longer
523        /// usable.
524        canonical: Chain<N>,
525        /// Right contains all subsequent blocks __after__ the [`ChainSplitTarget`] that are still
526        /// pending.
527        ///
528        /// The state of the original chain is moved here.
529        pending: Chain<N>,
530    },
531}
532
533/// Bincode-compatible [`Chain`] serde implementation.
534#[cfg(feature = "serde-bincode-compat")]
535pub(super) mod serde_bincode_compat {
536    use crate::ExecutionOutcome;
537    use alloc::borrow::Cow;
538    use alloy_primitives::BlockNumber;
539    use reth_primitives::{
540        serde_bincode_compat::SealedBlockWithSenders, EthPrimitives, NodePrimitives,
541    };
542    use reth_trie_common::serde_bincode_compat::updates::TrieUpdates;
543    use serde::{ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer};
544    use serde_with::{DeserializeAs, SerializeAs};
545    use std::collections::BTreeMap;
546
547    /// Bincode-compatible [`super::Chain`] serde implementation.
548    ///
549    /// Intended to use with the [`serde_with::serde_as`] macro in the following way:
550    /// ```rust
551    /// use reth_execution_types::{serde_bincode_compat, Chain};
552    /// use serde::{Deserialize, Serialize};
553    /// use serde_with::serde_as;
554    ///
555    /// #[serde_as]
556    /// #[derive(Serialize, Deserialize)]
557    /// struct Data {
558    ///     #[serde_as(as = "serde_bincode_compat::Chain")]
559    ///     chain: Chain,
560    /// }
561    /// ```
562    #[derive(Debug, Serialize, Deserialize)]
563    pub struct Chain<'a, N = EthPrimitives>
564    where
565        N: NodePrimitives,
566    {
567        blocks: SealedBlocksWithSenders<'a, N::Block>,
568        execution_outcome: Cow<'a, ExecutionOutcome<N::Receipt>>,
569        trie_updates: Option<TrieUpdates<'a>>,
570    }
571
572    #[derive(Debug)]
573    struct SealedBlocksWithSenders<'a, B: reth_primitives_traits::Block>(
574        Cow<'a, BTreeMap<BlockNumber, reth_primitives::SealedBlockWithSenders<B>>>,
575    );
576
577    impl<B> Serialize for SealedBlocksWithSenders<'_, B>
578    where
579        B: reth_primitives_traits::Block,
580    {
581        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
582        where
583            S: Serializer,
584        {
585            let mut state = serializer.serialize_map(Some(self.0.len()))?;
586
587            for (block_number, block) in self.0.iter() {
588                state.serialize_entry(block_number, &SealedBlockWithSenders::<'_>::from(block))?;
589            }
590
591            state.end()
592        }
593    }
594
595    impl<'de, B> Deserialize<'de> for SealedBlocksWithSenders<'_, B>
596    where
597        B: reth_primitives_traits::Block,
598    {
599        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
600        where
601            D: Deserializer<'de>,
602        {
603            Ok(Self(Cow::Owned(
604                BTreeMap::<BlockNumber, SealedBlockWithSenders<'_, B>>::deserialize(deserializer)
605                    .map(|blocks| blocks.into_iter().map(|(n, b)| (n, b.into())).collect())?,
606            )))
607        }
608    }
609
610    impl<'a, N> From<&'a super::Chain<N>> for Chain<'a, N>
611    where
612        N: NodePrimitives,
613    {
614        fn from(value: &'a super::Chain<N>) -> Self {
615            Self {
616                blocks: SealedBlocksWithSenders(Cow::Borrowed(&value.blocks)),
617                execution_outcome: Cow::Borrowed(&value.execution_outcome),
618                trie_updates: value.trie_updates.as_ref().map(Into::into),
619            }
620        }
621    }
622
623    impl<'a, N> From<Chain<'a, N>> for super::Chain<N>
624    where
625        N: NodePrimitives,
626    {
627        fn from(value: Chain<'a, N>) -> Self {
628            Self {
629                blocks: value.blocks.0.into_owned(),
630                execution_outcome: value.execution_outcome.into_owned(),
631                trie_updates: value.trie_updates.map(Into::into),
632            }
633        }
634    }
635
636    impl SerializeAs<super::Chain> for Chain<'_> {
637        fn serialize_as<S>(source: &super::Chain, serializer: S) -> Result<S::Ok, S::Error>
638        where
639            S: Serializer,
640        {
641            Chain::from(source).serialize(serializer)
642        }
643    }
644
645    impl<'de> DeserializeAs<'de, super::Chain> for Chain<'de> {
646        fn deserialize_as<D>(deserializer: D) -> Result<super::Chain, D::Error>
647        where
648            D: Deserializer<'de>,
649        {
650            Chain::deserialize(deserializer).map(Into::into)
651        }
652    }
653
654    #[cfg(test)]
655    mod tests {
656        use arbitrary::Arbitrary;
657        use rand::Rng;
658        use reth_primitives::SealedBlockWithSenders;
659        use serde::{Deserialize, Serialize};
660        use serde_with::serde_as;
661
662        use super::super::{serde_bincode_compat, Chain};
663
664        #[test]
665        fn test_chain_bincode_roundtrip() {
666            #[serde_as]
667            #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
668            struct Data {
669                #[serde_as(as = "serde_bincode_compat::Chain")]
670                chain: Chain,
671            }
672
673            let mut bytes = [0u8; 1024];
674            rand::thread_rng().fill(bytes.as_mut_slice());
675            let data = Data {
676                chain: Chain::new(
677                    vec![SealedBlockWithSenders::arbitrary(&mut arbitrary::Unstructured::new(
678                        &bytes,
679                    ))
680                    .unwrap()],
681                    Default::default(),
682                    None,
683                ),
684            };
685
686            let encoded = bincode::serialize(&data).unwrap();
687            let decoded: Data = bincode::deserialize(&encoded).unwrap();
688            assert_eq!(decoded, data);
689        }
690    }
691}
692
693#[cfg(test)]
694mod tests {
695    use super::*;
696    use alloy_primitives::B256;
697    use revm::primitives::{AccountInfo, HashMap};
698
699    #[test]
700    fn chain_append() {
701        let block: SealedBlockWithSenders = Default::default();
702        let block1_hash = B256::new([0x01; 32]);
703        let block2_hash = B256::new([0x02; 32]);
704        let block3_hash = B256::new([0x03; 32]);
705        let block4_hash = B256::new([0x04; 32]);
706
707        let mut block1 = block.clone();
708        let mut block2 = block.clone();
709        let mut block3 = block.clone();
710        let mut block4 = block;
711
712        block1.block.header.set_hash(block1_hash);
713        block2.block.header.set_hash(block2_hash);
714        block3.block.header.set_hash(block3_hash);
715        block4.block.header.set_hash(block4_hash);
716
717        block3.set_parent_hash(block2_hash);
718
719        let mut chain1: Chain =
720            Chain { blocks: BTreeMap::from([(1, block1), (2, block2)]), ..Default::default() };
721
722        let chain2 =
723            Chain { blocks: BTreeMap::from([(3, block3), (4, block4)]), ..Default::default() };
724
725        assert!(chain1.append_chain(chain2.clone()).is_ok());
726
727        // chain1 got changed so this will fail
728        assert!(chain1.append_chain(chain2).is_err());
729    }
730
731    #[test]
732    fn test_number_split() {
733        let execution_outcome1: ExecutionOutcome = ExecutionOutcome::new(
734            BundleState::new(
735                vec![(
736                    Address::new([2; 20]),
737                    None,
738                    Some(AccountInfo::default()),
739                    HashMap::default(),
740                )],
741                vec![vec![(Address::new([2; 20]), None, vec![])]],
742                vec![],
743            ),
744            vec![vec![]].into(),
745            1,
746            vec![],
747        );
748
749        let execution_outcome2 = ExecutionOutcome::new(
750            BundleState::new(
751                vec![(
752                    Address::new([3; 20]),
753                    None,
754                    Some(AccountInfo::default()),
755                    HashMap::default(),
756                )],
757                vec![vec![(Address::new([3; 20]), None, vec![])]],
758                vec![],
759            ),
760            vec![vec![]].into(),
761            2,
762            vec![],
763        );
764
765        let mut block1: SealedBlockWithSenders = Default::default();
766        let block1_hash = B256::new([15; 32]);
767        block1.set_block_number(1);
768        block1.set_hash(block1_hash);
769        block1.senders.push(Address::new([4; 20]));
770
771        let mut block2: SealedBlockWithSenders = Default::default();
772        let block2_hash = B256::new([16; 32]);
773        block2.set_block_number(2);
774        block2.set_hash(block2_hash);
775        block2.senders.push(Address::new([4; 20]));
776
777        let mut block_state_extended = execution_outcome1;
778        block_state_extended.extend(execution_outcome2);
779
780        let chain: Chain =
781            Chain::new(vec![block1.clone(), block2.clone()], block_state_extended, None);
782
783        let (split1_execution_outcome, split2_execution_outcome) =
784            chain.execution_outcome.clone().split_at(2);
785
786        let chain_split1 = Chain {
787            execution_outcome: split1_execution_outcome.unwrap(),
788            blocks: BTreeMap::from([(1, block1.clone())]),
789            trie_updates: None,
790        };
791
792        let chain_split2 = Chain {
793            execution_outcome: split2_execution_outcome,
794            blocks: BTreeMap::from([(2, block2.clone())]),
795            trie_updates: None,
796        };
797
798        // return tip state
799        assert_eq!(
800            chain.execution_outcome_at_block(block2.number),
801            Some(chain.execution_outcome.clone())
802        );
803        assert_eq!(
804            chain.execution_outcome_at_block(block1.number),
805            Some(chain_split1.execution_outcome.clone())
806        );
807        // state at unknown block
808        assert_eq!(chain.execution_outcome_at_block(100), None);
809
810        // split in two
811        assert_eq!(
812            chain.clone().split(block1_hash.into()),
813            ChainSplit::Split { canonical: chain_split1, pending: chain_split2 }
814        );
815
816        // split at unknown block hash
817        assert_eq!(
818            chain.clone().split(B256::new([100; 32]).into()),
819            ChainSplit::NoSplitPending(chain.clone())
820        );
821
822        // split at higher number
823        assert_eq!(chain.clone().split(10u64.into()), ChainSplit::NoSplitPending(chain.clone()));
824
825        // split at lower number
826        assert_eq!(chain.clone().split(0u64.into()), ChainSplit::NoSplitPending(chain));
827    }
828
829    #[test]
830    #[cfg(not(feature = "optimism"))]
831    fn receipts_by_block_hash() {
832        use reth_primitives::{Receipt, Receipts, TxType};
833
834        // Create a default SealedBlockWithSenders object
835        let block: SealedBlockWithSenders = Default::default();
836
837        // Define block hashes for block1 and block2
838        let block1_hash = B256::new([0x01; 32]);
839        let block2_hash = B256::new([0x02; 32]);
840
841        // Clone the default block into block1 and block2
842        let mut block1 = block.clone();
843        let mut block2 = block;
844
845        // Set the hashes of block1 and block2
846        block1.block.header.set_hash(block1_hash);
847        block2.block.header.set_hash(block2_hash);
848
849        // Create a random receipt object, receipt1
850        let receipt1 = Receipt {
851            tx_type: TxType::Legacy,
852            cumulative_gas_used: 46913,
853            logs: vec![],
854            success: true,
855        };
856
857        // Create another random receipt object, receipt2
858        let receipt2 = Receipt {
859            tx_type: TxType::Legacy,
860            cumulative_gas_used: 1325345,
861            logs: vec![],
862            success: true,
863        };
864
865        // Create a Receipts object with a vector of receipt vectors
866        let receipts =
867            Receipts { receipt_vec: vec![vec![Some(receipt1.clone())], vec![Some(receipt2)]] };
868
869        // Create an ExecutionOutcome object with the created bundle, receipts, an empty requests
870        // vector, and first_block set to 10
871        let execution_outcome = ExecutionOutcome {
872            bundle: Default::default(),
873            receipts,
874            requests: vec![],
875            first_block: 10,
876        };
877
878        // Create a Chain object with a BTreeMap of blocks mapped to their block numbers,
879        // including block1_hash and block2_hash, and the execution_outcome
880        let chain: Chain = Chain {
881            blocks: BTreeMap::from([(10, block1), (11, block2)]),
882            execution_outcome: execution_outcome.clone(),
883            ..Default::default()
884        };
885
886        // Assert that the proper receipt vector is returned for block1_hash
887        assert_eq!(chain.receipts_by_block_hash(block1_hash), Some(vec![&receipt1]));
888
889        // Create an ExecutionOutcome object with a single receipt vector containing receipt1
890        let execution_outcome1 = ExecutionOutcome {
891            bundle: Default::default(),
892            receipts: Receipts { receipt_vec: vec![vec![Some(receipt1)]] },
893            requests: vec![],
894            first_block: 10,
895        };
896
897        // Assert that the execution outcome at the first block contains only the first receipt
898        assert_eq!(chain.execution_outcome_at_block(10), Some(execution_outcome1));
899
900        // Assert that the execution outcome at the tip block contains the whole execution outcome
901        assert_eq!(chain.execution_outcome_at_block(11), Some(execution_outcome));
902    }
903}