fix(rpc): return -32602 for PayloadAttributes structure validation errors (#22374)

Co-authored-by: yongkangc <chiayongkang@hotmail.com>
This commit is contained in:
Emma Jamieson-Hoare
2026-02-19 12:32:31 +00:00
committed by GitHub
parent 6552a3a9ab
commit cd6e895a97

View File

@@ -14,8 +14,6 @@ use thiserror::Error;
/// The Engine API result type
pub type EngineApiResult<Ok> = Result<Ok, EngineApiError>;
/// Invalid payload attributes code.
pub const INVALID_PAYLOAD_ATTRIBUTES: i32 = -38003;
/// Payload unsupported fork code.
pub const UNSUPPORTED_FORK_CODE: i32 = -38005;
/// Payload unknown error code.
@@ -26,9 +24,6 @@ pub const REQUEST_TOO_LARGE_CODE: i32 = -38004;
/// Error message for the request too large error.
const REQUEST_TOO_LARGE_MESSAGE: &str = "Too large request";
/// Error message for the request too large error.
const INVALID_PAYLOAD_ATTRIBUTES_MSG: &str = "Invalid payload attributes";
/// Error returned by [`EngineApi`][crate::EngineApi]
///
/// Note: This is a high-fidelity error type which can be converted to an RPC error that adheres to
@@ -120,7 +115,13 @@ impl From<EngineApiError> for jsonrpsee_types::error::ErrorObject<'static> {
EngineApiError::InvalidBodiesRange { .. } |
EngineApiError::EngineObjectValidationError(
EngineObjectValidationError::Payload(_) |
EngineObjectValidationError::InvalidParams(_),
EngineObjectValidationError::InvalidParams(_) |
// Per Engine API spec, structure validation errors for PayloadAttributes
// (e.g., missing withdrawals post-Shanghai, missing parentBeaconBlockRoot
// post-Cancun) should return -32602 "Invalid params", not -38003.
// See: https://github.com/ethereum/execution-apis/blob/main/src/engine/shanghai.md
// Fixes: https://github.com/paradigmxyz/reth/issues/8732
EngineObjectValidationError::PayloadAttributes(_),
) |
EngineApiError::UnexpectedRequestsHash => {
// Note: the data field is not required by the spec, but is also included by other
@@ -131,17 +132,6 @@ impl From<EngineApiError> for jsonrpsee_types::error::ErrorObject<'static> {
Some(ErrorData::new(error)),
)
}
EngineApiError::EngineObjectValidationError(
EngineObjectValidationError::PayloadAttributes(_),
) => {
// Note: the data field is not required by the spec, but is also included by other
// clients
jsonrpsee_types::error::ErrorObject::owned(
INVALID_PAYLOAD_ATTRIBUTES,
INVALID_PAYLOAD_ATTRIBUTES_MSG,
Some(ErrorData::new(error)),
)
}
EngineApiError::UnknownPayload => jsonrpsee_types::error::ErrorObject::owned(
UNKNOWN_PAYLOAD_CODE,
error.to_string(),
@@ -208,6 +198,7 @@ impl From<EngineApiError> for jsonrpsee_types::error::ErrorObject<'static> {
mod tests {
use super::*;
use alloy_rpc_types_engine::ForkchoiceUpdateError;
use reth_payload_primitives::VersionSpecificValidationError;
#[track_caller]
fn ensure_engine_rpc_error(
@@ -246,6 +237,8 @@ mod tests {
)),
);
// ForkchoiceUpdateError::UpdatedInvalidPayloadAttributes is for semantic validation
// errors that occur AFTER the structure check passes, so it returns -38003
ensure_engine_rpc_error(
-38003,
"Invalid payload attributes",
@@ -259,5 +252,18 @@ mod tests {
"Unknown payload",
EngineApiError::UnknownPayload,
);
// PayloadAttributes structure validation errors (e.g., missing withdrawals post-Shanghai)
// should return -32602 per the Engine API spec
// See: https://github.com/paradigmxyz/reth/issues/8732
ensure_engine_rpc_error(
INVALID_PARAMS_CODE,
INVALID_PARAMS_MSG,
EngineApiError::EngineObjectValidationError(
EngineObjectValidationError::PayloadAttributes(
VersionSpecificValidationError::NoWithdrawalsPostShanghai,
),
),
);
}
}