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

@@ -13,9 +13,15 @@ pub trait EnrExt {
/// The vector remains empty if these fields are not defined.
fn multiaddr(&self) -> Vec<Multiaddr>;
/// Returns the multiaddr with the `PeerId` prepended.
/// Returns a list of multiaddrs with the `PeerId` prepended.
fn multiaddr_p2p(&self) -> Vec<Multiaddr>;
/// Returns any multiaddrs that contain the TCP protocol with the `PeerId` prepended.
fn multiaddr_p2p_tcp(&self) -> Vec<Multiaddr>;
/// Returns any multiaddrs that contain the UDP protocol with the `PeerId` prepended.
fn multiaddr_p2p_udp(&self) -> Vec<Multiaddr>;
/// Returns any multiaddrs that contain the TCP protocol.
fn multiaddr_tcp(&self) -> Vec<Multiaddr>;
}
@@ -111,6 +117,58 @@ impl EnrExt for Enr {
multiaddrs
}
/// Returns a list of multiaddrs if the ENR has an `ip` and a `tcp` key **or** an `ip6` and a `tcp6`.
/// The vector remains empty if these fields are not defined.
///
/// This also prepends the `PeerId` into each multiaddr with the `P2p` protocol.
fn multiaddr_p2p_tcp(&self) -> Vec<Multiaddr> {
let peer_id = self.peer_id();
let mut multiaddrs: Vec<Multiaddr> = Vec::new();
if let Some(ip) = self.ip() {
if let Some(tcp) = self.tcp() {
let mut multiaddr: Multiaddr = ip.into();
multiaddr.push(Protocol::Tcp(tcp));
multiaddr.push(Protocol::P2p(peer_id.clone().into()));
multiaddrs.push(multiaddr);
}
}
if let Some(ip6) = self.ip6() {
if let Some(tcp6) = self.tcp6() {
let mut multiaddr: Multiaddr = ip6.into();
multiaddr.push(Protocol::Tcp(tcp6));
multiaddr.push(Protocol::P2p(peer_id.into()));
multiaddrs.push(multiaddr);
}
}
multiaddrs
}
/// Returns a list of multiaddrs if the ENR has an `ip` and a `udp` key **or** an `ip6` and a `udp6`.
/// The vector remains empty if these fields are not defined.
///
/// This also prepends the `PeerId` into each multiaddr with the `P2p` protocol.
fn multiaddr_p2p_udp(&self) -> Vec<Multiaddr> {
let peer_id = self.peer_id();
let mut multiaddrs: Vec<Multiaddr> = Vec::new();
if let Some(ip) = self.ip() {
if let Some(udp) = self.udp() {
let mut multiaddr: Multiaddr = ip.into();
multiaddr.push(Protocol::Udp(udp));
multiaddr.push(Protocol::P2p(peer_id.clone().into()));
multiaddrs.push(multiaddr);
}
}
if let Some(ip6) = self.ip6() {
if let Some(udp6) = self.udp6() {
let mut multiaddr: Multiaddr = ip6.into();
multiaddr.push(Protocol::Udp(udp6));
multiaddr.push(Protocol::P2p(peer_id.into()));
multiaddrs.push(multiaddr);
}
}
multiaddrs
}
/// Returns a list of multiaddrs if the ENR has an `ip` and either a `tcp` or `udp` key **or** an `ip6` and either a `tcp6` or `udp6`.
/// The vector remains empty if these fields are not defined.
fn multiaddr_tcp(&self) -> Vec<Multiaddr> {

View File

@@ -5,7 +5,7 @@ pub mod enr_ext;
// Allow external use of the lighthouse ENR builder
pub use enr::{build_enr, create_enr_builder_from_config, use_or_load_enr, CombinedKey, Eth2Enr};
pub use enr_ext::{peer_id_to_node_id, CombinedKeyExt, EnrExt};
pub use libp2p::core::identity::Keypair;
pub use libp2p::core::identity::{Keypair, PublicKey};
use crate::metrics;
use crate::{error, Enr, NetworkConfig, NetworkGlobals, SubnetDiscovery};

View File

@@ -69,6 +69,7 @@ pub use libp2p::{core::ConnectedPoint, PeerId, Swarm};
pub use libp2p::{multiaddr, Multiaddr};
pub use metrics::scrape_discovery_metrics;
pub use peer_manager::{
client::Client, score::PeerAction, PeerDB, PeerInfo, PeerSyncStatus, SyncInfo,
client::Client, score::PeerAction, ConnectionDirection, PeerConnectionStatus, PeerDB, PeerInfo,
PeerSyncStatus, SyncInfo,
};
pub use service::{load_private_key, Libp2pEvent, Service, NETWORK_KEY_FILENAME};

View File

@@ -29,7 +29,7 @@ mod peer_sync_status;
mod peerdb;
pub(crate) mod score;
pub use peer_info::{PeerConnectionStatus::*, PeerInfo};
pub use peer_info::{ConnectionDirection, PeerConnectionStatus, PeerConnectionStatus::*, PeerInfo};
pub use peer_sync_status::{PeerSyncStatus, SyncInfo};
use score::{PeerAction, ScoreState};
use std::collections::HashMap;
@@ -623,16 +623,18 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
slog::crit!(self.log, "Connection has been allowed to a banned peer"; "peer_id" => peer_id.to_string());
}
let enr = self.discovery.enr_of_peer(peer_id);
match connection {
ConnectingType::Dialing => {
peerdb.dialing_peer(peer_id);
peerdb.dialing_peer(peer_id, enr);
return true;
}
ConnectingType::IngoingConnected { multiaddr } => {
peerdb.connect_outgoing(peer_id, multiaddr)
peerdb.connect_outgoing(peer_id, multiaddr, enr)
}
ConnectingType::OutgoingConnected { multiaddr } => {
peerdb.connect_ingoing(peer_id, multiaddr)
peerdb.connect_ingoing(peer_id, multiaddr, enr)
}
}
}

