Add Experimental QUIC support (#4577)

## Issue Addressed

#4402 

## Proposed Changes

This PR adds QUIC support to Lighthouse. As this is not officially spec'd this will only work between lighthouse <-> lighthouse connections. We attempt a QUIC connection (if the node advertises it) and if it fails we fallback to TCP. 

This should be a backwards compatible modification. We want to test this functionality on live networks to observe any improvements in bandwidth/latency.

NOTE: This also removes the websockets transport as I believe no one is really using it. It should be mentioned in our release however.


Co-authored-by: João Oliveira <hello@jxs.pt>
This commit is contained in:
Age Manning
2023-09-15 03:07:24 +00:00
parent 35f47f454f
commit e4ed317b76
35 changed files with 1161 additions and 752 deletions

View File

@@ -6,12 +6,15 @@ 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 either a `tcp` or `udp` key **or** an `ip6` and either a `tcp6` or `udp6`.
/// 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>;
@@ -26,6 +29,15 @@ pub trait EnrExt {
/// 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.
@@ -49,7 +61,17 @@ impl EnrExt for Enr {
self.public_key().as_peer_id()
}
/// 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`.
/// 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();
@@ -59,6 +81,12 @@ impl EnrExt for Enr {
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();
@@ -73,6 +101,13 @@ impl EnrExt for Enr {
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));
@@ -174,8 +209,30 @@ impl EnrExt for Enr {
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`.
/// The vector remains empty if these fields are not defined.
fn multiaddr_tcp(&self) -> Vec<Multiaddr> {
let mut multiaddrs: Vec<Multiaddr> = Vec::new();
if let Some(ip) = self.ip4() {