diff --git a/Cargo.lock b/Cargo.lock index 6ffd0d88e..50c1e48ff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5137,6 +5137,8 @@ version = "0.1.0" dependencies = [ "assert_matches", "futures", + "jsonrpsee-core", + "jsonrpsee-types", "reth-beacon-consensus", "reth-interfaces", "reth-primitives", diff --git a/crates/consensus/beacon/src/engine/mod.rs b/crates/consensus/beacon/src/engine/mod.rs index 97f1c1041..5a18a14d1 100644 --- a/crates/consensus/beacon/src/engine/mod.rs +++ b/crates/consensus/beacon/src/engine/mod.rs @@ -186,10 +186,10 @@ where /// When the Consensus layer receives a new block via the consensus gossip protocol, /// the transactions in the block are sent to the execution layer in the form of a - /// `ExecutionPayload`. The Execution layer executes the transactions and validates the + /// [`ExecutionPayload`]. The Execution layer executes the transactions and validates the /// state in the block header, then passes validation data back to Consensus layer, that /// adds the block to the head of its own blockchain and attests to it. The block is then - /// broadcasted over the consensus p2p network in the form of a "Beacon block". + /// broadcast over the consensus p2p network in the form of a "Beacon block". /// /// These responses should adhere to the [Engine API Spec for /// `engine_newPayload`](https://github.com/ethereum/execution-apis/blob/main/src/engine/paris.md#specification). diff --git a/crates/rpc/rpc-engine-api/Cargo.toml b/crates/rpc/rpc-engine-api/Cargo.toml index c289093b0..67bcb17e9 100644 --- a/crates/rpc/rpc-engine-api/Cargo.toml +++ b/crates/rpc/rpc-engine-api/Cargo.toml @@ -21,6 +21,8 @@ tokio-stream = "0.1" # misc thiserror = "1.0.37" +jsonrpsee-types = "0.16" +jsonrpsee-core = "0.16" [dev-dependencies] reth-interfaces = { path = "../../interfaces", features = ["test-utils"] } diff --git a/crates/rpc/rpc-engine-api/src/engine_api.rs b/crates/rpc/rpc-engine-api/src/engine_api.rs index 26827bea6..2085f73ea 100644 --- a/crates/rpc/rpc-engine-api/src/engine_api.rs +++ b/crates/rpc/rpc-engine-api/src/engine_api.rs @@ -98,7 +98,7 @@ impl), } + +impl From for jsonrpsee_types::error::CallError { + fn from(error: EngineApiError) -> Self { + let code = match error { + EngineApiError::InvalidBodiesRange { .. } | + EngineApiError::WithdrawalsNotSupportedInV1 | + EngineApiError::NoWithdrawalsPostShanghai | + EngineApiError::HasWithdrawalsPreShanghai => INVALID_PARAMS_CODE, + EngineApiError::PayloadUnknown => UNKNOWN_PAYLOAD_CODE, + EngineApiError::PayloadRequestTooLarge { .. } => REQUEST_TOO_LARGE_CODE, + // Any other server error + _ => INTERNAL_ERROR_CODE, + }; + jsonrpsee_types::error::CallError::Custom(jsonrpsee_types::error::ErrorObject::owned( + code, + error.to_string(), + None::<()>, + )) + } +} + +impl From for jsonrpsee_core::error::Error { + fn from(error: EngineApiError) -> Self { + jsonrpsee_types::error::CallError::from(error).into() + } +} diff --git a/crates/rpc/rpc/src/engine.rs b/crates/rpc/rpc/src/engine.rs index d2a555b10..025b5d685 100644 --- a/crates/rpc/rpc/src/engine.rs +++ b/crates/rpc/rpc/src/engine.rs @@ -1,15 +1,10 @@ -use crate::result::rpc_err; use async_trait::async_trait; -use jsonrpsee::{ - core::{Error, RpcResult as Result}, - types::error::INVALID_PARAMS_CODE, -}; +use jsonrpsee::core::{Error, RpcResult as Result}; use reth_interfaces::consensus::ForkchoiceState; use reth_primitives::{BlockHash, ChainSpec, Hardfork, H64, U64}; use reth_rpc_api::EngineApiServer; use reth_rpc_engine_api::{ EngineApiError, EngineApiHandle, EngineApiMessage, EngineApiMessageVersion, EngineApiResult, - REQUEST_TOO_LARGE_CODE, UNKNOWN_PAYLOAD_CODE, }; use reth_rpc_types::engine::{ ExecutionPayload, ExecutionPayloadBodies, ForkchoiceUpdated, PayloadAttributes, PayloadStatus, @@ -18,18 +13,6 @@ use reth_rpc_types::engine::{ use std::sync::Arc; use tokio::sync::oneshot::{self, Receiver}; -fn to_rpc_error>(error: E) -> Error { - let error = error.into(); - let code = match error { - EngineApiError::InvalidParams => INVALID_PARAMS_CODE, - EngineApiError::PayloadUnknown => UNKNOWN_PAYLOAD_CODE, - EngineApiError::PayloadRequestTooLarge { .. } => REQUEST_TOO_LARGE_CODE, - // Any other server error - _ => jsonrpsee::types::error::INTERNAL_ERROR_CODE, - }; - rpc_err(code, error.to_string(), None) -} - /// The server implementation of Engine API pub struct EngineApi { /// Chain spec @@ -65,15 +48,19 @@ impl EngineApi { match version { EngineApiMessageVersion::V1 => { - if is_shanghai || has_withdrawals { - return Err(EngineApiError::InvalidParams) + if has_withdrawals { + return Err(EngineApiError::WithdrawalsNotSupportedInV1) + } + if is_shanghai { + return Err(EngineApiError::NoWithdrawalsPostShanghai) } } EngineApiMessageVersion::V2 => { - let shanghai_with_no_withdrawals = is_shanghai && !has_withdrawals; - let not_shanghai_with_withdrawals = !is_shanghai && has_withdrawals; - if shanghai_with_no_withdrawals || not_shanghai_with_withdrawals { - return Err(EngineApiError::InvalidParams) + if is_shanghai && !has_withdrawals { + return Err(EngineApiError::NoWithdrawalsPostShanghai) + } + if !is_shanghai && has_withdrawals { + return Err(EngineApiError::HasWithdrawalsPreShanghai) } } }; @@ -87,13 +74,13 @@ impl EngineApi { rx: Receiver>, ) -> Result { let _ = self.engine_tx.send(msg); - rx.await.map_err(|err| Error::Custom(err.to_string()))?.map_err(|err| to_rpc_error(err)) + Ok(rx.await.map_err(|err| Error::Custom(err.to_string()))?.map_err(Into::into)?) } } #[async_trait] impl EngineApiServer for EngineApi { - /// Handler for `engine_getPayloadV1` + /// Handler for `engine_newPayloadV1` /// See also /// Caution: This should not accept the `withdrawals` field async fn new_payload_v1(&self, payload: ExecutionPayload) -> Result { @@ -101,21 +88,19 @@ impl EngineApiServer for EngineApi { EngineApiMessageVersion::V1, payload.timestamp.as_u64(), payload.withdrawals.is_some(), - ) - .map_err(to_rpc_error)?; + )?; let (tx, rx) = oneshot::channel(); self.delegate_request(EngineApiMessage::NewPayload(payload, tx), rx).await } - /// Handler for `engine_getPayloadV2` + /// Handler for `engine_newPayloadV1` /// See also async fn new_payload_v2(&self, payload: ExecutionPayload) -> Result { self.validate_withdrawals_presence( EngineApiMessageVersion::V2, payload.timestamp.as_u64(), payload.withdrawals.is_some(), - ) - .map_err(to_rpc_error)?; + )?; let (tx, rx) = oneshot::channel(); self.delegate_request(EngineApiMessage::NewPayload(payload, tx), rx).await } @@ -134,8 +119,7 @@ impl EngineApiServer for EngineApi { EngineApiMessageVersion::V1, attrs.timestamp.as_u64(), attrs.withdrawals.is_some(), - ) - .map_err(to_rpc_error)?; + )?; } let (tx, rx) = oneshot::channel(); self.delegate_request( @@ -157,8 +141,7 @@ impl EngineApiServer for EngineApi { EngineApiMessageVersion::V2, attrs.timestamp.as_u64(), attrs.withdrawals.is_some(), - ) - .map_err(to_rpc_error)?; + )?; } let (tx, rx) = oneshot::channel(); self.delegate_request(