Adds peers and connected_peers to lighthouse http API (#1030)

This commit is contained in:
Age Manning 2020-04-21 23:27:49 +10:00 committed by GitHub
parent fa7147f7c5
commit 9e42a851e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 249 additions and 18 deletions

View File

@ -3,9 +3,10 @@
//! Currently using identify to fingerprint.
use libp2p::identify::IdentifyInfo;
use serde::Serialize;
#[derive(Debug)]
/// Various client and protocol information related to a node.
#[derive(Clone, Debug, Serialize)]
pub struct Client {
/// The client's name (Ex: lighthouse, prism, nimbus, etc)
pub kind: ClientKind,
@ -19,7 +20,7 @@ pub struct Client {
pub agent_string: Option<String>,
}
#[derive(Debug)]
#[derive(Clone, Debug, Serialize)]
pub enum ClientKind {
/// A lighthouse node (the best kind).
Lighthouse,
@ -125,6 +126,11 @@ fn client_from_agent_version(agent_version: &str) -> (ClientKind, String, String
}
(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");
(ClientKind::Unknown, unknown.clone(), unknown)

View File

@ -2,12 +2,17 @@ use super::client::Client;
use super::peerdb::{Rep, DEFAULT_REPUTATION};
use crate::rpc::MetaData;
use crate::Multiaddr;
use serde::{
ser::{SerializeStructVariant, Serializer},
Serialize,
};
use std::time::Instant;
use types::{EthSpec, Slot, SubnetId};
use PeerConnectionStatus::*;
/// Information about a given connected peer.
#[derive(Debug)]
#[derive(Clone, Debug, Serialize)]
#[serde(bound = "T: EthSpec")]
pub struct PeerInfo<T: EthSpec> {
/// The connection status of the peer
_status: PeerStatus,
@ -54,7 +59,7 @@ impl<T: EthSpec> PeerInfo<T> {
}
}
#[derive(Debug)]
#[derive(Clone, Debug, Serialize)]
pub enum PeerStatus {
/// The peer is healthy
Healthy,
@ -69,7 +74,7 @@ impl Default for PeerStatus {
}
/// Connection Status of the peer
#[derive(Debug, Clone)]
#[derive(Clone, Debug)]
pub enum PeerConnectionStatus {
Connected {
/// number of ingoing connections
@ -86,12 +91,41 @@ pub enum PeerConnectionStatus {
since: Instant,
},
Unknown {
/// time since we know of this peer
/// time since we last saw this peer
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 {
/// At the current state as our node or ahead of us.
Synced {

View File

@ -41,8 +41,13 @@ impl<TSpec: EthSpec> PeerDB<TSpec> {
.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.
pub fn peers(&self) -> impl Iterator<Item = &PeerId> {
pub fn peer_ids(&self) -> impl Iterator<Item = &PeerId> {
self.peers.keys()
}
@ -66,7 +71,14 @@ impl<TSpec: EthSpec> PeerDB<TSpec> {
}
/// 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
.iter()
.filter(|(_, info)| info.connection_status.is_connected())
@ -373,7 +385,7 @@ mod tests {
}
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);
}

View File

@ -1,6 +1,7 @@
//! Available RPC methods types and ids.
use crate::types::EnrBitfield;
use serde::Serialize;
use ssz_derive::{Decode, Encode};
use types::{Epoch, EthSpec, Hash256, SignedBeaconBlock, Slot};
@ -37,7 +38,8 @@ pub struct Ping {
}
/// 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> {
/// A sequential counter indicating when data gets modified.
pub seq_number: u64,

View File

@ -80,7 +80,7 @@ impl<TSpec: EthSpec> NetworkGlobals<TSpec> {
/// Returns the number of libp2p connected peers.
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.

View File

@ -2,12 +2,57 @@
use crate::response_builder::ResponseBuilder;
use crate::ApiResult;
use eth2_libp2p::NetworkGlobals;
use eth2_libp2p::{NetworkGlobals, PeerInfo};
use hyper::{Body, Request};
use serde::Serialize;
use std::sync::Arc;
use types::EthSpec;
/// The syncing state of the beacon node.
pub fn syncing<T: EthSpec>(req: Request<Body>, network: Arc<NetworkGlobals<T>>) -> ApiResult {
ResponseBuilder::new(&req)?.body_no_ssz(&network.sync_state())
pub fn syncing<T: EthSpec>(
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>,
}

View File

@ -65,7 +65,7 @@ pub fn get_peer_list<T: BeaconChainTypes>(
let connected_peers: Vec<String> = network
.peers
.read()
.connected_peers()
.connected_peer_ids()
.map(PeerId::to_string)
.collect();
ResponseBuilder::new(&req)?.body_no_ssz(&connected_peers)

View File

@ -203,7 +203,6 @@ pub fn route<T: BeaconChainTypes>(
(&Method::GET, "/advanced/operation_pool") => {
into_boxfut(advanced::get_operation_pool::<T>(req, beacon_chain))
}
(&Method::GET, "/metrics") => into_boxfut(metrics::get_prometheus::<T>(
req,
beacon_chain,
@ -215,7 +214,12 @@ pub fn route<T: BeaconChainTypes>(
(&Method::GET, "/lighthouse/syncing") => {
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(
"Request path and/or method not found.".to_owned(),
))),

View File

@ -7,6 +7,8 @@ The `/lighthouse` endpoints provide lighthouse-specific information about the be
HTTP Path | Description |
| --- | -- |
[`/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`
@ -52,3 +54,129 @@ If the node is 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"
}
},
]
```