View File

@@ -3,6 +3,7 @@ use super::score::{PeerAction, Score, ScoreState};
use super::PeerSyncStatus;
use crate::rpc::MetaData;
use crate::Multiaddr;
use discv5::Enr;
use serde::{
ser::{SerializeStruct, Serializer},
Serialize,
@@ -46,6 +47,8 @@ pub struct PeerInfo<T: EthSpec> {
/// Direction of the first connection of the last (or current) connected session with this peer.
/// None if this peer was never connected.
pub connection_direction: Option<ConnectionDirection>,
/// The enr of the peer, if known.
pub enr: Option<Enr>,
}
impl<TSpec: EthSpec> Default for PeerInfo<TSpec> {
@@ -62,6 +65,7 @@ impl<TSpec: EthSpec> Default for PeerInfo<TSpec> {
min_ttl: None,
is_trusted: false,
connection_direction: None,
enr: None,
}
}
}

View File

@@ -3,6 +3,7 @@ use super::peer_sync_status::PeerSyncStatus;
use super::score::{Score, ScoreState};
use crate::multiaddr::{Multiaddr, Protocol};
use crate::rpc::methods::MetaData;
use crate::Enr;
use crate::PeerId;
use rand::seq::SliceRandom;
use slog::{crit, debug, trace, warn};
@@ -191,7 +192,7 @@ impl<TSpec: EthSpec> PeerDB<TSpec> {
}
}
/// Gives the ids of all known connected peers.
/// Gives the ids and info of all known connected peers.
pub fn connected_peers(&self) -> impl Iterator<Item = (&PeerId, &PeerInfo<TSpec>)> {
self.peers
.iter()
@@ -318,8 +319,9 @@ impl<TSpec: EthSpec> PeerDB<TSpec> {
/* Setters */
/// A peer is being dialed.
pub fn dialing_peer(&mut self, peer_id: &PeerId) {
pub fn dialing_peer(&mut self, peer_id: &PeerId, enr: Option<Enr>) {
let info = self.peers.entry(peer_id.clone()).or_default();
info.enr = enr;
if info.connection_status.is_disconnected() {
self.disconnected_peers = self.disconnected_peers.saturating_sub(1);
@@ -370,8 +372,9 @@ impl<TSpec: EthSpec> PeerDB<TSpec> {
}
/// Sets a peer as connected with an ingoing connection.
pub fn connect_ingoing(&mut self, peer_id: &PeerId, multiaddr: Multiaddr) {
pub fn connect_ingoing(&mut self, peer_id: &PeerId, multiaddr: Multiaddr, enr: Option<Enr>) {
let info = self.peers.entry(peer_id.clone()).or_default();
info.enr = enr;
if info.connection_status.is_disconnected() {
self.disconnected_peers = self.disconnected_peers.saturating_sub(1);
@@ -391,8 +394,9 @@ impl<TSpec: EthSpec> PeerDB<TSpec> {
}
/// Sets a peer as connected with an outgoing connection.
pub fn connect_outgoing(&mut self, peer_id: &PeerId, multiaddr: Multiaddr) {
pub fn connect_outgoing(&mut self, peer_id: &PeerId, multiaddr: Multiaddr, enr: Option<Enr>) {
let info = self.peers.entry(peer_id.clone()).or_default();
info.enr = enr;
if info.connection_status.is_disconnected() {
self.disconnected_peers = self.disconnected_peers.saturating_sub(1);
@@ -578,10 +582,10 @@ mod tests {
let (n_in, n_out) = (10, 20);
for _ in 0..n_in {
pdb.connect_ingoing(&random_peer, "/ip4/0.0.0.0".parse().unwrap());
pdb.connect_ingoing(&random_peer, "/ip4/0.0.0.0".parse().unwrap(), None);
}
for _ in 0..n_out {
pdb.connect_outgoing(&random_peer, "/ip4/0.0.0.0".parse().unwrap());
pdb.connect_outgoing(&random_peer, "/ip4/0.0.0.0".parse().unwrap(), None);
}
// the peer is known
@@ -606,7 +610,7 @@ mod tests {
for _ in 0..MAX_DC_PEERS + 1 {
let p = PeerId::random();
pdb.connect_ingoing(&p, "/ip4/0.0.0.0".parse().unwrap());
pdb.connect_ingoing(&p, "/ip4/0.0.0.0".parse().unwrap(), None);
}
assert_eq!(pdb.disconnected_peers, 0);
@@ -623,7 +627,7 @@ mod tests {
for _ in 0..MAX_BANNED_PEERS + 1 {
let p = PeerId::random();
pdb.connect_ingoing(&p, "/ip4/0.0.0.0".parse().unwrap());
pdb.connect_ingoing(&p, "/ip4/0.0.0.0".parse().unwrap(), None);
}
assert_eq!(pdb.banned_peers_count.banned_peers(), 0);
@@ -641,9 +645,9 @@ mod tests {
let p0 = PeerId::random();
let p1 = PeerId::random();
let p2 = PeerId::random();
pdb.connect_ingoing(&p0, "/ip4/0.0.0.0".parse().unwrap());
pdb.connect_ingoing(&p1, "/ip4/0.0.0.0".parse().unwrap());
pdb.connect_ingoing(&p2, "/ip4/0.0.0.0".parse().unwrap());
pdb.connect_ingoing(&p0, "/ip4/0.0.0.0".parse().unwrap(), None);
pdb.connect_ingoing(&p1, "/ip4/0.0.0.0".parse().unwrap(), None);
pdb.connect_ingoing(&p2, "/ip4/0.0.0.0".parse().unwrap(), None);
add_score(&mut pdb, &p0, 70.0);
add_score(&mut pdb, &p1, 100.0);
add_score(&mut pdb, &p2, 50.0);
@@ -663,9 +667,9 @@ mod tests {
let p0 = PeerId::random();
let p1 = PeerId::random();
let p2 = PeerId::random();
pdb.connect_ingoing(&p0, "/ip4/0.0.0.0".parse().unwrap());
pdb.connect_ingoing(&p1, "/ip4/0.0.0.0".parse().unwrap());
pdb.connect_ingoing(&p2, "/ip4/0.0.0.0".parse().unwrap());
pdb.connect_ingoing(&p0, "/ip4/0.0.0.0".parse().unwrap(), None);
pdb.connect_ingoing(&p1, "/ip4/0.0.0.0".parse().unwrap(), None);
pdb.connect_ingoing(&p2, "/ip4/0.0.0.0".parse().unwrap(), None);
add_score(&mut pdb, &p0, 70.0);
add_score(&mut pdb, &p1, 100.0);
add_score(&mut pdb, &p2, 50.0);
@@ -683,18 +687,18 @@ mod tests {
let random_peer = PeerId::random();
pdb.connect_ingoing(&random_peer, "/ip4/0.0.0.0".parse().unwrap());
pdb.connect_ingoing(&random_peer, "/ip4/0.0.0.0".parse().unwrap(), None);
assert_eq!(pdb.disconnected_peers, pdb.disconnected_peers().count());
dbg!("1");
pdb.connect_ingoing(&random_peer, "/ip4/0.0.0.0".parse().unwrap());
pdb.connect_ingoing(&random_peer, "/ip4/0.0.0.0".parse().unwrap(), None);
assert_eq!(pdb.disconnected_peers, pdb.disconnected_peers().count());
dbg!("1");
pdb.disconnect(&random_peer);
assert_eq!(pdb.disconnected_peers, pdb.disconnected_peers().count());
dbg!("1");
pdb.connect_outgoing(&random_peer, "/ip4/0.0.0.0".parse().unwrap());
pdb.connect_outgoing(&random_peer, "/ip4/0.0.0.0".parse().unwrap(), None);
assert_eq!(pdb.disconnected_peers, pdb.disconnected_peers().count());
dbg!("1");
pdb.disconnect(&random_peer);
@@ -725,20 +729,20 @@ mod tests {
let random_peer2 = PeerId::random();
let random_peer3 = PeerId::random();
pdb.connect_ingoing(&random_peer, "/ip4/0.0.0.0".parse().unwrap());
pdb.connect_ingoing(&random_peer1, "/ip4/0.0.0.0".parse().unwrap());
pdb.connect_ingoing(&random_peer2, "/ip4/0.0.0.0".parse().unwrap());
pdb.connect_ingoing(&random_peer3, "/ip4/0.0.0.0".parse().unwrap());
pdb.connect_ingoing(&random_peer, "/ip4/0.0.0.0".parse().unwrap(), None);
pdb.connect_ingoing(&random_peer1, "/ip4/0.0.0.0".parse().unwrap(), None);
pdb.connect_ingoing(&random_peer2, "/ip4/0.0.0.0".parse().unwrap(), None);
pdb.connect_ingoing(&random_peer3, "/ip4/0.0.0.0".parse().unwrap(), None);
assert_eq!(pdb.disconnected_peers, pdb.disconnected_peers().count());
assert_eq!(
pdb.banned_peers_count.banned_peers(),
pdb.banned_peers().count()
);
pdb.connect_ingoing(&random_peer, "/ip4/0.0.0.0".parse().unwrap());
pdb.connect_ingoing(&random_peer, "/ip4/0.0.0.0".parse().unwrap(), None);
pdb.disconnect(&random_peer1);
pdb.ban(&random_peer2);
pdb.connect_ingoing(&random_peer3, "/ip4/0.0.0.0".parse().unwrap());
pdb.connect_ingoing(&random_peer3, "/ip4/0.0.0.0".parse().unwrap(), None);
assert_eq!(pdb.disconnected_peers, pdb.disconnected_peers().count());
assert_eq!(
pdb.banned_peers_count.banned_peers(),
@@ -751,7 +755,7 @@ mod tests {
pdb.banned_peers().count()
);
pdb.connect_outgoing(&random_peer2, "/ip4/0.0.0.0".parse().unwrap());
pdb.connect_outgoing(&random_peer2, "/ip4/0.0.0.0".parse().unwrap(), None);
assert_eq!(pdb.disconnected_peers, pdb.disconnected_peers().count());
assert_eq!(
pdb.banned_peers_count.banned_peers(),
@@ -765,10 +769,10 @@ mod tests {
);
pdb.ban(&random_peer3);
pdb.connect_ingoing(&random_peer1, "/ip4/0.0.0.0".parse().unwrap());
pdb.connect_ingoing(&random_peer1, "/ip4/0.0.0.0".parse().unwrap(), None);
pdb.disconnect(&random_peer2);
pdb.ban(&random_peer3);
pdb.connect_ingoing(&random_peer, "/ip4/0.0.0.0".parse().unwrap());
pdb.connect_ingoing(&random_peer, "/ip4/0.0.0.0".parse().unwrap(), None);
assert_eq!(pdb.disconnected_peers, pdb.disconnected_peers().count());
assert_eq!(
pdb.banned_peers_count.banned_peers(),
@@ -797,7 +801,7 @@ mod tests {
for ip in ips {
let mut addr = Multiaddr::empty();
addr.push(Protocol::from(ip));
pdb.connect_ingoing(&p, addr);
pdb.connect_ingoing(&p, addr, None);
}
p
}
@@ -956,7 +960,7 @@ mod tests {
let log = build_log(slog::Level::Debug, false);
let mut pdb: PeerDB<M> = PeerDB::new(vec![trusted_peer.clone()], &log);
pdb.connect_ingoing(&trusted_peer, "/ip4/0.0.0.0".parse().unwrap());
pdb.connect_ingoing(&trusted_peer, "/ip4/0.0.0.0".parse().unwrap(), None);
// Check trusted status and score
assert!(pdb.peer_info(&trusted_peer).unwrap().is_trusted);