aboutsummaryrefslogtreecommitdiffstats
path: root/src/transport
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-01 13:20:08 +0100
committertv <tv@krebsco.de>2026-11-01 13:20:08 +0100
commit2ec7d7e0eedf504035417bebcace68f22f38ba10 (patch)
tree65b1b4c6273bc0af4472e9fd0a772e0a7db862ea /src/transport
parent59833811cce25f03efbdc889f806ad75804942ab (diff)
libp2p: revise published address count/selection
Diffstat (limited to 'src/transport')
-rw-r--r--src/transport/identity.rs5
-rw-r--r--src/transport/libp2p/book.rs4
-rw-r--r--src/transport/libp2p/mod.rs15
-rw-r--r--src/transport/paths.rs21
4 files changed, 34 insertions, 11 deletions
diff --git a/src/transport/identity.rs b/src/transport/identity.rs
index a748505..fb1600b 100644
--- a/src/transport/identity.rs
+++ b/src/transport/identity.rs
@@ -58,8 +58,9 @@ const ASK_INTERVAL: Duration = Duration::from_secs(5);
const OTHER_PATHS_ASK_INTERVAL: Duration = Duration::from_secs(60);
/// How long resolving a seed waits for its ME.
const RESOLVE_TIMEOUT: Duration = Duration::from_secs(10);
-/// Addresses kept per node from hints: about one per transport.
-const MAX_HINTS: usize = 8;
+/// Addresses kept per node from hints: as many as a member lists
+/// (`members::MAX_ADDRESSES`).
+const MAX_HINTS: usize = 16;
/// Addresses with a proven node, nodes with hints, and addresses asked, each at most:
/// anyone can send us proofs (keys are free), so the books are bounded.
const MAX_ENTRIES: usize = 4096;
diff --git a/src/transport/libp2p/book.rs b/src/transport/libp2p/book.rs
index b2ce7bb..02a6b49 100644
--- a/src/transport/libp2p/book.rs
+++ b/src/transport/libp2p/book.rs
@@ -267,8 +267,8 @@ impl Book {
let address = without_peer(address.clone());
(!address.is_empty() && !is_relayed(&address)).then_some(address)
});
- // First: the member list keeps only so many (`members::MAX_ADDRESSES`), and a
- // node listening everywhere has many.
+ // First: only so many are published (`PUBLISHED_DIRECT`), and a node listening
+ // everywhere has many.
let mut first: Vec<Multiaddr> = Vec::new();
for address in self.mapped.iter().cloned().chain(confirmed) {
if !first.contains(&address) {
diff --git a/src/transport/libp2p/mod.rs b/src/transport/libp2p/mod.rs
index 6032891..2ad07e5 100644
--- a/src/transport/libp2p/mod.rs
+++ b/src/transport/libp2p/mod.rs
@@ -145,6 +145,11 @@ const MIN_RATE: u64 = 1 << 20;
const READS: usize = 32;
/// Addresses kept per peer, and peers with addresses at most.
const ADDRESSES_PER_PEER: usize = 8;
+/// Of this node's own, the direct ones (the best first) and those through relays it
+/// publishes at most (`local_addresses`): a node listening everywhere has many direct
+/// ones, and those through a relay are what reaches it from behind a NAT.
+const PUBLISHED_DIRECT: usize = 4;
+const PUBLISHED_RELAYED: usize = 2;
const MAX_PEERS: usize = 4096;
/// A relayed connection (circuit) through this node lasts at most this long and carries
@@ -363,20 +368,24 @@ impl Transport for Libp2pTransport {
}
/// Where we can be reached, each with our peer ID: the announced addresses, or else
- /// those we listen on (`published`), and those through relays. A relay adds each
- /// direct one again, ending in `/p2p-circuit`: where to reserve a slot.
+ /// those we listen on (`published`), and those through relays; at most
+ /// `PUBLISHED_DIRECT` and `PUBLISHED_RELAYED` of them, so the direct ones never
+ /// crowd out the relayed ones. A relay adds each direct one again, ending in
+ /// `/p2p-circuit`: where to reserve a slot.
fn local_addresses(&self) -> Vec<String> {
let book = lock(&self.book);
let direct: Vec<Multiaddr> = book
.direct()
.into_iter()
.filter_map(|address| address.with_p2p(self.peer_id).ok())
+ .take(PUBLISHED_DIRECT)
.collect();
let relayed = book
.listening
.iter()
.filter(|address| is_relayed(address))
- .filter_map(|address| address.clone().with_p2p(self.peer_id).ok());
+ .filter_map(|address| address.clone().with_p2p(self.peer_id).ok())
+ .take(PUBLISHED_RELAYED);
let offers: Vec<Multiaddr> = if book.serving {
direct
.iter()
diff --git a/src/transport/paths.rs b/src/transport/paths.rs
index 658f681..ce19fd4 100644
--- a/src/transport/paths.rs
+++ b/src/transport/paths.rs
@@ -620,17 +620,30 @@ impl Paths {
.unwrap_or_default()
}
- /// Each transport's (`Transport::local_addresses`), with its scheme.
+ /// Each transport's (`Transport::local_addresses`), with its scheme: taken in turns,
+ /// each transport's first in the configured order, then each one's second, and so on,
+ /// so a list cut short (`members::MAX_ADDRESSES`) still has every transport's best.
pub(crate) fn local_addresses(&self) -> Vec<String> {
- self.links
+ let mut each: Vec<std::vec::IntoIter<String>> = self
+ .links
.iter()
- .flat_map(|link| {
+ .map(|link| {
link.inner
.local_addresses()
.into_iter()
.map(|target| link.address(&target))
+ .collect::<Vec<_>>()
+ .into_iter()
})
- .collect()
+ .collect();
+ let mut addresses = Vec::new();
+ loop {
+ let before = addresses.len();
+ addresses.extend(each.iter_mut().filter_map(Iterator::next));
+ if addresses.len() == before {
+ return addresses;
+ }
+ }
}
/// The schemes of the transports, in order of preference.