Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
e5435fc
feat(swarm): improve `PeerAddresses` configurability
stormshield-frb Aug 28, 2024
3baf1ec
trigger GitHub actions
stormshield-frb Aug 29, 2024
f610b78
Merge branch 'master' into feat/identify-make-peer-cache-configurable
stormshield-frb Sep 6, 2024
7ddd854
deprecate with_cache_size instead of removing it
stormshield-frb Sep 6, 2024
4d17c21
slight changes to changelog messages
stormshield-frb Sep 6, 2024
457c063
don't make PeerAddressesConfig attributes public
stormshield-frb Sep 6, 2024
6521a7f
fix semver checks
stormshield-frb Sep 6, 2024
bad6c29
Uniformed rust doc
stormshield-frb Sep 6, 2024
187f010
ensure caching can be disabled
stormshield-frb Sep 6, 2024
ad15d3f
Merge branch 'master' into feat/identify-make-peer-cache-configurable
dariusc93 Sep 25, 2024
b4754f9
Merge branch 'master' into feat/identify-make-peer-cache-configurable
stormshield-frb Oct 18, 2024
38a9c5c
Merge branch 'master' into feat/identify-make-peer-cache-configurable
dariusc93 Oct 31, 2024
a550d6f
Merge branch 'master' into feat/identify-make-peer-cache-configurable
stormshield-frb Nov 15, 2024
1035649
removing deprecations
stormshield-frb Nov 15, 2024
3e66c4f
remove unneeded allow deprecated
stormshield-frb Nov 15, 2024
8221904
update changelog
stormshield-frb Nov 15, 2024
914662d
rename with_number_of_addresses_by(per)_peer
stormshield-frb Nov 15, 2024
31ab1fb
fix typo
stormshield-frb Nov 15, 2024
312a1f2
Merge branch 'master' into feat/identify-make-peer-cache-configurable
stormshield-frb Sep 3, 2025
3afca6e
fix clippy
stormshield-frb Sep 3, 2025
632feee
post merge fixes
stormshield-frb Sep 3, 2025
d28be0c
Merge branch 'master' into feat/identify-make-peer-cache-configurable
elenaf9 Oct 21, 2025
29b2b24
swarm/peer_addresses: document default config values
elenaf9 Oct 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ libp2p-dcutr = { version = "0.14.0", path = "protocols/dcutr" }
libp2p-dns = { version = "0.44.0", path = "transports/dns" }
libp2p-floodsub = { version = "0.47.0", path = "protocols/floodsub" }
libp2p-gossipsub = { version = "0.50.0", path = "protocols/gossipsub" }
libp2p-identify = { version = "0.47.0", path = "protocols/identify" }
libp2p-identify = { version = "0.48.0", path = "protocols/identify" }
libp2p-identity = { version = "0.2.12" }
libp2p-kad = { version = "0.49.0", path = "protocols/kad" }
libp2p-mdns = { version = "0.48.0", path = "protocols/mdns" }
Expand All @@ -102,7 +102,7 @@ libp2p-rendezvous = { version = "0.17.0", path = "protocols/rendezvous" }
libp2p-request-response = { version = "0.29.0", path = "protocols/request-response" }
libp2p-server = { version = "0.12.7", path = "misc/server" }
libp2p-stream = { version = "0.4.0-alpha", path = "protocols/stream" }
libp2p-swarm = { version = "0.47.0", path = "swarm" }
libp2p-swarm = { version = "0.47.1", path = "swarm" }
libp2p-swarm-derive = { version = "=0.35.1", path = "swarm-derive" } # `libp2p-swarm-derive` may not be compatible with different `libp2p-swarm` non-breaking releases. E.g. `libp2p-swarm` might introduce a new enum variant `FromSwarm` (which is `#[non-exhaustive]`) in a non-breaking release. Older versions of `libp2p-swarm-derive` would not forward this enum variant within the `NetworkBehaviour` hierarchy. Thus the version pinning is required.
libp2p-swarm-test = { version = "0.6.0", path = "swarm-test" }
libp2p-tcp = { version = "0.44.0", path = "transports/tcp" }
Expand Down
5 changes: 5 additions & 0 deletions protocols/identify/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 0.48.0

