diff --git a/src/addresses.rs b/src/addresses.rs new file mode 100644 index 00000000..609efbe0 --- /dev/null +++ b/src/addresses.rs @@ -0,0 +1,159 @@ +// Copyright 2024 litep2p developers +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +use std::{collections::HashSet, sync::Arc}; + +use multiaddr::{Multiaddr, Protocol}; +use parking_lot::RwLock; + +use crate::PeerId; + +/// Set of the public addresses of the local node. +/// +/// The format of the addresses stored in the set contain the local peer ID. +/// This requirement is enforced by the [`PublicAddresses::add_address`] method, +/// that will add the local peer ID to the address if it is missing. +/// +/// # Note +/// +/// - The addresses are reported to the identify protocol and are used by other nodes +/// to establish a connection with the local node. +/// +/// - Users must ensure that the addresses are reachable from the network. +#[derive(Debug, Clone)] +pub struct PublicAddresses { + pub(crate) inner: Arc>>, + local_peer_id: PeerId, +} + +impl PublicAddresses { + /// Creates new [`PublicAddresses`] from the given peer ID. + pub(crate) fn new(local_peer_id: PeerId) -> Self { + Self { + inner: Arc::new(RwLock::new(HashSet::new())), + local_peer_id, + } + } + + /// Add a public address to the list of addresses. + /// + /// The address must contain the local peer ID, otherwise an error is returned. + /// In case the address does not contain any peer ID, it will be added. + /// + /// Returns true if the address was added, false if it was already present. + pub fn add_address(&self, address: Multiaddr) -> Result { + let address = ensure_local_peer(address, self.local_peer_id)?; + Ok(self.inner.write().insert(address)) + } + + /// Remove the exact public address. + /// + /// The provided address must contain the local peer ID. + pub fn remove_address(&self, address: &Multiaddr) -> bool { + self.inner.write().remove(address) + } + + /// Returns a vector of the available listen addresses. + pub fn get_addresses(&self) -> Vec { + self.inner.read().iter().cloned().collect() + } +} + +/// Check if the address contains the local peer ID. +/// +/// If the address does not contain any peer ID, it will be added. +fn ensure_local_peer( + mut address: Multiaddr, + local_peer_id: PeerId, +) -> Result { + if address.is_empty() { + return Err(InsertionError::EmptyAddress); + } + + // Verify the peer ID from the address corresponds to the local peer ID. + if let Some(peer_id) = PeerId::try_from_multiaddr(&address) { + if peer_id != local_peer_id { + return Err(InsertionError::DifferentPeerId); + } + } else { + address.push(Protocol::P2p(local_peer_id.into())); + } + + Ok(address) +} + +/// The error returned when an address cannot be inserted. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum InsertionError { + /// The address is empty. + EmptyAddress, + /// The address contains a different peer ID than the local peer ID. + DifferentPeerId, +} + +#[cfg(test)] +mod tests { + use super::*; + use std::str::FromStr; + + #[test] + fn add_remove_contains() { + let peer_id = PeerId::random(); + let addresses = PublicAddresses::new(peer_id); + let address = Multiaddr::from_str("/dns/domain1.com/tcp/30333").unwrap(); + let peer_address = Multiaddr::from_str("/dns/domain1.com/tcp/30333") + .unwrap() + .with(Protocol::P2p(peer_id.into())); + + assert!(!addresses.get_addresses().contains(&address)); + + assert!(addresses.add_address(address.clone()).unwrap()); + // Adding the address a second time returns Ok(false). + assert!(!addresses.add_address(address.clone()).unwrap()); + + assert!(!addresses.get_addresses().contains(&address)); + assert!(addresses.get_addresses().contains(&peer_address)); + + addresses.remove_address(&peer_address); + assert!(!addresses.get_addresses().contains(&peer_address)); + } + + #[test] + fn get_addresses() { + let peer_id = PeerId::random(); + let addresses = PublicAddresses::new(peer_id); + let address1 = Multiaddr::from_str("/dns/domain1.com/tcp/30333").unwrap(); + let address2 = Multiaddr::from_str("/dns/domain2.com/tcp/30333").unwrap(); + // Addresses different than the local peer ID are ignored. + let address3 = Multiaddr::from_str( + "/dns/domain2.com/tcp/30333/p2p/12D3KooWSueCPH3puP2PcvqPJdNaDNF3jMZjtJtDiSy35pWrbt5h", + ) + .unwrap(); + + assert!(addresses.add_address(address1.clone()).unwrap()); + assert!(addresses.add_address(address2.clone()).unwrap()); + addresses.add_address(address3.clone()).unwrap_err(); + + let addresses = addresses.get_addresses(); + assert_eq!(addresses.len(), 2); + assert!(addresses.contains(&address1.with(Protocol::P2p(peer_id.into())))); + assert!(addresses.contains(&address2.with(Protocol::P2p(peer_id.into())))); + } +} diff --git a/src/lib.rs b/src/lib.rs index c42d6fda..d28739eb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,7 +29,9 @@ #![allow(clippy::match_like_matches_macro)] use crate::{ + addresses::PublicAddresses, config::Litep2pConfig, + error::DialError, protocol::{ libp2p::{bitswap::Bitswap, identify::Identify, kademlia::Kademlia, ping::Ping}, mdns::Mdns, @@ -50,7 +52,6 @@ use crate::transport::webrtc::WebRtcTransport; #[cfg(feature = "websocket")] use crate::transport::websocket::WebSocketTransport; -use error::DialError; use multiaddr::{Multiaddr, Protocol}; use multihash::Multihash; use transport::Endpoint; @@ -65,6 +66,7 @@ pub use types::protocol::ProtocolName; pub(crate) mod peer_id; +pub mod addresses; pub mod codec; pub mod config; pub mod crypto; @@ -387,7 +389,7 @@ impl Litep2p { // if identify was enabled, give it the enabled protocols and listen addresses and start it if let Some((service, mut identify_config)) = identify_info.take() { identify_config.protocols = transport_manager.protocols().cloned().collect(); - let identify = Identify::new(service, identify_config, listen_addresses.clone()); + let identify = Identify::new(service, identify_config); litep2p_config.executor.run(Box::pin(async move { let _ = identify.run().await; @@ -450,7 +452,12 @@ impl Litep2p { &self.local_peer_id } - /// Get listen address of litep2p. + /// Get the list of public addresses of the node. + pub fn public_addresses(&self) -> PublicAddresses { + self.transport_manager.public_addresses() + } + + /// Get the list of listen addresses of the node. pub fn listen_addresses(&self) -> impl Iterator { self.listen_addresses.iter() } @@ -473,7 +480,7 @@ impl Litep2p { /// Add one ore more known addresses for peer. /// /// Return value denotes how many addresses were added for the peer. - // Addresses belonging to disabled/unsupported transports will be ignored. + /// Addresses belonging to disabled/unsupported transports will be ignored. pub fn add_known_address( &mut self, peer: PeerId, diff --git a/src/protocol/libp2p/identify.rs b/src/protocol/libp2p/identify.rs index 30117e87..184f7fb1 100644 --- a/src/protocol/libp2p/identify.rs +++ b/src/protocol/libp2p/identify.rs @@ -79,9 +79,6 @@ pub struct Config { /// Protocols supported by the local node, filled by `Litep2p`. pub(crate) protocols: Vec, - /// Public addresses. - pub(crate) public_addresses: Vec, - /// Protocol version. pub(crate) protocol_version: String, @@ -97,7 +94,6 @@ impl Config { pub fn new( protocol_version: String, user_agent: Option, - public_addresses: Vec, ) -> (Self, Box + Send + Unpin>) { let (tx_event, rx_event) = channel(DEFAULT_CHANNEL_SIZE); @@ -105,7 +101,6 @@ impl Config { Self { tx_event, public: None, - public_addresses, protocol_version, user_agent, codec: ProtocolCodec::UnsignedVarint(Some(IDENTIFY_PAYLOAD_SIZE)), @@ -182,9 +177,6 @@ pub(crate) struct Identify { /// User agent. user_agent: String, - /// Public addresses. - listen_addresses: HashSet, - /// Protocols supported by the local node, filled by `Litep2p`. protocols: Vec, @@ -200,16 +192,11 @@ pub(crate) struct Identify { impl Identify { /// Create new [`Identify`] protocol. - pub(crate) fn new( - service: TransportService, - config: Config, - listen_addresses: Vec, - ) -> Self { + pub(crate) fn new(service: TransportService, config: Config) -> Self { Self { service, tx: config.tx_event, peers: HashMap::new(), - listen_addresses: config.public_addresses.into_iter().chain(listen_addresses).collect(), public: config.public.expect("public key to be supplied"), protocol_version: config.protocol_version, user_agent: config.user_agent.unwrap_or(DEFAULT_AGENT.to_string()), @@ -265,15 +252,16 @@ impl Identify { } }; + let mut listen_addr: HashSet<_> = + self.service.listen_addresses().into_iter().map(|addr| addr.to_vec()).collect(); + listen_addr + .extend(self.service.public_addresses().inner.read().iter().map(|addr| addr.to_vec())); + let identify = identify_schema::Identify { protocol_version: Some(self.protocol_version.clone()), agent_version: Some(self.user_agent.clone()), public_key: Some(self.public.to_protobuf_encoding()), - listen_addrs: self - .listen_addresses - .iter() - .map(|address| address.to_vec()) - .collect::>(), + listen_addrs: listen_addr.into_iter().collect(), observed_addr, protocols: self.protocols.clone(), }; @@ -413,3 +401,74 @@ impl Identify { } } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::{config::ConfigBuilder, transport::tcp::config::Config as TcpConfig, Litep2p}; + use multiaddr::{Multiaddr, Protocol}; + + fn create_litep2p() -> ( + Litep2p, + Box + Send + Unpin>, + PeerId, + ) { + let (identify_config, identify) = + Config::new("1.0.0".to_string(), Some("litep2p/1.0.0".to_string())); + + let keypair = crate::crypto::ed25519::Keypair::generate(); + let peer = PeerId::from_public_key(&crate::crypto::PublicKey::Ed25519(keypair.public())); + let config = ConfigBuilder::new() + .with_keypair(keypair) + .with_tcp(TcpConfig { + listen_addresses: vec!["/ip6/::1/tcp/0".parse().unwrap()], + ..Default::default() + }) + .with_libp2p_identify(identify_config) + .build(); + + (Litep2p::new(config).unwrap(), identify, peer) + } + + #[tokio::test] + async fn update_identify_addresses() { + // Create two instances of litep2p + let (mut litep2p1, mut event_stream1, peer1) = create_litep2p(); + let (mut litep2p2, mut event_stream2, _peer2) = create_litep2p(); + let litep2p1_address = litep2p1.listen_addresses().into_iter().next().unwrap(); + + let multiaddr: Multiaddr = "/ip6/::9/tcp/111".parse().unwrap(); + // Litep2p1 is now reporting the new address. + assert!(litep2p1.public_addresses().add_address(multiaddr.clone()).unwrap()); + + // Dial `litep2p1` + litep2p2.dial_address(litep2p1_address.clone()).await.unwrap(); + + let expected_multiaddr = multiaddr.with(Protocol::P2p(peer1.into())); + + tokio::spawn(async move { + loop { + tokio::select! { + _ = litep2p1.next_event() => {} + _event = event_stream1.next() => {} + } + } + }); + + loop { + tokio::select! { + _ = litep2p2.next_event() => {} + event = event_stream2.next() => match event { + Some(IdentifyEvent::PeerIdentified { + listen_addresses, + .. + }) => { + assert!(listen_addresses.iter().any(|address| address == &expected_multiaddr)); + break; + } + _ => {} + } + } + } + } +} diff --git a/src/protocol/transport_service.rs b/src/protocol/transport_service.rs index f8b6b282..1525cb53 100644 --- a/src/protocol/transport_service.rs +++ b/src/protocol/transport_service.rs @@ -19,6 +19,7 @@ // DEALINGS IN THE SOFTWARE. use crate::{ + addresses::PublicAddresses, error::Error, protocol::{connection::ConnectionHandle, InnerTransportEvent, TransportEvent}, transport::{manager::TransportManagerHandle, Endpoint}, @@ -150,13 +151,23 @@ impl TransportService { transport_handle, next_substream_id, connections: HashMap::new(), - keep_alive_timeout: keep_alive_timeout, + keep_alive_timeout, pending_keep_alive_timeouts: FuturesUnordered::new(), }, tx, ) } + /// Get the list of public addresses of the node. + pub fn public_addresses(&self) -> PublicAddresses { + self.transport_handle.public_addresses() + } + + /// Get the list of listen addresses of the node. + pub fn listen_addresses(&self) -> HashSet { + self.transport_handle.listen_addresses() + } + /// Handle connection established event. fn on_connection_established( &mut self, @@ -445,6 +456,7 @@ mod tests { cmd_tx, HashSet::new(), Default::default(), + PublicAddresses::new(peer), ); let (service, sender) = TransportService::new( diff --git a/src/transport/manager/handle.rs b/src/transport/manager/handle.rs index ece77f02..90fe7efc 100644 --- a/src/transport/manager/handle.rs +++ b/src/transport/manager/handle.rs @@ -19,6 +19,7 @@ // DEALINGS IN THE SOFTWARE. use crate::{ + addresses::PublicAddresses, crypto::ed25519::Keypair, error::{AddressError, Error}, executor::Executor, @@ -77,6 +78,9 @@ pub struct TransportManagerHandle { /// Local listen addresess. listen_addresses: Arc>>, + + /// Public addresses. + public_addresses: PublicAddresses, } impl TransportManagerHandle { @@ -87,13 +91,15 @@ impl TransportManagerHandle { cmd_tx: Sender, supported_transport: HashSet, listen_addresses: Arc>>, + public_addresses: PublicAddresses, ) -> Self { Self { peers, cmd_tx, local_peer_id, - listen_addresses, supported_transport, + listen_addresses, + public_addresses, } } @@ -102,6 +108,16 @@ impl TransportManagerHandle { self.supported_transport.insert(transport); } + /// Get the list of public addresses of the node. + pub(crate) fn public_addresses(&self) -> PublicAddresses { + self.public_addresses.clone() + } + + /// Get the list of listen addresses of the node. + pub(crate) fn listen_addresses(&self) -> HashSet { + self.listen_addresses.read().clone() + } + /// Check if `address` is supported by one of the enabled transports. pub fn supported_transport(&self, address: &Multiaddr) -> bool { let mut iter = address.iter(); @@ -313,6 +329,7 @@ impl TransportHandle { mod tests { use super::*; use multihash::Multihash; + use parking_lot::lock_api::RwLock; use tokio::sync::mpsc::{channel, Receiver}; fn make_transport_manager_handle() -> ( @@ -321,13 +338,15 @@ mod tests { ) { let (cmd_tx, cmd_rx) = channel(64); + let local_peer_id = PeerId::random(); ( TransportManagerHandle { - local_peer_id: PeerId::random(), + local_peer_id, cmd_tx, peers: Default::default(), supported_transport: HashSet::new(), listen_addresses: Default::default(), + public_addresses: PublicAddresses::new(local_peer_id), }, cmd_rx, ) @@ -587,21 +606,22 @@ mod tests { fn is_local_address() { let (cmd_tx, _cmd_rx) = channel(64); + let local_peer_id = PeerId::random(); + let first_addr: Multiaddr = "/ip6/::1/tcp/8888".parse().expect("valid multiaddress"); + let second_addr: Multiaddr = "/ip4/127.0.0.1/tcp/8888".parse().expect("valid multiaddress"); + + let listen_addresses = Arc::new(RwLock::new( + [first_addr.clone(), second_addr.clone()].iter().cloned().collect(), + )); + println!("{:?}", listen_addresses); + let handle = TransportManagerHandle { - local_peer_id: PeerId::random(), + local_peer_id, cmd_tx, peers: Default::default(), supported_transport: HashSet::new(), - listen_addresses: Arc::new(RwLock::new(HashSet::from_iter([ - "/ip6/::1/tcp/8888".parse().expect("valid multiaddress"), - "/ip4/127.0.0.1/tcp/8888".parse().expect("valid multiaddress"), - "/ip6/::1/tcp/8888/p2p/12D3KooWT2ouvz5uMmCvHJGzAGRHiqDts5hzXR7NdoQ27pGdzp9Q" - .parse() - .expect("valid multiaddress"), - "/ip4/127.0.0.1/tcp/8888/p2p/12D3KooWT2ouvz5uMmCvHJGzAGRHiqDts5hzXR7NdoQ27pGdzp9Q" - .parse() - .expect("valid multiaddress"), - ]))), + listen_addresses, + public_addresses: PublicAddresses::new(local_peer_id), }; // local addresses diff --git a/src/transport/manager/mod.rs b/src/transport/manager/mod.rs index 066327bf..6816bbf2 100644 --- a/src/transport/manager/mod.rs +++ b/src/transport/manager/mod.rs @@ -19,6 +19,7 @@ // DEALINGS IN THE SOFTWARE. use crate::{ + addresses::PublicAddresses, codec::ProtocolCodec, crypto::ed25519::Keypair, error::{AddressError, DialError, Error}, @@ -219,6 +220,9 @@ pub struct TransportManager { /// Listen addresses. listen_addresses: Arc>>, + /// Listen addresses. + public_addresses: PublicAddresses, + /// Next connection ID. next_connection_id: Arc, @@ -268,12 +272,14 @@ impl TransportManager { let (cmd_tx, cmd_rx) = channel(256); let (event_tx, event_rx) = channel(256); let listen_addresses = Arc::new(RwLock::new(HashSet::new())); + let public_addresses = PublicAddresses::new(local_peer_id); let handle = TransportManagerHandle::new( local_peer_id, peers.clone(), cmd_tx, supported_transports, - Arc::clone(&listen_addresses), + listen_addresses.clone(), + public_addresses.clone(), ); ( @@ -286,6 +292,7 @@ impl TransportManager { local_peer_id, bandwidth_sink, listen_addresses, + public_addresses, max_parallel_dials, protocols: HashMap::new(), transports: TransportContext::new(), @@ -381,6 +388,11 @@ impl TransportManager { self.transport_manager_handle.register_transport(name); } + /// Get the list of public addresses of the node. + pub(crate) fn public_addresses(&self) -> PublicAddresses { + self.public_addresses.clone() + } + /// Register local listen address. pub fn register_listen_address(&mut self, address: Multiaddr) { assert!(!address.iter().any(|protocol| std::matches!(protocol, Protocol::P2p(_)))); @@ -479,8 +491,9 @@ impl TransportManager { return Err(Error::NoAddressAvailable(peer)); } + let locked_addresses = self.listen_addresses.read(); for record in records.values() { - if self.listen_addresses.read().contains(record.as_ref()) { + if locked_addresses.contains(record.as_ref()) { tracing::warn!( target: LOG_TARGET, ?peer, @@ -492,6 +505,7 @@ impl TransportManager { return Err(Error::TriedToDialSelf); } } + drop(locked_addresses); // set connection id for the address record and put peer into `Opening` state let connection_id = @@ -1770,6 +1784,8 @@ impl TransportManager { mod tests { use limits::ConnectionLimitsConfig; + use multihash::Multihash; + use super::*; use crate::{ crypto::ed25519::Keypair, diff --git a/tests/conformance/rust/identify.rs b/tests/conformance/rust/identify.rs index c29ca882..24af7e19 100644 --- a/tests/conformance/rust/identify.rs +++ b/tests/conformance/rust/identify.rs @@ -72,7 +72,7 @@ fn initialize_litep2p() -> ( let keypair = Keypair::generate(); let (ping_config, ping_event_stream) = PingConfig::default(); let (identify_config, identify_event_stream) = - IdentifyConfig::new("proto v1".to_string(), None, Vec::new()); + IdentifyConfig::new("proto v1".to_string(), None); let litep2p = Litep2p::new( ConfigBuilder::new() diff --git a/tests/connection/mod.rs b/tests/connection/mod.rs index 8f037e62..0d16d840 100644 --- a/tests/connection/mod.rs +++ b/tests/connection/mod.rs @@ -1040,10 +1040,9 @@ async fn multiple_listen_addresses( let (mut litep2p2, _event_stream) = make_dummy_litep2p(transport2).await; let (mut litep2p3, _event_stream) = make_dummy_litep2p(transport3).await; - let mut address_iter = litep2p1.listen_addresses(); - let address1 = address_iter.next().unwrap().clone(); - let address2 = address_iter.next().unwrap().clone(); - drop(address_iter); + let addresses: Vec<_> = litep2p1.listen_addresses().cloned().collect(); + let address1 = addresses.get(0).unwrap().clone(); + let address2 = addresses.get(1).unwrap().clone(); tokio::spawn(async move { loop { @@ -1176,11 +1175,7 @@ async fn unspecified_listen_address_tcp() { let mut litep2p1 = Litep2p::new(config1).unwrap(); let peer1 = *litep2p1.local_peer_id(); - for address in litep2p1.listen_addresses() { - tracing::info!("address: {address:?}"); - } - - let listen_address = litep2p1.listen_addresses().collect::>(); + let listen_address: Vec<_> = litep2p1.listen_addresses().cloned().collect(); let ip4_port = listen_address.iter().find_map(|address| { let mut iter = address.iter(); @@ -1281,11 +1276,7 @@ async fn unspecified_listen_address_websocket() { let mut litep2p1 = Litep2p::new(config1).unwrap(); let peer1 = *litep2p1.local_peer_id(); - for address in litep2p1.listen_addresses() { - tracing::info!("address: {address:?}"); - } - - let listen_address = litep2p1.listen_addresses().collect::>(); + let listen_address: Vec<_> = litep2p1.listen_addresses().cloned().collect(); let ip4_port = listen_address.iter().find_map(|address| { let mut iter = address.iter(); @@ -1430,8 +1421,8 @@ async fn simultaneous_dial_then_redial(transport1: Transport, transport2: Transp let peer1 = *litep2p1.local_peer_id(); let peer2 = *litep2p2.local_peer_id(); - litep2p1.add_known_address(peer2, litep2p2.listen_addresses().cloned()); - litep2p2.add_known_address(peer1, litep2p1.listen_addresses().cloned()); + litep2p1.add_known_address(peer2, litep2p2.listen_addresses().into_iter().cloned()); + litep2p2.add_known_address(peer1, litep2p1.listen_addresses().into_iter().cloned()); let (_, _) = tokio::join!(litep2p1.dial(&peer2), litep2p2.dial(&peer1)); diff --git a/tests/protocol/identify.rs b/tests/protocol/identify.rs index efb3da28..a4ed3b7a 100644 --- a/tests/protocol/identify.rs +++ b/tests/protocol/identify.rs @@ -65,21 +65,15 @@ async fn identify_supported(transport1: Transport, transport2: Transport) { .with_env_filter(tracing_subscriber::EnvFilter::from_default_env()) .try_init(); - let (identify_config1, mut identify_event_stream1) = Config::new( - "/proto/1".to_string(), - Some("agent v1".to_string()), - Vec::new(), - ); + let (identify_config1, mut identify_event_stream1) = + Config::new("/proto/1".to_string(), Some("agent v1".to_string())); let config_builder1 = ConfigBuilder::new() .with_keypair(Keypair::generate()) .with_libp2p_identify(identify_config1); let config1 = add_transport(config_builder1, transport1).build(); - let (identify_config2, mut identify_event_stream2) = Config::new( - "/proto/2".to_string(), - Some("agent v2".to_string()), - Vec::new(), - ); + let (identify_config2, mut identify_event_stream2) = + Config::new("/proto/2".to_string(), Some("agent v2".to_string())); let config_builder2 = ConfigBuilder::new() .with_keypair(Keypair::generate()) .with_libp2p_identify(identify_config2); @@ -193,8 +187,7 @@ async fn identify_not_supported(transport1: Transport, transport2: Transport) { .with_libp2p_ping(ping_config); let config1 = add_transport(config_builder1, transport1).build(); - let (identify_config2, mut identify_event_stream2) = - Config::new("litep2p".to_string(), None, Vec::new()); + let (identify_config2, mut identify_event_stream2) = Config::new("litep2p".to_string(), None); let config_builder2 = ConfigBuilder::new() .with_keypair(Keypair::generate()) .with_libp2p_identify(identify_config2);