Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion crates/node-builder/src/launch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ use reth_node_core::{
engine_skip_fcu::EngineApiSkipFcu,
exit::NodeExitFuture,
init::init_genesis,
CLIENTVERSIONV1,
};
use reth_node_events::{cl::ConsensusLayerHealthEvents, node};
use reth_primitives::format_ether;
Expand Down Expand Up @@ -450,13 +451,19 @@ ReadyTransaction");
database.clone(),
),
);

let client = ClientVersionV1 {
code: CLIENTVERSIONV1.code,
name: CLIENTVERSIONV1.name,
version: CLIENTVERSIONV1.version,
commit: CLIENTVERSIONV1.commit,
};
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");

Expand Down
36 changes: 35 additions & 1 deletion crates/node-core/src/version.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
//! Version information for reth.

use reth_db::models::client_version::ClientVersion;

// The client code for Reth
pub const CLIENT_CODE: &str = "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");

Expand All @@ -11,6 +15,36 @@ pub const VERGEN_GIT_SHA: &str = env!("VERGEN_GIT_SHA");
/// The build timestamp.
pub const VERGEN_BUILD_TIMESTAMP: &str = env!("VERGEN_BUILD_TIMESTAMP");

//The identification of the client
/// - The two letter client code
/// - The human readable name of the client
/// - The version string of the current implementation
/// - first four bytes of the latest commit hash of this build
///
/// # Example
///
/// ```text
// {
// code: "RH",
// name: "Reth",
// version: "v0.2.0-beta.5",
// commit: "defa64b2"
// }
/// ```
struct ClientVersionV1<'a> {
code: &'a str,
name: &'a str,
version: &'a str,
commit: &'a str,
}

pub const CLIENTVERSIONV1: ClientVersionV1<'_> = ClientVersionV1 {
code: CLIENT_CODE,
name: NAME_CLIENT,
version: &const_str::concat!(env!("CARGO_PKG_VERSION"), env!("RETH_VERSION_SUFFIX")),
commit: env!("VERGEN_GIT_SHA"),
};

/// The short version information for reth.
///
/// - The latest version from Cargo.toml
Expand Down
19 changes: 17 additions & 2 deletions crates/rpc/rpc-api/src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -154,6 +155,20 @@ pub trait EngineApi<Engine: EngineTypes> {
transition_configuration: TransitionConfiguration,
) -> RpcResult<TransitionConfiguration>;

/// This function will return the ClientVersionV1 object.
/// <https://github.com/ethereum/execution-apis/blob/main/src/engine/identification.md#engine_getclientversionv1> See also
///
/// - 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>>;
Expand Down
2 changes: 1 addition & 1 deletion crates/rpc/rpc-engine-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ reth-payload-builder.workspace = true
reth-tasks.workspace = true
reth-rpc-types-compat.workspace = true
reth-engine-primitives.workspace = true

#reth-node-core.workspace= true
# async
tokio = { workspace = true, features = ["sync"] }

Expand Down
32 changes: 29 additions & 3 deletions crates/rpc/rpc-engine-api/src/engine_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ 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, ForkchoiceState, ForkchoiceUpdated, PayloadId,
PayloadStatus, TransitionConfiguration, CAPABILITIES,
CancunPayloadFields, ClientVersionV1, ExecutionPayload, ExecutionPayloadBodiesV1,
ExecutionPayloadInputV2, ExecutionPayloadV1, ExecutionPayloadV3, ForkchoiceState,
ForkchoiceUpdated, PayloadId, PayloadStatus, TransitionConfiguration, CAPABILITIES,
};
use reth_rpc_types_compat::engine::payload::{
convert_payload_input_v2_to_payload, convert_to_payload_body_v1,
Expand Down Expand Up @@ -48,6 +48,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>
Expand All @@ -62,6 +64,7 @@ where
beacon_consensus: BeaconConsensusEngineHandle<EngineT>,
payload_store: PayloadStore<EngineT>,
task_spawner: Box<dyn TaskSpawner>,
client: ClientVersionV1,
) -> Self {
let inner = Arc::new(EngineApiInner {
provider,
Expand All @@ -70,6 +73,7 @@ where
payload_store,
task_spawner,
metrics: EngineApiMetrics::default(),
client,
});
Self { inner }
}
Expand Down Expand Up @@ -690,6 +694,19 @@ 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/main/src/engine/identification.md>
async fn get_client_version_v1(
&self,
client: ClientVersionV1,
) -> RpcResult<Vec<ClientVersionV1>> {
trace!(target: "rpc::engine", "Serving engine_getClientVersionV1");
let _start = Instant::now();
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>
Expand All @@ -714,15 +731,23 @@ mod tests {
use reth_beacon_consensus::BeaconEngineMessage;
use reth_ethereum_engine_primitives::EthEngineTypes;
use reth_interfaces::test_utils::generators::random_block;
use reth_node_core::CLIENTVERSIONV1;
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::ClientVersionV1;
use reth_rpc_types_compat::engine::payload::execution_payload_from_sealed_block;
use reth_tasks::TokioTaskExecutor;
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver};

fn setup_engine_api() -> (EngineApiTestHandle, EngineApi<Arc<MockEthProvider>, EthEngineTypes>)
{
let client = ClientVersionV1 {
code: CLIENTVERSIONV1.code,
name: CLIENTVERSIONV1.name,
version: CLIENTVERSIONV1.version,
commit: CLIENTVERSIONV1.commit,
};
let chain_spec: Arc<ChainSpec> = MAINNET.clone();
let provider = Arc::new(MockEthProvider::default());
let payload_store = spawn_test_payload_service();
Expand All @@ -734,6 +759,7 @@ mod tests {
BeaconConsensusEngineHandle::new(to_engine),
payload_store.into(),
task_executor,
client,
);
let handle = EngineApiTestHandle { chain_spec, provider, from_api: engine_rx };
(handle, api)
Expand Down