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 priority fee above gas fee")]
93    TxGasOverflowError,
94    #[error("Transaction intrinsic gas overflow")]
95    TxTipAboveFeeCapError,
96    #[error("Transaction intrinsic gas cost above gas limit")]
97    TxIntrinsicGasCostAboveLimitError,
98    #[error("Transaction blob base fee too low")]
99    TxBlobBaseFeeTooLowError,
100    #[error("Blob transaction submited without blobs bundle")]
101    BlobTxNoBlobsBundle,
102    #[error("Nonce for account too low")]
103    NonceTooLow,
104    #[error("Nonce already used")]
105    InvalidNonce,
106    #[error("Transaction chain id mismatch, expected chain id: {0}")]
107    InvalidChainId(u64),
108    #[error("Account does not have enough balance to cover the tx cost")]
109    NotEnoughBalance,
110    #[error("Transaction gas fields are invalid")]
111    InvalidTxGasvalues,
112    #[error("Invalid pooled TxType, expected: {0}")]
113    InvalidPooledTxType(u8),
114    #[error("Invalid pooled transaction size, differs from expected")]
115    InvalidPooledTxSize,
116    #[error("Requested pooled transaction was not received")]
117    RequestedPooledTxNotFound,
118    #[error("Transaction sender is invalid {0}")]
119    InvalidTxSender(#[from] ethrex_crypto::CryptoError),
120    #[error("Attempted to replace a pooled transaction with an underpriced transaction")]
121    UnderpricedReplacement,
122}
123
124#[derive(Debug)]
125pub enum ForkChoiceElement {
126    Head,
127    Safe,
128    Finalized,
129}
130
131#[derive(Debug, thiserror::Error)]
132pub enum InvalidForkChoice {
133    #[error("DB error: {0}")]
134    StoreError(#[from] StoreError),
135    #[error("The node has not finished syncing.")]
136    Syncing,
137    #[error("Head hash value is invalid.")]
138    InvalidHeadHash,
139    #[error("New head block is already canonical. Skipping update.")]
140    NewHeadAlreadyCanonical,
141    #[error("A fork choice element ({:?}) was not found, but an ancestor was, so it's not a sync problem.", ._0)]
142    ElementNotFound(ForkChoiceElement),
143    #[error("Pre merge block can't be a fork choice update.")]
144    PreMergeBlock,
145    #[error("Safe, finalized and head blocks are not in the correct order.")]
146    Unordered,
147    #[error("The following blocks are not connected between each other: {:?}, {:?}", ._0, ._1)]
148    Disconnected(ForkChoiceElement, ForkChoiceElement),
149    #[error("Requested head is an invalid block.")]
150    InvalidHead,
151    #[error("Previously rejected block.")]
152    InvalidAncestor(BlockHash),
153    #[error("Cannot find link between Head and the canonical chain")]
154    UnlinkedHead,
155    #[error("Reorg depth {reorg_depth} exceeds the client's limit of {limit}")]
156    TooDeepReorg { reorg_depth: u64, limit: u64 },
157
158    // TODO(#5564): handle arbitrary reorgs
159    #[error("State root of the new head is not reachable from the database")]
160    StateNotReachable,
161}