reth_rpc_api/
engine.rs

1//! Server traits for the engine API
2//!
3//! This contains the `engine_` namespace and the subset of the `eth_` namespace that is exposed to
4//! the consensus client.
5
6use alloy_eips::{eip4844::BlobAndProofV1, eip7685::Requests, BlockId, BlockNumberOrTag};
7use alloy_json_rpc::RpcObject;
8use alloy_primitives::{Address, BlockHash, Bytes, B256, U256, U64};
9use alloy_rpc_types::TransactionRequest;
10use alloy_rpc_types_engine::{
11    ClientVersionV1, ExecutionPayloadBodiesV1, ExecutionPayloadInputV2, ExecutionPayloadV1,
12    ExecutionPayloadV3, ForkchoiceState, ForkchoiceUpdated, PayloadId, PayloadStatus,
13    TransitionConfiguration,
14};
15use alloy_rpc_types_eth::{
16    state::StateOverride, BlockOverrides, EIP1186AccountProofResponse, Filter, Log, SyncStatus,
17};
18use alloy_serde::JsonStorageKey;
19use jsonrpsee::{core::RpcResult, proc_macros::rpc};
20use reth_engine_primitives::EngineTypes;
21
22// NOTE: We can't use associated types in the `EngineApi` trait because of jsonrpsee, so we use a
23// generic here. It would be nice if the rpc macro would understand which types need to have serde.
24// By default, if the trait has a generic, the rpc macro will add e.g. `Engine: DeserializeOwned` to
25// the trait bounds, which is not what we want, because `Types` is not used directly in any of the
26// trait methods. Instead, we have to add the bounds manually. This would be disastrous if we had
27// more than one associated type used in the trait methods.
28
29#[cfg_attr(not(feature = "client"), rpc(server, namespace = "engine"), server_bounds(Engine::PayloadAttributes: jsonrpsee::core::DeserializeOwned))]
30#[cfg_attr(feature = "client", rpc(server, client, namespace = "engine", client_bounds(Engine::PayloadAttributes: jsonrpsee::core::Serialize + Clone), server_bounds(Engine::PayloadAttributes: jsonrpsee::core::DeserializeOwned)))]
31pub trait EngineApi<Engine: EngineTypes> {
32    /// See also <https://github.com/ethereum/execution-apis/blob/6709c2a795b707202e93c4f2867fa0bf2640a84f/src/engine/paris.md#engine_newpayloadv1>
33    /// Caution: This should not accept the `withdrawals` field
34    #[method(name = "newPayloadV1")]
35    async fn new_payload_v1(&self, payload: ExecutionPayloadV1) -> RpcResult<PayloadStatus>;
36
37    /// See also <https://github.com/ethereum/execution-apis/blob/584905270d8ad665718058060267061ecfd79ca5/src/engine/shanghai.md#engine_newpayloadv2>
38    #[method(name = "newPayloadV2")]
39    async fn new_payload_v2(&self, payload: ExecutionPayloadInputV2) -> RpcResult<PayloadStatus>;
40
41    /// Post Cancun payload handler
42    ///
43    /// See also <https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#engine_newpayloadv3>
44    #[method(name = "newPayloadV3")]
45    async fn new_payload_v3(
46        &self,
47        payload: ExecutionPayloadV3,
48        versioned_hashes: Vec<B256>,
49        parent_beacon_block_root: B256,
50    ) -> RpcResult<PayloadStatus>;
51
52    /// Post Prague payload handler
53    ///
54    /// See also <https://github.com/ethereum/execution-apis/blob/main/src/engine/prague.md#engine_newpayloadv4>
55    #[method(name = "newPayloadV4")]
56    async fn new_payload_v4(
57        &self,
58        payload: ExecutionPayloadV3,
59        versioned_hashes: Vec<B256>,
60        parent_beacon_block_root: B256,
61        execution_requests: Requests,
62    ) -> RpcResult<PayloadStatus>;
63
64    /// See also <https://github.com/ethereum/execution-apis/blob/6709c2a795b707202e93c4f2867fa0bf2640a84f/src/engine/paris.md#engine_forkchoiceupdatedv1>
65    ///
66    /// Caution: This should not accept the `withdrawals` field in the payload attributes.
67    #[method(name = "forkchoiceUpdatedV1")]
68    async fn fork_choice_updated_v1(
69        &self,
70        fork_choice_state: ForkchoiceState,
71        payload_attributes: Option<Engine::PayloadAttributes>,
72    ) -> RpcResult<ForkchoiceUpdated>;
73
74    /// Post Shanghai forkchoice update handler
75    ///
76    /// This is the same as `forkchoiceUpdatedV1`, but expects an additional `withdrawals` field in
77    /// the `payloadAttributes`, if payload attributes are provided.
78    ///
79    /// See also <https://github.com/ethereum/execution-apis/blob/6709c2a795b707202e93c4f2867fa0bf2640a84f/src/engine/shanghai.md#engine_forkchoiceupdatedv2>
80    ///
81    /// Caution: This should not accept the `parentBeaconBlockRoot` field in the payload
82    /// attributes.
83    #[method(name = "forkchoiceUpdatedV2")]
84    async fn fork_choice_updated_v2(
85        &self,
86        fork_choice_state: ForkchoiceState,
87        payload_attributes: Option<Engine::PayloadAttributes>,
88    ) -> RpcResult<ForkchoiceUpdated>;
89
90    /// Post Cancun forkchoice update handler
91    ///
92    /// This is the same as `forkchoiceUpdatedV2`, but expects an additional
93    /// `parentBeaconBlockRoot` field in the `payloadAttributes`, if payload attributes
94    /// are provided.
95    ///
96    /// See also <https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#engine_forkchoiceupdatedv3>
97    #[method(name = "forkchoiceUpdatedV3")]
98    async fn fork_choice_updated_v3(
99        &self,
100        fork_choice_state: ForkchoiceState,
101        payload_attributes: Option<Engine::PayloadAttributes>,
102    ) -> RpcResult<ForkchoiceUpdated>;
103
104    /// See also <https://github.com/ethereum/execution-apis/blob/6709c2a795b707202e93c4f2867fa0bf2640a84f/src/engine/paris.md#engine_getpayloadv1>
105    ///
106    /// Returns the most recent version of the payload that is available in the corresponding
107    /// payload build process at the time of receiving this call.
108    ///
109    /// Caution: This should not return the `withdrawals` field
110    ///
111    /// Note:
112    /// > Provider software MAY stop the corresponding build process after serving this call.
113    #[method(name = "getPayloadV1")]
114    async fn get_payload_v1(
115        &self,
116        payload_id: PayloadId,
117    ) -> RpcResult<Engine::ExecutionPayloadEnvelopeV1>;
118
119    /// See also <https://github.com/ethereum/execution-apis/blob/6709c2a795b707202e93c4f2867fa0bf2640a84f/src/engine/shanghai.md#engine_getpayloadv2>
120    ///
121    /// Returns the most recent version of the payload that is available in the corresponding
122    /// payload build process at the time of receiving this call. Note:
123    /// > Provider software MAY stop the corresponding build process after serving this call.
124    #[method(name = "getPayloadV2")]
125    async fn get_payload_v2(
126        &self,
127        payload_id: PayloadId,
128    ) -> RpcResult<Engine::ExecutionPayloadEnvelopeV2>;
129
130    /// Post Cancun payload handler which also returns a blobs bundle.
131    ///
132    /// See also <https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#engine_getpayloadv3>
133    ///
134    /// Returns the most recent version of the payload that is available in the corresponding
135    /// payload build process at the time of receiving this call. Note:
136    /// > Provider software MAY stop the corresponding build process after serving this call.
137    #[method(name = "getPayloadV3")]
138    async fn get_payload_v3(
139        &self,
140        payload_id: PayloadId,
141    ) -> RpcResult<Engine::ExecutionPayloadEnvelopeV3>;
142
143    /// Post Prague payload handler.
144    ///
145    /// See also <https://github.com/ethereum/execution-apis/blob/main/src/engine/prague.md#engine_getpayloadv4>
146    ///
147    /// Returns the most recent version of the payload that is available in the corresponding
148    /// payload build process at the time of receiving this call. Note:
149    /// > Provider software MAY stop the corresponding build process after serving this call.
150    #[method(name = "getPayloadV4")]
151    async fn get_payload_v4(
152        &self,
153        payload_id: PayloadId,
154    ) -> RpcResult<Engine::ExecutionPayloadEnvelopeV4>;
155
156    /// See also <https://github.com/ethereum/execution-apis/blob/6452a6b194d7db269bf1dbd087a267251d3cc7f8/src/engine/shanghai.md#engine_getpayloadbodiesbyhashv1>
157    #[method(name = "getPayloadBodiesByHashV1")]
158    async fn get_payload_bodies_by_hash_v1(
159        &self,
160        block_hashes: Vec<BlockHash>,
161    ) -> RpcResult<ExecutionPayloadBodiesV1>;
162
163    /// See also <https://github.com/ethereum/execution-apis/blob/6452a6b194d7db269bf1dbd087a267251d3cc7f8/src/engine/shanghai.md#engine_getpayloadbodiesbyrangev1>
164    ///
165    /// Returns the execution payload bodies by the range starting at `start`, containing `count`
166    /// blocks.
167    ///
168    /// WARNING: This method is associated with the BeaconBlocksByRange message in the consensus
169    /// layer p2p specification, meaning the input should be treated as untrusted or potentially
170    /// adversarial.
171    ///
172    /// Implementers should take care when acting on the input to this method, specifically
173    /// ensuring that the range is limited properly, and that the range boundaries are computed
174    /// correctly and without panics.
175    #[method(name = "getPayloadBodiesByRangeV1")]
176    async fn get_payload_bodies_by_range_v1(
177        &self,
178        start: U64,
179        count: U64,
180    ) -> RpcResult<ExecutionPayloadBodiesV1>;
181
182    /// See also <https://github.com/ethereum/execution-apis/blob/6709c2a795b707202e93c4f2867fa0bf2640a84f/src/engine/paris.md#engine_exchangetransitionconfigurationv1>
183    ///
184    /// Note: This method will be deprecated after the cancun hardfork:
185    ///
186    /// > Consensus and execution layer clients MAY remove support of this method after Cancun. If
187    /// > no longer supported, this method MUST be removed from the engine_exchangeCapabilities
188    /// > request or response list depending on whether it is consensus or execution layer client.
189    #[method(name = "exchangeTransitionConfigurationV1")]
190    async fn exchange_transition_configuration(
191        &self,
192        transition_configuration: TransitionConfiguration,
193    ) -> RpcResult<TransitionConfiguration>;
194
195    /// This function will return the ClientVersionV1 object.
196    /// See also:
197    /// <https://github.com/ethereum/execution-apis/blob/03911ffc053b8b806123f1fc237184b0092a485a/src/engine/identification.md#engine_getclientversionv1>make fmt
198    ///
199    ///
200    /// - When connected to a single execution client, the consensus client **MUST** receive an
201    ///   array with a single `ClientVersionV1` object.
202    /// - When connected to multiple execution clients via a multiplexer, the multiplexer **MUST**
203    ///   concatenate the responses from each execution client into a single,
204    /// flat array before returning the response to the consensus client.
205    #[method(name = "getClientVersionV1")]
206    async fn get_client_version_v1(
207        &self,
208        client_version: ClientVersionV1,
209    ) -> RpcResult<Vec<ClientVersionV1>>;
210
211    /// See also <https://github.com/ethereum/execution-apis/blob/6452a6b194d7db269bf1dbd087a267251d3cc7f8/src/engine/common.md#capabilities>
212    #[method(name = "exchangeCapabilities")]
213    async fn exchange_capabilities(&self, capabilities: Vec<String>) -> RpcResult<Vec<String>>;
214
215    /// Fetch blobs for the consensus layer from the in-memory blob cache.
216    #[method(name = "getBlobsV1")]
217    async fn get_blobs_v1(
218        &self,
219        versioned_hashes: Vec<B256>,
220    ) -> RpcResult<Vec<Option<BlobAndProofV1>>>;
221}
222
223/// A subset of the ETH rpc interface: <https://ethereum.github.io/execution-apis/api-documentation/>
224///
225/// Specifically for the engine auth server: <https://github.com/ethereum/execution-apis/blob/main/src/engine/common.md#underlying-protocol>
226#[cfg_attr(not(feature = "client"), rpc(server, namespace = "eth"))]
227#[cfg_attr(feature = "client", rpc(server, client, namespace = "eth"))]
228pub trait EngineEthApi<B: RpcObject> {
229    /// Returns an object with data about the sync status or false.
230    #[method(name = "syncing")]
231    fn syncing(&self) -> RpcResult<SyncStatus>;
232
233    /// Returns the chain ID of the current network.
234    #[method(name = "chainId")]
235    async fn chain_id(&self) -> RpcResult<Option<U64>>;
236
237    /// Returns the number of most recent block.
238    #[method(name = "blockNumber")]
239    fn block_number(&self) -> RpcResult<U256>;
240
241    /// Executes a new message call immediately without creating a transaction on the block chain.
242    #[method(name = "call")]
243    async fn call(
244        &self,
245        request: TransactionRequest,
246        block_number: Option<BlockId>,
247        state_overrides: Option<StateOverride>,
248        block_overrides: Option<Box<BlockOverrides>>,
249    ) -> RpcResult<Bytes>;
250
251    /// Returns code at a given address at given block number.
252    #[method(name = "getCode")]
253    async fn get_code(&self, address: Address, block_id: Option<BlockId>) -> RpcResult<Bytes>;
254
255    /// Returns information about a block by hash.
256    #[method(name = "getBlockByHash")]
257    async fn block_by_hash(&self, hash: B256, full: bool) -> RpcResult<Option<B>>;
258
259    /// Returns information about a block by number.
260    #[method(name = "getBlockByNumber")]
261    async fn block_by_number(&self, number: BlockNumberOrTag, full: bool) -> RpcResult<Option<B>>;
262
263    /// Sends signed transaction, returning its hash.
264    #[method(name = "sendRawTransaction")]
265    async fn send_raw_transaction(&self, bytes: Bytes) -> RpcResult<B256>;
266
267    /// Returns logs matching given filter object.
268    #[method(name = "getLogs")]
269    async fn logs(&self, filter: Filter) -> RpcResult<Vec<Log>>;
270
271    /// Returns the account and storage values of the specified account including the Merkle-proof.
272    /// This call can be used to verify that the data you are pulling from is not tampered with.
273    #[method(name = "getProof")]
274    async fn get_proof(
275        &self,
276        address: Address,
277        keys: Vec<JsonStorageKey>,
278        block_number: Option<BlockId>,
279    ) -> RpcResult<EIP1186AccountProofResponse>;
280}