Skip to content

Commit

Permalink
feat: add EngineApi extension trait (#676)
Browse files Browse the repository at this point in the history
* feat: add `EngineApi` extension trait

* feat: add get_client_version_v1()

* nit: rename `engine` feature

* nit: update get_client_version_v1() doc
  • Loading branch information
leruaa authored May 6, 2024
1 parent df1cd7b commit 0d77f1e
Show file tree
Hide file tree
Showing 4 changed files with 260 additions and 1 deletion.
2 changes: 2 additions & 0 deletions crates/provider/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ alloy-signer-wallet = { workspace = true, optional = true }
alloy-rpc-client.workspace = true
alloy-rpc-types-trace.workspace = true
alloy-rpc-types.workspace = true
alloy-rpc-types-engine = { workspace = true, optional = true }
alloy-transport-http = { workspace = true, optional = true }
alloy-transport-ipc = { workspace = true, optional = true }
alloy-transport-ws = { workspace = true, optional = true }
Expand Down Expand Up @@ -70,3 +71,4 @@ reqwest-default-tls = ["alloy-transport-http?/reqwest-default-tls"]
reqwest-rustls-tls = ["alloy-transport-http?/reqwest-rustls-tls"]
reqwest-native-tls = ["alloy-transport-http?/reqwest-native-tls"]
anvil = ["reqwest", "dep:alloy-node-bindings", "dep:alloy-signer-wallet"]
engine-api = ["dep:alloy-rpc-types-engine"]
1 change: 0 additions & 1 deletion crates/provider/src/ext/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ where
P: Provider<T, N>,
{
async fn add_peer(&self, record: &str) -> TransportResult<bool> {
// self.client().
self.client().request("admin_addPeer", (record,)).await
}

Expand Down
253 changes: 253 additions & 0 deletions crates/provider/src/ext/engine.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
use alloy_network::Network;
use alloy_primitives::{BlockHash, B256};
use alloy_rpc_types_engine::{
ClientVersionV1, ExecutionPayloadBodiesV1, ExecutionPayloadInputV2, ExecutionPayloadV1,
ExecutionPayloadV2, ExecutionPayloadV3, ForkchoiceState, ForkchoiceUpdated, PayloadAttributes,
PayloadId, PayloadStatus,
};
use alloy_transport::{Transport, TransportResult};

use crate::Provider;

/// Extension trait that gives access to engine api RPC methods.
///
/// Note:
/// > The provider should use a JWT authentication layer.
#[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
pub trait EngineApi<N, T>: Send + Sync {
/// Sends the given payload to the execution layer client, as specified for the Paris fork.
///
/// Caution: This should not accept the `withdrawals` field
///
/// See also <https://github.com/ethereum/execution-apis/blob/6709c2a795b707202e93c4f2867fa0bf2640a84f/src/engine/paris.md#engine_newpayloadv1>
async fn new_payload_v1(&self, payload: ExecutionPayloadV1) -> TransportResult<PayloadStatus>;

/// Sends the given payload to the execution layer client, as specified for the Shanghai fork.
///
/// See also <https://github.com/ethereum/execution-apis/blob/584905270d8ad665718058060267061ecfd79ca5/src/engine/shanghai.md#engine_newpayloadv2>
async fn new_payload_v2(
&self,
payload: ExecutionPayloadInputV2,
) -> TransportResult<PayloadStatus>;

/// Sends the given payload to the execution layer client, as specified for the Cancun fork.
///
/// See also <https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#engine_newpayloadv3>
async fn new_payload_v3(
&self,
payload: ExecutionPayloadV3,
versioned_hashes: Vec<B256>,
parent_beacon_block_root: B256,
) -> TransportResult<PayloadStatus>;

/// Updates the execution layer client with the given fork choice, as specified for the Paris
/// fork.
///
/// Caution: This should not accept the `withdrawals` field in the payload attributes.
///
/// See also <https://github.com/ethereum/execution-apis/blob/6709c2a795b707202e93c4f2867fa0bf2640a84f/src/engine/paris.md#engine_forkchoiceupdatedv1>
async fn fork_choice_updated_v1(
&self,
fork_choice_state: ForkchoiceState,
payload_attributes: Option<PayloadAttributes>,
) -> TransportResult<ForkchoiceUpdated>;

/// Updates the execution layer client with the given fork choice, as specified for the Shanghai
/// fork.
///
/// Caution: This should not accept the `parentBeaconBlockRoot` field in the payload attributes.
///
/// See also <https://github.com/ethereum/execution-apis/blob/6709c2a795b707202e93c4f2867fa0bf2640a84f/src/engine/shanghai.md#engine_forkchoiceupdatedv2>
async fn fork_choice_updated_v2(
&self,
fork_choice_state: ForkchoiceState,
payload_attributes: Option<PayloadAttributes>,
) -> TransportResult<ForkchoiceUpdated>;

/// Updates the execution layer client with the given fork choice, as specified for the Cancun
/// fork.
///
/// See also <https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#engine_forkchoiceupdatedv3>
async fn fork_choice_updated_v3(
&self,
fork_choice_state: ForkchoiceState,
payload_attributes: Option<PayloadAttributes>,
) -> TransportResult<ForkchoiceUpdated>;

/// Retrieves an executionpayload from a previously started build process, as specified for the
/// Paris fork.
///
/// Caution: This should not return the `withdrawals` field
///
/// See also <https://github.com/ethereum/execution-apis/blob/6709c2a795b707202e93c4f2867fa0bf2640a84f/src/engine/paris.md#engine_getpayloadv1>
///
/// Note:
/// > Provider software MAY stop the corresponding build process after serving this call.
async fn get_payload_v1(&self, payload_id: PayloadId) -> TransportResult<ExecutionPayloadV1>;

/// Retrieves an executionpayload from a previously started build process, as specified for the
/// Shanghai fork.
///
/// See also <https://github.com/ethereum/execution-apis/blob/6709c2a795b707202e93c4f2867fa0bf2640a84f/src/engine/shanghai.md#engine_getpayloadv2>
///
/// Note:
/// > Provider software MAY stop the corresponding build process after serving this call.
async fn get_payload_v2(&self, payload_id: PayloadId) -> TransportResult<ExecutionPayloadV2>;

/// Retrieves an executionpayload from a previously started build process, as specified for the
/// Cancun fork.
///
/// See also <https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#engine_getpayloadv3>
///
/// Note:
/// > Provider software MAY stop the corresponding build process after serving this call.
async fn get_payload_v3(&self, payload_id: PayloadId) -> TransportResult<ExecutionPayloadV2>;

/// Returns the execution payload bodies by the given hash.
///
/// See also <https://github.com/ethereum/execution-apis/blob/6452a6b194d7db269bf1dbd087a267251d3cc7f8/src/engine/shanghai.md#engine_getpayloadbodiesbyhashv1>
async fn get_payload_bodies_by_hash_v1(
&self,
block_hashes: Vec<BlockHash>,
) -> TransportResult<ExecutionPayloadBodiesV1>;

/// 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.
///
/// See also <https://github.com/ethereum/execution-apis/blob/6452a6b194d7db269bf1dbd087a267251d3cc7f8/src/engine/shanghai.md#engine_getpayloadbodiesbyrangev1>
async fn get_payload_bodies_by_range_v1(
&self,
start: u64,
count: u64,
) -> TransportResult<ExecutionPayloadBodiesV1>;

/// Returns the execution client version information.
///
/// Note:
/// > The `client_version` parameter identifies the consensus client.
///
/// See also <https://github.com/ethereum/execution-apis/blob/main/src/engine/identification.md#engine_getclientversionv1>
async fn get_client_version_v1(
&self,
client_version: ClientVersionV1,
) -> TransportResult<Vec<ClientVersionV1>>;

/// Returns the list of Engine api methods supported by the execution layer client software.
///
/// See also <https://github.com/ethereum/execution-apis/blob/6452a6b194d7db269bf1dbd087a267251d3cc7f8/src/engine/common.md#capabilities>
async fn exchange_capabilities(
&self,
capabilities: Vec<String>,
) -> TransportResult<Vec<String>>;
}

#[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
impl<N, T, P> EngineApi<N, T> for P
where
N: Network,
T: Transport + Clone,
P: Provider<T, N>,
{
async fn new_payload_v1(&self, payload: ExecutionPayloadV1) -> TransportResult<PayloadStatus> {
self.client().request("engine_newPayloadV1", (payload,)).await
}

async fn new_payload_v2(
&self,
payload: ExecutionPayloadInputV2,
) -> TransportResult<PayloadStatus> {
self.client().request("engine_newPayloadV2", (payload,)).await
}

async fn new_payload_v3(
&self,
payload: ExecutionPayloadV3,
versioned_hashes: Vec<B256>,
parent_beacon_block_root: B256,
) -> TransportResult<PayloadStatus> {
self.client()
.request("engine_newPayloadV3", (payload, versioned_hashes, parent_beacon_block_root))
.await
}

async fn fork_choice_updated_v1(
&self,
fork_choice_state: ForkchoiceState,
payload_attributes: Option<PayloadAttributes>,
) -> TransportResult<ForkchoiceUpdated> {
self.client()
.request("engine_forkchoiceUpdatedV1", (fork_choice_state, payload_attributes))
.await
}

async fn fork_choice_updated_v2(
&self,
fork_choice_state: ForkchoiceState,
payload_attributes: Option<PayloadAttributes>,
) -> TransportResult<ForkchoiceUpdated> {
self.client()
.request("engine_forkchoiceUpdatedV2", (fork_choice_state, payload_attributes))
.await
}

async fn fork_choice_updated_v3(
&self,
fork_choice_state: ForkchoiceState,
payload_attributes: Option<PayloadAttributes>,
) -> TransportResult<ForkchoiceUpdated> {
self.client()
.request("engine_forkchoiceUpdatedV3", (fork_choice_state, payload_attributes))
.await
}

async fn get_payload_v1(&self, payload_id: PayloadId) -> TransportResult<ExecutionPayloadV1> {
self.client().request("engine_getPayloadV1", (payload_id,)).await
}

async fn get_payload_v2(&self, payload_id: PayloadId) -> TransportResult<ExecutionPayloadV2> {
self.client().request("engine_getPayloadV2", (payload_id,)).await
}

async fn get_payload_v3(&self, payload_id: PayloadId) -> TransportResult<ExecutionPayloadV2> {
self.client().request("engine_getPayloadV3", (payload_id,)).await
}

async fn get_payload_bodies_by_hash_v1(
&self,
block_hashes: Vec<BlockHash>,
) -> TransportResult<ExecutionPayloadBodiesV1> {
self.client().request("engine_getPayloadBodiesByHashV1", (block_hashes,)).await
}

async fn get_payload_bodies_by_range_v1(
&self,
start: u64,
count: u64,
) -> TransportResult<ExecutionPayloadBodiesV1> {
self.client().request("engine_getPayloadBodiesByRangeV1", (start, count)).await
}

async fn get_client_version_v1(
&self,
client_version: ClientVersionV1,
) -> TransportResult<Vec<ClientVersionV1>> {
self.client().request("engine_getClientVersionV1", (client_version,)).await
}

async fn exchange_capabilities(
&self,
capabilities: Vec<String>,
) -> TransportResult<Vec<String>> {
self.client().request("engine_exchangeCapabilities", (capabilities,)).await
}
}
5 changes: 5 additions & 0 deletions crates/provider/src/ext/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
mod admin;
pub use admin::AdminApi;

#[cfg(feature = "engine-api")]
mod engine;
#[cfg(feature = "engine-api")]
pub use engine::EngineApi;

mod debug;
pub use debug::DebugApi;

Expand Down

0 comments on commit 0d77f1e

Please sign in to comment.