- Replace `with_cache_size` by `with_cache_config` to fully configure the identify cache using `PeerAddressesConfig`.
See [PR 5574](https://github.com/libp2p/rust-libp2p/pull/5574).

## 0.47.0

- Implement optional `signedPeerRecord` support for identify messages.
Expand Down
2 changes: 1 addition & 1 deletion protocols/identify/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "libp2p-identify"
edition.workspace = true
rust-version = { workspace = true }
description = "Nodes identification protocol for libp2p"
version = "0.47.0"
version = "0.48.0"
authors = ["Parity Technologies <[email protected]>"]
license = "MIT"
repository = "https://github.com/libp2p/rust-libp2p"
Expand Down
41 changes: 16 additions & 25 deletions protocols/identify/src/behaviour.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

use std::{
collections::{hash_map::Entry, HashMap, HashSet, VecDeque},
num::NonZeroUsize,
sync::Arc,
task::{Context, Poll},
time::Duration,
Expand All @@ -35,8 +34,8 @@ use libp2p_identity::{Keypair, PeerId, PublicKey};
use libp2p_swarm::{
behaviour::{ConnectionClosed, ConnectionEstablished, DialFailure, FromSwarm},
ConnectionDenied, ConnectionId, DialError, ExternalAddresses, ListenAddresses,
NetworkBehaviour, NotifyHandler, PeerAddresses, StreamUpgradeError, THandler, THandlerInEvent,
THandlerOutEvent, ToSwarm, _address_translation,
NetworkBehaviour, NotifyHandler, PeerAddresses, PeerAddressesConfig, StreamUpgradeError,
THandler, THandlerInEvent, THandlerOutEvent, ToSwarm, _address_translation,
};

use crate::{
Expand Down Expand Up @@ -145,11 +144,8 @@ pub struct Config {
/// Disabled by default.
push_listen_addr_updates: bool,

/// How many entries of discovered peers to keep before we discard
/// the least-recently used one.
///
/// Defaults to 100
cache_size: usize,
/// Configuration for the LRU cache of discovered peers.
cache_config: Option<PeerAddressesConfig>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this required to be optional?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's None the cache is disabled. Before, cache size 0 was used for that.


/// Whether to include our listen addresses in our responses. If enabled,
/// we will effectively only share our external addresses.
Expand Down Expand Up @@ -182,7 +178,7 @@ impl Config {
local_key: Arc::new(key.into()),
interval: Duration::from_secs(5 * 60),
push_listen_addr_updates: false,
cache_size: 100,
cache_config: Some(Default::default()),
hide_listen_addrs: false,
}
}
Expand All @@ -208,9 +204,11 @@ impl Config {
self
}

/// Configures the size of the LRU cache, caching addresses of discovered peers.
pub fn with_cache_size(mut self, cache_size: usize) -> Self {
self.cache_size = cache_size;
/// Configures the LRU cache responsible for caching addresses of discovered peers.
///
/// If set to [`None`], caching is disabled.
pub fn with_cache_config(mut self, cache_config: Option<PeerAddressesConfig>) -> Self {
self.cache_config = cache_config;
self
}

Expand Down Expand Up @@ -245,9 +243,9 @@ impl Config {
self.push_listen_addr_updates
}

/// Get the cache size of the Config.
pub fn cache_size(&self) -> usize {
self.cache_size
/// Get the config of the LRU cache responsible for caching addresses of discovered peers.
pub fn cache_config(&self) -> &Option<PeerAddressesConfig> {
&self.cache_config
}

/// Get the hide listen address boolean value of the Config.
Expand All @@ -259,10 +257,7 @@ impl Config {
impl Behaviour {
/// Creates a new identify [`Behaviour`].
pub fn new(config: Config) -> Self {
let discovered_peers = match NonZeroUsize::new(config.cache_size) {
None => PeerCache::disabled(),
Some(size) => PeerCache::enabled(size),
};
let discovered_peers = PeerCache::new(config.cache_config.clone());

Self {
config,
Expand Down Expand Up @@ -681,12 +676,8 @@ fn multiaddr_matches_peer_id(addr: &Multiaddr, peer_id: &PeerId) -> bool {
struct PeerCache(Option<PeerAddresses>);

impl PeerCache {
fn disabled() -> Self {
Self(None)
}

fn enabled(size: NonZeroUsize) -> Self {
Self(Some(PeerAddresses::new(size)))
fn new(cache_config: Option<PeerAddressesConfig>) -> Self {
Self(cache_config.map(PeerAddresses::new))
}

fn get(&mut self, peer: &PeerId) -> Vec<Multiaddr> {
Expand Down
13 changes: 10 additions & 3 deletions protocols/identify/tests/smoke.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
use std::{
collections::HashSet,
iter,
num::NonZeroUsize,
time::{Duration, Instant},
};

use futures::StreamExt;
use libp2p_identify as identify;
use libp2p_identity::Keypair;
use libp2p_swarm::{Swarm, SwarmEvent};
use libp2p_swarm::{PeerAddressesConfig, Swarm, SwarmEvent};
use libp2p_swarm_test::SwarmExt;
use tracing_subscriber::EnvFilter;

Expand Down Expand Up @@ -165,7 +166,10 @@ async fn emits_unique_listen_addresses() {
identify::Config::new("a".to_string(), identity.public())
.with_agent_version("b".to_string())
.with_interval(Duration::from_secs(1))
.with_cache_size(10),
.with_cache_config(Some(
PeerAddressesConfig::default()
.with_number_of_peers(NonZeroUsize::new(10).expect("10 != 0")),
)),
)
});
let mut swarm2 = Swarm::new_ephemeral_tokio(|identity| {
Expand Down Expand Up @@ -237,7 +241,10 @@ async fn hides_listen_addresses() {
identify::Config::new("a".to_string(), identity.public())
.with_agent_version("b".to_string())
.with_interval(Duration::from_secs(1))
.with_cache_size(10),
.with_cache_config(Some(
PeerAddressesConfig::default()
.with_number_of_peers(NonZeroUsize::new(10).expect("10 != 0")),
)),
)
});
let mut swarm2 = Swarm::new_ephemeral_tokio(|identity| {
Expand Down
5 changes: 5 additions & 0 deletions swarm/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 0.47.1

- Add `PeerAddressesConfig` and the possibility to configure the number of addresses cached per peer.
See [PR 5574](https://github.com/libp2p/rust-libp2p/pull/5574).

## 0.47.0

- Remove `async-std` support.
Expand Down
2 changes: 1 addition & 1 deletion swarm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "libp2p-swarm"
edition.workspace = true
rust-version = { workspace = true }
description = "The libp2p swarm"
version = "0.47.0"
version = "0.47.1"
authors = ["Parity Technologies <[email protected]>"]
license = "MIT"
repository = "https://github.com/libp2p/rust-libp2p"
Expand Down
2 changes: 1 addition & 1 deletion swarm/src/behaviour.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ use libp2p_core::{
};
use libp2p_identity::PeerId;
pub use listen_addresses::ListenAddresses;
pub use peer_addresses::PeerAddresses;
pub use peer_addresses::{PeerAddresses, PeerAddressesConfig};

use crate::{
connection::ConnectionId, dial_opts::DialOpts, listen_opts::ListenOpts, ConnectionDenied,
Expand Down
62 changes: 52 additions & 10 deletions swarm/src/behaviour/peer_addresses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,58 @@ use libp2p_identity::PeerId;

use crate::{behaviour::FromSwarm, DialError, DialFailure, NewExternalAddrOfPeer};

#[derive(Debug, Clone)]
/// Configuration of a [`PeerAddresses`] instance.
pub struct PeerAddressesConfig {
/// Capacity of the [`PeerAddresses`] cache.
number_of_peers: NonZeroUsize,

/// Maximum number of cached addresses per peer.
number_of_addresses_per_peer: NonZeroUsize,
}

impl PeerAddressesConfig {
/// Configure the capacity of the [`PeerAddresses`] cache.
/// The default capacity is 100.
pub fn with_number_of_peers(mut self, number_of_peers: NonZeroUsize) -> Self {
self.number_of_peers = number_of_peers;
self
}

/// Configure the maximum number of cached addresses per peer.
/// The default number is 10.
pub fn with_number_of_addresses_per_peer(
mut self,
number_of_addresses_per_peer: NonZeroUsize,
) -> Self {
self.number_of_addresses_per_peer = number_of_addresses_per_peer;
self
}
}

impl Default for PeerAddressesConfig {
fn default() -> Self {
Self {
number_of_peers: NonZeroUsize::new(100).expect("100 != 0"),
number_of_addresses_per_peer: NonZeroUsize::new(10).expect("10 != 0"),
}
}
}

/// Struct for tracking peers' external addresses of the [`Swarm`](crate::Swarm).
#[derive(Debug)]
pub struct PeerAddresses(LruCache<PeerId, LruCache<Multiaddr, ()>>);
pub struct PeerAddresses {
config: PeerAddressesConfig,
inner: LruCache<PeerId, LruCache<Multiaddr, ()>>,
}

impl PeerAddresses {
/// Creates a [`PeerAddresses`] cache with capacity for the given number of peers.
///
/// For each peer, we will at most store 10 addresses.
pub fn new(number_of_peers: NonZeroUsize) -> Self {
Self(LruCache::new(number_of_peers.get()))
/// For each peer, we will at most store `config.number_of_addresses_per_peer` addresses.
pub fn new(config: PeerAddressesConfig) -> Self {
let inner = LruCache::new(config.number_of_peers.get());
Self { config, inner }
Comment on lines +57 to +60
Copy link
Member

@elenaf9 elenaf9 Oct 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah sorry, I just noticed now that this is a breaking change.
Breaking changes in the swarm are quite painful, because we need to do a minor bump and release for every single behavior protocol that depends on the swarm.

We could avoid the breaking change by not adding the PeerAddressesConfig here and instead just add with_number_of_addresses_per_peer directly for PeerAddresses.
The PeerAddressesConfig could still live as CacheConfig in identity.

Wdyt? I understand that by now you might not be working on this anymore, so I can also push this change if folks agree with it. cc @jxs

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Elena, yeah agree, let's have this as a separate method.
Btw François has left Stormshield and so this account is probably not working, nonetheless I think this is a useful feature to have, I can finish this PR if you are busy

}

/// Feed a [`FromSwarm`] event to this struct.
Expand Down Expand Up @@ -47,12 +89,12 @@ impl PeerAddresses {
pub fn add(&mut self, peer: PeerId, address: Multiaddr) -> bool {
match prepare_addr(&peer, &address) {
Ok(address) => {
if let Some(cached) = self.0.get_mut(&peer) {
if let Some(cached) = self.inner.get_mut(&peer) {
cached.insert(address, ()).is_none()
} else {
let mut set = LruCache::new(10);
let mut set = LruCache::new(self.config.number_of_addresses_per_peer.get());
set.insert(address, ());
self.0.insert(peer, set);
self.inner.insert(peer, set);

true
}
Expand All @@ -63,7 +105,7 @@ impl PeerAddresses {

/// Returns peer's external addresses.
pub fn get(&mut self, peer: &PeerId) -> impl Iterator<Item = Multiaddr> + '_ {
self.0
self.inner
.get(peer)
.into_iter()
.flat_map(|c| c.iter().map(|(m, ())| m))
Expand All @@ -73,7 +115,7 @@ impl PeerAddresses {
/// Removes address from peer addresses cache.
/// Returns true if the address was removed.
pub fn remove(&mut self, peer: &PeerId, address: &Multiaddr) -> bool {
match self.0.get_mut(peer) {
match self.inner.get_mut(peer) {
Some(addrs) => match prepare_addr(peer, address) {
Ok(address) => addrs.remove(&address).is_some(),
Err(_) => false,
Expand All @@ -89,7 +131,7 @@ fn prepare_addr(peer: &PeerId, addr: &Multiaddr) -> Result<Multiaddr, Multiaddr>

impl Default for PeerAddresses {
fn default() -> Self {
Self(LruCache::new(100))
Self::new(Default::default())
}
}

Expand Down
3 changes: 2 additions & 1 deletion swarm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ pub use behaviour::{
AddressChange, CloseConnection, ConnectionClosed, DialFailure, ExpiredListenAddr,
ExternalAddrExpired, ExternalAddresses, FromSwarm, ListenAddresses, ListenFailure,
ListenerClosed, ListenerError, NetworkBehaviour, NewExternalAddrCandidate,
NewExternalAddrOfPeer, NewListenAddr, NotifyHandler, PeerAddresses, ToSwarm,
NewExternalAddrOfPeer, NewListenAddr, NotifyHandler, PeerAddresses, PeerAddressesConfig,
ToSwarm,
};
pub use connection::{pool::ConnectionCounters, ConnectionError, ConnectionId, SupportedProtocols};
use connection::{
Expand Down