Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Upgrade libp2p from 0.52.4 to 0.54.1 #6248

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open
700 changes: 298 additions & 402 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -841,7 +841,7 @@ kvdb-shared-tests = { version = "0.11.0" }
landlock = { version = "0.3.0" }
libc = { version = "0.2.155" }
libfuzzer-sys = { version = "0.4" }
libp2p = { version = "0.52.4" }
libp2p = { version = "0.54.1" }
libp2p-identity = { version = "0.2.9" }
libsecp256k1 = { version = "0.7.0", default-features = false }
linked-hash-map = { version = "0.5.4" }
Expand Down
16 changes: 16 additions & 0 deletions prdoc/pr_6248.prdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
title: Upgrade libp2p to 0.54.1

doc:
- audience: [Node Dev, Node Operator]
description: |
Upgrade libp2p from 0.52.4 to 0.54.1

crates:
- name: sc-authority-discovery
bump: major
- name: sc-network
bump: major
- name: sc-network-sync
bump: major
- name: sc-telemetry
bump: major
2 changes: 1 addition & 1 deletion substrate/client/authority-discovery/src/worker/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use futures::{
sink::SinkExt,
task::LocalSpawn,
};
use libp2p::{identity::SigningError, kad::record::Key as KademliaKey};
use libp2p::{identity::SigningError, kad::RecordKey as KademliaKey};
use prometheus_endpoint::prometheus::default_registry;

use sc_client_api::HeaderBackend;
Expand Down
1 change: 1 addition & 0 deletions substrate/client/network/src/behaviour.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ pub struct Behaviour<B: BlockT> {
}

/// Event generated by `Behaviour`.
#[derive(Debug)]
pub enum BehaviourOut {
/// Started a random iterative Kademlia discovery query.
RandomKademliaStarted,
Expand Down
159 changes: 69 additions & 90 deletions substrate/client/network/src/discovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,12 @@ use futures::prelude::*;
use futures_timer::Delay;
use ip_network::IpNetwork;
use libp2p::{
core::{Endpoint, Multiaddr},
core::{transport::PortUse, Endpoint, Multiaddr},
kad::{
self,
record::store::{MemoryStore, RecordStore},
store::{MemoryStore, RecordStore},
Behaviour as Kademlia, BucketInserts, Config as KademliaConfig, Event as KademliaEvent,
GetClosestPeersError, GetRecordOk, PeerRecord, QueryId, QueryResult, Quorum, Record,
Event, GetClosestPeersError, GetRecordOk, PeerRecord, QueryId, QueryResult, Quorum, Record,
RecordKey,
},
mdns::{self, tokio::Behaviour as TokioMdns},
Expand All @@ -68,8 +68,8 @@ use libp2p::{
toggle::{Toggle, ToggleConnectionHandler},
DialFailure, ExternalAddrConfirmed, FromSwarm,
},
ConnectionDenied, ConnectionId, DialError, NetworkBehaviour, PollParameters,
StreamProtocol, THandler, THandlerInEvent, THandlerOutEvent, ToSwarm,
ConnectionDenied, ConnectionId, DialError, NetworkBehaviour, StreamProtocol, THandler,
THandlerInEvent, THandlerOutEvent, ToSwarm,
},
PeerId,
};
Expand Down Expand Up @@ -214,23 +214,14 @@ impl DiscoveryConfig {
enable_mdns,
kademlia_disjoint_query_paths,
kademlia_protocol,
kademlia_legacy_protocol,
kademlia_legacy_protocol: _,
kademlia_replication_factor,
} = self;

let kademlia = if let Some(ref kademlia_protocol) = kademlia_protocol {
let mut config = KademliaConfig::default();
let mut config = KademliaConfig::new(kademlia_protocol.clone());

config.set_replication_factor(kademlia_replication_factor);
// Populate kad with both the legacy and the new protocol names.
// Remove the legacy protocol:
// https://github.com/paritytech/polkadot-sdk/issues/504
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should wait a bit and scrape the network. I believe everything should be fine, but let's double check first.

I guess we can merge #6109 before this one as it also handles legacy_protocol removal, but shouldn't matter too much.

I'll have a look this week and investigate versions, generally I think its safe for now

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I specifically used kademlia_legacy_protocol: _, above instead of full removal of the property to reduce the inevitable conflict with #6109 whichever ends up being first.

let kademlia_protocols = if let Some(legacy_protocol) = kademlia_legacy_protocol {
vec![kademlia_protocol.clone(), legacy_protocol]
} else {
vec![kademlia_protocol.clone()]
};
Comment on lines -225 to -232
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks good! We should finally do this)

