feat: add version_specific_fields method to EngineTypes (#6050)

This commit is contained in:
Dan Cline
2024-01-15 15:29:45 -05:00
committed by GitHub
parent 685d1c51e4
commit 9d65a4cfbb
9 changed files with 135 additions and 21 deletions

View File

@@ -17,7 +17,7 @@
//! ```no_run
//! # use reth_rpc_types::engine::{PayloadAttributes as EthPayloadAttributes, PayloadId, Withdrawal};
//! # use reth_primitives::{B256, ChainSpec, Address};
//! # use reth_node_api::{EngineTypes, EngineApiMessageVersion, validate_version_specific_fields, AttributesValidationError, PayloadAttributes, PayloadBuilderAttributes};
//! # use reth_node_api::{EngineTypes, EngineApiMessageVersion, validate_version_specific_fields, AttributesValidationError, PayloadAttributes, PayloadBuilderAttributes, PayloadOrAttributes};
//! # use reth_payload_builder::{EthPayloadBuilderAttributes, EthBuiltPayload};
//! # use serde::{Deserialize, Serialize};
//! # use thiserror::Error;
@@ -58,7 +58,7 @@
//! chain_spec: &ChainSpec,
//! version: EngineApiMessageVersion,
//! ) -> Result<(), AttributesValidationError> {
//! validate_version_specific_fields(chain_spec, version, &self.into())?;
//! validate_version_specific_fields(chain_spec, version, self.into())?;
//!
//! // custom validation logic - ensure that the custom field is not zero
//! if self.custom == 0 {
@@ -122,6 +122,14 @@
//! type PayloadAttributes = CustomPayloadAttributes;
//! type PayloadBuilderAttributes = CustomPayloadBuilderAttributes;
//! type BuiltPayload = EthBuiltPayload;
//!
//! fn validate_version_specific_fields(
//! chain_spec: &ChainSpec,
//! version: EngineApiMessageVersion,
//! payload_or_attrs: PayloadOrAttributes<'_, CustomPayloadAttributes>,
//! ) -> Result<(), AttributesValidationError> {
//! validate_version_specific_fields(chain_spec, version, payload_or_attrs)
//! }
//! }
//! ```
@@ -152,6 +160,14 @@ pub trait EngineTypes: Send + Sync {
/// The built payload type.
type BuiltPayload: BuiltPayload + Clone + Unpin;
/// Validates the presence or exclusion of fork-specific fields based on the payload attributes
/// and the message version.
fn validate_version_specific_fields(
chain_spec: &ChainSpec,
version: EngineApiMessageVersion,
payload_or_attrs: PayloadOrAttributes<'_, Self::PayloadAttributes>,
) -> Result<(), AttributesValidationError>;
}
/// Validates the timestamp depending on the version called:
@@ -198,6 +214,44 @@ pub fn validate_payload_timestamp(
Ok(())
}
#[cfg(feature = "optimism")]
/// Validates the presence of the `withdrawals` field according to the payload timestamp.
///
/// After Canyon, withdrawals field must be [Some].
/// Before Canyon, withdrawals field must be [None];
///
/// Canyon activates the Shanghai EIPs, see the Canyon specs for more details:
/// <https://github.com/ethereum-optimism/optimism/blob/ab926c5fd1e55b5c864341c44842d6d1ca679d99/specs/superchain-upgrades.md#canyon>
pub fn optimism_validate_withdrawals_presence(
chain_spec: &ChainSpec,
version: EngineApiMessageVersion,
timestamp: u64,
has_withdrawals: bool,
) -> Result<(), AttributesValidationError> {
let is_shanghai = chain_spec.fork(Hardfork::Canyon).active_at_timestamp(timestamp);
match version {
EngineApiMessageVersion::V1 => {
if has_withdrawals {
return Err(AttributesValidationError::WithdrawalsNotSupportedInV1)
}
if is_shanghai {
return Err(AttributesValidationError::NoWithdrawalsPostShanghai)
}
}
EngineApiMessageVersion::V2 | EngineApiMessageVersion::V3 => {
if is_shanghai && !has_withdrawals {
return Err(AttributesValidationError::NoWithdrawalsPostShanghai)
}
if !is_shanghai && has_withdrawals {
return Err(AttributesValidationError::HasWithdrawalsPreShanghai)
}
}
};
Ok(())
}
/// Validates the presence of the `withdrawals` field according to the payload timestamp.
/// After Shanghai, withdrawals field must be [Some].
/// Before Shanghai, withdrawals field must be [None];
@@ -290,7 +344,7 @@ pub fn validate_parent_beacon_block_root_presence(
pub fn validate_version_specific_fields<Type>(
chain_spec: &ChainSpec,
version: EngineApiMessageVersion,
payload_or_attrs: &PayloadOrAttributes<'_, Type>,
payload_or_attrs: PayloadOrAttributes<'_, Type>,
) -> Result<(), AttributesValidationError>
where
Type: PayloadAttributes,
@@ -309,6 +363,31 @@ where
)
}
#[cfg(feature = "optimism")]
/// Validates the presence or exclusion of fork-specific fields based on the payload attributes
/// and the message version.
pub fn optimism_validate_version_specific_fields<Type>(
chain_spec: &ChainSpec,
version: EngineApiMessageVersion,
payload_or_attrs: PayloadOrAttributes<'_, Type>,
) -> Result<(), AttributesValidationError>
where
Type: PayloadAttributes,
{
optimism_validate_withdrawals_presence(
chain_spec,
version,
payload_or_attrs.timestamp(),
payload_or_attrs.withdrawals().is_some(),
)?;
validate_parent_beacon_block_root_presence(
chain_spec,
version,
payload_or_attrs.timestamp(),
payload_or_attrs.parent_beacon_block_root().is_some(),
)
}
/// The version of Engine API message.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EngineApiMessageVersion {

View File

@@ -180,7 +180,7 @@ impl PayloadAttributes for EthPayloadAttributes {
chain_spec: &ChainSpec,
version: EngineApiMessageVersion,
) -> Result<(), AttributesValidationError> {
validate_version_specific_fields(chain_spec, version, &self.into())
validate_version_specific_fields(chain_spec, version, self.into())
}
}
@@ -202,7 +202,7 @@ impl PayloadAttributes for OptimismPayloadAttributes {
chain_spec: &ChainSpec,
version: EngineApiMessageVersion,
) -> Result<(), AttributesValidationError> {
validate_version_specific_fields(chain_spec, version, &self.into())?;
validate_version_specific_fields(chain_spec, version, self.into())?;
if self.gas_limit.is_none() && chain_spec.is_optimism() {
return Err(AttributesValidationError::InvalidParams(