feat: Introduce payload primitives (#8642)

Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
This commit is contained in:
jn
2024-06-06 16:19:21 -07:00
committed by GitHub
parent f80b054174
commit c362fc6c36
31 changed files with 558 additions and 361 deletions

View File

@ -0,0 +1,26 @@
[package]
name = "reth-payload-primitives"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true
exclude.workspace = true
[lints]
workspace = true
[dependencies]
# reth
reth-errors.workspace = true
reth-primitives.workspace = true
reth-transaction-pool.workspace = true
reth-rpc-types.workspace = true
# async
tokio = { workspace = true, features = ["sync"] }
# misc
thiserror.workspace = true
serde.workspace = true

View File

@ -0,0 +1,117 @@
//! Error types emitted by types or implementations of this crate.
use reth_errors::{ProviderError, RethError};
use reth_primitives::{revm_primitives::EVMError, B256};
use reth_transaction_pool::BlobStoreError;
use tokio::sync::oneshot;
/// Possible error variants during payload building.
#[derive(Debug, thiserror::Error)]
pub enum PayloadBuilderError {
/// Thrown when the parent block is missing.
#[error("missing parent block {0}")]
MissingParentBlock(B256),
/// An oneshot channels has been closed.
#[error("sender has been dropped")]
ChannelClosed,
/// Error occurring in the blob store.
#[error(transparent)]
BlobStore(#[from] BlobStoreError),
/// Other internal error
#[error(transparent)]
Internal(#[from] RethError),
/// Unrecoverable error during evm execution.
#[error("evm execution error: {0}")]
EvmExecutionError(EVMError<ProviderError>),
/// Thrown if the payload requests withdrawals before Shanghai activation.
#[error("withdrawals set before Shanghai activation")]
WithdrawalsBeforeShanghai,
/// Any other payload building errors.
#[error(transparent)]
Other(Box<dyn std::error::Error + Send + Sync>),
}
impl PayloadBuilderError {
/// Create a new error from a boxed error.
pub fn other<E>(error: E) -> Self
where
E: std::error::Error + Send + Sync + 'static,
{
Self::Other(Box::new(error))
}
}
impl From<ProviderError> for PayloadBuilderError {
fn from(error: ProviderError) -> Self {
Self::Internal(RethError::Provider(error))
}
}
impl From<oneshot::error::RecvError> for PayloadBuilderError {
fn from(_: oneshot::error::RecvError) -> Self {
Self::ChannelClosed
}
}
/// Thrown when the payload or attributes are known to be invalid before processing.
///
/// This is used mainly for
/// [`validate_version_specific_fields`](crate::validate_version_specific_fields), which validates
/// both execution payloads and forkchoice update attributes with respect to a method version.
#[derive(thiserror::Error, Debug)]
pub enum EngineObjectValidationError {
/// Thrown when the underlying validation error occurred while validating an
/// `ExecutionPayload`.
#[error("Payload validation error: {0}")]
Payload(VersionSpecificValidationError),
/// Thrown when the underlying validation error occurred while validating a
/// `PayloadAttributes`.
#[error("Payload attributes validation error: {0}")]
PayloadAttributes(VersionSpecificValidationError),
/// Thrown if `PayloadAttributes` or `ExecutionPayload` were provided with a timestamp, but the
/// version of the engine method called is meant for a fork that occurs after the provided
/// timestamp.
#[error("Unsupported fork")]
UnsupportedFork,
/// Another type of error that is not covered by the above variants.
#[error("Invalid params: {0}")]
InvalidParams(#[from] Box<dyn std::error::Error + Send + Sync>),
}
/// Thrown when validating an execution payload OR payload attributes fails due to:
/// * The existence of a new field that is not supported in the given engine method version, or
/// * The absence of a field that is required in the given engine method version
#[derive(thiserror::Error, Debug)]
pub enum VersionSpecificValidationError {
/// Thrown if the pre-V3 `PayloadAttributes` or `ExecutionPayload` contains a parent beacon
/// block root
#[error("parent beacon block root not supported before V3")]
ParentBeaconBlockRootNotSupportedBeforeV3,
/// Thrown if `engine_forkchoiceUpdatedV1` or `engine_newPayloadV1` contains withdrawals
#[error("withdrawals not supported in V1")]
WithdrawalsNotSupportedInV1,
/// Thrown if `engine_forkchoiceUpdated` or `engine_newPayload` contains no withdrawals after
/// Shanghai
#[error("no withdrawals post-Shanghai")]
NoWithdrawalsPostShanghai,
/// Thrown if `engine_forkchoiceUpdated` or `engine_newPayload` contains withdrawals before
/// Shanghai
#[error("withdrawals pre-Shanghai")]
HasWithdrawalsPreShanghai,
/// Thrown if the `PayloadAttributes` or `ExecutionPayload` contains no parent beacon block
/// root after Cancun
#[error("no parent beacon block root post-cancun")]
NoParentBeaconBlockRootPostCancun,
}
impl EngineObjectValidationError {
/// Creates an instance of the `InvalidParams` variant with the given error.
pub fn invalid_params<E>(error: E) -> Self
where
E: std::error::Error + Send + Sync + 'static,
{
Self::InvalidParams(Box::new(error))
}
}

View File

@ -0,0 +1,333 @@
//! This crate defines abstractions to create and update payloads (blocks)
#![doc(
html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png",
html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256",
issue_tracker_base_url = "https://github.com/paradigmxyz/reth/issues/"
)]
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
mod error;
pub use error::{EngineObjectValidationError, PayloadBuilderError, VersionSpecificValidationError};
/// Contains traits to abstract over payload attributes types and default implementations of the
/// [`PayloadAttributes`] trait for ethereum mainnet and optimism types.
mod traits;
pub use traits::{BuiltPayload, PayloadAttributes, PayloadBuilderAttributes};
mod payload;
pub use payload::PayloadOrAttributes;
use reth_primitives::ChainSpec;
use std::fmt::Debug;
/// Validates the timestamp depending on the version called:
///
/// * If V2, this ensures that the payload timestamp is pre-Cancun.
/// * If V3, this ensures that the payload timestamp is within the Cancun timestamp.
/// * If V4, this ensures that the payload timestamp is within the Prague timestamp.
///
/// Otherwise, this will return [`EngineObjectValidationError::UnsupportedFork`].
pub fn validate_payload_timestamp(
chain_spec: &ChainSpec,
version: EngineApiMessageVersion,
timestamp: u64,
) -> Result<(), EngineObjectValidationError> {
let is_cancun = chain_spec.is_cancun_active_at_timestamp(timestamp);
if version == EngineApiMessageVersion::V2 && is_cancun {
// From the Engine API spec:
//
// ### Update the methods of previous forks
//
// This document defines how Cancun payload should be handled by the [`Shanghai
// API`](https://github.com/ethereum/execution-apis/blob/ff43500e653abde45aec0f545564abfb648317af/src/engine/shanghai.md).
//
// For the following methods:
//
// - [`engine_forkchoiceUpdatedV2`](https://github.com/ethereum/execution-apis/blob/ff43500e653abde45aec0f545564abfb648317af/src/engine/shanghai.md#engine_forkchoiceupdatedv2)
// - [`engine_newPayloadV2`](https://github.com/ethereum/execution-apis/blob/ff43500e653abde45aec0f545564abfb648317af/src/engine/shanghai.md#engine_newpayloadV2)
// - [`engine_getPayloadV2`](https://github.com/ethereum/execution-apis/blob/ff43500e653abde45aec0f545564abfb648317af/src/engine/shanghai.md#engine_getpayloadv2)
//
// a validation **MUST** be added:
//
// 1. Client software **MUST** return `-38005: Unsupported fork` error if the `timestamp` of
// payload or payloadAttributes is greater or equal to the Cancun activation timestamp.
return Err(EngineObjectValidationError::UnsupportedFork)
}
if version == EngineApiMessageVersion::V3 && !is_cancun {
// From the Engine API spec:
// <https://github.com/ethereum/execution-apis/blob/ff43500e653abde45aec0f545564abfb648317af/src/engine/cancun.md#specification-2>
//
// For `engine_getPayloadV3`:
//
// 1. Client software **MUST** return `-38005: Unsupported fork` error if the `timestamp` of
// the built payload does not fall within the time frame of the Cancun fork.
//
// For `engine_forkchoiceUpdatedV3`:
//
// 2. Client software **MUST** return `-38005: Unsupported fork` error if the
// `payloadAttributes` is set and the `payloadAttributes.timestamp` does not fall within
// the time frame of the Cancun fork.
//
// For `engine_newPayloadV3`:
//
// 2. Client software **MUST** return `-38005: Unsupported fork` error if the `timestamp` of
// the payload does not fall within the time frame of the Cancun fork.
return Err(EngineObjectValidationError::UnsupportedFork)
}
let is_prague = chain_spec.is_prague_active_at_timestamp(timestamp);
if version == EngineApiMessageVersion::V4 && !is_prague {
// From the Engine API spec:
// <https://github.com/ethereum/execution-apis/blob/7907424db935b93c2fe6a3c0faab943adebe8557/src/engine/prague.md#specification-1>
//
// For `engine_getPayloadV4`:
//
// 1. Client software **MUST** return `-38005: Unsupported fork` error if the `timestamp` of
// the built payload does not fall within the time frame of the Prague fork.
//
// For `engine_forkchoiceUpdatedV4`:
//
// 2. Client software **MUST** return `-38005: Unsupported fork` error if the
// `payloadAttributes` is set and the `payloadAttributes.timestamp` does not fall within
// the time frame of the Prague fork.
//
// For `engine_newPayloadV4`:
//
// 2. Client software **MUST** return `-38005: Unsupported fork` error if the `timestamp` of
// the payload does not fall within the time frame of the Prague fork.
return Err(EngineObjectValidationError::UnsupportedFork)
}
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];
pub fn validate_withdrawals_presence(
chain_spec: &ChainSpec,
version: EngineApiMessageVersion,
message_validation_kind: MessageValidationKind,
timestamp: u64,
has_withdrawals: bool,
) -> Result<(), EngineObjectValidationError> {
let is_shanghai_active = chain_spec.is_shanghai_active_at_timestamp(timestamp);
match version {
EngineApiMessageVersion::V1 => {
if has_withdrawals {
return Err(message_validation_kind
.to_error(VersionSpecificValidationError::WithdrawalsNotSupportedInV1))
}
}
EngineApiMessageVersion::V2 | EngineApiMessageVersion::V3 | EngineApiMessageVersion::V4 => {
if is_shanghai_active && !has_withdrawals {
return Err(message_validation_kind
.to_error(VersionSpecificValidationError::NoWithdrawalsPostShanghai))
}
if !is_shanghai_active && has_withdrawals {
return Err(message_validation_kind
.to_error(VersionSpecificValidationError::HasWithdrawalsPreShanghai))
}
}
};
Ok(())
}
/// Validate the presence of the `parentBeaconBlockRoot` field according to the given timestamp.
/// This method is meant to be used with either a `payloadAttributes` field or a full payload, with
/// the `engine_forkchoiceUpdated` and `engine_newPayload` methods respectively.
///
/// After Cancun, the `parentBeaconBlockRoot` field must be [Some].
/// Before Cancun, the `parentBeaconBlockRoot` field must be [None].
///
/// If the engine API message version is V1 or V2, and the timestamp is post-Cancun, then this will
/// return [`EngineObjectValidationError::UnsupportedFork`].
///
/// If the timestamp is before the Cancun fork and the engine API message version is V3, then this
/// will return [`EngineObjectValidationError::UnsupportedFork`].
///
/// If the engine API message version is V3, but the `parentBeaconBlockRoot` is [None], then
/// this will return [`VersionSpecificValidationError::NoParentBeaconBlockRootPostCancun`].
///
/// This implements the following Engine API spec rules:
///
/// 1. Client software **MUST** check that provided set of parameters and their fields strictly
/// matches the expected one and return `-32602: Invalid params` error if this check fails. Any
/// field having `null` value **MUST** be considered as not provided.
///
/// For `engine_forkchoiceUpdatedV3`:
///
/// 1. Client software **MUST** check that provided set of parameters and their fields strictly
/// matches the expected one and return `-32602: Invalid params` error if this check fails. Any
/// field having `null` value **MUST** be considered as not provided.
///
/// 2. Extend point (7) of the `engine_forkchoiceUpdatedV1` specification by defining the following
/// sequence of checks that **MUST** be run over `payloadAttributes`:
/// 1. `payloadAttributes` matches the `PayloadAttributesV3` structure, return `-38003: Invalid
/// payload attributes` on failure.
/// 2. `payloadAttributes.timestamp` falls within the time frame of the Cancun fork, return
/// `-38005: Unsupported fork` on failure.
/// 3. `payloadAttributes.timestamp` is greater than `timestamp` of a block referenced by
/// `forkchoiceState.headBlockHash`, return `-38003: Invalid payload attributes` on failure.
/// 4. If any of the above checks fails, the `forkchoiceState` update **MUST NOT** be rolled
/// back.
///
/// For `engine_newPayloadV3`:
///
/// 2. Client software **MUST** return `-38005: Unsupported fork` error if the `timestamp` of the
/// payload does not fall within the time frame of the Cancun fork.
///
/// For `engine_newPayloadV4`:
///
/// 2. Client software **MUST** return `-38005: Unsupported fork` error if the `timestamp` of the
/// payload does not fall within the time frame of the Prague fork.
///
/// Returning the right error code (ie, if the client should return `-38003: Invalid payload
/// attributes` is handled by the `message_validation_kind` parameter. If the parameter is
/// `MessageValidationKind::Payload`, then the error code will be `-32602: Invalid params`. If the
/// parameter is `MessageValidationKind::PayloadAttributes`, then the error code will be `-38003:
/// Invalid payload attributes`.
pub fn validate_parent_beacon_block_root_presence(
chain_spec: &ChainSpec,
version: EngineApiMessageVersion,
validation_kind: MessageValidationKind,
timestamp: u64,
has_parent_beacon_block_root: bool,
) -> Result<(), EngineObjectValidationError> {
// 1. Client software **MUST** check that provided set of parameters and their fields strictly
// matches the expected one and return `-32602: Invalid params` error if this check fails.
// Any field having `null` value **MUST** be considered as not provided.
//
// For `engine_forkchoiceUpdatedV3`:
//
// 2. Extend point (7) of the `engine_forkchoiceUpdatedV1` specification by defining the
// following sequence of checks that **MUST** be run over `payloadAttributes`:
// 1. `payloadAttributes` matches the `PayloadAttributesV3` structure, return `-38003:
// Invalid payload attributes` on failure.
// 2. `payloadAttributes.timestamp` falls within the time frame of the Cancun fork, return
// `-38005: Unsupported fork` on failure.
// 3. `payloadAttributes.timestamp` is greater than `timestamp` of a block referenced by
// `forkchoiceState.headBlockHash`, return `-38003: Invalid payload attributes` on
// failure.
// 4. If any of the above checks fails, the `forkchoiceState` update **MUST NOT** be rolled
// back.
match version {
EngineApiMessageVersion::V1 | EngineApiMessageVersion::V2 => {
if has_parent_beacon_block_root {
return Err(validation_kind.to_error(
VersionSpecificValidationError::ParentBeaconBlockRootNotSupportedBeforeV3,
))
}
}
EngineApiMessageVersion::V3 | EngineApiMessageVersion::V4 => {
if !has_parent_beacon_block_root {
return Err(validation_kind
.to_error(VersionSpecificValidationError::NoParentBeaconBlockRootPostCancun))
}
}
};
// For `engine_forkchoiceUpdatedV3`:
//
// 2. Client software **MUST** return `-38005: Unsupported fork` error if the
// `payloadAttributes` is set and the `payloadAttributes.timestamp` does not fall within the
// time frame of the Cancun fork.
//
// For `engine_newPayloadV3`:
//
// 2. Client software **MUST** return `-38005: Unsupported fork` error if the `timestamp` of the
// payload does not fall within the time frame of the Cancun fork.
validate_payload_timestamp(chain_spec, version, timestamp)?;
Ok(())
}
/// A type that represents whether or not we are validating a payload or payload attributes.
///
/// This is used to ensure that the correct error code is returned when validating the payload or
/// payload attributes.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MessageValidationKind {
/// We are validating fields of a payload attributes.
PayloadAttributes,
/// We are validating fields of a payload.
Payload,
}
impl MessageValidationKind {
/// Returns an `EngineObjectValidationError` based on the given
/// `VersionSpecificValidationError` and the current validation kind.
pub const fn to_error(
self,
error: VersionSpecificValidationError,
) -> EngineObjectValidationError {
match self {
Self::Payload => EngineObjectValidationError::Payload(error),
Self::PayloadAttributes => EngineObjectValidationError::PayloadAttributes(error),
}
}
}
/// Validates the presence or exclusion of fork-specific fields based on the ethereum execution
/// payload, or payload attributes, and the message version.
///
/// The object being validated is provided by the [`PayloadOrAttributes`] argument, which can be
/// either an execution payload, or payload attributes.
///
/// The version is provided by the [`EngineApiMessageVersion`] argument.
pub fn validate_version_specific_fields<Type>(
chain_spec: &ChainSpec,
version: EngineApiMessageVersion,
payload_or_attrs: PayloadOrAttributes<'_, Type>,
) -> Result<(), EngineObjectValidationError>
where
Type: PayloadAttributes,
{
validate_withdrawals_presence(
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(
chain_spec,
version,
payload_or_attrs.message_validation_kind(),
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, PartialOrd, Ord)]
pub enum EngineApiMessageVersion {
/// Version 1
V1,
/// Version 2
///
/// Added in the Shanghai hardfork.
V2,
/// Version 3
///
/// Added in the Cancun hardfork.
V3,
/// Version 4
///
/// Added in the Prague hardfork.
V4,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn version_ord() {
assert!(EngineApiMessageVersion::V4 > EngineApiMessageVersion::V3);
}
}

View File

@ -0,0 +1,72 @@
use crate::{MessageValidationKind, PayloadAttributes};
use reth_primitives::B256;
use reth_rpc_types::engine::ExecutionPayload;
/// Either an [`ExecutionPayload`] or a types that implements the [`PayloadAttributes`] trait.
#[derive(Debug)]
pub enum PayloadOrAttributes<'a, AttributesType> {
/// 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>,
},
/// A payload attributes type.
PayloadAttributes(&'a AttributesType),
}
impl<'a, AttributesType> PayloadOrAttributes<'a, AttributesType>
where
AttributesType: PayloadAttributes,
{
/// 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 }
}
/// Return the withdrawals for the payload or attributes.
pub fn withdrawals(&self) -> Option<&Vec<reth_rpc_types::Withdrawal>> {
match self {
Self::ExecutionPayload { payload, .. } => payload.withdrawals(),
Self::PayloadAttributes(attributes) => attributes.withdrawals(),
}
}
/// Return the timestamp for the payload or attributes.
pub fn timestamp(&self) -> u64 {
match self {
Self::ExecutionPayload { payload, .. } => payload.timestamp(),
Self::PayloadAttributes(attributes) => attributes.timestamp(),
}
}
/// 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::PayloadAttributes(attributes) => attributes.parent_beacon_block_root(),
}
}
/// Return a [`MessageValidationKind`] for the payload or attributes.
pub const fn message_validation_kind(&self) -> MessageValidationKind {
match self {
Self::ExecutionPayload { .. } => MessageValidationKind::Payload,
Self::PayloadAttributes(_) => MessageValidationKind::PayloadAttributes,
}
}
}
impl<'a, AttributesType> From<&'a AttributesType> for PayloadOrAttributes<'a, AttributesType>
where
AttributesType: PayloadAttributes,
{
fn from(attributes: &'a AttributesType) -> Self {
Self::PayloadAttributes(attributes)
}
}

