feat: add CancunPayloadFields for engine_newPayloadV3 (#4407)

This commit is contained in:
Dan Cline
2023-08-30 09:28:53 -07:00
committed by GitHub
parent e576c007e3
commit 1c83740720
7 changed files with 50 additions and 29 deletions

View File

@ -5,9 +5,9 @@ use crate::{
BeaconForkChoiceUpdateError, BeaconOnNewPayloadError, BeaconForkChoiceUpdateError, BeaconOnNewPayloadError,
}; };
use futures::TryFutureExt; use futures::TryFutureExt;
use reth_primitives::H256;
use reth_rpc_types::engine::{ 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::sync::{mpsc, mpsc::UnboundedSender, oneshot};
use tokio_stream::wrappers::UnboundedReceiverStream; use tokio_stream::wrappers::UnboundedReceiverStream;
@ -35,14 +35,10 @@ impl BeaconConsensusEngineHandle {
pub async fn new_payload( pub async fn new_payload(
&self, &self,
payload: ExecutionPayload, payload: ExecutionPayload,
parent_beacon_block_root: Option<H256>, cancun_fields: Option<CancunPayloadFields>,
) -> Result<PayloadStatus, BeaconOnNewPayloadError> { ) -> Result<PayloadStatus, BeaconOnNewPayloadError> {
let (tx, rx) = oneshot::channel(); let (tx, rx) = oneshot::channel();
let _ = self.to_engine.send(BeaconEngineMessage::NewPayload { let _ = self.to_engine.send(BeaconEngineMessage::NewPayload { payload, cancun_fields, tx });
payload,
parent_beacon_block_root,
tx,
});
rx.await.map_err(|_| BeaconOnNewPayloadError::EngineUnavailable)? rx.await.map_err(|_| BeaconOnNewPayloadError::EngineUnavailable)?
} }

View File

@ -5,10 +5,9 @@ use crate::{
use futures::{future::Either, FutureExt}; use futures::{future::Either, FutureExt};
use reth_interfaces::consensus::ForkchoiceState; use reth_interfaces::consensus::ForkchoiceState;
use reth_payload_builder::error::PayloadBuilderError; use reth_payload_builder::error::PayloadBuilderError;
use reth_primitives::H256;
use reth_rpc_types::engine::{ use reth_rpc_types::engine::{
ExecutionPayload, ForkChoiceUpdateResult, ForkchoiceUpdateError, ForkchoiceUpdated, CancunPayloadFields, ExecutionPayload, ForkChoiceUpdateResult, ForkchoiceUpdateError,
PayloadAttributes, PayloadId, PayloadStatus, PayloadStatusEnum, ForkchoiceUpdated, PayloadAttributes, PayloadId, PayloadStatus, PayloadStatusEnum,
}; };
use std::{ use std::{
future::Future, future::Future,
@ -147,8 +146,8 @@ pub enum BeaconEngineMessage {
NewPayload { NewPayload {
/// The execution payload received by Engine API. /// The execution payload received by Engine API.
payload: ExecutionPayload, payload: ExecutionPayload,
/// The parent beacon block root, if any. /// The cancun-related newPayload fields, if any.
parent_beacon_block_root: Option<H256>, cancun_fields: Option<CancunPayloadFields>,
/// The sender for returning payload status result. /// The sender for returning payload status result.
tx: oneshot::Sender<Result<PayloadStatus, BeaconOnNewPayloadError>>, tx: oneshot::Sender<Result<PayloadStatus, BeaconOnNewPayloadError>>,
}, },

View File

@ -31,7 +31,8 @@ use reth_provider::{
}; };
use reth_prune::Pruner; use reth_prune::Pruner;
use reth_rpc_types::engine::{ use reth_rpc_types::engine::{
ExecutionPayload, PayloadAttributes, PayloadStatus, PayloadStatusEnum, PayloadValidationError, CancunPayloadFields, ExecutionPayload, PayloadAttributes, PayloadStatus, PayloadStatusEnum,
PayloadValidationError,
}; };
use reth_stages::{ControlFlow, Pipeline, PipelineError}; use reth_stages::{ControlFlow, Pipeline, PipelineError};
use reth_tasks::TaskSpawner; use reth_tasks::TaskSpawner;
@ -1049,13 +1050,16 @@ where
/// ///
/// This returns a [`PayloadStatus`] that represents the outcome of a processed new payload and /// This returns a [`PayloadStatus`] that represents the outcome of a processed new payload and
/// returns an error if an internal error occurred. /// 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( fn on_new_payload(
&mut self, &mut self,
payload: ExecutionPayload, payload: ExecutionPayload,
parent_beacon_block_root: Option<H256>, cancun_fields: Option<CancunPayloadFields>,
) -> Result<PayloadStatus, BeaconOnNewPayloadError> { ) -> Result<PayloadStatus, BeaconOnNewPayloadError> {
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, Ok(block) => block,
Err(status) => return Ok(status), 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); 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); let _ = tx.send(res);
} }
BeaconEngineMessage::TransitionConfigurationExchanged => { BeaconEngineMessage::TransitionConfigurationExchanged => {

View File

@ -27,7 +27,9 @@ use reth_provider::{
}; };
use reth_prune::Pruner; use reth_prune::Pruner;
use reth_revm::Factory; 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::{ use reth_stages::{
sets::DefaultStages, stages::HeaderSyncMode, test_utils::TestStages, ExecOutput, Pipeline, sets::DefaultStages, stages::HeaderSyncMode, test_utils::TestStages, ExecOutput, Pipeline,
StageError, StageError,
@ -69,9 +71,9 @@ impl<DB> TestEnv<DB> {
pub async fn send_new_payload<T: Into<ExecutionPayload>>( pub async fn send_new_payload<T: Into<ExecutionPayload>>(
&self, &self,
payload: T, payload: T,
parent_beacon_block_root: Option<H256>, cancun_fields: Option<CancunPayloadFields>,
) -> Result<PayloadStatus, BeaconOnNewPayloadError> { ) -> Result<PayloadStatus, BeaconOnNewPayloadError> {
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 /// Sends the `ExecutionPayload` message to the consensus engine and retries if the engine
@ -79,11 +81,11 @@ impl<DB> TestEnv<DB> {
pub async fn send_new_payload_retry_on_syncing<T: Into<ExecutionPayload>>( pub async fn send_new_payload_retry_on_syncing<T: Into<ExecutionPayload>>(
&self, &self,
payload: T, payload: T,
parent_beacon_block_root: Option<H256>, cancun_fields: Option<CancunPayloadFields>,
) -> Result<PayloadStatus, BeaconOnNewPayloadError> { ) -> Result<PayloadStatus, BeaconOnNewPayloadError> {
let payload: ExecutionPayload = payload.into(); let payload: ExecutionPayload = payload.into();
loop { 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() { if !result.is_syncing() {
return Ok(result) return Ok(result)
} }

View File

@ -10,7 +10,7 @@ use reth_primitives::{BlockHash, BlockHashOrNumber, BlockNumber, ChainSpec, Hard
use reth_provider::{BlockReader, EvmEnvProvider, HeaderProvider, StateProviderFactory}; use reth_provider::{BlockReader, EvmEnvProvider, HeaderProvider, StateProviderFactory};
use reth_rpc_api::EngineApiServer; use reth_rpc_api::EngineApiServer;
use reth_rpc_types::engine::{ use reth_rpc_types::engine::{
ExecutionPayload, ExecutionPayloadBodiesV1, ExecutionPayloadEnvelopeV2, CancunPayloadFields, ExecutionPayload, ExecutionPayloadBodiesV1, ExecutionPayloadEnvelopeV2,
ExecutionPayloadEnvelopeV3, ExecutionPayloadV1, ExecutionPayloadV3, ForkchoiceUpdated, ExecutionPayloadEnvelopeV3, ExecutionPayloadV1, ExecutionPayloadV3, ForkchoiceUpdated,
PayloadAttributes, PayloadId, PayloadStatus, TransitionConfiguration, CAPABILITIES, PayloadAttributes, PayloadId, PayloadStatus, TransitionConfiguration, CAPABILITIES,
}; };
@ -92,8 +92,8 @@ where
/// See also <https://github.com/ethereum/execution-apis/blob/fe8e13c288c592ec154ce25c534e26cb7ce0530d/src/engine/cancun.md#engine_newpayloadv3> /// See also <https://github.com/ethereum/execution-apis/blob/fe8e13c288c592ec154ce25c534e26cb7ce0530d/src/engine/cancun.md#engine_newpayloadv3>
pub async fn new_payload_v3( pub async fn new_payload_v3(
&self, &self,
payload: ExecutionPayloadV1, payload: ExecutionPayloadV3,
_versioned_hashes: Vec<H256>, versioned_hashes: Vec<H256>,
parent_beacon_block_root: H256, parent_beacon_block_root: H256,
) -> EngineApiResult<PayloadStatus> { ) -> EngineApiResult<PayloadStatus> {
let payload = ExecutionPayload::from(payload); let payload = ExecutionPayload::from(payload);
@ -101,8 +101,10 @@ where
PayloadOrAttributes::from_execution_payload(&payload, Some(parent_beacon_block_root)); PayloadOrAttributes::from_execution_payload(&payload, Some(parent_beacon_block_root));
self.validate_version_specific_fields(EngineApiMessageVersion::V3, &payload_or_attrs)?; 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 // 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_ /// Sends a message to the beacon consensus engine to update the fork choice _without_

View File

@ -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:
/// <https://github.com/ethereum/execution-apis/blob/fe8e13c288c592ec154ce25c534e26cb7ce0530d/src/engine/cancun.md#request>
#[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<H256>,
}

View File

@ -2,11 +2,12 @@
#![allow(missing_docs)] #![allow(missing_docs)]
mod cancun;
mod forkchoice; mod forkchoice;
mod payload; mod payload;
mod transition; mod transition;
pub use self::{forkchoice::*, payload::*, transition::*}; pub use self::{cancun::*, forkchoice::*, payload::*, transition::*};
/// The list of supported Engine capabilities /// The list of supported Engine capabilities
pub const CAPABILITIES: [&str; 9] = [ pub const CAPABILITIES: [&str; 9] = [