Node endpoints (#1778)

## Issue Addressed

`node` endpoints in #1434

## Proposed Changes

Implement these:
```
 /eth/v1/node/health
 /eth/v1/node/peers/{peer_id}
 /eth/v1/node/peers
```
- Add an `Option<Enr>` to `PeerInfo`
- Finish implementation of `/eth/v1/node/identity`

## Additional Info
- should update the `peers` endpoints when #1764 is resolved



Co-authored-by: realbigsean <seananderson33@gmail.com>
This commit is contained in:
realbigsean
2020-10-22 02:59:42 +00:00
parent 8f86baa48d
commit a3552a4b70
12 changed files with 493 additions and 50 deletions

View File

@@ -18,6 +18,7 @@ use serde::{de::DeserializeOwned, Serialize};
use std::convert::TryFrom;
use std::fmt;
use eth2_libp2p::PeerId;
pub use reqwest;
pub use reqwest::{StatusCode, Url};
@@ -582,6 +583,18 @@ impl BeaconNodeHttpClient {
self.get(path).await
}
/// `GET node/identity`
pub async fn get_node_identity(&self) -> Result<GenericResponse<IdentityData>, Error> {
let mut path = self.eth_path()?;
path.path_segments_mut()
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
.push("node")
.push("identity");
self.get(path).await
}
/// `GET node/syncing`
pub async fn get_node_syncing(&self) -> Result<GenericResponse<SyncingData>, Error> {
let mut path = self.eth_path()?;
@@ -594,6 +607,57 @@ impl BeaconNodeHttpClient {
self.get(path).await
}
/// `GET node/health`
pub async fn get_node_health(&self) -> Result<StatusCode, Error> {
let mut path = self.eth_path()?;
path.path_segments_mut()
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
.push("node")
.push("health");
let status = self
.client
.get(path)
.send()
.await
.map_err(Error::Reqwest)?
.status();
if status == StatusCode::OK || status == StatusCode::PARTIAL_CONTENT {
Ok(status)
} else {
Err(Error::StatusCode(status))
}
}
/// `GET node/peers/{peer_id}`
pub async fn get_node_peers_by_id(
&self,
peer_id: PeerId,
) -> Result<GenericResponse<PeerData>, Error> {
let mut path = self.eth_path()?;
path.path_segments_mut()
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
.push("node")
.push("peers")
.push(&peer_id.to_string());
self.get(path).await
}
/// `GET node/peers`
pub async fn get_node_peers(&self) -> Result<GenericResponse<Vec<PeerData>>, Error> {
let mut path = self.eth_path()?;
path.path_segments_mut()
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
.push("node")
.push("peers");
self.get(path).await
}
/// `GET debug/beacon/states/{state_id}`
pub async fn get_debug_beacon_states<T: EthSpec>(
&self,

View File

@@ -1,7 +1,7 @@
//! This module exposes a superset of the `types` crate. It adds additional types that are only
//! required for the HTTP API.
use eth2_libp2p::{Enr, Multiaddr};
use eth2_libp2p::{ConnectionDirection, Enr, Multiaddr, PeerConnectionStatus};
use serde::{Deserialize, Serialize};
use std::convert::TryFrom;
use std::fmt;
@@ -321,12 +321,15 @@ pub struct IdentityData {
pub peer_id: String,
pub enr: Enr,
pub p2p_addresses: Vec<Multiaddr>,
// TODO: missing the following fields:
//
// - discovery_addresses
// - metadata
//
// Tracked here: https://github.com/sigp/lighthouse/issues/1434
pub discovery_addresses: Vec<Multiaddr>,
pub metadata: MetaData,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct MetaData {
#[serde(with = "serde_utils::quoted_u64")]
pub seq_number: u64,
pub attnets: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
@@ -418,6 +421,78 @@ pub struct BeaconCommitteeSubscription {
pub is_aggregator: bool,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PeerData {
pub peer_id: String,
pub enr: Option<String>,
pub last_seen_p2p_address: String,
pub state: PeerState,
pub direction: PeerDirection,
}
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum PeerState {
Connected,
Connecting,
Disconnected,
Disconnecting,
}
impl PeerState {
pub fn from_peer_connection_status(status: &PeerConnectionStatus) -> Self {
match status {
PeerConnectionStatus::Connected { .. } => PeerState::Connected,
PeerConnectionStatus::Dialing { .. } => PeerState::Connecting,
PeerConnectionStatus::Disconnected { .. }
| PeerConnectionStatus::Banned { .. }
| PeerConnectionStatus::Unknown => PeerState::Disconnected,
}
}
}
impl FromStr for PeerState {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"connected" => Ok(PeerState::Connected),
"connecting" => Ok(PeerState::Connecting),
"disconnected" => Ok(PeerState::Disconnected),
"disconnecting" => Ok(PeerState::Disconnecting),
_ => Err("peer state cannot be parsed.".to_string()),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum PeerDirection {
Inbound,
Outbound,
}
impl PeerDirection {
pub fn from_connection_direction(direction: &ConnectionDirection) -> Self {
match direction {
ConnectionDirection::Incoming => PeerDirection::Inbound,
ConnectionDirection::Outgoing => PeerDirection::Outbound,
}
}
}
impl FromStr for PeerDirection {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"inbound" => Ok(PeerDirection::Inbound),
"outbound" => Ok(PeerDirection::Outbound),
_ => Err("peer direction cannot be parsed.".to_string()),
}
}
}
#[cfg(test)]
mod tests {
use super::*;