Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 34 additions & 15 deletions crates/rpc/rpc-api/src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ use alloy_eips::{
use alloy_json_rpc::RpcObject;
use alloy_primitives::{Address, BlockHash, Bytes, B256, U256, U64};
use alloy_rpc_types_engine::{
ClientVersionV1, ExecutionPayloadBodiesV1, ExecutionPayloadInputV2, ExecutionPayloadV1,
ExecutionPayloadV3, ExecutionPayloadV4, ForkchoiceState, ForkchoiceUpdated, PayloadId,
PayloadStatus,
ClientVersionV1, ExecutionPayloadBodiesV1, ExecutionPayloadBodiesV2, ExecutionPayloadInputV2,
ExecutionPayloadV1, ExecutionPayloadV3, ExecutionPayloadV4, ForkchoiceState, ForkchoiceUpdated,
PayloadId, PayloadStatus,
};
use alloy_rpc_types_eth::{
state::StateOverride, BlockOverrides, EIP1186AccountProofResponse, Filter, Log, SyncStatus,
Expand Down Expand Up @@ -211,6 +211,17 @@ pub trait EngineApi<Engine: EngineTypes> {
block_hashes: Vec<BlockHash>,
) -> RpcResult<ExecutionPayloadBodiesV1>;

/// Returns `ExecutionPayloadBodyV2` objects for the given block hashes.
///
/// V2 includes the `block_access_list` field for EIP-7928 BAL support.
///
/// See also <https://eips.ethereum.org/EIPS/eip-7928>
#[method(name = "getPayloadBodiesByHashV2")]
async fn get_payload_bodies_by_hash_v2(
&self,
block_hashes: Vec<BlockHash>,
) -> RpcResult<ExecutionPayloadBodiesV2>;

/// See also <https://github.com/ethereum/execution-apis/blob/6452a6b194d7db269bf1dbd087a267251d3cc7f8/src/engine/shanghai.md#engine_getpayloadbodiesbyrangev1>
///
/// Returns the execution payload bodies by the range starting at `start`, containing `count`
Expand All @@ -230,6 +241,26 @@ pub trait EngineApi<Engine: EngineTypes> {
count: U64,
) -> RpcResult<ExecutionPayloadBodiesV1>;

/// Returns `ExecutionPayloadBodyV2` objects for the given block range.
///
/// V2 includes the `block_access_list` field for EIP-7928 BAL support.
///
/// WARNING: This method is associated with the `BeaconBlocksByRange` message in the consensus
/// layer p2p specification, meaning the input should be treated as untrusted or potentially
/// adversarial.
///
/// Implementers should take care when acting on the input to this method, specifically
/// ensuring that the range is limited properly, and that the range boundaries are computed
/// correctly and without panics.
///
/// See also <https://eips.ethereum.org/EIPS/eip-7928>
#[method(name = "getPayloadBodiesByRangeV2")]
async fn get_payload_bodies_by_range_v2(
&self,
start: U64,
count: U64,
) -> RpcResult<ExecutionPayloadBodiesV2>;

/// This function will return the [`ClientVersionV1`] object.
/// See also:
/// <https://github.com/ethereum/execution-apis/blob/03911ffc053b8b806123f1fc237184b0092a485a/src/engine/identification.md#engine_getclientversionv1>
Expand Down Expand Up @@ -278,18 +309,6 @@ pub trait EngineApi<Engine: EngineTypes> {
&self,
versioned_hashes: Vec<B256>,
) -> RpcResult<Option<Vec<Option<BlobAndProofV2>>>>;

/// Returns the Block Access Lists for the given block hashes.
///
/// See also <https://eips.ethereum.org/EIPS/eip-7928>
#[method(name = "getBALsByHashV1")]
async fn get_bals_by_hash_v1(&self, block_hashes: Vec<BlockHash>) -> RpcResult<Vec<Bytes>>;

/// Returns the Block Access Lists for the given block range.
///
/// See also <https://eips.ethereum.org/EIPS/eip-7928>
#[method(name = "getBALsByRangeV1")]
async fn get_bals_by_range_v1(&self, start: U64, count: U64) -> RpcResult<Vec<Bytes>>;
}

/// A subset of the ETH rpc interface: <https://ethereum.github.io/execution-apis/api-documentation>
Expand Down
2 changes: 2 additions & 0 deletions crates/rpc/rpc-engine-api/src/capabilities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ pub const CAPABILITIES: &[&str] = &[
"engine_newPayloadV3",
"engine_newPayloadV4",
"engine_getPayloadBodiesByHashV1",
"engine_getPayloadBodiesByHashV2",
"engine_getPayloadBodiesByRangeV1",
"engine_getPayloadBodiesByRangeV2",
"engine_getBlobsV1",
"engine_getBlobsV2",
"engine_getBlobsV3",
Expand Down
115 changes: 85 additions & 30 deletions crates/rpc/rpc-engine-api/src/engine_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ use alloy_eips::{
use alloy_primitives::{BlockHash, BlockNumber, B256, U64};
use alloy_rpc_types_engine::{
CancunPayloadFields, ClientVersionV1, ExecutionData, ExecutionPayloadBodiesV1,
ExecutionPayloadBodyV1, ExecutionPayloadInputV2, ExecutionPayloadSidecar, ExecutionPayloadV1,
ExecutionPayloadV3, ExecutionPayloadV4, ForkchoiceState, ForkchoiceUpdated, PayloadId,
PayloadStatus, PraguePayloadFields,
ExecutionPayloadBodiesV2, ExecutionPayloadBodyV1, ExecutionPayloadBodyV2,
ExecutionPayloadInputV2, ExecutionPayloadSidecar, ExecutionPayloadV1, ExecutionPayloadV3,
ExecutionPayloadV4, ForkchoiceState, ForkchoiceUpdated, PayloadId, PayloadStatus,
PraguePayloadFields,
};
use async_trait::async_trait;
use jsonrpsee_core::{server::RpcModule, RpcResult};
Expand Down Expand Up @@ -612,6 +613,34 @@ where
res
}

/// Returns the execution payload bodies by the range (V2).
///
/// V2 includes the `block_access_list` field for EIP-7928 BAL support.
pub async fn get_payload_bodies_by_range_v2(
&self,
start: BlockNumber,
count: u64,
) -> EngineApiResult<ExecutionPayloadBodiesV2> {
self.get_payload_bodies_by_range_with(start, count, |block| ExecutionPayloadBodyV2 {
transactions: block.body().encoded_2718_transactions(),
withdrawals: block.body().withdrawals().cloned().map(Withdrawals::into_inner),
block_access_list: None,
})
.await
}

/// Metrics version of `get_payload_bodies_by_range_v2`
pub async fn get_payload_bodies_by_range_v2_metered(
&self,
start: BlockNumber,
count: u64,
) -> EngineApiResult<ExecutionPayloadBodiesV2> {
let start_time = Instant::now();
let res = Self::get_payload_bodies_by_range_v2(self, start, count).await;
self.inner.metrics.latency.get_payload_bodies_by_range_v2.record(start_time.elapsed());
res
}

/// Called to retrieve execution payload bodies by hashes.
pub async fn get_payload_bodies_by_hash_with<F, R>(
&self,
Expand Down Expand Up @@ -673,6 +702,32 @@ where
res
}

/// Called to retrieve execution payload bodies by hashes (V2).
///
/// V2 includes the `block_access_list` field for EIP-7928 BAL support.
pub async fn get_payload_bodies_by_hash_v2(
&self,
hashes: Vec<BlockHash>,
) -> EngineApiResult<ExecutionPayloadBodiesV2> {
self.get_payload_bodies_by_hash_with(hashes, |block| ExecutionPayloadBodyV2 {
transactions: block.body().encoded_2718_transactions(),
withdrawals: block.body().withdrawals().cloned().map(Withdrawals::into_inner),
block_access_list: None,
})
.await
}

/// Metrics version of `get_payload_bodies_by_hash_v2`
pub async fn get_payload_bodies_by_hash_v2_metered(
&self,
hashes: Vec<BlockHash>,
) -> EngineApiResult<ExecutionPayloadBodiesV2> {
let start = Instant::now();
let res = Self::get_payload_bodies_by_hash_v2(self, hashes).await;
self.inner.metrics.latency.get_payload_bodies_by_hash_v2.record(start.elapsed());
res
}

/// Validates the `engine_forkchoiceUpdated` payload attributes and executes the forkchoice
/// update.
///
Expand Down Expand Up @@ -1129,6 +1184,19 @@ where
Ok(self.get_payload_bodies_by_hash_v1_metered(block_hashes).await?)
}

/// Handler for `engine_getPayloadBodiesByHashV2`
///
/// V2 includes the `block_access_list` field for EIP-7928 BAL support.
///
/// See also <https://eips.ethereum.org/EIPS/eip-7928>
async fn get_payload_bodies_by_hash_v2(
&self,
block_hashes: Vec<BlockHash>,
) -> RpcResult<ExecutionPayloadBodiesV2> {
trace!(target: "rpc::engine", "Serving engine_getPayloadBodiesByHashV2");
Ok(self.get_payload_bodies_by_hash_v2_metered(block_hashes).await?)
}

/// Handler for `engine_getPayloadBodiesByRangeV1`
///
/// See also <https://github.com/ethereum/execution-apis/blob/6452a6b194d7db269bf1dbd087a267251d3cc7f8/src/engine/shanghai.md#engine_getpayloadbodiesbyrangev1>
Expand All @@ -1154,6 +1222,20 @@ where
Ok(self.get_payload_bodies_by_range_v1_metered(start.to(), count.to()).await?)
}

