Skip to content

Commit 1c98806

Browse files
committed
Allow libp2p to determine listening addresses (#4700)
## Issue Addressed #4675 ## Proposed Changes - Update local ENR (**only port numbers**) with local addresses received from libp2p (via `SwarmEvent::NewListenAddr`) - Only use the zero port for CLI tests ## Additional Info ### See Also ### - #4705 - #4402 - #4745
1 parent a935dae commit 1c98806

File tree

3 files changed

+158
-57
lines changed

3 files changed

+158
-57
lines changed

beacon_node/lighthouse_network/src/config.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ use std::sync::Arc;
1616
use std::time::Duration;
1717
use types::{ForkContext, ForkName};
1818

19+
pub const DEFAULT_IPV4_ADDRESS: Ipv4Addr = Ipv4Addr::UNSPECIFIED;
20+
pub const DEFAULT_TCP_PORT: u16 = 9000u16;
21+
pub const DEFAULT_DISC_PORT: u16 = 9000u16;
22+
pub const DEFAULT_QUIC_PORT: u16 = 9001u16;
23+
1924
/// The cache time is set to accommodate the circulation time of an attestation.
2025
///
2126
/// The p2p spec declares that we accept attestations within the following range:
@@ -304,10 +309,10 @@ impl Default for Config {
304309
.expect("The total rate limit has been specified"),
305310
);
306311
let listen_addresses = ListenAddress::V4(ListenAddr {
307-
addr: Ipv4Addr::UNSPECIFIED,
308-
disc_port: 9000,
309-
quic_port: 9001,
310-
tcp_port: 9000,
312+
addr: DEFAULT_IPV4_ADDRESS,
313+
disc_port: DEFAULT_DISC_PORT,
314+
quic_port: DEFAULT_QUIC_PORT,
315+
tcp_port: DEFAULT_TCP_PORT,
311316
});
312317

313318
let discv5_listen_config =

beacon_node/lighthouse_network/src/discovery/mod.rs

Lines changed: 94 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,11 @@ pub use libp2p::identity::{Keypair, PublicKey};
2121
use enr::{ATTESTATION_BITFIELD_ENR_KEY, ETH2_ENR_KEY, SYNC_COMMITTEE_BITFIELD_ENR_KEY};
2222
use futures::prelude::*;
2323
use futures::stream::FuturesUnordered;
24+
use libp2p::multiaddr::Protocol;
2425
use libp2p::swarm::behaviour::{DialFailure, FromSwarm};
2526
use libp2p::swarm::THandlerInEvent;
2627
pub use libp2p::{
27-
core::{ConnectedPoint, Multiaddr},
28+
core::{transport::ListenerId, ConnectedPoint, Multiaddr},
2829
identity::PeerId,
2930
swarm::{
3031
dummy::ConnectionHandler, ConnectionId, DialError, NetworkBehaviour, NotifyHandler,
@@ -77,6 +78,19 @@ pub struct DiscoveredPeers {
7778
pub peers: HashMap<Enr, Option<Instant>>,
7879
}
7980

81+
/// Specifies which port numbers should be modified after start of the discovery service
82+
#[derive(Debug)]
83+
pub struct UpdatePorts {
84+
/// TCP port associated wih IPv4 address (if present)
85+
pub tcp4: bool,
86+
/// TCP port associated wih IPv6 address (if present)
87+
pub tcp6: bool,
88+
/// QUIC port associated wih IPv4 address (if present)
89+
pub quic4: bool,
90+
/// QUIC port associated wih IPv6 address (if present)
91+
pub quic6: bool,
92+
}
93+
8094
#[derive(Clone, PartialEq)]
8195
struct SubnetQuery {
8296
subnet: Subnet,
@@ -177,12 +191,8 @@ pub struct Discovery<TSpec: EthSpec> {
177191
/// always false.
178192
pub started: bool,
179193

180-
/// This keeps track of whether an external UDP port change should also indicate an internal
181-
/// TCP port change. As we cannot detect our external TCP port, we assume that the external UDP
182-
/// port is also our external TCP port. This assumption only holds if the user has not
183-
/// explicitly set their ENR TCP port via the CLI config. The first indicates tcp4 and the
184-
/// second indicates tcp6.
185-
update_tcp_port: (bool, bool),
194+
/// Specifies whether various port numbers should be updated after the discovery service has been started
195+
update_ports: UpdatePorts,
186196

187197
/// Logger for the discovery behaviour.
188198
log: slog::Logger,
@@ -300,10 +310,12 @@ impl<TSpec: EthSpec> Discovery<TSpec> {
300310
}
301311
}
302312

303-
let update_tcp_port = (
304-
config.enr_tcp4_port.is_none(),
305-
config.enr_tcp6_port.is_none(),
306-
);
313+
let update_ports = UpdatePorts {
314+
tcp4: config.enr_tcp4_port.is_none(),
315+
tcp6: config.enr_tcp6_port.is_none(),
316+
quic4: config.enr_quic4_port.is_none(),
317+
quic6: config.enr_quic6_port.is_none(),
318+
};
307319

308320
Ok(Self {
309321
cached_enrs: LruCache::new(50),
@@ -314,7 +326,7 @@ impl<TSpec: EthSpec> Discovery<TSpec> {
314326
discv5,
315327
event_stream,
316328
started: !config.disable_discovery,
317-
update_tcp_port,
329+
update_ports,
318330
log,
319331
enr_dir,
320332
})
@@ -1006,8 +1018,8 @@ impl<TSpec: EthSpec> NetworkBehaviour for Discovery<TSpec> {
10061018
// Discv5 will have updated our local ENR. We save the updated version
10071019
// to disk.
10081020

1009-
if (self.update_tcp_port.0 && socket_addr.is_ipv4())
1010-
|| (self.update_tcp_port.1 && socket_addr.is_ipv6())
1021+
if (self.update_ports.tcp4 && socket_addr.is_ipv4())
1022+
|| (self.update_ports.tcp6 && socket_addr.is_ipv6())
10111023
{
10121024
// Update the TCP port in the ENR
10131025
self.discv5.update_local_enr_socket(socket_addr, true);
@@ -1036,12 +1048,79 @@ impl<TSpec: EthSpec> NetworkBehaviour for Discovery<TSpec> {
10361048
FromSwarm::DialFailure(DialFailure { peer_id, error, .. }) => {
10371049
self.on_dial_failure(peer_id, error)
10381050
}
1051+
FromSwarm::NewListenAddr(ev) => {
1052+
let addr = ev.addr;
1053+
let listener_id = ev.listener_id;
1054+
1055+
trace!(self.log, "Received NewListenAddr event from swarm"; "listener_id" => ?listener_id, "addr" => ?addr);
1056+
1057+
let mut addr_iter = addr.iter();
1058+
1059+
let attempt_enr_update = match addr_iter.next() {
1060+
Some(Protocol::Ip4(_)) => match (addr_iter.next(), addr_iter.next()) {
1061+
(Some(Protocol::Tcp(port)), None) => {
1062+
if !self.update_ports.tcp4 {
1063+
debug!(self.log, "Skipping ENR update"; "multiaddr" => ?addr);
1064+
return;
1065+
}
1066+
1067+
self.update_enr_tcp_port(port)
1068+
}
1069+
(Some(Protocol::Udp(port)), Some(Protocol::QuicV1)) => {
1070+
if !self.update_ports.quic4 {
1071+
debug!(self.log, "Skipping ENR update"; "multiaddr" => ?addr);
1072+
return;
1073+
}
1074+
1075+
self.update_enr_quic_port(port)
1076+
}
1077+
_ => {
1078+
debug!(self.log, "Encountered unacceptable multiaddr for listening (unsupported transport)"; "addr" => ?addr);
1079+
return;
1080+
}
1081+
},
1082+
Some(Protocol::Ip6(_)) => match (addr_iter.next(), addr_iter.next()) {
1083+
(Some(Protocol::Tcp(port)), None) => {
1084+
if !self.update_ports.tcp6 {
1085+
debug!(self.log, "Skipping ENR update"; "multiaddr" => ?addr);
1086+
return;
1087+
}
1088+
1089+
self.update_enr_tcp_port(port)
1090+
}
1091+
(Some(Protocol::Udp(port)), Some(Protocol::QuicV1)) => {
1092+
if !self.update_ports.quic6 {
1093+
debug!(self.log, "Skipping ENR update"; "multiaddr" => ?addr);
1094+
return;
1095+
}
1096+
1097+
self.update_enr_quic_port(port)
1098+
}
1099+
_ => {
1100+
debug!(self.log, "Encountered unacceptable multiaddr for listening (unsupported transport)"; "addr" => ?addr);
1101+
return;
1102+
}
1103+
},
1104+
_ => {
1105+
debug!(self.log, "Encountered unacceptable multiaddr for listening (no IP)"; "addr" => ?addr);
1106+
return;
1107+
}
1108+
};
1109+
1110+
let local_enr: Enr = self.discv5.local_enr();
1111+
1112+
match attempt_enr_update {
1113+
Ok(_) => {
1114+
info!(self.log, "Updated local ENR"; "enr" => local_enr.to_base64(), "seq" => local_enr.seq(), "id"=> %local_enr.node_id(), "ip4" => ?local_enr.ip4(), "udp4"=> ?local_enr.udp4(), "tcp4" => ?local_enr.tcp4(), "tcp6" => ?local_enr.tcp6(), "udp6" => ?local_enr.udp6())
1115+
}
1116+
Err(e) => warn!(self.log, "Failed to update ENR"; "error" => ?e),
1117+
}
1118+
}
10391119
FromSwarm::ConnectionEstablished(_)
10401120
| FromSwarm::ConnectionClosed(_)
10411121
| FromSwarm::AddressChange(_)
10421122
| FromSwarm::ListenFailure(_)
10431123
| FromSwarm::NewListener(_)
1044-
| FromSwarm::NewListenAddr(_)
10451124
| FromSwarm::ExpiredListenAddr(_)
10461125
| FromSwarm::ListenerError(_)
10471126
| FromSwarm::ListenerClosed(_)

0 commit comments

Comments
 (0)