From e53d15aa20e77eb35ccb590bb7ef940d3eca7dbb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastian=20K=C3=B6cher?= <git@kchr.de>
Date: Tue, 4 Jul 2023 10:09:14 +0200
Subject: [PATCH] Do not depend on native runtimes for `RuntimeApi` (#7451)

* Implement runtime apis for fake runtime

These runtime api implementations are only used to make the compiler
think that we have implemented all required runtime apis. They will not
be called as we switch the executor to `WasmExecutor`. In the near
future we will not require these fake implementations anymore after
Substrate has shifted away from this compile time requirement.

This brings us the advantage that the `polkadot-service` doesn't need to
depend on the runtimes for getting the `RuntimeApi` type.

It also removes around 1min of build time on my machine ;)

* Fix warning

* FMT

* ".git/.scripts/commands/fmt/fmt.sh"

* Use more descriptive id

* Fix warnings

* Adapt path

* Fix :see_no_evil:

---------

Co-authored-by: command-bot <>
---
 polkadot/Cargo.lock                           | 158 +++--
 polkadot/Cargo.toml                           |   3 +-
 polkadot/cli/Cargo.toml                       |   4 +-
 polkadot/cli/src/command.rs                   |  77 +--
 polkadot/cli/src/lib.rs                       |   2 -
 polkadot/node/client/Cargo.toml               |  63 --
 polkadot/node/client/src/benchmarking.rs      | 390 ------------
 polkadot/node/client/src/lib.rs               | 590 ------------------
 polkadot/node/service/Cargo.toml              |  24 +-
 polkadot/node/service/src/benchmarking.rs     | 430 +++++++++++++
 polkadot/node/service/src/chain_spec.rs       |  44 +-
 polkadot/node/service/src/fake_runtime_api.rs | 398 ++++++++++++
 polkadot/node/service/src/lib.rs              | 393 ++++--------
 polkadot/node/test/client/Cargo.toml          |   3 +
 .../node/test/client/src/block_builder.rs     |   3 +-
 polkadot/node/test/client/src/lib.rs          |  20 +-
 polkadot/node/test/service/Cargo.toml         |   2 -
 polkadot/node/test/service/src/lib.rs         |  36 +-
 polkadot/tests/purge_chain_works.rs           |  22 +-
 19 files changed, 1155 insertions(+), 1507 deletions(-)
 delete mode 100644 polkadot/node/client/Cargo.toml
 delete mode 100644 polkadot/node/client/src/benchmarking.rs
 delete mode 100644 polkadot/node/client/src/lib.rs
 create mode 100644 polkadot/node/service/src/benchmarking.rs
 create mode 100644 polkadot/node/service/src/fake_runtime_api.rs

