feat: implement clientVersionV1 in engine API (#8016)

This commit is contained in:
guha-rahul
2024-05-24 23:08:06 +05:30
committed by GitHub
parent 59622dbd48
commit a8e5eb6186
7 changed files with 96 additions and 7 deletions

1
Cargo.lock generated
View File

@@ -7325,6 +7325,7 @@ dependencies = [
"reth-rpc",
"reth-rpc-engine-api",
"reth-rpc-layer",
"reth-rpc-types",
"reth-stages",
"reth-static-file",
"reth-tasks",

View File

@@ -1,6 +1,12 @@
//! Version information for reth.
use reth_db::models::client_version::ClientVersion;
use reth_rpc_types::engine::ClientCode;
/// The client code for Reth
pub const CLIENT_CODE: ClientCode = ClientCode::RH;
/// The human readable name of the client
pub const NAME_CLIENT: &str = "Reth";
/// The latest version from Cargo.toml.
pub const CARGO_PKG_VERSION: &str = env!("CARGO_PKG_VERSION");

View File

@@ -39,7 +39,7 @@ reth-config.workspace = true
reth-downloaders.workspace = true
reth-node-events.workspace = true
reth-consensus.workspace = true
reth-rpc-types.workspace = true
## async
futures.workspace = true
tokio = { workspace = true, features = [

View File

@@ -25,11 +25,13 @@ use reth_node_core::{
dirs::{ChainPath, DataDirPath},
engine::EngineMessageStreamExt,
exit::NodeExitFuture,
version::{CARGO_PKG_VERSION, CLIENT_CODE, NAME_CLIENT, VERGEN_GIT_SHA},
};
use reth_node_events::{cl::ConsensusLayerHealthEvents, node};
use reth_primitives::format_ether;
use reth_provider::{providers::BlockchainProvider, CanonStateSubscriptions};
use reth_rpc_engine_api::EngineApi;
use reth_rpc_types::engine::ClientVersionV1;
use reth_tasks::TaskExecutor;
use reth_tracing::tracing::{debug, info};
use reth_transaction_pool::TransactionPool;
@@ -407,12 +409,19 @@ where
),
);
let client = ClientVersionV1 {
code: CLIENT_CODE,
name: NAME_CLIENT.to_string(),
version: CARGO_PKG_VERSION.to_string(),
commit: VERGEN_GIT_SHA.to_string(),
};
let engine_api = EngineApi::new(
blockchain_db.clone(),
ctx.chain_spec(),
beacon_engine_handle,
node_adapter.components.payload_builder().clone().into(),
Box::new(ctx.task_executor().clone()),
client,
);
info!(target: "reth::cli", "Engine API handler initialized");

View File

@@ -8,8 +8,9 @@ use reth_engine_primitives::EngineTypes;
use reth_primitives::{Address, BlockHash, BlockId, BlockNumberOrTag, Bytes, B256, U256, U64};
use reth_rpc_types::{
engine::{
ExecutionPayloadBodiesV1, ExecutionPayloadInputV2, ExecutionPayloadV1, ExecutionPayloadV3,
ForkchoiceState, ForkchoiceUpdated, PayloadId, PayloadStatus, TransitionConfiguration,
ClientVersionV1, ExecutionPayloadBodiesV1, ExecutionPayloadInputV2, ExecutionPayloadV1,
ExecutionPayloadV3, ForkchoiceState, ForkchoiceUpdated, PayloadId, PayloadStatus,
TransitionConfiguration,
},
state::StateOverride,
BlockOverrides, Filter, Log, RichBlock, SyncStatus, TransactionRequest,
@@ -154,6 +155,22 @@ pub trait EngineApi<Engine: EngineTypes> {
transition_configuration: TransitionConfiguration,
) -> RpcResult<TransitionConfiguration>;
/// This function will return the ClientVersionV1 object.
/// See also:
/// <https://github.com/ethereum/execution-apis/blob/03911ffc053b8b806123f1fc237184b0092a485a/src/engine/identification.md#engine_getclientversionv1>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<Vec<ClientVersionV1>>;
/// See also <https://github.com/ethereum/execution-apis/blob/6452a6b194d7db269bf1dbd087a267251d3cc7f8/src/engine/common.md#capabilities>
#[method(name = "exchangeCapabilities")]
async fn exchange_capabilities(&self, capabilities: Vec<String>) -> RpcResult<Vec<String>>;

View File

@@ -12,6 +12,7 @@ use reth_rpc_builder::{
};
use reth_rpc_engine_api::EngineApi;
use reth_rpc_layer::JwtSecret;
use reth_rpc_types::engine::{ClientCode, ClientVersionV1};
use reth_tasks::TokioTaskExecutor;
use reth_transaction_pool::test_utils::{TestPool, TestPoolBuilder};
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
@@ -28,12 +29,20 @@ pub async fn launch_auth(secret: JwtSecret) -> AuthServerHandle {
let (tx, _rx) = unbounded_channel();
let beacon_engine_handle =
BeaconConsensusEngineHandle::<EthEngineTypes>::new(tx, Default::default());
let client = ClientVersionV1 {
code: ClientCode::RH,
name: "Reth".to_string(),
version: "v0.2.0-beta.5".to_string(),
commit: "defa64b2".to_string(),
};
let engine_api = EngineApi::new(
NoopProvider::default(),
MAINNET.clone(),
beacon_engine_handle,
spawn_test_payload_service().into(),
Box::<TokioTaskExecutor>::default(),
client,
);
let module = AuthRpcModule::new(engine_api);
module.start_server(config).await.unwrap()

View File

@@ -11,9 +11,10 @@ use reth_primitives::{BlockHash, BlockHashOrNumber, BlockNumber, ChainSpec, Hard
use reth_provider::{BlockReader, EvmEnvProvider, HeaderProvider, StateProviderFactory};
use reth_rpc_api::EngineApiServer;
use reth_rpc_types::engine::{
CancunPayloadFields, ExecutionPayload, ExecutionPayloadBodiesV1, ExecutionPayloadInputV2,
ExecutionPayloadV1, ExecutionPayloadV3, ExecutionPayloadV4, ForkchoiceState, ForkchoiceUpdated,
PayloadId, PayloadStatus, TransitionConfiguration, CAPABILITIES,
CancunPayloadFields, ClientVersionV1, ExecutionPayload, ExecutionPayloadBodiesV1,
ExecutionPayloadInputV2, ExecutionPayloadV1, ExecutionPayloadV3, ExecutionPayloadV4,
ForkchoiceState, ForkchoiceUpdated, PayloadId, PayloadStatus, TransitionConfiguration,
CAPABILITIES,
};
use reth_rpc_types_compat::engine::payload::{
convert_payload_input_v2_to_payload, convert_to_payload_body_v1,
@@ -48,6 +49,8 @@ struct EngineApiInner<Provider, EngineT: EngineTypes> {
task_spawner: Box<dyn TaskSpawner>,
/// The latency and response type metrics for engine api calls
metrics: EngineApiMetrics,
/// Identification of the execution client used by the consensus client
client: ClientVersionV1,
}
impl<Provider, EngineT> EngineApi<Provider, EngineT>
@@ -62,6 +65,7 @@ where
beacon_consensus: BeaconConsensusEngineHandle<EngineT>,
payload_store: PayloadStore<EngineT>,
task_spawner: Box<dyn TaskSpawner>,
client: ClientVersionV1,
) -> Self {
let inner = Arc::new(EngineApiInner {
provider,
@@ -70,10 +74,18 @@ where
payload_store,
task_spawner,
metrics: EngineApiMetrics::default(),
client,
});
Self { inner }
}
/// Fetches the client version.
async fn get_client_version_v1(
&self,
_client: ClientVersionV1,
) -> EngineApiResult<Vec<ClientVersionV1>> {
Ok(vec![self.inner.client.clone()])
}
/// Fetches the attributes for the payload with the given id.
async fn get_payload_attributes(
&self,
@@ -749,6 +761,18 @@ where
self.inner.metrics.latency.exchange_transition_configuration.record(start.elapsed());
Ok(res?)
}
/// Handler for `engine_getClientVersionV1`
///
/// See also <https://github.com/ethereum/execution-apis/blob/03911ffc053b8b806123f1fc237184b0092a485a/src/engine/identification.md>
async fn get_client_version_v1(
&self,
client: ClientVersionV1,
) -> RpcResult<Vec<ClientVersionV1>> {
trace!(target: "rpc::engine", "Serving engine_getClientVersionV1");
let res = EngineApi::get_client_version_v1(self, client).await;
Ok(res?)
}
/// Handler for `engine_exchangeCapabilitiesV1`
/// See also <https://github.com/ethereum/execution-apis/blob/6452a6b194d7db269bf1dbd087a267251d3cc7f8/src/engine/common.md#capabilities>
@@ -773,9 +797,11 @@ mod tests {
use reth_beacon_consensus::{BeaconConsensusEngineEvent, BeaconEngineMessage};
use reth_ethereum_engine_primitives::EthEngineTypes;
use reth_interfaces::test_utils::generators::random_block;
use reth_payload_builder::test_utils::spawn_test_payload_service;
use reth_primitives::{SealedBlock, B256, MAINNET};
use reth_provider::test_utils::MockEthProvider;
use reth_rpc_types::engine::{ClientCode, ClientVersionV1};
use reth_rpc_types_compat::engine::payload::execution_payload_from_sealed_block;
use reth_tasks::TokioTaskExecutor;
use reth_tokio_util::EventSender;
@@ -783,6 +809,13 @@ mod tests {
fn setup_engine_api() -> (EngineApiTestHandle, EngineApi<Arc<MockEthProvider>, EthEngineTypes>)
{
let client = ClientVersionV1 {
code: ClientCode::RH,
name: "Reth".to_string(),
version: "v0.2.0-beta.5".to_string(),
commit: "defa64b2".to_string(),
};
let chain_spec: Arc<ChainSpec> = MAINNET.clone();
let provider = Arc::new(MockEthProvider::default());
let payload_store = spawn_test_payload_service();
@@ -795,11 +828,25 @@ mod tests {
BeaconConsensusEngineHandle::new(to_engine, event_sender),
payload_store.into(),
task_executor,
client,
);
let handle = EngineApiTestHandle { chain_spec, provider, from_api: engine_rx };
(handle, api)
}
#[tokio::test]
async fn engine_client_version_v1() {
let client = ClientVersionV1 {
code: ClientCode::RH,
name: "Reth".to_string(),
version: "v0.2.0-beta.5".to_string(),
commit: "defa64b2".to_string(),
};
let (_, api) = setup_engine_api();
let res = api.get_client_version_v1(client.clone()).await;
assert_eq!(res.unwrap(), vec![client]);
}
struct EngineApiTestHandle {
chain_spec: Arc<ChainSpec>,
provider: Arc<MockEthProvider>,