diff --git a/crates/consensus/beacon/src/engine/handle.rs b/crates/consensus/beacon/src/engine/handle.rs index 176a8cbbf..f7b70929b 100644 --- a/crates/consensus/beacon/src/engine/handle.rs +++ b/crates/consensus/beacon/src/engine/handle.rs @@ -5,9 +5,9 @@ use crate::{ BeaconForkChoiceUpdateError, BeaconOnNewPayloadError, }; use futures::TryFutureExt; -use reth_primitives::H256; use reth_rpc_types::engine::{ - ExecutionPayload, ForkchoiceState, ForkchoiceUpdated, PayloadAttributes, PayloadStatus, + CancunPayloadFields, ExecutionPayload, ForkchoiceState, ForkchoiceUpdated, PayloadAttributes, + PayloadStatus, }; use tokio::sync::{mpsc, mpsc::UnboundedSender, oneshot}; use tokio_stream::wrappers::UnboundedReceiverStream; @@ -35,14 +35,10 @@ impl BeaconConsensusEngineHandle { pub async fn new_payload( &self, payload: ExecutionPayload, - parent_beacon_block_root: Option, + cancun_fields: Option, ) -> Result { let (tx, rx) = oneshot::channel(); - let _ = self.to_engine.send(BeaconEngineMessage::NewPayload { - payload, - parent_beacon_block_root, - tx, - }); + let _ = self.to_engine.send(BeaconEngineMessage::NewPayload { payload, cancun_fields, tx }); rx.await.map_err(|_| BeaconOnNewPayloadError::EngineUnavailable)? } diff --git a/crates/consensus/beacon/src/engine/message.rs b/crates/consensus/beacon/src/engine/message.rs index 9e29a07d5..b3b3c86c8 100644 --- a/crates/consensus/beacon/src/engine/message.rs +++ b/crates/consensus/beacon/src/engine/message.rs @@ -5,10 +5,9 @@ use crate::{ use futures::{future::Either, FutureExt}; use reth_interfaces::consensus::ForkchoiceState; use reth_payload_builder::error::PayloadBuilderError; -use reth_primitives::H256; use reth_rpc_types::engine::{ - ExecutionPayload, ForkChoiceUpdateResult, ForkchoiceUpdateError, ForkchoiceUpdated, - PayloadAttributes, PayloadId, PayloadStatus, PayloadStatusEnum, + CancunPayloadFields, ExecutionPayload, ForkChoiceUpdateResult, ForkchoiceUpdateError, + ForkchoiceUpdated, PayloadAttributes, PayloadId, PayloadStatus, PayloadStatusEnum, }; use std::{ future::Future, @@ -147,8 +146,8 @@ pub enum BeaconEngineMessage { NewPayload { /// The execution payload received by Engine API. payload: ExecutionPayload, - /// The parent beacon block root, if any. - parent_beacon_block_root: Option, + /// The cancun-related newPayload fields, if any. + cancun_fields: Option, /// The sender for returning payload status result. tx: oneshot::Sender>, }, diff --git a/crates/consensus/beacon/src/engine/mod.rs b/crates/consensus/beacon/src/engine/mod.rs index c6f7cadfe..71bc15da3 100644 --- a/crates/consensus/beacon/src/engine/mod.rs +++ b/crates/consensus/beacon/src/engine/mod.rs @@ -31,7 +31,8 @@ use reth_provider::{ }; use reth_prune::Pruner; use reth_rpc_types::engine::{ - ExecutionPayload, PayloadAttributes, PayloadStatus, PayloadStatusEnum, PayloadValidationError, + CancunPayloadFields, ExecutionPayload, PayloadAttributes, PayloadStatus, PayloadStatusEnum, + PayloadValidationError, }; use reth_stages::{ControlFlow, Pipeline, PipelineError}; use reth_tasks::TaskSpawner; @@ -1049,13 +1050,16 @@ where /// /// This returns a [`PayloadStatus`] that represents the outcome of a processed new payload and /// returns an error if an internal error occurred. - #[instrument(level = "trace", skip(self, payload, parent_beacon_block_root), fields(block_hash= ?payload.block_hash(), block_number = %payload.block_number(), is_pipeline_idle = %self.sync.is_pipeline_idle()), target = "consensus::engine")] + #[instrument(level = "trace", skip(self, payload, cancun_fields), fields(block_hash= ?payload.block_hash(), block_number = %payload.block_number(), is_pipeline_idle = %self.sync.is_pipeline_idle()), target = "consensus::engine")] fn on_new_payload( &mut self, payload: ExecutionPayload, - parent_beacon_block_root: Option, + cancun_fields: Option, ) -> Result { - let block = match self.ensure_well_formed_payload(payload, parent_beacon_block_root) { + let block = match self.ensure_well_formed_payload( + payload, + cancun_fields.map(|fields| fields.parent_beacon_block_root), + ) { Ok(block) => block, Err(status) => return Ok(status), }; @@ -1727,9 +1731,9 @@ where } } } - BeaconEngineMessage::NewPayload { payload, parent_beacon_block_root, tx } => { + BeaconEngineMessage::NewPayload { payload, cancun_fields, tx } => { this.metrics.new_payload_messages.increment(1); - let res = this.on_new_payload(payload, parent_beacon_block_root); + let res = this.on_new_payload(payload, cancun_fields); let _ = tx.send(res); } BeaconEngineMessage::TransitionConfigurationExchanged => { diff --git a/crates/consensus/beacon/src/engine/test_utils.rs b/crates/consensus/beacon/src/engine/test_utils.rs index c9c76a786..0fdda91da 100644 --- a/crates/consensus/beacon/src/engine/test_utils.rs +++ b/crates/consensus/beacon/src/engine/test_utils.rs @@ -27,7 +27,9 @@ use reth_provider::{ }; use reth_prune::Pruner; use reth_revm::Factory; -use reth_rpc_types::engine::{ExecutionPayload, ForkchoiceState, ForkchoiceUpdated, PayloadStatus}; +use reth_rpc_types::engine::{ + CancunPayloadFields, ExecutionPayload, ForkchoiceState, ForkchoiceUpdated, PayloadStatus, +}; use reth_stages::{ sets::DefaultStages, stages::HeaderSyncMode, test_utils::TestStages, ExecOutput, Pipeline, StageError, @@ -69,9 +71,9 @@ impl TestEnv { pub async fn send_new_payload>( &self, payload: T, - parent_beacon_block_root: Option, + cancun_fields: Option, ) -> Result { - self.engine_handle.new_payload(payload.into(), parent_beacon_block_root).await + self.engine_handle.new_payload(payload.into(), cancun_fields).await } /// Sends the `ExecutionPayload` message to the consensus engine and retries if the engine @@ -79,11 +81,11 @@ impl TestEnv { pub async fn send_new_payload_retry_on_syncing>( &self, payload: T, - parent_beacon_block_root: Option, + cancun_fields: Option, ) -> Result { let payload: ExecutionPayload = payload.into(); loop { - let result = self.send_new_payload(payload.clone(), parent_beacon_block_root).await?; + let result = self.send_new_payload(payload.clone(), cancun_fields.clone()).await?; if !result.is_syncing() { return Ok(result) } diff --git a/crates/rpc/rpc-engine-api/src/engine_api.rs b/crates/rpc/rpc-engine-api/src/engine_api.rs index cea1003ed..c61731d5c 100644 --- a/crates/rpc/rpc-engine-api/src/engine_api.rs +++ b/crates/rpc/rpc-engine-api/src/engine_api.rs @@ -10,7 +10,7 @@ use reth_primitives::{BlockHash, BlockHashOrNumber, BlockNumber, ChainSpec, Hard use reth_provider::{BlockReader, EvmEnvProvider, HeaderProvider, StateProviderFactory}; use reth_rpc_api::EngineApiServer; use reth_rpc_types::engine::{ - ExecutionPayload, ExecutionPayloadBodiesV1, ExecutionPayloadEnvelopeV2, + CancunPayloadFields, ExecutionPayload, ExecutionPayloadBodiesV1, ExecutionPayloadEnvelopeV2, ExecutionPayloadEnvelopeV3, ExecutionPayloadV1, ExecutionPayloadV3, ForkchoiceUpdated, PayloadAttributes, PayloadId, PayloadStatus, TransitionConfiguration, CAPABILITIES, }; @@ -92,8 +92,8 @@ where /// See also pub async fn new_payload_v3( &self, - payload: ExecutionPayloadV1, - _versioned_hashes: Vec, + payload: ExecutionPayloadV3, + versioned_hashes: Vec, parent_beacon_block_root: H256, ) -> EngineApiResult { let payload = ExecutionPayload::from(payload); @@ -101,8 +101,10 @@ where PayloadOrAttributes::from_execution_payload(&payload, Some(parent_beacon_block_root)); self.validate_version_specific_fields(EngineApiMessageVersion::V3, &payload_or_attrs)?; + let cancun_fields = CancunPayloadFields { versioned_hashes, parent_beacon_block_root }; + // TODO: validate versioned hashes and figure out what to do with parent_beacon_block_root - Ok(self.inner.beacon_consensus.new_payload(payload, Some(parent_beacon_block_root)).await?) + Ok(self.inner.beacon_consensus.new_payload(payload, Some(cancun_fields)).await?) } /// Sends a message to the beacon consensus engine to update the fork choice _without_ diff --git a/crates/rpc/rpc-types/src/eth/engine/cancun.rs b/crates/rpc/rpc-types/src/eth/engine/cancun.rs new file mode 100644 index 000000000..92dea6074 --- /dev/null +++ b/crates/rpc/rpc-types/src/eth/engine/cancun.rs @@ -0,0 +1,17 @@ +//! Contains types related to the Cancun hardfork that will be used by RPC to communicate with the +//! beacon consensus engine. +use reth_primitives::H256; + +/// Fields introduced in `engine_newPayloadV3` that are not present in the `ExecutionPayload` RPC +/// object. +/// +/// See also: +/// +#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)] +pub struct CancunPayloadFields { + /// The parent beacon block root. + pub parent_beacon_block_root: H256, + + /// The expected blob versioned hashes. + pub versioned_hashes: Vec, +} diff --git a/crates/rpc/rpc-types/src/eth/engine/mod.rs b/crates/rpc/rpc-types/src/eth/engine/mod.rs index 2a814374f..54cf8ccf0 100644 --- a/crates/rpc/rpc-types/src/eth/engine/mod.rs +++ b/crates/rpc/rpc-types/src/eth/engine/mod.rs @@ -2,11 +2,12 @@ #![allow(missing_docs)] +mod cancun; mod forkchoice; mod payload; mod transition; -pub use self::{forkchoice::*, payload::*, transition::*}; +pub use self::{cancun::*, forkchoice::*, payload::*, transition::*}; /// The list of supported Engine capabilities pub const CAPABILITIES: [&str; 9] = [