Adds peers and connected_peers to lighthouse http API (#1030)
This commit is contained in:
parent
fa7147f7c5
commit
9e42a851e4
@ -3,9 +3,10 @@
|
|||||||
//! Currently using identify to fingerprint.
|
//! Currently using identify to fingerprint.
|
||||||
|
|
||||||
use libp2p::identify::IdentifyInfo;
|
use libp2p::identify::IdentifyInfo;
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
/// Various client and protocol information related to a node.
|
/// Various client and protocol information related to a node.
|
||||||
|
#[derive(Clone, Debug, Serialize)]
|
||||||
pub struct Client {
|
pub struct Client {
|
||||||
/// The client's name (Ex: lighthouse, prism, nimbus, etc)
|
/// The client's name (Ex: lighthouse, prism, nimbus, etc)
|
||||||
pub kind: ClientKind,
|
pub kind: ClientKind,
|
||||||
@ -19,7 +20,7 @@ pub struct Client {
|
|||||||
pub agent_string: Option<String>,
|
pub agent_string: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Clone, Debug, Serialize)]
|
||||||
pub enum ClientKind {
|
pub enum ClientKind {
|
||||||
/// A lighthouse node (the best kind).
|
/// A lighthouse node (the best kind).
|
||||||
Lighthouse,
|
Lighthouse,
|
||||||
@ -125,6 +126,11 @@ fn client_from_agent_version(agent_version: &str) -> (ClientKind, String, String
|
|||||||
}
|
}
|
||||||
(kind, version, os_version)
|
(kind, version, os_version)
|
||||||
}
|
}
|
||||||
|
Some("github.com") => {
|
||||||
|
let kind = ClientKind::Prysm;
|
||||||
|
let unknown = String::from("unknown");
|
||||||
|
(kind, unknown.clone(), unknown)
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let unknown = String::from("unknown");
|
let unknown = String::from("unknown");
|
||||||
(ClientKind::Unknown, unknown.clone(), unknown)
|
(ClientKind::Unknown, unknown.clone(), unknown)
|
||||||
|
@ -2,12 +2,17 @@ use super::client::Client;
|
|||||||
use super::peerdb::{Rep, DEFAULT_REPUTATION};
|
use super::peerdb::{Rep, DEFAULT_REPUTATION};
|
||||||
use crate::rpc::MetaData;
|
use crate::rpc::MetaData;
|
||||||
use crate::Multiaddr;
|
use crate::Multiaddr;
|
||||||
|
use serde::{
|
||||||
|
ser::{SerializeStructVariant, Serializer},
|
||||||
|
Serialize,
|
||||||
|
};
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use types::{EthSpec, Slot, SubnetId};
|
use types::{EthSpec, Slot, SubnetId};
|
||||||
use PeerConnectionStatus::*;
|
use PeerConnectionStatus::*;
|
||||||
|
|
||||||
/// Information about a given connected peer.
|
/// Information about a given connected peer.
|
||||||
#[derive(Debug)]
|
#[derive(Clone, Debug, Serialize)]
|
||||||
|
#[serde(bound = "T: EthSpec")]
|
||||||
pub struct PeerInfo<T: EthSpec> {
|
pub struct PeerInfo<T: EthSpec> {
|
||||||
/// The connection status of the peer
|
/// The connection status of the peer
|
||||||
_status: PeerStatus,
|
_status: PeerStatus,
|
||||||
@ -54,7 +59,7 @@ impl<T: EthSpec> PeerInfo<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Clone, Debug, Serialize)]
|
||||||
pub enum PeerStatus {
|
pub enum PeerStatus {
|
||||||
/// The peer is healthy
|
/// The peer is healthy
|
||||||
Healthy,
|
Healthy,
|
||||||
@ -69,7 +74,7 @@ impl Default for PeerStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Connection Status of the peer
|
/// Connection Status of the peer
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum PeerConnectionStatus {
|
pub enum PeerConnectionStatus {
|
||||||
Connected {
|
Connected {
|
||||||
/// number of ingoing connections
|
/// number of ingoing connections
|
||||||
@ -86,12 +91,41 @@ pub enum PeerConnectionStatus {
|
|||||||
since: Instant,
|
since: Instant,
|
||||||
},
|
},
|
||||||
Unknown {
|
Unknown {
|
||||||
/// time since we know of this peer
|
/// time since we last saw this peer
|
||||||
since: Instant,
|
since: Instant,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
/// Serialization for http requests.
|
||||||
|
impl Serialize for PeerConnectionStatus {
|
||||||
|
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||||
|
match self {
|
||||||
|
Connected { n_in, n_out } => {
|
||||||
|
let mut s = serializer.serialize_struct_variant("", 0, "Connected", 2)?;
|
||||||
|
s.serialize_field("in", n_in)?;
|
||||||
|
s.serialize_field("out", n_out)?;
|
||||||
|
s.end()
|
||||||
|
}
|
||||||
|
Disconnected { since } => {
|
||||||
|
let mut s = serializer.serialize_struct_variant("", 1, "Disconnected", 1)?;
|
||||||
|
s.serialize_field("since", &since.elapsed().as_secs())?;
|
||||||
|
s.end()
|
||||||
|
}
|
||||||
|
Banned { since } => {
|
||||||
|
let mut s = serializer.serialize_struct_variant("", 2, "Banned", 1)?;
|
||||||
|
s.serialize_field("since", &since.elapsed().as_secs())?;
|
||||||
|
s.end()
|
||||||
|
}
|
||||||
|
Unknown { since } => {
|
||||||
|
let mut s = serializer.serialize_struct_variant("", 3, "Unknown", 1)?;
|
||||||
|
s.serialize_field("since", &since.elapsed().as_secs())?;
|
||||||
|
s.end()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize)]
|
||||||
pub enum PeerSyncStatus {
|
pub enum PeerSyncStatus {
|
||||||
/// At the current state as our node or ahead of us.
|
/// At the current state as our node or ahead of us.
|
||||||
Synced {
|
Synced {
|
||||||
|
@ -41,8 +41,13 @@ impl<TSpec: EthSpec> PeerDB<TSpec> {
|
|||||||
.map_or(DEFAULT_REPUTATION, |info| info.reputation)
|
.map_or(DEFAULT_REPUTATION, |info| info.reputation)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns an iterator over all peers in the db.
|
||||||
|
pub fn peers(&self) -> impl Iterator<Item = (&PeerId, &PeerInfo<TSpec>)> {
|
||||||
|
self.peers.iter()
|
||||||
|
}
|
||||||
|
|
||||||
/// Gives the ids of all known peers.
|
/// Gives the ids of all known peers.
|
||||||
pub fn peers(&self) -> impl Iterator<Item = &PeerId> {
|
pub fn peer_ids(&self) -> impl Iterator<Item = &PeerId> {
|
||||||
self.peers.keys()
|
self.peers.keys()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,7 +71,14 @@ impl<TSpec: EthSpec> PeerDB<TSpec> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Gives the ids of all known connected peers.
|
/// Gives the ids of all known connected peers.
|
||||||
pub fn connected_peers(&self) -> impl Iterator<Item = &PeerId> {
|
pub fn connected_peers(&self) -> impl Iterator<Item = (&PeerId, &PeerInfo<TSpec>)> {
|
||||||
|
self.peers
|
||||||
|
.iter()
|
||||||
|
.filter(|(_, info)| info.connection_status.is_connected())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gives the ids of all known connected peers.
|
||||||
|
pub fn connected_peer_ids(&self) -> impl Iterator<Item = &PeerId> {
|
||||||
self.peers
|
self.peers
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, info)| info.connection_status.is_connected())
|
.filter(|(_, info)| info.connection_status.is_connected())
|
||||||
@ -373,7 +385,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
assert_eq!(pdb.n_dc, 0);
|
assert_eq!(pdb.n_dc, 0);
|
||||||
|
|
||||||
for p in pdb.connected_peers().cloned().collect::<Vec<_>>() {
|
for p in pdb.connected_peer_ids().cloned().collect::<Vec<_>>() {
|
||||||
pdb.disconnect(&p);
|
pdb.disconnect(&p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
//! Available RPC methods types and ids.
|
//! Available RPC methods types and ids.
|
||||||
|
|
||||||
use crate::types::EnrBitfield;
|
use crate::types::EnrBitfield;
|
||||||
|
use serde::Serialize;
|
||||||
use ssz_derive::{Decode, Encode};
|
use ssz_derive::{Decode, Encode};
|
||||||
use types::{Epoch, EthSpec, Hash256, SignedBeaconBlock, Slot};
|
use types::{Epoch, EthSpec, Hash256, SignedBeaconBlock, Slot};
|
||||||
|
|
||||||
@ -37,7 +38,8 @@ pub struct Ping {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The METADATA response structure.
|
/// The METADATA response structure.
|
||||||
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
|
#[derive(Encode, Decode, Clone, Debug, PartialEq, Serialize)]
|
||||||
|
#[serde(bound = "T: EthSpec")]
|
||||||
pub struct MetaData<T: EthSpec> {
|
pub struct MetaData<T: EthSpec> {
|
||||||
/// A sequential counter indicating when data gets modified.
|
/// A sequential counter indicating when data gets modified.
|
||||||
pub seq_number: u64,
|
pub seq_number: u64,
|
||||||
|
@ -80,7 +80,7 @@ impl<TSpec: EthSpec> NetworkGlobals<TSpec> {
|
|||||||
|
|
||||||
/// Returns the number of libp2p connected peers.
|
/// Returns the number of libp2p connected peers.
|
||||||
pub fn connected_peers(&self) -> usize {
|
pub fn connected_peers(&self) -> usize {
|
||||||
self.peers.read().connected_peers().count()
|
self.peers.read().connected_peer_ids().count()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns in the node is syncing.
|
/// Returns in the node is syncing.
|
||||||
|
@ -2,12 +2,57 @@
|
|||||||
|
|
||||||
use crate::response_builder::ResponseBuilder;
|
use crate::response_builder::ResponseBuilder;
|
||||||
use crate::ApiResult;
|
use crate::ApiResult;
|
||||||
use eth2_libp2p::NetworkGlobals;
|
use eth2_libp2p::{NetworkGlobals, PeerInfo};
|
||||||
use hyper::{Body, Request};
|
use hyper::{Body, Request};
|
||||||
|
use serde::Serialize;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use types::EthSpec;
|
use types::EthSpec;
|
||||||
|
|
||||||
/// The syncing state of the beacon node.
|
/// The syncing state of the beacon node.
|
||||||
pub fn syncing<T: EthSpec>(req: Request<Body>, network: Arc<NetworkGlobals<T>>) -> ApiResult {
|
pub fn syncing<T: EthSpec>(
|
||||||
ResponseBuilder::new(&req)?.body_no_ssz(&network.sync_state())
|
req: Request<Body>,
|
||||||
|
network_globals: Arc<NetworkGlobals<T>>,
|
||||||
|
) -> ApiResult {
|
||||||
|
ResponseBuilder::new(&req)?.body_no_ssz(&network_globals.sync_state())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns all known peers and corresponding information
|
||||||
|
pub fn peers<T: EthSpec>(req: Request<Body>, network_globals: Arc<NetworkGlobals<T>>) -> ApiResult {
|
||||||
|
let peers: Vec<Peer<T>> = network_globals
|
||||||
|
.peers
|
||||||
|
.read()
|
||||||
|
.peers()
|
||||||
|
.map(|(peer_id, peer_info)| Peer {
|
||||||
|
peer_id: peer_id.to_string(),
|
||||||
|
peer_info: peer_info.clone(),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
ResponseBuilder::new(&req)?.body_no_ssz(&peers)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns all known connected peers and their corresponding information
|
||||||
|
pub fn connected_peers<T: EthSpec>(
|
||||||
|
req: Request<Body>,
|
||||||
|
network_globals: Arc<NetworkGlobals<T>>,
|
||||||
|
) -> ApiResult {
|
||||||
|
let peers: Vec<Peer<T>> = network_globals
|
||||||
|
.peers
|
||||||
|
.read()
|
||||||
|
.connected_peers()
|
||||||
|
.map(|(peer_id, peer_info)| Peer {
|
||||||
|
peer_id: peer_id.to_string(),
|
||||||
|
peer_info: peer_info.clone(),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
ResponseBuilder::new(&req)?.body_no_ssz(&peers)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Information returned by `peers` and `connected_peers`.
|
||||||
|
#[derive(Clone, Debug, Serialize)]
|
||||||
|
#[serde(bound = "T: EthSpec")]
|
||||||
|
struct Peer<T: EthSpec> {
|
||||||
|
/// The Peer's ID
|
||||||
|
peer_id: String,
|
||||||
|
/// The PeerInfo associated with the peer.
|
||||||
|
peer_info: PeerInfo<T>,
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ pub fn get_peer_list<T: BeaconChainTypes>(
|
|||||||
let connected_peers: Vec<String> = network
|
let connected_peers: Vec<String> = network
|
||||||
.peers
|
.peers
|
||||||
.read()
|
.read()
|
||||||
.connected_peers()
|
.connected_peer_ids()
|
||||||
.map(PeerId::to_string)
|
.map(PeerId::to_string)
|
||||||
.collect();
|
.collect();
|
||||||
ResponseBuilder::new(&req)?.body_no_ssz(&connected_peers)
|
ResponseBuilder::new(&req)?.body_no_ssz(&connected_peers)
|
||||||
|
@ -203,7 +203,6 @@ pub fn route<T: BeaconChainTypes>(
|
|||||||
(&Method::GET, "/advanced/operation_pool") => {
|
(&Method::GET, "/advanced/operation_pool") => {
|
||||||
into_boxfut(advanced::get_operation_pool::<T>(req, beacon_chain))
|
into_boxfut(advanced::get_operation_pool::<T>(req, beacon_chain))
|
||||||
}
|
}
|
||||||
|
|
||||||
(&Method::GET, "/metrics") => into_boxfut(metrics::get_prometheus::<T>(
|
(&Method::GET, "/metrics") => into_boxfut(metrics::get_prometheus::<T>(
|
||||||
req,
|
req,
|
||||||
beacon_chain,
|
beacon_chain,
|
||||||
@ -215,7 +214,12 @@ pub fn route<T: BeaconChainTypes>(
|
|||||||
(&Method::GET, "/lighthouse/syncing") => {
|
(&Method::GET, "/lighthouse/syncing") => {
|
||||||
into_boxfut(lighthouse::syncing::<T::EthSpec>(req, network_globals))
|
into_boxfut(lighthouse::syncing::<T::EthSpec>(req, network_globals))
|
||||||
}
|
}
|
||||||
|
(&Method::GET, "/lighthouse/peers") => {
|
||||||
|
into_boxfut(lighthouse::peers::<T::EthSpec>(req, network_globals))
|
||||||
|
}
|
||||||
|
(&Method::GET, "/lighthouse/connected_peers") => into_boxfut(
|
||||||
|
lighthouse::connected_peers::<T::EthSpec>(req, network_globals),
|
||||||
|
),
|
||||||
_ => Box::new(futures::future::err(ApiError::NotFound(
|
_ => Box::new(futures::future::err(ApiError::NotFound(
|
||||||
"Request path and/or method not found.".to_owned(),
|
"Request path and/or method not found.".to_owned(),
|
||||||
))),
|
))),
|
||||||
|
@ -7,6 +7,8 @@ The `/lighthouse` endpoints provide lighthouse-specific information about the be
|
|||||||
HTTP Path | Description |
|
HTTP Path | Description |
|
||||||
| --- | -- |
|
| --- | -- |
|
||||||
[`/lighthouse/syncing`](#lighthousesyncing) | Get the node's syncing status
|
[`/lighthouse/syncing`](#lighthousesyncing) | Get the node's syncing status
|
||||||
|
[`/lighthouse/peers`](#lighthousepeers) | Get the peers info known by the beacon node
|
||||||
|
[`/lighthouse/connected_peers`](#lighthousepeers) | Get the connected_peers known by the beacon node
|
||||||
|
|
||||||
## `/lighthouse/syncing`
|
## `/lighthouse/syncing`
|
||||||
|
|
||||||
@ -52,3 +54,129 @@ If the node is synced
|
|||||||
"Synced"
|
"Synced"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## `/lighthouse/peers`
|
||||||
|
|
||||||
|
Get all known peers info from the beacon node.
|
||||||
|
|
||||||
|
### HTTP Specification
|
||||||
|
|
||||||
|
| Property | Specification |
|
||||||
|
| --- |--- |
|
||||||
|
Path | `/lighthouse/peers`
|
||||||
|
Method | GET
|
||||||
|
JSON Encoding | Object
|
||||||
|
Query Parameters | None
|
||||||
|
Typical Responses | 200
|
||||||
|
|
||||||
|
### Example Response
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"peer_id" : "16Uiu2HAmTEinipUS3haxqucrn7d7SmCKx5XzAVbAZCiNW54ncynG",
|
||||||
|
"peer_info" : {
|
||||||
|
"_status" : "Healthy",
|
||||||
|
"client" : {
|
||||||
|
"agent_string" : "github.com/libp2p/go-libp2p",
|
||||||
|
"kind" : "Prysm",
|
||||||
|
"os_version" : "unknown",
|
||||||
|
"protocol_version" : "ipfs/0.1.0",
|
||||||
|
"version" : "unknown"
|
||||||
|
},
|
||||||
|
"connection_status" : {
|
||||||
|
"Disconnected" : {
|
||||||
|
"since" : 3
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"listening_addresses" : [
|
||||||
|
"/ip4/10.3.58.241/tcp/9001",
|
||||||
|
"/ip4/35.172.14.146/tcp/9001",
|
||||||
|
"/ip4/35.172.14.146/tcp/9001"
|
||||||
|
],
|
||||||
|
"meta_data" : {
|
||||||
|
"attnets" : "0x0000000000000000",
|
||||||
|
"seq_number" : 0
|
||||||
|
},
|
||||||
|
"reputation" : 20,
|
||||||
|
"sync_status" : {
|
||||||
|
"Synced" : {
|
||||||
|
"status_head_slot" : 18146
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"peer_id" : "16Uiu2HAm8XZfPv3YjktCjitSRtfS7UfHfEvpiUyHrdiX6uAD55xZ",
|
||||||
|
"peer_info" : {
|
||||||
|
"_status" : "Healthy",
|
||||||
|
"client" : {
|
||||||
|
"agent_string" : null,
|
||||||
|
"kind" : "Unknown",
|
||||||
|
"os_version" : "unknown",
|
||||||
|
"protocol_version" : "unknown",
|
||||||
|
"version" : "unknown"
|
||||||
|
},
|
||||||
|
"connection_status" : {
|
||||||
|
"Disconnected" : {
|
||||||
|
"since" : 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"listening_addresses" : [],
|
||||||
|
"meta_data" : {
|
||||||
|
"attnets" : "0x0900000000000000",
|
||||||
|
"seq_number" : 0
|
||||||
|
},
|
||||||
|
"reputation" : 20,
|
||||||
|
"sync_status" : "Unknown"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
## `/lighthouse/connected_peers`
|
||||||
|
|
||||||
|
Get all known peers info from the beacon node.
|
||||||
|
|
||||||
|
### HTTP Specification
|
||||||
|
|
||||||
|
| Property | Specification |
|
||||||
|
| --- |--- |
|
||||||
|
Path | `/lighthouse/connected_peers`
|
||||||
|
Method | GET
|
||||||
|
JSON Encoding | Object
|
||||||
|
Query Parameters | None
|
||||||
|
Typical Responses | 200
|
||||||
|
|
||||||
|
### Example Response
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"peer_id" : "16Uiu2HAm8XZfPv3YjktCjitSRtfS7UfHfEvpiUyHrdiX6uAD55xZ",
|
||||||
|
"peer_info" : {
|
||||||
|
"_status" : "Healthy",
|
||||||
|
"client" : {
|
||||||
|
"agent_string" : null,
|
||||||
|
"kind" : "Unknown",
|
||||||
|
"os_version" : "unknown",
|
||||||
|
"protocol_version" : "unknown",
|
||||||
|
"version" : "unknown"
|
||||||
|
},
|
||||||
|
"connection_status" : {
|
||||||
|
"Connected" : {
|
||||||
|
"in" : 5,
|
||||||
|
"out" : 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"listening_addresses" : [],
|
||||||
|
"meta_data" : {
|
||||||
|
"attnets" : "0x0900000000000000",
|
||||||
|
"seq_number" : 0
|
||||||
|
},
|
||||||
|
"reputation" : 20,
|
||||||
|
"sync_status" : "Unknown"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
]
|
||||||
|
```
|
||||||
|
Loading…
Reference in New Issue
Block a user