mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
Make PayloadOrAttributes generic over ExecutionData (#14666)
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
@ -13,9 +13,7 @@ extern crate alloc;
|
||||
|
||||
use alloy_consensus::BlockHeader;
|
||||
use alloy_eips::eip7685::Requests;
|
||||
use alloy_primitives::B256;
|
||||
use alloy_rpc_types_engine::ExecutionData;
|
||||
use core::fmt::{self, Debug};
|
||||
use core::fmt;
|
||||
use reth_payload_primitives::{
|
||||
validate_execution_requests, BuiltPayload, EngineApiMessageVersion,
|
||||
EngineObjectValidationError, InvalidPayloadAttributesError, NewPayloadError, PayloadAttributes,
|
||||
@ -25,6 +23,9 @@ use reth_primitives::{NodePrimitives, RecoveredBlock, SealedBlock};
|
||||
use reth_primitives_traits::Block;
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
|
||||
// Re-export [`ExecutionPayload`] moved to `reth_payload_primitives`
|
||||
pub use reth_payload_primitives::ExecutionPayload;
|
||||
|
||||
mod error;
|
||||
pub use error::*;
|
||||
|
||||
@ -40,34 +41,6 @@ pub use event::*;
|
||||
mod invalid_block_hook;
|
||||
pub use invalid_block_hook::InvalidBlockHook;
|
||||
|
||||
/// An execution payload.
|
||||
pub trait ExecutionPayload:
|
||||
Serialize + DeserializeOwned + Debug + Clone + Send + Sync + 'static
|
||||
{
|
||||
/// Returns the parent hash of the block.
|
||||
fn parent_hash(&self) -> B256;
|
||||
|
||||
/// Returns the hash of the block.
|
||||
fn block_hash(&self) -> B256;
|
||||
|
||||
/// Returns the number of the block.
|
||||
fn block_number(&self) -> u64;
|
||||
}
|
||||
|
||||
impl ExecutionPayload for ExecutionData {
|
||||
fn parent_hash(&self) -> B256 {
|
||||
self.payload.parent_hash()
|
||||
}
|
||||
|
||||
fn block_hash(&self) -> B256 {
|
||||
self.payload.block_hash()
|
||||
}
|
||||
|
||||
fn block_number(&self) -> u64 {
|
||||
self.payload.block_number()
|
||||
}
|
||||
}
|
||||
|
||||
/// This type defines the versioned types of the engine API.
|
||||
///
|
||||
/// This includes the execution payload types and payload attributes that are used to trigger a
|
||||
@ -117,7 +90,7 @@ pub trait EngineTypes:
|
||||
/// Execution data.
|
||||
type ExecutionData: ExecutionPayload;
|
||||
|
||||
/// Converts a [`BuiltPayload`] into an [`ExecutionData`].
|
||||
/// Converts a [`BuiltPayload`] into an [`Self::ExecutionData`].
|
||||
fn block_to_payload(
|
||||
block: SealedBlock<
|
||||
<<Self::BuiltPayload as BuiltPayload>::Primitives as NodePrimitives>::Block,
|
||||
@ -165,7 +138,11 @@ pub trait EngineValidator<Types: EngineTypes>:
|
||||
fn validate_version_specific_fields(
|
||||
&self,
|
||||
version: EngineApiMessageVersion,
|
||||
payload_or_attrs: PayloadOrAttributes<'_, <Types as PayloadTypes>::PayloadAttributes>,
|
||||
payload_or_attrs: PayloadOrAttributes<
|
||||
'_,
|
||||
Types::ExecutionData,
|
||||
<Types as PayloadTypes>::PayloadAttributes,
|
||||
>,
|
||||
) -> Result<(), EngineObjectValidationError>;
|
||||
|
||||
/// Ensures that the payload attributes are valid for the given [`EngineApiMessageVersion`].
|
||||
|
||||
@ -117,7 +117,7 @@ where
|
||||
fn validate_version_specific_fields(
|
||||
&self,
|
||||
version: EngineApiMessageVersion,
|
||||
payload_or_attrs: PayloadOrAttributes<'_, EthPayloadAttributes>,
|
||||
payload_or_attrs: PayloadOrAttributes<'_, Self::ExecutionData, EthPayloadAttributes>,
|
||||
) -> Result<(), EngineObjectValidationError> {
|
||||
validate_version_specific_fields(self.chain_spec(), version, payload_or_attrs)
|
||||
}
|
||||
@ -127,6 +127,12 @@ where
|
||||
version: EngineApiMessageVersion,
|
||||
attributes: &EthPayloadAttributes,
|
||||
) -> Result<(), EngineObjectValidationError> {
|
||||
validate_version_specific_fields(self.chain_spec(), version, attributes.into())
|
||||
validate_version_specific_fields(
|
||||
self.chain_spec(),
|
||||
version,
|
||||
PayloadOrAttributes::<Self::ExecutionData, EthPayloadAttributes>::PayloadAttributes(
|
||||
attributes,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,7 +123,7 @@ where
|
||||
fn validate_version_specific_fields(
|
||||
&self,
|
||||
version: EngineApiMessageVersion,
|
||||
payload_or_attrs: PayloadOrAttributes<'_, OpPayloadAttributes>,
|
||||
payload_or_attrs: PayloadOrAttributes<'_, Self::ExecutionData, OpPayloadAttributes>,
|
||||
) -> Result<(), EngineObjectValidationError> {
|
||||
validate_withdrawals_presence(
|
||||
self.chain_spec(),
|
||||
@ -146,7 +146,13 @@ where
|
||||
version: EngineApiMessageVersion,
|
||||
attributes: &OpPayloadAttributes,
|
||||
) -> Result<(), EngineObjectValidationError> {
|
||||
validate_version_specific_fields(self.chain_spec(), version, attributes.into())?;
|
||||
validate_version_specific_fields(
|
||||
self.chain_spec(),
|
||||
version,
|
||||
PayloadOrAttributes::<Self::ExecutionData, OpPayloadAttributes>::PayloadAttributes(
|
||||
attributes,
|
||||
),
|
||||
)?;
|
||||
|
||||
if attributes.gas_limit.is_none() {
|
||||
return Err(EngineObjectValidationError::InvalidParams(
|
||||
|
||||
@ -29,7 +29,7 @@ pub use traits::{
|
||||
};
|
||||
|
||||
mod payload;
|
||||
pub use payload::PayloadOrAttributes;
|
||||
pub use payload::{ExecutionPayload, PayloadOrAttributes};
|
||||
|
||||
/// The types that are used by the engine API.
|
||||
pub trait PayloadTypes: Send + Sync + Unpin + core::fmt::Debug + Clone + 'static {
|
||||
@ -302,12 +302,13 @@ impl MessageValidationKind {
|
||||
/// either an execution payload, or payload attributes.
|
||||
///
|
||||
/// The version is provided by the [`EngineApiMessageVersion`] argument.
|
||||
pub fn validate_version_specific_fields<Type, T>(
|
||||
pub fn validate_version_specific_fields<Payload, Type, T>(
|
||||
chain_spec: &T,
|
||||
version: EngineApiMessageVersion,
|
||||
payload_or_attrs: PayloadOrAttributes<'_, Type>,
|
||||
payload_or_attrs: PayloadOrAttributes<'_, Payload, Type>,
|
||||
) -> Result<(), EngineObjectValidationError>
|
||||
where
|
||||
Payload: ExecutionPayload,
|
||||
Type: PayloadAttributes,
|
||||
T: EthereumHardforks,
|
||||
{
|
||||
|
||||
@ -2,32 +2,75 @@ use crate::{MessageValidationKind, PayloadAttributes};
|
||||
use alloc::vec::Vec;
|
||||
use alloy_eips::eip4895::Withdrawal;
|
||||
use alloy_primitives::B256;
|
||||
use alloy_rpc_types_engine::ExecutionPayload;
|
||||
use alloy_rpc_types_engine::ExecutionData;
|
||||
use core::fmt::Debug;
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
|
||||
/// Either an [`ExecutionPayload`] or a type that implements the [`PayloadAttributes`] trait.
|
||||
/// An execution payload.
|
||||
pub trait ExecutionPayload:
|
||||
Serialize + DeserializeOwned + Debug + Clone + Send + Sync + 'static
|
||||
{
|
||||
/// Returns the parent hash of the block.
|
||||
fn parent_hash(&self) -> B256;
|
||||
|
||||
/// Returns the hash of the block.
|
||||
fn block_hash(&self) -> B256;
|
||||
|
||||
/// Returns the number of the block.
|
||||
fn block_number(&self) -> u64;
|
||||
|
||||
/// Returns the withdrawals for the payload, if it exists.
|
||||
fn withdrawals(&self) -> Option<&Vec<Withdrawal>>;
|
||||
|
||||
/// Return the parent beacon block root for the payload, if it exists.
|
||||
fn parent_beacon_block_root(&self) -> Option<B256>;
|
||||
|
||||
/// Returns the timestamp to be used in the payload.
|
||||
fn timestamp(&self) -> u64;
|
||||
}
|
||||
|
||||
impl ExecutionPayload for ExecutionData {
|
||||
fn parent_hash(&self) -> B256 {
|
||||
self.payload.parent_hash()
|
||||
}
|
||||
|
||||
fn block_hash(&self) -> B256 {
|
||||
self.payload.block_hash()
|
||||
}
|
||||
|
||||
fn block_number(&self) -> u64 {
|
||||
self.payload.block_number()
|
||||
}
|
||||
|
||||
fn withdrawals(&self) -> Option<&Vec<Withdrawal>> {
|
||||
self.payload.withdrawals()
|
||||
}
|
||||
|
||||
fn parent_beacon_block_root(&self) -> Option<B256> {
|
||||
self.sidecar.parent_beacon_block_root()
|
||||
}
|
||||
|
||||
fn timestamp(&self) -> u64 {
|
||||
self.payload.timestamp()
|
||||
}
|
||||
}
|
||||
|
||||
/// Either a type that implements the [`ExecutionPayload`] or a type that implements the
|
||||
/// [`PayloadAttributes`] trait.
|
||||
///
|
||||
/// This is a helper type to unify pre-validation of version specific fields of the engine API.
|
||||
#[derive(Debug)]
|
||||
pub enum PayloadOrAttributes<'a, Attributes> {
|
||||
/// An [`ExecutionPayload`] and optional parent beacon block root.
|
||||
ExecutionPayload {
|
||||
/// The inner execution payload
|
||||
payload: &'a ExecutionPayload,
|
||||
/// The parent beacon block root
|
||||
parent_beacon_block_root: Option<B256>,
|
||||
},
|
||||
pub enum PayloadOrAttributes<'a, Payload, Attributes> {
|
||||
/// An [`ExecutionPayload`]
|
||||
ExecutionPayload(&'a Payload),
|
||||
/// A payload attributes type.
|
||||
PayloadAttributes(&'a Attributes),
|
||||
}
|
||||
|
||||
impl<'a, Attributes> PayloadOrAttributes<'a, Attributes> {
|
||||
/// Construct a [`PayloadOrAttributes`] from an [`ExecutionPayload`] and optional parent beacon
|
||||
/// block root.
|
||||
pub const fn from_execution_payload(
|
||||
payload: &'a ExecutionPayload,
|
||||
parent_beacon_block_root: Option<B256>,
|
||||
) -> Self {
|
||||
Self::ExecutionPayload { payload, parent_beacon_block_root }
|
||||
impl<'a, Payload, Attributes> PayloadOrAttributes<'a, Payload, Attributes> {
|
||||
/// Construct a [`PayloadOrAttributes::ExecutionPayload`] variant
|
||||
pub const fn from_execution_payload(payload: &'a Payload) -> Self {
|
||||
Self::ExecutionPayload(payload)
|
||||
}
|
||||
|
||||
/// Construct a [`PayloadOrAttributes::PayloadAttributes`] variant
|
||||
@ -36,14 +79,15 @@ impl<'a, Attributes> PayloadOrAttributes<'a, Attributes> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Attributes> PayloadOrAttributes<'_, Attributes>
|
||||
impl<Payload, Attributes> PayloadOrAttributes<'_, Payload, Attributes>
|
||||
where
|
||||
Payload: ExecutionPayload,
|
||||
Attributes: PayloadAttributes,
|
||||
{
|
||||
/// Return the withdrawals for the payload or attributes.
|
||||
pub fn withdrawals(&self) -> Option<&Vec<Withdrawal>> {
|
||||
match self {
|
||||
Self::ExecutionPayload { payload, .. } => payload.withdrawals(),
|
||||
Self::ExecutionPayload(payload) => payload.withdrawals(),
|
||||
Self::PayloadAttributes(attributes) => attributes.withdrawals(),
|
||||
}
|
||||
}
|
||||
@ -51,7 +95,7 @@ where
|
||||
/// Return the timestamp for the payload or attributes.
|
||||
pub fn timestamp(&self) -> u64 {
|
||||
match self {
|
||||
Self::ExecutionPayload { payload, .. } => payload.timestamp(),
|
||||
Self::ExecutionPayload(payload) => payload.timestamp(),
|
||||
Self::PayloadAttributes(attributes) => attributes.timestamp(),
|
||||
}
|
||||
}
|
||||
@ -59,7 +103,7 @@ where
|
||||
/// Return the parent beacon block root for the payload or attributes.
|
||||
pub fn parent_beacon_block_root(&self) -> Option<B256> {
|
||||
match self {
|
||||
Self::ExecutionPayload { parent_beacon_block_root, .. } => *parent_beacon_block_root,
|
||||
Self::ExecutionPayload(payload) => payload.parent_beacon_block_root(),
|
||||
Self::PayloadAttributes(attributes) => attributes.parent_beacon_block_root(),
|
||||
}
|
||||
}
|
||||
@ -73,7 +117,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, AttributesType> From<&'a AttributesType> for PayloadOrAttributes<'a, AttributesType>
|
||||
impl<'a, Payload, AttributesType> From<&'a AttributesType>
|
||||
for PayloadOrAttributes<'a, Payload, AttributesType>
|
||||
where
|
||||
AttributesType: PayloadAttributes,
|
||||
{
|
||||
|
||||
@ -9,10 +9,10 @@ use alloy_eips::{
|
||||
};
|
||||
use alloy_primitives::{BlockHash, BlockNumber, B256, U64};
|
||||
use alloy_rpc_types_engine::{
|
||||
CancunPayloadFields, ClientVersionV1, ExecutionData, ExecutionPayload,
|
||||
ExecutionPayloadBodiesV1, ExecutionPayloadBodyV1, ExecutionPayloadInputV2,
|
||||
ExecutionPayloadSidecar, ExecutionPayloadV1, ExecutionPayloadV3, ForkchoiceState,
|
||||
ForkchoiceUpdated, PayloadId, PayloadStatus, PraguePayloadFields, TransitionConfiguration,
|
||||
CancunPayloadFields, ClientVersionV1, ExecutionData, ExecutionPayloadBodiesV1,
|
||||
ExecutionPayloadBodyV1, ExecutionPayloadInputV2, ExecutionPayloadSidecar, ExecutionPayloadV1,
|
||||
ExecutionPayloadV3, ForkchoiceState, ForkchoiceUpdated, PayloadId, PayloadStatus,
|
||||
PraguePayloadFields, TransitionConfiguration,
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
use jsonrpsee_core::{server::RpcModule, RpcResult};
|
||||
@ -560,10 +560,11 @@ where
|
||||
&self,
|
||||
payload: ExecutionPayloadV1,
|
||||
) -> EngineApiResult<PayloadStatus> {
|
||||
let payload = ExecutionPayload::from(payload);
|
||||
let payload =
|
||||
ExecutionData { payload: payload.into(), sidecar: ExecutionPayloadSidecar::none() };
|
||||
let payload_or_attrs =
|
||||
PayloadOrAttributes::<'_, EngineT::PayloadAttributes>::from_execution_payload(
|
||||
&payload, None,
|
||||
PayloadOrAttributes::<'_, ExecutionData, EngineT::PayloadAttributes>::from_execution_payload(
|
||||
&payload,
|
||||
);
|
||||
self.inner
|
||||
.validator
|
||||
@ -572,7 +573,7 @@ where
|
||||
Ok(self
|
||||
.inner
|
||||
.beacon_consensus
|
||||
.new_payload(ExecutionData { payload, sidecar: ExecutionPayloadSidecar::none() })
|
||||
.new_payload(payload)
|
||||
.await
|
||||
.inspect(|_| self.inner.on_new_payload_response())?)
|
||||
}
|
||||
@ -596,10 +597,13 @@ where
|
||||
&self,
|
||||
payload: ExecutionPayloadInputV2,
|
||||
) -> EngineApiResult<PayloadStatus> {
|
||||
let payload = payload.into_payload();
|
||||
let payload = ExecutionData {
|
||||
payload: payload.into_payload(),
|
||||
sidecar: ExecutionPayloadSidecar::none(),
|
||||
};
|
||||
let payload_or_attrs =
|
||||
PayloadOrAttributes::<'_, EngineT::PayloadAttributes>::from_execution_payload(
|
||||
&payload, None,
|
||||
PayloadOrAttributes::<'_, ExecutionData, EngineT::PayloadAttributes>::from_execution_payload(
|
||||
&payload,
|
||||
);
|
||||
self.inner
|
||||
.validator
|
||||
@ -607,7 +611,7 @@ where
|
||||
Ok(self
|
||||
.inner
|
||||
.beacon_consensus
|
||||
.new_payload(ExecutionData { payload, sidecar: ExecutionPayloadSidecar::none() })
|
||||
.new_payload(payload)
|
||||
.await
|
||||
.inspect(|_| self.inner.on_new_payload_response())?)
|
||||
}
|
||||
@ -633,11 +637,16 @@ where
|
||||
versioned_hashes: Vec<B256>,
|
||||
parent_beacon_block_root: B256,
|
||||
) -> EngineApiResult<PayloadStatus> {
|
||||
let payload = ExecutionPayload::from(payload);
|
||||
let payload = ExecutionData {
|
||||
payload: payload.into(),
|
||||
sidecar: ExecutionPayloadSidecar::v3(CancunPayloadFields {
|
||||
versioned_hashes,
|
||||
parent_beacon_block_root,
|
||||
}),
|
||||
};
|
||||
let payload_or_attrs =
|
||||
PayloadOrAttributes::<'_, EngineT::PayloadAttributes>::from_execution_payload(
|
||||
PayloadOrAttributes::<'_, ExecutionData, EngineT::PayloadAttributes>::from_execution_payload(
|
||||
&payload,
|
||||
Some(parent_beacon_block_root),
|
||||
);
|
||||
self.inner
|
||||
.validator
|
||||
@ -646,13 +655,7 @@ where
|
||||
Ok(self
|
||||
.inner
|
||||
.beacon_consensus
|
||||
.new_payload(ExecutionData {
|
||||
payload,
|
||||
sidecar: ExecutionPayloadSidecar::v3(CancunPayloadFields {
|
||||
versioned_hashes,
|
||||
parent_beacon_block_root,
|
||||
}),
|
||||
})
|
||||
.new_payload(payload)
|
||||
.await
|
||||
.inspect(|_| self.inner.on_new_payload_response())?)
|
||||
}
|
||||
@ -682,27 +685,29 @@ where
|
||||
parent_beacon_block_root: B256,
|
||||
execution_requests: Requests,
|
||||
) -> EngineApiResult<PayloadStatus> {
|
||||
let payload = ExecutionPayload::from(payload);
|
||||
let payload = ExecutionData {
|
||||
payload: payload.into(),
|
||||
sidecar: ExecutionPayloadSidecar::v4(
|
||||
CancunPayloadFields { versioned_hashes, parent_beacon_block_root },
|
||||
PraguePayloadFields { requests: RequestsOrHash::Requests(execution_requests) },
|
||||
),
|
||||
};
|
||||
let payload_or_attrs =
|
||||
PayloadOrAttributes::<'_, EngineT::PayloadAttributes>::from_execution_payload(
|
||||
PayloadOrAttributes::<'_, ExecutionData, 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)?;
|
||||
if let Some(requests) = payload.sidecar.requests() {
|
||||
self.inner.validator.validate_execution_requests(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) },
|
||||
),
|
||||
})
|
||||
.new_payload(payload)
|
||||
.await
|
||||
.inspect(|_| self.inner.on_new_payload_response())?)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user