diff --git a/Cargo.lock b/Cargo.lock index 5f9891c..72b2eae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1521,7 +1521,7 @@ dependencies = [ [[package]] name = "base-reth-flashblocks-rpc" -version = "0.1.0" +version = "0.1.10" dependencies = [ "alloy-consensus", "alloy-eips", @@ -1575,7 +1575,7 @@ dependencies = [ [[package]] name = "base-reth-node" -version = "0.1.0" +version = "0.1.10" dependencies = [ "alloy-consensus", "alloy-eips", @@ -1633,7 +1633,7 @@ dependencies = [ [[package]] name = "base-reth-transaction-tracing" -version = "0.1.0" +version = "0.1.10" dependencies = [ "alloy-primitives", "chrono", diff --git a/Cargo.toml b/Cargo.toml index 0a96175..63adb97 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace.package] -version = "0.1.0" +version = "0.1.10" edition = "2021" rust-version = "1.85" license = "MIT" @@ -8,7 +8,11 @@ repository = "https://github.com/base/node-reth" [workspace] resolver = "2" -members = ["crates/flashblocks-rpc", "crates/node", "crates/transaction-tracing"] +members = [ + "crates/flashblocks-rpc", + "crates/node", + "crates/transaction-tracing", +] default-members = ["crates/node"] @@ -119,4 +123,4 @@ chrono = "0.4.41" brotli = "8.0.1" arc-swap = "1.7.1" once_cell = "1.19" -rand = "0.9.2" \ No newline at end of file +rand = "0.9.2" diff --git a/crates/flashblocks-rpc/src/lib.rs b/crates/flashblocks-rpc/src/lib.rs index 3df5145..54e614f 100644 --- a/crates/flashblocks-rpc/src/lib.rs +++ b/crates/flashblocks-rpc/src/lib.rs @@ -3,5 +3,7 @@ mod pending_blocks; pub mod rpc; pub mod state; pub mod subscription; +pub mod web3; + #[cfg(test)] mod tests; diff --git a/crates/flashblocks-rpc/src/metrics.rs b/crates/flashblocks-rpc/src/metrics.rs index bd73816..434f887 100644 --- a/crates/flashblocks-rpc/src/metrics.rs +++ b/crates/flashblocks-rpc/src/metrics.rs @@ -32,6 +32,9 @@ pub struct Metrics { #[metric(describe = "Count of times flashblocks get_block_by_number is called")] pub get_block_by_number: Counter, + #[metric(describe = "Count of times web3_clientVersion is called")] + pub web3_client_version: Counter, + #[metric(describe = "Number of flashblocks in a block")] pub flashblocks_in_block: Histogram, diff --git a/crates/flashblocks-rpc/src/tests/rpc.rs b/crates/flashblocks-rpc/src/tests/rpc.rs index 0ed37d4..affa059 100644 --- a/crates/flashblocks-rpc/src/tests/rpc.rs +++ b/crates/flashblocks-rpc/src/tests/rpc.rs @@ -4,6 +4,7 @@ mod tests { use crate::state::FlashblocksState; use crate::subscription::{Flashblock, FlashblocksReceiver, Metadata}; use crate::tests::{BLOCK_INFO_TXN, BLOCK_INFO_TXN_HASH}; + use crate::web3::{Web3ApiExt, Web3ApiOverrideServer, NODE_RETH_CLIENT_VERSION}; use alloy_consensus::Receipt; use alloy_eips::BlockNumberOrTag; use alloy_genesis::Genesis; @@ -23,6 +24,7 @@ mod tests { use reth::builder::{Node, NodeBuilder, NodeConfig, NodeHandle}; use reth::chainspec::Chain; use reth::core::exit::NodeExitFuture; + use reth::core::primitives::constants::RETH_CLIENT_VERSION; use reth::tasks::TaskManager; use reth_optimism_chainspec::OpChainSpecBuilder; use reth_optimism_node::args::RollupArgs; @@ -134,13 +136,15 @@ mod tests { let flashblocks_state = Arc::new(FlashblocksState::new(ctx.provider().clone())); flashblocks_state.start(); - let api_ext = EthApiExt::new( + let eth_api_ext = EthApiExt::new( ctx.registry.eth_api().clone(), ctx.registry.eth_handlers().filter.clone(), flashblocks_state.clone(), ); + ctx.modules.replace_configured(eth_api_ext.into_rpc())?; - ctx.modules.replace_configured(api_ext.into_rpc())?; + let web3_api_ext = Web3ApiExt::new(); + ctx.modules.replace_configured(web3_api_ext.into_rpc())?; tokio::spawn(async move { while let Some((payload, tx)) = receiver.recv().await { @@ -881,4 +885,18 @@ mod tests { Ok(()) } + + #[tokio::test] + async fn test_web3_client_version() -> eyre::Result<()> { + reth_tracing::init_test_tracing(); + let node = setup_node().await?; + let provider = node.provider().await?; + + let client_version = provider.get_client_version().await?; + assert_eq!( + client_version, + format!("{}/{}", RETH_CLIENT_VERSION, NODE_RETH_CLIENT_VERSION) + ); + Ok(()) + } } diff --git a/crates/flashblocks-rpc/src/web3.rs b/crates/flashblocks-rpc/src/web3.rs new file mode 100644 index 0000000..a36ae83 --- /dev/null +++ b/crates/flashblocks-rpc/src/web3.rs @@ -0,0 +1,51 @@ +use jsonrpsee::{ + core::{async_trait, RpcResult}, + proc_macros::rpc, +}; + +use reth::core::primitives::constants::RETH_CLIENT_VERSION; +use tracing::debug; + +use crate::metrics::Metrics; + +/// The node-reth client version: `base/v{major}.{minor}.{patch}` +/// E.g. `base/v0.1.10` +pub const NODE_RETH_CLIENT_VERSION: &str = concat!("base/v", env!("CARGO_PKG_VERSION")); + +#[cfg_attr(not(test), rpc(server, namespace = "web3"))] +#[cfg_attr(test, rpc(server, client, namespace = "web3"))] +pub trait Web3ApiOverride { + #[method(name = "clientVersion")] + async fn client_version(&self) -> RpcResult; +} + +#[derive(Debug)] +pub struct Web3ApiExt { + metrics: Metrics, +} + +impl Default for Web3ApiExt { + fn default() -> Self { + Self::new() + } +} + +impl Web3ApiExt { + pub fn new() -> Self { + Self { + metrics: Metrics::default(), + } + } +} + +#[async_trait] +impl Web3ApiOverrideServer for Web3ApiExt { + async fn client_version(&self) -> RpcResult { + debug!(message = "web3::client_version"); + self.metrics.web3_client_version.increment(1); + + // reth/v{major}.{minor}.{patch}/base/v{major}.{minor}.{patch} + let client_version = format!("{}/{}", RETH_CLIENT_VERSION, NODE_RETH_CLIENT_VERSION); + Ok(client_version) + } +} diff --git a/crates/node/src/main.rs b/crates/node/src/main.rs index d1e7cd7..148168e 100644 --- a/crates/node/src/main.rs +++ b/crates/node/src/main.rs @@ -1,4 +1,5 @@ use base_reth_flashblocks_rpc::rpc::EthApiExt; +use base_reth_flashblocks_rpc::web3::Web3ApiExt; use futures_util::TryStreamExt; use once_cell::sync::OnceCell; use reth_exex::ExExEvent; @@ -7,6 +8,7 @@ use std::sync::Arc; use base_reth_flashblocks_rpc::rpc::EthApiOverrideServer; use base_reth_flashblocks_rpc::state::FlashblocksState; use base_reth_flashblocks_rpc::subscription::FlashblocksSubscriber; +use base_reth_flashblocks_rpc::web3::Web3ApiOverrideServer; use base_reth_transaction_tracing::transaction_tracing_exex; use clap::Parser; use reth::builder::Node; @@ -128,6 +130,9 @@ fn main() { } else { info!(message = "flashblocks integration is disabled"); } + + let web3_api_ext = Web3ApiExt::new(); + ctx.modules.replace_configured(web3_api_ext.into_rpc())?; Ok(()) }) .launch_with_fn(|builder| {