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