From 414a8fc2eda3bb72e30cefdba628cf6c361cd6e1 Mon Sep 17 00:00:00 2001 From: Aaro Altonen <48052676+altonen@users.noreply.github.com> Date: Tue, 25 Jun 2024 16:51:05 +0300 Subject: [PATCH] Upgrade libp2p to 0.52.4 (#1631) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Upgrade libp2p to 0.52.4, including a fix: * Set Kademlia to server mode (https://github.com/paritytech/substrate/pull/14703) ### TODO - [x] Fix 3 zombienet tests failing: - [x] `zombienet-substrate-0002-validators-warp-sync` - [ ] ~`zombienet-polkadot-functional-0005-parachains-disputes-past-session`~ The test is also flaky in other PRs and is not required for CI to succeed. - [x] `zombienet-polkadot-functional-0009-approval-voting-coalescing` - [x] Uncomment and update to the actual libp2p API tests in [`substrate/client/network/src/protocol/notifications/handler.rs`](https://github.com/paritytech/polkadot-sdk/blob/7331f1796f1a0b0e9fb0cd7bf441239ad9664595/substrate/client/network/src/protocol/notifications/handler.rs#L1009). - [x] When upgrading `multihash` crate as part of libp2p upgrade to version v0.19.1, uncomment the conversion code at https://github.com/paritytech/polkadot-sdk/blob/7547c4942a887029c11cbcfd5103f6d8315ab95c/substrate/client/network/types/src/multihash.rs#L159 - [x] Perform a burn-in. --------- Co-authored-by: Anton Co-authored-by: command-bot <> Co-authored-by: Dmitry Markin Co-authored-by: Bastian Köcher --- Cargo.lock | 766 ++++++++++-------- Cargo.toml | 10 +- prdoc/pr_1631.prdoc | 39 + .../client/authority-discovery/Cargo.toml | 7 +- .../client/authority-discovery/src/service.rs | 2 +- .../client/authority-discovery/src/worker.rs | 12 +- .../src/worker/addr_cache.rs | 16 +- substrate/client/network-gossip/Cargo.toml | 1 - substrate/client/network-gossip/src/bridge.rs | 3 +- substrate/client/network-gossip/src/lib.rs | 10 +- .../network-gossip/src/state_machine.rs | 2 +- substrate/client/network/src/behaviour.rs | 18 +- substrate/client/network/src/config.rs | 8 +- substrate/client/network/src/discovery.rs | 147 ++-- .../client/network/src/litep2p/service.rs | 16 +- substrate/client/network/src/peer_info.rs | 92 ++- substrate/client/network/src/protocol.rs | 19 +- .../src/protocol/notifications/behaviour.rs | 37 +- .../src/protocol/notifications/handler.rs | 85 +- .../src/protocol/notifications/tests.rs | 16 +- .../src/protocol/notifications/upgrade.rs | 1 + .../protocol/notifications/upgrade/collec.rs | 12 +- .../notifications/upgrade/notifications.rs | 228 +++--- .../client/network/src/request_responses.rs | 49 +- substrate/client/network/src/service.rs | 146 ++-- substrate/client/network/src/transport.rs | 4 +- substrate/client/network/src/types.rs | 8 +- substrate/client/network/statement/Cargo.toml | 1 - .../client/network/transactions/Cargo.toml | 1 - substrate/client/network/types/Cargo.toml | 5 +- .../client/network/types/src/multiaddr.rs | 13 + .../network/types/src/multiaddr/protocol.rs | 112 +++ .../client/network/types/src/multihash.rs | 30 +- substrate/client/offchain/Cargo.toml | 1 - substrate/client/telemetry/src/transport.rs | 2 +- 35 files changed, 1128 insertions(+), 791 deletions(-) create mode 100644 prdoc/pr_1631.prdoc diff --git a/Cargo.lock b/Cargo.lock index 8052bcceee64..6f1e91f7b025 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1076,7 +1076,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" dependencies = [ "concurrent-queue", - "event-listener", + "event-listener 2.5.3", "futures-core", ] @@ -1086,11 +1086,11 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fa3dc5f2a8564f07759c008b9109dc0d39de92a88d5588b8a5036d286383afb" dependencies = [ - "async-lock", + "async-lock 2.8.0", "async-task", "concurrent-queue", "fastrand 1.9.0", - "futures-lite", + "futures-lite 1.13.0", "slab", ] @@ -1100,10 +1100,10 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06" dependencies = [ - "async-lock", + "async-lock 2.8.0", "autocfg", "blocking", - "futures-lite", + "futures-lite 1.13.0", ] [[package]] @@ -1114,10 +1114,10 @@ checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" dependencies = [ "async-channel", "async-executor", - "async-io", - "async-lock", + "async-io 1.13.0", + "async-lock 2.8.0", "blocking", - "futures-lite", + "futures-lite 1.13.0", "once_cell", ] @@ -1127,27 +1127,57 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" dependencies = [ - "async-lock", + "async-lock 2.8.0", "autocfg", "cfg-if", "concurrent-queue", - "futures-lite", + "futures-lite 1.13.0", "log", "parking", - "polling", + "polling 2.8.0", "rustix 0.37.23", "slab", "socket2 0.4.9", "waker-fn", ] +[[package]] +name = "async-io" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6baa8f0178795da0e71bc42c9e5d13261aac7ee549853162e66a241ba17964" +dependencies = [ + "async-lock 3.4.0", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite 2.3.0", + "parking", + "polling 3.4.0", + "rustix 0.38.21", + "slab", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "async-lock" version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" dependencies = [ - "event-listener", + "event-listener 2.5.3", +] + +[[package]] +name = "async-lock" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +dependencies = [ + "event-listener 5.2.0", + "event-listener-strategy", + "pin-project-lite 0.2.12", ] [[package]] @@ -1156,10 +1186,10 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4051e67316bc7eff608fe723df5d32ed639946adcd69e07df41fd42a7b411f1f" dependencies = [ - "async-io", + "async-io 1.13.0", "autocfg", "blocking", - "futures-lite", + "futures-lite 1.13.0", ] [[package]] @@ -1168,13 +1198,13 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a9d28b1d97e08915212e2e45310d47854eafa69600756fc735fb788f75199c9" dependencies = [ - "async-io", - "async-lock", + "async-io 1.13.0", + "async-lock 2.8.0", "autocfg", "blocking", "cfg-if", - "event-listener", - "futures-lite", + "event-listener 2.5.3", + "futures-lite 1.13.0", "rustix 0.37.23", "signal-hook", "windows-sys 0.48.0", @@ -1189,13 +1219,13 @@ dependencies = [ "async-attributes", "async-channel", "async-global-executor", - "async-io", - "async-lock", + "async-io 1.13.0", + "async-lock 2.8.0", "crossbeam-utils", "futures-channel", "futures-core", "futures-io", - "futures-lite", + "futures-lite 1.13.0", "gloo-timers", "kv-log-macro", "log", @@ -1271,6 +1301,17 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3" +[[package]] +name = "attohttpc" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d9a9bf8b79a749ee0b911b91b671cc2b6c670bdbc7e3dfd537576ddc94bb2a2" +dependencies = [ + "http", + "log", + "url", +] + [[package]] name = "atty" version = "0.2.14" @@ -1603,11 +1644,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77231a1c8f801696fc0123ec6150ce92cffb8e164a02afb9c8ddee0e9b65ad65" dependencies = [ "async-channel", - "async-lock", + "async-lock 2.8.0", "async-task", "atomic-waker", "fastrand 1.9.0", - "futures-lite", + "futures-lite 1.13.0", "log", ] @@ -5334,6 +5375,27 @@ version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +[[package]] +name = "event-listener" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b5fb89194fa3cad959b833185b3063ba881dbfc7030680b314250779fb4cc91" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite 0.2.12", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +dependencies = [ + "event-listener 5.2.0", + "pin-project-lite 0.2.12", +] + [[package]] name = "exit-future" version = "0.2.0" @@ -5574,7 +5636,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" dependencies = [ "crc32fast", - "libz-sys", "miniz_oxide", ] @@ -5939,7 +6000,7 @@ dependencies = [ "frame-support-procedural-tools", "itertools 0.11.0", "macro_magic", - "proc-macro-warning", + "proc-macro-warning 1.0.0", "proc-macro2 1.0.82", "quote 1.0.35", "regex", @@ -6141,6 +6202,16 @@ dependencies = [ "futures-util", ] +[[package]] +name = "futures-bounded" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b07bbbe7d7e78809544c6f718d875627addc73a7c3582447abc052cd3dc67e0" +dependencies = [ + "futures-timer", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.30" @@ -6190,6 +6261,16 @@ dependencies = [ "waker-fn", ] +[[package]] +name = "futures-lite" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +dependencies = [ + "futures-core", + "pin-project-lite 0.2.12", +] + [[package]] name = "futures-macro" version = "0.3.30" @@ -6203,13 +6284,12 @@ dependencies = [ [[package]] name = "futures-rustls" -version = "0.22.2" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2411eed028cdf8c8034eaf21f9915f956b6c3abec4d4c7949ee67f0721127bd" +checksum = "35bd3cf68c183738046838e300353e4716c674dc5e56890de4826801a6622a28" dependencies = [ "futures-io", - "rustls 0.20.8", - "webpki", + "rustls 0.21.7", ] [[package]] @@ -6744,7 +6824,7 @@ dependencies = [ "http", "hyper", "log", - "rustls 0.21.6", + "rustls 0.21.7", "rustls-native-certs 0.6.3", "tokio", "tokio-rustls 0.24.1", @@ -6796,21 +6876,21 @@ dependencies = [ [[package]] name = "if-addrs" -version = "0.7.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc0fa01ffc752e9dbc72818cdb072cd028b86be5e09dd04c5a643704fe101a9" +checksum = "cabb0019d51a643781ff15c9c8a3e5dedc365c47211270f4e8f82812fedd8f0a" dependencies = [ "libc", - "winapi", + "windows-sys 0.48.0", ] [[package]] name = "if-watch" -version = "3.0.1" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9465340214b296cd17a0009acdb890d6160010b8adf8f78a00d0d7ab270f79f" +checksum = "d6b0422c86d7ce0e97169cc42e04ae643caf278874a7a3c87b8150a220dc7e1e" dependencies = [ - "async-io", + "async-io 2.3.3", "core-foundation", "fnv", "futures", @@ -6820,7 +6900,26 @@ dependencies = [ "rtnetlink", "system-configuration", "tokio", - "windows 0.34.0", + "windows 0.51.1", +] + +[[package]] +name = "igd-next" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "064d90fec10d541084e7b39ead8875a5a80d9114a2b18791565253bae25f49e4" +dependencies = [ + "async-trait", + "attohttpc", + "bytes", + "futures", + "http", + "hyper", + "log", + "rand 0.8.5", + "tokio", + "url", + "xmltree", ] [[package]] @@ -7037,13 +7136,13 @@ dependencies = [ "curl", "curl-sys", "encoding_rs", - "event-listener", - "futures-lite", + "event-listener 2.5.3", + "futures-lite 1.13.0", "http", "log", "mime", "once_cell", - "polling", + "polling 2.8.0", "slab", "sluice", "tracing", @@ -7458,11 +7557,12 @@ dependencies = [ [[package]] name = "libp2p" -version = "0.51.4" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f35eae38201a993ece6bdc823292d6abd1bffed1c4d0f4a3517d2bd8e1d917fe" +checksum = "e94495eb319a85b70a68b85e2389a95bb3555c71c49025b78c691a854a7e6464" dependencies = [ "bytes", + "either", "futures", "futures-timer", "getrandom 0.2.10", @@ -7482,18 +7582,21 @@ dependencies = [ "libp2p-request-response", "libp2p-swarm", "libp2p-tcp", + "libp2p-upnp", "libp2p-wasm-ext", "libp2p-websocket", "libp2p-yamux", - "multiaddr", + "multiaddr 0.18.1", "pin-project", + "rw-stream-sink", + "thiserror", ] [[package]] name = "libp2p-allow-block-list" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "510daa05efbc25184458db837f6f9a5143888f1caa742426d92e1833ddd38a50" +checksum = "55b46558c5c0bf99d3e2a1a38fd54ff5476ca66dd1737b12466a1824dd219311" dependencies = [ "libp2p-core", "libp2p-identity", @@ -7503,9 +7606,9 @@ dependencies = [ [[package]] name = "libp2p-connection-limits" -version = "0.1.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4caa33f1d26ed664c4fe2cca81a08c8e07d4c1c04f2f4ac7655c2dd85467fda0" +checksum = "2f5107ad45cb20b2f6c3628c7b6014b996fcb13a88053f4569c872c6e30abf58" dependencies = [ "libp2p-core", "libp2p-identity", @@ -7515,9 +7618,9 @@ dependencies = [ [[package]] name = "libp2p-core" -version = "0.39.2" +version = "0.40.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c1df63c0b582aa434fb09b2d86897fa2b419ffeccf934b36f87fcedc8e835c2" +checksum = "dd44289ab25e4c9230d9246c475a22241e301b23e8f4061d3bdef304a1a99713" dependencies = [ "either", "fnv", @@ -7526,8 +7629,8 @@ dependencies = [ "instant", "libp2p-identity", "log", - "multiaddr", - "multihash 0.17.0", + "multiaddr 0.18.1", + "multihash 0.19.1", "multistream-select", "once_cell", "parking_lot 0.12.1", @@ -7543,33 +7646,36 @@ dependencies = [ [[package]] name = "libp2p-dns" -version = "0.39.0" +version = "0.40.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146ff7034daae62077c415c2376b8057368042df6ab95f5432ad5e88568b1554" +checksum = "e6a18db73084b4da2871438f6239fef35190b05023de7656e877c18a00541a3b" dependencies = [ + "async-trait", "futures", "libp2p-core", + "libp2p-identity", "log", "parking_lot 0.12.1", "smallvec", - "trust-dns-resolver 0.22.0", + "trust-dns-resolver", ] [[package]] name = "libp2p-identify" -version = "0.42.2" +version = "0.43.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5455f472243e63b9c497ff320ded0314254a9eb751799a39c283c6f20b793f3c" +checksum = "45a96638a0a176bec0a4bcaebc1afa8cf909b114477209d7456ade52c61cd9cd" dependencies = [ "asynchronous-codec", "either", "futures", + "futures-bounded", "futures-timer", "libp2p-core", "libp2p-identity", "libp2p-swarm", "log", - "lru 0.10.1", + "lru 0.12.3", "quick-protobuf", "quick-protobuf-codec", "smallvec", @@ -7579,27 +7685,27 @@ dependencies = [ [[package]] name = "libp2p-identity" -version = "0.1.3" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "276bb57e7af15d8f100d3c11cbdd32c6752b7eef4ba7a18ecf464972c07abcce" +checksum = "999ec70441b2fb35355076726a6bc466c932e9bdc66f6a11c6c0aa17c7ab9be0" dependencies = [ - "bs58 0.4.0", + "bs58 0.5.0", "ed25519-dalek 2.1.1", - "log", - "multiaddr", - "multihash 0.17.0", + "hkdf", + "multihash 0.19.1", "quick-protobuf", "rand 0.8.5", "sha2 0.10.8", "thiserror", + "tracing", "zeroize", ] [[package]] name = "libp2p-kad" -version = "0.43.3" +version = "0.44.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39d5ef876a2b2323d63c258e63c2f8e36f205fe5a11f0b3095d59635650790ff" +checksum = "16ea178dabba6dde6ffc260a8e0452ccdc8f79becf544946692fff9d412fc29d" dependencies = [ "arrayvec 0.7.4", "asynchronous-codec", @@ -7614,6 +7720,7 @@ dependencies = [ "libp2p-swarm", "log", "quick-protobuf", + "quick-protobuf-codec", "rand 0.8.5", "sha2 0.10.8", "smallvec", @@ -7625,9 +7732,9 @@ dependencies = [ [[package]] name = "libp2p-mdns" -version = "0.43.1" +version = "0.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19983e1f949f979a928f2c603de1cf180cc0dc23e4ac93a62651ccb18341460b" +checksum = "42a2567c305232f5ef54185e9604579a894fd0674819402bb0ac0246da82f52a" dependencies = [ "data-encoding", "futures", @@ -7638,7 +7745,7 @@ dependencies = [ "log", "rand 0.8.5", "smallvec", - "socket2 0.4.9", + "socket2 0.5.6", "tokio", "trust-dns-proto 0.22.0", "void", @@ -7646,30 +7753,35 @@ dependencies = [ [[package]] name = "libp2p-metrics" -version = "0.12.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a42ec91e227d7d0dafa4ce88b333cdf5f277253873ab087555c92798db2ddd46" +checksum = "239ba7d28f8d0b5d77760dc6619c05c7e88e74ec8fbbe97f856f20a56745e620" dependencies = [ + "instant", "libp2p-core", "libp2p-identify", + "libp2p-identity", "libp2p-kad", "libp2p-ping", "libp2p-swarm", + "once_cell", "prometheus-client", ] [[package]] name = "libp2p-noise" -version = "0.42.2" +version = "0.43.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3673da89d29936bc6435bafc638e2f184180d554ce844db65915113f86ec5e" +checksum = "d2eeec39ad3ad0677551907dd304b2f13f17208ccebe333bef194076cd2e8921" dependencies = [ "bytes", - "curve25519-dalek 3.2.0", + "curve25519-dalek 4.1.3", "futures", "libp2p-core", "libp2p-identity", "log", + "multiaddr 0.18.1", + "multihash 0.19.1", "once_cell", "quick-protobuf", "rand 0.8.5", @@ -7677,21 +7789,22 @@ dependencies = [ "snow", "static_assertions", "thiserror", - "x25519-dalek 1.1.1", + "x25519-dalek", "zeroize", ] [[package]] name = "libp2p-ping" -version = "0.42.0" +version = "0.43.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e57759c19c28a73ef1eb3585ca410cefb72c1a709fcf6de1612a378e4219202" +checksum = "e702d75cd0827dfa15f8fd92d15b9932abe38d10d21f47c50438c71dd1b5dae3" dependencies = [ "either", "futures", "futures-timer", "instant", "libp2p-core", + "libp2p-identity", "libp2p-swarm", "log", "rand 0.8.5", @@ -7700,9 +7813,9 @@ dependencies = [ [[package]] name = "libp2p-quic" -version = "0.7.0-alpha.3" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6b26abd81cd2398382a1edfe739b539775be8a90fa6914f39b2ab49571ec735" +checksum = "130d451d83f21b81eb7b35b360bc7972aeafb15177784adc56528db082e6b927" dependencies = [ "bytes", "futures", @@ -7713,18 +7826,20 @@ dependencies = [ "libp2p-tls", "log", "parking_lot 0.12.1", - "quinn-proto", + "quinn 0.10.2", "rand 0.8.5", - "rustls 0.20.8", + "ring 0.16.20", + "rustls 0.21.7", + "socket2 0.5.6", "thiserror", "tokio", ] [[package]] name = "libp2p-request-response" -version = "0.24.1" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffdb374267d42dc5ed5bc53f6e601d4a64ac5964779c6e40bb9e4f14c1e30d5" +checksum = "d8e3b4d67870478db72bac87bfc260ee6641d0734e0e3e275798f089c3fecfd4" dependencies = [ "async-trait", "futures", @@ -7732,15 +7847,17 @@ dependencies = [ "libp2p-core", "libp2p-identity", "libp2p-swarm", + "log", "rand 0.8.5", "smallvec", + "void", ] [[package]] name = "libp2p-swarm" -version = "0.42.2" +version = "0.43.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "903b3d592d7694e56204d211f29d31bc004be99386644ba8731fc3e3ef27b296" +checksum = "580189e0074af847df90e75ef54f3f30059aedda37ea5a1659e8b9fca05c0141" dependencies = [ "either", "fnv", @@ -7751,6 +7868,8 @@ dependencies = [ "libp2p-identity", "libp2p-swarm-derive", "log", + "multistream-select", + "once_cell", "rand 0.8.5", "smallvec", "tokio", @@ -7759,36 +7878,39 @@ dependencies = [ [[package]] name = "libp2p-swarm-derive" -version = "0.32.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fba456131824ab6acd4c7bf61e9c0f0a3014b5fc9868ccb8e10d344594cdc4f" +checksum = "c4d5ec2a3df00c7836d7696c136274c9c59705bac69133253696a6c932cd1d74" dependencies = [ "heck 0.4.1", + "proc-macro-warning 0.4.2", + "proc-macro2 1.0.82", "quote 1.0.35", - "syn 1.0.109", + "syn 2.0.61", ] [[package]] name = "libp2p-tcp" -version = "0.39.0" +version = "0.40.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d33698596d7722d85d3ab0c86c2c322254fce1241e91208e3679b4eb3026cf" +checksum = "b558dd40d1bcd1aaaed9de898e9ec6a436019ecc2420dd0016e712fbb61c5508" dependencies = [ "futures", "futures-timer", "if-watch", "libc", "libp2p-core", + "libp2p-identity", "log", - "socket2 0.4.9", + "socket2 0.5.6", "tokio", ] [[package]] name = "libp2p-tls" -version = "0.1.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff08d13d0dc66e5e9ba6279c1de417b84fa0d0adc3b03e5732928c180ec02781" +checksum = "8218d1d5482b122ccae396bbf38abdcb283ecc96fa54760e1dfd251f0546ac61" dependencies = [ "futures", "futures-rustls", @@ -7796,51 +7918,68 @@ dependencies = [ "libp2p-identity", "rcgen", "ring 0.16.20", - "rustls 0.20.8", + "rustls 0.21.7", + "rustls-webpki 0.101.4", "thiserror", - "webpki", - "x509-parser 0.14.0", + "x509-parser", "yasna", ] +[[package]] +name = "libp2p-upnp" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82775a47b34f10f787ad3e2a22e2c1541e6ebef4fe9f28f3ac553921554c94c1" +dependencies = [ + "futures", + "futures-timer", + "igd-next", + "libp2p-core", + "libp2p-swarm", + "log", + "tokio", + "void", +] + [[package]] name = "libp2p-wasm-ext" -version = "0.39.0" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77dff9d32353a5887adb86c8afc1de1a94d9e8c3bc6df8b2201d7cdf5c848f43" +checksum = "1e5d8e3a9e07da0ef5b55a9f26c009c8fb3c725d492d8bb4b431715786eea79c" dependencies = [ "futures", "js-sys", "libp2p-core", - "parity-send-wrapper", + "send_wrapper", "wasm-bindgen", "wasm-bindgen-futures", ] [[package]] name = "libp2p-websocket" -version = "0.41.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "111273f7b3d3510524c752e8b7a5314b7f7a1fee7e68161c01a7d72cbb06db9f" +checksum = "3facf0691bab65f571bc97c6c65ffa836248ca631d631b7691ac91deb7fceb5f" dependencies = [ "either", "futures", "futures-rustls", "libp2p-core", + "libp2p-identity", "log", "parking_lot 0.12.1", "quicksink", "rw-stream-sink", "soketto", "url", - "webpki-roots 0.22.6", + "webpki-roots", ] [[package]] name = "libp2p-yamux" -version = "0.43.1" +version = "0.44.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd21d950662700a385d4c6d68e2f5f54d778e97068cdd718522222ef513bda" +checksum = "8eedcb62824c4300efb9cfd4e2a6edaf3ca097b9e68b36dabe45a44469fd6a85" dependencies = [ "futures", "libp2p-core", @@ -8022,7 +8161,7 @@ dependencies = [ "indexmap 2.2.3", "libc", "mockall 0.12.1", - "multiaddr", + "multiaddr 0.17.1", "multihash 0.17.0", "network-interface", "nohash-hasher", @@ -8030,11 +8169,11 @@ dependencies = [ "pin-project", "prost 0.11.9", "prost-build 0.11.9", - "quinn", + "quinn 0.9.4", "rand 0.8.5", "rcgen", "ring 0.16.20", - "rustls 0.20.8", + "rustls 0.20.9", "serde", "sha2 0.10.8", "simple-dns", @@ -8049,13 +8188,13 @@ dependencies = [ "tokio-tungstenite", "tokio-util", "tracing", - "trust-dns-resolver 0.23.2", + "trust-dns-resolver", "uint", "unsigned-varint", "url", "webpki", - "x25519-dalek 2.0.0", - "x509-parser 0.15.1", + "x25519-dalek", + "x509-parser", "yasna", "zeroize", ] @@ -8091,18 +8230,18 @@ dependencies = [ [[package]] name = "lru" -version = "0.10.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "718e8fae447df0c7e1ba7f5189829e63fd536945c8988d61444c19039f16b670" -dependencies = [ - "hashbrown 0.13.2", -] +checksum = "eedb2bdbad7e0634f83989bf596f497b070130daaa398ab22d84c39e266deec5" [[package]] name = "lru" -version = "0.11.0" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eedb2bdbad7e0634f83989bf596f497b070130daaa398ab22d84c39e266deec5" +checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +dependencies = [ + "hashbrown 0.14.3", +] [[package]] name = "lru-cache" @@ -8601,6 +8740,25 @@ dependencies = [ "url", ] +[[package]] +name = "multiaddr" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b852bc02a2da5feed68cd14fa50d0774b92790a5bdbfa932a813926c8472070" +dependencies = [ + "arrayref", + "byteorder", + "data-encoding", + "libp2p-identity", + "multibase", + "multihash 0.19.1", + "percent-encoding", + "serde", + "static_assertions", + "unsigned-varint", + "url", +] + [[package]] name = "multibase" version = "0.9.1" @@ -8623,7 +8781,7 @@ dependencies = [ "blake3", "core2", "digest 0.10.7", - "multihash-derive 0.8.0", + "multihash-derive", "sha2 0.10.8", "sha3", "unsigned-varint", @@ -8640,7 +8798,7 @@ dependencies = [ "blake3", "core2", "digest 0.10.7", - "multihash-derive 0.8.0", + "multihash-derive", "sha2 0.10.8", "sha3", "unsigned-varint", @@ -8656,26 +8814,6 @@ dependencies = [ "unsigned-varint", ] -[[package]] -name = "multihash-codetable" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6d815ecb3c8238d00647f8630ede7060a642c9f704761cd6082cb4028af6935" -dependencies = [ - "blake2b_simd", - "blake2s_simd", - "blake3", - "core2", - "digest 0.10.7", - "multihash-derive 0.9.0", - "ripemd", - "serde", - "sha1", - "sha2 0.10.8", - "sha3", - "strobe-rs", -] - [[package]] name = "multihash-derive" version = "0.8.0" @@ -8690,31 +8828,6 @@ dependencies = [ "synstructure", ] -[[package]] -name = "multihash-derive" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "890e72cb7396cb99ed98c1246a97b243cc16394470d94e0bc8b0c2c11d84290e" -dependencies = [ - "core2", - "multihash 0.19.1", - "multihash-derive-impl", -] - -[[package]] -name = "multihash-derive-impl" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d38685e08adb338659871ecfc6ee47ba9b22dcc8abcf6975d379cc49145c3040" -dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro-error", - "proc-macro2 1.0.82", - "quote 1.0.35", - "syn 1.0.109", - "synstructure", -] - [[package]] name = "multimap" version = "0.8.3" @@ -8723,9 +8836,9 @@ checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" [[package]] name = "multistream-select" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8552ab875c1313b97b8d20cb857b9fd63e2d1d6a0a1b53ce9821e575405f27a" +checksum = "ea0df8e5eec2298a62b326ee4f0d7fe1a6b90a09dfcf9df37b38f947a8c42f19" dependencies = [ "bytes", "futures", @@ -12058,12 +12171,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "parity-send-wrapper" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa9777aa91b8ad9dd5aaa04a9b6bcb02c7f1deb952fca5a66034d5e63afc5c6f" - [[package]] name = "parity-util-mem" version = "0.12.0" @@ -14969,6 +15076,20 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "polling" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30054e72317ab98eddd8561db0f6524df3367636884b7b21b703e4b280a84a14" +dependencies = [ + "cfg-if", + "concurrent-queue", + "pin-project-lite 0.2.12", + "rustix 0.38.21", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "poly1305" version = "0.8.0" @@ -15191,6 +15312,17 @@ version = "0.5.20+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" +[[package]] +name = "proc-macro-warning" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1eaa7fa0aa1929ffdf7eeb6eac234dde6268914a14ad44d23521ab6a9b258e" +dependencies = [ + "proc-macro2 1.0.82", + "quote 1.0.35", + "syn 2.0.61", +] + [[package]] name = "proc-macro-warning" version = "1.0.0" @@ -15262,9 +15394,9 @@ dependencies = [ [[package]] name = "prometheus-client" -version = "0.19.0" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6fa99d535dd930d1249e6c79cb3c2915f9172a540fe2b02a4c8f9ca954721e" +checksum = "3c99afa9a01501019ac3a14d71d9f94050346f55ca471ce90c799a15c58f61e2" dependencies = [ "dtoa", "itoa", @@ -15494,9 +15626,9 @@ dependencies = [ [[package]] name = "quick-protobuf-codec" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1693116345026436eb2f10b677806169c1a1260c1c60eaaffe3fb5a29ae23d8b" +checksum = "f8ededb1cd78531627244d51dd0c7139fbe736c7d57af0092a76f0ffb2f56e98" dependencies = [ "asynchronous-codec", "bytes", @@ -15546,27 +15678,45 @@ checksum = "2e8b432585672228923edbbf64b8b12c14e1112f62e88737655b4a083dbcd78e" dependencies = [ "bytes", "pin-project-lite 0.2.12", - "quinn-proto", - "quinn-udp", + "quinn-proto 0.9.6", + "quinn-udp 0.3.2", "rustc-hash", - "rustls 0.20.8", + "rustls 0.20.9", "thiserror", "tokio", "tracing", "webpki", ] +[[package]] +name = "quinn" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cc2c5017e4b43d5995dcea317bc46c1e09404c0a9664d2908f7f02dfe943d75" +dependencies = [ + "bytes", + "futures-io", + "pin-project-lite 0.2.12", + "quinn-proto 0.10.6", + "quinn-udp 0.4.1", + "rustc-hash", + "rustls 0.21.7", + "thiserror", + "tokio", + "tracing", +] + [[package]] name = "quinn-proto" -version = "0.9.5" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c956be1b23f4261676aed05a0046e204e8a6836e50203902683a718af0797989" +checksum = "94b0b33c13a79f669c85defaf4c275dc86a0c0372807d0ca3d78e0bb87274863" dependencies = [ "bytes", "rand 0.8.5", "ring 0.16.20", "rustc-hash", - "rustls 0.20.8", + "rustls 0.20.9", "slab", "thiserror", "tinyvec", @@ -15574,6 +15724,23 @@ dependencies = [ "webpki", ] +[[package]] +name = "quinn-proto" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "141bf7dfde2fbc246bfd3fe12f2455aa24b0fbd9af535d8c86c7bd1381ff2b1a" +dependencies = [ + "bytes", + "rand 0.8.5", + "ring 0.16.20", + "rustc-hash", + "rustls 0.21.7", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + [[package]] name = "quinn-udp" version = "0.3.2" @@ -15581,12 +15748,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "641538578b21f5e5c8ea733b736895576d0fe329bb883b937db6f4d163dbaaf4" dependencies = [ "libc", - "quinn-proto", + "quinn-proto 0.9.6", "socket2 0.4.9", "tracing", "windows-sys 0.42.0", ] +[[package]] +name = "quinn-udp" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "055b4e778e8feb9f93c4e439f71dc2156ef13360b432b799e179a8c4cdf0b1d7" +dependencies = [ + "bytes", + "libc", + "socket2 0.5.6", + "tracing", + "windows-sys 0.48.0", +] + [[package]] name = "quote" version = "0.6.13" @@ -16034,7 +16214,7 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite 0.2.12", - "rustls 0.21.6", + "rustls 0.21.7", "rustls-pemfile 1.0.3", "serde", "serde_json", @@ -16046,7 +16226,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots 0.25.2", + "webpki-roots", "winreg", ] @@ -16115,15 +16295,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "ripemd" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" -dependencies = [ - "digest 0.10.7", -] - [[package]] name = "rle-decode-fast" version = "1.0.3" @@ -16564,11 +16735,10 @@ dependencies = [ [[package]] name = "rustls" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" +checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" dependencies = [ - "log", "ring 0.16.20", "sct", "webpki", @@ -16576,9 +16746,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.6" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1feddffcfcc0b33f5c6ce9a29e341e4cd59c3f78e7ee45f4a40c038b1d6cbb" +checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" dependencies = [ "log", "ring 0.16.20", @@ -16702,9 +16872,9 @@ dependencies = [ [[package]] name = "rw-stream-sink" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26338f5e09bb721b85b135ea05af7767c90b52f6de4f087d4f4a3a9d64e7dc04" +checksum = "d8c9026ff5d2f23da5e45bbc283f156383001bfb09c4e44256d02c1a685fe9a1" dependencies = [ "futures", "pin-project", @@ -16765,8 +16935,7 @@ dependencies = [ "libp2p", "linked_hash_set", "log", - "multihash 0.17.0", - "multihash-codetable", + "multihash 0.19.1", "parity-scale-codec", "prost 0.12.4", "prost-build 0.12.4", @@ -17472,7 +17641,7 @@ dependencies = [ "futures-timer", "log", "mixnet", - "multiaddr", + "multiaddr 0.18.1", "parity-scale-codec", "parking_lot 0.12.1", "sc-client-api", @@ -17578,7 +17747,6 @@ dependencies = [ "async-trait", "futures", "futures-timer", - "libp2p", "log", "parity-scale-codec", "quickcheck", @@ -17621,7 +17789,6 @@ dependencies = [ "array-bytes", "async-channel", "futures", - "libp2p", "log", "parity-scale-codec", "sc-network", @@ -17712,7 +17879,6 @@ version = "0.33.0" dependencies = [ "array-bytes", "futures", - "libp2p", "log", "parity-scale-codec", "sc-network", @@ -17733,8 +17899,9 @@ dependencies = [ "ed25519-dalek 2.1.1", "libp2p-identity", "litep2p", - "multiaddr", - "multihash 0.17.0", + "log", + "multiaddr 0.18.1", + "multihash 0.19.1", "quickcheck", "rand 0.8.5", "thiserror", @@ -17754,7 +17921,6 @@ dependencies = [ "hyper", "hyper-rustls", "lazy_static", - "libp2p", "log", "num_cpus", "once_cell", @@ -18571,6 +18737,12 @@ dependencies = [ "pest", ] +[[package]] +name = "send_wrapper" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" + [[package]] name = "separator" version = "0.4.1" @@ -18982,12 +19154,12 @@ dependencies = [ "async-channel", "async-executor", "async-fs", - "async-io", - "async-lock", + "async-io 1.13.0", + "async-lock 2.8.0", "async-net", "async-process", "blocking", - "futures-lite", + "futures-lite 1.13.0", ] [[package]] @@ -19006,7 +19178,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0bb30cf57b7b5f6109ce17c3164445e2d6f270af2cb48f6e4d31c2967c9a9f5" dependencies = [ "arrayvec 0.7.4", - "async-lock", + "async-lock 2.8.0", "atomic-take", "base64 0.21.2", "bip39", @@ -19017,9 +19189,9 @@ dependencies = [ "derive_more", "ed25519-zebra", "either", - "event-listener", + "event-listener 2.5.3", "fnv", - "futures-lite", + "futures-lite 1.13.0", "futures-util", "hashbrown 0.14.3", "hex", @@ -19049,7 +19221,7 @@ dependencies = [ "soketto", "twox-hash", "wasmi 0.31.2", - "x25519-dalek 2.0.0", + "x25519-dalek", "zeroize", ] @@ -19060,15 +19232,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "256b5bad1d6b49045e95fe87492ce73d5af81545d8b4d8318a872d2007024c33" dependencies = [ "async-channel", - "async-lock", + "async-lock 2.8.0", "base64 0.21.2", "blake2-rfc", "derive_more", "either", - "event-listener", + "event-listener 2.5.3", "fnv", "futures-channel", - "futures-lite", + "futures-lite 1.13.0", "futures-util", "hashbrown 0.14.3", "hex", @@ -19460,7 +19632,6 @@ checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" dependencies = [ "base64 0.13.1", "bytes", - "flate2", "futures", "http", "httparse", @@ -20389,7 +20560,7 @@ dependencies = [ "sp-runtime", "sp-runtime-interface 24.0.0", "thiserror", - "x25519-dalek 2.0.0", + "x25519-dalek", ] [[package]] @@ -20877,19 +21048,6 @@ dependencies = [ "serde", ] -[[package]] -name = "strobe-rs" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabb238a1cccccfa4c4fb703670c0d157e1256c1ba695abf1b93bd2bb14bab2d" -dependencies = [ - "bitflags 1.3.2", - "byteorder", - "keccak", - "subtle 2.5.0", - "zeroize", -] - [[package]] name = "strsim" version = "0.8.0" @@ -21955,7 +22113,7 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls 0.21.6", + "rustls 0.21.7", "tokio", ] @@ -22003,7 +22161,7 @@ checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" dependencies = [ "futures-util", "log", - "rustls 0.21.6", + "rustls 0.21.7", "rustls-native-certs 0.6.3", "tokio", "tokio-rustls 0.24.1", @@ -22360,26 +22518,6 @@ dependencies = [ "url", ] -[[package]] -name = "trust-dns-resolver" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aff21aa4dcefb0a1afbfac26deb0adc93888c7d295fb63ab273ef276ba2b7cfe" -dependencies = [ - "cfg-if", - "futures-util", - "ipconfig", - "lazy_static", - "lru-cache", - "parking_lot 0.12.1", - "resolv-conf", - "smallvec", - "thiserror", - "tokio", - "tracing", - "trust-dns-proto 0.22.0", -] - [[package]] name = "trust-dns-resolver" version = "0.23.2" @@ -22442,7 +22580,7 @@ dependencies = [ "httparse", "log", "rand 0.8.5", - "rustls 0.21.6", + "rustls 0.21.7", "sha1", "thiserror", "url", @@ -23239,15 +23377,6 @@ dependencies = [ "untrusted 0.9.0", ] -[[package]] -name = "webpki-roots" -version = "0.22.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" -dependencies = [ - "webpki", -] - [[package]] name = "webpki-roots" version = "0.25.2" @@ -23474,23 +23603,20 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.34.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45296b64204227616fdbf2614cefa4c236b98ee64dfaaaa435207ed99fe7829f" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows_aarch64_msvc 0.34.0", - "windows_i686_gnu 0.34.0", - "windows_i686_msvc 0.34.0", - "windows_x86_64_gnu 0.34.0", - "windows_x86_64_msvc 0.34.0", + "windows-targets 0.48.5", ] [[package]] name = "windows" -version = "0.48.0" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" dependencies = [ + "windows-core 0.51.1", "windows-targets 0.48.5", ] @@ -23500,10 +23626,19 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ - "windows-core", + "windows-core 0.52.0", "windows-targets 0.52.0", ] +[[package]] +name = "windows-core" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-core" version = "0.52.0" @@ -23618,12 +23753,6 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" -[[package]] -name = "windows_aarch64_msvc" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" - [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -23642,12 +23771,6 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" -[[package]] -name = "windows_i686_gnu" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" - [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -23666,12 +23789,6 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" -[[package]] -name = "windows_i686_msvc" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" - [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -23690,12 +23807,6 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" -[[package]] -name = "windows_x86_64_gnu" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" - [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -23732,12 +23843,6 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" -[[package]] -name = "windows_x86_64_msvc" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" - [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -23784,17 +23889,6 @@ dependencies = [ "tap", ] -[[package]] -name = "x25519-dalek" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a0c105152107e3b96f6a00a65e86ce82d9b125230e1c4302940eca58ff71f4f" -dependencies = [ - "curve25519-dalek 3.2.0", - "rand_core 0.5.1", - "zeroize", -] - [[package]] name = "x25519-dalek" version = "2.0.0" @@ -23807,24 +23901,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "x509-parser" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0ecbeb7b67ce215e40e3cc7f2ff902f94a223acf44995934763467e7b1febc8" -dependencies = [ - "asn1-rs", - "base64 0.13.1", - "data-encoding", - "der-parser", - "lazy_static", - "nom", - "oid-registry", - "rusticata-macros", - "thiserror", - "time", -] - [[package]] name = "x509-parser" version = "0.15.1" @@ -24045,16 +24121,32 @@ dependencies = [ "xcm-simulator", ] +[[package]] +name = "xml-rs" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791978798f0597cfc70478424c2b4fdc2b7a8024aaff78497ef00f24ef674193" + +[[package]] +name = "xmltree" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7d8a75eaf6557bb84a65ace8609883db44a29951042ada9b393151532e41fcb" +dependencies = [ + "xml-rs", +] + [[package]] name = "yamux" -version = "0.10.2" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d9ba232399af1783a58d8eb26f6b5006fbefe2dc9ef36bd283324792d03ea5" +checksum = "9ed0164ae619f2dc144909a9f082187ebb5893693d8c0196e8085283ccd4b776" dependencies = [ "futures", "log", "nohash-hasher", "parking_lot 0.12.1", + "pin-project", "rand 0.8.5", "static_assertions", ] diff --git a/Cargo.toml b/Cargo.toml index 60459500a890..7eea70c31aa8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -805,8 +805,8 @@ landlock = { version = "0.3.0" } lazy_static = { version = "1.4.0" } libc = { version = "0.2.153" } libfuzzer-sys = { version = "0.4" } -libp2p = { version = "0.51.4" } -libp2p-identity = { version = "0.1.3" } +libp2p = { version = "0.52.4" } +libp2p-identity = { version = "0.2.3" } libsecp256k1 = { version = "0.7.0", default-features = false } linked-hash-map = { version = "0.5.4" } linked_hash_set = { version = "0.1.4" } @@ -831,10 +831,10 @@ mmr-gadget = { path = "substrate/client/merkle-mountain-range", default-features mmr-lib = { version = "0.5.2", package = "ckb-merkle-mountain-range" } mmr-rpc = { path = "substrate/client/merkle-mountain-range/rpc", default-features = false } mockall = { version = "0.11.3" } -multiaddr = { version = "0.17.1" } -multihash = { version = "0.17.0", default-features = false } +multiaddr = { version = "0.18.1" } +multihash = { version = "0.19.1", default-features = false } multihash-codetable = { version = "0.1.1" } -multistream-select = { version = "0.12.1" } +multistream-select = { version = "0.13.0" } names = { version = "0.14.0", default-features = false } nix = { version = "0.28.0" } node-cli = { path = "substrate/bin/node/cli", package = "staging-node-cli" } diff --git a/prdoc/pr_1631.prdoc b/prdoc/pr_1631.prdoc new file mode 100644 index 000000000000..f73d00968552 --- /dev/null +++ b/prdoc/pr_1631.prdoc @@ -0,0 +1,39 @@ +# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 +# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json + +title: Upgrade libp2p to 0.52.4 + +doc: + - audience: [Node Dev, Node Operator] + description: | + Upgrade libp2p from 0.51.4 to 0.52.4 + +crates: + - name: sc-authority-discovery + bump: minor + - name: sc-cli + bump: minor + - name: sc-mixnet + bump: minor + - name: sc-network + bump: minor + - name: sc-network-gossip + bump: minor + - name: sc-network-common + bump: minor + - name: sc-network-light + bump: minor + - name: sc-network-statement + bump: minor + - name: sc-network-sync + bump: minor + - name: sc-network-test + bump: minor + - name: sc-network-transactions + bump: minor + - name: sc-network-types + bump: minor + - name: sc-offchain + bump: major + - name: sc-telemetry + bump: major diff --git a/substrate/client/authority-discovery/Cargo.toml b/substrate/client/authority-discovery/Cargo.toml index 4dfbe7f24ac5..309c9c542a0b 100644 --- a/substrate/client/authority-discovery/Cargo.toml +++ b/substrate/client/authority-discovery/Cargo.toml @@ -25,7 +25,7 @@ futures = { workspace = true } futures-timer = { workspace = true } ip_network = { workspace = true } libp2p = { features = ["ed25519", "kad"], workspace = true } -multihash = { features = ["sha2", "std"], workspace = true } +multihash = { workspace = true } linked_hash_set = { workspace = true } log = { workspace = true, default-features = true } prost = { workspace = true } @@ -42,11 +42,6 @@ sp-core = { workspace = true, default-features = true } sp-keystore = { workspace = true, default-features = true } sp-runtime = { workspace = true, default-features = true } async-trait = { workspace = true } -multihash-codetable = { features = [ - "digest", - "serde", - "sha2", -], workspace = true } [dev-dependencies] quickcheck = { workspace = true } diff --git a/substrate/client/authority-discovery/src/service.rs b/substrate/client/authority-discovery/src/service.rs index 60c7a2b99037..852d3ab80c9b 100644 --- a/substrate/client/authority-discovery/src/service.rs +++ b/substrate/client/authority-discovery/src/service.rs @@ -55,7 +55,7 @@ impl Service { /// [`crate::Worker`] failed. /// /// Note: [`Multiaddr`]s returned always include a [`PeerId`] via a - /// [`libp2p::core::multiaddr::Protocol::P2p`] component. Equality of + /// [`sc_network_types::multiaddr::Protocol::P2p`] component. Equality of /// [`PeerId`]s across [`Multiaddr`]s returned by a single call is not /// enforced today, given that there are still authorities out there /// publishing the addresses of their sentry nodes on the DHT. In the future diff --git a/substrate/client/authority-discovery/src/worker.rs b/substrate/client/authority-discovery/src/worker.rs index f20cf6aa2121..b81b10b3ae0a 100644 --- a/substrate/client/authority-discovery/src/worker.rs +++ b/substrate/client/authority-discovery/src/worker.rs @@ -45,10 +45,7 @@ use sc_network::{ event::DhtEvent, multiaddr, KademliaKey, Multiaddr, NetworkDHTProvider, NetworkSigner, NetworkStateInfo, }; -use sc_network_types::{ - multihash::{Code, Multihash}, - PeerId, -}; +use sc_network_types::{multihash::Code, PeerId}; use schema::PeerSignature; use sp_api::{ApiError, ProvideRuntimeApi}; use sp_authority_discovery::{ @@ -247,14 +244,14 @@ where }; let public_addresses = { - let local_peer_id: Multihash = network.local_peer_id().into(); + let local_peer_id = network.local_peer_id(); config .public_addresses .into_iter() .map(|mut address| { if let Some(multiaddr::Protocol::P2p(peer_id)) = address.iter().last() { - if peer_id != local_peer_id { + if peer_id != *local_peer_id.as_ref() { error!( target: LOG_TARGET, "Discarding invalid local peer ID in public address {address}.", @@ -401,10 +398,9 @@ where ); // The address must include the local peer id. - let local_peer_id: Multihash = local_peer_id.into(); addresses .into_iter() - .map(move |a| a.with(multiaddr::Protocol::P2p(local_peer_id))) + .map(move |a| a.with(multiaddr::Protocol::P2p(*local_peer_id.as_ref()))) } /// Publish own public addresses. diff --git a/substrate/client/authority-discovery/src/worker/addr_cache.rs b/substrate/client/authority-discovery/src/worker/addr_cache.rs index 77cdfbd4f150..13bb990bf8b9 100644 --- a/substrate/client/authority-discovery/src/worker/addr_cache.rs +++ b/substrate/client/authority-discovery/src/worker/addr_cache.rs @@ -177,7 +177,7 @@ mod tests { use super::*; use quickcheck::{Arbitrary, Gen, QuickCheck, TestResult}; - use sc_network_types::multihash::Multihash; + use sc_network_types::multihash::{Code, Multihash}; use sp_authority_discovery::{AuthorityId, AuthorityPair}; use sp_core::crypto::Pair; @@ -198,10 +198,9 @@ mod tests { impl Arbitrary for TestMultiaddr { fn arbitrary(g: &mut Gen) -> Self { let seed = (0..32).map(|_| u8::arbitrary(g)).collect::>(); - let peer_id = PeerId::from_multihash( - Multihash::wrap(multihash::Code::Sha2_256.into(), &seed).unwrap(), - ) - .unwrap(); + let peer_id = + PeerId::from_multihash(Multihash::wrap(Code::Sha2_256.into(), &seed).unwrap()) + .unwrap(); let multiaddr = "/ip6/2001:db8:0:0:0:0:0:2/tcp/30333" .parse::() .unwrap() @@ -217,10 +216,9 @@ mod tests { impl Arbitrary for TestMultiaddrsSamePeerCombo { fn arbitrary(g: &mut Gen) -> Self { let seed = (0..32).map(|_| u8::arbitrary(g)).collect::>(); - let peer_id = PeerId::from_multihash( - Multihash::wrap(multihash::Code::Sha2_256.into(), &seed).unwrap(), - ) - .unwrap(); + let peer_id = + PeerId::from_multihash(Multihash::wrap(Code::Sha2_256.into(), &seed).unwrap()) + .unwrap(); let multiaddr1 = "/ip6/2001:db8:0:0:0:0:0:2/tcp/30333" .parse::() .unwrap() diff --git a/substrate/client/network-gossip/Cargo.toml b/substrate/client/network-gossip/Cargo.toml index 6a2b3e3ef78a..f1441e4a1cf2 100644 --- a/substrate/client/network-gossip/Cargo.toml +++ b/substrate/client/network-gossip/Cargo.toml @@ -20,7 +20,6 @@ targets = ["x86_64-unknown-linux-gnu"] ahash = { workspace = true } futures = { workspace = true } futures-timer = { workspace = true } -libp2p = { workspace = true } log = { workspace = true, default-features = true } schnellru = { workspace = true } tracing = { workspace = true, default-features = true } diff --git a/substrate/client/network-gossip/src/bridge.rs b/substrate/client/network-gossip/src/bridge.rs index cd344d9196d8..414da9b2a589 100644 --- a/substrate/client/network-gossip/src/bridge.rs +++ b/substrate/client/network-gossip/src/bridge.rs @@ -348,7 +348,7 @@ impl futures::future::FusedFuture for GossipEngine { #[cfg(test)] mod tests { use super::*; - use crate::{multiaddr::Multiaddr, ValidationResult, ValidatorContext}; + use crate::{ValidationResult, ValidatorContext}; use codec::{DecodeAll, Encode}; use futures::{ channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender}, @@ -363,6 +363,7 @@ mod tests { }; use sc_network_common::role::ObservedRole; use sc_network_sync::SyncEventStream; + use sc_network_types::multiaddr::Multiaddr; use sp_runtime::{ testing::H256, traits::{Block as BlockT, NumberFor}, diff --git a/substrate/client/network-gossip/src/lib.rs b/substrate/client/network-gossip/src/lib.rs index e04ea2a91e7c..20d9922200c2 100644 --- a/substrate/client/network-gossip/src/lib.rs +++ b/substrate/client/network-gossip/src/lib.rs @@ -67,9 +67,12 @@ pub use self::{ validator::{DiscardAll, MessageIntent, ValidationResult, Validator, ValidatorContext}, }; -use sc_network::{multiaddr, types::ProtocolName, NetworkBlock, NetworkEventStream, NetworkPeers}; +use sc_network::{types::ProtocolName, NetworkBlock, NetworkEventStream, NetworkPeers}; use sc_network_sync::SyncEventStream; -use sc_network_types::PeerId; +use sc_network_types::{ + multiaddr::{Multiaddr, Protocol}, + PeerId, +}; use sp_runtime::traits::{Block as BlockT, NumberFor}; use std::iter; @@ -80,8 +83,7 @@ mod validator; /// Abstraction over a network. pub trait Network: NetworkPeers + NetworkEventStream { fn add_set_reserved(&self, who: PeerId, protocol: ProtocolName) { - let addr = - iter::once(multiaddr::Protocol::P2p(who.into())).collect::(); + let addr = Multiaddr::empty().with(Protocol::P2p(*who.as_ref())); let result = self.add_peers_to_reserved_set(protocol, iter::once(addr).collect()); if let Err(err) = result { log::error!(target: "gossip", "add_set_reserved failed: {}", err); diff --git a/substrate/client/network-gossip/src/state_machine.rs b/substrate/client/network-gossip/src/state_machine.rs index 016afa95ecea..ac3f7a1b8c74 100644 --- a/substrate/client/network-gossip/src/state_machine.rs +++ b/substrate/client/network-gossip/src/state_machine.rs @@ -542,12 +542,12 @@ impl Metrics { #[cfg(test)] mod tests { use super::*; - use crate::multiaddr::Multiaddr; use futures::prelude::*; use sc_network::{ config::MultiaddrWithPeerId, event::Event, service::traits::NotificationEvent, MessageSink, NetworkBlock, NetworkEventStream, NetworkPeers, ReputationChange, }; + use sc_network_types::multiaddr::Multiaddr; use sp_runtime::{ testing::{Block as RawBlock, ExtrinsicWrapper, H256}, traits::NumberFor, diff --git a/substrate/client/network/src/behaviour.rs b/substrate/client/network/src/behaviour.rs index 68deac0f47bc..68816a10980d 100644 --- a/substrate/client/network/src/behaviour.rs +++ b/substrate/client/network/src/behaviour.rs @@ -31,8 +31,8 @@ use crate::{ use futures::channel::oneshot; use libp2p::{ - core::Multiaddr, identify::Info as IdentifyInfo, identity::PublicKey, kad::RecordKey, - swarm::NetworkBehaviour, PeerId, + connection_limits::ConnectionLimits, core::Multiaddr, identify::Info as IdentifyInfo, + identity::PublicKey, kad::RecordKey, swarm::NetworkBehaviour, PeerId, StreamProtocol, }; use parking_lot::Mutex; @@ -47,8 +47,10 @@ pub use crate::request_responses::{InboundFailure, OutboundFailure, ResponseFail /// General behaviour of the network. Combines all protocols together. #[derive(NetworkBehaviour)] -#[behaviour(out_event = "BehaviourOut")] +#[behaviour(to_swarm = "BehaviourOut")] pub struct Behaviour { + /// Connection limits. + connection_limits: libp2p::connection_limits::Behaviour, /// All the substrate-specific protocols. substrate: Protocol, /// Periodically pings and identifies the nodes we are connected to, and store information in a @@ -180,6 +182,7 @@ impl Behaviour { request_response_protocols: Vec, peer_store_handle: Arc, external_addresses: Arc>>, + connection_limits: ConnectionLimits, ) -> Result { Ok(Self { substrate, @@ -193,6 +196,7 @@ impl Behaviour { request_response_protocols.into_iter(), peer_store_handle, )?, + connection_limits: libp2p::connection_limits::Behaviour::new(connection_limits), }) } @@ -267,7 +271,7 @@ impl Behaviour { pub fn add_self_reported_address_to_dht( &mut self, peer_id: &PeerId, - supported_protocols: &[impl AsRef<[u8]>], + supported_protocols: &[StreamProtocol], addr: Multiaddr, ) { self.discovery.add_self_reported_address(peer_id, supported_protocols, addr); @@ -376,3 +380,9 @@ impl From for BehaviourOut { } } } + +impl From for BehaviourOut { + fn from(e: void::Void) -> Self { + void::unreachable(e) + } +} diff --git a/substrate/client/network/src/config.rs b/substrate/client/network/src/config.rs index 100a1e9dfb38..e939558b20b8 100644 --- a/substrate/client/network/src/config.rs +++ b/substrate/client/network/src/config.rs @@ -114,13 +114,13 @@ pub fn parse_str_addr(addr_str: &str) -> Result<(PeerId, Multiaddr), ParseErr> { /// Splits a Multiaddress into a Multiaddress and PeerId. pub fn parse_addr(mut addr: Multiaddr) -> Result<(PeerId, Multiaddr), ParseErr> { - let who = match addr.pop() { - Some(multiaddr::Protocol::P2p(key)) => - PeerId::from_multihash(key).map_err(|_| ParseErr::InvalidPeerId)?, + let multihash = match addr.pop() { + Some(multiaddr::Protocol::P2p(multihash)) => multihash, _ => return Err(ParseErr::PeerIdMissing), }; + let peer_id = PeerId::from_multihash(multihash).map_err(|_| ParseErr::InvalidPeerId)?; - Ok((who, addr)) + Ok((peer_id, addr)) } /// Address of a node, including its identity. diff --git a/substrate/client/network/src/discovery.rs b/substrate/client/network/src/discovery.rs index 2c788ec713f3..3145b891a8d3 100644 --- a/substrate/client/network/src/discovery.rs +++ b/substrate/client/network/src/discovery.rs @@ -55,20 +55,20 @@ use ip_network::IpNetwork; use libp2p::{ core::{Endpoint, Multiaddr}, kad::{ - handler::KademliaHandler, + self, record::store::{MemoryStore, RecordStore}, - GetClosestPeersError, GetRecordOk, Kademlia, KademliaBucketInserts, KademliaConfig, - KademliaEvent, QueryId, QueryResult, Quorum, Record, RecordKey, + Behaviour as Kademlia, BucketInserts, Config as KademliaConfig, Event as KademliaEvent, + GetClosestPeersError, GetRecordOk, QueryId, QueryResult, Quorum, Record, RecordKey, }, mdns::{self, tokio::Behaviour as TokioMdns}, multiaddr::Protocol, swarm::{ behaviour::{ toggle::{Toggle, ToggleConnectionHandler}, - DialFailure, FromSwarm, NewExternalAddr, + DialFailure, ExternalAddrConfirmed, FromSwarm, }, - ConnectionDenied, ConnectionId, DialError, NetworkBehaviour, PollParameters, THandler, - THandlerInEvent, THandlerOutEvent, ToSwarm, + ConnectionDenied, ConnectionId, DialError, NetworkBehaviour, PollParameters, + StreamProtocol, THandler, THandlerInEvent, THandlerOutEvent, ToSwarm, }, PeerId, }; @@ -105,8 +105,8 @@ pub struct DiscoveryConfig { discovery_only_if_under_num: u64, enable_mdns: bool, kademlia_disjoint_query_paths: bool, - kademlia_protocol: Vec, - kademlia_legacy_protocol: Vec, + kademlia_protocol: Option, + kademlia_legacy_protocol: Option, kademlia_replication_factor: NonZeroUsize, } @@ -122,8 +122,8 @@ impl DiscoveryConfig { discovery_only_if_under_num: std::u64::MAX, enable_mdns: false, kademlia_disjoint_query_paths: false, - kademlia_protocol: Vec::new(), - kademlia_legacy_protocol: Vec::new(), + kademlia_protocol: None, + kademlia_legacy_protocol: None, kademlia_replication_factor: NonZeroUsize::new(DEFAULT_KADEMLIA_REPLICATION_FACTOR) .expect("value is a constant; constant is non-zero; qed."), } @@ -179,8 +179,8 @@ impl DiscoveryConfig { fork_id: Option<&str>, protocol_id: &ProtocolId, ) -> &mut Self { - self.kademlia_protocol = kademlia_protocol_name(genesis_hash, fork_id); - self.kademlia_legacy_protocol = legacy_kademlia_protocol_name(protocol_id); + self.kademlia_protocol = Some(kademlia_protocol_name(genesis_hash, fork_id)); + self.kademlia_legacy_protocol = Some(legacy_kademlia_protocol_name(protocol_id)); self } @@ -213,26 +213,31 @@ impl DiscoveryConfig { kademlia_replication_factor, } = self; - let kademlia = if !kademlia_protocol.is_empty() { + let kademlia = if let Some(ref kademlia_protocol) = kademlia_protocol { let mut config = KademliaConfig::default(); 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 - let kademlia_protocols = [kademlia_protocol.clone(), kademlia_legacy_protocol]; + let kademlia_protocols = if let Some(legacy_protocol) = kademlia_legacy_protocol { + vec![kademlia_protocol.clone(), legacy_protocol] + } else { + vec![kademlia_protocol.clone()] + }; config.set_protocol_names(kademlia_protocols.into_iter().map(Into::into).collect()); - config.set_record_filtering(libp2p::kad::KademliaStoreInserts::FilterBoth); + config.set_record_filtering(libp2p::kad::StoreInserts::FilterBoth); // By default Kademlia attempts to insert all peers into its routing table once a // dialing attempt succeeds. In order to control which peer is added, disable the // auto-insertion and instead add peers manually. - config.set_kbucket_inserts(KademliaBucketInserts::Manual); + config.set_kbucket_inserts(BucketInserts::Manual); config.disjoint_query_paths(kademlia_disjoint_query_paths); let store = MemoryStore::new(local_peer_id); let mut kad = Kademlia::with_config(local_peer_id, store, config); + kad.set_mode(Some(kad::Mode::Server)); for (peer_id, addr) in &permanent_addresses { kad.add_address(peer_id, addr.clone()); @@ -323,7 +328,7 @@ pub struct DiscoveryBehaviour { /// /// Remove when all nodes are upgraded to genesis hash and fork ID-based Kademlia: /// . - kademlia_protocol: Vec, + kademlia_protocol: Option, } impl DiscoveryBehaviour { @@ -369,7 +374,7 @@ impl DiscoveryBehaviour { pub fn add_self_reported_address( &mut self, peer_id: &PeerId, - supported_protocols: &[impl AsRef<[u8]>], + supported_protocols: &[StreamProtocol], addr: Multiaddr, ) { if let Some(kademlia) = self.kademlia.as_mut() { @@ -386,10 +391,12 @@ impl DiscoveryBehaviour { // Extract the chain-based Kademlia protocol from `kademlia.protocol_name()` // when all nodes are upgraded to genesis hash and fork ID-based Kademlia: // https://github.com/paritytech/polkadot-sdk/issues/504. - if !supported_protocols - .iter() - .any(|p| p.as_ref() == self.kademlia_protocol.as_slice()) - { + if !supported_protocols.iter().any(|p| { + p == self + .kademlia_protocol + .as_ref() + .expect("kademlia protocol was checked above to be enabled; qed") + }) { trace!( target: "sub-libp2p", "Ignoring self-reported address {} from {} as remote node is not part of the \ @@ -503,7 +510,7 @@ impl DiscoveryBehaviour { #[derive(Debug)] pub enum DiscoveryOut { /// A connection to a peer has been established but the peer has not been - /// added to the routing table because [`KademliaBucketInserts::Manual`] is + /// added to the routing table because [`BucketInserts::Manual`] is /// configured. If the peer is to be included in the routing table, it must /// be explicitly added via /// [`DiscoveryBehaviour::add_self_reported_address`]. @@ -552,8 +559,9 @@ pub enum DiscoveryOut { } impl NetworkBehaviour for DiscoveryBehaviour { - type ConnectionHandler = ToggleConnectionHandler>; - type OutEvent = DiscoveryOut; + type ConnectionHandler = + ToggleConnectionHandler< as NetworkBehaviour>::ConnectionHandler>; + type ToSwarm = DiscoveryOut; fn handle_established_inbound_connection( &mut self, @@ -689,11 +697,11 @@ impl NetworkBehaviour for DiscoveryBehaviour { FromSwarm::ListenerError(e) => { self.kademlia.on_swarm_event(FromSwarm::ListenerError(e)); }, - FromSwarm::ExpiredExternalAddr(e) => { + FromSwarm::ExternalAddrExpired(e) => { // We intentionally don't remove the element from `known_external_addresses` in // order to not print the log line again. - self.kademlia.on_swarm_event(FromSwarm::ExpiredExternalAddr(e)); + self.kademlia.on_swarm_event(FromSwarm::ExternalAddrExpired(e)); }, FromSwarm::NewListener(e) => { self.kademlia.on_swarm_event(FromSwarm::NewListener(e)); @@ -701,8 +709,18 @@ impl NetworkBehaviour for DiscoveryBehaviour { FromSwarm::ExpiredListenAddr(e) => { self.kademlia.on_swarm_event(FromSwarm::ExpiredListenAddr(e)); }, - FromSwarm::NewExternalAddr(e @ NewExternalAddr { addr }) => { - let new_addr = addr.clone().with(Protocol::P2p(self.local_peer_id.into())); + FromSwarm::NewExternalAddrCandidate(e) => { + self.kademlia.on_swarm_event(FromSwarm::NewExternalAddrCandidate(e)); + }, + FromSwarm::AddressChange(e) => { + self.kademlia.on_swarm_event(FromSwarm::AddressChange(e)); + }, + FromSwarm::NewListenAddr(e) => { + self.kademlia.on_swarm_event(FromSwarm::NewListenAddr(e)); + self.mdns.on_swarm_event(FromSwarm::NewListenAddr(e)); + }, + FromSwarm::ExternalAddrConfirmed(e @ ExternalAddrConfirmed { addr }) => { + let new_addr = addr.clone().with(Protocol::P2p(self.local_peer_id)); if Self::can_add_to_dht(addr) { // NOTE: we might re-discover the same address multiple times @@ -716,14 +734,7 @@ impl NetworkBehaviour for DiscoveryBehaviour { } } - self.kademlia.on_swarm_event(FromSwarm::NewExternalAddr(e)); - }, - FromSwarm::AddressChange(e) => { - self.kademlia.on_swarm_event(FromSwarm::AddressChange(e)); - }, - FromSwarm::NewListenAddr(e) => { - self.kademlia.on_swarm_event(FromSwarm::NewListenAddr(e)); - self.mdns.on_swarm_event(FromSwarm::NewListenAddr(e)); + self.kademlia.on_swarm_event(FromSwarm::ExternalAddrConfirmed(e)); }, } } @@ -741,7 +752,7 @@ impl NetworkBehaviour for DiscoveryBehaviour { &mut self, cx: &mut Context, params: &mut impl PollParameters, - ) -> Poll>> { + ) -> Poll>> { // Immediately process the content of `discovered`. if let Some(ev) = self.pending_events.pop_front() { return Poll::Ready(ToSwarm::GenerateEvent(ev)) @@ -963,10 +974,17 @@ impl NetworkBehaviour for DiscoveryBehaviour { 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::ReportObservedAddr { address, score } => - return Poll::Ready(ToSwarm::ReportObservedAddr { address, score }), 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 }), } } @@ -979,8 +997,9 @@ impl NetworkBehaviour for DiscoveryBehaviour { continue } - self.pending_events - .extend(list.map(|(peer_id, _)| DiscoveryOut::Discovered(peer_id))); + self.pending_events.extend( + list.into_iter().map(|(peer_id, _)| DiscoveryOut::Discovered(peer_id)), + ); if let Some(ev) = self.pending_events.pop_front() { return Poll::Ready(ToSwarm::GenerateEvent(ev)) } @@ -990,13 +1009,19 @@ impl NetworkBehaviour for DiscoveryBehaviour { ToSwarm::Dial { .. } => { unreachable!("mDNS never dials!"); }, - ToSwarm::NotifyHandler { event, .. } => match event {}, /* `event` is an */ - // enum with no - // variant - ToSwarm::ReportObservedAddr { address, score } => - return Poll::Ready(ToSwarm::ReportObservedAddr { address, score }), + // `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 }), } } @@ -1005,21 +1030,24 @@ impl NetworkBehaviour for DiscoveryBehaviour { } /// Legacy (fallback) Kademlia protocol name based on `protocol_id`. -fn legacy_kademlia_protocol_name(id: &ProtocolId) -> Vec { - let mut v = vec![b'/']; - v.extend_from_slice(id.as_ref().as_bytes()); - v.extend_from_slice(b"/kad"); - v +fn legacy_kademlia_protocol_name(id: &ProtocolId) -> StreamProtocol { + let name = format!("/{}/kad", id.as_ref()); + StreamProtocol::try_from_owned(name).expect("protocol name is valid. qed") } /// Kademlia protocol name based on `genesis_hash` and `fork_id`. -fn kademlia_protocol_name>(genesis_hash: Hash, fork_id: Option<&str>) -> Vec { +fn kademlia_protocol_name>( + genesis_hash: Hash, + fork_id: Option<&str>, +) -> StreamProtocol { let genesis_hash_hex = bytes2hex("", genesis_hash.as_ref()); - if let Some(fork_id) = fork_id { - format!("/{}/{}/kad", genesis_hash_hex, fork_id).as_bytes().into() + let name = if let Some(fork_id) = fork_id { + format!("/{genesis_hash_hex}/{fork_id}/kad") } else { - format!("/{}/kad", genesis_hash_hex).as_bytes().into() - } + format!("/{genesis_hash_hex}/kad") + }; + + StreamProtocol::try_from_owned(name).expect("protocol name is valid. qed") } #[cfg(test)] @@ -1036,7 +1064,7 @@ mod tests { }, identity::Keypair, noise, - swarm::{Executor, Swarm, SwarmBuilder, SwarmEvent}, + swarm::{Executor, Swarm, SwarmEvent}, yamux, Multiaddr, }; use sp_core::hash::H256; @@ -1082,7 +1110,8 @@ mod tests { }; let runtime = tokio::runtime::Runtime::new().unwrap(); - let mut swarm = SwarmBuilder::with_executor( + #[allow(deprecated)] + let mut swarm = libp2p::swarm::SwarmBuilder::with_executor( transport, behaviour, keypair.public().to_peer_id(), diff --git a/substrate/client/network/src/litep2p/service.rs b/substrate/client/network/src/litep2p/service.rs index 8f36b0828bd3..20bf6cd12d21 100644 --- a/substrate/client/network/src/litep2p/service.rs +++ b/substrate/client/network/src/litep2p/service.rs @@ -264,8 +264,20 @@ impl NetworkStatusProvider for Litep2pNetworkService { async fn network_state(&self) -> Result { Ok(NetworkState { peer_id: self.local_peer_id.to_base58(), - listened_addresses: self.listen_addresses.read().iter().cloned().collect(), - external_addresses: self.external_addresses.read().iter().cloned().collect(), + listened_addresses: self + .listen_addresses + .read() + .iter() + .cloned() + .map(|a| Multiaddr::from(a).into()) + .collect(), + external_addresses: self + .external_addresses + .read() + .iter() + .cloned() + .map(|a| Multiaddr::from(a).into()) + .collect(), connected_peers: HashMap::new(), not_connected_peers: HashMap::new(), // TODO: Check what info we can include here. diff --git a/substrate/client/network/src/peer_info.rs b/substrate/client/network/src/peer_info.rs index 2735bd873db9..21eeea6bcc0c 100644 --- a/substrate/client/network/src/peer_info.rs +++ b/substrate/client/network/src/peer_info.rs @@ -31,14 +31,15 @@ use libp2p::{ Info as IdentifyInfo, }, identity::PublicKey, - ping::{Behaviour as Ping, Config as PingConfig, Event as PingEvent, Success as PingSuccess}, + ping::{Behaviour as Ping, Config as PingConfig, Event as PingEvent}, swarm::{ behaviour::{ - AddressChange, ConnectionClosed, ConnectionEstablished, DialFailure, FromSwarm, - ListenFailure, + AddressChange, ConnectionClosed, ConnectionEstablished, DialFailure, + ExternalAddrConfirmed, FromSwarm, ListenFailure, }, - ConnectionDenied, ConnectionHandler, ConnectionId, IntoConnectionHandlerSelect, - NetworkBehaviour, PollParameters, THandler, THandlerInEvent, THandlerOutEvent, ToSwarm, + ConnectionDenied, ConnectionHandler, ConnectionHandlerSelect, ConnectionId, + NetworkBehaviour, NewExternalAddrCandidate, PollParameters, THandler, THandlerInEvent, + THandlerOutEvent, ToSwarm, }, Multiaddr, PeerId, }; @@ -47,7 +48,7 @@ use parking_lot::Mutex; use smallvec::SmallVec; use std::{ - collections::{hash_map::Entry, HashSet}, + collections::{hash_map::Entry, HashSet, VecDeque}, pin::Pin, sync::Arc, task::{Context, Poll}, @@ -71,6 +72,8 @@ pub struct PeerInfoBehaviour { garbage_collect: Pin + Send>>, /// Record keeping of external addresses. Data is queried by the `NetworkService`. external_addresses: ExternalAddresses, + /// Pending events to emit to [`Swarm`](libp2p::swarm::Swarm). + pending_actions: VecDeque>>, } /// Information about a node we're connected to. @@ -134,6 +137,7 @@ impl PeerInfoBehaviour { nodes_info: FnvHashMap::default(), garbage_collect: Box::pin(interval(GARBAGE_COLLECT_INTERVAL)), external_addresses: ExternalAddresses { addresses: external_addresses }, + pending_actions: Default::default(), } } @@ -148,13 +152,18 @@ impl PeerInfoBehaviour { /// Inserts a ping time in the cache. Has no effect if we don't have any entry for that node, /// which shouldn't happen. - fn handle_ping_report(&mut self, peer_id: &PeerId, ping_time: Duration) { - trace!(target: "sub-libp2p", "Ping time with {:?}: {:?}", peer_id, ping_time); + fn handle_ping_report( + &mut self, + peer_id: &PeerId, + ping_time: Duration, + connection: ConnectionId, + ) { + trace!(target: "sub-libp2p", "Ping time with {:?} via {:?}: {:?}", peer_id, connection, ping_time); if let Some(entry) = self.nodes_info.get_mut(peer_id) { entry.latest_ping = Some(ping_time); } else { error!(target: "sub-libp2p", - "Received ping from node we're not connected to {:?}", peer_id); + "Received ping from node we're not connected to {:?} via {:?}", peer_id, connection); } } @@ -208,11 +217,11 @@ pub enum PeerInfoEvent { } impl NetworkBehaviour for PeerInfoBehaviour { - type ConnectionHandler = IntoConnectionHandlerSelect< + type ConnectionHandler = ConnectionHandlerSelect< ::ConnectionHandler, ::ConnectionHandler, >; - type OutEvent = PeerInfoEvent; + type ToSwarm = PeerInfoEvent; fn handle_pending_inbound_connection( &mut self, @@ -378,9 +387,9 @@ impl NetworkBehaviour for PeerInfoBehaviour { self.ping.on_swarm_event(FromSwarm::ListenerError(e)); self.identify.on_swarm_event(FromSwarm::ListenerError(e)); }, - FromSwarm::ExpiredExternalAddr(e) => { - self.ping.on_swarm_event(FromSwarm::ExpiredExternalAddr(e)); - self.identify.on_swarm_event(FromSwarm::ExpiredExternalAddr(e)); + FromSwarm::ExternalAddrExpired(e) => { + self.ping.on_swarm_event(FromSwarm::ExternalAddrExpired(e)); + self.identify.on_swarm_event(FromSwarm::ExternalAddrExpired(e)); }, FromSwarm::NewListener(e) => { self.ping.on_swarm_event(FromSwarm::NewListener(e)); @@ -391,10 +400,23 @@ impl NetworkBehaviour for PeerInfoBehaviour { self.identify.on_swarm_event(FromSwarm::ExpiredListenAddr(e)); self.external_addresses.remove(e.addr); }, - FromSwarm::NewExternalAddr(e) => { - self.ping.on_swarm_event(FromSwarm::NewExternalAddr(e)); - self.identify.on_swarm_event(FromSwarm::NewExternalAddr(e)); - self.external_addresses.add(e.addr.clone()); + FromSwarm::NewExternalAddrCandidate(e @ NewExternalAddrCandidate { addr }) => { + self.ping.on_swarm_event(FromSwarm::NewExternalAddrCandidate(e)); + self.identify.on_swarm_event(FromSwarm::NewExternalAddrCandidate(e)); + + // Manually confirm all external address candidates. + // TODO: consider adding [AutoNAT protocol](https://docs.rs/libp2p/0.52.3/libp2p/autonat/index.html) + // (must go through the polkadot protocol spec) or implemeting heuristics for + // approving external address candidates. This can be done, for example, by + // approving only addresses reported by multiple peers. + // See also https://github.com/libp2p/rust-libp2p/pull/4721 introduced + // in libp2p v0.53 for heuristics approach. + self.pending_actions.push_back(ToSwarm::ExternalAddrConfirmed(addr.clone())); + }, + FromSwarm::ExternalAddrConfirmed(e @ ExternalAddrConfirmed { addr }) => { + self.ping.on_swarm_event(FromSwarm::ExternalAddrConfirmed(e)); + self.identify.on_swarm_event(FromSwarm::ExternalAddrConfirmed(e)); + self.external_addresses.add(addr.clone()); }, FromSwarm::AddressChange(e @ AddressChange { peer_id, old, new, .. }) => { self.ping.on_swarm_event(FromSwarm::AddressChange(e)); @@ -437,13 +459,17 @@ impl NetworkBehaviour for PeerInfoBehaviour { &mut self, cx: &mut Context, params: &mut impl PollParameters, - ) -> Poll>> { + ) -> Poll>> { + if let Some(event) = self.pending_actions.pop_front() { + return Poll::Ready(event) + } + loop { match self.ping.poll(cx, params) { Poll::Pending => break, Poll::Ready(ToSwarm::GenerateEvent(ev)) => { - if let PingEvent { peer, result: Ok(PingSuccess::Ping { rtt }) } = ev { - self.handle_ping_report(&peer, rtt) + if let PingEvent { peer, result: Ok(rtt), connection } = ev { + self.handle_ping_report(&peer, rtt, connection) } }, Poll::Ready(ToSwarm::Dial { opts }) => return Poll::Ready(ToSwarm::Dial { opts }), @@ -453,10 +479,18 @@ impl NetworkBehaviour for PeerInfoBehaviour { handler, event: Either::Left(event), }), - Poll::Ready(ToSwarm::ReportObservedAddr { address, score }) => - return Poll::Ready(ToSwarm::ReportObservedAddr { address, score }), Poll::Ready(ToSwarm::CloseConnection { peer_id, connection }) => return Poll::Ready(ToSwarm::CloseConnection { peer_id, connection }), + Poll::Ready(ToSwarm::NewExternalAddrCandidate(observed)) => + return Poll::Ready(ToSwarm::NewExternalAddrCandidate(observed)), + Poll::Ready(ToSwarm::ExternalAddrConfirmed(addr)) => + return Poll::Ready(ToSwarm::ExternalAddrConfirmed(addr)), + Poll::Ready(ToSwarm::ExternalAddrExpired(addr)) => + return Poll::Ready(ToSwarm::ExternalAddrExpired(addr)), + Poll::Ready(ToSwarm::ListenOn { opts }) => + return Poll::Ready(ToSwarm::ListenOn { opts }), + Poll::Ready(ToSwarm::RemoveListener { id }) => + return Poll::Ready(ToSwarm::RemoveListener { id }), } } @@ -482,10 +516,18 @@ impl NetworkBehaviour for PeerInfoBehaviour { handler, event: Either::Right(event), }), - Poll::Ready(ToSwarm::ReportObservedAddr { address, score }) => - return Poll::Ready(ToSwarm::ReportObservedAddr { address, score }), Poll::Ready(ToSwarm::CloseConnection { peer_id, connection }) => return Poll::Ready(ToSwarm::CloseConnection { peer_id, connection }), + Poll::Ready(ToSwarm::NewExternalAddrCandidate(observed)) => + return Poll::Ready(ToSwarm::NewExternalAddrCandidate(observed)), + Poll::Ready(ToSwarm::ExternalAddrConfirmed(addr)) => + return Poll::Ready(ToSwarm::ExternalAddrConfirmed(addr)), + Poll::Ready(ToSwarm::ExternalAddrExpired(addr)) => + return Poll::Ready(ToSwarm::ExternalAddrExpired(addr)), + Poll::Ready(ToSwarm::ListenOn { opts }) => + return Poll::Ready(ToSwarm::ListenOn { opts }), + Poll::Ready(ToSwarm::RemoveListener { id }) => + return Poll::Ready(ToSwarm::RemoveListener { id }), } } diff --git a/substrate/client/network/src/protocol.rs b/substrate/client/network/src/protocol.rs index 2e57ff1b6a86..977c4c4de663 100644 --- a/substrate/client/network/src/protocol.rs +++ b/substrate/client/network/src/protocol.rs @@ -163,9 +163,6 @@ impl Protocol { pub fn disconnect_peer(&mut self, peer_id: &PeerId, protocol_name: ProtocolName) { if let Some(position) = self.notification_protocols.iter().position(|p| *p == protocol_name) { - // Note: no need to remove a peer from `self.peers` if we are dealing with sync - // protocol, because it will be done when handling - // `NotificationsOut::CustomProtocolClosed`. self.behaviour.disconnect_peer(peer_id, SetId::from(position)); } else { warn!(target: "sub-libp2p", "disconnect_peer() with invalid protocol name") @@ -229,7 +226,7 @@ pub enum CustomMessageOutcome { impl NetworkBehaviour for Protocol { type ConnectionHandler = ::ConnectionHandler; - type OutEvent = CustomMessageOutcome; + type ToSwarm = CustomMessageOutcome; fn handle_established_inbound_connection( &mut self, @@ -290,17 +287,25 @@ impl NetworkBehaviour for Protocol { &mut self, cx: &mut std::task::Context, params: &mut impl PollParameters, - ) -> Poll>> { + ) -> Poll>> { let event = match self.behaviour.poll(cx, params) { Poll::Pending => return Poll::Pending, Poll::Ready(ToSwarm::GenerateEvent(ev)) => ev, Poll::Ready(ToSwarm::Dial { opts }) => return Poll::Ready(ToSwarm::Dial { opts }), Poll::Ready(ToSwarm::NotifyHandler { peer_id, handler, event }) => return Poll::Ready(ToSwarm::NotifyHandler { peer_id, handler, event }), - Poll::Ready(ToSwarm::ReportObservedAddr { address, score }) => - return Poll::Ready(ToSwarm::ReportObservedAddr { address, score }), Poll::Ready(ToSwarm::CloseConnection { peer_id, connection }) => return Poll::Ready(ToSwarm::CloseConnection { peer_id, connection }), + Poll::Ready(ToSwarm::NewExternalAddrCandidate(observed)) => + return Poll::Ready(ToSwarm::NewExternalAddrCandidate(observed)), + Poll::Ready(ToSwarm::ExternalAddrConfirmed(addr)) => + return Poll::Ready(ToSwarm::ExternalAddrConfirmed(addr)), + Poll::Ready(ToSwarm::ExternalAddrExpired(addr)) => + return Poll::Ready(ToSwarm::ExternalAddrExpired(addr)), + Poll::Ready(ToSwarm::ListenOn { opts }) => + return Poll::Ready(ToSwarm::ListenOn { opts }), + Poll::Ready(ToSwarm::RemoveListener { id }) => + return Poll::Ready(ToSwarm::RemoveListener { id }), }; let outcome = match event { diff --git a/substrate/client/network/src/protocol/notifications/behaviour.rs b/substrate/client/network/src/protocol/notifications/behaviour.rs index 03ba437a6672..cb4f089995e3 100644 --- a/substrate/client/network/src/protocol/notifications/behaviour.rs +++ b/substrate/client/network/src/protocol/notifications/behaviour.rs @@ -1198,7 +1198,7 @@ impl Notifications { impl NetworkBehaviour for Notifications { type ConnectionHandler = NotifsHandler; - type OutEvent = NotificationsOut; + type ToSwarm = NotificationsOut; fn handle_pending_inbound_connection( &mut self, @@ -1678,10 +1678,11 @@ impl NetworkBehaviour for Notifications { FromSwarm::ListenerClosed(_) => {}, FromSwarm::ListenFailure(_) => {}, FromSwarm::ListenerError(_) => {}, - FromSwarm::ExpiredExternalAddr(_) => {}, + FromSwarm::ExternalAddrExpired(_) => {}, FromSwarm::NewListener(_) => {}, FromSwarm::ExpiredListenAddr(_) => {}, - FromSwarm::NewExternalAddr(_) => {}, + FromSwarm::NewExternalAddrCandidate(_) => {}, + FromSwarm::ExternalAddrConfirmed(_) => {}, FromSwarm::AddressChange(_) => {}, FromSwarm::NewListenAddr(_) => {}, } @@ -2239,7 +2240,7 @@ impl NetworkBehaviour for Notifications { &mut self, cx: &mut Context, _params: &mut impl PollParameters, - ) -> Poll>> { + ) -> Poll>> { if let Some(event) = self.events.pop_front() { return Poll::Ready(event) } @@ -2382,7 +2383,6 @@ mod tests { protocol::notifications::handler::tests::*, protocol_controller::{IncomingIndex, ProtoSetConfig, ProtocolController}, }; - use libp2p::swarm::AddressRecord; use sc_utils::mpsc::tracing_unbounded; use std::{collections::HashSet, iter}; @@ -2402,31 +2402,14 @@ mod tests { } #[derive(Clone)] - struct MockPollParams { - peer_id: PeerId, - addr: Multiaddr, - } + struct MockPollParams {} impl PollParameters for MockPollParams { type SupportedProtocolsIter = std::vec::IntoIter>; - type ListenedAddressesIter = std::vec::IntoIter; - type ExternalAddressesIter = std::vec::IntoIter; fn supported_protocols(&self) -> Self::SupportedProtocolsIter { vec![].into_iter() } - - fn listened_addresses(&self) -> Self::ListenedAddressesIter { - vec![self.addr.clone()].into_iter() - } - - fn external_addresses(&self) -> Self::ExternalAddressesIter { - vec![].into_iter() - } - - fn local_peer_id(&self) -> &PeerId { - &self.peer_id - } } fn development_notifs( @@ -3331,7 +3314,7 @@ mod tests { notif.on_swarm_event(FromSwarm::DialFailure(libp2p::swarm::behaviour::DialFailure { peer_id: Some(peer), - error: &libp2p::swarm::DialError::Banned, + error: &libp2p::swarm::DialError::Aborted, connection_id: ConnectionId::new_unchecked(1337), })); @@ -3877,7 +3860,7 @@ mod tests { let now = Instant::now(); notif.on_swarm_event(FromSwarm::DialFailure(libp2p::swarm::behaviour::DialFailure { peer_id: Some(peer), - error: &libp2p::swarm::DialError::Banned, + error: &libp2p::swarm::DialError::Aborted, connection_id: ConnectionId::new_unchecked(0), })); @@ -4003,7 +3986,7 @@ mod tests { assert!(notif.peers.get(&(peer, set_id)).is_some()); if tokio::time::timeout(Duration::from_secs(5), async { - let mut params = MockPollParams { peer_id: PeerId::random(), addr: Multiaddr::empty() }; + let mut params = MockPollParams {}; loop { futures::future::poll_fn(|cx| { @@ -4115,7 +4098,7 @@ mod tests { // verify that the code continues to keep the peer disabled by resetting the timer // after the first one expired. if tokio::time::timeout(Duration::from_secs(5), async { - let mut params = MockPollParams { peer_id: PeerId::random(), addr: Multiaddr::empty() }; + let mut params = MockPollParams {}; loop { futures::future::poll_fn(|cx| { diff --git a/substrate/client/network/src/protocol/notifications/handler.rs b/substrate/client/network/src/protocol/notifications/handler.rs index cb09583b73a2..967ef614c556 100644 --- a/substrate/client/network/src/protocol/notifications/handler.rs +++ b/substrate/client/network/src/protocol/notifications/handler.rs @@ -75,8 +75,8 @@ use futures::{ use libp2p::{ core::ConnectedPoint, swarm::{ - handler::ConnectionEvent, ConnectionHandler, ConnectionHandlerEvent, KeepAlive, - NegotiatedSubstream, SubstreamProtocol, + handler::ConnectionEvent, ConnectionHandler, ConnectionHandlerEvent, KeepAlive, Stream, + SubstreamProtocol, }, PeerId, }; @@ -199,7 +199,7 @@ enum State { /// emitted. OpenDesiredByRemote { /// Substream opened by the remote and that hasn't been accepted/rejected yet. - in_substream: NotificationsInSubstream, + in_substream: NotificationsInSubstream, /// See [`State::Closed::pending_opening`]. pending_opening: bool, @@ -212,7 +212,7 @@ enum State { /// be emitted when transitioning to respectively [`State::Open`] or [`State::Closed`]. Opening { /// Substream opened by the remote. If `Some`, has been accepted. - in_substream: Option>, + in_substream: Option>, /// Is the connection inbound. inbound: bool, }, @@ -236,14 +236,14 @@ enum State { /// Always `Some` on transition to [`State::Open`]. Switched to `None` only if the remote /// closed the substream. If `None`, a [`NotifsHandlerOut::CloseDesired`] event has been /// emitted. - out_substream: Option>, + out_substream: Option>, /// Substream opened by the remote. /// /// Contrary to the `out_substream` field, operations continue as normal even if the /// substream has been closed by the remote. A `None` is treated the same way as if there /// was an idle substream. - in_substream: Option>, + in_substream: Option>, }, } @@ -481,8 +481,8 @@ pub enum NotifsHandlerError { } impl ConnectionHandler for NotifsHandler { - type InEvent = NotifsHandlerIn; - type OutEvent = NotifsHandlerOut; + type FromBehaviour = NotifsHandlerIn; + type ToBehaviour = NotifsHandlerOut; type Error = NotifsHandlerError; type InboundProtocol = UpgradeCollec; type OutboundProtocol = NotificationsOut; @@ -517,7 +517,7 @@ impl ConnectionHandler for NotifsHandler { match protocol_info.state { State::Closed { pending_opening } => { - self.events_queue.push_back(ConnectionHandlerEvent::Custom( + self.events_queue.push_back(ConnectionHandlerEvent::NotifyBehaviour( NotifsHandlerOut::OpenDesiredByRemote { protocol_index, handshake: in_substream_open.handshake, @@ -586,7 +586,7 @@ impl ConnectionHandler for NotifsHandler { in_substream: in_substream.take(), }; - self.events_queue.push_back(ConnectionHandlerEvent::Custom( + self.events_queue.push_back(ConnectionHandlerEvent::NotifyBehaviour( NotifsHandlerOut::OpenResultOk { protocol_index, negotiated_fallback: new_open.negotiated_fallback, @@ -600,6 +600,8 @@ impl ConnectionHandler for NotifsHandler { } }, ConnectionEvent::AddressChange(_address_change) => {}, + ConnectionEvent::LocalProtocolsChange(_) => {}, + ConnectionEvent::RemoteProtocolsChange(_) => {}, ConnectionEvent::DialUpgradeError(dial_upgrade_error) => match self.protocols [dial_upgrade_error.info] .state @@ -614,7 +616,7 @@ impl ConnectionHandler for NotifsHandler { self.protocols[dial_upgrade_error.info].state = State::Closed { pending_opening: false }; - self.events_queue.push_back(ConnectionHandlerEvent::Custom( + self.events_queue.push_back(ConnectionHandlerEvent::NotifyBehaviour( NotifsHandlerOut::OpenResultErr { protocol_index: dial_upgrade_error.info }, )); }, @@ -701,7 +703,7 @@ impl ConnectionHandler for NotifsHandler { self.protocols[protocol_index].state = State::Closed { pending_opening: true }; - self.events_queue.push_back(ConnectionHandlerEvent::Custom( + self.events_queue.push_back(ConnectionHandlerEvent::NotifyBehaviour( NotifsHandlerOut::OpenResultErr { protocol_index }, )); }, @@ -711,7 +713,7 @@ impl ConnectionHandler for NotifsHandler { State::Closed { .. } => {}, } - self.events_queue.push_back(ConnectionHandlerEvent::Custom( + self.events_queue.push_back(ConnectionHandlerEvent::NotifyBehaviour( NotifsHandlerOut::CloseResult { protocol_index }, )); }, @@ -726,9 +728,11 @@ impl ConnectionHandler for NotifsHandler { // A grace period of `INITIAL_KEEPALIVE_TIME` must be given to leave time for the remote // to express desire to open substreams. + #[allow(deprecated)] KeepAlive::Until(self.when_connection_open + INITIAL_KEEPALIVE_TIME) } + #[allow(deprecated)] fn poll( &mut self, cx: &mut Context, @@ -736,7 +740,7 @@ impl ConnectionHandler for NotifsHandler { ConnectionHandlerEvent< Self::OutboundProtocol, Self::OutboundOpenInfo, - Self::OutEvent, + Self::ToBehaviour, Self::Error, >, > { @@ -755,6 +759,7 @@ impl ConnectionHandler for NotifsHandler { // Only proceed with `out_substream.poll_ready_unpin` if there is an element // available in `notifications_sink_rx`. This avoids waking up the task when // a substream is ready to send if there isn't actually something to send. + #[allow(deprecated)] match Pin::new(&mut *notifications_sink_rx).as_mut().poll_peek(cx) { Poll::Ready(Some(&NotificationsSinkMessage::ForceClose)) => return Poll::Ready(ConnectionHandlerEvent::Close( @@ -808,7 +813,7 @@ impl ConnectionHandler for NotifsHandler { Poll::Ready(Err(_)) => { *out_substream = None; let event = NotifsHandlerOut::CloseDesired { protocol_index }; - return Poll::Ready(ConnectionHandlerEvent::Custom(event)) + return Poll::Ready(ConnectionHandlerEvent::NotifyBehaviour(event)) }, }; }, @@ -830,11 +835,14 @@ impl ConnectionHandler for NotifsHandler { State::Opening { in_substream: None, .. } => {}, State::Open { in_substream: in_substream @ Some(_), .. } => - match Stream::poll_next(Pin::new(in_substream.as_mut().unwrap()), cx) { + match futures::prelude::stream::Stream::poll_next( + Pin::new(in_substream.as_mut().unwrap()), + cx, + ) { Poll::Pending => {}, Poll::Ready(Some(Ok(message))) => { let event = NotifsHandlerOut::Notification { protocol_index, message }; - return Poll::Ready(ConnectionHandlerEvent::Custom(event)) + return Poll::Ready(ConnectionHandlerEvent::NotifyBehaviour(event)) }, Poll::Ready(None) | Poll::Ready(Some(Err(_))) => *in_substream = None, }, @@ -846,7 +854,7 @@ impl ConnectionHandler for NotifsHandler { Poll::Ready(Err(_)) => { self.protocols[protocol_index].state = State::Closed { pending_opening: *pending_opening }; - return Poll::Ready(ConnectionHandlerEvent::Custom( + return Poll::Ready(ConnectionHandlerEvent::NotifyBehaviour( NotifsHandlerOut::CloseDesired { protocol_index }, )) }, @@ -880,8 +888,8 @@ pub mod tests { use asynchronous_codec::Framed; use libp2p::{ core::muxing::SubstreamBox, - swarm::{handler, ConnectionHandlerUpgrErr}, - Multiaddr, + swarm::handler::{self, StreamUpgradeError}, + Multiaddr, Stream, }; use multistream_select::{dialer_select_proto, listener_select_proto, Negotiated, Version}; use std::{ @@ -972,6 +980,7 @@ pub mod tests { .await } } + struct MockSubstream { pub rx: mpsc::Receiver>, pub tx: mpsc::Sender>, @@ -991,18 +1000,35 @@ pub mod tests { } /// Create new negotiated substream pair. - pub async fn negotiated() -> (Negotiated, Negotiated) { + pub async fn negotiated() -> (Stream, Stream) { let (socket1, socket2) = Self::new(); let socket1 = SubstreamBox::new(socket1); let socket2 = SubstreamBox::new(socket2); - let protos = vec![b"/echo/1.0.0", b"/echo/2.5.0"]; + let protos = vec!["/echo/1.0.0", "/echo/2.5.0"]; let (res1, res2) = tokio::join!( dialer_select_proto(socket1, protos.clone(), Version::V1), listener_select_proto(socket2, protos), ); - (res1.unwrap().1, res2.unwrap().1) + (Self::stream_new(res1.unwrap().1), Self::stream_new(res2.unwrap().1)) + } + + /// Unsafe substitute for `Stream::new` private constructor. + fn stream_new(stream: Negotiated) -> Stream { + // Static asserts to make sure this doesn't break. + const _: () = { + assert!( + core::mem::size_of::() == + core::mem::size_of::>() + ); + assert!( + core::mem::align_of::() == + core::mem::align_of::>() + ); + }; + + unsafe { core::mem::transmute(stream) } } } @@ -1504,7 +1530,7 @@ pub mod tests { // inject dial failure to an already closed substream and verify outbound state is reset handler.on_connection_event(handler::ConnectionEvent::DialUpgradeError( - handler::DialUpgradeError { info: 0, error: ConnectionHandlerUpgrErr::Timeout }, + handler::DialUpgradeError { info: 0, error: StreamUpgradeError::Timeout }, )); assert!(std::matches!( handler.protocols[0].state, @@ -1574,7 +1600,7 @@ pub mod tests { // inject dial failure to an already closed substream and verify outbound state is reset handler.on_connection_event(handler::ConnectionEvent::DialUpgradeError( - handler::DialUpgradeError { info: 0, error: ConnectionHandlerUpgrErr::Timeout }, + handler::DialUpgradeError { info: 0, error: StreamUpgradeError::Timeout }, )); assert!(std::matches!( handler.protocols[0].state, @@ -1610,6 +1636,7 @@ pub mod tests { notifications_sink.send_sync_notification(vec![1, 3, 3, 9]); notifications_sink.send_sync_notification(vec![1, 3, 4, 0]); + #[allow(deprecated)] futures::future::poll_fn(|cx| { assert!(std::matches!( handler.poll(cx), @@ -1648,15 +1675,15 @@ pub mod tests { futures::future::poll_fn(|cx| { assert!(std::matches!( handler.poll(cx), - Poll::Ready(ConnectionHandlerEvent::Custom( + Poll::Ready(ConnectionHandlerEvent::NotifyBehaviour( NotifsHandlerOut::OpenDesiredByRemote { protocol_index: 0, .. }, )) )); assert!(std::matches!( handler.poll(cx), - Poll::Ready(ConnectionHandlerEvent::Custom(NotifsHandlerOut::CloseDesired { - protocol_index: 0 - },)) + Poll::Ready(ConnectionHandlerEvent::NotifyBehaviour( + NotifsHandlerOut::CloseDesired { protocol_index: 0 }, + )) )); Poll::Ready(()) }) diff --git a/substrate/client/network/src/protocol/notifications/tests.rs b/substrate/client/network/src/protocol/notifications/tests.rs index a72b5b4a6748..90c9cc5b7cde 100644 --- a/substrate/client/network/src/protocol/notifications/tests.rs +++ b/substrate/client/network/src/protocol/notifications/tests.rs @@ -33,9 +33,8 @@ use libp2p::{ core::{transport::MemoryTransport, upgrade, Endpoint}, identity, noise, swarm::{ - behaviour::FromSwarm, ConnectionDenied, ConnectionId, Executor, NetworkBehaviour, - PollParameters, Swarm, SwarmBuilder, SwarmEvent, THandler, THandlerInEvent, - THandlerOutEvent, ToSwarm, + self, behaviour::FromSwarm, ConnectionDenied, ConnectionId, Executor, NetworkBehaviour, + PollParameters, Swarm, SwarmEvent, THandler, THandlerInEvent, THandlerOutEvent, ToSwarm, }, yamux, Multiaddr, PeerId, Transport, }; @@ -141,13 +140,12 @@ fn build_nodes() -> (Swarm, Swarm) { } }); - let mut swarm = SwarmBuilder::with_executor( + let mut swarm = Swarm::new( transport, behaviour, keypairs[index].public().to_peer_id(), - TokioExecutor(runtime), - ) - .build(); + swarm::Config::with_executor(TokioExecutor(runtime)), + ); swarm.listen_on(addrs[index].clone()).unwrap(); out.push(swarm); } @@ -183,7 +181,7 @@ impl std::ops::DerefMut for CustomProtoWithAddr { impl NetworkBehaviour for CustomProtoWithAddr { type ConnectionHandler = ::ConnectionHandler; - type OutEvent = ::OutEvent; + type ToSwarm = ::ToSwarm; fn handle_pending_inbound_connection( &mut self, @@ -261,7 +259,7 @@ impl NetworkBehaviour for CustomProtoWithAddr { &mut self, cx: &mut Context, params: &mut impl PollParameters, - ) -> Poll>> { + ) -> Poll>> { let _ = self.peer_store_future.poll_unpin(cx); let _ = self.protocol_controller_future.poll_unpin(cx); self.inner.poll(cx, params) diff --git a/substrate/client/network/src/protocol/notifications/upgrade.rs b/substrate/client/network/src/protocol/notifications/upgrade.rs index 8fd837f949d8..72e0c2d10396 100644 --- a/substrate/client/network/src/protocol/notifications/upgrade.rs +++ b/substrate/client/network/src/protocol/notifications/upgrade.rs @@ -20,6 +20,7 @@ pub(crate) use self::notifications::{ NotificationsInOpen, NotificationsInSubstreamHandshake, NotificationsOutOpen, }; + pub use self::{ collec::UpgradeCollec, notifications::{ diff --git a/substrate/client/network/src/protocol/notifications/upgrade/collec.rs b/substrate/client/network/src/protocol/notifications/upgrade/collec.rs index 33c090ae50e9..ab0f87215cca 100644 --- a/substrate/client/network/src/protocol/notifications/upgrade/collec.rs +++ b/substrate/client/network/src/protocol/notifications/upgrade/collec.rs @@ -17,7 +17,7 @@ // along with this program. If not, see . use futures::prelude::*; -use libp2p::core::upgrade::{InboundUpgrade, ProtocolName, UpgradeInfo}; +use libp2p::core::upgrade::{InboundUpgrade, UpgradeInfo}; use std::{ pin::Pin, task::{Context, Poll}, @@ -75,9 +75,9 @@ where #[derive(Debug, Clone, PartialEq)] pub struct ProtoNameWithUsize(T, usize); -impl ProtocolName for ProtoNameWithUsize { - fn protocol_name(&self) -> &[u8] { - self.0.protocol_name() +impl> AsRef for ProtoNameWithUsize { + fn as_ref(&self) -> &str { + self.0.as_ref() } } @@ -103,13 +103,13 @@ impl>, O, E> Future for FutWithUsize { mod tests { use super::*; use crate::types::ProtocolName as ProtoName; - use libp2p::core::upgrade::{ProtocolName, UpgradeInfo}; + use libp2p::core::upgrade::UpgradeInfo; // TODO: move to mocks mockall::mock! { pub ProtocolUpgrade {} - impl UpgradeInfo for ProtocolUpgrade { + impl> UpgradeInfo for ProtocolUpgrade { type Info = T; type InfoIter = vec::IntoIter; fn protocol_info(&self) -> vec::IntoIter; diff --git a/substrate/client/network/src/protocol/notifications/upgrade/notifications.rs b/substrate/client/network/src/protocol/notifications/upgrade/notifications.rs index c760b7a963fc..a8a9e453a7bb 100644 --- a/substrate/client/network/src/protocol/notifications/upgrade/notifications.rs +++ b/substrate/client/network/src/protocol/notifications/upgrade/notifications.rs @@ -513,45 +513,99 @@ pub enum NotificationsOutError { #[cfg(test)] mod tests { + use crate::ProtocolName; + use super::{ - NotificationsIn, NotificationsInOpen, NotificationsOut, NotificationsOutError, - NotificationsOutOpen, + NotificationsHandshakeError, NotificationsIn, NotificationsInOpen, + NotificationsInSubstream, NotificationsOut, NotificationsOutError, NotificationsOutOpen, + NotificationsOutSubstream, }; - use futures::{channel::oneshot, future, prelude::*}; - use libp2p::core::upgrade; + use futures::{channel::oneshot, future, prelude::*, SinkExt, StreamExt}; + use libp2p::core::{upgrade, InboundUpgrade, OutboundUpgrade, UpgradeInfo}; use std::{pin::Pin, task::Poll}; use tokio::net::{TcpListener, TcpStream}; use tokio_util::compat::TokioAsyncReadCompatExt; + /// Opens a substream to the given address, negotiates the protocol, and returns the substream + /// along with the handshake message. + async fn dial( + addr: std::net::SocketAddr, + handshake: impl Into>, + ) -> Result< + ( + Vec, + NotificationsOutSubstream< + multistream_select::Negotiated>, + >, + ), + NotificationsHandshakeError, + > { + let socket = TcpStream::connect(addr).await.unwrap(); + let notifs_out = NotificationsOut::new("/test/proto/1", Vec::new(), handshake, 1024 * 1024); + let (_, substream) = multistream_select::dialer_select_proto( + socket.compat(), + notifs_out.protocol_info(), + upgrade::Version::V1, + ) + .await + .unwrap(); + let NotificationsOutOpen { handshake, substream, .. } = + >::upgrade_outbound( + notifs_out, + substream, + "/test/proto/1".into(), + ) + .await?; + Ok((handshake, substream)) + } + + /// Listens on a localhost, negotiates the protocol, and returns the substream along with the + /// handshake message. + /// + /// Also sends the listener address through the given channel. + async fn listen_on_localhost( + listener_addr_tx: oneshot::Sender, + ) -> Result< + ( + Vec, + NotificationsInSubstream< + multistream_select::Negotiated>, + >, + ), + NotificationsHandshakeError, + > { + let listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); + listener_addr_tx.send(listener.local_addr().unwrap()).unwrap(); + + let (socket, _) = listener.accept().await.unwrap(); + let notifs_in = NotificationsIn::new("/test/proto/1", Vec::new(), 1024 * 1024); + let (_, substream) = + multistream_select::listener_select_proto(socket.compat(), notifs_in.protocol_info()) + .await + .unwrap(); + let NotificationsInOpen { handshake, substream, .. } = + >::upgrade_inbound( + notifs_in, + substream, + "/test/proto/1".into(), + ) + .await?; + Ok((handshake, substream)) + } + #[tokio::test] async fn basic_works() { - const PROTO_NAME: &str = "/test/proto/1"; let (listener_addr_tx, listener_addr_rx) = oneshot::channel(); let client = tokio::spawn(async move { - let socket = TcpStream::connect(listener_addr_rx.await.unwrap()).await.unwrap(); - let NotificationsOutOpen { handshake, mut substream, .. } = upgrade::apply_outbound( - socket.compat(), - NotificationsOut::new(PROTO_NAME, Vec::new(), &b"initial message"[..], 1024 * 1024), - upgrade::Version::V1, - ) - .await - .unwrap(); + let (handshake, mut substream) = + dial(listener_addr_rx.await.unwrap(), &b"initial message"[..]).await.unwrap(); assert_eq!(handshake, b"hello world"); substream.send(b"test message".to_vec()).await.unwrap(); }); - let listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); - listener_addr_tx.send(listener.local_addr().unwrap()).unwrap(); - - let (socket, _) = listener.accept().await.unwrap(); - let NotificationsInOpen { handshake, mut substream, .. } = upgrade::apply_inbound( - socket.compat(), - NotificationsIn::new(PROTO_NAME, Vec::new(), 1024 * 1024), - ) - .await - .unwrap(); + let (handshake, mut substream) = listen_on_localhost(listener_addr_tx).await.unwrap(); assert_eq!(handshake, b"initial message"); substream.send_handshake(&b"hello world"[..]); @@ -566,33 +620,17 @@ mod tests { async fn empty_handshake() { // Check that everything still works when the handshake messages are empty. - const PROTO_NAME: &str = "/test/proto/1"; let (listener_addr_tx, listener_addr_rx) = oneshot::channel(); let client = tokio::spawn(async move { - let socket = TcpStream::connect(listener_addr_rx.await.unwrap()).await.unwrap(); - let NotificationsOutOpen { handshake, mut substream, .. } = upgrade::apply_outbound( - socket.compat(), - NotificationsOut::new(PROTO_NAME, Vec::new(), vec![], 1024 * 1024), - upgrade::Version::V1, - ) - .await - .unwrap(); + let (handshake, mut substream) = + dial(listener_addr_rx.await.unwrap(), vec![]).await.unwrap(); assert!(handshake.is_empty()); substream.send(Default::default()).await.unwrap(); }); - let listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); - listener_addr_tx.send(listener.local_addr().unwrap()).unwrap(); - - let (socket, _) = listener.accept().await.unwrap(); - let NotificationsInOpen { handshake, mut substream, .. } = upgrade::apply_inbound( - socket.compat(), - NotificationsIn::new(PROTO_NAME, Vec::new(), 1024 * 1024), - ) - .await - .unwrap(); + let (handshake, mut substream) = listen_on_localhost(listener_addr_tx).await.unwrap(); assert!(handshake.is_empty()); substream.send_handshake(vec![]); @@ -605,17 +643,10 @@ mod tests { #[tokio::test] async fn refused() { - const PROTO_NAME: &str = "/test/proto/1"; let (listener_addr_tx, listener_addr_rx) = oneshot::channel(); let client = tokio::spawn(async move { - let socket = TcpStream::connect(listener_addr_rx.await.unwrap()).await.unwrap(); - let outcome = upgrade::apply_outbound( - socket.compat(), - NotificationsOut::new(PROTO_NAME, Vec::new(), &b"hello"[..], 1024 * 1024), - upgrade::Version::V1, - ) - .await; + let outcome = dial(listener_addr_rx.await.unwrap(), &b"hello"[..]).await; // Despite the protocol negotiation being successfully conducted on the listener // side, we have to receive an error here because the listener didn't send the @@ -623,17 +654,7 @@ mod tests { assert!(outcome.is_err()); }); - let listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); - listener_addr_tx.send(listener.local_addr().unwrap()).unwrap(); - - let (socket, _) = listener.accept().await.unwrap(); - let NotificationsInOpen { handshake, substream, .. } = upgrade::apply_inbound( - socket.compat(), - NotificationsIn::new(PROTO_NAME, Vec::new(), 1024 * 1024), - ) - .await - .unwrap(); - + let (handshake, substream) = listen_on_localhost(listener_addr_tx).await.unwrap(); assert_eq!(handshake, b"hello"); // We successfully upgrade to the protocol, but then close the substream. @@ -644,66 +665,29 @@ mod tests { #[tokio::test] async fn large_initial_message_refused() { - const PROTO_NAME: &str = "/test/proto/1"; let (listener_addr_tx, listener_addr_rx) = oneshot::channel(); let client = tokio::spawn(async move { - let socket = TcpStream::connect(listener_addr_rx.await.unwrap()).await.unwrap(); - let ret = upgrade::apply_outbound( - socket.compat(), - // We check that an initial message that is too large gets refused. - NotificationsOut::new( - PROTO_NAME, - Vec::new(), - (0..32768).map(|_| 0).collect::>(), - 1024 * 1024, - ), - upgrade::Version::V1, - ) - .await; + let ret = + dial(listener_addr_rx.await.unwrap(), (0..32768).map(|_| 0).collect::>()) + .await; assert!(ret.is_err()); }); - let listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); - listener_addr_tx.send(listener.local_addr().unwrap()).unwrap(); - - let (socket, _) = listener.accept().await.unwrap(); - let ret = upgrade::apply_inbound( - socket.compat(), - NotificationsIn::new(PROTO_NAME, Vec::new(), 1024 * 1024), - ) - .await; - assert!(ret.is_err()); - + let _ret = listen_on_localhost(listener_addr_tx).await; client.await.unwrap(); } #[tokio::test] async fn large_handshake_refused() { - const PROTO_NAME: &str = "/test/proto/1"; let (listener_addr_tx, listener_addr_rx) = oneshot::channel(); let client = tokio::spawn(async move { - let socket = TcpStream::connect(listener_addr_rx.await.unwrap()).await.unwrap(); - let ret = upgrade::apply_outbound( - socket.compat(), - NotificationsOut::new(PROTO_NAME, Vec::new(), &b"initial message"[..], 1024 * 1024), - upgrade::Version::V1, - ) - .await; + let ret = dial(listener_addr_rx.await.unwrap(), &b"initial message"[..]).await; assert!(ret.is_err()); }); - let listener = TcpListener::bind("127.0.0.1:0").await.unwrap(); - listener_addr_tx.send(listener.local_addr().unwrap()).unwrap(); - - let (socket, _) = listener.accept().await.unwrap(); - let NotificationsInOpen { handshake, mut substream, .. } = upgrade::apply_inbound( - socket.compat(), - NotificationsIn::new(PROTO_NAME, Vec::new(), 1024 * 1024), - ) - .await - .unwrap(); + let (handshake, mut substream) = listen_on_localhost(listener_addr_tx).await.unwrap(); assert_eq!(handshake, b"initial message"); // We check that a handshake that is too large gets refused. @@ -720,10 +704,10 @@ mod tests { let client = tokio::spawn(async move { let socket = TcpStream::connect(listener_addr_rx.await.unwrap()).await.unwrap(); - let NotificationsOutOpen { handshake, .. } = upgrade::apply_outbound( - socket.compat(), + let NotificationsOutOpen { handshake, .. } = OutboundUpgrade::upgrade_outbound( NotificationsOut::new(PROTO_NAME, Vec::new(), &b"initial message"[..], 1024 * 1024), - upgrade::Version::V1, + socket.compat(), + ProtocolName::Static(PROTO_NAME), ) .await .unwrap(); @@ -735,9 +719,10 @@ mod tests { listener_addr_tx.send(listener.local_addr().unwrap()).unwrap(); let (socket, _) = listener.accept().await.unwrap(); - let NotificationsInOpen { handshake, mut substream, .. } = upgrade::apply_inbound( - socket.compat(), + let NotificationsInOpen { handshake, mut substream, .. } = InboundUpgrade::upgrade_inbound( NotificationsIn::new(PROTO_NAME, Vec::new(), 1024 * 1024), + socket.compat(), + ProtocolName::Static(PROTO_NAME), ) .await .unwrap(); @@ -758,13 +743,19 @@ mod tests { let client = tokio::spawn(async move { let socket = TcpStream::connect(listener_addr_rx.await.unwrap()).await.unwrap(); - let NotificationsOutOpen { handshake, mut substream, .. } = upgrade::apply_outbound( - socket.compat(), - NotificationsOut::new(PROTO_NAME, Vec::new(), &b"initial message"[..], 1024 * 1024), - upgrade::Version::V1, - ) - .await - .unwrap(); + let NotificationsOutOpen { handshake, mut substream, .. } = + OutboundUpgrade::upgrade_outbound( + NotificationsOut::new( + PROTO_NAME, + Vec::new(), + &b"initial message"[..], + 1024 * 1024, + ), + socket.compat(), + ProtocolName::Static(PROTO_NAME), + ) + .await + .unwrap(); assert_eq!(handshake, b"hello world"); @@ -786,9 +777,10 @@ mod tests { listener_addr_tx.send(listener.local_addr().unwrap()).unwrap(); let (socket, _) = listener.accept().await.unwrap(); - let NotificationsInOpen { handshake, mut substream, .. } = upgrade::apply_inbound( - socket.compat(), + let NotificationsInOpen { handshake, mut substream, .. } = InboundUpgrade::upgrade_inbound( NotificationsIn::new(PROTO_NAME, Vec::new(), 1024 * 1024), + socket.compat(), + ProtocolName::Static(PROTO_NAME), ) .await .unwrap(); diff --git a/substrate/client/network/src/request_responses.rs b/substrate/client/network/src/request_responses.rs index fbf050a65713..3671d76ea630 100644 --- a/substrate/client/network/src/request_responses.rs +++ b/substrate/client/network/src/request_responses.rs @@ -318,7 +318,6 @@ impl RequestResponsesBehaviour { let mut protocols = HashMap::new(); for protocol in list { let mut cfg = Config::default(); - cfg.set_connection_keep_alive(Duration::from_secs(10)); cfg.set_request_timeout(protocol.request_timeout); let protocol_support = if protocol.inbound_queue.is_some() { @@ -327,13 +326,13 @@ impl RequestResponsesBehaviour { ProtocolSupport::Outbound }; - let rq_rp = Behaviour::new( + let rq_rp = Behaviour::with_codec( GenericCodec { max_request_size: protocol.max_request_size, max_response_size: protocol.max_response_size, }, - iter::once(protocol.name.as_bytes().to_vec()) - .chain(protocol.fallback_names.iter().map(|name| name.as_bytes().to_vec())) + iter::once(protocol.name.clone()) + .chain(protocol.fallback_names) .zip(iter::repeat(protocol_support)), cfg, ); @@ -427,7 +426,7 @@ impl RequestResponsesBehaviour { impl NetworkBehaviour for RequestResponsesBehaviour { type ConnectionHandler = MultiHandler as NetworkBehaviour>::ConnectionHandler>; - type OutEvent = Event; + type ToSwarm = Event; fn handle_pending_inbound_connection( &mut self, @@ -543,9 +542,9 @@ impl NetworkBehaviour for RequestResponsesBehaviour { for (p, _) in self.protocols.values_mut() { NetworkBehaviour::on_swarm_event(p, FromSwarm::ListenerError(e)); }, - FromSwarm::ExpiredExternalAddr(e) => + FromSwarm::ExternalAddrExpired(e) => for (p, _) in self.protocols.values_mut() { - NetworkBehaviour::on_swarm_event(p, FromSwarm::ExpiredExternalAddr(e)); + NetworkBehaviour::on_swarm_event(p, FromSwarm::ExternalAddrExpired(e)); }, FromSwarm::NewListener(e) => for (p, _) in self.protocols.values_mut() { @@ -555,9 +554,13 @@ impl NetworkBehaviour for RequestResponsesBehaviour { for (p, _) in self.protocols.values_mut() { NetworkBehaviour::on_swarm_event(p, FromSwarm::ExpiredListenAddr(e)); }, - FromSwarm::NewExternalAddr(e) => + FromSwarm::NewExternalAddrCandidate(e) => for (p, _) in self.protocols.values_mut() { - NetworkBehaviour::on_swarm_event(p, FromSwarm::NewExternalAddr(e)); + NetworkBehaviour::on_swarm_event(p, FromSwarm::NewExternalAddrCandidate(e)); + }, + FromSwarm::ExternalAddrConfirmed(e) => + for (p, _) in self.protocols.values_mut() { + NetworkBehaviour::on_swarm_event(p, FromSwarm::ExternalAddrConfirmed(e)); }, FromSwarm::AddressChange(e) => for (p, _) in self.protocols.values_mut() { @@ -592,7 +595,7 @@ impl NetworkBehaviour for RequestResponsesBehaviour { &mut self, cx: &mut Context, params: &mut impl PollParameters, - ) -> Poll>> { + ) -> Poll>> { 'poll_all: loop { // Poll to see if any response is ready to be sent back. while let Poll::Ready(Some(outcome)) = self.pending_responses.poll_next_unpin(cx) { @@ -663,10 +666,18 @@ impl NetworkBehaviour for RequestResponsesBehaviour { handler, event: ((*protocol).to_string(), event), }), - ToSwarm::ReportObservedAddr { address, score } => - return Poll::Ready(ToSwarm::ReportObservedAddr { address, score }), 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 }), }; match ev { @@ -950,7 +961,7 @@ pub struct GenericCodec { #[async_trait::async_trait] impl Codec for GenericCodec { - type Protocol = Vec; + type Protocol = ProtocolName; type Request = Vec; type Response = Result, ()>; @@ -1078,7 +1089,7 @@ mod tests { }, identity::Keypair, noise, - swarm::{Executor, Swarm, SwarmBuilder, SwarmEvent}, + swarm::{Config as SwarmConfig, Executor, Swarm, SwarmEvent}, Multiaddr, }; use std::{iter, time::Duration}; @@ -1104,16 +1115,18 @@ mod tests { let behaviour = RequestResponsesBehaviour::new(list, Arc::new(MockPeerStore {})).unwrap(); let runtime = tokio::runtime::Runtime::new().unwrap(); - let mut swarm = SwarmBuilder::with_executor( + + let mut swarm = Swarm::new( transport, behaviour, keypair.public().to_peer_id(), - TokioExecutor(runtime), - ) - .build(); + SwarmConfig::with_executor(TokioExecutor(runtime)), + ); + let listen_addr: Multiaddr = format!("/memory/{}", rand::random::()).parse().unwrap(); swarm.listen_on(listen_addr.clone()).unwrap(); + (swarm, listen_addr) } diff --git a/substrate/client/network/src/service.rs b/substrate/client/network/src/service.rs index 2cf4564e312c..3a685787c48e 100644 --- a/substrate/client/network/src/service.rs +++ b/substrate/client/network/src/service.rs @@ -61,18 +61,18 @@ use crate::{ use codec::DecodeAll; use either::Either; use futures::{channel::oneshot, prelude::*}; -use libp2p::identity::ed25519; #[allow(deprecated)] +use libp2p::swarm::THandlerErr; use libp2p::{ - connection_limits::Exceeded, + connection_limits::{ConnectionLimits, Exceeded}, core::{upgrade, ConnectedPoint, Endpoint}, identify::Info as IdentifyInfo, + identity::ed25519, kad::record::Key as KademliaKey, multiaddr::{self, Multiaddr}, - ping::Failure as PingFailure, swarm::{ - AddressScore, ConnectionError, ConnectionId, ConnectionLimits, DialError, Executor, - ListenError, NetworkBehaviour, Swarm, SwarmBuilder, SwarmEvent, THandlerErr, + Config as SwarmConfig, ConnectionError, ConnectionId, DialError, Executor, ListenError, + NetworkBehaviour, Swarm, SwarmEvent, }, PeerId, }; @@ -274,10 +274,6 @@ where let local_identity: ed25519::Keypair = local_identity.into(); let local_public: ed25519::PublicKey = local_public.into(); let local_peer_id: PeerId = local_peer_id.into(); - let listen_addresses: Vec = - network_config.listen_addresses.iter().cloned().map(Into::into).collect(); - let public_addresses: Vec = - network_config.public_addresses.iter().cloned().map(Into::into).collect(); network_config.boot_nodes = network_config .boot_nodes @@ -559,6 +555,11 @@ where request_response_protocols, Arc::clone(&peer_store_handle), external_addresses.clone(), + ConnectionLimits::default() + .with_max_established_per_peer(Some(crate::MAX_CONNECTIONS_PER_PEER as u32)) + .with_max_established_incoming(Some( + crate::MAX_CONNECTIONS_ESTABLISHED_INCOMING, + )), ); match result { @@ -568,37 +569,27 @@ where } }; - let builder = { + let swarm = { struct SpawnImpl(F); impl + Send>>)> Executor for SpawnImpl { fn exec(&self, f: Pin + Send>>) { (self.0)(f) } } - SwarmBuilder::with_executor( - transport, - behaviour, - local_peer_id, - SpawnImpl(params.executor), - ) + + let config = SwarmConfig::with_executor(SpawnImpl(params.executor)) + .with_substream_upgrade_protocol_override(upgrade::Version::V1) + .with_notify_handler_buffer_size(NonZeroUsize::new(32).expect("32 != 0; qed")) + // NOTE: 24 is somewhat arbitrary and should be tuned in the future if + // necessary. See + .with_per_connection_event_buffer_size(24) + .with_max_negotiating_inbound_streams(2048) + .with_idle_connection_timeout(Duration::from_secs(10)); + + Swarm::new(transport, behaviour, local_peer_id, config) }; - #[allow(deprecated)] - let builder = builder - .connection_limits( - ConnectionLimits::default() - .with_max_established_per_peer(Some(crate::MAX_CONNECTIONS_PER_PEER as u32)) - .with_max_established_incoming(Some( - crate::MAX_CONNECTIONS_ESTABLISHED_INCOMING, - )), - ) - .substream_upgrade_protocol_override(upgrade::Version::V1) - .notify_handler_buffer_size(NonZeroUsize::new(32).expect("32 != 0; qed")) - // NOTE: 24 is somewhat arbitrary and should be tuned in the future if necessary. - // See - .per_connection_event_buffer_size(24) - .max_negotiating_inbound_streams(2048); - - (builder.build(), Arc::new(Libp2pBandwidthSink { sink: bandwidth })) + + (swarm, Arc::new(Libp2pBandwidthSink { sink: bandwidth })) }; // Initialize the metrics. @@ -614,19 +605,15 @@ where }; // Listen on multiaddresses. - for addr in &listen_addresses { - if let Err(err) = Swarm::>::listen_on(&mut swarm, addr.clone()) { + for addr in &network_config.listen_addresses { + if let Err(err) = Swarm::>::listen_on(&mut swarm, addr.clone().into()) { warn!(target: "sub-libp2p", "Can't listen on {} because: {:?}", addr, err) } } // Add external addresses. - for addr in &public_addresses { - Swarm::>::add_external_address( - &mut swarm, - addr.clone(), - AddressScore::Infinite, - ); + for addr in &network_config.public_addresses { + Swarm::>::add_external_address(&mut swarm, addr.clone().into()); } let listen_addresses_set = Arc::new(Mutex::new(HashSet::new())); @@ -807,7 +794,7 @@ where let peer_id = Swarm::>::local_peer_id(swarm).to_base58(); let listened_addresses = swarm.listeners().cloned().collect(); - let external_addresses = swarm.external_addresses().map(|r| &r.addr).cloned().collect(); + let external_addresses = swarm.external_addresses().cloned().collect(); NetworkState { peer_id, @@ -867,8 +854,7 @@ impl NetworkService { .into_iter() .map(|mut addr| { let peer = match addr.pop() { - Some(multiaddr::Protocol::P2p(key)) => PeerId::from_multihash(key) - .map_err(|_| "Invalid PeerId format".to_string())?, + Some(multiaddr::Protocol::P2p(peer_id)) => peer_id, _ => return Err("Missing PeerId from address".to_string()), }; @@ -1492,6 +1478,7 @@ where } /// Process the next event coming from `Swarm`. + #[allow(deprecated)] fn handle_swarm_event(&mut self, event: SwarmEvent>>) { match event { SwarmEvent::Behaviour(BehaviourOut::InboundRequest { protocol, result, .. }) => { @@ -1586,9 +1573,11 @@ where listen_addrs.truncate(30); } for addr in listen_addrs { - self.network_service - .behaviour_mut() - .add_self_reported_address_to_dht(&peer_id, &protocols, addr); + self.network_service.behaviour_mut().add_self_reported_address_to_dht( + &peer_id, + &protocols, + addr.clone(), + ); } self.peer_store_handle.add_known_peer(peer_id.into()); }, @@ -1705,8 +1694,14 @@ where } } }, - SwarmEvent::ConnectionClosed { peer_id, cause, endpoint, num_established } => { - debug!(target: "sub-libp2p", "Libp2p => Disconnected({:?}, {:?})", peer_id, cause); + SwarmEvent::ConnectionClosed { + connection_id, + peer_id, + cause, + endpoint, + num_established, + } => { + debug!(target: "sub-libp2p", "Libp2p => Disconnected({peer_id:?} via {connection_id:?}, {cause:?})"); if let Some(metrics) = self.metrics.as_ref() { let direction = match endpoint { ConnectedPoint::Dialer { .. } => "out", @@ -1715,11 +1710,13 @@ where let reason = match cause { Some(ConnectionError::IO(_)) => "transport-error", Some(ConnectionError::Handler(Either::Left(Either::Left( - Either::Right(Either::Left(PingFailure::Timeout)), - )))) => "ping-timeout", - Some(ConnectionError::Handler(Either::Left(Either::Left( - Either::Left(NotifsHandlerError::SyncNotificationsClogged), + Either::Left(Either::Right( + NotifsHandlerError::SyncNotificationsClogged, + )), )))) => "sync-notifications-clogged", + Some(ConnectionError::Handler(Either::Left(Either::Left( + Either::Right(Either::Left(_)), + )))) => "ping-timeout", Some(ConnectionError::Handler(_)) => "protocol-error", Some(ConnectionError::KeepAliveTimeout) => "keep-alive-timeout", None => "actively-closed", @@ -1746,12 +1743,11 @@ where } self.listen_addresses.lock().remove(&address); }, - SwarmEvent::OutgoingConnectionError { peer_id, error } => { + SwarmEvent::OutgoingConnectionError { connection_id, peer_id, error } => { if let Some(peer_id) = peer_id { trace!( target: "sub-libp2p", - "Libp2p => Failed to reach {:?}: {}", - peer_id, error, + "Libp2p => Failed to reach {peer_id:?} via {connection_id:?}: {error}", ); let not_reported = !self.reported_invalid_boot_nodes.contains(&peer_id); @@ -1789,12 +1785,9 @@ where } else { None }, - DialError::ConnectionLimit(_) => Some("limit-reached"), - DialError::InvalidPeerId(_) | - DialError::WrongPeerId { .. } | - DialError::LocalPeerId { .. } => Some("invalid-peer-id"), + DialError::LocalPeerId { .. } => Some("local-peer-id"), + DialError::WrongPeerId { .. } => Some("invalid-peer-id"), DialError::Transport(_) => Some("transport-error"), - DialError::Banned | DialError::NoAddresses | DialError::DialPeerConditionFalse(_) | DialError::Aborted => None, // ignore them @@ -1804,21 +1797,24 @@ where } } }, - SwarmEvent::Dialing(peer_id) => { - trace!(target: "sub-libp2p", "Libp2p => Dialing({:?})", peer_id) + SwarmEvent::Dialing { connection_id, peer_id } => { + trace!(target: "sub-libp2p", "Libp2p => Dialing({peer_id:?}) via {connection_id:?}") }, - SwarmEvent::IncomingConnection { local_addr, send_back_addr } => { - trace!(target: "sub-libp2p", "Libp2p => IncomingConnection({},{}))", - local_addr, send_back_addr); + SwarmEvent::IncomingConnection { connection_id, local_addr, send_back_addr } => { + trace!(target: "sub-libp2p", "Libp2p => IncomingConnection({local_addr},{send_back_addr} via {connection_id:?}))"); if let Some(metrics) = self.metrics.as_ref() { metrics.incoming_connections_total.inc(); } }, - SwarmEvent::IncomingConnectionError { local_addr, send_back_addr, error } => { + SwarmEvent::IncomingConnectionError { + connection_id, + local_addr, + send_back_addr, + error, + } => { debug!( target: "sub-libp2p", - "Libp2p => IncomingConnectionError({},{}): {}", - local_addr, send_back_addr, error, + "Libp2p => IncomingConnectionError({local_addr},{send_back_addr} via {connection_id:?}): {error}" ); if let Some(metrics) = self.metrics.as_ref() { #[allow(deprecated)] @@ -1829,7 +1825,6 @@ where } else { None }, - ListenError::ConnectionLimit(_) => Some("limit-reached"), ListenError::WrongPeerId { .. } | ListenError::LocalPeerId { .. } => Some("invalid-peer-id"), ListenError::Transport(_) => Some("transport-error"), @@ -1844,17 +1839,6 @@ where } } }, - #[allow(deprecated)] - SwarmEvent::BannedPeer { peer_id, endpoint } => { - debug!( - target: "sub-libp2p", - "Libp2p => BannedPeer({}). Connected via {:?}.", - peer_id, endpoint, - ); - if let Some(metrics) = self.metrics.as_ref() { - metrics.incoming_connections_errors_total.with_label_values(&["banned"]).inc(); - } - }, SwarmEvent::ListenerClosed { reason, addresses, .. } => { if let Some(metrics) = self.metrics.as_ref() { metrics.listeners_local_addresses.sub(addresses.len() as u64); diff --git a/substrate/client/network/src/transport.rs b/substrate/client/network/src/transport.rs index 4136b34fc0e8..ed7e7c574e16 100644 --- a/substrate/client/network/src/transport.rs +++ b/substrate/client/network/src/transport.rs @@ -57,7 +57,7 @@ pub fn build_transport( // Main transport: DNS(TCP) let tcp_config = tcp::Config::new().nodelay(true); let tcp_trans = tcp::tokio::Transport::new(tcp_config.clone()); - let dns_init = dns::TokioDnsConfig::system(tcp_trans); + let dns_init = dns::tokio::Transport::system(tcp_trans); Either::Left(if let Ok(dns) = dns_init { // WS + WSS transport @@ -66,7 +66,7 @@ pub fn build_transport( // unresolved addresses (BUT WSS transport itself needs an instance of DNS transport to // resolve and dial addresses). let tcp_trans = tcp::tokio::Transport::new(tcp_config); - let dns_for_wss = dns::TokioDnsConfig::system(tcp_trans) + let dns_for_wss = dns::tokio::Transport::system(tcp_trans) .expect("same system_conf & resolver to work"); Either::Left(websocket::WsConfig::new(dns_for_wss).or_transport(dns)) } else { diff --git a/substrate/client/network/src/types.rs b/substrate/client/network/src/types.rs index 25517599469e..0652bbcdddec 100644 --- a/substrate/client/network/src/types.rs +++ b/substrate/client/network/src/types.rs @@ -18,8 +18,6 @@ //! `sc-network` type definitions -use libp2p::core::upgrade; - use std::{ borrow::Borrow, fmt, @@ -94,9 +92,9 @@ impl fmt::Display for ProtocolName { } } -impl upgrade::ProtocolName for ProtocolName { - fn protocol_name(&self) -> &[u8] { - (self as &str).as_bytes() +impl AsRef for ProtocolName { + fn as_ref(&self) -> &str { + self as &str } } diff --git a/substrate/client/network/statement/Cargo.toml b/substrate/client/network/statement/Cargo.toml index 55ff3d54bba0..4cced49fee79 100644 --- a/substrate/client/network/statement/Cargo.toml +++ b/substrate/client/network/statement/Cargo.toml @@ -20,7 +20,6 @@ array-bytes = { workspace = true, default-features = true } async-channel = { workspace = true } codec = { features = ["derive"], workspace = true, default-features = true } futures = { workspace = true } -libp2p = { workspace = true } log = { workspace = true, default-features = true } prometheus-endpoint = { workspace = true, default-features = true } sc-network-common = { workspace = true, default-features = true } diff --git a/substrate/client/network/transactions/Cargo.toml b/substrate/client/network/transactions/Cargo.toml index a561aa2da470..eb907b606d58 100644 --- a/substrate/client/network/transactions/Cargo.toml +++ b/substrate/client/network/transactions/Cargo.toml @@ -19,7 +19,6 @@ targets = ["x86_64-unknown-linux-gnu"] array-bytes = { workspace = true, default-features = true } codec = { features = ["derive"], workspace = true, default-features = true } futures = { workspace = true } -libp2p = { workspace = true } log = { workspace = true, default-features = true } prometheus-endpoint = { workspace = true, default-features = true } sc-network = { workspace = true, default-features = true } diff --git a/substrate/client/network/types/Cargo.toml b/substrate/client/network/types/Cargo.toml index b54617eafd0d..811ccddbef93 100644 --- a/substrate/client/network/types/Cargo.toml +++ b/substrate/client/network/types/Cargo.toml @@ -12,10 +12,11 @@ documentation = "https://docs.rs/sc-network-types" [dependencies] bs58 = { workspace = true, default-features = true } ed25519-dalek = { workspace = true, default-features = true } -libp2p-identity = { features = ["ed25519", "peerid"], workspace = true } +libp2p-identity = { features = ["ed25519", "peerid", "rand"], workspace = true } litep2p = { workspace = true } +log = { workspace = true, default-features = true } multiaddr = { workspace = true } -multihash = { features = ["identity", "multihash-impl", "sha2", "std"], workspace = true } +multihash = { workspace = true } rand = { workspace = true, default-features = true } thiserror = { workspace = true } zeroize = { workspace = true } diff --git a/substrate/client/network/types/src/multiaddr.rs b/substrate/client/network/types/src/multiaddr.rs index de317e2aa1cf..925e24fe70d6 100644 --- a/substrate/client/network/types/src/multiaddr.rs +++ b/substrate/client/network/types/src/multiaddr.rs @@ -20,6 +20,7 @@ use litep2p::types::multiaddr::{ Error as LiteP2pError, Iter as LiteP2pIter, Multiaddr as LiteP2pMultiaddr, Protocol as LiteP2pProtocol, }; +use multiaddr::Multiaddr as LibP2pMultiaddr; use std::{ fmt::{self, Debug, Display}, net::{IpAddr, Ipv4Addr, Ipv6Addr}, @@ -103,6 +104,18 @@ impl From for LiteP2pMultiaddr { } } +impl From for Multiaddr { + fn from(multiaddr: LibP2pMultiaddr) -> Self { + multiaddr.into_iter().map(Into::into).collect() + } +} + +impl From for LibP2pMultiaddr { + fn from(multiaddr: Multiaddr) -> Self { + multiaddr.into_iter().map(Into::into).collect() + } +} + impl From for Multiaddr { fn from(v: IpAddr) -> Multiaddr { match v { diff --git a/substrate/client/network/types/src/multiaddr/protocol.rs b/substrate/client/network/types/src/multiaddr/protocol.rs index 2a3b59e6a682..aca3a3113686 100644 --- a/substrate/client/network/types/src/multiaddr/protocol.rs +++ b/substrate/client/network/types/src/multiaddr/protocol.rs @@ -17,12 +17,18 @@ // along with this program. If not, see . use crate::multihash::Multihash; +use libp2p_identity::PeerId; use litep2p::types::multiaddr::Protocol as LiteP2pProtocol; +use multiaddr::Protocol as LibP2pProtocol; use std::{ borrow::Cow, + fmt::{self, Debug, Display}, net::{IpAddr, Ipv4Addr, Ipv6Addr}, }; +// Log target for this file. +const LOG_TARGET: &str = "sub-libp2p"; + /// [`Protocol`] describes all possible multiaddress protocols. #[derive(PartialEq, Eq, Clone, Debug)] pub enum Protocol<'a> { @@ -60,6 +66,13 @@ pub enum Protocol<'a> { Wss(Cow<'a, str>), } +impl<'a> Display for Protocol<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let protocol = LiteP2pProtocol::from(self.clone()); + Display::fmt(&protocol, f) + } +} + impl<'a> From for Protocol<'a> { #[inline] fn from(addr: IpAddr) -> Self { @@ -160,3 +173,102 @@ impl<'a> From> for LiteP2pProtocol<'a> { } } } + +impl<'a> From> for Protocol<'a> { + fn from(protocol: LibP2pProtocol<'a>) -> Self { + match protocol { + LibP2pProtocol::Dccp(port) => Protocol::Dccp(port), + LibP2pProtocol::Dns(str) => Protocol::Dns(str), + LibP2pProtocol::Dns4(str) => Protocol::Dns4(str), + LibP2pProtocol::Dns6(str) => Protocol::Dns6(str), + LibP2pProtocol::Dnsaddr(str) => Protocol::Dnsaddr(str), + LibP2pProtocol::Http => Protocol::Http, + LibP2pProtocol::Https => Protocol::Https, + LibP2pProtocol::Ip4(ipv4_addr) => Protocol::Ip4(ipv4_addr), + LibP2pProtocol::Ip6(ipv6_addr) => Protocol::Ip6(ipv6_addr), + LibP2pProtocol::P2pWebRtcDirect => Protocol::P2pWebRtcDirect, + LibP2pProtocol::P2pWebRtcStar => Protocol::P2pWebRtcStar, + LibP2pProtocol::Certhash(multihash) => Protocol::Certhash(multihash.into()), + LibP2pProtocol::P2pWebSocketStar => Protocol::P2pWebSocketStar, + LibP2pProtocol::Memory(port) => Protocol::Memory(port), + LibP2pProtocol::Onion(str, port) => Protocol::Onion(str, port), + LibP2pProtocol::Onion3(addr) => Protocol::Onion3(Cow::Owned(*addr.hash()), addr.port()), + LibP2pProtocol::P2p(peer_id) => Protocol::P2p((*peer_id.as_ref()).into()), + LibP2pProtocol::P2pCircuit => Protocol::P2pCircuit, + LibP2pProtocol::Quic => Protocol::Quic, + LibP2pProtocol::QuicV1 => Protocol::QuicV1, + LibP2pProtocol::Sctp(port) => Protocol::Sctp(port), + LibP2pProtocol::Tcp(port) => Protocol::Tcp(port), + LibP2pProtocol::Tls => Protocol::Tls, + LibP2pProtocol::Noise => Protocol::Noise, + LibP2pProtocol::Udp(port) => Protocol::Udp(port), + LibP2pProtocol::Udt => Protocol::Udt, + LibP2pProtocol::Unix(str) => Protocol::Unix(str), + LibP2pProtocol::Utp => Protocol::Utp, + LibP2pProtocol::Ws(str) => Protocol::Ws(str), + LibP2pProtocol::Wss(str) => Protocol::Wss(str), + protocol => { + log::error!( + target: LOG_TARGET, + "Got unsupported multiaddr protocol '{}'", + protocol.tag(), + ); + // Strictly speaking, this conversion is incorrect. But making protocol conversion + // fallible would significantly complicate the client code. As DCCP transport is not + // used by substrate, this conversion should be safe. + // Also, as of `multiaddr-18.1`, all enum variants are actually covered. + Protocol::Dccp(0) + }, + } + } +} + +impl<'a> From> for LibP2pProtocol<'a> { + fn from(protocol: Protocol<'a>) -> Self { + match protocol { + Protocol::Dccp(port) => LibP2pProtocol::Dccp(port), + Protocol::Dns(str) => LibP2pProtocol::Dns(str), + Protocol::Dns4(str) => LibP2pProtocol::Dns4(str), + Protocol::Dns6(str) => LibP2pProtocol::Dns6(str), + Protocol::Dnsaddr(str) => LibP2pProtocol::Dnsaddr(str), + Protocol::Http => LibP2pProtocol::Http, + Protocol::Https => LibP2pProtocol::Https, + Protocol::Ip4(ipv4_addr) => LibP2pProtocol::Ip4(ipv4_addr), + Protocol::Ip6(ipv6_addr) => LibP2pProtocol::Ip6(ipv6_addr), + Protocol::P2pWebRtcDirect => LibP2pProtocol::P2pWebRtcDirect, + Protocol::P2pWebRtcStar => LibP2pProtocol::P2pWebRtcStar, + // Protocol #280 is called `WebRTC` in multiaddr-17.0 and `WebRTCDirect` in + // multiaddr-18.1. + Protocol::WebRTC => LibP2pProtocol::WebRTCDirect, + Protocol::Certhash(multihash) => LibP2pProtocol::Certhash(multihash.into()), + Protocol::P2pWebSocketStar => LibP2pProtocol::P2pWebSocketStar, + Protocol::Memory(port) => LibP2pProtocol::Memory(port), + Protocol::Onion(str, port) => LibP2pProtocol::Onion(str, port), + Protocol::Onion3(str, port) => LibP2pProtocol::Onion3((str.into_owned(), port).into()), + Protocol::P2p(multihash) => + LibP2pProtocol::P2p(PeerId::from_multihash(multihash.into()).unwrap_or_else(|_| { + // This is better than making conversion fallible and complicating the + // client code. + log::error!( + target: LOG_TARGET, + "Received multiaddr with p2p multihash which is not a valid \ + peer_id. Replacing with random peer_id." + ); + PeerId::random() + })), + Protocol::P2pCircuit => LibP2pProtocol::P2pCircuit, + Protocol::Quic => LibP2pProtocol::Quic, + Protocol::QuicV1 => LibP2pProtocol::QuicV1, + Protocol::Sctp(port) => LibP2pProtocol::Sctp(port), + Protocol::Tcp(port) => LibP2pProtocol::Tcp(port), + Protocol::Tls => LibP2pProtocol::Tls, + Protocol::Noise => LibP2pProtocol::Noise, + Protocol::Udp(port) => LibP2pProtocol::Udp(port), + Protocol::Udt => LibP2pProtocol::Udt, + Protocol::Unix(str) => LibP2pProtocol::Unix(str), + Protocol::Utp => LibP2pProtocol::Utp, + Protocol::Ws(str) => LibP2pProtocol::Ws(str), + Protocol::Wss(str) => LibP2pProtocol::Wss(str), + } + } +} diff --git a/substrate/client/network/types/src/multihash.rs b/substrate/client/network/types/src/multihash.rs index 91f5b6353a71..321211c598d3 100644 --- a/substrate/client/network/types/src/multihash.rs +++ b/substrate/client/network/types/src/multihash.rs @@ -156,22 +156,20 @@ impl From for LiteP2pMultihash { } } -// TODO: uncomment this after upgrading `multihash` crate to v0.19.1. -// -// impl From> for Multihash { -// fn from(generic: multihash::MultihashGeneric<64>) -> Self { -// LiteP2pMultihash::wrap(generic.code(), generic.digest()) -// .expect("both have size 64; qed") -// .into() -// } -// } -// -// impl From for multihash::Multihash<64> { -// fn from(multihash: Multihash) -> Self { -// multihash::Multihash::<64>::wrap(multihash.code(), multihash.digest()) -// .expect("both have size 64; qed") -// } -// } +impl From> for Multihash { + fn from(generic: multihash::Multihash<64>) -> Self { + LiteP2pMultihash::wrap(generic.code(), generic.digest()) + .expect("both have size 64; qed") + .into() + } +} + +impl From for multihash::Multihash<64> { + fn from(multihash: Multihash) -> Self { + multihash::Multihash::<64>::wrap(multihash.code(), multihash.digest()) + .expect("both have size 64; qed") + } +} #[cfg(test)] mod tests { diff --git a/substrate/client/offchain/Cargo.toml b/substrate/client/offchain/Cargo.toml index be8162393061..5046808f013d 100644 --- a/substrate/client/offchain/Cargo.toml +++ b/substrate/client/offchain/Cargo.toml @@ -24,7 +24,6 @@ futures = { workspace = true } futures-timer = { workspace = true } hyper = { features = ["http2", "stream"], workspace = true, default-features = true } hyper-rustls = { features = ["http2"], workspace = true } -libp2p = { workspace = true } num_cpus = { workspace = true } once_cell = { workspace = true } parking_lot = { workspace = true, default-features = true } diff --git a/substrate/client/telemetry/src/transport.rs b/substrate/client/telemetry/src/transport.rs index a82626caac2d..ca6ceecbed63 100644 --- a/substrate/client/telemetry/src/transport.rs +++ b/substrate/client/telemetry/src/transport.rs @@ -31,7 +31,7 @@ const CONNECT_TIMEOUT: Duration = Duration::from_secs(20); pub(crate) fn initialize_transport() -> Result { let transport = { let tcp_transport = libp2p::tcp::tokio::Transport::new(libp2p::tcp::Config::new()); - let inner = libp2p::dns::TokioDnsConfig::system(tcp_transport)?; + let inner = libp2p::dns::tokio::Transport::system(tcp_transport)?; libp2p::websocket::framed::WsConfig::new(inner).and_then(|connec, _| { let connec = connec .with(|item| {