/// Handler for `engine_getPayloadBodiesByRangeV2`
///
/// V2 includes the `block_access_list` field for EIP-7928 BAL support.
///
/// See also <https://eips.ethereum.org/EIPS/eip-7928>
async fn get_payload_bodies_by_range_v2(
&self,
start: U64,
count: U64,
) -> RpcResult<ExecutionPayloadBodiesV2> {
trace!(target: "rpc::engine", "Serving engine_getPayloadBodiesByRangeV2");
Ok(self.get_payload_bodies_by_range_v2_metered(start.to(), count.to()).await?)
}

/// Handler for `engine_getClientVersionV1`
///
/// See also <https://github.com/ethereum/execution-apis/blob/03911ffc053b8b806123f1fc237184b0092a485a/src/engine/identification.md>
Expand Down Expand Up @@ -1199,33 +1281,6 @@ where
trace!(target: "rpc::engine", "Serving engine_getBlobsV3");
Ok(self.get_blobs_v3_metered(versioned_hashes)?)
}

/// Handler for `engine_getBALsByHashV1`
///
/// See also <https://eips.ethereum.org/EIPS/eip-7928>
async fn get_bals_by_hash_v1(
&self,
_block_hashes: Vec<BlockHash>,
) -> RpcResult<Vec<alloy_primitives::Bytes>> {
trace!(target: "rpc::engine", "Serving engine_getBALsByHashV1");
Err(EngineApiError::EngineObjectValidationError(
reth_payload_primitives::EngineObjectValidationError::UnsupportedFork,
))?
}