diff --git a/polkadot/Cargo.lock b/polkadot/Cargo.lock
index c0991ae3b78..b8bca8772e4 100644
--- a/polkadot/Cargo.lock
+++ b/polkadot/Cargo.lock
@@ -4575,11 +4575,10 @@ dependencies = [
 
 [[package]]
 name = "log"
-version = "0.4.17"
+version = "0.4.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
+checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
 dependencies = [
- "cfg-if",
  "serde",
  "value-bag",
 ]
@@ -6917,7 +6916,6 @@ dependencies = [
  "frame-benchmarking-cli",
  "futures",
  "log",
- "polkadot-client",
  "polkadot-node-core-pvf-execute-worker",
  "polkadot-node-core-pvf-prepare-worker",
  "polkadot-node-metrics",
@@ -6940,50 +6938,6 @@ dependencies = [
  "try-runtime-cli",
 ]
 
-[[package]]
-name = "polkadot-client"
-version = "0.9.43"
-dependencies = [
- "async-trait",
- "frame-benchmarking",
- "frame-benchmarking-cli",
- "frame-system",
- "frame-system-rpc-runtime-api",
- "futures",
- "kusama-runtime",
- "pallet-transaction-payment",
- "pallet-transaction-payment-rpc-runtime-api",
- "polkadot-core-primitives",
- "polkadot-node-core-parachains-inherent",
- "polkadot-primitives",
- "polkadot-runtime",
- "polkadot-runtime-common",
- "rococo-runtime",
- "sc-client-api",
- "sc-consensus",
- "sc-executor",
- "sc-service",
- "sp-api",
- "sp-authority-discovery",
- "sp-block-builder",
- "sp-blockchain",
- "sp-consensus",
- "sp-consensus-babe",
- "sp-consensus-beefy",
- "sp-consensus-grandpa",
- "sp-core",
- "sp-inherents",
- "sp-keyring",
- "sp-mmr-primitives",
- "sp-offchain",
- "sp-runtime",
- "sp-session",
- "sp-storage",
- "sp-timestamp",
- "sp-transaction-pool",
- "westend-runtime",
-]
-
 [[package]]
 name = "polkadot-collator-protocol"
 version = "0.9.43"
@@ -8071,8 +8025,10 @@ dependencies = [
  "assert_matches",
  "async-trait",
  "env_logger 0.9.0",
+ "frame-benchmarking",
  "frame-benchmarking-cli",
  "frame-support",
+ "frame-system",
  "frame-system-rpc-runtime-api",
  "futures",
  "hex-literal 0.4.1",
@@ -8086,14 +8042,16 @@ dependencies = [
  "pallet-babe",
  "pallet-im-online",
  "pallet-staking",
+ "pallet-transaction-payment",
  "pallet-transaction-payment-rpc-runtime-api",
  "parity-db",
+ "parity-scale-codec",
  "polkadot-approval-distribution",
  "polkadot-availability-bitfield-distribution",
  "polkadot-availability-distribution",
  "polkadot-availability-recovery",
- "polkadot-client",
  "polkadot-collator-protocol",
+ "polkadot-core-primitives",
  "polkadot-dispute-distribution",
  "polkadot-gossip-support",
  "polkadot-network-bridge",
@@ -8121,6 +8079,7 @@ dependencies = [
  "polkadot-primitives",
  "polkadot-rpc",
  "polkadot-runtime",
+ "polkadot-runtime-common",
  "polkadot-runtime-constants",
  "polkadot-runtime-parachains",
  "polkadot-statement-distribution",
@@ -8162,6 +8121,7 @@ dependencies = [
  "sp-core",
  "sp-inherents",
  "sp-io",
+ "sp-keyring",
  "sp-keystore",
  "sp-mmr-primitives",
  "sp-offchain",
@@ -8172,6 +8132,8 @@ dependencies = [
  "sp-timestamp",
  "sp-transaction-pool",
  "sp-trie",
+ "sp-version",
+ "sp-weights",
  "substrate-prometheus-endpoint",
  "tempfile",
  "thiserror",
@@ -8224,6 +8186,7 @@ dependencies = [
 name = "polkadot-test-client"
 version = "0.9.43"
 dependencies = [
+ "frame-benchmarking",
  "futures",
  "parity-scale-codec",
  "polkadot-node-subsystem",
@@ -8232,6 +8195,7 @@ dependencies = [
  "polkadot-test-service",
  "sc-block-builder",
  "sc-consensus",
+ "sc-offchain",
  "sc-service",
  "sp-api",
  "sp-blockchain",
@@ -8239,6 +8203,7 @@ dependencies = [
  "sp-consensus-babe",
  "sp-core",
  "sp-inherents",
+ "sp-io",
  "sp-keyring",
  "sp-runtime",
  "sp-state-machine",
@@ -8344,7 +8309,6 @@ dependencies = [
 name = "polkadot-test-service"
 version = "0.9.43"
 dependencies = [
- "frame-benchmarking",
  "frame-system",
  "futures",
  "hex",
@@ -8369,7 +8333,6 @@ dependencies = [
  "sc-consensus",
  "sc-consensus-babe",
  "sc-consensus-grandpa",
- "sc-executor",
  "sc-network",
  "sc-service",
  "sc-tracing",
@@ -12195,11 +12158,70 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
 
 [[package]]
 name = "sval"
-version = "1.0.0-alpha.5"
+version = "2.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b031320a434d3e9477ccf9b5756d57d4272937b8d22cb88af80b7633a1b78b1"
+
+[[package]]
+name = "sval_buffer"
+version = "2.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6bf7e9412af26b342f3f2cc5cc4122b0105e9d16eb76046cd14ed10106cf6028"
+dependencies = [
+ "sval",
+ "sval_ref",
+]
+
+[[package]]
+name = "sval_dynamic"
+version = "2.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0ef628e8a77a46ed3338db8d1b08af77495123cc229453084e47cd716d403cf"
+dependencies = [
+ "sval",
+]
+
+[[package]]
+name = "sval_fmt"
+version = "2.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7dc09e9364c2045ab5fa38f7b04d077b3359d30c4c2b3ec4bae67a358bd64326"
+dependencies = [
+ "itoa",
+ "ryu",
+ "sval",
+]
+
+[[package]]
+name = "sval_json"
+version = "2.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "45f6ee7c7b87caf59549e9fe45d6a69c75c8019e79e212a835c5da0e92f0ba08"
+checksum = "ada6f627e38cbb8860283649509d87bc4a5771141daa41c78fd31f2b9485888d"
+dependencies = [
+ "itoa",
+ "ryu",
+ "sval",
+]
+
+[[package]]
+name = "sval_ref"
+version = "2.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "703ca1942a984bd0d9b5a4c0a65ab8b4b794038d080af4eb303c71bc6bf22d7c"
+dependencies = [
+ "sval",
+]
+
+[[package]]
+name = "sval_serde"
+version = "2.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "830926cd0581f7c3e5d51efae4d35c6b6fc4db583842652891ba2f1bed8db046"
 dependencies = [
  "serde",
+ "sval",
+ "sval_buffer",
+ "sval_fmt",
 ]
 
 [[package]]
@@ -13248,16 +13270,38 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
 
 [[package]]
 name = "value-bag"
-version = "1.0.0-alpha.9"
+version = "1.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2209b78d1249f7e6f3293657c9779fe31ced465df091bbd433a1cf88e916ec55"
+checksum = "d92ccd67fb88503048c01b59152a04effd0782d035a83a6d256ce6085f08f4a3"
+dependencies = [
+ "value-bag-serde1",
+ "value-bag-sval2",
+]
+
+[[package]]
+name = "value-bag-serde1"
+version = "1.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0b9f3feef403a50d4d67e9741a6d8fc688bcbb4e4f31bd4aab72cc690284394"
 dependencies = [
- "ctor",
  "erased-serde",
  "serde",
  "serde_fmt",
+]
+
+[[package]]
+name = "value-bag-sval2"
+version = "1.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30b24f4146b6f3361e91cbf527d1fb35e9376c3c0cef72ca5ec5af6d640fad7d"
+dependencies = [
  "sval",
- "version_check",
+ "sval_buffer",
+ "sval_dynamic",
+ "sval_fmt",
+ "sval_json",
+ "sval_ref",
+ "sval_serde",
 ]
 
 [[package]]
diff --git a/polkadot/Cargo.toml b/polkadot/Cargo.toml
index c4cd139b68f..74f2b957051 100644
--- a/polkadot/Cargo.toml
+++ b/polkadot/Cargo.toml
@@ -23,7 +23,7 @@ color-eyre = { version = "0.6.1", default-features = false }
 tikv-jemallocator = "0.5.0"
 
 # Crates in our workspace, defined as dependencies so we can pass them feature flags.
-polkadot-cli = { path = "cli", features = [ "kusama-native", "westend-native", "rococo-native" ]  }
+polkadot-cli = { path = "cli", features = [ "polkadot-native", "kusama-native", "westend-native", "rococo-native" ]  }
 polkadot-node-core-pvf-prepare-worker = { path = "node/core/pvf/prepare-worker" }
 polkadot-overseer = { path = "node/overseer" }
 
@@ -68,7 +68,6 @@ members = [
 	"xcm/pallet-xcm",
 	"xcm/pallet-xcm-benchmarks",
 	"xcm/procedural",
-	"node/client",
 	"node/collation-generation",
 	"node/core/approval-voting",
 	"node/core/av-store",
diff --git a/polkadot/cli/Cargo.toml b/polkadot/cli/Cargo.toml
index 64ce6e7ca59..e7aa562880c 100644
--- a/polkadot/cli/Cargo.toml
+++ b/polkadot/cli/Cargo.toml
@@ -22,7 +22,6 @@ pyro = { package = "pyroscope", version = "0.5.3", optional = true }
 pyroscope_pprofrs = { version = "0.2", optional = true }
 
 service = { package = "polkadot-service", path = "../node/service", default-features = false, optional = true }
-polkadot-client = { path = "../node/client", optional = true }
 polkadot-node-core-pvf-execute-worker = { path = "../node/core/pvf/execute-worker", optional = true }
 polkadot-node-core-pvf-prepare-worker = { path = "../node/core/pvf/prepare-worker", optional = true }
 polkadot-performance-test = { path = "../node/test/performance-test", optional = true }
@@ -45,7 +44,7 @@ sc-storage-monitor = { git = "https://github.com/paritytech/substrate", branch =
 substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "master" }
 
 [features]
-default = ["db", "cli", "full-node", "polkadot-native"]
+default = ["db", "cli", "full-node"]
 db = ["service/db"]
 cli = [
 	"clap",
@@ -54,7 +53,6 @@ cli = [
 	"sc-tracing",
 	"frame-benchmarking-cli",
 	"try-runtime-cli",
-	"polkadot-client",
 	"polkadot-node-core-pvf-execute-worker",
 	"polkadot-node-core-pvf-prepare-worker",
 	"service",
diff --git a/polkadot/cli/src/command.rs b/polkadot/cli/src/command.rs
index db5ebe150ec..4cf06f254b0 100644
--- a/polkadot/cli/src/command.rs
+++ b/polkadot/cli/src/command.rs
@@ -18,11 +18,12 @@ use crate::cli::{Cli, Subcommand};
 use frame_benchmarking_cli::{BenchmarkCmd, ExtrinsicFactory, SUBSTRATE_REFERENCE_HARDWARE};
 use futures::future::TryFutureExt;
 use log::info;
-use polkadot_client::benchmarking::{
-	benchmark_inherent_data, ExistentialDepositProvider, RemarkBuilder, TransferKeepAliveBuilder,
-};
 use sc_cli::{RuntimeVersion, SubstrateCli};
-use service::{self, HeaderBackend, IdentifyVariant};
+use service::{
+	self,
+	benchmarking::{benchmark_inherent_data, RemarkBuilder, TransferKeepAliveBuilder},
+	HeaderBackend, IdentifyVariant,
+};
 use sp_core::crypto::Ss58AddressFormatRegistry;
 use sp_keyring::Sr25519Keyring;
 use std::net::ToSocketAddrs;
@@ -225,31 +226,6 @@ fn ensure_dev(spec: &Box<dyn service::ChainSpec>) -> std::result::Result<(), Str
 	}
 }
 
-/// Unwraps a [`polkadot_client::Client`] into the concrete runtime client.
-macro_rules! unwrap_client {
-	(
-		$client:ident,
-		$code:expr
-	) => {
-		match $client.as_ref() {
-			#[cfg(feature = "polkadot-native")]
-			polkadot_client::Client::Polkadot($client) => $code,
-			#[cfg(feature = "westend-native")]
-			polkadot_client::Client::Westend($client) => $code,
-			#[cfg(feature = "kusama-native")]
-			polkadot_client::Client::Kusama($client) => $code,
-			#[cfg(feature = "rococo-native")]
-			polkadot_client::Client::Rococo($client) => $code,
-			#[allow(unreachable_patterns)]
-			_ => {
-				let _ = $client;
-
-				Err(Error::CommandNotImplemented)
-			},
-		}
-	};
-}
-
 /// Runs performance checks.
 /// Should only be used in release build since the check would take too much time otherwise.
 fn host_perf_check() -> Result<()> {
@@ -540,15 +516,12 @@ pub fn run() -> Result<()> {
 					let db = backend.expose_db();
 					let storage = backend.expose_storage();
 
-					unwrap_client!(
-						client,
-						cmd.run(config, client.clone(), db, storage).map_err(Error::SubstrateCli)
-					)
+					cmd.run(config, client.clone(), db, storage).map_err(Error::SubstrateCli)
 				}),
 				BenchmarkCmd::Block(cmd) => runner.sync_run(|mut config| {
 					let (client, _, _, _) = service::new_chain_ops(&mut config, None)?;
 
-					unwrap_client!(client, cmd.run(client.clone()).map_err(Error::SubstrateCli))
+					cmd.run(client.clone()).map_err(Error::SubstrateCli)
 				}),
 				// These commands are very similar and can be handled in nearly the same way.
 				BenchmarkCmd::Extrinsic(_) | BenchmarkCmd::Overhead(_) => {
@@ -558,14 +531,15 @@ pub fn run() -> Result<()> {
 						let header = client.header(client.info().genesis_hash).unwrap().unwrap();
 						let inherent_data = benchmark_inherent_data(header)
 							.map_err(|e| format!("generating inherent data: {:?}", e))?;
-						let remark_builder = RemarkBuilder::new(client.clone());
+						let remark_builder =
+							RemarkBuilder::new(client.clone(), config.chain_spec.identify_chain());
 
 						match cmd {
 							BenchmarkCmd::Extrinsic(cmd) => {
 								let tka_builder = TransferKeepAliveBuilder::new(
 									client.clone(),
 									Sr25519Keyring::Alice.to_account_id(),
-									client.existential_deposit(),
+									config.chain_spec.identify_chain(),
 								);
 
 								let ext_factory = ExtrinsicFactory(vec![
@@ -573,28 +547,18 @@ pub fn run() -> Result<()> {
 									Box::new(tka_builder),
 								]);
 
-								unwrap_client!(
-									client,
-									cmd.run(
-										client.clone(),
-										inherent_data,
-										Vec::new(),
-										&ext_factory
-									)
+								cmd.run(client.clone(), inherent_data, Vec::new(), &ext_factory)
 									.map_err(Error::SubstrateCli)
-								)
 							},
-							BenchmarkCmd::Overhead(cmd) => unwrap_client!(
-								client,
-								cmd.run(
+							BenchmarkCmd::Overhead(cmd) => cmd
+								.run(
 									config,
 									client.clone(),
 									inherent_data,
 									Vec::new(),
-									&remark_builder
+									&remark_builder,
 								)
-								.map_err(Error::SubstrateCli)
-							),
+								.map_err(Error::SubstrateCli),
 							_ => unreachable!("Ensured by the outside match; qed"),
 						}
 					})
@@ -637,17 +601,12 @@ pub fn run() -> Result<()> {
 		Some(Subcommand::Key(cmd)) => Ok(cmd.run(&cli)?),
 		#[cfg(feature = "try-runtime")]
 		Some(Subcommand::TryRuntime(cmd)) => {
-			use sc_executor::{sp_wasm_interface::ExtendedHostFunctions, NativeExecutionDispatch};
 			use sc_service::TaskManager;
 			use try_runtime_cli::block_building_info::timestamp_with_babe_info;
 
 			let runner = cli.create_runner(cmd)?;
 			let chain_spec = &runner.config().chain_spec;
 			set_default_ss58_version(chain_spec);
-			type HostFunctionsOf<E> = ExtendedHostFunctions<
-				sp_io::SubstrateHostFunctions,
-				<E as NativeExecutionDispatch>::ExtendHostFunctions,
-			>;
 
 			let registry = &runner.config().prometheus_config.as_ref().map(|cfg| &cfg.registry);
 			let task_manager = TaskManager::new(runner.config().tokio_handle.clone(), *registry)
@@ -659,7 +618,7 @@ pub fn run() -> Result<()> {
 			if chain_spec.is_kusama() {
 				return runner.async_run(|_| {
 					Ok((
-						cmd.run::<service::kusama_runtime::Block, HostFunctionsOf<service::KusamaExecutorDispatch>, _>(
+						cmd.run::<service::kusama_runtime::Block, sp_io::SubstrateHostFunctions, _>(
 							Some(timestamp_with_babe_info(service::kusama_runtime_constants::time::MILLISECS_PER_BLOCK))
 						)
 						.map_err(Error::SubstrateCli),
@@ -672,7 +631,7 @@ pub fn run() -> Result<()> {
 			if chain_spec.is_westend() {
 				return runner.async_run(|_| {
 					Ok((
-						cmd.run::<service::westend_runtime::Block, HostFunctionsOf<service::WestendExecutorDispatch>, _>(
+						cmd.run::<service::westend_runtime::Block, sp_io::SubstrateHostFunctions, _>(
 							Some(timestamp_with_babe_info(service::westend_runtime_constants::time::MILLISECS_PER_BLOCK))
 						)
 						.map_err(Error::SubstrateCli),
@@ -685,7 +644,7 @@ pub fn run() -> Result<()> {
 			{
 				return runner.async_run(|_| {
 					Ok((
-						cmd.run::<service::polkadot_runtime::Block, HostFunctionsOf<service::PolkadotExecutorDispatch>, _>(
+						cmd.run::<service::polkadot_runtime::Block, sp_io::SubstrateHostFunctions, _>(
 							Some(timestamp_with_babe_info(service::polkadot_runtime_constants::time::MILLISECS_PER_BLOCK))
 						)
 						.map_err(Error::SubstrateCli),
diff --git a/polkadot/cli/src/lib.rs b/polkadot/cli/src/lib.rs
index 8a859c1b2bd..057592fa8a1 100644
--- a/polkadot/cli/src/lib.rs
+++ b/polkadot/cli/src/lib.rs
@@ -27,8 +27,6 @@ mod error;
 #[cfg(all(feature = "hostperfcheck", build_type = "release"))]
 mod host_perf_check;
 
-#[cfg(feature = "full-node")]
-pub use service::RuntimeApiCollection;
 #[cfg(feature = "service")]
 pub use service::{self, Block, CoreApi, IdentifyVariant, ProvideRuntimeApi, TFullClient};
 
diff --git a/polkadot/node/client/Cargo.toml b/polkadot/node/client/Cargo.toml
deleted file mode 100644
index 3b4e8e725ae..00000000000
--- a/polkadot/node/client/Cargo.toml
+++ /dev/null
@@ -1,63 +0,0 @@
-[package]
-name = "polkadot-client"
-version.workspace = true
-authors.workspace = true
-edition.workspace = true
-
-[dependencies]
-async-trait = "0.1.57"
-futures = "0.3.21"
-frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" }
-frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" }
-pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" }
-pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
-frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" }
-frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
-
-sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
-sp-storage = { git = "https://github.com/paritytech/substrate", branch = "master" }
-sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
-sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
-sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
-sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" }
-sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" }
-sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" }
-sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" }
-sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" }
-sp-authority-discovery = { git = "https://github.com/paritytech/substrate", branch = "master" }
-sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "master" }
-sp-consensus-beefy = { git = "https://github.com/paritytech/substrate", branch = "master" }
-sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "master" }
-sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" }
-sp-offchain = { package = "sp-offchain", git = "https://github.com/paritytech/substrate", branch = "master" }
-sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
-sp-mmr-primitives = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
-
-sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
-sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" }
-sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
-sc-service = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
-
-# Polkadot Runtimes
-polkadot-runtime = { path = "../../runtime/polkadot", optional = true }
-kusama-runtime = { path = "../../runtime/kusama", optional = true }
-westend-runtime = { path = "../../runtime/westend", optional = true }
-rococo-runtime = { path = "../../runtime/rococo", optional = true }
-
-polkadot-core-primitives = { path = "../../core-primitives" }
-polkadot-primitives = { path = "../../primitives" }
-polkadot-node-core-parachains-inherent = { path = "../core/parachains-inherent" }
-polkadot-runtime-common = { path = "../../runtime/common" }
-
-[features]
-default = ["polkadot"]
-polkadot = ["polkadot-runtime"]
-kusama = ["kusama-runtime"]
-rococo = ["rococo-runtime"]
-westend = ["westend-runtime"]
-runtime-metrics = [
-    "rococo-runtime/runtime-metrics",
-    "kusama-runtime/runtime-metrics",
-    "westend-runtime/runtime-metrics",
-    "polkadot-runtime/runtime-metrics",
-]
diff --git a/polkadot/node/client/src/benchmarking.rs b/polkadot/node/client/src/benchmarking.rs
deleted file mode 100644
index 69927c11a91..00000000000
--- a/polkadot/node/client/src/benchmarking.rs
+++ /dev/null
@@ -1,390 +0,0 @@
-// Copyright (C) Parity Technologies (UK) Ltd.
-// This file is part of Polkadot.
-
-// Polkadot is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Polkadot is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
-
-//! Code related to benchmarking a [`crate::Client`].
-
-use polkadot_primitives::{AccountId, Balance};
-use sp_core::{Pair, H256};
-use sp_keyring::Sr25519Keyring;
-use sp_runtime::OpaqueExtrinsic;
-
-use crate::*;
-
-/// Generates `System::Remark` extrinsics for the benchmarks.
-///
-/// Note: Should only be used for benchmarking.
-pub struct RemarkBuilder {
-	client: Arc<Client>,
-}
-
-impl RemarkBuilder {
-	/// Creates a new [`Self`] from the given client.
-	pub fn new(client: Arc<Client>) -> Self {
-		Self { client }
-	}
-}
-
-impl frame_benchmarking_cli::ExtrinsicBuilder for RemarkBuilder {
-	fn pallet(&self) -> &str {
-		"system"
-	}
-
-	fn extrinsic(&self) -> &str {
-		"remark"
-	}
-
-	fn build(&self, nonce: u32) -> std::result::Result<OpaqueExtrinsic, &'static str> {
-		with_client! {
-			self.client.as_ref(), client, {
-				use runtime::{RuntimeCall, SystemCall};
-
-				let call = RuntimeCall::System(SystemCall::remark { remark: vec![] });
-				let signer = Sr25519Keyring::Bob.pair();
-
-				let period = polkadot_runtime_common::BlockHashCount::get().checked_next_power_of_two().map(|c| c / 2).unwrap_or(2) as u64;
-				let genesis = client.usage_info().chain.best_hash;
-
-				Ok(client.sign_call(call, nonce, 0, period, genesis, signer))
-			}
-		}
-	}
-}
-
-/// Generates `Balances::TransferKeepAlive` extrinsics for the benchmarks.
-///
-/// Note: Should only be used for benchmarking.
-pub struct TransferKeepAliveBuilder {
-	client: Arc<Client>,
-	dest: AccountId,
-	value: Balance,
-}
-
-impl TransferKeepAliveBuilder {
-	/// Creates a new [`Self`] from the given client and the arguments for the extrinsics.
-
-	pub fn new(client: Arc<Client>, dest: AccountId, value: Balance) -> Self {
-		Self { client, dest, value }
-	}
-}
-
-impl frame_benchmarking_cli::ExtrinsicBuilder for TransferKeepAliveBuilder {
-	fn pallet(&self) -> &str {
-		"balances"
-	}
-
-	fn extrinsic(&self) -> &str {
-		"transfer_keep_alive"
-	}
-
-	fn build(&self, nonce: u32) -> std::result::Result<OpaqueExtrinsic, &'static str> {
-		with_client! {
-			self.client.as_ref(), client, {
-				use runtime::{RuntimeCall, BalancesCall};
-
-				let call = RuntimeCall::Balances(BalancesCall::transfer_keep_alive {
-					dest: self.dest.clone().into(),
-					value: self.value.into(),
-				});
-				let signer = Sr25519Keyring::Bob.pair();
-
-				let period = polkadot_runtime_common::BlockHashCount::get().checked_next_power_of_two().map(|c| c / 2).unwrap_or(2) as u64;
-				let genesis = client.usage_info().chain.best_hash;
-
-				Ok(client.sign_call(call, nonce, 0, period, genesis, signer))
-			}
-		}
-	}
-}
-
-/// Helper trait to implement [`frame_benchmarking_cli::ExtrinsicBuilder`].
-///
-/// Should only be used for benchmarking since it makes strong assumptions
-/// about the chain state that these calls will be valid for.
-trait BenchmarkCallSigner<RuntimeCall: Encode + Clone, Signer: Pair> {
-	/// Signs a call together with the signed extensions of the specific runtime.
-	///
-	/// Only works if the current block is the genesis block since the
-	/// `CheckMortality` check is mocked by using the genesis block.
-	fn sign_call(
-		&self,
-		call: RuntimeCall,
-		nonce: u32,
-		current_block: u64,
-		period: u64,
-		genesis: H256,
-		acc: Signer,
-	) -> OpaqueExtrinsic;
-}
-
-#[cfg(feature = "polkadot")]
-impl BenchmarkCallSigner<polkadot_runtime::RuntimeCall, sp_core::sr25519::Pair>
-	for FullClient<polkadot_runtime::RuntimeApi, PolkadotExecutorDispatch>
-{
-	fn sign_call(
-		&self,
-		call: polkadot_runtime::RuntimeCall,
-		nonce: u32,
-		current_block: u64,
-		period: u64,
-		genesis: H256,
-		acc: sp_core::sr25519::Pair,
-	) -> OpaqueExtrinsic {
-		use polkadot_runtime as runtime;
-
-		let extra: runtime::SignedExtra = (
-			frame_system::CheckNonZeroSender::<runtime::Runtime>::new(),
-			frame_system::CheckSpecVersion::<runtime::Runtime>::new(),
-			frame_system::CheckTxVersion::<runtime::Runtime>::new(),
-			frame_system::CheckGenesis::<runtime::Runtime>::new(),
-			frame_system::CheckMortality::<runtime::Runtime>::from(
-				sp_runtime::generic::Era::mortal(period, current_block),
-			),
-			frame_system::CheckNonce::<runtime::Runtime>::from(nonce),
-			frame_system::CheckWeight::<runtime::Runtime>::new(),
-			pallet_transaction_payment::ChargeTransactionPayment::<runtime::Runtime>::from(0),
-			polkadot_runtime_common::claims::PrevalidateAttests::<runtime::Runtime>::new(),
-		);
-
-		let payload = runtime::SignedPayload::from_raw(
-			call.clone(),
-			extra.clone(),
-			(
-				(),
-				runtime::VERSION.spec_version,
-				runtime::VERSION.transaction_version,
-				genesis,
-				genesis,
-				(),
-				(),
-				(),
-				(),
-			),
-		);
-
-		let signature = payload.using_encoded(|p| acc.sign(p));
-		runtime::UncheckedExtrinsic::new_signed(
-			call,
-			sp_runtime::AccountId32::from(acc.public()).into(),
-			polkadot_core_primitives::Signature::Sr25519(signature.clone()),
-			extra,
-		)
-		.into()
-	}
-}
-
-#[cfg(feature = "westend")]
-impl BenchmarkCallSigner<westend_runtime::RuntimeCall, sp_core::sr25519::Pair>
-	for FullClient<westend_runtime::RuntimeApi, WestendExecutorDispatch>
-{
-	fn sign_call(
-		&self,
-		call: westend_runtime::RuntimeCall,
-		nonce: u32,
-		current_block: u64,
-		period: u64,
-		genesis: H256,
-		acc: sp_core::sr25519::Pair,
-	) -> OpaqueExtrinsic {
-		use westend_runtime as runtime;
-
-		let extra: runtime::SignedExtra = (
-			frame_system::CheckNonZeroSender::<runtime::Runtime>::new(),
-			frame_system::CheckSpecVersion::<runtime::Runtime>::new(),
-			frame_system::CheckTxVersion::<runtime::Runtime>::new(),
-			frame_system::CheckGenesis::<runtime::Runtime>::new(),
-			frame_system::CheckMortality::<runtime::Runtime>::from(
-				sp_runtime::generic::Era::mortal(period, current_block),
-			),
-			frame_system::CheckNonce::<runtime::Runtime>::from(nonce),
-			frame_system::CheckWeight::<runtime::Runtime>::new(),
-			pallet_transaction_payment::ChargeTransactionPayment::<runtime::Runtime>::from(0),
-		);
-
-		let payload = runtime::SignedPayload::from_raw(
-			call.clone(),
-			extra.clone(),
-			(
-				(),
-				runtime::VERSION.spec_version,
-				runtime::VERSION.transaction_version,
-				genesis,
-				genesis,
-				(),
-				(),
-				(),
-			),
-		);
-
-		let signature = payload.using_encoded(|p| acc.sign(p));
-		runtime::UncheckedExtrinsic::new_signed(
-			call,
-			sp_runtime::AccountId32::from(acc.public()).into(),
-			polkadot_core_primitives::Signature::Sr25519(signature.clone()),
-			extra,
-		)
-		.into()
-	}
-}
-
-#[cfg(feature = "kusama")]
-impl BenchmarkCallSigner<kusama_runtime::RuntimeCall, sp_core::sr25519::Pair>
-	for FullClient<kusama_runtime::RuntimeApi, KusamaExecutorDispatch>
-{
-	fn sign_call(
-		&self,
-		call: kusama_runtime::RuntimeCall,
-		nonce: u32,
-		current_block: u64,
-		period: u64,
-		genesis: H256,
-		acc: sp_core::sr25519::Pair,
-	) -> OpaqueExtrinsic {
-		use kusama_runtime as runtime;
-
-		let extra: runtime::SignedExtra = (
-			frame_system::CheckNonZeroSender::<runtime::Runtime>::new(),
-			frame_system::CheckSpecVersion::<runtime::Runtime>::new(),
-			frame_system::CheckTxVersion::<runtime::Runtime>::new(),
-			frame_system::CheckGenesis::<runtime::Runtime>::new(),
-			frame_system::CheckMortality::<runtime::Runtime>::from(
-				sp_runtime::generic::Era::mortal(period, current_block),
-			),
-			frame_system::CheckNonce::<runtime::Runtime>::from(nonce),
-			frame_system::CheckWeight::<runtime::Runtime>::new(),
-			pallet_transaction_payment::ChargeTransactionPayment::<runtime::Runtime>::from(0),
-		);
-
-		let payload = runtime::SignedPayload::from_raw(
-			call.clone(),
-			extra.clone(),
-			(
-				(),
-				runtime::VERSION.spec_version,
-				runtime::VERSION.transaction_version,
-				genesis,
-				genesis,
-				(),
-				(),
-				(),
-			),
-		);
-
-		let signature = payload.using_encoded(|p| acc.sign(p));
-		runtime::UncheckedExtrinsic::new_signed(
-			call,
-			sp_runtime::AccountId32::from(acc.public()).into(),
-			polkadot_core_primitives::Signature::Sr25519(signature.clone()),
-			extra,
-		)
-		.into()
-	}
-}
-
-#[cfg(feature = "rococo")]
-impl BenchmarkCallSigner<rococo_runtime::RuntimeCall, sp_core::sr25519::Pair>
-	for FullClient<rococo_runtime::RuntimeApi, RococoExecutorDispatch>
-{
-	fn sign_call(
-		&self,
-		call: rococo_runtime::RuntimeCall,
-		nonce: u32,
-		current_block: u64,
-		period: u64,
-		genesis: H256,
-		acc: sp_core::sr25519::Pair,
-	) -> OpaqueExtrinsic {
-		use rococo_runtime as runtime;
-
-		let extra: runtime::SignedExtra = (
-			frame_system::CheckNonZeroSender::<runtime::Runtime>::new(),
-			frame_system::CheckSpecVersion::<runtime::Runtime>::new(),
-			frame_system::CheckTxVersion::<runtime::Runtime>::new(),
-			frame_system::CheckGenesis::<runtime::Runtime>::new(),
-			frame_system::CheckMortality::<runtime::Runtime>::from(
-				sp_runtime::generic::Era::mortal(period, current_block),
-			),
-			frame_system::CheckNonce::<runtime::Runtime>::from(nonce),
-			frame_system::CheckWeight::<runtime::Runtime>::new(),
-			pallet_transaction_payment::ChargeTransactionPayment::<runtime::Runtime>::from(0),
-		);
-
-		let payload = runtime::SignedPayload::from_raw(
-			call.clone(),
-			extra.clone(),
-			(
-				(),
-				runtime::VERSION.spec_version,
-				runtime::VERSION.transaction_version,
-				genesis,
-				genesis,
-				(),
-				(),
-				(),
-			),
-		);
-
-		let signature = payload.using_encoded(|p| acc.sign(p));
-		runtime::UncheckedExtrinsic::new_signed(
-			call,
-			sp_runtime::AccountId32::from(acc.public()).into(),
-			polkadot_core_primitives::Signature::Sr25519(signature.clone()),
-			extra,
-		)
-		.into()
-	}
-}
-
-/// Generates inherent data for benchmarking Polkadot, Kusama, Westend and Rococo.
-///
-/// Not to be used outside of benchmarking since it returns mocked values.
-pub fn benchmark_inherent_data(
-	header: polkadot_core_primitives::Header,
-) -> std::result::Result<sp_inherents::InherentData, sp_inherents::Error> {
-	use sp_inherents::InherentDataProvider;
-	let mut inherent_data = sp_inherents::InherentData::new();
-
-	// Assume that all runtimes have the `timestamp` pallet.
-	let d = std::time::Duration::from_millis(0);
-	let timestamp = sp_timestamp::InherentDataProvider::new(d.into());
-	futures::executor::block_on(timestamp.provide_inherent_data(&mut inherent_data))?;
-
-	let para_data = polkadot_primitives::InherentData {
-		bitfields: Vec::new(),
-		backed_candidates: Vec::new(),
-		disputes: Vec::new(),
-		parent_header: header,
-	};
-
-	inherent_data.put_data(polkadot_primitives::PARACHAINS_INHERENT_IDENTIFIER, &para_data)?;
-
-	Ok(inherent_data)
-}
-
-/// Provides the existential deposit that is only needed for benchmarking.
-pub trait ExistentialDepositProvider {
-	/// Returns the existential deposit.
-	fn existential_deposit(&self) -> Balance;
-}
-
-impl ExistentialDepositProvider for Client {
-	fn existential_deposit(&self) -> Balance {
-		with_client! {
-			self,
-			_client,
-			runtime::ExistentialDeposit::get()
-		}
-	}
-}
diff --git a/polkadot/node/client/src/lib.rs b/polkadot/node/client/src/lib.rs
deleted file mode 100644
index 1ef0e7f6c02..00000000000
--- a/polkadot/node/client/src/lib.rs
+++ /dev/null
@@ -1,590 +0,0 @@
-// Copyright (C) Parity Technologies (UK) Ltd.
-// This file is part of Polkadot.
-
-// Polkadot is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Polkadot is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
-
-//! Polkadot Client
-//!
-//! Provides the [`AbstractClient`] trait that is a super trait that combines all the traits the client implements.
-//! There is also the [`Client`] enum that combines all the different clients into one common structure.
-
-use polkadot_primitives::{
-	runtime_api::ParachainHost, AccountId, Balance, Block, BlockNumber, Hash, Header, Nonce,
-};
-use sc_client_api::{
-	AuxStore, Backend as BackendT, BlockchainEvents, KeysIter, PairsIter, UsageProvider,
-};
-use sc_executor::NativeElseWasmExecutor;
-use sp_api::{CallApiAt, Encode, NumberFor, ProvideRuntimeApi};
-use sp_blockchain::{HeaderBackend, HeaderMetadata};
-use sp_consensus::BlockStatus;
-use sp_runtime::{
-	generic::SignedBlock,
-	traits::{BlakeTwo256, Block as BlockT},
-	Justifications,
-};
-use sp_storage::{ChildInfo, StorageData, StorageKey};
-use std::sync::Arc;
-
-pub mod benchmarking;
-
-pub type FullBackend = sc_service::TFullBackend<Block>;
-
-pub type FullClient<RuntimeApi, ExecutorDispatch> =
-	sc_service::TFullClient<Block, RuntimeApi, NativeElseWasmExecutor<ExecutorDispatch>>;
-
-#[cfg(not(any(
-	feature = "rococo",
-	feature = "kusama",
-	feature = "westend",
-	feature = "polkadot"
-)))]
-compile_error!("at least one runtime feature must be enabled");
-
-/// The native executor instance for Polkadot.
-#[cfg(feature = "polkadot")]
-pub struct PolkadotExecutorDispatch;
-
-#[cfg(feature = "polkadot")]
-impl sc_executor::NativeExecutionDispatch for PolkadotExecutorDispatch {
-	type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;
-
-	fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {
-		polkadot_runtime::api::dispatch(method, data)
-	}
-
-	fn native_version() -> sc_executor::NativeVersion {
-		polkadot_runtime::native_version()
-	}
-}
-
-#[cfg(feature = "kusama")]
-/// The native executor instance for Kusama.
-pub struct KusamaExecutorDispatch;
-
-#[cfg(feature = "kusama")]
-impl sc_executor::NativeExecutionDispatch for KusamaExecutorDispatch {
-	type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;
-
-	fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {
-		kusama_runtime::api::dispatch(method, data)
-	}
-
-	fn native_version() -> sc_executor::NativeVersion {
-		kusama_runtime::native_version()
-	}
-}
-
-#[cfg(feature = "westend")]
-/// The native executor instance for Westend.
-pub struct WestendExecutorDispatch;
-
-#[cfg(feature = "westend")]
-impl sc_executor::NativeExecutionDispatch for WestendExecutorDispatch {
-	type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;
-
-	fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {
-		westend_runtime::api::dispatch(method, data)
-	}
-
-	fn native_version() -> sc_executor::NativeVersion {
-		westend_runtime::native_version()
-	}
-}
-
-#[cfg(feature = "rococo")]
-/// The native executor instance for Rococo.
-pub struct RococoExecutorDispatch;
-
-#[cfg(feature = "rococo")]
-impl sc_executor::NativeExecutionDispatch for RococoExecutorDispatch {
-	type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;
-
-	fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {
-		rococo_runtime::api::dispatch(method, data)
-	}
-
-	fn native_version() -> sc_executor::NativeVersion {
-		rococo_runtime::native_version()
-	}
-}
-
-/// A set of APIs that polkadot-like runtimes must implement.
-pub trait RuntimeApiCollection:
-	sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
-	+ sp_api::ApiExt<Block>
-	+ sp_consensus_babe::BabeApi<Block>
-	+ sp_consensus_grandpa::GrandpaApi<Block>
-	+ ParachainHost<Block>
-	+ sp_block_builder::BlockBuilder<Block>
-	+ frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Nonce>
-	+ sp_mmr_primitives::MmrApi<Block, <Block as BlockT>::Hash, BlockNumber>
-	+ pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>
-	+ sp_api::Metadata<Block>
-	+ sp_offchain::OffchainWorkerApi<Block>
-	+ sp_session::SessionKeys<Block>
-	+ sp_authority_discovery::AuthorityDiscoveryApi<Block>
-	+ sp_consensus_beefy::BeefyApi<Block>
-where
-	<Self as sp_api::ApiExt<Block>>::StateBackend: sp_api::StateBackend<BlakeTwo256>,
-{
-}
-
-impl<Api> RuntimeApiCollection for Api
-where
-	Api: sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block>
-		+ sp_api::ApiExt<Block>
-		+ sp_consensus_babe::BabeApi<Block>
-		+ sp_consensus_grandpa::GrandpaApi<Block>
-		+ ParachainHost<Block>
-		+ sp_block_builder::BlockBuilder<Block>
-		+ frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Nonce>
-		+ sp_mmr_primitives::MmrApi<Block, <Block as BlockT>::Hash, BlockNumber>
-		+ pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance>
-		+ sp_api::Metadata<Block>
-		+ sp_offchain::OffchainWorkerApi<Block>
-		+ sp_session::SessionKeys<Block>
-		+ sp_authority_discovery::AuthorityDiscoveryApi<Block>
-		+ sp_consensus_beefy::BeefyApi<Block>,
-	<Self as sp_api::ApiExt<Block>>::StateBackend: sp_api::StateBackend<BlakeTwo256>,
-{
-}
-
-/// Trait that abstracts over all available client implementations.
-///
-/// For a concrete type there exists [`Client`].
-pub trait AbstractClient<Block, Backend>:
-	BlockchainEvents<Block>
-	+ Sized
-	+ Send
-	+ Sync
-	+ ProvideRuntimeApi<Block>
-	+ HeaderBackend<Block>
-	+ CallApiAt<Block, StateBackend = Backend::State>
-	+ AuxStore
-	+ UsageProvider<Block>
-	+ HeaderMetadata<Block, Error = sp_blockchain::Error>
-where
-	Block: BlockT,
-	Backend: BackendT<Block>,
-	Backend::State: sp_api::StateBackend<BlakeTwo256>,
-	Self::Api: RuntimeApiCollection<StateBackend = Backend::State>,
-{
-}
-
-impl<Block, Backend, Client> AbstractClient<Block, Backend> for Client
-where
-	Block: BlockT,
-	Backend: BackendT<Block>,
-	Backend::State: sp_api::StateBackend<BlakeTwo256>,
-	Client: BlockchainEvents<Block>
-		+ ProvideRuntimeApi<Block>
-		+ HeaderBackend<Block>
-		+ AuxStore
-		+ UsageProvider<Block>
-		+ Sized
-		+ Send
-		+ Sync
-		+ CallApiAt<Block, StateBackend = Backend::State>
-		+ HeaderMetadata<Block, Error = sp_blockchain::Error>,
-	Client::Api: RuntimeApiCollection<StateBackend = Backend::State>,
-{
-}
-
-/// Execute something with the client instance.
-///
-/// As there exist multiple chains inside Polkadot, like Polkadot itself, Kusama, Westend etc,
-/// there can exist different kinds of client types. As these client types differ in the generics
-/// that are being used, we can not easily return them from a function. For returning them from a
-/// function there exists [`Client`]. However, the problem on how to use this client instance still
-/// exists. This trait "solves" it in a dirty way. It requires a type to implement this trait and
-/// than the [`execute_with_client`](ExecuteWithClient::execute_with_client) function can be called
-/// with any possible client instance.
-///
-/// In a perfect world, we could make a closure work in this way.
-pub trait ExecuteWithClient {
-	/// The return type when calling this instance.
-	type Output;
-
-	/// Execute whatever should be executed with the given client instance.
-	fn execute_with_client<Client, Api, Backend>(self, client: Arc<Client>) -> Self::Output
-	where
-		<Api as sp_api::ApiExt<Block>>::StateBackend: sp_api::StateBackend<BlakeTwo256>,
-		Backend: sc_client_api::Backend<Block> + 'static,
-		Backend::State: sp_api::StateBackend<BlakeTwo256>,
-		Api: crate::RuntimeApiCollection<StateBackend = Backend::State>,
-		Client: AbstractClient<Block, Backend, Api = Api> + 'static;
-}
-
-/// A handle to a Polkadot client instance.
-///
-/// The Polkadot service supports multiple different runtimes (Westend, Polkadot itself, etc). As each runtime has a
-/// specialized client, we need to hide them behind a trait. This is this trait.
-///
-/// When wanting to work with the inner client, you need to use `execute_with`.
-///
-/// See [`ExecuteWithClient`](trait.ExecuteWithClient.html) for more information.
-pub trait ClientHandle {
-	/// Execute the given something with the client.
-	fn execute_with<T: ExecuteWithClient>(&self, t: T) -> T::Output;
-}
-
-/// Unwraps a [`Client`] into the concrete client type and
-/// provides the concrete runtime as `runtime`.
-macro_rules! with_client {
-	{
-		// The client instance that should be unwrapped.
-		$self:expr,
-		// The name that the unwrapped client will have.
-		$client:ident,
-		// NOTE: Using an expression here is fine since blocks are also expressions.
-		$code:expr
-	} => {
-		match $self {
-			#[cfg(feature = "polkadot")]
-			Client::Polkadot($client) => {
-				#[allow(unused_imports)]
-				use polkadot_runtime as runtime;
-
-				$code
-			},
-			#[cfg(feature = "westend")]
-			Client::Westend($client) => {
-				#[allow(unused_imports)]
-				use westend_runtime as runtime;
-
-				$code
-			},
-			#[cfg(feature = "kusama")]
-			Client::Kusama($client) => {
-				#[allow(unused_imports)]
-				use kusama_runtime as runtime;
-
-				$code
-			},
-			#[cfg(feature = "rococo")]
-			Client::Rococo($client) => {
-				#[allow(unused_imports)]
-				use rococo_runtime as runtime;
-
-				$code
-			},
-		}
-	}
-}
-// Make the macro available only within this crate.
-pub(crate) use with_client;
-
-/// A client instance of Polkadot.
-///
-/// See [`ExecuteWithClient`] for more information.
-#[derive(Clone)]
-pub enum Client {
-	#[cfg(feature = "polkadot")]
-	Polkadot(Arc<FullClient<polkadot_runtime::RuntimeApi, PolkadotExecutorDispatch>>),
-	#[cfg(feature = "westend")]
-	Westend(Arc<FullClient<westend_runtime::RuntimeApi, WestendExecutorDispatch>>),
-	#[cfg(feature = "kusama")]
-	Kusama(Arc<FullClient<kusama_runtime::RuntimeApi, KusamaExecutorDispatch>>),
-	#[cfg(feature = "rococo")]
-	Rococo(Arc<FullClient<rococo_runtime::RuntimeApi, RococoExecutorDispatch>>),
-}
-
-impl ClientHandle for Client {
-	fn execute_with<T: ExecuteWithClient>(&self, t: T) -> T::Output {
-		with_client! {
-			self,
-			client,
-			{
-				T::execute_with_client::<_, _, FullBackend>(t, client.clone())
-			}
-		}
-	}
-}
-
-impl UsageProvider<Block> for Client {
-	fn usage_info(&self) -> sc_client_api::ClientInfo<Block> {
-		with_client! {
-			self,
-			client,
-			{
-				client.usage_info()
-			}
-		}
-	}
-}
-
-impl sc_client_api::BlockBackend<Block> for Client {
-	fn block_body(
-		&self,
-		hash: <Block as BlockT>::Hash,
-	) -> sp_blockchain::Result<Option<Vec<<Block as BlockT>::Extrinsic>>> {
-		with_client! {
-			self,
-			client,
-			{
-				client.block_body(hash)
-			}
-		}
-	}
-
-	fn block(
-		&self,
-		hash: <Block as BlockT>::Hash,
-	) -> sp_blockchain::Result<Option<SignedBlock<Block>>> {
-		with_client! {
-			self,
-			client,
-			{
-				client.block(hash)
-			}
-		}
-	}
-
-	fn block_status(&self, hash: <Block as BlockT>::Hash) -> sp_blockchain::Result<BlockStatus> {
-		with_client! {
-			self,
-			client,
-			{
-				client.block_status(hash)
-			}
-		}
-	}
-
-	fn justifications(
-		&self,
-		hash: <Block as BlockT>::Hash,
-	) -> sp_blockchain::Result<Option<Justifications>> {
-		with_client! {
-			self,
-			client,
-			{
-				client.justifications(hash)
-			}
-		}
-	}
-
-	fn block_hash(
-		&self,
-		number: NumberFor<Block>,
-	) -> sp_blockchain::Result<Option<<Block as BlockT>::Hash>> {
-		with_client! {
-			self,
-			client,
-			{
-				client.block_hash(number)
-			}
-		}
-	}
-
-	fn indexed_transaction(
-		&self,
-		id: <Block as BlockT>::Hash,
-	) -> sp_blockchain::Result<Option<Vec<u8>>> {
-		with_client! {
-			self,
-			client,
-			{
-				client.indexed_transaction(id)
-			}
-		}
-	}
-
-	fn block_indexed_body(
-		&self,
-		id: <Block as BlockT>::Hash,
-	) -> sp_blockchain::Result<Option<Vec<Vec<u8>>>> {
-		with_client! {
-			self,
-			client,
-			{
-				client.block_indexed_body(id)
-			}
-		}
-	}
-
-	fn requires_full_sync(&self) -> bool {
-		with_client! {
-			self,
-			client,
-			{
-				client.requires_full_sync()
-			}
-		}
-	}
-}
-
-impl sc_client_api::StorageProvider<Block, crate::FullBackend> for Client {
-	fn storage(
-		&self,
-		hash: <Block as BlockT>::Hash,
-		key: &StorageKey,
-	) -> sp_blockchain::Result<Option<StorageData>> {
-		with_client! {
-			self,
-			client,
-			{
-				client.storage(hash, key)
-			}
-		}
-	}
-
-	fn storage_hash(
-		&self,
-		hash: <Block as BlockT>::Hash,
-		key: &StorageKey,
-	) -> sp_blockchain::Result<Option<<Block as BlockT>::Hash>> {
-		with_client! {
-			self,
-			client,
-			{
-				client.storage_hash(hash, key)
-			}
-		}
-	}
-
-	fn storage_pairs(
-		&self,
-		hash: <Block as BlockT>::Hash,
-		key_prefix: Option<&StorageKey>,
-		start_key: Option<&StorageKey>,
-	) -> sp_blockchain::Result<
-		PairsIter<<crate::FullBackend as sc_client_api::Backend<Block>>::State, Block>,
-	> {
-		with_client! {
-			self,
-			client,
-			{
-				client.storage_pairs(hash, key_prefix, start_key)
-			}
-		}
-	}
-
-	fn storage_keys(
-		&self,
-		hash: <Block as BlockT>::Hash,
-		prefix: Option<&StorageKey>,
-		start_key: Option<&StorageKey>,
-	) -> sp_blockchain::Result<
-		KeysIter<<crate::FullBackend as sc_client_api::Backend<Block>>::State, Block>,
-	> {
-		with_client! {
-			self,
-			client,
-			{
-				client.storage_keys(hash, prefix, start_key)
-			}
-		}
-	}
-
-	fn child_storage(
-		&self,
-		hash: <Block as BlockT>::Hash,
-		child_info: &ChildInfo,
-		key: &StorageKey,
-	) -> sp_blockchain::Result<Option<StorageData>> {
-		with_client! {
-			self,
-			client,
-			{
-				client.child_storage(hash, child_info, key)
-			}
-		}
-	}
-
-	fn child_storage_keys(
-		&self,
-		hash: <Block as BlockT>::Hash,
-		child_info: ChildInfo,
-		prefix: Option<&StorageKey>,
-		start_key: Option<&StorageKey>,
-	) -> sp_blockchain::Result<
-		KeysIter<<crate::FullBackend as sc_client_api::Backend<Block>>::State, Block>,
-	> {
-		with_client! {
-			self,
-			client,
-			{
-				client.child_storage_keys(hash, child_info, prefix, start_key)
-			}
-		}
-	}
-
-	fn child_storage_hash(
-		&self,
-		hash: <Block as BlockT>::Hash,
-		child_info: &ChildInfo,
-		key: &StorageKey,
-	) -> sp_blockchain::Result<Option<<Block as BlockT>::Hash>> {
-		with_client! {
-			self,
-			client,
-			{
-				client.child_storage_hash(hash, child_info, key)
-			}
-		}
-	}
-}
-
-impl sp_blockchain::HeaderBackend<Block> for Client {
-	fn header(&self, hash: Hash) -> sp_blockchain::Result<Option<Header>> {
-		with_client! {
-			self,
-			client,
-			{
-				client.header(hash)
-			}
-		}
-	}
-
-	fn info(&self) -> sp_blockchain::Info<Block> {
-		with_client! {
-			self,
-			client,
-			{
-				client.info()
-			}
-		}
-	}
-
-	fn status(&self, hash: Hash) -> sp_blockchain::Result<sp_blockchain::BlockStatus> {
-		with_client! {
-			self,
-			client,
-			{
-				client.status(hash)
-			}
-		}
-	}
-
-	fn number(&self, hash: Hash) -> sp_blockchain::Result<Option<BlockNumber>> {
-		with_client! {
-			self,
-			client,
-			{
-				client.number(hash)
-			}
-		}
-	}
-
-	fn hash(&self, number: BlockNumber) -> sp_blockchain::Result<Option<Hash>> {
-		with_client! {
-			self,
-			client,
-			{
-				client.hash(number)
-			}
-		}
-	}
-}
diff --git a/polkadot/node/service/Cargo.toml b/polkadot/node/service/Cargo.toml
index 34b69d04575..91eb139d67f 100644
--- a/polkadot/node/service/Cargo.toml
+++ b/polkadot/node/service/Cargo.toml
@@ -37,7 +37,8 @@ sp-authority-discovery = { git = "https://github.com/paritytech/substrate", bran
 consensus_common = { package = "sp-consensus", git = "https://github.com/paritytech/substrate", branch = "master" }
 beefy-primitives = { package = "sp-consensus-beefy", git = "https://github.com/paritytech/substrate", branch = "master" }
 grandpa_primitives = { package = "sp-consensus-grandpa", git = "https://github.com/paritytech/substrate", branch = "master" }
-inherents = { package = "sp-inherents", git = "https://github.com/paritytech/substrate", branch = "master" }
+sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" }
+sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" }
 sp-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
 sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
 sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
@@ -49,22 +50,27 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master
 sp-session = { git = "https://github.com/paritytech/substrate", branch = "master" }
 sp-storage = { git = "https://github.com/paritytech/substrate", branch = "master" }
 sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" }
+pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" }
 sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" }
 sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" }
 sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "master" }
 sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "master" }
+sp-weights = { git = "https://github.com/paritytech/substrate", branch = "master" }
+sp-version = { git = "https://github.com/paritytech/substrate", branch = "master" }
 
 # Substrate Pallets
 pallet-babe = { git = "https://github.com/paritytech/substrate", branch = "master" }
 pallet-im-online = { git = "https://github.com/paritytech/substrate", branch = "master" }
 pallet-staking = { git = "https://github.com/paritytech/substrate", branch = "master" }
 pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
+frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" }
 
 # Substrate Other
 frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
 prometheus-endpoint = { package = "substrate-prometheus-endpoint", git = "https://github.com/paritytech/substrate", branch = "master" }
 frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" }
 frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "master" }
+frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" }
 
 # External Crates
 futures = "0.3.21"
@@ -76,15 +82,16 @@ thiserror = "1.0.31"
 kvdb = "0.13.0"
 kvdb-rocksdb = { version = "0.19.0", optional = true }
 parity-db = { version = "0.4.8", optional = true }
+codec = { package = "parity-scale-codec", version = "3.6.1" }
 
 async-trait = "0.1.57"
 lru = "0.9"
 log = "0.4.17"
 
 # Polkadot
+polkadot-core-primitives = { path = "../../core-primitives" }
 polkadot-node-core-parachains-inherent = { path = "../core/parachains-inherent" }
 polkadot-overseer = { path = "../overseer" }
-polkadot-client = { path = "../client", default-features = false, optional = true }
 polkadot-parachain = { path = "../../parachain" }
 polkadot-primitives = { path = "../../primitives" }
 polkadot-node-primitives = { path = "../primitives" }
@@ -94,6 +101,7 @@ polkadot-node-subsystem-util = { path = "../subsystem-util" }
 polkadot-node-subsystem-types = { path = "../subsystem-types" }
 polkadot-runtime-parachains = { path = "../../runtime/parachains" }
 polkadot-node-network-protocol = { path = "../network/protocol" }
+polkadot-runtime-common = { path = "../../runtime/common" }
 
 # Polkadot Runtime Constants
 polkadot-runtime-constants = { path = "../../runtime/polkadot/constants", optional = true }
@@ -138,7 +146,7 @@ assert_matches = "1.5.0"
 tempfile = "3.2"
 
 [features]
-default = ["db", "full-node", "polkadot-native"]
+default = ["db", "full-node"]
 
 db = [
 	"service/rocksdb"
@@ -150,7 +158,6 @@ full-node = [
 	"polkadot-availability-bitfield-distribution",
 	"polkadot-availability-distribution",
 	"polkadot-availability-recovery",
-	"polkadot-client",
 	"polkadot-collator-protocol",
 	"polkadot-dispute-distribution",
 	"polkadot-gossip-support",
@@ -174,10 +181,10 @@ full-node = [
 # Configure the native runtimes to use. Polkadot is enabled by default.
 #
 # Validators require the native runtime currently
-polkadot-native = [ "polkadot-runtime", "polkadot-runtime-constants", "polkadot-client/polkadot" ]
-kusama-native = [ "kusama-runtime", "kusama-runtime-constants", "polkadot-client/kusama" ]
-westend-native = [ "westend-runtime", "westend-runtime-constants", "polkadot-client/westend" ]
-rococo-native = [ "rococo-runtime", "rococo-runtime-constants", "polkadot-client/rococo" ]
+polkadot-native = [ "polkadot-runtime", "polkadot-runtime-constants" ]
+kusama-native = [ "kusama-runtime", "kusama-runtime-constants" ]
+westend-native = [ "westend-runtime", "westend-runtime-constants" ]
+rococo-native = [ "rococo-runtime", "rococo-runtime-constants" ]
 
 runtime-benchmarks = [
 	"polkadot-runtime?/runtime-benchmarks",
@@ -202,7 +209,6 @@ fast-runtime = [
 
 malus = ["full-node"]
 runtime-metrics = [
-	"polkadot-client/runtime-metrics",
 	"rococo-runtime?/runtime-metrics",
 	"westend-runtime?/runtime-metrics",
 	"kusama-runtime?/runtime-metrics",
diff --git a/polkadot/node/service/src/benchmarking.rs b/polkadot/node/service/src/benchmarking.rs
new file mode 100644
index 00000000000..7d2bae88e5f
--- /dev/null
+++ b/polkadot/node/service/src/benchmarking.rs
@@ -0,0 +1,430 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// This file is part of Polkadot.
+
+// Polkadot is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Polkadot is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Code related to benchmarking a [`crate::Client`].
+
+use codec::Encode;
+use polkadot_primitives::AccountId;
+use sc_client_api::UsageProvider;
+use sp_core::{Pair, H256};
+use sp_keyring::Sr25519Keyring;
+use sp_runtime::OpaqueExtrinsic;
+
+use crate::*;
+
+macro_rules! identify_chain {
+	(
+		$chain:expr,
+		$nonce:ident,
+		$current_block:ident,
+		$period:ident,
+		$genesis:ident,
+		$signer:ident,
+		$generic_code:expr $(,)*
+	) => {
+		match $chain {
+			Chain::Polkadot => {
+				#[cfg(feature = "polkadot-native")]
+				{
+					use polkadot_runtime as runtime;
+
+					let call = $generic_code;
+
+					Ok(polkadot_sign_call(call, $nonce, $current_block, $period, $genesis, $signer))
+				}
+
+				#[cfg(not(feature = "polkadot-native"))]
+				{
+					Err("`polkadot-native` feature not enabled")
+				}
+			},
+			Chain::Kusama => {
+				#[cfg(feature = "kusama-native")]
+				{
+					use kusama_runtime as runtime;
+
+					let call = $generic_code;
+
+					Ok(kusama_sign_call(call, $nonce, $current_block, $period, $genesis, $signer))
+				}
+
+				#[cfg(not(feature = "kusama-native"))]
+				{
+					Err("`kusama-native` feature not enabled")
+				}
+			},
+			Chain::Rococo => {
+				#[cfg(feature = "rococo-native")]
+				{
+					use rococo_runtime as runtime;
+
+					let call = $generic_code;
+
+					Ok(rococo_sign_call(call, $nonce, $current_block, $period, $genesis, $signer))
+				}
+
+				#[cfg(not(feature = "rococo-native"))]
+				{
+					Err("`rococo-native` feature not enabled")
+				}
+			},
+			Chain::Westend => {
+				#[cfg(feature = "westend-native")]
+				{
+					use westend_runtime as runtime;
+
+					let call = $generic_code;
+
+					Ok(westend_sign_call(call, $nonce, $current_block, $period, $genesis, $signer))
+				}
+
+				#[cfg(not(feature = "westend-native"))]
+				{
+					Err("`westend-native` feature not enabled")
+				}
+			},
+			Chain::Unknown => Err("Unknown chain"),
+		}
+	};
+}
+
+/// Generates `System::Remark` extrinsics for the benchmarks.
+///
+/// Note: Should only be used for benchmarking.
+pub struct RemarkBuilder {
+	client: Arc<FullClient>,
+	chain: Chain,
+}
+
+impl RemarkBuilder {
+	/// Creates a new [`Self`] from the given client.
+	pub fn new(client: Arc<FullClient>, chain: Chain) -> Self {
+		Self { client, chain }
+	}
+}
+
+impl frame_benchmarking_cli::ExtrinsicBuilder for RemarkBuilder {
+	fn pallet(&self) -> &str {
+		"system"
+	}
+
+	fn extrinsic(&self) -> &str {
+		"remark"
+	}
+
+	fn build(&self, nonce: u32) -> std::result::Result<OpaqueExtrinsic, &'static str> {
+		let period = polkadot_runtime_common::BlockHashCount::get()
+			.checked_next_power_of_two()
+			.map(|c| c / 2)
+			.unwrap_or(2) as u64;
+		let genesis = self.client.usage_info().chain.best_hash;
+		let signer = Sr25519Keyring::Bob.pair();
+		let current_block = 0;
+
+		identify_chain! {
+			self.chain,
+			nonce,
+			current_block,
+			period,
+			genesis,
+			signer,
+			{
+				runtime::RuntimeCall::System(
+					runtime::SystemCall::remark { remark: vec![] }
+				)
+			},
+		}
+	}
+}
+
+/// Generates `Balances::TransferKeepAlive` extrinsics for the benchmarks.
+///
+/// Note: Should only be used for benchmarking.
+pub struct TransferKeepAliveBuilder {
+	client: Arc<FullClient>,
+	dest: AccountId,
+	chain: Chain,
+}
+
+impl TransferKeepAliveBuilder {
+	/// Creates a new [`Self`] from the given client and the arguments for the extrinsics.
+	pub fn new(client: Arc<FullClient>, dest: AccountId, chain: Chain) -> Self {
+		Self { client, dest, chain }
+	}
+}
+
+impl frame_benchmarking_cli::ExtrinsicBuilder for TransferKeepAliveBuilder {
+	fn pallet(&self) -> &str {
+		"balances"
+	}
+
+	fn extrinsic(&self) -> &str {
+		"transfer_keep_alive"
+	}
+
+	fn build(&self, nonce: u32) -> std::result::Result<OpaqueExtrinsic, &'static str> {
+		let signer = Sr25519Keyring::Bob.pair();
+		let period = polkadot_runtime_common::BlockHashCount::get()
+			.checked_next_power_of_two()
+			.map(|c| c / 2)
+			.unwrap_or(2) as u64;
+		let genesis = self.client.usage_info().chain.best_hash;
+		let current_block = 0;
+
+		identify_chain! {
+			self.chain,
+			nonce,
+			current_block,
+			period,
+			genesis,
+			signer,
+			{
+				runtime::RuntimeCall::Balances(runtime::BalancesCall::transfer_keep_alive {
+					dest: self.dest.clone().into(),
+					value: runtime::ExistentialDeposit::get(),
+				})
+			},
+		}
+	}
+}
+
+#[cfg(feature = "polkadot-native")]
+fn polkadot_sign_call(
+	call: polkadot_runtime::RuntimeCall,
+	nonce: u32,
+	current_block: u64,
+	period: u64,
+	genesis: H256,
+	acc: sp_core::sr25519::Pair,
+) -> OpaqueExtrinsic {
+	use polkadot_runtime as runtime;
+
+	let extra: runtime::SignedExtra = (
+		frame_system::CheckNonZeroSender::<runtime::Runtime>::new(),
+		frame_system::CheckSpecVersion::<runtime::Runtime>::new(),
+		frame_system::CheckTxVersion::<runtime::Runtime>::new(),
+		frame_system::CheckGenesis::<runtime::Runtime>::new(),
+		frame_system::CheckMortality::<runtime::Runtime>::from(sp_runtime::generic::Era::mortal(
+			period,
+			current_block,
+		)),
+		frame_system::CheckNonce::<runtime::Runtime>::from(nonce),
+		frame_system::CheckWeight::<runtime::Runtime>::new(),
+		pallet_transaction_payment::ChargeTransactionPayment::<runtime::Runtime>::from(0),
+		polkadot_runtime_common::claims::PrevalidateAttests::<runtime::Runtime>::new(),
+	);
+
+	let payload = runtime::SignedPayload::from_raw(
+		call.clone(),
+		extra.clone(),
+		(
+			(),
+			runtime::VERSION.spec_version,
+			runtime::VERSION.transaction_version,
+			genesis,
+			genesis,
+			(),
+			(),
+			(),
+			(),
+		),
+	);
+
+	let signature = payload.using_encoded(|p| acc.sign(p));
+	runtime::UncheckedExtrinsic::new_signed(
+		call,
+		sp_runtime::AccountId32::from(acc.public()).into(),
+		polkadot_core_primitives::Signature::Sr25519(signature.clone()),
+		extra,
+	)
+	.into()
+}
+
+#[cfg(feature = "westend-native")]
+fn westend_sign_call(
+	call: westend_runtime::RuntimeCall,
+	nonce: u32,
+	current_block: u64,
+	period: u64,
+	genesis: H256,
+	acc: sp_core::sr25519::Pair,
+) -> OpaqueExtrinsic {
+	use westend_runtime as runtime;
+
+	let extra: runtime::SignedExtra = (
+		frame_system::CheckNonZeroSender::<runtime::Runtime>::new(),
+		frame_system::CheckSpecVersion::<runtime::Runtime>::new(),
+		frame_system::CheckTxVersion::<runtime::Runtime>::new(),
+		frame_system::CheckGenesis::<runtime::Runtime>::new(),
+		frame_system::CheckMortality::<runtime::Runtime>::from(sp_runtime::generic::Era::mortal(
+			period,
+			current_block,
+		)),
+		frame_system::CheckNonce::<runtime::Runtime>::from(nonce),
+		frame_system::CheckWeight::<runtime::Runtime>::new(),
+		pallet_transaction_payment::ChargeTransactionPayment::<runtime::Runtime>::from(0),
+	);
+
+	let payload = runtime::SignedPayload::from_raw(
+		call.clone(),
+		extra.clone(),
+		(
+			(),
+			runtime::VERSION.spec_version,
+			runtime::VERSION.transaction_version,
+			genesis,
+			genesis,
+			(),
+			(),
+			(),
+		),
+	);
+
+	let signature = payload.using_encoded(|p| acc.sign(p));
+	runtime::UncheckedExtrinsic::new_signed(
+		call,
+		sp_runtime::AccountId32::from(acc.public()).into(),
+		polkadot_core_primitives::Signature::Sr25519(signature.clone()),
+		extra,
+	)
+	.into()
+}
+
+#[cfg(feature = "kusama-native")]
+fn kusama_sign_call(
+	call: kusama_runtime::RuntimeCall,
+	nonce: u32,
+	current_block: u64,
+	period: u64,
+	genesis: H256,
+	acc: sp_core::sr25519::Pair,
+) -> OpaqueExtrinsic {
+	use kusama_runtime as runtime;
+
+	let extra: runtime::SignedExtra = (
+		frame_system::CheckNonZeroSender::<runtime::Runtime>::new(),
+		frame_system::CheckSpecVersion::<runtime::Runtime>::new(),
+		frame_system::CheckTxVersion::<runtime::Runtime>::new(),
+		frame_system::CheckGenesis::<runtime::Runtime>::new(),
+		frame_system::CheckMortality::<runtime::Runtime>::from(sp_runtime::generic::Era::mortal(
+			period,
+			current_block,
+		)),
+		frame_system::CheckNonce::<runtime::Runtime>::from(nonce),
+		frame_system::CheckWeight::<runtime::Runtime>::new(),
+		pallet_transaction_payment::ChargeTransactionPayment::<runtime::Runtime>::from(0),
+	);
+
+	let payload = runtime::SignedPayload::from_raw(
+		call.clone(),
+		extra.clone(),
+		(
+			(),
+			runtime::VERSION.spec_version,
+			runtime::VERSION.transaction_version,
+			genesis,
+			genesis,
+			(),
+			(),
+			(),
+		),
+	);
+
+	let signature = payload.using_encoded(|p| acc.sign(p));
+	runtime::UncheckedExtrinsic::new_signed(
+		call,
+		sp_runtime::AccountId32::from(acc.public()).into(),
+		polkadot_core_primitives::Signature::Sr25519(signature.clone()),
+		extra,
+	)
+	.into()
+}
+
+#[cfg(feature = "rococo-native")]
+fn rococo_sign_call(
+	call: rococo_runtime::RuntimeCall,
+	nonce: u32,
+	current_block: u64,
+	period: u64,
+	genesis: H256,
+	acc: sp_core::sr25519::Pair,
+) -> OpaqueExtrinsic {
+	use rococo_runtime as runtime;
+
+	let extra: runtime::SignedExtra = (
+		frame_system::CheckNonZeroSender::<runtime::Runtime>::new(),
+		frame_system::CheckSpecVersion::<runtime::Runtime>::new(),
+		frame_system::CheckTxVersion::<runtime::Runtime>::new(),
+		frame_system::CheckGenesis::<runtime::Runtime>::new(),
+		frame_system::CheckMortality::<runtime::Runtime>::from(sp_runtime::generic::Era::mortal(
+			period,
+			current_block,
+		)),
+		frame_system::CheckNonce::<runtime::Runtime>::from(nonce),
+		frame_system::CheckWeight::<runtime::Runtime>::new(),
+		pallet_transaction_payment::ChargeTransactionPayment::<runtime::Runtime>::from(0),
+	);
+
+	let payload = runtime::SignedPayload::from_raw(
+		call.clone(),
+		extra.clone(),
+		(
+			(),
+			runtime::VERSION.spec_version,
+			runtime::VERSION.transaction_version,
+			genesis,
+			genesis,
+			(),
+			(),
+			(),
+		),
+	);
+
+	let signature = payload.using_encoded(|p| acc.sign(p));
+	runtime::UncheckedExtrinsic::new_signed(
+		call,
+		sp_runtime::AccountId32::from(acc.public()).into(),
+		polkadot_core_primitives::Signature::Sr25519(signature.clone()),
+		extra,
+	)
+	.into()
+}
+
+/// Generates inherent data for benchmarking Polkadot, Kusama, Westend and Rococo.
+///
+/// Not to be used outside of benchmarking since it returns mocked values.
+pub fn benchmark_inherent_data(
+	header: polkadot_core_primitives::Header,
+) -> std::result::Result<sp_inherents::InherentData, sp_inherents::Error> {
+	use sp_inherents::InherentDataProvider;
+	let mut inherent_data = sp_inherents::InherentData::new();
+
+	// Assume that all runtimes have the `timestamp` pallet.
+	let d = std::time::Duration::from_millis(0);
+	let timestamp = sp_timestamp::InherentDataProvider::new(d.into());
+	futures::executor::block_on(timestamp.provide_inherent_data(&mut inherent_data))?;
+
+	let para_data = polkadot_primitives::InherentData {
+		bitfields: Vec::new(),
+		backed_candidates: Vec::new(),
+		disputes: Vec::new(),
+		parent_header: header,
+	};
+
+	inherent_data.put_data(polkadot_primitives::PARACHAINS_INHERENT_IDENTIFIER, &para_data)?;
+
+	Ok(inherent_data)
+}
diff --git a/polkadot/node/service/src/chain_spec.rs b/polkadot/node/service/src/chain_spec.rs
index 9e788bc8326..9d76f9c8ce6 100644
--- a/polkadot/node/service/src/chain_spec.rs
+++ b/polkadot/node/service/src/chain_spec.rs
@@ -23,6 +23,12 @@ use kusama_runtime as kusama;
 #[cfg(feature = "kusama-native")]
 use kusama_runtime_constants::currency::UNITS as KSM;
 use pallet_im_online::sr25519::AuthorityId as ImOnlineId;
+#[cfg(any(
+	feature = "polkadot-native",
+	feature = "kusama-native",
+	feature = "westend-native",
+	feature = "rococo-native"
+))]
 use pallet_staking::Forcing;
 use polkadot_primitives::{AccountId, AccountPublic, AssignmentId, ValidatorId};
 #[cfg(feature = "polkadot-native")]
@@ -36,10 +42,30 @@ use sp_consensus_babe::AuthorityId as BabeId;
 use rococo_runtime as rococo;
 #[cfg(feature = "rococo-native")]
 use rococo_runtime_constants::currency::UNITS as ROC;
-use sc_chain_spec::{ChainSpecExtension, ChainType};
+use sc_chain_spec::ChainSpecExtension;
+#[cfg(any(
+	feature = "polkadot-native",
+	feature = "kusama-native",
+	feature = "westend-native",
+	feature = "rococo-native"
+))]
+use sc_chain_spec::ChainType;
 use serde::{Deserialize, Serialize};
 use sp_core::{sr25519, Pair, Public};
-use sp_runtime::{traits::IdentifyAccount, Perbill};
+use sp_runtime::traits::IdentifyAccount;
+#[cfg(any(
+	feature = "polkadot-native",
+	feature = "kusama-native",
+	feature = "westend-native",
+	feature = "rococo-native"
+))]
+use sp_runtime::Perbill;
+#[cfg(any(
+	feature = "polkadot-native",
+	feature = "kusama-native",
+	feature = "westend-native",
+	feature = "rococo-native"
+))]
 use telemetry::TelemetryEndpoints;
 #[cfg(feature = "westend-native")]
 use westend_runtime as westend;
@@ -56,6 +82,12 @@ const WESTEND_STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/
 const ROCOCO_STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/";
 #[cfg(feature = "rococo-native")]
 const VERSI_STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/";
+#[cfg(any(
+	feature = "polkadot-native",
+	feature = "kusama-native",
+	feature = "westend-native",
+	feature = "rococo-native"
+))]
 const DEFAULT_PROTOCOL_ID: &str = "dot";
 
 /// Node `ChainSpec` extensions.
@@ -1271,6 +1303,12 @@ pub fn get_authority_keys_from_seed_no_beefy(
 	)
 }
 
+#[cfg(any(
+	feature = "polkadot-native",
+	feature = "kusama-native",
+	feature = "westend-native",
+	feature = "rococo-native"
+))]
 fn testnet_accounts() -> Vec<AccountId> {
 	vec![
 		get_account_id_from_seed::<sr25519::Public>("Alice"),
@@ -1667,7 +1705,7 @@ pub fn polkadot_development_config() -> Result<PolkadotChainSpec, String> {
 
 	Ok(PolkadotChainSpec::from_genesis(
 		"Development",
-		"dev",
+		"polkadot_dev",
 		ChainType::Development,
 		move || polkadot_development_config_genesis(wasm_binary),
 		vec![],
diff --git a/polkadot/node/service/src/fake_runtime_api.rs b/polkadot/node/service/src/fake_runtime_api.rs
new file mode 100644
index 00000000000..f4864d5c201
--- /dev/null
+++ b/polkadot/node/service/src/fake_runtime_api.rs
@@ -0,0 +1,398 @@
+// Copyright (C) Parity Technologies (UK) Ltd.
+// This file is part of Polkadot.
+
+// Polkadot is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Polkadot is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
+
+//! Provides "fake" runtime api implementations
+//!
+//! These are used to provide a type that implements these runtime apis without requiring to import the native runtimes.
+
+use beefy_primitives::crypto::{AuthorityId as BeefyId, Signature as BeefySignature};
+use grandpa_primitives::AuthorityId as GrandpaId;
+use pallet_transaction_payment::{FeeDetails, RuntimeDispatchInfo};
+use polkadot_primitives::{
+	runtime_api, slashing, AccountId, AuthorityDiscoveryId, Balance, Block, BlockNumber,
+	CandidateCommitments, CandidateEvent, CandidateHash, CommittedCandidateReceipt, CoreState,
+	DisputeState, ExecutorParams, GroupRotationInfo, Hash, Id as ParaId, InboundDownwardMessage,
+	InboundHrmpMessage, Nonce, OccupiedCoreAssumption, PersistedValidationData, PvfCheckStatement,
+	ScrapedOnChainVotes, SessionIndex, SessionInfo, ValidationCode, ValidationCodeHash,
+	ValidatorId, ValidatorIndex, ValidatorSignature,
+};
+use sp_core::OpaqueMetadata;
+use sp_runtime::{
+	traits::Block as BlockT,
+	transaction_validity::{TransactionSource, TransactionValidity},
+	ApplyExtrinsicResult,
+};
+use sp_version::RuntimeVersion;
+use sp_weights::Weight;
+use std::collections::BTreeMap;
+
+sp_api::decl_runtime_apis! {
+	/// This runtime api is only implemented for the test runtime!
+	pub trait GetLastTimestamp {
+		/// Returns the last timestamp of a runtime.
+		fn get_last_timestamp() -> u64;
+	}
+}
+
+struct Runtime;
+
+sp_api::impl_runtime_apis! {
+	impl sp_api::Core<Block> for Runtime {
+		fn version() -> RuntimeVersion {
+			unimplemented!()
+		}
+
+		fn execute_block(_: Block) {
+			unimplemented!()
+		}
+
+		fn initialize_block(_: &<Block as BlockT>::Header) {
+			unimplemented!()
+		}
+	}
+
+	impl sp_api::Metadata<Block> for Runtime {
+		fn metadata() -> OpaqueMetadata {
+			unimplemented!()
+		}
+
+		fn metadata_at_version(_: u32) -> Option<OpaqueMetadata> {
+			unimplemented!()
+		}
+
+		fn metadata_versions() -> Vec<u32> {
+			unimplemented!()
+		}
+	}
+
+	impl sp_block_builder::BlockBuilder<Block> for Runtime {
+		fn apply_extrinsic(_: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
+			unimplemented!()
+		}
+
+		fn finalize_block() -> <Block as BlockT>::Header {
+			unimplemented!()
+		}
+
+		fn inherent_extrinsics(_: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
+			unimplemented!()
+		}
+
+		fn check_inherents(
+			_: Block,
+			_: sp_inherents::InherentData,
+		) -> sp_inherents::CheckInherentsResult {
+			unimplemented!()
+		}
+	}
+
+	impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
+		fn validate_transaction(
+			_: TransactionSource,
+			_: <Block as BlockT>::Extrinsic,
+			_: <Block as BlockT>::Hash,
+		) -> TransactionValidity {
+			unimplemented!()
+		}
+	}
+
+	impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
+		fn offchain_worker(_: &<Block as BlockT>::Header) {
+			unimplemented!()
+		}
+	}
+
+	impl runtime_api::ParachainHost<Block, Hash, BlockNumber> for Runtime {
+		fn validators() -> Vec<ValidatorId> {
+			unimplemented!()
+		}
+
+		fn validator_groups() -> (Vec<Vec<ValidatorIndex>>, GroupRotationInfo<BlockNumber>) {
+			unimplemented!()
+		}
+
+		fn availability_cores() -> Vec<CoreState<Hash, BlockNumber>> {
+			unimplemented!()
+		}
+
+		fn persisted_validation_data(_: ParaId, _: OccupiedCoreAssumption)
+			-> Option<PersistedValidationData<Hash, BlockNumber>> {
+			unimplemented!()
+		}
+
+		fn assumed_validation_data(
+			_: ParaId,
+			_: Hash,
+		) -> Option<(PersistedValidationData<Hash, BlockNumber>, ValidationCodeHash)> {
+			unimplemented!()
+		}
+
+		fn check_validation_outputs(
+			_: ParaId,
+			_: CandidateCommitments,
+		) -> bool {
+			unimplemented!()
+		}
+
+		fn session_index_for_child() -> SessionIndex {
+			unimplemented!()
+		}
+
+		fn validation_code(_: ParaId, _: OccupiedCoreAssumption)
+			-> Option<ValidationCode> {
+			unimplemented!()
+		}
+
+		fn candidate_pending_availability(_: ParaId) -> Option<CommittedCandidateReceipt<Hash>> {
+			unimplemented!()
+		}
+
+		fn candidate_events() -> Vec<CandidateEvent<Hash>> {
+			unimplemented!()
+		}
+
+		fn session_info(_: SessionIndex) -> Option<SessionInfo> {
+			unimplemented!()
+		}
+
+		fn session_executor_params(_: SessionIndex) -> Option<ExecutorParams> {
+			unimplemented!()
+		}
+
+		fn dmq_contents(_: ParaId) -> Vec<InboundDownwardMessage<BlockNumber>> {
+			unimplemented!()
+		}
+
+		fn inbound_hrmp_channels_contents(
+			_: ParaId
+		) -> BTreeMap<ParaId, Vec<InboundHrmpMessage<BlockNumber>>> {
+			unimplemented!()
+		}
+
+		fn validation_code_by_hash(_: ValidationCodeHash) -> Option<ValidationCode> {
+			unimplemented!()
+		}
+
+		fn on_chain_votes() -> Option<ScrapedOnChainVotes<Hash>> {
+			unimplemented!()
+		}
+
+		fn submit_pvf_check_statement(
+			_: PvfCheckStatement,
+			_: ValidatorSignature,
+		) {
+			unimplemented!()
+		}
+
+		fn pvfs_require_precheck() -> Vec<ValidationCodeHash> {
+			unimplemented!()
+		}
+
+		fn validation_code_hash(_: ParaId, _: OccupiedCoreAssumption)
+			-> Option<ValidationCodeHash>
+		{
+			unimplemented!()
+		}
+
+		fn disputes() -> Vec<(SessionIndex, CandidateHash, DisputeState<BlockNumber>)> {
+			unimplemented!()
+		}
+
+		fn unapplied_slashes(
+		) -> Vec<(SessionIndex, CandidateHash, slashing::PendingSlashes)> {
+			unimplemented!()
+		}
+
+		fn key_ownership_proof(
+			_: ValidatorId,
+		) -> Option<slashing::OpaqueKeyOwnershipProof> {
+			unimplemented!()
+		}
+
+		fn submit_report_dispute_lost(
+			_: slashing::DisputeProof,
+			_: slashing::OpaqueKeyOwnershipProof,
+		) -> Option<()> {
+			unimplemented!()
+		}
+	}
+
+	impl beefy_primitives::BeefyApi<Block> for Runtime {
+		fn beefy_genesis() -> Option<BlockNumber> {
+			unimplemented!()
+		}
+
+		fn validator_set() -> Option<beefy_primitives::ValidatorSet<BeefyId>> {
+			unimplemented!()
+		}
+
+		fn submit_report_equivocation_unsigned_extrinsic(
+			_: beefy_primitives::EquivocationProof<
+				BlockNumber,
+				BeefyId,
+				BeefySignature,
+			>,
+			_: beefy_primitives::OpaqueKeyOwnershipProof,
+		) -> Option<()> {
+			unimplemented!()
+		}
+
+		fn generate_key_ownership_proof(
+			_: beefy_primitives::ValidatorSetId,
+			_: BeefyId,
+		) -> Option<beefy_primitives::OpaqueKeyOwnershipProof> {
+			unimplemented!()
+		}
+	}
+
+	impl sp_mmr_primitives::MmrApi<Block, Hash, BlockNumber> for Runtime {
+		fn mmr_root() -> Result<Hash, sp_mmr_primitives::Error> {
+			unimplemented!()
+		}
+
+		fn mmr_leaf_count() -> Result<sp_mmr_primitives::LeafIndex, sp_mmr_primitives::Error> {
+			unimplemented!()
+		}
+
+		fn generate_proof(
+			_: Vec<BlockNumber>,
+			_: Option<BlockNumber>,
+		) -> Result<(Vec<sp_mmr_primitives::EncodableOpaqueLeaf>, sp_mmr_primitives::Proof<Hash>), sp_mmr_primitives::Error> {
+			unimplemented!()
+		}
+
+		fn verify_proof(_: Vec<sp_mmr_primitives::EncodableOpaqueLeaf>, _: sp_mmr_primitives::Proof<Hash>)
+			-> Result<(), sp_mmr_primitives::Error>
+		{
+			unimplemented!()
+		}
+
+		fn verify_proof_stateless(
+			_: Hash,
+			_: Vec<sp_mmr_primitives::EncodableOpaqueLeaf>,
+			_: sp_mmr_primitives::Proof<Hash>
+		) -> Result<(), sp_mmr_primitives::Error> {
+			unimplemented!()
+		}
+	}
+
+	impl grandpa_primitives::GrandpaApi<Block> for Runtime {
+		fn grandpa_authorities() -> Vec<(GrandpaId, u64)> {
+			unimplemented!()
+		}
+
+		fn current_set_id() -> grandpa_primitives::SetId {
+			unimplemented!()
+		}
+
+		fn submit_report_equivocation_unsigned_extrinsic(
+			_: grandpa_primitives::EquivocationProof<
+				<Block as BlockT>::Hash,
+				sp_runtime::traits::NumberFor<Block>,
+			>,
+			_: grandpa_primitives::OpaqueKeyOwnershipProof,
+		) -> Option<()> {
+			unimplemented!()
+		}
+
+		fn generate_key_ownership_proof(
+			_: grandpa_primitives::SetId,
+			_: grandpa_primitives::AuthorityId,
+		) -> Option<grandpa_primitives::OpaqueKeyOwnershipProof> {
+			unimplemented!()
+		}
+	}
+
+	impl sp_consensus_babe::BabeApi<Block> for Runtime {
+		fn configuration() -> sp_consensus_babe::BabeConfiguration {
+			unimplemented!()
+		}
+
+		fn current_epoch_start() -> sp_consensus_babe::Slot {
+			unimplemented!()
+		}
+
+		fn current_epoch() -> sp_consensus_babe::Epoch {
+			unimplemented!()
+		}
+
+		fn next_epoch() -> sp_consensus_babe::Epoch {
+			unimplemented!()
+		}
+
+		fn generate_key_ownership_proof(
+			_: sp_consensus_babe::Slot,
+			_: sp_consensus_babe::AuthorityId,
+		) -> Option<sp_consensus_babe::OpaqueKeyOwnershipProof> {
+			unimplemented!()
+		}
+
+		fn submit_report_equivocation_unsigned_extrinsic(
+			_: sp_consensus_babe::EquivocationProof<<Block as BlockT>::Header>,
+			_: sp_consensus_babe::OpaqueKeyOwnershipProof,
+		) -> Option<()> {
+			unimplemented!()
+		}
+	}
+
+	impl sp_authority_discovery::AuthorityDiscoveryApi<Block> for Runtime {
+		fn authorities() -> Vec<AuthorityDiscoveryId> {
+			unimplemented!()
+		}
+	}
+
+	impl sp_session::SessionKeys<Block> for Runtime {
+		fn generate_session_keys(_: Option<Vec<u8>>) -> Vec<u8> {
+			unimplemented!()
+		}
+
+		fn decode_session_keys(
+			_: Vec<u8>,
+		) -> Option<Vec<(Vec<u8>, sp_core::crypto::KeyTypeId)>> {
+			unimplemented!()
+		}
+	}
+
+	impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Nonce> for Runtime {
+		fn account_nonce(_: AccountId) -> Nonce {
+			unimplemented!()
+		}
+	}
+
+	impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<
+		Block,
+		Balance,
+	> for Runtime {
+		fn query_info(_: <Block as BlockT>::Extrinsic, _: u32) -> RuntimeDispatchInfo<Balance> {
+			unimplemented!()
+		}
+		fn query_fee_details(_: <Block as BlockT>::Extrinsic, _: u32) -> FeeDetails<Balance> {
+			unimplemented!()
+		}
+		fn query_weight_to_fee(_: Weight) -> Balance {
+			unimplemented!()
+		}
+		fn query_length_to_fee(_: u32) -> Balance {
+			unimplemented!()
+		}
+	}
+
+	impl crate::fake_runtime_api::GetLastTimestamp<Block> for Runtime {
+		fn get_last_timestamp() -> u64 {
+			unimplemented!()
+		}
+	}
+}
diff --git a/polkadot/node/service/src/lib.rs b/polkadot/node/service/src/lib.rs
index c48ae9ea2ff..4e22736aeba 100644
--- a/polkadot/node/service/src/lib.rs
+++ b/polkadot/node/service/src/lib.rs
@@ -18,7 +18,15 @@
 
 #![deny(unused_results)]
 
+#[cfg(any(
+	feature = "polkadot-native",
+	feature = "kusama-native",
+	feature = "westend-native",
+	feature = "rococo-native"
+))]
+pub mod benchmarking;
 pub mod chain_spec;
+mod fake_runtime_api;
 mod grandpa_support;
 mod parachains_db;
 mod relay_chain_selection;
@@ -80,34 +88,15 @@ use telemetry::TelemetryWorker;
 #[cfg(feature = "full-node")]
 use telemetry::{Telemetry, TelemetryWorkerHandle};
 
-#[cfg(feature = "rococo-native")]
-pub use polkadot_client::RococoExecutorDispatch;
-
-#[cfg(feature = "westend-native")]
-pub use polkadot_client::WestendExecutorDispatch;
-
-#[cfg(feature = "kusama-native")]
-pub use polkadot_client::KusamaExecutorDispatch;
-
-#[cfg(feature = "polkadot-native")]
-pub use polkadot_client::PolkadotExecutorDispatch;
-
 pub use chain_spec::{KusamaChainSpec, PolkadotChainSpec, RococoChainSpec, WestendChainSpec};
-pub use consensus_common::{block_validation::Chain, Proposal, SelectChain};
+pub use consensus_common::{Proposal, SelectChain};
 use frame_benchmarking_cli::SUBSTRATE_REFERENCE_HARDWARE;
 use mmr_gadget::MmrGadget;
-#[cfg(feature = "full-node")]
-pub use polkadot_client::{
-	AbstractClient, Client, ClientHandle, ExecuteWithClient, FullBackend, FullClient,
-	RuntimeApiCollection,
-};
 pub use polkadot_primitives::{Block, BlockId, BlockNumber, CollatorPair, Hash, Id as ParaId};
 pub use sc_client_api::{Backend, CallExecutor, ExecutionStrategy};
 pub use sc_consensus::{BlockImport, LongestChain};
 pub use sc_executor::NativeExecutionDispatch;
-use sc_executor::{
-	HeapAllocStrategy, NativeElseWasmExecutor, WasmExecutor, DEFAULT_HEAP_ALLOC_STRATEGY,
-};
+use sc_executor::{HeapAllocStrategy, WasmExecutor, DEFAULT_HEAP_ALLOC_STRATEGY};
 pub use service::{
 	config::{DatabaseSource, PrometheusConfig},
 	ChainSpec, Configuration, Error as SubstrateServiceError, PruningMode, Role, RuntimeGenesis,
@@ -130,6 +119,18 @@ pub use {rococo_runtime, rococo_runtime_constants};
 #[cfg(feature = "westend-native")]
 pub use {westend_runtime, westend_runtime_constants};
 
+pub use fake_runtime_api::{GetLastTimestamp, RuntimeApi};
+
+#[cfg(feature = "full-node")]
+pub type FullBackend = service::TFullBackend<Block>;
+
+#[cfg(feature = "full-node")]
+pub type FullClient = service::TFullClient<
+	Block,
+	RuntimeApi,
+	WasmExecutor<(sp_io::SubstrateHostFunctions, frame_benchmarking::benchmarking::HostFunctions)>,
+>;
+
 /// Provides the header and block number for a hash.
 ///
 /// Decouples `sc_client_api::Backend` and `sp_blockchain::HeaderBackend`.
@@ -239,6 +240,21 @@ pub enum Error {
 	NoRuntime,
 }
 
+/// Identifies the variant of the chain.
+#[derive(Debug, Clone, Copy, PartialEq)]
+pub enum Chain {
+	/// Polkadot.
+	Polkadot,
+	/// Kusama.
+	Kusama,
+	/// Rococo or one of its derivations.
+	Rococo,
+	/// Westend.
+	Westend,
+	/// Unknown chain?
+	Unknown,
+}
+
 /// Can be called for a `Configuration` to identify which network the configuration targets.
 pub trait IdentifyVariant {
 	/// Returns if this is a configuration for the `Polkadot` network.
@@ -261,6 +277,9 @@ pub trait IdentifyVariant {
 
 	/// Returns true if this configuration is for a development network.
 	fn is_dev(&self) -> bool;
+
+	/// Identifies the variant of the chain.
+	fn identify_chain(&self) -> Chain;
 }
 
 impl IdentifyVariant for Box<dyn ChainSpec> {
@@ -285,6 +304,19 @@ impl IdentifyVariant for Box<dyn ChainSpec> {
 	fn is_dev(&self) -> bool {
 		self.id().ends_with("dev")
 	}
+	fn identify_chain(&self) -> Chain {
+		if self.is_polkadot() {
+			Chain::Polkadot
+		} else if self.is_kusama() {
+			Chain::Kusama
+		} else if self.is_westend() {
+			Chain::Westend
+		} else if self.is_rococo() || self.is_versi() || self.is_wococo() {
+			Chain::Rococo
+		} else {
+			Chain::Unknown
+		}
+	}
 }
 
 #[cfg(feature = "full-node")]
@@ -340,55 +372,27 @@ fn jaeger_launch_collector_with_agent(
 #[cfg(feature = "full-node")]
 type FullSelectChain = relay_chain_selection::SelectRelayChain<FullBackend>;
 #[cfg(feature = "full-node")]
-type FullGrandpaBlockImport<RuntimeApi, ExecutorDispatch, ChainSelection = FullSelectChain> =
-	grandpa::GrandpaBlockImport<
-		FullBackend,
-		Block,
-		FullClient<RuntimeApi, ExecutorDispatch>,
-		ChainSelection,
-	>;
+type FullGrandpaBlockImport<ChainSelection = FullSelectChain> =
+	grandpa::GrandpaBlockImport<FullBackend, Block, FullClient, ChainSelection>;
 #[cfg(feature = "full-node")]
-type FullBeefyBlockImport<RuntimeApi, ExecutorDispatch, InnerBlockImport> =
-	beefy::import::BeefyBlockImport<
-		Block,
-		FullBackend,
-		FullClient<RuntimeApi, ExecutorDispatch>,
-		InnerBlockImport,
-	>;
+type FullBeefyBlockImport<InnerBlockImport> =
+	beefy::import::BeefyBlockImport<Block, FullBackend, FullClient, InnerBlockImport>;
 
 #[cfg(feature = "full-node")]
-struct Basics<RuntimeApi, ExecutorDispatch>
-where
-	RuntimeApi: ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>
-		+ Send
-		+ Sync
-		+ 'static,
-	RuntimeApi::RuntimeApi:
-		RuntimeApiCollection<StateBackend = sc_client_api::StateBackendFor<FullBackend, Block>>,
-	ExecutorDispatch: NativeExecutionDispatch + 'static,
-{
+struct Basics {
 	task_manager: TaskManager,
-	client: Arc<FullClient<RuntimeApi, ExecutorDispatch>>,
+	client: Arc<FullClient>,
 	backend: Arc<FullBackend>,
 	keystore_container: KeystoreContainer,
 	telemetry: Option<Telemetry>,
 }
 
 #[cfg(feature = "full-node")]
-fn new_partial_basics<RuntimeApi, ExecutorDispatch>(
+fn new_partial_basics(
 	config: &mut Configuration,
 	jaeger_agent: Option<std::net::SocketAddr>,
 	telemetry_worker_handle: Option<TelemetryWorkerHandle>,
-) -> Result<Basics<RuntimeApi, ExecutorDispatch>, Error>
-where
-	RuntimeApi: ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>
-		+ Send
-		+ Sync
-		+ 'static,
-	RuntimeApi::RuntimeApi:
-		RuntimeApiCollection<StateBackend = sc_client_api::StateBackendFor<FullBackend, Block>>,
-	ExecutorDispatch: NativeExecutionDispatch + 'static,
-{
+) -> Result<Basics, Error> {
 	let telemetry = config
 		.telemetry_endpoints
 		.clone()
@@ -410,7 +414,7 @@ where
 		.default_heap_pages
 		.map_or(DEFAULT_HEAP_ALLOC_STRATEGY, |h| HeapAllocStrategy::Static { extra_pages: h as _ });
 
-	let wasm = WasmExecutor::builder()
+	let executor = WasmExecutor::builder()
 		.with_execution_method(config.wasm_method)
 		.with_onchain_heap_alloc_strategy(heap_pages)
 		.with_offchain_heap_alloc_strategy(heap_pages)
@@ -418,8 +422,6 @@ where
 		.with_runtime_cache_size(config.runtime_cache_size)
 		.build();
 
-	let executor = NativeElseWasmExecutor::<ExecutorDispatch>::new_with_wasm_executor(wasm);
-
 	let (client, backend, keystore_container, task_manager) =
 		service::new_full_parts::<Block, RuntimeApi, _>(
 			&config,
@@ -445,20 +447,17 @@ where
 }
 
 #[cfg(feature = "full-node")]
-fn new_partial<RuntimeApi, ExecutorDispatch, ChainSelection>(
+fn new_partial<ChainSelection>(
 	config: &mut Configuration,
-	Basics { task_manager, backend, client, keystore_container, telemetry }: Basics<
-		RuntimeApi,
-		ExecutorDispatch,
-	>,
+	Basics { task_manager, backend, client, keystore_container, telemetry }: Basics,
 	select_chain: ChainSelection,
 ) -> Result<
 	service::PartialComponents<
-		FullClient<RuntimeApi, ExecutorDispatch>,
+		FullClient,
 		FullBackend,
 		ChainSelection,
-		sc_consensus::DefaultImportQueue<Block, FullClient<RuntimeApi, ExecutorDispatch>>,
-		sc_transaction_pool::FullPool<Block, FullClient<RuntimeApi, ExecutorDispatch>>,
+		sc_consensus::DefaultImportQueue<Block, FullClient>,
+		sc_transaction_pool::FullPool<Block, FullClient>,
 		(
 			impl Fn(
 				polkadot_rpc::DenyUnsafe,
@@ -467,14 +466,10 @@ fn new_partial<RuntimeApi, ExecutorDispatch, ChainSelection>(
 			(
 				babe::BabeBlockImport<
 					Block,
-					FullClient<RuntimeApi, ExecutorDispatch>,
-					FullBeefyBlockImport<
-						RuntimeApi,
-						ExecutorDispatch,
-						FullGrandpaBlockImport<RuntimeApi, ExecutorDispatch, ChainSelection>,
-					>,
+					FullClient,
+					FullBeefyBlockImport<FullGrandpaBlockImport<ChainSelection>>,
 				>,
-				grandpa::LinkHalf<Block, FullClient<RuntimeApi, ExecutorDispatch>, ChainSelection>,
+				grandpa::LinkHalf<Block, FullClient, ChainSelection>,
 				babe::BabeLink<Block>,
 				beefy::BeefyVoterLinks<Block>,
 			),
@@ -486,13 +481,6 @@ fn new_partial<RuntimeApi, ExecutorDispatch, ChainSelection>(
 	Error,
 >
 where
-	RuntimeApi: ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>
-		+ Send
-		+ Sync
-		+ 'static,
-	RuntimeApi::RuntimeApi:
-		RuntimeApiCollection<StateBackend = sc_client_api::StateBackendFor<FullBackend, Block>>,
-	ExecutorDispatch: NativeExecutionDispatch + 'static,
 	ChainSelection: 'static + SelectChain<Block>,
 {
 	let transaction_pool = sc_transaction_pool::BasicPool::new_full(
@@ -616,9 +604,9 @@ where
 }
 
 #[cfg(feature = "full-node")]
-pub struct NewFull<C> {
+pub struct NewFull {
 	pub task_manager: TaskManager,
-	pub client: C,
+	pub client: Arc<FullClient>,
 	pub overseer_handle: Option<Handle>,
 	pub network: Arc<sc_network::NetworkService<Block, <Block as BlockT>::Hash>>,
 	pub sync_service: Arc<sc_network_sync::SyncingService<Block>>,
@@ -626,22 +614,6 @@ pub struct NewFull<C> {
 	pub backend: Arc<FullBackend>,
 }
 
-#[cfg(feature = "full-node")]
-impl<C> NewFull<C> {
-	/// Convert the client type using the given `func`.
-	pub fn with_client<NC>(self, func: impl FnOnce(C) -> NC) -> NewFull<NC> {
-		NewFull {
-			client: func(self.client),
-			task_manager: self.task_manager,
-			overseer_handle: self.overseer_handle,
-			network: self.network,
-			sync_service: self.sync_service,
-			rpc_handlers: self.rpc_handlers,
-			backend: self.backend,
-		}
-	}
-}
-
 /// Is this node a collator?
 #[cfg(feature = "full-node")]
 #[derive(Clone)]
@@ -685,7 +657,7 @@ pub const AVAILABILITY_CONFIG: AvailabilityConfig = AvailabilityConfig {
 /// regardless of the role the node has. The relay chain selection (longest or disputes-aware) is
 /// still determined based on the role of the node. Likewise for authority discovery.
 #[cfg(feature = "full-node")]
-pub fn new_full<RuntimeApi, ExecutorDispatch, OverseerGenerator>(
+pub fn new_full<OverseerGenerator>(
 	mut config: Configuration,
 	is_collator: IsCollator,
 	grandpa_pause: Option<(u32, u32)>,
@@ -698,15 +670,8 @@ pub fn new_full<RuntimeApi, ExecutorDispatch, OverseerGenerator>(
 	overseer_message_channel_capacity_override: Option<usize>,
 	_malus_finality_delay: Option<u32>,
 	hwbench: Option<sc_sysinfo::HwBench>,
-) -> Result<NewFull<Arc<FullClient<RuntimeApi, ExecutorDispatch>>>, Error>
+) -> Result<NewFull, Error>
 where
-	RuntimeApi: ConstructRuntimeApi<Block, FullClient<RuntimeApi, ExecutorDispatch>>
-		+ Send
-		+ Sync
-		+ 'static,
-	RuntimeApi::RuntimeApi:
-		RuntimeApiCollection<StateBackend = sc_client_api::StateBackendFor<FullBackend, Block>>,
-	ExecutorDispatch: NativeExecutionDispatch + 'static,
 	OverseerGenerator: OverseerGen,
 {
 	use polkadot_node_network_protocol::request_response::IncomingRequest;
@@ -743,11 +708,7 @@ where
 	let disable_grandpa = config.disable_grandpa;
 	let name = config.network.node_name.clone();
 
-	let basics = new_partial_basics::<RuntimeApi, ExecutorDispatch>(
-		&mut config,
-		jaeger_agent,
-		telemetry_worker_handle,
-	)?;
+	let basics = new_partial_basics(&mut config, jaeger_agent, telemetry_worker_handle)?;
 
 	let prometheus_registry = config.prometheus_registry().cloned();
 
@@ -783,11 +744,7 @@ where
 		import_queue,
 		transaction_pool,
 		other: (rpc_extensions_builder, import_setup, rpc_setup, slot_duration, mut telemetry),
-	} = new_partial::<RuntimeApi, ExecutorDispatch, SelectRelayChain<_>>(
-		&mut config,
-		basics,
-		select_chain,
-	)?;
+	} = new_partial::<SelectRelayChain<_>>(&mut config, basics, select_chain)?;
 
 	let shared_voter_state = rpc_setup;
 	let auth_disc_publish_non_global_ips = config.network.allow_non_globals_in_dht;
@@ -1003,7 +960,7 @@ where
 
 	let overseer_handle = if let Some(authority_discovery_service) = authority_discovery_service {
 		let (overseer, overseer_handle) = overseer_gen
-			.generate::<service::SpawnTaskHandle, FullClient<RuntimeApi, ExecutorDispatch>>(
+			.generate::<service::SpawnTaskHandle, FullClient>(
 				overseer_connector,
 				OverseerGenArgs {
 					keystore,
@@ -1259,27 +1216,19 @@ where
 
 #[cfg(feature = "full-node")]
 macro_rules! chain_ops {
-	($config:expr, $jaeger_agent:expr, $telemetry_worker_handle:expr; $scope:ident, $executor:ident, $variant:ident) => {{
+	($config:expr, $jaeger_agent:expr, $telemetry_worker_handle:expr) => {{
 		let telemetry_worker_handle = $telemetry_worker_handle;
 		let jaeger_agent = $jaeger_agent;
 		let mut config = $config;
-		let basics = new_partial_basics::<$scope::RuntimeApi, $executor>(
-			config,
-			jaeger_agent,
-			telemetry_worker_handle,
-		)?;
+		let basics = new_partial_basics(config, jaeger_agent, telemetry_worker_handle)?;
 
 		use ::sc_consensus::LongestChain;
 		// use the longest chain selection, since there is no overseer available
 		let chain_selection = LongestChain::new(basics.backend.clone());
 
 		let service::PartialComponents { client, backend, import_queue, task_manager, .. } =
-			new_partial::<$scope::RuntimeApi, $executor, LongestChain<_, Block>>(
-				&mut config,
-				basics,
-				chain_selection,
-			)?;
-		Ok((Arc::new(Client::$variant(client)), backend, import_queue, task_manager))
+			new_partial::<LongestChain<_, Block>>(&mut config, basics, chain_selection)?;
+		Ok((client, backend, import_queue, task_manager))
 	}};
 }
 
@@ -1290,7 +1239,7 @@ pub fn new_chain_ops(
 	jaeger_agent: Option<std::net::SocketAddr>,
 ) -> Result<
 	(
-		Arc<Client>,
+		Arc<FullClient>,
 		Arc<FullBackend>,
 		sc_consensus::BasicQueue<Block, PrefixedMemoryDB<BlakeTwo256>>,
 		TaskManager,
@@ -1299,35 +1248,17 @@ pub fn new_chain_ops(
 > {
 	config.keystore = service::config::KeystoreConfig::InMemory;
 
-	#[cfg(feature = "rococo-native")]
 	if config.chain_spec.is_rococo() ||
 		config.chain_spec.is_wococo() ||
 		config.chain_spec.is_versi()
 	{
-		return chain_ops!(config, jaeger_agent, None; rococo_runtime, RococoExecutorDispatch, Rococo)
-	}
-
-	#[cfg(feature = "kusama-native")]
-	if config.chain_spec.is_kusama() {
-		return chain_ops!(config, jaeger_agent, None; kusama_runtime, KusamaExecutorDispatch, Kusama)
-	}
-
-	#[cfg(feature = "westend-native")]
-	if config.chain_spec.is_westend() {
-		return chain_ops!(config, jaeger_agent, None; westend_runtime, WestendExecutorDispatch, Westend)
-	}
-
-	#[cfg(feature = "polkadot-native")]
-	{
-		return chain_ops!(config, jaeger_agent, None; polkadot_runtime, PolkadotExecutorDispatch, Polkadot)
-	}
-
-	#[cfg(not(feature = "polkadot-native"))]
-	{
-		let _ = config;
-		let _ = jaeger_agent;
-
-		Err(Error::NoRuntime)
+		chain_ops!(config, jaeger_agent, None)
+	} else if config.chain_spec.is_kusama() {
+		chain_ops!(config, jaeger_agent, None)
+	} else if config.chain_spec.is_westend() {
+		return chain_ops!(config, jaeger_agent, None)
+	} else {
+		chain_ops!(config, jaeger_agent, None)
 	}
 }
 
@@ -1352,105 +1283,28 @@ pub fn build_full(
 	overseer_message_channel_override: Option<usize>,
 	malus_finality_delay: Option<u32>,
 	hwbench: Option<sc_sysinfo::HwBench>,
-) -> Result<NewFull<Client>, Error> {
-	#[cfg(feature = "rococo-native")]
-	if config.chain_spec.is_rococo() ||
-		config.chain_spec.is_wococo() ||
-		config.chain_spec.is_versi()
-	{
-		return new_full::<rococo_runtime::RuntimeApi, RococoExecutorDispatch, _>(
-			config,
-			is_collator,
-			grandpa_pause,
-			enable_beefy,
-			jaeger_agent,
-			telemetry_worker_handle,
-			None,
-			overseer_enable_anyways,
-			overseer_gen,
-			overseer_message_channel_override,
-			malus_finality_delay,
-			hwbench,
-		)
-		.map(|full| full.with_client(Client::Rococo))
-	}
-
-	#[cfg(feature = "kusama-native")]
-	if config.chain_spec.is_kusama() {
-		return new_full::<kusama_runtime::RuntimeApi, KusamaExecutorDispatch, _>(
-			config,
-			is_collator,
-			grandpa_pause,
-			enable_beefy,
-			jaeger_agent,
-			telemetry_worker_handle,
-			None,
-			overseer_enable_anyways,
-			overseer_gen,
-			overseer_message_channel_override,
-			malus_finality_delay,
-			hwbench,
-		)
-		.map(|full| full.with_client(Client::Kusama))
-	}
+) -> Result<NewFull, Error> {
+	let is_polkadot = config.chain_spec.is_polkadot();
 
-	#[cfg(feature = "westend-native")]
-	if config.chain_spec.is_westend() {
-		return new_full::<westend_runtime::RuntimeApi, WestendExecutorDispatch, _>(
-			config,
-			is_collator,
-			grandpa_pause,
-			enable_beefy,
-			jaeger_agent,
-			telemetry_worker_handle,
-			None,
-			overseer_enable_anyways,
-			overseer_gen,
-			overseer_message_channel_override,
-			malus_finality_delay,
-			hwbench,
-		)
-		.map(|full| full.with_client(Client::Westend))
-	}
-
-	#[cfg(feature = "polkadot-native")]
-	{
-		return new_full::<polkadot_runtime::RuntimeApi, PolkadotExecutorDispatch, _>(
-			config,
-			is_collator,
-			grandpa_pause,
-			enable_beefy,
-			jaeger_agent,
-			telemetry_worker_handle,
-			None,
-			overseer_enable_anyways,
-			overseer_gen,
-			overseer_message_channel_override.map(|capacity| {
+	new_full(
+		config,
+		is_collator,
+		grandpa_pause,
+		enable_beefy,
+		jaeger_agent,
+		telemetry_worker_handle,
+		None,
+		overseer_enable_anyways,
+		overseer_gen,
+		overseer_message_channel_override.map(move |capacity| {
+			if is_polkadot {
 				gum::warn!("Channel capacity should _never_ be tampered with on polkadot!");
-				capacity
-			}),
-			malus_finality_delay,
-			hwbench,
-		)
-		.map(|full| full.with_client(Client::Polkadot))
-	}
-
-	#[cfg(not(feature = "polkadot-native"))]
-	{
-		let _ = config;
-		let _ = is_collator;
-		let _ = grandpa_pause;
-		let _ = enable_beefy;
-		let _ = jaeger_agent;
-		let _ = telemetry_worker_handle;
-		let _ = overseer_enable_anyways;
-		let _ = overseer_gen;
-		let _ = overseer_message_channel_override;
-		let _ = malus_finality_delay;
-		let _ = hwbench;
-
-		Err(Error::NoRuntime)
-	}
+			}
+			capacity
+		}),
+		malus_finality_delay,
+		hwbench,
+	)
 }
 
 /// Reverts the node state down to at most the last finalized block.
@@ -1461,7 +1315,7 @@ pub fn build_full(
 /// - Low level Babe and Grandpa consensus data.
 #[cfg(feature = "full-node")]
 pub fn revert_backend(
-	client: Arc<Client>,
+	client: Arc<FullClient>,
 	backend: Arc<FullBackend>,
 	blocks: BlockNumber,
 	config: Configuration,
@@ -1488,7 +1342,8 @@ pub fn revert_backend(
 	revert_approval_voting(parachains_db.clone(), hash)?;
 	revert_chain_selection(parachains_db, hash)?;
 	// Revert Substrate consensus related components
-	client.execute_with(RevertConsensus { blocks, backend })?;
+	babe::revert(client.clone(), backend, blocks)?;
+	grandpa::revert(client, blocks)?;
 
 	Ok(())
 }
@@ -1525,27 +1380,3 @@ fn revert_approval_voting(db: Arc<dyn Database>, hash: Hash) -> sp_blockchain::R
 		.revert_to(hash)
 		.map_err(|err| sp_blockchain::Error::Backend(err.to_string()))
 }
-
-struct RevertConsensus {
-	blocks: BlockNumber,
-	backend: Arc<FullBackend>,
-}
-
-impl ExecuteWithClient for RevertConsensus {
-	type Output = sp_blockchain::Result<()>;
-
-	fn execute_with_client<Client, Api, Backend>(self, client: Arc<Client>) -> Self::Output
-	where
-		<Api as sp_api::ApiExt<Block>>::StateBackend: sp_api::StateBackend<BlakeTwo256>,
-		Backend: sc_client_api::Backend<Block> + 'static,
-		Backend::State: sp_api::StateBackend<BlakeTwo256>,
-		Api: polkadot_client::RuntimeApiCollection<StateBackend = Backend::State>,
-		Client: AbstractClient<Block, Backend, Api = Api> + 'static,
-	{
-		// Revert consensus-related components.
-		// The operations are not correlated, thus call order is not relevant.
-		babe::revert(client.clone(), self.backend, self.blocks)?;
-		grandpa::revert(client, self.blocks)?;
-		Ok(())
-	}
-}
diff --git a/polkadot/node/test/client/Cargo.toml b/polkadot/node/test/client/Cargo.toml
index 7f61ed2408a..366d244952c 100644
--- a/polkadot/node/test/client/Cargo.toml
+++ b/polkadot/node/test/client/Cargo.toml
@@ -18,6 +18,7 @@ substrate-test-client = { git = "https://github.com/paritytech/substrate", branc
 sc-service = { git = "https://github.com/paritytech/substrate", branch = "master" }
 sc-block-builder = { git = "https://github.com/paritytech/substrate", branch = "master" }
 sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
+sc-offchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
 sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
 sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master" }
 sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" }
@@ -27,6 +28,8 @@ sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "mast
 sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
 sp-consensus-babe = { git = "https://github.com/paritytech/substrate", branch = "master" }
 sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "master" }
+sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" }
+frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" }
 
 [dev-dependencies]
 sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" }
diff --git a/polkadot/node/test/client/src/block_builder.rs b/polkadot/node/test/client/src/block_builder.rs
index 33b01d018d0..88160e782a7 100644
--- a/polkadot/node/test/client/src/block_builder.rs
+++ b/polkadot/node/test/client/src/block_builder.rs
@@ -17,7 +17,8 @@
 use crate::{Client, FullBackend};
 use parity_scale_codec::{Decode, Encode};
 use polkadot_primitives::{Block, InherentData as ParachainsInherentData};
-use polkadot_test_runtime::{GetLastTimestamp, UncheckedExtrinsic};
+use polkadot_test_runtime::UncheckedExtrinsic;
+use polkadot_test_service::GetLastTimestamp;
 use sc_block_builder::{BlockBuilder, BlockBuilderProvider};
 use sp_api::ProvideRuntimeApi;
 use sp_consensus_babe::{
diff --git a/polkadot/node/test/client/src/lib.rs b/polkadot/node/test/client/src/lib.rs
index 457634a9e16..2996bc84c76 100644
--- a/polkadot/node/test/client/src/lib.rs
+++ b/polkadot/node/test/client/src/lib.rs
@@ -22,12 +22,12 @@ mod block_builder;
 
 use polkadot_primitives::Block;
 use sp_runtime::BuildStorage;
+use std::sync::Arc;
 
 pub use block_builder::*;
 pub use polkadot_test_runtime as runtime;
 pub use polkadot_test_service::{
 	construct_extrinsic, construct_transfer_extrinsic, Client, FullBackend,
-	PolkadotTestExecutorDispatch,
 };
 pub use substrate_test_client::*;
 
@@ -35,7 +35,7 @@ pub use substrate_test_client::*;
 pub type Executor = client::LocalCallExecutor<
 	Block,
 	FullBackend,
-	sc_executor::NativeElseWasmExecutor<PolkadotTestExecutorDispatch>,
+	WasmExecutor<(sp_io::SubstrateHostFunctions, frame_benchmarking::benchmarking::HostFunctions)>,
 >;
 
 /// Test client builder for Polkadot.
@@ -70,7 +70,21 @@ pub trait TestClientBuilderExt: Sized {
 
 impl TestClientBuilderExt for TestClientBuilder {
 	fn build_with_longest_chain(self) -> (Client, LongestChain) {
-		self.build_with_native_executor(None)
+		let executor = WasmExecutor::builder().build();
+		let executor = client::LocalCallExecutor::new(
+			self.backend().clone(),
+			executor.clone(),
+			Default::default(),
+			ExecutionExtensions::new(
+				Default::default(),
+				None,
+				sc_offchain::OffchainDb::factory_from_backend(&*self.backend()),
+				Arc::new(executor),
+			),
+		)
+		.unwrap();
+
+		self.build_with_executor(executor)
 	}
 }
 
diff --git a/polkadot/node/test/service/Cargo.toml b/polkadot/node/test/service/Cargo.toml
index 8bf8ba6976b..504ee5beca7 100644
--- a/polkadot/node/test/service/Cargo.toml
+++ b/polkadot/node/test/service/Cargo.toml
@@ -31,7 +31,6 @@ sc-authority-discovery = { git = "https://github.com/paritytech/substrate", bran
 babe = { package = "sc-consensus-babe", git = "https://github.com/paritytech/substrate", branch = "master" }
 babe-primitives = { package = "sp-consensus-babe", git = "https://github.com/paritytech/substrate", branch = "master" }
 consensus_common = { package = "sp-consensus", git = "https://github.com/paritytech/substrate", branch = "master" }
-frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master" }
 frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" }
 grandpa = { package = "sc-consensus-grandpa", git = "https://github.com/paritytech/substrate", branch = "master" }
 grandpa_primitives = { package = "sp-consensus-grandpa", git = "https://github.com/paritytech/substrate", branch = "master" }
@@ -43,7 +42,6 @@ sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "mas
 sc-cli = { git = "https://github.com/paritytech/substrate", branch = "master" }
 sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "master" }
 sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "master" }
-sc-executor = { git = "https://github.com/paritytech/substrate", branch = "master" }
 sc-network = { git = "https://github.com/paritytech/substrate", branch = "master" }
 sc-tracing = { git = "https://github.com/paritytech/substrate", branch = "master" }
 sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "master" }
diff --git a/polkadot/node/test/service/src/lib.rs b/polkadot/node/test/service/src/lib.rs
index 3e7f6612888..08d09f8fe69 100644
--- a/polkadot/node/test/service/src/lib.rs
+++ b/polkadot/node/test/service/src/lib.rs
@@ -28,9 +28,7 @@ use polkadot_overseer::Handle;
 use polkadot_primitives::{Balance, CollatorPair, HeadData, Id as ParaId, ValidationCode};
 use polkadot_runtime_common::BlockHashCount;
 use polkadot_runtime_parachains::paras::{ParaGenesisArgs, ParaKind};
-use polkadot_service::{
-	ClientHandle, Error, ExecuteWithClient, FullClient, IsCollator, NewFull, PrometheusConfig,
-};
+use polkadot_service::{Error, FullClient, IsCollator, NewFull, PrometheusConfig};
 use polkadot_test_runtime::{
 	ParasCall, ParasSudoWrapperCall, Runtime, SignedExtra, SignedPayload, SudoCall,
 	UncheckedExtrinsic, VERSION,
@@ -63,26 +61,11 @@ use std::{
 use substrate_test_client::{
 	BlockchainEventsExt, RpcHandlersExt, RpcTransactionError, RpcTransactionOutput,
 };
-/// Declare an instance of the native executor named `PolkadotTestExecutorDispatch`. Include the wasm binary as the
-/// equivalent wasm code.
-pub struct PolkadotTestExecutorDispatch;
-
-impl sc_executor::NativeExecutionDispatch for PolkadotTestExecutorDispatch {
-	type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions;
-
-	fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {
-		polkadot_test_runtime::api::dispatch(method, data)
-	}
-
-	fn native_version() -> sc_executor::NativeVersion {
-		polkadot_test_runtime::native_version()
-	}
-}
 
 /// The client type being used by the test service.
-pub type Client = FullClient<polkadot_test_runtime::RuntimeApi, PolkadotTestExecutorDispatch>;
+pub type Client = FullClient;
 
-pub use polkadot_service::FullBackend;
+pub use polkadot_service::{FullBackend, GetLastTimestamp};
 
 /// Create a new full node.
 #[sc_tracing::logging::prefix_logs_with(config.network.node_name.as_str())]
@@ -90,8 +73,8 @@ pub fn new_full(
 	config: Configuration,
 	is_collator: IsCollator,
 	worker_program_path: Option<PathBuf>,
-) -> Result<NewFull<Arc<Client>>, Error> {
-	polkadot_service::new_full::<polkadot_test_runtime::RuntimeApi, PolkadotTestExecutorDispatch, _>(
+) -> Result<NewFull, Error> {
+	polkadot_service::new_full(
 		config,
 		is_collator,
 		None,
@@ -107,15 +90,6 @@ pub fn new_full(
 	)
 }
 
-/// A wrapper for the test client that implements `ClientHandle`.
-pub struct TestClient(pub Arc<Client>);
-
-impl ClientHandle for TestClient {
-	fn execute_with<T: ExecuteWithClient>(&self, t: T) -> T::Output {
-		T::execute_with_client::<_, _, polkadot_service::FullBackend>(t, self.0.clone())
-	}
-}
-
 /// Returns a prometheus config usable for testing.
 pub fn test_prometheus_config(port: u16) -> PrometheusConfig {
 	PrometheusConfig::new_with_default_registry(
diff --git a/polkadot/tests/purge_chain_works.rs b/polkadot/tests/purge_chain_works.rs
index c93a0dde9a8..3e9a3781478 100644
--- a/polkadot/tests/purge_chain_works.rs
+++ b/polkadot/tests/purge_chain_works.rs
@@ -55,9 +55,9 @@ async fn purge_chain_rocksdb_works() {
 	kill(Pid::from_raw(cmd.id().try_into().unwrap()), SIGINT).unwrap();
 	// Wait for the node to handle it and exit.
 	assert!(common::wait_for(&mut cmd, 30).map(|x| x.success()).unwrap_or_default());
-	assert!(tmpdir.path().join("chains/dev").exists());
-	assert!(tmpdir.path().join("chains/dev/db/full").exists());
-	assert!(tmpdir.path().join("chains/dev/db/full/parachains").exists());
+	assert!(tmpdir.path().join("chains/polkadot_dev").exists());
+	assert!(tmpdir.path().join("chains/polkadot_dev/db/full").exists());
+	assert!(tmpdir.path().join("chains/polkadot_dev/db/full/parachains").exists());
 
 	// Purge chain
 	let status = Command::new(cargo_bin("polkadot"))
@@ -69,8 +69,8 @@ async fn purge_chain_rocksdb_works() {
 	assert!(status.success());
 
 	// Make sure that the chain folder exists, but `db/full` is deleted.
-	assert!(tmpdir.path().join("chains/dev").exists());
-	assert!(!tmpdir.path().join("chains/dev/db/full").exists());
+	assert!(tmpdir.path().join("chains/polkadot_dev").exists());
+	assert!(!tmpdir.path().join("chains/polkadot_dev/db/full").exists());
 }
 
 #[tokio::test]
@@ -105,9 +105,9 @@ async fn purge_chain_paritydb_works() {
 	kill(Pid::from_raw(cmd.id().try_into().unwrap()), SIGINT).unwrap();
 	// Wait for the node to handle it and exit.
 	assert!(common::wait_for(&mut cmd, 30).map(|x| x.success()).unwrap_or_default());
-	assert!(tmpdir.path().join("chains/dev").exists());
-	assert!(tmpdir.path().join("chains/dev/paritydb/full").exists());
-	assert!(tmpdir.path().join("chains/dev/paritydb/parachains").exists());
+	assert!(tmpdir.path().join("chains/polkadot_dev").exists());
+	assert!(tmpdir.path().join("chains/polkadot_dev/paritydb/full").exists());
+	assert!(tmpdir.path().join("chains/polkadot_dev/paritydb/parachains").exists());
 
 	// Purge chain
 	let status = Command::new(cargo_bin("polkadot"))
@@ -121,8 +121,8 @@ async fn purge_chain_paritydb_works() {
 	assert!(status.success());
 
 	// Make sure that the chain folder exists, but `db/full` is deleted.
-	assert!(tmpdir.path().join("chains/dev").exists());
-	assert!(!tmpdir.path().join("chains/dev/paritydb/full").exists());
+	assert!(tmpdir.path().join("chains/polkadot_dev").exists());
+	assert!(!tmpdir.path().join("chains/polkadot_dev/paritydb/full").exists());
 	// Parachains removal requires calling "purge-chain --parachains".
-	assert!(tmpdir.path().join("chains/dev/paritydb/parachains").exists());
+	assert!(tmpdir.path().join("chains/polkadot_dev/paritydb/parachains").exists());
 }
-- 
GitLab