Skip to content

Commit 5de3ea7

Browse files
nazar-pcdmitry-markin
authored andcommitted
Upgrade libp2p from 0.52.4 to 0.54.1 (paritytech#6248)
# Description Fixes paritytech#5996 https://github.com/libp2p/rust-libp2p/releases/tag/libp2p-v0.53.0 https://github.com/libp2p/rust-libp2p/blob/master/CHANGELOG.md ## Integration Nothing special is needed, just note that `yamux_window_size` is no longer applicable to libp2p (litep2p seems to still have it though). ## Review Notes There are a few simplifications and improvements done in libp2p 0.53 regarding swarm interface, I'll list a few key/applicable here. libp2p/rust-libp2p#4788 removed `write_length_prefixed` function, so I inlined its code instead. libp2p/rust-libp2p#4120 introduced new `libp2p::SwarmBuilder` instead of now deprecated `libp2p::swarm::SwarmBuilder`, the transition is straightforward and quite ergonomic (can be seen in tests). libp2p/rust-libp2p#4581 is the most annoying change I have seen that basically makes many enums `#[non_exhaustive]`. I mapped some, but those that couldn't be mapped I dealt with by printing log messages once they are hit (the best solution I could come up with, at least with stable Rust). libp2p/rust-libp2p#4306 makes connection close as soon as there are no handler using it, so I had to replace `KeepAlive::Until` with an explicit future that flips internal boolean after timeout, achieving the old behavior, though it should ideally be removed completely at some point. `yamux_window_size` is no longer used by libp2p thanks to libp2p/rust-libp2p#4970 and generally Yamux should have a higher performance now. I have resolved and cleaned up all deprecations related to libp2p except `BandwidthSinks`. Libp2p deprecated it (though it is still present in 0.54.1, which is why I didn't handle it just yet). Ideally Substrate would finally [switch to the official Prometheus client](paritytech/substrate#12699), in which case we'd get metrics for free. Otherwise a bit of code will need to be copy-pasted to maintain current behavior with `BandwidthSinks` gone, which I left a TODO about. The biggest change in 0.54.0 is libp2p/rust-libp2p#4568 that changed transport APIs and enabled unconditional potential port reuse, which can lead to very confusing errors if running two Substrate nodes on the same machine without changing listening port explicitly. Overall nothing scary here, but testing is always appreciated. # Checklist * [x] My PR includes a detailed description as outlined in the "Description" and its two subsections above. * [x] My PR follows the [labeling requirements]( https://github.com/paritytech/polkadot-sdk/blob/master/docs/contributor/CONTRIBUTING.md#Process ) of this project (at minimum one label for `T` required) * External contributors: ask maintainers to put the right label on your PR. --- Polkadot Address: 1vSxzbyz2cJREAuVWjhXUT1ds8vBzoxn2w4asNpusQKwjJd --------- Co-authored-by: Dmitry Markin <[email protected]>
1 parent d219572 commit 5de3ea7

20 files changed

+850
-1070
lines changed

Cargo.lock

Lines changed: 284 additions & 398 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -848,7 +848,7 @@ kvdb-shared-tests = { version = "0.11.0" }
848848
landlock = { version = "0.3.0" }
849849
libc = { version = "0.2.155" }
850850
libfuzzer-sys = { version = "0.4" }
851-
libp2p = { version = "0.52.4" }
851+
libp2p = { version = "0.54.1" }
852852
libp2p-identity = { version = "0.2.9" }
853853
libsecp256k1 = { version = "0.7.0", default-features = false }
854854
linked-hash-map = { version = "0.5.4" }

prdoc/pr_6248.prdoc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
title: Upgrade libp2p to 0.54.1
2+
3+
doc:
4+
- audience: [Node Dev, Node Operator]
5+
description: |
6+
Upgrade libp2p from 0.52.4 to 0.54.1
7+
8+
crates:
9+
- name: sc-network
10+
bump: major
11+
- name: sc-network-types
12+
bump: minor
13+
- name: sc-network-sync
14+
bump: patch
15+
- name: sc-telemetry
16+
bump: minor

substrate/client/network/src/behaviour.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ pub struct Behaviour<B: BlockT> {
6868
}
6969

7070
/// Event generated by `Behaviour`.
71+
#[derive(Debug)]
7172
pub enum BehaviourOut {
7273
/// Started a random iterative Kademlia discovery query.
7374
RandomKademliaStarted,

substrate/client/network/src/discovery.rs

Lines changed: 83 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,13 @@ use futures::prelude::*;
5353
use futures_timer::Delay;
5454
use ip_network::IpNetwork;
5555
use libp2p::{
56-
core::{Endpoint, Multiaddr},
56+
core::{transport::PortUse, Endpoint, Multiaddr},
5757
kad::{
5858
self,
59-
record::store::{MemoryStore, RecordStore},
59+
store::{MemoryStore, RecordStore},
6060
Behaviour as Kademlia, BucketInserts, Config as KademliaConfig, Event as KademliaEvent,
61-
GetClosestPeersError, GetProvidersError, GetProvidersOk, GetRecordOk, PeerRecord, QueryId,
62-
QueryResult, Quorum, Record, RecordKey,
61+
Event, GetClosestPeersError, GetProvidersError, GetProvidersOk, GetRecordOk, PeerRecord,
62+
QueryId, QueryResult, Quorum, Record, RecordKey,
6363
},
6464
mdns::{self, tokio::Behaviour as TokioMdns},
6565
multiaddr::Protocol,
@@ -68,8 +68,8 @@ use libp2p::{
6868
toggle::{Toggle, ToggleConnectionHandler},
6969
DialFailure, ExternalAddrConfirmed, FromSwarm,
7070
},
71-
ConnectionDenied, ConnectionId, DialError, NetworkBehaviour, PollParameters,
72-
StreamProtocol, THandler, THandlerInEvent, THandlerOutEvent, ToSwarm,
71+
ConnectionDenied, ConnectionId, DialError, NetworkBehaviour, StreamProtocol, THandler,
72+
THandlerInEvent, THandlerOutEvent, ToSwarm,
7373
},
7474
PeerId,
7575
};
@@ -214,23 +214,14 @@ impl DiscoveryConfig {
214214
enable_mdns,
215215
kademlia_disjoint_query_paths,
216216
kademlia_protocol,
217-
kademlia_legacy_protocol,
217+
kademlia_legacy_protocol: _,
218218
kademlia_replication_factor,
219219
} = self;
220220

221221
let kademlia = if let Some(ref kademlia_protocol) = kademlia_protocol {
222-
let mut config = KademliaConfig::default();
222+
let mut config = KademliaConfig::new(kademlia_protocol.clone());
223223

224224
config.set_replication_factor(kademlia_replication_factor);
225-
// Populate kad with both the legacy and the new protocol names.
226-
// Remove the legacy protocol:
227-
// https://github.com/paritytech/polkadot-sdk/issues/504
228-
let kademlia_protocols = if let Some(legacy_protocol) = kademlia_legacy_protocol {
229-
vec![kademlia_protocol.clone(), legacy_protocol]
230-
} else {
231-
vec![kademlia_protocol.clone()]
232-
};
233-
config.set_protocol_names(kademlia_protocols.into_iter().map(Into::into).collect());
234225

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

@@ -647,12 +638,14 @@ impl NetworkBehaviour for DiscoveryBehaviour {
647638
peer: PeerId,
648639
addr: &Multiaddr,
649640
role_override: Endpoint,
641+
port_use: PortUse,
650642
) -> Result<THandler<Self>, ConnectionDenied> {
651643
self.kademlia.handle_established_outbound_connection(
652644
connection_id,
653645
peer,
654646
addr,
655647
role_override,
648+
port_use,
656649
)
657650
}
658651

@@ -724,7 +717,7 @@ impl NetworkBehaviour for DiscoveryBehaviour {
724717
Ok(list.into_iter().collect())
725718
}
726719

727-
fn on_swarm_event(&mut self, event: FromSwarm<Self::ConnectionHandler>) {
720+
fn on_swarm_event(&mut self, event: FromSwarm) {
728721
match event {
729722
FromSwarm::ConnectionEstablished(e) => {
730723
self.num_connections += 1;
@@ -811,6 +804,10 @@ impl NetworkBehaviour for DiscoveryBehaviour {
811804

812805
self.kademlia.on_swarm_event(FromSwarm::ExternalAddrConfirmed(e));
813806
},
807+
event => {
808+
debug!(target: "sub-libp2p", "New unknown `FromSwarm` libp2p event: {event:?}");
809+
self.kademlia.on_swarm_event(event);
810+
},
814811
}
815812
}
816813

@@ -823,11 +820,7 @@ impl NetworkBehaviour for DiscoveryBehaviour {
823820
self.kademlia.on_connection_handler_event(peer_id, connection_id, event);
824821
}
825822

826-
fn poll(
827-
&mut self,
828-
cx: &mut Context,
829-
params: &mut impl PollParameters,
830-
) -> Poll<ToSwarm<Self::ToSwarm, THandlerInEvent<Self>>> {
823+
fn poll(&mut self, cx: &mut Context) -> Poll<ToSwarm<Self::ToSwarm, THandlerInEvent<Self>>> {
831824
// Immediately process the content of `discovered`.
832825
if let Some(ev) = self.pending_events.pop_front() {
833826
return Poll::Ready(ToSwarm::GenerateEvent(ev))
@@ -870,7 +863,7 @@ impl NetworkBehaviour for DiscoveryBehaviour {
870863
}
871864
}
872865

873-
while let Poll::Ready(ev) = self.kademlia.poll(cx, params) {
866+
while let Poll::Ready(ev) = self.kademlia.poll(cx) {
874867
match ev {
875868
ToSwarm::GenerateEvent(ev) => match ev {
876869
KademliaEvent::RoutingUpdated { peer, .. } => {
@@ -1103,30 +1096,38 @@ impl NetworkBehaviour for DiscoveryBehaviour {
11031096
e.key(), e,
11041097
),
11051098
},
1099+
KademliaEvent::OutboundQueryProgressed {
1100+
result: QueryResult::Bootstrap(res),
1101+
..
1102+
} => match res {
1103+
Ok(ok) => debug!(
1104+
target: "sub-libp2p",
1105+
"Libp2p => DHT bootstrap progressed: {ok:?}",
1106+
),
1107+
Err(e) => warn!(
1108+
target: "sub-libp2p",
1109+
"Libp2p => DHT bootstrap error: {e:?}",
1110+
),
1111+
},
11061112
// We never start any other type of query.
11071113
KademliaEvent::OutboundQueryProgressed { result: e, .. } => {
11081114
warn!(target: "sub-libp2p", "Libp2p => Unhandled Kademlia event: {:?}", e)
11091115
},
1116+
Event::ModeChanged { new_mode } => {
1117+
debug!(target: "sub-libp2p", "Libp2p => Kademlia mode changed: {new_mode}")
1118+
},
11101119
},
11111120
ToSwarm::Dial { opts } => return Poll::Ready(ToSwarm::Dial { opts }),
1112-
ToSwarm::NotifyHandler { peer_id, handler, event } =>
1113-
return Poll::Ready(ToSwarm::NotifyHandler { peer_id, handler, event }),
1114-
ToSwarm::CloseConnection { peer_id, connection } =>
1115-
return Poll::Ready(ToSwarm::CloseConnection { peer_id, connection }),
1116-
ToSwarm::NewExternalAddrCandidate(observed) =>
1117-
return Poll::Ready(ToSwarm::NewExternalAddrCandidate(observed)),
1118-
ToSwarm::ExternalAddrConfirmed(addr) =>
1119-
return Poll::Ready(ToSwarm::ExternalAddrConfirmed(addr)),
1120-
ToSwarm::ExternalAddrExpired(addr) =>
1121-
return Poll::Ready(ToSwarm::ExternalAddrExpired(addr)),
1122-
ToSwarm::ListenOn { opts } => return Poll::Ready(ToSwarm::ListenOn { opts }),
1123-
ToSwarm::RemoveListener { id } =>
1124-
return Poll::Ready(ToSwarm::RemoveListener { id }),
1121+
event => {
1122+
return Poll::Ready(event.map_out(|_| {
1123+
unreachable!("`GenerateEvent` is handled in a branch above; qed")
1124+
}));
1125+
},
11251126
}
11261127
}
11271128

11281129
// Poll mDNS.
1129-
while let Poll::Ready(ev) = self.mdns.poll(cx, params) {
1130+
while let Poll::Ready(ev) = self.mdns.poll(cx) {
11301131
match ev {
11311132
ToSwarm::GenerateEvent(event) => match event {
11321133
mdns::Event::Discovered(list) => {
@@ -1148,17 +1149,17 @@ impl NetworkBehaviour for DiscoveryBehaviour {
11481149
},
11491150
// `event` is an enum with no variant
11501151
ToSwarm::NotifyHandler { event, .. } => match event {},
1151-
ToSwarm::CloseConnection { peer_id, connection } =>
1152-
return Poll::Ready(ToSwarm::CloseConnection { peer_id, connection }),
1153-
ToSwarm::NewExternalAddrCandidate(observed) =>
1154-
return Poll::Ready(ToSwarm::NewExternalAddrCandidate(observed)),
1155-
ToSwarm::ExternalAddrConfirmed(addr) =>
1156-
return Poll::Ready(ToSwarm::ExternalAddrConfirmed(addr)),
1157-
ToSwarm::ExternalAddrExpired(addr) =>
1158-
return Poll::Ready(ToSwarm::ExternalAddrExpired(addr)),
1159-
ToSwarm::ListenOn { opts } => return Poll::Ready(ToSwarm::ListenOn { opts }),
1160-
ToSwarm::RemoveListener { id } =>
1161-
return Poll::Ready(ToSwarm::RemoveListener { id }),
1152+
event => {
1153+
return Poll::Ready(
1154+
event
1155+
.map_in(|_| {
1156+
unreachable!("`NotifyHandler` is handled in a branch above; qed")
1157+
})
1158+
.map_out(|_| {
1159+
unreachable!("`GenerateEvent` is handled in a branch above; qed")
1160+
}),
1161+
);
1162+
},
11621163
}
11631164
}
11641165

@@ -1201,21 +1202,14 @@ mod tests {
12011202
},
12021203
identity::Keypair,
12031204
noise,
1204-
swarm::{Executor, Swarm, SwarmEvent},
1205+
swarm::{Swarm, SwarmEvent},
12051206
yamux, Multiaddr,
12061207
};
12071208
use sp_core::hash::H256;
1208-
use std::{collections::HashSet, pin::Pin, task::Poll};
1209+
use std::{collections::HashSet, task::Poll, time::Duration};
12091210

1210-
struct TokioExecutor(tokio::runtime::Runtime);
1211-
impl Executor for TokioExecutor {
1212-
fn exec(&self, f: Pin<Box<dyn Future<Output = ()> + Send>>) {
1213-
let _ = self.0.spawn(f);
1214-
}
1215-
}
1216-
1217-
#[test]
1218-
fn discovery_working() {
1211+
#[tokio::test]
1212+
async fn discovery_working() {
12191213
let mut first_swarm_peer_id_and_addr = None;
12201214

12211215
let genesis_hash = H256::from_low_u64_be(1);
@@ -1226,42 +1220,40 @@ mod tests {
12261220
// the first swarm via `with_permanent_addresses`.
12271221
let mut swarms = (0..25)
12281222
.map(|i| {
1229-
let keypair = Keypair::generate_ed25519();
1230-
1231-
let transport = MemoryTransport::new()
1232-
.upgrade(upgrade::Version::V1)
1233-
.authenticate(noise::Config::new(&keypair).unwrap())
1234-
.multiplex(yamux::Config::default())
1235-
.boxed();
1236-
1237-
let behaviour = {
1238-
let mut config = DiscoveryConfig::new(keypair.public().to_peer_id());
1239-
config
1240-
.with_permanent_addresses(first_swarm_peer_id_and_addr.clone())
1241-
.allow_private_ip(true)
1242-
.allow_non_globals_in_dht(true)
1243-
.discovery_limit(50)
1244-
.with_kademlia(genesis_hash, fork_id, &protocol_id);
1245-
1246-
config.finish()
1247-
};
1248-
1249-
let runtime = tokio::runtime::Runtime::new().unwrap();
1250-
#[allow(deprecated)]
1251-
let mut swarm = libp2p::swarm::SwarmBuilder::with_executor(
1252-
transport,
1253-
behaviour,
1254-
keypair.public().to_peer_id(),
1255-
TokioExecutor(runtime),
1256-
)
1257-
.build();
1223+
let mut swarm = libp2p::SwarmBuilder::with_new_identity()
1224+
.with_tokio()
1225+
.with_other_transport(|keypair| {
1226+
MemoryTransport::new()
1227+
.upgrade(upgrade::Version::V1)
1228+
.authenticate(noise::Config::new(&keypair).unwrap())
1229+
.multiplex(yamux::Config::default())
1230+
.boxed()
1231+
})
1232+
.unwrap()
1233+
.with_behaviour(|keypair| {
1234+
let mut config = DiscoveryConfig::new(keypair.public().to_peer_id());
1235+
config
1236+
.with_permanent_addresses(first_swarm_peer_id_and_addr.clone())
1237+
.allow_private_ip(true)
1238+
.allow_non_globals_in_dht(true)
1239+
.discovery_limit(50)
1240+
.with_kademlia(genesis_hash, fork_id, &protocol_id);
1241+
1242+
config.finish()
1243+
})
1244+
.unwrap()
1245+
.with_swarm_config(|config| {
1246+
// This is taken care of by notification protocols in non-test environment
1247+
config.with_idle_connection_timeout(Duration::from_secs(10))
1248+
})
1249+
.build();
12581250

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

12621254
if i == 0 {
12631255
first_swarm_peer_id_and_addr =
1264-
Some((keypair.public().to_peer_id(), listen_addr.clone()))
1256+
Some((*swarm.local_peer_id(), listen_addr.clone()))
12651257
}
12661258

12671259
swarm.listen_on(listen_addr.clone()).unwrap();
@@ -1348,7 +1340,7 @@ mod tests {
13481340
}
13491341
});
13501342

1351-
futures::executor::block_on(fut);
1343+
fut.await
13521344
}
13531345

13541346
#[test]

substrate/client/network/src/network_state.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ pub enum Endpoint {
106106
impl From<ConnectedPoint> for PeerEndpoint {
107107
fn from(endpoint: ConnectedPoint) -> Self {
108108
match endpoint {
109-
ConnectedPoint::Dialer { address, role_override } =>
109+
ConnectedPoint::Dialer { address, role_override, port_use: _ } =>
110110
Self::Dialing(address, role_override.into()),
111111
ConnectedPoint::Listener { local_addr, send_back_addr } =>
112112
Self::Listening { local_addr, send_back_addr },

0 commit comments

Comments
 (0)