Skip to content

Commit e9af82f

Browse files
authored
Merge pull request #2242 from subspace/autonat-wrapper
Autonat and Kademlia settings updates.
2 parents 21b1c75 + 9e5f337 commit e9af82f

File tree

5 files changed

+220
-50
lines changed

5 files changed

+220
-50
lines changed

crates/subspace-networking/src/behavior.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ pub(crate) mod persistent_parameters;
22
#[cfg(test)]
33
mod tests;
44

5+
use crate::protocols::autonat_wrapper::{
6+
Behaviour as AutonatWrapper, Config as AutonatWrapperConfig,
7+
};
58
use crate::protocols::connected_peers::{
69
Behaviour as ConnectedPeersBehaviour, Config as ConnectedPeersConfig,
710
Event as ConnectedPeersEvent,
@@ -19,7 +22,7 @@ use crate::protocols::subspace_connection_limits::Behaviour as ConnectionLimitsB
1922
use crate::PeerInfoProvider;
2023
use derive_more::From;
2124
use libp2p::allow_block_list::{Behaviour as AllowBlockListBehaviour, BlockedPeers};
22-
use libp2p::autonat::{Behaviour as Autonat, Config as AutonatConfig, Event as AutonatEvent};
25+
use libp2p::autonat::Event as AutonatEvent;
2326
use libp2p::connection_limits::ConnectionLimits;
2427
use libp2p::gossipsub::{
2528
Behaviour as Gossipsub, Config as GossipsubConfig, Event as GossipsubEvent, MessageAuthenticity,
@@ -59,8 +62,8 @@ pub(crate) struct BehaviorConfig<RecordStore> {
5962
pub(crate) general_connected_peers_config: Option<ConnectedPeersConfig>,
6063
/// The configuration for the [`ConnectedPeers`] protocol (special instance).
6164
pub(crate) special_connected_peers_config: Option<ConnectedPeersConfig>,
62-
/// Autonat configuration (optional).
63-
pub(crate) autonat: Option<AutonatConfig>,
65+
/// Autonat configuration.
66+
pub(crate) autonat: AutonatWrapperConfig,
6467
}
6568

6669
#[derive(Debug, Clone, Copy)]
@@ -85,7 +88,7 @@ pub(crate) struct Behavior<RecordStore> {
8588
Toggle<ConnectedPeersBehaviour<GeneralConnectedPeersInstance>>,
8689
pub(crate) special_connected_peers:
8790
Toggle<ConnectedPeersBehaviour<SpecialConnectedPeersInstance>>,
88-
pub(crate) autonat: Toggle<Autonat>,
91+
pub(crate) autonat: AutonatWrapper,
8992
}
9093

9194
impl<RecordStore> Behavior<RecordStore>
@@ -137,10 +140,7 @@ where
137140
.special_connected_peers_config
138141
.map(ConnectedPeersBehaviour::new)
139142
.into(),
140-
autonat: config
141-
.autonat
142-
.map(|autonat_config| Autonat::new(config.peer_id, autonat_config))
143-
.into(),
143+
autonat: AutonatWrapper::new(config.autonat),
144144
}
145145
}
146146
}

crates/subspace-networking/src/constructor.rs

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::constructor::temporary_bans::TemporaryBans;
99
use crate::constructor::transport::build_transport;
1010
use crate::node::Node;
1111
use crate::node_runner::{NodeRunner, NodeRunnerConfig};
12+
use crate::protocols::autonat_wrapper::Config as AutonatWrapperConfig;
1213
use crate::protocols::connected_peers::Config as ConnectedPeersConfig;
1314
use crate::protocols::peer_info::PeerInfoProvider;
1415
use crate::protocols::request_response::request_response_factory::RequestHandler;
@@ -99,6 +100,8 @@ const YAMUX_BUFFER_SIZE: usize = Piece::SIZE + 1024 * 1024;
99100

100101
/// Max confidence for autonat protocol. Could affect Kademlia mode change.
101102
pub(crate) const AUTONAT_MAX_CONFIDENCE: usize = 3;
103+
/// We set a very long pause before autonat initialization (Duration::Max panics).
104+
const AUTONAT_SERVER_PROBE_DELAY: Duration = Duration::from_secs(3600 * 24 * 365);
102105

103106
/// Defines Kademlia mode
104107
#[derive(Clone, Debug)]
@@ -481,8 +484,18 @@ where
481484

482485
debug!(?connection_limits, "DSN connection limits set.");
483486

484-
let enable_autonat = external_addresses.is_empty() && kademlia_mode.is_dynamic();
485-
debug!(%enable_autonat, ?external_addresses, ?kademlia_mode, "Autonat settings.");
487+
let autonat_boot_delay = if kademlia_mode.is_static() || !external_addresses.is_empty() {
488+
AUTONAT_SERVER_PROBE_DELAY
489+
} else {
490+
AutonatConfig::default().boot_delay
491+
};
492+
493+
debug!(
494+
?autonat_boot_delay,
495+
?kademlia_mode,
496+
?external_addresses,
497+
"Autonat boot delay set."
498+
);
486499

