Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(swarm): improve PeerAddresses configurability #5574

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions protocols/identify/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

- Make `identify::Config` fields private and add getter functions.
See [PR 5663](https://github.com/libp2p/rust-libp2p/pull/5663).
- 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.45.1

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 @@ -28,13 +28,12 @@ use libp2p_identity::PublicKey;
use libp2p_swarm::behaviour::{ConnectionClosed, ConnectionEstablished, DialFailure, FromSwarm};
use libp2p_swarm::{
ConnectionDenied, DialError, ExternalAddresses, ListenAddresses, NetworkBehaviour,
NotifyHandler, PeerAddresses, StreamUpgradeError, THandlerInEvent, ToSwarm,
_address_translation,
NotifyHandler, PeerAddresses, PeerAddressesConfig, StreamUpgradeError, THandlerInEvent,
ToSwarm, _address_translation,
};
use libp2p_swarm::{ConnectionId, THandler, THandlerOutEvent};

use std::collections::hash_map::Entry;
use std::num::NonZeroUsize;
use std::{
collections::{HashMap, HashSet, VecDeque},
task::Context,
Expand Down Expand Up @@ -142,11 +141,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.
///
/// Disabled by default.
cache_size: usize,
/// Configuration for the LRU cache of discovered peers.
cache_config: Option<PeerAddressesConfig>,

/// Whether to include our listen addresses in our responses. If enabled,
/// we will effectively only share our external addresses.
Expand All @@ -165,7 +161,7 @@ impl Config {
local_public_key,
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 @@ -191,9 +187,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 @@ -228,9 +226,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 @@ -242,10 +240,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 @@ -650,12 +645,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,9 +1,10 @@
use futures::StreamExt;
use libp2p_identify as identify;
use libp2p_swarm::{Swarm, SwarmEvent};
use libp2p_swarm::{PeerAddressesConfig, Swarm, SwarmEvent};
use libp2p_swarm_test::SwarmExt;
use std::collections::HashSet;
use std::iter;
use std::num::NonZeroUsize;
use std::time::{Duration, Instant};
use tracing_subscriber::EnvFilter;

Expand Down Expand Up @@ -161,7 +162,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(|identity| {
Expand Down Expand Up @@ -233,7 +237,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(|identity| {
Expand Down
2 changes: 2 additions & 0 deletions swarm/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

- Don't report `NewExternalAddrCandidate` for confirmed external addresses.
See [PR 5582](https://github.com/libp2p/rust-libp2p/pull/5582).
- 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.45.1

Expand Down
2 changes: 1 addition & 1 deletion swarm/src/behaviour.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub mod toggle;

pub use external_addresses::ExternalAddresses;
pub use listen_addresses::ListenAddresses;
pub use peer_addresses::PeerAddresses;
pub use peer_addresses::{PeerAddresses, PeerAddressesConfig};

use crate::connection::ConnectionId;
use crate::dial_opts::DialOpts;
Expand Down
60 changes: 50 additions & 10 deletions swarm/src/behaviour/peer_addresses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,56 @@ use lru::LruCache;

use std::num::NonZeroUsize;

#[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.
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.
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"),
dariusc93 marked this conversation as resolved.
Show resolved Hide resolved
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))
/// 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);
Self { config, inner }
}

/// Feed a [`FromSwarm`] event to this struct.
Expand Down Expand Up @@ -50,12 +90,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.put(address, ()).is_none()
} else {
let mut set = LruCache::new(NonZeroUsize::new(10).expect("10 > 0"));
let mut set = LruCache::new(self.config.number_of_addresses_per_peer);
set.put(address, ());
self.0.put(peer, set);
self.inner.put(peer, set);

true
}
Expand All @@ -66,7 +106,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 @@ -76,7 +116,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.pop(&address).is_some(),
Err(_) => false,
Expand All @@ -92,7 +132,7 @@ fn prepare_addr(peer: &PeerId, addr: &Multiaddr) -> Result<Multiaddr, Multiaddr>

impl Default for PeerAddresses {
fn default() -> Self {
Self(LruCache::new(NonZeroUsize::new(100).unwrap()))
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 @@ -111,7 +111,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;
pub use connection::{ConnectionError, ConnectionId, SupportedProtocols};
Expand Down