From 7a2592e8458f8b3c5d9683eb02380a0f5959b5b3 Mon Sep 17 00:00:00 2001
From: Niklas Adolfsson <niklasadolfsson1@gmail.com>
Date: Wed, 26 Jun 2024 12:25:24 +0200
Subject: [PATCH] rpc: upgrade jsonrpsee v0.23 (#4730)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This is PR updates jsonrpsee v0.23 which mainly changes:
- Add `Extensions` which we now is using to get the connection id (used
by the rpc spec v2 impl)
- Update hyper to v1.0, http v1.0, soketto and related crates
(hyper::service::make_service_fn is removed)
- The subscription API for the client is modified to know why a
subscription was closed.

Full changelog here:
https://github.com/paritytech/jsonrpsee/releases/tag/v0.23.0

---------

Co-authored-by: Bastian Köcher <git@kchr.de>
---
 Cargo.lock                                    | 400 +++++++++++++-----
 Cargo.toml                                    |   7 +-
 bridges/relays/client-substrate/Cargo.toml    |   1 +
 .../src/client/subscription.rs                |   3 +-
 .../src/light_client_worker.rs                |   4 +-
 prdoc/pr_4730.prdoc                           |  25 ++
 substrate/client/rpc-servers/Cargo.toml       |  12 +-
 substrate/client/rpc-servers/src/lib.rs       |  82 ++--
 .../rpc-servers/src/middleware/node_health.rs |  42 +-
 substrate/client/rpc-servers/src/utils.rs     |  14 +-
 .../client/rpc-spec-v2/src/chain_head/api.rs  |  14 +-
 .../rpc-spec-v2/src/chain_head/chain_head.rs  |  86 ++--
 .../src/chain_head/subscription/inner.rs      |  15 +-
 .../rpc-spec-v2/src/common/connections.rs     |  45 +-
 .../client/rpc-spec-v2/src/transaction/api.rs |   4 +-
 .../src/transaction/transaction_broadcast.rs  |  24 +-
 substrate/client/rpc/src/utils.rs             |  31 +-
 .../frame/remote-externalities/src/lib.rs     |   7 +-
 18 files changed, 548 insertions(+), 268 deletions(-)
 create mode 100644 prdoc/pr_4730.prdoc

diff --git a/Cargo.lock b/Cargo.lock
index 5935e7ba730..537adb68792 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1307,7 +1307,7 @@ version = "0.24.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8d9a9bf8b79a749ee0b911b91b671cc2b6c670bdbc7e3dfd537576ddc94bb2a2"
 dependencies = [
- "http",
+ "http 0.2.9",
  "log",
  "url",
 ]
@@ -1414,6 +1414,12 @@ version = "0.21.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d"
 
+[[package]]
+name = "base64"
+version = "0.22.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
+
 [[package]]
 name = "base64ct"
 version = "1.6.0"
@@ -1536,9 +1542,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
 [[package]]
 name = "bitflags"
-version = "2.4.0"
+version = "2.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
+checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
 
 [[package]]
 name = "bitvec"
@@ -2491,6 +2497,12 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "cesu8"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
+
 [[package]]
 name = "cexpr"
 version = "0.6.0"
@@ -3207,9 +3219,9 @@ checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
 
 [[package]]
 name = "core-foundation"
-version = "0.9.3"
+version = "0.9.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
+checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
 dependencies = [
  "core-foundation-sys",
  "libc",
@@ -3217,9 +3229,9 @@ dependencies = [
 
 [[package]]
 name = "core-foundation-sys"
-version = "0.8.4"
+version = "0.8.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
+checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
 
 [[package]]
 name = "core2"
@@ -6548,7 +6560,26 @@ dependencies = [
  "futures-core",
  "futures-sink",
  "futures-util",
- "http",
+ "http 0.2.9",
+ "indexmap 2.2.3",
+ "slab",
+ "tokio",
+ "tokio-util",
+ "tracing",
+]
+
+[[package]]
+name = "h2"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab"
+dependencies = [
+ "atomic-waker",
+ "bytes",
+ "fnv",
+ "futures-core",
+ "futures-sink",
+ "http 1.1.0",
  "indexmap 2.2.3",
  "slab",
  "tokio",
@@ -6756,6 +6787,17 @@ dependencies = [
  "itoa",
 ]
 
+[[package]]
+name = "http"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258"
+dependencies = [
+ "bytes",
+ "fnv",
+ "itoa",
+]
+
 [[package]]
 name = "http-body"
 version = "0.4.5"
@@ -6763,15 +6805,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
 dependencies = [
  "bytes",
- "http",
+ "http 0.2.9",
  "pin-project-lite 0.2.12",
 ]
 
 [[package]]
-name = "http-range-header"
-version = "0.3.1"
+name = "http-body"
+version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f"
+checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643"
+dependencies = [
+ "bytes",
+ "http 1.1.0",
+]
+
+[[package]]
+name = "http-body-util"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f"
+dependencies = [
+ "bytes",
+ "futures-util",
+ "http 1.1.0",
+ "http-body 1.0.0",
+ "pin-project-lite 0.2.12",
+]
 
 [[package]]
 name = "httparse"
@@ -6801,9 +6860,9 @@ dependencies = [
  "futures-channel",
  "futures-core",
  "futures-util",
- "h2",
- "http",
- "http-body",
+ "h2 0.3.26",
+ "http 0.2.9",
+ "http-body 0.4.5",
  "httparse",
  "httpdate",
  "itoa",
@@ -6815,6 +6874,27 @@ dependencies = [
  "want",
 ]
 
+[[package]]
+name = "hyper"
+version = "1.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d"
+dependencies = [
+ "bytes",
+ "futures-channel",
+ "futures-util",
+ "h2 0.4.5",
+ "http 1.1.0",
+ "http-body 1.0.0",
+ "httparse",
+ "httpdate",
+ "itoa",
+ "pin-project-lite 0.2.12",
+ "smallvec",
+ "tokio",
+ "want",
+]
+
 [[package]]
 name = "hyper-rustls"
 version = "0.24.1"
@@ -6822,8 +6902,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97"
 dependencies = [
  "futures-util",
- "http",
- "hyper",
+ "http 0.2.9",
+ "hyper 0.14.27",
  "log",
  "rustls 0.21.7",
  "rustls-native-certs 0.6.3",
@@ -6831,6 +6911,44 @@ dependencies = [
  "tokio-rustls 0.24.1",
 ]
 
+[[package]]
+name = "hyper-rustls"
+version = "0.27.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155"
+dependencies = [
+ "futures-util",
+ "http 1.1.0",
+ "hyper 1.3.1",
+ "hyper-util",
+ "log",
+ "rustls 0.23.10",
+ "rustls-pki-types",
+ "tokio",
+ "tokio-rustls 0.26.0",
+ "tower-service",
+]
+
+[[package]]
+name = "hyper-util"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56"
+dependencies = [
+ "bytes",
+ "futures-channel",
+ "futures-util",
+ "http 1.1.0",
+ "http-body 1.0.0",
+ "hyper 1.3.1",
+ "pin-project-lite 0.2.12",
+ "socket2 0.5.6",
+ "tokio",
+ "tower",
+ "tower-service",
+ "tracing",
+]
+
 [[package]]
 name = "iana-time-zone"
 version = "0.1.57"
@@ -6914,8 +7032,8 @@ dependencies = [
  "attohttpc",
  "bytes",
  "futures",
- "http",
- "hyper",
+ "http 0.2.9",
+ "hyper 0.14.27",
  "log",
  "rand 0.8.5",
  "tokio",
@@ -7139,7 +7257,7 @@ dependencies = [
  "encoding_rs",
  "event-listener 2.5.3",
  "futures-lite 1.13.0",
- "http",
+ "http 0.2.9",
  "log",
  "mime",
  "once_cell",
@@ -7176,6 +7294,26 @@ version = "1.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
 
+[[package]]
+name = "jni"
+version = "0.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec"
+dependencies = [
+ "cesu8",
+ "combine",
+ "jni-sys",
+ "log",
+ "thiserror",
+ "walkdir",
+]
+
+[[package]]
+name = "jni-sys"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
+
 [[package]]
 name = "jobserver"
 version = "0.1.26"
@@ -7213,9 +7351,9 @@ dependencies = [
 
 [[package]]
 name = "jsonrpsee"
-version = "0.22.5"
+version = "0.23.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cfdb12a2381ea5b2e68c3469ec604a007b367778cdb14d09612c8069ebd616ad"
+checksum = "62b089779ad7f80768693755a031cc14a7766aba707cbe886674e3f79e9b7e47"
 dependencies = [
  "jsonrpsee-core",
  "jsonrpsee-http-client",
@@ -7229,20 +7367,22 @@ dependencies = [
 
 [[package]]
 name = "jsonrpsee-client-transport"
-version = "0.22.5"
+version = "0.23.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4978087a58c3ab02efc5b07c5e5e2803024536106fd5506f558db172c889b3aa"
+checksum = "08163edd8bcc466c33d79e10f695cdc98c00d1e6ddfb95cec41b6b0279dd5432"
 dependencies = [
+ "base64 0.22.1",
  "futures-util",
- "http",
+ "http 1.1.0",
  "jsonrpsee-core",
  "pin-project",
- "rustls-native-certs 0.7.0",
+ "rustls 0.23.10",
  "rustls-pki-types",
- "soketto",
+ "rustls-platform-verifier",
+ "soketto 0.8.0",
  "thiserror",
  "tokio",
- "tokio-rustls 0.25.0",
+ "tokio-rustls 0.26.0",
  "tokio-util",
  "tracing",
  "url",
@@ -7250,16 +7390,19 @@ dependencies = [
 
 [[package]]
 name = "jsonrpsee-core"
-version = "0.22.5"
+version = "0.23.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4b257e1ec385e07b0255dde0b933f948b5c8b8c28d42afda9587c3a967b896d"
+checksum = "79712302e737d23ca0daa178e752c9334846b08321d439fd89af9a384f8c830b"
 dependencies = [
  "anyhow",
  "async-trait",
  "beef",
+ "bytes",
  "futures-timer",
  "futures-util",
- "hyper",
+ "http 1.1.0",
+ "http-body 1.0.0",
+ "http-body-util",
  "jsonrpsee-types",
  "parking_lot 0.12.1",
  "pin-project",
@@ -7275,15 +7418,20 @@ dependencies = [
 
 [[package]]
 name = "jsonrpsee-http-client"
-version = "0.22.5"
+version = "0.23.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ccf93fc4a0bfe05d851d37d7c32b7f370fe94336b52a2f0efc5f1981895c2e5"
+checksum = "2d90064e04fb9d7282b1c71044ea94d0bbc6eff5621c66f1a0bce9e9de7cf3ac"
 dependencies = [
  "async-trait",
- "hyper",
- "hyper-rustls",
+ "base64 0.22.1",
+ "http-body 1.0.0",
+ "hyper 1.3.1",
+ "hyper-rustls 0.27.2",
+ "hyper-util",
  "jsonrpsee-core",
  "jsonrpsee-types",
+ "rustls 0.23.10",
+ "rustls-platform-verifier",
  "serde",
  "serde_json",
  "thiserror",
@@ -7295,11 +7443,11 @@ dependencies = [
 
 [[package]]
 name = "jsonrpsee-proc-macros"
-version = "0.22.5"
+version = "0.23.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d0bb047e79a143b32ea03974a6bf59b62c2a4c5f5d42a381c907a8bbb3f75c0"
+checksum = "7895f186d5921065d96e16bd795e5ca89ac8356ec423fafc6e3d7cf8ec11aee4"
 dependencies = [
- "heck 0.4.1",
+ "heck 0.5.0",
  "proc-macro-crate 3.1.0",
  "proc-macro2 1.0.82",
  "quote 1.0.35",
@@ -7308,20 +7456,24 @@ dependencies = [
 
 [[package]]
 name = "jsonrpsee-server"
-version = "0.22.5"
+version = "0.23.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12d8b6a9674422a8572e0b0abb12feeb3f2aeda86528c80d0350c2bd0923ab41"
+checksum = "654afab2e92e5d88ebd8a39d6074483f3f2bfdf91c5ac57fe285e7127cdd4f51"
 dependencies = [
+ "anyhow",
  "futures-util",
- "http",
- "hyper",
+ "http 1.1.0",
+ "http-body 1.0.0",
+ "http-body-util",
+ "hyper 1.3.1",
+ "hyper-util",
  "jsonrpsee-core",
  "jsonrpsee-types",
  "pin-project",
  "route-recognizer",
  "serde",
  "serde_json",
- "soketto",
+ "soketto 0.8.0",
  "thiserror",
  "tokio",
  "tokio-stream",
@@ -7332,12 +7484,12 @@ dependencies = [
 
 [[package]]
 name = "jsonrpsee-types"
-version = "0.22.5"
+version = "0.23.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "150d6168405890a7a3231a3c74843f58b8959471f6df76078db2619ddee1d07d"
+checksum = "d9c465fbe385238e861fdc4d1c85e04ada6c1fd246161d26385c1b311724d2af"
 dependencies = [
- "anyhow",
  "beef",
+ "http 1.1.0",
  "serde",
  "serde_json",
  "thiserror",
@@ -7345,11 +7497,11 @@ dependencies = [
 
 [[package]]
 name = "jsonrpsee-ws-client"
-version = "0.22.5"
+version = "0.23.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58b9db2dfd5bb1194b0ce921504df9ceae210a345bc2f6c5a61432089bbab070"
+checksum = "1c28759775f5cb2f1ea9667672d3fe2b0e701d1f4b7b67954e60afe7fd058b5e"
 dependencies = [
- "http",
+ "http 1.1.0",
  "jsonrpsee-client-transport",
  "jsonrpsee-core",
  "jsonrpsee-types",
@@ -7971,9 +8123,9 @@ dependencies = [
  "parking_lot 0.12.1",
  "quicksink",
  "rw-stream-sink",
- "soketto",
+ "soketto 0.7.1",
  "url",
- "webpki-roots",
+ "webpki-roots 0.25.2",
 ]
 
 [[package]]
@@ -8999,7 +9151,7 @@ version = "0.28.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
 dependencies = [
- "bitflags 2.4.0",
+ "bitflags 2.6.0",
  "cfg-if",
  "cfg_aliases",
  "libc",
@@ -9407,7 +9559,7 @@ version = "0.10.64"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f"
 dependencies = [
- "bitflags 2.4.0",
+ "bitflags 2.6.0",
  "cfg-if",
  "foreign-types",
  "libc",
@@ -13541,7 +13693,7 @@ dependencies = [
  "bs58 0.5.0",
  "futures",
  "futures-timer",
- "hyper",
+ "hyper 0.14.27",
  "log",
  "parity-scale-codec",
  "polkadot-primitives",
@@ -15359,7 +15511,7 @@ version = "0.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "731e0d9356b0c25f16f33b5be79b1c57b562f141ebfcdb0ad8ac2c13a24293b4"
 dependencies = [
- "bitflags 2.4.0",
+ "bitflags 2.6.0",
  "chrono",
  "flate2",
  "hex",
@@ -15374,7 +15526,7 @@ version = "0.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2d3554923a69f4ce04c4a754260c338f505ce22642d3830e049a399fc2059a29"
 dependencies = [
- "bitflags 2.4.0",
+ "bitflags 2.6.0",
  "chrono",
  "hex",
 ]
@@ -15436,7 +15588,7 @@ checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf"
 dependencies = [
  "bit-set",
  "bit-vec",
- "bitflags 2.4.0",
+ "bitflags 2.6.0",
  "lazy_static",
  "num-traits",
  "rand 0.8.5",
@@ -16139,6 +16291,7 @@ dependencies = [
  "sc-rpc-api",
  "sc-transaction-pool-api",
  "scale-info",
+ "serde_json",
  "sp-consensus-grandpa",
  "sp-core",
  "sp-rpc",
@@ -16203,11 +16356,11 @@ dependencies = [
  "encoding_rs",
  "futures-core",
  "futures-util",
- "h2",
- "http",
- "http-body",
- "hyper",
- "hyper-rustls",
+ "h2 0.3.26",
+ "http 0.2.9",
+ "http-body 0.4.5",
+ "hyper 0.14.27",
+ "hyper-rustls 0.24.1",
  "ipnet",
  "js-sys",
  "log",
@@ -16227,7 +16380,7 @@ dependencies = [
  "wasm-bindgen",
  "wasm-bindgen-futures",
  "web-sys",
- "webpki-roots",
+ "webpki-roots 0.25.2",
  "winreg",
 ]
 
@@ -16727,7 +16880,7 @@ version = "0.38.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3"
 dependencies = [
- "bitflags 2.4.0",
+ "bitflags 2.6.0",
  "errno",
  "libc",
  "linux-raw-sys 0.4.10",
@@ -16759,14 +16912,15 @@ dependencies = [
 
 [[package]]
 name = "rustls"
-version = "0.22.2"
+version = "0.23.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e87c9956bd9807afa1f77e0f7594af32566e830e088a5576d27c5b6f30f49d41"
+checksum = "05cff451f60db80f490f3c182b77c35260baace73209e9cdbbe526bfe3a4d402"
 dependencies = [
  "log",
+ "once_cell",
  "ring 0.17.7",
  "rustls-pki-types",
- "rustls-webpki 0.102.2",
+ "rustls-webpki 0.102.4",
  "subtle 2.5.0",
  "zeroize",
 ]
@@ -16817,9 +16971,36 @@ dependencies = [
 
 [[package]]
 name = "rustls-pki-types"
-version = "1.2.0"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d"
+
+[[package]]
+name = "rustls-platform-verifier"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5f0d26fa1ce3c790f9590868f0109289a044acb954525f933e2aa3b871c157d"
+dependencies = [
+ "core-foundation",
+ "core-foundation-sys",
+ "jni",
+ "log",
+ "once_cell",
+ "rustls 0.23.10",
+ "rustls-native-certs 0.7.0",
+ "rustls-platform-verifier-android",
+ "rustls-webpki 0.102.4",
+ "security-framework",
+ "security-framework-sys",
+ "webpki-roots 0.26.3",
+ "winapi",
+]
+
+[[package]]
+name = "rustls-platform-verifier-android"
+version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0a716eb65e3158e90e17cd93d855216e27bde02745ab842f2cab4a39dba1bacf"
+checksum = "84e217e7fdc8466b5b35d30f8c0a30febd29173df4a3a0c2115d306b9c4117ad"
 
 [[package]]
 name = "rustls-webpki"
@@ -16833,9 +17014,9 @@ dependencies = [
 
 [[package]]
 name = "rustls-webpki"
-version = "0.102.2"
+version = "0.102.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610"
+checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e"
 dependencies = [
  "ring 0.17.7",
  "rustls-pki-types",
@@ -17919,8 +18100,8 @@ dependencies = [
  "fnv",
  "futures",
  "futures-timer",
- "hyper",
- "hyper-rustls",
+ "hyper 0.14.27",
+ "hyper-rustls 0.24.1",
  "lazy_static",
  "log",
  "num_cpus",
@@ -18027,8 +18208,9 @@ dependencies = [
  "forwarded-header-value",
  "futures",
  "governor",
- "http",
- "hyper",
+ "http 1.1.0",
+ "http-body-util",
+ "hyper 1.3.1",
  "ip_network",
  "jsonrpsee",
  "log",
@@ -18631,22 +18813,23 @@ dependencies = [
 
 [[package]]
 name = "security-framework"
-version = "2.9.2"
+version = "2.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de"
+checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0"
 dependencies = [
- "bitflags 1.3.2",
+ "bitflags 2.6.0",
  "core-foundation",
  "core-foundation-sys",
  "libc",
+ "num-bigint",
  "security-framework-sys",
 ]
 
 [[package]]
 name = "security-framework-sys"
-version = "2.9.1"
+version = "2.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a"
+checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7"
 dependencies = [
  "core-foundation-sys",
  "libc",
@@ -19074,7 +19257,7 @@ version = "0.5.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cae9a3fcdadafb6d97f4c0e007e4247b114ee0f119f650c3cbf3a8b3a1479694"
 dependencies = [
- "bitflags 2.4.0",
+ "bitflags 2.6.0",
 ]
 
 [[package]]
@@ -19219,7 +19402,7 @@ dependencies = [
  "siphasher",
  "slab",
  "smallvec",
- "soketto",
+ "soketto 0.7.1",
  "twox-hash",
  "wasmi 0.31.2",
  "x25519-dalek",
@@ -19634,13 +19817,28 @@ dependencies = [
  "base64 0.13.1",
  "bytes",
  "futures",
- "http",
  "httparse",
  "log",
  "rand 0.8.5",
  "sha-1 0.9.8",
 ]
 
+[[package]]
+name = "soketto"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37468c595637c10857701c990f93a40ce0e357cedb0953d1c26c8d8027f9bb53"
+dependencies = [
+ "base64 0.22.1",
+ "bytes",
+ "futures",
+ "http 1.1.0",
+ "httparse",
+ "log",
+ "rand 0.8.5",
+ "sha1",
+]
+
 [[package]]
 name = "solochain-template-node"
 version = "0.0.0"
@@ -20869,7 +21067,7 @@ dependencies = [
  "scale-info",
  "serde",
  "serde_json",
- "soketto",
+ "soketto 0.7.1",
  "staging-node-inspect",
  "substrate-cli-test-utils",
  "tempfile",
@@ -21241,7 +21439,7 @@ dependencies = [
 name = "substrate-prometheus-endpoint"
 version = "0.17.0"
 dependencies = [
- "hyper",
+ "hyper 0.14.27",
  "log",
  "prometheus",
  "thiserror",
@@ -22120,11 +22318,11 @@ dependencies = [
 
 [[package]]
 name = "tokio-rustls"
-version = "0.25.0"
+version = "0.26.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f"
+checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4"
 dependencies = [
- "rustls 0.22.2",
+ "rustls 0.23.10",
  "rustls-pki-types",
  "tokio",
 ]
@@ -22247,6 +22445,7 @@ dependencies = [
  "futures-util",
  "pin-project",
  "pin-project-lite 0.2.12",
+ "tokio",
  "tower-layer",
  "tower-service",
  "tracing",
@@ -22254,17 +22453,15 @@ dependencies = [
 
 [[package]]
 name = "tower-http"
-version = "0.4.3"
+version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55ae70283aba8d2a8b411c695c437fe25b8b5e44e23e780662002fc72fb47a82"
+checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5"
 dependencies = [
- "bitflags 2.4.0",
+ "bitflags 2.6.0",
  "bytes",
- "futures-core",
- "futures-util",
- "http",
- "http-body",
- "http-range-header",
+ "http 1.1.0",
+ "http-body 1.0.0",
+ "http-body-util",
  "pin-project-lite 0.2.12",
  "tower-layer",
  "tower-service",
@@ -22577,7 +22774,7 @@ dependencies = [
  "byteorder",
  "bytes",
  "data-encoding",
- "http",
+ "http 0.2.9",
  "httparse",
  "log",
  "rand 0.8.5",
@@ -23384,6 +23581,15 @@ version = "0.25.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc"
 
+[[package]]
+name = "webpki-roots"
+version = "0.26.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd"
+dependencies = [
+ "rustls-pki-types",
+]
+
 [[package]]
 name = "westend-emulated-chain"
 version = "0.0.0"
diff --git a/Cargo.toml b/Cargo.toml
index 7eea70c31aa..9ddfedd5155 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -780,6 +780,7 @@ hkdf = { version = "0.12.0" }
 hmac = { version = "0.12.1" }
 honggfuzz = { version = "0.5.55" }
 http = { version = "0.2.8" }
+http-body-util = { version = "0.1.2" }
 hyper = { version = "0.14.27", default-features = false }
 hyper-rustls = { version = "0.24.0" }
 impl-serde = { version = "0.4.0", default-features = false }
@@ -793,8 +794,8 @@ is_executable = { version = "1.0.1" }
 isahc = { version = "1.2" }
 itertools = { version = "0.11" }
 jsonpath_lib = { version = "0.3" }
-jsonrpsee = { version = "0.22.5" }
-jsonrpsee-core = { version = "0.22" }
+jsonrpsee = { version = "0.23.2" }
+jsonrpsee-core = { version = "0.23.2" }
 k256 = { version = "0.13.3", default-features = false }
 kitchensink-runtime = { path = "substrate/bin/node/runtime" }
 kvdb = { version = "0.13.0" }
@@ -1298,7 +1299,7 @@ tokio-util = { version = "0.7.8" }
 toml = { version = "0.8.8" }
 toml_edit = { version = "0.19" }
 tower = { version = "0.4.13" }
-tower-http = { version = "0.4.0" }
+tower-http = { version = "0.5.2" }
 tracing = { version = "0.1.37", default-features = false }
 tracing-core = { version = "0.1.32", default-features = false }
 tracing-futures = { version = "0.2.4" }
diff --git a/bridges/relays/client-substrate/Cargo.toml b/bridges/relays/client-substrate/Cargo.toml
index 6db4f3e9ef6..66501d03691 100644
--- a/bridges/relays/client-substrate/Cargo.toml
+++ b/bridges/relays/client-substrate/Cargo.toml
@@ -19,6 +19,7 @@ jsonrpsee = { features = ["macros", "ws-client"], workspace = true }
 log = { workspace = true }
 num-traits = { workspace = true, default-features = true }
 rand = { workspace = true, default-features = true }
+serde_json = { workspace = true }
 scale-info = { features = ["derive"], workspace = true, default-features = true }
 tokio = { features = ["rt-multi-thread"], workspace = true, default-features = true }
 thiserror = { workspace = true }
diff --git a/bridges/relays/client-substrate/src/client/subscription.rs b/bridges/relays/client-substrate/src/client/subscription.rs
index 43a46573f98..9f08097cb58 100644
--- a/bridges/relays/client-substrate/src/client/subscription.rs
+++ b/bridges/relays/client-substrate/src/client/subscription.rs
@@ -21,7 +21,6 @@ use async_std::{
 	stream::StreamExt,
 };
 use futures::{FutureExt, Stream};
-use jsonrpsee::core::ClientError;
 use sp_runtime::DeserializeOwned;
 use std::{
 	fmt::Debug,
@@ -143,7 +142,7 @@ impl<T: 'static + Clone + DeserializeOwned + Send> Subscription<T> {
 	/// Create new forwarded subscription.
 	pub fn new_forwarded(
 		desc: StreamDescription,
-		subscription: impl Stream<Item = StdResult<T, ClientError>> + Unpin + Send + 'static,
+		subscription: impl Stream<Item = StdResult<T, serde_json::Error>> + Unpin + Send + 'static,
 	) -> Self {
 		Self {
 			desc: desc.clone(),
diff --git a/cumulus/client/relay-chain-rpc-interface/src/light_client_worker.rs b/cumulus/client/relay-chain-rpc-interface/src/light_client_worker.rs
index 9a49b60281b..2347dbb85f7 100644
--- a/cumulus/client/relay-chain-rpc-interface/src/light_client_worker.rs
+++ b/cumulus/client/relay-chain-rpc-interface/src/light_client_worker.rs
@@ -20,7 +20,7 @@
 
 use futures::{channel::mpsc::Sender, prelude::*, stream::FuturesUnordered};
 use jsonrpsee::core::client::{
-	Client as JsonRpseeClient, ClientBuilder, ClientT, Error, ReceivedMessage, TransportReceiverT,
+	Client as JsonRpseeClient, ClientBuilder, ClientT, ReceivedMessage, TransportReceiverT,
 	TransportSenderT,
 };
 use smoldot_light::{ChainId, Client as SmoldotClient, JsonRpcResponses};
@@ -124,7 +124,7 @@ pub struct LightClientRpcWorker {
 }
 
 fn handle_notification(
-	maybe_header: Option<Result<RelayHeader, Error>>,
+	maybe_header: Option<Result<RelayHeader, serde_json::Error>>,
 	senders: &mut Vec<Sender<RelayHeader>>,
 ) -> Result<(), ()> {
 	match maybe_header {
diff --git a/prdoc/pr_4730.prdoc b/prdoc/pr_4730.prdoc
new file mode 100644
index 00000000000..9af14534bcb
--- /dev/null
+++ b/prdoc/pr_4730.prdoc
@@ -0,0 +1,25 @@
+# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0
+# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json
+
+title: rpc upgrade jsonrpsee to v0.23.1
+
+doc:
+  - audience: Node Dev
+    description: |
+      Upgrade the rpc library jsonrpsee to v0.23.1 to utilize:
+
+      - Add Extensions which we now is using to get the connection id (used by the rpc spec v2)
+      - Update hyper to v1.0, http v1.0, soketto and related crates (hyper::service::make_service_fn is removed)
+      - The subscription API for the client is modified to know why a subscription was closed.
+
+crates:
+  - name: sc-rpc-spec-v2
+    bump: patch
+  - name: sc-rpc
+    bump: patch
+  - name: sc-rpc-server
+    bump: patch
+  - name: cumulus-relay-chain-rpc-interface
+    bump: patch
+  - name: frame-remote-externalities
+    bump: patch
diff --git a/substrate/client/rpc-servers/Cargo.toml b/substrate/client/rpc-servers/Cargo.toml
index d5b76b70c94..7986408d2b2 100644
--- a/substrate/client/rpc-servers/Cargo.toml
+++ b/substrate/client/rpc-servers/Cargo.toml
@@ -19,8 +19,7 @@ targets = ["x86_64-unknown-linux-gnu"]
 forwarded-header-value = { workspace = true }
 futures = { workspace = true }
 governor = { workspace = true }
-http = { workspace = true }
-hyper = { workspace = true, default-features = true }
+http-body-util = { workspace = true }
 ip_network = { workspace = true }
 jsonrpsee = { features = ["server"], workspace = true }
 log = { workspace = true, default-features = true }
@@ -28,5 +27,10 @@ prometheus-endpoint = { workspace = true, default-features = true }
 serde = { workspace = true }
 serde_json = { workspace = true, default-features = true }
 tokio = { features = ["parking_lot"], workspace = true, default-features = true }
-tower = { features = ["util"], workspace = true }
-tower-http = { features = ["cors"], workspace = true }
+tower = { workspace = true, features = ["util"] }
+tower-http = { workspace = true, features = ["cors"] }
+
+# Dependencies outside of the polkadot-sdk workspace
+# which requires hyper v1 and http v1
+http = "1.1"
+hyper = "1.3"
diff --git a/substrate/client/rpc-servers/src/lib.rs b/substrate/client/rpc-servers/src/lib.rs
index 647a7ca7e43..619498b3333 100644
--- a/substrate/client/rpc-servers/src/lib.rs
+++ b/substrate/client/rpc-servers/src/lib.rs
@@ -23,16 +23,13 @@
 pub mod middleware;
 pub mod utils;
 
-use std::{
-	convert::Infallible, error::Error as StdError, net::SocketAddr, num::NonZeroU32, time::Duration,
-};
+use std::{error::Error as StdError, net::SocketAddr, num::NonZeroU32, sync::Arc, time::Duration};
 
-use hyper::{
-	server::conn::AddrStream,
-	service::{make_service_fn, service_fn},
-};
 use jsonrpsee::{
-	server::{stop_channel, ws, PingConfig, StopHandle, TowerServiceBuilder},
+	core::BoxError,
+	server::{
+		serve_with_graceful_shutdown, stop_channel, ws, PingConfig, StopHandle, TowerServiceBuilder,
+	},
 	Methods, RpcModule,
 };
 use middleware::NodeHealthProxyLayer;
@@ -97,6 +94,7 @@ struct PerConnection<RpcMiddleware, HttpMiddleware> {
 	metrics: Option<RpcMetrics>,
 	tokio_handle: tokio::runtime::Handle,
 	service_builder: TowerServiceBuilder<RpcMiddleware, HttpMiddleware>,
+	rate_limit_whitelisted_ips: Arc<Vec<IpNetwork>>,
 }
 
 /// Start RPC server listening on given address.
@@ -124,8 +122,8 @@ where
 		rate_limit_trust_proxy_headers,
 	} = config;
 
-	let std_listener = TcpListener::bind(addrs.as_slice()).await?.into_std()?;
-	let local_addr = std_listener.local_addr().ok();
+	let listener = TcpListener::bind(addrs.as_slice()).await?;
+	let local_addr = listener.local_addr().ok();
 	let host_filter = host_filtering(cors.is_some(), local_addr);
 
 	let http_middleware = tower::ServiceBuilder::new()
@@ -161,20 +159,38 @@ where
 		methods: build_rpc_api(rpc_api).into(),
 		service_builder: builder.to_service_builder(),
 		metrics,
-		tokio_handle,
-		stop_handle: stop_handle.clone(),
+		tokio_handle: tokio_handle.clone(),
+		stop_handle,
+		rate_limit_whitelisted_ips: Arc::new(rate_limit_whitelisted_ips),
 	};
 
-	let make_service = make_service_fn(move |addr: &AddrStream| {
-		let cfg = cfg.clone();
-		let rate_limit_whitelisted_ips = rate_limit_whitelisted_ips.clone();
-		let ip = addr.remote_addr().ip();
-
-		async move {
-			let cfg = cfg.clone();
-			let rate_limit_whitelisted_ips = rate_limit_whitelisted_ips.clone();
+	tokio_handle.spawn(async move {
+		loop {
+			let (sock, remote_addr) = tokio::select! {
+				res = listener.accept() => {
+					match res {
+						Ok(s) => s,
+						Err(e) => {
+							log::debug!(target: "rpc", "Failed to accept ipv4 connection: {:?}", e);
+							continue;
+						}
+					}
+				}
+				_ = cfg.stop_handle.clone().shutdown() => break,
+			};
+
+			let ip = remote_addr.ip();
+			let cfg2 = cfg.clone();
+			let svc = tower::service_fn(move |req: http::Request<hyper::body::Incoming>| {
+				let PerConnection {
+					methods,
+					service_builder,
+					metrics,
+					tokio_handle,
+					stop_handle,
+					rate_limit_whitelisted_ips,
+				} = cfg2.clone();
 
-			Ok::<_, Infallible>(service_fn(move |req| {
 				let proxy_ip =
 					if rate_limit_trust_proxy_headers { get_proxy_ip(&req) } else { None };
 
@@ -191,9 +207,6 @@ where
 					rate_limit
 				};
 
-				let PerConnection { service_builder, metrics, tokio_handle, stop_handle, methods } =
-					cfg.clone();
-
 				let is_websocket = ws::is_upgrade_request(&req);
 				let transport_label = if is_websocket { "ws" } else { "http" };
 
@@ -213,7 +226,6 @@ where
 
 				let rpc_middleware =
 					RpcServiceBuilder::new().option_layer(middleware_layer.clone());
-
 				let mut svc =
 					service_builder.set_rpc_middleware(rpc_middleware).build(methods, stop_handle);
 
@@ -230,17 +242,19 @@ where
 						});
 					}
 
-					svc.call(req).await
+					// https://github.com/rust-lang/rust/issues/102211 the error type can't be inferred
+					// to be `Box<dyn std::error::Error + Send + Sync>` so we need to convert it to
+					// a concrete type as workaround.
+					svc.call(req).await.map_err(|e| BoxError::from(e))
 				}
-			}))
-		}
-	});
-
-	let server = hyper::Server::from_tcp(std_listener)?.serve(make_service);
+			});
 
-	tokio::spawn(async move {
-		let graceful = server.with_graceful_shutdown(async move { stop_handle.shutdown().await });
-		let _ = graceful.await;
+			cfg.tokio_handle.spawn(serve_with_graceful_shutdown(
+				sock,
+				svc,
+				cfg.stop_handle.clone().shutdown(),
+			));
+		}
 	});
 
 	log::info!(
diff --git a/substrate/client/rpc-servers/src/middleware/node_health.rs b/substrate/client/rpc-servers/src/middleware/node_health.rs
index d68ec14cb8f..69c9e0829ac 100644
--- a/substrate/client/rpc-servers/src/middleware/node_health.rs
+++ b/substrate/client/rpc-servers/src/middleware/node_health.rs
@@ -27,8 +27,10 @@ use std::{
 
 use futures::future::FutureExt;
 use http::{HeaderValue, Method, StatusCode, Uri};
-use hyper::Body;
-use jsonrpsee::types::{Response as RpcResponse, ResponseSuccess as RpcResponseSuccess};
+use jsonrpsee::{
+	server::{HttpBody, HttpRequest, HttpResponse},
+	types::{Response as RpcResponse, ResponseSuccess as RpcResponseSuccess},
+};
 use tower::Service;
 
 const RPC_SYSTEM_HEALTH_CALL: &str = r#"{"jsonrpc":"2.0","method":"system_health","id":0}"#;
@@ -57,9 +59,9 @@ impl<S> NodeHealthProxy<S> {
 	}
 }
 
-impl<S> tower::Service<http::Request<Body>> for NodeHealthProxy<S>
+impl<S> tower::Service<http::Request<hyper::body::Incoming>> for NodeHealthProxy<S>
 where
-	S: Service<http::Request<Body>, Response = http::Response<Body>>,
+	S: Service<HttpRequest, Response = HttpResponse>,
 	S::Response: 'static,
 	S::Error: Into<Box<dyn Error + Send + Sync>> + 'static,
 	S::Future: Send + 'static,
@@ -73,7 +75,8 @@ where
 		self.0.poll_ready(cx).map_err(Into::into)
 	}
 
-	fn call(&mut self, mut req: http::Request<Body>) -> Self::Future {
+	fn call(&mut self, req: http::Request<hyper::body::Incoming>) -> Self::Future {
+		let mut req = req.map(|body| HttpBody::new(body));
 		let maybe_intercept = InterceptRequest::from_http(&req);
 
 		// Modify the request and proxy it to `system_health`
@@ -88,7 +91,7 @@ where
 			req.headers_mut().insert(http::header::ACCEPT, HEADER_VALUE_JSON);
 
 			// Adjust the body to reflect the method call.
-			req = req.map(|_| Body::from(RPC_SYSTEM_HEALTH_CALL));
+			req = req.map(|_| HttpBody::from(RPC_SYSTEM_HEALTH_CALL));
 		}
 
 		// Call the inner service and get a future that resolves to the response.
@@ -99,7 +102,7 @@ where
 
 			Ok(match maybe_intercept {
 				InterceptRequest::Deny =>
-					http_response(StatusCode::METHOD_NOT_ALLOWED, Body::empty()),
+					http_response(StatusCode::METHOD_NOT_ALLOWED, HttpBody::empty()),
 				InterceptRequest::No => res,
 				InterceptRequest::Health => {
 					let health = parse_rpc_response(res.into_body()).await?;
@@ -108,7 +111,7 @@ where
 				InterceptRequest::Readiness => {
 					let health = parse_rpc_response(res.into_body()).await?;
 					if (!health.is_syncing && health.peers > 0) || !health.should_have_peers {
-						http_ok_response(Body::empty())
+						http_ok_response(HttpBody::empty())
 					} else {
 						http_internal_error()
 					}
@@ -133,27 +136,28 @@ struct Health {
 	pub should_have_peers: bool,
 }
 
-fn http_ok_response<S: Into<hyper::Body>>(body: S) -> hyper::Response<hyper::Body> {
+fn http_ok_response<S: Into<HttpBody>>(body: S) -> HttpResponse {
 	http_response(StatusCode::OK, body)
 }
 
-fn http_response<S: Into<hyper::Body>>(
-	status_code: StatusCode,
-	body: S,
-) -> hyper::Response<hyper::Body> {
-	hyper::Response::builder()
+fn http_response<S: Into<HttpBody>>(status_code: StatusCode, body: S) -> HttpResponse {
+	HttpResponse::builder()
 		.status(status_code)
 		.header(http::header::CONTENT_TYPE, HEADER_VALUE_JSON)
 		.body(body.into())
 		.expect("Header is valid; qed")
 }
 
-fn http_internal_error() -> hyper::Response<hyper::Body> {
-	http_response(hyper::StatusCode::INTERNAL_SERVER_ERROR, Body::empty())
+fn http_internal_error() -> HttpResponse {
+	http_response(hyper::StatusCode::INTERNAL_SERVER_ERROR, HttpBody::empty())
 }
 
-async fn parse_rpc_response(body: Body) -> Result<Health, Box<dyn Error + Send + Sync + 'static>> {
-	let bytes = hyper::body::to_bytes(body).await?;
+async fn parse_rpc_response(
+	body: HttpBody,
+) -> Result<Health, Box<dyn Error + Send + Sync + 'static>> {
+	use http_body_util::BodyExt;
+
+	let bytes = body.collect().await?.to_bytes();
 
 	let raw_rp = serde_json::from_slice::<RpcResponse<Health>>(&bytes)?;
 	let rp = RpcResponseSuccess::<Health>::try_from(raw_rp)?;
@@ -178,7 +182,7 @@ enum InterceptRequest {
 }
 
 impl InterceptRequest {
-	fn from_http(req: &http::Request<Body>) -> InterceptRequest {
+	fn from_http(req: &HttpRequest) -> InterceptRequest {
 		match req.uri().path() {
 			"/health" =>
 				if req.method() == http::Method::GET {
diff --git a/substrate/client/rpc-servers/src/utils.rs b/substrate/client/rpc-servers/src/utils.rs
index d99b8e637d9..d9d943c7c1f 100644
--- a/substrate/client/rpc-servers/src/utils.rs
+++ b/substrate/client/rpc-servers/src/utils.rs
@@ -25,10 +25,7 @@ use std::{
 };
 
 use forwarded_header_value::ForwardedHeaderValue;
-use hyper::{
-	header::{HeaderName, HeaderValue},
-	Request,
-};
+use http::header::{HeaderName, HeaderValue};
 use jsonrpsee::{server::middleware::http::HostFilterLayer, RpcModule};
 use tower_http::cors::{AllowOrigin, CorsLayer};
 
@@ -57,7 +54,7 @@ pub(crate) fn build_rpc_api<M: Send + Sync + 'static>(mut rpc_api: RpcModule<M>)
 	available_methods.sort();
 
 	rpc_api
-		.register_method("rpc_methods", move |_, _| {
+		.register_method("rpc_methods", move |_, _, _| {
 			serde_json::json!({
 				"methods": available_methods,
 			})
@@ -96,7 +93,7 @@ pub(crate) fn format_cors(maybe_cors: Option<&Vec<String>>) -> String {
 /// 1. `Forwarded` header.
 /// 2. `X-Forwarded-For` header.
 /// 3. `X-Real-Ip`.
-pub(crate) fn get_proxy_ip(req: &Request<hyper::Body>) -> Option<IpAddr> {
+pub(crate) fn get_proxy_ip<B>(req: &http::Request<B>) -> Option<IpAddr> {
 	if let Some(ip) = req
 		.headers()
 		.get(&FORWARDED)
@@ -133,9 +130,10 @@ pub(crate) fn get_proxy_ip(req: &Request<hyper::Body>) -> Option<IpAddr> {
 mod tests {
 	use super::*;
 	use hyper::header::HeaderValue;
+	use jsonrpsee::server::{HttpBody, HttpRequest};
 
-	fn request() -> hyper::Request<hyper::Body> {
-		hyper::Request::builder().body(hyper::Body::empty()).unwrap()
+	fn request() -> http::Request<HttpBody> {
+		HttpRequest::builder().body(HttpBody::empty()).unwrap()
 	}
 
 	#[test]
diff --git a/substrate/client/rpc-spec-v2/src/chain_head/api.rs b/substrate/client/rpc-spec-v2/src/chain_head/api.rs
index 23cb0bbf545..128d803521f 100644
--- a/substrate/client/rpc-spec-v2/src/chain_head/api.rs
+++ b/substrate/client/rpc-spec-v2/src/chain_head/api.rs
@@ -54,7 +54,7 @@ pub trait ChainHeadApi<Hash> {
 	/// # Unstable
 	///
 	/// This method is unstable and subject to change in the future.
-	#[method(name = "chainHead_v1_body", raw_method)]
+	#[method(name = "chainHead_v1_body", with_extensions)]
 	async fn chain_head_unstable_body(
 		&self,
 		follow_subscription: String,
@@ -73,7 +73,7 @@ pub trait ChainHeadApi<Hash> {
 	/// # Unstable
 	///
 	/// This method is unstable and subject to change in the future.
-	#[method(name = "chainHead_v1_header", raw_method)]
+	#[method(name = "chainHead_v1_header", with_extensions)]
 	async fn chain_head_unstable_header(
 		&self,
 		follow_subscription: String,
@@ -85,7 +85,7 @@ pub trait ChainHeadApi<Hash> {
 	/// # Unstable
 	///
 	/// This method is unstable and subject to change in the future.
-	#[method(name = "chainHead_v1_storage", raw_method)]
+	#[method(name = "chainHead_v1_storage", with_extensions)]
 	async fn chain_head_unstable_storage(
 		&self,
 		follow_subscription: String,
@@ -99,7 +99,7 @@ pub trait ChainHeadApi<Hash> {
 	/// # Unstable
 	///
 	/// This method is unstable and subject to change in the future.
-	#[method(name = "chainHead_v1_call", raw_method)]
+	#[method(name = "chainHead_v1_call", with_extensions)]
 	async fn chain_head_unstable_call(
 		&self,
 		follow_subscription: String,
@@ -118,7 +118,7 @@ pub trait ChainHeadApi<Hash> {
 	/// # Unstable
 	///
 	/// This method is unstable and subject to change in the future.
-	#[method(name = "chainHead_v1_unpin", raw_method)]
+	#[method(name = "chainHead_v1_unpin", with_extensions)]
 	async fn chain_head_unstable_unpin(
 		&self,
 		follow_subscription: String,
@@ -131,7 +131,7 @@ pub trait ChainHeadApi<Hash> {
 	/// # Unstable
 	///
 	/// This method is unstable and subject to change in the future.
-	#[method(name = "chainHead_v1_continue", raw_method)]
+	#[method(name = "chainHead_v1_continue", with_extensions)]
 	async fn chain_head_unstable_continue(
 		&self,
 		follow_subscription: String,
@@ -145,7 +145,7 @@ pub trait ChainHeadApi<Hash> {
 	/// # Unstable
 	///
 	/// This method is unstable and subject to change in the future.
-	#[method(name = "chainHead_v1_stopOperation", raw_method)]
+	#[method(name = "chainHead_v1_stopOperation", with_extensions)]
 	async fn chain_head_unstable_stop_operation(
 		&self,
 		follow_subscription: String,
diff --git a/substrate/client/rpc-spec-v2/src/chain_head/chain_head.rs b/substrate/client/rpc-spec-v2/src/chain_head/chain_head.rs
index 6779180a414..a056b4d437c 100644
--- a/substrate/client/rpc-spec-v2/src/chain_head/chain_head.rs
+++ b/substrate/client/rpc-spec-v2/src/chain_head/chain_head.rs
@@ -36,7 +36,7 @@ use crate::{
 use codec::Encode;
 use futures::{channel::oneshot, future::FutureExt};
 use jsonrpsee::{
-	core::async_trait, server::ResponsePayload, types::SubscriptionId, ConnectionDetails,
+	core::async_trait, server::ResponsePayload, types::SubscriptionId, ConnectionId, Extensions,
 	MethodResponseFuture, PendingSubscriptionSink, SubscriptionSink,
 };
 use log::debug;
@@ -251,14 +251,16 @@ where
 
 	async fn chain_head_unstable_body(
 		&self,
-		connection_details: ConnectionDetails,
+		ext: &Extensions,
 		follow_subscription: String,
 		hash: Block::Hash,
 	) -> ResponsePayload<'static, MethodResponse> {
-		if !self
-			.subscriptions
-			.contains_subscription(connection_details.id(), &follow_subscription)
-		{
+		let conn_id = ext
+			.get::<ConnectionId>()
+			.copied()
+			.expect("ConnectionId is always set by jsonrpsee; qed");
+
+		if !self.subscriptions.contains_subscription(conn_id, &follow_subscription) {
 			// The spec says to return `LimitReached` if the follow subscription is invalid or
 			// stale.
 			return ResponsePayload::success(MethodResponse::LimitReached);
@@ -335,14 +337,16 @@ where
 
 	async fn chain_head_unstable_header(
 		&self,
-		connection_details: ConnectionDetails,
+		ext: &Extensions,
 		follow_subscription: String,
 		hash: Block::Hash,
 	) -> Result<Option<String>, ChainHeadRpcError> {
-		if !self
-			.subscriptions
-			.contains_subscription(connection_details.id(), &follow_subscription)
-		{
+		let conn_id = ext
+			.get::<ConnectionId>()
+			.copied()
+			.expect("ConnectionId is always set by jsonrpsee; qed");
+
+		if !self.subscriptions.contains_subscription(conn_id, &follow_subscription) {
 			return Ok(None);
 		}
 
@@ -371,16 +375,18 @@ where
 
 	async fn chain_head_unstable_storage(
 		&self,
-		connection_details: ConnectionDetails,
+		ext: &Extensions,
 		follow_subscription: String,
 		hash: Block::Hash,
 		items: Vec<StorageQuery<String>>,
 		child_trie: Option<String>,
 	) -> ResponsePayload<'static, MethodResponse> {
-		if !self
-			.subscriptions
-			.contains_subscription(connection_details.id(), &follow_subscription)
-		{
+		let conn_id = ext
+			.get::<ConnectionId>()
+			.copied()
+			.expect("ConnectionId is always set by jsonrpsee; qed");
+
+		if !self.subscriptions.contains_subscription(conn_id, &follow_subscription) {
 			// The spec says to return `LimitReached` if the follow subscription is invalid or
 			// stale.
 			return ResponsePayload::success(MethodResponse::LimitReached);
@@ -452,7 +458,7 @@ where
 
 	async fn chain_head_unstable_call(
 		&self,
-		connection_details: ConnectionDetails,
+		ext: &Extensions,
 		follow_subscription: String,
 		hash: Block::Hash,
 		function: String,
@@ -463,10 +469,12 @@ where
 			Err(err) => return ResponsePayload::error(err),
 		};
 
-		if !self
-			.subscriptions
-			.contains_subscription(connection_details.id(), &follow_subscription)
-		{
+		let conn_id = ext
+			.get::<ConnectionId>()
+			.copied()
+			.expect("ConnectionId is always set by jsonrpsee; qed");
+
+		if !self.subscriptions.contains_subscription(conn_id, &follow_subscription) {
 			// The spec says to return `LimitReached` if the follow subscription is invalid or
 			// stale.
 			return ResponsePayload::success(MethodResponse::LimitReached);
@@ -530,14 +538,16 @@ where
 
 	async fn chain_head_unstable_unpin(
 		&self,
-		connection_details: ConnectionDetails,
+		ext: &Extensions,
 		follow_subscription: String,
 		hash_or_hashes: ListOrValue<Block::Hash>,
 	) -> Result<(), ChainHeadRpcError> {
-		if !self
-			.subscriptions
-			.contains_subscription(connection_details.id(), &follow_subscription)
-		{
+		let conn_id = ext
+			.get::<ConnectionId>()
+			.copied()
+			.expect("ConnectionId is always set by jsonrpsee; qed");
+
+		if !self.subscriptions.contains_subscription(conn_id, &follow_subscription) {
 			return Ok(());
 		}
 
@@ -566,14 +576,16 @@ where
 
 	async fn chain_head_unstable_continue(
 		&self,
-		connection_details: ConnectionDetails,
+		ext: &Extensions,
 		follow_subscription: String,
 		operation_id: String,
 	) -> Result<(), ChainHeadRpcError> {
-		if !self
-			.subscriptions
-			.contains_subscription(connection_details.id(), &follow_subscription)
-		{
+		let conn_id = ext
+			.get::<ConnectionId>()
+			.copied()
+			.expect("ConnectionId is always set by jsonrpsee; qed");
+
+		if !self.subscriptions.contains_subscription(conn_id, &follow_subscription) {
 			return Ok(())
 		}
 
@@ -592,14 +604,16 @@ where
 
 	async fn chain_head_unstable_stop_operation(
 		&self,
-		connection_details: ConnectionDetails,
+		ext: &Extensions,
 		follow_subscription: String,
 		operation_id: String,
 	) -> Result<(), ChainHeadRpcError> {
-		if !self
-			.subscriptions
-			.contains_subscription(connection_details.id(), &follow_subscription)
-		{
+		let conn_id = ext
+			.get::<ConnectionId>()
+			.copied()
+			.expect("ConnectionId is always set by jsonrpsee; qed");
+
+		if !self.subscriptions.contains_subscription(conn_id, &follow_subscription) {
 			return Ok(())
 		}
 
diff --git a/substrate/client/rpc-spec-v2/src/chain_head/subscription/inner.rs b/substrate/client/rpc-spec-v2/src/chain_head/subscription/inner.rs
index a6edc344bc6..d4d616f54dc 100644
--- a/substrate/client/rpc-spec-v2/src/chain_head/subscription/inner.rs
+++ b/substrate/client/rpc-spec-v2/src/chain_head/subscription/inner.rs
@@ -846,6 +846,7 @@ impl<Block: BlockT, BE: Backend<Block>> SubscriptionsInner<Block, BE> {
 #[cfg(test)]
 mod tests {
 	use super::*;
+	use jsonrpsee::ConnectionId;
 	use sc_block_builder::BlockBuilderBuilder;
 	use sc_service::client::new_in_mem;
 	use sp_consensus::BlockOrigin;
@@ -1420,17 +1421,20 @@ mod tests {
 				rpc_connections.clone(),
 			);
 
-		let reserved_sub_first = subscription_management.reserve_subscription(1).unwrap();
-		let mut reserved_sub_second = subscription_management.reserve_subscription(1).unwrap();
+		let reserved_sub_first =
+			subscription_management.reserve_subscription(ConnectionId(1)).unwrap();
+		let mut reserved_sub_second =
+			subscription_management.reserve_subscription(ConnectionId(1)).unwrap();
 		// Subscriptions reserved but not yet populated.
 		assert_eq!(subs.read().subs.len(), 0);
 
 		// Cannot reserve anymore.
-		assert!(subscription_management.reserve_subscription(1).is_none());
+		assert!(subscription_management.reserve_subscription(ConnectionId(1)).is_none());
 		// Drop the first subscription.
 		drop(reserved_sub_first);
 		// Space is freed-up for the rpc connections.
-		let mut reserved_sub_first = subscription_management.reserve_subscription(1).unwrap();
+		let mut reserved_sub_first =
+			subscription_management.reserve_subscription(ConnectionId(1)).unwrap();
 
 		// Insert subscriptions.
 		let _sub_data_first =
@@ -1445,7 +1449,8 @@ mod tests {
 		// Check that the subscription is removed.
 		assert_eq!(subs.read().subs.len(), 1);
 		// Space is freed-up for the rpc connections.
-		let reserved_sub_first = subscription_management.reserve_subscription(1).unwrap();
+		let reserved_sub_first =
+			subscription_management.reserve_subscription(ConnectionId(1)).unwrap();
 
 		// Drop all subscriptions.
 		drop(reserved_sub_first);
diff --git a/substrate/client/rpc-spec-v2/src/common/connections.rs b/substrate/client/rpc-spec-v2/src/common/connections.rs
index c16a80bf49d..f0c31d612eb 100644
--- a/substrate/client/rpc-spec-v2/src/common/connections.rs
+++ b/substrate/client/rpc-spec-v2/src/common/connections.rs
@@ -195,68 +195,71 @@ mod tests {
 	#[test]
 	fn reserve_space() {
 		let rpc_connections = RpcConnections::new(2);
-		let reserved = rpc_connections.reserve_space(1);
+		let conn_id = ConnectionId(1);
+		let reserved = rpc_connections.reserve_space(conn_id);
+
 		assert!(reserved.is_some());
-		assert_eq!(1, rpc_connections.data.lock().get(&1).unwrap().num_identifiers);
+		assert_eq!(1, rpc_connections.data.lock().get(&conn_id).unwrap().num_identifiers);
 		assert_eq!(rpc_connections.data.lock().len(), 1);
 
 		let reserved = reserved.unwrap();
 		let registered = reserved.register("identifier1".to_string()).unwrap();
-		assert!(rpc_connections.contains_identifier(1, "identifier1"));
-		assert_eq!(1, rpc_connections.data.lock().get(&1).unwrap().num_identifiers);
+		assert!(rpc_connections.contains_identifier(conn_id, "identifier1"));
+		assert_eq!(1, rpc_connections.data.lock().get(&conn_id).unwrap().num_identifiers);
 		drop(registered);
 
 		// Data is dropped.
-		assert!(rpc_connections.data.lock().get(&1).is_none());
+		assert!(rpc_connections.data.lock().get(&conn_id).is_none());
 		assert!(rpc_connections.data.lock().is_empty());
 		// Checks can still happen.
-		assert!(!rpc_connections.contains_identifier(1, "identifier1"));
+		assert!(!rpc_connections.contains_identifier(conn_id, "identifier1"));
 	}
 
 	#[test]
 	fn reserve_space_capacity_reached() {
 		let rpc_connections = RpcConnections::new(2);
+		let conn_id = ConnectionId(1);
 
 		// Reserve identifier for connection 1.
-		let reserved = rpc_connections.reserve_space(1);
+		let reserved = rpc_connections.reserve_space(conn_id);
 		assert!(reserved.is_some());
-		assert_eq!(1, rpc_connections.data.lock().get(&1).unwrap().num_identifiers);
+		assert_eq!(1, rpc_connections.data.lock().get(&conn_id).unwrap().num_identifiers);
 
 		// Add identifier for connection 1.
 		let reserved = reserved.unwrap();
 		let registered = reserved.register("identifier1".to_string()).unwrap();
-		assert!(rpc_connections.contains_identifier(1, "identifier1"));
-		assert_eq!(1, rpc_connections.data.lock().get(&1).unwrap().num_identifiers);
+		assert!(rpc_connections.contains_identifier(conn_id, "identifier1"));
+		assert_eq!(1, rpc_connections.data.lock().get(&conn_id).unwrap().num_identifiers);
 
 		// Reserve identifier for connection 1 again.
-		let reserved = rpc_connections.reserve_space(1);
+		let reserved = rpc_connections.reserve_space(conn_id);
 		assert!(reserved.is_some());
-		assert_eq!(2, rpc_connections.data.lock().get(&1).unwrap().num_identifiers);
+		assert_eq!(2, rpc_connections.data.lock().get(&conn_id).unwrap().num_identifiers);
 
 		// Add identifier for connection 1 again.
 		let reserved = reserved.unwrap();
 		let registered_second = reserved.register("identifier2".to_string()).unwrap();
-		assert!(rpc_connections.contains_identifier(1, "identifier2"));
-		assert_eq!(2, rpc_connections.data.lock().get(&1).unwrap().num_identifiers);
+		assert!(rpc_connections.contains_identifier(conn_id, "identifier2"));
+		assert_eq!(2, rpc_connections.data.lock().get(&conn_id).unwrap().num_identifiers);
 
 		// Cannot reserve more identifiers.
-		let reserved = rpc_connections.reserve_space(1);
+		let reserved = rpc_connections.reserve_space(conn_id);
 		assert!(reserved.is_none());
 
 		// Drop the first identifier.
 		drop(registered);
-		assert_eq!(1, rpc_connections.data.lock().get(&1).unwrap().num_identifiers);
-		assert!(rpc_connections.contains_identifier(1, "identifier2"));
-		assert!(!rpc_connections.contains_identifier(1, "identifier1"));
+		assert_eq!(1, rpc_connections.data.lock().get(&conn_id).unwrap().num_identifiers);
+		assert!(rpc_connections.contains_identifier(conn_id, "identifier2"));
+		assert!(!rpc_connections.contains_identifier(conn_id, "identifier1"));
 
 		// Can reserve again after clearing the space.
-		let reserved = rpc_connections.reserve_space(1);
+		let reserved = rpc_connections.reserve_space(conn_id);
 		assert!(reserved.is_some());
-		assert_eq!(2, rpc_connections.data.lock().get(&1).unwrap().num_identifiers);
+		assert_eq!(2, rpc_connections.data.lock().get(&conn_id).unwrap().num_identifiers);
 
 		// Ensure data is cleared.
 		drop(reserved);
 		drop(registered_second);
-		assert!(rpc_connections.data.lock().get(&1).is_none());
+		assert!(rpc_connections.data.lock().get(&conn_id).is_none());
 	}
 }
diff --git a/substrate/client/rpc-spec-v2/src/transaction/api.rs b/substrate/client/rpc-spec-v2/src/transaction/api.rs
index ed358922d53..6af6f167844 100644
--- a/substrate/client/rpc-spec-v2/src/transaction/api.rs
+++ b/substrate/client/rpc-spec-v2/src/transaction/api.rs
@@ -48,7 +48,7 @@ pub trait TransactionBroadcastApi {
 	///
 	/// This method is unstable and subject to change in the future.
 
-	#[method(name = "transaction_v1_broadcast", raw_method)]
+	#[method(name = "transaction_v1_broadcast", with_extensions)]
 	async fn broadcast(&self, bytes: Bytes) -> RpcResult<Option<String>>;
 
 	/// Broadcast an extrinsic to the chain.
@@ -56,6 +56,6 @@ pub trait TransactionBroadcastApi {
 	/// # Unstable
 	///
 	/// This method is unstable and subject to change in the future.
-	#[method(name = "transaction_v1_stop", raw_method)]
+	#[method(name = "transaction_v1_stop", with_extensions)]
 	async fn stop_broadcast(&self, operation_id: String) -> Result<(), ErrorBroadcast>;
 }
diff --git a/substrate/client/rpc-spec-v2/src/transaction/transaction_broadcast.rs b/substrate/client/rpc-spec-v2/src/transaction/transaction_broadcast.rs
index 68c19010e31..2fd4ce24545 100644
--- a/substrate/client/rpc-spec-v2/src/transaction/transaction_broadcast.rs
+++ b/substrate/client/rpc-spec-v2/src/transaction/transaction_broadcast.rs
@@ -27,7 +27,7 @@ use futures::{FutureExt, Stream, StreamExt};
 use futures_util::stream::AbortHandle;
 use jsonrpsee::{
 	core::{async_trait, RpcResult},
-	ConnectionDetails,
+	ConnectionId, Extensions,
 };
 use parking_lot::RwLock;
 use rand::{distributions::Alphanumeric, Rng};
@@ -121,19 +121,18 @@ where
 	<Pool::Block as BlockT>::Hash: Unpin,
 	Client: HeaderBackend<Pool::Block> + BlockchainEvents<Pool::Block> + Send + Sync + 'static,
 {
-	async fn broadcast(
-		&self,
-		connection_details: ConnectionDetails,
-		bytes: Bytes,
-	) -> RpcResult<Option<String>> {
+	async fn broadcast(&self, ext: &Extensions, bytes: Bytes) -> RpcResult<Option<String>> {
 		let pool = self.pool.clone();
+		let conn_id = ext
+			.get::<ConnectionId>()
+			.copied()
+			.expect("ConnectionId is always set by jsonrpsee; qed");
 
 		// The unique ID of this operation.
 		let id = self.generate_unique_id();
 
 		// Ensure that the connection has not reached the maximum number of active operations.
-		let Some(reserved_connection) = self.rpc_connections.reserve_space(connection_details.id())
-		else {
+		let Some(reserved_connection) = self.rpc_connections.reserve_space(conn_id) else {
 			return Ok(None)
 		};
 		let Some(reserved_identifier) = reserved_connection.register(id.clone()) else {
@@ -245,11 +244,16 @@ where
 
 	async fn stop_broadcast(
 		&self,
-		connection_details: ConnectionDetails,
+		ext: &Extensions,
 		operation_id: String,
 	) -> Result<(), ErrorBroadcast> {
+		let conn_id = ext
+			.get::<ConnectionId>()
+			.copied()
+			.expect("ConnectionId is always set by jsonrpsee; qed");
+
 		// The operation ID must correlate to the same connection ID.
-		if !self.rpc_connections.contains_identifier(connection_details.id(), &operation_id) {
+		if !self.rpc_connections.contains_identifier(conn_id, &operation_id) {
 			return Err(ErrorBroadcast::InvalidOperationID)
 		}
 
diff --git a/substrate/client/rpc/src/utils.rs b/substrate/client/rpc/src/utils.rs
index 3b5372615e7..bc566ed37f2 100644
--- a/substrate/client/rpc/src/utils.rs
+++ b/substrate/client/rpc/src/utils.rs
@@ -130,7 +130,7 @@ async fn inner_pipe_from_stream<S, T>(
 						"Subscription buffer limit={} exceeded for subscription={} conn_id={}; dropping subscription",
 						buf.max_cap,
 						sink.method_name(),
-						sink.connection_id()
+						sink.connection_id().0
 					);
 					return
 				}
@@ -189,7 +189,7 @@ mod tests {
 	async fn subscribe() -> Subscription {
 		let mut module = RpcModule::new(());
 		module
-			.register_subscription("sub", "my_sub", "unsub", |_, pending, _| async move {
+			.register_subscription("sub", "my_sub", "unsub", |_, pending, _, _| async move {
 				let stream = futures::stream::iter([0; 16]);
 				pipe_from_stream(pending, stream).await;
 				Ok(())
@@ -217,7 +217,7 @@ mod tests {
 
 		let mut module = RpcModule::new(tx);
 		module
-			.register_subscription("sub", "my_sub", "unsub", |_, pending, ctx| async move {
+			.register_subscription("sub", "my_sub", "unsub", |_, pending, ctx, _| async move {
 				let stream = futures::stream::iter([0; 32]);
 				pipe_from_stream(pending, stream).await;
 				_ = ctx.unbounded_send(());
@@ -239,16 +239,21 @@ mod tests {
 
 		let mut module = RpcModule::new(notify_tx);
 		module
-			.register_subscription("sub", "my_sub", "unsub", |_, pending, notify_tx| async move {
-				// emulate empty stream for simplicity: otherwise we need some mechanism
-				// to sync buffer and channel send operations
-				let stream = futures::stream::empty::<()>();
-				// this should exit immediately
-				pipe_from_stream(pending, stream).await;
-				// notify that the `pipe_from_stream` has returned
-				notify_tx.notify_one();
-				Ok(())
-			})
+			.register_subscription(
+				"sub",
+				"my_sub",
+				"unsub",
+				|_, pending, notify_tx, _| async move {
+					// emulate empty stream for simplicity: otherwise we need some mechanism
+					// to sync buffer and channel send operations
+					let stream = futures::stream::empty::<()>();
+					// this should exit immediately
+					pipe_from_stream(pending, stream).await;
+					// notify that the `pipe_from_stream` has returned
+					notify_tx.notify_one();
+					Ok(())
+				},
+			)
 			.unwrap();
 		module.subscribe("sub", EmptyServerParams::new(), 1).await.unwrap();
 
diff --git a/substrate/utils/frame/remote-externalities/src/lib.rs b/substrate/utils/frame/remote-externalities/src/lib.rs
index 44e5f467d89..40864085349 100644
--- a/substrate/utils/frame/remote-externalities/src/lib.rs
+++ b/substrate/utils/frame/remote-externalities/src/lib.rs
@@ -22,10 +22,7 @@
 
 use codec::{Compact, Decode, Encode};
 use indicatif::{ProgressBar, ProgressStyle};
-use jsonrpsee::{
-	core::params::ArrayParams,
-	http_client::{HttpClient, HttpClientBuilder},
-};
+use jsonrpsee::{core::params::ArrayParams, http_client::HttpClient};
 use log::*;
 use serde::de::DeserializeOwned;
 use sp_core::{
@@ -190,7 +187,7 @@ impl Transport {
 			} else {
 				uri.clone()
 			};
-			let http_client = HttpClientBuilder::default()
+			let http_client = HttpClient::builder()
 				.max_request_size(u32::MAX)
 				.max_response_size(u32::MAX)
 				.request_timeout(std::time::Duration::from_secs(60 * 5))
-- 
GitLab