reth_node_ethereum/
engine.rs

1//! Validates execution payload wrt Ethereum Execution Engine API version.
2
3use alloy_rpc_types_engine::ExecutionData;
4pub use alloy_rpc_types_engine::{
5    ExecutionPayloadEnvelopeV2, ExecutionPayloadEnvelopeV3, ExecutionPayloadEnvelopeV4,
6    ExecutionPayloadV1, PayloadAttributes as EthPayloadAttributes,
7};
8use reth_chainspec::{EthChainSpec, EthereumHardforks};
9use reth_engine_primitives::{EngineApiValidator, PayloadValidator};
10use reth_ethereum_payload_builder::EthereumExecutionPayloadValidator;
11use reth_ethereum_primitives::Block;
12use reth_node_api::PayloadTypes;
13use reth_payload_primitives::{
14    validate_execution_requests, validate_version_specific_fields, EngineApiMessageVersion,
15    EngineObjectValidationError, NewPayloadError, PayloadOrAttributes,
16};
17use reth_primitives_traits::RecoveredBlock;
18use std::sync::Arc;
19
20/// Validator for the ethereum engine API.
21#[derive(Debug, Clone)]
22pub struct EthereumEngineValidator<ChainSpec = reth_chainspec::ChainSpec> {
23    inner: EthereumExecutionPayloadValidator<ChainSpec>,
24}
25
26impl<ChainSpec> EthereumEngineValidator<ChainSpec> {
27    /// Instantiates a new validator.
28    pub const fn new(chain_spec: Arc<ChainSpec>) -> Self {
29        Self { inner: EthereumExecutionPayloadValidator::new(chain_spec) }
30    }
31
32    /// Returns the chain spec used by the validator.
33    #[inline]
34    fn chain_spec(&self) -> &ChainSpec {
35        self.inner.chain_spec()
36    }
37}
38
39impl<ChainSpec, Types> PayloadValidator<Types> for EthereumEngineValidator<ChainSpec>
40where
41    ChainSpec: EthChainSpec + EthereumHardforks + 'static,
42    Types: PayloadTypes<ExecutionData = ExecutionData>,
43{
44    type Block = Block;
45
46    fn ensure_well_formed_payload(
47        &self,
48        payload: ExecutionData,
49    ) -> Result<RecoveredBlock<Self::Block>, NewPayloadError> {
50        let sealed_block = self.inner.ensure_well_formed_payload(payload)?;
51        sealed_block.try_recover().map_err(|e| NewPayloadError::Other(e.into()))
52    }
53}
54
55impl<ChainSpec, Types> EngineApiValidator<Types> for EthereumEngineValidator<ChainSpec>
56where
57    ChainSpec: EthChainSpec + EthereumHardforks + 'static,
58    Types: PayloadTypes<PayloadAttributes = EthPayloadAttributes, ExecutionData = ExecutionData>,
59{
60    fn validate_version_specific_fields(
61        &self,
62        version: EngineApiMessageVersion,
63        payload_or_attrs: PayloadOrAttributes<'_, Types::ExecutionData, EthPayloadAttributes>,
64    ) -> Result<(), EngineObjectValidationError> {
65        payload_or_attrs
66            .execution_requests()
67            .map(|requests| validate_execution_requests(requests))
68            .transpose()?;
69
70        validate_version_specific_fields(self.chain_spec(), version, payload_or_attrs)
71    }
72
73    fn ensure_well_formed_attributes(
74        &self,
75        version: EngineApiMessageVersion,
76        attributes: &EthPayloadAttributes,
77    ) -> Result<(), EngineObjectValidationError> {
78        validate_version_specific_fields(
79            self.chain_spec(),
80            version,
81            PayloadOrAttributes::<Types::ExecutionData, EthPayloadAttributes>::PayloadAttributes(
82                attributes,
83            ),
84        )
85    }
86}