From 102694791b22b8a45a0249fdbbf13597485398ac Mon Sep 17 00:00:00 2001 From: StemCll Date: Tue, 28 Nov 2023 19:21:04 +0100 Subject: [PATCH 01/23] swarm: Add NewExternalAddrOfPeer --- Cargo.lock | 2 +- Cargo.toml | 8 ++++++-- swarm-derive/CHANGELOG.md | 5 +++++ swarm-derive/Cargo.toml | 10 ++++++++-- swarm/CHANGELOG.md | 5 +++++ swarm/src/behaviour.rs | 18 ++++++++++++++++++ swarm/src/lib.rs | 12 ++++++++++-- 7 files changed, 53 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6247efa643e..8c818de4a9f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3280,7 +3280,7 @@ dependencies = [ [[package]] name = "libp2p-swarm-derive" -version = "0.34.2" +version = "0.35.0" dependencies = [ "heck", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index d10ed7e3bbf..c0f97b006a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -100,7 +100,7 @@ libp2p-rendezvous = { version = "0.14.0", path = "protocols/rendezvous" } libp2p-request-response = { version = "0.26.1", path = "protocols/request-response" } libp2p-server = { version = "0.12.5", path = "misc/server" } libp2p-swarm = { version = "0.44.1", path = "swarm" } -libp2p-swarm-derive = { version = "=0.34.2", 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-derive = { version = "=0.35.0", 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.3.0", path = "swarm-test" } libp2p-tcp = { version = "0.41.0", path = "transports/tcp" } libp2p-tls = { version = "0.3.0", path = "transports/tls" } @@ -141,4 +141,8 @@ clippy.manual_let_else = "warn" clippy.dbg_macro = "warn" [workspace.metadata.release] -pre-release-hook = ["/bin/sh", '-c', '/bin/sh $WORKSPACE_ROOT/scripts/add-changelog-header.sh'] # Nested use of shell to expand variables. +pre-release-hook = [ + "/bin/sh", + '-c', + '/bin/sh $WORKSPACE_ROOT/scripts/add-changelog-header.sh', +] # Nested use of shell to expand variables. diff --git a/swarm-derive/CHANGELOG.md b/swarm-derive/CHANGELOG.md index 74f35806eec..9c97a39915e 100644 --- a/swarm-derive/CHANGELOG.md +++ b/swarm-derive/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.35.0 - unreleased + +- Generate code for `libp2p-swarm`'s `from_swarm::NewExternalAddrOfPeer` enum variant. + See [PR 4371](https://github.com/libp2p/rust-libp2p/pull/4371) + ## 0.34.2 - Restore support for generic constraints on behaviours combined with `out_event` generated by `NetworkBehaviour` where no where clause is used. diff --git a/swarm-derive/Cargo.toml b/swarm-derive/Cargo.toml index 7740d57feb1..1b13b4b6453 100644 --- a/swarm-derive/Cargo.toml +++ b/swarm-derive/Cargo.toml @@ -3,7 +3,7 @@ name = "libp2p-swarm-derive" edition = "2021" rust-version = { workspace = true } description = "Procedural macros of libp2p-swarm" -version = "0.34.2" +version = "0.35.0" authors = ["Parity Technologies "] license = "MIT" repository = "https://github.com/libp2p/rust-libp2p" @@ -16,7 +16,13 @@ proc-macro = true [dependencies] heck = "0.4" quote = "1.0" -syn = { version = "2.0.43", default-features = false, features = ["clone-impls", "derive", "parsing", "printing", "proc-macro"] } +syn = { version = "2.0.43", default-features = false, features = [ + "clone-impls", + "derive", + "parsing", + "printing", + "proc-macro", +] } proc-macro2 = "1.0" # Passing arguments to the docsrs builder in order to properly document cfg's. diff --git a/swarm/CHANGELOG.md b/swarm/CHANGELOG.md index 65dce4b002a..1e88282758c 100644 --- a/swarm/CHANGELOG.md +++ b/swarm/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.44.2 - unreleased + +- Add `FromSwarm::NewExternalAddrOfPeer` event. + See [PR 4371](https://github.com/libp2p/rust-libp2p/pull/4371) + ## 0.44.1 - Implement `Clone` & `Copy` for `FromSwarm. diff --git a/swarm/src/behaviour.rs b/swarm/src/behaviour.rs index 4be129a4eea..7cd5f5e9d7e 100644 --- a/swarm/src/behaviour.rs +++ b/swarm/src/behaviour.rs @@ -303,6 +303,9 @@ pub enum ToSwarm { /// Whether to close a specific or all connections to the given peer. connection: CloseConnection, }, + + /// Reports external address of a remote peer to the [`Swarm`](crate::Swarm) and through that to other [`NetworkBehaviour`]s. + NewExternalAddrOfPeer { peer_id: PeerId, addr: Multiaddr }, } impl ToSwarm { @@ -335,6 +338,9 @@ impl ToSwarm { ToSwarm::NewExternalAddrCandidate(addr) => ToSwarm::NewExternalAddrCandidate(addr), ToSwarm::ExternalAddrConfirmed(addr) => ToSwarm::ExternalAddrConfirmed(addr), ToSwarm::ExternalAddrExpired(addr) => ToSwarm::ExternalAddrExpired(addr), + ToSwarm::NewExternalAddrOfPeer { addr, peer_id } => { + ToSwarm::NewExternalAddrOfPeer { addr, peer_id } + } } } } @@ -366,6 +372,9 @@ impl ToSwarm { peer_id, connection, }, + ToSwarm::NewExternalAddrOfPeer { addr, peer_id } => { + ToSwarm::NewExternalAddrOfPeer { addr, peer_id } + } } } } @@ -432,6 +441,8 @@ pub enum FromSwarm<'a> { ExternalAddrConfirmed(ExternalAddrConfirmed<'a>), /// Informs the behaviour that an external address of the local node expired, i.e. is no-longer confirmed. ExternalAddrExpired(ExternalAddrExpired<'a>), + /// Informs the behaviour that we have discovered a new external address for a remote peer. + NewExternalAddrOfPeer(NewExternalAddrOfPeer<'a>), } /// [`FromSwarm`] variant that informs the behaviour about a newly established connection to a peer. @@ -543,3 +554,10 @@ pub struct ExternalAddrConfirmed<'a> { pub struct ExternalAddrExpired<'a> { pub addr: &'a Multiaddr, } + +/// [`FromSwarm`] variant that informs the behaviour that a new external address for a remote peer was detected. +#[derive(Clone, Copy, Debug)] +pub struct NewExternalAddrOfPeer<'a> { + pub peer_id: PeerId, + pub addr: &'a Multiaddr, +} diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index 0354f39cfdc..d20e07a40d4 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -84,6 +84,7 @@ pub mod derive_prelude { pub use crate::behaviour::ListenerClosed; pub use crate::behaviour::ListenerError; pub use crate::behaviour::NewExternalAddrCandidate; + pub use crate::behaviour::NewExternalAddrOfPeer; pub use crate::behaviour::NewListenAddr; pub use crate::behaviour::NewListener; pub use crate::connection::ConnectionId; @@ -108,8 +109,8 @@ pub mod derive_prelude { pub use behaviour::{ AddressChange, CloseConnection, ConnectionClosed, DialFailure, ExpiredListenAddr, ExternalAddrExpired, ExternalAddresses, FromSwarm, ListenAddresses, ListenFailure, - ListenerClosed, ListenerError, NetworkBehaviour, NewExternalAddrCandidate, NewListenAddr, - NotifyHandler, ToSwarm, + ListenerClosed, ListenerError, NetworkBehaviour, NewExternalAddrCandidate, + NewExternalAddrOfPeer, NewListenAddr, NotifyHandler, ToSwarm, }; pub use connection::pool::ConnectionCounters; pub use connection::{ConnectionError, ConnectionId, SupportedProtocols}; @@ -1176,6 +1177,13 @@ where self.pool.disconnect(peer_id); } }, + ToSwarm::NewExternalAddrOfPeer { addr, peer_id } => { + self.behaviour + .on_swarm_event(FromSwarm::NewExternalAddrOfPeer(NewExternalAddrOfPeer { + peer_id, + addr: &addr, + })) + } } } From c6a323c6d1db83ebd1f04498a8318c02d8a24f73 Mon Sep 17 00:00:00 2001 From: StemCll Date: Wed, 29 Nov 2023 22:15:32 +0100 Subject: [PATCH 02/23] deprecate request-response add_address --- protocols/autonat/src/behaviour.rs | 1 + protocols/request-response/src/lib.rs | 1 + swarm/src/lib.rs | 11 +++++++++++ 3 files changed, 13 insertions(+) diff --git a/protocols/autonat/src/behaviour.rs b/protocols/autonat/src/behaviour.rs index e95163ab23f..a770e61e88a 100644 --- a/protocols/autonat/src/behaviour.rs +++ b/protocols/autonat/src/behaviour.rs @@ -268,6 +268,7 @@ impl Behaviour { pub fn add_server(&mut self, peer: PeerId, address: Option) { self.servers.insert(peer); if let Some(addr) = address { + #[allow(deprecated)] self.inner.add_address(&peer, addr); } } diff --git a/protocols/request-response/src/lib.rs b/protocols/request-response/src/lib.rs index fc68bd6cf1f..ee53f44cfc3 100644 --- a/protocols/request-response/src/lib.rs +++ b/protocols/request-response/src/lib.rs @@ -470,6 +470,7 @@ where /// /// Returns true if the address was added, false otherwise (i.e. if the /// address is already in the list). + #[deprecated(note = "Use `libp2p_swarm::add_address` instead.")] pub fn add_address(&mut self, peer: &PeerId, address: Multiaddr) -> bool { self.addresses.entry(*peer).or_default().insert(address) } diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index d20e07a40d4..3b7272e937e 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -624,6 +624,17 @@ where self.confirmed_external_addr.remove(addr); } + /// Add peer's new external address. + /// + /// The address is broadcast to all [`NetworkBehaviour`]s via [`FromSwarm::NewExternalAddrOfPeer`]. + pub fn add_peer_address(&mut self, peer_id: PeerId, addr: Multiaddr) { + self.behaviour + .on_swarm_event(FromSwarm::NewExternalAddrOfPeer(NewExternalAddrOfPeer { + peer_id, + addr: &addr, + })) + } + /// Disconnects a peer by its peer ID, closing all connections to said peer. /// /// Returns `Ok(())` if there was one or more established connections to the peer. From 03fd927e37dc29946867f43332a6f7c547e8f8ce Mon Sep 17 00:00:00 2001 From: StemCll Date: Wed, 29 Nov 2023 22:15:59 +0100 Subject: [PATCH 03/23] swarm: add peer addresses --- swarm/src/behaviour.rs | 2 + swarm/src/behaviour/peer_addresses.rs | 126 ++++++++++++++++++++++++++ swarm/src/lib.rs | 11 ++- 3 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 swarm/src/behaviour/peer_addresses.rs diff --git a/swarm/src/behaviour.rs b/swarm/src/behaviour.rs index 7cd5f5e9d7e..beb924c562e 100644 --- a/swarm/src/behaviour.rs +++ b/swarm/src/behaviour.rs @@ -21,10 +21,12 @@ mod either; mod external_addresses; mod listen_addresses; +mod peer_addresses; pub mod toggle; pub use external_addresses::ExternalAddresses; pub use listen_addresses::ListenAddresses; +pub use peer_addresses::PeerAddresses; use crate::connection::ConnectionId; use crate::dial_opts::DialOpts; diff --git a/swarm/src/behaviour/peer_addresses.rs b/swarm/src/behaviour/peer_addresses.rs new file mode 100644 index 00000000000..450bb8cf20e --- /dev/null +++ b/swarm/src/behaviour/peer_addresses.rs @@ -0,0 +1,126 @@ +use crate::{behaviour::FromSwarm, NewExternalAddrOfPeer}; +use libp2p_core::Multiaddr; +use libp2p_identity::PeerId; +use std::collections::HashMap; + +/// Struct for tracking peers' external addresses of the [`Swarm`](crate::Swarm). +#[derive(Debug, Clone, Default)] +pub struct PeerAddresses(HashMap>); + +impl PeerAddresses { + /// Feed a [`FromSwarm`] event to this struct. + /// + /// Returns whether the event changed peer's known external addresses. + pub fn on_swarm_event(&mut self, event: &FromSwarm) -> bool { + if let FromSwarm::NewExternalAddrOfPeer(NewExternalAddrOfPeer { peer_id, addr }) = event { + match self.0.get_mut(peer_id) { + None => { + let mut empty_vec: Vec = Vec::new(); + Self::push(&mut empty_vec, addr); + + self.0.insert(*peer_id, empty_vec); + return true; + } + Some(addrs) => { + if addrs.contains(addr) { + return false; + } + Self::push(addrs, addr); + + return true; + } + } + } + false + } + + /// Returns peer's external addresses. + /// Returns [`None`] if the peer did not have any addrs cached. + pub fn peer_addrs(&self, peer_id: &PeerId) -> Option<&Vec> { + self.0.get(peer_id) + } + + fn push(vec: &mut Vec, addr: &Multiaddr) { + vec.insert(0, addr.clone()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use libp2p_core::multiaddr::Protocol; + use once_cell::sync::Lazy; + + #[test] + fn new_peer_addr_returns_correct_changed_value() { + let mut cache = PeerAddresses::default(); + let peer_id = PeerId::random(); + + let event = new_external_addr_of_peer1(peer_id); + + let changed = cache.on_swarm_event(&event); + assert!(changed); + + let changed = cache.on_swarm_event(&event); + assert!(!changed); + } + + #[test] + fn new_peer_addr_saves_peer_addrs() { + let mut cache = PeerAddresses::default(); + let peer_id = PeerId::random(); + let event = new_external_addr_of_peer1(peer_id); + + let changed = cache.on_swarm_event(&event); + assert!(changed); + + let addr1 = MEMORY_ADDR_1000.clone(); + assert_eq!(cache.peer_addrs(&peer_id), Some(&vec![addr1])); + + let event = new_external_addr_of_peer2(peer_id); + let changed = cache.on_swarm_event(&event); + + let addr1 = MEMORY_ADDR_1000.clone(); + let addr2 = MEMORY_ADDR_2000.clone(); + + assert_eq!(cache.peer_addrs(&peer_id), Some(&vec![addr2, addr1])); + assert!(changed); + } + + #[test] + fn existing_addr_is_not_added_to_cache() { + let mut cache = PeerAddresses::default(); + let peer_id = PeerId::random(); + + let event = new_external_addr_of_peer1(peer_id); + + let addr1 = MEMORY_ADDR_1000.clone(); + let changed = cache.on_swarm_event(&event); + assert!(changed); + assert_eq!(cache.peer_addrs(&peer_id), Some(&vec![addr1])); + + let addr1 = MEMORY_ADDR_1000.clone(); + let changed = cache.on_swarm_event(&event); + assert!(!changed); + assert_eq!(cache.peer_addrs(&peer_id), Some(&vec![addr1])); + } + + fn new_external_addr_of_peer1(peer_id: PeerId) -> FromSwarm<'static> { + FromSwarm::NewExternalAddrOfPeer(NewExternalAddrOfPeer { + peer_id, + addr: &MEMORY_ADDR_1000, + }) + } + + fn new_external_addr_of_peer2(peer_id: PeerId) -> FromSwarm<'static> { + FromSwarm::NewExternalAddrOfPeer(NewExternalAddrOfPeer { + peer_id, + addr: &MEMORY_ADDR_2000, + }) + } + + static MEMORY_ADDR_1000: Lazy = + Lazy::new(|| Multiaddr::empty().with(Protocol::Memory(1000))); + static MEMORY_ADDR_2000: Lazy = + Lazy::new(|| Multiaddr::empty().with(Protocol::Memory(2000))); +} diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index 3b7272e937e..5e2657e02dc 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -110,7 +110,7 @@ pub use behaviour::{ AddressChange, CloseConnection, ConnectionClosed, DialFailure, ExpiredListenAddr, ExternalAddrExpired, ExternalAddresses, FromSwarm, ListenAddresses, ListenFailure, ListenerClosed, ListenerError, NetworkBehaviour, NewExternalAddrCandidate, - NewExternalAddrOfPeer, NewListenAddr, NotifyHandler, ToSwarm, + NewExternalAddrOfPeer, NewListenAddr, NotifyHandler, PeerAddresses, ToSwarm, }; pub use connection::pool::ConnectionCounters; pub use connection::{ConnectionError, ConnectionId, SupportedProtocols}; @@ -341,6 +341,9 @@ where /// Multiaddresses that our listeners are listening on, listened_addrs: HashMap>, + /// Cache of peers with their known external addresses. + peer_addrs: PeerAddresses, + /// Pending event to be delivered to connection handlers /// (or dropped if the peer disconnected) before the `behaviour` /// can be polled again. @@ -373,6 +376,7 @@ where supported_protocols: Default::default(), confirmed_external_addr: Default::default(), listened_addrs: HashMap::new(), + peer_addrs: Default::default(), pending_handler_event: None, pending_swarm_events: VecDeque::default(), } @@ -581,6 +585,11 @@ where self.confirmed_external_addr.iter() } + /// List external addresses of a known peer. + pub fn peer_addresses(&self, peer_id: &PeerId) -> Option<&Vec> { + self.peer_addrs.peer_addrs(peer_id) + } + fn add_listener(&mut self, opts: ListenOpts) -> Result<(), TransportError> { let addr = opts.address(); let listener_id = opts.listener_id(); From 6110643ada630bced8f116259de47e8a29dc5f33 Mon Sep 17 00:00:00 2001 From: StemCll Date: Sun, 10 Dec 2023 21:58:17 +0100 Subject: [PATCH 04/23] Move peer cache to peer addresses --- Cargo.lock | 1 + protocols/identify/src/behaviour.rs | 34 +++----- protocols/request-response/src/lib.rs | 2 +- swarm/Cargo.toml | 1 + swarm/src/behaviour/peer_addresses.rs | 120 +++++++++++++++++++------- swarm/src/lib.rs | 9 -- 6 files changed, 103 insertions(+), 64 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8c818de4a9f..d465ba6e376 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3265,6 +3265,7 @@ dependencies = [ "libp2p-swarm-derive", "libp2p-swarm-test", "libp2p-yamux", + "lru", "multistream-select", "once_cell", "quickcheck-ext", diff --git a/protocols/identify/src/behaviour.rs b/protocols/identify/src/behaviour.rs index e4da898f44c..498e1fecd67 100644 --- a/protocols/identify/src/behaviour.rs +++ b/protocols/identify/src/behaviour.rs @@ -26,15 +26,14 @@ use libp2p_identity::PublicKey; use libp2p_swarm::behaviour::{ConnectionClosed, ConnectionEstablished, DialFailure, FromSwarm}; use libp2p_swarm::{ ConnectionDenied, DialError, ExternalAddresses, ListenAddresses, NetworkBehaviour, - NotifyHandler, StreamUpgradeError, THandlerInEvent, ToSwarm, + NotifyHandler, PeerAddresses, StreamUpgradeError, THandlerInEvent, ToSwarm, }; use libp2p_swarm::{ConnectionId, THandler, THandlerOutEvent}; -use lru::LruCache; + use std::collections::hash_map::Entry; use std::num::NonZeroUsize; use std::{ collections::{HashMap, HashSet, VecDeque}, - iter::FromIterator, task::Context, task::Poll, time::Duration, @@ -445,7 +444,7 @@ fn multiaddr_matches_peer_id(addr: &Multiaddr, peer_id: &PeerId) -> bool { true } -struct PeerCache(Option>>); +struct PeerCache(Option); impl PeerCache { fn disabled() -> Self { @@ -453,7 +452,7 @@ impl PeerCache { } fn enabled(size: NonZeroUsize) -> Self { - Self(Some(LruCache::new(size))) + Self(Some(PeerAddresses::new(size))) } fn get_mut(&mut self, peer: &PeerId) -> Option<&mut HashSet> { @@ -461,26 +460,17 @@ impl PeerCache { } fn put(&mut self, peer: PeerId, addresses: impl Iterator) { - let cache = match self.0.as_mut() { - None => return, - Some(cache) => cache, - }; - - let addresses = addresses.filter_map(|a| a.with_p2p(peer).ok()); - cache.put(peer, HashSet::from_iter(addresses)); + if let Some(cache) = self.0.as_mut() { + cache.put(peer, addresses); + } } fn get(&mut self, peer: &PeerId) -> Vec { - let cache = match self.0.as_mut() { - None => return Vec::new(), - Some(cache) => cache, - }; - - cache - .get(peer) - .cloned() - .map(Vec::from_iter) - .unwrap_or_default() + if let Some(cache) = self.0.as_mut() { + cache.get(peer) + } else { + Vec::new() + } } } diff --git a/protocols/request-response/src/lib.rs b/protocols/request-response/src/lib.rs index ee53f44cfc3..fecc3df6590 100644 --- a/protocols/request-response/src/lib.rs +++ b/protocols/request-response/src/lib.rs @@ -470,7 +470,7 @@ where /// /// Returns true if the address was added, false otherwise (i.e. if the /// address is already in the list). - #[deprecated(note = "Use `libp2p_swarm::add_address` instead.")] + #[deprecated(note = "Use `libp2p_swarm::Swarm::add_peer_address` instead.")] pub fn add_address(&mut self, peer: &PeerId, address: Multiaddr) -> bool { self.addresses.entry(*peer).or_default().insert(address) } diff --git a/swarm/Cargo.toml b/swarm/Cargo.toml index 9de312e76d7..420c72d4556 100644 --- a/swarm/Cargo.toml +++ b/swarm/Cargo.toml @@ -20,6 +20,7 @@ instant = "0.1.12" libp2p-core = { workspace = true } libp2p-identity = { workspace = true } libp2p-swarm-derive = { workspace = true, optional = true } +lru = "0.12.1" multistream-select = { workspace = true } once_cell = "1.19.0" rand = "0.8" diff --git a/swarm/src/behaviour/peer_addresses.rs b/swarm/src/behaviour/peer_addresses.rs index 450bb8cf20e..59e8e356b32 100644 --- a/swarm/src/behaviour/peer_addresses.rs +++ b/swarm/src/behaviour/peer_addresses.rs @@ -1,52 +1,86 @@ -use crate::{behaviour::FromSwarm, NewExternalAddrOfPeer}; +use crate::behaviour::FromSwarm; +use crate::{DialError, DialFailure, NewExternalAddrOfPeer}; + use libp2p_core::Multiaddr; use libp2p_identity::PeerId; -use std::collections::HashMap; + +use lru::LruCache; + +use std::collections::HashSet; +use std::num::NonZeroUsize; /// Struct for tracking peers' external addresses of the [`Swarm`](crate::Swarm). -#[derive(Debug, Clone, Default)] -pub struct PeerAddresses(HashMap>); +#[derive(Debug)] +pub struct PeerAddresses(LruCache>); impl PeerAddresses { /// Feed a [`FromSwarm`] event to this struct. /// /// Returns whether the event changed peer's known external addresses. pub fn on_swarm_event(&mut self, event: &FromSwarm) -> bool { - if let FromSwarm::NewExternalAddrOfPeer(NewExternalAddrOfPeer { peer_id, addr }) = event { - match self.0.get_mut(peer_id) { - None => { - let mut empty_vec: Vec = Vec::new(); - Self::push(&mut empty_vec, addr); - - self.0.insert(*peer_id, empty_vec); + match event { + FromSwarm::NewExternalAddrOfPeer(NewExternalAddrOfPeer { peer_id, addr }) => { + if let Some(peer_addrs) = self.get_mut(peer_id) { + let addr = Self::prepare_addr(peer_id, addr); + return peer_addrs.insert(addr); + } else { + let addr = Self::prepare_addr(peer_id, addr); + self.put(*peer_id, std::iter::once(addr)); return true; } - Some(addrs) => { - if addrs.contains(addr) { - return false; + } + FromSwarm::DialFailure(DialFailure { peer_id, error, .. }) => { + if let Some(peer_id) = peer_id { + match error { + DialError::NoAddresses => return self.0.pop(peer_id).is_some(), + _ => return false, } - Self::push(addrs, addr); - - return true; } } - } + _ => return false, + }; false } + pub fn new(cache_size: NonZeroUsize) -> Self { + Self(LruCache::new(cache_size)) + } + + pub fn get_mut(&mut self, peer: &PeerId) -> Option<&mut HashSet> { + self.0.get_mut(peer) + } + + pub fn put(&mut self, peer: PeerId, addresses: impl Iterator) -> bool { + let addresses = addresses.filter_map(|a| a.with_p2p(peer).ok()); + self.0.put(peer, HashSet::from_iter(addresses)); + true + } + /// Returns peer's external addresses. - /// Returns [`None`] if the peer did not have any addrs cached. - pub fn peer_addrs(&self, peer_id: &PeerId) -> Option<&Vec> { - self.0.get(peer_id) + pub fn get(&mut self, peer: &PeerId) -> Vec { + self.0 + .get(peer) + .cloned() + .map(Vec::from_iter) + .unwrap_or_default() + } + + fn prepare_addr(peer: &PeerId, addr: &Multiaddr) -> Multiaddr { + let addr = addr.clone(); + addr.clone().with_p2p(*peer).unwrap_or(addr) } +} - fn push(vec: &mut Vec, addr: &Multiaddr) { - vec.insert(0, addr.clone()) +impl Default for PeerAddresses { + fn default() -> Self { + Self(LruCache::new(NonZeroUsize::new(100).unwrap())) } } #[cfg(test)] mod tests { + use crate::{ConnectionId, DialError}; + use super::*; use libp2p_core::multiaddr::Protocol; use once_cell::sync::Lazy; @@ -74,16 +108,16 @@ mod tests { let changed = cache.on_swarm_event(&event); assert!(changed); - let addr1 = MEMORY_ADDR_1000.clone(); - assert_eq!(cache.peer_addrs(&peer_id), Some(&vec![addr1])); + let addr1 = MEMORY_ADDR_1000.clone().with_p2p(peer_id).unwrap(); + assert_eq!(cache.get(&peer_id), vec![addr1]); let event = new_external_addr_of_peer2(peer_id); let changed = cache.on_swarm_event(&event); - let addr1 = MEMORY_ADDR_1000.clone(); - let addr2 = MEMORY_ADDR_2000.clone(); + let addr1 = MEMORY_ADDR_1000.clone().with_p2p(peer_id).unwrap(); + let addr2 = MEMORY_ADDR_2000.clone().with_p2p(peer_id).unwrap(); - assert_eq!(cache.peer_addrs(&peer_id), Some(&vec![addr2, addr1])); + assert_eq!(cache.get(&peer_id).sort(), vec![addr1, addr2].sort()); assert!(changed); } @@ -94,15 +128,29 @@ mod tests { let event = new_external_addr_of_peer1(peer_id); - let addr1 = MEMORY_ADDR_1000.clone(); + let addr1 = MEMORY_ADDR_1000.clone().with_p2p(peer_id).unwrap(); let changed = cache.on_swarm_event(&event); assert!(changed); - assert_eq!(cache.peer_addrs(&peer_id), Some(&vec![addr1])); + assert_eq!(cache.get(&peer_id), vec![addr1]); - let addr1 = MEMORY_ADDR_1000.clone(); + let addr1 = MEMORY_ADDR_1000.clone().with_p2p(peer_id).unwrap(); let changed = cache.on_swarm_event(&event); assert!(!changed); - assert_eq!(cache.peer_addrs(&peer_id), Some(&vec![addr1])); + assert_eq!(cache.get(&peer_id), vec![addr1]); + } + + #[test] + fn addrs_of_peer_are_removed_when_received_dial_failure_event() { + let mut cache = PeerAddresses::default(); + let peer_id = PeerId::random(); + + cache.on_swarm_event(&new_external_addr_of_peer1(peer_id)); + let event = dial_error(peer_id); + + let changed = cache.on_swarm_event(&event); + + assert!(changed); + assert_eq!(cache.get(&peer_id), vec![]); } fn new_external_addr_of_peer1(peer_id: PeerId) -> FromSwarm<'static> { @@ -119,6 +167,14 @@ mod tests { }) } + fn dial_error(peer_id: PeerId) -> FromSwarm<'static> { + FromSwarm::DialFailure(DialFailure { + peer_id: Some(peer_id), + error: &DialError::NoAddresses, + connection_id: ConnectionId::new_unchecked(8), + }) + } + static MEMORY_ADDR_1000: Lazy = Lazy::new(|| Multiaddr::empty().with(Protocol::Memory(1000))); static MEMORY_ADDR_2000: Lazy = diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index 5e2657e02dc..8a7218d9136 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -341,9 +341,6 @@ where /// Multiaddresses that our listeners are listening on, listened_addrs: HashMap>, - /// Cache of peers with their known external addresses. - peer_addrs: PeerAddresses, - /// Pending event to be delivered to connection handlers /// (or dropped if the peer disconnected) before the `behaviour` /// can be polled again. @@ -376,7 +373,6 @@ where supported_protocols: Default::default(), confirmed_external_addr: Default::default(), listened_addrs: HashMap::new(), - peer_addrs: Default::default(), pending_handler_event: None, pending_swarm_events: VecDeque::default(), } @@ -585,11 +581,6 @@ where self.confirmed_external_addr.iter() } - /// List external addresses of a known peer. - pub fn peer_addresses(&self, peer_id: &PeerId) -> Option<&Vec> { - self.peer_addrs.peer_addrs(peer_id) - } - fn add_listener(&mut self, opts: ListenOpts) -> Result<(), TransportError> { let addr = opts.address(); let listener_id = opts.listener_id(); From 3f227c783da0cec607f4bdf82bd3d644ce1cbd31 Mon Sep 17 00:00:00 2001 From: StemCll Date: Sun, 10 Dec 2023 23:14:48 +0100 Subject: [PATCH 05/23] Add pop function to peer address --- protocols/request-response/src/lib.rs | 35 +++++++++--------- swarm/src/behaviour/peer_addresses.rs | 51 +++++++++++++++++++++++++-- 2 files changed, 65 insertions(+), 21 deletions(-) diff --git a/protocols/request-response/src/lib.rs b/protocols/request-response/src/lib.rs index fecc3df6590..32fb4326d9d 100644 --- a/protocols/request-response/src/lib.rs +++ b/protocols/request-response/src/lib.rs @@ -84,8 +84,8 @@ use libp2p_identity::PeerId; use libp2p_swarm::{ behaviour::{AddressChange, ConnectionClosed, DialFailure, FromSwarm}, dial_opts::DialOpts, - ConnectionDenied, ConnectionHandler, ConnectionId, NetworkBehaviour, NotifyHandler, THandler, - THandlerInEvent, THandlerOutEvent, ToSwarm, + ConnectionDenied, ConnectionHandler, ConnectionId, NetworkBehaviour, NotifyHandler, + PeerAddresses, THandler, THandlerInEvent, THandlerOutEvent, ToSwarm, }; use smallvec::SmallVec; use std::{ @@ -357,7 +357,7 @@ where /// reachable addresses, if any. connected: HashMap>, /// Externally managed addresses via `add_address` and `remove_address`. - addresses: HashMap>, + addresses: PeerAddresses, /// Requests that have not yet been sent and are waiting for a connection /// to be established. pending_outbound_requests: HashMap; 10]>>, @@ -406,7 +406,7 @@ where pending_events: VecDeque::new(), connected: HashMap::new(), pending_outbound_requests: HashMap::new(), - addresses: HashMap::new(), + addresses: PeerAddresses::default(), } } @@ -472,19 +472,12 @@ where /// address is already in the list). #[deprecated(note = "Use `libp2p_swarm::Swarm::add_peer_address` instead.")] pub fn add_address(&mut self, peer: &PeerId, address: Multiaddr) -> bool { - self.addresses.entry(*peer).or_default().insert(address) + self.addresses.put(*peer, std::iter::once(address)) } - /// Removes an address of a peer previously added via `add_address`. + /// Removes an address of a peer previously added via [`Behaviour::add_address`]. pub fn remove_address(&mut self, peer: &PeerId, address: &Multiaddr) { - let mut last = false; - if let Some(addresses) = self.addresses.get_mut(peer) { - addresses.retain(|a| a != address); - last = addresses.is_empty(); - } - if last { - self.addresses.remove(peer); - } + self.addresses.pop(peer, address); } /// Checks whether a peer is currently connected. @@ -765,9 +758,9 @@ where if let Some(connections) = self.connected.get(&peer) { addresses.extend(connections.iter().filter_map(|c| c.remote_address.clone())) } - if let Some(more) = self.addresses.get(&peer) { - addresses.extend(more.iter().cloned()); - } + + let cached_addrs = self.addresses.get(&peer); + addresses.extend(cached_addrs.iter().cloned()); Ok(addresses) } @@ -804,7 +797,13 @@ where self.on_connection_closed(connection_closed) } FromSwarm::AddressChange(address_change) => self.on_address_change(address_change), - FromSwarm::DialFailure(dial_failure) => self.on_dial_failure(dial_failure), + FromSwarm::DialFailure(dial_failure) => { + self.on_dial_failure(dial_failure); + self.addresses.on_swarm_event(&event); + } + FromSwarm::NewExternalAddrOfPeer(_) => { + self.addresses.on_swarm_event(&event); + } _ => {} } } diff --git a/swarm/src/behaviour/peer_addresses.rs b/swarm/src/behaviour/peer_addresses.rs index 59e8e356b32..6f906a6b89c 100644 --- a/swarm/src/behaviour/peer_addresses.rs +++ b/swarm/src/behaviour/peer_addresses.rs @@ -65,6 +65,18 @@ impl PeerAddresses { .unwrap_or_default() } + /// Removes address from peer addresses cache. + /// Returns true if the address was removed. + pub fn pop(&mut self, peer: &PeerId, address: &Multiaddr) -> bool { + self.get_mut(peer).map_or_else( + || false, + |addrs| { + let address = Self::prepare_addr(peer, address); + addrs.remove(&address) + }, + ) + } + fn prepare_addr(peer: &PeerId, addr: &Multiaddr) -> Multiaddr { let addr = addr.clone(); addr.clone().with_p2p(*peer).unwrap_or(addr) @@ -117,7 +129,11 @@ mod tests { let addr1 = MEMORY_ADDR_1000.clone().with_p2p(peer_id).unwrap(); let addr2 = MEMORY_ADDR_2000.clone().with_p2p(peer_id).unwrap(); - assert_eq!(cache.get(&peer_id).sort(), vec![addr1, addr2].sort()); + assert!(cache.get(&peer_id).contains(&addr1)); + assert!(cache.get(&peer_id).contains(&addr2)); + + assert_eq!(cache.get(&peer_id).len(), 2); + assert!(changed); } @@ -136,7 +152,7 @@ mod tests { let addr1 = MEMORY_ADDR_1000.clone().with_p2p(peer_id).unwrap(); let changed = cache.on_swarm_event(&event); assert!(!changed); - assert_eq!(cache.get(&peer_id), vec![addr1]); + assert_eq!(cache.get(&peer_id), [addr1]); } #[test] @@ -150,7 +166,36 @@ mod tests { let changed = cache.on_swarm_event(&event); assert!(changed); - assert_eq!(cache.get(&peer_id), vec![]); + assert_eq!(cache.get(&peer_id), []); + } + + #[test] + fn pop_removes_address_if_present() { + let mut cache = PeerAddresses::default(); + let peer_id = PeerId::random(); + let addr: Multiaddr = "/ip4/127.0.0.1/tcp/8080".parse().unwrap(); + + cache.put(peer_id, std::iter::once(addr.clone())); + + assert!(cache.pop(&peer_id, &addr)); + } + + #[test] + fn pop_returns_false_if_address_not_present() { + let mut cache = PeerAddresses::default(); + let peer_id = PeerId::random(); + let addr: Multiaddr = "/ip4/127.0.0.1/tcp/8080".parse().unwrap(); + + assert!(!cache.pop(&peer_id, &addr)); + } + + #[test] + fn pop_returns_false_if_peer_not_present() { + let mut cache = PeerAddresses::default(); + let peer_id = PeerId::random(); + let addr: Multiaddr = "/ip4/127.0.0.1/tcp/8080".parse().unwrap(); + + assert!(!cache.pop(&peer_id, &addr)); } fn new_external_addr_of_peer1(peer_id: PeerId) -> FromSwarm<'static> { From 959a1314f46367e27526f46efbed731143c617dc Mon Sep 17 00:00:00 2001 From: StemCll Date: Mon, 11 Dec 2023 22:16:49 +0100 Subject: [PATCH 06/23] Add CR changes --- protocols/identify/src/behaviour.rs | 2 +- protocols/request-response/src/lib.rs | 13 ++---- swarm/src/behaviour/peer_addresses.rs | 67 ++++++++++++++------------- 3 files changed, 40 insertions(+), 42 deletions(-) diff --git a/protocols/identify/src/behaviour.rs b/protocols/identify/src/behaviour.rs index 498e1fecd67..6adc11f2a41 100644 --- a/protocols/identify/src/behaviour.rs +++ b/protocols/identify/src/behaviour.rs @@ -467,7 +467,7 @@ impl PeerCache { fn get(&mut self, peer: &PeerId) -> Vec { if let Some(cache) = self.0.as_mut() { - cache.get(peer) + cache.get(peer).collect() } else { Vec::new() } diff --git a/protocols/request-response/src/lib.rs b/protocols/request-response/src/lib.rs index 32fb4326d9d..3553c829993 100644 --- a/protocols/request-response/src/lib.rs +++ b/protocols/request-response/src/lib.rs @@ -477,7 +477,7 @@ where /// Removes an address of a peer previously added via [`Behaviour::add_address`]. pub fn remove_address(&mut self, peer: &PeerId, address: &Multiaddr) { - self.addresses.pop(peer, address); + self.addresses.remove(peer, address); } /// Checks whether a peer is currently connected. @@ -760,7 +760,7 @@ where } let cached_addrs = self.addresses.get(&peer); - addresses.extend(cached_addrs.iter().cloned()); + addresses.extend(cached_addrs); Ok(addresses) } @@ -791,19 +791,14 @@ where } fn on_swarm_event(&mut self, event: FromSwarm) { + self.addresses.on_swarm_event(&event); match event { FromSwarm::ConnectionEstablished(_) => {} FromSwarm::ConnectionClosed(connection_closed) => { self.on_connection_closed(connection_closed) } FromSwarm::AddressChange(address_change) => self.on_address_change(address_change), - FromSwarm::DialFailure(dial_failure) => { - self.on_dial_failure(dial_failure); - self.addresses.on_swarm_event(&event); - } - FromSwarm::NewExternalAddrOfPeer(_) => { - self.addresses.on_swarm_event(&event); - } + FromSwarm::DialFailure(dial_failure) => self.on_dial_failure(dial_failure), _ => {} } } diff --git a/swarm/src/behaviour/peer_addresses.rs b/swarm/src/behaviour/peer_addresses.rs index 6f906a6b89c..9076e73d116 100644 --- a/swarm/src/behaviour/peer_addresses.rs +++ b/swarm/src/behaviour/peer_addresses.rs @@ -21,25 +21,21 @@ impl PeerAddresses { match event { FromSwarm::NewExternalAddrOfPeer(NewExternalAddrOfPeer { peer_id, addr }) => { if let Some(peer_addrs) = self.get_mut(peer_id) { - let addr = Self::prepare_addr(peer_id, addr); - return peer_addrs.insert(addr); + let addr = prepare_addr(peer_id, addr); + peer_addrs.insert(addr) } else { - let addr = Self::prepare_addr(peer_id, addr); + let addr = prepare_addr(peer_id, addr); self.put(*peer_id, std::iter::once(addr)); - return true; + true } } - FromSwarm::DialFailure(DialFailure { peer_id, error, .. }) => { - if let Some(peer_id) = peer_id { - match error { - DialError::NoAddresses => return self.0.pop(peer_id).is_some(), - _ => return false, - } - } - } - _ => return false, - }; - false + FromSwarm::DialFailure(DialFailure { + peer_id: Some(peer_id), + error: DialError::NoAddresses, + .. + }) => self.0.pop(peer_id).is_some(), + _ => false, + } } pub fn new(cache_size: NonZeroUsize) -> Self { @@ -57,30 +53,31 @@ impl PeerAddresses { } /// Returns peer's external addresses. - pub fn get(&mut self, peer: &PeerId) -> Vec { + pub fn get(&mut self, peer: &PeerId) -> impl Iterator { self.0 .get(peer) .cloned() .map(Vec::from_iter) .unwrap_or_default() + .into_iter() } /// Removes address from peer addresses cache. /// Returns true if the address was removed. - pub fn pop(&mut self, peer: &PeerId, address: &Multiaddr) -> bool { + pub fn remove(&mut self, peer: &PeerId, address: &Multiaddr) -> bool { self.get_mut(peer).map_or_else( || false, |addrs| { - let address = Self::prepare_addr(peer, address); + let address = prepare_addr(peer, address); addrs.remove(&address) }, ) } +} - fn prepare_addr(peer: &PeerId, addr: &Multiaddr) -> Multiaddr { - let addr = addr.clone(); - addr.clone().with_p2p(*peer).unwrap_or(addr) - } +fn prepare_addr(peer: &PeerId, addr: &Multiaddr) -> Multiaddr { + let addr = addr.clone(); + addr.clone().with_p2p(*peer).unwrap_or(addr) } impl Default for PeerAddresses { @@ -121,7 +118,8 @@ mod tests { assert!(changed); let addr1 = MEMORY_ADDR_1000.clone().with_p2p(peer_id).unwrap(); - assert_eq!(cache.get(&peer_id), vec![addr1]); + let expected = cache.get(&peer_id).collect::>(); + assert_eq!(expected, vec![addr1]); let event = new_external_addr_of_peer2(peer_id); let changed = cache.on_swarm_event(&event); @@ -129,10 +127,12 @@ mod tests { let addr1 = MEMORY_ADDR_1000.clone().with_p2p(peer_id).unwrap(); let addr2 = MEMORY_ADDR_2000.clone().with_p2p(peer_id).unwrap(); - assert!(cache.get(&peer_id).contains(&addr1)); - assert!(cache.get(&peer_id).contains(&addr2)); + let expected_addrs = cache.get(&peer_id).collect::>(); + assert!(expected_addrs.contains(&addr1)); + assert!(expected_addrs.contains(&addr2)); - assert_eq!(cache.get(&peer_id).len(), 2); + let expected = cache.get(&peer_id).collect::>().len(); + assert_eq!(expected, 2); assert!(changed); } @@ -146,13 +146,15 @@ mod tests { let addr1 = MEMORY_ADDR_1000.clone().with_p2p(peer_id).unwrap(); let changed = cache.on_swarm_event(&event); + let expected = cache.get(&peer_id).collect::>(); assert!(changed); - assert_eq!(cache.get(&peer_id), vec![addr1]); + assert_eq!(expected, vec![addr1]); let addr1 = MEMORY_ADDR_1000.clone().with_p2p(peer_id).unwrap(); let changed = cache.on_swarm_event(&event); + let expected = cache.get(&peer_id).collect::>(); assert!(!changed); - assert_eq!(cache.get(&peer_id), [addr1]); + assert_eq!(expected, [addr1]); } #[test] @@ -166,7 +168,8 @@ mod tests { let changed = cache.on_swarm_event(&event); assert!(changed); - assert_eq!(cache.get(&peer_id), []); + let expected = cache.get(&peer_id).collect::>(); + assert_eq!(expected, []); } #[test] @@ -177,7 +180,7 @@ mod tests { cache.put(peer_id, std::iter::once(addr.clone())); - assert!(cache.pop(&peer_id, &addr)); + assert!(cache.remove(&peer_id, &addr)); } #[test] @@ -186,7 +189,7 @@ mod tests { let peer_id = PeerId::random(); let addr: Multiaddr = "/ip4/127.0.0.1/tcp/8080".parse().unwrap(); - assert!(!cache.pop(&peer_id, &addr)); + assert!(!cache.remove(&peer_id, &addr)); } #[test] @@ -195,7 +198,7 @@ mod tests { let peer_id = PeerId::random(); let addr: Multiaddr = "/ip4/127.0.0.1/tcp/8080".parse().unwrap(); - assert!(!cache.pop(&peer_id, &addr)); + assert!(!cache.remove(&peer_id, &addr)); } fn new_external_addr_of_peer1(peer_id: PeerId) -> FromSwarm<'static> { From c30643470b6bc65a20b500a59899bfbb26b3e3ec Mon Sep 17 00:00:00 2001 From: StemCll Date: Thu, 14 Dec 2023 17:52:47 +0100 Subject: [PATCH 07/23] Remove public get_mut from peer addresses --- protocols/identify/src/behaviour.rs | 18 +++++++----------- swarm/src/behaviour/peer_addresses.rs | 8 ++------ 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/protocols/identify/src/behaviour.rs b/protocols/identify/src/behaviour.rs index 6adc11f2a41..f013ff6265c 100644 --- a/protocols/identify/src/behaviour.rs +++ b/protocols/identify/src/behaviour.rs @@ -199,9 +199,9 @@ impl Behaviour { .or_default() .insert(conn, addr); - if let Some(entry) = self.discovered_peers.get_mut(&peer_id) { + if let Some(cache) = self.discovered_peers.0.as_mut() { for addr in failed_addresses { - entry.remove(addr); + cache.remove(&peer_id, addr); } } } @@ -386,11 +386,11 @@ impl NetworkBehaviour for Behaviour { self.our_observed_addresses.remove(&connection_id); } FromSwarm::DialFailure(DialFailure { peer_id, error, .. }) => { - if let Some(entry) = peer_id.and_then(|id| self.discovered_peers.get_mut(&id)) { - if let DialError::Transport(errors) = error { - for (addr, _error) in errors { - entry.remove(addr); - } + if let (Some(peer_id), Some(cache), DialError::Transport(errors)) = + (peer_id, self.discovered_peers.0.as_mut(), error) + { + for (addr, _error) in errors { + cache.remove(&peer_id, addr); } } } @@ -455,10 +455,6 @@ impl PeerCache { Self(Some(PeerAddresses::new(size))) } - fn get_mut(&mut self, peer: &PeerId) -> Option<&mut HashSet> { - self.0.as_mut()?.get_mut(peer) - } - fn put(&mut self, peer: PeerId, addresses: impl Iterator) { if let Some(cache) = self.0.as_mut() { cache.put(peer, addresses); diff --git a/swarm/src/behaviour/peer_addresses.rs b/swarm/src/behaviour/peer_addresses.rs index 9076e73d116..fb8b144366d 100644 --- a/swarm/src/behaviour/peer_addresses.rs +++ b/swarm/src/behaviour/peer_addresses.rs @@ -20,7 +20,7 @@ impl PeerAddresses { pub fn on_swarm_event(&mut self, event: &FromSwarm) -> bool { match event { FromSwarm::NewExternalAddrOfPeer(NewExternalAddrOfPeer { peer_id, addr }) => { - if let Some(peer_addrs) = self.get_mut(peer_id) { + if let Some(peer_addrs) = self.0.get_mut(peer_id) { let addr = prepare_addr(peer_id, addr); peer_addrs.insert(addr) } else { @@ -42,10 +42,6 @@ impl PeerAddresses { Self(LruCache::new(cache_size)) } - pub fn get_mut(&mut self, peer: &PeerId) -> Option<&mut HashSet> { - self.0.get_mut(peer) - } - pub fn put(&mut self, peer: PeerId, addresses: impl Iterator) -> bool { let addresses = addresses.filter_map(|a| a.with_p2p(peer).ok()); self.0.put(peer, HashSet::from_iter(addresses)); @@ -65,7 +61,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 { - self.get_mut(peer).map_or_else( + self.0.get_mut(peer).map_or_else( || false, |addrs| { let address = prepare_addr(peer, address); From 6619f0deea13f540de2f7caf7637244ac0f93908 Mon Sep 17 00:00:00 2001 From: StemCll Date: Sun, 17 Dec 2023 12:40:08 +0100 Subject: [PATCH 08/23] identify: emit when identified new peer; add changelog entries and versions --- Cargo.lock | 8 +-- Cargo.toml | 8 +-- protocols/autonat/CHANGELOG.md | 5 ++ protocols/autonat/Cargo.toml | 2 +- protocols/identify/CHANGELOG.md | 5 ++ protocols/identify/Cargo.toml | 2 +- protocols/identify/src/behaviour.rs | 74 ++++++++++++++++++++++++- protocols/request-response/CHANGELOG.md | 5 ++ protocols/request-response/Cargo.toml | 6 +- swarm/Cargo.toml | 2 +- 10 files changed, 102 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d465ba6e376..ebceba7522d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2629,7 +2629,7 @@ dependencies = [ [[package]] name = "libp2p-autonat" -version = "0.12.0" +version = "0.12.1" dependencies = [ "async-std", "async-trait", @@ -2808,7 +2808,7 @@ dependencies = [ [[package]] name = "libp2p-identify" -version = "0.44.1" +version = "0.45.0" dependencies = [ "async-std", "asynchronous-codec", @@ -3198,7 +3198,7 @@ dependencies = [ [[package]] name = "libp2p-request-response" -version = "0.26.1" +version = "0.27.0" dependencies = [ "anyhow", "async-std", @@ -3247,7 +3247,7 @@ dependencies = [ [[package]] name = "libp2p-swarm" -version = "0.44.1" +version = "0.44.2" dependencies = [ "async-std", "either", diff --git a/Cargo.toml b/Cargo.toml index c0f97b006a9..d6bddc80d90 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -74,14 +74,14 @@ asynchronous-codec = { version = "0.7.0" } futures-bounded = { version = "0.2.3", path = "misc/futures-bounded" } libp2p = { version = "0.53.2", path = "libp2p" } libp2p-allow-block-list = { version = "0.3.0", path = "misc/allow-block-list" } -libp2p-autonat = { version = "0.12.0", path = "protocols/autonat" } +libp2p-autonat = { version = "0.12.1", path = "protocols/autonat" } libp2p-connection-limits = { version = "0.3.1", path = "misc/connection-limits" } libp2p-core = { version = "0.41.2", path = "core" } libp2p-dcutr = { version = "0.11.0", path = "protocols/dcutr" } libp2p-dns = { version = "0.41.1", path = "transports/dns" } libp2p-floodsub = { version = "0.44.0", path = "protocols/floodsub" } libp2p-gossipsub = { version = "0.46.1", path = "protocols/gossipsub" } -libp2p-identify = { version = "0.44.1", path = "protocols/identify" } +libp2p-identify = { version = "0.45.0", path = "protocols/identify" } libp2p-identity = { version = "0.2.8" } libp2p-kad = { version = "0.45.3", path = "protocols/kad" } libp2p-mdns = { version = "0.45.1", path = "protocols/mdns" } @@ -97,10 +97,10 @@ libp2p-pnet = { version = "0.24.0", path = "transports/pnet" } libp2p-quic = { version = "0.10.2", path = "transports/quic" } libp2p-relay = { version = "0.17.1", path = "protocols/relay" } libp2p-rendezvous = { version = "0.14.0", path = "protocols/rendezvous" } -libp2p-request-response = { version = "0.26.1", path = "protocols/request-response" } +libp2p-request-response = { version = "0.27.0", path = "protocols/request-response" } libp2p-server = { version = "0.12.5", path = "misc/server" } -libp2p-swarm = { version = "0.44.1", path = "swarm" } libp2p-swarm-derive = { version = "=0.35.0", 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 = { version = "0.44.2", path = "swarm" } libp2p-swarm-test = { version = "0.3.0", path = "swarm-test" } libp2p-tcp = { version = "0.41.0", path = "transports/tcp" } libp2p-tls = { version = "0.3.0", path = "transports/tls" } diff --git a/protocols/autonat/CHANGELOG.md b/protocols/autonat/CHANGELOG.md index 1259dd01fd4..484bb11b97a 100644 --- a/protocols/autonat/CHANGELOG.md +++ b/protocols/autonat/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.12.1 - unreleased + +- Allow temporary use of deprecated `libp2p_request_response::add_address`. + See [PR 4371](https://github.com/libp2p/rust-libp2p/pull/4371) + ## 0.12.0 - Remove `Clone`, `PartialEq` and `Eq` implementations on `Event` and its sub-structs. diff --git a/protocols/autonat/Cargo.toml b/protocols/autonat/Cargo.toml index a1ecae7ccab..4f44c2fb7a9 100644 --- a/protocols/autonat/Cargo.toml +++ b/protocols/autonat/Cargo.toml @@ -3,8 +3,8 @@ name = "libp2p-autonat" edition = "2021" rust-version = { workspace = true } description = "NAT and firewall detection for libp2p" -version = "0.12.0" authors = ["David Craven ", "Elena Frank "] +version = "0.12.1" license = "MIT" repository = "https://github.com/libp2p/rust-libp2p" keywords = ["peer-to-peer", "libp2p", "networking"] diff --git a/protocols/identify/CHANGELOG.md b/protocols/identify/CHANGELOG.md index 22c74b28cae..00681fdba84 100644 --- a/protocols/identify/CHANGELOG.md +++ b/protocols/identify/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.45.0 - unreleased + +- Emit `ToSwarm::NewExternalAddrOfPeer` when identified new peer. `PeerCache` uses `libp2p_swarm::PeerAddresses` + See [PR 4371](https://github.com/libp2p/rust-libp2p/pull/4371) + ## 0.44.1 - Ensure `Multiaddr` handled and returned by `Behaviour` are `/p2p` terminated. diff --git a/protocols/identify/Cargo.toml b/protocols/identify/Cargo.toml index cd5a26d79ac..7211b9efc48 100644 --- a/protocols/identify/Cargo.toml +++ b/protocols/identify/Cargo.toml @@ -3,7 +3,7 @@ name = "libp2p-identify" edition = "2021" rust-version = { workspace = true } description = "Nodes identifcation protocol for libp2p" -version = "0.44.1" +version = "0.45.0" authors = ["Parity Technologies "] license = "MIT" repository = "https://github.com/libp2p/rust-libp2p" diff --git a/protocols/identify/src/behaviour.rs b/protocols/identify/src/behaviour.rs index f013ff6265c..953163af1ac 100644 --- a/protocols/identify/src/behaviour.rs +++ b/protocols/identify/src/behaviour.rs @@ -273,7 +273,19 @@ impl NetworkBehaviour for Behaviour { let observed = info.observed_addr.clone(); self.events - .push_back(ToSwarm::GenerateEvent(Event::Received { peer_id, info })); + .push_back(ToSwarm::GenerateEvent(Event::Received { + peer_id, + info: info.clone(), + })); + + filter_new_external_addrs(&self.discovered_peers.get(&peer_id), &info.listen_addrs) + .iter() + .for_each(|address| { + self.events.push_back(ToSwarm::NewExternalAddrOfPeer { + peer_id, + addr: address.clone(), + }) + }); match self.our_observed_addresses.entry(id) { Entry::Vacant(not_yet_observed) => { @@ -444,6 +456,20 @@ fn multiaddr_matches_peer_id(addr: &Multiaddr, peer_id: &PeerId) -> bool { true } +fn filter_new_external_addrs( + cached_addrs: &[Multiaddr], + listen_addrs: &Vec, +) -> Vec { + let mut new_addresses = Vec::::new(); + + for address in listen_addrs { + if !cached_addrs.contains(address) { + new_addresses.push(address.clone()); + } + } + new_addresses +} + struct PeerCache(Option); impl PeerCache { @@ -495,4 +521,50 @@ mod tests { )); assert!(multiaddr_matches_peer_id(&addr_without_peer_id, &peer_id)); } + + #[test] + fn filter_new_external_addrs_leaves_new_addrs() { + let addr: Multiaddr = "/ip4/147.75.69.143/tcp/4001" + .parse() + .expect("failed to parse multiaddr"); + + let addr1: Multiaddr = "/ip4/147.75.69.143/tcp/4002" + .parse() + .expect("failed to parse multiaddr"); + + let old_addr: Multiaddr = "/memory/1234".parse().unwrap(); + let old_addr1: Multiaddr = "/memory/1233".parse().unwrap(); + let old_addr2: Multiaddr = "/memory/1235".parse().unwrap(); + + let old_addrs: Vec = [old_addr, old_addr1, old_addr2].to_vec(); + + let new_addrs = Vec::from([addr, addr1]); + + assert_eq!( + filter_new_external_addrs(&old_addrs, &new_addrs), + new_addrs.clone(), + ); + } + + #[test] + fn filter_new_external_addrs_filter_duplicates() { + let addr: Multiaddr = "/ip4/147.75.69.143/tcp/4001" + .parse() + .expect("failed to parse multiaddr"); + + let addr1: Multiaddr = "/ip4/147.75.69.143/tcp/4002" + .parse() + .expect("failed to parse multiaddr"); + + let old_addr: Multiaddr = "/memory/1234".parse().unwrap(); + let old_addr1: Multiaddr = "/memory/1233".parse().unwrap(); + let old_addr2: Multiaddr = "/memory/1235".parse().unwrap(); + + let mut old_addrs: Vec = [old_addr, old_addr1, old_addr2].to_vec(); + + let new_addrs = Vec::from([addr.clone(), addr1.clone()]); + old_addrs.append(&mut new_addrs.clone()); + + assert_eq!(filter_new_external_addrs(&old_addrs, &new_addrs), []) + } } diff --git a/protocols/request-response/CHANGELOG.md b/protocols/request-response/CHANGELOG.md index d53ff479ee2..6ca52ba3304 100644 --- a/protocols/request-response/CHANGELOG.md +++ b/protocols/request-response/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.27.0 - unreleased + +- Deprecate `libp2p_request_response::add_address`. `Behaviour` `addresses` field uses `libp2p_swarm::PeerAddresses`. + See [PR 4371](https://github.com/libp2p/rust-libp2p/pull/4371) + ## 0.26.1 - Derive `PartialOrd` and `Ord` for `{Out,In}boundRequestId`. diff --git a/protocols/request-response/Cargo.toml b/protocols/request-response/Cargo.toml index e85ff691969..2e2be529dad 100644 --- a/protocols/request-response/Cargo.toml +++ b/protocols/request-response/Cargo.toml @@ -3,7 +3,7 @@ name = "libp2p-request-response" edition = "2021" rust-version = { workspace = true } description = "Generic Request/Response Protocols" -version = "0.26.1" +version = "0.27.0" authors = ["Parity Technologies "] license = "MIT" repository = "https://github.com/libp2p/rust-libp2p" @@ -19,7 +19,7 @@ libp2p-core = { workspace = true } libp2p-swarm = { workspace = true } libp2p-identity = { workspace = true } rand = "0.8" -serde = { version = "1.0", optional = true} +serde = { version = "1.0", optional = true } serde_json = { version = "1.0.108", optional = true } smallvec = "1.11.2" tracing = "0.1.37" @@ -40,7 +40,7 @@ libp2p-yamux = { workspace = true } rand = "0.8" libp2p-swarm-test = { path = "../../swarm-test" } futures_ringbuf = "0.4.0" -serde = { version = "1.0", features = ["derive"]} +serde = { version = "1.0", features = ["derive"] } tracing-subscriber = { version = "0.3", features = ["env-filter"] } # Passing arguments to the docsrs builder in order to properly document cfg's. diff --git a/swarm/Cargo.toml b/swarm/Cargo.toml index 420c72d4556..20564fc7614 100644 --- a/swarm/Cargo.toml +++ b/swarm/Cargo.toml @@ -3,7 +3,7 @@ name = "libp2p-swarm" edition = "2021" rust-version = { workspace = true } description = "The libp2p swarm" -version = "0.44.1" +version = "0.44.2" authors = ["Parity Technologies "] license = "MIT" repository = "https://github.com/libp2p/rust-libp2p" From 1bda7747e5784d72e8d0377b648cb5545d5e4903 Mon Sep 17 00:00:00 2001 From: StemCll Date: Mon, 25 Dec 2023 18:58:21 +0100 Subject: [PATCH 09/23] Revert version changes --- Cargo.lock | 6 +++--- Cargo.toml | 6 +++--- protocols/identify/CHANGELOG.md | 2 +- protocols/identify/Cargo.toml | 2 +- protocols/request-response/CHANGELOG.md | 2 +- protocols/request-response/Cargo.toml | 2 +- swarm-derive/CHANGELOG.md | 2 +- swarm-derive/Cargo.toml | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ebceba7522d..4824ccbf607 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2808,7 +2808,7 @@ dependencies = [ [[package]] name = "libp2p-identify" -version = "0.45.0" +version = "0.44.2" dependencies = [ "async-std", "asynchronous-codec", @@ -3198,7 +3198,7 @@ dependencies = [ [[package]] name = "libp2p-request-response" -version = "0.27.0" +version = "0.26.2" dependencies = [ "anyhow", "async-std", @@ -3281,7 +3281,7 @@ dependencies = [ [[package]] name = "libp2p-swarm-derive" -version = "0.35.0" +version = "0.34.3" dependencies = [ "heck", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index d6bddc80d90..9ddd221f409 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -81,7 +81,7 @@ libp2p-dcutr = { version = "0.11.0", path = "protocols/dcutr" } libp2p-dns = { version = "0.41.1", path = "transports/dns" } libp2p-floodsub = { version = "0.44.0", path = "protocols/floodsub" } libp2p-gossipsub = { version = "0.46.1", path = "protocols/gossipsub" } -libp2p-identify = { version = "0.45.0", path = "protocols/identify" } +libp2p-identify = { version = "0.44.2", path = "protocols/identify" } libp2p-identity = { version = "0.2.8" } libp2p-kad = { version = "0.45.3", path = "protocols/kad" } libp2p-mdns = { version = "0.45.1", path = "protocols/mdns" } @@ -97,9 +97,9 @@ libp2p-pnet = { version = "0.24.0", path = "transports/pnet" } libp2p-quic = { version = "0.10.2", path = "transports/quic" } libp2p-relay = { version = "0.17.1", path = "protocols/relay" } libp2p-rendezvous = { version = "0.14.0", path = "protocols/rendezvous" } -libp2p-request-response = { version = "0.27.0", path = "protocols/request-response" } +libp2p-request-response = { version = "0.26.2", path = "protocols/request-response" } libp2p-server = { version = "0.12.5", path = "misc/server" } -libp2p-swarm-derive = { version = "=0.35.0", 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-derive = { version = "=0.34.3", 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 = { version = "0.44.2", path = "swarm" } libp2p-swarm-test = { version = "0.3.0", path = "swarm-test" } libp2p-tcp = { version = "0.41.0", path = "transports/tcp" } diff --git a/protocols/identify/CHANGELOG.md b/protocols/identify/CHANGELOG.md index 00681fdba84..98523325c48 100644 --- a/protocols/identify/CHANGELOG.md +++ b/protocols/identify/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.45.0 - unreleased +## 0.44.2 - unreleased - Emit `ToSwarm::NewExternalAddrOfPeer` when identified new peer. `PeerCache` uses `libp2p_swarm::PeerAddresses` See [PR 4371](https://github.com/libp2p/rust-libp2p/pull/4371) diff --git a/protocols/identify/Cargo.toml b/protocols/identify/Cargo.toml index 7211b9efc48..6fe334e87ac 100644 --- a/protocols/identify/Cargo.toml +++ b/protocols/identify/Cargo.toml @@ -3,7 +3,7 @@ name = "libp2p-identify" edition = "2021" rust-version = { workspace = true } description = "Nodes identifcation protocol for libp2p" -version = "0.45.0" +version = "0.44.2" authors = ["Parity Technologies "] license = "MIT" repository = "https://github.com/libp2p/rust-libp2p" diff --git a/protocols/request-response/CHANGELOG.md b/protocols/request-response/CHANGELOG.md index 6ca52ba3304..a7bc1e487a1 100644 --- a/protocols/request-response/CHANGELOG.md +++ b/protocols/request-response/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.27.0 - unreleased +## 0.26.2 - unreleased - Deprecate `libp2p_request_response::add_address`. `Behaviour` `addresses` field uses `libp2p_swarm::PeerAddresses`. See [PR 4371](https://github.com/libp2p/rust-libp2p/pull/4371) diff --git a/protocols/request-response/Cargo.toml b/protocols/request-response/Cargo.toml index 2e2be529dad..bd750e9e308 100644 --- a/protocols/request-response/Cargo.toml +++ b/protocols/request-response/Cargo.toml @@ -3,7 +3,7 @@ name = "libp2p-request-response" edition = "2021" rust-version = { workspace = true } description = "Generic Request/Response Protocols" -version = "0.27.0" +version = "0.26.2" authors = ["Parity Technologies "] license = "MIT" repository = "https://github.com/libp2p/rust-libp2p" diff --git a/swarm-derive/CHANGELOG.md b/swarm-derive/CHANGELOG.md index 9c97a39915e..9e85729e5ad 100644 --- a/swarm-derive/CHANGELOG.md +++ b/swarm-derive/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.35.0 - unreleased +## 0.34.3 - unreleased - Generate code for `libp2p-swarm`'s `from_swarm::NewExternalAddrOfPeer` enum variant. See [PR 4371](https://github.com/libp2p/rust-libp2p/pull/4371) diff --git a/swarm-derive/Cargo.toml b/swarm-derive/Cargo.toml index 1b13b4b6453..8073a6875e4 100644 --- a/swarm-derive/Cargo.toml +++ b/swarm-derive/Cargo.toml @@ -3,7 +3,7 @@ name = "libp2p-swarm-derive" edition = "2021" rust-version = { workspace = true } description = "Procedural macros of libp2p-swarm" -version = "0.35.0" +version = "0.34.3" authors = ["Parity Technologies "] license = "MIT" repository = "https://github.com/libp2p/rust-libp2p" From 32076ae55b70d60c3c45cbcf418ef2f34aa69d75 Mon Sep 17 00:00:00 2001 From: StemCll Date: Tue, 26 Dec 2023 12:53:58 +0100 Subject: [PATCH 10/23] Extend swarm changelog entry; fix peer_addresses put logic --- Cargo.toml | 2 +- swarm/CHANGELOG.md | 3 + swarm/src/behaviour/peer_addresses.rs | 81 +++++++++++++++++++++++---- 3 files changed, 73 insertions(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9ddd221f409..6b12a4979ce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -99,8 +99,8 @@ libp2p-relay = { version = "0.17.1", path = "protocols/relay" } libp2p-rendezvous = { version = "0.14.0", path = "protocols/rendezvous" } libp2p-request-response = { version = "0.26.2", path = "protocols/request-response" } libp2p-server = { version = "0.12.5", path = "misc/server" } -libp2p-swarm-derive = { version = "=0.34.3", 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 = { version = "0.44.2", path = "swarm" } +libp2p-swarm-derive = { version = "=0.34.3", 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.3.0", path = "swarm-test" } libp2p-tcp = { version = "0.41.0", path = "transports/tcp" } libp2p-tls = { version = "0.3.0", path = "transports/tls" } diff --git a/swarm/CHANGELOG.md b/swarm/CHANGELOG.md index 1e88282758c..e595cceae0f 100644 --- a/swarm/CHANGELOG.md +++ b/swarm/CHANGELOG.md @@ -1,6 +1,9 @@ ## 0.44.2 - unreleased - Add `FromSwarm::NewExternalAddrOfPeer` event. +- Add `libp2p::swarm::add_peer_address` that broadcasts address through `FromSwarm::NewExternalAddrOfPeer`. +- Add `libp2p_swarm::behaviour::PeerAddresses` which is used as a cache for storing known addresses + of connected peers. See [PR 4371](https://github.com/libp2p/rust-libp2p/pull/4371) ## 0.44.1 diff --git a/swarm/src/behaviour/peer_addresses.rs b/swarm/src/behaviour/peer_addresses.rs index fb8b144366d..ff164785d54 100644 --- a/swarm/src/behaviour/peer_addresses.rs +++ b/swarm/src/behaviour/peer_addresses.rs @@ -14,6 +14,11 @@ use std::num::NonZeroUsize; pub struct PeerAddresses(LruCache>); impl PeerAddresses { + /// Creates cache with capacity of `cache_size`. + pub fn new(cache_size: NonZeroUsize) -> Self { + Self(LruCache::new(cache_size)) + } + /// Feed a [`FromSwarm`] event to this struct. /// /// Returns whether the event changed peer's known external addresses. @@ -38,24 +43,30 @@ impl PeerAddresses { } } - pub fn new(cache_size: NonZeroUsize) -> Self { - Self(LruCache::new(cache_size)) - } - + /// Adds addresses to cache. + /// Appends addresses to the existing set if peer addresses already exist. + /// Creates a new cache entry for peer_id if no addresses are present. + /// Returns true if the newly added addresses were not previously in the cache. pub fn put(&mut self, peer: PeerId, addresses: impl Iterator) -> bool { let addresses = addresses.filter_map(|a| a.with_p2p(peer).ok()); - self.0.put(peer, HashSet::from_iter(addresses)); - true + if let Some(cached) = self.0.get_mut(&peer) { + let mut inserted_any = false; + for addr in addresses { + if cached.insert(addr) { + inserted_any = true; + } + } + + inserted_any + } else { + self.0.put(peer, HashSet::from_iter(addresses)); + true + } } /// Returns peer's external addresses. pub fn get(&mut self, peer: &PeerId) -> impl Iterator { - self.0 - .get(peer) - .cloned() - .map(Vec::from_iter) - .unwrap_or_default() - .into_iter() + self.0.get(peer).cloned().unwrap_or_default().into_iter() } /// Removes address from peer addresses cache. @@ -197,6 +208,52 @@ mod tests { assert!(!cache.remove(&peer_id, &addr)); } + #[test] + fn put_adds_new_address_to_cache() { + let mut cache = PeerAddresses::default(); + let peer_id = PeerId::random(); + let addr: Multiaddr = "/ip4/127.0.0.1/tcp/8080".parse().unwrap(); + + assert!(cache.put(peer_id, [addr.clone()].into_iter())); + + let mut cached = cache.get(&peer_id).collect::>(); + cached.sort(); + let expected = prepare_expected_addrs(peer_id, [addr].into_iter()); + + assert_eq!(cached, expected); + } + + #[test] + fn put_adds_address_to_cache_to_existing_key() { + let mut cache = PeerAddresses::default(); + let peer_id = PeerId::random(); + let addr: Multiaddr = "/ip4/127.0.0.1/tcp/8080".parse().unwrap(); + let addr2: Multiaddr = "/ip4/127.0.0.1/tcp/8081".parse().unwrap(); + let addr3: Multiaddr = "/ip4/127.0.0.1/tcp/8082".parse().unwrap(); + + assert!(cache.put(peer_id, [addr.clone()].into_iter())); + + cache.put(peer_id, [addr2.clone(), addr3.clone()].into_iter()); + + let expected = prepare_expected_addrs(peer_id, [addr, addr2, addr3].into_iter()); + + let mut cached = cache.get(&peer_id).collect::>(); + cached.sort(); + + assert_eq!(cached, expected); + } + + fn prepare_expected_addrs( + peer_id: PeerId, + addrs: impl Iterator, + ) -> Vec { + let mut addrs = addrs + .filter_map(|a| a.with_p2p(peer_id).ok()) + .collect::>(); + addrs.sort(); + addrs + } + fn new_external_addr_of_peer1(peer_id: PeerId) -> FromSwarm<'static> { FromSwarm::NewExternalAddrOfPeer(NewExternalAddrOfPeer { peer_id, From 2277bd617ca568b19d83bdc4a7a181e678d44141 Mon Sep 17 00:00:00 2001 From: StemCll Date: Tue, 26 Dec 2023 13:01:08 +0100 Subject: [PATCH 11/23] Add additional test for remove --- swarm/src/behaviour/peer_addresses.rs | 29 ++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/swarm/src/behaviour/peer_addresses.rs b/swarm/src/behaviour/peer_addresses.rs index ff164785d54..34f41c49fa5 100644 --- a/swarm/src/behaviour/peer_addresses.rs +++ b/swarm/src/behaviour/peer_addresses.rs @@ -180,7 +180,7 @@ mod tests { } #[test] - fn pop_removes_address_if_present() { + fn remove_removes_address_if_present() { let mut cache = PeerAddresses::default(); let peer_id = PeerId::random(); let addr: Multiaddr = "/ip4/127.0.0.1/tcp/8080".parse().unwrap(); @@ -191,7 +191,7 @@ mod tests { } #[test] - fn pop_returns_false_if_address_not_present() { + fn remove_returns_false_if_address_not_present() { let mut cache = PeerAddresses::default(); let peer_id = PeerId::random(); let addr: Multiaddr = "/ip4/127.0.0.1/tcp/8080".parse().unwrap(); @@ -200,7 +200,7 @@ mod tests { } #[test] - fn pop_returns_false_if_peer_not_present() { + fn remove_returns_false_if_peer_not_present() { let mut cache = PeerAddresses::default(); let peer_id = PeerId::random(); let addr: Multiaddr = "/ip4/127.0.0.1/tcp/8080".parse().unwrap(); @@ -208,6 +208,29 @@ mod tests { assert!(!cache.remove(&peer_id, &addr)); } + #[test] + fn remove_removes_address_provided_in_param() { + let mut cache = PeerAddresses::default(); + let peer_id = PeerId::random(); + let addr: Multiaddr = "/ip4/127.0.0.1/tcp/8080".parse().unwrap(); + let addr2: Multiaddr = "/ip4/127.0.0.1/tcp/8081".parse().unwrap(); + let addr3: Multiaddr = "/ip4/127.0.0.1/tcp/8082".parse().unwrap(); + + cache.put( + peer_id, + [addr.clone(), addr2.clone(), addr3.clone()].into_iter(), + ); + + assert!(cache.remove(&peer_id, &addr2)); + + let mut cached = cache.get(&peer_id).collect::>(); + cached.sort(); + + let expected = prepare_expected_addrs(peer_id, [addr, addr3].into_iter()); + + assert_eq!(cached, expected); + } + #[test] fn put_adds_new_address_to_cache() { let mut cache = PeerAddresses::default(); From 8e1dc1e8aa7c40ab66d92a088e3290772d36556e Mon Sep 17 00:00:00 2001 From: StemCll Date: Wed, 27 Dec 2023 01:11:15 +0100 Subject: [PATCH 12/23] Add connection test to request response --- protocols/identify/src/behaviour.rs | 15 ++--- .../request-response/tests/peer_address.rs | 60 +++++++++++++++++++ 2 files changed, 68 insertions(+), 7 deletions(-) create mode 100644 protocols/request-response/tests/peer_address.rs diff --git a/protocols/identify/src/behaviour.rs b/protocols/identify/src/behaviour.rs index 953163af1ac..dd96e99108a 100644 --- a/protocols/identify/src/behaviour.rs +++ b/protocols/identify/src/behaviour.rs @@ -278,14 +278,15 @@ impl NetworkBehaviour for Behaviour { info: info.clone(), })); - filter_new_external_addrs(&self.discovered_peers.get(&peer_id), &info.listen_addrs) - .iter() - .for_each(|address| { - self.events.push_back(ToSwarm::NewExternalAddrOfPeer { - peer_id, - addr: address.clone(), - }) + for address in filter_new_external_addrs( + &self.discovered_peers.get(&peer_id), + &info.listen_addrs, + ) { + self.events.push_back(ToSwarm::NewExternalAddrOfPeer { + peer_id, + addr: address.clone(), }); + } match self.our_observed_addresses.entry(id) { Entry::Vacant(not_yet_observed) => { diff --git a/protocols/request-response/tests/peer_address.rs b/protocols/request-response/tests/peer_address.rs new file mode 100644 index 00000000000..2bb4fec3fc3 --- /dev/null +++ b/protocols/request-response/tests/peer_address.rs @@ -0,0 +1,60 @@ +use libp2p_core::ConnectedPoint; +use libp2p_request_response as request_response; +use libp2p_request_response::ProtocolSupport; +use libp2p_swarm::{StreamProtocol, Swarm, SwarmEvent}; +use libp2p_swarm_test::SwarmExt; +use serde::{Deserialize, Serialize}; +use std::iter; +use tracing_subscriber::EnvFilter; + +#[async_std::test] +async fn dial_succeeds_after_adding_peers_address() { + let _ = tracing_subscriber::fmt() + .with_env_filter(EnvFilter::from_default_env()) + .try_init(); + + let protocols = iter::once((StreamProtocol::new("/ping/1"), ProtocolSupport::Full)); + let config = request_response::Config::default(); + + let mut swarm = Swarm::new_ephemeral(|_| { + request_response::cbor::Behaviour::::new(protocols.clone(), config.clone()) + }); + + let mut swarm2 = Swarm::new_ephemeral(|_| { + request_response::cbor::Behaviour::::new(protocols.clone(), config.clone()) + }); + + let peer_id2 = *swarm2.local_peer_id(); + + let (listen_addr, _) = swarm2.listen().with_memory_addr_external().await; + + swarm.add_peer_address(peer_id2.clone(), listen_addr.clone()); + + swarm.dial(peer_id2.clone()).unwrap(); + + async_std::task::spawn(swarm2.loop_on_next()); + + let (connected_peer_id, connected_address) = swarm + .wait(|event| match event { + SwarmEvent::ConnectionEstablished { + peer_id, endpoint, .. + } => { + let address = match endpoint { + ConnectedPoint::Dialer { address, .. } => Some(address), + _ => None, + }; + Some((peer_id, address)) + } + _ => None, + }) + .await; + let expected_address = listen_addr.with_p2p(peer_id2).unwrap(); + + assert_eq!(connected_peer_id, peer_id2); + assert_eq!(expected_address, connected_address.unwrap()); +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +struct Ping(Vec); +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +struct Pong(Vec); From 056d51e3ca5f62ffead343e9c5f20e9c687037e5 Mon Sep 17 00:00:00 2001 From: StemCll Date: Wed, 27 Dec 2023 01:17:01 +0100 Subject: [PATCH 13/23] Rever toml file format changes --- Cargo.toml | 8 ++------ swarm-derive/Cargo.toml | 8 +------- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6b12a4979ce..c9ba3ff3387 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -100,7 +100,7 @@ libp2p-rendezvous = { version = "0.14.0", path = "protocols/rendezvous" } libp2p-request-response = { version = "0.26.2", path = "protocols/request-response" } libp2p-server = { version = "0.12.5", path = "misc/server" } libp2p-swarm = { version = "0.44.2", path = "swarm" } -libp2p-swarm-derive = { version = "=0.34.3", 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-derive = { version = "=0.34.3", 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.3.0", path = "swarm-test" } libp2p-tcp = { version = "0.41.0", path = "transports/tcp" } libp2p-tls = { version = "0.3.0", path = "transports/tls" } @@ -141,8 +141,4 @@ clippy.manual_let_else = "warn" clippy.dbg_macro = "warn" [workspace.metadata.release] -pre-release-hook = [ - "/bin/sh", - '-c', - '/bin/sh $WORKSPACE_ROOT/scripts/add-changelog-header.sh', -] # Nested use of shell to expand variables. +pre-release-hook = ["/bin/sh", '-c', '/bin/sh $WORKSPACE_ROOT/scripts/add-changelog-header.sh'] # Nested use of shell to expand variables. diff --git a/swarm-derive/Cargo.toml b/swarm-derive/Cargo.toml index 8073a6875e4..f3c75749602 100644 --- a/swarm-derive/Cargo.toml +++ b/swarm-derive/Cargo.toml @@ -16,13 +16,7 @@ proc-macro = true [dependencies] heck = "0.4" quote = "1.0" -syn = { version = "2.0.43", default-features = false, features = [ - "clone-impls", - "derive", - "parsing", - "printing", - "proc-macro", -] } +syn = { version = "2.0.43", default-features = false, features = ["clone-impls", "derive", "parsing", "printing", "proc-macro"] } proc-macro2 = "1.0" # Passing arguments to the docsrs builder in order to properly document cfg's. From b8f8bc581d09008f46bee32d1b4b2050c9ff5e47 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Wed, 27 Dec 2023 19:17:14 +1100 Subject: [PATCH 14/23] Documentation fixes --- protocols/identify/CHANGELOG.md | 4 ++-- protocols/request-response/CHANGELOG.md | 6 +++--- swarm-derive/CHANGELOG.md | 6 +++--- swarm/CHANGELOG.md | 12 ++++++------ swarm/src/lib.rs | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/protocols/identify/CHANGELOG.md b/protocols/identify/CHANGELOG.md index 98523325c48..879fcaf457f 100644 --- a/protocols/identify/CHANGELOG.md +++ b/protocols/identify/CHANGELOG.md @@ -1,7 +1,7 @@ ## 0.44.2 - unreleased -- Emit `ToSwarm::NewExternalAddrOfPeer` when identified new peer. `PeerCache` uses `libp2p_swarm::PeerAddresses` - See [PR 4371](https://github.com/libp2p/rust-libp2p/pull/4371) +- Emit `ToSwarm::NewExternalAddrOfPeer` for all external addresses of remote peers. + See [PR 4371](https://github.com/libp2p/rust-libp2p/pull/4371). ## 0.44.1 diff --git a/protocols/request-response/CHANGELOG.md b/protocols/request-response/CHANGELOG.md index a7bc1e487a1..92417508786 100644 --- a/protocols/request-response/CHANGELOG.md +++ b/protocols/request-response/CHANGELOG.md @@ -1,7 +1,7 @@ -## 0.26.2 - unreleased +## 0.26.2 -- Deprecate `libp2p_request_response::add_address`. `Behaviour` `addresses` field uses `libp2p_swarm::PeerAddresses`. - See [PR 4371](https://github.com/libp2p/rust-libp2p/pull/4371) +- Deprecate `Behaviour::add_address` in favor of `Swarm::add_peer_address`. + See [PR 4371](https://github.com/libp2p/rust-libp2p/pull/4371). ## 0.26.1 diff --git a/swarm-derive/CHANGELOG.md b/swarm-derive/CHANGELOG.md index 9e85729e5ad..55f5e571664 100644 --- a/swarm-derive/CHANGELOG.md +++ b/swarm-derive/CHANGELOG.md @@ -1,7 +1,7 @@ -## 0.34.3 - unreleased +## 0.34.3 -- Generate code for `libp2p-swarm`'s `from_swarm::NewExternalAddrOfPeer` enum variant. - See [PR 4371](https://github.com/libp2p/rust-libp2p/pull/4371) +- Generate code for `libp2p-swarm`'s `FromSwarm::NewExternalAddrOfPeer` enum variant. + See [PR 4371](https://github.com/libp2p/rust-libp2p/pull/4371). ## 0.34.2 diff --git a/swarm/CHANGELOG.md b/swarm/CHANGELOG.md index e595cceae0f..3d8e3981c96 100644 --- a/swarm/CHANGELOG.md +++ b/swarm/CHANGELOG.md @@ -1,10 +1,10 @@ -## 0.44.2 - unreleased +## 0.44.2 -- Add `FromSwarm::NewExternalAddrOfPeer` event. -- Add `libp2p::swarm::add_peer_address` that broadcasts address through `FromSwarm::NewExternalAddrOfPeer`. -- Add `libp2p_swarm::behaviour::PeerAddresses` which is used as a cache for storing known addresses - of connected peers. - See [PR 4371](https://github.com/libp2p/rust-libp2p/pull/4371) +- Allow `NetworkBehaviour`s to share addresses of peers. + This is enabled via the new `ToSwarm::NewExternalAddrOfPeer` event. + The address is broadcast to all behaviours via `FromSwarm::NewExternalAddrOfPeer`. + Protocols that want to collect these addresses can use the new `PeerAddresses` utility. + See [PR 4371](https://github.com/libp2p/rust-libp2p/pull/4371). ## 0.44.1 diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index 8a7218d9136..501298357b1 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -624,7 +624,7 @@ where self.confirmed_external_addr.remove(addr); } - /// Add peer's new external address. + /// Add a new external address of a remote peer. /// /// The address is broadcast to all [`NetworkBehaviour`]s via [`FromSwarm::NewExternalAddrOfPeer`]. pub fn add_peer_address(&mut self, peer_id: PeerId, addr: Multiaddr) { From f5f162cd7335eadb16b750b265cb7eb8dc25b496 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Wed, 27 Dec 2023 19:18:07 +1100 Subject: [PATCH 15/23] Update protocols/identify/CHANGELOG.md --- protocols/identify/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocols/identify/CHANGELOG.md b/protocols/identify/CHANGELOG.md index 879fcaf457f..5eeb85d3989 100644 --- a/protocols/identify/CHANGELOG.md +++ b/protocols/identify/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.44.2 - unreleased +## 0.44.2 - Emit `ToSwarm::NewExternalAddrOfPeer` for all external addresses of remote peers. See [PR 4371](https://github.com/libp2p/rust-libp2p/pull/4371). From ff81f51d09cba72e28d935d58cdaa2bb994d07d3 Mon Sep 17 00:00:00 2001 From: StemCll Date: Wed, 27 Dec 2023 19:54:22 +0100 Subject: [PATCH 16/23] Revert autonat version bump --- Cargo.lock | 2 +- Cargo.toml | 2 +- protocols/autonat/CHANGELOG.md | 5 ----- protocols/autonat/Cargo.toml | 2 +- 4 files changed, 3 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4824ccbf607..b507fd62060 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2629,7 +2629,7 @@ dependencies = [ [[package]] name = "libp2p-autonat" -version = "0.12.1" +version = "0.12.0" dependencies = [ "async-std", "async-trait", diff --git a/Cargo.toml b/Cargo.toml index c9ba3ff3387..660559a6c41 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -74,7 +74,7 @@ asynchronous-codec = { version = "0.7.0" } futures-bounded = { version = "0.2.3", path = "misc/futures-bounded" } libp2p = { version = "0.53.2", path = "libp2p" } libp2p-allow-block-list = { version = "0.3.0", path = "misc/allow-block-list" } -libp2p-autonat = { version = "0.12.1", path = "protocols/autonat" } +libp2p-autonat = { version = "0.12.0", path = "protocols/autonat" } libp2p-connection-limits = { version = "0.3.1", path = "misc/connection-limits" } libp2p-core = { version = "0.41.2", path = "core" } libp2p-dcutr = { version = "0.11.0", path = "protocols/dcutr" } diff --git a/protocols/autonat/CHANGELOG.md b/protocols/autonat/CHANGELOG.md index 484bb11b97a..1259dd01fd4 100644 --- a/protocols/autonat/CHANGELOG.md +++ b/protocols/autonat/CHANGELOG.md @@ -1,8 +1,3 @@ -## 0.12.1 - unreleased - -- Allow temporary use of deprecated `libp2p_request_response::add_address`. - See [PR 4371](https://github.com/libp2p/rust-libp2p/pull/4371) - ## 0.12.0 - Remove `Clone`, `PartialEq` and `Eq` implementations on `Event` and its sub-structs. diff --git a/protocols/autonat/Cargo.toml b/protocols/autonat/Cargo.toml index 4f44c2fb7a9..fce64ad0c12 100644 --- a/protocols/autonat/Cargo.toml +++ b/protocols/autonat/Cargo.toml @@ -4,7 +4,7 @@ edition = "2021" rust-version = { workspace = true } description = "NAT and firewall detection for libp2p" authors = ["David Craven ", "Elena Frank "] -version = "0.12.1" +version = "0.12.0" license = "MIT" repository = "https://github.com/libp2p/rust-libp2p" keywords = ["peer-to-peer", "libp2p", "networking"] From 496c1855244b9dec01bd66789d3a76de590fcf0e Mon Sep 17 00:00:00 2001 From: StemCll Date: Mon, 1 Jan 2024 23:06:44 +0100 Subject: [PATCH 17/23] Rename put to add in PeerAddresses --- protocols/identify/src/behaviour.rs | 4 +- protocols/request-response/src/lib.rs | 4 +- swarm/src/behaviour/peer_addresses.rs | 117 +++++++++++++++----------- 3 files changed, 75 insertions(+), 50 deletions(-) diff --git a/protocols/identify/src/behaviour.rs b/protocols/identify/src/behaviour.rs index dd96e99108a..ce1af568ae4 100644 --- a/protocols/identify/src/behaviour.rs +++ b/protocols/identify/src/behaviour.rs @@ -484,7 +484,9 @@ impl PeerCache { fn put(&mut self, peer: PeerId, addresses: impl Iterator) { if let Some(cache) = self.0.as_mut() { - cache.put(peer, addresses); + for address in addresses { + cache.add(peer, address); + } } } diff --git a/protocols/request-response/src/lib.rs b/protocols/request-response/src/lib.rs index 3553c829993..e6781ef46de 100644 --- a/protocols/request-response/src/lib.rs +++ b/protocols/request-response/src/lib.rs @@ -470,9 +470,9 @@ where /// /// Returns true if the address was added, false otherwise (i.e. if the /// address is already in the list). - #[deprecated(note = "Use `libp2p_swarm::Swarm::add_peer_address` instead.")] + #[deprecated(note = "Use `Swarm::add_peer_address` instead.")] pub fn add_address(&mut self, peer: &PeerId, address: Multiaddr) -> bool { - self.addresses.put(*peer, std::iter::once(address)) + self.addresses.add(*peer, address) } /// Removes an address of a peer previously added via [`Behaviour::add_address`]. diff --git a/swarm/src/behaviour/peer_addresses.rs b/swarm/src/behaviour/peer_addresses.rs index 34f41c49fa5..4903d7bf3cf 100644 --- a/swarm/src/behaviour/peer_addresses.rs +++ b/swarm/src/behaviour/peer_addresses.rs @@ -25,41 +25,35 @@ impl PeerAddresses { pub fn on_swarm_event(&mut self, event: &FromSwarm) -> bool { match event { FromSwarm::NewExternalAddrOfPeer(NewExternalAddrOfPeer { peer_id, addr }) => { - if let Some(peer_addrs) = self.0.get_mut(peer_id) { - let addr = prepare_addr(peer_id, addr); - peer_addrs.insert(addr) - } else { - let addr = prepare_addr(peer_id, addr); - self.put(*peer_id, std::iter::once(addr)); - true - } + self.add(*peer_id, (*addr).clone()) } FromSwarm::DialFailure(DialFailure { peer_id: Some(peer_id), - error: DialError::NoAddresses, + error: DialError::Transport(errors), .. - }) => self.0.pop(peer_id).is_some(), + }) => { + for (addr, _error) in errors { + self.remove(peer_id, addr); + } + true + } _ => false, } } - /// Adds addresses to cache. - /// Appends addresses to the existing set if peer addresses already exist. + /// Adds address to cache. + /// Appends address to the existing set if peer addresses already exist. /// Creates a new cache entry for peer_id if no addresses are present. - /// Returns true if the newly added addresses were not previously in the cache. - pub fn put(&mut self, peer: PeerId, addresses: impl Iterator) -> bool { - let addresses = addresses.filter_map(|a| a.with_p2p(peer).ok()); + /// Returns true if the newly added address was not previously in the cache. + /// + pub fn add(&mut self, peer: PeerId, address: Multiaddr) -> bool { + let address = prepare_addr(&peer, &address); if let Some(cached) = self.0.get_mut(&peer) { - let mut inserted_any = false; - for addr in addresses { - if cached.insert(addr) { - inserted_any = true; - } - } - - inserted_any + cached.insert(address) } else { - self.0.put(peer, HashSet::from_iter(addresses)); + let mut set: HashSet = HashSet::new(); + set.insert(address); + self.0.put(peer, set); true } } @@ -95,10 +89,15 @@ impl Default for PeerAddresses { #[cfg(test)] mod tests { + use super::*; + use std::io; + use crate::{ConnectionId, DialError}; + use libp2p_core::{ + multiaddr::Protocol, + transport::{memory::MemoryTransportError, TransportError}, + }; - use super::*; - use libp2p_core::multiaddr::Protocol; use once_cell::sync::Lazy; #[test] @@ -165,18 +164,34 @@ mod tests { } #[test] - fn addrs_of_peer_are_removed_when_received_dial_failure_event() { + fn addresses_of_peer_are_removed_when_received_dial_failure() { let mut cache = PeerAddresses::default(); let peer_id = PeerId::random(); - cache.on_swarm_event(&new_external_addr_of_peer1(peer_id)); - let event = dial_error(peer_id); + let addr: Multiaddr = "/ip4/127.0.0.1/tcp/8080".parse().unwrap(); + let addr2: Multiaddr = "/ip4/127.0.0.1/tcp/8081".parse().unwrap(); + let addr3: Multiaddr = "/ip4/127.0.0.1/tcp/8082".parse().unwrap(); + + cache.add(peer_id, addr.clone()); + cache.add(peer_id, addr2.clone()); + cache.add(peer_id, addr3.clone()); + + let error = DialError::Transport(prepare_errors(vec![addr, addr3])); + + let event = FromSwarm::DialFailure(DialFailure { + peer_id: Some(peer_id), + error: &error, + connection_id: ConnectionId::new_unchecked(8), + }); let changed = cache.on_swarm_event(&event); assert!(changed); - let expected = cache.get(&peer_id).collect::>(); - assert_eq!(expected, []); + + let cached = cache.get(&peer_id).collect::>(); + let expected = prepare_expected_addrs(peer_id, [addr2].into_iter()); + + assert_eq!(cached, expected); } #[test] @@ -185,7 +200,7 @@ mod tests { let peer_id = PeerId::random(); let addr: Multiaddr = "/ip4/127.0.0.1/tcp/8080".parse().unwrap(); - cache.put(peer_id, std::iter::once(addr.clone())); + cache.add(peer_id, addr.clone()); assert!(cache.remove(&peer_id, &addr)); } @@ -216,10 +231,9 @@ mod tests { let addr2: Multiaddr = "/ip4/127.0.0.1/tcp/8081".parse().unwrap(); let addr3: Multiaddr = "/ip4/127.0.0.1/tcp/8082".parse().unwrap(); - cache.put( - peer_id, - [addr.clone(), addr2.clone(), addr3.clone()].into_iter(), - ); + cache.add(peer_id, addr.clone()); + cache.add(peer_id, addr2.clone()); + cache.add(peer_id, addr3.clone()); assert!(cache.remove(&peer_id, &addr2)); @@ -232,12 +246,12 @@ mod tests { } #[test] - fn put_adds_new_address_to_cache() { + fn add_adds_new_address_to_cache() { let mut cache = PeerAddresses::default(); let peer_id = PeerId::random(); let addr: Multiaddr = "/ip4/127.0.0.1/tcp/8080".parse().unwrap(); - assert!(cache.put(peer_id, [addr.clone()].into_iter())); + assert!(cache.add(peer_id, addr.clone())); let mut cached = cache.get(&peer_id).collect::>(); cached.sort(); @@ -247,16 +261,17 @@ mod tests { } #[test] - fn put_adds_address_to_cache_to_existing_key() { + fn add_adds_address_to_cache_to_existing_key() { let mut cache = PeerAddresses::default(); let peer_id = PeerId::random(); let addr: Multiaddr = "/ip4/127.0.0.1/tcp/8080".parse().unwrap(); let addr2: Multiaddr = "/ip4/127.0.0.1/tcp/8081".parse().unwrap(); let addr3: Multiaddr = "/ip4/127.0.0.1/tcp/8082".parse().unwrap(); - assert!(cache.put(peer_id, [addr.clone()].into_iter())); + assert!(cache.add(peer_id, addr.clone())); - cache.put(peer_id, [addr2.clone(), addr3.clone()].into_iter()); + cache.add(peer_id, addr2.clone()); + cache.add(peer_id, addr3.clone()); let expected = prepare_expected_addrs(peer_id, [addr, addr2, addr3].into_iter()); @@ -291,12 +306,20 @@ mod tests { }) } - fn dial_error(peer_id: PeerId) -> FromSwarm<'static> { - FromSwarm::DialFailure(DialFailure { - peer_id: Some(peer_id), - error: &DialError::NoAddresses, - connection_id: ConnectionId::new_unchecked(8), - }) + fn prepare_errors(addrs: Vec) -> Vec<(Multiaddr, TransportError)> { + let errors: Vec<(Multiaddr, TransportError)> = addrs + .iter() + .map(|addr| { + ( + addr.clone(), + TransportError::Other(io::Error::new( + io::ErrorKind::Other, + MemoryTransportError::Unreachable, + )), + ) + }) + .collect(); + errors } static MEMORY_ADDR_1000: Lazy = From db18158ebe169d9e3f16e31f9b0b3a7b820fa703 Mon Sep 17 00:00:00 2001 From: StemCll Date: Mon, 1 Jan 2024 23:07:19 +0100 Subject: [PATCH 18/23] Don't filter new external addresses --- protocols/identify/src/behaviour.rs | 77 ++++------------------------- 1 file changed, 9 insertions(+), 68 deletions(-) diff --git a/protocols/identify/src/behaviour.rs b/protocols/identify/src/behaviour.rs index ce1af568ae4..1061d276cd0 100644 --- a/protocols/identify/src/behaviour.rs +++ b/protocols/identify/src/behaviour.rs @@ -278,14 +278,15 @@ impl NetworkBehaviour for Behaviour { info: info.clone(), })); - for address in filter_new_external_addrs( - &self.discovered_peers.get(&peer_id), - &info.listen_addrs, - ) { - self.events.push_back(ToSwarm::NewExternalAddrOfPeer { - peer_id, - addr: address.clone(), - }); + if let Some(ref mut discovered_peers) = self.discovered_peers.0 { + for address in &info.listen_addrs { + if discovered_peers.add(peer_id, address.clone()) { + self.events.push_back(ToSwarm::NewExternalAddrOfPeer { + peer_id, + addr: address.clone(), + }); + } + } } match self.our_observed_addresses.entry(id) { @@ -457,20 +458,6 @@ fn multiaddr_matches_peer_id(addr: &Multiaddr, peer_id: &PeerId) -> bool { true } -fn filter_new_external_addrs( - cached_addrs: &[Multiaddr], - listen_addrs: &Vec, -) -> Vec { - let mut new_addresses = Vec::::new(); - - for address in listen_addrs { - if !cached_addrs.contains(address) { - new_addresses.push(address.clone()); - } - } - new_addresses -} - struct PeerCache(Option); impl PeerCache { @@ -524,50 +511,4 @@ mod tests { )); assert!(multiaddr_matches_peer_id(&addr_without_peer_id, &peer_id)); } - - #[test] - fn filter_new_external_addrs_leaves_new_addrs() { - let addr: Multiaddr = "/ip4/147.75.69.143/tcp/4001" - .parse() - .expect("failed to parse multiaddr"); - - let addr1: Multiaddr = "/ip4/147.75.69.143/tcp/4002" - .parse() - .expect("failed to parse multiaddr"); - - let old_addr: Multiaddr = "/memory/1234".parse().unwrap(); - let old_addr1: Multiaddr = "/memory/1233".parse().unwrap(); - let old_addr2: Multiaddr = "/memory/1235".parse().unwrap(); - - let old_addrs: Vec = [old_addr, old_addr1, old_addr2].to_vec(); - - let new_addrs = Vec::from([addr, addr1]); - - assert_eq!( - filter_new_external_addrs(&old_addrs, &new_addrs), - new_addrs.clone(), - ); - } - - #[test] - fn filter_new_external_addrs_filter_duplicates() { - let addr: Multiaddr = "/ip4/147.75.69.143/tcp/4001" - .parse() - .expect("failed to parse multiaddr"); - - let addr1: Multiaddr = "/ip4/147.75.69.143/tcp/4002" - .parse() - .expect("failed to parse multiaddr"); - - let old_addr: Multiaddr = "/memory/1234".parse().unwrap(); - let old_addr1: Multiaddr = "/memory/1233".parse().unwrap(); - let old_addr2: Multiaddr = "/memory/1235".parse().unwrap(); - - let mut old_addrs: Vec = [old_addr, old_addr1, old_addr2].to_vec(); - - let new_addrs = Vec::from([addr.clone(), addr1.clone()]); - old_addrs.append(&mut new_addrs.clone()); - - assert_eq!(filter_new_external_addrs(&old_addrs, &new_addrs), []) - } } From 7fa87fbc48d87a5373166c0c21432ac54150924b Mon Sep 17 00:00:00 2001 From: StemCll Date: Mon, 1 Jan 2024 23:21:31 +0100 Subject: [PATCH 19/23] Fix clippy warn --- protocols/request-response/tests/peer_address.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/protocols/request-response/tests/peer_address.rs b/protocols/request-response/tests/peer_address.rs index 2bb4fec3fc3..2a120931dcd 100644 --- a/protocols/request-response/tests/peer_address.rs +++ b/protocols/request-response/tests/peer_address.rs @@ -28,9 +28,9 @@ async fn dial_succeeds_after_adding_peers_address() { let (listen_addr, _) = swarm2.listen().with_memory_addr_external().await; - swarm.add_peer_address(peer_id2.clone(), listen_addr.clone()); + swarm.add_peer_address(peer_id2, listen_addr.clone()); - swarm.dial(peer_id2.clone()).unwrap(); + swarm.dial(peer_id2).unwrap(); async_std::task::spawn(swarm2.loop_on_next()); From 31723f2b4a871a4a293b383cdd5584cd38cad6a9 Mon Sep 17 00:00:00 2001 From: StemCll Date: Thu, 18 Jan 2024 09:23:42 +0100 Subject: [PATCH 20/23] Review suggestions resolved --- protocols/identify/src/behaviour.rs | 11 +++++--- protocols/request-response/src/lib.rs | 1 + swarm/src/behaviour/peer_addresses.rs | 37 +++++++++++++++------------ 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/protocols/identify/src/behaviour.rs b/protocols/identify/src/behaviour.rs index 1061d276cd0..07b46f41ae0 100644 --- a/protocols/identify/src/behaviour.rs +++ b/protocols/identify/src/behaviour.rs @@ -470,10 +470,13 @@ impl PeerCache { } fn put(&mut self, peer: PeerId, addresses: impl Iterator) { - if let Some(cache) = self.0.as_mut() { - for address in addresses { - cache.add(peer, address); - } + let cache = match self.0.as_mut() { + None => return, + Some(cache) => cache, + }; + + for address in addresses { + cache.add(peer, address); } } diff --git a/protocols/request-response/src/lib.rs b/protocols/request-response/src/lib.rs index e6781ef46de..4362b3255ad 100644 --- a/protocols/request-response/src/lib.rs +++ b/protocols/request-response/src/lib.rs @@ -476,6 +476,7 @@ where } /// Removes an address of a peer previously added via [`Behaviour::add_address`]. + #[deprecated(note = "Will be removed with the next breaking release and won't be replaced.")] pub fn remove_address(&mut self, peer: &PeerId, address: &Multiaddr) { self.addresses.remove(peer, address); } diff --git a/swarm/src/behaviour/peer_addresses.rs b/swarm/src/behaviour/peer_addresses.rs index 4903d7bf3cf..e80dadab171 100644 --- a/swarm/src/behaviour/peer_addresses.rs +++ b/swarm/src/behaviour/peer_addresses.rs @@ -47,14 +47,18 @@ impl PeerAddresses { /// Returns true if the newly added address was not previously in the cache. /// pub fn add(&mut self, peer: PeerId, address: Multiaddr) -> bool { - let address = prepare_addr(&peer, &address); - if let Some(cached) = self.0.get_mut(&peer) { - cached.insert(address) - } else { - let mut set: HashSet = HashSet::new(); - set.insert(address); - self.0.put(peer, set); - true + match prepare_addr(&peer, &address) { + Ok(address) => { + if let Some(cached) = self.0.get_mut(&peer) { + cached.insert(address) + } else { + let mut set: HashSet = HashSet::new(); + set.insert(address); + self.0.put(peer, set); + true + } + } + Err(_) => false, } } @@ -66,19 +70,18 @@ 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 { - self.0.get_mut(peer).map_or_else( - || false, - |addrs| { - let address = prepare_addr(peer, address); - addrs.remove(&address) + match self.0.get_mut(peer) { + Some(addrs) => match prepare_addr(peer, address) { + Ok(address) => addrs.remove(&address), + Err(_) => false, }, - ) + None => false, + } } } -fn prepare_addr(peer: &PeerId, addr: &Multiaddr) -> Multiaddr { - let addr = addr.clone(); - addr.clone().with_p2p(*peer).unwrap_or(addr) +fn prepare_addr(peer: &PeerId, addr: &Multiaddr) -> Result { + addr.clone().with_p2p(*peer) } impl Default for PeerAddresses { From da6294be209b7d70935f9ae943bb53a32329e275 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Sat, 20 Jan 2024 21:59:51 -0800 Subject: [PATCH 21/23] Re-work `PeerAddresses` to be limited in how many addresses we store This allows us to remove the `put` function and we can now safely add all addresses individually to the cache. With the addition of the `ToSwarm::NewExternalAddrOfPeer` event, the safeguard of overwriting all addresses in the peer cache was no longer useful because any other behaviour would have to apply this as well. As such, we needed to build this safe-guard directly _into_ `PeerAddresses`. This also makes the added test pass. Previously, the events would never get emitted because after calling `.put`, the addresses were already in the cache and the `add`-function always returned `false`. --- protocols/identify/CHANGELOG.md | 2 + protocols/identify/src/behaviour.rs | 17 +----- protocols/identify/tests/smoke.rs | 74 ++++++++++++++++++++++++++- swarm/src/behaviour.rs | 22 +++++--- swarm/src/behaviour/peer_addresses.rs | 28 ++++++---- swarm/src/lib.rs | 10 ++-- 6 files changed, 115 insertions(+), 38 deletions(-) diff --git a/protocols/identify/CHANGELOG.md b/protocols/identify/CHANGELOG.md index 5eeb85d3989..83984448d07 100644 --- a/protocols/identify/CHANGELOG.md +++ b/protocols/identify/CHANGELOG.md @@ -1,6 +1,8 @@ ## 0.44.2 - Emit `ToSwarm::NewExternalAddrOfPeer` for all external addresses of remote peers. + For this work, the address cache must be enabled via `identify::Config::with_cache_size`. + The default is 0, i.e. disabled. See [PR 4371](https://github.com/libp2p/rust-libp2p/pull/4371). ## 0.44.1 diff --git a/protocols/identify/src/behaviour.rs b/protocols/identify/src/behaviour.rs index 07b46f41ae0..43bddb52fe7 100644 --- a/protocols/identify/src/behaviour.rs +++ b/protocols/identify/src/behaviour.rs @@ -267,10 +267,6 @@ impl NetworkBehaviour for Behaviour { info.listen_addrs .retain(|addr| multiaddr_matches_peer_id(addr, &peer_id)); - // Replace existing addresses to prevent other peer from filling up our memory. - self.discovered_peers - .put(peer_id, info.listen_addrs.iter().cloned()); - let observed = info.observed_addr.clone(); self.events .push_back(ToSwarm::GenerateEvent(Event::Received { @@ -283,7 +279,7 @@ impl NetworkBehaviour for Behaviour { if discovered_peers.add(peer_id, address.clone()) { self.events.push_back(ToSwarm::NewExternalAddrOfPeer { peer_id, - addr: address.clone(), + address: address.clone(), }); } } @@ -469,17 +465,6 @@ impl PeerCache { Self(Some(PeerAddresses::new(size))) } - fn put(&mut self, peer: PeerId, addresses: impl Iterator) { - let cache = match self.0.as_mut() { - None => return, - Some(cache) => cache, - }; - - for address in addresses { - cache.add(peer, address); - } - } - fn get(&mut self, peer: &PeerId) -> Vec { if let Some(cache) = self.0.as_mut() { cache.get(peer).collect() diff --git a/protocols/identify/tests/smoke.rs b/protocols/identify/tests/smoke.rs index 5cccc09d863..dd92d10979a 100644 --- a/protocols/identify/tests/smoke.rs +++ b/protocols/identify/tests/smoke.rs @@ -110,7 +110,7 @@ async fn only_emits_address_candidate_once_per_connection() { async_std::task::spawn(swarm2.loop_on_next()); let swarm_events = futures::stream::poll_fn(|cx| swarm1.poll_next_unpin(cx)) - .take(5) + .take(8) .collect::>() .await; @@ -156,6 +156,78 @@ async fn only_emits_address_candidate_once_per_connection() { ); } +#[async_std::test] +async fn emits_unique_listen_addresses() { + let _ = tracing_subscriber::fmt() + .with_env_filter(EnvFilter::from_default_env()) + .try_init(); + + let mut swarm1 = Swarm::new_ephemeral(|identity| { + identify::Behaviour::new( + identify::Config::new("a".to_string(), identity.public()) + .with_agent_version("b".to_string()) + .with_interval(Duration::from_secs(1)) + .with_cache_size(10), + ) + }); + let mut swarm2 = Swarm::new_ephemeral(|identity| { + identify::Behaviour::new( + identify::Config::new("c".to_string(), identity.public()) + .with_agent_version("d".to_string()), + ) + }); + + let (swarm2_mem_listen_addr, swarm2_tcp_listen_addr) = + swarm2.listen().with_memory_addr_external().await; + let swarm2_peer_id = *swarm2.local_peer_id(); + swarm1.connect(&mut swarm2).await; + + async_std::task::spawn(swarm2.loop_on_next()); + + let swarm_events = futures::stream::poll_fn(|cx| swarm1.poll_next_unpin(cx)) + .take(8) + .collect::>() + .await; + + let infos = swarm_events + .iter() + .filter_map(|e| match e { + SwarmEvent::Behaviour(identify::Event::Received { info, .. }) => Some(info.clone()), + _ => None, + }) + .collect::>(); + + assert!( + infos.len() > 1, + "should exchange identify payload more than once" + ); + + let listen_addrs = infos + .iter() + .map(|i| i.listen_addrs.clone()) + .collect::>(); + + for addrs in listen_addrs { + assert_eq!(addrs.len(), 2); + assert!(addrs.contains(&swarm2_mem_listen_addr)); + assert!(addrs.contains(&swarm2_tcp_listen_addr)); + } + + let reported_addrs = swarm_events + .iter() + .filter_map(|e| match e { + SwarmEvent::NewExternalAddrOfPeer { peer_id, address } => { + Some((*peer_id, address.clone())) + } + _ => None, + }) + .collect::>(); + + assert_eq!(reported_addrs.len(), 2, "To have two addresses of remote"); + assert!(reported_addrs.contains(&(swarm2_peer_id, swarm2_mem_listen_addr))); + assert!(reported_addrs.contains(&(swarm2_peer_id, swarm2_tcp_listen_addr))); +} + #[async_std::test] async fn identify_push() { let _ = tracing_subscriber::fmt() diff --git a/swarm/src/behaviour.rs b/swarm/src/behaviour.rs index beb924c562e..5070871a4c1 100644 --- a/swarm/src/behaviour.rs +++ b/swarm/src/behaviour.rs @@ -307,7 +307,7 @@ pub enum ToSwarm { }, /// Reports external address of a remote peer to the [`Swarm`](crate::Swarm) and through that to other [`NetworkBehaviour`]s. - NewExternalAddrOfPeer { peer_id: PeerId, addr: Multiaddr }, + NewExternalAddrOfPeer { peer_id: PeerId, address: Multiaddr }, } impl ToSwarm { @@ -340,9 +340,13 @@ impl ToSwarm { ToSwarm::NewExternalAddrCandidate(addr) => ToSwarm::NewExternalAddrCandidate(addr), ToSwarm::ExternalAddrConfirmed(addr) => ToSwarm::ExternalAddrConfirmed(addr), ToSwarm::ExternalAddrExpired(addr) => ToSwarm::ExternalAddrExpired(addr), - ToSwarm::NewExternalAddrOfPeer { addr, peer_id } => { - ToSwarm::NewExternalAddrOfPeer { addr, peer_id } - } + ToSwarm::NewExternalAddrOfPeer { + address: addr, + peer_id, + } => ToSwarm::NewExternalAddrOfPeer { + address: addr, + peer_id, + }, } } } @@ -374,9 +378,13 @@ impl ToSwarm { peer_id, connection, }, - ToSwarm::NewExternalAddrOfPeer { addr, peer_id } => { - ToSwarm::NewExternalAddrOfPeer { addr, peer_id } - } + ToSwarm::NewExternalAddrOfPeer { + address: addr, + peer_id, + } => ToSwarm::NewExternalAddrOfPeer { + address: addr, + peer_id, + }, } } } diff --git a/swarm/src/behaviour/peer_addresses.rs b/swarm/src/behaviour/peer_addresses.rs index e80dadab171..a011867dcdf 100644 --- a/swarm/src/behaviour/peer_addresses.rs +++ b/swarm/src/behaviour/peer_addresses.rs @@ -6,17 +6,18 @@ use libp2p_identity::PeerId; use lru::LruCache; -use std::collections::HashSet; use std::num::NonZeroUsize; /// Struct for tracking peers' external addresses of the [`Swarm`](crate::Swarm). #[derive(Debug)] -pub struct PeerAddresses(LruCache>); +pub struct PeerAddresses(LruCache>); impl PeerAddresses { - /// Creates cache with capacity of `cache_size`. - pub fn new(cache_size: NonZeroUsize) -> Self { - Self(LruCache::new(cache_size)) + /// 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)) } /// Feed a [`FromSwarm`] event to this struct. @@ -50,11 +51,12 @@ impl PeerAddresses { match prepare_addr(&peer, &address) { Ok(address) => { if let Some(cached) = self.0.get_mut(&peer) { - cached.insert(address) + cached.put(address, ()).is_none() } else { - let mut set: HashSet = HashSet::new(); - set.insert(address); + let mut set = LruCache::new(NonZeroUsize::new(10).expect("10 > 0")); + set.put(address, ()); self.0.put(peer, set); + true } } @@ -63,8 +65,12 @@ impl PeerAddresses { } /// Returns peer's external addresses. - pub fn get(&mut self, peer: &PeerId) -> impl Iterator { - self.0.get(peer).cloned().unwrap_or_default().into_iter() + pub fn get(&mut self, peer: &PeerId) -> impl Iterator + '_ { + self.0 + .get(peer) + .into_iter() + .flat_map(|c| c.iter().map(|(m, ())| m)) + .cloned() } /// Removes address from peer addresses cache. @@ -72,7 +78,7 @@ impl PeerAddresses { pub fn remove(&mut self, peer: &PeerId, address: &Multiaddr) -> bool { match self.0.get_mut(peer) { Some(addrs) => match prepare_addr(peer, address) { - Ok(address) => addrs.remove(&address), + Ok(address) => addrs.pop(&address).is_some(), Err(_) => false, }, None => false, diff --git a/swarm/src/lib.rs b/swarm/src/lib.rs index 501298357b1..2f02e43348d 100644 --- a/swarm/src/lib.rs +++ b/swarm/src/lib.rs @@ -299,6 +299,8 @@ pub enum SwarmEvent { ExternalAddrConfirmed { address: Multiaddr }, /// An external address of the local node expired, i.e. is no-longer confirmed. ExternalAddrExpired { address: Multiaddr }, + /// We have discovered a new address of a peer. + NewExternalAddrOfPeer { peer_id: PeerId, address: Multiaddr }, } impl SwarmEvent { @@ -1188,12 +1190,14 @@ where self.pool.disconnect(peer_id); } }, - ToSwarm::NewExternalAddrOfPeer { addr, peer_id } => { + ToSwarm::NewExternalAddrOfPeer { peer_id, address } => { self.behaviour .on_swarm_event(FromSwarm::NewExternalAddrOfPeer(NewExternalAddrOfPeer { peer_id, - addr: &addr, - })) + addr: &address, + })); + self.pending_swarm_events + .push_back(SwarmEvent::NewExternalAddrOfPeer { peer_id, address }); } } } From 6fae50171c679c4cfbe317236cf816ec38bc52ab Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Sat, 20 Jan 2024 22:07:18 -0800 Subject: [PATCH 22/23] Allow new event in dctur test --- protocols/dcutr/tests/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/protocols/dcutr/tests/lib.rs b/protocols/dcutr/tests/lib.rs index 9e1f0591e6d..f0c5a744d0c 100644 --- a/protocols/dcutr/tests/lib.rs +++ b/protocols/dcutr/tests/lib.rs @@ -203,6 +203,7 @@ async fn wait_for_reservation( SwarmEvent::ExternalAddrConfirmed { address } if !is_renewal => { assert_eq!(address, client_addr); } + SwarmEvent::NewExternalAddrOfPeer { peer_id, address } => {} e => panic!("{e:?}"), } } From 1866abdc3de5a965e3dded6efafa99fd2deeca95 Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Sat, 20 Jan 2024 22:15:24 -0800 Subject: [PATCH 23/23] Fix clippy warnings --- protocols/dcutr/tests/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocols/dcutr/tests/lib.rs b/protocols/dcutr/tests/lib.rs index f0c5a744d0c..084ee744145 100644 --- a/protocols/dcutr/tests/lib.rs +++ b/protocols/dcutr/tests/lib.rs @@ -203,7 +203,7 @@ async fn wait_for_reservation( SwarmEvent::ExternalAddrConfirmed { address } if !is_renewal => { assert_eq!(address, client_addr); } - SwarmEvent::NewExternalAddrOfPeer { peer_id, address } => {} + SwarmEvent::NewExternalAddrOfPeer { .. } => {} e => panic!("{e:?}"), } }