From e493720f64d7ea43f00967fdc96e96faa4d2988b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien?= Date: Wed, 25 Jan 2023 13:08:40 +0100 Subject: [PATCH] feat: integrate chain_id and protocol_version in NetworkInfo (#1029) --- crates/interfaces/src/error.rs | 3 +++ crates/net/network-api/src/lib.rs | 5 ++++ crates/net/network/src/manager.rs | 7 ++++-- crates/net/network/src/network.rs | 11 ++++++++- crates/net/rpc-api/src/eth.rs | 2 +- crates/net/rpc/src/eth/api/mod.rs | 37 +++++++++++++++++++--------- crates/net/rpc/src/eth/api/server.rs | 7 +++--- 7 files changed, 53 insertions(+), 19 deletions(-) diff --git a/crates/interfaces/src/error.rs b/crates/interfaces/src/error.rs index 565e70fdad..94acbcb285 100644 --- a/crates/interfaces/src/error.rs +++ b/crates/interfaces/src/error.rs @@ -16,4 +16,7 @@ pub enum Error { #[error(transparent)] Provider(#[from] crate::provider::Error), + + #[error(transparent)] + Network(#[from] reth_network_api::NetworkError), } diff --git a/crates/net/network-api/src/lib.rs b/crates/net/network-api/src/lib.rs index 8dfcd339d8..6ba098f374 100644 --- a/crates/net/network-api/src/lib.rs +++ b/crates/net/network-api/src/lib.rs @@ -26,6 +26,9 @@ pub trait NetworkInfo: Send + Sync { /// Returns the current status of the network being ran by the local node. async fn network_status(&self) -> Result; + + /// Returns the chain id + fn chain_id(&self) -> u64; } /// Provides general purpose information about Peers in the network. @@ -44,6 +47,8 @@ pub trait PeersInfo: Send + Sync { pub struct NetworkStatus { /// The local node client version. pub client_version: String, + /// The current ethereum protocol version + pub protocol_version: u64, /// Information about the Ethereum Wire Protocol. pub eth_protocol_info: EthProtocolInfo, } diff --git a/crates/net/network/src/manager.rs b/crates/net/network/src/manager.rs index 15f42723d8..1486563481 100644 --- a/crates/net/network/src/manager.rs +++ b/crates/net/network/src/manager.rs @@ -46,7 +46,7 @@ use std::{ net::SocketAddr, pin::Pin, sync::{ - atomic::{AtomicUsize, Ordering}, + atomic::{AtomicU64, AtomicUsize, Ordering}, Arc, }, task::{Context, Poll}, @@ -218,6 +218,7 @@ where peers_handle, network_mode, bandwidth_meter, + Arc::new(AtomicU64::new(chain_spec.chain.id())), ); Ok(Self { @@ -312,9 +313,11 @@ where pub fn status(&self) -> NetworkStatus { let sessions = self.swarm.sessions(); let status = sessions.status(); + let hello_message = sessions.hello_message(); NetworkStatus { - client_version: sessions.hello_message().client_version, + client_version: hello_message.client_version, + protocol_version: hello_message.protocol_version as u64, eth_protocol_info: EthProtocolInfo { difficulty: status.total_difficulty, head: status.blockhash, diff --git a/crates/net/network/src/network.rs b/crates/net/network/src/network.rs index 2ac9837c70..b02b5de4ce 100644 --- a/crates/net/network/src/network.rs +++ b/crates/net/network/src/network.rs @@ -19,7 +19,7 @@ use reth_primitives::{NodeRecord, PeerId, TransactionSigned, TxHash, H256, U256} use std::{ net::SocketAddr, sync::{ - atomic::{AtomicBool, AtomicUsize, Ordering}, + atomic::{AtomicBool, AtomicU64, AtomicUsize, Ordering}, Arc, }, }; @@ -39,6 +39,7 @@ pub struct NetworkHandle { impl NetworkHandle { /// Creates a single new instance. + #[allow(clippy::too_many_arguments)] pub(crate) fn new( num_active_peers: Arc, listener_address: Arc>, @@ -47,6 +48,7 @@ impl NetworkHandle { peers: PeersHandle, network_mode: NetworkMode, bandwidth_meter: BandwidthMeter, + chain_id: Arc, ) -> Self { let inner = NetworkInner { num_active_peers, @@ -57,6 +59,7 @@ impl NetworkHandle { network_mode, bandwidth_meter, is_syncing: Arc::new(Default::default()), + chain_id, }; Self { inner: Arc::new(inner) } } @@ -227,6 +230,10 @@ impl NetworkInfo for NetworkHandle { let _ = self.manager().send(NetworkHandleMessage::GetStatus(tx)); rx.await.map_err(Into::into) } + + fn chain_id(&self) -> u64 { + self.inner.chain_id.load(Ordering::Relaxed) + } } impl StatusUpdater for NetworkHandle { @@ -267,6 +274,8 @@ struct NetworkInner { bandwidth_meter: BandwidthMeter, /// Represents if the network is currently syncing. is_syncing: Arc, + /// The chain id + chain_id: Arc, } /// Internal messages that can be passed to the [`NetworkManager`](crate::NetworkManager). diff --git a/crates/net/rpc-api/src/eth.rs b/crates/net/rpc-api/src/eth.rs index 25eb4d1d2a..deff2d75c9 100644 --- a/crates/net/rpc-api/src/eth.rs +++ b/crates/net/rpc-api/src/eth.rs @@ -15,7 +15,7 @@ use reth_rpc_types::{ pub trait EthApi { /// Returns the protocol version encoded as a string. #[method(name = "eth_protocolVersion")] - fn protocol_version(&self) -> Result; + async fn protocol_version(&self) -> Result; /// Returns an object with data about the sync status or false. #[method(name = "eth_syncing")] diff --git a/crates/net/rpc/src/eth/api/mod.rs b/crates/net/rpc/src/eth/api/mod.rs index 355a049325..7330cea4b8 100644 --- a/crates/net/rpc/src/eth/api/mod.rs +++ b/crates/net/rpc/src/eth/api/mod.rs @@ -1,6 +1,8 @@ //! Provides everything related to `eth_` namespace +use async_trait::async_trait; use reth_interfaces::Result; +use reth_network_api::NetworkInfo; use reth_primitives::U64; use reth_provider::{BlockProvider, ChainInfo, StateProviderFactory}; use reth_rpc_types::Transaction; @@ -12,9 +14,10 @@ mod server; /// `Eth` API trait. /// /// Defines core functionality of the `eth` API implementation. +#[async_trait] pub trait EthApiSpec: Send + Sync { /// Returns the current ethereum protocol version. - fn protocol_version(&self) -> U64; + async fn protocol_version(&self) -> Result; /// Returns the chain id fn chain_id(&self) -> U64; @@ -32,19 +35,20 @@ pub trait EthApiSpec: Send + Sync { /// the main impls. This way [`EthApi`] is not limited to [`jsonrpsee`] and can be used standalone /// or in other network handlers (for example ipc). #[derive(Debug, Clone)] -pub struct EthApi { +pub struct EthApi { /// All nested fields bundled together. - inner: Arc>, + inner: Arc>, } -impl EthApi +impl EthApi where Pool: TransactionPool + 'static, Client: BlockProvider + StateProviderFactory + 'static, + Network: NetworkInfo, { /// Creates a new, shareable instance. - pub fn new(client: Arc, pool: Pool) -> Self { - let inner = EthApiInner { client, pool }; + pub fn new(client: Arc, pool: Pool, network: Network) -> Self { + let inner = EthApiInner { client, pool, network }; Self { inner: Arc::new(inner) } } @@ -52,23 +56,31 @@ where fn client(&self) -> &Arc { &self.inner.client } + + /// Returns the inner `Network` + fn network(&self) -> &Network { + &self.inner.network + } } -impl EthApiSpec for EthApi +#[async_trait] +impl EthApiSpec for EthApi where Pool: TransactionPool + Clone + 'static, Client: BlockProvider + StateProviderFactory + 'static, + Network: NetworkInfo + 'static, { /// Returns the current ethereum protocol version. /// /// Note: This returns an `U64`, since this should return as hex string. - fn protocol_version(&self) -> U64 { - 1u64.into() + async fn protocol_version(&self) -> Result { + let status = self.network().network_status().await?; + Ok(U64::from(status.protocol_version)) } /// Returns the chain id fn chain_id(&self) -> U64 { - todo!() + U64::from(self.network().chain_id()) } /// Returns the current info for the chain @@ -79,10 +91,11 @@ where /// Container type `EthApi` #[derive(Debug)] -struct EthApiInner { +struct EthApiInner { /// The transaction pool. pool: Pool, /// The client that can interact with the chain. client: Arc, - // TODO needs network access to handle things like `eth_syncing` + /// An interface to interact with the network + network: Network, } diff --git a/crates/net/rpc/src/eth/api/server.rs b/crates/net/rpc/src/eth/api/server.rs index 75d4c98a92..0720573158 100644 --- a/crates/net/rpc/src/eth/api/server.rs +++ b/crates/net/rpc/src/eth/api/server.rs @@ -19,14 +19,15 @@ use serde_json::Value; use super::EthApiSpec; #[async_trait::async_trait] -impl EthApiServer for EthApi +impl EthApiServer for EthApi where Self: EthApiSpec, Pool: TransactionPool + 'static, Client: BlockProvider + StateProviderFactory + 'static, + Network: 'static, { - fn protocol_version(&self) -> Result { - Ok(EthApiSpec::protocol_version(self)) + async fn protocol_version(&self) -> Result { + EthApiSpec::protocol_version(self).await.to_rpc_result() } fn syncing(&self) -> Result {