reth_engine_tree/tree/
error.rs

1//! Internal errors for the tree module.
2
3use alloy_consensus::BlockHeader;
4use reth_consensus::ConsensusError;
5use reth_errors::{BlockExecutionError, BlockValidationError, ProviderError};
6use reth_evm::execute::InternalBlockExecutionError;
7use reth_payload_primitives::NewPayloadError;
8use reth_primitives_traits::{Block, BlockBody, SealedBlock};
9
10/// This is an error that can come from advancing persistence.
11#[derive(Debug, thiserror::Error)]
12pub enum AdvancePersistenceError {
13    /// The persistence channel was closed unexpectedly
14    #[error("persistence channel closed")]
15    ChannelClosed,
16    /// A provider error
17    #[error(transparent)]
18    Provider(#[from] ProviderError),
19}
20
21#[derive(thiserror::Error)]
22#[error("Failed to insert block (hash={}, number={}, parent_hash={}): {}",
23    .block.hash(),
24    .block.number(),
25    .block.parent_hash(),
26    .kind)]
27struct InsertBlockErrorData<B: Block> {
28    block: SealedBlock<B>,
29    #[source]
30    kind: InsertBlockErrorKind,
31}
32
33impl<B: Block> std::fmt::Debug for InsertBlockErrorData<B> {
34    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35        f.debug_struct("InsertBlockError")
36            .field("error", &self.kind)
37            .field("hash", &self.block.hash())
38            .field("number", &self.block.number())
39            .field("parent_hash", &self.block.parent_hash())
40            .field("num_txs", &self.block.body().transactions().len())
41            .finish_non_exhaustive()
42    }
43}
44
45impl<B: Block> InsertBlockErrorData<B> {
46    const fn new(block: SealedBlock<B>, kind: InsertBlockErrorKind) -> Self {
47        Self { block, kind }
48    }
49
50    fn boxed(block: SealedBlock<B>, kind: InsertBlockErrorKind) -> Box<Self> {
51        Box::new(Self::new(block, kind))
52    }
53}
54
55/// Error thrown when inserting a block failed because the block is considered invalid.
56#[derive(thiserror::Error)]
57#[error(transparent)]
58pub struct InsertBlockError<B: Block> {
59    inner: Box<InsertBlockErrorData<B>>,
60}
61
62// === impl InsertBlockErrorTwo ===
63
64impl<B: Block> InsertBlockError<B> {
65    /// Create a new `InsertInvalidBlockErrorTwo`
66    pub fn new(block: SealedBlock<B>, kind: InsertBlockErrorKind) -> Self {
67        Self { inner: InsertBlockErrorData::boxed(block, kind) }
68    }
69
70    /// Create a new `InsertInvalidBlockError` from a consensus error
71    pub fn consensus_error(error: ConsensusError, block: SealedBlock<B>) -> Self {
72        Self::new(block, InsertBlockErrorKind::Consensus(error))
73    }
74
75    /// Consumes the error and returns the block that resulted in the error
76    #[inline]
77    pub fn into_block(self) -> SealedBlock<B> {
78        self.inner.block
79    }
80
81    /// Returns the error kind
82    #[inline]
83    pub const fn kind(&self) -> &InsertBlockErrorKind {
84        &self.inner.kind
85    }
86
87    /// Returns the block that resulted in the error
88    #[inline]
89    pub const fn block(&self) -> &SealedBlock<B> {
90        &self.inner.block
91    }
92
93    /// Consumes the type and returns the block and error kind.
94    #[inline]
95    pub fn split(self) -> (SealedBlock<B>, InsertBlockErrorKind) {
96        let inner = *self.inner;
97        (inner.block, inner.kind)
98    }
99}
100
101impl<B: Block> std::fmt::Debug for InsertBlockError<B> {
102    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
103        std::fmt::Debug::fmt(&self.inner, f)
104    }
105}
106
107/// All error variants possible when inserting a block
108#[derive(Debug, thiserror::Error)]
109pub enum InsertBlockErrorKind {
110    /// Block violated consensus rules.
111    #[error(transparent)]
112    Consensus(#[from] ConsensusError),
113    /// Block execution failed.
114    #[error(transparent)]
115    Execution(#[from] BlockExecutionError),
116    /// Provider error.
117    #[error(transparent)]
118    Provider(#[from] ProviderError),
119    /// Other errors.
120    #[error(transparent)]
121    Other(#[from] Box<dyn core::error::Error + Send + Sync + 'static>),
122}
123
124impl InsertBlockErrorKind {
125    /// Returns an [`InsertBlockValidationError`] if the error is caused by an invalid block.
126    ///
127    /// Returns an [`InsertBlockFatalError`] if the error is caused by an error that is not
128    /// validation related or is otherwise fatal.
129    ///
130    /// This is intended to be used to determine if we should respond `INVALID` as a response when
131    /// processing a new block.
132    pub fn ensure_validation_error(
133        self,
134    ) -> Result<InsertBlockValidationError, InsertBlockFatalError> {
135        match self {
136            Self::Consensus(err) => Ok(InsertBlockValidationError::Consensus(err)),
137            // other execution errors that are considered internal errors
138            Self::Execution(err) => {
139                match err {
140                    BlockExecutionError::Validation(err) => {
141                        Ok(InsertBlockValidationError::Validation(err))
142                    }
143                    // these are internal errors, not caused by an invalid block
144                    BlockExecutionError::Internal(error) => {
145                        Err(InsertBlockFatalError::BlockExecutionError(error))
146                    }
147                }
148            }
149            Self::Provider(err) => Err(InsertBlockFatalError::Provider(err)),
150            Self::Other(err) => Err(InternalBlockExecutionError::Other(err).into()),
151        }
152    }
153}
154
155/// Error variants that are not caused by invalid blocks
156#[derive(Debug, thiserror::Error)]
157pub enum InsertBlockFatalError {
158    /// A provider error
159    #[error(transparent)]
160    Provider(#[from] ProviderError),
161    /// An internal / fatal block execution error
162    #[error(transparent)]
163    BlockExecutionError(#[from] InternalBlockExecutionError),
164}
165
166/// Error variants that are caused by invalid blocks
167#[derive(Debug, thiserror::Error)]
168pub enum InsertBlockValidationError {
169    /// Block violated consensus rules.
170    #[error(transparent)]
171    Consensus(#[from] ConsensusError),
172    /// Validation error, transparently wrapping [`BlockValidationError`]
173    #[error(transparent)]
174    Validation(#[from] BlockValidationError),
175}
176
177/// Errors that may occur when inserting a payload.
178#[derive(Debug, thiserror::Error)]
179pub enum InsertPayloadError<B: Block> {
180    /// Block validation error
181    #[error(transparent)]
182    Block(#[from] InsertBlockError<B>),
183    /// Payload validation error
184    #[error(transparent)]
185    Payload(#[from] NewPayloadError),
186}