From c6531b48f883fb65571b9f13af682790e384cf64 Mon Sep 17 00:00:00 2001 From: Nil Medvedev Date: Tue, 10 Oct 2023 17:15:15 +0100 Subject: [PATCH] feat: Feat/add on rpc server started hook (#4947) Co-authored-by: Matthias Seitz --- bin/reth/Cargo.toml | 2 +- bin/reth/src/args/rpc_server_args.rs | 20 +++++++++----- bin/reth/src/cli/components.rs | 26 ++++++++++++++++++- bin/reth/src/cli/ext.rs | 39 ++++++++++++++++++++++++++++ bin/reth/src/node/mod.rs | 2 +- crates/rpc/rpc-builder/src/lib.rs | 2 +- 6 files changed, 81 insertions(+), 10 deletions(-) diff --git a/bin/reth/Cargo.toml b/bin/reth/Cargo.toml index f7be0688b..db28516ae 100644 --- a/bin/reth/Cargo.toml +++ b/bin/reth/Cargo.toml @@ -37,7 +37,7 @@ reth-rpc-builder = { path = "../../crates/rpc/rpc-builder" } reth-rpc = { path = "../../crates/rpc/rpc" } reth-rpc-types = { path = "../../crates/rpc/rpc-types" } reth-rpc-types-compat = { path = "../../crates/rpc/rpc-types-compat" } -reth-rpc-api = { path = "../../crates/rpc/rpc-api" } +reth-rpc-api = { path = "../../crates/rpc/rpc-api", features = ["client"] } reth-network = { path = "../../crates/net/network", features = ["serde"] } reth-network-api.workspace = true reth-downloaders = { path = "../../crates/net/downloaders", features = ["test-utils"] } diff --git a/bin/reth/src/args/rpc_server_args.rs b/bin/reth/src/args/rpc_server_args.rs index fe936049a..4b66eae3b 100644 --- a/bin/reth/src/args/rpc_server_args.rs +++ b/bin/reth/src/args/rpc_server_args.rs @@ -3,7 +3,7 @@ use crate::{ args::GasPriceOracleArgs, cli::{ - components::{RethNodeComponents, RethRpcComponents}, + components::{RethNodeComponents, RethRpcComponents, RethRpcServerHandles}, config::RethRpcConfig, ext::RethNodeCommandConfig, }, @@ -184,7 +184,7 @@ impl RpcServerArgs { engine_api: Engine, jwt_secret: JwtSecret, conf: &mut Conf, - ) -> eyre::Result<(RpcServerHandle, AuthServerHandle)> + ) -> eyre::Result where Reth: RethNodeComponents, Engine: EngineApiServer, @@ -202,12 +202,13 @@ impl RpcServerArgs { .with_events(components.events()) .with_executor(components.task_executor()) .build_with_auth_server(module_config, engine_api); - let node_modules = RethRpcComponents { registry: &mut registry, modules: &mut modules }; + + let rpc_components = RethRpcComponents { registry: &mut registry, modules: &mut modules }; // apply configured customization - conf.extend_rpc_modules(self, components, node_modules)?; + conf.extend_rpc_modules(self, components, rpc_components)?; let server_config = self.rpc_server_config(); - let launch_rpc = modules.start_server(server_config).map_ok(|handle| { + let launch_rpc = modules.clone().start_server(server_config).map_ok(|handle| { if let Some(url) = handle.ipc_endpoint() { info!(target: "reth::cli", url=%url, "RPC IPC server started"); } @@ -227,7 +228,14 @@ impl RpcServerArgs { }); // launch servers concurrently - Ok(futures::future::try_join(launch_rpc, launch_auth).await?) + let (rpc, auth) = futures::future::try_join(launch_rpc, launch_auth).await?; + let handles = RethRpcServerHandles { rpc, auth }; + + // call hook + let rpc_components = RethRpcComponents { registry: &mut registry, modules: &mut modules }; + conf.on_rpc_server_started(self, components, rpc_components, handles.clone())?; + + Ok(handles) } /// Convenience function for starting a rpc server with configs which extracted from cli args. diff --git a/bin/reth/src/cli/components.rs b/bin/reth/src/cli/components.rs index 1f51409cb..a550dfb2c 100644 --- a/bin/reth/src/cli/components.rs +++ b/bin/reth/src/cli/components.rs @@ -6,7 +6,9 @@ use reth_provider::{ AccountReader, BlockReaderIdExt, CanonStateSubscriptions, ChainSpecProvider, ChangeSetReader, EvmEnvProvider, StateProviderFactory, }; -use reth_rpc_builder::{RethModuleRegistry, TransportRpcModules}; +use reth_rpc_builder::{ + auth::AuthServerHandle, RethModuleRegistry, RpcServerHandle, TransportRpcModules, +}; use reth_tasks::TaskSpawner; use reth_transaction_pool::TransactionPool; use std::sync::Arc; @@ -143,3 +145,25 @@ where self.events.clone() } } + +/// Contains the handles to the spawned RPC servers. +/// +/// This can be used to access the endpoints of the servers. +/// +/// # Example +/// +/// ```rust +/// use reth::cli::components::RethRpcServerHandles; +/// use reth::rpc::api::EthApiClient; +/// # async fn t(handles: RethRpcServerHandles) { +/// let client = handles.rpc.http_client().expect("http server not started"); +/// let block_number = client.block_number().await.unwrap(); +/// # } +/// ``` +#[derive(Debug, Clone)] +pub struct RethRpcServerHandles { + /// The regular RPC server handle. + pub rpc: RpcServerHandle, + /// The handle to the auth server (engine API) + pub auth: AuthServerHandle, +} diff --git a/bin/reth/src/cli/ext.rs b/bin/reth/src/cli/ext.rs index e26434034..387284f0e 100644 --- a/bin/reth/src/cli/ext.rs +++ b/bin/reth/src/cli/ext.rs @@ -10,6 +10,8 @@ use reth_payload_builder::{PayloadBuilderHandle, PayloadBuilderService}; use reth_tasks::TaskSpawner; use std::{fmt, marker::PhantomData}; +use crate::cli::components::RethRpcServerHandles; + /// A trait that allows for extending parts of the CLI with additional functionality. /// /// This is intended as a way to allow to _extend_ the node command. For example, to register @@ -46,6 +48,25 @@ pub trait RethNodeCommandConfig: fmt::Debug { Ok(()) } + /// Event hook called once the rpc servers has been started. + fn on_rpc_server_started( + &mut self, + config: &Conf, + components: &Reth, + rpc_components: RethRpcComponents<'_, Reth>, + handles: RethRpcServerHandles, + ) -> eyre::Result<()> + where + Conf: RethRpcConfig, + Reth: RethNodeComponents, + { + let _ = config; + let _ = components; + let _ = rpc_components; + let _ = handles; + Ok(()) + } + /// Allows for registering additional RPC modules for the transports. /// /// This is expected to call the merge functions of [reth_rpc_builder::TransportRpcModules], for @@ -190,6 +211,24 @@ impl RethNodeCommandConfig for NoArgs { } } + fn on_rpc_server_started( + &mut self, + config: &Conf, + components: &Reth, + rpc_components: RethRpcComponents<'_, Reth>, + handles: RethRpcServerHandles, + ) -> eyre::Result<()> + where + Conf: RethRpcConfig, + Reth: RethNodeComponents, + { + if let Some(conf) = self.inner_mut() { + conf.on_rpc_server_started(config, components, rpc_components, handles) + } else { + Ok(()) + } + } + fn extend_rpc_modules( &mut self, config: &Conf, diff --git a/bin/reth/src/node/mod.rs b/bin/reth/src/node/mod.rs index dd58c009a..9fe1e74f3 100644 --- a/bin/reth/src/node/mod.rs +++ b/bin/reth/src/node/mod.rs @@ -533,7 +533,7 @@ impl NodeCommand { self.adjust_instance_ports(); // Start RPC servers - let (_rpc_server, _auth_server) = + let _rpc_server_handles = self.rpc.start_servers(&components, engine_api, jwt_secret, &mut self.ext).await?; // Run consensus engine to completion diff --git a/crates/rpc/rpc-builder/src/lib.rs b/crates/rpc/rpc-builder/src/lib.rs index 7c671b0c6..eac116896 100644 --- a/crates/rpc/rpc-builder/src/lib.rs +++ b/crates/rpc/rpc-builder/src/lib.rs @@ -1478,7 +1478,7 @@ impl TransportRpcModuleConfig { } /// Holds installed modules per transport type. -#[derive(Debug, Default)] +#[derive(Debug, Clone, Default)] pub struct TransportRpcModules { /// The original config config: TransportRpcModuleConfig,