487500
let mut behaviour = Behavior::new(BehaviorConfig {
488501
peer_id: local_peer_id,
@@ -516,12 +529,16 @@ where
516529
..ConnectedPeersConfig::default()
517530
}
518531
}),
519-
autonat: enable_autonat.then(|| AutonatConfig {
520-
use_connected: true,
521-
only_global_ips: !config.allow_non_global_addresses_in_dht,
522-
confidence_max: AUTONAT_MAX_CONFIDENCE,
523-
..Default::default()
524-
}),
532+
autonat: AutonatWrapperConfig {
533+
inner_config: AutonatConfig {
534+
use_connected: true,
535+
only_global_ips: !config.allow_non_global_addresses_in_dht,
536+
confidence_max: AUTONAT_MAX_CONFIDENCE,
537+
boot_delay: autonat_boot_delay,
538+
..Default::default()
539+
},
540+
local_peer_id,
541+
},
525542
});
526543

527544
match (kademlia_mode, external_addresses.is_empty()) {

crates/subspace-networking/src/node_runner.rs

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -733,22 +733,35 @@ where
733733
});
734734

735735
if full_kademlia_support {
736-
let old_addresses = kademlia
737-
.kbucket(peer_id)
738-
.and_then(|peers| {
739-
let key = peer_id.into();
740-
peers.iter().find_map(|peer| {
741-
(peer.node.key == &key).then_some(
742-
peer.node
743-
.value
744-
.iter()
745-
.filter(|address| info.listen_addrs.contains(address))
746-
.cloned()
747-
.collect::<Vec<_>>(),
748-
)
749-
})
750-
})
751-
.unwrap_or_default();
736+
//TODO: Consider restoring obsolete address removal
737+
// let old_addresses = kademlia
738+
// .kbucket(peer_id)
739+
// .and_then(|peers| {
740+
// let key = peer_id.into();
741+
// peers.iter().find_map(|peer| {
742+
// (peer.node.key == &key).then_some(
743+
// peer.node
744+
// .value
745+
// .iter()
746+
// .filter(|address| info.listen_addrs.contains(address))
747+
// .cloned()
748+
// .collect::<Vec<_>>(),
749+
// )
750+
// })
751+
// })
752+
// .unwrap_or_default();
753+
754+
// for old_address in old_addresses {
755+
// trace!(
756+
// %local_peer_id,
757+
// %peer_id,
758+
// %old_address,
759+
// "Removing old self-reported address from Kademlia DHT",
760+
// );
761+
//
762+
// kademlia.remove_address(&peer_id, &old_address);
763+
// }
764+
752765
for address in info.listen_addrs {
753766
if !self.allow_non_global_addresses_in_dht
754767
&& !is_global_address_or_dns(&address)
@@ -762,7 +775,7 @@ where
762775
continue;
763776
}
764777

765-
trace!(
778+
debug!(
766779
%local_peer_id,
767780
%peer_id,
768781
%address,
@@ -772,16 +785,6 @@ where
772785

773786
kademlia.add_address(&peer_id, address);
774787
}
775-
for old_address in old_addresses {
776-
trace!(
777-
%local_peer_id,
778-
%peer_id,
779-
%old_address,
780-
"Removing old self-reported address from Kademlia DHT",
781-
);
782-
783-
kademlia.remove_address(&peer_id, &old_address);
784-
}
785788
} else {
786789
debug!(
787790
%local_peer_id,
@@ -1190,13 +1193,12 @@ where
11901193

11911194
async fn handle_autonat_event(&mut self, event: AutonatEvent) {
11921195
trace!(?event, "Autonat event received.");
1193-
if let Some(autonat) = self.swarm.behaviour().autonat.as_ref() {
1194-
debug!(
1195-
public_address=?autonat.public_address(),
1196-
confidence=%autonat.confidence(),
1197-
"Current public address confidence."
1198-
);
1199-
}
1196+
let autonat = &self.swarm.behaviour().autonat;
1197+
debug!(
1198+
public_address=?autonat.public_address(),
1199+
confidence=%autonat.confidence(),
1200+
"Current public address confidence."
1201+
);
12001202

12011203
match event {
12021204
AutonatEvent::InboundProbe(_inbound_probe_event) => {

crates/subspace-networking/src/protocols.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
pub(crate) mod autonat_wrapper;
12
pub(crate) mod connected_peers;
23
pub mod peer_info;
34
pub mod request_response;
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
use crate::utils::is_global_address_or_dns;
2+
use libp2p::autonat::{Behaviour as Autonat, Config as AutonatConfig, Event as AutonatEvent};
3+
use libp2p::core::Endpoint;
4+
use libp2p::multiaddr::Protocol;
5+
use libp2p::swarm::{
6+
ConnectionDenied, ConnectionId, FromSwarm, NetworkBehaviour, THandler, THandlerInEvent,
7+
THandlerOutEvent, ToSwarm,
8+
};
9+
use libp2p::{Multiaddr, PeerId};
10+
use std::collections::HashSet;
11+
use std::task::{Context, Poll};
12+
use tracing::debug;
13+
14+
pub(crate) struct Config {
15+
pub(crate) inner_config: AutonatConfig,
16+
pub(crate) local_peer_id: PeerId,
17+
}
18+
19+
pub(crate) struct Behaviour {
20+
inner: Autonat,
21+
config: Config,
22+
listen_addresses: HashSet<Multiaddr>,
23+
}
24+
25+
impl Behaviour {
26+
pub(crate) fn new(config: Config) -> Self {
27+
Self {
28+
inner: Autonat::new(config.local_peer_id, config.inner_config.clone()),
29+
config,
30+
listen_addresses: Default::default(),
31+
}
32+
}
33+
34+
fn private_ips_enabled(&self) -> bool {
35+
!self.config.inner_config.only_global_ips
36+
}
37+
38+
fn address_corresponds_to_listening_addresses(&self, addr: &Multiaddr) -> bool {
39+
let candidate_protocol = addr
40+
.iter()
41+
.find_map(|protocol| match protocol {
42+
udp @ Protocol::Udp(_) => Some(udp),
43+
tcp @ Protocol::Tcp(_) => Some(tcp),
44+
_ => None,
45+
})
46+
.expect("Either TCP or UDP protocol should be enabled.");
47+
48+
let address_result = self
49+
.listen_addresses
50+
.iter()
51+
.any(|addr| addr.iter().any(|protocol| protocol == candidate_protocol));
52+
53+
debug!(
54+
%address_result,
55+
?addr,
56+
listen_addresses=?self.listen_addresses,
57+
"Address candidate corresponds to listening addresses."
58+
);
59+
60+
address_result
61+
}
62+
63+
pub(crate) fn public_address(&self) -> Option<&Multiaddr> {
64+
self.inner.public_address()
65+
}
66+
67+
pub(crate) fn confidence(&self) -> usize {
68+
self.inner.confidence()
69+
}
70+
}
71+
72+
impl NetworkBehaviour for Behaviour {
73+
type ConnectionHandler = <Autonat as NetworkBehaviour>::ConnectionHandler;
74+
type ToSwarm = AutonatEvent;
75+
76+
fn handle_established_inbound_connection(
77+
&mut self,
78+
connection_id: ConnectionId,
79+
peer: PeerId,
80+
local_addr: &Multiaddr,
81+
remote_addr: &Multiaddr,
82+
) -> Result<THandler<Self>, ConnectionDenied> {
83+
self.inner.handle_established_inbound_connection(
84+
connection_id,
85+
peer,
86+
local_addr,
87+
remote_addr,
88+
)
89+
}
90+
91+
fn handle_established_outbound_connection(
92+
&mut self,
93+
connection_id: ConnectionId,
94+
peer: PeerId,
95+
addr: &Multiaddr,
96+
role_override: Endpoint,
97+
) -> Result<THandler<Self>, ConnectionDenied> {
98+
self.inner
99+
.handle_established_outbound_connection(connection_id, peer, addr, role_override)
100+
}
101+
102+
fn on_swarm_event(&mut self, event: FromSwarm) {
103+
match event {
104+
new_listen_addr_event @ FromSwarm::NewListenAddr(_) => {
105+
if let FromSwarm::NewListenAddr(addr) = new_listen_addr_event {
106+
//TODO: handle listener address change
107+
self.listen_addresses.insert(addr.addr.clone());
108+
109+
if self.private_ips_enabled() || is_global_address_or_dns(addr.addr) {
110+
self.inner.on_swarm_event(new_listen_addr_event);
111+
} else {
112+
debug!(addr=?addr.addr, "Skipped listening address in AutonatWrapper.");
113+
}
114+
}
115+
}
116+
new_external_addr_event @ FromSwarm::NewExternalAddrCandidate(_) => {
117+
if let FromSwarm::NewExternalAddrCandidate(addr) = new_external_addr_event {
118+
if self.address_corresponds_to_listening_addresses(addr.addr) {
119+
self.inner.on_swarm_event(new_external_addr_event);
120+
} else {
121+
debug!(
122+
addr=?addr.addr,
123+
"Skipped external address candidate in AutonatWrapper."
124+
);
125+
}
126+
}
127+
}
128+
event => {
129+
self.inner.on_swarm_event(event);
130+
}
131+
}
132+
}
133+
134+
fn on_connection_handler_event(
135+
&mut self,
136+
peer_id: PeerId,
137+
connection_id: ConnectionId,
138+
event: THandlerOutEvent<Self>,
139+
) {
140+
self.inner
141+
.on_connection_handler_event(peer_id, connection_id, event)
142+
}
143+
144+
fn poll(
145+
&mut self,
146+
cx: &mut Context<'_>,
147+
) -> Poll<ToSwarm<Self::ToSwarm, THandlerInEvent<Self>>> {
148+
self.inner.poll(cx)
149+
}
150+
}

0 commit comments

Comments
 (0)