reth_payload_primitives/
error.rs

1//! Error types emitted by types or implementations of this crate.
2
3use alloy_primitives::B256;
4use alloy_rpc_types_engine::ForkchoiceUpdateError;
5use reth_errors::{ProviderError, RethError};
6use revm_primitives::EVMError;
7use tokio::sync::oneshot;
8
9/// Possible error variants during payload building.
10#[derive(Debug, thiserror::Error)]
11pub enum PayloadBuilderError {
12    /// Thrown when the parent header cannot be found
13    #[error("missing parent header: {0}")]
14    MissingParentHeader(B256),
15    /// Thrown when the parent block is missing.
16    #[error("missing parent block {0}")]
17    MissingParentBlock(B256),
18    /// An oneshot channels has been closed.
19    #[error("sender has been dropped")]
20    ChannelClosed,
21    /// If there's no payload to resolve.
22    #[error("missing payload")]
23    MissingPayload,
24    /// Other internal error
25    #[error(transparent)]
26    Internal(#[from] RethError),
27    /// Unrecoverable error during evm execution.
28    #[error("evm execution error: {0}")]
29    EvmExecutionError(EVMError<ProviderError>),
30    /// Any other payload building errors.
31    #[error(transparent)]
32    Other(Box<dyn core::error::Error + Send + Sync>),
33}
34
35impl PayloadBuilderError {
36    /// Create a new error from a boxed error.
37    pub fn other<E>(error: E) -> Self
38    where
39        E: core::error::Error + Send + Sync + 'static,
40    {
41        Self::Other(Box::new(error))
42    }
43}
44
45impl From<ProviderError> for PayloadBuilderError {
46    fn from(error: ProviderError) -> Self {
47        Self::Internal(RethError::Provider(error))
48    }
49}
50
51impl From<oneshot::error::RecvError> for PayloadBuilderError {
52    fn from(_: oneshot::error::RecvError) -> Self {
53        Self::ChannelClosed
54    }
55}
56
57/// Thrown when the payload or attributes are known to be invalid __before__ processing.
58///
59/// This is used mainly for
60/// [`validate_version_specific_fields`](crate::validate_version_specific_fields), which validates
61/// both execution payloads and forkchoice update attributes with respect to a method version.
62#[derive(thiserror::Error, Debug)]
63pub enum EngineObjectValidationError {
64    /// Thrown when the underlying validation error occurred while validating an
65    /// `ExecutionPayload`.
66    #[error("Payload validation error: {0}")]
67    Payload(VersionSpecificValidationError),
68
69    /// Thrown when the underlying validation error occurred while validating a
70    /// `PayloadAttributes`.
71    #[error("Payload attributes validation error: {0}")]
72    PayloadAttributes(VersionSpecificValidationError),
73
74    /// Thrown if `PayloadAttributes` or `ExecutionPayload` were provided with a timestamp, but the
75    /// version of the engine method called is meant for a fork that occurs after the provided
76    /// timestamp.
77    #[error("Unsupported fork")]
78    UnsupportedFork,
79    /// Another type of error that is not covered by the above variants.
80    #[error("Invalid params: {0}")]
81    InvalidParams(#[from] Box<dyn core::error::Error + Send + Sync>),
82}
83
84/// Thrown when validating an execution payload OR payload attributes fails due to:
85/// * The existence of a new field that is not supported in the given engine method version, or
86/// * The absence of a field that is required in the given engine method version
87#[derive(thiserror::Error, Debug)]
88pub enum VersionSpecificValidationError {
89    /// Thrown if the pre-V3 `PayloadAttributes` or `ExecutionPayload` contains a parent beacon
90    /// block root
91    #[error("parent beacon block root not supported before V3")]
92    ParentBeaconBlockRootNotSupportedBeforeV3,
93    /// Thrown if `engine_forkchoiceUpdatedV1` or `engine_newPayloadV1` contains withdrawals
94    #[error("withdrawals not supported in V1")]
95    WithdrawalsNotSupportedInV1,
96    /// Thrown if `engine_forkchoiceUpdated` or `engine_newPayload` contains no withdrawals after
97    /// Shanghai
98    #[error("no withdrawals post-Shanghai")]
99    NoWithdrawalsPostShanghai,
100    /// Thrown if `engine_forkchoiceUpdated` or `engine_newPayload` contains withdrawals before
101    /// Shanghai
102    #[error("withdrawals pre-Shanghai")]
103    HasWithdrawalsPreShanghai,
104    /// Thrown if the `PayloadAttributes` or `ExecutionPayload` contains no parent beacon block
105    /// root after Cancun
106    #[error("no parent beacon block root post-cancun")]
107    NoParentBeaconBlockRootPostCancun,
108}
109
110impl EngineObjectValidationError {
111    /// Creates an instance of the `InvalidParams` variant with the given error.
112    pub fn invalid_params<E>(error: E) -> Self
113    where
114        E: core::error::Error + Send + Sync + 'static,
115    {
116        Self::InvalidParams(Box::new(error))
117    }
118}
119
120/// Thrown when validating the correctness of a payloadattributes object.
121#[derive(thiserror::Error, Debug)]
122pub enum InvalidPayloadAttributesError {
123    /// Thrown if the timestamp of the payload attributes is invalid according to the engine specs.
124    #[error("parent beacon block root not supported before V3")]
125    InvalidTimestamp,
126    /// Another type of error that is not covered by the above variants.
127    #[error("Invalid params: {0}")]
128    InvalidParams(#[from] Box<dyn core::error::Error + Send + Sync>),
129}
130
131impl From<InvalidPayloadAttributesError> for ForkchoiceUpdateError {
132    fn from(_: InvalidPayloadAttributesError) -> Self {
133        Self::UpdatedInvalidPayloadAttributes
134    }
135}