From 59d8b864508ae6de178433ab0215723e03bb6338 Mon Sep 17 00:00:00 2001
From: Anton <anton.kalyaev@gmail.com>
Date: Tue, 25 Jul 2023 15:12:24 +0400
Subject: [PATCH] chore: update libp2p to 0.52.1 (#14429)

* update libp2p to 0.52.0

* proto name now must implement `AsRef<str>`

* update libp2p version everywhere

* ToSwarm, FromBehaviour, ToBehaviour

also LocalProtocolsChange and RemoteProtocolsChange

* new NetworkBehaviour invariants

* replace `Vec<u8>` with `StreamProtocol`

* rename ConnectionHandlerEvent::Custom to NotifyBehaviour

* remove DialError & ListenError invariants

also fix pending_events

* use connection_limits::Behaviour

See https://github.com/libp2p/rust-libp2p/pull/3885

* impl `void::Void` for `BehaviourOut`

also use `Behaviour::with_codec`

* KademliaHandler no longer public

* fix StreamProtocol construction

* update libp2p-identify to 0.2.0

* remove non-existing methods from PollParameters

rename ConnectionHandlerUpgrErr to StreamUpgradeError

* `P2p` now contains `PeerId`, not `Multihash`

* use multihash-codetable crate

* update Cargo.lock

* reformat text

* comment out tests for now

* remove `.into()` from P2p

* confirm observed addr manually

See https://github.com/libp2p/rust-libp2p/blob/master/protocols/identify/CHANGELOG.md#0430

* remove SwarmEvent::Banned

since we're not using `ban_peer_id`, this can be safely removed.
we may want to introduce `libp2p::allow_block_list` module in the future.

* fix imports

* replace `libp2p` with smaller deps in network-gossip

* bring back tests

* finish rewriting tests

* uncomment handler tests

* Revert "uncomment handler tests"

This reverts commit 720a06815887f4e10767c62b58864a7ec3a48e50.

* add a fixme

* update Cargo.lock

* remove extra From

* make void uninhabited

* fix discovery test

* use autonat protocols

confirming external addresses manually is unsafe in open networks

* fix SyncNotificationsClogged invariant

* only set server mode manually in tests

doubt that we need to set it on node since we're adding public addresses

* address @dmitry-markin comments

* remove autonat

* removed unused var

* fix EOL

* update smallvec and sha2

in attempt to compile polkadot

* bump k256

in attempt to build cumulus

---------

Co-authored-by: parity-processbot <>
---
 substrate/Cargo.lock                          | 1477 +++--------------
 .../client/authority-discovery/Cargo.toml     |    4 +-
 .../client/authority-discovery/src/tests.rs   |    2 +-
 .../client/authority-discovery/src/worker.rs  |    8 +-
 .../src/worker/addr_cache.rs                  |   29 +-
 .../authority-discovery/src/worker/tests.rs   |    6 +-
 substrate/client/cli/Cargo.toml               |    2 +-
 substrate/client/consensus/common/Cargo.toml  |    2 +-
 substrate/client/network-gossip/Cargo.toml    |    3 +-
 substrate/client/network-gossip/src/bridge.rs |    5 +-
 substrate/client/network-gossip/src/lib.rs    |    6 +-
 .../network-gossip/src/state_machine.rs       |    4 +-
 .../client/network-gossip/src/validator.rs    |    2 +-
 substrate/client/network/Cargo.toml           |    8 +-
 substrate/client/network/bitswap/Cargo.toml   |    2 +-
 substrate/client/network/common/Cargo.toml    |    2 +-
 substrate/client/network/light/Cargo.toml     |    2 +-
 substrate/client/network/src/behaviour.rs     |   18 +-
 substrate/client/network/src/config.rs        |    9 +-
 substrate/client/network/src/discovery.rs     |  119 +-
 substrate/client/network/src/peer_info.rs     |   65 +-
 substrate/client/network/src/protocol.rs      |   16 +-
 .../src/protocol/notifications/behaviour.rs   |   37 +-
 .../src/protocol/notifications/handler.rs     | 1267 +++++++-------
 .../src/protocol/notifications/tests.rs       |    4 +-
 .../protocol/notifications/upgrade/collec.rs  |   12 +-
 .../notifications/upgrade/notifications.rs    |  205 +--
 .../client/network/src/request_responses.rs   |   36 +-
 substrate/client/network/src/service.rs       |  116 +-
 substrate/client/network/src/types.rs         |    8 +-
 substrate/client/network/statement/Cargo.toml |    2 +-
 substrate/client/network/statement/src/lib.rs |    4 +-
 substrate/client/network/sync/Cargo.toml      |    4 +-
 substrate/client/network/test/Cargo.toml      |    2 +-
 .../client/network/transactions/Cargo.toml    |    2 +-
 .../client/network/transactions/src/lib.rs    |    4 +-
 substrate/client/offchain/Cargo.toml          |    2 +-
 substrate/client/service/src/lib.rs           |    2 +-
 substrate/client/telemetry/Cargo.toml         |    2 +-
 substrate/frame/support/Cargo.toml            |    4 +-
 substrate/primitives/core/hashing/Cargo.toml  |    2 +-
 substrate/primitives/state-machine/Cargo.toml |    2 +-
 .../primitives/statement-store/Cargo.toml     |    2 +-
 substrate/primitives/weights/Cargo.toml       |    2 +-
 44 files changed, 1311 insertions(+), 2201 deletions(-)

diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock
index 2e78549ad9b..93a8e5e9883 100644
--- a/substrate/Cargo.lock
+++ b/substrate/Cargo.lock
@@ -27,15 +27,6 @@ version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
 
-[[package]]
-name = "aead"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fc95d1bdb8e6666b2b217308eeeb09f2d6728d104be3e31916cc74d15420331"
-dependencies = [
- "generic-array 0.14.7",
-]
-
 [[package]]
 name = "aead"
 version = "0.4.3"
@@ -43,7 +34,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877"
 dependencies = [
  "generic-array 0.14.7",
- "rand_core 0.6.4",
 ]
 
 [[package]]
@@ -56,17 +46,6 @@ dependencies = [
  "generic-array 0.14.7",
 ]
 
-[[package]]
-name = "aes"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561"
-dependencies = [
- "aes-soft",
- "aesni",
- "cipher 0.2.5",
-]
-
 [[package]]
 name = "aes"
 version = "0.7.5"
@@ -81,9 +60,9 @@ dependencies = [
 
 [[package]]
 name = "aes"
-version = "0.8.2"
+version = "0.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "433cfd6710c9986c576a25ca913c39d66a6474107b406f34f91d4a8923395241"
+checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2"
 dependencies = [
  "cfg-if",
  "cipher 0.4.4",
@@ -111,33 +90,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "209b47e8954a928e1d72e86eca7000ebb6655fe1436d33eefc2201cad027e237"
 dependencies = [
  "aead 0.5.2",
- "aes 0.8.2",
+ "aes 0.8.3",
  "cipher 0.4.4",
  "ctr 0.9.2",
  "ghash 0.5.0",
  "subtle",
 ]
 
-[[package]]
-name = "aes-soft"
-version = "0.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072"
-dependencies = [
- "cipher 0.2.5",
- "opaque-debug 0.3.0",
-]
-
-[[package]]
-name = "aesni"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce"
-dependencies = [
- "cipher 0.2.5",
- "opaque-debug 0.3.0",
-]
-
 [[package]]
 name = "ahash"
 version = "0.7.6"
@@ -293,12 +252,6 @@ version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e2d098ff73c1ca148721f37baad5ea6a465a13f9573aba8641fbbbae8164a54e"
 
-[[package]]
-name = "arc-swap"
-version = "1.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
-
 [[package]]
 name = "ark-algebra-test-templates"
 version = "0.4.2"
@@ -316,7 +269,7 @@ dependencies = [
  "serde",
  "serde_derive",
  "serde_json",
- "sha2 0.10.6",
+ "sha2 0.10.7",
 ]
 
 [[package]]
@@ -545,76 +498,9 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
 
 [[package]]
 name = "arrayvec"
-version = "0.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
-
-[[package]]
-name = "asn1-rs"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30ff05a702273012438132f449575dbc804e27b2f3cbe3069aa237d26c98fa33"
-dependencies = [
- "asn1-rs-derive 0.1.0",
- "asn1-rs-impl",
- "displaydoc",
- "nom",
- "num-traits",
- "rusticata-macros",
- "thiserror",
- "time 0.3.21",
-]
-
-[[package]]
-name = "asn1-rs"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f6fd5ddaf0351dff5b8da21b2fb4ff8e08ddd02857f0bf69c47639106c0fff0"
-dependencies = [
- "asn1-rs-derive 0.4.0",
- "asn1-rs-impl",
- "displaydoc",
- "nom",
- "num-traits",
- "rusticata-macros",
- "thiserror",
- "time 0.3.21",
-]
-
-[[package]]
-name = "asn1-rs-derive"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db8b7511298d5b7784b40b092d9e9dcd3a627a5707e4b5e507931ab0d44eeebf"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 1.0.109",
- "synstructure",
-]
-
-[[package]]
-name = "asn1-rs-derive"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 1.0.109",
- "synstructure",
-]
-
-[[package]]
-name = "asn1-rs-impl"
-version = "0.1.0"
+version = "0.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 1.0.109",
-]
+checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
 
 [[package]]
 name = "assert_cmd"
@@ -664,7 +550,7 @@ dependencies = [
  "polling",
  "rustix 0.37.19",
  "slab",
- "socket2",
+ "socket2 0.4.9",
  "waker-fn",
 ]
 
@@ -734,12 +620,6 @@ dependencies = [
  "pin-project-lite 0.2.9",
 ]
 
-[[package]]
-name = "atomic-waker"
-version = "1.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3"
-
 [[package]]
 name = "atty"
 version = "0.2.14"
@@ -778,12 +658,6 @@ version = "0.2.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270"
 
-[[package]]
-name = "base16ct"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce"
-
 [[package]]
 name = "base16ct"
 version = "0.2.0"
@@ -902,7 +776,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3c2f0dc9a68c6317d884f97cc36cf5a3d20ba14ce404227df55e1af708ab04bc"
 dependencies = [
  "arrayref",
- "arrayvec 0.7.2",
+ "arrayvec 0.7.4",
  "constant_time_eq",
 ]
 
@@ -913,7 +787,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6637f448b9e61dfadbdcbae9a885fadee1f3eaffb1f8d3c1965d3ade8bdfd44f"
 dependencies = [
  "arrayref",
- "arrayvec 0.7.2",
+ "arrayvec 0.7.4",
  "constant_time_eq",
 ]
 
@@ -924,10 +798,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "42ae2468a89544a466886840aa467a25b766499f4f04bf7d9fcd10ecee9fccef"
 dependencies = [
  "arrayref",
- "arrayvec 0.7.2",
+ "arrayvec 0.7.4",
  "cc",
  "cfg-if",
  "constant_time_eq",
+ "digest 0.10.7",
 ]
 
 [[package]]
@@ -936,7 +811,7 @@ version = "0.7.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
 dependencies = [
- "block-padding 0.1.5",
+ "block-padding",
  "byte-tools",
  "byteorder",
  "generic-array 0.12.4",
@@ -960,16 +835,6 @@ dependencies = [
  "generic-array 0.14.7",
 ]
 
-[[package]]
-name = "block-modes"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57a0e8073e8baa88212fb5823574c02ebccb395136ba9a164ab89379ec6072f0"
-dependencies = [
- "block-padding 0.2.1",
- "cipher 0.2.5",
-]
-
 [[package]]
 name = "block-padding"
 version = "0.1.5"
@@ -979,12 +844,6 @@ dependencies = [
  "byte-tools",
 ]
 
-[[package]]
-name = "block-padding"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae"
-
 [[package]]
 name = "bounded-collections"
 version = "0.1.8"
@@ -1003,6 +862,15 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3"
 
+[[package]]
+name = "bs58"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896"
+dependencies = [
+ "tinyvec",
+]
+
 [[package]]
 name = "bstr"
 version = "1.5.0"
@@ -1118,17 +986,6 @@ dependencies = [
  "jobserver",
 ]
 
-[[package]]
-name = "ccm"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aca1a8fbc20b50ac9673ff014abfb2b5f4085ee1a850d408f14a159c5853ac7"
-dependencies = [
- "aead 0.3.2",
- "cipher 0.2.5",
- "subtle",
-]
-
 [[package]]
 name = "cexpr"
 version = "0.6.0"
@@ -1208,7 +1065,7 @@ dependencies = [
  "iana-time-zone",
  "js-sys",
  "num-traits",
- "time 0.1.45",
+ "time",
  "wasm-bindgen",
  "winapi",
 ]
@@ -1248,20 +1105,11 @@ checksum = "b9b68e3193982cd54187d71afdb2a271ad4cf8af157858e9cb911b91321de143"
 dependencies = [
  "core2",
  "multibase",
- "multihash",
+ "multihash 0.17.0",
  "serde",
  "unsigned-varint",
 ]
 
-[[package]]
-name = "cipher"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801"
-dependencies = [
- "generic-array 0.14.7",
-]
-
 [[package]]
 name = "cipher"
 version = "0.3.0"
@@ -1609,21 +1457,6 @@ dependencies = [
  "wasmtime-types",
 ]
 
-[[package]]
-name = "crc"
-version = "3.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe"
-dependencies = [
- "crc-catalog",
-]
-
-[[package]]
-name = "crc-catalog"
-version = "2.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484"
-
 [[package]]
 name = "crc32fast"
 version = "1.3.2"
@@ -1720,18 +1553,6 @@ version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
 
-[[package]]
-name = "crypto-bigint"
-version = "0.4.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef"
-dependencies = [
- "generic-array 0.14.7",
- "rand_core 0.6.4",
- "subtle",
- "zeroize",
-]
-
 [[package]]
 name = "crypto-bigint"
 version = "0.5.2"
@@ -1887,41 +1708,6 @@ dependencies = [
  "syn 2.0.18",
 ]
 
-[[package]]
-name = "darling"
-version = "0.14.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850"
-dependencies = [
- "darling_core",
- "darling_macro",
-]
-
-[[package]]
-name = "darling_core"
-version = "0.14.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0"
-dependencies = [
- "fnv",
- "ident_case",
- "proc-macro2",
- "quote",
- "strsim",
- "syn 1.0.109",
-]
-
-[[package]]
-name = "darling_macro"
-version = "0.14.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e"
-dependencies = [
- "darling_core",
- "quote",
- "syn 1.0.109",
-]
-
 [[package]]
 name = "data-encoding"
 version = "2.4.0"
@@ -1948,17 +1734,6 @@ dependencies = [
  "syn 1.0.109",
 ]
 
-[[package]]
-name = "der"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de"
-dependencies = [
- "const-oid",
- "pem-rfc7468",
- "zeroize",
-]
-
 [[package]]
 name = "der"
 version = "0.7.6"
@@ -1969,34 +1744,6 @@ dependencies = [
  "zeroize",
 ]
 
-[[package]]
-name = "der-parser"
-version = "7.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe398ac75057914d7d07307bf67dc7f3f574a26783b4fc7805a20ffa9f506e82"
-dependencies = [
- "asn1-rs 0.3.1",
- "displaydoc",
- "nom",
- "num-bigint",
- "num-traits",
- "rusticata-macros",
-]
-
-[[package]]
-name = "der-parser"
-version = "8.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e"
-dependencies = [
- "asn1-rs 0.5.2",
- "displaydoc",
- "nom",
- "num-bigint",
- "num-traits",
- "rusticata-macros",
-]
-
 [[package]]
 name = "derivative"
 version = "2.2.0"
@@ -2019,37 +1766,6 @@ dependencies = [
  "syn 1.0.109",
 ]
 
-[[package]]
-name = "derive_builder"
-version = "0.11.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d07adf7be193b71cc36b193d0f5fe60b918a3a9db4dad0449f57bcfd519704a3"
-dependencies = [
- "derive_builder_macro",
-]
-
-[[package]]
-name = "derive_builder_core"
-version = "0.11.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f91d4cfa921f1c05904dc3c57b4a32c38aed3340cce209f3a6fd1478babafc4"
-dependencies = [
- "darling",
- "proc-macro2",
- "quote",
- "syn 1.0.109",
-]
-
-[[package]]
-name = "derive_builder_macro"
-version = "0.11.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f0314b72bed045f3a68671b3c86328386762c93f82d98c65c3cb5e5f573dd68"
-dependencies = [
- "derive_builder_core",
- "syn 1.0.109",
-]
-
 [[package]]
 name = "derive_more"
 version = "0.99.17"
@@ -2144,17 +1860,6 @@ dependencies = [
  "winapi",
 ]
 
-[[package]]
-name = "displaydoc"
-version = "0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.18",
-]
-
 [[package]]
 name = "dissimilar"
 version = "1.0.6"
@@ -2264,30 +1969,18 @@ version = "1.0.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30"
 
-[[package]]
-name = "ecdsa"
-version = "0.14.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c"
-dependencies = [
- "der 0.6.1",
- "elliptic-curve 0.12.3",
- "rfc6979 0.3.1",
- "signature 1.6.4",
-]
-
 [[package]]
 name = "ecdsa"
 version = "0.16.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0997c976637b606099b9985693efa3581e84e41f5c11ba5255f88711058ad428"
 dependencies = [
- "der 0.7.6",
+ "der",
  "digest 0.10.7",
- "elliptic-curve 0.13.5",
- "rfc6979 0.4.0",
+ "elliptic-curve",
+ "rfc6979",
  "signature 2.1.0",
- "spki 0.7.2",
+ "spki",
 ]
 
 [[package]]
@@ -2333,43 +2026,21 @@ version = "1.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
 
-[[package]]
-name = "elliptic-curve"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3"
-dependencies = [
- "base16ct 0.1.1",
- "crypto-bigint 0.4.9",
- "der 0.6.1",
- "digest 0.10.7",
- "ff 0.12.1",
- "generic-array 0.14.7",
- "group 0.12.1",
- "hkdf",
- "pem-rfc7468",
- "pkcs8 0.9.0",
- "rand_core 0.6.4",
- "sec1 0.3.0",
- "subtle",
- "zeroize",
-]
-
 [[package]]
 name = "elliptic-curve"
 version = "0.13.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b"
 dependencies = [
- "base16ct 0.2.0",
- "crypto-bigint 0.5.2",
+ "base16ct",
+ "crypto-bigint",
  "digest 0.10.7",
- "ff 0.13.0",
+ "ff",
  "generic-array 0.14.7",
- "group 0.13.0",
- "pkcs8 0.10.2",
+ "group",
+ "pkcs8",
  "rand_core 0.6.4",
- "sec1 0.7.2",
+ "sec1",
  "subtle",
  "zeroize",
 ]
@@ -2523,16 +2194,6 @@ dependencies = [
  "libc",
 ]
 
-[[package]]
-name = "ff"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160"
-dependencies = [
- "rand_core 0.6.4",
- "subtle",
-]
-
 [[package]]
 name = "ff"
 version = "0.13.0"
@@ -2613,7 +2274,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743"
 dependencies = [
  "crc32fast",
- "libz-sys",
  "miniz_oxide 0.7.1",
 ]
 
@@ -3165,7 +2825,7 @@ checksum = "d2411eed028cdf8c8034eaf21f9915f956b6c3abec4d4c7949ee67f0721127bd"
 dependencies = [
  "futures-io",
  "rustls 0.20.8",
- "webpki 0.22.0",
+ "webpki",
 ]
 
 [[package]]
@@ -3297,7 +2957,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40"
 dependencies = [
  "opaque-debug 0.3.0",
- "polyval 0.6.0",
+ "polyval 0.6.1",
 ]
 
 [[package]]
@@ -3330,24 +2990,13 @@ dependencies = [
  "regex",
 ]
 
-[[package]]
-name = "group"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7"
-dependencies = [
- "ff 0.12.1",
- "rand_core 0.6.4",
- "subtle",
-]
-
 [[package]]
 name = "group"
 version = "0.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
 dependencies = [
- "ff 0.13.0",
+ "ff",
  "rand_core 0.6.4",
  "subtle",
 ]
