feat(swarm): replace address scoring with explicit candidates

Previously, a `NetworkBehaviour` could report an `AddressScore` for an external address. This score was a `u32` and addresses would be ranked amongst those.

In reality, an address is either confirmed to be publicly reachable (via a protocol such as AutoNAT) or merely represents a candidate that might be an external address. In a way, addresses are guilty (private) until proven innocent (publicly reachable).

When a `NetworkBehaviour` reports an address candidate, we perform address translation on it to potentially correct for ephemeral ports of TCP. These candidates are then injected back into the `NetworkBehaviour`. Protocols such as AutoNAT can use these addresses as a source for probing their NAT status. Once confirmed, they can emit a `ToSwarm::ExternalAddrConfirmed` event which again will be passed to all `NetworkBehaviour`s.

This simplified approach will allow us implement Kademlia's client-mode (https://github.com/libp2p/rust-libp2p/issues/2032) without additional configuration options: As soon as an address is reported as publicly reachable, we can activate server-mode for that connection.

Related: https://github.com/libp2p/rust-libp2p/pull/3877.
Related: https://github.com/libp2p/rust-libp2p/issues/3953.
Related: https://github.com/libp2p/rust-libp2p/issues/2032.
Related: https://github.com/libp2p/go-libp2p/issues/2229.

Co-authored-by: Max Inden <mail@max-inden.de>

Pull-Request: #3954.
This commit is contained in:
Thomas Eizinger
2023-05-24 09:52:16 +02:00
committed by GitHub
parent a424310d60
commit 5e8f2e82e4
32 changed files with 273 additions and 822 deletions

View File

@ -29,8 +29,7 @@ use libp2p_identity::PeerId;
use libp2p_plaintext::PlainText2Config;
use libp2p_swarm::dial_opts::PeerCondition;
use libp2p_swarm::{
dial_opts::DialOpts, AddressScore, NetworkBehaviour, Swarm, SwarmBuilder, SwarmEvent,
THandlerErr,
dial_opts::DialOpts, NetworkBehaviour, Swarm, SwarmBuilder, SwarmEvent, THandlerErr,
};
use libp2p_yamux as yamux;
use std::fmt::Debug;
@ -228,11 +227,7 @@ where
T: NetworkBehaviour + Send,
<T as NetworkBehaviour>::ToSwarm: Debug,
{
let external_addresses = other
.external_addresses()
.cloned()
.map(|r| r.addr)
.collect();
let external_addresses = other.external_addresses().cloned().collect();
let dial_opts = DialOpts::peer_id(*other.local_peer_id())
.addresses(external_addresses)
@ -315,7 +310,7 @@ where
.await;
// Memory addresses are externally reachable because they all share the same memory-space.
self.add_external_address(memory_multiaddr.clone(), AddressScore::Infinite);
self.add_external_address(memory_multiaddr.clone());
let tcp_addr_listener_id = self
.listen_on("/ip4/0.0.0.0/tcp/0".parse().unwrap())