mirror of
https://github.com/sigp/lighthouse.git
synced 2026-04-19 05:48:31 +00:00
Merge branch 'network-utils' into into-anchor
This commit is contained in:
@@ -31,6 +31,7 @@ logging = { workspace = true }
|
||||
lru = { workspace = true }
|
||||
lru_cache = { workspace = true }
|
||||
metrics = { workspace = true }
|
||||
network_utils = { workspace = true }
|
||||
parking_lot = { workspace = true }
|
||||
prometheus-client = "0.22.0"
|
||||
rand = { workspace = true }
|
||||
@@ -43,7 +44,6 @@ ssz_types = { workspace = true }
|
||||
strum = { workspace = true }
|
||||
superstruct = { workspace = true }
|
||||
task_executor = { workspace = true }
|
||||
tiny-keccak = "2"
|
||||
tokio = { workspace = true }
|
||||
tokio-io-timeout = "1"
|
||||
tokio-util = { workspace = true }
|
||||
@@ -51,7 +51,6 @@ tracing = { workspace = true }
|
||||
tracing-subscriber = { workspace = true }
|
||||
types = { workspace = true }
|
||||
unsigned-varint = { version = "0.8", features = ["codec"] }
|
||||
unused_port = { workspace = true }
|
||||
|
||||
[dependencies.libp2p]
|
||||
version = "0.55"
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use crate::listen_addr::{ListenAddr, ListenAddress};
|
||||
use crate::rpc::config::{InboundRateLimiterConfig, OutboundRateLimiterConfig};
|
||||
use crate::types::GossipKind;
|
||||
use crate::{Enr, PeerIdSerialized};
|
||||
@@ -7,6 +6,7 @@ use directory::{
|
||||
};
|
||||
use libp2p::Multiaddr;
|
||||
use local_ip_address::local_ipv6;
|
||||
use network_utils::listen_addr::{ListenAddr, ListenAddress};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::net::{Ipv4Addr, Ipv6Addr};
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
|
||||
pub use discv5::enr::CombinedKey;
|
||||
|
||||
use super::enr_ext::CombinedKeyExt;
|
||||
use super::enr_ext::{EnrExt, QUIC6_ENR_KEY, QUIC_ENR_KEY};
|
||||
use super::ENR_FILENAME;
|
||||
use crate::types::{Enr, EnrAttestationBitfield, EnrSyncCommitteeBitfield};
|
||||
use crate::NetworkConfig;
|
||||
use alloy_rlp::bytes::Bytes;
|
||||
use libp2p::identity::Keypair;
|
||||
use lighthouse_version::{client_name, version};
|
||||
use network_utils::enr_ext::CombinedKeyExt;
|
||||
use network_utils::enr_ext::{EnrExt, QUIC6_ENR_KEY, QUIC_ENR_KEY};
|
||||
use ssz::{Decode, Encode};
|
||||
use ssz_types::BitVector;
|
||||
use std::fs::File;
|
||||
|
||||
@@ -1,393 +0,0 @@
|
||||
//! ENR extension trait to support libp2p integration.
|
||||
|
||||
use crate::{Enr, Multiaddr, PeerId};
|
||||
use discv5::enr::{CombinedKey, CombinedPublicKey};
|
||||
use libp2p::core::multiaddr::Protocol;
|
||||
use libp2p::identity::{ed25519, secp256k1, KeyType, Keypair, PublicKey};
|
||||
use tiny_keccak::{Hasher, Keccak};
|
||||
|
||||
pub const QUIC_ENR_KEY: &str = "quic";
|
||||
pub const QUIC6_ENR_KEY: &str = "quic6";
|
||||
|
||||
/// Extend ENR for libp2p types.
|
||||
pub trait EnrExt {
|
||||
/// The libp2p `PeerId` for the record.
|
||||
fn peer_id(&self) -> PeerId;
|
||||
|
||||
/// Returns a list of multiaddrs if the ENR has an `ip` and one of [`tcp`,`udp`,`quic`] key **or** an `ip6` and one of [`tcp6`,`udp6`,`quic6`].
|
||||
/// The vector remains empty if these fields are not defined.
|
||||
fn multiaddr(&self) -> Vec<Multiaddr>;
|
||||
|
||||
/// 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>;
|
||||
|
||||
/// Returns any QUIC multiaddrs that are registered in this ENR.
|
||||
fn multiaddr_quic(&self) -> Vec<Multiaddr>;
|
||||
|
||||
/// Returns the quic port if one is set.
|
||||
fn quic4(&self) -> Option<u16>;
|
||||
|
||||
/// Returns the quic6 port if one is set.
|
||||
fn quic6(&self) -> Option<u16>;
|
||||
}
|
||||
|
||||
/// Extend ENR CombinedPublicKey for libp2p types.
|
||||
pub trait CombinedKeyPublicExt {
|
||||
/// Converts the publickey into a peer id, without consuming the key.
|
||||
fn as_peer_id(&self) -> PeerId;
|
||||
}
|
||||
|
||||
/// Extend ENR CombinedKey for conversion to libp2p keys.
|
||||
pub trait CombinedKeyExt {
|
||||
/// Converts a libp2p key into an ENR combined key.
|
||||
fn from_libp2p(key: Keypair) -> Result<CombinedKey, &'static str>;
|
||||
|
||||
/// Converts a [`secp256k1::Keypair`] into and Enr [`CombinedKey`].
|
||||
fn from_secp256k1(key: &secp256k1::Keypair) -> CombinedKey;
|
||||
}
|
||||
|
||||
impl EnrExt for Enr {
|
||||
/// The libp2p `PeerId` for the record.
|
||||
fn peer_id(&self) -> PeerId {
|
||||
self.public_key().as_peer_id()
|
||||
}
|
||||
|
||||
/// Returns the quic port if one is set.
|
||||
fn quic4(&self) -> Option<u16> {
|
||||
self.get_decodable(QUIC_ENR_KEY).and_then(Result::ok)
|
||||
}
|
||||
|
||||
/// Returns the quic6 port if one is set.
|
||||
fn quic6(&self) -> Option<u16> {
|
||||
self.get_decodable(QUIC6_ENR_KEY).and_then(Result::ok)
|
||||
}
|
||||
|
||||
/// Returns a list of multiaddrs if the ENR has an `ip` and either a `tcp`, `quic` or `udp` key **or** an `ip6` and either a `tcp6` `quic6` or `udp6`.
|
||||
/// The vector remains empty if these fields are not defined.
|
||||
fn multiaddr(&self) -> Vec<Multiaddr> {
|
||||
let mut multiaddrs: Vec<Multiaddr> = Vec::new();
|
||||
if let Some(ip) = self.ip4() {
|
||||
if let Some(udp) = self.udp4() {
|
||||
let mut multiaddr: Multiaddr = ip.into();
|
||||
multiaddr.push(Protocol::Udp(udp));
|
||||
multiaddrs.push(multiaddr);
|
||||
}
|
||||
if let Some(quic) = self.quic4() {
|
||||
let mut multiaddr: Multiaddr = ip.into();
|
||||
multiaddr.push(Protocol::Udp(quic));
|
||||
multiaddr.push(Protocol::QuicV1);
|
||||
multiaddrs.push(multiaddr);
|
||||
}
|
||||
|
||||
if let Some(tcp) = self.tcp4() {
|
||||
let mut multiaddr: Multiaddr = ip.into();
|
||||
multiaddr.push(Protocol::Tcp(tcp));
|
||||
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));
|
||||
multiaddrs.push(multiaddr);
|
||||
}
|
||||
|
||||
if let Some(quic6) = self.quic6() {
|
||||
let mut multiaddr: Multiaddr = ip6.into();
|
||||
multiaddr.push(Protocol::Udp(quic6));
|
||||
multiaddr.push(Protocol::QuicV1);
|
||||
multiaddrs.push(multiaddr);
|
||||
}
|
||||
|
||||
if let Some(tcp6) = self.tcp6() {
|
||||
let mut multiaddr: Multiaddr = ip6.into();
|
||||
multiaddr.push(Protocol::Tcp(tcp6));
|
||||
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.
|
||||
///
|
||||
/// This also prepends the `PeerId` into each multiaddr with the `P2p` protocol.
|
||||
fn multiaddr_p2p(&self) -> Vec<Multiaddr> {
|
||||
let peer_id = self.peer_id();
|
||||
let mut multiaddrs: Vec<Multiaddr> = Vec::new();
|
||||
if let Some(ip) = self.ip4() {
|
||||
if let Some(udp) = self.udp4() {
|
||||
let mut multiaddr: Multiaddr = ip.into();
|
||||
multiaddr.push(Protocol::Udp(udp));
|
||||
multiaddr.push(Protocol::P2p(peer_id));
|
||||
multiaddrs.push(multiaddr);
|
||||
}
|
||||
|
||||
if let Some(tcp) = self.tcp4() {
|
||||
let mut multiaddr: Multiaddr = ip.into();
|
||||
multiaddr.push(Protocol::Tcp(tcp));
|
||||
multiaddr.push(Protocol::P2p(peer_id));
|
||||
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));
|
||||
multiaddrs.push(multiaddr);
|
||||
}
|
||||
|
||||
if let Some(tcp6) = self.tcp6() {
|
||||
let mut multiaddr: Multiaddr = ip6.into();
|
||||
multiaddr.push(Protocol::Tcp(tcp6));
|
||||
multiaddr.push(Protocol::P2p(peer_id));
|
||||
multiaddrs.push(multiaddr);
|
||||
}
|
||||
}
|
||||
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.ip4() {
|
||||
if let Some(tcp) = self.tcp4() {
|
||||
let mut multiaddr: Multiaddr = ip.into();
|
||||
multiaddr.push(Protocol::Tcp(tcp));
|
||||
multiaddr.push(Protocol::P2p(peer_id));
|
||||
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));
|
||||
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.ip4() {
|
||||
if let Some(udp) = self.udp4() {
|
||||
let mut multiaddr: Multiaddr = ip.into();
|
||||
multiaddr.push(Protocol::Udp(udp));
|
||||
multiaddr.push(Protocol::P2p(peer_id));
|
||||
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));
|
||||
multiaddrs.push(multiaddr);
|
||||
}
|
||||
}
|
||||
multiaddrs
|
||||
}
|
||||
|
||||
/// Returns a list of multiaddrs if the ENR has an `ip` and a `quic` key **or** an `ip6` and a `quic6`.
|
||||
fn multiaddr_quic(&self) -> Vec<Multiaddr> {
|
||||
let mut multiaddrs: Vec<Multiaddr> = Vec::new();
|
||||
if let Some(quic_port) = self.quic4() {
|
||||
if let Some(ip) = self.ip4() {
|
||||
let mut multiaddr: Multiaddr = ip.into();
|
||||
multiaddr.push(Protocol::Udp(quic_port));
|
||||
multiaddr.push(Protocol::QuicV1);
|
||||
multiaddrs.push(multiaddr);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(quic6_port) = self.quic6() {
|
||||
if let Some(ip6) = self.ip6() {
|
||||
let mut multiaddr: Multiaddr = ip6.into();
|
||||
multiaddr.push(Protocol::Udp(quic6_port));
|
||||
multiaddr.push(Protocol::QuicV1);
|
||||
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`.
|
||||
fn multiaddr_tcp(&self) -> Vec<Multiaddr> {
|
||||
let mut multiaddrs: Vec<Multiaddr> = Vec::new();
|
||||
if let Some(ip) = self.ip4() {
|
||||
if let Some(tcp) = self.tcp4() {
|
||||
let mut multiaddr: Multiaddr = ip.into();
|
||||
multiaddr.push(Protocol::Tcp(tcp));
|
||||
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));
|
||||
multiaddrs.push(multiaddr);
|
||||
}
|
||||
}
|
||||
multiaddrs
|
||||
}
|
||||
}
|
||||
|
||||
impl CombinedKeyPublicExt for CombinedPublicKey {
|
||||
/// Converts the publickey into a peer id, without consuming the key.
|
||||
///
|
||||
/// This is only available with the `libp2p` feature flag.
|
||||
fn as_peer_id(&self) -> PeerId {
|
||||
match self {
|
||||
Self::Secp256k1(pk) => {
|
||||
let pk_bytes = pk.to_sec1_bytes();
|
||||
let libp2p_pk: PublicKey = secp256k1::PublicKey::try_from_bytes(&pk_bytes)
|
||||
.expect("valid public key")
|
||||
.into();
|
||||
PeerId::from_public_key(&libp2p_pk)
|
||||
}
|
||||
Self::Ed25519(pk) => {
|
||||
let pk_bytes = pk.to_bytes();
|
||||
let libp2p_pk: PublicKey = ed25519::PublicKey::try_from_bytes(&pk_bytes)
|
||||
.expect("valid public key")
|
||||
.into();
|
||||
PeerId::from_public_key(&libp2p_pk)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CombinedKeyExt for CombinedKey {
|
||||
fn from_libp2p(key: Keypair) -> Result<CombinedKey, &'static str> {
|
||||
match key.key_type() {
|
||||
KeyType::Secp256k1 => {
|
||||
let key = key.try_into_secp256k1().expect("right key type");
|
||||
let secret =
|
||||
discv5::enr::k256::ecdsa::SigningKey::from_slice(&key.secret().to_bytes())
|
||||
.expect("libp2p key must be valid");
|
||||
Ok(CombinedKey::Secp256k1(secret))
|
||||
}
|
||||
KeyType::Ed25519 => {
|
||||
let key = key.try_into_ed25519().expect("right key type");
|
||||
let ed_keypair = discv5::enr::ed25519_dalek::SigningKey::from_bytes(
|
||||
&(key.to_bytes()[..32])
|
||||
.try_into()
|
||||
.expect("libp2p key must be valid"),
|
||||
);
|
||||
Ok(CombinedKey::from(ed_keypair))
|
||||
}
|
||||
_ => Err("Unsupported keypair kind"),
|
||||
}
|
||||
}
|
||||
fn from_secp256k1(key: &secp256k1::Keypair) -> Self {
|
||||
let secret = discv5::enr::k256::ecdsa::SigningKey::from_slice(&key.secret().to_bytes())
|
||||
.expect("libp2p key must be valid");
|
||||
CombinedKey::Secp256k1(secret)
|
||||
}
|
||||
}
|
||||
|
||||
// helper function to convert a peer_id to a node_id. This is only possible for secp256k1/ed25519 libp2p
|
||||
// peer_ids
|
||||
pub fn peer_id_to_node_id(peer_id: &PeerId) -> Result<discv5::enr::NodeId, String> {
|
||||
// A libp2p peer id byte representation should be 2 length bytes + 4 protobuf bytes + compressed pk bytes
|
||||
// if generated from a PublicKey with Identity multihash.
|
||||
let pk_bytes = &peer_id.to_bytes()[2..];
|
||||
|
||||
let public_key = PublicKey::try_decode_protobuf(pk_bytes).map_err(|e| {
|
||||
format!(
|
||||
" Cannot parse libp2p public key public key from peer id: {}",
|
||||
e
|
||||
)
|
||||
})?;
|
||||
|
||||
match public_key.key_type() {
|
||||
KeyType::Secp256k1 => {
|
||||
let pk = public_key
|
||||
.clone()
|
||||
.try_into_secp256k1()
|
||||
.expect("right key type");
|
||||
let uncompressed_key_bytes = &pk.to_bytes_uncompressed()[1..];
|
||||
let mut output = [0_u8; 32];
|
||||
let mut hasher = Keccak::v256();
|
||||
hasher.update(uncompressed_key_bytes);
|
||||
hasher.finalize(&mut output);
|
||||
Ok(discv5::enr::NodeId::parse(&output).expect("Must be correct length"))
|
||||
}
|
||||
KeyType::Ed25519 => {
|
||||
let pk = public_key
|
||||
.clone()
|
||||
.try_into_ed25519()
|
||||
.expect("right key type");
|
||||
let uncompressed_key_bytes = pk.to_bytes();
|
||||
let mut output = [0_u8; 32];
|
||||
let mut hasher = Keccak::v256();
|
||||
hasher.update(&uncompressed_key_bytes);
|
||||
hasher.finalize(&mut output);
|
||||
Ok(discv5::enr::NodeId::parse(&output).expect("Must be correct length"))
|
||||
}
|
||||
|
||||
_ => Err(format!("Unsupported public key from peer {}", peer_id)),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_secp256k1_peer_id_conversion() {
|
||||
let sk_hex = "df94a73d528434ce2309abb19c16aedb535322797dbd59c157b1e04095900f48";
|
||||
let sk_bytes = hex::decode(sk_hex).unwrap();
|
||||
let secret_key = discv5::enr::k256::ecdsa::SigningKey::from_slice(&sk_bytes).unwrap();
|
||||
|
||||
let libp2p_sk = secp256k1::SecretKey::try_from_bytes(sk_bytes).unwrap();
|
||||
let secp256k1_kp: secp256k1::Keypair = libp2p_sk.into();
|
||||
let libp2p_kp: Keypair = secp256k1_kp.into();
|
||||
let peer_id = libp2p_kp.public().to_peer_id();
|
||||
|
||||
let enr = discv5::enr::Enr::builder().build(&secret_key).unwrap();
|
||||
let node_id = peer_id_to_node_id(&peer_id).unwrap();
|
||||
|
||||
assert_eq!(enr.node_id(), node_id);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ed25519_peer_conversion() {
|
||||
let sk_hex = "4dea8a5072119927e9d243a7d953f2f4bc95b70f110978e2f9bc7a9000e4b261";
|
||||
let sk_bytes = hex::decode(sk_hex).unwrap();
|
||||
let secret_key = discv5::enr::ed25519_dalek::SigningKey::from_bytes(
|
||||
&sk_bytes.clone().try_into().unwrap(),
|
||||
);
|
||||
|
||||
let libp2p_sk = ed25519::SecretKey::try_from_bytes(sk_bytes).unwrap();
|
||||
let secp256k1_kp: ed25519::Keypair = libp2p_sk.into();
|
||||
let libp2p_kp: Keypair = secp256k1_kp.into();
|
||||
let peer_id = libp2p_kp.public().to_peer_id();
|
||||
|
||||
let enr = discv5::enr::Enr::builder().build(&secret_key).unwrap();
|
||||
let node_id = peer_id_to_node_id(&peer_id).unwrap();
|
||||
|
||||
assert_eq!(enr.node_id(), node_id);
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@
|
||||
//! queries and manages access to the discovery routing table.
|
||||
|
||||
pub(crate) mod enr;
|
||||
pub mod enr_ext;
|
||||
|
||||
// Allow external use of the lighthouse ENR builder
|
||||
use crate::service::TARGET_SUBNET_PEERS;
|
||||
@@ -12,8 +11,8 @@ use crate::{metrics, ClearDialError};
|
||||
use crate::{Enr, NetworkConfig, NetworkGlobals, Subnet, SubnetDiscovery};
|
||||
use discv5::{enr::NodeId, Discv5};
|
||||
pub use enr::{build_enr, load_enr_from_disk, use_or_load_enr, CombinedKey, Eth2Enr};
|
||||
pub use enr_ext::{peer_id_to_node_id, CombinedKeyExt, EnrExt};
|
||||
pub use libp2p::identity::{Keypair, PublicKey};
|
||||
use network_utils::enr_ext::{peer_id_to_node_id, CombinedKeyExt, EnrExt};
|
||||
|
||||
use alloy_rlp::bytes::Bytes;
|
||||
use enr::{ATTESTATION_BITFIELD_ENR_KEY, ETH2_ENR_KEY, SYNC_COMMITTEE_BITFIELD_ENR_KEY};
|
||||
@@ -33,6 +32,7 @@ pub use libp2p::{
|
||||
};
|
||||
use logging::crit;
|
||||
use lru::LruCache;
|
||||
use network_utils::discovery_metrics;
|
||||
use ssz::Encode;
|
||||
use std::num::NonZeroUsize;
|
||||
use std::{
|
||||
@@ -687,7 +687,10 @@ impl<E: EthSpec> Discovery<E> {
|
||||
min_ttl,
|
||||
retries,
|
||||
});
|
||||
metrics::set_gauge(&metrics::DISCOVERY_QUEUE, self.queued_queries.len() as i64);
|
||||
metrics::set_gauge(
|
||||
&discovery_metrics::DISCOVERY_QUEUE,
|
||||
self.queued_queries.len() as i64,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -722,7 +725,10 @@ impl<E: EthSpec> Discovery<E> {
|
||||
}
|
||||
}
|
||||
// Update the queue metric
|
||||
metrics::set_gauge(&metrics::DISCOVERY_QUEUE, self.queued_queries.len() as i64);
|
||||
metrics::set_gauge(
|
||||
&discovery_metrics::DISCOVERY_QUEUE,
|
||||
self.queued_queries.len() as i64,
|
||||
);
|
||||
processed
|
||||
}
|
||||
|
||||
@@ -1227,7 +1233,7 @@ mod tests {
|
||||
let spec = Arc::new(ChainSpec::default());
|
||||
let keypair = secp256k1::Keypair::generate();
|
||||
let mut config = NetworkConfig::default();
|
||||
config.set_listening_addr(crate::ListenAddress::unused_v4_ports());
|
||||
config.set_listening_addr(network_utils::listen_addr::ListenAddress::unused_v4_ports());
|
||||
let config = Arc::new(config);
|
||||
let enr_key: CombinedKey = CombinedKey::from_secp256k1(&keypair);
|
||||
let next_fork_digest = [0; 4];
|
||||
|
||||
@@ -6,14 +6,12 @@ mod config;
|
||||
pub mod service;
|
||||
|
||||
pub mod discovery;
|
||||
pub mod listen_addr;
|
||||
pub mod metrics;
|
||||
pub mod peer_manager;
|
||||
pub mod rpc;
|
||||
pub mod types;
|
||||
|
||||
use libp2p::swarm::DialError;
|
||||
pub use listen_addr::*;
|
||||
|
||||
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
||||
use std::str::FromStr;
|
||||
@@ -107,13 +105,12 @@ pub use crate::types::{
|
||||
pub use prometheus_client;
|
||||
|
||||
pub use config::Config as NetworkConfig;
|
||||
pub use discovery::{CombinedKeyExt, EnrExt, Eth2Enr};
|
||||
pub use discovery::Eth2Enr;
|
||||
pub use discv5;
|
||||
pub use gossipsub::{IdentTopic, MessageAcceptance, MessageId, Topic, TopicHash};
|
||||
pub use libp2p;
|
||||
pub use libp2p::{core::ConnectedPoint, PeerId, Swarm};
|
||||
pub use libp2p::{multiaddr, Multiaddr};
|
||||
pub use metrics::scrape_discovery_metrics;
|
||||
pub use peer_manager::{
|
||||
peerdb::client::Client,
|
||||
peerdb::score::{PeerAction, ReportSource},
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
|
||||
|
||||
use libp2p::{multiaddr::Protocol, Multiaddr};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// A listening address composed by an Ip, an UDP port and a TCP port.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct ListenAddr<Ip> {
|
||||
/// The IP address we will listen on.
|
||||
pub addr: Ip,
|
||||
/// The UDP port that discovery will listen on.
|
||||
pub disc_port: u16,
|
||||
/// The UDP port that QUIC will listen on.
|
||||
pub quic_port: u16,
|
||||
/// The TCP port that libp2p will listen on.
|
||||
pub tcp_port: u16,
|
||||
}
|
||||
|
||||
impl<Ip: Into<IpAddr> + Clone> ListenAddr<Ip> {
|
||||
pub fn discovery_socket_addr(&self) -> SocketAddr {
|
||||
(self.addr.clone().into(), self.disc_port).into()
|
||||
}
|
||||
|
||||
pub fn quic_socket_addr(&self) -> SocketAddr {
|
||||
(self.addr.clone().into(), self.quic_port).into()
|
||||
}
|
||||
|
||||
pub fn tcp_socket_addr(&self) -> SocketAddr {
|
||||
(self.addr.clone().into(), self.tcp_port).into()
|
||||
}
|
||||
}
|
||||
|
||||
/// Types of listening addresses Lighthouse can accept.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum ListenAddress {
|
||||
V4(ListenAddr<Ipv4Addr>),
|
||||
V6(ListenAddr<Ipv6Addr>),
|
||||
DualStack(ListenAddr<Ipv4Addr>, ListenAddr<Ipv6Addr>),
|
||||
}
|
||||
|
||||
impl ListenAddress {
|
||||
/// Return the listening address over IpV4 if any.
|
||||
pub fn v4(&self) -> Option<&ListenAddr<Ipv4Addr>> {
|
||||
match self {
|
||||
ListenAddress::V4(v4_addr) | ListenAddress::DualStack(v4_addr, _) => Some(v4_addr),
|
||||
ListenAddress::V6(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the listening address over IpV6 if any.
|
||||
pub fn v6(&self) -> Option<&ListenAddr<Ipv6Addr>> {
|
||||
match self {
|
||||
ListenAddress::V6(v6_addr) | ListenAddress::DualStack(_, v6_addr) => Some(v6_addr),
|
||||
ListenAddress::V4(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the addresses the Swarm will listen on, given the setup.
|
||||
pub fn libp2p_addresses(&self) -> impl Iterator<Item = Multiaddr> {
|
||||
let v4_tcp_multiaddr = self
|
||||
.v4()
|
||||
.map(|v4_addr| Multiaddr::from(v4_addr.addr).with(Protocol::Tcp(v4_addr.tcp_port)));
|
||||
|
||||
let v4_quic_multiaddr = self.v4().map(|v4_addr| {
|
||||
Multiaddr::from(v4_addr.addr)
|
||||
.with(Protocol::Udp(v4_addr.quic_port))
|
||||
.with(Protocol::QuicV1)
|
||||
});
|
||||
|
||||
let v6_quic_multiaddr = self.v6().map(|v6_addr| {
|
||||
Multiaddr::from(v6_addr.addr)
|
||||
.with(Protocol::Udp(v6_addr.quic_port))
|
||||
.with(Protocol::QuicV1)
|
||||
});
|
||||
|
||||
let v6_tcp_multiaddr = self
|
||||
.v6()
|
||||
.map(|v6_addr| Multiaddr::from(v6_addr.addr).with(Protocol::Tcp(v6_addr.tcp_port)));
|
||||
|
||||
v4_tcp_multiaddr
|
||||
.into_iter()
|
||||
.chain(v4_quic_multiaddr)
|
||||
.chain(v6_quic_multiaddr)
|
||||
.chain(v6_tcp_multiaddr)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn unused_v4_ports() -> Self {
|
||||
ListenAddress::V4(ListenAddr {
|
||||
addr: Ipv4Addr::UNSPECIFIED,
|
||||
disc_port: unused_port::unused_udp4_port().unwrap(),
|
||||
quic_port: unused_port::unused_udp4_port().unwrap(),
|
||||
tcp_port: unused_port::unused_tcp4_port().unwrap(),
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn unused_v6_ports() -> Self {
|
||||
ListenAddress::V6(ListenAddr {
|
||||
addr: Ipv6Addr::UNSPECIFIED,
|
||||
disc_port: unused_port::unused_udp6_port().unwrap(),
|
||||
quic_port: unused_port::unused_udp6_port().unwrap(),
|
||||
tcp_port: unused_port::unused_tcp6_port().unwrap(),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,6 @@
|
||||
pub use metrics::*;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
pub static NAT_OPEN: LazyLock<Result<IntGaugeVec>> = LazyLock::new(|| {
|
||||
try_create_int_gauge_vec(
|
||||
"nat_open",
|
||||
"An estimate indicating if the local node is reachable from external nodes",
|
||||
&["protocol"],
|
||||
)
|
||||
});
|
||||
|
||||
pub static ADDRESS_UPDATE_COUNT: LazyLock<Result<IntCounter>> = LazyLock::new(|| {
|
||||
try_create_int_counter(
|
||||
"libp2p_address_update_total",
|
||||
@@ -53,31 +45,6 @@ pub static PEER_DISCONNECT_EVENT_COUNT: LazyLock<Result<IntCounter>> = LazyLock:
|
||||
"Count of libp2p peer disconnect events",
|
||||
)
|
||||
});
|
||||
pub static DISCOVERY_BYTES: LazyLock<Result<IntGaugeVec>> = LazyLock::new(|| {
|
||||
try_create_int_gauge_vec(
|
||||
"discovery_bytes",
|
||||
"The number of bytes sent and received in discovery",
|
||||
&["direction"],
|
||||
)
|
||||
});
|
||||
pub static DISCOVERY_QUEUE: LazyLock<Result<IntGauge>> = LazyLock::new(|| {
|
||||
try_create_int_gauge(
|
||||
"discovery_queue_size",
|
||||
"The number of discovery queries awaiting execution",
|
||||
)
|
||||
});
|
||||
pub static DISCOVERY_REQS: LazyLock<Result<Gauge>> = LazyLock::new(|| {
|
||||
try_create_float_gauge(
|
||||
"discovery_requests",
|
||||
"The number of unsolicited discovery requests per second",
|
||||
)
|
||||
});
|
||||
pub static DISCOVERY_SESSIONS: LazyLock<Result<IntGauge>> = LazyLock::new(|| {
|
||||
try_create_int_gauge(
|
||||
"discovery_sessions",
|
||||
"The number of active discovery sessions with peers",
|
||||
)
|
||||
});
|
||||
pub static DISCOVERY_NO_USEFUL_ENRS: LazyLock<Result<IntCounter>> = LazyLock::new(|| {
|
||||
try_create_int_counter(
|
||||
"discovery_no_useful_enrs_found",
|
||||
@@ -219,14 +186,3 @@ pub static RESPONSE_IDLING: LazyLock<Result<Histogram>> = LazyLock::new(|| {
|
||||
"The time our response remained idle in the response limiter",
|
||||
)
|
||||
});
|
||||
|
||||
pub fn scrape_discovery_metrics() {
|
||||
let metrics =
|
||||
discv5::metrics::Metrics::from(discv5::Discv5::<discv5::DefaultProtocolId>::raw_metrics());
|
||||
set_float_gauge(&DISCOVERY_REQS, metrics.unsolicited_requests_per_second);
|
||||
set_gauge(&DISCOVERY_SESSIONS, metrics.active_sessions as i64);
|
||||
set_gauge_vec(&DISCOVERY_BYTES, &["inbound"], metrics.bytes_recv as i64);
|
||||
set_gauge_vec(&DISCOVERY_BYTES, &["outbound"], metrics.bytes_sent as i64);
|
||||
set_gauge_vec(&NAT_OPEN, &["discv5_ipv4"], metrics.ipv4_contactable as i64);
|
||||
set_gauge_vec(&NAT_OPEN, &["discv5_ipv6"], metrics.ipv6_contactable as i64);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
//! Implementation of Lighthouse's peer management system.
|
||||
|
||||
use crate::discovery::enr_ext::EnrExt;
|
||||
use crate::discovery::peer_id_to_node_id;
|
||||
use crate::rpc::{GoodbyeReason, MetaData, Protocol, RPCError, RpcErrorResponse};
|
||||
use crate::service::TARGET_SUBNET_PEERS;
|
||||
use crate::{metrics, Gossipsub, NetworkGlobals, PeerId, Subnet, SubnetDiscovery};
|
||||
@@ -26,6 +24,8 @@ pub mod peerdb;
|
||||
|
||||
use crate::peer_manager::peerdb::client::ClientKind;
|
||||
use libp2p::multiaddr;
|
||||
use network_utils::discovery_metrics;
|
||||
use network_utils::enr_ext::{peer_id_to_node_id, EnrExt};
|
||||
pub use peerdb::peer_info::{
|
||||
ConnectionDirection, PeerConnectionStatus, PeerConnectionStatus::*, PeerInfo,
|
||||
};
|
||||
@@ -1418,16 +1418,16 @@ impl<E: EthSpec> PeerManager<E> {
|
||||
|
||||
// Set ipv4 nat_open metric flag if threshold of peercount is met, unset if below threshold
|
||||
if inbound_ipv4_peers_connected >= LIBP2P_NAT_OPEN_THRESHOLD {
|
||||
metrics::set_gauge_vec(&metrics::NAT_OPEN, &["libp2p_ipv4"], 1);
|
||||
metrics::set_gauge_vec(&discovery_metrics::NAT_OPEN, &["libp2p_ipv4"], 1);
|
||||
} else {
|
||||
metrics::set_gauge_vec(&metrics::NAT_OPEN, &["libp2p_ipv4"], 0);
|
||||
metrics::set_gauge_vec(&discovery_metrics::NAT_OPEN, &["libp2p_ipv4"], 0);
|
||||
}
|
||||
|
||||
// Set ipv6 nat_open metric flag if threshold of peercount is met, unset if below threshold
|
||||
if inbound_ipv6_peers_connected >= LIBP2P_NAT_OPEN_THRESHOLD {
|
||||
metrics::set_gauge_vec(&metrics::NAT_OPEN, &["libp2p_ipv6"], 1);
|
||||
metrics::set_gauge_vec(&discovery_metrics::NAT_OPEN, &["libp2p_ipv6"], 1);
|
||||
} else {
|
||||
metrics::set_gauge_vec(&metrics::NAT_OPEN, &["libp2p_ipv6"], 0);
|
||||
metrics::set_gauge_vec(&discovery_metrics::NAT_OPEN, &["libp2p_ipv6"], 0);
|
||||
}
|
||||
|
||||
// PEERS_CONNECTED
|
||||
|
||||
@@ -12,11 +12,12 @@ use libp2p::swarm::behaviour::{ConnectionClosed, ConnectionEstablished, DialFail
|
||||
use libp2p::swarm::dial_opts::{DialOpts, PeerCondition};
|
||||
use libp2p::swarm::dummy::ConnectionHandler;
|
||||
use libp2p::swarm::{ConnectionDenied, ConnectionId, NetworkBehaviour, ToSwarm};
|
||||
pub use metrics::{set_gauge_vec, NAT_OPEN};
|
||||
use metrics::set_gauge_vec;
|
||||
use network_utils::discovery_metrics::NAT_OPEN;
|
||||
use network_utils::enr_ext::EnrExt;
|
||||
use tracing::{debug, error, trace};
|
||||
use types::EthSpec;
|
||||
|
||||
use crate::discovery::enr_ext::EnrExt;
|
||||
use crate::types::SyncState;
|
||||
use crate::{metrics, ClearDialError};
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
use crate::discovery::enr::PEERDAS_CUSTODY_GROUP_COUNT_ENR_KEY;
|
||||
use crate::discovery::{peer_id_to_node_id, CombinedKey};
|
||||
use crate::{
|
||||
metrics, multiaddr::Multiaddr, types::Subnet, Enr, EnrExt, Gossipsub, PeerId, SyncInfo,
|
||||
};
|
||||
use crate::discovery::CombinedKey;
|
||||
use crate::{metrics, multiaddr::Multiaddr, types::Subnet, Enr, Gossipsub, PeerId, SyncInfo};
|
||||
use itertools::Itertools;
|
||||
use logging::crit;
|
||||
use network_utils::enr_ext::{peer_id_to_node_id, EnrExt};
|
||||
use peer_info::{ConnectionDirection, PeerConnectionStatus, PeerInfo};
|
||||
use score::{PeerAction, ReportSource, Score, ScoreState};
|
||||
use std::net::IpAddr;
|
||||
|
||||
@@ -17,7 +17,6 @@ use crate::types::{
|
||||
all_topics_at_fork, core_topics_to_subscribe, is_fork_non_core_topic, subnet_from_topic_hash,
|
||||
GossipEncoding, GossipKind, GossipTopic, SnappyTransform, Subnet, SubnetDiscovery,
|
||||
};
|
||||
use crate::EnrExt;
|
||||
use crate::Eth2Enr;
|
||||
use crate::{metrics, Enr, NetworkGlobals, PubsubMessage, TopicHash};
|
||||
use api_types::{AppRequestId, Response};
|
||||
@@ -33,6 +32,7 @@ use libp2p::swarm::{NetworkBehaviour, Swarm, SwarmEvent};
|
||||
use libp2p::upnp::tokio::Behaviour as Upnp;
|
||||
use libp2p::{identify, PeerId, SwarmBuilder};
|
||||
use logging::crit;
|
||||
use network_utils::enr_ext::EnrExt;
|
||||
use std::num::{NonZeroU8, NonZeroUsize};
|
||||
use std::path::PathBuf;
|
||||
use std::pin::Pin;
|
||||
|
||||
@@ -3,7 +3,8 @@ use super::TopicConfig;
|
||||
use crate::peer_manager::peerdb::PeerDB;
|
||||
use crate::rpc::{MetaData, MetaDataV3};
|
||||
use crate::types::{BackFillState, SyncState};
|
||||
use crate::{Client, Enr, EnrExt, GossipTopic, Multiaddr, NetworkConfig, PeerId};
|
||||
use crate::{Client, Enr, GossipTopic, Multiaddr, NetworkConfig, PeerId};
|
||||
use network_utils::enr_ext::EnrExt;
|
||||
use parking_lot::RwLock;
|
||||
use std::collections::HashSet;
|
||||
use std::sync::Arc;
|
||||
@@ -277,7 +278,7 @@ impl<E: EthSpec> NetworkGlobals<E> {
|
||||
config: Arc<NetworkConfig>,
|
||||
spec: Arc<ChainSpec>,
|
||||
) -> NetworkGlobals<E> {
|
||||
use crate::CombinedKeyExt;
|
||||
use network_utils::enr_ext::CombinedKeyExt;
|
||||
let keypair = libp2p::identity::secp256k1::Keypair::generate();
|
||||
let enr_key: discv5::enr::CombinedKey = discv5::enr::CombinedKey::from_secp256k1(&keypair);
|
||||
let enr = discv5::enr::Enr::builder().build(&enr_key).unwrap();
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#![cfg(test)]
|
||||
use lighthouse_network::service::Network as LibP2PService;
|
||||
use lighthouse_network::Enr;
|
||||
use lighthouse_network::EnrExt;
|
||||
use lighthouse_network::Multiaddr;
|
||||
use lighthouse_network::{NetworkConfig, NetworkEvent};
|
||||
use network_utils::enr_ext::EnrExt;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Weak;
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
Reference in New Issue
Block a user