Files
nanoreth/crates/optimism/node/src/engine.rs

101 lines
3.8 KiB
Rust

use reth_chainspec::ChainSpec;
use reth_node_api::{
payload::{
validate_parent_beacon_block_root_presence, EngineApiMessageVersion,
EngineObjectValidationError, MessageValidationKind, PayloadOrAttributes, PayloadTypes,
VersionSpecificValidationError,
},
EngineTypes,
};
use reth_optimism_forks::OptimismHardfork;
use reth_optimism_payload_builder::{OptimismBuiltPayload, OptimismPayloadBuilderAttributes};
use reth_rpc_types::{
engine::ExecutionPayloadEnvelopeV2,
optimism::{
OptimismExecutionPayloadEnvelopeV3, OptimismExecutionPayloadEnvelopeV4,
OptimismPayloadAttributes,
},
ExecutionPayloadV1,
};
/// The types used in the optimism beacon consensus engine.
#[derive(Debug, Default, Clone, serde::Deserialize, serde::Serialize)]
#[non_exhaustive]
pub struct OptimismEngineTypes;
impl PayloadTypes for OptimismEngineTypes {
type BuiltPayload = OptimismBuiltPayload;
type PayloadAttributes = OptimismPayloadAttributes;
type PayloadBuilderAttributes = OptimismPayloadBuilderAttributes;
}
impl EngineTypes for OptimismEngineTypes {
type ExecutionPayloadV1 = ExecutionPayloadV1;
type ExecutionPayloadV2 = ExecutionPayloadEnvelopeV2;
type ExecutionPayloadV3 = OptimismExecutionPayloadEnvelopeV3;
type ExecutionPayloadV4 = OptimismExecutionPayloadEnvelopeV4;
fn validate_version_specific_fields(
chain_spec: &ChainSpec,
version: EngineApiMessageVersion,
payload_or_attrs: PayloadOrAttributes<'_, Self::PayloadAttributes>,
) -> Result<(), EngineObjectValidationError> {
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(),
)
}
}
/// 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 validate_withdrawals_presence(
chain_spec: &ChainSpec,
version: EngineApiMessageVersion,
message_validation_kind: MessageValidationKind,
timestamp: u64,
has_withdrawals: bool,
) -> Result<(), EngineObjectValidationError> {
let is_shanghai = chain_spec.fork(OptimismHardfork::Canyon).active_at_timestamp(timestamp);
match version {
EngineApiMessageVersion::V1 => {
if has_withdrawals {
return Err(message_validation_kind
.to_error(VersionSpecificValidationError::WithdrawalsNotSupportedInV1))
}
if is_shanghai {
return Err(message_validation_kind
.to_error(VersionSpecificValidationError::NoWithdrawalsPostShanghai))
}
}
EngineApiMessageVersion::V2 | EngineApiMessageVersion::V3 | EngineApiMessageVersion::V4 => {
if is_shanghai && !has_withdrawals {
return Err(message_validation_kind
.to_error(VersionSpecificValidationError::NoWithdrawalsPostShanghai))
}
if !is_shanghai && has_withdrawals {
return Err(message_validation_kind
.to_error(VersionSpecificValidationError::HasWithdrawalsPreShanghai))
}
}
};
Ok(())
}