arb_node/
validator.rs

1//! Arbitrum engine API payload and attribute validators.
2
3use std::sync::Arc;
4
5use alloy_rpc_types_engine::ExecutionData;
6use arb_payload::{ArbBlock, ArbPayloadAttributes};
7use arb_primitives::ArbTransactionSigned;
8use reth_chainspec::ChainSpec;
9use reth_engine_primitives::{EngineApiValidator, PayloadValidator};
10use reth_payload_primitives::{
11    validate_version_specific_fields, EngineApiMessageVersion, EngineObjectValidationError,
12    NewPayloadError, PayloadOrAttributes, PayloadTypes,
13};
14use reth_primitives_traits::{Block as _, SealedBlock};
15
16/// Arbitrum engine API validator.
17///
18/// Validates execution payloads and attributes for the engine API,
19/// converting raw payloads to sealed blocks with Arbitrum transaction types.
20#[derive(Debug, Clone)]
21pub struct ArbPayloadValidator {
22    chain_spec: Arc<ChainSpec>,
23}
24
25impl ArbPayloadValidator {
26    /// Create a new validator with the given chain spec.
27    pub fn new(chain_spec: Arc<ChainSpec>) -> Self {
28        Self { chain_spec }
29    }
30}
31
32impl<Types> PayloadValidator<Types> for ArbPayloadValidator
33where
34    Types: PayloadTypes<ExecutionData = ExecutionData>,
35{
36    type Block = ArbBlock;
37
38    fn convert_payload_to_block(
39        &self,
40        payload: ExecutionData,
41    ) -> Result<SealedBlock<ArbBlock>, NewPayloadError> {
42        let ExecutionData { payload, sidecar } = payload;
43        let expected_hash = payload.block_hash();
44
45        let sealed_block: SealedBlock<alloy_consensus::Block<ArbTransactionSigned>> = payload
46            .try_into_block_with_sidecar(&sidecar)
47            .map_err(|e| NewPayloadError::Other(e.into()))?
48            .seal_slow();
49
50        if expected_hash != sealed_block.hash() {
51            return Err(NewPayloadError::Other(
52                alloy_rpc_types_engine::PayloadError::BlockHash {
53                    execution: sealed_block.hash(),
54                    consensus: expected_hash,
55                }
56                .into(),
57            ));
58        }
59
60        Ok(sealed_block)
61    }
62}
63
64impl<Types> EngineApiValidator<Types> for ArbPayloadValidator
65where
66    Types: PayloadTypes<ExecutionData = ExecutionData, PayloadAttributes = ArbPayloadAttributes>,
67{
68    fn validate_version_specific_fields(
69        &self,
70        version: EngineApiMessageVersion,
71        payload_or_attrs: PayloadOrAttributes<'_, Types::ExecutionData, ArbPayloadAttributes>,
72    ) -> Result<(), EngineObjectValidationError> {
73        validate_version_specific_fields(&*self.chain_spec, version, payload_or_attrs)
74    }
75
76    fn ensure_well_formed_attributes(
77        &self,
78        version: EngineApiMessageVersion,
79        attributes: &ArbPayloadAttributes,
80    ) -> Result<(), EngineObjectValidationError> {
81        validate_version_specific_fields(
82            &*self.chain_spec,
83            version,
84            PayloadOrAttributes::<Types::ExecutionData, ArbPayloadAttributes>::PayloadAttributes(
85                attributes,
86            ),
87        )
88    }
89}