From 7fc22f7b5bccc4996cd1edb85cd2324ca4df848b Mon Sep 17 00:00:00 2001 From: Georgios Konstantopoulos Date: Tue, 24 Feb 2026 07:46:02 -0800 Subject: [PATCH] feat(rpc): accept RLP-encoded blocks in reth_newPayload (#22533) Co-authored-by: Amp Co-authored-by: Arsenii Kulikov --- crates/rpc/rpc-api/src/lib.rs | 2 +- crates/rpc/rpc-api/src/reth_engine.rs | 25 ++++++++++++++++--- crates/rpc/rpc-engine-api/Cargo.toml | 1 + .../rpc/rpc-engine-api/src/reth_engine_api.rs | 22 ++++++++++++---- 4 files changed, 40 insertions(+), 10 deletions(-) diff --git a/crates/rpc/rpc-api/src/lib.rs b/crates/rpc/rpc-api/src/lib.rs index 964437012b..13ca617b46 100644 --- a/crates/rpc/rpc-api/src/lib.rs +++ b/crates/rpc/rpc-api/src/lib.rs @@ -48,7 +48,7 @@ pub mod servers { net::NetApiServer, otterscan::OtterscanServer, reth::RethApiServer, - reth_engine::{RethEngineApiServer, RethPayloadStatus}, + reth_engine::{RethEngineApiServer, RethNewPayloadInput, RethPayloadStatus}, rpc::RpcApiServer, testing::TestingApiServer, trace::TraceApiServer, diff --git a/crates/rpc/rpc-api/src/reth_engine.rs b/crates/rpc/rpc-api/src/reth_engine.rs index 6baa881c43..1704dc8f4d 100644 --- a/crates/rpc/rpc-api/src/reth_engine.rs +++ b/crates/rpc/rpc-api/src/reth_engine.rs @@ -1,5 +1,6 @@ //! Reth-specific engine API extensions. +use alloy_primitives::Bytes; use alloy_rpc_types_engine::PayloadStatus; use jsonrpsee::{core::RpcResult, proc_macros::rpc}; use serde::{Deserialize, Serialize}; @@ -22,18 +23,34 @@ pub struct RethPayloadStatus { pub sparse_trie_wait_us: u64, } +/// Input for `reth_newPayload` that accepts either `ExecutionData` directly or an RLP-encoded +/// block. +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum RethNewPayloadInput { + /// Standard execution data (payload + sidecar). + ExecutionData(ExecutionData), + /// An RLP-encoded block. + BlockRlp(Bytes), +} + /// Reth-specific engine API extensions. /// -/// This trait provides a `reth_newPayload` endpoint that takes `ExecutionData` directly -/// (payload + sidecar), waiting for persistence and cache locks before processing. +/// This trait provides a `reth_newPayload` endpoint that accepts either `ExecutionData` directly +/// (payload + sidecar) or an RLP-encoded block, waiting for persistence and cache locks before +/// processing. /// /// Responses include timing breakdowns with server-measured execution latency. #[cfg_attr(not(feature = "client"), rpc(server, namespace = "reth"))] #[cfg_attr(feature = "client", rpc(server, client, namespace = "reth"))] pub trait RethEngineApi { - /// Reth-specific newPayload that takes `ExecutionData` directly. + /// Reth-specific newPayload that accepts either `ExecutionData` directly or an RLP-encoded + /// block. /// /// Waits for persistence, execution cache, and sparse trie locks before processing. #[method(name = "newPayload")] - async fn reth_new_payload(&self, payload: ExecutionData) -> RpcResult; + async fn reth_new_payload( + &self, + payload: RethNewPayloadInput, + ) -> RpcResult; } diff --git a/crates/rpc/rpc-engine-api/Cargo.toml b/crates/rpc/rpc-engine-api/Cargo.toml index ba5d85977b..f73a48e821 100644 --- a/crates/rpc/rpc-engine-api/Cargo.toml +++ b/crates/rpc/rpc-engine-api/Cargo.toml @@ -28,6 +28,7 @@ reth-network-api.workspace = true # ethereum alloy-eips.workspace = true alloy-primitives.workspace = true +alloy-rlp.workspace = true alloy-rpc-types-engine.workspace = true # async diff --git a/crates/rpc/rpc-engine-api/src/reth_engine_api.rs b/crates/rpc/rpc-engine-api/src/reth_engine_api.rs index 1b65410ea5..db96d33b12 100644 --- a/crates/rpc/rpc-engine-api/src/reth_engine_api.rs +++ b/crates/rpc/rpc-engine-api/src/reth_engine_api.rs @@ -1,16 +1,18 @@ use crate::EngineApiError; +use alloy_rlp::Decodable; use async_trait::async_trait; use jsonrpsee_core::RpcResult; use reth_engine_primitives::ConsensusEngineHandle; use reth_payload_primitives::PayloadTypes; -use reth_rpc_api::{RethEngineApiServer, RethPayloadStatus}; +use reth_primitives_traits::SealedBlock; +use reth_rpc_api::{RethEngineApiServer, RethNewPayloadInput, RethPayloadStatus}; use tracing::trace; /// Standalone implementation of the `reth_` engine API namespace. /// -/// Provides the `reth_newPayload` endpoint that takes `ExecutionData` directly, -/// waits for persistence, execution cache, and sparse trie locks before processing, -/// and returns timing breakdowns with server-measured execution latency. +/// Provides the `reth_newPayload` endpoint that accepts either `ExecutionData` directly or an +/// RLP-encoded block, waits for persistence, execution cache, and sparse trie locks before +/// processing, and returns timing breakdowns with server-measured execution latency. #[derive(Debug)] pub struct RethEngineApi { beacon_engine_handle: ConsensusEngineHandle, @@ -27,9 +29,19 @@ impl RethEngineApi { impl RethEngineApiServer for RethEngineApi { async fn reth_new_payload( &self, - payload: Payload::ExecutionData, + input: RethNewPayloadInput, ) -> RpcResult { trace!(target: "rpc::engine", "Serving reth_newPayload"); + + let payload = match input { + RethNewPayloadInput::ExecutionData(data) => data, + RethNewPayloadInput::BlockRlp(rlp) => { + let block = Decodable::decode(&mut rlp.as_ref()) + .map_err(|err| EngineApiError::Internal(Box::new(err)))?; + Payload::block_to_payload(SealedBlock::new_unhashed(block)) + } + }; + let (status, timings) = self .beacon_engine_handle .reth_new_payload(payload)