1//! Error types emitted by types or implementations of this crate.
23use alloc::{boxed::Box, string::ToString};
4use alloy_primitives::B256;
5use alloy_rpc_types_engine::{ForkchoiceUpdateError, PayloadError, PayloadStatusEnum};
6use core::error;
7use reth_errors::{BlockExecutionError, ProviderError, RethError};
8use tokio::sync::oneshot;
910/// Possible error variants during payload building.
11#[derive(Debug, thiserror::Error)]
12pub enum PayloadBuilderError {
13/// Thrown when the parent header cannot be found
14#[error("missing parent header: {0}")]
15MissingParentHeader(B256),
16/// Thrown when the parent block is missing.
17#[error("missing parent block {0}")]
18MissingParentBlock(B256),
19/// An oneshot channels has been closed.
20#[error("sender has been dropped")]
21ChannelClosed,
22/// If there's no payload to resolve.
23#[error("missing payload")]
24MissingPayload,
25/// Other internal error
26#[error(transparent)]
27Internal(#[from] RethError),
28/// Unrecoverable error during evm execution.
29#[error("evm execution error: {0}")]
30EvmExecutionError(Box<dyn core::error::Error + Send + Sync>),
31/// Any other payload building errors.
32#[error(transparent)]
33Other(Box<dyn core::error::Error + Send + Sync>),
34}
3536impl PayloadBuilderError {
37/// Create a new EVM error from a boxed error.
38pub fn evm<E>(error: E) -> Self
39where
40E: core::error::Error + Send + Sync + 'static,
41 {
42Self::EvmExecutionError(Box::new(error))
43 }
4445/// Create a new error from a boxed error.
46pub fn other<E>(error: E) -> Self
47where
48E: core::error::Error + Send + Sync + 'static,
49 {
50Self::Other(Box::new(error))
51 }
52}
5354impl From<ProviderError> for PayloadBuilderError {
55fn from(error: ProviderError) -> Self {
56Self::Internal(RethError::Provider(error))
57 }
58}
5960impl From<oneshot::error::RecvError> for PayloadBuilderError {
61fn from(_: oneshot::error::RecvError) -> Self {
62Self::ChannelClosed
63 }
64}
6566impl From<BlockExecutionError> for PayloadBuilderError {
67fn from(error: BlockExecutionError) -> Self {
68Self::evm(error)
69 }
70}
7172/// Thrown when the payload or attributes are known to be invalid __before__ processing.
73///
74/// This is used mainly for
75/// [`validate_version_specific_fields`](crate::validate_version_specific_fields), which validates
76/// both execution payloads and forkchoice update attributes with respect to a method version.
77#[derive(thiserror::Error, Debug)]
78pub enum EngineObjectValidationError {
79/// Thrown when the underlying validation error occurred while validating an
80 /// `ExecutionPayload`.
81#[error("Payload validation error: {0}")]
82Payload(VersionSpecificValidationError),
8384/// Thrown when the underlying validation error occurred while validating a
85 /// `PayloadAttributes`.
86#[error("Payload attributes validation error: {0}")]
87PayloadAttributes(VersionSpecificValidationError),
8889/// Thrown if `PayloadAttributes` or `ExecutionPayload` were provided with a timestamp, but the
90 /// version of the engine method called is meant for a fork that occurs after the provided
91 /// timestamp.
92#[error("Unsupported fork")]
93UnsupportedFork,
94/// Another type of error that is not covered by the above variants.
95#[error("Invalid params: {0}")]
96InvalidParams(#[from] Box<dyn core::error::Error + Send + Sync>),
97}
9899/// Thrown when validating an execution payload OR payload attributes fails due to:
100/// * The existence of a new field that is not supported in the given engine method version, or
101/// * The absence of a field that is required in the given engine method version
102#[derive(thiserror::Error, Debug)]
103pub enum VersionSpecificValidationError {
104/// Thrown if the pre-V3 `PayloadAttributes` or `ExecutionPayload` contains a parent beacon
105 /// block root
106#[error("parent beacon block root not supported before V3")]
107ParentBeaconBlockRootNotSupportedBeforeV3,
108/// Thrown if `engine_forkchoiceUpdatedV1` or `engine_newPayloadV1` contains withdrawals
109#[error("withdrawals not supported in V1")]
110WithdrawalsNotSupportedInV1,
111/// Thrown if `engine_forkchoiceUpdated` or `engine_newPayload` contains no withdrawals after
112 /// Shanghai
113#[error("no withdrawals post-Shanghai")]
114NoWithdrawalsPostShanghai,
115/// Thrown if `engine_forkchoiceUpdated` or `engine_newPayload` contains withdrawals before
116 /// Shanghai
117#[error("withdrawals pre-Shanghai")]
118HasWithdrawalsPreShanghai,
119/// Thrown if the `PayloadAttributes` or `ExecutionPayload` contains no parent beacon block
120 /// root after Cancun
121#[error("no parent beacon block root post-cancun")]
122NoParentBeaconBlockRootPostCancun,
123}
124125/// Error validating payload received over `newPayload` API.
126#[derive(thiserror::Error, Debug)]
127pub enum NewPayloadError {
128/// Payload validation error.
129#[error(transparent)]
130Eth(#[from] PayloadError),
131/// Custom payload validation error.
132#[error(transparent)]
133Other(Box<dyn error::Error + Send + Sync>),
134}
135136impl NewPayloadError {
137/// Creates instance of variant [`NewPayloadError::Other`].
138#[inline]
139pub fn other(err: impl error::Error + Send + Sync + 'static) -> Self {
140Self::Other(Box::new(err))
141 }
142}
143144impl NewPayloadError {
145/// Returns `true` if the error is caused by a block hash mismatch.
146#[inline]
147pub const fn is_block_hash_mismatch(&self) -> bool {
148matches!(self, Self::Eth(PayloadError::BlockHash { .. }))
149 }
150151/// Returns `true` if the error is caused by invalid block hashes (Cancun).
152#[inline]
153pub const fn is_invalid_versioned_hashes(&self) -> bool {
154matches!(self, Self::Eth(PayloadError::InvalidVersionedHashes))
155 }
156}
157158impl From<NewPayloadError> for PayloadStatusEnum {
159fn from(error: NewPayloadError) -> Self {
160Self::Invalid { validation_error: error.to_string() }
161 }
162}
163164impl EngineObjectValidationError {
165/// Creates an instance of the `InvalidParams` variant with the given error.
166pub fn invalid_params<E>(error: E) -> Self
167where
168E: core::error::Error + Send + Sync + 'static,
169 {
170Self::InvalidParams(Box::new(error))
171 }
172}
173174/// Thrown when validating the correctness of a payloadattributes object.
175#[derive(thiserror::Error, Debug)]
176pub enum InvalidPayloadAttributesError {
177/// Thrown if the timestamp of the payload attributes is invalid according to the engine specs.
178#[error("parent beacon block root not supported before V3")]
179InvalidTimestamp,
180/// Another type of error that is not covered by the above variants.
181#[error("Invalid params: {0}")]
182InvalidParams(#[from] Box<dyn core::error::Error + Send + Sync>),
183}
184185impl From<InvalidPayloadAttributesError> for ForkchoiceUpdateError {
186fn from(_: InvalidPayloadAttributesError) -> Self {
187Self::UpdatedInvalidPayloadAttributes
188 }
189}