Integrate identify into peer manager (#1011)
This commit is contained in:
parent
6edb4f655c
commit
0b2b379f14
@ -19,7 +19,7 @@ use std::marker::PhantomData;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use types::{EnrForkId, EthSpec, SubnetId};
|
use types::{EnrForkId, EthSpec, SubnetId};
|
||||||
|
|
||||||
const MAX_IDENTIFY_ADDRESSES: usize = 20;
|
const MAX_IDENTIFY_ADDRESSES: usize = 10;
|
||||||
|
|
||||||
/// Builds the network behaviour that manages the core protocols of eth2.
|
/// Builds the network behaviour that manages the core protocols of eth2.
|
||||||
/// This core behaviour is managed by `Behaviour` which adds peer management to all core
|
/// This core behaviour is managed by `Behaviour` which adds peer management to all core
|
||||||
@ -508,10 +508,13 @@ impl<TSubstream: AsyncRead + AsyncWrite, TSpec: EthSpec> NetworkBehaviourEventPr
|
|||||||
if info.listen_addrs.len() > MAX_IDENTIFY_ADDRESSES {
|
if info.listen_addrs.len() > MAX_IDENTIFY_ADDRESSES {
|
||||||
debug!(
|
debug!(
|
||||||
self.log,
|
self.log,
|
||||||
"More than 20 addresses have been identified, truncating"
|
"More than 10 addresses have been identified, truncating"
|
||||||
);
|
);
|
||||||
info.listen_addrs.truncate(MAX_IDENTIFY_ADDRESSES);
|
info.listen_addrs.truncate(MAX_IDENTIFY_ADDRESSES);
|
||||||
}
|
}
|
||||||
|
// send peer info to the peer manager.
|
||||||
|
self.peer_manager.identify(&peer_id, &info);
|
||||||
|
|
||||||
debug!(self.log, "Identified Peer"; "peer" => format!("{}", peer_id),
|
debug!(self.log, "Identified Peer"; "peer" => format!("{}", peer_id),
|
||||||
"protocol_version" => info.protocol_version,
|
"protocol_version" => info.protocol_version,
|
||||||
"agent_version" => info.agent_version,
|
"agent_version" => info.agent_version,
|
||||||
|
133
beacon_node/eth2-libp2p/src/peer_manager/client.rs
Normal file
133
beacon_node/eth2-libp2p/src/peer_manager/client.rs
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
//! Known Ethereum 2.0 clients and their fingerprints.
|
||||||
|
//!
|
||||||
|
//! Currently using identify to fingerprint.
|
||||||
|
|
||||||
|
use libp2p::identify::IdentifyInfo;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
/// Various client and protocol information related to a node.
|
||||||
|
pub struct Client {
|
||||||
|
/// The client's name (Ex: lighthouse, prism, nimbus, etc)
|
||||||
|
pub kind: ClientKind,
|
||||||
|
/// The client's version.
|
||||||
|
pub version: String,
|
||||||
|
/// The OS version of the client.
|
||||||
|
pub os_version: String,
|
||||||
|
/// The libp2p protocol version.
|
||||||
|
pub protocol_version: String,
|
||||||
|
/// Identify agent string
|
||||||
|
pub agent_string: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ClientKind {
|
||||||
|
/// A lighthouse node (the best kind).
|
||||||
|
Lighthouse,
|
||||||
|
/// A Nimbus node.
|
||||||
|
Nimbus,
|
||||||
|
/// A Teku node.
|
||||||
|
Teku,
|
||||||
|
/// A Prysm node.
|
||||||
|
Prysm,
|
||||||
|
/// An unknown client.
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Client {
|
||||||
|
fn default() -> Self {
|
||||||
|
Client {
|
||||||
|
kind: ClientKind::Unknown,
|
||||||
|
version: "unknown".into(),
|
||||||
|
os_version: "unknown".into(),
|
||||||
|
protocol_version: "unknown".into(),
|
||||||
|
agent_string: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Client {
|
||||||
|
/// Builds a `Client` from `IdentifyInfo`.
|
||||||
|
pub fn from_identify_info(info: &IdentifyInfo) -> Self {
|
||||||
|
let (kind, version, os_version) = client_from_agent_version(&info.agent_version);
|
||||||
|
|
||||||
|
Client {
|
||||||
|
kind,
|
||||||
|
version,
|
||||||
|
os_version,
|
||||||
|
protocol_version: info.protocol_version.clone(),
|
||||||
|
agent_string: Some(info.agent_version.clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Client {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self.kind {
|
||||||
|
ClientKind::Lighthouse => write!(
|
||||||
|
f,
|
||||||
|
"Lighthouse: version: {}, os_version: {}",
|
||||||
|
self.version, self.os_version
|
||||||
|
),
|
||||||
|
ClientKind::Teku => write!(
|
||||||
|
f,
|
||||||
|
"Teku: version: {}, os_version: {}",
|
||||||
|
self.version, self.os_version
|
||||||
|
),
|
||||||
|
ClientKind::Nimbus => write!(
|
||||||
|
f,
|
||||||
|
"Nimbus: version: {}, os_version: {}",
|
||||||
|
self.version, self.os_version
|
||||||
|
),
|
||||||
|
ClientKind::Prysm => write!(
|
||||||
|
f,
|
||||||
|
"Prysm: version: {}, os_version: {}",
|
||||||
|
self.version, self.os_version
|
||||||
|
),
|
||||||
|
ClientKind::Unknown => {
|
||||||
|
if let Some(agent_string) = &self.agent_string {
|
||||||
|
write!(f, "Unknown: {}", agent_string)
|
||||||
|
} else {
|
||||||
|
write!(f, "Unknown")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper function to identify clients from their agent_version. Returns the client
|
||||||
|
// kind and it's associated version and the OS kind.
|
||||||
|
fn client_from_agent_version(agent_version: &str) -> (ClientKind, String, String) {
|
||||||
|
let mut agent_split = agent_version.split("/");
|
||||||
|
match agent_split.next() {
|
||||||
|
Some("Lighthouse") => {
|
||||||
|
let kind = ClientKind::Lighthouse;
|
||||||
|
let mut version = String::from("unknown");
|
||||||
|
let mut os_version = version.clone();
|
||||||
|
if let Some(agent_version) = agent_split.next() {
|
||||||
|
version = agent_version.into();
|
||||||
|
if let Some(agent_os_version) = agent_split.next() {
|
||||||
|
os_version = agent_os_version.into();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(kind, version, os_version)
|
||||||
|
}
|
||||||
|
Some("teku") => {
|
||||||
|
let kind = ClientKind::Teku;
|
||||||
|
let mut version = String::from("unknown");
|
||||||
|
let mut os_version = version.clone();
|
||||||
|
if let Some(_) = agent_split.next() {
|
||||||
|
if let Some(agent_version) = agent_split.next() {
|
||||||
|
version = agent_version.into();
|
||||||
|
if let Some(agent_os_version) = agent_split.next() {
|
||||||
|
os_version = agent_os_version.into();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(kind, version, os_version)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let unknown = String::from("unknown");
|
||||||
|
(ClientKind::Unknown, unknown.clone(), unknown)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,12 +7,14 @@ use crate::{NetworkGlobals, PeerId};
|
|||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
use futures::Stream;
|
use futures::Stream;
|
||||||
use hashmap_delay::HashSetDelay;
|
use hashmap_delay::HashSetDelay;
|
||||||
|
use libp2p::identify::IdentifyInfo;
|
||||||
use slog::{crit, debug, error, warn};
|
use slog::{crit, debug, error, warn};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
use types::EthSpec;
|
use types::EthSpec;
|
||||||
|
|
||||||
|
mod client;
|
||||||
mod peer_info;
|
mod peer_info;
|
||||||
mod peerdb;
|
mod peerdb;
|
||||||
|
|
||||||
@ -242,6 +244,16 @@ impl<TSpec: EthSpec> PeerManager<TSpec> {
|
|||||||
self.update_reputations();
|
self.update_reputations();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Updates `PeerInfo` with `identify` information.
|
||||||
|
pub fn identify(&mut self, peer_id: &PeerId, info: &IdentifyInfo) {
|
||||||
|
if let Some(peer_info) = self.network_globals.peers.write().peer_info_mut(peer_id) {
|
||||||
|
peer_info.client = client::Client::from_identify_info(info);
|
||||||
|
peer_info.listening_addresses = info.listen_addrs.clone();
|
||||||
|
} else {
|
||||||
|
crit!(self.log, "Received an Identify response from an unknown peer"; "peer_id" => format!("{}", peer_id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Internal functions */
|
/* Internal functions */
|
||||||
|
|
||||||
/// Registers a peer as connected. The `ingoing` parameter determines if the peer is being
|
/// Registers a peer as connected. The `ingoing` parameter determines if the peer is being
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
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 std::time::Instant;
|
use std::time::Instant;
|
||||||
use types::{EthSpec, Slot, SubnetId};
|
use types::{EthSpec, Slot, SubnetId};
|
||||||
use PeerConnectionStatus::*;
|
use PeerConnectionStatus::*;
|
||||||
@ -12,9 +14,11 @@ pub struct PeerInfo<T: EthSpec> {
|
|||||||
/// The peers reputation
|
/// The peers reputation
|
||||||
pub reputation: Rep,
|
pub reputation: Rep,
|
||||||
/// Client managing this peer
|
/// Client managing this peer
|
||||||
_client: Client,
|
pub client: Client,
|
||||||
/// Connection status of this peer
|
/// Connection status of this peer
|
||||||
pub connection_status: PeerConnectionStatus,
|
pub connection_status: PeerConnectionStatus,
|
||||||
|
/// The known listening addresses of this peer.
|
||||||
|
pub listening_addresses: Vec<Multiaddr>,
|
||||||
/// The current syncing state of the peer. The state may be determined after it's initial
|
/// The current syncing state of the peer. The state may be determined after it's initial
|
||||||
/// connection.
|
/// connection.
|
||||||
pub sync_status: PeerSyncStatus,
|
pub sync_status: PeerSyncStatus,
|
||||||
@ -26,13 +30,11 @@ pub struct PeerInfo<T: EthSpec> {
|
|||||||
impl<TSpec: EthSpec> Default for PeerInfo<TSpec> {
|
impl<TSpec: EthSpec> Default for PeerInfo<TSpec> {
|
||||||
fn default() -> PeerInfo<TSpec> {
|
fn default() -> PeerInfo<TSpec> {
|
||||||
PeerInfo {
|
PeerInfo {
|
||||||
reputation: DEFAULT_REPUTATION,
|
|
||||||
_status: Default::default(),
|
_status: Default::default(),
|
||||||
_client: Client {
|
reputation: DEFAULT_REPUTATION,
|
||||||
_client_name: "Unknown".into(),
|
client: Client::default(),
|
||||||
_version: vec![0],
|
|
||||||
},
|
|
||||||
connection_status: Default::default(),
|
connection_status: Default::default(),
|
||||||
|
listening_addresses: vec![],
|
||||||
sync_status: PeerSyncStatus::Unknown,
|
sync_status: PeerSyncStatus::Unknown,
|
||||||
meta_data: None,
|
meta_data: None,
|
||||||
}
|
}
|
||||||
@ -66,15 +68,6 @@ impl Default for PeerStatus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Representation of the client managing a peer
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Client {
|
|
||||||
/// The client's name (Ex: lighthouse, prism, nimbus, etc)
|
|
||||||
_client_name: String,
|
|
||||||
/// The client's version
|
|
||||||
_version: Vec<u8>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Connection Status of the peer
|
/// Connection Status of the peer
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum PeerConnectionStatus {
|
pub enum PeerConnectionStatus {
|
||||||
|
Loading…
Reference in New Issue
Block a user