-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Expand file tree
/
Copy pathlib.rs
More file actions
259 lines (240 loc) · 10.5 KB
/
lib.rs
File metadata and controls
259 lines (240 loc) · 10.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
//! Traits, validation methods, and helper types used to abstract over engine types.
#![doc(
html_logo_url = "https://raw.githubusercontent.com/paradigmxyz/reth/main/assets/reth-docs.png",
html_favicon_url = "https://avatars0.githubusercontent.com/u/97369466?s=256",
issue_tracker_base_url = "https://github.com/paradigmxyz/reth/issues/"
)]
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(not(feature = "std"), no_std)]
extern crate alloc;
use alloy_consensus::BlockHeader;
use alloy_primitives::B256;
use reth_errors::ConsensusError;
use reth_payload_primitives::{
EngineApiMessageVersion, EngineObjectValidationError, InvalidPayloadAttributesError,
NewPayloadError, PayloadAttributes, PayloadOrAttributes, PayloadTypes,
};
use reth_primitives_traits::{Block, RecoveredBlock, SealedBlock};
use reth_trie_common::HashedPostState;
use revm::database::states::BundleState;
use serde::{de::DeserializeOwned, Serialize};
// Re-export [`ExecutionPayload`] moved to `reth_payload_primitives`
#[cfg(feature = "std")]
pub use reth_evm::{ConfigureEngineEvm, ConvertTx, ExecutableTxIterator, ExecutableTxTuple};
pub use reth_payload_primitives::ExecutionPayload;
mod error;
pub use error::*;
mod forkchoice;
pub use forkchoice::{ForkchoiceStateHash, ForkchoiceStateTracker, ForkchoiceStatus};
#[cfg(feature = "std")]
mod message;
#[cfg(feature = "std")]
pub use message::*;
mod event;
pub use event::*;
mod invalid_block_hook;
pub use invalid_block_hook::{InvalidBlockHook, InvalidBlockHooks, NoopInvalidBlockHook};
pub mod config;
pub use config::*;
/// 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).
///
/// This includes the execution payload types and payload attributes that are used to trigger a
/// payload job. Hence this trait is also [`PayloadTypes`].
///
/// Implementations of this type are intended to be stateless and just define the types as
/// associated types.
/// This type is intended for non-ethereum chains that closely mirror the ethereum engine API spec,
/// but may have different payload, for example opstack, but structurally equivalent otherwise (same
/// engine API RPC endpoints for example).
pub trait EngineTypes:
PayloadTypes<
BuiltPayload: TryInto<Self::ExecutionPayloadEnvelopeV1>
+ TryInto<Self::ExecutionPayloadEnvelopeV2>
+ TryInto<Self::ExecutionPayloadEnvelopeV3>
+ TryInto<Self::ExecutionPayloadEnvelopeV4>
+ TryInto<Self::ExecutionPayloadEnvelopeV5>
+ TryInto<Self::ExecutionPayloadEnvelopeV6>,
> + DeserializeOwned
+ Serialize
{
/// Execution Payload V1 envelope type.
type ExecutionPayloadEnvelopeV1: DeserializeOwned
+ Serialize
+ Clone
+ Unpin
+ Send
+ Sync
+ 'static;
/// Execution Payload V2 envelope type.
type ExecutionPayloadEnvelopeV2: DeserializeOwned
+ Serialize
+ Clone
+ Unpin
+ Send
+ Sync
+ 'static;
/// Execution Payload V3 envelope type.
type ExecutionPayloadEnvelopeV3: DeserializeOwned
+ Serialize
+ Clone
+ Unpin
+ Send
+ Sync
+ 'static;
/// Execution Payload V4 envelope type.
type ExecutionPayloadEnvelopeV4: DeserializeOwned
+ Serialize
+ Clone
+ Unpin
+ Send
+ Sync
+ 'static;
/// Execution Payload V5 envelope type.
type ExecutionPayloadEnvelopeV5: DeserializeOwned
+ Serialize
+ Clone
+ Unpin
+ Send
+ Sync
+ 'static;
/// Execution Payload V6 envelope type.
type ExecutionPayloadEnvelopeV6: DeserializeOwned
+ Serialize
+ Clone
+ Unpin
+ Send
+ Sync
+ 'static;
}
/// Validates engine API requests at the RPC layer, before payloads and attributes
/// are forwarded to the engine for processing.
///
/// - [`validate_version_specific_fields`](Self::validate_version_specific_fields): Enforced in each
/// `engine_newPayloadVN` RPC handler to verify the payload contains the correct fields for the
/// engine API version (e.g., blob fields in V3+, requests in V4+).
///
/// - [`ensure_well_formed_attributes`](Self::ensure_well_formed_attributes): Enforced in
/// `engine_forkchoiceUpdatedVN` RPC handlers to validate payload attributes are well-formed for
/// the given version before forwarding to the engine.
///
/// After this validation passes, the engine performs the full consensus validation
/// pipeline (header, pre-execution, execution, post-execution).
pub trait EngineApiValidator<Types: PayloadTypes>: Send + Sync + Unpin + 'static {
/// Validates the presence or exclusion of fork-specific fields based on the payload attributes
/// and the message version.
fn validate_version_specific_fields(
&self,
version: EngineApiMessageVersion,
payload_or_attrs: PayloadOrAttributes<'_, Types::ExecutionData, Types::PayloadAttributes>,
) -> Result<(), EngineObjectValidationError>;
/// Ensures that the payload attributes are valid for the given [`EngineApiMessageVersion`].
fn ensure_well_formed_attributes(
&self,
version: EngineApiMessageVersion,
attributes: &Types::PayloadAttributes,
) -> Result<(), EngineObjectValidationError>;
}
/// Type that validates an [`ExecutionPayload`].
///
/// This trait handles validation at the engine API boundary — converting payloads
/// into blocks and validating payload attributes for block building.
///
/// # Methods and when they're used
///
/// - [`convert_payload_to_block`](Self::convert_payload_to_block): Used during `engine_newPayload`
/// processing to decode the payload into a [`SealedBlock`]. Also used to validate payload
/// structure during backfill buffering. In the engine tree, this runs concurrently with state
/// setup on a background thread.
///
/// - [`ensure_well_formed_payload`](Self::ensure_well_formed_payload): Converts payload and
/// recovers transaction signatures. Used when recovered senders are needed immediately.
///
/// - [`validate_payload_attributes_against_header`](Self::validate_payload_attributes_against_header):
/// Enforced as part of the engine's `forkchoiceUpdated` handling when payload attributes
/// are provided. Gates whether a payload build job is started.
///
/// - [`validate_block_post_execution_with_hashed_state`](Self::validate_block_post_execution_with_hashed_state):
/// Called after block execution in the engine's payload validation pipeline.
/// No-op on L1, used by L2s (e.g., OP Stack) for additional post-execution checks.
///
/// # Relationship to consensus traits
///
/// This trait does NOT replace the consensus traits (`Consensus`, `FullConsensus` from
/// `reth-consensus`). Those handle the actual consensus rule
/// validation (header checks, pre/post-execution). This trait handles engine API-specific
/// concerns: payload encoding/decoding and attribute validation.
#[auto_impl::auto_impl(&, Arc)]
pub trait PayloadValidator<Types: PayloadTypes>: Send + Sync + Unpin + 'static {
/// The block type used by the engine.
type Block: Block;
/// Converts the given payload into a sealed block without recovering signatures.
///
/// This function validates the payload and converts it into a [`SealedBlock`] which contains
/// the block hash but does not perform signature recovery on transactions.
///
/// This is more efficient than [`Self::ensure_well_formed_payload`] when signature recovery
/// is not needed immediately or will be performed later.
///
/// Implementers should ensure that the checks are done in the order that conforms with the
/// engine-API specification.
fn convert_payload_to_block(
&self,
payload: Types::ExecutionData,
) -> Result<SealedBlock<Self::Block>, NewPayloadError>;
/// Ensures that the given payload does not violate any consensus rules that concern the block's
/// layout.
///
/// This function must convert the payload into the executable block and pre-validate its
/// fields.
///
/// Implementers should ensure that the checks are done in the order that conforms with the
/// engine-API specification.
fn ensure_well_formed_payload(
&self,
payload: Types::ExecutionData,
) -> Result<RecoveredBlock<Self::Block>, NewPayloadError> {
let sealed_block = self.convert_payload_to_block(payload)?;
sealed_block.try_recover().map_err(|e| NewPayloadError::Other(e.into()))
}
/// Computes a custom state root for some networks, bypassing the default trie computation.
///
/// Returns `None` by default to use th standard Ethereum state root. Returning `Some` will
/// cause the engine to skip trie computation and validate using the returned value instead.
fn compute_state_root(&self, _bundle_state: &BundleState, _parent_hash: B256) -> Option<B256> {
None
}
/// Verifies payload post-execution w.r.t. hashed state updates.
fn validate_block_post_execution_with_hashed_state(
&self,
_state_updates: &HashedPostState,
_block: &RecoveredBlock<Self::Block>,
) -> Result<(), ConsensusError> {
// method not used by l1
Ok(())
}
/// Validates the payload attributes with respect to the header.
///
/// By default, this enforces that the payload attributes timestamp is greater than the
/// timestamp according to:
/// > 7. Client software MUST ensure that payloadAttributes.timestamp is greater than
/// > timestamp
/// > of a block referenced by forkchoiceState.headBlockHash.
///
/// See also: <https://github.com/ethereum/execution-apis/blob/main/src/engine/common.md#specification-1>
///
/// Enforced as part of the engine's `forkchoiceUpdated` handling when the consensus layer
/// provides payload attributes. If this returns an error, the forkchoice state update itself
/// is NOT rolled back, but no payload build job is started — the response includes
/// `INVALID_PAYLOAD_ATTRIBUTES`.
fn validate_payload_attributes_against_header(
&self,
attr: &Types::PayloadAttributes,
header: &<Self::Block as Block>::Header,
) -> Result<(), InvalidPayloadAttributesError> {
if attr.timestamp() <= header.timestamp() {
return Err(InvalidPayloadAttributesError::InvalidTimestamp);
}
Ok(())
}
}