reth_engine_primitives/
lib.rs

1//! Traits, validation methods, and helper types used to abstract over engine types.
2
3#![doc(
4    html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png",
5    html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256",
6    issue_tracker_base_url = "https://github.com/paradigmxyz/reth/issues/"
7)]
8#![cfg_attr(not(test), warn(unused_crate_dependencies))]
9#![cfg_attr(docsrs, feature(doc_cfg))]
10#![cfg_attr(not(feature = "std"), no_std)]
11
12extern crate alloc;
13
14use alloy_consensus::BlockHeader;
15use reth_errors::ConsensusError;
16use reth_payload_primitives::{
17    EngineApiMessageVersion, EngineObjectValidationError, InvalidPayloadAttributesError,
18    NewPayloadError, PayloadAttributes, PayloadOrAttributes, PayloadTypes,
19};
20use reth_primitives_traits::{Block, RecoveredBlock, SealedBlock};
21use reth_trie_common::HashedPostState;
22use serde::{de::DeserializeOwned, Serialize};
23
24// Re-export [`ExecutionPayload`] moved to `reth_payload_primitives`
25#[cfg(feature = "std")]
26pub use reth_evm::{ConfigureEngineEvm, ExecutableTxIterator, ExecutableTxTuple};
27pub use reth_payload_primitives::ExecutionPayload;
28
29mod error;
30pub use error::*;
31
32mod forkchoice;
33pub use forkchoice::{ForkchoiceStateHash, ForkchoiceStateTracker, ForkchoiceStatus};
34
35#[cfg(feature = "std")]
36mod message;
37#[cfg(feature = "std")]
38pub use message::*;
39
40mod event;
41pub use event::*;
42
43mod invalid_block_hook;
44pub use invalid_block_hook::{InvalidBlockHook, InvalidBlockHooks, NoopInvalidBlockHook};
45
46pub mod config;
47pub use config::*;
48
49/// This type defines the versioned types of the engine API based on the [ethereum engine API](https://github.com/ethereum/execution-apis/tree/main/src/engine).
50///
51/// This includes the execution payload types and payload attributes that are used to trigger a
52/// payload job. Hence this trait is also [`PayloadTypes`].
53///
54/// Implementations of this type are intended to be stateless and just define the types as
55/// associated types.
56/// This type is intended for non-ethereum chains that closely mirror the ethereum engine API spec,
57/// but may have different payload, for example opstack, but structurally equivalent otherwise (same
58/// engine API RPC endpoints for example).
59pub trait EngineTypes:
60    PayloadTypes<
61        BuiltPayload: TryInto<Self::ExecutionPayloadEnvelopeV1>
62                          + TryInto<Self::ExecutionPayloadEnvelopeV2>
63                          + TryInto<Self::ExecutionPayloadEnvelopeV3>
64                          + TryInto<Self::ExecutionPayloadEnvelopeV4>
65                          + TryInto<Self::ExecutionPayloadEnvelopeV5>,
66    > + DeserializeOwned
67    + Serialize
68{
69    /// Execution Payload V1 envelope type.
70    type ExecutionPayloadEnvelopeV1: DeserializeOwned
71        + Serialize
72        + Clone
73        + Unpin
74        + Send
75        + Sync
76        + 'static;
77    /// Execution Payload V2  envelope type.
78    type ExecutionPayloadEnvelopeV2: DeserializeOwned
79        + Serialize
80        + Clone
81        + Unpin
82        + Send
83        + Sync
84        + 'static;
85    /// Execution Payload V3 envelope type.
86    type ExecutionPayloadEnvelopeV3: DeserializeOwned
87        + Serialize
88        + Clone
89        + Unpin
90        + Send
91        + Sync
92        + 'static;
93    /// Execution Payload V4 envelope type.
94    type ExecutionPayloadEnvelopeV4: DeserializeOwned
95        + Serialize
96        + Clone
97        + Unpin
98        + Send
99        + Sync
100        + 'static;
101    /// Execution Payload V5 envelope type.
102    type ExecutionPayloadEnvelopeV5: DeserializeOwned
103        + Serialize
104        + Clone
105        + Unpin
106        + Send
107        + Sync
108        + 'static;
109}
110
111/// Type that validates the payloads processed by the engine API.
112pub trait EngineApiValidator<Types: PayloadTypes>: Send + Sync + Unpin + 'static {
113    /// Validates the presence or exclusion of fork-specific fields based on the payload attributes
114    /// and the message version.
115    fn validate_version_specific_fields(
116        &self,
117        version: EngineApiMessageVersion,
118        payload_or_attrs: PayloadOrAttributes<'_, Types::ExecutionData, Types::PayloadAttributes>,
119    ) -> Result<(), EngineObjectValidationError>;
120
121    /// Ensures that the payload attributes are valid for the given [`EngineApiMessageVersion`].
122    fn ensure_well_formed_attributes(
123        &self,
124        version: EngineApiMessageVersion,
125        attributes: &Types::PayloadAttributes,
126    ) -> Result<(), EngineObjectValidationError>;
127}
128
129/// Type that validates an [`ExecutionPayload`].
130#[auto_impl::auto_impl(&, Arc)]
131pub trait PayloadValidator<Types: PayloadTypes>: Send + Sync + Unpin + 'static {
132    /// The block type used by the engine.
133    type Block: Block;
134
135    /// Converts the given payload into a sealed block without recovering signatures.
136    ///
137    /// This function validates the payload and converts it into a [`SealedBlock`] which contains
138    /// the block hash but does not perform signature recovery on transactions.
139    ///
140    /// This is more efficient than [`Self::ensure_well_formed_payload`] when signature recovery
141    /// is not needed immediately or will be performed later.
142    ///
143    /// Implementers should ensure that the checks are done in the order that conforms with the
144    /// engine-API specification.
145    fn convert_payload_to_block(
146        &self,
147        payload: Types::ExecutionData,
148    ) -> Result<SealedBlock<Self::Block>, NewPayloadError>;
149
150    /// Ensures that the given payload does not violate any consensus rules that concern the block's
151    /// layout.
152    ///
153    /// This function must convert the payload into the executable block and pre-validate its
154    /// fields.
155    ///
156    /// Implementers should ensure that the checks are done in the order that conforms with the
157    /// engine-API specification.
158    fn ensure_well_formed_payload(
159        &self,
160        payload: Types::ExecutionData,
161    ) -> Result<RecoveredBlock<Self::Block>, NewPayloadError> {
162        let sealed_block = self.convert_payload_to_block(payload)?;
163        sealed_block.try_recover().map_err(|e| NewPayloadError::Other(e.into()))
164    }
165
166    /// Verifies payload post-execution w.r.t. hashed state updates.
167    fn validate_block_post_execution_with_hashed_state(
168        &self,
169        _state_updates: &HashedPostState,
170        _block: &RecoveredBlock<Self::Block>,
171    ) -> Result<(), ConsensusError> {
172        // method not used by l1
173        Ok(())
174    }
175
176    /// Validates the payload attributes with respect to the header.
177    ///
178    /// By default, this enforces that the payload attributes timestamp is greater than the
179    /// timestamp according to:
180    ///   > 7. Client software MUST ensure that payloadAttributes.timestamp is greater than
181    ///   > timestamp
182    ///   > of a block referenced by forkchoiceState.headBlockHash.
183    ///
184    /// See also: <https://github.com/ethereum/execution-apis/blob/main/src/engine/common.md#specification-1>
185    fn validate_payload_attributes_against_header(
186        &self,
187        attr: &Types::PayloadAttributes,
188        header: &<Self::Block as Block>::Header,
189    ) -> Result<(), InvalidPayloadAttributesError> {
190        if attr.timestamp() <= header.timestamp() {
191            return Err(InvalidPayloadAttributesError::InvalidTimestamp);
192        }
193        Ok(())
194    }
195}