config.set_protocol_names(kademlia_protocols.into_iter().map(Into::into).collect());

config.set_record_filtering(libp2p::kad::StoreInserts::FilterBoth);

Expand Down Expand Up @@ -613,12 +604,14 @@ impl NetworkBehaviour for DiscoveryBehaviour {
peer: PeerId,
addr: &Multiaddr,
role_override: Endpoint,
port_use: PortUse,
) -> Result<THandler<Self>, ConnectionDenied> {
self.kademlia.handle_established_outbound_connection(
connection_id,
peer,
addr,
role_override,
port_use,
)
}

Expand Down Expand Up @@ -690,7 +683,7 @@ impl NetworkBehaviour for DiscoveryBehaviour {
Ok(list.into_iter().collect())
}

fn on_swarm_event(&mut self, event: FromSwarm<Self::ConnectionHandler>) {
fn on_swarm_event(&mut self, event: FromSwarm) {
match event {
FromSwarm::ConnectionEstablished(e) => {
self.num_connections += 1;
Expand Down Expand Up @@ -765,6 +758,10 @@ impl NetworkBehaviour for DiscoveryBehaviour {

self.kademlia.on_swarm_event(FromSwarm::ExternalAddrConfirmed(e));
},
event => {
debug!(target: "sub-libp2p", "New unknown `FromSwarm` libp2p event: {event:?}");
self.kademlia.on_swarm_event(event);
},
}
}

Expand All @@ -777,11 +774,7 @@ impl NetworkBehaviour for DiscoveryBehaviour {
self.kademlia.on_connection_handler_event(peer_id, connection_id, event);
}

fn poll(
&mut self,
cx: &mut Context,
params: &mut impl PollParameters,
) -> Poll<ToSwarm<Self::ToSwarm, THandlerInEvent<Self>>> {
fn poll(&mut self, cx: &mut Context) -> Poll<ToSwarm<Self::ToSwarm, THandlerInEvent<Self>>> {
// Immediately process the content of `discovered`.
if let Some(ev) = self.pending_events.pop_front() {
return Poll::Ready(ToSwarm::GenerateEvent(ev))
Expand Down Expand Up @@ -824,7 +817,7 @@ impl NetworkBehaviour for DiscoveryBehaviour {
}
}

while let Poll::Ready(ev) = self.kademlia.poll(cx, params) {
while let Poll::Ready(ev) = self.kademlia.poll(cx) {
match ev {
ToSwarm::GenerateEvent(ev) => match ev {
KademliaEvent::RoutingUpdated { peer, .. } => {
Expand Down Expand Up @@ -1011,26 +1004,21 @@ impl NetworkBehaviour for DiscoveryBehaviour {
KademliaEvent::OutboundQueryProgressed { result: e, .. } => {
warn!(target: "sub-libp2p", "Libp2p => Unhandled Kademlia event: {:?}", e)
},
Event::ModeChanged { new_mode } => {
debug!(target: "sub-libp2p", "Libp2p => Kademlia mode changed: {new_mode}")
},
},
ToSwarm::Dial { opts } => return Poll::Ready(ToSwarm::Dial { opts }),
ToSwarm::NotifyHandler { peer_id, handler, event } =>
return Poll::Ready(ToSwarm::NotifyHandler { peer_id, handler, event }),
ToSwarm::CloseConnection { peer_id, connection } =>
return Poll::Ready(ToSwarm::CloseConnection { peer_id, connection }),
ToSwarm::NewExternalAddrCandidate(observed) =>
return Poll::Ready(ToSwarm::NewExternalAddrCandidate(observed)),
ToSwarm::ExternalAddrConfirmed(addr) =>
return Poll::Ready(ToSwarm::ExternalAddrConfirmed(addr)),
ToSwarm::ExternalAddrExpired(addr) =>
return Poll::Ready(ToSwarm::ExternalAddrExpired(addr)),
ToSwarm::ListenOn { opts } => return Poll::Ready(ToSwarm::ListenOn { opts }),
ToSwarm::RemoveListener { id } =>
return Poll::Ready(ToSwarm::RemoveListener { id }),
event => {
return Poll::Ready(event.map_out(|_| {
unreachable!("`GenerateEvent` is handled in a branch above; qed")
}));
},
}
}

// Poll mDNS.
while let Poll::Ready(ev) = self.mdns.poll(cx, params) {
while let Poll::Ready(ev) = self.mdns.poll(cx) {
match ev {
ToSwarm::GenerateEvent(event) => match event {
mdns::Event::Discovered(list) => {
Expand All @@ -1052,17 +1040,17 @@ impl NetworkBehaviour for DiscoveryBehaviour {
},
// `event` is an enum with no variant
ToSwarm::NotifyHandler { event, .. } => match event {},
ToSwarm::CloseConnection { peer_id, connection } =>
return Poll::Ready(ToSwarm::CloseConnection { peer_id, connection }),
ToSwarm::NewExternalAddrCandidate(observed) =>
return Poll::Ready(ToSwarm::NewExternalAddrCandidate(observed)),
ToSwarm::ExternalAddrConfirmed(addr) =>
return Poll::Ready(ToSwarm::ExternalAddrConfirmed(addr)),
ToSwarm::ExternalAddrExpired(addr) =>
return Poll::Ready(ToSwarm::ExternalAddrExpired(addr)),
ToSwarm::ListenOn { opts } => return Poll::Ready(ToSwarm::ListenOn { opts }),
ToSwarm::RemoveListener { id } =>
return Poll::Ready(ToSwarm::RemoveListener { id }),
event => {
return Poll::Ready(
event
.map_in(|_| {
unreachable!("`NotifyHandler` is handled in a branch above; qed")
})
.map_out(|_| {
unreachable!("`GenerateEvent` is handled in a branch above; qed")
}),
);
},
}
}

Expand Down Expand Up @@ -1105,21 +1093,14 @@ mod tests {
},
identity::Keypair,
noise,
swarm::{Executor, Swarm, SwarmEvent},
swarm::{Swarm, SwarmEvent},
yamux, Multiaddr,
};
use sp_core::hash::H256;
use std::{collections::HashSet, pin::Pin, task::Poll};
use std::{collections::HashSet, task::Poll, time::Duration};

struct TokioExecutor(tokio::runtime::Runtime);
impl Executor for TokioExecutor {
fn exec(&self, f: Pin<Box<dyn Future<Output = ()> + Send>>) {
let _ = self.0.spawn(f);
}
}

#[test]
fn discovery_working() {
#[tokio::test]
async fn discovery_working() {
let mut first_swarm_peer_id_and_addr = None;

let genesis_hash = H256::from_low_u64_be(1);
Expand All @@ -1130,42 +1111,40 @@ mod tests {
// the first swarm via `with_permanent_addresses`.
let mut swarms = (0..25)
.map(|i| {
let keypair = Keypair::generate_ed25519();

let transport = MemoryTransport::new()
.upgrade(upgrade::Version::V1)
.authenticate(noise::Config::new(&keypair).unwrap())
.multiplex(yamux::Config::default())
.boxed();

let behaviour = {
let mut config = DiscoveryConfig::new(keypair.public().to_peer_id());
config
.with_permanent_addresses(first_swarm_peer_id_and_addr.clone())
.allow_private_ip(true)
.allow_non_globals_in_dht(true)
.discovery_limit(50)
.with_kademlia(genesis_hash, fork_id, &protocol_id);

config.finish()
};

let runtime = tokio::runtime::Runtime::new().unwrap();
#[allow(deprecated)]
let mut swarm = libp2p::swarm::SwarmBuilder::with_executor(
transport,
behaviour,
keypair.public().to_peer_id(),
TokioExecutor(runtime),
)
.build();
let mut swarm = libp2p::SwarmBuilder::with_new_identity()
.with_tokio()
.with_other_transport(|keypair| {
MemoryTransport::new()
.upgrade(upgrade::Version::V1)
.authenticate(noise::Config::new(&keypair).unwrap())
.multiplex(yamux::Config::default())
.boxed()
})
.unwrap()
.with_behaviour(|keypair| {
let mut config = DiscoveryConfig::new(keypair.public().to_peer_id());
config
.with_permanent_addresses(first_swarm_peer_id_and_addr.clone())
.allow_private_ip(true)
.allow_non_globals_in_dht(true)
.discovery_limit(50)
.with_kademlia(genesis_hash, fork_id, &protocol_id);

config.finish()
})
.unwrap()
.with_swarm_config(|config| {
// This is taken care of by notification protocols in non-test environment
config.with_idle_connection_timeout(Duration::from_secs(10))
})
.build();

let listen_addr: Multiaddr =
format!("/memory/{}", rand::random::<u64>()).parse().unwrap();

if i == 0 {
first_swarm_peer_id_and_addr =
Some((keypair.public().to_peer_id(), listen_addr.clone()))
Some((*swarm.local_peer_id(), listen_addr.clone()))
}

swarm.listen_on(listen_addr.clone()).unwrap();
Expand Down Expand Up @@ -1252,7 +1231,7 @@ mod tests {
}
});

futures::executor::block_on(fut);
fut.await
}

#[test]
Expand Down
15 changes: 10 additions & 5 deletions substrate/client/network/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use crate::types::ProtocolName;

use bytes::Bytes;
use libp2p::{
kad::{record::Key, PeerRecord},
kad::{PeerRecord, RecordKey as KademliaKey},
PeerId,
};

Expand All @@ -37,16 +37,21 @@ pub enum DhtEvent {
ValueFound(PeerRecord),

/// The requested record has not been found in the DHT.
ValueNotFound(Key),
ValueNotFound(KademliaKey),

/// The record has been successfully inserted into the DHT.
ValuePut(Key),
ValuePut(KademliaKey),

/// An error has occurred while putting a record into the DHT.
ValuePutFailed(Key),
ValuePutFailed(KademliaKey),

/// The DHT received a put record request.
PutRecordRequest(Key, Vec<u8>, Option<sc_network_types::PeerId>, Option<std::time::Instant>),
PutRecordRequest(
KademliaKey,
Vec<u8>,
Option<sc_network_types::PeerId>,
Option<std::time::Instant>,
),
}

/// Type for events generated by networking layer.
Expand Down
2 changes: 1 addition & 1 deletion substrate/client/network/src/litep2p/discovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use array_bytes::bytes2hex;
use futures::{FutureExt, Stream};
use futures_timer::Delay;
use ip_network::IpNetwork;
use libp2p::kad::record::Key as KademliaKey;
use libp2p::kad::RecordKey as KademliaKey;
use litep2p::{
protocol::{
libp2p::{
Expand Down
2 changes: 1 addition & 1 deletion substrate/client/network/src/litep2p/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ use crate::{
use crate::litep2p::Record;
use codec::DecodeAll;
use futures::{channel::oneshot, stream::BoxStream};
use libp2p::{identity::SigningError, kad::record::Key as KademliaKey};
use libp2p::{identity::SigningError, kad::RecordKey as KademliaKey};
use litep2p::{
addresses::PublicAddresses, crypto::ed25519::Keypair,
types::multiaddr::Multiaddr as LiteP2pMultiaddr,
Expand Down
2 changes: 1 addition & 1 deletion substrate/client/network/src/network_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ pub enum Endpoint {
impl From<ConnectedPoint> for PeerEndpoint {
fn from(endpoint: ConnectedPoint) -> Self {
match endpoint {
ConnectedPoint::Dialer { address, role_override } =>
ConnectedPoint::Dialer { address, role_override, port_use: _ } =>
Self::Dialing(address, role_override.into()),
ConnectedPoint::Listener { local_addr, send_back_addr } =>
Self::Listening { local_addr, send_back_addr },
Expand Down
Loading
Loading