feat: extends engine validator (#12900)

This commit is contained in:
Matthias Seitz
2024-11-27 12:31:24 +01:00
committed by GitHub
parent 51afa4cdc9
commit b33757fcbe
10 changed files with 228 additions and 81 deletions

4
Cargo.lock generated
View File

@ -7194,6 +7194,7 @@ dependencies = [
name = "reth-engine-primitives" name = "reth-engine-primitives"
version = "1.1.2" version = "1.1.2"
dependencies = [ dependencies = [
"alloy-consensus",
"alloy-primitives", "alloy-primitives",
"alloy-rpc-types-engine", "alloy-rpc-types-engine",
"futures", "futures",
@ -7202,6 +7203,7 @@ dependencies = [
"reth-payload-builder-primitives", "reth-payload-builder-primitives",
"reth-payload-primitives", "reth-payload-primitives",
"reth-primitives", "reth-primitives",
"reth-primitives-traits",
"reth-trie", "reth-trie",
"serde", "serde",
"thiserror 1.0.69", "thiserror 1.0.69",
@ -7431,6 +7433,7 @@ dependencies = [
"reth-chainspec", "reth-chainspec",
"reth-engine-primitives", "reth-engine-primitives",
"reth-payload-primitives", "reth-payload-primitives",
"reth-payload-validator",
"reth-primitives", "reth-primitives",
"reth-rpc-types-compat", "reth-rpc-types-compat",
"serde", "serde",
@ -8348,6 +8351,7 @@ dependencies = [
"reth-optimism-rpc", "reth-optimism-rpc",
"reth-payload-builder", "reth-payload-builder",
"reth-payload-util", "reth-payload-util",
"reth-payload-validator",
"reth-primitives", "reth-primitives",
"reth-provider", "reth-provider",
"reth-revm", "reth-revm",

View File

@ -16,11 +16,13 @@ reth-execution-types.workspace = true
reth-payload-primitives.workspace = true reth-payload-primitives.workspace = true
reth-payload-builder-primitives.workspace = true reth-payload-builder-primitives.workspace = true
reth-primitives.workspace = true reth-primitives.workspace = true
reth-primitives-traits.workspace = true
reth-trie.workspace = true reth-trie.workspace = true
reth-errors.workspace = true reth-errors.workspace = true
# alloy # alloy
alloy-primitives.workspace = true alloy-primitives.workspace = true
alloy-consensus.workspace = true
alloy-rpc-types-engine.workspace = true alloy-rpc-types-engine.workspace = true
# async # async

View File

@ -9,6 +9,9 @@
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
mod error; mod error;
use alloy_consensus::BlockHeader;
use alloy_rpc_types_engine::{ExecutionPayload, ExecutionPayloadSidecar, PayloadError};
pub use error::BeaconOnNewPayloadError; pub use error::BeaconOnNewPayloadError;
mod forkchoice; mod forkchoice;
@ -24,6 +27,9 @@ pub use reth_payload_primitives::{
BuiltPayload, EngineApiMessageVersion, EngineObjectValidationError, PayloadOrAttributes, BuiltPayload, EngineApiMessageVersion, EngineObjectValidationError, PayloadOrAttributes,
PayloadTypes, PayloadTypes,
}; };
use reth_payload_primitives::{InvalidPayloadAttributesError, PayloadAttributes};
use reth_primitives::SealedBlockFor;
use reth_primitives_traits::Block;
use serde::{de::DeserializeOwned, ser::Serialize}; use serde::{de::DeserializeOwned, ser::Serialize};
/// This type defines the versioned types of the engine API. /// This type defines the versioned types of the engine API.
@ -74,8 +80,11 @@ pub trait EngineTypes:
+ 'static; + 'static;
} }
/// Type that validates the payloads sent to the engine. /// Type that validates the payloads processed by the engine.
pub trait EngineValidator<Types: EngineTypes>: Clone + Send + Sync + Unpin + 'static { pub trait EngineValidator<Types: EngineTypes>: Clone + Send + Sync + Unpin + 'static {
/// The block type used by the engine.
type Block: Block;
/// Validates the presence or exclusion of fork-specific fields based on the payload attributes /// Validates the presence or exclusion of fork-specific fields based on the payload attributes
/// and the message version. /// and the message version.
fn validate_version_specific_fields( fn validate_version_specific_fields(
@ -90,4 +99,38 @@ pub trait EngineValidator<Types: EngineTypes>: Clone + Send + Sync + Unpin + 'st
version: EngineApiMessageVersion, version: EngineApiMessageVersion,
attributes: &<Types as PayloadTypes>::PayloadAttributes, attributes: &<Types as PayloadTypes>::PayloadAttributes,
) -> Result<(), EngineObjectValidationError>; ) -> Result<(), EngineObjectValidationError>;
/// Ensures that the given payload does not violate any consensus rules that concern the block's
/// layout.
///
/// This function must convert the payload into the executable block and pre-validate its
/// fields.
///
/// Implementers should ensure that the checks are done in the order that conforms with the
/// engine-API specification.
fn ensure_well_formed_payload(
&self,
payload: ExecutionPayload,
sidecar: ExecutionPayloadSidecar,
) -> Result<SealedBlockFor<Self::Block>, PayloadError>;
/// Validates the payload attributes with respect to the header.
///
/// By default, this enforces that the payload attributes timestamp is greater than the
/// timestamp according to:
/// > 7. Client software MUST ensure that payloadAttributes.timestamp is greater than
/// > timestamp
/// > of a block referenced by forkchoiceState.headBlockHash.
///
/// See also [engine api spec](https://github.com/ethereum/execution-apis/tree/fe8e13c288c592ec154ce25c534e26cb7ce0530d/src/engine)
fn validate_payload_attributes_against_header(
&self,
attr: &<Types as PayloadTypes>::PayloadAttributes,
header: &<Self::Block as Block>::Header,
) -> Result<(), InvalidPayloadAttributesError> {
if attr.timestamp() <= header.timestamp() {
return Err(InvalidPayloadAttributesError::InvalidTimestamp);
}
Ok(())
}
} }

View File

@ -16,6 +16,7 @@ reth-chainspec.workspace = true
reth-primitives.workspace = true reth-primitives.workspace = true
reth-engine-primitives.workspace = true reth-engine-primitives.workspace = true
reth-payload-primitives.workspace = true reth-payload-primitives.workspace = true
reth-payload-validator.workspace = true
reth-rpc-types-compat.workspace = true reth-rpc-types-compat.workspace = true
alloy-rlp.workspace = true alloy-rlp.workspace = true
reth-chain-state.workspace = true reth-chain-state.workspace = true

View File

@ -11,6 +11,7 @@
mod payload; mod payload;
use std::sync::Arc; use std::sync::Arc;
use alloy_rpc_types_engine::{ExecutionPayload, ExecutionPayloadSidecar, PayloadError};
pub use alloy_rpc_types_engine::{ pub use alloy_rpc_types_engine::{
ExecutionPayloadEnvelopeV2, ExecutionPayloadEnvelopeV3, ExecutionPayloadEnvelopeV4, ExecutionPayloadEnvelopeV2, ExecutionPayloadEnvelopeV3, ExecutionPayloadEnvelopeV4,
ExecutionPayloadV1, PayloadAttributes as EthPayloadAttributes, ExecutionPayloadV1, PayloadAttributes as EthPayloadAttributes,
@ -22,6 +23,8 @@ use reth_payload_primitives::{
validate_version_specific_fields, EngineApiMessageVersion, EngineObjectValidationError, validate_version_specific_fields, EngineApiMessageVersion, EngineObjectValidationError,
PayloadOrAttributes, PayloadTypes, PayloadOrAttributes, PayloadTypes,
}; };
use reth_payload_validator::ExecutionPayloadValidator;
use reth_primitives::{Block, SealedBlock};
/// The types used in the default mainnet ethereum beacon consensus engine. /// The types used in the default mainnet ethereum beacon consensus engine.
#[derive(Debug, Default, Clone, serde::Deserialize, serde::Serialize)] #[derive(Debug, Default, Clone, serde::Deserialize, serde::Serialize)]
@ -63,13 +66,19 @@ impl PayloadTypes for EthPayloadTypes {
/// Validator for the ethereum engine API. /// Validator for the ethereum engine API.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct EthereumEngineValidator { pub struct EthereumEngineValidator {
chain_spec: Arc<ChainSpec>, inner: ExecutionPayloadValidator<ChainSpec>,
} }
impl EthereumEngineValidator { impl EthereumEngineValidator {
/// Instantiates a new validator. /// Instantiates a new validator.
pub const fn new(chain_spec: Arc<ChainSpec>) -> Self { pub const fn new(chain_spec: Arc<ChainSpec>) -> Self {
Self { chain_spec } Self { inner: ExecutionPayloadValidator::new(chain_spec) }
}
/// Returns the chain spec used by the validator.
#[inline]
fn chain_spec(&self) -> &ChainSpec {
self.inner.chain_spec()
} }
} }
@ -77,12 +86,14 @@ impl<Types> EngineValidator<Types> for EthereumEngineValidator
where where
Types: EngineTypes<PayloadAttributes = EthPayloadAttributes>, Types: EngineTypes<PayloadAttributes = EthPayloadAttributes>,
{ {
type Block = Block;
fn validate_version_specific_fields( fn validate_version_specific_fields(
&self, &self,
version: EngineApiMessageVersion, version: EngineApiMessageVersion,
payload_or_attrs: PayloadOrAttributes<'_, EthPayloadAttributes>, payload_or_attrs: PayloadOrAttributes<'_, EthPayloadAttributes>,
) -> Result<(), EngineObjectValidationError> { ) -> Result<(), EngineObjectValidationError> {
validate_version_specific_fields(&self.chain_spec, version, payload_or_attrs) validate_version_specific_fields(self.chain_spec(), version, payload_or_attrs)
} }
fn ensure_well_formed_attributes( fn ensure_well_formed_attributes(
@ -90,6 +101,14 @@ where
version: EngineApiMessageVersion, version: EngineApiMessageVersion,
attributes: &EthPayloadAttributes, attributes: &EthPayloadAttributes,
) -> Result<(), EngineObjectValidationError> { ) -> Result<(), EngineObjectValidationError> {
validate_version_specific_fields(&self.chain_spec, version, attributes.into()) validate_version_specific_fields(self.chain_spec(), version, attributes.into())
}
fn ensure_well_formed_payload(
&self,
payload: ExecutionPayload,
sidecar: ExecutionPayloadSidecar,
) -> Result<SealedBlock, PayloadError> {
self.inner.ensure_well_formed_payload(payload, sidecar)
} }
} }

View File

@ -18,6 +18,7 @@ reth-engine-local.workspace = true
reth-primitives.workspace = true reth-primitives.workspace = true
reth-payload-builder.workspace = true reth-payload-builder.workspace = true
reth-payload-util.workspace = true reth-payload-util.workspace = true
reth-payload-validator.workspace = true
reth-basic-payload-builder.workspace = true reth-basic-payload-builder.workspace = true
reth-consensus.workspace = true reth-consensus.workspace = true
reth-node-api.workspace = true reth-node-api.workspace = true

View File

@ -1,6 +1,7 @@
use std::sync::Arc; use alloy_rpc_types_engine::{
ExecutionPayload, ExecutionPayloadEnvelopeV2, ExecutionPayloadSidecar, ExecutionPayloadV1,
use alloy_rpc_types_engine::{ExecutionPayloadEnvelopeV2, ExecutionPayloadV1}; PayloadError,
};
use op_alloy_rpc_types_engine::{ use op_alloy_rpc_types_engine::{
OpExecutionPayloadEnvelopeV3, OpExecutionPayloadEnvelopeV4, OpPayloadAttributes, OpExecutionPayloadEnvelopeV3, OpExecutionPayloadEnvelopeV4, OpPayloadAttributes,
}; };
@ -16,6 +17,9 @@ use reth_node_api::{
use reth_optimism_chainspec::OpChainSpec; use reth_optimism_chainspec::OpChainSpec;
use reth_optimism_forks::{OpHardfork, OpHardforks}; use reth_optimism_forks::{OpHardfork, OpHardforks};
use reth_optimism_payload_builder::{OpBuiltPayload, OpPayloadBuilderAttributes}; use reth_optimism_payload_builder::{OpBuiltPayload, OpPayloadBuilderAttributes};
use reth_payload_validator::ExecutionPayloadValidator;
use reth_primitives::{Block, SealedBlockFor};
use std::sync::Arc;
/// The types used in the optimism beacon consensus engine. /// The types used in the optimism beacon consensus engine.
#[derive(Debug, Default, Clone, serde::Deserialize, serde::Serialize)] #[derive(Debug, Default, Clone, serde::Deserialize, serde::Serialize)]
@ -57,13 +61,88 @@ impl PayloadTypes for OpPayloadTypes {
/// Validator for Optimism engine API. /// Validator for Optimism engine API.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct OpEngineValidator { pub struct OpEngineValidator {
chain_spec: Arc<OpChainSpec>, inner: ExecutionPayloadValidator<OpChainSpec>,
} }
impl OpEngineValidator { impl OpEngineValidator {
/// Instantiates a new validator. /// Instantiates a new validator.
pub const fn new(chain_spec: Arc<OpChainSpec>) -> Self { pub const fn new(chain_spec: Arc<OpChainSpec>) -> Self {
Self { chain_spec } Self { inner: ExecutionPayloadValidator::new(chain_spec) }
}
/// Returns the chain spec used by the validator.
#[inline]
fn chain_spec(&self) -> &OpChainSpec {
self.inner.chain_spec()
}
}
impl<Types> EngineValidator<Types> for OpEngineValidator
where
Types: EngineTypes<PayloadAttributes = OpPayloadAttributes>,
{
type Block = Block;
fn validate_version_specific_fields(
&self,
version: EngineApiMessageVersion,
payload_or_attrs: PayloadOrAttributes<'_, OpPayloadAttributes>,
) -> Result<(), EngineObjectValidationError> {
validate_withdrawals_presence(
self.chain_spec(),
version,
payload_or_attrs.message_validation_kind(),
payload_or_attrs.timestamp(),
payload_or_attrs.withdrawals().is_some(),
)?;
validate_parent_beacon_block_root_presence(
self.chain_spec(),
version,
payload_or_attrs.message_validation_kind(),
payload_or_attrs.timestamp(),
payload_or_attrs.parent_beacon_block_root().is_some(),
)
}
fn ensure_well_formed_attributes(
&self,
version: EngineApiMessageVersion,
attributes: &OpPayloadAttributes,
) -> Result<(), EngineObjectValidationError> {
validate_version_specific_fields(self.chain_spec(), version, attributes.into())?;
if attributes.gas_limit.is_none() {
return Err(EngineObjectValidationError::InvalidParams(
"MissingGasLimitInPayloadAttributes".to_string().into(),
))
}
if self
.chain_spec()
.is_holocene_active_at_timestamp(attributes.payload_attributes.timestamp)
{
let (elasticity, denominator) =
attributes.decode_eip_1559_params().ok_or_else(|| {
EngineObjectValidationError::InvalidParams(
"MissingEip1559ParamsInPayloadAttributes".to_string().into(),
)
})?;
if elasticity != 0 && denominator == 0 {
return Err(EngineObjectValidationError::InvalidParams(
"Eip1559ParamsDenominatorZero".to_string().into(),
))
}
}
Ok(())
}
fn ensure_well_formed_payload(
&self,
payload: ExecutionPayload,
sidecar: ExecutionPayloadSidecar,
) -> Result<SealedBlockFor<Self::Block>, PayloadError> {
self.inner.ensure_well_formed_payload(payload, sidecar)
} }
} }
@ -109,63 +188,6 @@ pub fn validate_withdrawals_presence(
Ok(()) Ok(())
} }
impl<Types> EngineValidator<Types> for OpEngineValidator
where
Types: EngineTypes<PayloadAttributes = OpPayloadAttributes>,
{
fn validate_version_specific_fields(
&self,
version: EngineApiMessageVersion,
payload_or_attrs: PayloadOrAttributes<'_, OpPayloadAttributes>,
) -> Result<(), EngineObjectValidationError> {
validate_withdrawals_presence(
&self.chain_spec,
version,
payload_or_attrs.message_validation_kind(),
payload_or_attrs.timestamp(),
payload_or_attrs.withdrawals().is_some(),
)?;
validate_parent_beacon_block_root_presence(
&self.chain_spec,
version,
payload_or_attrs.message_validation_kind(),
payload_or_attrs.timestamp(),
payload_or_attrs.parent_beacon_block_root().is_some(),
)
}
fn ensure_well_formed_attributes(
&self,
version: EngineApiMessageVersion,
attributes: &OpPayloadAttributes,
) -> Result<(), EngineObjectValidationError> {
validate_version_specific_fields(&self.chain_spec, version, attributes.into())?;
if attributes.gas_limit.is_none() {
return Err(EngineObjectValidationError::InvalidParams(
"MissingGasLimitInPayloadAttributes".to_string().into(),
))
}
if self.chain_spec.is_holocene_active_at_timestamp(attributes.payload_attributes.timestamp)
{
let (elasticity, denominator) =
attributes.decode_eip_1559_params().ok_or_else(|| {
EngineObjectValidationError::InvalidParams(
"MissingEip1559ParamsInPayloadAttributes".to_string().into(),
)
})?;
if elasticity != 0 && denominator == 0 {
return Err(EngineObjectValidationError::InvalidParams(
"Eip1559ParamsDenominatorZero".to_string().into(),
))
}
}
Ok(())
}
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {

View File

@ -1,6 +1,7 @@
//! Error types emitted by types or implementations of this crate. //! Error types emitted by types or implementations of this crate.
use alloy_primitives::B256; use alloy_primitives::B256;
use alloy_rpc_types_engine::ForkchoiceUpdateError;
use reth_errors::{ProviderError, RethError}; use reth_errors::{ProviderError, RethError};
use revm_primitives::EVMError; use revm_primitives::EVMError;
use tokio::sync::oneshot; use tokio::sync::oneshot;
@ -53,7 +54,7 @@ impl From<oneshot::error::RecvError> for PayloadBuilderError {
} }
} }
/// Thrown when the payload or attributes are known to be invalid before processing. /// Thrown when the payload or attributes are known to be invalid __before__ processing.
/// ///
/// This is used mainly for /// This is used mainly for
/// [`validate_version_specific_fields`](crate::validate_version_specific_fields), which validates /// [`validate_version_specific_fields`](crate::validate_version_specific_fields), which validates
@ -115,3 +116,20 @@ impl EngineObjectValidationError {
Self::InvalidParams(Box::new(error)) Self::InvalidParams(Box::new(error))
} }
} }
/// Thrown when validating the correctness of a payloadattributes object.
#[derive(thiserror::Error, Debug)]
pub enum InvalidPayloadAttributesError {
/// Thrown if the timestamp of the payload attributes is invalid according to the engine specs.
#[error("parent beacon block root not supported before V3")]
InvalidTimestamp,
/// Another type of error that is not covered by the above variants.
#[error("Invalid params: {0}")]
InvalidParams(#[from] Box<dyn core::error::Error + Send + Sync>),
}
impl From<InvalidPayloadAttributesError> for ForkchoiceUpdateError {
fn from(_: InvalidPayloadAttributesError) -> Self {
Self::UpdatedInvalidPayloadAttributes
}
}

View File

@ -9,7 +9,10 @@
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
mod error; mod error;
pub use error::{EngineObjectValidationError, PayloadBuilderError, VersionSpecificValidationError}; pub use error::{
EngineObjectValidationError, InvalidPayloadAttributesError, PayloadBuilderError,
VersionSpecificValidationError,
};
/// Contains traits to abstract over payload attributes types and default implementations of the /// Contains traits to abstract over payload attributes types and default implementations of the
/// [`PayloadAttributes`] trait for ethereum mainnet and optimism types. /// [`PayloadAttributes`] trait for ethereum mainnet and optimism types.

View File

@ -17,11 +17,6 @@
#![cfg_attr(not(test), warn(unused_crate_dependencies))] #![cfg_attr(not(test), warn(unused_crate_dependencies))]
use std::{convert::Infallible, sync::Arc};
use serde::{Deserialize, Serialize};
use thiserror::Error;
use alloy_eips::eip4895::Withdrawals; use alloy_eips::eip4895::Withdrawals;
use alloy_genesis::Genesis; use alloy_genesis::Genesis;
use alloy_primitives::{Address, B256}; use alloy_primitives::{Address, B256};
@ -33,7 +28,7 @@ use alloy_rpc_types::{
Withdrawal, Withdrawal,
}; };
use reth::{ use reth::{
api::PayloadTypes, api::{InvalidPayloadAttributesError, PayloadTypes},
builder::{ builder::{
components::{ComponentsBuilder, PayloadServiceBuilder}, components::{ComponentsBuilder, PayloadServiceBuilder},
node::{NodeTypes, NodeTypesWithEngine}, node::{NodeTypes, NodeTypesWithEngine},
@ -42,9 +37,13 @@ use reth::{
PayloadBuilderConfig, PayloadBuilderConfig,
}, },
network::NetworkHandle, network::NetworkHandle,
primitives::EthPrimitives, payload::ExecutionPayloadValidator,
primitives::{Block, EthPrimitives, SealedBlockFor},
providers::{CanonStateSubscriptions, EthStorage, StateProviderFactory}, providers::{CanonStateSubscriptions, EthStorage, StateProviderFactory},
rpc::eth::EthApi, rpc::{
eth::EthApi,
types::engine::{ExecutionPayload, ExecutionPayloadSidecar, PayloadError},
},
tasks::TaskManager, tasks::TaskManager,
transaction_pool::TransactionPool, transaction_pool::TransactionPool,
}; };
@ -72,6 +71,9 @@ use reth_payload_builder::{
}; };
use reth_tracing::{RethTracer, Tracer}; use reth_tracing::{RethTracer, Tracer};
use reth_trie_db::MerklePatriciaTrie; use reth_trie_db::MerklePatriciaTrie;
use serde::{Deserialize, Serialize};
use std::{convert::Infallible, sync::Arc};
use thiserror::Error;
/// A custom payload attributes type. /// A custom payload attributes type.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
@ -171,19 +173,34 @@ impl EngineTypes for CustomEngineTypes {
/// Custom engine validator /// Custom engine validator
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct CustomEngineValidator { pub struct CustomEngineValidator {
chain_spec: Arc<ChainSpec>, inner: ExecutionPayloadValidator<ChainSpec>,
}
impl CustomEngineValidator {
/// Instantiates a new validator.
pub const fn new(chain_spec: Arc<ChainSpec>) -> Self {
Self { inner: ExecutionPayloadValidator::new(chain_spec) }
}
/// Returns the chain spec used by the validator.
#[inline]
fn chain_spec(&self) -> &ChainSpec {
self.inner.chain_spec()
}
} }
impl<T> EngineValidator<T> for CustomEngineValidator impl<T> EngineValidator<T> for CustomEngineValidator
where where
T: EngineTypes<PayloadAttributes = CustomPayloadAttributes>, T: EngineTypes<PayloadAttributes = CustomPayloadAttributes>,
{ {
type Block = Block;
fn validate_version_specific_fields( fn validate_version_specific_fields(
&self, &self,
version: EngineApiMessageVersion, version: EngineApiMessageVersion,
payload_or_attrs: PayloadOrAttributes<'_, T::PayloadAttributes>, payload_or_attrs: PayloadOrAttributes<'_, T::PayloadAttributes>,
) -> Result<(), EngineObjectValidationError> { ) -> Result<(), EngineObjectValidationError> {
validate_version_specific_fields(&self.chain_spec, version, payload_or_attrs) validate_version_specific_fields(self.chain_spec(), version, payload_or_attrs)
} }
fn ensure_well_formed_attributes( fn ensure_well_formed_attributes(
@ -191,7 +208,7 @@ where
version: EngineApiMessageVersion, version: EngineApiMessageVersion,
attributes: &T::PayloadAttributes, attributes: &T::PayloadAttributes,
) -> Result<(), EngineObjectValidationError> { ) -> Result<(), EngineObjectValidationError> {
validate_version_specific_fields(&self.chain_spec, version, attributes.into())?; validate_version_specific_fields(self.chain_spec(), version, attributes.into())?;
// custom validation logic - ensure that the custom field is not zero // custom validation logic - ensure that the custom field is not zero
if attributes.custom == 0 { if attributes.custom == 0 {
@ -202,6 +219,23 @@ where
Ok(()) Ok(())
} }
fn ensure_well_formed_payload(
&self,
payload: ExecutionPayload,
sidecar: ExecutionPayloadSidecar,
) -> Result<SealedBlockFor<Self::Block>, PayloadError> {
self.inner.ensure_well_formed_payload(payload, sidecar)
}
fn validate_payload_attributes_against_header(
&self,
_attr: &<T as PayloadTypes>::PayloadAttributes,
_header: &<Self::Block as reth::api::Block>::Header,
) -> Result<(), InvalidPayloadAttributesError> {
// skip default timestamp validation
Ok(())
}
} }
/// Custom engine validator builder /// Custom engine validator builder
@ -218,7 +252,7 @@ where
type Validator = CustomEngineValidator; type Validator = CustomEngineValidator;
async fn build(self, ctx: &AddOnsContext<'_, N>) -> eyre::Result<Self::Validator> { async fn build(self, ctx: &AddOnsContext<'_, N>) -> eyre::Result<Self::Validator> {
Ok(CustomEngineValidator { chain_spec: ctx.config.chain.clone() }) Ok(CustomEngineValidator::new(ctx.config.chain.clone()))
} }
} }