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::ChainSpec;
9use reth_engine_primitives::{EngineValidator, 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 {
23    inner: EthereumExecutionPayloadValidator<ChainSpec>,
24}
25
26impl EthereumEngineValidator {
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 PayloadValidator for EthereumEngineValidator {
40    type Block = Block;
41    type ExecutionData = ExecutionData;
42
43    fn ensure_well_formed_payload(
44        &self,
45        payload: ExecutionData,
46    ) -> Result<RecoveredBlock<Self::Block>, NewPayloadError> {
47        let sealed_block = self.inner.ensure_well_formed_payload(payload)?;
48        sealed_block.try_recover().map_err(|e| NewPayloadError::Other(e.into()))
49    }
50}
51
52impl<Types> EngineValidator<Types> for EthereumEngineValidator
53where
54    Types: PayloadTypes<PayloadAttributes = EthPayloadAttributes, ExecutionData = ExecutionData>,
55{
56    fn validate_version_specific_fields(
57        &self,
58        version: EngineApiMessageVersion,
59        payload_or_attrs: PayloadOrAttributes<'_, Self::ExecutionData, EthPayloadAttributes>,
60    ) -> Result<(), EngineObjectValidationError> {
61        payload_or_attrs
62            .execution_requests()
63            .map(|requests| validate_execution_requests(requests))
64            .transpose()?;
65
66        validate_version_specific_fields(self.chain_spec(), version, payload_or_attrs)
67    }
68
69    fn ensure_well_formed_attributes(
70        &self,
71        version: EngineApiMessageVersion,
72        attributes: &EthPayloadAttributes,
73    ) -> Result<(), EngineObjectValidationError> {
74        validate_version_specific_fields(
75            self.chain_spec(),
76            version,
77            PayloadOrAttributes::<Self::ExecutionData, EthPayloadAttributes>::PayloadAttributes(
78                attributes,
79            ),
80        )
81    }
82}