reth_execution_errors/
lib.rs

1//! Commonly used error types used when doing block execution.
2
3#![doc(
4    html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png",
5    html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256",
6    issue_tracker_base_url = "https://github.com/SeismicSystems/seismic-reth/issues/"
7)]
8#![cfg_attr(not(test), warn(unused_crate_dependencies))]
9#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
10#![cfg_attr(not(feature = "std"), no_std)]
11
12extern crate alloc;
13
14use alloc::{boxed::Box, string::String};
15use alloy_eips::BlockNumHash;
16use alloy_primitives::B256;
17use reth_consensus::ConsensusError;
18use reth_prune_types::PruneSegmentError;
19use reth_storage_errors::provider::ProviderError;
20use revm_primitives::EVMError;
21use thiserror::Error;
22
23pub mod trie;
24pub use trie::*;
25
26/// Transaction validation errors
27#[derive(Error, PartialEq, Eq, Clone, Debug)]
28pub enum BlockValidationError {
29    /// EVM error with transaction hash and message
30    #[error("EVM reported invalid transaction ({hash}): {error}")]
31    EVM {
32        /// The hash of the transaction
33        hash: B256,
34        /// The EVM error.
35        error: Box<EVMError<ProviderError>>,
36    },
37    /// Error when recovering the sender for a transaction
38    #[error("failed to recover sender for transaction")]
39    SenderRecoveryError,
40    /// Error when incrementing balance in post execution
41    #[error("incrementing balance in post execution failed")]
42    IncrementBalanceFailed,
43    /// Error when the state root does not match the expected value.
44    #[error(transparent)]
45    StateRoot(#[from] StateRootError),
46    /// Error when transaction gas limit exceeds available block gas
47    #[error(
48        "transaction gas limit {transaction_gas_limit} is more than blocks available gas {block_available_gas}"
49    )]
50    TransactionGasLimitMoreThanAvailableBlockGas {
51        /// The transaction's gas limit
52        transaction_gas_limit: u64,
53        /// The available block gas
54        block_available_gas: u64,
55    },
56    /// Error for pre-merge block
57    #[error("block {hash} is pre merge")]
58    BlockPreMerge {
59        /// The hash of the block
60        hash: B256,
61    },
62    /// Error for missing total difficulty
63    #[error("missing total difficulty for block {hash}")]
64    MissingTotalDifficulty {
65        /// The hash of the block
66        hash: B256,
67    },
68    /// Error for EIP-4788 when parent beacon block root is missing
69    #[error("EIP-4788 parent beacon block root missing for active Cancun block")]
70    MissingParentBeaconBlockRoot,
71    /// Error for Cancun genesis block when parent beacon block root is not zero
72    #[error(
73        "the parent beacon block root is not zero for Cancun genesis block: {parent_beacon_block_root}"
74    )]
75    CancunGenesisParentBeaconBlockRootNotZero {
76        /// The beacon block root
77        parent_beacon_block_root: B256,
78    },
79    /// EVM error during [EIP-4788] beacon root contract call.
80    ///
81    /// [EIP-4788]: https://eips.ethereum.org/EIPS/eip-4788
82    #[error("failed to apply beacon root contract call at {parent_beacon_block_root}: {message}")]
83    BeaconRootContractCall {
84        /// The beacon block root
85        parent_beacon_block_root: Box<B256>,
86        /// The error message.
87        message: String,
88    },
89    /// EVM error during [EIP-2935] blockhash contract call.
90    ///
91    /// [EIP-2935]: https://eips.ethereum.org/EIPS/eip-2935
92    #[error("failed to apply blockhash contract call: {message}")]
93    BlockHashContractCall {
94        /// The error message.
95        message: String,
96    },
97    /// EVM error during withdrawal requests contract call [EIP-7002]
98    ///
99    /// [EIP-7002]: https://eips.ethereum.org/EIPS/eip-7002
100    #[error("failed to apply withdrawal requests contract call: {message}")]
101    WithdrawalRequestsContractCall {
102        /// The error message.
103        message: String,
104    },
105    /// EVM error during consolidation requests contract call [EIP-7251]
106    ///
107    /// [EIP-7251]: https://eips.ethereum.org/EIPS/eip-7251
108    #[error("failed to apply consolidation requests contract call: {message}")]
109    ConsolidationRequestsContractCall {
110        /// The error message.
111        message: String,
112    },
113    /// Error when decoding deposit requests from receipts [EIP-6110]
114    ///
115    /// [EIP-6110]: https://eips.ethereum.org/EIPS/eip-6110
116    #[error("failed to decode deposit requests from receipts: {_0}")]
117    DepositRequestDecode(String),
118}
119
120/// `BlockExecutor` Errors
121#[derive(Error, Debug)]
122pub enum BlockExecutionError {
123    /// Validation error, transparently wrapping [`BlockValidationError`]
124    #[error(transparent)]
125    Validation(#[from] BlockValidationError),
126    /// Consensus error, transparently wrapping [`ConsensusError`]
127    #[error(transparent)]
128    Consensus(#[from] ConsensusError),
129    /// Internal, i.e. non consensus or validation related Block Executor Errors
130    #[error(transparent)]
131    Internal(#[from] InternalBlockExecutionError),
132}
133
134impl BlockExecutionError {
135    /// Create a new [`BlockExecutionError::Internal`] variant, containing a
136    /// [`InternalBlockExecutionError::Other`] error.
137    #[cfg(feature = "std")]
138    pub fn other<E>(error: E) -> Self
139    where
140        E: core::error::Error + Send + Sync + 'static,
141    {
142        Self::Internal(InternalBlockExecutionError::other(error))
143    }
144
145    /// Create a new [`BlockExecutionError::Internal`] variant, containing a
146    /// [`InternalBlockExecutionError::Other`] error with the given message.
147    #[cfg(feature = "std")]
148    pub fn msg(msg: impl std::fmt::Display) -> Self {
149        Self::Internal(InternalBlockExecutionError::msg(msg))
150    }
151
152    /// Returns the inner `BlockValidationError` if the error is a validation error.
153    pub const fn as_validation(&self) -> Option<&BlockValidationError> {
154        match self {
155            Self::Validation(err) => Some(err),
156            _ => None,
157        }
158    }
159
160    /// Returns `true` if the error is a state root error.
161    pub const fn is_state_root_error(&self) -> bool {
162        matches!(self, Self::Validation(BlockValidationError::StateRoot(_)))
163    }
164}
165
166impl From<ProviderError> for BlockExecutionError {
167    fn from(error: ProviderError) -> Self {
168        InternalBlockExecutionError::from(error).into()
169    }
170}
171
172/// Internal (i.e., not validation or consensus related) `BlockExecutor` Errors
173#[derive(Error, Debug)]
174pub enum InternalBlockExecutionError {
175    /// Pruning error, transparently wrapping [`PruneSegmentError`]
176    #[error(transparent)]
177    Pruning(#[from] PruneSegmentError),
178    /// Error when appending chain on fork is not possible
179    #[error(
180        "appending chain on fork (other_chain_fork:?) is not possible as the tip is {chain_tip:?}"
181    )]
182    AppendChainDoesntConnect {
183        /// The tip of the current chain
184        chain_tip: Box<BlockNumHash>,
185        /// The fork on the other chain
186        other_chain_fork: Box<BlockNumHash>,
187    },
188    /// Error when fetching latest block state.
189    #[error(transparent)]
190    LatestBlock(#[from] ProviderError),
191    /// Arbitrary Block Executor Errors
192    #[error(transparent)]
193    Other(Box<dyn core::error::Error + Send + Sync>),
194}
195
196impl InternalBlockExecutionError {
197    /// Create a new [`InternalBlockExecutionError::Other`] variant.
198    #[cfg(feature = "std")]
199    pub fn other<E>(error: E) -> Self
200    where
201        E: core::error::Error + Send + Sync + 'static,
202    {
203        Self::Other(Box::new(error))
204    }
205
206    /// Create a new [`InternalBlockExecutionError::Other`] from a given message.
207    #[cfg(feature = "std")]
208    pub fn msg(msg: impl std::fmt::Display) -> Self {
209        Self::Other(msg.to_string().into())
210    }
211}