From 40364d53216ab93b74651e577b4006566f8cb0a0 Mon Sep 17 00:00:00 2001 From: Yohann Kazoula Date: Sat, 22 Feb 2025 09:52:37 +0200 Subject: [PATCH] Relax EngineApi ExecutionData bounds (#14648) Co-authored-by: Matthias Seitz --- crates/rpc/rpc-engine-api/src/engine_api.rs | 367 ++++++++++---------- 1 file changed, 189 insertions(+), 178 deletions(-) diff --git a/crates/rpc/rpc-engine-api/src/engine_api.rs b/crates/rpc/rpc-engine-api/src/engine_api.rs index 8a860f80e068..41d12ba7329f 100644 --- a/crates/rpc/rpc-engine-api/src/engine_api.rs +++ b/crates/rpc/rpc-engine-api/src/engine_api.rs @@ -77,7 +77,7 @@ impl EngineApi where Provider: HeaderProvider + BlockReader + StateProviderFactory + 'static, - EngineT: EngineTypes, + EngineT: EngineTypes, Pool: TransactionPool + 'static, Validator: EngineValidator, ChainSpec: EthereumHardforks + Send + Sync + 'static, @@ -118,6 +118,7 @@ where ) -> EngineApiResult> { Ok(vec![self.inner.client.clone()]) } + /// Fetches the attributes for the payload with the given id. async fn get_payload_attributes( &self, @@ -131,183 +132,6 @@ where .ok_or(EngineApiError::UnknownPayload)??) } - /// See also - /// Caution: This should not accept the `withdrawals` field - pub async fn new_payload_v1( - &self, - payload: ExecutionPayloadV1, - ) -> EngineApiResult { - let payload = ExecutionPayload::from(payload); - let payload_or_attrs = - PayloadOrAttributes::<'_, EngineT::PayloadAttributes>::from_execution_payload( - &payload, None, - ); - self.inner - .validator - .validate_version_specific_fields(EngineApiMessageVersion::V1, payload_or_attrs)?; - - Ok(self - .inner - .beacon_consensus - .new_payload(ExecutionData { payload, sidecar: ExecutionPayloadSidecar::none() }) - .await - .inspect(|_| self.inner.on_new_payload_response())?) - } - - /// Metered version of `new_payload_v1`. - async fn new_payload_v1_metered( - &self, - payload: ExecutionPayloadV1, - ) -> EngineApiResult { - let start = Instant::now(); - let gas_used = payload.gas_used; - let res = Self::new_payload_v1(self, payload).await; - let elapsed = start.elapsed(); - self.inner.metrics.latency.new_payload_v1.record(elapsed); - self.inner.metrics.new_payload_response.update_response_metrics(&res, gas_used, elapsed); - res - } - - /// See also - pub async fn new_payload_v2( - &self, - payload: ExecutionPayloadInputV2, - ) -> EngineApiResult { - let payload = payload.into_payload(); - let payload_or_attrs = - PayloadOrAttributes::<'_, EngineT::PayloadAttributes>::from_execution_payload( - &payload, None, - ); - self.inner - .validator - .validate_version_specific_fields(EngineApiMessageVersion::V2, payload_or_attrs)?; - Ok(self - .inner - .beacon_consensus - .new_payload(ExecutionData { payload, sidecar: ExecutionPayloadSidecar::none() }) - .await - .inspect(|_| self.inner.on_new_payload_response())?) - } - - /// Metered version of `new_payload_v2`. - pub async fn new_payload_v2_metered( - &self, - payload: ExecutionPayloadInputV2, - ) -> EngineApiResult { - let start = Instant::now(); - let gas_used = payload.execution_payload.gas_used; - let res = Self::new_payload_v2(self, payload).await; - let elapsed = start.elapsed(); - self.inner.metrics.latency.new_payload_v2.record(elapsed); - self.inner.metrics.new_payload_response.update_response_metrics(&res, gas_used, elapsed); - res - } - - /// See also - pub async fn new_payload_v3( - &self, - payload: ExecutionPayloadV3, - versioned_hashes: Vec, - parent_beacon_block_root: B256, - ) -> EngineApiResult { - let payload = ExecutionPayload::from(payload); - let payload_or_attrs = - PayloadOrAttributes::<'_, EngineT::PayloadAttributes>::from_execution_payload( - &payload, - Some(parent_beacon_block_root), - ); - self.inner - .validator - .validate_version_specific_fields(EngineApiMessageVersion::V3, payload_or_attrs)?; - - Ok(self - .inner - .beacon_consensus - .new_payload(ExecutionData { - payload, - sidecar: ExecutionPayloadSidecar::v3(CancunPayloadFields { - versioned_hashes, - parent_beacon_block_root, - }), - }) - .await - .inspect(|_| self.inner.on_new_payload_response())?) - } - - // Metrics version of `new_payload_v3` - async fn new_payload_v3_metered( - &self, - payload: ExecutionPayloadV3, - versioned_hashes: Vec, - parent_beacon_block_root: B256, - ) -> RpcResult { - let start = Instant::now(); - let gas_used = payload.payload_inner.payload_inner.gas_used; - let res = - Self::new_payload_v3(self, payload, versioned_hashes, parent_beacon_block_root).await; - let elapsed = start.elapsed(); - self.inner.metrics.latency.new_payload_v3.record(elapsed); - self.inner.metrics.new_payload_response.update_response_metrics(&res, gas_used, elapsed); - Ok(res?) - } - - /// See also - pub async fn new_payload_v4( - &self, - payload: ExecutionPayloadV3, - versioned_hashes: Vec, - parent_beacon_block_root: B256, - execution_requests: Requests, - ) -> EngineApiResult { - let payload = ExecutionPayload::from(payload); - let payload_or_attrs = - PayloadOrAttributes::<'_, EngineT::PayloadAttributes>::from_execution_payload( - &payload, - Some(parent_beacon_block_root), - ); - self.inner - .validator - .validate_version_specific_fields(EngineApiMessageVersion::V4, payload_or_attrs)?; - - self.inner.validator.validate_execution_requests(&execution_requests)?; - Ok(self - .inner - .beacon_consensus - .new_payload(ExecutionData { - payload, - sidecar: ExecutionPayloadSidecar::v4( - CancunPayloadFields { versioned_hashes, parent_beacon_block_root }, - PraguePayloadFields { requests: RequestsOrHash::Requests(execution_requests) }, - ), - }) - .await - .inspect(|_| self.inner.on_new_payload_response())?) - } - - /// Metrics version of `new_payload_v4` - async fn new_payload_v4_metered( - &self, - payload: ExecutionPayloadV3, - versioned_hashes: Vec, - parent_beacon_block_root: B256, - execution_requests: Requests, - ) -> RpcResult { - let start = Instant::now(); - let gas_used = payload.payload_inner.payload_inner.gas_used; - let res = Self::new_payload_v4( - self, - payload, - versioned_hashes, - parent_beacon_block_root, - execution_requests, - ) - .await; - let elapsed = start.elapsed(); - self.inner.metrics.latency.new_payload_v4.record(elapsed); - self.inner.metrics.new_payload_response.update_response_metrics(&res, gas_used, elapsed); - Ok(res?) - } - /// Sends a message to the beacon consensus engine to update the fork choice _without_ /// withdrawals. /// @@ -721,6 +545,193 @@ where } } +impl + EngineApi +where + Provider: HeaderProvider + BlockReader + StateProviderFactory + 'static, + EngineT: EngineTypes, + Pool: TransactionPool + 'static, + Validator: EngineValidator, + ChainSpec: EthereumHardforks + Send + Sync + 'static, +{ + /// See also + /// Caution: This should not accept the `withdrawals` field + pub async fn new_payload_v1( + &self, + payload: ExecutionPayloadV1, + ) -> EngineApiResult { + let payload = ExecutionPayload::from(payload); + let payload_or_attrs = + PayloadOrAttributes::<'_, EngineT::PayloadAttributes>::from_execution_payload( + &payload, None, + ); + self.inner + .validator + .validate_version_specific_fields(EngineApiMessageVersion::V1, payload_or_attrs)?; + + Ok(self + .inner + .beacon_consensus + .new_payload(ExecutionData { payload, sidecar: ExecutionPayloadSidecar::none() }) + .await + .inspect(|_| self.inner.on_new_payload_response())?) + } + + /// Metered version of `new_payload_v1`. + async fn new_payload_v1_metered( + &self, + payload: ExecutionPayloadV1, + ) -> EngineApiResult { + let start = Instant::now(); + let gas_used = payload.gas_used; + let res = Self::new_payload_v1(self, payload).await; + let elapsed = start.elapsed(); + self.inner.metrics.latency.new_payload_v1.record(elapsed); + self.inner.metrics.new_payload_response.update_response_metrics(&res, gas_used, elapsed); + res + } + + /// See also + pub async fn new_payload_v2( + &self, + payload: ExecutionPayloadInputV2, + ) -> EngineApiResult { + let payload = payload.into_payload(); + let payload_or_attrs = + PayloadOrAttributes::<'_, EngineT::PayloadAttributes>::from_execution_payload( + &payload, None, + ); + self.inner + .validator + .validate_version_specific_fields(EngineApiMessageVersion::V2, payload_or_attrs)?; + Ok(self + .inner + .beacon_consensus + .new_payload(ExecutionData { payload, sidecar: ExecutionPayloadSidecar::none() }) + .await + .inspect(|_| self.inner.on_new_payload_response())?) + } + + /// Metered version of `new_payload_v2`. + pub async fn new_payload_v2_metered( + &self, + payload: ExecutionPayloadInputV2, + ) -> EngineApiResult { + let start = Instant::now(); + let gas_used = payload.execution_payload.gas_used; + let res = Self::new_payload_v2(self, payload).await; + let elapsed = start.elapsed(); + self.inner.metrics.latency.new_payload_v2.record(elapsed); + self.inner.metrics.new_payload_response.update_response_metrics(&res, gas_used, elapsed); + res + } + + /// See also + pub async fn new_payload_v3( + &self, + payload: ExecutionPayloadV3, + versioned_hashes: Vec, + parent_beacon_block_root: B256, + ) -> EngineApiResult { + let payload = ExecutionPayload::from(payload); + let payload_or_attrs = + PayloadOrAttributes::<'_, EngineT::PayloadAttributes>::from_execution_payload( + &payload, + Some(parent_beacon_block_root), + ); + self.inner + .validator + .validate_version_specific_fields(EngineApiMessageVersion::V3, payload_or_attrs)?; + + Ok(self + .inner + .beacon_consensus + .new_payload(ExecutionData { + payload, + sidecar: ExecutionPayloadSidecar::v3(CancunPayloadFields { + versioned_hashes, + parent_beacon_block_root, + }), + }) + .await + .inspect(|_| self.inner.on_new_payload_response())?) + } + + // Metrics version of `new_payload_v3` + async fn new_payload_v3_metered( + &self, + payload: ExecutionPayloadV3, + versioned_hashes: Vec, + parent_beacon_block_root: B256, + ) -> RpcResult { + let start = Instant::now(); + let gas_used = payload.payload_inner.payload_inner.gas_used; + let res = + Self::new_payload_v3(self, payload, versioned_hashes, parent_beacon_block_root).await; + let elapsed = start.elapsed(); + self.inner.metrics.latency.new_payload_v3.record(elapsed); + self.inner.metrics.new_payload_response.update_response_metrics(&res, gas_used, elapsed); + Ok(res?) + } + + /// See also + pub async fn new_payload_v4( + &self, + payload: ExecutionPayloadV3, + versioned_hashes: Vec, + parent_beacon_block_root: B256, + execution_requests: Requests, + ) -> EngineApiResult { + let payload = ExecutionPayload::from(payload); + let payload_or_attrs = + PayloadOrAttributes::<'_, EngineT::PayloadAttributes>::from_execution_payload( + &payload, + Some(parent_beacon_block_root), + ); + self.inner + .validator + .validate_version_specific_fields(EngineApiMessageVersion::V4, payload_or_attrs)?; + + self.inner.validator.validate_execution_requests(&execution_requests)?; + Ok(self + .inner + .beacon_consensus + .new_payload(ExecutionData { + payload, + sidecar: ExecutionPayloadSidecar::v4( + CancunPayloadFields { versioned_hashes, parent_beacon_block_root }, + PraguePayloadFields { requests: RequestsOrHash::Requests(execution_requests) }, + ), + }) + .await + .inspect(|_| self.inner.on_new_payload_response())?) + } + + /// Metrics version of `new_payload_v4` + async fn new_payload_v4_metered( + &self, + payload: ExecutionPayloadV3, + versioned_hashes: Vec, + parent_beacon_block_root: B256, + execution_requests: Requests, + ) -> RpcResult { + let start = Instant::now(); + let gas_used = payload.payload_inner.payload_inner.gas_used; + let res = Self::new_payload_v4( + self, + payload, + versioned_hashes, + parent_beacon_block_root, + execution_requests, + ) + .await; + let elapsed = start.elapsed(); + self.inner.metrics.latency.new_payload_v4.record(elapsed); + self.inner.metrics.new_payload_response.update_response_metrics(&res, gas_used, elapsed); + Ok(res?) + } +} + impl EngineApiInner where