Skip to main content

ethrex_blockchain/
error.rs

1use ethrex_common::{
2    H256,
3    types::{BlobsBundleError, BlockHash},
4};
5use ethrex_rlp::error::RLPDecodeError;
6use ethrex_storage::error::StoreError;
7use ethrex_trie::TrieError;
8use ethrex_vm::EvmError;
9
10// Re-export InvalidBlockError from ethrex-common for backwards compatibility
11pub use ethrex_common::InvalidBlockError;
12
13#[derive(Debug, thiserror::Error)]
14pub enum ChainError {
15    #[error("Invalid Block: {0}")]
16    InvalidBlock(#[from] InvalidBlockError),
17    #[error("Parent block not found")]
18    ParentNotFound,
19    //TODO: If a block with block_number greater than latest plus one is received
20    //maybe we are missing data and should wait for syncing
21    #[error("The post-state of the parent-block.")]
22    ParentStateNotFound,
23    #[error("DB error: {0}")]
24    StoreError(#[from] StoreError),
25    #[error("Trie error: {0}")]
26    TrieError(#[from] TrieError),
27    #[error("RLP decode error: {0}")]
28    RLPDecodeError(#[from] RLPDecodeError),
29    #[error("EVM error: {0}")]
30    EvmError(EvmError),
31    #[error("Invalid Transaction: {0}")]
32    InvalidTransaction(String),
33    #[error("Failed to generate witness: {0}")]
34    WitnessGeneration(String),
35    #[error("{0}")]
36    Custom(String),
37    #[error("Unknown Payload")]
38    UnknownPayload,
39}
40
41impl From<EvmError> for ChainError {
42    fn from(value: EvmError) -> Self {
43        match value {
44            EvmError::Transaction(err) => {
45                ChainError::InvalidBlock(InvalidBlockError::InvalidTransaction(err))
46            }
47            EvmError::InvalidDepositRequest => ChainError::InvalidBlock(
48                InvalidBlockError::InvalidTransaction("Invalid deposit request layout".to_string()),
49            ),
50            other_errors => ChainError::EvmError(other_errors),
51        }
52    }
53}
54
55#[cfg(feature = "metrics")]
56impl ChainError {
57    pub fn to_metric(&self) -> &str {
58        match self {
59            ChainError::InvalidBlock(_) => "invalid_block",
60            ChainError::ParentNotFound => "parent_not_found",
61            ChainError::ParentStateNotFound => "parent_state_not_found",
62            ChainError::StoreError(_) => "store_error",
63            ChainError::TrieError(_) => "trie_error",
64            ChainError::RLPDecodeError(_) => "rlp_decode_error",
65            ChainError::EvmError(_) => "evm_error",
66            ChainError::InvalidTransaction(_) => "invalid_transaction",
67            ChainError::WitnessGeneration(_) => "witness_generation",
68            ChainError::Custom(_) => "custom_error",
69            ChainError::UnknownPayload => "unknown_payload",
70        }
71    }
72}
73
74#[derive(Debug, thiserror::Error)]
75pub enum MempoolError {
76    #[error("No block header")]
77    NoBlockHeaderError,
78    #[error("DB error: {0}")]
79    StoreError(#[from] StoreError),
80    #[error("BlobsBundle error: {0}")]
81    BlobsBundleError(#[from] BlobsBundleError),
82    #[error("Transaction max init code size exceeded")]
83    TxMaxInitCodeSizeError,
84    #[error("Transaction encoded size ({actual} bytes) exceeds the {limit}-byte limit")]
85    TxSizeExceeded { actual: usize, limit: usize },
86    #[error("Transaction gas limit exceeded")]
87    TxGasLimitExceededError,
88    #[error(
89        "Transaction gas limit exceeds maximum. Transaction hash: {0}, transaction gas limit: {1}"
90    )]
91    TxMaxGasLimitExceededError(H256, u64),
92    #[error("Transaction intrinsic gas overflow")]
93    TxGasOverflowError,
94    #[error("Could not compute transaction intrinsic gas: {0}")]
95    IntrinsicGasError(String),
96    #[error("Transaction priority fee above gas fee")]
97    TxTipAboveFeeCapError,
98    #[error("Transaction intrinsic gas cost above gas limit")]
99    TxIntrinsicGasCostAboveLimitError,
100    #[error("Transaction blob base fee too low")]
101    TxBlobBaseFeeTooLowError,
102    #[error("Blob transaction submited without blobs bundle")]
103    BlobTxNoBlobsBundle,
104    #[error("Nonce for account too low")]
105    NonceTooLow,
106    #[error("Nonce already used")]
107    InvalidNonce,
108    #[error("Transaction chain id mismatch, expected chain id: {0}")]
109    InvalidChainId(u64),
110    #[error("Account does not have enough balance to cover the tx cost")]
111    NotEnoughBalance,
112    #[error("Transaction gas fields are invalid")]
113    InvalidTxGasvalues,
114    #[error("Invalid pooled TxType, expected: {0}")]
115    InvalidPooledTxType(u8),
116    #[error("Invalid pooled transaction size, differs from expected")]
117    InvalidPooledTxSize,
118    #[error("Requested pooled transaction was not received")]
119    RequestedPooledTxNotFound,
120    #[error("Transaction sender is invalid {0}")]
121    InvalidTxSender(#[from] ethrex_crypto::CryptoError),
122    #[error("Attempted to replace a pooled transaction with an underpriced transaction")]
123    UnderpricedReplacement,
124    #[error("EIP-7702 transaction has an empty authorization list")]
125    EmptyAuthorizationList,
126    #[error("EIP-7702 (type-4) transaction is not valid before Prague")]
127    Eip7702TxPreFork,
128}
129
130#[derive(Debug)]
131pub enum ForkChoiceElement {
132    Head,
133    Safe,
134    Finalized,
135}
136
137#[derive(Debug, thiserror::Error)]
138pub enum InvalidForkChoice {
139    #[error("DB error: {0}")]
140    StoreError(#[from] StoreError),
141    #[error("The node has not finished syncing.")]
142    Syncing,
143    #[error("Head hash value is invalid.")]
144    InvalidHeadHash,
145    #[error("New head block is already canonical. Skipping update.")]
146    NewHeadAlreadyCanonical,
147    #[error("A fork choice element ({:?}) was not found, but an ancestor was, so it's not a sync problem.", ._0)]
148    ElementNotFound(ForkChoiceElement),
149    #[error("Pre merge block can't be a fork choice update.")]
150    PreMergeBlock,
151    #[error("Safe, finalized and head blocks are not in the correct order.")]
152    Unordered,
153    #[error("The following blocks are not connected between each other: {:?}, {:?}", ._0, ._1)]
154    Disconnected(ForkChoiceElement, ForkChoiceElement),
155    #[error("Requested head is an invalid block.")]
156    InvalidHead,
157    #[error("Previously rejected block.")]
158    InvalidAncestor(BlockHash),
159    #[error("Cannot find link between Head and the canonical chain")]
160    UnlinkedHead,
161    #[error("Reorg depth {reorg_depth} exceeds the client's limit of {limit}")]
162    TooDeepReorg { reorg_depth: u64, limit: u64 },
163
164    // TODO(#5564): handle arbitrary reorgs
165    #[error("State root of the new head is not reachable from the database")]
166    StateNotReachable,
167}