//! Server traits for the engine API //! //! This contains the `engine_` namespace and the subset of the `eth_` namespace that is exposed to //! the consensus client. use alloy_eips::{ eip4844::{BlobAndProofV1, BlobAndProofV2}, eip7685::RequestsOrHash, BlockId, BlockNumberOrTag, }; use alloy_json_rpc::RpcObject; use alloy_primitives::{Address, BlockHash, Bytes, B256, U256, U64}; use alloy_rpc_types_engine::{ ClientVersionV1, ExecutionPayloadBodiesV1, ExecutionPayloadInputV2, ExecutionPayloadV1, ExecutionPayloadV3, ForkchoiceState, ForkchoiceUpdated, PayloadId, PayloadStatus, }; use alloy_rpc_types_eth::{ state::StateOverride, transaction::TransactionRequest, BlockOverrides, EIP1186AccountProofResponse, Filter, Log, SyncStatus, }; use alloy_serde::JsonStorageKey; use jsonrpsee::{core::RpcResult, proc_macros::rpc, RpcModule}; use reth_engine_primitives::EngineTypes; /// Helper trait for the engine api server. /// /// This type-erases the concrete [`jsonrpsee`] server implementation and only returns the /// [`RpcModule`] that contains all the endpoints of the server. pub trait IntoEngineApiRpcModule { /// Consumes the type and returns all the methods and subscriptions defined in the trait and /// returns them as a single [`RpcModule`] fn into_rpc_module(self) -> RpcModule<()>; } // NOTE: We can't use associated types in the `EngineApi` trait because of jsonrpsee, so we use a // generic here. It would be nice if the rpc macro would understand which types need to have serde. // By default, if the trait has a generic, the rpc macro will add e.g. `Engine: DeserializeOwned` to // the trait bounds, which is not what we want, because `Types` is not used directly in any of the // trait methods. Instead, we have to add the bounds manually. This would be disastrous if we had // more than one associated type used in the trait methods. #[cfg_attr(not(feature = "client"), rpc(server, namespace = "engine"), server_bounds(Engine::PayloadAttributes: jsonrpsee::core::DeserializeOwned))] #[cfg_attr(feature = "client", rpc(server, client, namespace = "engine", client_bounds(Engine::PayloadAttributes: jsonrpsee::core::Serialize + Clone), server_bounds(Engine::PayloadAttributes: jsonrpsee::core::DeserializeOwned)))] pub trait EngineApi { /// See also /// Caution: This should not accept the `withdrawals` field #[method(name = "newPayloadV1")] async fn new_payload_v1(&self, payload: ExecutionPayloadV1) -> RpcResult; /// See also #[method(name = "newPayloadV2")] async fn new_payload_v2(&self, payload: ExecutionPayloadInputV2) -> RpcResult; /// Post Cancun payload handler /// /// See also #[method(name = "newPayloadV3")] async fn new_payload_v3( &self, payload: ExecutionPayloadV3, versioned_hashes: Vec, parent_beacon_block_root: B256, ) -> RpcResult; /// Post Prague payload handler /// /// See also #[method(name = "newPayloadV4")] async fn new_payload_v4( &self, payload: ExecutionPayloadV3, versioned_hashes: Vec, parent_beacon_block_root: B256, execution_requests: RequestsOrHash, ) -> RpcResult; /// See also /// /// Caution: This should not accept the `withdrawals` field in the payload attributes. #[method(name = "forkchoiceUpdatedV1")] async fn fork_choice_updated_v1( &self, fork_choice_state: ForkchoiceState, payload_attributes: Option, ) -> RpcResult; /// Post Shanghai forkchoice update handler /// /// This is the same as `forkchoiceUpdatedV1`, but expects an additional `withdrawals` field in /// the `payloadAttributes`, if payload attributes are provided. /// /// See also /// /// Caution: This should not accept the `parentBeaconBlockRoot` field in the payload /// attributes. #[method(name = "forkchoiceUpdatedV2")] async fn fork_choice_updated_v2( &self, fork_choice_state: ForkchoiceState, payload_attributes: Option, ) -> RpcResult; /// Post Cancun forkchoice update handler /// /// This is the same as `forkchoiceUpdatedV2`, but expects an additional /// `parentBeaconBlockRoot` field in the `payloadAttributes`, if payload attributes /// are provided. /// /// See also #[method(name = "forkchoiceUpdatedV3")] async fn fork_choice_updated_v3( &self, fork_choice_state: ForkchoiceState, payload_attributes: Option, ) -> RpcResult; /// See also /// /// Returns the most recent version of the payload that is available in the corresponding /// payload build process at the time of receiving this call. /// /// Caution: This should not return the `withdrawals` field /// /// Note: /// > Provider software MAY stop the corresponding build process after serving this call. #[method(name = "getPayloadV1")] async fn get_payload_v1( &self, payload_id: PayloadId, ) -> RpcResult; /// See also /// /// Returns the most recent version of the payload that is available in the corresponding /// payload build process at the time of receiving this call. Note: /// > Provider software MAY stop the corresponding build process after serving this call. #[method(name = "getPayloadV2")] async fn get_payload_v2( &self, payload_id: PayloadId, ) -> RpcResult; /// Post Cancun payload handler which also returns a blobs bundle. /// /// See also /// /// Returns the most recent version of the payload that is available in the corresponding /// payload build process at the time of receiving this call. Note: /// > Provider software MAY stop the corresponding build process after serving this call. #[method(name = "getPayloadV3")] async fn get_payload_v3( &self, payload_id: PayloadId, ) -> RpcResult; /// Post Prague payload handler. /// /// See also /// /// Returns the most recent version of the payload that is available in the corresponding /// payload build process at the time of receiving this call. Note: /// > Provider software MAY stop the corresponding build process after serving this call. #[method(name = "getPayloadV4")] async fn get_payload_v4( &self, payload_id: PayloadId, ) -> RpcResult; /// Post Osaka payload handler. /// /// See also . /// /// Returns the most recent version of the payload that is available in the corresponding /// payload build process at the time of receiving this call. Note: /// > Provider software MAY stop the corresponding build process after serving this call. #[method(name = "getPayloadV5")] async fn get_payload_v5( &self, payload_id: PayloadId, ) -> RpcResult; /// See also #[method(name = "getPayloadBodiesByHashV1")] async fn get_payload_bodies_by_hash_v1( &self, block_hashes: Vec, ) -> RpcResult; /// See also /// /// Returns the execution payload bodies by the range starting at `start`, containing `count` /// blocks. /// /// WARNING: This method is associated with the BeaconBlocksByRange message in the consensus /// layer p2p specification, meaning the input should be treated as untrusted or potentially /// adversarial. /// /// Implementers should take care when acting on the input to this method, specifically /// ensuring that the range is limited properly, and that the range boundaries are computed /// correctly and without panics. #[method(name = "getPayloadBodiesByRangeV1")] async fn get_payload_bodies_by_range_v1( &self, start: U64, count: U64, ) -> RpcResult; /// This function will return the ClientVersionV1 object. /// See also: /// make fmt /// /// /// - When connected to a single execution client, the consensus client **MUST** receive an /// array with a single `ClientVersionV1` object. /// - When connected to multiple execution clients via a multiplexer, the multiplexer **MUST** /// concatenate the responses from each execution client into a single, /// flat array before returning the response to the consensus client. #[method(name = "getClientVersionV1")] async fn get_client_version_v1( &self, client_version: ClientVersionV1, ) -> RpcResult>; /// See also #[method(name = "exchangeCapabilities")] async fn exchange_capabilities(&self, capabilities: Vec) -> RpcResult>; /// Fetch blobs for the consensus layer from the in-memory blob cache. #[method(name = "getBlobsV1")] async fn get_blobs_v1( &self, versioned_hashes: Vec, ) -> RpcResult>>; /// Fetch blobs for the consensus layer from the blob store. #[method(name = "getBlobsV2")] async fn get_blobs_v2( &self, versioned_hashes: Vec, ) -> RpcResult>>; } /// A subset of the ETH rpc interface: /// /// This also includes additional eth functions required by optimism. /// /// Specifically for the engine auth server: #[cfg_attr(not(feature = "client"), rpc(server, namespace = "eth"))] #[cfg_attr(feature = "client", rpc(server, client, namespace = "eth"))] pub trait EngineEthApi { /// Returns an object with data about the sync status or false. #[method(name = "syncing")] fn syncing(&self) -> RpcResult; /// Returns the chain ID of the current network. #[method(name = "chainId")] async fn chain_id(&self) -> RpcResult>; /// Returns the number of most recent block. #[method(name = "blockNumber")] fn block_number(&self) -> RpcResult; /// Executes a new message call immediately without creating a transaction on the block chain. #[method(name = "call")] async fn call( &self, request: TransactionRequest, block_id: Option, state_overrides: Option, block_overrides: Option>, ) -> RpcResult; /// Returns code at a given address at given block number. #[method(name = "getCode")] async fn get_code(&self, address: Address, block_id: Option) -> RpcResult; /// Returns information about a block by hash. #[method(name = "getBlockByHash")] async fn block_by_hash(&self, hash: B256, full: bool) -> RpcResult>; /// Returns information about a block by number. #[method(name = "getBlockByNumber")] async fn block_by_number(&self, number: BlockNumberOrTag, full: bool) -> RpcResult>; /// Returns all transaction receipts for a given block. #[method(name = "getBlockReceipts")] async fn block_receipts(&self, block_id: BlockId) -> RpcResult>>; /// Sends signed transaction, returning its hash. #[method(name = "sendRawTransaction")] async fn send_raw_transaction(&self, bytes: Bytes) -> RpcResult; /// Returns the receipt of a transaction by transaction hash. #[method(name = "getTransactionReceipt")] async fn transaction_receipt(&self, hash: B256) -> RpcResult>; /// Returns logs matching given filter object. #[method(name = "getLogs")] async fn logs(&self, filter: Filter) -> RpcResult>; /// Returns the account and storage values of the specified account including the Merkle-proof. /// This call can be used to verify that the data you are pulling from is not tampered with. #[method(name = "getProof")] async fn get_proof( &self, address: Address, keys: Vec, block_number: Option, ) -> RpcResult; }