mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
fix(rpc/admin): missing enode/enr in admin_peers endpoint (#9043)
Signed-off-by: jsvisa <delweng@gmail.com>
This commit is contained in:
@ -195,6 +195,10 @@ pub struct PeerInfo {
|
||||
pub remote_id: PeerId,
|
||||
/// The client's name and version
|
||||
pub client_version: Arc<str>,
|
||||
/// The peer's enode
|
||||
pub enode: String,
|
||||
/// The peer's enr
|
||||
pub enr: Option<String>,
|
||||
/// The peer's address we're connected to
|
||||
pub remote_addr: SocketAddr,
|
||||
/// The local address of the connection
|
||||
@ -207,6 +211,8 @@ pub struct PeerInfo {
|
||||
pub status: Arc<Status>,
|
||||
/// The timestamp when the session to that peer has been established.
|
||||
pub session_established: Instant,
|
||||
/// The peer's connection kind
|
||||
pub kind: PeerKind,
|
||||
}
|
||||
|
||||
/// The direction of the connection.
|
||||
|
||||
@ -42,7 +42,7 @@ use reth_eth_wire::{
|
||||
DisconnectReason, EthVersion, Status,
|
||||
};
|
||||
use reth_metrics::common::mpsc::UnboundedMeteredSender;
|
||||
use reth_network_api::{EthProtocolInfo, NetworkStatus, ReputationChangeKind};
|
||||
use reth_network_api::{EthProtocolInfo, NetworkStatus, PeerInfo, ReputationChangeKind};
|
||||
use reth_network_peers::{NodeRecord, PeerId};
|
||||
use reth_primitives::ForkId;
|
||||
use reth_provider::{BlockNumReader, BlockReader};
|
||||
@ -604,17 +604,17 @@ where
|
||||
}
|
||||
}
|
||||
NetworkHandleMessage::GetPeerInfos(tx) => {
|
||||
let _ = tx.send(self.swarm.sessions_mut().get_peer_info());
|
||||
let _ = tx.send(self.get_peer_infos());
|
||||
}
|
||||
NetworkHandleMessage::GetPeerInfoById(peer_id, tx) => {
|
||||
let _ = tx.send(self.swarm.sessions_mut().get_peer_info_by_id(peer_id));
|
||||
let _ = tx.send(self.get_peer_info_by_id(peer_id));
|
||||
}
|
||||
NetworkHandleMessage::GetPeerInfosByIds(peer_ids, tx) => {
|
||||
let _ = tx.send(self.swarm.sessions().get_peer_infos_by_ids(peer_ids));
|
||||
let _ = tx.send(self.get_peer_infos_by_ids(peer_ids));
|
||||
}
|
||||
NetworkHandleMessage::GetPeerInfosByPeerKind(kind, tx) => {
|
||||
let peers = self.swarm.state().peers().peers_by_kind(kind);
|
||||
let _ = tx.send(self.swarm.sessions().get_peer_infos_by_ids(peers));
|
||||
let peer_ids = self.swarm.state().peers().peers_by_kind(kind);
|
||||
let _ = tx.send(self.get_peer_infos_by_ids(peer_ids));
|
||||
}
|
||||
NetworkHandleMessage::AddRlpxSubProtocol(proto) => self.add_rlpx_sub_protocol(proto),
|
||||
NetworkHandleMessage::GetTransactionsHandle(tx) => {
|
||||
@ -865,6 +865,42 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns [`PeerInfo`] for all connected peers
|
||||
fn get_peer_infos(&self) -> Vec<PeerInfo> {
|
||||
self.swarm
|
||||
.sessions()
|
||||
.active_sessions()
|
||||
.iter()
|
||||
.filter_map(|(&peer_id, session)| {
|
||||
self.swarm
|
||||
.state()
|
||||
.peers()
|
||||
.peer_by_id(peer_id)
|
||||
.map(|(record, kind)| session.peer_info(&record, kind))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Returns [`PeerInfo`] for a given peer.
|
||||
///
|
||||
/// Returns `None` if there's no active session to the peer.
|
||||
fn get_peer_info_by_id(&self, peer_id: PeerId) -> Option<PeerInfo> {
|
||||
self.swarm.sessions().active_sessions().get(&peer_id).and_then(|session| {
|
||||
self.swarm
|
||||
.state()
|
||||
.peers()
|
||||
.peer_by_id(peer_id)
|
||||
.map(|(record, kind)| session.peer_info(&record, kind))
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns [`PeerInfo`] for a given peers.
|
||||
///
|
||||
/// Ignore the non-active peer.
|
||||
fn get_peer_infos_by_ids(&self, peer_ids: impl IntoIterator<Item = PeerId>) -> Vec<PeerInfo> {
|
||||
peer_ids.into_iter().filter_map(|peer_id| self.get_peer_info_by_id(peer_id)).collect()
|
||||
}
|
||||
|
||||
/// Updates the metrics for active,established connections
|
||||
#[inline]
|
||||
fn update_active_connection_metrics(&self) {
|
||||
|
||||
@ -212,15 +212,17 @@ impl PeersManager {
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the [`NodeRecord`] for the given peer id
|
||||
#[allow(dead_code)]
|
||||
fn peer_by_id(&self, peer_id: PeerId) -> Option<NodeRecord> {
|
||||
/// Returns the `NodeRecord` and `PeerKind` for the given peer id
|
||||
pub(crate) fn peer_by_id(&self, peer_id: PeerId) -> Option<(NodeRecord, PeerKind)> {
|
||||
self.peers.get(&peer_id).map(|v| {
|
||||
NodeRecord::new_with_ports(
|
||||
v.addr.tcp.ip(),
|
||||
v.addr.tcp.port(),
|
||||
v.addr.udp.map(|addr| addr.port()),
|
||||
peer_id,
|
||||
(
|
||||
NodeRecord::new_with_ports(
|
||||
v.addr.tcp.ip(),
|
||||
v.addr.tcp.port(),
|
||||
v.addr.udp.map(|addr| addr.port()),
|
||||
peer_id,
|
||||
),
|
||||
v.kind,
|
||||
)
|
||||
})
|
||||
}
|
||||
@ -1378,7 +1380,7 @@ mod tests {
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
let record = peers.peer_by_id(peer).unwrap();
|
||||
let (record, _) = peers.peer_by_id(peer).unwrap();
|
||||
assert_eq!(record.tcp_addr(), socket_addr);
|
||||
assert_eq!(record.udp_addr(), socket_addr);
|
||||
}
|
||||
@ -1405,7 +1407,7 @@ mod tests {
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
let record = peers.peer_by_id(peer).unwrap();
|
||||
let (record, _) = peers.peer_by_id(peer).unwrap();
|
||||
assert_eq!(record.tcp_addr(), tcp_addr);
|
||||
assert_eq!(record.udp_addr(), udp_addr);
|
||||
}
|
||||
|
||||
@ -11,8 +11,8 @@ use reth_eth_wire::{
|
||||
errors::EthStreamError,
|
||||
DisconnectReason, EthVersion, Status,
|
||||
};
|
||||
use reth_network_api::PeerInfo;
|
||||
use reth_network_peers::PeerId;
|
||||
use reth_network_api::{PeerInfo, PeerKind};
|
||||
use reth_network_peers::{NodeRecord, PeerId};
|
||||
use std::{io, net::SocketAddr, sync::Arc, time::Instant};
|
||||
use tokio::sync::{
|
||||
mpsc::{self, error::SendError},
|
||||
@ -136,10 +136,12 @@ impl ActiveSessionHandle {
|
||||
}
|
||||
|
||||
/// Extracts the [`PeerInfo`] from the session handle.
|
||||
pub(crate) fn peer_info(&self) -> PeerInfo {
|
||||
pub(crate) fn peer_info(&self, record: &NodeRecord, kind: PeerKind) -> PeerInfo {
|
||||
PeerInfo {
|
||||
remote_id: self.remote_id,
|
||||
direction: self.direction,
|
||||
enode: record.to_string(),
|
||||
enr: None,
|
||||
remote_addr: self.remote_addr,
|
||||
local_addr: self.local_addr,
|
||||
capabilities: self.capabilities.clone(),
|
||||
@ -147,6 +149,7 @@ impl ActiveSessionHandle {
|
||||
eth_version: self.version,
|
||||
status: self.status.clone(),
|
||||
session_established: self.established,
|
||||
kind,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -170,6 +170,11 @@ impl SessionManager {
|
||||
self.secret_key
|
||||
}
|
||||
|
||||
/// Returns a borrowed reference to the active sessions.
|
||||
pub const fn active_sessions(&self) -> &HashMap<PeerId, ActiveSessionHandle> {
|
||||
&self.active_sessions
|
||||
}
|
||||
|
||||
/// Returns the session hello message.
|
||||
pub fn hello_message(&self) -> HelloMessageWithProtocols {
|
||||
self.hello_message.clone()
|
||||
@ -587,35 +592,6 @@ impl SessionManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns [`PeerInfo`] for all connected peers
|
||||
pub(crate) fn get_peer_info(&self) -> Vec<PeerInfo> {
|
||||
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(crate) fn get_peer_info_by_id(&self, peer_id: PeerId) -> Option<PeerInfo> {
|
||||
self.active_sessions.get(&peer_id).map(ActiveSessionHandle::peer_info)
|
||||
}
|
||||
/// Returns [`PeerInfo`] for a given peer.
|
||||
///
|
||||
/// Returns `None` if there's no active session to the peer.
|
||||
pub(crate) fn get_peer_infos_by_ids(
|
||||
&self,
|
||||
peer_ids: impl IntoIterator<Item = PeerId>,
|
||||
) -> Vec<PeerInfo> {
|
||||
let mut infos = Vec::new();
|
||||
for peer_id in peer_ids {
|
||||
if let Some(info) =
|
||||
self.active_sessions.get(&peer_id).map(ActiveSessionHandle::peer_info)
|
||||
{
|
||||
infos.push(info);
|
||||
}
|
||||
}
|
||||
infos
|
||||
}
|
||||
}
|
||||
|
||||
/// Events produced by the [`SessionManager`]
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use jsonrpsee::{core::RpcResult, proc_macros::rpc};
|
||||
use reth_network_peers::{AnyNode, NodeRecord};
|
||||
use reth_rpc_types::{admin::NodeInfo, PeerInfo};
|
||||
use reth_rpc_types::admin::{NodeInfo, PeerInfo};
|
||||
|
||||
/// Admin namespace rpc interface that gives access to several non-standard RPC methods.
|
||||
#[cfg_attr(not(feature = "client"), rpc(server, namespace = "admin"))]
|
||||
|
||||
@ -6,12 +6,12 @@ use async_trait::async_trait;
|
||||
use jsonrpsee::core::RpcResult;
|
||||
use reth_chainspec::ChainSpec;
|
||||
use reth_network_api::{NetworkInfo, PeerKind, Peers};
|
||||
use reth_network_peers::{AnyNode, NodeRecord};
|
||||
use reth_network_peers::{id2pk, AnyNode, NodeRecord};
|
||||
use reth_rpc_api::AdminApiServer;
|
||||
use reth_rpc_server_types::ToRpcResult;
|
||||
use reth_rpc_types::{
|
||||
admin::{EthProtocolInfo, NodeInfo, Ports, ProtocolInfo},
|
||||
PeerEthProtocolInfo, PeerInfo, PeerNetworkInfo, PeerProtocolsInfo,
|
||||
use reth_rpc_types::admin::{
|
||||
EthInfo, EthPeerInfo, EthProtocolInfo, NodeInfo, PeerInfo, PeerNetworkInfo, PeerProtocolInfo,
|
||||
Ports, ProtocolInfo,
|
||||
};
|
||||
|
||||
/// `admin` API implementation.
|
||||
@ -63,33 +63,43 @@ where
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
/// Handler for `admin_peers`
|
||||
async fn peers(&self) -> RpcResult<Vec<PeerInfo>> {
|
||||
let peers = self.network.get_all_peers().await.to_rpc_result()?;
|
||||
let peers = peers
|
||||
.into_iter()
|
||||
.map(|peer| PeerInfo {
|
||||
id: Some(peer.remote_id.to_string()),
|
||||
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: peer.status.blockhash.to_string(),
|
||||
version: peer.status.version as u32,
|
||||
}),
|
||||
pip: None,
|
||||
},
|
||||
})
|
||||
.collect();
|
||||
let mut infos = Vec::with_capacity(peers.len());
|
||||
|
||||
Ok(peers)
|
||||
for peer in peers {
|
||||
if let Ok(pk) = id2pk(peer.remote_id) {
|
||||
infos.push(PeerInfo {
|
||||
id: pk.to_string(),
|
||||
name: peer.client_version.to_string(),
|
||||
enode: peer.enode,
|
||||
enr: peer.enr,
|
||||
caps: peer
|
||||
.capabilities
|
||||
.capabilities()
|
||||
.iter()
|
||||
.map(|cap| cap.to_string())
|
||||
.collect(),
|
||||
network: PeerNetworkInfo {
|
||||
remote_address: peer.remote_addr,
|
||||
local_address: peer.local_addr.unwrap_or_else(|| self.network.local_addr()),
|
||||
inbound: peer.direction.is_incoming(),
|
||||
trusted: peer.kind.is_trusted(),
|
||||
static_node: peer.kind.is_static(),
|
||||
},
|
||||
protocols: PeerProtocolInfo {
|
||||
eth: Some(EthPeerInfo::Info(EthInfo {
|
||||
version: peer.status.version as u64,
|
||||
})),
|
||||
snap: None,
|
||||
other: Default::default(),
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Ok(infos)
|
||||
}
|
||||
|
||||
/// Handler for `admin_nodeInfo`
|
||||
|
||||
Reference in New Issue
Block a user