mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat: support admin_peers (#4435)
This commit is contained in:
@ -113,6 +113,11 @@ impl<S> MeteredStream<S> {
|
||||
pub fn get_bandwidth_meter(&self) -> &BandwidthMeter {
|
||||
&self.meter
|
||||
}
|
||||
|
||||
/// Returns the wrapped stream
|
||||
pub fn inner(&self) -> &S {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<Stream: AsyncRead> AsyncRead for MeteredStream<Stream> {
|
||||
|
||||
@ -5,6 +5,7 @@ use reth_codecs::add_arbitrary_tests;
|
||||
use reth_primitives::bytes::{BufMut, Bytes};
|
||||
use reth_rlp::{Decodable, DecodeError, Encodable, RlpDecodable, RlpEncodable};
|
||||
use smol_str::SmolStr;
|
||||
use std::fmt;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -72,6 +73,12 @@ impl Capability {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Capability {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}/{}", self.name, self.version)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "arbitrary"))]
|
||||
impl<'a> arbitrary::Arbitrary<'a> for Capability {
|
||||
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
|
||||
|
||||
@ -75,6 +75,11 @@ impl<S> UnauthedP2PStream<S> {
|
||||
pub fn new(inner: S) -> Self {
|
||||
Self { inner }
|
||||
}
|
||||
|
||||
/// Returns a reference to the inner stream.
|
||||
pub fn inner(&self) -> &S {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> UnauthedP2PStream<S>
|
||||
@ -242,6 +247,11 @@ impl<S> P2PStream<S> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to the inner stream.
|
||||
pub fn inner(&self) -> &S {
|
||||
&self.inner
|
||||
}
|
||||
|
||||
/// Sets a custom outgoing message buffer capacity.
|
||||
///
|
||||
/// # Panics
|
||||
|
||||
@ -19,13 +19,14 @@
|
||||
//!
|
||||
//! - `serde` (default): Enable serde support
|
||||
use async_trait::async_trait;
|
||||
use reth_eth_wire::DisconnectReason;
|
||||
use reth_eth_wire::{DisconnectReason, EthVersion, Status};
|
||||
use reth_primitives::{NodeRecord, PeerId};
|
||||
use reth_rpc_types::NetworkStatus;
|
||||
use std::net::SocketAddr;
|
||||
use std::{net::SocketAddr, sync::Arc};
|
||||
|
||||
pub use error::NetworkError;
|
||||
pub use reputation::{Reputation, ReputationChangeKind};
|
||||
use reth_eth_wire::capability::Capabilities;
|
||||
|
||||
/// Network Error
|
||||
pub mod error;
|
||||
@ -81,6 +82,9 @@ pub trait Peers: PeersInfo {
|
||||
/// Adds a peer to the known peer set, with the given kind.
|
||||
fn add_peer_kind(&self, peer: PeerId, kind: PeerKind, addr: SocketAddr);
|
||||
|
||||
/// Returns the rpc [PeerInfo] for all connected peers.
|
||||
async fn get_peers(&self) -> Result<Vec<PeerInfo>, NetworkError>;
|
||||
|
||||
/// Removes a peer from the peer set that corresponds to given kind.
|
||||
fn remove_peer(&self, peer: PeerId, kind: PeerKind);
|
||||
|
||||
@ -106,3 +110,54 @@ pub enum PeerKind {
|
||||
/// Trusted peer.
|
||||
Trusted,
|
||||
}
|
||||
|
||||
/// Info about an active peer session.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PeerInfo {
|
||||
/// Announced capabilities of the peer
|
||||
pub capabilities: Arc<Capabilities>,
|
||||
/// The identifier of the remote peer
|
||||
pub remote_id: PeerId,
|
||||
/// The client's name and version
|
||||
pub client_version: Arc<String>,
|
||||
/// The peer's address we're connected to
|
||||
pub remote_addr: SocketAddr,
|
||||
/// The local address of the connection
|
||||
pub local_addr: Option<SocketAddr>,
|
||||
/// The direction of the session
|
||||
pub direction: Direction,
|
||||
/// The negotiated eth version.
|
||||
pub eth_version: EthVersion,
|
||||
/// The Status message the peer sent for the `eth` handshake
|
||||
pub status: Status,
|
||||
}
|
||||
|
||||
/// The direction of the connection.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum Direction {
|
||||
/// Incoming connection.
|
||||
Incoming,
|
||||
/// Outgoing connection to a specific node.
|
||||
Outgoing(PeerId),
|
||||
}
|
||||
|
||||
impl Direction {
|
||||
/// Returns `true` if this an incoming connection.
|
||||
pub fn is_incoming(&self) -> bool {
|
||||
matches!(self, Direction::Incoming)
|
||||
}
|
||||
|
||||
/// Returns `true` if this an outgoing connection.
|
||||
pub fn is_outgoing(&self) -> bool {
|
||||
matches!(self, Direction::Outgoing(_))
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Direction {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Direction::Incoming => write!(f, "incoming"),
|
||||
Direction::Outgoing(_) => write!(f, "outgoing"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,7 +4,8 @@
|
||||
//! generic over it.
|
||||
|
||||
use crate::{
|
||||
NetworkError, NetworkInfo, PeerKind, Peers, PeersInfo, Reputation, ReputationChangeKind,
|
||||
NetworkError, NetworkInfo, PeerInfo, PeerKind, Peers, PeersInfo, Reputation,
|
||||
ReputationChangeKind,
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
use reth_discv4::DEFAULT_DISCOVERY_PORT;
|
||||
@ -66,6 +67,10 @@ impl PeersInfo for NoopNetwork {
|
||||
impl Peers for NoopNetwork {
|
||||
fn add_peer_kind(&self, _peer: PeerId, _kind: PeerKind, _addr: SocketAddr) {}
|
||||
|
||||
async fn get_peers(&self) -> Result<Vec<PeerInfo>, NetworkError> {
|
||||
Ok(vec![])
|
||||
}
|
||||
|
||||
fn remove_peer(&self, _peer: PeerId, _kind: PeerKind) {}
|
||||
|
||||
fn disconnect_peer(&self, _peer: PeerId) {}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
config::NetworkMode, discovery::DiscoveryEvent, manager::NetworkEvent, message::PeerRequest,
|
||||
peers::PeersHandle, session::PeerInfo, FetchClient,
|
||||
peers::PeersHandle, FetchClient,
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
use parking_lot::Mutex;
|
||||
@ -8,7 +8,8 @@ use reth_eth_wire::{DisconnectReason, NewBlock, NewPooledTransactionHashes, Shar
|
||||
use reth_interfaces::sync::{NetworkSyncUpdater, SyncState, SyncStateProvider};
|
||||
use reth_net_common::bandwidth_meter::BandwidthMeter;
|
||||
use reth_network_api::{
|
||||
NetworkError, NetworkInfo, PeerKind, Peers, PeersInfo, Reputation, ReputationChangeKind,
|
||||
NetworkError, NetworkInfo, PeerInfo, PeerKind, Peers, PeersInfo, Reputation,
|
||||
ReputationChangeKind,
|
||||
};
|
||||
use reth_primitives::{Head, NodeRecord, PeerId, TransactionSigned, H256};
|
||||
use reth_rpc_types::NetworkStatus;
|
||||
@ -102,13 +103,6 @@ impl NetworkHandle {
|
||||
rx.await
|
||||
}
|
||||
|
||||
/// Returns [`PeerInfo`] for all connected peers
|
||||
pub async fn get_peers(&self) -> Result<Vec<PeerInfo>, oneshot::error::RecvError> {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
let _ = self.manager().send(NetworkHandleMessage::GetPeerInfo(tx));
|
||||
rx.await
|
||||
}
|
||||
|
||||
/// Returns [`PeerInfo`] for a given peer.
|
||||
///
|
||||
/// Returns `None` if there's no active session to the peer.
|
||||
@ -209,6 +203,12 @@ impl Peers for NetworkHandle {
|
||||
self.send_message(NetworkHandleMessage::AddPeerAddress(peer, kind, addr));
|
||||
}
|
||||
|
||||
async fn get_peers(&self) -> Result<Vec<PeerInfo>, NetworkError> {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
let _ = self.manager().send(NetworkHandleMessage::GetPeerInfo(tx));
|
||||
Ok(rx.await?)
|
||||
}
|
||||
|
||||
/// Sends a message to the [`NetworkManager`](crate::NetworkManager) to remove a peer from the
|
||||
/// set corresponding to given kind.
|
||||
fn remove_peer(&self, peer: PeerId, kind: PeerKind) {
|
||||
|
||||
@ -10,6 +10,7 @@ use reth_eth_wire::{
|
||||
DisconnectReason, EthStream, EthVersion, P2PStream, Status,
|
||||
};
|
||||
use reth_net_common::bandwidth_meter::MeteredStream;
|
||||
use reth_network_api::PeerInfo;
|
||||
use reth_primitives::PeerId;
|
||||
use std::{io, net::SocketAddr, sync::Arc, time::Instant};
|
||||
use tokio::{
|
||||
@ -53,7 +54,6 @@ impl PendingSessionHandle {
|
||||
/// Within an active session that supports the `Ethereum Wire Protocol `, three high-level tasks can
|
||||
/// be performed: chain synchronization, block propagation and transaction exchange.
|
||||
#[derive(Debug)]
|
||||
#[allow(unused)]
|
||||
pub struct ActiveSessionHandle {
|
||||
/// The direction of the session
|
||||
pub(crate) direction: Direction,
|
||||
@ -73,6 +73,10 @@ pub struct ActiveSessionHandle {
|
||||
pub(crate) client_version: Arc<String>,
|
||||
/// The address we're connected to
|
||||
pub(crate) remote_addr: SocketAddr,
|
||||
/// The local address of the connection.
|
||||
pub(crate) local_addr: Option<SocketAddr>,
|
||||
/// The Status message the peer sent for the `eth` handshake
|
||||
pub(crate) status: Status,
|
||||
}
|
||||
|
||||
// === impl ActiveSessionHandle ===
|
||||
@ -132,21 +136,20 @@ impl ActiveSessionHandle {
|
||||
pub fn remote_addr(&self) -> SocketAddr {
|
||||
self.remote_addr
|
||||
}
|
||||
}
|
||||
|
||||
/// Info about an active peer session.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PeerInfo {
|
||||
/// Announced capabilities of the peer
|
||||
pub capabilities: Arc<Capabilities>,
|
||||
/// The identifier of the remote peer
|
||||
pub remote_id: PeerId,
|
||||
/// The client's name and version
|
||||
pub client_version: Arc<String>,
|
||||
/// The address we're connected to
|
||||
pub remote_addr: SocketAddr,
|
||||
/// The direction of the session
|
||||
pub direction: Direction,
|
||||
/// Extracts the [PeerInfo] from the session handle.
|
||||
pub(crate) fn peer_info(&self) -> PeerInfo {
|
||||
PeerInfo {
|
||||
remote_id: self.remote_id,
|
||||
direction: self.direction,
|
||||
remote_addr: self.remote_addr,
|
||||
local_addr: self.local_addr,
|
||||
capabilities: self.capabilities.clone(),
|
||||
client_version: self.client_version.clone(),
|
||||
eth_version: self.version,
|
||||
status: self.status,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Events a pending session can produce.
|
||||
@ -162,6 +165,8 @@ pub enum PendingSessionEvent {
|
||||
session_id: SessionId,
|
||||
/// The remote node's socket address
|
||||
remote_addr: SocketAddr,
|
||||
/// The local address of the connection
|
||||
local_addr: Option<SocketAddr>,
|
||||
/// The remote node's public key
|
||||
peer_id: PeerId,
|
||||
/// All capabilities the peer announced
|
||||
|
||||
@ -4,7 +4,6 @@ use crate::{
|
||||
metrics::SessionManagerMetrics,
|
||||
session::{active::ActiveSession, config::SessionCounter},
|
||||
};
|
||||
pub use crate::{message::PeerRequestSender, session::handle::PeerInfo};
|
||||
use fnv::FnvHashMap;
|
||||
use futures::{future::Either, io, FutureExt, StreamExt};
|
||||
use reth_ecies::{stream::ECIESStream, ECIESError};
|
||||
@ -40,11 +39,13 @@ use tracing::{instrument, trace};
|
||||
mod active;
|
||||
mod config;
|
||||
mod handle;
|
||||
pub use crate::message::PeerRequestSender;
|
||||
pub use config::{SessionLimits, SessionsConfig};
|
||||
pub use handle::{
|
||||
ActiveSessionHandle, ActiveSessionMessage, PendingSessionEvent, PendingSessionHandle,
|
||||
SessionCommand,
|
||||
};
|
||||
pub use reth_network_api::{Direction, PeerInfo};
|
||||
|
||||
/// Internal identifier for active sessions.
|
||||
#[derive(Debug, Clone, Copy, PartialOrd, PartialEq, Eq, Hash)]
|
||||
@ -388,6 +389,7 @@ impl SessionManager {
|
||||
PendingSessionEvent::Established {
|
||||
session_id,
|
||||
remote_addr,
|
||||
local_addr,
|
||||
peer_id,
|
||||
capabilities,
|
||||
conn,
|
||||
@ -460,6 +462,7 @@ impl SessionManager {
|
||||
|
||||
let client_version = Arc::new(client_id);
|
||||
let handle = ActiveSessionHandle {
|
||||
status,
|
||||
direction,
|
||||
session_id,
|
||||
remote_id: peer_id,
|
||||
@ -469,6 +472,7 @@ impl SessionManager {
|
||||
commands_to_session,
|
||||
client_version: Arc::clone(&client_version),
|
||||
remote_addr,
|
||||
local_addr,
|
||||
};
|
||||
|
||||
self.active_sessions.insert(peer_id, handle);
|
||||
@ -563,29 +567,14 @@ impl SessionManager {
|
||||
|
||||
/// Returns [`PeerInfo`] for all connected peers
|
||||
pub fn get_peer_info(&self) -> Vec<PeerInfo> {
|
||||
self.active_sessions
|
||||
.values()
|
||||
.map(|session| PeerInfo {
|
||||
remote_id: session.remote_id,
|
||||
direction: session.direction,
|
||||
remote_addr: session.remote_addr,
|
||||
capabilities: session.capabilities.clone(),
|
||||
client_version: session.client_version.clone(),
|
||||
})
|
||||
.collect()
|
||||
self.active_sessions.values().map(ActiveSessionHandle::peer_info).collect()
|
||||
}
|
||||
|
||||
/// Returns [`PeerInfo`] for a given peer.
|
||||
///
|
||||
/// Returns `None` if there's no active session to the peer.
|
||||
pub fn get_peer_info_by_id(&self, peer_id: PeerId) -> Option<PeerInfo> {
|
||||
self.active_sessions.get(&peer_id).map(|session| PeerInfo {
|
||||
remote_id: session.remote_id,
|
||||
direction: session.direction,
|
||||
remote_addr: session.remote_addr,
|
||||
capabilities: session.capabilities.clone(),
|
||||
client_version: session.client_version.clone(),
|
||||
})
|
||||
self.active_sessions.get(&peer_id).map(ActiveSessionHandle::peer_info)
|
||||
}
|
||||
}
|
||||
|
||||
@ -713,36 +702,6 @@ impl PendingSessionHandshakeError {
|
||||
}
|
||||
}
|
||||
|
||||
/// The direction of the connection.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum Direction {
|
||||
/// Incoming connection.
|
||||
Incoming,
|
||||
/// Outgoing connection to a specific node.
|
||||
Outgoing(PeerId),
|
||||
}
|
||||
|
||||
impl Direction {
|
||||
/// Returns `true` if this an incoming connection.
|
||||
pub fn is_incoming(&self) -> bool {
|
||||
matches!(self, Direction::Incoming)
|
||||
}
|
||||
|
||||
/// Returns `true` if this an outgoing connection.
|
||||
pub(crate) fn is_outgoing(&self) -> bool {
|
||||
matches!(self, Direction::Outgoing(_))
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Direction {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Direction::Incoming => write!(f, "incoming"),
|
||||
Direction::Outgoing(_) => write!(f, "outgoing"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The error thrown when the max configured limit has been reached and no more connections are
|
||||
/// accepted.
|
||||
#[derive(Debug, Clone, thiserror::Error)]
|
||||
@ -837,6 +796,7 @@ async fn authenticate(
|
||||
status: Status,
|
||||
fork_filter: ForkFilter,
|
||||
) {
|
||||
let local_addr = stream.inner().local_addr().ok();
|
||||
let stream = match get_eciess_stream(stream, secret_key, direction).await {
|
||||
Ok(stream) => stream,
|
||||
Err(error) => {
|
||||
@ -858,6 +818,7 @@ async fn authenticate(
|
||||
unauthed,
|
||||
session_id,
|
||||
remote_addr,
|
||||
local_addr,
|
||||
direction,
|
||||
hello,
|
||||
status,
|
||||
@ -905,6 +866,7 @@ async fn authenticate_stream(
|
||||
stream: UnauthedP2PStream<ECIESStream<MeteredStream<TcpStream>>>,
|
||||
session_id: SessionId,
|
||||
remote_addr: SocketAddr,
|
||||
local_addr: Option<SocketAddr>,
|
||||
direction: Direction,
|
||||
hello: HelloMessage,
|
||||
status: Status,
|
||||
@ -942,6 +904,7 @@ async fn authenticate_stream(
|
||||
PendingSessionEvent::Established {
|
||||
session_id,
|
||||
remote_addr,
|
||||
local_addr,
|
||||
peer_id: their_hello.id,
|
||||
capabilities: Arc::new(Capabilities::from(their_hello.capabilities)),
|
||||
status: their_status,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use jsonrpsee::{core::RpcResult, proc_macros::rpc};
|
||||
use reth_primitives::NodeRecord;
|
||||
use reth_rpc_types::NodeInfo;
|
||||
use reth_rpc_types::{NodeInfo, PeerInfo};
|
||||
|
||||
/// Admin namespace rpc interface that gives access to several non-standard RPC methods.
|
||||
#[cfg_attr(not(feature = "client"), rpc(server, namespace = "admin"))]
|
||||
@ -28,11 +28,18 @@ pub trait AdminApi {
|
||||
#[method(name = "removeTrustedPeer")]
|
||||
fn remove_trusted_peer(&self, record: NodeRecord) -> RpcResult<bool>;
|
||||
|
||||
/// The peers administrative property can be queried for all the information known about the
|
||||
/// connected remote nodes at the networking granularity. These include general information
|
||||
/// about the nodes themselves as participants of the devp2p P2P overlay protocol, as well as
|
||||
/// specialized information added by each of the running application protocols
|
||||
#[method(name = "peers")]
|
||||
async fn peers(&self) -> RpcResult<Vec<PeerInfo>>;
|
||||
|
||||
/// Creates an RPC subscription which serves events received from the network.
|
||||
#[subscription(
|
||||
name = "peerEvents",
|
||||
unsubscribe = "peerEvents_unsubscribe",
|
||||
item = String
|
||||
name = "peerEvents",
|
||||
unsubscribe = "peerEvents_unsubscribe",
|
||||
item = String
|
||||
)]
|
||||
async fn subscribe_peer_events(&self) -> jsonrpsee::core::SubscriptionResult;
|
||||
|
||||
|
||||
@ -42,7 +42,7 @@ pub enum PeerCount {
|
||||
}
|
||||
|
||||
/// Peer connection information
|
||||
#[derive(Debug, Clone, Default, Serialize)]
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
pub struct PeerInfo {
|
||||
/// Public node id
|
||||
pub id: Option<String>,
|
||||
@ -57,7 +57,7 @@ pub struct PeerInfo {
|
||||
}
|
||||
|
||||
/// Peer network information
|
||||
#[derive(Debug, Clone, Default, Serialize)]
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PeerNetworkInfo {
|
||||
/// Remote endpoint address
|
||||
@ -67,11 +67,12 @@ pub struct PeerNetworkInfo {
|
||||
}
|
||||
|
||||
/// Peer protocols information
|
||||
#[derive(Debug, Clone, Default, Serialize)]
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
pub struct PeerProtocolsInfo {
|
||||
/// Ethereum protocol information
|
||||
pub eth: Option<PeerEthProtocolInfo>,
|
||||
/// PIP protocol information.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub pip: Option<PipProtocolInfo>,
|
||||
}
|
||||
|
||||
@ -87,7 +88,7 @@ pub struct PeerEthProtocolInfo {
|
||||
}
|
||||
|
||||
/// Peer PIP protocol information
|
||||
#[derive(Debug, Clone, Default, Serialize)]
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
pub struct PipProtocolInfo {
|
||||
/// Negotiated PIP protocol version
|
||||
pub version: u32,
|
||||
|
||||
@ -4,7 +4,7 @@ use jsonrpsee::core::RpcResult;
|
||||
use reth_network_api::{NetworkInfo, PeerKind, Peers};
|
||||
use reth_primitives::NodeRecord;
|
||||
use reth_rpc_api::AdminApiServer;
|
||||
use reth_rpc_types::NodeInfo;
|
||||
use reth_rpc_types::{NodeInfo, PeerEthProtocolInfo, PeerInfo, PeerNetworkInfo, PeerProtocolsInfo};
|
||||
|
||||
/// `admin` API implementation.
|
||||
///
|
||||
@ -50,12 +50,33 @@ where
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
/// Handler for `admin_peerEvents`
|
||||
async fn subscribe_peer_events(
|
||||
&self,
|
||||
_pending: jsonrpsee::PendingSubscriptionSink,
|
||||
) -> jsonrpsee::core::SubscriptionResult {
|
||||
Err("admin_peerEvents is not implemented yet".into())
|
||||
async fn peers(&self) -> RpcResult<Vec<PeerInfo>> {
|
||||
let peers = self.network.get_peers().await.to_rpc_result()?;
|
||||
let peers = peers
|
||||
.into_iter()
|
||||
.map(|peer| PeerInfo {
|
||||
id: Some(format!("{:?}", peer.remote_id)),
|
||||
name: peer.client_version.to_string(),
|
||||
caps: peer.capabilities.capabilities().iter().map(|cap| cap.to_string()).collect(),
|
||||
network: PeerNetworkInfo {
|
||||
remote_address: peer.remote_addr.to_string(),
|
||||
local_address: peer
|
||||
.local_addr
|
||||
.unwrap_or_else(|| self.network.local_addr())
|
||||
.to_string(),
|
||||
},
|
||||
protocols: PeerProtocolsInfo {
|
||||
eth: Some(PeerEthProtocolInfo {
|
||||
difficulty: Some(peer.status.total_difficulty),
|
||||
head: format!("{:?}", peer.status.blockhash),
|
||||
version: peer.status.version as u32,
|
||||
}),
|
||||
pip: None,
|
||||
},
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(peers)
|
||||
}
|
||||
|
||||
/// Handler for `admin_nodeInfo`
|
||||
@ -65,6 +86,14 @@ where
|
||||
|
||||
Ok(NodeInfo::new(enr, status))
|
||||
}
|
||||
|
||||
/// Handler for `admin_peerEvents`
|
||||
async fn subscribe_peer_events(
|
||||
&self,
|
||||
_pending: jsonrpsee::PendingSubscriptionSink,
|
||||
) -> jsonrpsee::core::SubscriptionResult {
|
||||
Err("admin_peerEvents is not implemented yet".into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> std::fmt::Debug for AdminApi<N> {
|
||||
|
||||
Reference in New Issue
Block a user