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

@@ -17,6 +17,8 @@ use std::path::Path;
use std::str::FromStr;
use types::{EnrForkId, EthSpec};
use super::enr_ext::{EnrExt, QUIC6_ENR_KEY, QUIC_ENR_KEY};
/// The ENR field specifying the fork id.
pub const ETH2_ENR_KEY: &str = "eth2";
/// The ENR field specifying the attestation subnet bitfield.
@@ -142,7 +144,7 @@ pub fn build_or_load_enr<T: EthSpec>(
pub fn create_enr_builder_from_config<T: EnrKey>(
config: &NetworkConfig,
enable_tcp: bool,
enable_libp2p: bool,
) -> EnrBuilder<T> {
let mut builder = EnrBuilder::new("v4");
let (maybe_ipv4_address, maybe_ipv6_address) = &config.enr_address;
@@ -163,7 +165,28 @@ pub fn create_enr_builder_from_config<T: EnrKey>(
builder.udp6(udp6_port);
}
if enable_tcp {
if enable_libp2p {
// Add QUIC fields to the ENR.
// Since QUIC is used as an alternative transport for the libp2p protocols,
// the related fields should only be added when both QUIC and libp2p are enabled
if !config.disable_quic_support {
// If we are listening on ipv4, add the quic ipv4 port.
if let Some(quic4_port) = config
.enr_quic4_port
.or_else(|| config.listen_addrs().v4().map(|v4_addr| v4_addr.quic_port))
{
builder.add_value(QUIC_ENR_KEY, &quic4_port);
}
// If we are listening on ipv6, add the quic ipv6 port.
if let Some(quic6_port) = config
.enr_quic6_port
.or_else(|| config.listen_addrs().v6().map(|v6_addr| v6_addr.quic_port))
{
builder.add_value(QUIC6_ENR_KEY, &quic6_port);
}
}
// If the ENR port is not set, and we are listening over that ip version, use the listening port instead.
let tcp4_port = config
.enr_tcp4_port
@@ -218,6 +241,9 @@ fn compare_enr(local_enr: &Enr, disk_enr: &Enr) -> bool {
// tcp ports must match
&& local_enr.tcp4() == disk_enr.tcp4()
&& local_enr.tcp6() == disk_enr.tcp6()
// quic ports must match
&& local_enr.quic4() == disk_enr.quic4()
&& local_enr.quic6() == disk_enr.quic6()
// must match on the same fork
&& local_enr.get(ETH2_ENR_KEY) == disk_enr.get(ETH2_ENR_KEY)
// take preference over disk udp port if one is not specified