/// Handler for `engine_getBALsByRangeV1`
///
/// See also <https://eips.ethereum.org/EIPS/eip-7928>
async fn get_bals_by_range_v1(
&self,
_start: U64,
_count: U64,
) -> RpcResult<Vec<alloy_primitives::Bytes>> {
trace!(target: "rpc::engine", "Serving engine_getBALsByRangeV1");
Err(EngineApiError::EngineObjectValidationError(
reth_payload_primitives::EngineObjectValidationError::UnsupportedFork,
))?
}
}

impl<Provider, EngineT, Pool, Validator, ChainSpec> IntoEngineApiRpcModule
Expand Down
4 changes: 4 additions & 0 deletions crates/rpc/rpc-engine-api/src/metrics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,12 @@ pub(crate) struct EngineApiLatencyMetrics {
pub(crate) get_payload_v5: Histogram,
/// Latency for `engine_getPayloadBodiesByRangeV1`
pub(crate) get_payload_bodies_by_range_v1: Histogram,
/// Latency for `engine_getPayloadBodiesByRangeV2`
pub(crate) get_payload_bodies_by_range_v2: Histogram,
/// Latency for `engine_getPayloadBodiesByHashV1`
pub(crate) get_payload_bodies_by_hash_v1: Histogram,
/// Latency for `engine_getPayloadBodiesByHashV2`
pub(crate) get_payload_bodies_by_hash_v2: Histogram,
/// Latency for `engine_getBlobsV1`
pub(crate) get_blobs_v1: Histogram,
/// Latency for `engine_getBlobsV2`
Expand Down
Loading