reth_blockchain_tree_api/
error.rs1use alloy_consensus::BlockHeader;
4use alloy_primitives::{BlockHash, BlockNumber};
5use reth_consensus::ConsensusError;
6use reth_execution_errors::{
7 BlockExecutionError, BlockValidationError, InternalBlockExecutionError,
8};
9use reth_primitives::{SealedBlock, SealedBlockFor};
10use reth_primitives_traits::{Block, BlockBody};
11pub use reth_storage_errors::provider::ProviderError;
12
13#[derive(Debug, Clone, Copy, thiserror::Error, Eq, PartialEq)]
15pub enum BlockchainTreeError {
16 #[error("block number is lower than the last finalized block number #{last_finalized}")]
18 PendingBlockIsFinalized {
19 last_finalized: BlockNumber,
21 },
22 #[error("chainId can't be found in BlockchainTree with internal index {chain_id}")]
24 BlockSideChainIdConsistency {
25 chain_id: u64,
27 },
28 #[error("canonical chain header {block_hash} can't be found")]
30 CanonicalChain {
31 block_hash: BlockHash,
33 },
34 #[error("block number #{block_number} not found in blockchain tree chain")]
36 BlockNumberNotFoundInChain {
37 block_number: BlockNumber,
39 },
40 #[error("block hash {block_hash} not found in blockchain tree chain")]
42 BlockHashNotFoundInChain {
43 block_hash: BlockHash,
45 },
46 #[error("block with hash {block_hash} failed to buffer")]
48 BlockBufferingFailed {
49 block_hash: BlockHash,
51 },
52 #[error("genesis block has no parent")]
54 GenesisBlockHasNoParent,
55}
56
57#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq)]
59pub enum CanonicalError {
60 #[error(transparent)]
62 Validation(#[from] BlockValidationError),
63 #[error(transparent)]
65 BlockchainTree(#[from] BlockchainTreeError),
66 #[error(transparent)]
68 Provider(#[from] ProviderError),
69 #[error("transaction error on revert: {0}")]
71 CanonicalRevert(String),
72 #[error("transaction error on commit: {0}")]
74 CanonicalCommit(String),
75 #[error("transaction error on revert: {0}")]
77 OptimisticTargetRevert(BlockNumber),
78}
79
80impl CanonicalError {
81 pub const fn is_fatal(&self) -> bool {
83 matches!(self, Self::CanonicalCommit(_) | Self::CanonicalRevert(_))
84 }
85
86 pub const fn is_block_hash_not_found(&self) -> bool {
89 matches!(self, Self::BlockchainTree(BlockchainTreeError::BlockHashNotFoundInChain { .. }))
90 }
91
92 pub const fn optimistic_revert_block_number(&self) -> Option<BlockNumber> {
95 match self {
96 Self::OptimisticTargetRevert(block_number) => Some(*block_number),
97 _ => None,
98 }
99 }
100}
101
102#[derive(thiserror::Error)]
104#[error(transparent)]
105pub struct InsertBlockError {
106 inner: Box<InsertBlockErrorData>,
107}
108
109impl InsertBlockError {
112 pub fn new(block: SealedBlock, kind: InsertBlockErrorKind) -> Self {
114 Self { inner: InsertBlockErrorData::boxed(block, kind) }
115 }
116
117 pub fn tree_error(error: BlockchainTreeError, block: SealedBlock) -> Self {
119 Self::new(block, InsertBlockErrorKind::Tree(error))
120 }
121
122 pub fn consensus_error(error: ConsensusError, block: SealedBlock) -> Self {
124 Self::new(block, InsertBlockErrorKind::Consensus(error))
125 }
126
127 pub fn sender_recovery_error(block: SealedBlock) -> Self {
129 Self::new(block, InsertBlockErrorKind::SenderRecovery)
130 }
131
132 pub fn execution_error(error: BlockExecutionError, block: SealedBlock) -> Self {
134 Self::new(block, InsertBlockErrorKind::Execution(error))
135 }
136
137 #[inline]
139 pub fn into_block(self) -> SealedBlock {
140 self.inner.block
141 }
142
143 #[inline]
145 pub const fn kind(&self) -> &InsertBlockErrorKind {
146 &self.inner.kind
147 }
148
149 #[inline]
151 pub const fn block(&self) -> &SealedBlock {
152 &self.inner.block
153 }
154
155 #[inline]
157 pub fn split(self) -> (SealedBlock, InsertBlockErrorKind) {
158 let inner = *self.inner;
159 (inner.block, inner.kind)
160 }
161}
162
163impl std::fmt::Debug for InsertBlockError {
164 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
165 std::fmt::Debug::fmt(&self.inner, f)
166 }
167}
168
169#[derive(thiserror::Error, Debug)]
170#[error("Failed to insert block (hash={}, number={}, parent_hash={}): {kind}",
171 .block.hash(),
172 .block.number,
173 .block.parent_hash)]
174struct InsertBlockErrorData {
175 block: SealedBlock,
176 #[source]
177 kind: InsertBlockErrorKind,
178}
179
180impl InsertBlockErrorData {
181 const fn new(block: SealedBlock, kind: InsertBlockErrorKind) -> Self {
182 Self { block, kind }
183 }
184
185 fn boxed(block: SealedBlock, kind: InsertBlockErrorKind) -> Box<Self> {
186 Box::new(Self::new(block, kind))
187 }
188}
189
190struct InsertBlockErrorDataTwo<B: Block> {
191 block: SealedBlockFor<B>,
192 kind: InsertBlockErrorKindTwo,
193}
194
195impl<B: Block> std::fmt::Display for InsertBlockErrorDataTwo<B> {
196 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
197 write!(
198 f,
199 "Failed to insert block (hash={}, number={}, parent_hash={}): {}",
200 self.block.hash(),
201 self.block.number(),
202 self.block.parent_hash(),
203 self.kind
204 )
205 }
206}
207
208impl<B: Block> std::fmt::Debug for InsertBlockErrorDataTwo<B> {
209 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
210 f.debug_struct("InsertBlockError")
211 .field("error", &self.kind)
212 .field("hash", &self.block.hash())
213 .field("number", &self.block.number())
214 .field("parent_hash", &self.block.parent_hash())
215 .field("num_txs", &self.block.body.transactions().len())
216 .finish_non_exhaustive()
217 }
218}
219
220impl<B: Block> core::error::Error for InsertBlockErrorDataTwo<B> {
221 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
222 Some(&self.kind)
223 }
224}
225
226impl<B: Block> InsertBlockErrorDataTwo<B> {
227 const fn new(block: SealedBlockFor<B>, kind: InsertBlockErrorKindTwo) -> Self {
228 Self { block, kind }
229 }
230
231 fn boxed(block: SealedBlockFor<B>, kind: InsertBlockErrorKindTwo) -> Box<Self> {
232 Box::new(Self::new(block, kind))
233 }
234}
235
236#[derive(thiserror::Error)]
238#[error(transparent)]
239pub struct InsertBlockErrorTwo<B: Block> {
240 inner: Box<InsertBlockErrorDataTwo<B>>,
241}
242
243impl<B: Block> InsertBlockErrorTwo<B> {
246 pub fn new(block: SealedBlockFor<B>, kind: InsertBlockErrorKindTwo) -> Self {
248 Self { inner: InsertBlockErrorDataTwo::boxed(block, kind) }
249 }
250
251 pub fn consensus_error(error: ConsensusError, block: SealedBlockFor<B>) -> Self {
253 Self::new(block, InsertBlockErrorKindTwo::Consensus(error))
254 }
255
256 pub fn sender_recovery_error(block: SealedBlockFor<B>) -> Self {
258 Self::new(block, InsertBlockErrorKindTwo::SenderRecovery)
259 }
260
261 pub fn execution_error(error: BlockExecutionError, block: SealedBlockFor<B>) -> Self {
263 Self::new(block, InsertBlockErrorKindTwo::Execution(error))
264 }
265
266 #[inline]
268 pub fn into_block(self) -> SealedBlockFor<B> {
269 self.inner.block
270 }
271
272 #[inline]
274 pub const fn kind(&self) -> &InsertBlockErrorKindTwo {
275 &self.inner.kind
276 }
277
278 #[inline]
280 pub const fn block(&self) -> &SealedBlockFor<B> {
281 &self.inner.block
282 }
283
284 #[inline]
286 pub fn split(self) -> (SealedBlockFor<B>, InsertBlockErrorKindTwo) {
287 let inner = *self.inner;
288 (inner.block, inner.kind)
289 }
290}
291
292impl<B: Block> std::fmt::Debug for InsertBlockErrorTwo<B> {
293 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
294 std::fmt::Debug::fmt(&self.inner, f)
295 }
296}
297
298#[derive(Debug, thiserror::Error)]
300pub enum InsertBlockErrorKindTwo {
301 #[error("failed to recover senders for block")]
303 SenderRecovery,
304 #[error(transparent)]
306 Consensus(#[from] ConsensusError),
307 #[error(transparent)]
309 Execution(#[from] BlockExecutionError),
310 #[error(transparent)]
312 Provider(#[from] ProviderError),
313 #[error(transparent)]
315 Other(#[from] Box<dyn core::error::Error + Send + Sync + 'static>),
316}
317
318impl InsertBlockErrorKindTwo {
319 pub fn ensure_validation_error(
327 self,
328 ) -> Result<InsertBlockValidationError, InsertBlockFatalError> {
329 match self {
330 Self::SenderRecovery => Ok(InsertBlockValidationError::SenderRecovery),
331 Self::Consensus(err) => Ok(InsertBlockValidationError::Consensus(err)),
332 Self::Execution(err) => {
334 match err {
335 BlockExecutionError::Validation(err) => {
336 Ok(InsertBlockValidationError::Validation(err))
337 }
338 BlockExecutionError::Consensus(err) => {
339 Ok(InsertBlockValidationError::Consensus(err))
340 }
341 BlockExecutionError::Internal(error) => {
343 Err(InsertBlockFatalError::BlockExecutionError(error))
344 }
345 }
346 }
347 Self::Provider(err) => Err(InsertBlockFatalError::Provider(err)),
348 Self::Other(err) => Err(InternalBlockExecutionError::Other(err).into()),
349 }
350 }
351}
352
353#[derive(Debug, thiserror::Error)]
355pub enum InsertBlockFatalError {
356 #[error(transparent)]
358 Provider(#[from] ProviderError),
359 #[error(transparent)]
361 BlockExecutionError(#[from] InternalBlockExecutionError),
362}
363
364#[derive(Debug, thiserror::Error)]
366pub enum InsertBlockValidationError {
367 #[error("failed to recover senders for block")]
369 SenderRecovery,
370 #[error(transparent)]
372 Consensus(#[from] ConsensusError),
373 #[error(transparent)]
375 Validation(#[from] BlockValidationError),
376}
377
378impl InsertBlockValidationError {
379 pub const fn is_block_pre_merge(&self) -> bool {
381 matches!(self, Self::Validation(BlockValidationError::BlockPreMerge { .. }))
382 }
383}
384
385#[derive(Debug, thiserror::Error)]
387pub enum InsertBlockErrorKind {
388 #[error("failed to recover senders for block")]
390 SenderRecovery,
391 #[error(transparent)]
393 Consensus(#[from] ConsensusError),
394 #[error(transparent)]
396 Execution(#[from] BlockExecutionError),
397 #[error(transparent)]
399 Tree(#[from] BlockchainTreeError),
400 #[error(transparent)]
402 Provider(#[from] ProviderError),
403 #[error(transparent)]
405 Internal(#[from] Box<dyn core::error::Error + Send + Sync>),
406 #[error(transparent)]
408 Canonical(#[from] CanonicalError),
409}
410
411impl InsertBlockErrorKind {
412 pub const fn is_tree_error(&self) -> bool {
414 matches!(self, Self::Tree(_))
415 }
416
417 pub const fn is_consensus_error(&self) -> bool {
419 matches!(self, Self::Consensus(_))
420 }
421
422 pub const fn is_state_root_error(&self) -> bool {
424 match self {
426 Self::Execution(err) => {
427 matches!(
428 err,
429 BlockExecutionError::Validation(BlockValidationError::StateRoot { .. })
430 )
431 }
432 Self::Canonical(err) => {
433 matches!(
434 err,
435 CanonicalError::Validation(BlockValidationError::StateRoot { .. }) |
436 CanonicalError::Provider(
437 ProviderError::StateRootMismatch(_) |
438 ProviderError::UnwindStateRootMismatch(_)
439 )
440 )
441 }
442 Self::Provider(err) => {
443 matches!(
444 err,
445 ProviderError::StateRootMismatch(_) | ProviderError::UnwindStateRootMismatch(_)
446 )
447 }
448 _ => false,
449 }
450 }
451
452 #[allow(clippy::match_same_arms)]
456 pub const fn is_invalid_block(&self) -> bool {
457 match self {
458 Self::SenderRecovery | Self::Consensus(_) => true,
459 Self::Execution(err) => {
461 match err {
462 BlockExecutionError::Validation(_) | BlockExecutionError::Consensus(_) => {
463 true
465 }
466 BlockExecutionError::Internal(_) => false,
468 }
469 }
470 Self::Tree(err) => {
471 match err {
472 BlockchainTreeError::PendingBlockIsFinalized { .. } => {
473 true
475 }
476 BlockchainTreeError::BlockSideChainIdConsistency { .. } |
477 BlockchainTreeError::CanonicalChain { .. } |
478 BlockchainTreeError::BlockNumberNotFoundInChain { .. } |
479 BlockchainTreeError::BlockHashNotFoundInChain { .. } |
480 BlockchainTreeError::BlockBufferingFailed { .. } |
481 BlockchainTreeError::GenesisBlockHasNoParent => false,
482 }
483 }
484 Self::Provider(_) | Self::Internal(_) => {
485 false
487 }
488 Self::Canonical(err) => match err {
489 CanonicalError::BlockchainTree(_) |
490 CanonicalError::CanonicalCommit(_) |
491 CanonicalError::CanonicalRevert(_) |
492 CanonicalError::OptimisticTargetRevert(_) |
493 CanonicalError::Provider(_) => false,
494 CanonicalError::Validation(_) => true,
495 },
496 }
497 }
498
499 pub const fn is_block_pre_merge(&self) -> bool {
501 matches!(
502 self,
503 Self::Execution(BlockExecutionError::Validation(
504 BlockValidationError::BlockPreMerge { .. }
505 ))
506 )
507 }
508
509 pub const fn is_execution_error(&self) -> bool {
511 matches!(self, Self::Execution(_))
512 }
513
514 pub const fn is_internal(&self) -> bool {
516 matches!(self, Self::Internal(_))
517 }
518
519 pub const fn as_tree_error(&self) -> Option<BlockchainTreeError> {
521 match self {
522 Self::Tree(err) => Some(*err),
523 _ => None,
524 }
525 }
526
527 pub const fn as_consensus_error(&self) -> Option<&ConsensusError> {
529 match self {
530 Self::Consensus(err) => Some(err),
531 _ => None,
532 }
533 }
534
535 pub const fn as_execution_error(&self) -> Option<&BlockExecutionError> {
537 match self {
538 Self::Execution(err) => Some(err),
539 _ => None,
540 }
541 }
542}