@@ -3601,7 +3250,7 @@ dependencies = [
  "httpdate",
  "itoa",
  "pin-project-lite 0.2.9",
- "socket2",
+ "socket2 0.4.9",
  "tokio",
  "tower-service",
  "tracing",
@@ -3621,7 +3270,7 @@ dependencies = [
  "rustls-native-certs",
  "tokio",
  "tokio-rustls 0.23.4",
- "webpki-roots",
+ "webpki-roots 0.22.6",
 ]
 
 [[package]]
@@ -3662,12 +3311,6 @@ dependencies = [
  "cc",
 ]
 
-[[package]]
-name = "ident_case"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
-
 [[package]]
 name = "idna"
 version = "0.2.3"
@@ -3834,25 +3477,6 @@ dependencies = [
  "num-traits",
 ]
 
-[[package]]
-name = "interceptor"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e8a11ae2da61704edada656798b61c94b35ecac2c58eb955156987d5e6be90b"
-dependencies = [
- "async-trait",
- "bytes",
- "log",
- "rand 0.8.5",
- "rtcp",
- "rtp",
- "thiserror",
- "tokio",
- "waitgroup",
- "webrtc-srtp",
- "webrtc-util",
-]
-
 [[package]]
 name = "intx"
 version = "0.1.0"
@@ -3882,7 +3506,7 @@ version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bd302af1b90f2463a98fa5ad469fc212c8e3175a41c3068601bfa2727591c5be"
 dependencies = [
- "socket2",
+ "socket2 0.4.9",
  "widestring",
  "winapi",
  "winreg",
@@ -3983,7 +3607,7 @@ dependencies = [
  "tokio-rustls 0.23.4",
  "tokio-util",
  "tracing",
- "webpki-roots",
+ "webpki-roots 0.22.6",
 ]
 
 [[package]]
@@ -3993,7 +3617,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a4e70b4439a751a5de7dd5ed55eacff78ebf4ffe0fc009cb1ebb11417f5b536b"
 dependencies = [
  "anyhow",
- "arrayvec 0.7.2",
+ "arrayvec 0.7.4",
  "async-lock",
  "async-trait",
  "beef",
@@ -4101,10 +3725,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc"
 dependencies = [
  "cfg-if",
- "ecdsa 0.16.7",
- "elliptic-curve 0.13.5",
+ "ecdsa",
+ "elliptic-curve",
  "once_cell",
- "sha2 0.10.6",
+ "sha2 0.10.7",
 ]
 
 [[package]]
@@ -4317,9 +3941,9 @@ checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4"
 
 [[package]]
 name = "libp2p"
-version = "0.51.3"
+version = "0.52.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f210d259724eae82005b5c48078619b7745edb7b76de370b03f8ba59ea103097"
+checksum = "38039ba2df4f3255842050845daef4a004cc1f26da03dbc645535088b51910ef"
 dependencies = [
  "bytes",
  "futures",
@@ -4337,12 +3961,10 @@ dependencies = [
  "libp2p-metrics",
  "libp2p-noise",
  "libp2p-ping",
- "libp2p-quic",
  "libp2p-request-response",
  "libp2p-swarm",
  "libp2p-tcp",
  "libp2p-wasm-ext",
- "libp2p-webrtc",
  "libp2p-websocket",
  "libp2p-yamux",
  "multiaddr",
@@ -4351,9 +3973,9 @@ dependencies = [
 
 [[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",
@@ -4363,9 +3985,9 @@ dependencies = [
 
 [[package]]
 name = "libp2p-connection-limits"
-version = "0.1.0"
+version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4caa33f1d26ed664c4fe2cca81a08c8e07d4c1c04f2f4ac7655c2dd85467fda0"
+checksum = "d45dd90e8f0e1fa59e85ff5316dd4d1ac41a9a507e79cda1b0e9b7be43ad1a56"
 dependencies = [
  "libp2p-core",
  "libp2p-identity",
@@ -4375,9 +3997,9 @@ dependencies = [
 
 [[package]]
 name = "libp2p-core"
-version = "0.39.2"
+version = "0.40.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c1df63c0b582aa434fb09b2d86897fa2b419ffeccf934b36f87fcedc8e835c2"
+checksum = "ef7dd7b09e71aac9271c60031d0e558966cdb3253ba0308ab369bb2de80630d0"
 dependencies = [
  "either",
  "fnv",
@@ -4387,7 +4009,7 @@ dependencies = [
  "libp2p-identity",
  "log",
  "multiaddr",
- "multihash",
+ "multihash 0.19.0",
  "multistream-select",
  "once_cell",
  "parking_lot 0.12.1",
@@ -4403,12 +4025,13 @@ dependencies = [
 
 [[package]]
 name = "libp2p-dns"
-version = "0.39.0"
+version = "0.40.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "146ff7034daae62077c415c2376b8057368042df6ab95f5432ad5e88568b1554"
+checksum = "fd4394c81c0c06d7b4a60f3face7e8e8a9b246840f98d2c80508d0721b032147"
 dependencies = [
  "futures",
  "libp2p-core",
+ "libp2p-identity",
  "log",
  "parking_lot 0.12.1",
  "smallvec",
@@ -4417,9 +4040,9 @@ dependencies = [
 
 [[package]]
 name = "libp2p-identify"
-version = "0.42.2"
+version = "0.43.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5455f472243e63b9c497ff320ded0314254a9eb751799a39c283c6f20b793f3c"
+checksum = "6a29675a32dbcc87790db6cf599709e64308f1ae9d5ecea2d259155889982db8"
 dependencies = [
  "asynchronous-codec",
  "either",
@@ -4439,29 +4062,28 @@ dependencies = [
 
 [[package]]
 name = "libp2p-identity"
-version = "0.1.2"
+version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e2d584751cecb2aabaa56106be6be91338a60a0f4e420cf2af639204f596fc1"
+checksum = "d2874d9c6575f1d7a151022af5c42bb0ffdcdfbafe0a6fd039de870b384835a2"
 dependencies = [
- "bs58",
+ "bs58 0.5.0",
  "ed25519-dalek",
  "log",
- "multiaddr",
- "multihash",
+ "multihash 0.19.0",
  "quick-protobuf",
  "rand 0.8.5",
- "sha2 0.10.6",
+ "sha2 0.10.7",
  "thiserror",
  "zeroize",
 ]
 
 [[package]]
 name = "libp2p-kad"
-version = "0.43.3"
+version = "0.44.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39d5ef876a2b2323d63c258e63c2f8e36f205fe5a11f0b3095d59635650790ff"
+checksum = "f0eeb75763862ff762c3240722fbed06ff6bb025d6afbdf2ce887f3610657789"
 dependencies = [
- "arrayvec 0.7.2",
+ "arrayvec 0.7.4",
  "asynchronous-codec",
  "bytes",
  "either",
@@ -4475,7 +4097,7 @@ dependencies = [
  "log",
  "quick-protobuf",
  "rand 0.8.5",
- "sha2 0.10.6",
+ "sha2 0.10.7",
  "smallvec",
  "thiserror",
  "uint",
@@ -4485,9 +4107,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",
@@ -4498,7 +4120,7 @@ dependencies = [
  "log",
  "rand 0.8.5",
  "smallvec",
- "socket2",
+ "socket2 0.5.3",
  "tokio",
  "trust-dns-proto",
  "void",
@@ -4506,23 +4128,26 @@ dependencies = [
 
 [[package]]
 name = "libp2p-metrics"
-version = "0.12.0"
+version = "0.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a42ec91e227d7d0dafa4ce88b333cdf5f277253873ab087555c92798db2ddd46"
+checksum = "3787ea81798dcc5bf1d8b40a8e8245cf894b168d04dd70aa48cb3ff2fff141d2"
 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.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c3673da89d29936bc6435bafc638e2f184180d554ce844db65915113f86ec5e"
+checksum = "87945db2b3f977af09b62b9aa0a5f3e4870995a577ecd845cdeba94cdf6bbca7"
 dependencies = [
  "bytes",
  "curve25519-dalek 3.2.0",
@@ -4530,10 +4155,12 @@ dependencies = [
  "libp2p-core",
  "libp2p-identity",
  "log",
+ "multiaddr",
+ "multihash 0.19.0",
  "once_cell",
  "quick-protobuf",
  "rand 0.8.5",
- "sha2 0.10.6",
+ "sha2 0.10.7",
  "snow",
  "static_assertions",
  "thiserror",
@@ -4543,48 +4170,27 @@ dependencies = [
 
 [[package]]
 name = "libp2p-ping"
-version = "0.42.0"
+version = "0.43.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e57759c19c28a73ef1eb3585ca410cefb72c1a709fcf6de1612a378e4219202"
+checksum = "3cd5ee3270229443a2b34b27ed0cb7470ef6b4a6e45e54e89a8771fa683bab48"
 dependencies = [
  "either",
  "futures",
  "futures-timer",
  "instant",
  "libp2p-core",
+ "libp2p-identity",
  "libp2p-swarm",
  "log",
  "rand 0.8.5",
  "void",
 ]
 
-[[package]]
-name = "libp2p-quic"
-version = "0.7.0-alpha.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6b26abd81cd2398382a1edfe739b539775be8a90fa6914f39b2ab49571ec735"
-dependencies = [
- "bytes",
- "futures",
- "futures-timer",
- "if-watch",
- "libp2p-core",
- "libp2p-identity",
- "libp2p-tls",
- "log",
- "parking_lot 0.12.1",
- "quinn-proto",
- "rand 0.8.5",
- "rustls 0.20.8",
- "thiserror",
- "tokio",
-]
-
 [[package]]
 name = "libp2p-request-response"
-version = "0.24.1"
+version = "0.25.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ffdb374267d42dc5ed5bc53f6e601d4a64ac5964779c6e40bb9e4f14c1e30d5"
+checksum = "20bd837798cdcce4283d2675f08bcd3756a650d56eab4d4367e1b3f27eed6887"
 dependencies = [
  "async-trait",
  "futures",
@@ -4592,15 +4198,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.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "903b3d592d7694e56204d211f29d31bc004be99386644ba8731fc3e3ef27b296"
+checksum = "5de15b2097fc3bde063df8c202803538ff467fedb18f01c13bc5da55913d246c"
 dependencies = [
  "either",
  "fnv",
@@ -4611,6 +4219,8 @@ dependencies = [
  "libp2p-identity",
  "libp2p-swarm-derive",
  "log",
+ "multistream-select",
+ "once_cell",
  "rand 0.8.5",
  "smallvec",
  "tokio",
@@ -4619,119 +4229,73 @@ 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",
+ "proc-macro-warning",
+ "proc-macro2",
  "quote",
- "syn 1.0.109",
+ "syn 2.0.18",
 ]
 
 [[package]]
 name = "libp2p-tcp"
-version = "0.39.0"
+version = "0.40.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33d33698596d7722d85d3ab0c86c2c322254fce1241e91208e3679b4eb3026cf"
+checksum = "09bfdfb6f945c5c014b87872a0bdb6e0aef90e92f380ef57cd9013f118f9289d"
 dependencies = [
  "futures",
  "futures-timer",
  "if-watch",
  "libc",
  "libp2p-core",
+ "libp2p-identity",
  "log",
- "socket2",
+ "socket2 0.5.3",
  "tokio",
 ]
 
-[[package]]
-name = "libp2p-tls"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff08d13d0dc66e5e9ba6279c1de417b84fa0d0adc3b03e5732928c180ec02781"
-dependencies = [
- "futures",
- "futures-rustls",
- "libp2p-core",
- "libp2p-identity",
- "rcgen 0.10.0",
- "ring",
- "rustls 0.20.8",
- "thiserror",
- "webpki 0.22.0",
- "x509-parser 0.14.0",
- "yasna",
-]
-
 [[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-webrtc"
-version = "0.4.0-alpha.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dba48592edbc2f60b4bc7c10d65445b0c3964c07df26fdf493b6880d33be36f8"
-dependencies = [
- "async-trait",
- "asynchronous-codec",
- "bytes",
- "futures",
- "futures-timer",
- "hex",
- "if-watch",
- "libp2p-core",
- "libp2p-identity",
- "libp2p-noise",
- "log",
- "multihash",
- "quick-protobuf",
- "quick-protobuf-codec",
- "rand 0.8.5",
- "rcgen 0.9.3",
- "serde",
- "stun",
- "thiserror",
- "tinytemplate",
- "tokio",
- "tokio-util",
- "webrtc",
-]
-
 [[package]]
 name = "libp2p-websocket"
-version = "0.41.0"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "111273f7b3d3510524c752e8b7a5314b7f7a1fee7e68161c01a7d72cbb06db9f"
+checksum = "956d981ebc84abc3377e5875483c06d94ff57bc6b25f725047f9fd52592f72d4"
 dependencies = [
  "either",
  "futures",
  "futures-rustls",
  "libp2p-core",
+ "libp2p-identity",
  "log",
  "parking_lot 0.12.1",
  "quicksink",
  "rw-stream-sink",
  "soketto",
  "url",
- "webpki-roots",
+ "webpki-roots 0.23.1",
 ]
 
 [[package]]
 name = "libp2p-yamux"
-version = "0.43.1"
+version = "0.44.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dcd21d950662700a385d4c6d68e2f5f54d778e97068cdd718522222ef513bda"
+checksum = "c0a9b42ab6de15c6f076d8fb11dc5f48d899a10b55a2e16b12be9012a05287b0"
 dependencies = [
  "futures",
  "libp2p-core",
@@ -4889,9 +4453,9 @@ dependencies = [
 
 [[package]]
 name = "log"
-version = "0.4.18"
+version = "0.4.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de"
+checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
 
 [[package]]
 name = "lru"
@@ -5030,17 +4594,8 @@ version = "0.3.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "090126dc04f95dc0d1c1c91f61bdd474b3930ca064c1edc8a849da2c6cbe1e77"
 dependencies = [
- "autocfg",
- "rawpointer",
-]
-
-[[package]]
-name = "md-5"
-version = "0.10.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca"
-dependencies = [
- "digest 0.10.7",
+ "autocfg",
+ "rawpointer",
 ]
 
 [[package]]
@@ -5067,15 +4622,6 @@ dependencies = [
  "libc",
 ]
 
-[[package]]
-name = "memoffset"
-version = "0.6.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
-dependencies = [
- "autocfg",
-]
-
 [[package]]
 name = "memoffset"
 version = "0.7.1"
@@ -5218,16 +4764,16 @@ dependencies = [
 
 [[package]]
 name = "multiaddr"
-version = "0.17.1"
+version = "0.18.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b36f567c7099511fa8612bbbb52dda2419ce0bdbacf31714e3a5ffdb766d3bd"
+checksum = "92a651988b3ed3ad1bc8c87d016bb92f6f395b84ed1db9b926b32b1fc5a2c8b5"
 dependencies = [
  "arrayref",
  "byteorder",
  "data-encoding",
- "log",
+ "libp2p-identity",
  "multibase",
- "multihash",
+ "multihash 0.19.0",
  "percent-encoding",
  "serde",
  "static_assertions",
@@ -5257,17 +4803,71 @@ dependencies = [
  "blake3",
  "core2",
  "digest 0.10.7",
- "multihash-derive",
- "sha2 0.10.6",
+ "multihash-derive 0.8.0",
+ "sha2 0.10.7",
  "sha3",
  "unsigned-varint",
 ]
 
+[[package]]
+name = "multihash"
+version = "0.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2fd59dcc2bbe70baabeac52cd22ae52c55eefe6c38ff11a9439f16a350a939f2"
+dependencies = [
+ "core2",
+ "unsigned-varint",
+]
+
+[[package]]
+name = "multihash-codetable"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e46d7ff0b9b8d818e709e12135bfb6582fcde982ba2be48ea52e6e1df098c7a4"
+dependencies = [
+ "blake2b_simd",
+ "blake2s_simd",
+ "blake3",
+ "core2",
+ "digest 0.10.7",
+ "multihash-derive 0.9.0",
+ "ripemd",
+ "sha-1 0.10.1",
+ "sha2 0.10.7",
+ "sha3",
+ "strobe-rs",
+]
+
 [[package]]
 name = "multihash-derive"
-version = "0.8.1"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc076939022111618a5026d3be019fd8b366e76314538ff9a1b59ffbcbf98bcd"
+dependencies = [
+ "proc-macro-crate",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "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.0",
+ "multihash-derive-impl",
+]
+
+[[package]]
+name = "multihash-derive-impl"
+version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d6d4752e6230d8ef7adf7bd5d8c4b1f6561c1014c5ba9a37445ccefe18aa1db"
+checksum = "d38685e08adb338659871ecfc6ee47ba9b22dcc8abcf6975d379cc49145c3040"
 dependencies = [
  "proc-macro-crate",
  "proc-macro-error",
@@ -5285,9 +4885,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",
@@ -5408,7 +5008,6 @@ dependencies = [
  "bitflags",
  "cfg-if",
  "libc",
- "memoffset 0.6.5",
 ]
 
 [[package]]
@@ -5853,7 +5452,7 @@ version = "0.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3"
 dependencies = [
- "arrayvec 0.7.2",
+ "arrayvec 0.7.4",
  "itoa",
 ]
 
@@ -5928,24 +5527,6 @@ dependencies = [
  "memchr",
 ]
 
-[[package]]
-name = "oid-registry"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38e20717fa0541f39bd146692035c37bedfa532b3e5071b35761082407546b2a"
-dependencies = [
- "asn1-rs 0.3.1",
-]
-
-[[package]]
-name = "oid-registry"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9bedf36ffb6ba96c2eb7144ef6270557b52e54b20c0a8e1eb2ff99a6c6959bff"
-dependencies = [
- "asn1-rs 0.5.2",
-]
-
 [[package]]
 name = "once_cell"
 version = "1.18.0"
@@ -5997,28 +5578,6 @@ version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
 
-[[package]]
-name = "p256"
-version = "0.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594"
-dependencies = [
- "ecdsa 0.14.8",
- "elliptic-curve 0.12.3",
- "sha2 0.10.6",
-]
-
-[[package]]
-name = "p384"
-version = "0.11.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dfc8c5bf642dde52bb9e87c0ecd8ca5a76faac2eeed98dedb7c717997e1080aa"
-dependencies = [
- "ecdsa 0.14.8",
- "elliptic-curve 0.12.3",
- "sha2 0.10.6",
-]
-
 [[package]]
 name = "packed_simd_2"
 version = "0.3.8"
@@ -7804,7 +7363,7 @@ version = "3.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2287753623c76f953acd29d15d8100bcab84d29db78fb6f352adb3c53e83b967"
 dependencies = [
- "arrayvec 0.7.2",
+ "arrayvec 0.7.4",
  "bitvec",
  "byte-slice-cast",
  "bytes",
@@ -7825,12 +7384,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-wasm"
 version = "0.45.0"
@@ -7927,24 +7480,6 @@ version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
 
-[[package]]
-name = "pem"
-version = "1.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8"
-dependencies = [
- "base64 0.13.1",
-]
-
-[[package]]
-name = "pem-rfc7468"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24d159833a9105500e0398934e205e0773f0b27529557134ecfc51c27646adac"
-dependencies = [
- "base64ct",
-]
-
 [[package]]
 name = "percent-encoding"
 version = "2.3.0"
@@ -7992,7 +7527,7 @@ checksum = "745a452f8eb71e39ffd8ee32b3c5f51d03845f99786fa9b68db6ff509c505411"
 dependencies = [
  "once_cell",
  "pest",
- "sha2 0.10.6",
+ "sha2 0.10.7",
 ]
 
 [[package]]
@@ -8043,24 +7578,14 @@ version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
 
-[[package]]
-name = "pkcs8"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba"
-dependencies = [
- "der 0.6.1",
- "spki 0.6.0",
-]
-
 [[package]]
 name = "pkcs8"
 version = "0.10.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
 dependencies = [
- "der 0.7.6",
- "spki 0.7.2",
+ "der",
+ "spki",
 ]
 
 [[package]]
@@ -8144,9 +7669,9 @@ dependencies = [
 
 [[package]]
 name = "polyval"
-version = "0.6.0"
+version = "0.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ef234e08c11dfcb2e56f79fd70f6f2eb7f025c0ce2333e82f4f0518ecad30c6"
+checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb"
 dependencies = [
  "cfg-if",
  "cpufeatures",
@@ -8256,12 +7781,12 @@ dependencies = [
 
 [[package]]
 name = "proc-macro-crate"
-version = "1.1.3"
+version = "1.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a"
+checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919"
 dependencies = [
- "thiserror",
- "toml 0.5.11",
+ "once_cell",
+ "toml_edit",
 ]
 
 [[package]]
@@ -8330,9 +7855,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",
@@ -8431,9 +7956,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",
@@ -8462,24 +7987,6 @@ dependencies = [
  "pin-project-lite 0.1.12",
 ]
 
-[[package]]
-name = "quinn-proto"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67c10f662eee9c94ddd7135043e544f3c82fa839a1e7b865911331961b53186c"
-dependencies = [
- "bytes",
- "rand 0.8.5",
- "ring",
- "rustc-hash",
- "rustls 0.20.8",
- "slab",
- "thiserror",
- "tinyvec",
- "tracing",
- "webpki 0.22.0",
-]
-
 [[package]]
 name = "quote"
 version = "1.0.28"
@@ -8613,31 +8120,6 @@ dependencies = [
  "num_cpus",
 ]
 
-[[package]]
-name = "rcgen"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6413f3de1edee53342e6138e75b56d32e7bc6e332b3bd62d497b1929d4cfbcdd"
-dependencies = [
- "pem",
- "ring",
- "time 0.3.21",
- "x509-parser 0.13.2",
- "yasna",
-]
-
-[[package]]
-name = "rcgen"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ffbe84efe2f38dea12e9bfc1f65377fdf03e53a18cb3b995faedf7934c7e785b"
-dependencies = [
- "pem",
- "ring",
- "time 0.3.21",
- "yasna",
-]
-
 [[package]]
 name = "redox_syscall"
 version = "0.2.16"
@@ -8741,17 +8223,6 @@ dependencies = [
  "quick-error",
 ]
 
-[[package]]
-name = "rfc6979"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb"
-dependencies = [
- "crypto-bigint 0.4.9",
- "hmac 0.12.1",
- "zeroize",
-]
-
 [[package]]
 name = "rfc6979"
 version = "0.4.0"
@@ -8777,6 +8248,15 @@ dependencies = [
  "winapi",
 ]
 
+[[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 = "rocksdb"
 version = "0.21.0"
@@ -8798,17 +8278,6 @@ dependencies = [
  "winapi",
 ]
 
-[[package]]
-name = "rtcp"
-version = "0.7.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1919efd6d4a6a85d13388f9487549bb8e359f17198cc03ffd72f79b553873691"
-dependencies = [
- "bytes",
- "thiserror",
- "webrtc-util",
-]
-
 [[package]]
 name = "rtnetlink"
 version = "0.10.1"
@@ -8834,20 +8303,6 @@ dependencies = [
  "winapi",
 ]
 
-[[package]]
-name = "rtp"
-version = "0.6.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2a095411ff00eed7b12e4c6a118ba984d113e1079582570d56a5ee723f11f80"
-dependencies = [
- "async-trait",
- "bytes",
- "rand 0.8.5",
- "serde",
- "thiserror",
- "webrtc-util",
-]
-
 [[package]]
 name = "rustc-demangle"
 version = "0.1.23"
@@ -8884,15 +8339,6 @@ dependencies = [
  "semver 1.0.17",
 ]
 
-[[package]]
-name = "rusticata-macros"
-version = "4.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632"
-dependencies = [
- "nom",
-]
-
 [[package]]
 name = "rustix"
 version = "0.36.14"
@@ -8921,19 +8367,6 @@ dependencies = [
  "windows-sys 0.48.0",
 ]
 
-[[package]]
-name = "rustls"
-version = "0.19.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7"
-dependencies = [
- "base64 0.13.1",
- "log",
- "ring",
- "sct 0.6.1",
- "webpki 0.21.4",
-]
-
 [[package]]
 name = "rustls"
 version = "0.20.8"
@@ -8942,8 +8375,8 @@ checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f"
 dependencies = [
  "log",
  "ring",
- "sct 0.7.0",
- "webpki 0.22.0",
+ "sct",
+ "webpki",
 ]
 
 [[package]]
@@ -8955,7 +8388,7 @@ dependencies = [
  "log",
  "ring",
  "rustls-webpki",
- "sct 0.7.0",
+ "sct",
 ]
 
 [[package]]
@@ -9008,9 +8441,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",
@@ -9070,7 +8503,7 @@ dependencies = [
  "ip_network",
  "libp2p",
  "log",
- "multihash",
+ "multihash-codetable",
  "parity-scale-codec",
  "prost",
  "prost-build",
@@ -9744,6 +9177,7 @@ dependencies = [
  "futures-timer",
  "ip_network",
  "libp2p",
+ "libp2p-kad",
  "linked_hash_set",
  "log",
  "mockall",
@@ -9776,6 +9210,7 @@ dependencies = [
  "tokio-test",
  "tokio-util",
  "unsigned-varint",
+ "void",
  "wasm-timer",
  "zeroize",
 ]
@@ -9830,8 +9265,9 @@ dependencies = [
  "ahash 0.8.3",
  "futures",
  "futures-timer",
- "libp2p",
+ "libp2p-identity",
  "log",
+ "multiaddr",
  "quickcheck",
  "sc-network",
  "sc-network-common",
@@ -10512,16 +9948,6 @@ version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1"
 
-[[package]]
-name = "sct"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce"
-dependencies = [
- "ring",
- "untrusted",
-]
-
 [[package]]
 name = "sct"
 version = "0.7.0"
@@ -10532,42 +9958,16 @@ dependencies = [
  "untrusted",
 ]
 
-[[package]]
-name = "sdp"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d22a5ef407871893fd72b4562ee15e4742269b173959db4b8df6f538c414e13"
-dependencies = [
- "rand 0.8.5",
- "substring",
- "thiserror",
- "url",
-]
-
-[[package]]
-name = "sec1"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928"
-dependencies = [
- "base16ct 0.1.1",
- "der 0.6.1",
- "generic-array 0.14.7",
- "pkcs8 0.9.0",
- "subtle",
- "zeroize",
-]
-
 [[package]]
 name = "sec1"
 version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f0aec48e813d6b90b15f0b8948af3c63483992dee44c03e9930b3eebdabe046e"
 dependencies = [
- "base16ct 0.2.0",
- "der 0.7.6",
+ "base16ct",
+ "der",
  "generic-array 0.14.7",
- "pkcs8 0.10.2",
+ "pkcs8",
  "subtle",
  "zeroize",
 ]
@@ -10655,6 +10055,12 @@ version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
 
+[[package]]
+name = "send_wrapper"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73"
+
 [[package]]
 name = "serde"
 version = "1.0.164"
@@ -10709,10 +10115,10 @@ dependencies = [
 ]
 
 [[package]]
-name = "sha1"
-version = "0.10.5"
+name = "sha-1"
+version = "0.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3"
+checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c"
 dependencies = [
  "cfg-if",
  "cpufeatures",
@@ -10746,9 +10152,9 @@ dependencies = [
 
 [[package]]
 name = "sha2"
-version = "0.10.6"
+version = "0.10.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0"
+checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8"
 dependencies = [
  "cfg-if",
  "cpufeatures",
@@ -10794,10 +10200,6 @@ name = "signature"
 version = "1.6.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c"
-dependencies = [
- "digest 0.10.7",
- "rand_core 0.6.4",
-]
 
 [[package]]
 name = "signature"
@@ -10845,9 +10247,9 @@ checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7"
 
 [[package]]
 name = "smallvec"
-version = "1.10.0"
+version = "1.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
+checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
 
 [[package]]
 name = "snap"
@@ -10868,7 +10270,7 @@ dependencies = [
  "rand_core 0.6.4",
  "ring",
  "rustc_version 0.4.0",
- "sha2 0.10.6",
+ "sha2 0.10.7",
  "subtle",
 ]
 
@@ -10876,10 +10278,20 @@ dependencies = [
 name = "socket2"
 version = "0.4.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
+checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "socket2"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877"
 dependencies = [
  "libc",
- "winapi",
+ "windows-sys 0.48.0",
 ]
 
 [[package]]
@@ -10890,13 +10302,12 @@ checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2"
 dependencies = [
  "base64 0.13.1",
  "bytes",
- "flate2",
  "futures",
  "http",
  "httparse",
  "log",
  "rand 0.8.5",
- "sha-1",
+ "sha-1 0.9.8",
 ]
 
 [[package]]
@@ -11257,7 +10668,7 @@ dependencies = [
  "bitflags",
  "blake2",
  "bounded-collections",
- "bs58",
+ "bs58 0.4.0",
  "criterion",
  "dyn-clonable",
  "ed25519-zebra",
@@ -11305,7 +10716,7 @@ dependencies = [
  "blake2b_simd",
  "byteorder",
  "digest 0.10.7",
- "sha2 0.10.6",
+ "sha2 0.10.7",
  "sha3",
  "twox-hash",
 ]
@@ -11695,7 +11106,7 @@ dependencies = [
  "parity-scale-codec",
  "rand 0.8.5",
  "scale-info",
- "sha2 0.10.6",
+ "sha2 0.10.7",
  "sp-api",
  "sp-application-crypto",
  "sp-core",
@@ -11884,16 +11295,6 @@ dependencies = [
  "strum",
 ]
 
-[[package]]
-name = "spki"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b"
-dependencies = [
- "base64ct",
- "der 0.6.1",
-]
-
 [[package]]
 name = "spki"
 version = "0.7.2"
@@ -11901,7 +11302,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a"
 dependencies = [
  "base64ct",
- "der 0.7.6",
+ "der",
 ]
 
 [[package]]
@@ -11959,6 +11360,19 @@ dependencies = [
  "syn 1.0.109",
 ]
 
+[[package]]
+name = "strobe-rs"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fabb238a1cccccfa4c4fb703670c0d157e1256c1ba695abf1b93bd2bb14bab2d"
+dependencies = [
+ "bitflags",
+ "byteorder",
+ "keccak",
+ "subtle",
+ "zeroize",
+]
+
 [[package]]
 name = "strsim"
 version = "0.10.0"
@@ -11987,25 +11401,6 @@ dependencies = [
  "syn 1.0.109",
 ]
 
-[[package]]
-name = "stun"
-version = "0.4.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7e94b1ec00bad60e6410e058b52f1c66de3dc5fe4d62d09b3e52bb7d3b73e25"
-dependencies = [
- "base64 0.13.1",
- "crc",
- "lazy_static",
- "md-5",
- "rand 0.8.5",
- "ring",
- "subtle",
- "thiserror",
- "tokio",
- "url",
- "webrtc-util",
-]
-
 [[package]]
 name = "subkey"
 version = "3.0.0"
@@ -12313,15 +11708,6 @@ dependencies = [
  "wasm-opt",
 ]
 
-[[package]]
-name = "substring"
-version = "1.4.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42ee6433ecef213b2e72f587ef64a2f5943e7cd16fbd82dbe8bc07486c534c86"
-dependencies = [
- "autocfg",
-]
-
 [[package]]
 name = "subtle"
 version = "2.4.1"
@@ -12507,33 +11893,6 @@ dependencies = [
  "winapi",
 ]
 
-[[package]]
-name = "time"
-version = "0.3.21"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f3403384eaacbca9923fa06940178ac13e4edb725486d70e8e15881d0c836cc"
-dependencies = [
- "itoa",
- "serde",
- "time-core",
- "time-macros",
-]
-
-[[package]]
-name = "time-core"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
-
-[[package]]
-name = "time-macros"
-version = "0.2.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b"
-dependencies = [
- "time-core",
-]
-
 [[package]]
 name = "tiny-bip39"
 version = "1.0.0"
@@ -12546,7 +11905,7 @@ dependencies = [
  "pbkdf2 0.11.0",
  "rand 0.8.5",
  "rustc-hash",
- "sha2 0.10.6",
+ "sha2 0.10.7",
  "thiserror",
  "unicode-normalization",
  "wasm-bindgen",
@@ -12589,11 +11948,12 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
 
 [[package]]
 name = "tokio"
-version = "1.28.2"
+version = "1.29.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2"
+checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da"
 dependencies = [
  "autocfg",
+ "backtrace",
  "bytes",
  "libc",
  "mio",
@@ -12601,7 +11961,7 @@ dependencies = [
  "parking_lot 0.12.1",
  "pin-project-lite 0.2.9",
  "signal-hook-registry",
- "socket2",
+ "socket2 0.4.9",
  "tokio-macros",
  "windows-sys 0.48.0",
 ]
@@ -12636,7 +11996,7 @@ checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
 dependencies = [
  "rustls 0.20.8",
  "tokio",
- "webpki 0.22.0",
+ "webpki",
 ]
 
 [[package]]
@@ -12945,7 +12305,7 @@ dependencies = [
  "lazy_static",
  "rand 0.8.5",
  "smallvec",
- "socket2",
+ "socket2 0.4.9",
  "thiserror",
  "tinyvec",
  "tokio",
@@ -13042,25 +12402,6 @@ version = "1.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f4f195fd851901624eee5a58c4bb2b4f06399148fcd0ed336e6f1cb60a9881df"
 
-[[package]]
-name = "turn"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4712ee30d123ec7ae26d1e1b218395a16c87cdbaf4b3925d170d684af62ea5e8"
-dependencies = [
- "async-trait",
- "base64 0.13.1",
- "futures",
- "log",
- "md-5",
- "rand 0.8.5",
- "ring",
- "stun",
- "thiserror",
- "tokio",
- "webrtc-util",
-]
-
 [[package]]
 name = "twox-hash"
 version = "1.6.3"
@@ -13185,15 +12526,6 @@ version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
 
-[[package]]
-name = "uuid"
-version = "1.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2"
-dependencies = [
- "getrandom 0.2.9",
-]
-
 [[package]]
 name = "valuable"
 version = "0.1.0"
@@ -13236,7 +12568,7 @@ dependencies = [
  "rand 0.8.5",
  "rand_chacha 0.3.1",
  "rand_core 0.6.4",
- "sha2 0.10.6",
+ "sha2 0.10.7",
  "sha3",
  "thiserror",
  "zeroize",
@@ -13251,15 +12583,6 @@ dependencies = [
  "libc",
 ]
 
-[[package]]
-name = "waitgroup"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d1f50000a783467e6c0200f9d10642f4bc424e39efc1b770203e88b488f79292"
-dependencies = [
- "atomic-waker",
-]
-
 [[package]]
 name = "waker-fn"
 version = "1.1.0"
@@ -13554,7 +12877,7 @@ dependencies = [
  "log",
  "rustix 0.36.14",
  "serde",
- "sha2 0.10.6",
+ "sha2 0.10.7",
  "toml 0.5.11",
  "windows-sys 0.45.0",
  "zstd 0.11.2+zstd.1.5.2",
@@ -13729,16 +13052,6 @@ dependencies = [
  "wasm-bindgen",
 ]
 
-[[package]]
-name = "webpki"
-version = "0.21.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea"
-dependencies = [
- "ring",
- "untrusted",
-]
-
 [[package]]
 name = "webpki"
 version = "0.22.0"
@@ -13755,216 +13068,16 @@ version = "0.22.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87"
 dependencies = [
- "webpki 0.22.0",
-]
-
-[[package]]
-name = "webrtc"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d3bc9049bdb2cea52f5fd4f6f728184225bdb867ed0dc2410eab6df5bdd67bb"
-dependencies = [
- "arc-swap",
- "async-trait",
- "bytes",
- "hex",
- "interceptor",
- "lazy_static",
- "log",
- "rand 0.8.5",
- "rcgen 0.9.3",
- "regex",
- "ring",
- "rtcp",
- "rtp",
- "rustls 0.19.1",
- "sdp",
- "serde",
- "serde_json",
- "sha2 0.10.6",
- "stun",
- "thiserror",
- "time 0.3.21",
- "tokio",
- "turn",
- "url",
- "waitgroup",
- "webrtc-data",
- "webrtc-dtls",
- "webrtc-ice",
- "webrtc-mdns",
- "webrtc-media",
- "webrtc-sctp",
- "webrtc-srtp",
- "webrtc-util",
-]
-
-[[package]]
-name = "webrtc-data"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ef36a4d12baa6e842582fe9ec16a57184ba35e1a09308307b67d43ec8883100"
-dependencies = [
- "bytes",
- "derive_builder",
- "log",
- "thiserror",
- "tokio",
- "webrtc-sctp",
- "webrtc-util",
-]
-
-[[package]]
-name = "webrtc-dtls"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "942be5bd85f072c3128396f6e5a9bfb93ca8c1939ded735d177b7bcba9a13d05"
-dependencies = [
- "aes 0.6.0",
- "aes-gcm 0.10.2",
- "async-trait",
- "bincode",
- "block-modes",
- "byteorder",
- "ccm",
- "curve25519-dalek 3.2.0",
- "der-parser 8.2.0",
- "elliptic-curve 0.12.3",
- "hkdf",
- "hmac 0.12.1",
- "log",
- "oid-registry 0.6.1",
- "p256",
- "p384",
- "rand 0.8.5",
- "rand_core 0.6.4",
- "rcgen 0.9.3",
- "ring",
- "rustls 0.19.1",
- "sec1 0.3.0",
- "serde",
- "sha1",
- "sha2 0.10.6",
- "signature 1.6.4",
- "subtle",
- "thiserror",
- "tokio",
- "webpki 0.21.4",
- "webrtc-util",
- "x25519-dalek 2.0.0-pre.1",
- "x509-parser 0.13.2",
-]
-
-[[package]]
-name = "webrtc-ice"
-version = "0.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "465a03cc11e9a7d7b4f9f99870558fe37a102b65b93f8045392fef7c67b39e80"
-dependencies = [
- "arc-swap",
- "async-trait",
- "crc",
- "log",
- "rand 0.8.5",
- "serde",
- "serde_json",
- "stun",
- "thiserror",
- "tokio",
- "turn",
- "url",
- "uuid",
- "waitgroup",
- "webrtc-mdns",
- "webrtc-util",
-]
-
-[[package]]
-name = "webrtc-mdns"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f08dfd7a6e3987e255c4dbe710dde5d94d0f0574f8a21afa95d171376c143106"
-dependencies = [
- "log",
- "socket2",
- "thiserror",
- "tokio",
- "webrtc-util",
-]
-
-[[package]]
-name = "webrtc-media"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f72e1650a8ae006017d1a5280efb49e2610c19ccc3c0905b03b648aee9554991"
-dependencies = [
- "byteorder",
- "bytes",
- "rand 0.8.5",
- "rtp",
- "thiserror",
-]
-
-[[package]]
-name = "webrtc-sctp"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d47adcd9427eb3ede33d5a7f3424038f63c965491beafcc20bc650a2f6679c0"
-dependencies = [
- "arc-swap",
- "async-trait",
- "bytes",
- "crc",
- "log",
- "rand 0.8.5",
- "thiserror",
- "tokio",
- "webrtc-util",
-]
-
-[[package]]
-name = "webrtc-srtp"
-version = "0.9.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6183edc4c1c6c0175f8812eefdce84dfa0aea9c3ece71c2bf6ddd3c964de3da5"
-dependencies = [
- "aead 0.4.3",
- "aes 0.7.5",
- "aes-gcm 0.9.4",
- "async-trait",
- "byteorder",
- "bytes",
- "ctr 0.8.0",
- "hmac 0.11.0",
- "log",
- "rtcp",
- "rtp",
- "sha-1",
- "subtle",
- "thiserror",
- "tokio",
- "webrtc-util",
+ "webpki",
 ]
 
 [[package]]
-name = "webrtc-util"
-version = "0.7.0"
+name = "webpki-roots"
+version = "0.23.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93f1db1727772c05cf7a2cfece52c3aca8045ca1e176cd517d323489aa3c6d87"
+checksum = "b03058f88386e5ff5310d9111d53f48b17d732b401aeb83a8d5190f2ac459338"
 dependencies = [
- "async-trait",
- "bitflags",
- "bytes",
- "cc",
- "ipnet",
- "lazy_static",
- "libc",
- "log",
- "nix 0.24.3",
- "rand 0.8.5",
- "thiserror",
- "tokio",
- "winapi",
+ "rustls-webpki",
 ]
 
 [[package]]
@@ -14258,43 +13371,6 @@ dependencies = [
  "zeroize",
 ]
 
-[[package]]
-name = "x509-parser"
-version = "0.13.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fb9bace5b5589ffead1afb76e43e34cff39cd0f3ce7e170ae0c29e53b88eb1c"
-dependencies = [
- "asn1-rs 0.3.1",
- "base64 0.13.1",
- "data-encoding",
- "der-parser 7.0.0",
- "lazy_static",
- "nom",
- "oid-registry 0.4.0",
- "ring",
- "rusticata-macros",
- "thiserror",
- "time 0.3.21",
-]
-
-[[package]]
-name = "x509-parser"
-version = "0.14.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0ecbeb7b67ce215e40e3cc7f2ff902f94a223acf44995934763467e7b1febc8"
-dependencies = [
- "asn1-rs 0.5.2",
- "base64 0.13.1",
- "data-encoding",
- "der-parser 8.2.0",
- "lazy_static",
- "nom",
- "oid-registry 0.6.1",
- "rusticata-macros",
- "thiserror",
- "time 0.3.21",
-]
-
 [[package]]
 name = "xattr"
 version = "0.2.3"
@@ -14324,15 +13400,6 @@ version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
 
-[[package]]
-name = "yasna"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd"
-dependencies = [
- "time 0.3.21",
-]
-
 [[package]]
 name = "zeroize"
 version = "1.6.0"
diff --git a/substrate/client/authority-discovery/Cargo.toml b/substrate/client/authority-discovery/Cargo.toml
index 0324cac4669..2203b619b18 100644
--- a/substrate/client/authority-discovery/Cargo.toml
+++ b/substrate/client/authority-discovery/Cargo.toml
@@ -21,8 +21,8 @@ codec = { package = "parity-scale-codec", version = "3.6.1", default-features =
 futures = "0.3.21"
 futures-timer = "3.0.1"
 ip_network = "0.4.1"
-libp2p = { version = "0.51.3", features = ["kad", "ed25519"] }
-multihash = { version = "0.17.0", default-features = false, features = ["std", "sha2"] }
+libp2p = { version = "0.52.1", features = ["kad", "ed25519"] }
+multihash-codetable = { version = "0.1.0", features = ["sha2", "digest"] }
 log = "0.4.17"
 prost = "0.11"
 rand = "0.8.5"
diff --git a/substrate/client/authority-discovery/src/tests.rs b/substrate/client/authority-discovery/src/tests.rs
index 4fbc196c5ec..16700e35ca5 100644
--- a/substrate/client/authority-discovery/src/tests.rs
+++ b/substrate/client/authority-discovery/src/tests.rs
@@ -56,7 +56,7 @@ fn get_addresses_and_authority_id() {
 	let remote_addr = "/ip6/2001:db8:0:0:0:0:0:2/tcp/30333"
 		.parse::<Multiaddr>()
 		.unwrap()
-		.with(Protocol::P2p(remote_peer_id.into()));
+		.with(Protocol::P2p(remote_peer_id));
 
 	let test_api = Arc::new(TestApi { authorities: vec![] });
 
diff --git a/substrate/client/authority-discovery/src/worker.rs b/substrate/client/authority-discovery/src/worker.rs
index a29e74df9ac..2552646c125 100644
--- a/substrate/client/authority-discovery/src/worker.rs
+++ b/substrate/client/authority-discovery/src/worker.rs
@@ -34,8 +34,8 @@ use futures::{channel::mpsc, future, stream::Fuse, FutureExt, Stream, StreamExt}
 use addr_cache::AddrCache;
 use codec::{Decode, Encode};
 use ip_network::IpNetwork;
-use libp2p::{core::multiaddr, identity::PublicKey, multihash::Multihash, Multiaddr, PeerId};
-use multihash::{Code, MultihashDigest};
+use libp2p::{core::multiaddr, identity::PublicKey, Multiaddr};
+use multihash_codetable::{Code, MultihashDigest};
 
 use log::{debug, error, log_enabled};
 use prometheus_endpoint::{register, Counter, CounterVec, Gauge, Opts, U64};
@@ -304,7 +304,7 @@ where
 	}
 
 	fn addresses_to_publish(&self) -> impl Iterator<Item = Multiaddr> {
-		let peer_id: Multihash = self.network.local_peer_id().into();
+		let peer_id = self.network.local_peer_id();
 		let publish_non_global_ips = self.publish_non_global_ips;
 		self.network
 			.external_addresses()
@@ -529,7 +529,7 @@ where
 					.map_err(Error::ParsingMultiaddress)?;
 
 				let get_peer_id = |a: &Multiaddr| match a.iter().last() {
-					Some(multiaddr::Protocol::P2p(key)) => PeerId::from_multihash(key).ok(),
+					Some(multiaddr::Protocol::P2p(peer_id)) => Some(peer_id),
 					_ => None,
 				};
 
diff --git a/substrate/client/authority-discovery/src/worker/addr_cache.rs b/substrate/client/authority-discovery/src/worker/addr_cache.rs
index 8084b7f0a6d..ad7bf61d650 100644
--- a/substrate/client/authority-discovery/src/worker/addr_cache.rs
+++ b/substrate/client/authority-discovery/src/worker/addr_cache.rs
@@ -162,8 +162,8 @@ impl AddrCache {
 
 fn peer_id_from_multiaddr(addr: &Multiaddr) -> Option<PeerId> {
 	addr.iter().last().and_then(|protocol| {
-		if let Protocol::P2p(multihash) = protocol {
-			PeerId::from_multihash(multihash).ok()
+		if let Protocol::P2p(peer_id) = protocol {
+			Some(peer_id)
 		} else {
 			None
 		}
@@ -178,7 +178,8 @@ fn addresses_to_peer_ids(addresses: &HashSet<Multiaddr>) -> HashSet<PeerId> {
 mod tests {
 	use super::*;
 
-	use libp2p::multihash::{self, Multihash};
+	use libp2p::multihash::Multihash;
+	use multihash_codetable::Code;
 	use quickcheck::{Arbitrary, Gen, QuickCheck, TestResult};
 
 	use sp_authority_discovery::{AuthorityId, AuthorityPair};
@@ -200,14 +201,13 @@ mod tests {
 	impl Arbitrary for TestMultiaddr {
 		fn arbitrary(g: &mut Gen) -> Self {
 			let seed = (0..32).map(|_| u8::arbitrary(g)).collect::<Vec<_>>();
-			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::<Multiaddr>()
 				.unwrap()
-				.with(Protocol::P2p(peer_id.into()));
+				.with(Protocol::P2p(peer_id));
 
 			TestMultiaddr(multiaddr)
 		}
@@ -219,18 +219,17 @@ mod tests {
 	impl Arbitrary for TestMultiaddrsSamePeerCombo {
 		fn arbitrary(g: &mut Gen) -> Self {
 			let seed = (0..32).map(|_| u8::arbitrary(g)).collect::<Vec<_>>();
-			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::<Multiaddr>()
 				.unwrap()
-				.with(Protocol::P2p(peer_id.into()));
+				.with(Protocol::P2p(peer_id));
 			let multiaddr2 = "/ip6/2002:db8:0:0:0:0:0:2/tcp/30133"
 				.parse::<Multiaddr>()
 				.unwrap()
-				.with(Protocol::P2p(peer_id.into()));
+				.with(Protocol::P2p(peer_id));
 			TestMultiaddrsSamePeerCombo(multiaddr1, multiaddr2)
 		}
 	}
@@ -367,7 +366,7 @@ mod tests {
 		let mut addr_cache = AddrCache::new();
 
 		let peer_id = PeerId::random();
-		let addr = Multiaddr::empty().with(Protocol::P2p(peer_id.into()));
+		let addr = Multiaddr::empty().with(Protocol::P2p(peer_id));
 
 		let authority_id0 = AuthorityPair::generate().0.public();
 		let authority_id1 = AuthorityPair::generate().0.public();
diff --git a/substrate/client/authority-discovery/src/worker/tests.rs b/substrate/client/authority-discovery/src/worker/tests.rs
index c2912088194..791f013cfed 100644
--- a/substrate/client/authority-discovery/src/worker/tests.rs
+++ b/substrate/client/authority-discovery/src/worker/tests.rs
@@ -415,7 +415,7 @@ fn dont_stop_polling_dht_event_stream_after_bogus_event() {
 		let peer_id = PeerId::random();
 		let address: Multiaddr = "/ip6/2001:db8:0:0:0:0:0:1/tcp/30333".parse().unwrap();
 
-		address.with(multiaddr::Protocol::P2p(peer_id.into()))
+		address.with(multiaddr::Protocol::P2p(peer_id))
 	};
 	let remote_key_store = MemoryKeystore::new();
 	let remote_public_key: AuthorityId = remote_key_store
@@ -526,7 +526,7 @@ impl DhtValueFoundTester {
 		let address: Multiaddr =
 			format!("/ip6/2001:db8:0:0:0:0:0:{:x}/tcp/30333", idx).parse().unwrap();
 
-		address.with(multiaddr::Protocol::P2p(peer_id.into()))
+		address.with(multiaddr::Protocol::P2p(peer_id))
 	}
 
 	fn process_value_found(
@@ -749,7 +749,7 @@ fn lookup_throttling() {
 		let peer_id = PeerId::random();
 		let address: Multiaddr = "/ip6/2001:db8:0:0:0:0:0:1/tcp/30333".parse().unwrap();
 
-		address.with(multiaddr::Protocol::P2p(peer_id.into()))
+		address.with(multiaddr::Protocol::P2p(peer_id))
 	};
 	let remote_key_store = MemoryKeystore::new();
 	let remote_public_keys: Vec<AuthorityId> = (0..20)
diff --git a/substrate/client/cli/Cargo.toml b/substrate/client/cli/Cargo.toml
index 61750766fa3..eab0df3487e 100644
--- a/substrate/client/cli/Cargo.toml
+++ b/substrate/client/cli/Cargo.toml
@@ -18,7 +18,7 @@ chrono = "0.4.10"
 clap = { version = "4.2.5", features = ["derive", "string"] }
 fdlimit = "0.2.1"
 futures = "0.3.21"
-libp2p-identity = { version = "0.1.2", features = ["peerid", "ed25519"]}
+libp2p-identity = { version = "0.2.0", features = ["peerid", "ed25519"]}
 log = "0.4.17"
 names = { version = "0.13.0", default-features = false }
 parity-scale-codec = "3.6.1"
diff --git a/substrate/client/consensus/common/Cargo.toml b/substrate/client/consensus/common/Cargo.toml
index adb6f0920be..5a0e6776730 100644
--- a/substrate/client/consensus/common/Cargo.toml
+++ b/substrate/client/consensus/common/Cargo.toml
@@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 async-trait = "0.1.57"
 futures = { version = "0.3.21", features = ["thread-pool"] }
 futures-timer = "3.0.1"
-libp2p-identity = { version = "0.1.2", features = ["peerid", "ed25519"] }
+libp2p-identity = { version = "0.2.0", features = ["peerid", "ed25519"] }
 log = "0.4.17"
 mockall = "0.11.3"
 parking_lot = "0.12.1"
diff --git a/substrate/client/network-gossip/Cargo.toml b/substrate/client/network-gossip/Cargo.toml
index e25a769587d..e69020560e2 100644
--- a/substrate/client/network-gossip/Cargo.toml
+++ b/substrate/client/network-gossip/Cargo.toml
@@ -17,7 +17,8 @@ targets = ["x86_64-unknown-linux-gnu"]
 ahash = "0.8.2"
 futures = "0.3.21"
 futures-timer = "3.0.1"
-libp2p = "0.51.3"
+libp2p-identity = { version = "0.2.0", features = ["peerid", "ed25519"]}
+multiaddr = "0.18.0"
 log = "0.4.17"
 schnellru = "0.2.1"
 tracing = "0.1.29"
diff --git a/substrate/client/network-gossip/src/bridge.rs b/substrate/client/network-gossip/src/bridge.rs
index 2cd4e181715..f3ad7983482 100644
--- a/substrate/client/network-gossip/src/bridge.rs
+++ b/substrate/client/network-gossip/src/bridge.rs
@@ -28,7 +28,7 @@ use futures::{
 	channel::mpsc::{channel, Receiver, Sender},
 	prelude::*,
 };
-use libp2p::PeerId;
+use libp2p_identity::PeerId;
 use log::trace;
 use prometheus_endpoint::Registry;
 use sp_runtime::traits::Block as BlockT;
@@ -330,12 +330,13 @@ impl<B: BlockT> futures::future::FusedFuture for GossipEngine<B> {
 #[cfg(test)]
 mod tests {
 	use super::*;
-	use crate::{multiaddr::Multiaddr, ValidationResult, ValidatorContext};
+	use crate::{ValidationResult, ValidatorContext};
 	use futures::{
 		channel::mpsc::{unbounded, UnboundedSender},
 		executor::{block_on, block_on_stream},
 		future::poll_fn,
 	};
+	use multiaddr::Multiaddr;
 	use quickcheck::{Arbitrary, Gen, QuickCheck};
 	use sc_network::{
 		config::MultiaddrWithPeerId, NetworkBlock, NetworkEventStream, NetworkNotification,
diff --git a/substrate/client/network-gossip/src/lib.rs b/substrate/client/network-gossip/src/lib.rs
index ef87dd599e0..d126f85646e 100644
--- a/substrate/client/network-gossip/src/lib.rs
+++ b/substrate/client/network-gossip/src/lib.rs
@@ -67,7 +67,8 @@ pub use self::{
 	validator::{DiscardAll, MessageIntent, ValidationResult, Validator, ValidatorContext},
 };
 
-use libp2p::{multiaddr, PeerId};
+use libp2p_identity::PeerId;
+use multiaddr::{Multiaddr, Protocol};
 use sc_network::{
 	types::ProtocolName, NetworkBlock, NetworkEventStream, NetworkNotification, NetworkPeers,
 };
@@ -82,8 +83,7 @@ mod validator;
 /// Abstraction over a network.
 pub trait Network<B: BlockT>: NetworkPeers + NetworkEventStream + NetworkNotification {
 	fn add_set_reserved(&self, who: PeerId, protocol: ProtocolName) {
-		let addr =
-			iter::once(multiaddr::Protocol::P2p(who.into())).collect::<multiaddr::Multiaddr>();
+		let addr = Multiaddr::empty().with(Protocol::P2p(who));
 		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 f874a5c15b3..4b474baab76 100644
--- a/substrate/client/network-gossip/src/state_machine.rs
+++ b/substrate/client/network-gossip/src/state_machine.rs
@@ -19,7 +19,7 @@
 use crate::{MessageIntent, Network, ValidationResult, Validator, ValidatorContext};
 
 use ahash::AHashSet;
-use libp2p::PeerId;
+use libp2p_identity::PeerId;
 use schnellru::{ByLength, LruMap};
 
 use prometheus_endpoint::{register, Counter, PrometheusError, Registry, U64};
@@ -521,8 +521,8 @@ impl Metrics {
 #[cfg(test)]
 mod tests {
 	use super::*;
-	use crate::multiaddr::Multiaddr;
 	use futures::prelude::*;
+	use multiaddr::Multiaddr;
 	use sc_network::{
 		config::MultiaddrWithPeerId, event::Event, NetworkBlock, NetworkEventStream,
 		NetworkNotification, NetworkPeers, NotificationSenderError,
diff --git a/substrate/client/network-gossip/src/validator.rs b/substrate/client/network-gossip/src/validator.rs
index 2272efba506..04585bb7218 100644
--- a/substrate/client/network-gossip/src/validator.rs
+++ b/substrate/client/network-gossip/src/validator.rs
@@ -16,7 +16,7 @@
 // You should have received a copy of the GNU General Public License
 // along with this program. If not, see <https://www.gnu.org/licenses/>.
 
-use libp2p::PeerId;
+use libp2p_identity::PeerId;
 use sc_network_common::role::ObservedRole;
 use sp_runtime::traits::Block as BlockT;
 
diff --git a/substrate/client/network/Cargo.toml b/substrate/client/network/Cargo.toml
index 786aa68d808..e716978f409 100644
--- a/substrate/client/network/Cargo.toml
+++ b/substrate/client/network/Cargo.toml
@@ -25,7 +25,8 @@ fnv = "1.0.6"
 futures = "0.3.21"
 futures-timer = "3.0.2"
 ip_network = "0.4.1"
-libp2p = { version = "0.51.3", features = ["dns", "identify", "kad", "macros", "mdns", "noise", "ping", "tcp",  "tokio", "yamux", "websocket", "request-response"] }
+libp2p = { version = "0.52.1", features = ["dns", "identify", "kad", "macros", "mdns", "noise", "ping", "tcp", "tokio", "yamux", "websocket", "request-response"] }
+libp2p-kad = { version = "0.44.2" }
 linked_hash_set = "0.1.3"
 log = "0.4.17"
 mockall = "0.11.3"
@@ -35,9 +36,10 @@ pin-project = "1.0.12"
 rand = "0.8.5"
 serde = { version = "1.0.163", features = ["derive"] }
 serde_json = "1.0.85"
-smallvec = "1.8.0"
+smallvec = "1.11.0"
 thiserror = "1.0"
 unsigned-varint = { version = "0.7.1", features = ["futures", "asynchronous_codec"] }
+void = "1"
 zeroize = "1.4.3"
 prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.10.0-dev", path = "../../utils/prometheus" }
 sc-client-api = { version = "4.0.0-dev", path = "../api" }
@@ -52,7 +54,7 @@ wasm-timer = "0.2"
 [dev-dependencies]
 assert_matches = "1.3"
 mockall = "0.11.3"
-multistream-select = "0.12.1"
+multistream-select = "0.13.0"
 rand = "0.8.5"
 tempfile = "3.1.0"
 tokio = { version = "1.22.0", features = ["macros"] }
diff --git a/substrate/client/network/bitswap/Cargo.toml b/substrate/client/network/bitswap/Cargo.toml
index bdc9e18f745..ce9507638d8 100644
--- a/substrate/client/network/bitswap/Cargo.toml
+++ b/substrate/client/network/bitswap/Cargo.toml
@@ -19,7 +19,7 @@ prost-build = "0.11"
 async-channel = "1.8.0"
 cid = "0.9.0"
 futures = "0.3.21"
-libp2p-identity = { version = "0.1.2", features = ["peerid"] }
+libp2p-identity = { version = "0.2.0", features = ["peerid"] }
 log = "0.4.17"
 prost = "0.11"
 thiserror = "1.0"
diff --git a/substrate/client/network/common/Cargo.toml b/substrate/client/network/common/Cargo.toml
index c2fee608d79..b5045f45290 100644
--- a/substrate/client/network/common/Cargo.toml
+++ b/substrate/client/network/common/Cargo.toml
@@ -22,7 +22,7 @@ codec = { package = "parity-scale-codec", version = "3.6.1", features = [
 	"derive",
 ] }
 futures = "0.3.21"
-libp2p-identity = { version = "0.1.2", features = ["peerid"] }
+libp2p-identity = { version = "0.2.0", features = ["peerid"] }
 sc-consensus = { version = "0.10.0-dev", path = "../../consensus/common" }
 sp-consensus = { version = "0.10.0-dev", path = "../../../primitives/consensus/common" }
 sp-consensus-grandpa = { version = "4.0.0-dev", path = "../../../primitives/consensus/grandpa" }
diff --git a/substrate/client/network/light/Cargo.toml b/substrate/client/network/light/Cargo.toml
index 8bdb640d555..980e3d3545f 100644
--- a/substrate/client/network/light/Cargo.toml
+++ b/substrate/client/network/light/Cargo.toml
@@ -22,7 +22,7 @@ codec = { package = "parity-scale-codec", version = "3.6.1", features = [
     "derive",
 ] }
 futures = "0.3.21"
-libp2p-identity = { version = "0.1.2", features = ["peerid"] }
+libp2p-identity = { version = "0.2.0", features = ["peerid"] }
 log = "0.4.16"
 prost = "0.11"
 sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" }
diff --git a/substrate/client/network/src/behaviour.rs b/substrate/client/network/src/behaviour.rs
index a4c19c47c3a..4799807d2cb 100644
--- a/substrate/client/network/src/behaviour.rs
+++ b/substrate/client/network/src/behaviour.rs
@@ -30,8 +30,8 @@ use crate::{
 use bytes::Bytes;
 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,
 };
 
 use sc_network_common::role::{ObservedRole, Roles};
@@ -42,7 +42,7 @@ pub use crate::request_responses::{InboundFailure, OutboundFailure, RequestId, R
 
 /// General behaviour of the network. Combines all protocols together.
 #[derive(NetworkBehaviour)]
-#[behaviour(out_event = "BehaviourOut")]
+#[behaviour(to_swarm = "BehaviourOut")]
 pub struct Behaviour<B: BlockT> {
 	/// All the substrate-specific protocols.
 	substrate: Protocol<B>,
@@ -51,6 +51,8 @@ pub struct Behaviour<B: BlockT> {
 	peer_info: peer_info::PeerInfoBehaviour,
 	/// Discovers nodes of the network.
 	discovery: DiscoveryBehaviour,
+	/// Connection limits.
+	connection_limits: libp2p::connection_limits::Behaviour,
 	/// Generic request-response protocols.
 	request_responses: request_responses::RequestResponsesBehaviour,
 }
@@ -171,11 +173,13 @@ impl<B: BlockT> Behaviour<B> {
 		disco_config: DiscoveryConfig,
 		request_response_protocols: Vec<ProtocolConfig>,
 		peerset: PeersetHandle,
+		connection_limits: ConnectionLimits,
 	) -> Result<Self, request_responses::RegisterError> {
 		Ok(Self {
 			substrate,
 			peer_info: peer_info::PeerInfoBehaviour::new(user_agent, local_public_key),
 			discovery: disco_config.finish(),
+			connection_limits: libp2p::connection_limits::Behaviour::new(connection_limits),
 			request_responses: request_responses::RequestResponsesBehaviour::new(
 				request_response_protocols.into_iter(),
 				peerset,
@@ -247,7 +251,7 @@ impl<B: BlockT> Behaviour<B> {
 	pub fn add_self_reported_address_to_dht(
 		&mut self,
 		peer_id: &PeerId,
-		supported_protocols: &[impl AsRef<[u8]>],
+		supported_protocols: &[impl AsRef<str>],
 		addr: Multiaddr,
 	) {
 		self.discovery.add_self_reported_address(peer_id, supported_protocols, addr);
@@ -351,3 +355,9 @@ impl From<DiscoveryOut> for BehaviourOut {
 		}
 	}
 }
+
+impl From<void::Void> 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 4c1247f786f..e13b6ac0a37 100644
--- a/substrate/client/network/src/config.rs
+++ b/substrate/client/network/src/config.rs
@@ -109,8 +109,7 @@ 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)?,
+		Some(multiaddr::Protocol::P2p(peer_id)) => peer_id,
 		_ => return Err(ParseErr::PeerIdMissing),
 	};
 
@@ -143,7 +142,7 @@ pub struct MultiaddrWithPeerId {
 impl MultiaddrWithPeerId {
 	/// Concatenates the multiaddress and peer ID into one multiaddress containing both.
 	pub fn concat(&self) -> Multiaddr {
-		let proto = multiaddr::Protocol::P2p(From::from(self.peer_id));
+		let proto = multiaddr::Protocol::P2p(self.peer_id);
 		self.multiaddr.clone().with(proto)
 	}
 }
@@ -181,8 +180,6 @@ impl TryFrom<String> for MultiaddrWithPeerId {
 pub enum ParseErr {
 	/// Error while parsing the multiaddress.
 	MultiaddrParse(multiaddr::Error),
-	/// Multihash of the peer ID is invalid.
-	InvalidPeerId,
 	/// The peer ID is missing from the address.
 	PeerIdMissing,
 }
@@ -191,7 +188,6 @@ impl fmt::Display for ParseErr {
 	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 		match self {
 			Self::MultiaddrParse(err) => write!(f, "{}", err),
-			Self::InvalidPeerId => write!(f, "Peer id at the end of the address is invalid"),
 			Self::PeerIdMissing => write!(f, "Peer id is missing from the address"),
 		}
 	}
@@ -201,7 +197,6 @@ impl std::error::Error for ParseErr {
 	fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
 		match self {
 			Self::MultiaddrParse(err) => Some(err),
-			Self::InvalidPeerId => None,
 			Self::PeerIdMissing => None,
 		}
 	}
diff --git a/substrate/client/network/src/discovery.rs b/substrate/client/network/src/discovery.rs
index d9fad538443..77224c3a0fd 100644
--- a/substrate/client/network/src/discovery.rs
+++ b/substrate/client/network/src/discovery.rs
@@ -55,7 +55,6 @@ use ip_network::IpNetwork;
 use libp2p::{
 	core::{Endpoint, Multiaddr},
 	kad::{
-		handler::KademliaHandler,
 		record::store::{MemoryStore, RecordStore},
 		GetClosestPeersError, GetRecordOk, Kademlia, KademliaBucketInserts, KademliaConfig,
 		KademliaEvent, QueryId, QueryResult, Quorum, Record, RecordKey,
@@ -65,10 +64,10 @@ use libp2p::{
 	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,
 };
@@ -104,7 +103,7 @@ pub struct DiscoveryConfig {
 	discovery_only_if_under_num: u64,
 	enable_mdns: bool,
 	kademlia_disjoint_query_paths: bool,
-	kademlia_protocols: Vec<Vec<u8>>,
+	kademlia_protocols: Vec<StreamProtocol>,
 	kademlia_replication_factor: NonZeroUsize,
 }
 
@@ -353,7 +352,7 @@ impl DiscoveryBehaviour {
 	pub fn add_self_reported_address(
 		&mut self,
 		peer_id: &PeerId,
-		supported_protocols: &[impl AsRef<[u8]>],
+		supported_protocols: &[impl AsRef<str>],
 		addr: Multiaddr,
 	) {
 		if let Some(kademlia) = self.kademlia.as_mut() {
@@ -372,7 +371,7 @@ impl DiscoveryBehaviour {
 				trace!(
 					target: "sub-libp2p",
 					"Adding self-reported address {} from {} to Kademlia DHT {}.",
-					addr, peer_id, String::from_utf8_lossy(matching_protocol.as_ref()),
+					addr, peer_id, matching_protocol.as_ref(),
 				);
 				kademlia.add_address(peer_id, addr.clone());
 			} else {
@@ -498,8 +497,9 @@ pub enum DiscoveryOut {
 }
 
 impl NetworkBehaviour for DiscoveryBehaviour {
-	type ConnectionHandler = ToggleConnectionHandler<KademliaHandler<QueryId>>;
-	type OutEvent = DiscoveryOut;
+	type ConnectionHandler =
+		ToggleConnectionHandler<<Kademlia<MemoryStore> as NetworkBehaviour>::ConnectionHandler>;
+	type ToSwarm = DiscoveryOut;
 
 	fn handle_established_inbound_connection(
 		&mut self,
@@ -629,11 +629,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));
@@ -641,8 +641,21 @@ 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));
+
+				if let Some(ref mut mdns) = self.mdns {
+					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
@@ -656,17 +669,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));
-
-				if let Some(ref mut mdns) = self.mdns {
-					mdns.on_swarm_event(FromSwarm::NewListenAddr(e));
-				}
+				self.kademlia.on_swarm_event(FromSwarm::ExternalAddrConfirmed(e));
 			},
 		}
 	}
@@ -684,7 +687,7 @@ impl NetworkBehaviour for DiscoveryBehaviour {
 		&mut self,
 		cx: &mut Context,
 		params: &mut impl PollParameters,
-	) -> Poll<ToSwarm<Self::OutEvent, THandlerInEvent<Self>>> {
+	) -> Poll<ToSwarm<Self::ToSwarm, THandlerInEvent<Self>>> {
 		// Immediately process the content of `discovered`.
 		if let Some(ev) = self.pending_events.pop_front() {
 			return Poll::Ready(ToSwarm::GenerateEvent(ev))
@@ -895,10 +898,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 }),
 			}
 		}
 
@@ -912,8 +922,10 @@ 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))
 							}
@@ -926,10 +938,17 @@ impl NetworkBehaviour for DiscoveryBehaviour {
 					ToSwarm::NotifyHandler { event, .. } => match event {}, /* `event` is an */
 					// enum with no
 					// variant
-					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 }),
 				}
 			}
 		}
@@ -939,21 +958,23 @@ impl NetworkBehaviour for DiscoveryBehaviour {
 }
 
 /// Legacy (fallback) Kademlia protocol name based on `protocol_id`.
-fn legacy_kademlia_protocol_name(id: &ProtocolId) -> Vec<u8> {
-	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<Hash: AsRef<[u8]>>(genesis_hash: Hash, fork_id: Option<&str>) -> Vec<u8> {
+fn kademlia_protocol_name<Hash: AsRef<[u8]>>(
+	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!("/{}/{}/kad", genesis_hash_hex, fork_id)
 	} else {
-		format!("/{}/kad", genesis_hash_hex).as_bytes().into()
-	}
+		format!("/{}/kad", genesis_hash_hex)
+	};
+	StreamProtocol::try_from_owned(name).expect("protocol name is valid. qed")
 }
 
 #[cfg(test)]
@@ -969,7 +990,7 @@ mod tests {
 			upgrade,
 		},
 		identity::Keypair,
-		noise,
+		kad, noise,
 		swarm::{Executor, Swarm, SwarmBuilder, SwarmEvent},
 		yamux, Multiaddr,
 	};
@@ -1023,6 +1044,18 @@ mod tests {
 					TokioExecutor(runtime),
 				)
 				.build();
+
+				// Set the Kademlia mode to server so that it can accept incoming requests.
+				//
+				// Note: the server mode is set automatically when the node learns its external
+				// address, but that does not happen in tests => hence we set it manually.
+				swarm
+					.behaviour_mut()
+					.kademlia
+					.as_mut()
+					.unwrap()
+					.set_mode(Some(kad::Mode::Server));
+
 				let listen_addr: Multiaddr =
 					format!("/memory/{}", rand::random::<u64>()).parse().unwrap();
 
@@ -1083,7 +1116,7 @@ mod tests {
 												.add_self_reported_address(
 													&other,
 													&[protocol_name],
-													addr,
+													addr.clone(),
 												);
 
 											to_discover[swarm_n].remove(&other);
diff --git a/substrate/client/network/src/peer_info.rs b/substrate/client/network/src/peer_info.rs
index aab3fc9487e..d7f9e6858fa 100644
--- a/substrate/client/network/src/peer_info.rs
+++ b/substrate/client/network/src/peer_info.rs
@@ -31,13 +31,13 @@ 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,
 		},
-		ConnectionDenied, ConnectionHandler, ConnectionId, IntoConnectionHandlerSelect,
+		ConnectionDenied, ConnectionHandler, ConnectionHandlerSelect, ConnectionId,
 		NetworkBehaviour, PollParameters, THandler, THandlerInEvent, THandlerOutEvent, ToSwarm,
 	},
 	Multiaddr, PeerId,
@@ -121,13 +121,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);
 		}
 	}
 
@@ -181,11 +186,11 @@ pub enum PeerInfoEvent {
 }
 
 impl NetworkBehaviour for PeerInfoBehaviour {
-	type ConnectionHandler = IntoConnectionHandlerSelect<
+	type ConnectionHandler = ConnectionHandlerSelect<
 		<Ping as NetworkBehaviour>::ConnectionHandler,
 		<Identify as NetworkBehaviour>::ConnectionHandler,
 	>;
-	type OutEvent = PeerInfoEvent;
+	type ToSwarm = PeerInfoEvent;
 
 	fn handle_pending_inbound_connection(
 		&mut self,
@@ -351,9 +356,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));
@@ -363,9 +368,13 @@ impl NetworkBehaviour for PeerInfoBehaviour {
 				self.ping.on_swarm_event(FromSwarm::ExpiredListenAddr(e));
 				self.identify.on_swarm_event(FromSwarm::ExpiredListenAddr(e));
 			},
-			FromSwarm::NewExternalAddr(e) => {
-				self.ping.on_swarm_event(FromSwarm::NewExternalAddr(e));
-				self.identify.on_swarm_event(FromSwarm::NewExternalAddr(e));
+			FromSwarm::NewExternalAddrCandidate(e) => {
+				self.ping.on_swarm_event(FromSwarm::NewExternalAddrCandidate(e));
+				self.identify.on_swarm_event(FromSwarm::NewExternalAddrCandidate(e));
+			},
+			FromSwarm::ExternalAddrConfirmed(e) => {
+				self.ping.on_swarm_event(FromSwarm::ExternalAddrConfirmed(e));
+				self.identify.on_swarm_event(FromSwarm::ExternalAddrConfirmed(e));
 			},
 			FromSwarm::AddressChange(e @ AddressChange { peer_id, old, new, .. }) => {
 				self.ping.on_swarm_event(FromSwarm::AddressChange(e));
@@ -408,13 +417,13 @@ impl NetworkBehaviour for PeerInfoBehaviour {
 		&mut self,
 		cx: &mut Context,
 		params: &mut impl PollParameters,
-	) -> Poll<ToSwarm<Self::OutEvent, THandlerInEvent<Self>>> {
+	) -> Poll<ToSwarm<Self::ToSwarm, THandlerInEvent<Self>>> {
 		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 }),
@@ -424,10 +433,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 }),
 			}
 		}
 
@@ -453,10 +470,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 0e444c2d330..2c41eeccd58 100644
--- a/substrate/client/network/src/protocol.rs
+++ b/substrate/client/network/src/protocol.rs
@@ -353,7 +353,7 @@ pub enum CustomMessageOutcome {
 
 impl<B: BlockT> NetworkBehaviour for Protocol<B> {
 	type ConnectionHandler = <Notifications as NetworkBehaviour>::ConnectionHandler;
-	type OutEvent = CustomMessageOutcome;
+	type ToSwarm = CustomMessageOutcome;
 
 	fn handle_established_inbound_connection(
 		&mut self,
@@ -414,7 +414,7 @@ impl<B: BlockT> NetworkBehaviour for Protocol<B> {
 		&mut self,
 		cx: &mut std::task::Context,
 		params: &mut impl PollParameters,
-	) -> Poll<ToSwarm<Self::OutEvent, THandlerInEvent<Self>>> {
+	) -> Poll<ToSwarm<Self::ToSwarm, THandlerInEvent<Self>>> {
 		while let Poll::Ready(Some(validation_result)) =
 			self.sync_substream_validations.poll_next_unpin(cx)
 		{
@@ -438,10 +438,18 @@ impl<B: BlockT> NetworkBehaviour for Protocol<B> {
 			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 dd0971aef50..2037af41702 100644
--- a/substrate/client/network/src/protocol/notifications/behaviour.rs
+++ b/substrate/client/network/src/protocol/notifications/behaviour.rs
@@ -999,7 +999,7 @@ impl Notifications {
 
 impl NetworkBehaviour for Notifications {
 	type ConnectionHandler = NotifsHandler;
-	type OutEvent = NotificationsOut;
+	type ToSwarm = NotificationsOut;
 
 	fn handle_pending_inbound_connection(
 		&mut self,
@@ -1468,10 +1468,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(_) => {},
 		}
@@ -2008,7 +2009,7 @@ impl NetworkBehaviour for Notifications {
 		&mut self,
 		cx: &mut Context,
 		_params: &mut impl PollParameters,
-	) -> Poll<ToSwarm<Self::OutEvent, THandlerInEvent<Self>>> {
+	) -> Poll<ToSwarm<Self::ToSwarm, THandlerInEvent<Self>>> {
 		if let Some(event) = self.events.pop_front() {
 			return Poll::Ready(event)
 		}
@@ -2108,7 +2109,6 @@ impl NetworkBehaviour for Notifications {
 mod tests {
 	use super::*;
 	use crate::{peerset::IncomingIndex, protocol::notifications::handler::tests::*};
-	use libp2p::swarm::AddressRecord;
 	use std::{collections::HashSet, iter};
 
 	impl PartialEq for ConnectionState {
@@ -2127,31 +2127,14 @@ mod tests {
 	}
 
 	#[derive(Clone)]
-	struct MockPollParams {
-		peer_id: PeerId,
-		addr: Multiaddr,
-	}
+	struct MockPollParams {}
 
 	impl PollParameters for MockPollParams {
 		type SupportedProtocolsIter = std::vec::IntoIter<Vec<u8>>;
-		type ListenedAddressesIter = std::vec::IntoIter<Multiaddr>;
-		type ExternalAddressesIter = std::vec::IntoIter<AddressRecord>;
 
 		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() -> (Notifications, crate::peerset::PeersetHandle) {
@@ -3015,7 +2998,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),
 		}));
 
@@ -3552,7 +3535,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),
 		}));
 
@@ -3672,7 +3655,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| {
@@ -3781,7 +3764,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 cffdec7d71e..3cec85f815c 100644
--- a/substrate/client/network/src/protocol/notifications/handler.rs
+++ b/substrate/client/network/src/protocol/notifications/handler.rs
@@ -74,8 +74,8 @@ use futures::{
 use libp2p::{
 	core::ConnectedPoint,
 	swarm::{
-		handler::ConnectionEvent, ConnectionHandler, ConnectionHandlerEvent, KeepAlive,
-		NegotiatedSubstream, SubstreamProtocol,
+		handler::ConnectionEvent, ConnectionHandler, ConnectionHandlerEvent, KeepAlive, Stream,
+		SubstreamProtocol,
 	},
 	PeerId,
 };
@@ -189,7 +189,7 @@ enum State {
 	/// emitted.
 	OpenDesiredByRemote {
 		/// Substream opened by the remote and that hasn't been accepted/rejected yet.
-		in_substream: NotificationsInSubstream<NegotiatedSubstream>,
+		in_substream: NotificationsInSubstream<Stream>,
 
 		/// See [`State::Closed::pending_opening`].
 		pending_opening: bool,
@@ -202,7 +202,7 @@ enum State {
 	/// be emitted when transitionning to respectively [`State::Open`] or [`State::Closed`].
 	Opening {
 		/// Substream opened by the remote. If `Some`, has been accepted.
-		in_substream: Option<NotificationsInSubstream<NegotiatedSubstream>>,
+		in_substream: Option<NotificationsInSubstream<Stream>>,
 		/// Is the connection inbound.
 		inbound: bool,
 	},
@@ -226,14 +226,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<NotificationsOutSubstream<NegotiatedSubstream>>,
+		out_substream: Option<NotificationsOutSubstream<Stream>>,
 
 		/// 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<NotificationsInSubstream<NegotiatedSubstream>>,
+		in_substream: Option<NotificationsInSubstream<Stream>>,
 	},
 }
 
@@ -439,8 +439,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<NotificationsIn>;
 	type OutboundProtocol = NotificationsOut;
@@ -475,7 +475,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 },
 						));
 
@@ -540,7 +540,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,
@@ -554,6 +554,8 @@ impl ConnectionHandler for NotifsHandler {
 				}
 			},
 			ConnectionEvent::AddressChange(_address_change) => {},
+			ConnectionEvent::LocalProtocolsChange(_protocols_change) => {},
+			ConnectionEvent::RemoteProtocolsChange(_protocols_change) => {},
 			ConnectionEvent::DialUpgradeError(dial_upgrade_error) => match self.protocols
 				[dial_upgrade_error.info]
 				.state
@@ -568,7 +570,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 },
 					));
 				},
@@ -655,7 +657,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 },
 						));
 					},
@@ -665,7 +667,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 },
 				));
 			},
@@ -690,7 +692,7 @@ impl ConnectionHandler for NotifsHandler {
 		ConnectionHandlerEvent<
 			Self::OutboundProtocol,
 			Self::OutboundOpenInfo,
-			Self::OutEvent,
+			Self::ToBehaviour,
 			Self::Error,
 		>,
 	> {
@@ -759,7 +761,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))
 						},
 					};
 				},
@@ -781,11 +783,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::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,
 					},
@@ -797,7 +802,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 },
 							))
 						},
@@ -825,22 +830,18 @@ impl ConnectionHandler for NotifsHandler {
 #[cfg(test)]
 pub mod tests {
 	use super::*;
-	use crate::protocol::notifications::upgrade::{
-		NotificationsInOpen, NotificationsInSubstreamHandshake, NotificationsOutOpen,
-	};
-	use asynchronous_codec::Framed;
-	use libp2p::{
-		core::muxing::SubstreamBox,
-		swarm::{handler, ConnectionHandlerUpgrErr},
-		Multiaddr,
-	};
-	use multistream_select::{dialer_select_proto, listener_select_proto, Negotiated, Version};
+	// use crate::protocol::notifications::upgrade::{
+	// 	NotificationsInOpen, NotificationsInSubstreamHandshake, NotificationsOutOpen,
+	// };
+	// use asynchronous_codec::Framed;
+	// use libp2p::Multiaddr;
+	// use multistream_select::{dialer_select_proto, listener_select_proto, Negotiated, Version};
 	use std::{
 		collections::HashMap,
 		io::{Error, IoSlice, IoSliceMut},
 	};
 	use tokio::sync::mpsc;
-	use unsigned_varint::codec::UviBytes;
+	// use unsigned_varint::codec::UviBytes;
 
 	struct OpenSubstream {
 		notifications: stream::Peekable<
@@ -940,20 +941,20 @@ pub mod tests {
 			)
 		}
 
-		/// Create new negotiated substream pair.
-		pub async fn negotiated() -> (Negotiated<SubstreamBox>, Negotiated<SubstreamBox>) {
-			let (socket1, socket2) = Self::new();
-			let socket1 = SubstreamBox::new(socket1);
-			let socket2 = SubstreamBox::new(socket2);
+		// /// Create new negotiated substream pair.
+		// pub async fn negotiated() -> (Negotiated<SubstreamBox>, Negotiated<SubstreamBox>) {
+		// 	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 (res1, res2) = tokio::join!(
-				dialer_select_proto(socket1, protos.clone(), Version::V1),
-				listener_select_proto(socket2, protos),
-			);
+		// 	let protos = vec![b"/echo/1.0.0", b"/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)
-		}
+		// 	(res1.unwrap().1, res2.unwrap().1)
+		// }
 	}
 
 	impl AsyncWrite for MockSubstream {
@@ -1018,596 +1019,596 @@ pub mod tests {
 		}
 	}
 
-	/// Create new [`NotifsHandler`].
-	fn notifs_handler() -> NotifsHandler {
-		let proto = Protocol {
-			config: ProtocolConfig {
-				name: "/foo".into(),
-				fallback_names: vec![],
-				handshake: Arc::new(RwLock::new(b"hello, world".to_vec())),
-				max_notification_size: u64::MAX,
-			},
-			in_upgrade: NotificationsIn::new("/foo", Vec::new(), u64::MAX),
-			state: State::Closed { pending_opening: false },
-		};
-
-		NotifsHandler {
-			protocols: vec![proto],
-			when_connection_open: Instant::now(),
-			endpoint: ConnectedPoint::Listener {
-				local_addr: Multiaddr::empty(),
-				send_back_addr: Multiaddr::empty(),
-			},
-			peer_id: PeerId::random(),
-			events_queue: VecDeque::new(),
-		}
-	}
-
-	// verify that if another substream is attempted to be opened by remote while an inbound
-	// substream already exists, the new inbound stream is rejected and closed by the local node.
-	#[tokio::test]
-	async fn second_open_desired_by_remote_rejected() {
-		let mut handler = notifs_handler();
-		let (io, mut io2) = MockSubstream::negotiated().await;
-		let mut codec = UviBytes::default();
-		codec.set_max_len(usize::MAX);
-
-		let notif_in = NotificationsInOpen {
-			handshake: b"hello, world".to_vec(),
-			negotiated_fallback: None,
-			substream: NotificationsInSubstream::new(
-				Framed::new(io, codec),
-				NotificationsInSubstreamHandshake::NotSent,
-			),
-		};
-
-		handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedInbound(
-			handler::FullyNegotiatedInbound { protocol: (notif_in, 0), info: () },
-		));
-
-		// verify that the substream is in (partly) opened state
-		assert!(std::matches!(handler.protocols[0].state, State::OpenDesiredByRemote { .. }));
-		futures::future::poll_fn(|cx| {
-			let mut buf = Vec::with_capacity(512);
-			assert!(std::matches!(Pin::new(&mut io2).poll_read(cx, &mut buf), Poll::Pending));
-			Poll::Ready(())
-		})
-		.await;
-
-		// attempt to open another inbound substream and verify that it is rejected
-		let (io, mut io2) = MockSubstream::negotiated().await;
-		let mut codec = UviBytes::default();
-		codec.set_max_len(usize::MAX);
-
-		let notif_in = NotificationsInOpen {
-			handshake: b"hello, world".to_vec(),
-			negotiated_fallback: None,
-			substream: NotificationsInSubstream::new(
-				Framed::new(io, codec),
-				NotificationsInSubstreamHandshake::NotSent,
-			),
-		};
-
-		handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedInbound(
-			handler::FullyNegotiatedInbound { protocol: (notif_in, 0), info: () },
-		));
-
-		// verify that the new substream is rejected and closed
-		futures::future::poll_fn(|cx| {
-			let mut buf = Vec::with_capacity(512);
-
-			if let Poll::Ready(Err(err)) = Pin::new(&mut io2).poll_read(cx, &mut buf) {
-				assert_eq!(err.kind(), std::io::ErrorKind::UnexpectedEof,);
-			}
-
-			Poll::Ready(())
-		})
-		.await;
-	}
-
-	#[tokio::test]
-	async fn open_rejected_if_substream_is_opening() {
-		let mut handler = notifs_handler();
-		let (io, mut io2) = MockSubstream::negotiated().await;
-		let mut codec = UviBytes::default();
-		codec.set_max_len(usize::MAX);
-
-		let notif_in = NotificationsInOpen {
-			handshake: b"hello, world".to_vec(),
-			negotiated_fallback: None,
-			substream: NotificationsInSubstream::new(
-				Framed::new(io, codec),
-				NotificationsInSubstreamHandshake::NotSent,
-			),
-		};
-
-		handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedInbound(
-			handler::FullyNegotiatedInbound { protocol: (notif_in, 0), info: () },
-		));
-
-		// verify that the substream is in (partly) opened state
-		assert!(std::matches!(handler.protocols[0].state, State::OpenDesiredByRemote { .. }));
-		futures::future::poll_fn(|cx| {
-			let mut buf = Vec::with_capacity(512);
-			assert!(std::matches!(Pin::new(&mut io2).poll_read(cx, &mut buf), Poll::Pending));
-			Poll::Ready(())
-		})
-		.await;
-
-		// move the handler state to 'Opening'
-		handler.on_behaviour_event(NotifsHandlerIn::Open { protocol_index: 0 });
-		assert!(std::matches!(
-			handler.protocols[0].state,
-			State::Opening { in_substream: Some(_), .. }
-		));
-
-		// remote now tries to open another substream, verify that it is rejected and closed
-		let (io, mut io2) = MockSubstream::negotiated().await;
-		let mut codec = UviBytes::default();
-		codec.set_max_len(usize::MAX);
-
-		let notif_in = NotificationsInOpen {
-			handshake: b"hello, world".to_vec(),
-			negotiated_fallback: None,
-			substream: NotificationsInSubstream::new(
-				Framed::new(io, codec),
-				NotificationsInSubstreamHandshake::NotSent,
-			),
-		};
-
-		handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedInbound(
-			handler::FullyNegotiatedInbound { protocol: (notif_in, 0), info: () },
-		));
-
-		// verify that the new substream is rejected and closed but that the first substream is
-		// still in correct state
-		futures::future::poll_fn(|cx| {
-			let mut buf = Vec::with_capacity(512);
-
-			if let Poll::Ready(Err(err)) = Pin::new(&mut io2).poll_read(cx, &mut buf) {
-				assert_eq!(err.kind(), std::io::ErrorKind::UnexpectedEof,);
-			} else {
-				panic!("unexpected result");
-			}
-
-			Poll::Ready(())
-		})
-		.await;
-		assert!(std::matches!(
-			handler.protocols[0].state,
-			State::Opening { in_substream: Some(_), .. }
-		));
-	}
-
-	#[tokio::test]
-	async fn open_rejected_if_substream_already_open() {
-		let mut handler = notifs_handler();
-		let (io, mut io2) = MockSubstream::negotiated().await;
-		let mut codec = UviBytes::default();
-		codec.set_max_len(usize::MAX);
-
-		let notif_in = NotificationsInOpen {
-			handshake: b"hello, world".to_vec(),
-			negotiated_fallback: None,
-			substream: NotificationsInSubstream::new(
-				Framed::new(io, codec),
-				NotificationsInSubstreamHandshake::NotSent,
-			),
-		};
-		handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedInbound(
-			handler::FullyNegotiatedInbound { protocol: (notif_in, 0), info: () },
-		));
-
-		// verify that the substream is in (partly) opened state
-		assert!(std::matches!(handler.protocols[0].state, State::OpenDesiredByRemote { .. }));
-		futures::future::poll_fn(|cx| {
-			let mut buf = Vec::with_capacity(512);
-			assert!(std::matches!(Pin::new(&mut io2).poll_read(cx, &mut buf), Poll::Pending));
-			Poll::Ready(())
-		})
-		.await;
-
-		// move the handler state to 'Opening'
-		handler.on_behaviour_event(NotifsHandlerIn::Open { protocol_index: 0 });
-		assert!(std::matches!(
-			handler.protocols[0].state,
-			State::Opening { in_substream: Some(_), .. }
-		));
-
-		// accept the substream and move its state to `Open`
-		let (io, _io2) = MockSubstream::negotiated().await;
-		let mut codec = UviBytes::default();
-		codec.set_max_len(usize::MAX);
-
-		let notif_out = NotificationsOutOpen {
-			handshake: b"hello, world".to_vec(),
-			negotiated_fallback: None,
-			substream: NotificationsOutSubstream::new(Framed::new(io, codec)),
-		};
-		handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedOutbound(
-			handler::FullyNegotiatedOutbound { protocol: notif_out, info: 0 },
-		));
-
-		assert!(std::matches!(
-			handler.protocols[0].state,
-			State::Open { in_substream: Some(_), .. }
-		));
-
-		// remote now tries to open another substream, verify that it is rejected and closed
-		let (io, mut io2) = MockSubstream::negotiated().await;
-		let mut codec = UviBytes::default();
-		codec.set_max_len(usize::MAX);
-		let notif_in = NotificationsInOpen {
-			handshake: b"hello, world".to_vec(),
-			negotiated_fallback: None,
-			substream: NotificationsInSubstream::new(
-				Framed::new(io, codec),
-				NotificationsInSubstreamHandshake::NotSent,
-			),
-		};
-		handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedInbound(
-			handler::FullyNegotiatedInbound { protocol: (notif_in, 0), info: () },
-		));
-
-		// verify that the new substream is rejected and closed but that the first substream is
-		// still in correct state
-		futures::future::poll_fn(|cx| {
-			let mut buf = Vec::with_capacity(512);
-
-			if let Poll::Ready(Err(err)) = Pin::new(&mut io2).poll_read(cx, &mut buf) {
-				assert_eq!(err.kind(), std::io::ErrorKind::UnexpectedEof);
-			} else {
-				panic!("unexpected result");
-			}
-
-			Poll::Ready(())
-		})
-		.await;
-		assert!(std::matches!(
-			handler.protocols[0].state,
-			State::Open { in_substream: Some(_), .. }
-		));
-	}
-
-	#[tokio::test]
-	async fn fully_negotiated_resets_state_for_closed_substream() {
-		let mut handler = notifs_handler();
-		let (io, mut io2) = MockSubstream::negotiated().await;
-		let mut codec = UviBytes::default();
-		codec.set_max_len(usize::MAX);
-
-		let notif_in = NotificationsInOpen {
-			handshake: b"hello, world".to_vec(),
-			negotiated_fallback: None,
-			substream: NotificationsInSubstream::new(
-				Framed::new(io, codec),
-				NotificationsInSubstreamHandshake::NotSent,
-			),
-		};
-		handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedInbound(
-			handler::FullyNegotiatedInbound { protocol: (notif_in, 0), info: () },
-		));
-
-		// verify that the substream is in (partly) opened state
-		assert!(std::matches!(handler.protocols[0].state, State::OpenDesiredByRemote { .. }));
-		futures::future::poll_fn(|cx| {
-			let mut buf = Vec::with_capacity(512);
-			assert!(std::matches!(Pin::new(&mut io2).poll_read(cx, &mut buf), Poll::Pending));
-			Poll::Ready(())
-		})
-		.await;
-
-		// first instruct the handler to open a connection and then close it right after
-		// so the handler is in state `Closed { pending_opening: true }`
-		handler.on_behaviour_event(NotifsHandlerIn::Open { protocol_index: 0 });
-		assert!(std::matches!(
-			handler.protocols[0].state,
-			State::Opening { in_substream: Some(_), .. }
-		));
-
-		handler.on_behaviour_event(NotifsHandlerIn::Close { protocol_index: 0 });
-		assert!(std::matches!(handler.protocols[0].state, State::Closed { pending_opening: true }));
-
-		// verify that if the the outbound substream is successfully negotiated, the state is not
-		// changed as the substream was commanded to be closed by the handler.
-		let (io, _io2) = MockSubstream::negotiated().await;
-		let mut codec = UviBytes::default();
-		codec.set_max_len(usize::MAX);
-
-		let notif_out = NotificationsOutOpen {
-			handshake: b"hello, world".to_vec(),
-			negotiated_fallback: None,
-			substream: NotificationsOutSubstream::new(Framed::new(io, codec)),
-		};
-		handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedOutbound(
-			handler::FullyNegotiatedOutbound { protocol: notif_out, info: 0 },
-		));
-
-		assert!(std::matches!(
-			handler.protocols[0].state,
-			State::Closed { pending_opening: false }
-		));
-	}
-
-	#[tokio::test]
-	async fn fully_negotiated_resets_state_for_open_desired_substream() {
-		let mut handler = notifs_handler();
-		let (io, mut io2) = MockSubstream::negotiated().await;
-		let mut codec = UviBytes::default();
-		codec.set_max_len(usize::MAX);
-
-		let notif_in = NotificationsInOpen {
-			handshake: b"hello, world".to_vec(),
-			negotiated_fallback: None,
-			substream: NotificationsInSubstream::new(
-				Framed::new(io, codec),
-				NotificationsInSubstreamHandshake::NotSent,
-			),
-		};
-		handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedInbound(
-			handler::FullyNegotiatedInbound { protocol: (notif_in, 0), info: () },
-		));
-
-		// verify that the substream is in (partly) opened state
-		assert!(std::matches!(handler.protocols[0].state, State::OpenDesiredByRemote { .. }));
-		futures::future::poll_fn(|cx| {
-			let mut buf = Vec::with_capacity(512);
-			assert!(std::matches!(Pin::new(&mut io2).poll_read(cx, &mut buf), Poll::Pending));
-			Poll::Ready(())
-		})
-		.await;
-
-		// first instruct the handler to open a connection and then close it right after
-		// so the handler is in state `Closed { pending_opening: true }`
-		handler.on_behaviour_event(NotifsHandlerIn::Open { protocol_index: 0 });
-		assert!(std::matches!(
-			handler.protocols[0].state,
-			State::Opening { in_substream: Some(_), .. }
-		));
-
-		handler.on_behaviour_event(NotifsHandlerIn::Close { protocol_index: 0 });
-		assert!(std::matches!(handler.protocols[0].state, State::Closed { pending_opening: true }));
-
-		// attempt to open another inbound substream and verify that it is rejected
-		let (io, _io2) = MockSubstream::negotiated().await;
-		let mut codec = UviBytes::default();
-		codec.set_max_len(usize::MAX);
-
-		let notif_in = NotificationsInOpen {
-			handshake: b"hello, world".to_vec(),
-			negotiated_fallback: None,
-			substream: NotificationsInSubstream::new(
-				Framed::new(io, codec),
-				NotificationsInSubstreamHandshake::NotSent,
-			),
-		};
-		handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedInbound(
-			handler::FullyNegotiatedInbound { protocol: (notif_in, 0), info: () },
-		));
-
-		assert!(std::matches!(
-			handler.protocols[0].state,
-			State::OpenDesiredByRemote { pending_opening: true, .. }
-		));
-
-		// verify that if the the outbound substream is successfully negotiated, the state is not
-		// changed as the substream was commanded to be closed by the handler.
-		let (io, _io2) = MockSubstream::negotiated().await;
-		let mut codec = UviBytes::default();
-		codec.set_max_len(usize::MAX);
-
-		let notif_out = NotificationsOutOpen {
-			handshake: b"hello, world".to_vec(),
-			negotiated_fallback: None,
-			substream: NotificationsOutSubstream::new(Framed::new(io, codec)),
-		};
-
-		handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedOutbound(
-			handler::FullyNegotiatedOutbound { protocol: notif_out, info: 0 },
-		));
-
-		assert!(std::matches!(
-			handler.protocols[0].state,
-			State::OpenDesiredByRemote { pending_opening: false, .. }
-		));
-	}
-
-	#[tokio::test]
-	async fn dial_upgrade_error_resets_closed_outbound_state() {
-		let mut handler = notifs_handler();
-		let (io, mut io2) = MockSubstream::negotiated().await;
-		let mut codec = UviBytes::default();
-		codec.set_max_len(usize::MAX);
-
-		let notif_in = NotificationsInOpen {
-			handshake: b"hello, world".to_vec(),
-			negotiated_fallback: None,
-			substream: NotificationsInSubstream::new(
-				Framed::new(io, codec),
-				NotificationsInSubstreamHandshake::NotSent,
-			),
-		};
-		handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedInbound(
-			handler::FullyNegotiatedInbound { protocol: (notif_in, 0), info: () },
-		));
-
-		// verify that the substream is in (partly) opened state
-		assert!(std::matches!(handler.protocols[0].state, State::OpenDesiredByRemote { .. }));
-		futures::future::poll_fn(|cx| {
-			let mut buf = Vec::with_capacity(512);
-			assert!(std::matches!(Pin::new(&mut io2).poll_read(cx, &mut buf), Poll::Pending));
-			Poll::Ready(())
-		})
-		.await;
-
-		// first instruct the handler to open a connection and then close it right after
-		// so the handler is in state `Closed { pending_opening: true }`
-		handler.on_behaviour_event(NotifsHandlerIn::Open { protocol_index: 0 });
-		assert!(std::matches!(
-			handler.protocols[0].state,
-			State::Opening { in_substream: Some(_), .. }
-		));
-
-		handler.on_behaviour_event(NotifsHandlerIn::Close { protocol_index: 0 });
-		assert!(std::matches!(handler.protocols[0].state, State::Closed { pending_opening: true }));
-
-		// 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 },
-		));
-		assert!(std::matches!(
-			handler.protocols[0].state,
-			State::Closed { pending_opening: false }
-		));
-	}
-
-	#[tokio::test]
-	async fn dial_upgrade_error_resets_open_desired_state() {
-		let mut handler = notifs_handler();
-		let (io, mut io2) = MockSubstream::negotiated().await;
-		let mut codec = UviBytes::default();
-		codec.set_max_len(usize::MAX);
-
-		let notif_in = NotificationsInOpen {
-			handshake: b"hello, world".to_vec(),
-			negotiated_fallback: None,
-			substream: NotificationsInSubstream::new(
-				Framed::new(io, codec),
-				NotificationsInSubstreamHandshake::NotSent,
-			),
-		};
-		handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedInbound(
-			handler::FullyNegotiatedInbound { protocol: (notif_in, 0), info: () },
-		));
-
-		// verify that the substream is in (partly) opened state
-		assert!(std::matches!(handler.protocols[0].state, State::OpenDesiredByRemote { .. }));
-		futures::future::poll_fn(|cx| {
-			let mut buf = Vec::with_capacity(512);
-			assert!(std::matches!(Pin::new(&mut io2).poll_read(cx, &mut buf), Poll::Pending));
-			Poll::Ready(())
-		})
-		.await;
-
-		// first instruct the handler to open a connection and then close it right after
-		// so the handler is in state `Closed { pending_opening: true }`
-		handler.on_behaviour_event(NotifsHandlerIn::Open { protocol_index: 0 });
-		assert!(std::matches!(
-			handler.protocols[0].state,
-			State::Opening { in_substream: Some(_), .. }
-		));
-
-		handler.on_behaviour_event(NotifsHandlerIn::Close { protocol_index: 0 });
-		assert!(std::matches!(handler.protocols[0].state, State::Closed { pending_opening: true }));
-
-		let (io, _io2) = MockSubstream::negotiated().await;
-		let mut codec = UviBytes::default();
-		codec.set_max_len(usize::MAX);
-
-		let notif_in = NotificationsInOpen {
-			handshake: b"hello, world".to_vec(),
-			negotiated_fallback: None,
-			substream: NotificationsInSubstream::new(
-				Framed::new(io, codec),
-				NotificationsInSubstreamHandshake::NotSent,
-			),
-		};
-		handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedInbound(
-			handler::FullyNegotiatedInbound { protocol: (notif_in, 0), info: () },
-		));
-
-		assert!(std::matches!(
-			handler.protocols[0].state,
-			State::OpenDesiredByRemote { pending_opening: true, .. }
-		));
-
-		// 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 },
-		));
-		assert!(std::matches!(
-			handler.protocols[0].state,
-			State::OpenDesiredByRemote { pending_opening: false, .. }
-		));
-	}
-
-	#[tokio::test]
-	async fn sync_notifications_clogged() {
-		let mut handler = notifs_handler();
-		let (io, _) = MockSubstream::negotiated().await;
-		let codec = UviBytes::default();
-
-		let (async_tx, async_rx) = futures::channel::mpsc::channel(ASYNC_NOTIFICATIONS_BUFFER_SIZE);
-		let (sync_tx, sync_rx) = futures::channel::mpsc::channel(1);
-		let notifications_sink = NotificationsSink {
-			inner: Arc::new(NotificationsSinkInner {
-				peer_id: PeerId::random(),
-				async_channel: FuturesMutex::new(async_tx),
-				sync_channel: Mutex::new(Some(sync_tx)),
-			}),
-		};
-
-		handler.protocols[0].state = State::Open {
-			notifications_sink_rx: stream::select(async_rx.fuse(), sync_rx.fuse()).peekable(),
-			out_substream: Some(NotificationsOutSubstream::new(Framed::new(io, codec))),
-			in_substream: None,
-		};
-
-		notifications_sink.send_sync_notification(vec![1, 3, 3, 7]);
-		notifications_sink.send_sync_notification(vec![1, 3, 3, 8]);
-		notifications_sink.send_sync_notification(vec![1, 3, 3, 9]);
-		notifications_sink.send_sync_notification(vec![1, 3, 4, 0]);
-
-		futures::future::poll_fn(|cx| {
-			assert!(std::matches!(
-				handler.poll(cx),
-				Poll::Ready(ConnectionHandlerEvent::Close(
-					NotifsHandlerError::SyncNotificationsClogged,
-				))
-			));
-			Poll::Ready(())
-		})
-		.await;
-	}
-
-	#[tokio::test]
-	async fn close_desired_by_remote() {
-		let mut handler = notifs_handler();
-		let (io, io2) = MockSubstream::negotiated().await;
-		let mut codec = UviBytes::default();
-		codec.set_max_len(usize::MAX);
-
-		let notif_in = NotificationsInOpen {
-			handshake: b"hello, world".to_vec(),
-			negotiated_fallback: None,
-			substream: NotificationsInSubstream::new(
-				Framed::new(io, codec),
-				NotificationsInSubstreamHandshake::PendingSend(vec![1, 2, 3, 4]),
-			),
-		};
-
-		// add new inbound substream but close it immediately and verify that correct events are
-		// emitted
-		handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedInbound(
-			handler::FullyNegotiatedInbound { protocol: (notif_in, 0), info: () },
-		));
-		drop(io2);
-
-		futures::future::poll_fn(|cx| {
-			assert!(std::matches!(
-				handler.poll(cx),
-				Poll::Ready(ConnectionHandlerEvent::Custom(
-					NotifsHandlerOut::OpenDesiredByRemote { protocol_index: 0 },
-				))
-			));
-			assert!(std::matches!(
-				handler.poll(cx),
-				Poll::Ready(ConnectionHandlerEvent::Custom(NotifsHandlerOut::CloseDesired {
-					protocol_index: 0
-				},))
-			));
-			Poll::Ready(())
-		})
-		.await;
-	}
+	// /// Create new [`NotifsHandler`].
+	// fn notifs_handler() -> NotifsHandler {
+	// 	let proto = Protocol {
+	// 		config: ProtocolConfig {
+	// 			name: "/foo".into(),
+	// 			fallback_names: vec![],
+	// 			handshake: Arc::new(RwLock::new(b"hello, world".to_vec())),
+	// 			max_notification_size: u64::MAX,
+	// 		},
+	// 		in_upgrade: NotificationsIn::new("/foo", Vec::new(), u64::MAX),
+	// 		state: State::Closed { pending_opening: false },
+	// 	};
+
+	// 	NotifsHandler {
+	// 		protocols: vec![proto],
+	// 		when_connection_open: Instant::now(),
+	// 		endpoint: ConnectedPoint::Listener {
+	// 			local_addr: Multiaddr::empty(),
+	// 			send_back_addr: Multiaddr::empty(),
+	// 		},
+	// 		peer_id: PeerId::random(),
+	// 		events_queue: VecDeque::new(),
+	// 	}
+	// }
+
+	// // verify that if another substream is attempted to be opened by remote while an inbound
+	// // substream already exists, the new inbound stream is rejected and closed by the local node.
+	// #[tokio::test]
+	// async fn second_open_desired_by_remote_rejected() {
+	// 	let mut handler = notifs_handler();
+	// 	let (io, mut io2) = MockSubstream::negotiated().await;
+	// 	let mut codec = UviBytes::default();
+	// 	codec.set_max_len(usize::MAX);
+
+	// 	let notif_in = NotificationsInOpen {
+	// 		handshake: b"hello, world".to_vec(),
+	// 		negotiated_fallback: None,
+	// 		substream: NotificationsInSubstream::new(
+	// 			Framed::new(io, codec),
+	// 			NotificationsInSubstreamHandshake::NotSent,
+	// 		),
+	// 	};
+
+	// 	handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedInbound(
+	// 		handler::FullyNegotiatedInbound { protocol: (notif_in, 0), info: () },
+	// 	));
+
+	// 	// verify that the substream is in (partly) opened state
+	// 	assert!(std::matches!(handler.protocols[0].state, State::OpenDesiredByRemote { .. }));
+	// 	futures::future::poll_fn(|cx| {
+	// 		let mut buf = Vec::with_capacity(512);
+	// 		assert!(std::matches!(Pin::new(&mut io2).poll_read(cx, &mut buf), Poll::Pending));
+	// 		Poll::Ready(())
+	// 	})
+	// 	.await;
+
+	// 	// attempt to open another inbound substream and verify that it is rejected
+	// 	let (io, mut io2) = MockSubstream::negotiated().await;
+	// 	let mut codec = UviBytes::default();
+	// 	codec.set_max_len(usize::MAX);
+
+	// 	let notif_in = NotificationsInOpen {
+	// 		handshake: b"hello, world".to_vec(),
+	// 		negotiated_fallback: None,
+	// 		substream: NotificationsInSubstream::new(
+	// 			Framed::new(io, codec),
+	// 			NotificationsInSubstreamHandshake::NotSent,
+	// 		),
+	// 	};
+
+	// 	handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedInbound(
+	// 		handler::FullyNegotiatedInbound { protocol: (notif_in, 0), info: () },
+	// 	));
+
+	// 	// verify that the new substream is rejected and closed
+	// 	futures::future::poll_fn(|cx| {
+	// 		let mut buf = Vec::with_capacity(512);
+
+	// 		if let Poll::Ready(Err(err)) = Pin::new(&mut io2).poll_read(cx, &mut buf) {
+	// 			assert_eq!(err.kind(), std::io::ErrorKind::UnexpectedEof,);
+	// 		}
+
+	// 		Poll::Ready(())
+	// 	})
+	// 	.await;
+	// }
+
+	// #[tokio::test]
+	// async fn open_rejected_if_substream_is_opening() {
+	// 	let mut handler = notifs_handler();
+	// 	let (io, mut io2) = MockSubstream::negotiated().await;
+	// 	let mut codec = UviBytes::default();
+	// 	codec.set_max_len(usize::MAX);
+
+	// 	let notif_in = NotificationsInOpen {
+	// 		handshake: b"hello, world".to_vec(),
+	// 		negotiated_fallback: None,
+	// 		substream: NotificationsInSubstream::new(
+	// 			Framed::new(io, codec),
+	// 			NotificationsInSubstreamHandshake::NotSent,
+	// 		),
+	// 	};
+
+	// 	handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedInbound(
+	// 		handler::FullyNegotiatedInbound { protocol: (notif_in, 0), info: () },
+	// 	));
+
+	// 	// verify that the substream is in (partly) opened state
+	// 	assert!(std::matches!(handler.protocols[0].state, State::OpenDesiredByRemote { .. }));
+	// 	futures::future::poll_fn(|cx| {
+	// 		let mut buf = Vec::with_capacity(512);
+	// 		assert!(std::matches!(Pin::new(&mut io2).poll_read(cx, &mut buf), Poll::Pending));
+	// 		Poll::Ready(())
+	// 	})
+	// 	.await;
+
+	// 	// move the handler state to 'Opening'
+	// 	handler.on_behaviour_event(NotifsHandlerIn::Open { protocol_index: 0 });
+	// 	assert!(std::matches!(
+	// 		handler.protocols[0].state,
+	// 		State::Opening { in_substream: Some(_), .. }
+	// 	));
+
+	// 	// remote now tries to open another substream, verify that it is rejected and closed
+	// 	let (io, mut io2) = MockSubstream::negotiated().await;
+	// 	let mut codec = UviBytes::default();
+	// 	codec.set_max_len(usize::MAX);
+
+	// 	let notif_in = NotificationsInOpen {
+	// 		handshake: b"hello, world".to_vec(),
+	// 		negotiated_fallback: None,
+	// 		substream: NotificationsInSubstream::new(
+	// 			Framed::new(io, codec),
+	// 			NotificationsInSubstreamHandshake::NotSent,
+	// 		),
+	// 	};
+
+	// 	handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedInbound(
+	// 		handler::FullyNegotiatedInbound { protocol: (notif_in, 0), info: () },
+	// 	));
+
+	// 	// verify that the new substream is rejected and closed but that the first substream is
+	// 	// still in correct state
+	// 	futures::future::poll_fn(|cx| {
+	// 		let mut buf = Vec::with_capacity(512);
+
+	// 		if let Poll::Ready(Err(err)) = Pin::new(&mut io2).poll_read(cx, &mut buf) {
+	// 			assert_eq!(err.kind(), std::io::ErrorKind::UnexpectedEof,);
+	// 		} else {
+	// 			panic!("unexpected result");
+	// 		}
+
+	// 		Poll::Ready(())
+	// 	})
+	// 	.await;
+	// 	assert!(std::matches!(
+	// 		handler.protocols[0].state,
+	// 		State::Opening { in_substream: Some(_), .. }
+	// 	));
+	// }
+
+	// #[tokio::test]
+	// async fn open_rejected_if_substream_already_open() {
+	// 	let mut handler = notifs_handler();
+	// 	let (io, mut io2) = MockSubstream::negotiated().await;
+	// 	let mut codec = UviBytes::default();
+	// 	codec.set_max_len(usize::MAX);
+
+	// 	let notif_in = NotificationsInOpen {
+	// 		handshake: b"hello, world".to_vec(),
+	// 		negotiated_fallback: None,
+	// 		substream: NotificationsInSubstream::new(
+	// 			Framed::new(io, codec),
+	// 			NotificationsInSubstreamHandshake::NotSent,
+	// 		),
+	// 	};
+	// 	handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedInbound(
+	// 		handler::FullyNegotiatedInbound { protocol: (notif_in, 0), info: () },
+	// 	));
+
+	// 	// verify that the substream is in (partly) opened state
+	// 	assert!(std::matches!(handler.protocols[0].state, State::OpenDesiredByRemote { .. }));
+	// 	futures::future::poll_fn(|cx| {
+	// 		let mut buf = Vec::with_capacity(512);
+	// 		assert!(std::matches!(Pin::new(&mut io2).poll_read(cx, &mut buf), Poll::Pending));
+	// 		Poll::Ready(())
+	// 	})
+	// 	.await;
+
+	// 	// move the handler state to 'Opening'
+	// 	handler.on_behaviour_event(NotifsHandlerIn::Open { protocol_index: 0 });
+	// 	assert!(std::matches!(
+	// 		handler.protocols[0].state,
+	// 		State::Opening { in_substream: Some(_), .. }
+	// 	));
+
+	// 	// accept the substream and move its state to `Open`
+	// 	let (io, _io2) = MockSubstream::negotiated().await;
+	// 	let mut codec = UviBytes::default();
+	// 	codec.set_max_len(usize::MAX);
+
+	// 	let notif_out = NotificationsOutOpen {
+	// 		handshake: b"hello, world".to_vec(),
+	// 		negotiated_fallback: None,
+	// 		substream: NotificationsOutSubstream::new(Framed::new(io, codec)),
+	// 	};
+	// 	handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedOutbound(
+	// 		handler::FullyNegotiatedOutbound { protocol: notif_out, info: 0 },
+	// 	));
+
+	// 	assert!(std::matches!(
+	// 		handler.protocols[0].state,
+	// 		State::Open { in_substream: Some(_), .. }
+	// 	));
+
+	// 	// remote now tries to open another substream, verify that it is rejected and closed
+	// 	let (io, mut io2) = MockSubstream::negotiated().await;
+	// 	let mut codec = UviBytes::default();
+	// 	codec.set_max_len(usize::MAX);
+	// 	let notif_in = NotificationsInOpen {
+	// 		handshake: b"hello, world".to_vec(),
+	// 		negotiated_fallback: None,
+	// 		substream: NotificationsInSubstream::new(
+	// 			Framed::new(io, codec),
+	// 			NotificationsInSubstreamHandshake::NotSent,
+	// 		),
+	// 	};
+	// 	handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedInbound(
+	// 		handler::FullyNegotiatedInbound { protocol: (notif_in, 0), info: () },
+	// 	));
+
+	// 	// verify that the new substream is rejected and closed but that the first substream is
+	// 	// still in correct state
+	// 	futures::future::poll_fn(|cx| {
+	// 		let mut buf = Vec::with_capacity(512);
+
+	// 		if let Poll::Ready(Err(err)) = Pin::new(&mut io2).poll_read(cx, &mut buf) {
+	// 			assert_eq!(err.kind(), std::io::ErrorKind::UnexpectedEof);
+	// 		} else {
+	// 			panic!("unexpected result");
+	// 		}
+
+	// 		Poll::Ready(())
+	// 	})
+	// 	.await;
+	// 	assert!(std::matches!(
+	// 		handler.protocols[0].state,
+	// 		State::Open { in_substream: Some(_), .. }
+	// 	));
+	// }
+
+	// #[tokio::test]
+	// async fn fully_negotiated_resets_state_for_closed_substream() {
+	// 	let mut handler = notifs_handler();
+	// 	let (io, mut io2) = MockSubstream::negotiated().await;
+	// 	let mut codec = UviBytes::default();
+	// 	codec.set_max_len(usize::MAX);
+
+	// 	let notif_in = NotificationsInOpen {
+	// 		handshake: b"hello, world".to_vec(),
+	// 		negotiated_fallback: None,
+	// 		substream: NotificationsInSubstream::new(
+	// 			Framed::new(io, codec),
+	// 			NotificationsInSubstreamHandshake::NotSent,
+	// 		),
+	// 	};
+	// 	handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedInbound(
+	// 		handler::FullyNegotiatedInbound { protocol: (notif_in, 0), info: () },
+	// 	));
+
+	// 	// verify that the substream is in (partly) opened state
+	// 	assert!(std::matches!(handler.protocols[0].state, State::OpenDesiredByRemote { .. }));
+	// 	futures::future::poll_fn(|cx| {
+	// 		let mut buf = Vec::with_capacity(512);
+	// 		assert!(std::matches!(Pin::new(&mut io2).poll_read(cx, &mut buf), Poll::Pending));
+	// 		Poll::Ready(())
+	// 	})
+	// 	.await;
+
+	// 	// first instruct the handler to open a connection and then close it right after
+	// 	// so the handler is in state `Closed { pending_opening: true }`
+	// 	handler.on_behaviour_event(NotifsHandlerIn::Open { protocol_index: 0 });
+	// 	assert!(std::matches!(
+	// 		handler.protocols[0].state,
+	// 		State::Opening { in_substream: Some(_), .. }
+	// 	));
+
+	// 	handler.on_behaviour_event(NotifsHandlerIn::Close { protocol_index: 0 });
+	// 	assert!(std::matches!(handler.protocols[0].state, State::Closed { pending_opening: true }));
+
+	// 	// verify that if the the outbound substream is successfully negotiated, the state is not
+	// 	// changed as the substream was commanded to be closed by the handler.
+	// 	let (io, _io2) = MockSubstream::negotiated().await;
+	// 	let mut codec = UviBytes::default();
+	// 	codec.set_max_len(usize::MAX);
+
+	// 	let notif_out = NotificationsOutOpen {
+	// 		handshake: b"hello, world".to_vec(),
+	// 		negotiated_fallback: None,
+	// 		substream: NotificationsOutSubstream::new(Framed::new(io, codec)),
+	// 	};
+	// 	handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedOutbound(
+	// 		handler::FullyNegotiatedOutbound { protocol: notif_out, info: 0 },
+	// 	));
+
+	// 	assert!(std::matches!(
+	// 		handler.protocols[0].state,
+	// 		State::Closed { pending_opening: false }
+	// 	));
+	// }
+
+	// #[tokio::test]
+	// async fn fully_negotiated_resets_state_for_open_desired_substream() {
+	// 	let mut handler = notifs_handler();
+	// 	let (io, mut io2) = MockSubstream::negotiated().await;
+	// 	let mut codec = UviBytes::default();
+	// 	codec.set_max_len(usize::MAX);
+
+	// 	let notif_in = NotificationsInOpen {
+	// 		handshake: b"hello, world".to_vec(),
+	// 		negotiated_fallback: None,
+	// 		substream: NotificationsInSubstream::new(
+	// 			Framed::new(io, codec),
+	// 			NotificationsInSubstreamHandshake::NotSent,
+	// 		),
+	// 	};
+	// 	handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedInbound(
+	// 		handler::FullyNegotiatedInbound { protocol: (notif_in, 0), info: () },
+	// 	));
+
+	// 	// verify that the substream is in (partly) opened state
+	// 	assert!(std::matches!(handler.protocols[0].state, State::OpenDesiredByRemote { .. }));
+	// 	futures::future::poll_fn(|cx| {
+	// 		let mut buf = Vec::with_capacity(512);
+	// 		assert!(std::matches!(Pin::new(&mut io2).poll_read(cx, &mut buf), Poll::Pending));
+	// 		Poll::Ready(())
+	// 	})
+	// 	.await;
+
+	// 	// first instruct the handler to open a connection and then close it right after
+	// 	// so the handler is in state `Closed { pending_opening: true }`
+	// 	handler.on_behaviour_event(NotifsHandlerIn::Open { protocol_index: 0 });
+	// 	assert!(std::matches!(
+	// 		handler.protocols[0].state,
+	// 		State::Opening { in_substream: Some(_), .. }
+	// 	));
+
+	// 	handler.on_behaviour_event(NotifsHandlerIn::Close { protocol_index: 0 });
+	// 	assert!(std::matches!(handler.protocols[0].state, State::Closed { pending_opening: true }));
+
+	// 	// attempt to open another inbound substream and verify that it is rejected
+	// 	let (io, _io2) = MockSubstream::negotiated().await;
+	// 	let mut codec = UviBytes::default();
+	// 	codec.set_max_len(usize::MAX);
+
+	// 	let notif_in = NotificationsInOpen {
+	// 		handshake: b"hello, world".to_vec(),
+	// 		negotiated_fallback: None,
+	// 		substream: NotificationsInSubstream::new(
+	// 			Framed::new(io, codec),
+	// 			NotificationsInSubstreamHandshake::NotSent,
+	// 		),
+	// 	};
+	// 	handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedInbound(
+	// 		handler::FullyNegotiatedInbound { protocol: (notif_in, 0), info: () },
+	// 	));
+
+	// 	assert!(std::matches!(
+	// 		handler.protocols[0].state,
+	// 		State::OpenDesiredByRemote { pending_opening: true, .. }
+	// 	));
+
+	// 	// verify that if the the outbound substream is successfully negotiated, the state is not
+	// 	// changed as the substream was commanded to be closed by the handler.
+	// 	let (io, _io2) = MockSubstream::negotiated().await;
+	// 	let mut codec = UviBytes::default();
+	// 	codec.set_max_len(usize::MAX);
+
+	// 	let notif_out = NotificationsOutOpen {
+	// 		handshake: b"hello, world".to_vec(),
+	// 		negotiated_fallback: None,
+	// 		substream: NotificationsOutSubstream::new(Framed::new(io, codec)),
+	// 	};
+
+	// 	handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedOutbound(
+	// 		handler::FullyNegotiatedOutbound { protocol: notif_out, info: 0 },
+	// 	));
+
+	// 	assert!(std::matches!(
+	// 		handler.protocols[0].state,
+	// 		State::OpenDesiredByRemote { pending_opening: false, .. }
+	// 	));
+	// }
+
+	// #[tokio::test]
+	// async fn dial_upgrade_error_resets_closed_outbound_state() {
+	// 	let mut handler = notifs_handler();
+	// 	let (io, mut io2) = MockSubstream::negotiated().await;
+	// 	let mut codec = UviBytes::default();
+	// 	codec.set_max_len(usize::MAX);
+
+	// 	let notif_in = NotificationsInOpen {
+	// 		handshake: b"hello, world".to_vec(),
+	// 		negotiated_fallback: None,
+	// 		substream: NotificationsInSubstream::new(
+	// 			Framed::new(io, codec),
+	// 			NotificationsInSubstreamHandshake::NotSent,
+	// 		),
+	// 	};
+	// 	handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedInbound(
+	// 		handler::FullyNegotiatedInbound { protocol: (notif_in, 0), info: () },
+	// 	));
+
+	// 	// verify that the substream is in (partly) opened state
+	// 	assert!(std::matches!(handler.protocols[0].state, State::OpenDesiredByRemote { .. }));
+	// 	futures::future::poll_fn(|cx| {
+	// 		let mut buf = Vec::with_capacity(512);
+	// 		assert!(std::matches!(Pin::new(&mut io2).poll_read(cx, &mut buf), Poll::Pending));
+	// 		Poll::Ready(())
+	// 	})
+	// 	.await;
+
+	// 	// first instruct the handler to open a connection and then close it right after
+	// 	// so the handler is in state `Closed { pending_opening: true }`
+	// 	handler.on_behaviour_event(NotifsHandlerIn::Open { protocol_index: 0 });
+	// 	assert!(std::matches!(
+	// 		handler.protocols[0].state,
+	// 		State::Opening { in_substream: Some(_), .. }
+	// 	));
+
+	// 	handler.on_behaviour_event(NotifsHandlerIn::Close { protocol_index: 0 });
+	// 	assert!(std::matches!(handler.protocols[0].state, State::Closed { pending_opening: true }));
+
+	// 	// 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 },
+	// 	));
+	// 	assert!(std::matches!(
+	// 		handler.protocols[0].state,
+	// 		State::Closed { pending_opening: false }
+	// 	));
+	// }
+
+	// #[tokio::test]
+	// async fn dial_upgrade_error_resets_open_desired_state() {
+	// 	let mut handler = notifs_handler();
+	// 	let (io, mut io2) = MockSubstream::negotiated().await;
+	// 	let mut codec = UviBytes::default();
+	// 	codec.set_max_len(usize::MAX);
+
+	// 	let notif_in = NotificationsInOpen {
+	// 		handshake: b"hello, world".to_vec(),
+	// 		negotiated_fallback: None,
+	// 		substream: NotificationsInSubstream::new(
+	// 			Framed::new(io, codec),
+	// 			NotificationsInSubstreamHandshake::NotSent,
+	// 		),
+	// 	};
+	// 	handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedInbound(
+	// 		handler::FullyNegotiatedInbound { protocol: (notif_in, 0), info: () },
+	// 	));
+
+	// 	// verify that the substream is in (partly) opened state
+	// 	assert!(std::matches!(handler.protocols[0].state, State::OpenDesiredByRemote { .. }));
+	// 	futures::future::poll_fn(|cx| {
+	// 		let mut buf = Vec::with_capacity(512);
+	// 		assert!(std::matches!(Pin::new(&mut io2).poll_read(cx, &mut buf), Poll::Pending));
+	// 		Poll::Ready(())
+	// 	})
+	// 	.await;
+
+	// 	// first instruct the handler to open a connection and then close it right after
+	// 	// so the handler is in state `Closed { pending_opening: true }`
+	// 	handler.on_behaviour_event(NotifsHandlerIn::Open { protocol_index: 0 });
+	// 	assert!(std::matches!(
+	// 		handler.protocols[0].state,
+	// 		State::Opening { in_substream: Some(_), .. }
+	// 	));
+
+	// 	handler.on_behaviour_event(NotifsHandlerIn::Close { protocol_index: 0 });
+	// 	assert!(std::matches!(handler.protocols[0].state, State::Closed { pending_opening: true }));
+
+	// 	let (io, _io2) = MockSubstream::negotiated().await;
+	// 	let mut codec = UviBytes::default();
+	// 	codec.set_max_len(usize::MAX);
+
+	// 	let notif_in = NotificationsInOpen {
+	// 		handshake: b"hello, world".to_vec(),
+	// 		negotiated_fallback: None,
+	// 		substream: NotificationsInSubstream::new(
+	// 			Framed::new(io, codec),
+	// 			NotificationsInSubstreamHandshake::NotSent,
+	// 		),
+	// 	};
+	// 	handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedInbound(
+	// 		handler::FullyNegotiatedInbound { protocol: (notif_in, 0), info: () },
+	// 	));
+
+	// 	assert!(std::matches!(
+	// 		handler.protocols[0].state,
+	// 		State::OpenDesiredByRemote { pending_opening: true, .. }
+	// 	));
+
+	// 	// 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 },
+	// 	));
+	// 	assert!(std::matches!(
+	// 		handler.protocols[0].state,
+	// 		State::OpenDesiredByRemote { pending_opening: false, .. }
+	// 	));
+	// }
+
+	// #[tokio::test]
+	// async fn sync_notifications_clogged() {
+	// 	let mut handler = notifs_handler();
+	// 	let (io, _) = MockSubstream::negotiated().await;
+	// 	let codec = UviBytes::default();
+
+	// 	let (async_tx, async_rx) = futures::channel::mpsc::channel(ASYNC_NOTIFICATIONS_BUFFER_SIZE);
+	// 	let (sync_tx, sync_rx) = futures::channel::mpsc::channel(1);
+	// 	let notifications_sink = NotificationsSink {
+	// 		inner: Arc::new(NotificationsSinkInner {
+	// 			peer_id: PeerId::random(),
+	// 			async_channel: FuturesMutex::new(async_tx),
+	// 			sync_channel: Mutex::new(Some(sync_tx)),
+	// 		}),
+	// 	};
+
+	// 	handler.protocols[0].state = State::Open {
+	// 		notifications_sink_rx: stream::select(async_rx.fuse(), sync_rx.fuse()).peekable(),
+	// 		out_substream: Some(NotificationsOutSubstream::new(Framed::new(io, codec))),
+	// 		in_substream: None,
+	// 	};
+
+	// 	notifications_sink.send_sync_notification(vec![1, 3, 3, 7]);
+	// 	notifications_sink.send_sync_notification(vec![1, 3, 3, 8]);
+	// 	notifications_sink.send_sync_notification(vec![1, 3, 3, 9]);
+	// 	notifications_sink.send_sync_notification(vec![1, 3, 4, 0]);
+
+	// 	futures::future::poll_fn(|cx| {
+	// 		assert!(std::matches!(
+	// 			handler.poll(cx),
+	// 			Poll::Ready(ConnectionHandlerEvent::Close(
+	// 				NotifsHandlerError::SyncNotificationsClogged,
+	// 			))
+	// 		));
+	// 		Poll::Ready(())
+	// 	})
+	// 	.await;
+	// }
+
+	// #[tokio::test]
+	// async fn close_desired_by_remote() {
+	// 	let mut handler = notifs_handler();
+	// 	let (io, io2) = MockSubstream::negotiated().await;
+	// 	let mut codec = UviBytes::default();
+	// 	codec.set_max_len(usize::MAX);
+
+	// 	let notif_in = NotificationsInOpen {
+	// 		handshake: b"hello, world".to_vec(),
+	// 		negotiated_fallback: None,
+	// 		substream: NotificationsInSubstream::new(
+	// 			Framed::new(io, codec),
+	// 			NotificationsInSubstreamHandshake::PendingSend(vec![1, 2, 3, 4]),
+	// 		),
+	// 	};
+
+	// 	// add new inbound substream but close it immediately and verify that correct events are
+	// 	// emitted
+	// 	handler.on_connection_event(handler::ConnectionEvent::FullyNegotiatedInbound(
+	// 		handler::FullyNegotiatedInbound { protocol: (notif_in, 0), info: () },
+	// 	));
+	// 	drop(io2);
+
+	// 	futures::future::poll_fn(|cx| {
+	// 		assert!(std::matches!(
+	// 			handler.poll(cx),
+	// 			Poll::Ready(ConnectionHandlerEvent::Custom(
+	// 				NotifsHandlerOut::OpenDesiredByRemote { protocol_index: 0 },
+	// 			))
+	// 		));
+	// 		assert!(std::matches!(
+	// 			handler.poll(cx),
+	// 			Poll::Ready(ConnectionHandlerEvent::Custom(NotifsHandlerOut::CloseDesired {
+	// 				protocol_index: 0
+	// 			},))
+	// 		));
+	// 		Poll::Ready(())
+	// 	})
+	// 	.await;
+	// }
 }
diff --git a/substrate/client/network/src/protocol/notifications/tests.rs b/substrate/client/network/src/protocol/notifications/tests.rs
index 0c2eb89262f..ddeea495a27 100644
--- a/substrate/client/network/src/protocol/notifications/tests.rs
+++ b/substrate/client/network/src/protocol/notifications/tests.rs
@@ -151,7 +151,7 @@ impl std::ops::DerefMut for CustomProtoWithAddr {
 
 impl NetworkBehaviour for CustomProtoWithAddr {
 	type ConnectionHandler = <Notifications as NetworkBehaviour>::ConnectionHandler;
-	type OutEvent = <Notifications as NetworkBehaviour>::OutEvent;
+	type ToSwarm = <Notifications as NetworkBehaviour>::ToSwarm;
 
 	fn handle_pending_inbound_connection(
 		&mut self,
@@ -229,7 +229,7 @@ impl NetworkBehaviour for CustomProtoWithAddr {
 		&mut self,
 		cx: &mut Context,
 		params: &mut impl PollParameters,
-	) -> Poll<ToSwarm<Self::OutEvent, THandlerInEvent<Self>>> {
+	) -> Poll<ToSwarm<Self::ToSwarm, THandlerInEvent<Self>>> {
 		self.inner.poll(cx, params)
 	}
 }
diff --git a/substrate/client/network/src/protocol/notifications/upgrade/collec.rs b/substrate/client/network/src/protocol/notifications/upgrade/collec.rs
index 791821b3f75..2b26410fbe8 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 <https://www.gnu.org/licenses/>.
 
 use futures::prelude::*;
-use libp2p::core::upgrade::{InboundUpgrade, ProtocolName, UpgradeInfo};
+use libp2p::core::upgrade::{InboundUpgrade, UpgradeInfo};
 use std::{
 	iter::FromIterator,
 	pin::Pin,
@@ -76,9 +76,9 @@ where
 #[derive(Debug, Clone, PartialEq)]
 pub struct ProtoNameWithUsize<T>(T, usize);
 
-impl<T: ProtocolName> ProtocolName for ProtoNameWithUsize<T> {
-	fn protocol_name(&self) -> &[u8] {
-		self.0.protocol_name()
+impl<T: AsRef<str>> AsRef<str> for ProtoNameWithUsize<T> {
+	fn as_ref(&self) -> &str {
+		self.0.as_ref()
 	}
 }
 
@@ -104,13 +104,13 @@ impl<T: Future<Output = Result<O, E>>, O, E> Future for FutWithUsize<T> {
 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<T> {}
 
-		impl<T: Clone + ProtocolName> UpgradeInfo for ProtocolUpgrade<T> {
+		impl<T: Clone + AsRef<str>> UpgradeInfo for ProtocolUpgrade<T> {
 			type Info = T;
 			type InfoIter = vec::IntoIter<T>;
 			fn protocol_info(&self) -> vec::IntoIter<T>;
diff --git a/substrate/client/network/src/protocol/notifications/upgrade/notifications.rs b/substrate/client/network/src/protocol/notifications/upgrade/notifications.rs
index 4e1c033f33b..0148fd22bd8 100644
--- a/substrate/client/network/src/protocol/notifications/upgrade/notifications.rs
+++ b/substrate/client/network/src/protocol/notifications/upgrade/notifications.rs
@@ -114,13 +114,6 @@ pub struct NotificationsOutSubstream<TSubstream> {
 	socket: Framed<TSubstream, UviBytes<io::Cursor<Vec<u8>>>>,
 }
 
-#[cfg(test)]
-impl<TSubstream> NotificationsOutSubstream<TSubstream> {
-	pub fn new(socket: Framed<TSubstream, UviBytes<io::Cursor<Vec<u8>>>>) -> Self {
-		Self { socket }
-	}
-}
-
 impl NotificationsIn {
 	/// Builds a new potential upgrade.
 	pub fn new(
@@ -203,13 +196,13 @@ impl<TSubstream> NotificationsInSubstream<TSubstream>
 where
 	TSubstream: AsyncRead + AsyncWrite + Unpin,
 {
-	#[cfg(test)]
-	pub fn new(
-		socket: Framed<TSubstream, UviBytes<io::Cursor<Vec<u8>>>>,
-		handshake: NotificationsInSubstreamHandshake,
-	) -> Self {
-		Self { socket, handshake }
-	}
+	// #[cfg(test)]
+	// pub fn new(
+	// 	socket: Framed<TSubstream, UviBytes<io::Cursor<Vec<u8>>>>,
+	// 	handshake: NotificationsInSubstreamHandshake,
+	// ) -> Self {
+	// 	Self { socket, handshake }
+	// }
 
 	/// Sends the handshake in order to inform the remote that we accept the substream.
 	pub fn send_handshake(&mut self, message: impl Into<Vec<u8>>) {
@@ -498,41 +491,92 @@ pub enum NotificationsOutError {
 
 #[cfg(test)]
 mod tests {
-	use super::{NotificationsIn, NotificationsInOpen, NotificationsOut, NotificationsOutOpen};
-	use futures::{channel::oneshot, prelude::*};
-	use libp2p::core::upgrade;
+	use super::*;
+	use futures::channel::oneshot;
+	use libp2p::core::{upgrade, InboundUpgrade, OutboundUpgrade, UpgradeInfo};
 	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<Vec<u8>>,
+	) -> Result<
+		(
+			Vec<u8>,
+			NotificationsOutSubstream<
+				multistream_select::Negotiated<tokio_util::compat::Compat<TcpStream>>,
+			>,
+		),
+		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().into_iter(),
+			upgrade::Version::V1,
+		)
+		.await
+		.unwrap();
+		let NotificationsOutOpen { handshake, substream, .. } =
+			<NotificationsOut as OutboundUpgrade<_>>::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<std::net::SocketAddr>,
+	) -> Result<
+		(
+			Vec<u8>,
+			NotificationsInSubstream<
+				multistream_select::Negotiated<tokio_util::compat::Compat<TcpStream>>,
+			>,
+		),
+		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, .. } =
+			<NotificationsIn as InboundUpgrade<_>>::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"[..]);
@@ -547,33 +591,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![]);
@@ -586,17 +614,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
@@ -604,16 +625,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");
 
@@ -625,35 +637,16 @@ 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::<Vec<_>>(),
-					1024 * 1024,
-				),
-				upgrade::Version::V1,
-			)
-			.await;
+			let ret =
+				dial(listener_addr_rx.await.unwrap(), (0..32768).map(|_| 0).collect::<Vec<_>>())
+					.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;
+		let ret = listen_on_localhost(listener_addr_tx).await;
 		assert!(ret.is_err());
 
 		client.await.unwrap();
@@ -661,30 +654,14 @@ mod tests {
 
 	#[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.
diff --git a/substrate/client/network/src/request_responses.rs b/substrate/client/network/src/request_responses.rs
index b98a298bc0d..c0754132a13 100644
--- a/substrate/client/network/src/request_responses.rs
+++ b/substrate/client/network/src/request_responses.rs
@@ -331,13 +331,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,
 			);
@@ -405,7 +405,7 @@ impl RequestResponsesBehaviour {
 impl NetworkBehaviour for RequestResponsesBehaviour {
 	type ConnectionHandler =
 		MultiHandler<String, <Behaviour<GenericCodec> as NetworkBehaviour>::ConnectionHandler>;
-	type OutEvent = Event;
+	type ToSwarm = Event;
 
 	fn handle_pending_inbound_connection(
 		&mut self,
@@ -521,9 +521,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() {
@@ -533,9 +533,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() {
@@ -570,7 +574,7 @@ impl NetworkBehaviour for RequestResponsesBehaviour {
 		&mut self,
 		cx: &mut Context,
 		params: &mut impl PollParameters,
-	) -> Poll<ToSwarm<Self::OutEvent, THandlerInEvent<Self>>> {
+	) -> Poll<ToSwarm<Self::ToSwarm, THandlerInEvent<Self>>> {
 		'poll_all: loop {
 			if let Some(message_request) = self.message_request.take() {
 				// Now we can can poll `MessageRequest` until we get the reputation
@@ -729,10 +733,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 {
@@ -934,7 +946,7 @@ pub struct GenericCodec {
 
 #[async_trait::async_trait]
 impl Codec for GenericCodec {
-	type Protocol = Vec<u8>;
+	type Protocol = ProtocolName;
 	type Request = Vec<u8>;
 	type Response = Result<Vec<u8>, ()>;
 
diff --git a/substrate/client/network/src/service.rs b/substrate/client/network/src/service.rs
index b6fda5ab079..28ad85074c4 100644
--- a/substrate/client/network/src/service.rs
+++ b/substrate/client/network/src/service.rs
@@ -55,17 +55,15 @@ use crate::{
 
 use either::Either;
 use futures::{channel::oneshot, prelude::*};
-#[allow(deprecated)]
 use libp2p::{
-	connection_limits::Exceeded,
+	connection_limits::{ConnectionLimits, Exceeded},
 	core::{upgrade, ConnectedPoint, Endpoint},
 	identify::Info as IdentifyInfo,
 	kad::record::Key as KademliaKey,
 	multiaddr,
-	ping::Failure as PingFailure,
 	swarm::{
-		AddressScore, ConnectionError, ConnectionId, ConnectionLimits, DialError, Executor,
-		ListenError, NetworkBehaviour, Swarm, SwarmBuilder, SwarmEvent, THandlerErr,
+		ConnectionError, ConnectionId, DialError, Executor, ListenError, NetworkBehaviour, Swarm,
+		SwarmBuilder, SwarmEvent, THandlerErr,
 	},
 	Multiaddr, PeerId,
 };
@@ -351,6 +349,11 @@ where
 					discovery_config,
 					request_response_protocols,
 					peerset_handle.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 {
@@ -374,15 +377,7 @@ where
 					SpawnImpl(params.executor),
 				)
 			};
-			#[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::V1Lazy)
 				.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.
@@ -414,11 +409,7 @@ where
 
 		// Add external addresses.
 		for addr in &network_config.public_addresses {
-			Swarm::<Behaviour<B>>::add_external_address(
-				&mut swarm,
-				addr.clone(),
-				AddressScore::Infinite,
-			);
+			Swarm::<Behaviour<B>>::add_external_address(&mut swarm, addr.clone());
 		}
 
 		let external_addresses = Arc::new(Mutex::new(Vec::new()));
@@ -602,7 +593,7 @@ where
 
 		let peer_id = Swarm::<Behaviour<B>>::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,
@@ -680,8 +671,7 @@ impl<B: BlockT + 'static, H: ExHashT> NetworkService<B, H> {
 			.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()),
 				};
 
@@ -1197,8 +1187,7 @@ where
 			self.network_service.behaviour_mut().user_protocol_mut().num_connected_peers();
 		self.num_connected.store(num_connected_peers, Ordering::Relaxed);
 		{
-			let external_addresses =
-				self.network_service.external_addresses().map(|r| &r.addr).cloned().collect();
+			let external_addresses = self.network_service.external_addresses().cloned().collect();
 			*self.external_addresses.lock() = external_addresses;
 
 			let listen_addresses =
@@ -1401,7 +1390,12 @@ where
 				peer_id,
 				info:
 					IdentifyInfo {
-						protocol_version, agent_version, mut listen_addrs, protocols, ..
+						protocol_version,
+						agent_version,
+						mut listen_addrs,
+						protocols,
+						observed_addr,
+						..
 					},
 			}) => {
 				if listen_addrs.len() > 30 {
@@ -1413,11 +1407,17 @@ 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.network_service.behaviour_mut().user_protocol_mut().add_known_peer(peer_id);
+				// Confirm the observed address manually since they are no longer trusted by
+				// default (libp2p >= 0.52)
+				// TODO: remove this when/if AutoNAT is implemented.
+				self.network_service.add_external_address(observed_addr);
 			},
 			SwarmEvent::Behaviour(BehaviourOut::Discovered(peer_id)) => {
 				self.network_service.behaviour_mut().user_protocol_mut().add_known_peer(peer_id);
@@ -1562,8 +1562,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({:?} via {:?}: {:?})", peer_id, connection_id, cause);
 				if let Some(metrics) = self.metrics.as_ref() {
 					let direction = match endpoint {
 						ConnectedPoint::Dialer { .. } => "out",
@@ -1572,10 +1578,12 @@ where
 					let reason = match cause {
 						Some(ConnectionError::IO(_)) => "transport-error",
 						Some(ConnectionError::Handler(Either::Left(Either::Left(
-							Either::Right(Either::Left(PingFailure::Timeout)),
+							Either::Left(Either::Right(_)),
 						)))) => "ping-timeout",
 						Some(ConnectionError::Handler(Either::Left(Either::Left(
-							Either::Left(NotifsHandlerError::SyncNotificationsClogged),
+							Either::Left(Either::Left(
+								NotifsHandlerError::SyncNotificationsClogged,
+							)),
 						)))) => "sync-notifications-clogged",
 						Some(ConnectionError::Handler(_)) => "protocol-error",
 						Some(ConnectionError::KeepAliveTimeout) => "keep-alive-timeout",
@@ -1601,12 +1609,12 @@ where
 					metrics.listeners_local_addresses.dec();
 				}
 			},
-			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 {:?} via {:?}: {}",
+						peer_id, connection_id, error,
 					);
 
 					let not_reported = !self.reported_invalid_boot_nodes.contains(&peer_id);
@@ -1644,12 +1652,9 @@ where
 							} else {
 								None
 							},
-						DialError::ConnectionLimit(_) => Some("limit-reached"),
-						DialError::InvalidPeerId(_) |
-						DialError::WrongPeerId { .. } |
-						DialError::LocalPeerId { .. } => Some("invalid-peer-id"),
+						DialError::WrongPeerId { .. } | DialError::LocalPeerId { .. } =>
+							Some("invalid-peer-id"),
 						DialError::Transport(_) => Some("transport-error"),
-						DialError::Banned |
 						DialError::NoAddresses |
 						DialError::DialPeerConditionFalse(_) |
 						DialError::Aborted => None, // ignore them
@@ -1659,21 +1664,26 @@ where
 					}
 				}
 			},
-			SwarmEvent::Dialing(peer_id) => {
-				trace!(target: "sub-libp2p", "Libp2p => Dialing({:?})", peer_id)
+			SwarmEvent::Dialing { peer_id, connection_id } => {
+				trace!(target: "sub-libp2p", "Libp2p => Dialing({:?} via {:?})", peer_id, 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({},{} via {:?}))",
+					local_addr, send_back_addr, 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({},{} via {:?}): {}",
+					local_addr, send_back_addr, connection_id, error,
 				);
 				if let Some(metrics) = self.metrics.as_ref() {
 					#[allow(deprecated)]
@@ -1684,7 +1694,6 @@ where
 							} else {
 								None
 							},
-						ListenError::ConnectionLimit(_) => Some("limit-reached"),
 						ListenError::WrongPeerId { .. } | ListenError::LocalPeerId { .. } =>
 							Some("invalid-peer-id"),
 						ListenError::Transport(_) => Some("transport-error"),
@@ -1699,17 +1708,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/types.rs b/substrate/client/network/src/types.rs
index b0e32ae1091..5444a1e0603 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,
@@ -92,9 +90,9 @@ impl fmt::Display for ProtocolName {
 	}
 }
 
-impl upgrade::ProtocolName for ProtocolName {
-	fn protocol_name(&self) -> &[u8] {
-		(self as &str).as_bytes()
+impl AsRef<str> 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 63377710dc4..e70fc5e929a 100644
--- a/substrate/client/network/statement/Cargo.toml
+++ b/substrate/client/network/statement/Cargo.toml
@@ -17,7 +17,7 @@ array-bytes = "6.1"
 async-channel = "1.8.0"
 codec = { package = "parity-scale-codec", version = "3.6.1", features = ["derive"] }
 futures = "0.3.21"
-libp2p = "0.51.3"
+libp2p = "0.52.1"
 log = "0.4.17"
 prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.10.0-dev", path = "../../../utils/prometheus" }
 sc-network-common = { version = "0.10.0-dev", path = "../common" }
diff --git a/substrate/client/network/statement/src/lib.rs b/substrate/client/network/statement/src/lib.rs
index 2c966a346ad..a055cd07a07 100644
--- a/substrate/client/network/statement/src/lib.rs
+++ b/substrate/client/network/statement/src/lib.rs
@@ -286,8 +286,8 @@ where
 	fn handle_sync_event(&mut self, event: SyncEvent) {
 		match event {
 			SyncEvent::PeerConnected(remote) => {
-				let addr = iter::once(multiaddr::Protocol::P2p(remote.into()))
-					.collect::<multiaddr::Multiaddr>();
+				let addr =
+					iter::once(multiaddr::Protocol::P2p(remote)).collect::<multiaddr::Multiaddr>();
 				let result = self.network.add_peers_to_reserved_set(
 					self.protocol_name.clone(),
 					iter::once(addr).collect(),
diff --git a/substrate/client/network/sync/Cargo.toml b/substrate/client/network/sync/Cargo.toml
index 1feb1316dbc..53bb987a6f4 100644
--- a/substrate/client/network/sync/Cargo.toml
+++ b/substrate/client/network/sync/Cargo.toml
@@ -22,12 +22,12 @@ async-trait = "0.1.58"
 codec = { package = "parity-scale-codec", version = "3.6.1", features = ["derive"] }
 futures = "0.3.21"
 futures-timer = "3.0.2"
-libp2p = "0.51.3"
+libp2p = "0.52.1"
 log = "0.4.17"
 mockall = "0.11.3"
 prost = "0.11"
 schnellru = "0.2.1"
-smallvec = "1.8.0"
+smallvec = "1.11.0"
 thiserror = "1.0"
 fork-tree = { version = "3.0.0", path = "../../../utils/fork-tree" }
 prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.10.0-dev", path = "../../../utils/prometheus" }
diff --git a/substrate/client/network/test/Cargo.toml b/substrate/client/network/test/Cargo.toml
index ddd218051c4..c1c546e0458 100644
--- a/substrate/client/network/test/Cargo.toml
+++ b/substrate/client/network/test/Cargo.toml
@@ -17,7 +17,7 @@ tokio = "1.22.0"
 async-trait = "0.1.57"
 futures = "0.3.21"
 futures-timer = "3.0.1"
-libp2p = "0.51.3"
+libp2p = "0.52.1"
 log = "0.4.17"
 parking_lot = "0.12.1"
 rand = "0.8.5"
diff --git a/substrate/client/network/transactions/Cargo.toml b/substrate/client/network/transactions/Cargo.toml
index ce62c89e8a5..e212afe743e 100644
--- a/substrate/client/network/transactions/Cargo.toml
+++ b/substrate/client/network/transactions/Cargo.toml
@@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 array-bytes = "6.1"
 codec = { package = "parity-scale-codec", version = "3.6.1", features = ["derive"] }
 futures = "0.3.21"
-libp2p = "0.51.3"
+libp2p = "0.52.1"
 log = "0.4.17"
 prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.10.0-dev", path = "../../../utils/prometheus" }
 sc-network = { version = "0.10.0-dev", path = "../" }
diff --git a/substrate/client/network/transactions/src/lib.rs b/substrate/client/network/transactions/src/lib.rs
index 78fd432ab0c..5d86e3c35d8 100644
--- a/substrate/client/network/transactions/src/lib.rs
+++ b/substrate/client/network/transactions/src/lib.rs
@@ -327,8 +327,8 @@ where
 	fn handle_sync_event(&mut self, event: SyncEvent) {
 		match event {
 			SyncEvent::PeerConnected(remote) => {
-				let addr = iter::once(multiaddr::Protocol::P2p(remote.into()))
-					.collect::<multiaddr::Multiaddr>();
+				let addr =
+					iter::once(multiaddr::Protocol::P2p(remote)).collect::<multiaddr::Multiaddr>();
 				let result = self.network.add_peers_to_reserved_set(
 					self.protocol_name.clone(),
 					iter::once(addr).collect(),
diff --git a/substrate/client/offchain/Cargo.toml b/substrate/client/offchain/Cargo.toml
index f52b0aa2878..492b3ea3946 100644
--- a/substrate/client/offchain/Cargo.toml
+++ b/substrate/client/offchain/Cargo.toml
@@ -21,7 +21,7 @@ futures = "0.3.21"
 futures-timer = "3.0.2"
 hyper = { version = "0.14.16", features = ["stream", "http2"] }
 hyper-rustls = { version = "0.24.0", features = ["http2"] }
-libp2p = "0.51.3"
+libp2p = "0.52.1"
 num_cpus = "1.13"
 once_cell = "1.8"
 parking_lot = "0.12.1"
diff --git a/substrate/client/service/src/lib.rs b/substrate/client/service/src/lib.rs
index 0961967f9ca..7cb34890e53 100644
--- a/substrate/client/service/src/lib.rs
+++ b/substrate/client/service/src/lib.rs
@@ -255,7 +255,7 @@ pub async fn build_system_rpc_future<
 				let _ = sender.send(network_service.local_peer_id().to_base58());
 			},
 			sc_rpc::system::Request::LocalListenAddresses(sender) => {
-				let peer_id = (network_service.local_peer_id()).into();
+				let peer_id = network_service.local_peer_id();
 				let p2p_proto_suffix = sc_network::multiaddr::Protocol::P2p(peer_id);
 				let addresses = network_service
 					.listen_addresses()
diff --git a/substrate/client/telemetry/Cargo.toml b/substrate/client/telemetry/Cargo.toml
index f138557c8c2..c56f89517a4 100644
--- a/substrate/client/telemetry/Cargo.toml
+++ b/substrate/client/telemetry/Cargo.toml
@@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 [dependencies]
 chrono = "0.4.19"
 futures = "0.3.21"
-libp2p = { version = "0.51.3", features = ["dns", "tcp", "tokio", "wasm-ext", "websocket"] }
+libp2p = { version = "0.52.1", features = ["dns", "tcp", "tokio", "wasm-ext", "websocket"] }
 log = "0.4.17"
 parking_lot = "0.12.1"
 pin-project = "1.0.12"
diff --git a/substrate/frame/support/Cargo.toml b/substrate/frame/support/Cargo.toml
index 9139e19c01c..189014f4d4b 100644
--- a/substrate/frame/support/Cargo.toml
+++ b/substrate/frame/support/Cargo.toml
@@ -35,10 +35,10 @@ paste = "1.0"
 sp-state-machine = { version = "0.28.0", default-features = false, optional = true, path = "../../primitives/state-machine" }
 bitflags = "1.3"
 impl-trait-for-tuples = "0.2.2"
-smallvec = "1.8.0"
+smallvec = "1.11.0"
 log = { version = "0.4.17", default-features = false }
 sp-core-hashing-proc-macro = { version = "9.0.0", path = "../../primitives/core/hashing/proc-macro" }
-k256 = { version = "0.13.0", default-features = false, features = ["ecdsa"] }
+k256 = { version = "0.13.1", default-features = false, features = ["ecdsa"] }
 environmental = { version = "1.1.4", default-features = false }
 sp-genesis-builder = { version = "0.1.0", default-features=false, path = "../../primitives/genesis-builder" }
 serde_json = { version = "1.0.85", default-features = false, features = ["alloc"] }
diff --git a/substrate/primitives/core/hashing/Cargo.toml b/substrate/primitives/core/hashing/Cargo.toml
index 9b7fdabd3d4..43a13883358 100644
--- a/substrate/primitives/core/hashing/Cargo.toml
+++ b/substrate/primitives/core/hashing/Cargo.toml
@@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 blake2b_simd = { version = "1.0.1", default-features = false }
 byteorder = { version = "1.3.2", default-features = false }
 digest = { version = "0.10.3", default-features = false }
-sha2 = { version = "0.10.2", default-features = false }
+sha2 = { version = "0.10.7", default-features = false }
 sha3 = { version = "0.10.0", default-features = false }
 twox-hash = { version = "1.6.3", default-features = false, features = ["digest_0_10"] }
 
diff --git a/substrate/primitives/state-machine/Cargo.toml b/substrate/primitives/state-machine/Cargo.toml
index cffa4236c2a..302f05324c8 100644
--- a/substrate/primitives/state-machine/Cargo.toml
+++ b/substrate/primitives/state-machine/Cargo.toml
@@ -19,7 +19,7 @@ hash-db = { version = "0.16.0", default-features = false }
 log = { version = "0.4.17", default-features = false }
 parking_lot = { version = "0.12.1", optional = true }
 rand = { version = "0.8.5", optional = true }
-smallvec = "1.8.0"
+smallvec = "1.11.0"
 thiserror = { version = "1.0.30", optional = true }
 tracing = { version = "0.1.29", optional = true }
 sp-core = { version = "21.0.0", default-features = false, path = "../core" }
diff --git a/substrate/primitives/statement-store/Cargo.toml b/substrate/primitives/statement-store/Cargo.toml
index 02ee6f4c155..ea240e6e252 100644
--- a/substrate/primitives/statement-store/Cargo.toml
+++ b/substrate/primitives/statement-store/Cargo.toml
@@ -30,7 +30,7 @@ x25519-dalek = { version = "2.0.0-pre.1", optional = true }
 curve25519-dalek = { version = "3.2", optional = true }
 aes-gcm = { version = "0.10", optional = true }
 hkdf = { version = "0.12.0", optional = true }
-sha2 = { version = "0.10.0", optional = true }
+sha2 = { version = "0.10.7", optional = true }
 rand = { version = "0.8.5", features = ["small_rng"],  optional = true }
 
 [features]
diff --git a/substrate/primitives/weights/Cargo.toml b/substrate/primitives/weights/Cargo.toml
index 32c0d486cb1..05fc58a10e1 100644
--- a/substrate/primitives/weights/Cargo.toml
+++ b/substrate/primitives/weights/Cargo.toml
@@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive"] }
 scale-info = { version = "2.5.0", default-features = false, features = ["derive"] }
 serde = { version = "1.0.163", default-features = false, optional = true, features = ["derive", "alloc"] }
-smallvec = "1.8.0"
+smallvec = "1.11.0"
 sp-arithmetic = { version = "16.0.0", default-features = false, path = "../arithmetic" }
 sp-core = { version = "21.0.0", default-features = false, path = "../core" }
 sp-debug-derive = { version = "8.0.0", default-features = false, path = "../debug-derive" }
-- 
GitLab