View File

@ -0,0 +1,157 @@
use reth_primitives::{
revm_primitives::{BlockEnv, CfgEnvWithHandlerCfg},
Address, ChainSpec, Header, SealedBlock, Withdrawals, B256, U256,
};
use reth_rpc_types::{
engine::{OptimismPayloadAttributes, PayloadAttributes as EthPayloadAttributes, PayloadId},
Withdrawal,
};
use crate::{
validate_version_specific_fields, EngineApiMessageVersion, EngineObjectValidationError,
};
/// Represents a built payload type that contains a built [`SealedBlock`] and can be converted into
/// engine API execution payloads.
pub trait BuiltPayload: Send + Sync + std::fmt::Debug {
/// Returns the built block (sealed)
fn block(&self) -> &SealedBlock;
/// Returns the fees collected for the built block
fn fees(&self) -> U256;
}
/// This can be implemented by types that describe a currently running payload job.
///
/// This is used as a conversion type, transforming a payload attributes type that the engine API
/// receives, into a type that the payload builder can use.
pub trait PayloadBuilderAttributes: Send + Sync + std::fmt::Debug {
/// The payload attributes that can be used to construct this type. Used as the argument in
/// [`PayloadBuilderAttributes::try_new`].
type RpcPayloadAttributes;
/// The error type used in [`PayloadBuilderAttributes::try_new`].
type Error: std::error::Error;
/// Creates a new payload builder for the given parent block and the attributes.
///
/// Derives the unique [`PayloadId`] for the given parent and attributes
fn try_new(
parent: B256,
rpc_payload_attributes: Self::RpcPayloadAttributes,
) -> Result<Self, Self::Error>
where
Self: Sized;
/// Returns the [`PayloadId`] for the running payload job.
fn payload_id(&self) -> PayloadId;
/// Returns the parent block hash for the running payload job.
fn parent(&self) -> B256;
/// Returns the timestamp for the running payload job.
fn timestamp(&self) -> u64;
/// Returns the parent beacon block root for the running payload job, if it exists.
fn parent_beacon_block_root(&self) -> Option<B256>;
/// Returns the suggested fee recipient for the running payload job.
fn suggested_fee_recipient(&self) -> Address;
/// Returns the prevrandao field for the running payload job.
fn prev_randao(&self) -> B256;
/// Returns the withdrawals for the running payload job.
fn withdrawals(&self) -> &Withdrawals;
/// Returns the configured [`CfgEnvWithHandlerCfg`] and [`BlockEnv`] for the targeted payload
/// (that has the `parent` as its parent).
///
/// The `chain_spec` is used to determine the correct chain id and hardfork for the payload
/// based on its timestamp.
///
/// Block related settings are derived from the `parent` block and the configured attributes.
///
/// NOTE: This is only intended for beacon consensus (after merge).
fn cfg_and_block_env(
&self,
chain_spec: &ChainSpec,
parent: &Header,
) -> (CfgEnvWithHandlerCfg, BlockEnv);
}
/// The execution payload attribute type the CL node emits via the engine API.
/// This trait should be implemented by types that could be used to spawn a payload job.
///
/// This type is emitted as part of the forkchoiceUpdated call
pub trait PayloadAttributes:
serde::de::DeserializeOwned + serde::Serialize + std::fmt::Debug + Clone + Send + Sync + 'static
{
/// Returns the timestamp to be used in the payload job.
fn timestamp(&self) -> u64;
/// Returns the withdrawals for the given payload attributes.
fn withdrawals(&self) -> Option<&Vec<Withdrawal>>;
/// Return the parent beacon block root for the payload attributes.
fn parent_beacon_block_root(&self) -> Option<B256>;
/// Ensures that the payload attributes are valid for the given [`ChainSpec`] and
/// [`EngineApiMessageVersion`].
fn ensure_well_formed_attributes(
&self,
chain_spec: &ChainSpec,
version: EngineApiMessageVersion,
) -> Result<(), EngineObjectValidationError>;
}
impl PayloadAttributes for EthPayloadAttributes {
fn timestamp(&self) -> u64 {
self.timestamp
}
fn withdrawals(&self) -> Option<&Vec<Withdrawal>> {
self.withdrawals.as_ref()
}
fn parent_beacon_block_root(&self) -> Option<B256> {
self.parent_beacon_block_root
}
fn ensure_well_formed_attributes(
&self,
chain_spec: &ChainSpec,
version: EngineApiMessageVersion,
) -> Result<(), EngineObjectValidationError> {
validate_version_specific_fields(chain_spec, version, self.into())
}
}
impl PayloadAttributes for OptimismPayloadAttributes {
fn timestamp(&self) -> u64 {
self.payload_attributes.timestamp
}
fn withdrawals(&self) -> Option<&Vec<Withdrawal>> {
self.payload_attributes.withdrawals.as_ref()
}
fn parent_beacon_block_root(&self) -> Option<B256> {
self.payload_attributes.parent_beacon_block_root
}
fn ensure_well_formed_attributes(
&self,
chain_spec: &ChainSpec,
version: EngineApiMessageVersion,
) -> Result<(), EngineObjectValidationError> {
validate_version_specific_fields(chain_spec, version, self.into())?;
if self.gas_limit.is_none() && chain_spec.is_optimism() {
return Err(EngineObjectValidationError::InvalidParams(
"MissingGasLimitInPayloadAttributes".to_string().into(),
))
}
Ok(())
}
}