From 6a295e7c283b0a418ff98af26464319838031245 Mon Sep 17 00:00:00 2001
From: Michal Kucharczyk <1728078+michalkucharczyk@users.noreply.github.com>
Date: Thu, 4 May 2023 18:20:22 +0200
Subject: [PATCH] substrate-test-runtime migrated to "pure" frame runtime
 (#13737)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* substrate-test-runtime migrated to pure-frame based

* test block builder: helpers added

* simple renaming

* basic_authorship test adjusted

* block_building storage_proof test adjusted

* babe: tests: should_panic expected added

* babe: tests adjusted

ConsensusLog::NextEpochData is now added by pallet_babe as
pallet_babe::SameAuthoritiesForever trigger is used in runtime config.

* beefy: tests adjusted

test-substrate-runtime is now using frame::executive to finalize the
block. during finalization the digests stored during block execution are
checked against header digests:
https://github.com/paritytech/substrate/blob/91bb2d29ca905599098a5b35eaf24867c4fbd60a/frame/executive/src/lib.rs#L585-L591

It makes impossible to directly manipulate header's digets, w/o
depositing logs into system pallet storage `Digest<T: Config>`.

Instead of this dedicated extrinsic allowing to store logs items
(MmrRoot / AuthoritiesChange) is used.

* grandpa: tests adjusted

test-substrate-runtime is now using frame::executive to finalize the
block. during finalization the digest logs stored during block execution are
checked against header digest logs:
https://github.com/paritytech/substrate/blob/91bb2d29ca905599098a5b35eaf24867c4fbd60a/frame/executive/src/lib.rs#L585-L591

It makes impossible to directly manipulate header's digets, w/o
depositing logs into system pallet storage `Digest<T: Config>`.

Instead of this dedicated extrinsic allowing to store logs items
(ScheduledChange / ForcedChange and DigestItem::Other) is used.

* network:bitswap: test adjusted

The size of unchecked extrinsic was increased. The pattern used in test will
be placed at the end of scale-encoded buffer.

* runtime apis versions adjusted

* storage keys used in runtime adjusted

* wasm vs native tests removed

* rpc tests: adjusted

Transfer transaction processing was slightly improved, test was
adjusted.

* tests: sizes adjusted

Runtime extrinsic size was increased. Size of data read during block
execution was also increased due to usage of new pallets in runtime.

Sizes were adjusted in tests.

* cargo.lock update

cargo update -p substrate-test-runtime -p substrate-test-runtime-client

* warnings fixed

* builders cleanup: includes / std

* extrinsic validation cleanup

* txpool: benches performance fixed

* fmt

* spelling

* Apply suggestions from code review

Co-authored-by: Davide Galassi <davxy@datawok.net>

* Apply code review suggestions

* Apply code review suggestions

* get rid of 1063 const

* renaming: UncheckedExtrinsic -> Extrinsic

* test-utils-runtime: further step to pure-frame

* basic-authorship: tests OK

* CheckSubstrateCall added + tests fixes

* test::Transfer call removed

* priority / propagate / no sudo+root-testing

* fixing warnings + format

* cleanup: build2/nonce + format

* final tests fixes

all tests are passing

* logs/comments removal

* should_not_accept_old_signatures test removed

* make txpool benches work again

* Cargo.lock reset

* format

* sudo hack removed

* txpool benches fix+cleanup

* .gitignore reverted

* rebase fixing + unsigned cleanup

* Cargo.toml/Cargo.lock cleanup

* force-debug feature removed

* mmr tests fixed

* make cargo-clippy happy

* network sync test uses unsigned extrinsic

* cleanup

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

* push_storage_change signed call remove

* GenesisConfig cleanup

* fix

* fix

* GenesisConfig simplified

* storage_keys_works: reworked

* storage_keys_works: expected keys in vec

* storage keys list moved to substrate-test-runtime

* substrate-test: some sanity tests + GenesisConfigBuilder rework

* Apply suggestions from code review

Co-authored-by: Bastian Köcher <git@kchr.de>

* Apply suggestions from code review

* Review suggestions

* fix

* fix

* beefy: generate_blocks_and_sync block_num sync with actaul value

* Apply suggestions from code review

Co-authored-by: Davide Galassi <davxy@datawok.net>

* Update test-utils/runtime/src/genesismap.rs

Co-authored-by: Davide Galassi <davxy@datawok.net>

* cargo update -p sc-rpc -p sc-transaction-pool

* Review suggestions

* fix

* doc added

* slot_duration adjusted for Babe::slot_duration

* small doc fixes

* array_bytes::hex used instead of hex

* tiny -> medium name fix

* Apply suggestions from code review

Co-authored-by: Sebastian Kunert <skunert49@gmail.com>

* TransferData::try_from_unchecked_extrinsic -> try_from

* Update Cargo.lock

---------

Co-authored-by: parity-processbot <>
Co-authored-by: Davide Galassi <davxy@datawok.net>
Co-authored-by: Bastian Köcher <git@kchr.de>
Co-authored-by: Sebastian Kunert <skunert49@gmail.com>
---
 substrate/Cargo.lock                          |   80 +-
 .../basic-authorship/src/basic_authorship.rs  |  180 +-
 substrate/client/basic-authorship/src/lib.rs  |    2 +-
 substrate/client/block-builder/src/lib.rs     |   19 +-
 substrate/client/consensus/babe/src/tests.rs  |   61 +-
 substrate/client/consensus/beefy/src/tests.rs |   42 +-
 .../client/consensus/grandpa/src/tests.rs     |  117 +-
 .../consensus/grandpa/src/warp_proof.rs       |   12 +-
 substrate/client/network/bitswap/src/lib.rs   |    8 +-
 substrate/client/network/test/src/lib.rs      |   16 +-
 substrate/client/network/test/src/sync.rs     |    8 +-
 substrate/client/offchain/src/lib.rs          |   26 +-
 .../rpc-spec-v2/src/chain_head/tests.rs       |    7 +-
 substrate/client/rpc/src/author/tests.rs      |   31 +-
 substrate/client/rpc/src/dev/tests.rs         |   22 +-
 substrate/client/rpc/src/state/tests.rs       |   63 +-
 substrate/client/service/src/lib.rs           |   11 +-
 .../client/service/test/src/client/mod.rs     |  225 +--
 .../client/transaction-pool/benches/basics.rs |   21 +-
 .../client/transaction-pool/src/graph/pool.rs |   95 +-
 .../transaction-pool/src/revalidation.rs      |    3 +-
 .../client/transaction-pool/src/tests.rs      |   26 +-
 .../client/transaction-pool/tests/pool.rs     |  115 +-
 .../api/test/tests/runtime_calls.rs           |   51 +-
 substrate/test-utils/runtime/Cargo.toml       |   18 +-
 .../runtime/client/src/block_builder_ext.rs   |   21 +-
 .../test-utils/runtime/client/src/lib.rs      |   66 +-
 substrate/test-utils/runtime/src/extrinsic.rs |  207 ++
 .../test-utils/runtime/src/genesismap.rs      |  148 +-
 substrate/test-utils/runtime/src/lib.rs       | 1765 +++++++----------
 .../runtime/src/substrate_test_pallet.rs      |  244 +++
 substrate/test-utils/runtime/src/system.rs    |  587 ------
 .../runtime/transaction-pool/src/lib.rs       |   10 +-
 substrate/utils/frame/rpc/system/src/lib.rs   |    8 +-
 34 files changed, 1951 insertions(+), 2364 deletions(-)
 create mode 100644 substrate/test-utils/runtime/src/extrinsic.rs
 create mode 100644 substrate/test-utils/runtime/src/substrate_test_pallet.rs
 delete mode 100644 substrate/test-utils/runtime/src/system.rs

diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock
index e65562a56b5..3f1fd0bd580 100644
--- a/substrate/Cargo.lock
+++ b/substrate/Cargo.lock
@@ -291,6 +291,12 @@ version = "4.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f52f63c5c1316a16a4b35eaac8b76a98248961a533f061684cb2a7cb0eafb6c6"
 
+[[package]]
+name = "array-bytes"
+version = "6.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b1c5a481ec30a5abd8dfbd94ab5cf1bb4e9a66be7f1b3b322f2f1170c200fd"
+
 [[package]]
 name = "arrayref"
 version = "0.3.6"
@@ -597,7 +603,7 @@ dependencies = [
 name = "binary-merkle-tree"
 version = "4.0.0-dev"
 dependencies = [
- "array-bytes",
+ "array-bytes 4.2.0",
  "env_logger 0.9.3",
  "hash-db",
  "log",
@@ -2327,7 +2333,7 @@ checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa"
 name = "frame-benchmarking"
 version = "4.0.0-dev"
 dependencies = [
- "array-bytes",
+ "array-bytes 4.2.0",
  "frame-support",
  "frame-support-procedural",
  "frame-system",
@@ -2355,7 +2361,7 @@ name = "frame-benchmarking-cli"
 version = "4.0.0-dev"
 dependencies = [
  "Inflector",
- "array-bytes",
+ "array-bytes 4.2.0",
  "chrono",
  "clap 4.2.5",
  "comfy-table",
@@ -2465,7 +2471,7 @@ dependencies = [
 name = "frame-executive"
 version = "4.0.0-dev"
 dependencies = [
- "array-bytes",
+ "array-bytes 4.2.0",
  "frame-support",
  "frame-system",
  "frame-try-runtime",
@@ -5043,7 +5049,7 @@ dependencies = [
 name = "node-bench"
 version = "0.9.0-dev"
 dependencies = [
- "array-bytes",
+ "array-bytes 4.2.0",
  "clap 4.2.5",
  "derive_more",
  "fs_extra",
@@ -5079,7 +5085,7 @@ dependencies = [
 name = "node-cli"
 version = "3.0.0-dev"
 dependencies = [
- "array-bytes",
+ "array-bytes 4.2.0",
  "assert_cmd",
  "clap 4.2.5",
  "clap_complete",
@@ -5641,7 +5647,7 @@ dependencies = [
 name = "pallet-alliance"
 version = "4.0.0-dev"
 dependencies = [
- "array-bytes",
+ "array-bytes 4.2.0",
  "frame-benchmarking",
  "frame-support",
  "frame-system",
@@ -5898,7 +5904,7 @@ dependencies = [
 name = "pallet-beefy-mmr"
 version = "4.0.0-dev"
 dependencies = [
- "array-bytes",
+ "array-bytes 4.2.0",
  "binary-merkle-tree",
  "frame-support",
  "frame-system",
@@ -5975,7 +5981,7 @@ dependencies = [
 name = "pallet-contracts"
 version = "4.0.0-dev"
 dependencies = [
- "array-bytes",
+ "array-bytes 4.2.0",
  "assert_matches",
  "bitflags",
  "env_logger 0.9.3",
@@ -6420,7 +6426,7 @@ dependencies = [
 name = "pallet-mmr"
 version = "4.0.0-dev"
 dependencies = [
- "array-bytes",
+ "array-bytes 4.2.0",
  "env_logger 0.9.3",
  "frame-benchmarking",
  "frame-support",
@@ -7128,7 +7134,7 @@ dependencies = [
 name = "pallet-transaction-storage"
 version = "4.0.0-dev"
 dependencies = [
- "array-bytes",
+ "array-bytes 4.2.0",
  "frame-benchmarking",
  "frame-support",
  "frame-system",
@@ -8584,7 +8590,7 @@ dependencies = [
 name = "sc-cli"
 version = "0.10.0-dev"
 dependencies = [
- "array-bytes",
+ "array-bytes 4.2.0",
  "chrono",
  "clap 4.2.5",
  "fdlimit",
@@ -8655,7 +8661,7 @@ dependencies = [
 name = "sc-client-db"
 version = "0.10.0-dev"
 dependencies = [
- "array-bytes",
+ "array-bytes 4.2.0",
  "criterion",
  "hash-db",
  "kitchensink-runtime",
@@ -8822,7 +8828,7 @@ dependencies = [
 name = "sc-consensus-beefy"
 version = "4.0.0-dev"
 dependencies = [
- "array-bytes",
+ "array-bytes 4.2.0",
  "async-trait",
  "fnv",
  "futures",
@@ -8899,7 +8905,7 @@ name = "sc-consensus-grandpa"
 version = "0.10.0-dev"
 dependencies = [
  "ahash 0.8.3",
- "array-bytes",
+ "array-bytes 4.2.0",
  "assert_matches",
  "async-trait",
  "dyn-clone",
@@ -9053,7 +9059,7 @@ dependencies = [
 name = "sc-executor"
 version = "0.10.0-dev"
 dependencies = [
- "array-bytes",
+ "array-bytes 4.2.0",
  "assert_matches",
  "criterion",
  "env_logger 0.9.3",
@@ -9156,7 +9162,7 @@ dependencies = [
 name = "sc-keystore"
 version = "4.0.0-dev"
 dependencies = [
- "array-bytes",
+ "array-bytes 4.2.0",
  "async-trait",
  "parking_lot 0.12.1",
  "serde_json",
@@ -9171,7 +9177,7 @@ dependencies = [
 name = "sc-network"
 version = "0.10.0-dev"
 dependencies = [
- "array-bytes",
+ "array-bytes 4.2.0",
  "assert_matches",
  "async-channel",
  "async-trait",
@@ -9253,7 +9259,7 @@ dependencies = [
 name = "sc-network-common"
 version = "0.10.0-dev"
 dependencies = [
- "array-bytes",
+ "array-bytes 4.2.0",
  "async-trait",
  "bitflags",
  "bytes",
@@ -9302,7 +9308,7 @@ dependencies = [
 name = "sc-network-light"
 version = "0.10.0-dev"
 dependencies = [
- "array-bytes",
+ "array-bytes 4.2.0",
  "futures",
  "libp2p",
  "log",
@@ -9323,7 +9329,7 @@ dependencies = [
 name = "sc-network-statement"
 version = "0.10.0-dev"
 dependencies = [
- "array-bytes",
+ "array-bytes 4.2.0",
  "async-channel",
  "futures",
  "libp2p",
@@ -9343,7 +9349,7 @@ dependencies = [
 name = "sc-network-sync"
 version = "0.10.0-dev"
 dependencies = [
- "array-bytes",
+ "array-bytes 4.2.0",
  "async-trait",
  "fork-tree",
  "futures",
@@ -9413,7 +9419,7 @@ dependencies = [
 name = "sc-network-transactions"
 version = "0.10.0-dev"
 dependencies = [
- "array-bytes",
+ "array-bytes 4.2.0",
  "futures",
  "libp2p",
  "log",
@@ -9432,7 +9438,7 @@ dependencies = [
 name = "sc-offchain"
 version = "4.0.0-dev"
 dependencies = [
- "array-bytes",
+ "array-bytes 4.2.0",
  "bytes",
  "fnv",
  "futures",
@@ -9562,7 +9568,7 @@ dependencies = [
 name = "sc-rpc-spec-v2"
 version = "0.10.0-dev"
 dependencies = [
- "array-bytes",
+ "array-bytes 4.2.0",
  "assert_matches",
  "futures",
  "futures-util",
@@ -9676,7 +9682,7 @@ dependencies = [
 name = "sc-service-test"
 version = "2.0.0"
 dependencies = [
- "array-bytes",
+ "array-bytes 4.2.0",
  "async-channel",
  "fdlimit",
  "futures",
@@ -9858,7 +9864,7 @@ dependencies = [
 name = "sc-transaction-pool"
 version = "4.0.0-dev"
 dependencies = [
- "array-bytes",
+ "array-bytes 4.2.0",
  "assert_matches",
  "async-trait",
  "criterion",
@@ -10585,7 +10591,7 @@ dependencies = [
 name = "sp-consensus-beefy"
 version = "4.0.0-dev"
 dependencies = [
- "array-bytes",
+ "array-bytes 4.2.0",
  "lazy_static",
  "parity-scale-codec",
  "scale-info",
@@ -10644,7 +10650,7 @@ dependencies = [
 name = "sp-core"
 version = "7.0.0"
 dependencies = [
- "array-bytes",
+ "array-bytes 4.2.0",
  "bitflags",
  "blake2",
  "bounded-collections",
@@ -10824,7 +10830,7 @@ dependencies = [
 name = "sp-mmr-primitives"
 version = "4.0.0-dev"
 dependencies = [
- "array-bytes",
+ "array-bytes 4.2.0",
  "ckb-merkle-mountain-range",
  "log",
  "parity-scale-codec",
@@ -11031,7 +11037,7 @@ dependencies = [
 name = "sp-state-machine"
 version = "0.13.0"
 dependencies = [
- "array-bytes",
+ "array-bytes 4.2.0",
  "assert_matches",
  "hash-db",
  "log",
@@ -11149,7 +11155,7 @@ name = "sp-trie"
 version = "7.0.0"
 dependencies = [
  "ahash 0.8.3",
- "array-bytes",
+ "array-bytes 4.2.0",
  "criterion",
  "hash-db",
  "hashbrown 0.13.2",
@@ -11501,7 +11507,7 @@ dependencies = [
 name = "substrate-test-client"
 version = "2.0.1"
 dependencies = [
- "array-bytes",
+ "array-bytes 4.2.0",
  "async-trait",
  "futures",
  "parity-scale-codec",
@@ -11526,7 +11532,8 @@ dependencies = [
 name = "substrate-test-runtime"
 version = "2.0.0"
 dependencies = [
- "cfg-if",
+ "array-bytes 6.1.0",
+ "frame-executive",
  "frame-support",
  "frame-system",
  "frame-system-rpc-runtime-api",
@@ -11534,7 +11541,10 @@ dependencies = [
  "log",
  "memory-db",
  "pallet-babe",
+ "pallet-balances",
  "pallet-beefy-mmr",
+ "pallet-root-testing",
+ "pallet-sudo",
  "pallet-timestamp",
  "parity-scale-codec",
  "sc-block-builder",
@@ -11551,6 +11561,7 @@ dependencies = [
  "sp-consensus-beefy",
  "sp-consensus-grandpa",
  "sp-core",
+ "sp-debug-derive",
  "sp-externalities",
  "sp-inherents",
  "sp-io",
@@ -11561,6 +11572,7 @@ dependencies = [
  "sp-session",
  "sp-state-machine",
  "sp-std",
+ "sp-tracing",
  "sp-transaction-pool",
  "sp-trie",
  "sp-version",
diff --git a/substrate/client/basic-authorship/src/basic_authorship.rs b/substrate/client/basic-authorship/src/basic_authorship.rs
index 795288d0a1d..642900d2f35 100644
--- a/substrate/client/basic-authorship/src/basic_authorship.rs
+++ b/substrate/client/basic-authorship/src/basic_authorship.rs
@@ -547,37 +547,29 @@ mod tests {
 	use sp_api::Core;
 	use sp_blockchain::HeaderBackend;
 	use sp_consensus::{BlockOrigin, Environment, Proposer};
-	use sp_core::Pair;
-	use sp_runtime::{generic::BlockId, traits::NumberFor};
+	use sp_runtime::{generic::BlockId, traits::NumberFor, Perbill};
 	use substrate_test_runtime_client::{
 		prelude::*,
-		runtime::{Extrinsic, Transfer},
+		runtime::{Block as TestBlock, Extrinsic, ExtrinsicBuilder, Transfer},
 		TestClientBuilder, TestClientBuilderExt,
 	};
 
 	const SOURCE: TransactionSource = TransactionSource::External;
 
-	fn extrinsic(nonce: u64) -> Extrinsic {
-		Transfer {
-			amount: Default::default(),
-			nonce,
-			from: AccountKeyring::Alice.into(),
-			to: AccountKeyring::Bob.into(),
-		}
-		.into_signed_tx()
-	}
+	// Note:
+	// Maximum normal extrinsic size for `substrate_test_runtime` is ~65% of max_block (refer to
+	// `substrate_test_runtime::RuntimeBlockWeights` for details).
+	// This extrinsic sizing allows for:
+	// - one huge xts + a lot of tiny dust
+	// - one huge, no medium,
+	// - two medium xts
+	// This is widely exploited in following tests.
+	const HUGE: u32 = 649000000;
+	const MEDIUM: u32 = 250000000;
+	const TINY: u32 = 1000;
 
-	fn exhausts_resources_extrinsic_from(who: usize) -> Extrinsic {
-		let pair = AccountKeyring::numeric(who);
-		let transfer = Transfer {
-			// increase the amount to bump priority
-			amount: 1,
-			nonce: 0,
-			from: pair.public(),
-			to: AccountKeyring::Bob.into(),
-		};
-		let signature = pair.sign(&transfer.encode()).into();
-		Extrinsic::Transfer { transfer, signature, exhaust_resources_when_not_first: true }
+	fn extrinsic(nonce: u64) -> Extrinsic {
+		ExtrinsicBuilder::new_fill_block(Perbill::from_parts(TINY)).nonce(nonce).build()
 	}
 
 	fn chain_event<B: BlockT>(header: B::Header) -> ChainEvent<B>
@@ -738,7 +730,7 @@ mod tests {
 	#[test]
 	fn should_not_remove_invalid_transactions_from_the_same_sender_after_one_was_invalid() {
 		// given
-		let mut client = Arc::new(substrate_test_runtime_client::new());
+		let client = Arc::new(substrate_test_runtime_client::new());
 		let spawner = sp_core::testing::TaskExecutor::new();
 		let txpool = BasicPool::new_full(
 			Default::default(),
@@ -748,38 +740,29 @@ mod tests {
 			client.clone(),
 		);
 
+		let medium = |nonce| {
+			ExtrinsicBuilder::new_fill_block(Perbill::from_parts(MEDIUM))
+				.nonce(nonce)
+				.build()
+		};
+		let huge = |nonce| {
+			ExtrinsicBuilder::new_fill_block(Perbill::from_parts(HUGE)).nonce(nonce).build()
+		};
+
 		block_on(txpool.submit_at(
 			&BlockId::number(0),
 			SOURCE,
-			vec![
-				extrinsic(0),
-				extrinsic(1),
-				Transfer {
-					amount: Default::default(),
-					nonce: 2,
-					from: AccountKeyring::Alice.into(),
-					to: AccountKeyring::Bob.into(),
-				}.into_resources_exhausting_tx(),
-				extrinsic(3),
-				Transfer {
-					amount: Default::default(),
-					nonce: 4,
-					from: AccountKeyring::Alice.into(),
-					to: AccountKeyring::Bob.into(),
-				}.into_resources_exhausting_tx(),
-				extrinsic(5),
-				extrinsic(6),
-			],
+			vec![medium(0), medium(1), huge(2), medium(3), huge(4), medium(5), medium(6)],
 		))
 		.unwrap();
 
 		let mut proposer_factory =
 			ProposerFactory::new(spawner.clone(), client.clone(), txpool.clone(), None, None);
 		let mut propose_block = |client: &TestClient,
-		                         number,
+		                         parent_number,
 		                         expected_block_extrinsics,
 		                         expected_pool_transactions| {
-			let hash = client.expect_block_hash_from_id(&BlockId::Number(number)).unwrap();
+			let hash = client.expect_block_hash_from_id(&BlockId::Number(parent_number)).unwrap();
 			let proposer = proposer_factory.init_with_now(
 				&client.expect_header(hash).unwrap(),
 				Box::new(move || time::Instant::now()),
@@ -794,12 +777,30 @@ mod tests {
 
 			// then
 			// block should have some extrinsics although we have some more in the pool.
-			assert_eq!(txpool.ready().count(), expected_pool_transactions);
-			assert_eq!(block.extrinsics().len(), expected_block_extrinsics);
+			assert_eq!(
+				txpool.ready().count(),
+				expected_pool_transactions,
+				"at block: {}",
+				block.header.number
+			);
+			assert_eq!(
+				block.extrinsics().len(),
+				expected_block_extrinsics,
+				"at block: {}",
+				block.header.number
+			);
 
 			block
 		};
 
+		let import_and_maintain = |mut client: Arc<TestClient>, block: TestBlock| {
+			let hash = block.hash();
+			block_on(client.import(BlockOrigin::Own, block)).unwrap();
+			block_on(txpool.maintain(chain_event(
+				client.expect_header(hash).expect("there should be header"),
+			)));
+		};
+
 		block_on(
 			txpool.maintain(chain_event(
 				client
@@ -811,19 +812,28 @@ mod tests {
 
 		// let's create one block and import it
 		let block = propose_block(&client, 0, 2, 7);
-		let hashof1 = block.hash();
-		block_on(client.import(BlockOrigin::Own, block)).unwrap();
-
-		block_on(
-			txpool.maintain(chain_event(
-				client.expect_header(hashof1).expect("there should be header"),
-			)),
-		);
+		import_and_maintain(client.clone(), block);
 		assert_eq!(txpool.ready().count(), 5);
 
 		// now let's make sure that we can still make some progress
-		let block = propose_block(&client, 1, 2, 5);
-		block_on(client.import(BlockOrigin::Own, block)).unwrap();
+		let block = propose_block(&client, 1, 1, 5);
+		import_and_maintain(client.clone(), block);
+		assert_eq!(txpool.ready().count(), 4);
+
+		// again let's make sure that we can still make some progress
+		let block = propose_block(&client, 2, 1, 4);
+		import_and_maintain(client.clone(), block);
+		assert_eq!(txpool.ready().count(), 3);
+
+		// again let's make sure that we can still make some progress
+		let block = propose_block(&client, 3, 1, 3);
+		import_and_maintain(client.clone(), block);
+		assert_eq!(txpool.ready().count(), 2);
+
+		// again let's make sure that we can still make some progress
+		let block = propose_block(&client, 4, 2, 2);
+		import_and_maintain(client.clone(), block);
+		assert_eq!(txpool.ready().count(), 0);
 	}
 
 	#[test]
@@ -849,9 +859,9 @@ mod tests {
 				amount: 100,
 				nonce: 0,
 			}
-			.into_signed_tx(),
+			.into_unchecked_extrinsic(),
 		)
-		.chain((0..extrinsics_num - 1).map(|v| Extrinsic::IncludeData(vec![v as u8; 10])))
+		.chain((1..extrinsics_num as u64).map(extrinsic))
 		.collect::<Vec<_>>();
 
 		let block_limit = genesis_header.encoded_size() +
@@ -862,7 +872,7 @@ mod tests {
 				.sum::<usize>() +
 			Vec::<Extrinsic>::new().encoded_size();
 
-		block_on(txpool.submit_at(&BlockId::number(0), SOURCE, extrinsics)).unwrap();
+		block_on(txpool.submit_at(&BlockId::number(0), SOURCE, extrinsics.clone())).unwrap();
 
 		block_on(txpool.maintain(chain_event(genesis_header.clone())));
 
@@ -905,7 +915,13 @@ mod tests {
 
 		let proposer = block_on(proposer_factory.init(&genesis_header)).unwrap();
 
-		// Give it enough time
+		// Exact block_limit, which includes:
+		// 99 (header_size) + 718 (proof@initialize_block) + 246 (one Transfer extrinsic)
+		let block_limit = {
+			let builder =
+				client.new_block_at(genesis_header.hash(), Default::default(), true).unwrap();
+			builder.estimate_block_size(true) + extrinsics[0].encoded_size()
+		};
 		let block = block_on(proposer.propose(
 			Default::default(),
 			Default::default(),
@@ -915,7 +931,7 @@ mod tests {
 		.map(|r| r.block)
 		.unwrap();
 
-		// The block limit didn't changed, but we now include the proof in the estimation of the
+		// The block limit was increased, but we now include the proof in the estimation of the
 		// block size and thus, only the `Transfer` will fit into the block. It reads more data
 		// than we have reserved in the block limit.
 		assert_eq!(block.extrinsics().len(), 1);
@@ -934,6 +950,15 @@ mod tests {
 			client.clone(),
 		);
 
+		let tiny = |nonce| {
+			ExtrinsicBuilder::new_fill_block(Perbill::from_parts(TINY)).nonce(nonce).build()
+		};
+		let huge = |who| {
+			ExtrinsicBuilder::new_fill_block(Perbill::from_parts(HUGE))
+				.signer(AccountKeyring::numeric(who))
+				.build()
+		};
+
 		block_on(
 			txpool.submit_at(
 				&BlockId::number(0),
@@ -941,9 +966,9 @@ mod tests {
 				// add 2 * MAX_SKIPPED_TRANSACTIONS that exhaust resources
 				(0..MAX_SKIPPED_TRANSACTIONS * 2)
 					.into_iter()
-					.map(|i| exhausts_resources_extrinsic_from(i))
+					.map(huge)
 					// and some transactions that are okay.
-					.chain((0..MAX_SKIPPED_TRANSACTIONS).into_iter().map(|i| extrinsic(i as _)))
+					.chain((0..MAX_SKIPPED_TRANSACTIONS as u64).into_iter().map(tiny))
 					.collect(),
 			),
 		)
@@ -997,15 +1022,27 @@ mod tests {
 			client.clone(),
 		);
 
+		let tiny = |who| {
+			ExtrinsicBuilder::new_fill_block(Perbill::from_parts(TINY))
+				.signer(AccountKeyring::numeric(who))
+				.nonce(1)
+				.build()
+		};
+		let huge = |who| {
+			ExtrinsicBuilder::new_fill_block(Perbill::from_parts(HUGE))
+				.signer(AccountKeyring::numeric(who))
+				.build()
+		};
+
 		block_on(
 			txpool.submit_at(
 				&BlockId::number(0),
 				SOURCE,
 				(0..MAX_SKIPPED_TRANSACTIONS + 2)
 					.into_iter()
-					.map(|i| exhausts_resources_extrinsic_from(i))
+					.map(huge)
 					// and some transactions that are okay.
-					.chain((0..MAX_SKIPPED_TRANSACTIONS).into_iter().map(|i| extrinsic(i as _)))
+					.chain((0..MAX_SKIPPED_TRANSACTIONS + 2).into_iter().map(tiny))
 					.collect(),
 			),
 		)
@@ -1018,7 +1055,7 @@ mod tests {
 					.expect("there should be header"),
 			)),
 		);
-		assert_eq!(txpool.ready().count(), MAX_SKIPPED_TRANSACTIONS * 2 + 2);
+		assert_eq!(txpool.ready().count(), MAX_SKIPPED_TRANSACTIONS * 2 + 4);
 
 		let mut proposer_factory =
 			ProposerFactory::new(spawner.clone(), client.clone(), txpool.clone(), None, None);
@@ -1049,8 +1086,13 @@ mod tests {
 				.map(|r| r.block)
 				.unwrap();
 
-		// then the block should have no transactions despite some in the pool
-		assert_eq!(block.extrinsics().len(), 1);
+		// then the block should have one or two transactions. This maybe random as they are
+		// processed in parallel. The same signer and consecutive nonces for huge and tiny
+		// transactions guarantees that max two transactions will get to the block.
+		assert!(
+			(1..3).contains(&block.extrinsics().len()),
+			"Block shall contain one or two extrinsics."
+		);
 		assert!(
 			cell2.lock().0 > MAX_SKIPPED_TRANSACTIONS,
 			"Not enough calls to current time, which indicates the test might have ended because of deadline, not soft deadline"
diff --git a/substrate/client/basic-authorship/src/lib.rs b/substrate/client/basic-authorship/src/lib.rs
index 23a2120ac62..8f47c2ea00e 100644
--- a/substrate/client/basic-authorship/src/lib.rs
+++ b/substrate/client/basic-authorship/src/lib.rs
@@ -26,7 +26,7 @@
 //! # use sp_runtime::generic::BlockId;
 //! # use std::{sync::Arc, time::Duration};
 //! # use substrate_test_runtime_client::{
-//! #     runtime::{Extrinsic, Transfer}, AccountKeyring,
+//! #     runtime::Transfer, AccountKeyring,
 //! #     DefaultTestClientBuilderExt, TestClientBuilderExt,
 //! # };
 //! # use sc_transaction_pool::{BasicPool, FullChainApi};
diff --git a/substrate/client/block-builder/src/lib.rs b/substrate/client/block-builder/src/lib.rs
index 21f8e6fdd39..f055d468882 100644
--- a/substrate/client/block-builder/src/lib.rs
+++ b/substrate/client/block-builder/src/lib.rs
@@ -313,7 +313,7 @@ mod tests {
 	use sp_core::Blake2Hasher;
 	use sp_state_machine::Backend;
 	use substrate_test_runtime_client::{
-		runtime::Extrinsic, DefaultTestClientBuilderExt, TestClientBuilderExt,
+		runtime::ExtrinsicBuilder, DefaultTestClientBuilderExt, TestClientBuilderExt,
 	};
 
 	#[test]
@@ -322,9 +322,11 @@ mod tests {
 		let backend = builder.backend();
 		let client = builder.build();
 
+		let genesis_hash = client.info().best_hash;
+
 		let block = BlockBuilder::new(
 			&client,
-			client.info().best_hash,
+			genesis_hash,
 			client.info().best_number,
 			RecordProof::Yes,
 			Default::default(),
@@ -335,12 +337,11 @@ mod tests {
 		.unwrap();
 
 		let proof = block.proof.expect("Proof is build on request");
+		let genesis_state_root = client.header(genesis_hash).unwrap().unwrap().state_root;
 
-		let backend = sp_state_machine::create_proof_check_backend::<Blake2Hasher>(
-			block.storage_changes.transaction_storage_root,
-			proof,
-		)
-		.unwrap();
+		let backend =
+			sp_state_machine::create_proof_check_backend::<Blake2Hasher>(genesis_state_root, proof)
+				.unwrap();
 
 		assert!(backend
 			.storage(&sp_core::storage::well_known_keys::CODE)
@@ -364,7 +365,7 @@ mod tests {
 		)
 		.unwrap();
 
-		block_builder.push(Extrinsic::ReadAndPanic(8)).unwrap_err();
+		block_builder.push(ExtrinsicBuilder::new_read_and_panic(8).build()).unwrap_err();
 
 		let block = block_builder.build().unwrap();
 
@@ -380,7 +381,7 @@ mod tests {
 		)
 		.unwrap();
 
-		block_builder.push(Extrinsic::Read(8)).unwrap();
+		block_builder.push(ExtrinsicBuilder::new_read(8).build()).unwrap();
 
 		let block = block_builder.build().unwrap();
 
diff --git a/substrate/client/consensus/babe/src/tests.rs b/substrate/client/consensus/babe/src/tests.rs
index aa3e32fa09d..59b4076e2fd 100644
--- a/substrate/client/consensus/babe/src/tests.rs
+++ b/substrate/client/consensus/babe/src/tests.rs
@@ -71,15 +71,12 @@ const SLOT_DURATION_MS: u64 = 1000;
 struct DummyFactory {
 	client: Arc<TestClient>,
 	epoch_changes: SharedEpochChanges<TestBlock, Epoch>,
-	config: BabeConfiguration,
 	mutator: Mutator,
 }
 
 struct DummyProposer {
 	factory: DummyFactory,
 	parent_hash: Hash,
-	parent_number: u64,
-	parent_slot: Slot,
 }
 
 impl Environment<TestBlock> for DummyFactory {
@@ -88,15 +85,9 @@ impl Environment<TestBlock> for DummyFactory {
 	type Error = Error;
 
 	fn init(&mut self, parent_header: &<TestBlock as BlockT>::Header) -> Self::CreateProposer {
-		let parent_slot = crate::find_pre_digest::<TestBlock>(parent_header)
-			.expect("parent header has a pre-digest")
-			.slot();
-
 		future::ready(Ok(DummyProposer {
 			factory: self.clone(),
 			parent_hash: parent_header.hash(),
-			parent_number: *parent_header.number(),
-			parent_slot,
 		}))
 	}
 }
@@ -123,39 +114,6 @@ impl DummyProposer {
 			Err(e) => return future::ready(Err(e)),
 		};
 
-		let this_slot = crate::find_pre_digest::<TestBlock>(block.header())
-			.expect("baked block has valid pre-digest")
-			.slot();
-
-		// figure out if we should add a consensus digest, since the test runtime
-		// doesn't.
-		let epoch_changes = self.factory.epoch_changes.shared_data();
-		let epoch = epoch_changes
-			.epoch_data_for_child_of(
-				descendent_query(&*self.factory.client),
-				&self.parent_hash,
-				self.parent_number,
-				this_slot,
-				|slot| Epoch::genesis(&self.factory.config, slot),
-			)
-			.expect("client has data to find epoch")
-			.expect("can compute epoch for baked block");
-
-		let first_in_epoch = self.parent_slot < epoch.start_slot;
-		if first_in_epoch {
-			// push a `Consensus` digest signalling next change.
-			// we just reuse the same randomness and authorities as the prior
-			// epoch. this will break when we add light client support, since
-			// that will re-check the randomness logic off-chain.
-			let digest_data = ConsensusLog::NextEpochData(NextEpochDescriptor {
-				authorities: epoch.authorities.clone(),
-				randomness: epoch.randomness,
-			})
-			.encode();
-			let digest = DigestItem::Consensus(BABE_ENGINE_ID, digest_data);
-			block.header.digest_mut().push(digest)
-		}
-
 		// mutate the block header according to the mutator.
 		(self.factory.mutator)(&mut block.header, Stage::PreSeal);
 
@@ -351,7 +309,7 @@ impl TestNetFactory for BabeTestNet {
 }
 
 #[tokio::test]
-#[should_panic]
+#[should_panic(expected = "No BABE pre-runtime digest found")]
 async fn rejects_empty_block() {
 	sp_tracing::try_init_simple();
 	let mut net = BabeTestNet::new(3);
@@ -398,7 +356,6 @@ async fn run_one_test(mutator: impl Fn(&mut TestHeader, Stage) + Send + Sync + '
 
 		let environ = DummyFactory {
 			client: client.clone(),
-			config: data.link.config.clone(),
 			epoch_changes: data.link.epoch_changes.clone(),
 			mutator: mutator.clone(),
 		};
@@ -483,7 +440,7 @@ async fn authoring_blocks() {
 }
 
 #[tokio::test]
-#[should_panic]
+#[should_panic(expected = "valid babe headers must contain a predigest")]
 async fn rejects_missing_inherent_digest() {
 	run_one_test(|header: &mut TestHeader, stage| {
 		let v = std::mem::take(&mut header.digest_mut().logs);
@@ -496,7 +453,7 @@ async fn rejects_missing_inherent_digest() {
 }
 
 #[tokio::test]
-#[should_panic]
+#[should_panic(expected = "has a bad seal")]
 async fn rejects_missing_seals() {
 	run_one_test(|header: &mut TestHeader, stage| {
 		let v = std::mem::take(&mut header.digest_mut().logs);
@@ -509,7 +466,7 @@ async fn rejects_missing_seals() {
 }
 
 #[tokio::test]
-#[should_panic]
+#[should_panic(expected = "Expected epoch change to happen")]
 async fn rejects_missing_consensus_digests() {
 	run_one_test(|header: &mut TestHeader, stage| {
 		let v = std::mem::take(&mut header.digest_mut().logs);
@@ -770,7 +727,6 @@ async fn importing_block_one_sets_genesis_epoch() {
 
 	let mut proposer_factory = DummyFactory {
 		client: client.clone(),
-		config: data.link.config.clone(),
 		epoch_changes: data.link.epoch_changes.clone(),
 		mutator: Arc::new(|_, _| ()),
 	};
@@ -814,7 +770,6 @@ async fn revert_prunes_epoch_changes_and_removes_weights() {
 
 	let mut proposer_factory = DummyFactory {
 		client: client.clone(),
-		config: data.link.config.clone(),
 		epoch_changes: data.link.epoch_changes.clone(),
 		mutator: Arc::new(|_, _| ()),
 	};
@@ -902,7 +857,6 @@ async fn revert_not_allowed_for_finalized() {
 
 	let mut proposer_factory = DummyFactory {
 		client: client.clone(),
-		config: data.link.config.clone(),
 		epoch_changes: data.link.epoch_changes.clone(),
 		mutator: Arc::new(|_, _| ()),
 	};
@@ -943,7 +897,6 @@ async fn importing_epoch_change_block_prunes_tree() {
 
 	let mut proposer_factory = DummyFactory {
 		client: client.clone(),
-		config: data.link.config.clone(),
 		epoch_changes: data.link.epoch_changes.clone(),
 		mutator: Arc::new(|_, _| ()),
 	};
@@ -1030,7 +983,7 @@ async fn importing_epoch_change_block_prunes_tree() {
 }
 
 #[tokio::test]
-#[should_panic]
+#[should_panic(expected = "Slot number must increase: parent slot: 999, this slot: 999")]
 async fn verify_slots_are_strictly_increasing() {
 	let mut net = BabeTestNet::new(1);
 
@@ -1042,7 +995,6 @@ async fn verify_slots_are_strictly_increasing() {
 
 	let mut proposer_factory = DummyFactory {
 		client: client.clone(),
-		config: data.link.config.clone(),
 		epoch_changes: data.link.epoch_changes.clone(),
 		mutator: Arc::new(|_, _| ()),
 	};
@@ -1082,7 +1034,6 @@ async fn obsolete_blocks_aux_data_cleanup() {
 
 	let mut proposer_factory = DummyFactory {
 		client: client.clone(),
-		config: data.link.config.clone(),
 		epoch_changes: data.link.epoch_changes.clone(),
 		mutator: Arc::new(|_, _| ()),
 	};
@@ -1168,7 +1119,6 @@ async fn allows_skipping_epochs() {
 
 	let mut proposer_factory = DummyFactory {
 		client: client.clone(),
-		config: data.link.config.clone(),
 		epoch_changes: data.link.epoch_changes.clone(),
 		mutator: Arc::new(|_, _| ()),
 	};
@@ -1298,7 +1248,6 @@ async fn allows_skipping_epochs_on_some_forks() {
 
 	let mut proposer_factory = DummyFactory {
 		client: client.clone(),
-		config: data.link.config.clone(),
 		epoch_changes: data.link.epoch_changes.clone(),
 		mutator: Arc::new(|_, _| ()),
 	};
diff --git a/substrate/client/consensus/beefy/src/tests.rs b/substrate/client/consensus/beefy/src/tests.rs
index 48ecebdac35..288a9fde5b8 100644
--- a/substrate/client/consensus/beefy/src/tests.rs
+++ b/substrate/client/consensus/beefy/src/tests.rs
@@ -66,7 +66,7 @@ use sp_runtime::{
 	BuildStorage, DigestItem, EncodedJustification, Justifications, Storage,
 };
 use std::{marker::PhantomData, sync::Arc, task::Poll};
-use substrate_test_runtime_client::{runtime::Header, ClientExt};
+use substrate_test_runtime_client::{BlockBuilderExt, ClientExt};
 use tokio::time::Duration;
 
 const GENESIS_HASH: H256 = H256::zero();
@@ -165,20 +165,22 @@ impl BeefyTestNet {
 		// push genesis to make indexing human readable (index equals to block number)
 		all_hashes.push(self.peer(0).client().info().genesis_hash);
 
-		let built_hashes = self.peer(0).generate_blocks(count, BlockOrigin::File, |builder| {
-			let mut block = builder.build().unwrap().block;
-
+		let mut block_num: NumberFor<Block> = self.peer(0).client().info().best_number;
+		let built_hashes = self.peer(0).generate_blocks(count, BlockOrigin::File, |mut builder| {
+			block_num = block_num.saturating_add(1).try_into().unwrap();
 			if include_mmr_digest {
-				let block_num = *block.header.number();
 				let num_byte = block_num.to_le_bytes().into_iter().next().unwrap();
 				let mmr_root = MmrRootHash::repeat_byte(num_byte);
-				add_mmr_digest(&mut block.header, mmr_root);
+				add_mmr_digest(&mut builder, mmr_root);
 			}
 
-			if *block.header.number() % session_length == 0 {
-				add_auth_change_digest(&mut block.header, validator_set.clone());
+			if block_num % session_length == 0 {
+				add_auth_change_digest(&mut builder, validator_set.clone());
 			}
 
+			let block = builder.build().unwrap().block;
+			assert_eq!(block.header.number, block_num);
+
 			block
 		});
 		all_hashes.extend(built_hashes);
@@ -325,18 +327,22 @@ sp_api::mock_impl_runtime_apis! {
 	}
 }
 
-fn add_mmr_digest(header: &mut Header, mmr_hash: MmrRootHash) {
-	header.digest_mut().push(DigestItem::Consensus(
-		BEEFY_ENGINE_ID,
-		ConsensusLog::<AuthorityId>::MmrRoot(mmr_hash).encode(),
-	));
+fn add_mmr_digest(builder: &mut impl BlockBuilderExt, mmr_hash: MmrRootHash) {
+	builder
+		.push_deposit_log_digest_item(DigestItem::Consensus(
+			BEEFY_ENGINE_ID,
+			ConsensusLog::<AuthorityId>::MmrRoot(mmr_hash).encode(),
+		))
+		.unwrap();
 }
 
-fn add_auth_change_digest(header: &mut Header, new_auth_set: BeefyValidatorSet) {
-	header.digest_mut().push(DigestItem::Consensus(
-		BEEFY_ENGINE_ID,
-		ConsensusLog::<AuthorityId>::AuthoritiesChange(new_auth_set).encode(),
-	));
+fn add_auth_change_digest(builder: &mut impl BlockBuilderExt, new_auth_set: BeefyValidatorSet) {
+	builder
+		.push_deposit_log_digest_item(DigestItem::Consensus(
+			BEEFY_ENGINE_ID,
+			ConsensusLog::<AuthorityId>::AuthoritiesChange(new_auth_set).encode(),
+		))
+		.unwrap();
 }
 
 pub(crate) fn make_beefy_ids(keys: &[BeefyKeyring]) -> Vec<AuthorityId> {
diff --git a/substrate/client/consensus/grandpa/src/tests.rs b/substrate/client/consensus/grandpa/src/tests.rs
index 7a3f862d360..c46e249be48 100644
--- a/substrate/client/consensus/grandpa/src/tests.rs
+++ b/substrate/client/consensus/grandpa/src/tests.rs
@@ -48,7 +48,7 @@ use sp_runtime::{
 	Justifications,
 };
 use std::{collections::HashSet, pin::Pin};
-use substrate_test_runtime_client::runtime::BlockNumber;
+use substrate_test_runtime_client::{runtime::BlockNumber, BlockBuilderExt};
 use tokio::runtime::Handle;
 
 use authorities::AuthoritySet;
@@ -399,22 +399,27 @@ async fn run_to_completion(
 	run_to_completion_with(blocks, net, peers, |_| None).await
 }
 
-fn add_scheduled_change(block: &mut Block, change: ScheduledChange<BlockNumber>) {
-	block.header.digest_mut().push(DigestItem::Consensus(
-		GRANDPA_ENGINE_ID,
-		sp_consensus_grandpa::ConsensusLog::ScheduledChange(change).encode(),
-	));
+fn add_scheduled_change(builder: &mut impl BlockBuilderExt, change: ScheduledChange<BlockNumber>) {
+	builder
+		.push_deposit_log_digest_item(DigestItem::Consensus(
+			GRANDPA_ENGINE_ID,
+			sp_consensus_grandpa::ConsensusLog::ScheduledChange(change).encode(),
+		))
+		.unwrap();
 }
 
 fn add_forced_change(
-	block: &mut Block,
+	builder: &mut impl BlockBuilderExt,
 	median_last_finalized: BlockNumber,
 	change: ScheduledChange<BlockNumber>,
 ) {
-	block.header.digest_mut().push(DigestItem::Consensus(
-		GRANDPA_ENGINE_ID,
-		sp_consensus_grandpa::ConsensusLog::ForcedChange(median_last_finalized, change).encode(),
-	));
+	builder
+		.push_deposit_log_digest_item(DigestItem::Consensus(
+			GRANDPA_ENGINE_ID,
+			sp_consensus_grandpa::ConsensusLog::ForcedChange(median_last_finalized, change)
+				.encode(),
+		))
+		.unwrap();
 }
 
 #[tokio::test]
@@ -605,28 +610,24 @@ async fn transition_3_voters_twice_1_full_observer() {
 					},
 					14 => {
 						// generate transition at block 15, applied at 20.
-						net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |builder| {
-							let mut block = builder.build().unwrap().block;
+						net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |mut builder| {
 							add_scheduled_change(
-								&mut block,
+								&mut builder,
 								ScheduledChange { next_authorities: make_ids(peers_b), delay: 4 },
 							);
-
-							block
+							builder.build().unwrap().block
 						});
 						net.lock().peer(0).push_blocks(5, false);
 					},
 					20 => {
 						// at block 21 we do another transition, but this time instant.
 						// add more until we have 30.
-						net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |builder| {
-							let mut block = builder.build().unwrap().block;
+						net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |mut builder| {
 							add_scheduled_change(
-								&mut block,
+								&mut builder,
 								ScheduledChange { next_authorities: make_ids(&peers_c), delay: 0 },
 							);
-
-							block
+							builder.build().unwrap().block
 						});
 						net.lock().peer(0).push_blocks(9, false);
 					},
@@ -708,13 +709,12 @@ async fn sync_justifications_on_change_blocks() {
 	// at block 21 we do add a transition which is instant
 	let hashof21 = net
 		.peer(0)
-		.generate_blocks(1, BlockOrigin::File, |builder| {
-			let mut block = builder.build().unwrap().block;
+		.generate_blocks(1, BlockOrigin::File, |mut builder| {
 			add_scheduled_change(
-				&mut block,
+				&mut builder,
 				ScheduledChange { next_authorities: make_ids(peers_b), delay: 0 },
 			);
-			block
+			builder.build().unwrap().block
 		})
 		.pop()
 		.unwrap();
@@ -778,26 +778,24 @@ async fn finalizes_multiple_pending_changes_in_order() {
 	net.peer(0).push_blocks(20, false);
 
 	// at block 21 we do add a transition which is instant
-	net.peer(0).generate_blocks(1, BlockOrigin::File, |builder| {
-		let mut block = builder.build().unwrap().block;
+	net.peer(0).generate_blocks(1, BlockOrigin::File, |mut builder| {
 		add_scheduled_change(
-			&mut block,
+			&mut builder,
 			ScheduledChange { next_authorities: make_ids(peers_b), delay: 0 },
 		);
-		block
+		builder.build().unwrap().block
 	});
 
 	// add more blocks on top of it (until we have 25)
 	net.peer(0).push_blocks(4, false);
 
 	// at block 26 we add another which is enacted at block 30
-	net.peer(0).generate_blocks(1, BlockOrigin::File, |builder| {
-		let mut block = builder.build().unwrap().block;
+	net.peer(0).generate_blocks(1, BlockOrigin::File, |mut builder| {
 		add_scheduled_change(
-			&mut block,
+			&mut builder,
 			ScheduledChange { next_authorities: make_ids(peers_c), delay: 4 },
 		);
-		block
+		builder.build().unwrap().block
 	});
 
 	// add more blocks on top of it (until we have 30)
@@ -833,23 +831,21 @@ async fn force_change_to_new_set() {
 	let voters_future = initialize_grandpa(&mut net, peers_a);
 	let net = Arc::new(Mutex::new(net));
 
-	net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |builder| {
-		let mut block = builder.build().unwrap().block;
-
+	net.lock().peer(0).generate_blocks(1, BlockOrigin::File, |mut builder| {
 		// add a forced transition at block 12.
 		add_forced_change(
-			&mut block,
+			&mut builder,
 			0,
 			ScheduledChange { next_authorities: voters.clone(), delay: 10 },
 		);
 
 		// add a normal transition too to ensure that forced changes take priority.
 		add_scheduled_change(
-			&mut block,
+			&mut builder,
 			ScheduledChange { next_authorities: make_ids(genesis_authorities), delay: 5 },
 		);
 
-		block
+		builder.build().unwrap().block
 	});
 
 	net.lock().peer(0).push_blocks(25, false);
@@ -885,14 +881,15 @@ async fn allows_reimporting_change_blocks() {
 	let (mut block_import, ..) = net.make_block_import(client.clone());
 
 	let full_client = client.as_client();
-	let builder = full_client
+	let mut builder = full_client
 		.new_block_at(full_client.chain_info().genesis_hash, Default::default(), false)
 		.unwrap();
-	let mut block = builder.build().unwrap().block;
+
 	add_scheduled_change(
-		&mut block,
+		&mut builder,
 		ScheduledChange { next_authorities: make_ids(peers_b), delay: 0 },
 	);
+	let block = builder.build().unwrap().block;
 
 	let block = || {
 		let block = block.clone();
@@ -929,16 +926,17 @@ async fn test_bad_justification() {
 	let (mut block_import, ..) = net.make_block_import(client.clone());
 
 	let full_client = client.as_client();
-	let builder = full_client
+	let mut builder = full_client
 		.new_block_at(full_client.chain_info().genesis_hash, Default::default(), false)
 		.unwrap();
-	let mut block = builder.build().unwrap().block;
 
 	add_scheduled_change(
-		&mut block,
+		&mut builder,
 		ScheduledChange { next_authorities: make_ids(peers_b), delay: 0 },
 	);
 
+	let block = builder.build().unwrap().block;
+
 	let block = || {
 		let block = block.clone();
 		let mut import = BlockImportParams::new(BlockOrigin::File, block.header);
@@ -1629,6 +1627,7 @@ async fn grandpa_environment_passes_actual_best_block_to_voting_rules() {
 
 #[tokio::test]
 async fn grandpa_environment_checks_if_best_block_is_descendent_of_finality_target() {
+	sp_tracing::try_init_simple();
 	use finality_grandpa::voter::Environment;
 
 	let peers = &[Ed25519Keyring::Alice];
@@ -1662,10 +1661,9 @@ async fn grandpa_environment_checks_if_best_block_is_descendent_of_finality_targ
 		BlockId::Number(4),
 		6,
 		BlockOrigin::File,
-		|builder| {
-			let mut block = builder.build().unwrap().block;
-			block.header.digest_mut().push(DigestItem::Other(vec![1]));
-			block
+		|mut builder| {
+			builder.push_deposit_log_digest_item(DigestItem::Other(vec![1])).unwrap();
+			builder.build().unwrap().block
 		},
 		false,
 		false,
@@ -1999,13 +1997,12 @@ async fn revert_prunes_authority_changes() {
 
 	type TestBlockBuilder<'a> =
 		BlockBuilder<'a, Block, PeersFullClient, substrate_test_runtime_client::Backend>;
-	let edit_block = |builder: TestBlockBuilder| {
-		let mut block = builder.build().unwrap().block;
+	let edit_block = |mut builder: TestBlockBuilder| {
 		add_scheduled_change(
-			&mut block,
+			&mut builder,
 			ScheduledChange { next_authorities: make_ids(peers), delay: 0 },
 		);
-		block
+		builder.build().unwrap().block
 	};
 
 	let api = TestApi::new(make_ids(peers));
@@ -2047,10 +2044,9 @@ async fn revert_prunes_authority_changes() {
 			BlockId::Number(23),
 			3,
 			BlockOrigin::File,
-			|builder| {
-				let mut block = builder.build().unwrap().block;
-				block.header.digest_mut().push(DigestItem::Other(vec![1]));
-				block
+			|mut builder| {
+				builder.push_deposit_log_digest_item(DigestItem::Other(vec![1])).unwrap();
+				builder.build().unwrap().block
 			},
 			false,
 			false,
@@ -2079,10 +2075,9 @@ async fn revert_prunes_authority_changes() {
 			BlockId::Number(25),
 			3,
 			BlockOrigin::File,
-			|builder| {
-				let mut block = builder.build().unwrap().block;
-				block.header.digest_mut().push(DigestItem::Other(vec![2]));
-				block
+			|mut builder| {
+				builder.push_deposit_log_digest_item(DigestItem::Other(vec![2])).unwrap();
+				builder.build().unwrap().block
 			},
 			false,
 			false,
diff --git a/substrate/client/consensus/grandpa/src/warp_proof.rs b/substrate/client/consensus/grandpa/src/warp_proof.rs
index cd4fedf96b4..ec2d25c328b 100644
--- a/substrate/client/consensus/grandpa/src/warp_proof.rs
+++ b/substrate/client/consensus/grandpa/src/warp_proof.rs
@@ -326,11 +326,10 @@ mod tests {
 	use sp_consensus::BlockOrigin;
 	use sp_consensus_grandpa::GRANDPA_ENGINE_ID;
 	use sp_keyring::Ed25519Keyring;
-	use sp_runtime::traits::Header as _;
 	use std::sync::Arc;
 	use substrate_test_runtime_client::{
-		ClientBlockImportExt, ClientExt, DefaultTestClientBuilderExt, TestClientBuilder,
-		TestClientBuilderExt,
+		BlockBuilderExt, ClientBlockImportExt, ClientExt, DefaultTestClientBuilderExt,
+		TestClientBuilder, TestClientBuilderExt,
 	};
 
 	#[test]
@@ -348,8 +347,7 @@ mod tests {
 		let mut authority_set_changes = Vec::new();
 
 		for n in 1..=100 {
-			let mut block = client.new_block(Default::default()).unwrap().build().unwrap().block;
-
+			let mut builder = client.new_block(Default::default()).unwrap();
 			let mut new_authorities = None;
 
 			// we will trigger an authority set change every 10 blocks
@@ -376,9 +374,11 @@ mod tests {
 					.encode(),
 				);
 
-				block.header.digest_mut().logs.push(digest);
+				builder.push_deposit_log_digest_item(digest).unwrap();
 			}
 
+			let block = builder.build().unwrap().block;
+
 			futures::executor::block_on(client.import(BlockOrigin::Own, block)).unwrap();
 
 			if let Some(new_authorities) = new_authorities {
diff --git a/substrate/client/network/bitswap/src/lib.rs b/substrate/client/network/bitswap/src/lib.rs
index 5a7a7b51355..db73023bd37 100644
--- a/substrate/client/network/bitswap/src/lib.rs
+++ b/substrate/client/network/bitswap/src/lib.rs
@@ -297,7 +297,7 @@ mod tests {
 	};
 	use sp_consensus::BlockOrigin;
 	use sp_runtime::codec::Encode;
-	use substrate_test_runtime::Extrinsic;
+	use substrate_test_runtime::ExtrinsicBuilder;
 	use substrate_test_runtime_client::{self, prelude::*, TestClientBuilder};
 
 	#[tokio::test]
@@ -470,7 +470,9 @@ mod tests {
 		let mut client = TestClientBuilder::with_tx_storage(u32::MAX).build();
 		let mut block_builder = client.new_block(Default::default()).unwrap();
 
-		let ext = Extrinsic::Store(vec![0x13, 0x37, 0x13, 0x38]);
+		// encoded extrinsic: [161, .. , 2, 6, 16, 19, 55, 19, 56]
+		let ext = ExtrinsicBuilder::new_indexed_call(vec![0x13, 0x37, 0x13, 0x38]).build();
+		let pattern_index = ext.encoded_size() - 4;
 
 		block_builder.push(ext.clone()).unwrap();
 		let block = block_builder.build().unwrap().block;
@@ -494,7 +496,7 @@ mod tests {
 								0x70,
 								cid::multihash::Multihash::wrap(
 									u64::from(cid::multihash::Code::Blake2b256),
-									&sp_core::hashing::blake2_256(&ext.encode()[2..]),
+									&sp_core::hashing::blake2_256(&ext.encode()[pattern_index..]),
 								)
 								.unwrap(),
 							)
diff --git a/substrate/client/network/test/src/lib.rs b/substrate/client/network/test/src/lib.rs
index f85d6ed63c2..9e740d0856c 100644
--- a/substrate/client/network/test/src/lib.rs
+++ b/substrate/client/network/test/src/lib.rs
@@ -88,13 +88,11 @@ use sp_runtime::{
 };
 use substrate_test_runtime_client::AccountKeyring;
 pub use substrate_test_runtime_client::{
-	runtime::{Block, Extrinsic, Hash, Header, Transfer},
+	runtime::{Block, ExtrinsicBuilder, Hash, Header, Transfer},
 	TestClient, TestClientBuilder, TestClientBuilderExt,
 };
 use tokio::time::timeout;
 
-type AuthorityId = sp_consensus_babe::AuthorityId;
-
 /// A Verifier that accepts all blocks and passes them on with the configured
 /// finality to be imported.
 #[derive(Clone)]
@@ -474,7 +472,7 @@ where
 						amount: 1,
 						nonce,
 					};
-					builder.push(transfer.into_signed_tx()).unwrap();
+					builder.push(transfer.into_unchecked_extrinsic()).unwrap();
 					nonce += 1;
 					builder.build().unwrap().block
 				},
@@ -497,16 +495,6 @@ where
 		}
 	}
 
-	pub fn push_authorities_change_block(
-		&mut self,
-		new_authorities: Vec<AuthorityId>,
-	) -> Vec<H256> {
-		self.generate_blocks(1, BlockOrigin::File, |mut builder| {
-			builder.push(Extrinsic::AuthoritiesChange(new_authorities.clone())).unwrap();
-			builder.build().unwrap().block
-		})
-	}
-
 	/// Get a reference to the client.
 	pub fn client(&self) -> &PeersClient {
 		&self.client
diff --git a/substrate/client/network/test/src/sync.rs b/substrate/client/network/test/src/sync.rs
index af46d15a2ba..81707445dc9 100644
--- a/substrate/client/network/test/src/sync.rs
+++ b/substrate/client/network/test/src/sync.rs
@@ -1183,7 +1183,7 @@ async fn syncs_indexed_blocks() {
 		64,
 		BlockOrigin::Own,
 		|mut builder| {
-			let ex = Extrinsic::Store(n.to_le_bytes().to_vec());
+			let ex = ExtrinsicBuilder::new_indexed_call(n.to_le_bytes().to_vec()).nonce(n).build();
 			n += 1;
 			builder.push(ex).unwrap();
 			builder.build().unwrap().block
@@ -1305,11 +1305,13 @@ async fn syncs_huge_blocks() {
 		builder.build().unwrap().block
 	});
 
+	let mut nonce = 0;
 	net.peer(0).generate_blocks(32, BlockOrigin::Own, |mut builder| {
 		// Add 32 extrinsics 32k each = 1MiB total
-		for _ in 0..32 {
-			let ex = Extrinsic::IncludeData([42u8; 32 * 1024].to_vec());
+		for _ in 0..32u64 {
+			let ex = ExtrinsicBuilder::new_include_data(vec![42u8; 32 * 1024]).nonce(nonce).build();
 			builder.push(ex).unwrap();
+			nonce += 1;
 		}
 		builder.build().unwrap().block
 	});
diff --git a/substrate/client/offchain/src/lib.rs b/substrate/client/offchain/src/lib.rs
index 677d89267e3..f46fb637a92 100644
--- a/substrate/client/offchain/src/lib.rs
+++ b/substrate/client/offchain/src/lib.rs
@@ -254,8 +254,10 @@ mod tests {
 	use sp_runtime::generic::BlockId;
 	use std::{collections::HashSet, sync::Arc};
 	use substrate_test_runtime_client::{
-		runtime::Block, ClientBlockImportExt, DefaultTestClientBuilderExt, TestClient,
-		TestClientBuilderExt,
+		runtime::{
+			substrate_test_pallet::pallet::Call as PalletCall, Block, ExtrinsicBuilder, RuntimeCall,
+		},
+		ClientBlockImportExt, DefaultTestClientBuilderExt, TestClient, TestClientBuilderExt,
 	};
 
 	struct TestNetwork();
@@ -385,7 +387,10 @@ mod tests {
 
 		// then
 		assert_eq!(pool.0.status().ready, 1);
-		assert_eq!(pool.0.ready().next().unwrap().is_propagable(), false);
+		assert!(matches!(
+			pool.0.ready().next().unwrap().data().function,
+			RuntimeCall::SubstrateTest(PalletCall::storage_change { .. })
+		));
 	}
 
 	#[test]
@@ -403,12 +408,8 @@ mod tests {
 		let key = &b"hello"[..];
 		let value = &b"world"[..];
 		let mut block_builder = client.new_block(Default::default()).unwrap();
-		block_builder
-			.push(substrate_test_runtime_client::runtime::Extrinsic::OffchainIndexSet(
-				key.to_vec(),
-				value.to_vec(),
-			))
-			.unwrap();
+		let ext = ExtrinsicBuilder::new_offchain_index_set(key.to_vec(), value.to_vec()).build();
+		block_builder.push(ext).unwrap();
 
 		let block = block_builder.build().unwrap().block;
 		block_on(client.import(BlockOrigin::Own, block)).unwrap();
@@ -416,11 +417,8 @@ mod tests {
 		assert_eq!(value, &offchain_db.get(sp_offchain::STORAGE_PREFIX, &key).unwrap());
 
 		let mut block_builder = client.new_block(Default::default()).unwrap();
-		block_builder
-			.push(substrate_test_runtime_client::runtime::Extrinsic::OffchainIndexClear(
-				key.to_vec(),
-			))
-			.unwrap();
+		let ext = ExtrinsicBuilder::new_offchain_index_clear(key.to_vec()).nonce(1).build();
+		block_builder.push(ext).unwrap();
 
 		let block = block_builder.build().unwrap().block;
 		block_on(client.import(BlockOrigin::Own, block)).unwrap();
diff --git a/substrate/client/rpc-spec-v2/src/chain_head/tests.rs b/substrate/client/rpc-spec-v2/src/chain_head/tests.rs
index 76644ccb472..d3d4fc649e3 100644
--- a/substrate/client/rpc-spec-v2/src/chain_head/tests.rs
+++ b/substrate/client/rpc-spec-v2/src/chain_head/tests.rs
@@ -184,12 +184,13 @@ async fn follow_with_runtime() {
 	// Initialized must always be reported first.
 	let event: FollowEvent<String> = get_next_event(&mut sub).await;
 
+	// it is basically json-encoded substrate_test_runtime_client::runtime::VERSION
 	let runtime_str = "{\"specName\":\"test\",\"implName\":\"parity-test\",\"authoringVersion\":1,\
 		\"specVersion\":2,\"implVersion\":2,\"apis\":[[\"0xdf6acb689907609b\",4],\
 		[\"0x37e397fc7c91f5e4\",2],[\"0xd2bc9897eed08f15\",3],[\"0x40fe3ad401f8959a\",6],\
-		[\"0xc6e9a76309f39b09\",1],[\"0xdd718d5cc53262d4\",1],[\"0xcbca25e39f142387\",2],\
-		[\"0xf78b278be53f454c\",2],[\"0xab3c0572291feb8b\",1],[\"0xbc9d89904f5b923f\",1]],\
-		\"transactionVersion\":1,\"stateVersion\":1}";
+		[\"0xbc9d89904f5b923f\",1],[\"0xc6e9a76309f39b09\",2],[\"0xdd718d5cc53262d4\",1],\
+		[\"0xcbca25e39f142387\",2],[\"0xf78b278be53f454c\",2],[\"0xab3c0572291feb8b\",1],\
+		[\"0xed99c5acb25eedf5\",3]],\"transactionVersion\":1,\"stateVersion\":1}";
 	let runtime: RuntimeVersion = serde_json::from_str(runtime_str).unwrap();
 
 	let finalized_block_runtime =
diff --git a/substrate/client/rpc/src/author/tests.rs b/substrate/client/rpc/src/author/tests.rs
index fbbd1a92fda..1f688e8e85e 100644
--- a/substrate/client/rpc/src/author/tests.rs
+++ b/substrate/client/rpc/src/author/tests.rs
@@ -37,10 +37,11 @@ use sp_core::{
 	H256,
 };
 use sp_keystore::{testing::MemoryKeystore, Keystore};
+use sp_runtime::Perbill;
 use std::sync::Arc;
 use substrate_test_runtime_client::{
 	self,
-	runtime::{Block, Extrinsic, SessionKeys, Transfer},
+	runtime::{Block, Extrinsic, ExtrinsicBuilder, SessionKeys, Transfer},
 	AccountKeyring, Backend, Client, DefaultTestClientBuilderExt, TestClientBuilderExt,
 };
 
@@ -51,7 +52,7 @@ fn uxt(sender: AccountKeyring, nonce: u64) -> Extrinsic {
 		from: sender.into(),
 		to: AccountKeyring::Bob.into(),
 	};
-	tx.into_signed_tx()
+	ExtrinsicBuilder::new_transfer(tx).build()
 }
 
 type FullTransactionPool = BasicPool<FullChainApi<Client<Backend>, Block>, Block>;
@@ -111,7 +112,13 @@ async fn author_submit_transaction_should_not_cause_error() {
 #[tokio::test]
 async fn author_should_watch_extrinsic() {
 	let api = TestSetup::into_rpc();
-	let xt = to_hex(&uxt(AccountKeyring::Alice, 0).encode(), true);
+	let xt = to_hex(
+		&ExtrinsicBuilder::new_call_with_priority(0)
+			.signer(AccountKeyring::Alice.into())
+			.build()
+			.encode(),
+		true,
+	);
 
 	let mut sub = api.subscribe("author_submitAndWatchExtrinsic", [xt]).await.unwrap();
 	let (tx, sub_id) = timeout_secs(10, sub.next::<TransactionStatus<H256, Block>>())
@@ -125,15 +132,11 @@ async fn author_should_watch_extrinsic() {
 
 	// Replace the extrinsic and observe the subscription is notified.
 	let (xt_replacement, xt_hash) = {
-		let tx = Transfer {
-			amount: 5,
-			nonce: 0,
-			from: AccountKeyring::Alice.into(),
-			to: AccountKeyring::Bob.into(),
-		};
-		let tx = tx.into_signed_tx().encode();
+		let tx = ExtrinsicBuilder::new_call_with_priority(1)
+			.signer(AccountKeyring::Alice.into())
+			.build()
+			.encode();
 		let hash = blake2_256(&tx);
-
 		(to_hex(&tx, true), hash)
 	};
 
@@ -152,10 +155,10 @@ async fn author_should_watch_extrinsic() {
 async fn author_should_return_watch_validation_error() {
 	const METHOD: &'static str = "author_submitAndWatchExtrinsic";
 
+	let invalid_xt = ExtrinsicBuilder::new_fill_block(Perbill::from_percent(100)).build();
+
 	let api = TestSetup::into_rpc();
-	let failed_sub = api
-		.subscribe(METHOD, [to_hex(&uxt(AccountKeyring::Alice, 179).encode(), true)])
-		.await;
+	let failed_sub = api.subscribe(METHOD, [to_hex(&invalid_xt.encode(), true)]).await;
 
 	assert_matches!(
 		failed_sub,
diff --git a/substrate/client/rpc/src/dev/tests.rs b/substrate/client/rpc/src/dev/tests.rs
index 9beb0118258..db6a9a119da 100644
--- a/substrate/client/rpc/src/dev/tests.rs
+++ b/substrate/client/rpc/src/dev/tests.rs
@@ -28,6 +28,22 @@ async fn block_stats_work() {
 	let api = <Dev<Block, _>>::new(client.clone(), DenyUnsafe::No).into_rpc();
 
 	let block = client.new_block(Default::default()).unwrap().build().unwrap().block;
+
+	let (expected_witness_len, expected_witness_compact_len, expected_block_len) = {
+		let genesis_hash = client.chain_info().genesis_hash;
+		let mut runtime_api = client.runtime_api();
+		runtime_api.record_proof();
+		runtime_api.execute_block(genesis_hash, block.clone()).unwrap();
+		let witness = runtime_api.extract_proof().unwrap();
+		let pre_root = *client.header(genesis_hash).unwrap().unwrap().state_root();
+
+		(
+			witness.clone().encoded_size() as u64,
+			witness.into_compact_proof::<HasherOf<Block>>(pre_root).unwrap().encoded_size() as u64,
+			block.encoded_size() as u64,
+		)
+	};
+
 	client.import(BlockOrigin::Own, block).await.unwrap();
 
 	// Can't gather stats for a block without a parent.
@@ -43,9 +59,9 @@ async fn block_stats_work() {
 			.await
 			.unwrap(),
 		Some(BlockStats {
-			witness_len: 630,
-			witness_compact_len: 534,
-			block_len: 99,
+			witness_len: expected_witness_len,
+			witness_compact_len: expected_witness_compact_len,
+			block_len: expected_block_len,
 			num_extrinsics: 0,
 		}),
 	);
diff --git a/substrate/client/rpc/src/state/tests.rs b/substrate/client/rpc/src/state/tests.rs
index ae193e662b0..9e00a04abe3 100644
--- a/substrate/client/rpc/src/state/tests.rs
+++ b/substrate/client/rpc/src/state/tests.rs
@@ -29,9 +29,11 @@ use sc_block_builder::BlockBuilderProvider;
 use sc_rpc_api::DenyUnsafe;
 use sp_consensus::BlockOrigin;
 use sp_core::{hash::H256, storage::ChildInfo};
-use sp_io::hashing::blake2_256;
 use std::sync::Arc;
-use substrate_test_runtime_client::{prelude::*, runtime};
+use substrate_test_runtime_client::{
+	prelude::*,
+	runtime::{ExtrinsicBuilder, Transfer},
+};
 
 const STORAGE_KEY: &[u8] = b"child";
 
@@ -218,7 +220,7 @@ async fn should_notify_about_storage_changes() {
 		// Cause a change:
 		let mut builder = client.new_block(Default::default()).unwrap();
 		builder
-			.push_transfer(runtime::Transfer {
+			.push_transfer(Transfer {
 				from: AccountKeyring::Alice.into(),
 				to: AccountKeyring::Ferdie.into(),
 				amount: 42,
@@ -244,18 +246,26 @@ async fn should_send_initial_storage_changes_and_notifications() {
 		let mut client = Arc::new(substrate_test_runtime_client::new());
 		let (api, _child) = new_full(client.clone(), test_executor(), DenyUnsafe::No);
 
-		let alice_balance_key =
-			blake2_256(&runtime::system::balance_of_key(AccountKeyring::Alice.into()));
+		let alice_balance_key = [
+			sp_core::hashing::twox_128(b"System"),
+			sp_core::hashing::twox_128(b"Account"),
+			sp_core::hashing::blake2_128(&AccountKeyring::Alice.public()),
+		]
+		.concat()
+		.iter()
+		.chain(AccountKeyring::Alice.public().0.iter())
+		.cloned()
+		.collect::<Vec<u8>>();
 
 		let api_rpc = api.into_rpc();
 		let sub = api_rpc
-			.subscribe("state_subscribeStorage", [[StorageKey(alice_balance_key.to_vec())]])
+			.subscribe("state_subscribeStorage", [[StorageKey(alice_balance_key)]])
 			.await
 			.unwrap();
 
 		let mut builder = client.new_block(Default::default()).unwrap();
 		builder
-			.push_transfer(runtime::Transfer {
+			.push_transfer(Transfer {
 				from: AccountKeyring::Alice.into(),
 				to: AccountKeyring::Ferdie.into(),
 				amount: 42,
@@ -280,22 +290,42 @@ async fn should_query_storage() {
 	async fn run_tests(mut client: Arc<TestClient>) {
 		let (api, _child) = new_full(client.clone(), test_executor(), DenyUnsafe::No);
 
-		let mut add_block = |nonce| {
+		let mut add_block = |index| {
 			let mut builder = client.new_block(Default::default()).unwrap();
 			// fake change: None -> None -> None
-			builder.push_storage_change(vec![1], None).unwrap();
+			builder
+				.push(ExtrinsicBuilder::new_storage_change(vec![1], None).build())
+				.unwrap();
 			// fake change: None -> Some(value) -> Some(value)
-			builder.push_storage_change(vec![2], Some(vec![2])).unwrap();
+			builder
+				.push(ExtrinsicBuilder::new_storage_change(vec![2], Some(vec![2])).build())
+				.unwrap();
 			// actual change: None -> Some(value) -> None
 			builder
-				.push_storage_change(vec![3], if nonce == 0 { Some(vec![3]) } else { None })
+				.push(
+					ExtrinsicBuilder::new_storage_change(
+						vec![3],
+						if index == 0 { Some(vec![3]) } else { None },
+					)
+					.build(),
+				)
 				.unwrap();
 			// actual change: None -> Some(value)
 			builder
-				.push_storage_change(vec![4], if nonce == 0 { None } else { Some(vec![4]) })
+				.push(
+					ExtrinsicBuilder::new_storage_change(
+						vec![4],
+						if index == 0 { None } else { Some(vec![4]) },
+					)
+					.build(),
+				)
 				.unwrap();
 			// actual change: Some(value1) -> Some(value2)
-			builder.push_storage_change(vec![5], Some(vec![nonce as u8])).unwrap();
+			builder
+				.push(
+					ExtrinsicBuilder::new_storage_change(vec![5], Some(vec![index as u8])).build(),
+				)
+				.unwrap();
 			let block = builder.build().unwrap().block;
 			let hash = block.header.hash();
 			executor::block_on(client.import(BlockOrigin::Own, block)).unwrap();
@@ -482,12 +512,13 @@ async fn should_return_runtime_version() {
 	let client = Arc::new(substrate_test_runtime_client::new());
 	let (api, _child) = new_full(client.clone(), test_executor(), DenyUnsafe::No);
 
+	// it is basically json-encoded substrate_test_runtime_client::runtime::VERSION
 	let result = "{\"specName\":\"test\",\"implName\":\"parity-test\",\"authoringVersion\":1,\
 		\"specVersion\":2,\"implVersion\":2,\"apis\":[[\"0xdf6acb689907609b\",4],\
 		[\"0x37e397fc7c91f5e4\",2],[\"0xd2bc9897eed08f15\",3],[\"0x40fe3ad401f8959a\",6],\
-		[\"0xc6e9a76309f39b09\",1],[\"0xdd718d5cc53262d4\",1],[\"0xcbca25e39f142387\",2],\
-		[\"0xf78b278be53f454c\",2],[\"0xab3c0572291feb8b\",1],[\"0xbc9d89904f5b923f\",1]],\
-		\"transactionVersion\":1,\"stateVersion\":1}";
+		[\"0xbc9d89904f5b923f\",1],[\"0xc6e9a76309f39b09\",2],[\"0xdd718d5cc53262d4\",1],\
+		[\"0xcbca25e39f142387\",2],[\"0xf78b278be53f454c\",2],[\"0xab3c0572291feb8b\",1],\
+		[\"0xed99c5acb25eedf5\",3]],\"transactionVersion\":1,\"stateVersion\":1}";
 
 	let runtime_version = api.runtime_version(None.into()).unwrap();
 	let serialized = serde_json::to_string(&runtime_version).unwrap();
diff --git a/substrate/client/service/src/lib.rs b/substrate/client/service/src/lib.rs
index a5667717055..b90eb71c1ea 100644
--- a/substrate/client/service/src/lib.rs
+++ b/substrate/client/service/src/lib.rs
@@ -520,10 +520,9 @@ mod tests {
 	use futures::executor::block_on;
 	use sc_transaction_pool::BasicPool;
 	use sp_consensus::SelectChain;
-	use sp_runtime::traits::BlindCheckable;
 	use substrate_test_runtime_client::{
 		prelude::*,
-		runtime::{Extrinsic, Transfer},
+		runtime::{ExtrinsicBuilder, Transfer, TransferData},
 	};
 
 	#[test]
@@ -542,13 +541,13 @@ mod tests {
 			from: AccountKeyring::Alice.into(),
 			to: AccountKeyring::Bob.into(),
 		}
-		.into_signed_tx();
+		.into_unchecked_extrinsic();
 		block_on(pool.submit_one(&BlockId::hash(best.hash()), source, transaction.clone()))
 			.unwrap();
 		block_on(pool.submit_one(
 			&BlockId::hash(best.hash()),
 			source,
-			Extrinsic::IncludeData(vec![1]),
+			ExtrinsicBuilder::new_call_do_not_propagate().nonce(1).build(),
 		))
 		.unwrap();
 		assert_eq!(pool.status().ready, 2);
@@ -558,8 +557,6 @@ mod tests {
 
 		// then
 		assert_eq!(transactions.len(), 1);
-		assert!(transactions[0].1.clone().check().is_ok());
-		// this should not panic
-		let _ = transactions[0].1.transfer();
+		assert!(TransferData::try_from(&transactions[0].1).is_ok());
 	}
 }
diff --git a/substrate/client/service/test/src/client/mod.rs b/substrate/client/service/test/src/client/mod.rs
index 520a9b52fea..a33bce50aa4 100644
--- a/substrate/client/service/test/src/client/mod.rs
+++ b/substrate/client/service/test/src/client/mod.rs
@@ -48,7 +48,8 @@ use substrate_test_runtime_client::{
 	new_native_or_wasm_executor,
 	prelude::*,
 	runtime::{
-		genesismap::{insert_genesis_block, GenesisConfig},
+		currency::DOLLARS,
+		genesismap::{insert_genesis_block, GenesisStorageBuilder},
 		Block, BlockNumber, Digest, Hash, Header, RuntimeApi, Transfer,
 	},
 	AccountKeyring, BlockBuilderExt, ClientBlockImportExt, ClientExt, DefaultTestClientBuilderExt,
@@ -66,7 +67,7 @@ fn construct_block(
 	state_root: Hash,
 	txs: Vec<Transfer>,
 ) -> (Vec<u8>, Hash) {
-	let transactions = txs.into_iter().map(|tx| tx.into_signed_tx()).collect::<Vec<_>>();
+	let transactions = txs.into_iter().map(|tx| tx.into_unchecked_extrinsic()).collect::<Vec<_>>();
 
 	let iter = transactions.iter().map(Encode::encode);
 	let extrinsics_root = LayoutV0::<BlakeTwo256>::ordered_trie_root(iter).into();
@@ -137,9 +138,9 @@ fn block1(genesis_hash: Hash, backend: &InMemoryBackend<BlakeTwo256>) -> (Vec<u8
 			"25e5b37074063ab75c889326246640729b40d0c86932edc527bc80db0e04fe5c",
 		),
 		vec![Transfer {
-			from: AccountKeyring::One.into(),
+			from: AccountKeyring::Alice.into(),
 			to: AccountKeyring::Two.into(),
-			amount: 69,
+			amount: 69 * DOLLARS,
 			nonce: 0,
 		}],
 	)
@@ -167,14 +168,12 @@ fn finality_notification_check(
 
 #[test]
 fn construct_genesis_should_work_with_native() {
-	let mut storage = GenesisConfig::new(
+	let mut storage = GenesisStorageBuilder::new(
 		vec![Sr25519Keyring::One.public().into(), Sr25519Keyring::Two.public().into()],
 		vec![AccountKeyring::One.into(), AccountKeyring::Two.into()],
-		1000,
-		None,
-		Default::default(),
+		1000 * DOLLARS,
 	)
-	.genesis_map();
+	.build_storage();
 	let genesis_hash = insert_genesis_block(&mut storage);
 
 	let backend = InMemoryBackend::from((storage, StateVersion::default()));
@@ -200,14 +199,12 @@ fn construct_genesis_should_work_with_native() {
 
 #[test]
 fn construct_genesis_should_work_with_wasm() {
-	let mut storage = GenesisConfig::new(
+	let mut storage = GenesisStorageBuilder::new(
 		vec![Sr25519Keyring::One.public().into(), Sr25519Keyring::Two.public().into()],
 		vec![AccountKeyring::One.into(), AccountKeyring::Two.into()],
-		1000,
-		None,
-		Default::default(),
+		1000 * DOLLARS,
 	)
-	.genesis_map();
+	.build_storage();
 	let genesis_hash = insert_genesis_block(&mut storage);
 
 	let backend = InMemoryBackend::from((storage, StateVersion::default()));
@@ -231,39 +228,6 @@ fn construct_genesis_should_work_with_wasm() {
 	.unwrap();
 }
 
-#[test]
-fn construct_genesis_with_bad_transaction_should_panic() {
-	let mut storage = GenesisConfig::new(
-		vec![Sr25519Keyring::One.public().into(), Sr25519Keyring::Two.public().into()],
-		vec![AccountKeyring::One.into(), AccountKeyring::Two.into()],
-		68,
-		None,
-		Default::default(),
-	)
-	.genesis_map();
-	let genesis_hash = insert_genesis_block(&mut storage);
-
-	let backend = InMemoryBackend::from((storage, StateVersion::default()));
-	let (b1data, _b1hash) = block1(genesis_hash, &backend);
-	let backend_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&backend);
-	let runtime_code = backend_runtime_code.runtime_code().expect("Code is part of the backend");
-
-	let mut overlay = OverlayedChanges::default();
-
-	let r = StateMachine::new(
-		&backend,
-		&mut overlay,
-		&new_native_or_wasm_executor(),
-		"Core_execute_block",
-		&b1data,
-		Default::default(),
-		&runtime_code,
-		CallContext::Onchain,
-	)
-	.execute(ExecutionStrategy::NativeElseWasm);
-	assert!(r.is_err());
-}
-
 #[test]
 fn client_initializes_from_genesis_ok() {
 	let client = substrate_test_runtime_client::new();
@@ -273,14 +237,14 @@ fn client_initializes_from_genesis_ok() {
 			.runtime_api()
 			.balance_of(client.chain_info().best_hash, AccountKeyring::Alice.into())
 			.unwrap(),
-		1000
+		1000 * DOLLARS
 	);
 	assert_eq!(
 		client
 			.runtime_api()
 			.balance_of(client.chain_info().best_hash, AccountKeyring::Ferdie.into())
 			.unwrap(),
-		0
+		0 * DOLLARS
 	);
 }
 
@@ -305,7 +269,7 @@ fn block_builder_works_with_transactions() {
 		.push_transfer(Transfer {
 			from: AccountKeyring::Alice.into(),
 			to: AccountKeyring::Ferdie.into(),
-			amount: 42,
+			amount: 42 * DOLLARS,
 			nonce: 0,
 		})
 		.unwrap();
@@ -340,42 +304,43 @@ fn block_builder_works_with_transactions() {
 			.runtime_api()
 			.balance_of(client.chain_info().best_hash, AccountKeyring::Alice.into())
 			.unwrap(),
-		958
+		958 * DOLLARS
 	);
 	assert_eq!(
 		client
 			.runtime_api()
 			.balance_of(client.chain_info().best_hash, AccountKeyring::Ferdie.into())
 			.unwrap(),
-		42
+		42 * DOLLARS
 	);
 }
 
 #[test]
 fn block_builder_does_not_include_invalid() {
 	let mut client = substrate_test_runtime_client::new();
-
 	let mut builder = client.new_block(Default::default()).unwrap();
 
 	builder
 		.push_transfer(Transfer {
 			from: AccountKeyring::Alice.into(),
 			to: AccountKeyring::Ferdie.into(),
-			amount: 42,
+			amount: 42 * DOLLARS,
 			nonce: 0,
 		})
 		.unwrap();
 
 	assert!(builder
 		.push_transfer(Transfer {
-			from: AccountKeyring::Eve.into(),
-			to: AccountKeyring::Alice.into(),
-			amount: 42,
+			from: AccountKeyring::Alice.into(),
+			to: AccountKeyring::Ferdie.into(),
+			amount: 30 * DOLLARS,
 			nonce: 0,
 		})
 		.is_err());
 
 	let block = builder.build().unwrap().block;
+	//transfer from Eve should not be included
+	assert_eq!(block.extrinsics.len(), 1);
 	block_on(client.import(BlockOrigin::Own, block)).unwrap();
 
 	let hashof0 = client
@@ -491,7 +456,7 @@ fn uncles_with_multiple_forks() {
 		.push_transfer(Transfer {
 			from: AccountKeyring::Alice.into(),
 			to: AccountKeyring::Ferdie.into(),
-			amount: 41,
+			amount: 41 * DOLLARS,
 			nonce: 0,
 		})
 		.unwrap();
@@ -523,7 +488,7 @@ fn uncles_with_multiple_forks() {
 		.push_transfer(Transfer {
 			from: AccountKeyring::Alice.into(),
 			to: AccountKeyring::Ferdie.into(),
-			amount: 1,
+			amount: 1 * DOLLARS,
 			nonce: 1,
 		})
 		.unwrap();
@@ -537,7 +502,7 @@ fn uncles_with_multiple_forks() {
 		.push_transfer(Transfer {
 			from: AccountKeyring::Alice.into(),
 			to: AccountKeyring::Ferdie.into(),
-			amount: 1,
+			amount: 1 * DOLLARS,
 			nonce: 0,
 		})
 		.unwrap();
@@ -646,7 +611,7 @@ fn finality_target_on_longest_chain_with_multiple_forks() {
 		.push_transfer(Transfer {
 			from: AccountKeyring::Alice.into(),
 			to: AccountKeyring::Ferdie.into(),
-			amount: 41,
+			amount: 41 * DOLLARS,
 			nonce: 0,
 		})
 		.unwrap();
@@ -678,7 +643,7 @@ fn finality_target_on_longest_chain_with_multiple_forks() {
 		.push_transfer(Transfer {
 			from: AccountKeyring::Alice.into(),
 			to: AccountKeyring::Ferdie.into(),
-			amount: 1,
+			amount: 1 * DOLLARS,
 			nonce: 1,
 		})
 		.unwrap();
@@ -692,7 +657,7 @@ fn finality_target_on_longest_chain_with_multiple_forks() {
 		.push_transfer(Transfer {
 			from: AccountKeyring::Alice.into(),
 			to: AccountKeyring::Ferdie.into(),
-			amount: 1,
+			amount: 1 * DOLLARS,
 			nonce: 0,
 		})
 		.unwrap();
@@ -868,7 +833,7 @@ fn finality_target_with_best_not_on_longest_chain() {
 		.push_transfer(Transfer {
 			from: AccountKeyring::Alice.into(),
 			to: AccountKeyring::Ferdie.into(),
-			amount: 41,
+			amount: 41 * DOLLARS,
 			nonce: 0,
 		})
 		.unwrap();
@@ -993,7 +958,7 @@ fn importing_diverged_finalized_block_should_trigger_reorg() {
 	b1.push_transfer(Transfer {
 		from: AccountKeyring::Alice.into(),
 		to: AccountKeyring::Ferdie.into(),
-		amount: 1,
+		amount: 1 * DOLLARS,
 		nonce: 0,
 	})
 	.unwrap();
@@ -1048,7 +1013,7 @@ fn finalizing_diverged_block_should_trigger_reorg() {
 	b1.push_transfer(Transfer {
 		from: AccountKeyring::Alice.into(),
 		to: AccountKeyring::Ferdie.into(),
-		amount: 1,
+		amount: 1 * DOLLARS,
 		nonce: 0,
 	})
 	.unwrap();
@@ -1166,7 +1131,7 @@ fn finality_notifications_content() {
 	c1.push_transfer(Transfer {
 		from: AccountKeyring::Alice.into(),
 		to: AccountKeyring::Ferdie.into(),
-		amount: 2,
+		amount: 2 * DOLLARS,
 		nonce: 0,
 	})
 	.unwrap();
@@ -1178,7 +1143,7 @@ fn finality_notifications_content() {
 	d3.push_transfer(Transfer {
 		from: AccountKeyring::Alice.into(),
 		to: AccountKeyring::Ferdie.into(),
-		amount: 2,
+		amount: 2 * DOLLARS,
 		nonce: 0,
 	})
 	.unwrap();
@@ -1252,7 +1217,7 @@ fn state_reverted_on_reorg() {
 	a1.push_transfer(Transfer {
 		from: AccountKeyring::Alice.into(),
 		to: AccountKeyring::Bob.into(),
-		amount: 10,
+		amount: 10 * DOLLARS,
 		nonce: 0,
 	})
 	.unwrap();
@@ -1265,7 +1230,7 @@ fn state_reverted_on_reorg() {
 	b1.push_transfer(Transfer {
 		from: AccountKeyring::Alice.into(),
 		to: AccountKeyring::Ferdie.into(),
-		amount: 50,
+		amount: 50 * DOLLARS,
 		nonce: 0,
 	})
 	.unwrap();
@@ -1273,19 +1238,19 @@ fn state_reverted_on_reorg() {
 	// Reorg to B1
 	block_on(client.import_as_best(BlockOrigin::Own, b1.clone())).unwrap();
 
-	assert_eq!(950, current_balance(&client));
+	assert_eq!(950 * DOLLARS, current_balance(&client));
 	let mut a2 = client.new_block_at(a1.hash(), Default::default(), false).unwrap();
 	a2.push_transfer(Transfer {
 		from: AccountKeyring::Alice.into(),
 		to: AccountKeyring::Charlie.into(),
-		amount: 10,
+		amount: 10 * DOLLARS,
 		nonce: 1,
 	})
 	.unwrap();
 	let a2 = a2.build().unwrap().block;
 	// Re-org to A2
 	block_on(client.import_as_best(BlockOrigin::Own, a2)).unwrap();
-	assert_eq!(980, current_balance(&client));
+	assert_eq!(980 * DOLLARS, current_balance(&client));
 }
 
 #[test]
@@ -1342,7 +1307,7 @@ fn doesnt_import_blocks_that_revert_finality() {
 	b1.push_transfer(Transfer {
 		from: AccountKeyring::Alice.into(),
 		to: AccountKeyring::Ferdie.into(),
-		amount: 1,
+		amount: 1 * DOLLARS,
 		nonce: 0,
 	})
 	.unwrap();
@@ -1386,7 +1351,7 @@ fn doesnt_import_blocks_that_revert_finality() {
 	c1.push_transfer(Transfer {
 		from: AccountKeyring::Alice.into(),
 		to: AccountKeyring::Ferdie.into(),
-		amount: 2,
+		amount: 2 * DOLLARS,
 		nonce: 0,
 	})
 	.unwrap();
@@ -1579,7 +1544,7 @@ fn returns_status_for_pruned_blocks() {
 	b1.push_transfer(Transfer {
 		from: AccountKeyring::Alice.into(),
 		to: AccountKeyring::Ferdie.into(),
-		amount: 1,
+		amount: 1 * DOLLARS,
 		nonce: 0,
 	})
 	.unwrap();
@@ -1718,8 +1683,9 @@ fn storage_keys_prefix_and_start_key_works() {
 		res,
 		[
 			child_root.clone(),
-			array_bytes::hex2bytes_unchecked("3a636f6465"),
-			array_bytes::hex2bytes_unchecked("3a686561707061676573"),
+			array_bytes::hex2bytes_unchecked("3a636f6465"), //":code"
+			array_bytes::hex2bytes_unchecked("3a65787472696e7369635f696e646578"), //":extrinsic_index"
+			array_bytes::hex2bytes_unchecked("3a686561707061676573"), //":heappages"
 		]
 	);
 
@@ -1732,7 +1698,13 @@ fn storage_keys_prefix_and_start_key_works() {
 		.unwrap()
 		.map(|x| x.0)
 		.collect();
-	assert_eq!(res, [array_bytes::hex2bytes_unchecked("3a686561707061676573")]);
+	assert_eq!(
+		res,
+		[
+			array_bytes::hex2bytes_unchecked("3a65787472696e7369635f696e646578"),
+			array_bytes::hex2bytes_unchecked("3a686561707061676573")
+		]
+	);
 
 	let res: Vec<_> = client
 		.storage_keys(
@@ -1762,54 +1734,32 @@ fn storage_keys_prefix_and_start_key_works() {
 
 #[test]
 fn storage_keys_works() {
-	let client = substrate_test_runtime_client::new();
+	sp_tracing::try_init_simple();
 
-	let block_hash = client.info().best_hash;
+	let expected_keys =
+		substrate_test_runtime::storage_key_generator::get_expected_storage_hashed_keys();
 
+	let client = substrate_test_runtime_client::new();
+	let block_hash = client.info().best_hash;
 	let prefix = StorageKey(array_bytes::hex2bytes_unchecked(""));
 
 	let res: Vec<_> = client
 		.storage_keys(block_hash, Some(&prefix), None)
 		.unwrap()
-		.take(9)
+		.take(19)
 		.map(|x| array_bytes::bytes2hex("", &x.0))
 		.collect();
-	assert_eq!(
-		res,
-		[
-			"00c232cf4e70a5e343317016dc805bf80a6a8cd8ad39958d56f99891b07851e0",
-			"085b2407916e53a86efeb8b72dbe338c4b341dab135252f96b6ed8022209b6cb",
-			"0befda6e1ca4ef40219d588a727f1271",
-			"1a560ecfd2a62c2b8521ef149d0804eb621050e3988ed97dca55f0d7c3e6aa34",
-			"1d66850d32002979d67dd29dc583af5b2ae2a1f71c1f35ad90fff122be7a3824",
-			"237498b98d8803334286e9f0483ef513098dd3c1c22ca21c4dc155b4ef6cc204",
-			"26aa394eea5630e07c48ae0c9558cef75e0621c4869aa60c02be9adcc98a0d1d",
-			"29b9db10ec5bf7907d8f74b5e60aa8140c4fbdd8127a1ee5600cb98e5ec01729",
-			"3a636f6465",
-		]
-	);
+
+	assert_eq!(res, expected_keys[0..19],);
 
 	// Starting at an empty key nothing gets skipped.
 	let res: Vec<_> = client
 		.storage_keys(block_hash, Some(&prefix), Some(&StorageKey("".into())))
 		.unwrap()
-		.take(9)
+		.take(19)
 		.map(|x| array_bytes::bytes2hex("", &x.0))
 		.collect();
-	assert_eq!(
-		res,
-		[
-			"00c232cf4e70a5e343317016dc805bf80a6a8cd8ad39958d56f99891b07851e0",
-			"085b2407916e53a86efeb8b72dbe338c4b341dab135252f96b6ed8022209b6cb",
-			"0befda6e1ca4ef40219d588a727f1271",
-			"1a560ecfd2a62c2b8521ef149d0804eb621050e3988ed97dca55f0d7c3e6aa34",
-			"1d66850d32002979d67dd29dc583af5b2ae2a1f71c1f35ad90fff122be7a3824",
-			"237498b98d8803334286e9f0483ef513098dd3c1c22ca21c4dc155b4ef6cc204",
-			"26aa394eea5630e07c48ae0c9558cef75e0621c4869aa60c02be9adcc98a0d1d",
-			"29b9db10ec5bf7907d8f74b5e60aa8140c4fbdd8127a1ee5600cb98e5ec01729",
-			"3a636f6465",
-		]
-	);
+	assert_eq!(res, expected_keys[0..19],);
 
 	// Starting at an incomplete key nothing gets skipped.
 	let res: Vec<_> = client
@@ -1824,16 +1774,12 @@ fn storage_keys_works() {
 		.collect();
 	assert_eq!(
 		res,
-		[
-			"3a636f6465",
-			"3a686561707061676573",
-			"52008686cc27f6e5ed83a216929942f8bcd32a396f09664a5698f81371934b56",
-			"5348d72ac6cc66e5d8cbecc27b0e0677503b845fe2382d819f83001781788fd5",
-			"5c2d5fda66373dabf970e4fb13d277ce91c5233473321129d32b5a8085fa8133",
-			"6644b9b8bc315888ac8e41a7968dc2b4141a5403c58acdf70b7e8f7e07bf5081",
-			"66484000ed3f75c95fc7b03f39c20ca1e1011e5999278247d3b2f5e3c3273808",
-			"7d5007603a7f5dd729d51d93cf695d6465789443bb967c0d1fe270e388c96eaa",
-		]
+		expected_keys
+			.iter()
+			.filter(|&i| i > &"3a636f64".to_string())
+			.take(8)
+			.cloned()
+			.collect::<Vec<String>>()
 	);
 
 	// Starting at a complete key the first key is skipped.
@@ -1849,38 +1795,33 @@ fn storage_keys_works() {
 		.collect();
 	assert_eq!(
 		res,
-		[
-			"3a686561707061676573",
-			"52008686cc27f6e5ed83a216929942f8bcd32a396f09664a5698f81371934b56",
-			"5348d72ac6cc66e5d8cbecc27b0e0677503b845fe2382d819f83001781788fd5",
-			"5c2d5fda66373dabf970e4fb13d277ce91c5233473321129d32b5a8085fa8133",
-			"6644b9b8bc315888ac8e41a7968dc2b4141a5403c58acdf70b7e8f7e07bf5081",
-			"66484000ed3f75c95fc7b03f39c20ca1e1011e5999278247d3b2f5e3c3273808",
-			"7d5007603a7f5dd729d51d93cf695d6465789443bb967c0d1fe270e388c96eaa",
-		]
+		expected_keys
+			.iter()
+			.filter(|&i| i > &"3a636f6465".to_string())
+			.take(8)
+			.cloned()
+			.collect::<Vec<String>>()
 	);
 
+	const SOME_BALANCE_KEY : &str = "26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9e2c1dc507e2035edbbd8776c440d870460c57f0008067cc01c5ff9eb2e2f9b3a94299a915a91198bd1021a6c55596f57";
 	let res: Vec<_> = client
 		.storage_keys(
 			block_hash,
 			Some(&prefix),
-			Some(&StorageKey(array_bytes::hex2bytes_unchecked(
-				"7d5007603a7f5dd729d51d93cf695d6465789443bb967c0d1fe270e388c96eaa",
-			))),
+			Some(&StorageKey(array_bytes::hex2bytes_unchecked(SOME_BALANCE_KEY))),
 		)
 		.unwrap()
-		.take(5)
+		.take(8)
 		.map(|x| array_bytes::bytes2hex("", &x.0))
 		.collect();
 	assert_eq!(
 		res,
-		[
-			"811ecfaadcf5f2ee1d67393247e2f71a1662d433e8ce7ff89fb0d4aa9561820b",
-			"a93d74caa7ec34ea1b04ce1e5c090245f867d333f0f88278a451e45299654dc5",
-			"a9ee1403384afbfc13f13be91ff70bfac057436212e53b9733914382ac942892",
-			"cf722c0832b5231d35e29f319ff27389f5032bfc7bfc3ba5ed7839f2042fb99f",
-			"e3b47b6c84c0493481f97c5197d2554f",
-		]
+		expected_keys
+			.iter()
+			.filter(|&i| i > &SOME_BALANCE_KEY.to_string())
+			.take(8)
+			.cloned()
+			.collect::<Vec<String>>()
 	);
 }
 
@@ -1999,7 +1940,7 @@ fn reorg_triggers_a_notification_even_for_sources_that_should_not_trigger_notifi
 	b1.push_transfer(Transfer {
 		from: AccountKeyring::Alice.into(),
 		to: AccountKeyring::Ferdie.into(),
-		amount: 1,
+		amount: 1 * DOLLARS,
 		nonce: 0,
 	})
 	.unwrap();
diff --git a/substrate/client/transaction-pool/benches/basics.rs b/substrate/client/transaction-pool/benches/basics.rs
index f7739ef73a9..d114acc343d 100644
--- a/substrate/client/transaction-pool/benches/basics.rs
+++ b/substrate/client/transaction-pool/benches/basics.rs
@@ -18,7 +18,7 @@
 
 use criterion::{criterion_group, criterion_main, Criterion};
 
-use codec::{Decode, Encode};
+use codec::Encode;
 use futures::{
 	executor::block_on,
 	future::{ready, Ready},
@@ -33,7 +33,7 @@ use sp_runtime::{
 		ValidTransaction,
 	},
 };
-use substrate_test_runtime::{AccountId, Block, Extrinsic, Transfer, H256};
+use substrate_test_runtime::{AccountId, Block, Extrinsic, ExtrinsicBuilder, TransferData, H256};
 
 #[derive(Clone, Debug, Default)]
 struct TestApi {
@@ -65,8 +65,10 @@ impl ChainApi for TestApi {
 		_source: TransactionSource,
 		uxt: <Self::Block as BlockT>::Extrinsic,
 	) -> Self::ValidationFuture {
-		let nonce = uxt.transfer().nonce;
-		let from = uxt.transfer().from;
+		let transfer = TransferData::try_from(&uxt)
+			.expect("uxt is expected to be bench_call (carrying TransferData)");
+		let nonce = transfer.nonce;
+		let from = transfer.from;
 
 		match self.block_id_to_number(at) {
 			Ok(Some(num)) if num > 5 => return ready(Ok(Err(InvalidTransaction::Stale.into()))),
@@ -131,13 +133,8 @@ impl ChainApi for TestApi {
 	}
 }
 
-fn uxt(transfer: Transfer) -> Extrinsic {
-	Extrinsic::Transfer {
-		transfer,
-		signature: Decode::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes())
-			.expect("infinite input; no dead input space; qed"),
-		exhaust_resources_when_not_first: false,
-	}
+fn uxt(transfer: TransferData) -> Extrinsic {
+	ExtrinsicBuilder::new_bench_call(transfer).build()
 }
 
 fn bench_configured(pool: Pool<TestApi>, number: u64) {
@@ -146,7 +143,7 @@ fn bench_configured(pool: Pool<TestApi>, number: u64) {
 	let mut tags = Vec::new();
 
 	for nonce in 1..=number {
-		let xt = uxt(Transfer {
+		let xt = uxt(TransferData {
 			from: AccountId::from_h256(H256::from_low_u64_be(1)),
 			to: AccountId::from_h256(H256::from_low_u64_be(2)),
 			amount: 5,
diff --git a/substrate/client/transaction-pool/src/graph/pool.rs b/substrate/client/transaction-pool/src/graph/pool.rs
index 54534df8202..4d34737a7ba 100644
--- a/substrate/client/transaction-pool/src/graph/pool.rs
+++ b/substrate/client/transaction-pool/src/graph/pool.rs
@@ -463,7 +463,8 @@ mod tests {
 	use sc_transaction_pool_api::TransactionStatus;
 	use sp_runtime::transaction_validity::TransactionSource;
 	use std::{collections::HashMap, time::Instant};
-	use substrate_test_runtime::{AccountId, Extrinsic, Transfer, H256};
+	use substrate_test_runtime::{AccountId, ExtrinsicBuilder, Transfer, H256};
+	use substrate_test_runtime_client::AccountKeyring::{Alice, Bob};
 
 	const SOURCE: TransactionSource = TransactionSource::External;
 
@@ -477,7 +478,7 @@ mod tests {
 			&BlockId::Number(0),
 			SOURCE,
 			uxt(Transfer {
-				from: AccountId::from_h256(H256::from_low_u64_be(1)),
+				from: Alice.into(),
 				to: AccountId::from_h256(H256::from_low_u64_be(2)),
 				amount: 5,
 				nonce: 0,
@@ -494,7 +495,7 @@ mod tests {
 		// given
 		let pool = pool();
 		let uxt = uxt(Transfer {
-			from: AccountId::from_h256(H256::from_low_u64_be(1)),
+			from: Alice.into(),
 			to: AccountId::from_h256(H256::from_low_u64_be(2)),
 			amount: 5,
 			nonce: 0,
@@ -520,8 +521,8 @@ mod tests {
 			TestApi::default().into(),
 		);
 
-		// after validation `IncludeData` will be set to non-propagable
-		let uxt = Extrinsic::IncludeData(vec![42]);
+		// after validation `IncludeData` will be set to non-propagable (validate_transaction mock)
+		let uxt = ExtrinsicBuilder::new_include_data(vec![42]).build();
 
 		// when
 		let res = block_on(pool.submit_one(&BlockId::Number(0), SOURCE, uxt));
@@ -542,7 +543,7 @@ mod tests {
 				&BlockId::Number(0),
 				SOURCE,
 				uxt(Transfer {
-					from: AccountId::from_h256(H256::from_low_u64_be(1)),
+					from: Alice.into(),
 					to: AccountId::from_h256(H256::from_low_u64_be(2)),
 					amount: 5,
 					nonce: 0,
@@ -553,7 +554,7 @@ mod tests {
 				&BlockId::Number(0),
 				SOURCE,
 				uxt(Transfer {
-					from: AccountId::from_h256(H256::from_low_u64_be(1)),
+					from: Alice.into(),
 					to: AccountId::from_h256(H256::from_low_u64_be(2)),
 					amount: 5,
 					nonce: 1,
@@ -565,7 +566,7 @@ mod tests {
 				&BlockId::Number(0),
 				SOURCE,
 				uxt(Transfer {
-					from: AccountId::from_h256(H256::from_low_u64_be(1)),
+					from: Alice.into(),
 					to: AccountId::from_h256(H256::from_low_u64_be(2)),
 					amount: 5,
 					nonce: 3,
@@ -594,7 +595,7 @@ mod tests {
 			&BlockId::Number(0),
 			SOURCE,
 			uxt(Transfer {
-				from: AccountId::from_h256(H256::from_low_u64_be(1)),
+				from: Alice.into(),
 				to: AccountId::from_h256(H256::from_low_u64_be(2)),
 				amount: 5,
 				nonce: 0,
@@ -605,7 +606,7 @@ mod tests {
 			&BlockId::Number(0),
 			SOURCE,
 			uxt(Transfer {
-				from: AccountId::from_h256(H256::from_low_u64_be(1)),
+				from: Alice.into(),
 				to: AccountId::from_h256(H256::from_low_u64_be(2)),
 				amount: 5,
 				nonce: 1,
@@ -616,7 +617,7 @@ mod tests {
 			&BlockId::Number(0),
 			SOURCE,
 			uxt(Transfer {
-				from: AccountId::from_h256(H256::from_low_u64_be(1)),
+				from: Alice.into(),
 				to: AccountId::from_h256(H256::from_low_u64_be(2)),
 				amount: 5,
 				nonce: 3,
@@ -645,7 +646,7 @@ mod tests {
 			&BlockId::Number(0),
 			SOURCE,
 			uxt(Transfer {
-				from: AccountId::from_h256(H256::from_low_u64_be(1)),
+				from: Alice.into(),
 				to: AccountId::from_h256(H256::from_low_u64_be(2)),
 				amount: 5,
 				nonce: 0,
@@ -659,27 +660,27 @@ mod tests {
 		// then
 		assert!(pool.validated_pool.is_banned(&hash1));
 	}
+	use codec::Encode;
 
 	#[test]
 	fn should_limit_futures() {
+		sp_tracing::try_init_simple();
+
+		let xt = uxt(Transfer {
+			from: Alice.into(),
+			to: AccountId::from_h256(H256::from_low_u64_be(2)),
+			amount: 5,
+			nonce: 1,
+		});
+
 		// given
-		let limit = Limit { count: 100, total_bytes: 200 };
+		let limit = Limit { count: 100, total_bytes: xt.encoded_size() };
 
 		let options = Options { ready: limit.clone(), future: limit.clone(), ..Default::default() };
 
 		let pool = Pool::new(options, true.into(), TestApi::default().into());
 
-		let hash1 = block_on(pool.submit_one(
-			&BlockId::Number(0),
-			SOURCE,
-			uxt(Transfer {
-				from: AccountId::from_h256(H256::from_low_u64_be(1)),
-				to: AccountId::from_h256(H256::from_low_u64_be(2)),
-				amount: 5,
-				nonce: 1,
-			}),
-		))
-		.unwrap();
+		let hash1 = block_on(pool.submit_one(&BlockId::Number(0), SOURCE, xt)).unwrap();
 		assert_eq!(pool.validated_pool().status().future, 1);
 
 		// when
@@ -687,7 +688,7 @@ mod tests {
 			&BlockId::Number(0),
 			SOURCE,
 			uxt(Transfer {
-				from: AccountId::from_h256(H256::from_low_u64_be(2)),
+				from: Bob.into(),
 				to: AccountId::from_h256(H256::from_low_u64_be(2)),
 				amount: 5,
 				nonce: 10,
@@ -715,7 +716,7 @@ mod tests {
 			&BlockId::Number(0),
 			SOURCE,
 			uxt(Transfer {
-				from: AccountId::from_h256(H256::from_low_u64_be(1)),
+				from: Alice.into(),
 				to: AccountId::from_h256(H256::from_low_u64_be(2)),
 				amount: 5,
 				nonce: 1,
@@ -738,7 +739,7 @@ mod tests {
 			&BlockId::Number(0),
 			SOURCE,
 			uxt(Transfer {
-				from: AccountId::from_h256(H256::from_low_u64_be(1)),
+				from: Alice.into(),
 				to: AccountId::from_h256(H256::from_low_u64_be(2)),
 				amount: 5,
 				nonce: INVALID_NONCE,
@@ -763,7 +764,7 @@ mod tests {
 				&BlockId::Number(0),
 				SOURCE,
 				uxt(Transfer {
-					from: AccountId::from_h256(H256::from_low_u64_be(1)),
+					from: Alice.into(),
 					to: AccountId::from_h256(H256::from_low_u64_be(2)),
 					amount: 5,
 					nonce: 0,
@@ -795,7 +796,7 @@ mod tests {
 				&BlockId::Number(0),
 				SOURCE,
 				uxt(Transfer {
-					from: AccountId::from_h256(H256::from_low_u64_be(1)),
+					from: Alice.into(),
 					to: AccountId::from_h256(H256::from_low_u64_be(2)),
 					amount: 5,
 					nonce: 0,
@@ -828,7 +829,7 @@ mod tests {
 				&BlockId::Number(0),
 				SOURCE,
 				uxt(Transfer {
-					from: AccountId::from_h256(H256::from_low_u64_be(1)),
+					from: Alice.into(),
 					to: AccountId::from_h256(H256::from_low_u64_be(2)),
 					amount: 5,
 					nonce: 1,
@@ -843,7 +844,7 @@ mod tests {
 				&BlockId::Number(0),
 				SOURCE,
 				uxt(Transfer {
-					from: AccountId::from_h256(H256::from_low_u64_be(1)),
+					from: Alice.into(),
 					to: AccountId::from_h256(H256::from_low_u64_be(2)),
 					amount: 5,
 					nonce: 0,
@@ -863,7 +864,7 @@ mod tests {
 			// given
 			let pool = pool();
 			let uxt = uxt(Transfer {
-				from: AccountId::from_h256(H256::from_low_u64_be(1)),
+				from: Alice.into(),
 				to: AccountId::from_h256(H256::from_low_u64_be(2)),
 				amount: 5,
 				nonce: 0,
@@ -887,7 +888,7 @@ mod tests {
 			// given
 			let pool = pool();
 			let uxt = uxt(Transfer {
-				from: AccountId::from_h256(H256::from_low_u64_be(1)),
+				from: Alice.into(),
 				to: AccountId::from_h256(H256::from_low_u64_be(2)),
 				amount: 5,
 				nonce: 0,
@@ -918,7 +919,7 @@ mod tests {
 			let pool = Pool::new(options, true.into(), TestApi::default().into());
 
 			let xt = uxt(Transfer {
-				from: AccountId::from_h256(H256::from_low_u64_be(1)),
+				from: Alice.into(),
 				to: AccountId::from_h256(H256::from_low_u64_be(2)),
 				amount: 5,
 				nonce: 0,
@@ -928,7 +929,7 @@ mod tests {
 
 			// when
 			let xt = uxt(Transfer {
-				from: AccountId::from_h256(H256::from_low_u64_be(2)),
+				from: Bob.into(),
 				to: AccountId::from_h256(H256::from_low_u64_be(1)),
 				amount: 4,
 				nonce: 1,
@@ -952,13 +953,17 @@ mod tests {
 
 				let pool = Pool::new(options, true.into(), TestApi::default().into());
 
-				let xt = Extrinsic::IncludeData(Vec::new());
+				// after validation `IncludeData` will have priority set to 9001
+				// (validate_transaction mock)
+				let xt = ExtrinsicBuilder::new_include_data(Vec::new()).build();
 				block_on(pool.submit_one(&BlockId::Number(0), SOURCE, xt)).unwrap();
 				assert_eq!(pool.validated_pool().status().ready, 1);
 
 				// then
+				// after validation `Transfer` will have priority set to 4 (validate_transaction
+				// mock)
 				let xt = uxt(Transfer {
-					from: AccountId::from_h256(H256::from_low_u64_be(2)),
+					from: Bob.into(),
 					to: AccountId::from_h256(H256::from_low_u64_be(1)),
 					amount: 4,
 					nonce: 1,
@@ -977,12 +982,16 @@ mod tests {
 
 				let pool = Pool::new(options, true.into(), TestApi::default().into());
 
-				let xt = Extrinsic::IncludeData(Vec::new());
+				// after validation `IncludeData` will have priority set to 9001
+				// (validate_transaction mock)
+				let xt = ExtrinsicBuilder::new_include_data(Vec::new()).build();
 				block_on(pool.submit_and_watch(&BlockId::Number(0), SOURCE, xt)).unwrap();
 				assert_eq!(pool.validated_pool().status().ready, 1);
 
+				// after validation `Transfer` will have priority set to 4 (validate_transaction
+				// mock)
 				let xt = uxt(Transfer {
-					from: AccountId::from_h256(H256::from_low_u64_be(1)),
+					from: Alice.into(),
 					to: AccountId::from_h256(H256::from_low_u64_be(2)),
 					amount: 5,
 					nonce: 0,
@@ -992,7 +1001,9 @@ mod tests {
 				assert_eq!(pool.validated_pool().status().ready, 2);
 
 				// when
-				let xt = Extrinsic::Store(Vec::new());
+				// after validation `Store` will have priority set to 9001 (validate_transaction
+				// mock)
+				let xt = ExtrinsicBuilder::new_indexed_call(Vec::new()).build();
 				block_on(pool.submit_one(&BlockId::Number(1), SOURCE, xt)).unwrap();
 				assert_eq!(pool.validated_pool().status().ready, 2);
 
@@ -1014,7 +1025,7 @@ mod tests {
 
 			// when
 			let xt = uxt(Transfer {
-				from: AccountId::from_h256(H256::from_low_u64_be(1)),
+				from: Alice.into(),
 				to: AccountId::from_h256(H256::from_low_u64_be(2)),
 				amount: 5,
 				nonce: 1,
@@ -1030,7 +1041,7 @@ mod tests {
 			// But now before the previous one is imported we import
 			// the one that it depends on.
 			let xt = uxt(Transfer {
-				from: AccountId::from_h256(H256::from_low_u64_be(1)),
+				from: Alice.into(),
 				to: AccountId::from_h256(H256::from_low_u64_be(2)),
 				amount: 4,
 				nonce: 0,
diff --git a/substrate/client/transaction-pool/src/revalidation.rs b/substrate/client/transaction-pool/src/revalidation.rs
index bd8f3dd6498..b2c41be92ee 100644
--- a/substrate/client/transaction-pool/src/revalidation.rs
+++ b/substrate/client/transaction-pool/src/revalidation.rs
@@ -362,6 +362,7 @@ mod tests {
 	use sc_transaction_pool_api::TransactionSource;
 	use sp_runtime::generic::BlockId;
 	use substrate_test_runtime::{AccountId, Transfer, H256};
+	use substrate_test_runtime_client::AccountKeyring::Alice;
 
 	#[test]
 	fn revalidation_queue_works() {
@@ -370,7 +371,7 @@ mod tests {
 		let queue = Arc::new(RevalidationQueue::new(api.clone(), pool.clone()));
 
 		let uxt = uxt(Transfer {
-			from: AccountId::from_h256(H256::from_low_u64_be(1)),
+			from: Alice.into(),
 			to: AccountId::from_h256(H256::from_low_u64_be(2)),
 			amount: 5,
 			nonce: 0,
diff --git a/substrate/client/transaction-pool/src/tests.rs b/substrate/client/transaction-pool/src/tests.rs
index 3945c88d49c..62911d5cbb4 100644
--- a/substrate/client/transaction-pool/src/tests.rs
+++ b/substrate/client/transaction-pool/src/tests.rs
@@ -31,7 +31,10 @@ use sp_runtime::{
 	},
 };
 use std::{collections::HashSet, sync::Arc};
-use substrate_test_runtime::{Block, Extrinsic, Hashing, Transfer, H256};
+use substrate_test_runtime::{
+	substrate_test_pallet::pallet::Call as PalletCall, BalancesCall, Block, Extrinsic,
+	ExtrinsicBuilder, Hashing, RuntimeCall, Transfer, TransferData, H256,
+};
 
 pub(crate) const INVALID_NONCE: u64 = 254;
 
@@ -70,9 +73,11 @@ impl ChainApi for TestApi {
 		let block_number = self.block_id_to_number(at).unwrap().unwrap();
 
 		let res = match uxt {
-			Extrinsic::Transfer { transfer, .. } => {
-				let nonce = transfer.nonce;
-
+			Extrinsic {
+				function: RuntimeCall::Balances(BalancesCall::transfer_allow_death { .. }),
+				..
+			} => {
+				let TransferData { nonce, .. } = (&uxt).try_into().unwrap();
 				// This is used to control the test flow.
 				if nonce > 0 {
 					let opt = self.delay.lock().take();
@@ -115,14 +120,20 @@ impl ChainApi for TestApi {
 					Ok(transaction)
 				}
 			},
-			Extrinsic::IncludeData(_) => Ok(ValidTransaction {
+			Extrinsic {
+				function: RuntimeCall::SubstrateTest(PalletCall::include_data { .. }),
+				..
+			} => Ok(ValidTransaction {
 				priority: 9001,
 				requires: vec![],
 				provides: vec![vec![42]],
 				longevity: 9001,
 				propagate: false,
 			}),
-			Extrinsic::Store(_) => Ok(ValidTransaction {
+			Extrinsic {
+				function: RuntimeCall::SubstrateTest(PalletCall::indexed_call { .. }),
+				..
+			} => Ok(ValidTransaction {
 				priority: 9001,
 				requires: vec![],
 				provides: vec![vec![43]],
@@ -185,8 +196,7 @@ impl ChainApi for TestApi {
 }
 
 pub(crate) fn uxt(transfer: Transfer) -> Extrinsic {
-	let signature = TryFrom::try_from(&[0; 64][..]).unwrap();
-	Extrinsic::Transfer { transfer, signature, exhaust_resources_when_not_first: false }
+	ExtrinsicBuilder::new_transfer(transfer).build()
 }
 
 pub(crate) fn pool() -> Pool<TestApi> {
diff --git a/substrate/client/transaction-pool/tests/pool.rs b/substrate/client/transaction-pool/tests/pool.rs
index 284c777a683..ac029d71700 100644
--- a/substrate/client/transaction-pool/tests/pool.rs
+++ b/substrate/client/transaction-pool/tests/pool.rs
@@ -35,11 +35,11 @@ use sp_consensus::BlockOrigin;
 use sp_runtime::{
 	generic::BlockId,
 	traits::Block as _,
-	transaction_validity::{InvalidTransaction, TransactionSource, ValidTransaction},
+	transaction_validity::{TransactionSource, ValidTransaction},
 };
 use std::{collections::BTreeSet, pin::Pin, sync::Arc};
 use substrate_test_runtime_client::{
-	runtime::{Block, Extrinsic, Hash, Header, Index, Transfer},
+	runtime::{Block, Extrinsic, ExtrinsicBuilder, Hash, Header, Index, Transfer, TransferData},
 	AccountKeyring::*,
 	ClientBlockImportExt,
 };
@@ -86,7 +86,11 @@ fn submission_should_work() {
 	let pool = pool();
 	block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt(Alice, 209))).unwrap();
 
-	let pending: Vec<_> = pool.validated_pool().ready().map(|a| a.data.transfer().nonce).collect();
+	let pending: Vec<_> = pool
+		.validated_pool()
+		.ready()
+		.map(|a| TransferData::try_from(&a.data).unwrap().nonce)
+		.collect();
 	assert_eq!(pending, vec![209]);
 }
 
@@ -96,16 +100,25 @@ fn multiple_submission_should_work() {
 	block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt(Alice, 209))).unwrap();
 	block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt(Alice, 210))).unwrap();
 
-	let pending: Vec<_> = pool.validated_pool().ready().map(|a| a.data.transfer().nonce).collect();
+	let pending: Vec<_> = pool
+		.validated_pool()
+		.ready()
+		.map(|a| TransferData::try_from(&a.data).unwrap().nonce)
+		.collect();
 	assert_eq!(pending, vec![209, 210]);
 }
 
 #[test]
 fn early_nonce_should_be_culled() {
+	sp_tracing::try_init_simple();
 	let pool = pool();
 	block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt(Alice, 208))).unwrap();
 
-	let pending: Vec<_> = pool.validated_pool().ready().map(|a| a.data.transfer().nonce).collect();
+	let pending: Vec<_> = pool
+		.validated_pool()
+		.ready()
+		.map(|a| TransferData::try_from(&a.data).unwrap().nonce)
+		.collect();
 	assert_eq!(pending, Vec::<Index>::new());
 }
 
@@ -114,11 +127,19 @@ fn late_nonce_should_be_queued() {
 	let pool = pool();
 
 	block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt(Alice, 210))).unwrap();
-	let pending: Vec<_> = pool.validated_pool().ready().map(|a| a.data.transfer().nonce).collect();
+	let pending: Vec<_> = pool
+		.validated_pool()
+		.ready()
+		.map(|a| TransferData::try_from(&a.data).unwrap().nonce)
+		.collect();
 	assert_eq!(pending, Vec::<Index>::new());
 
 	block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt(Alice, 209))).unwrap();
-	let pending: Vec<_> = pool.validated_pool().ready().map(|a| a.data.transfer().nonce).collect();
+	let pending: Vec<_> = pool
+		.validated_pool()
+		.ready()
+		.map(|a| TransferData::try_from(&a.data).unwrap().nonce)
+		.collect();
 	assert_eq!(pending, vec![209, 210]);
 }
 
@@ -128,14 +149,22 @@ fn prune_tags_should_work() {
 	let hash209 = block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt(Alice, 209))).unwrap();
 	block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt(Alice, 210))).unwrap();
 
-	let pending: Vec<_> = pool.validated_pool().ready().map(|a| a.data.transfer().nonce).collect();
+	let pending: Vec<_> = pool
+		.validated_pool()
+		.ready()
+		.map(|a| TransferData::try_from(&a.data).unwrap().nonce)
+		.collect();
 	assert_eq!(pending, vec![209, 210]);
 
 	pool.validated_pool().api().push_block(1, Vec::new(), true);
 	block_on(pool.prune_tags(&BlockId::number(1), vec![vec![209]], vec![hash209]))
 		.expect("Prune tags");
 
-	let pending: Vec<_> = pool.validated_pool().ready().map(|a| a.data.transfer().nonce).collect();
+	let pending: Vec<_> = pool
+		.validated_pool()
+		.ready()
+		.map(|a| TransferData::try_from(&a.data).unwrap().nonce)
+		.collect();
 	assert_eq!(pending, vec![210]);
 }
 
@@ -148,7 +177,11 @@ fn should_ban_invalid_transactions() {
 	block_on(pool.submit_one(&BlockId::number(0), SOURCE, uxt.clone())).unwrap_err();
 
 	// when
-	let pending: Vec<_> = pool.validated_pool().ready().map(|a| a.data.transfer().nonce).collect();
+	let pending: Vec<_> = pool
+		.validated_pool()
+		.ready()
+		.map(|a| TransferData::try_from(&a.data).unwrap().nonce)
+		.collect();
 	assert_eq!(pending, Vec::<Index>::new());
 
 	// then
@@ -197,7 +230,11 @@ fn should_correctly_prune_transactions_providing_more_than_one_tag() {
 	block_on(pool.submit_one(&BlockId::number(2), SOURCE, xt.clone())).expect("2. Imported");
 	assert_eq!(pool.validated_pool().status().ready, 1);
 	assert_eq!(pool.validated_pool().status().future, 1);
-	let pending: Vec<_> = pool.validated_pool().ready().map(|a| a.data.transfer().nonce).collect();
+	let pending: Vec<_> = pool
+		.validated_pool()
+		.ready()
+		.map(|a| TransferData::try_from(&a.data).unwrap().nonce)
+		.collect();
 	assert_eq!(pending, vec![211]);
 
 	// prune it and make sure the pool is empty
@@ -472,6 +509,7 @@ fn finalization() {
 
 #[test]
 fn fork_aware_finalization() {
+	sp_tracing::try_init_simple();
 	let api = TestApi::empty();
 	// starting block A1 (last finalized.)
 	let a_header = api.push_block(1, vec![], true);
@@ -888,48 +926,6 @@ fn ready_set_should_eventually_resolve_when_block_update_arrives() {
 	}
 }
 
-#[test]
-fn should_not_accept_old_signatures() {
-	let client = Arc::new(substrate_test_runtime_client::new());
-	let best_hash = client.info().best_hash;
-	let finalized_hash = client.info().finalized_hash;
-	let pool = Arc::new(
-		BasicPool::new_test(
-			Arc::new(FullChainApi::new(client, None, &sp_core::testing::TaskExecutor::new())),
-			best_hash,
-			finalized_hash,
-		)
-		.0,
-	);
-
-	let transfer = Transfer { from: Alice.into(), to: Bob.into(), nonce: 0, amount: 1 };
-	let _bytes: sp_core::sr25519::Signature = transfer.using_encoded(|e| Alice.sign(e)).into();
-
-	// generated with schnorrkel 0.1.1 from `_bytes`
-	let old_singature = sp_core::sr25519::Signature::try_from(
-		&array_bytes::hex2bytes(
-			"c427eb672e8c441c86d31f1a81b22b43102058e9ce237cabe9897ea5099ffd426\
-		cd1c6a1f4f2869c3df57901d36bedcb295657adb3a4355add86ed234eb83108",
-		)
-		.expect("hex invalid")[..],
-	)
-	.expect("signature construction failed");
-
-	let xt = Extrinsic::Transfer {
-		transfer,
-		signature: old_singature,
-		exhaust_resources_when_not_first: false,
-	};
-
-	assert_matches::assert_matches!(
-		block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt.clone())),
-		Err(error::Error::Pool(sc_transaction_pool_api::error::Error::InvalidTransaction(
-			InvalidTransaction::BadProof
-		))),
-		"Should be invalid transaction with bad proof",
-	);
-}
-
 #[test]
 fn import_notification_to_pool_maintain_works() {
 	let mut client = Arc::new(substrate_test_runtime_client::new());
@@ -975,7 +971,7 @@ fn import_notification_to_pool_maintain_works() {
 fn pruning_a_transaction_should_remove_it_from_best_transaction() {
 	let (pool, api, _guard) = maintained_pool();
 
-	let xt1 = Extrinsic::IncludeData(Vec::new());
+	let xt1 = ExtrinsicBuilder::new_include_data(Vec::new()).build();
 
 	block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt1.clone())).expect("1. Imported");
 	assert_eq!(pool.status().ready, 1);
@@ -1001,7 +997,7 @@ fn stale_transactions_are_pruned() {
 	let (pool, api, _guard) = maintained_pool();
 
 	xts.into_iter().for_each(|xt| {
-		block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt.into_signed_tx()))
+		block_on(pool.submit_one(&BlockId::number(0), SOURCE, xt.into_unchecked_extrinsic()))
 			.expect("1. Imported");
 	});
 	assert_eq!(pool.status().ready, 0);
@@ -1010,9 +1006,12 @@ fn stale_transactions_are_pruned() {
 	// Almost the same as our initial transactions, but with some different `amount`s to make them
 	// generate a different hash
 	let xts = vec![
-		Transfer { from: Alice.into(), to: Bob.into(), nonce: 1, amount: 2 }.into_signed_tx(),
-		Transfer { from: Alice.into(), to: Bob.into(), nonce: 2, amount: 2 }.into_signed_tx(),
-		Transfer { from: Alice.into(), to: Bob.into(), nonce: 3, amount: 2 }.into_signed_tx(),
+		Transfer { from: Alice.into(), to: Bob.into(), nonce: 1, amount: 2 }
+			.into_unchecked_extrinsic(),
+		Transfer { from: Alice.into(), to: Bob.into(), nonce: 2, amount: 2 }
+			.into_unchecked_extrinsic(),
+		Transfer { from: Alice.into(), to: Bob.into(), nonce: 3, amount: 2 }
+			.into_unchecked_extrinsic(),
 	];
 
 	// Import block
diff --git a/substrate/primitives/api/test/tests/runtime_calls.rs b/substrate/primitives/api/test/tests/runtime_calls.rs
index 956a6a25f15..a591bc0b779 100644
--- a/substrate/primitives/api/test/tests/runtime_calls.rs
+++ b/substrate/primitives/api/test/tests/runtime_calls.rs
@@ -60,55 +60,6 @@ fn calling_native_runtime_signature_changed_function() {
 	assert_eq!(runtime_api.function_signature_changed(best_hash).unwrap(), 1);
 }
 
-#[test]
-fn calling_wasm_runtime_signature_changed_old_function() {
-	let client = TestClientBuilder::new()
-		.set_execution_strategy(ExecutionStrategy::AlwaysWasm)
-		.build();
-	let runtime_api = client.runtime_api();
-	let best_hash = client.chain_info().best_hash;
-
-	#[allow(deprecated)]
-	let res = runtime_api.function_signature_changed_before_version_2(best_hash).unwrap();
-	assert_eq!(&res, &[1, 2]);
-}
-
-#[test]
-fn calling_with_both_strategy_and_fail_on_wasm_should_return_error() {
-	let client = TestClientBuilder::new().set_execution_strategy(ExecutionStrategy::Both).build();
-	let runtime_api = client.runtime_api();
-	let best_hash = client.chain_info().best_hash;
-	assert!(runtime_api.fail_on_wasm(best_hash).is_err());
-}
-
-#[test]
-fn calling_with_both_strategy_and_fail_on_native_should_work() {
-	let client = TestClientBuilder::new().set_execution_strategy(ExecutionStrategy::Both).build();
-	let runtime_api = client.runtime_api();
-	let best_hash = client.chain_info().best_hash;
-	assert_eq!(runtime_api.fail_on_native(best_hash).unwrap(), 1);
-}
-
-#[test]
-fn calling_with_native_else_wasm_and_fail_on_wasm_should_work() {
-	let client = TestClientBuilder::new()
-		.set_execution_strategy(ExecutionStrategy::NativeElseWasm)
-		.build();
-	let runtime_api = client.runtime_api();
-	let best_hash = client.chain_info().best_hash;
-	assert_eq!(runtime_api.fail_on_wasm(best_hash).unwrap(), 1);
-}
-
-#[test]
-fn calling_with_native_else_wasm_and_fail_on_native_should_work() {
-	let client = TestClientBuilder::new()
-		.set_execution_strategy(ExecutionStrategy::NativeElseWasm)
-		.build();
-	let runtime_api = client.runtime_api();
-	let best_hash = client.chain_info().best_hash;
-	assert_eq!(runtime_api.fail_on_native(best_hash).unwrap(), 1);
-}
-
 #[test]
 fn use_trie_function() {
 	let client = TestClientBuilder::new()
@@ -162,7 +113,7 @@ fn record_proof_works() {
 		from: AccountKeyring::Alice.into(),
 		to: AccountKeyring::Bob.into(),
 	}
-	.into_signed_tx();
+	.into_unchecked_extrinsic();
 
 	// Build the block and record proof
 	let mut builder = client
diff --git a/substrate/test-utils/runtime/Cargo.toml b/substrate/test-utils/runtime/Cargo.toml
index 68267e91d62..2bcdafed961 100644
--- a/substrate/test-utils/runtime/Cargo.toml
+++ b/substrate/test-utils/runtime/Cargo.toml
@@ -35,6 +35,10 @@ sp-session = { version = "4.0.0-dev", default-features = false, path = "../../pr
 sp-api = { version = "4.0.0-dev", default-features = false, path = "../../primitives/api" }
 sp-runtime = { version = "7.0.0", default-features = false, path = "../../primitives/runtime" }
 pallet-babe = { version = "4.0.0-dev", default-features = false, path = "../../frame/babe" }
+pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../../frame/balances" }
+pallet-root-testing = { version = "1.0.0-dev", default-features = false, path = "../../frame/root-testing" }
+pallet-sudo = { version = "4.0.0-dev", default-features = false, path = "../../frame/sudo" }
+frame-executive = { version = "4.0.0-dev", default-features = false, path = "../../frame/executive" }
 frame-system = { version = "4.0.0-dev", default-features = false, path = "../../frame/system" }
 frame-system-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../../frame/system/rpc/runtime-api" }
 pallet-timestamp = { version = "4.0.0-dev", default-features = false, path = "../../frame/timestamp" }
@@ -45,18 +49,20 @@ trie-db = { version = "0.27.0", default-features = false }
 sc-service = { version = "0.10.0-dev", default-features = false, optional = true, features = ["test-helpers"], path = "../../client/service" }
 sp-state-machine = { version = "0.13.0", default-features = false, path = "../../primitives/state-machine" }
 sp-externalities = { version = "0.13.0", default-features = false, path = "../../primitives/externalities" }
+sp-debug-derive = { path = "../../primitives/debug-derive" }
 
 # 3rd party
-cfg-if = "1.0"
+array-bytes = { version = "6.1", optional = true }
 log = { version = "0.4.17", default-features = false }
 serde = { version = "1.0.136", optional = true, features = ["derive"] }
 
 [dev-dependencies]
+futures = "0.3.21"
 sc-block-builder = { version = "0.10.0-dev", path = "../../client/block-builder" }
 sc-executor = { version = "0.10.0-dev", path = "../../client/executor" }
 sp-consensus = { version = "0.10.0-dev", path = "../../primitives/consensus/common" }
 substrate-test-runtime-client = { version = "2.0.0", path = "./client" }
-futures = "0.3.21"
+sp-tracing = { version = "6.0.0", path = "../../primitives/tracing" }
 
 [build-dependencies]
 substrate-wasm-builder = { version = "5.0.0-dev", path = "../../utils/wasm-builder", optional = true }
@@ -66,7 +72,7 @@ default = [
 	"std",
 ]
 std = [
-	"pallet-beefy-mmr/std",
+	"array-bytes",
 	"sp-application-crypto/std",
 	"sp-consensus-aura/std",
 	"sp-consensus-babe/std",
@@ -93,9 +99,13 @@ std = [
 	"sp-externalities/std",
 	"sp-state-machine/std",
 	"pallet-babe/std",
+	"pallet-beefy-mmr/std",
+	"pallet-timestamp/std",
+	"pallet-balances/std",
+	"pallet-sudo/std",
+	"pallet-root-testing/std",
 	"frame-system-rpc-runtime-api/std",
 	"frame-system/std",
-	"pallet-timestamp/std",
 	"sc-service",
 	"sp-consensus-grandpa/std",
 	"sp-trie/std",
diff --git a/substrate/test-utils/runtime/client/src/block_builder_ext.rs b/substrate/test-utils/runtime/client/src/block_builder_ext.rs
index 3c5e1122f06..a9b0d49f354 100644
--- a/substrate/test-utils/runtime/client/src/block_builder_ext.rs
+++ b/substrate/test-utils/runtime/client/src/block_builder_ext.rs
@@ -21,6 +21,7 @@ use sc_client_api::backend;
 use sp_api::{ApiExt, ProvideRuntimeApi};
 
 use sc_block_builder::BlockBuilderApi;
+use substrate_test_runtime::*;
 
 /// Extension trait for test block builder.
 pub trait BlockBuilderExt {
@@ -29,12 +30,19 @@ pub trait BlockBuilderExt {
 		&mut self,
 		transfer: substrate_test_runtime::Transfer,
 	) -> Result<(), sp_blockchain::Error>;
-	/// Add storage change extrinsic to the block.
+
+	/// Add unsigned storage change extrinsic to the block.
 	fn push_storage_change(
 		&mut self,
 		key: Vec<u8>,
 		value: Option<Vec<u8>>,
 	) -> Result<(), sp_blockchain::Error>;
+
+	/// Adds an extrinsic which pushes DigestItem to header's log
+	fn push_deposit_log_digest_item(
+		&mut self,
+		log: sp_runtime::generic::DigestItem,
+	) -> Result<(), sp_blockchain::Error>;
 }
 
 impl<'a, A, B> BlockBuilderExt
@@ -52,7 +60,7 @@ where
 		&mut self,
 		transfer: substrate_test_runtime::Transfer,
 	) -> Result<(), sp_blockchain::Error> {
-		self.push(transfer.into_signed_tx())
+		self.push(transfer.into_unchecked_extrinsic())
 	}
 
 	fn push_storage_change(
@@ -60,6 +68,13 @@ where
 		key: Vec<u8>,
 		value: Option<Vec<u8>>,
 	) -> Result<(), sp_blockchain::Error> {
-		self.push(substrate_test_runtime::Extrinsic::StorageChange(key, value))
+		self.push(ExtrinsicBuilder::new_storage_change(key, value).build())
+	}
+
+	fn push_deposit_log_digest_item(
+		&mut self,
+		log: sp_runtime::generic::DigestItem,
+	) -> Result<(), sp_blockchain::Error> {
+		self.push(ExtrinsicBuilder::new_deposit_log_digest_item(log).build())
 	}
 }
diff --git a/substrate/test-utils/runtime/client/src/lib.rs b/substrate/test-utils/runtime/client/src/lib.rs
index 5e4b5d6a12d..b2c1e8f47b1 100644
--- a/substrate/test-utils/runtime/client/src/lib.rs
+++ b/substrate/test-utils/runtime/client/src/lib.rs
@@ -30,16 +30,9 @@ pub use substrate_test_runtime as runtime;
 
 pub use self::block_builder_ext::BlockBuilderExt;
 
-use sc_chain_spec::construct_genesis_block;
-use sp_api::StateVersion;
-use sp_core::{
-	sr25519,
-	storage::{ChildInfo, Storage, StorageChild},
-	Pair,
-};
-use sp_runtime::traits::{Block as BlockT, Hash as HashT, Header as HeaderT};
+use sp_core::storage::{ChildInfo, Storage, StorageChild};
 use substrate_test_client::sc_executor::WasmExecutor;
-use substrate_test_runtime::genesismap::{additional_storage_with_genesis, GenesisConfig};
+use substrate_test_runtime::genesismap::GenesisStorageBuilder;
 
 /// A prelude to import in tests.
 pub mod prelude {
@@ -92,28 +85,6 @@ pub struct GenesisParameters {
 }
 
 impl GenesisParameters {
-	fn genesis_config(&self) -> GenesisConfig {
-		GenesisConfig::new(
-			vec![
-				sr25519::Public::from(Sr25519Keyring::Alice).into(),
-				sr25519::Public::from(Sr25519Keyring::Bob).into(),
-				sr25519::Public::from(Sr25519Keyring::Charlie).into(),
-			],
-			(0..16_usize)
-				.into_iter()
-				.map(|i| AccountKeyring::numeric(i).public())
-				.chain(vec![
-					AccountKeyring::Alice.into(),
-					AccountKeyring::Bob.into(),
-					AccountKeyring::Charlie.into(),
-				])
-				.collect(),
-			1000,
-			self.heap_pages_override,
-			self.extra_storage.clone(),
-		)
-	}
-
 	/// Set the wasm code that should be used at genesis.
 	pub fn set_wasm_code(&mut self, code: Vec<u8>) {
 		self.wasm_code = Some(code);
@@ -127,34 +98,11 @@ impl GenesisParameters {
 
 impl GenesisInit for GenesisParameters {
 	fn genesis_storage(&self) -> Storage {
-		use codec::Encode;
-
-		let mut storage = self.genesis_config().genesis_map();
-
-		if let Some(ref code) = self.wasm_code {
-			storage
-				.top
-				.insert(sp_core::storage::well_known_keys::CODE.to_vec(), code.clone());
-		}
-
-		let child_roots = storage.children_default.values().map(|child_content| {
-			let state_root =
-				<<<runtime::Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
-					child_content.data.clone().into_iter().collect(),
-					sp_runtime::StateVersion::V1,
-				);
-			let prefixed_storage_key = child_content.child_info.prefixed_storage_key();
-			(prefixed_storage_key.into_inner(), state_root.encode())
-		});
-		let state_root =
-			<<<runtime::Block as BlockT>::Header as HeaderT>::Hashing as HashT>::trie_root(
-				storage.top.clone().into_iter().chain(child_roots).collect(),
-				sp_runtime::StateVersion::V1,
-			);
-		let block: runtime::Block = construct_genesis_block(state_root, StateVersion::V1);
-		storage.top.extend(additional_storage_with_genesis(&block));
-
-		storage
+		GenesisStorageBuilder::default()
+			.with_heap_pages(self.heap_pages_override)
+			.with_wasm_code(&self.wasm_code)
+			.with_extra_storage(self.extra_storage.clone())
+			.build_storage()
 	}
 }
 
diff --git a/substrate/test-utils/runtime/src/extrinsic.rs b/substrate/test-utils/runtime/src/extrinsic.rs
new file mode 100644
index 00000000000..a6e13226fac
--- /dev/null
+++ b/substrate/test-utils/runtime/src/extrinsic.rs
@@ -0,0 +1,207 @@
+// This file is part of Substrate.
+
+// Copyright (C) Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Provides utils for building the `Extrinsic` instances used with `substrate-test-runtime`.
+
+use crate::{
+	substrate_test_pallet::pallet::Call as PalletCall, AccountId, Balance, BalancesCall,
+	CheckSubstrateCall, Extrinsic, Index, Pair, RuntimeCall, SignedPayload, TransferData,
+};
+use codec::Encode;
+use frame_system::{CheckNonce, CheckWeight};
+use sp_core::crypto::Pair as TraitPair;
+use sp_keyring::AccountKeyring;
+use sp_runtime::{transaction_validity::TransactionPriority, Perbill};
+use sp_std::prelude::*;
+
+/// Transfer used in test substrate pallet. Extrinsic is created and signed using this data.
+#[derive(Clone)]
+pub struct Transfer {
+	/// Transfer sender and signer of created extrinsic
+	pub from: Pair,
+	/// The recipient of the transfer
+	pub to: AccountId,
+	/// Amount of transfer
+	pub amount: Balance,
+	/// Sender's account nonce at which transfer is valid
+	pub nonce: u64,
+}
+
+impl Transfer {
+	/// Convert into a signed unchecked extrinsic.
+	pub fn into_unchecked_extrinsic(self) -> Extrinsic {
+		ExtrinsicBuilder::new_transfer(self).build()
+	}
+}
+
+impl Default for TransferData {
+	fn default() -> Self {
+		Self {
+			from: AccountKeyring::Alice.into(),
+			to: AccountKeyring::Bob.into(),
+			amount: 0,
+			nonce: 0,
+		}
+	}
+}
+
+/// If feasible converts given `Extrinsic` to `TransferData`
+impl TryFrom<&Extrinsic> for TransferData {
+	type Error = ();
+	fn try_from(uxt: &Extrinsic) -> Result<Self, Self::Error> {
+		match uxt {
+			Extrinsic {
+				function: RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest, value }),
+				signature: Some((from, _, (CheckNonce(nonce), ..))),
+			} => Ok(TransferData { from: *from, to: *dest, amount: *value, nonce: *nonce }),
+			Extrinsic {
+				function: RuntimeCall::SubstrateTest(PalletCall::bench_call { transfer }),
+				signature: None,
+			} => Ok(transfer.clone()),
+			_ => Err(()),
+		}
+	}
+}
+
+/// Generates `Extrinsic`
+pub struct ExtrinsicBuilder {
+	function: RuntimeCall,
+	signer: Option<Pair>,
+	nonce: Option<Index>,
+}
+
+impl ExtrinsicBuilder {
+	/// Create builder for given `RuntimeCall`. By default `Extrinsic` will be signed by `Alice`.
+	pub fn new(function: impl Into<RuntimeCall>) -> Self {
+		Self { function: function.into(), signer: Some(AccountKeyring::Alice.pair()), nonce: None }
+	}
+
+	/// Create builder for given `RuntimeCall`. `Extrinsic` will be unsigned.
+	pub fn new_unsigned(function: impl Into<RuntimeCall>) -> Self {
+		Self { function: function.into(), signer: None, nonce: None }
+	}
+
+	/// Create builder for `pallet_call::bench_transfer` from given `TransferData`.
+	pub fn new_bench_call(transfer: TransferData) -> Self {
+		Self::new_unsigned(PalletCall::bench_call { transfer })
+	}
+
+	/// Create builder for given `Transfer`. Transfer `nonce` will be used as `Extrinsic` nonce.
+	/// Transfer `from` will be used as Extrinsic signer.
+	pub fn new_transfer(transfer: Transfer) -> Self {
+		Self {
+			nonce: Some(transfer.nonce),
+			signer: Some(transfer.from.clone()),
+			..Self::new(BalancesCall::transfer_allow_death {
+				dest: transfer.to,
+				value: transfer.amount,
+			})
+		}
+	}
+
+	/// Create builder for `PalletCall::include_data` call using given parameters
+	pub fn new_include_data(data: Vec<u8>) -> Self {
+		Self::new(PalletCall::include_data { data })
+	}
+
+	/// Create builder for `PalletCall::storage_change` call using given parameters. Will
+	/// create unsigned Extrinsic.
+	pub fn new_storage_change(key: Vec<u8>, value: Option<Vec<u8>>) -> Self {
+		Self::new_unsigned(PalletCall::storage_change { key, value })
+	}
+
+	/// Create builder for `PalletCall::offchain_index_set` call using given parameters
+	pub fn new_offchain_index_set(key: Vec<u8>, value: Vec<u8>) -> Self {
+		Self::new(PalletCall::offchain_index_set { key, value })
+	}
+
+	/// Create builder for `PalletCall::offchain_index_clear` call using given parameters
+	pub fn new_offchain_index_clear(key: Vec<u8>) -> Self {
+		Self::new(PalletCall::offchain_index_clear { key })
+	}
+
+	/// Create builder for `PalletCall::indexed_call` call using given parameters
+	pub fn new_indexed_call(data: Vec<u8>) -> Self {
+		Self::new(PalletCall::indexed_call { data })
+	}
+
+	/// Create builder for `PalletCall::new_deposit_log_digest_item` call using given `log`
+	pub fn new_deposit_log_digest_item(log: sp_runtime::generic::DigestItem) -> Self {
+		Self::new_unsigned(PalletCall::deposit_log_digest_item { log })
+	}
+
+	/// Create builder for `PalletCall::Call::new_deposit_log_digest_item`
+	pub fn new_fill_block(ratio: Perbill) -> Self {
+		Self::new(PalletCall::fill_block { ratio })
+	}
+
+	/// Create builder for `PalletCall::call_do_not_propagate` call using given parameters
+	pub fn new_call_do_not_propagate() -> Self {
+		Self::new(PalletCall::call_do_not_propagate {})
+	}
+
+	/// Create builder for `PalletCall::call_with_priority` call using given parameters
+	pub fn new_call_with_priority(priority: TransactionPriority) -> Self {
+		Self::new(PalletCall::call_with_priority { priority })
+	}
+
+	/// Create builder for `PalletCall::read` call using given parameters
+	pub fn new_read(count: u32) -> Self {
+		Self::new_unsigned(PalletCall::read { count })
+	}
+
+	/// Create builder for `PalletCall::read` call using given parameters
+	pub fn new_read_and_panic(count: u32) -> Self {
+		Self::new_unsigned(PalletCall::read_and_panic { count })
+	}
+
+	/// Unsigned `Extrinsic` will be created
+	pub fn unsigned(mut self) -> Self {
+		self.signer = None;
+		self
+	}
+
+	/// Given `nonce` will be set in `Extrinsic`
+	pub fn nonce(mut self, nonce: Index) -> Self {
+		self.nonce = Some(nonce);
+		self
+	}
+
+	/// Extrinsic will be signed by `signer`
+	pub fn signer(mut self, signer: Pair) -> Self {
+		self.signer = Some(signer);
+		self
+	}
+
+	/// Build `Extrinsic` using embedded parameters
+	pub fn build(self) -> Extrinsic {
+		if let Some(signer) = self.signer {
+			let extra = (
+				CheckNonce::from(self.nonce.unwrap_or(0)),
+				CheckWeight::new(),
+				CheckSubstrateCall {},
+			);
+			let raw_payload =
+				SignedPayload::from_raw(self.function.clone(), extra.clone(), ((), (), ()));
+			let signature = raw_payload.using_encoded(|e| signer.sign(e));
+
+			Extrinsic::new_signed(self.function, signer.public(), signature, extra)
+		} else {
+			Extrinsic::new_unsigned(self.function)
+		}
+	}
+}
diff --git a/substrate/test-utils/runtime/src/genesismap.rs b/substrate/test-utils/runtime/src/genesismap.rs
index 9e00dd29999..62ce26c55e3 100644
--- a/substrate/test-utils/runtime/src/genesismap.rs
+++ b/substrate/test-utils/runtime/src/genesismap.rs
@@ -17,75 +17,119 @@
 
 //! Tool for creating the genesis block.
 
-use super::{system, wasm_binary_unwrap, AccountId, AuthorityId, Runtime};
-use codec::{Encode, Joiner, KeyedVec};
-use frame_support::traits::GenesisBuild;
+use super::{
+	currency, substrate_test_pallet, wasm_binary_unwrap, AccountId, AuthorityId, Balance,
+	GenesisConfig,
+};
+use codec::Encode;
 use sc_service::construct_genesis_block;
 use sp_core::{
-	map,
+	sr25519,
 	storage::{well_known_keys, StateVersion, Storage},
+	Pair,
+};
+use sp_keyring::{AccountKeyring, Sr25519Keyring};
+use sp_runtime::{
+	traits::{Block as BlockT, Hash as HashT, Header as HeaderT},
+	BuildStorage,
 };
-use sp_io::hashing::{blake2_256, twox_128};
-use sp_runtime::traits::{Block as BlockT, Hash as HashT, Header as HeaderT};
-use std::collections::BTreeMap;
 
-/// Configuration of a general Substrate test genesis block.
-pub struct GenesisConfig {
+/// Builder for generating storage from substrate-test-runtime genesis config. Default storage can
+/// be extended with additional key-value pairs.
+pub struct GenesisStorageBuilder {
 	authorities: Vec<AuthorityId>,
 	balances: Vec<(AccountId, u64)>,
 	heap_pages_override: Option<u64>,
 	/// Additional storage key pairs that will be added to the genesis map.
 	extra_storage: Storage,
+	wasm_code: Option<Vec<u8>>,
+}
+
+impl Default for GenesisStorageBuilder {
+	/// Creates a builder with default settings for `substrate_test_runtime`.
+	fn default() -> Self {
+		Self::new(
+			vec![
+				sr25519::Public::from(Sr25519Keyring::Alice).into(),
+				sr25519::Public::from(Sr25519Keyring::Bob).into(),
+				sr25519::Public::from(Sr25519Keyring::Charlie).into(),
+			],
+			(0..16_usize)
+				.into_iter()
+				.map(|i| AccountKeyring::numeric(i).public())
+				.chain(vec![
+					AccountKeyring::Alice.into(),
+					AccountKeyring::Bob.into(),
+					AccountKeyring::Charlie.into(),
+				])
+				.collect(),
+			1000 * currency::DOLLARS,
+		)
+	}
 }
 
-impl GenesisConfig {
+impl GenesisStorageBuilder {
+	/// Creates a storage builder for genesis config. `substrage test runtime` `GenesisConfig` is
+	/// initialized with provided `authorities`, `endowed_accounts` with given balance. Key-pairs
+	/// from `extra_storage` will be injected into built storage. `HEAP_PAGES` key and value will
+	/// also be placed into storage.
 	pub fn new(
 		authorities: Vec<AuthorityId>,
 		endowed_accounts: Vec<AccountId>,
-		balance: u64,
-		heap_pages_override: Option<u64>,
-		extra_storage: Storage,
+		balance: Balance,
 	) -> Self {
-		GenesisConfig {
+		GenesisStorageBuilder {
 			authorities,
 			balances: endowed_accounts.into_iter().map(|a| (a, balance)).collect(),
-			heap_pages_override,
-			extra_storage,
+			heap_pages_override: None,
+			extra_storage: Default::default(),
+			wasm_code: None,
 		}
 	}
 
-	pub fn genesis_map(&self) -> Storage {
-		let wasm_runtime = wasm_binary_unwrap().to_vec();
-		let mut map: BTreeMap<Vec<u8>, Vec<u8>> = self
-			.balances
-			.iter()
-			.map(|&(ref account, balance)| {
-				(account.to_keyed_vec(b"balance:"), vec![].and(&balance))
-			})
-			.map(|(k, v)| (blake2_256(&k[..])[..].to_vec(), v.to_vec()))
-			.chain(
-				vec![
-					(well_known_keys::CODE.into(), wasm_runtime),
-					(
-						well_known_keys::HEAP_PAGES.into(),
-						vec![].and(&(self.heap_pages_override.unwrap_or(16_u64))),
-					),
-				]
-				.into_iter(),
-			)
-			.collect();
-		map.insert(twox_128(&b"sys:auth"[..])[..].to_vec(), self.authorities.encode());
-		// Add the extra storage entries.
-		map.extend(self.extra_storage.top.clone().into_iter());
-
-		// Assimilate the system genesis config.
-		let mut storage =
-			Storage { top: map, children_default: self.extra_storage.children_default.clone() };
-		<system::GenesisConfig as GenesisBuild<Runtime>>::assimilate_storage(
-			&system::GenesisConfig { authorities: self.authorities.clone() },
-			&mut storage,
-		)
-		.expect("Adding `system::GensisConfig` to the genesis");
+	/// Override default wasm code to be placed into GenesisConfig.
+	pub fn with_wasm_code(mut self, wasm_code: &Option<Vec<u8>>) -> Self {
+		self.wasm_code = wasm_code.clone();
+		self
+	}
+
+	pub fn with_heap_pages(mut self, heap_pages_override: Option<u64>) -> Self {
+		self.heap_pages_override = heap_pages_override;
+		self
+	}
+
+	pub fn with_extra_storage(mut self, storage: Storage) -> Self {
+		self.extra_storage = storage;
+		self
+	}
+
+	/// Builds the `GenesisConfig` and returns its storage.
+	pub fn build_storage(&mut self) -> Storage {
+		let genesis_config = GenesisConfig {
+			system: frame_system::GenesisConfig {
+				code: self.wasm_code.clone().unwrap_or(wasm_binary_unwrap().to_vec()),
+			},
+			babe: pallet_babe::GenesisConfig {
+				authorities: self.authorities.clone().into_iter().map(|x| (x, 1)).collect(),
+				epoch_config: Some(crate::TEST_RUNTIME_BABE_EPOCH_CONFIGURATION),
+			},
+			substrate_test: substrate_test_pallet::GenesisConfig {
+				authorities: self.authorities.clone(),
+			},
+			balances: pallet_balances::GenesisConfig { balances: self.balances.clone() },
+		};
+
+		let mut storage = genesis_config
+			.build_storage()
+			.expect("Build storage from substrate-test-runtime GenesisConfig");
+
+		storage.top.insert(
+			well_known_keys::HEAP_PAGES.into(),
+			self.heap_pages_override.unwrap_or(16_u64).encode(),
+		);
+
+		storage.top.extend(self.extra_storage.top.clone());
+		storage.children_default.extend(self.extra_storage.children_default.clone());
 
 		storage
 	}
@@ -108,12 +152,6 @@ pub fn insert_genesis_block(storage: &mut Storage) -> sp_core::hash::H256 {
 	);
 	let block: crate::Block = construct_genesis_block(state_root, StateVersion::V1);
 	let genesis_hash = block.header.hash();
-	storage.top.extend(additional_storage_with_genesis(&block));
-	genesis_hash
-}
 
-pub fn additional_storage_with_genesis(genesis_block: &crate::Block) -> BTreeMap<Vec<u8>, Vec<u8>> {
-	map![
-		twox_128(&b"latest"[..]).to_vec() => genesis_block.hash().as_fixed_bytes().to_vec()
-	]
+	genesis_hash
 }
diff --git a/substrate/test-utils/runtime/src/lib.rs b/substrate/test-utils/runtime/src/lib.rs
index b5600843c27..00db6a745b3 100644
--- a/substrate/test-utils/runtime/src/lib.rs
+++ b/substrate/test-utils/runtime/src/lib.rs
@@ -19,13 +19,29 @@
 
 #![cfg_attr(not(feature = "std"), no_std)]
 
+#[cfg(feature = "std")]
+pub mod extrinsic;
 #[cfg(feature = "std")]
 pub mod genesismap;
-pub mod system;
+pub mod substrate_test_pallet;
 
-use codec::{Decode, Encode, Error, Input, MaxEncodedLen};
+use codec::{Decode, Encode};
+use frame_support::{
+	construct_runtime,
+	dispatch::DispatchClass,
+	parameter_types,
+	traits::{ConstU32, ConstU64},
+	weights::{
+		constants::{BlockExecutionWeight, ExtrinsicBaseWeight, WEIGHT_REF_TIME_PER_SECOND},
+		Weight,
+	},
+};
+use frame_system::{
+	limits::{BlockLength, BlockWeights},
+	CheckNonce, CheckWeight,
+};
 use scale_info::TypeInfo;
-use sp_std::{marker::PhantomData, prelude::*};
+use sp_std::prelude::*;
 
 use sp_application_crypto::{ecdsa, ed25519, sr25519, RuntimeAppPublic};
 use sp_core::{OpaqueMetadata, RuntimeDebug};
@@ -35,29 +51,13 @@ use sp_trie::{
 };
 use trie_db::{Trie, TrieMut};
 
-use cfg_if::cfg_if;
-use frame_support::{
-	dispatch::RawOrigin,
-	parameter_types,
-	traits::{CallerTrait, ConstU32, ConstU64, CrateVersion},
-	weights::{RuntimeDbWeight, Weight},
-};
-use frame_system::limits::{BlockLength, BlockWeights};
 use sp_api::{decl_runtime_apis, impl_runtime_apis};
 pub use sp_core::hash::H256;
 use sp_inherents::{CheckInherentsResult, InherentData};
-#[cfg(feature = "std")]
-use sp_runtime::traits::NumberFor;
 use sp_runtime::{
 	create_runtime_str, impl_opaque_keys,
-	traits::{
-		BlakeTwo256, BlindCheckable, Block as BlockT, Extrinsic as ExtrinsicT, GetNodeBlockType,
-		GetRuntimeBlockType, IdentityLookup, Verify,
-	},
-	transaction_validity::{
-		InvalidTransaction, TransactionSource, TransactionValidity, TransactionValidityError,
-		ValidTransaction,
-	},
+	traits::{BlakeTwo256, Block as BlockT, DispatchInfoOf, NumberFor, Verify},
+	transaction_validity::{TransactionSource, TransactionValidity, TransactionValidityError},
 	ApplyExtrinsicResult, Perbill,
 };
 #[cfg(any(feature = "std", test))]
@@ -65,10 +65,17 @@ use sp_version::NativeVersion;
 use sp_version::RuntimeVersion;
 
 // Ensure Babe and Aura use the same crypto to simplify things a bit.
-pub use sp_consensus_babe::{AllowedSlots, AuthorityId, Slot};
+pub use sp_consensus_babe::{AllowedSlots, AuthorityId, BabeEpochConfiguration, Slot};
+
+pub use pallet_balances::Call as BalancesCall;
 
 pub type AuraId = sp_consensus_aura::sr25519::AuthorityId;
 
+#[cfg(feature = "std")]
+pub use extrinsic::{ExtrinsicBuilder, Transfer};
+
+const LOG_TARGET: &str = "substrate-test-runtime";
+
 // Include the WASM binary
 #[cfg(feature = "std")]
 include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
@@ -119,164 +126,31 @@ pub fn native_version() -> NativeVersion {
 	NativeVersion { runtime_version: VERSION, can_author_with: Default::default() }
 }
 
-/// Calls in transactions.
+/// Transfer data extracted from Extrinsic containing `Balances::transfer_allow_death`.
 #[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)]
-pub struct Transfer {
+pub struct TransferData {
 	pub from: AccountId,
 	pub to: AccountId,
-	pub amount: u64,
-	pub nonce: u64,
-}
-
-impl Transfer {
-	/// Convert into a signed extrinsic.
-	#[cfg(feature = "std")]
-	pub fn into_signed_tx(self) -> Extrinsic {
-		let signature = sp_keyring::AccountKeyring::from_public(&self.from)
-			.expect("Creates keyring from public key.")
-			.sign(&self.encode());
-		Extrinsic::Transfer { transfer: self, signature, exhaust_resources_when_not_first: false }
-	}
-
-	/// Convert into a signed extrinsic, which will only end up included in the block
-	/// if it's the first transaction. Otherwise it will cause `ResourceExhaustion` error
-	/// which should be considered as block being full.
-	#[cfg(feature = "std")]
-	pub fn into_resources_exhausting_tx(self) -> Extrinsic {
-		let signature = sp_keyring::AccountKeyring::from_public(&self.from)
-			.expect("Creates keyring from public key.")
-			.sign(&self.encode());
-		Extrinsic::Transfer { transfer: self, signature, exhaust_resources_when_not_first: true }
-	}
-}
-
-/// Extrinsic for test-runtime.
-#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)]
-pub enum Extrinsic {
-	AuthoritiesChange(Vec<AuthorityId>),
-	Transfer {
-		transfer: Transfer,
-		signature: AccountSignature,
-		exhaust_resources_when_not_first: bool,
-	},
-	IncludeData(Vec<u8>),
-	StorageChange(Vec<u8>, Option<Vec<u8>>),
-	OffchainIndexSet(Vec<u8>, Vec<u8>),
-	OffchainIndexClear(Vec<u8>),
-	Store(Vec<u8>),
-	/// Read X times from the state some data and then panic!
-	///
-	/// Returns `Ok` if it didn't read anything.
-	ReadAndPanic(u32),
-	/// Read X times from the state some data.
-	///
-	/// Panics if it can not read `X` times.
-	Read(u32),
+	pub amount: Balance,
+	pub nonce: Index,
 }
 
+/// The address format for describing accounts.
+pub type Address = sp_core::sr25519::Public;
+pub type Signature = sr25519::Signature;
 #[cfg(feature = "std")]
-impl serde::Serialize for Extrinsic {
-	fn serialize<S>(&self, seq: S) -> Result<S::Ok, S::Error>
-	where
-		S: serde::Serializer,
-	{
-		self.using_encoded(|bytes| seq.serialize_bytes(bytes))
-	}
-}
+pub type Pair = sp_core::sr25519::Pair;
 
-// rustc can't deduce this trait bound https://github.com/rust-lang/rust/issues/48214
-#[cfg(feature = "std")]
-impl<'a> serde::Deserialize<'a> for Extrinsic {
-	fn deserialize<D>(de: D) -> Result<Self, D::Error>
-	where
-		D: serde::Deserializer<'a>,
-	{
-		let r = sp_core::bytes::deserialize(de)?;
-		Decode::decode(&mut &r[..])
-			.map_err(|e| serde::de::Error::custom(format!("Decode error: {}", e)))
-	}
-}
+/// The SignedExtension to the basic transaction logic.
+pub type SignedExtra = (CheckNonce<Runtime>, CheckWeight<Runtime>, CheckSubstrateCall);
+/// The payload being signed in transactions.
+pub type SignedPayload = sp_runtime::generic::SignedPayload<RuntimeCall, SignedExtra>;
+/// Unchecked extrinsic type as expected by this runtime.
+pub type Extrinsic =
+	sp_runtime::generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, SignedExtra>;
 
-impl BlindCheckable for Extrinsic {
-	type Checked = Self;
-
-	fn check(self) -> Result<Self, TransactionValidityError> {
-		match self {
-			Extrinsic::AuthoritiesChange(new_auth) => Ok(Extrinsic::AuthoritiesChange(new_auth)),
-			Extrinsic::Transfer { transfer, signature, exhaust_resources_when_not_first } =>
-				if sp_runtime::verify_encoded_lazy(&signature, &transfer, &transfer.from) {
-					Ok(Extrinsic::Transfer {
-						transfer,
-						signature,
-						exhaust_resources_when_not_first,
-					})
-				} else {
-					Err(InvalidTransaction::BadProof.into())
-				},
-			Extrinsic::IncludeData(v) => Ok(Extrinsic::IncludeData(v)),
-			Extrinsic::StorageChange(key, value) => Ok(Extrinsic::StorageChange(key, value)),
-			Extrinsic::OffchainIndexSet(key, value) => Ok(Extrinsic::OffchainIndexSet(key, value)),
-			Extrinsic::OffchainIndexClear(key) => Ok(Extrinsic::OffchainIndexClear(key)),
-			Extrinsic::Store(data) => Ok(Extrinsic::Store(data)),
-			Extrinsic::ReadAndPanic(i) => Ok(Extrinsic::ReadAndPanic(i)),
-			Extrinsic::Read(i) => Ok(Extrinsic::Read(i)),
-		}
-	}
-}
-
-impl ExtrinsicT for Extrinsic {
-	type Call = Extrinsic;
-	type SignaturePayload = ();
-
-	fn is_signed(&self) -> Option<bool> {
-		if let Extrinsic::IncludeData(_) = *self {
-			Some(false)
-		} else {
-			Some(true)
-		}
-	}
-
-	fn new(call: Self::Call, _signature_payload: Option<Self::SignaturePayload>) -> Option<Self> {
-		Some(call)
-	}
-}
-
-impl sp_runtime::traits::Dispatchable for Extrinsic {
-	type RuntimeOrigin = RuntimeOrigin;
-	type Config = ();
-	type Info = ();
-	type PostInfo = ();
-	fn dispatch(
-		self,
-		_origin: Self::RuntimeOrigin,
-	) -> sp_runtime::DispatchResultWithInfo<Self::PostInfo> {
-		panic!("This implementation should not be used for actual dispatch.");
-	}
-}
-
-impl Extrinsic {
-	/// Convert `&self` into `&Transfer`.
-	///
-	/// Panics if this is no `Transfer` extrinsic.
-	pub fn transfer(&self) -> &Transfer {
-		self.try_transfer().expect("cannot convert to transfer ref")
-	}
-
-	/// Try to convert `&self` into `&Transfer`.
-	///
-	/// Returns `None` if this is no `Transfer` extrinsic.
-	pub fn try_transfer(&self) -> Option<&Transfer> {
-		match self {
-			Extrinsic::Transfer { ref transfer, .. } => Some(transfer),
-			_ => None,
-		}
-	}
-}
-
-/// The signature type used by accounts/transactions.
-pub type AccountSignature = sr25519::Signature;
 /// An identifier for an account on this system.
-pub type AccountId = <AccountSignature as Verify>::Signer;
+pub type AccountId = <Signature as Verify>::Signer;
 /// A simple hash type for all our hashing.
 pub type Hash = H256;
 /// The hashing algorithm used.
@@ -293,351 +167,200 @@ pub type Digest = sp_runtime::generic::Digest;
 pub type Block = sp_runtime::generic::Block<Header, Extrinsic>;
 /// A test block's header.
 pub type Header = sp_runtime::generic::Header<BlockNumber, Hashing>;
-
-/// Run whatever tests we have.
-pub fn run_tests(mut input: &[u8]) -> Vec<u8> {
-	use sp_runtime::print;
-
-	print("run_tests...");
-	let block = Block::decode(&mut input).unwrap();
-	print("deserialized block.");
-	let stxs = block.extrinsics.iter().map(Encode::encode);
-	print("reserialized transactions.");
-	[stxs.count() as u8].encode()
-}
-
-/// A type that can not be decoded.
-#[derive(PartialEq, TypeInfo)]
-pub struct DecodeFails<B: BlockT> {
-	_phantom: PhantomData<B>,
-}
-
-impl<B: BlockT> Encode for DecodeFails<B> {
-	fn encode(&self) -> Vec<u8> {
-		Vec::new()
-	}
-}
-
-impl<B: BlockT> codec::EncodeLike for DecodeFails<B> {}
-
-impl<B: BlockT> Default for DecodeFails<B> {
-	/// Create a default instance.
-	fn default() -> DecodeFails<B> {
-		DecodeFails { _phantom: Default::default() }
-	}
-}
-
-impl<B: BlockT> Decode for DecodeFails<B> {
-	fn decode<I: Input>(_: &mut I) -> Result<Self, Error> {
-		Err("DecodeFails always fails".into())
-	}
-}
-
-cfg_if! {
-	if #[cfg(feature = "std")] {
-		decl_runtime_apis! {
-			#[api_version(2)]
-			pub trait TestAPI {
-				/// Return the balance of the given account id.
-				fn balance_of(id: AccountId) -> u64;
-				/// A benchmark function that adds one to the given value and returns the result.
-				fn benchmark_add_one(val: &u64) -> u64;
-				/// A benchmark function that adds one to each value in the given vector and returns the
-				/// result.
-				fn benchmark_vector_add_one(vec: &Vec<u64>) -> Vec<u64>;
-				/// A function that always fails to convert a parameter between runtime and node.
-				fn fail_convert_parameter(param: DecodeFails<Block>);
-				/// A function that always fails to convert its return value between runtime and node.
-				fn fail_convert_return_value() -> DecodeFails<Block>;
-				/// A function for that the signature changed in version `2`.
-				#[changed_in(2)]
-				fn function_signature_changed() -> Vec<u64>;
-				/// The new signature.
-				fn function_signature_changed() -> u64;
-				fn fail_on_native() -> u64;
-				fn fail_on_wasm() -> u64;
-				/// trie no_std testing
-				fn use_trie() -> u64;
-				fn benchmark_indirect_call() -> u64;
-				fn benchmark_direct_call() -> u64;
-				fn vec_with_capacity(size: u32) -> Vec<u8>;
-				/// Returns the initialized block number.
-				fn get_block_number() -> u64;
-				/// Takes and returns the initialized block number.
-				fn take_block_number() -> Option<u64>;
-				/// Test that `ed25519` crypto works in the runtime.
-				///
-				/// Returns the signature generated for the message `ed25519` and the public key.
-				fn test_ed25519_crypto() -> (ed25519::AppSignature, ed25519::AppPublic);
-				/// Test that `sr25519` crypto works in the runtime.
-				///
-				/// Returns the signature generated for the message `sr25519`.
-				fn test_sr25519_crypto() -> (sr25519::AppSignature, sr25519::AppPublic);
-				/// Test that `ecdsa` crypto works in the runtime.
-				///
-				/// Returns the signature generated for the message `ecdsa`.
-				fn test_ecdsa_crypto() -> (ecdsa::AppSignature, ecdsa::AppPublic);
-				/// Run various tests against storage.
-				fn test_storage();
-				/// Check a witness.
-				fn test_witness(proof: StorageProof, root: crate::Hash);
-				/// Test that ensures that we can call a function that takes multiple
-				/// arguments.
-				fn test_multiple_arguments(data: Vec<u8>, other: Vec<u8>, num: u32);
-				/// Traces log "Hey I'm runtime."
-				fn do_trace_log();
-				/// Verify the given signature, public & message bundle.
-				fn verify_ed25519(sig: ed25519::Signature, public: ed25519::Public, message: Vec<u8>) -> bool;
-			}
-		}
-	} else {
-		decl_runtime_apis! {
-			pub trait TestAPI {
-				/// Return the balance of the given account id.
-				fn balance_of(id: AccountId) -> u64;
-				/// A benchmark function that adds one to the given value and returns the result.
-				fn benchmark_add_one(val: &u64) -> u64;
-				/// A benchmark function that adds one to each value in the given vector and returns the
-				/// result.
-				fn benchmark_vector_add_one(vec: &Vec<u64>) -> Vec<u64>;
-				/// A function that always fails to convert a parameter between runtime and node.
-				fn fail_convert_parameter(param: DecodeFails<Block>);
-				/// A function that always fails to convert its return value between runtime and node.
-				fn fail_convert_return_value() -> DecodeFails<Block>;
-				/// In wasm we just emulate the old behavior.
-				fn function_signature_changed() -> Vec<u64>;
-				fn fail_on_native() -> u64;
-				fn fail_on_wasm() -> u64;
-				/// trie no_std testing
-				fn use_trie() -> u64;
-				fn benchmark_indirect_call() -> u64;
-				fn benchmark_direct_call() -> u64;
-				fn vec_with_capacity(size: u32) -> Vec<u8>;
-				/// Returns the initialized block number.
-				fn get_block_number() -> u64;
-				/// Takes and returns the initialized block number.
-				fn take_block_number() -> Option<u64>;
-				/// Test that `ed25519` crypto works in the runtime.
-				///
-				/// Returns the signature generated for the message `ed25519` and the public key.
-				fn test_ed25519_crypto() -> (ed25519::AppSignature, ed25519::AppPublic);
-				/// Test that `sr25519` crypto works in the runtime.
-				///
-				/// Returns the signature generated for the message `sr25519`.
-				fn test_sr25519_crypto() -> (sr25519::AppSignature, sr25519::AppPublic);
-				/// Test that `ecdsa` crypto works in the runtime.
-				///
-				/// Returns the signature generated for the message `ecdsa`.
-				fn test_ecdsa_crypto() -> (ecdsa::AppSignature, ecdsa::AppPublic);
-				/// Run various tests against storage.
-				fn test_storage();
-				/// Check a witness.
-				fn test_witness(proof: StorageProof, root: crate::Hash);
-				/// Test that ensures that we can call a function that takes multiple
-				/// arguments.
-				fn test_multiple_arguments(data: Vec<u8>, other: Vec<u8>, num: u32);
-				/// Traces log "Hey I'm runtime."
-				fn do_trace_log();
-				/// Verify the given signature, public & message bundle.
-				fn verify_ed25519(sig: ed25519::Signature, public: ed25519::Public, message: Vec<u8>) -> bool;
-			}
-		}
-	}
-}
-
-#[derive(Clone, Eq, PartialEq, TypeInfo)]
-pub struct Runtime;
-impl GetNodeBlockType for Runtime {
-	type NodeBlock = Block;
-}
-
-impl GetRuntimeBlockType for Runtime {
-	type RuntimeBlock = Block;
-}
-
-#[derive(Clone, RuntimeDebug, Encode, Decode, PartialEq, Eq, TypeInfo, MaxEncodedLen)]
-pub struct RuntimeOrigin;
-
-impl From<RawOrigin<<Runtime as frame_system::Config>::AccountId>> for RuntimeOrigin {
-	fn from(_: RawOrigin<<Runtime as frame_system::Config>::AccountId>) -> Self {
-		unimplemented!("Not required in tests!")
+/// Balance of an account.
+pub type Balance = u64;
+
+decl_runtime_apis! {
+	#[api_version(2)]
+	pub trait TestAPI {
+		/// Return the balance of the given account id.
+		fn balance_of(id: AccountId) -> u64;
+		/// A benchmark function that adds one to the given value and returns the result.
+		fn benchmark_add_one(val: &u64) -> u64;
+		/// A benchmark function that adds one to each value in the given vector and returns the
+		/// result.
+		fn benchmark_vector_add_one(vec: &Vec<u64>) -> Vec<u64>;
+		/// A function for that the signature changed in version `2`.
+		#[changed_in(2)]
+		fn function_signature_changed() -> Vec<u64>;
+		/// The new signature.
+		fn function_signature_changed() -> u64;
+		/// trie no_std testing
+		fn use_trie() -> u64;
+		/// Calls function in the loop using never-inlined function pointer
+		fn benchmark_indirect_call() -> u64;
+		/// Calls function in the loop
+		fn benchmark_direct_call() -> u64;
+		/// Allocates vector with given capacity.
+		fn vec_with_capacity(size: u32) -> Vec<u8>;
+		/// Returns the initialized block number.
+		fn get_block_number() -> u64;
+
+		/// Test that `ed25519` crypto works in the runtime.
+		///
+		/// Returns the signature generated for the message `ed25519` and the public key.
+		fn test_ed25519_crypto() -> (ed25519::AppSignature, ed25519::AppPublic);
+		/// Test that `sr25519` crypto works in the runtime.
+		///
+		/// Returns the signature generated for the message `sr25519`.
+		fn test_sr25519_crypto() -> (sr25519::AppSignature, sr25519::AppPublic);
+		/// Test that `ecdsa` crypto works in the runtime.
+		///
+		/// Returns the signature generated for the message `ecdsa`.
+		fn test_ecdsa_crypto() -> (ecdsa::AppSignature, ecdsa::AppPublic);
+		/// Run various tests against storage.
+		fn test_storage();
+		/// Check a witness.
+		fn test_witness(proof: StorageProof, root: crate::Hash);
+		/// Test that ensures that we can call a function that takes multiple
+		/// arguments.
+		fn test_multiple_arguments(data: Vec<u8>, other: Vec<u8>, num: u32);
+		/// Traces log "Hey I'm runtime."
+		fn do_trace_log();
+		/// Verify the given signature, public & message bundle.
+		fn verify_ed25519(sig: ed25519::Signature, public: ed25519::Public, message: Vec<u8>) -> bool;
 	}
 }
 
-impl CallerTrait<<Runtime as frame_system::Config>::AccountId> for RuntimeOrigin {
-	fn into_system(self) -> Option<RawOrigin<<Runtime as frame_system::Config>::AccountId>> {
-		unimplemented!("Not required in tests!")
-	}
+pub type Executive = frame_executive::Executive<
+	Runtime,
+	Block,
+	frame_system::ChainContext<Runtime>,
+	Runtime,
+	AllPalletsWithSystem,
+>;
 
-	fn as_system_ref(&self) -> Option<&RawOrigin<<Runtime as frame_system::Config>::AccountId>> {
-		unimplemented!("Not required in tests!")
-	}
-}
+#[derive(Copy, Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)]
+pub struct CheckSubstrateCall;
 
-impl From<RuntimeOrigin> for Result<frame_system::Origin<Runtime>, RuntimeOrigin> {
-	fn from(_origin: RuntimeOrigin) -> Result<frame_system::Origin<Runtime>, RuntimeOrigin> {
-		unimplemented!("Not required in tests!")
+impl sp_runtime::traits::Printable for CheckSubstrateCall {
+	fn print(&self) {
+		"CheckSubstrateCall".print()
 	}
 }
 
-impl frame_support::traits::OriginTrait for RuntimeOrigin {
-	type Call = <Runtime as frame_system::Config>::RuntimeCall;
-	type PalletsOrigin = RuntimeOrigin;
-	type AccountId = <Runtime as frame_system::Config>::AccountId;
-
-	fn add_filter(&mut self, _filter: impl Fn(&Self::Call) -> bool + 'static) {
-		unimplemented!("Not required in tests!")
-	}
-
-	fn reset_filter(&mut self) {
-		unimplemented!("Not required in tests!")
-	}
-
-	fn set_caller_from(&mut self, _other: impl Into<Self>) {
-		unimplemented!("Not required in tests!")
-	}
-
-	fn filter_call(&self, _call: &Self::Call) -> bool {
-		unimplemented!("Not required in tests!")
-	}
-
-	fn caller(&self) -> &Self::PalletsOrigin {
-		unimplemented!("Not required in tests!")
-	}
+impl sp_runtime::traits::Dispatchable for CheckSubstrateCall {
+	type RuntimeOrigin = CheckSubstrateCall;
+	type Config = CheckSubstrateCall;
+	type Info = CheckSubstrateCall;
+	type PostInfo = CheckSubstrateCall;
 
-	fn into_caller(self) -> Self::PalletsOrigin {
-		unimplemented!("Not required in tests!")
-	}
-
-	fn try_with_caller<R>(
+	fn dispatch(
 		self,
-		_f: impl FnOnce(Self::PalletsOrigin) -> Result<R, Self::PalletsOrigin>,
-	) -> Result<R, Self> {
-		unimplemented!("Not required in tests!")
-	}
-
-	fn none() -> Self {
-		unimplemented!("Not required in tests!")
-	}
-	fn root() -> Self {
-		unimplemented!("Not required in tests!")
-	}
-	fn signed(_by: Self::AccountId) -> Self {
-		unimplemented!("Not required in tests!")
-	}
-	fn as_signed(self) -> Option<Self::AccountId> {
-		unimplemented!("Not required in tests!")
-	}
-	fn as_system_ref(&self) -> Option<&RawOrigin<Self::AccountId>> {
-		unimplemented!("Not required in tests!")
+		_origin: Self::RuntimeOrigin,
+	) -> sp_runtime::DispatchResultWithInfo<Self::PostInfo> {
+		panic!("This implementation should not be used for actual dispatch.");
 	}
 }
 
-#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo)]
-pub struct RuntimeEvent;
-
-impl From<frame_system::Event<Runtime>> for RuntimeEvent {
-	fn from(_evt: frame_system::Event<Runtime>) -> Self {
-		unimplemented!("Not required in tests!")
+impl sp_runtime::traits::SignedExtension for CheckSubstrateCall {
+	type AccountId = AccountId;
+	type Call = RuntimeCall;
+	type AdditionalSigned = ();
+	type Pre = ();
+	const IDENTIFIER: &'static str = "CheckSubstrateCall";
+
+	fn additional_signed(
+		&self,
+	) -> sp_std::result::Result<Self::AdditionalSigned, TransactionValidityError> {
+		Ok(())
 	}
-}
 
-impl frame_support::traits::PalletInfo for Runtime {
-	fn index<P: 'static>() -> Option<usize> {
-		let type_id = sp_std::any::TypeId::of::<P>();
-		if type_id == sp_std::any::TypeId::of::<system::Pallet<Runtime>>() {
-			return Some(0)
-		}
-		if type_id == sp_std::any::TypeId::of::<pallet_timestamp::Pallet<Runtime>>() {
-			return Some(1)
+	fn validate(
+		&self,
+		_who: &Self::AccountId,
+		call: &Self::Call,
+		_info: &DispatchInfoOf<Self::Call>,
+		_len: usize,
+	) -> TransactionValidity {
+		log::trace!(target: LOG_TARGET, "validate");
+		match call {
+			RuntimeCall::SubstrateTest(ref substrate_test_call) =>
+				substrate_test_pallet::validate_runtime_call(substrate_test_call),
+			_ => Ok(Default::default()),
 		}
-		if type_id == sp_std::any::TypeId::of::<pallet_babe::Pallet<Runtime>>() {
-			return Some(2)
-		}
-
-		None
 	}
-	fn name<P: 'static>() -> Option<&'static str> {
-		let type_id = sp_std::any::TypeId::of::<P>();
-		if type_id == sp_std::any::TypeId::of::<system::Pallet<Runtime>>() {
-			return Some("System")
-		}
-		if type_id == sp_std::any::TypeId::of::<pallet_timestamp::Pallet<Runtime>>() {
-			return Some("Timestamp")
-		}
-		if type_id == sp_std::any::TypeId::of::<pallet_babe::Pallet<Runtime>>() {
-			return Some("Babe")
-		}
-
-		None
-	}
-	fn module_name<P: 'static>() -> Option<&'static str> {
-		let type_id = sp_std::any::TypeId::of::<P>();
-		if type_id == sp_std::any::TypeId::of::<system::Pallet<Runtime>>() {
-			return Some("system")
-		}
-		if type_id == sp_std::any::TypeId::of::<pallet_timestamp::Pallet<Runtime>>() {
-			return Some("pallet_timestamp")
-		}
-		if type_id == sp_std::any::TypeId::of::<pallet_babe::Pallet<Runtime>>() {
-			return Some("pallet_babe")
-		}
 
-		None
+	fn pre_dispatch(
+		self,
+		who: &Self::AccountId,
+		call: &Self::Call,
+		info: &sp_runtime::traits::DispatchInfoOf<Self::Call>,
+		len: usize,
+	) -> Result<Self::Pre, TransactionValidityError> {
+		self.validate(who, call, info, len).map(drop)
 	}
-	fn crate_version<P: 'static>() -> Option<CrateVersion> {
-		use frame_support::traits::PalletInfoAccess as _;
-		let type_id = sp_std::any::TypeId::of::<P>();
-		if type_id == sp_std::any::TypeId::of::<system::Pallet<Runtime>>() {
-			return Some(system::Pallet::<Runtime>::crate_version())
-		}
-		if type_id == sp_std::any::TypeId::of::<pallet_timestamp::Pallet<Runtime>>() {
-			return Some(pallet_timestamp::Pallet::<Runtime>::crate_version())
-		}
-		if type_id == sp_std::any::TypeId::of::<pallet_babe::Pallet<Runtime>>() {
-			return Some(pallet_babe::Pallet::<Runtime>::crate_version())
-		}
+}
 
-		None
+construct_runtime!(
+	pub enum Runtime where
+		Block = Block,
+		NodeBlock = Block,
+		UncheckedExtrinsic = Extrinsic
+	{
+		System: frame_system,
+		Babe: pallet_babe,
+		SubstrateTest: substrate_test_pallet::pallet,
+		Balances: pallet_balances,
 	}
-}
+);
+
+/// We assume that ~10% of the block weight is consumed by `on_initialize` handlers.
+/// This is used to limit the maximal weight of a single extrinsic.
+const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10);
+/// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be used
+/// by  Operational  extrinsics.
+const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
+/// Max weight, actual value does not matter for test runtime.
+const MAXIMUM_BLOCK_WEIGHT: Weight =
+	Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2), u64::MAX);
 
 parameter_types! {
-	pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight {
-		read: 100,
-		write: 1000,
-	};
-	pub RuntimeBlockLength: BlockLength =
-		BlockLength::max(4 * 1024 * 1024);
-	pub RuntimeBlockWeights: BlockWeights =
-		BlockWeights::with_sensible_defaults(Weight::from_parts(4 * 1024 * 1024, 0), Perbill::from_percent(75));
-}
+	pub const BlockHashCount: BlockNumber = 2400;
+	pub const Version: RuntimeVersion = VERSION;
 
-impl From<frame_system::Call<Runtime>> for Extrinsic {
-	fn from(_: frame_system::Call<Runtime>) -> Self {
-		unimplemented!("Not required in tests!")
-	}
+	pub RuntimeBlockLength: BlockLength =
+		BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);
+
+	pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()
+		.base_block(BlockExecutionWeight::get())
+		.for_class(DispatchClass::all(), |weights| {
+			weights.base_extrinsic = ExtrinsicBaseWeight::get();
+		})
+		.for_class(DispatchClass::Normal, |weights| {
+			weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);
+		})
+		.for_class(DispatchClass::Operational, |weights| {
+			weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);
+			// Operational transactions have some extra reserved space, so that they
+			// are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.
+			weights.reserved = Some(
+				MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT
+			);
+		})
+		.avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)
+		.build_or_panic();
 }
 
 impl frame_system::pallet::Config for Runtime {
 	type BaseCallFilter = frame_support::traits::Everything;
 	type BlockWeights = RuntimeBlockWeights;
-	type BlockLength = RuntimeBlockLength;
+	type BlockLength = ();
 	type RuntimeOrigin = RuntimeOrigin;
-	type RuntimeCall = Extrinsic;
-	type Index = u64;
-	type BlockNumber = u64;
+	type RuntimeCall = RuntimeCall;
+	type Index = Index;
+	type BlockNumber = BlockNumber;
 	type Hash = H256;
 	type Hashing = Hashing;
-	type AccountId = u64;
-	type Lookup = IdentityLookup<Self::AccountId>;
+	type AccountId = AccountId;
+	type Lookup = sp_runtime::traits::IdentityLookup<Self::AccountId>;
 	type Header = Header;
 	type RuntimeEvent = RuntimeEvent;
 	type BlockHashCount = ConstU64<2400>;
 	type DbWeight = ();
 	type Version = ();
-	type PalletInfo = Self;
-	type AccountData = ();
+	type PalletInfo = PalletInfo;
+	type AccountData = pallet_balances::AccountData<Balance>;
 	type OnNewAccount = ();
 	type OnKilledAccount = ();
 	type SystemWeightInfo = ();
@@ -646,14 +369,45 @@ impl frame_system::pallet::Config for Runtime {
 	type MaxConsumers = ConstU32<16>;
 }
 
-impl system::Config for Runtime {}
+pub mod currency {
+	use crate::Balance;
+	const MILLICENTS: Balance = 1_000_000_000;
+	const CENTS: Balance = 1_000 * MILLICENTS; // assume this is worth about a cent.
+	pub const DOLLARS: Balance = 100 * CENTS;
+}
 
+parameter_types! {
+	pub const ExistentialDeposit: Balance = 1 * currency::DOLLARS;
+	// For weight estimation, we assume that the most locks on an individual account will be 50.
+	// This number may need to be adjusted in the future if this assumption no longer holds true.
+	pub const MaxLocks: u32 = 50;
+	pub const MaxReserves: u32 = 50;
+}
+
+impl pallet_balances::Config for Runtime {
+	type MaxLocks = MaxLocks;
+	type MaxReserves = MaxReserves;
+	type ReserveIdentifier = [u8; 8];
+	type Balance = Balance;
+	type DustRemoval = ();
+	type RuntimeEvent = RuntimeEvent;
+	type ExistentialDeposit = ExistentialDeposit;
+	type AccountStore = System;
+	type WeightInfo = pallet_balances::weights::SubstrateWeight<Runtime>;
+	type FreezeIdentifier = ();
+	type MaxFreezes = ();
+	type HoldIdentifier = ();
+	type MaxHolds = ConstU32<1>;
+}
+
+impl substrate_test_pallet::Config for Runtime {}
+
+// Required for `pallet_babe::Config`.
 impl pallet_timestamp::Config for Runtime {
-	/// A timestamp: milliseconds since the unix epoch.
 	type Moment = u64;
-	type OnTimestampSet = ();
-	type MinimumPeriod = ConstU64<5>;
-	type WeightInfo = ();
+	type OnTimestampSet = Babe;
+	type MinimumPeriod = ConstU64<500>;
+	type WeightInfo = pallet_timestamp::weights::SubstrateWeight<Runtime>;
 }
 
 parameter_types! {
@@ -663,15 +417,12 @@ parameter_types! {
 impl pallet_babe::Config for Runtime {
 	type EpochDuration = EpochDuration;
 	type ExpectedBlockTime = ConstU64<10_000>;
-	// there is no actual runtime in this test-runtime, so testing crates
-	// are manually adding the digests. normally in this situation you'd use
-	// pallet_babe::SameAuthoritiesForever.
-	type EpochChangeTrigger = pallet_babe::ExternalTrigger;
+	type EpochChangeTrigger = pallet_babe::SameAuthoritiesForever;
 	type DisabledValidators = ();
-	type WeightInfo = ();
-	type MaxAuthorities = ConstU32<10>;
 	type KeyOwnerProof = sp_core::Void;
 	type EquivocationReportSystem = ();
+	type WeightInfo = ();
+	type MaxAuthorities = ConstU32<10>;
 }
 
 /// Adds one to the given input and returns the final result.
@@ -680,11 +431,6 @@ fn benchmark_add_one(i: u64) -> u64 {
 	i + 1
 }
 
-/// The `benchmark_add_one` function as function pointer.
-#[cfg(not(feature = "std"))]
-static BENCHMARK_ADD_ONE: sp_runtime_interface::wasm::ExchangeableFunction<fn(u64) -> u64> =
-	sp_runtime_interface::wasm::ExchangeableFunction::new(benchmark_add_one);
-
 fn code_using_trie() -> u64 {
 	let pairs = [
 		(b"0103000000000000000464".to_vec(), b"0400000000".to_vec()),
@@ -717,549 +463,257 @@ impl_opaque_keys! {
 	}
 }
 
-cfg_if! {
-	if #[cfg(feature = "std")] {
-		impl_runtime_apis! {
-			impl sp_api::Core<Block> for Runtime {
-				fn version() -> RuntimeVersion {
-					version()
-				}
-
-				fn execute_block(block: Block) {
-					system::execute_block(block);
-				}
-
-				fn initialize_block(header: &<Block as BlockT>::Header) {
-					system::initialize_block(header)
-				}
-			}
+pub(crate) const TEST_RUNTIME_BABE_EPOCH_CONFIGURATION: BabeEpochConfiguration =
+	BabeEpochConfiguration {
+		c: (3, 10),
+		allowed_slots: AllowedSlots::PrimaryAndSecondaryPlainSlots,
+	};
 
-			impl sp_api::Metadata<Block> for Runtime {
-				fn metadata() -> OpaqueMetadata {
-					unimplemented!()
-				}
+impl_runtime_apis! {
+	impl sp_api::Core<Block> for Runtime {
+		fn version() -> RuntimeVersion {
+			version()
+		}
 
-				fn metadata_at_version(_version: u32) -> Option<OpaqueMetadata> {
-						unimplemented!()
-				}
+		fn execute_block(block: Block) {
+			log::trace!(target: LOG_TARGET, "execute_block: {block:#?}");
+			Executive::execute_block(block);
+		}
 
-				fn metadata_versions() -> sp_std::vec::Vec<u32> {
-						unimplemented!()
-				}
-			}
+		fn initialize_block(header: &<Block as BlockT>::Header) {
+			log::trace!(target: LOG_TARGET, "initialize_block: {header:#?}");
+			Executive::initialize_block(header);
+		}
+	}
 
-			impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
-				fn validate_transaction(
-					_source: TransactionSource,
-					utx: <Block as BlockT>::Extrinsic,
-					_: <Block as BlockT>::Hash,
-				) -> TransactionValidity {
-					if let Extrinsic::IncludeData(data) = utx {
-						return Ok(ValidTransaction {
-							priority: data.len() as u64,
-							requires: vec![],
-							provides: vec![data],
-							longevity: 1,
-							propagate: false,
-						});
-					}
-
-					system::validate_transaction(utx)
-				}
-			}
+	impl sp_api::Metadata<Block> for Runtime {
+		fn metadata() -> OpaqueMetadata {
+			unimplemented!()
+		}
 
-			impl sp_block_builder::BlockBuilder<Block> for Runtime {
-				fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
-					system::execute_transaction(extrinsic)
-				}
+		fn metadata_at_version(_version: u32) -> Option<OpaqueMetadata> {
+			unimplemented!()
+		}
+		fn metadata_versions() -> sp_std::vec::Vec<u32> {
+			unimplemented!()
+		}
+	}
 
-				fn finalize_block() -> <Block as BlockT>::Header {
-					system::finalize_block()
-				}
+	impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
+		fn validate_transaction(
+			source: TransactionSource,
+			utx: <Block as BlockT>::Extrinsic,
+			block_hash: <Block as BlockT>::Hash,
+		) -> TransactionValidity {
+			let validity = Executive::validate_transaction(source, utx.clone(), block_hash);
+			log::trace!(target: LOG_TARGET, "validate_transaction {:?} {:?}", utx, validity);
+			validity
+		}
+	}
 
-				fn inherent_extrinsics(_data: InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
-					vec![]
-				}
+	impl sp_block_builder::BlockBuilder<Block> for Runtime {
+		fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
+			Executive::apply_extrinsic(extrinsic)
+		}
 
-				fn check_inherents(_block: Block, _data: InherentData) -> CheckInherentsResult {
-					CheckInherentsResult::new()
-				}
-			}
+		fn finalize_block() -> <Block as BlockT>::Header {
+			log::trace!(target: LOG_TARGET, "finalize_block");
+			Executive::finalize_block()
+		}
 
-			impl self::TestAPI<Block> for Runtime {
-				fn balance_of(id: AccountId) -> u64 {
-					system::balance_of(id)
-				}
-
-				fn benchmark_add_one(val: &u64) -> u64 {
-					val + 1
-				}
-
-				fn benchmark_vector_add_one(vec: &Vec<u64>) -> Vec<u64> {
-					let mut vec = vec.clone();
-					vec.iter_mut().for_each(|v| *v += 1);
-					vec
-				}
-
-				fn fail_convert_parameter(_: DecodeFails<Block>) {}
-
-				fn fail_convert_return_value() -> DecodeFails<Block> {
-					DecodeFails::default()
-				}
-
-				fn function_signature_changed() -> u64 {
-					1
-				}
-
-				fn fail_on_native() -> u64 {
-					panic!("Failing because we are on native")
-				}
-				fn fail_on_wasm() -> u64 {
-					1
-				}
-
-				fn use_trie() -> u64 {
-					code_using_trie()
-				}
-
-				fn benchmark_indirect_call() -> u64 {
-					let function = benchmark_add_one;
-					(0..1000).fold(0, |p, i| p + function(i))
-				}
-				fn benchmark_direct_call() -> u64 {
-					(0..1000).fold(0, |p, i| p + benchmark_add_one(i))
-				}
-
-				fn vec_with_capacity(_size: u32) -> Vec<u8> {
-					unimplemented!("is not expected to be invoked from non-wasm builds");
-				}
-
-				fn get_block_number() -> u64 {
-					system::get_block_number().expect("Block number is initialized")
-				}
-
-				fn take_block_number() -> Option<u64> {
-					system::take_block_number()
-				}
-
-				fn test_ed25519_crypto() -> (ed25519::AppSignature, ed25519::AppPublic) {
-					test_ed25519_crypto()
-				}
-
-				fn test_sr25519_crypto() -> (sr25519::AppSignature, sr25519::AppPublic) {
-					test_sr25519_crypto()
-				}
-
-				fn test_ecdsa_crypto() -> (ecdsa::AppSignature, ecdsa::AppPublic) {
-					test_ecdsa_crypto()
-				}
-
-				fn test_storage() {
-					test_read_storage();
-					test_read_child_storage();
-				}
-
-				fn test_witness(proof: StorageProof, root: crate::Hash) {
-					test_witness(proof, root);
-				}
-
-				fn test_multiple_arguments(data: Vec<u8>, other: Vec<u8>, num: u32) {
-					assert_eq!(&data[..], &other[..]);
-					assert_eq!(data.len(), num as usize);
-				}
-
-				fn do_trace_log() {
-					log::trace!("Hey I'm runtime");
-				}
-
-				fn verify_ed25519(sig: ed25519::Signature, public: ed25519::Public, message: Vec<u8>) -> bool {
-					sp_io::crypto::ed25519_verify(&sig, &message, &public)
-				}
-			}
+		fn inherent_extrinsics(_data: InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
+			vec![]
+		}
 
-			impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {
-				fn slot_duration() -> sp_consensus_aura::SlotDuration {
-					sp_consensus_aura::SlotDuration::from_millis(1000)
-				}
-
-				fn authorities() -> Vec<AuraId> {
-					system::authorities().into_iter().map(|a| {
-						let authority: sr25519::Public = a.into();
-						AuraId::from(authority)
-					}).collect()
-				}
-			}
+		fn check_inherents(_block: Block, _data: InherentData) -> CheckInherentsResult {
+			CheckInherentsResult::new()
+		}
+	}
 
-			impl sp_consensus_babe::BabeApi<Block> for Runtime {
-				fn configuration() -> sp_consensus_babe::BabeConfiguration {
-					sp_consensus_babe::BabeConfiguration {
-						slot_duration: 1000,
-						epoch_length: EpochDuration::get(),
-						c: (3, 10),
-						authorities: system::authorities()
-							.into_iter().map(|x|(x, 1)).collect(),
-						randomness: <pallet_babe::Pallet<Runtime>>::randomness(),
-						allowed_slots: AllowedSlots::PrimaryAndSecondaryPlainSlots,
-					}
-				}
-
-				fn current_epoch_start() -> Slot {
-					<pallet_babe::Pallet<Runtime>>::current_epoch_start()
-				}
-
-				fn current_epoch() -> sp_consensus_babe::Epoch {
-					<pallet_babe::Pallet<Runtime>>::current_epoch()
-				}
-
-				fn next_epoch() -> sp_consensus_babe::Epoch {
-					<pallet_babe::Pallet<Runtime>>::next_epoch()
-				}
-
-				fn submit_report_equivocation_unsigned_extrinsic(
-					_equivocation_proof: sp_consensus_babe::EquivocationProof<
-						<Block as BlockT>::Header,
-					>,
-					_key_owner_proof: sp_consensus_babe::OpaqueKeyOwnershipProof,
-				) -> Option<()> {
-					None
-				}
-
-				fn generate_key_ownership_proof(
-					_slot: sp_consensus_babe::Slot,
-					_authority_id: sp_consensus_babe::AuthorityId,
-				) -> Option<sp_consensus_babe::OpaqueKeyOwnershipProof> {
-					None
-				}
-			}
+	impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {
+		fn account_nonce(account: AccountId) -> Index {
+			System::account_nonce(account)
+		}
+	}
 
-			impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
-				fn offchain_worker(header: &<Block as BlockT>::Header) {
-					let ex = Extrinsic::IncludeData(header.number.encode());
-					sp_io::offchain::submit_transaction(ex.encode()).unwrap();
-				}
-			}
+	impl self::TestAPI<Block> for Runtime {
+		fn balance_of(id: AccountId) -> u64 {
+			Balances::free_balance(id)
+		}
 
-			impl sp_session::SessionKeys<Block> for Runtime {
-				fn generate_session_keys(_: Option<Vec<u8>>) -> Vec<u8> {
-					SessionKeys::generate(None)
-				}
+		fn benchmark_add_one(val: &u64) -> u64 {
+			val + 1
+		}
 
-				fn decode_session_keys(
-					encoded: Vec<u8>,
-				) -> Option<Vec<(Vec<u8>, sp_core::crypto::KeyTypeId)>> {
-					SessionKeys::decode_into_raw_public_keys(&encoded)
-				}
-			}
+		fn benchmark_vector_add_one(vec: &Vec<u64>) -> Vec<u64> {
+			let mut vec = vec.clone();
+			vec.iter_mut().for_each(|v| *v += 1);
+			vec
+		}
 
-			impl sp_consensus_grandpa::GrandpaApi<Block> for Runtime {
-				fn grandpa_authorities() -> sp_consensus_grandpa::AuthorityList {
-					Vec::new()
-				}
-
-				fn current_set_id() -> sp_consensus_grandpa::SetId {
-					0
-				}
-
-				fn submit_report_equivocation_unsigned_extrinsic(
-					_equivocation_proof: sp_consensus_grandpa::EquivocationProof<
-						<Block as BlockT>::Hash,
-						NumberFor<Block>,
-					>,
-					_key_owner_proof: sp_consensus_grandpa::OpaqueKeyOwnershipProof,
-				) -> Option<()> {
-					None
-				}
-
-				fn generate_key_ownership_proof(
-					_set_id: sp_consensus_grandpa::SetId,
-					_authority_id: sp_consensus_grandpa::AuthorityId,
-				) -> Option<sp_consensus_grandpa::OpaqueKeyOwnershipProof> {
-					None
-				}
-			}
+		fn function_signature_changed() -> u64 {
+			1
+		}
 
-			impl sp_consensus_beefy::BeefyApi<Block> for Runtime {
-				fn beefy_genesis() -> Option<BlockNumber> {
-					None
-				}
-
-				fn validator_set() -> Option<sp_consensus_beefy::ValidatorSet<sp_consensus_beefy::crypto::AuthorityId>> {
-					None
-				}
-
-				fn submit_report_equivocation_unsigned_extrinsic(
-					_equivocation_proof: sp_consensus_beefy::EquivocationProof<
-						NumberFor<Block>,
-						sp_consensus_beefy::crypto::AuthorityId,
-						sp_consensus_beefy::crypto::Signature
-					>,
-					_key_owner_proof: sp_consensus_beefy::OpaqueKeyOwnershipProof,
-				) -> Option<()> { None }
-
-				fn generate_key_ownership_proof(
-					_set_id: sp_consensus_beefy::ValidatorSetId,
-					_authority_id: sp_consensus_beefy::crypto::AuthorityId,
-				) -> Option<sp_consensus_beefy::OpaqueKeyOwnershipProof> { None }
-			}
+		fn use_trie() -> u64 {
+			code_using_trie()
+		}
 
-			impl pallet_beefy_mmr::BeefyMmrApi<Block, sp_consensus_beefy::MmrRootHash> for Runtime {
-				fn authority_set_proof() -> sp_consensus_beefy::mmr::BeefyAuthoritySet<sp_consensus_beefy::MmrRootHash> {
-					Default::default()
-				}
+		fn benchmark_indirect_call() -> u64 {
+			let function = benchmark_add_one;
+			(0..1000).fold(0, |p, i| p + function(i))
+		}
+		fn benchmark_direct_call() -> u64 {
+			(0..1000).fold(0, |p, i| p + benchmark_add_one(i))
+		}
 
-				fn next_authority_set_proof() -> sp_consensus_beefy::mmr::BeefyNextAuthoritySet<sp_consensus_beefy::MmrRootHash> {
-					Default::default()
-				}
-			}
+		fn vec_with_capacity(size: u32) -> Vec<u8> {
+			Vec::with_capacity(size as usize)
+		}
 
-			impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {
-				fn account_nonce(_account: AccountId) -> Index {
-					0
-				}
-			}
+		fn get_block_number() -> u64 {
+			System::block_number()
+		}
+
+		fn test_ed25519_crypto() -> (ed25519::AppSignature, ed25519::AppPublic) {
+			test_ed25519_crypto()
 		}
-	} else {
-		impl_runtime_apis! {
-			impl sp_api::Core<Block> for Runtime {
-				fn version() -> RuntimeVersion {
-					version()
-				}
-
-				fn execute_block(block: Block) {
-					system::execute_block(block);
-				}
-
-				fn initialize_block(header: &<Block as BlockT>::Header) {
-					system::initialize_block(header)
-				}
-			}
 
-			impl sp_api::Metadata<Block> for Runtime {
-				fn metadata() -> OpaqueMetadata {
-					unimplemented!()
-				}
+		fn test_sr25519_crypto() -> (sr25519::AppSignature, sr25519::AppPublic) {
+			test_sr25519_crypto()
+		}
 
-				fn metadata_at_version(_version: u32) -> Option<OpaqueMetadata> {
-						unimplemented!()
-				}
+		fn test_ecdsa_crypto() -> (ecdsa::AppSignature, ecdsa::AppPublic) {
+			test_ecdsa_crypto()
+		}
 
-				fn metadata_versions() -> sp_std::vec::Vec<u32> {
-						unimplemented!()
-				}
-			}
+		fn test_storage() {
+			test_read_storage();
+			test_read_child_storage();
+		}
 
-			impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
-				fn validate_transaction(
-					_source: TransactionSource,
-					utx: <Block as BlockT>::Extrinsic,
-					_: <Block as BlockT>::Hash,
-				) -> TransactionValidity {
-					if let Extrinsic::IncludeData(data) = utx {
-						return Ok(ValidTransaction{
-							priority: data.len() as u64,
-							requires: vec![],
-							provides: vec![data],
-							longevity: 1,
-							propagate: false,
-						});
-					}
-
-					system::validate_transaction(utx)
-				}
-			}
+		fn test_witness(proof: StorageProof, root: crate::Hash) {
+			test_witness(proof, root);
+		}
+
+		fn test_multiple_arguments(data: Vec<u8>, other: Vec<u8>, num: u32) {
+			assert_eq!(&data[..], &other[..]);
+			assert_eq!(data.len(), num as usize);
+		}
 
-			impl sp_block_builder::BlockBuilder<Block> for Runtime {
-				fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
-					system::execute_transaction(extrinsic)
-				}
+		fn do_trace_log() {
+			log::trace!("Hey I'm runtime");
+		}
 
-				fn finalize_block() -> <Block as BlockT>::Header {
-					system::finalize_block()
-				}
+		fn verify_ed25519(sig: ed25519::Signature, public: ed25519::Public, message: Vec<u8>) -> bool {
+			sp_io::crypto::ed25519_verify(&sig, &message, &public)
+		}
+	}
 
-				fn inherent_extrinsics(_data: InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
-					vec![]
-				}
+	impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {
+		fn slot_duration() -> sp_consensus_aura::SlotDuration {
+			sp_consensus_aura::SlotDuration::from_millis(1000)
+		}
 
-				fn check_inherents(_block: Block, _data: InherentData) -> CheckInherentsResult {
-					CheckInherentsResult::new()
-				}
-			}
+		fn authorities() -> Vec<AuraId> {
+			SubstrateTest::authorities().into_iter().map(|a| {
+				let authority: sr25519::Public = a.into();
+				AuraId::from(authority)
+			}).collect()
+		}
+	}
 
-			impl self::TestAPI<Block> for Runtime {
-				fn balance_of(id: AccountId) -> u64 {
-					system::balance_of(id)
-				}
-
-				fn benchmark_add_one(val: &u64) -> u64 {
-					val + 1
-				}
-
-				fn benchmark_vector_add_one(vec: &Vec<u64>) -> Vec<u64> {
-					let mut vec = vec.clone();
-					vec.iter_mut().for_each(|v| *v += 1);
-					vec
-				}
-
-				fn fail_convert_parameter(_: DecodeFails<Block>) {}
-
-				fn fail_convert_return_value() -> DecodeFails<Block> {
-					DecodeFails::default()
-				}
-
-				fn function_signature_changed() -> Vec<u64> {
-					let mut vec = Vec::new();
-					vec.push(1);
-					vec.push(2);
-					vec
-				}
-
-				fn fail_on_native() -> u64 {
-					1
-				}
-
-				fn fail_on_wasm() -> u64 {
-					panic!("Failing because we are on wasm")
-				}
-
-				fn use_trie() -> u64 {
-					code_using_trie()
-				}
-
-				fn benchmark_indirect_call() -> u64 {
-					(0..10000).fold(0, |p, i| p + BENCHMARK_ADD_ONE.get()(i))
-				}
-
-				fn benchmark_direct_call() -> u64 {
-					(0..10000).fold(0, |p, i| p + benchmark_add_one(i))
-				}
-
-				fn vec_with_capacity(size: u32) -> Vec<u8> {
-					Vec::with_capacity(size as usize)
-				}
-
-				fn get_block_number() -> u64 {
-					system::get_block_number().expect("Block number is initialized")
-				}
-
-				fn take_block_number() -> Option<u64> {
-					system::take_block_number()
-				}
-
-				fn test_ed25519_crypto() -> (ed25519::AppSignature, ed25519::AppPublic) {
-					test_ed25519_crypto()
-				}
-
-				fn test_sr25519_crypto() -> (sr25519::AppSignature, sr25519::AppPublic) {
-					test_sr25519_crypto()
-				}
-
-				fn test_ecdsa_crypto() -> (ecdsa::AppSignature, ecdsa::AppPublic) {
-					test_ecdsa_crypto()
-				}
-
-				fn test_storage() {
-					test_read_storage();
-					test_read_child_storage();
-				}
-
-				fn test_witness(proof: StorageProof, root: crate::Hash) {
-					test_witness(proof, root);
-				}
-
-				fn test_multiple_arguments(data: Vec<u8>, other: Vec<u8>, num: u32) {
-					assert_eq!(&data[..], &other[..]);
-					assert_eq!(data.len(), num as usize);
-				}
-
-				fn do_trace_log() {
-					log::trace!("Hey I'm runtime: {}", log::STATIC_MAX_LEVEL);
-				}
-
-				fn verify_ed25519(sig: ed25519::Signature, public: ed25519::Public, message: Vec<u8>) -> bool {
-					sp_io::crypto::ed25519_verify(&sig, &message, &public)
-				}
+	impl sp_consensus_babe::BabeApi<Block> for Runtime {
+		fn configuration() -> sp_consensus_babe::BabeConfiguration {
+			let epoch_config = Babe::epoch_config().unwrap_or(TEST_RUNTIME_BABE_EPOCH_CONFIGURATION);
+			sp_consensus_babe::BabeConfiguration {
+				slot_duration: Babe::slot_duration(),
+				epoch_length: EpochDuration::get(),
+				c: epoch_config.c,
+				authorities: SubstrateTest::authorities()
+					.into_iter().map(|x|(x, 1)).collect(),
+					randomness: Babe::randomness(),
+					allowed_slots: epoch_config.allowed_slots,
 			}
+		}
 
-			impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {
-				fn slot_duration() -> sp_consensus_aura::SlotDuration {
-					sp_consensus_aura::SlotDuration::from_millis(1000)
-				}
-
-				fn authorities() -> Vec<AuraId> {
-					system::authorities().into_iter().map(|a| {
-						let authority: sr25519::Public = a.into();
-						AuraId::from(authority)
-					}).collect()
-				}
-			}
+		fn current_epoch_start() -> Slot {
+			Babe::current_epoch_start()
+		}
 
-			impl sp_consensus_babe::BabeApi<Block> for Runtime {
-				fn configuration() -> sp_consensus_babe::BabeConfiguration {
-					sp_consensus_babe::BabeConfiguration {
-						slot_duration: 1000,
-						epoch_length: EpochDuration::get(),
-						c: (3, 10),
-						authorities: system::authorities()
-							.into_iter().map(|x|(x, 1)).collect(),
-						randomness: <pallet_babe::Pallet<Runtime>>::randomness(),
-						allowed_slots: AllowedSlots::PrimaryAndSecondaryPlainSlots,
-					}
-				}
-
-				fn current_epoch_start() -> Slot {
-					<pallet_babe::Pallet<Runtime>>::current_epoch_start()
-				}
-
-				fn current_epoch() -> sp_consensus_babe::Epoch {
-					<pallet_babe::Pallet<Runtime>>::current_epoch()
-				}
-
-				fn next_epoch() -> sp_consensus_babe::Epoch {
-					<pallet_babe::Pallet<Runtime>>::next_epoch()
-				}
-
-				fn submit_report_equivocation_unsigned_extrinsic(
-					_equivocation_proof: sp_consensus_babe::EquivocationProof<
-						<Block as BlockT>::Header,
-					>,
-					_key_owner_proof: sp_consensus_babe::OpaqueKeyOwnershipProof,
-				) -> Option<()> {
-					None
-				}
-
-				fn generate_key_ownership_proof(
-					_slot: sp_consensus_babe::Slot,
-					_authority_id: sp_consensus_babe::AuthorityId,
-				) -> Option<sp_consensus_babe::OpaqueKeyOwnershipProof> {
-					None
-				}
-			}
+		fn current_epoch() -> sp_consensus_babe::Epoch {
+			Babe::current_epoch()
+		}
 
-			impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
-				fn offchain_worker(header: &<Block as BlockT>::Header) {
-					let ex = Extrinsic::IncludeData(header.number.encode());
-					sp_io::offchain::submit_transaction(ex.encode()).unwrap()
-				}
-			}
+		fn next_epoch() -> sp_consensus_babe::Epoch {
+			Babe::next_epoch()
+		}
 
-			impl sp_session::SessionKeys<Block> for Runtime {
-				fn generate_session_keys(_: Option<Vec<u8>>) -> Vec<u8> {
-					SessionKeys::generate(None)
-				}
+		fn submit_report_equivocation_unsigned_extrinsic(
+			_equivocation_proof: sp_consensus_babe::EquivocationProof<
+			<Block as BlockT>::Header,
+			>,
+			_key_owner_proof: sp_consensus_babe::OpaqueKeyOwnershipProof,
+		) -> Option<()> {
+			None
+		}
 
-				fn decode_session_keys(
-					encoded: Vec<u8>,
-				) -> Option<Vec<(Vec<u8>, sp_core::crypto::KeyTypeId)>> {
-					SessionKeys::decode_into_raw_public_keys(&encoded)
-				}
-			}
+		fn generate_key_ownership_proof(
+			_slot: sp_consensus_babe::Slot,
+			_authority_id: sp_consensus_babe::AuthorityId,
+		) -> Option<sp_consensus_babe::OpaqueKeyOwnershipProof> {
+			None
+		}
+	}
 
-			impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {
-				fn account_nonce(_account: AccountId) -> Index {
-					0
-				}
-			}
+	impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
+		fn offchain_worker(header: &<Block as BlockT>::Header) {
+			let ext = Extrinsic::new_unsigned(
+				substrate_test_pallet::pallet::Call::storage_change{
+					key:b"some_key".encode(),
+					value:Some(header.number.encode())
+				}.into(),
+			);
+			sp_io::offchain::submit_transaction(ext.encode()).unwrap();
+		}
+	}
+
+	impl sp_session::SessionKeys<Block> for Runtime {
+		fn generate_session_keys(_: Option<Vec<u8>>) -> Vec<u8> {
+			SessionKeys::generate(None)
+		}
+
+		fn decode_session_keys(
+			encoded: Vec<u8>,
+		) -> Option<Vec<(Vec<u8>, sp_core::crypto::KeyTypeId)>> {
+			SessionKeys::decode_into_raw_public_keys(&encoded)
+		}
+	}
+
+	impl sp_consensus_grandpa::GrandpaApi<Block> for Runtime {
+		fn grandpa_authorities() -> sp_consensus_grandpa::AuthorityList {
+			Vec::new()
+		}
+
+		fn current_set_id() -> sp_consensus_grandpa::SetId {
+			0
+		}
+
+		fn submit_report_equivocation_unsigned_extrinsic(
+			_equivocation_proof: sp_consensus_grandpa::EquivocationProof<
+			<Block as BlockT>::Hash,
+			NumberFor<Block>,
+			>,
+			_key_owner_proof: sp_consensus_grandpa::OpaqueKeyOwnershipProof,
+		) -> Option<()> {
+			None
+		}
+
+		fn generate_key_ownership_proof(
+			_set_id: sp_consensus_grandpa::SetId,
+			_authority_id: sp_consensus_grandpa::AuthorityId,
+		) -> Option<sp_consensus_grandpa::OpaqueKeyOwnershipProof> {
+			None
 		}
 	}
 }
@@ -1360,13 +814,194 @@ fn test_witness(proof: StorageProof, root: crate::Hash) {
 	assert!(ext.storage_root(Default::default()).as_slice() != &root[..]);
 }
 
+/// Some tests require the hashed keys of the storage. As the values of hashed keys are not trivial
+/// to guess, this small module provides the values of the keys, and the code which is required to
+/// generate the keys.
+#[cfg(feature = "std")]
+pub mod storage_key_generator {
+	use super::*;
+	use sp_core::Pair;
+	use sp_keyring::AccountKeyring;
+
+	/// Generate hex string without prefix
+	pub(super) fn hex<T>(x: T) -> String
+	where
+		T: array_bytes::Hex,
+	{
+		x.hex(Default::default())
+	}
+
+	fn concat_hashes(input: &Vec<&[u8]>) -> String {
+		input.iter().map(|s| sp_core::hashing::twox_128(s)).map(hex).collect()
+	}
+
+	fn twox_64_concat(x: &[u8]) -> Vec<u8> {
+		sp_core::hashing::twox_64(x).iter().chain(x.iter()).cloned().collect::<Vec<_>>()
+	}
+
+	/// Generate the hashed storage keys from the raw literals. These keys are expected to be be in
+	/// storage with given substrate-test runtime.
+	pub fn generate_expected_storage_hashed_keys() -> Vec<String> {
+		let literals: Vec<&[u8]> = vec![b":code", b":extrinsic_index", b":heappages"];
+
+		let keys: Vec<Vec<&[u8]>> = vec![
+			vec![b"Babe", b"Authorities"],
+			vec![b"Babe", b"EpochConfig"],
+			vec![b"Babe", b"NextAuthorities"],
+			vec![b"Babe", b"SegmentIndex"],
+			vec![b"Babe", b":__STORAGE_VERSION__:"],
+			vec![b"Balances", b":__STORAGE_VERSION__:"],
+			vec![b"Balances", b"TotalIssuance"],
+			vec![b"SubstrateTest", b"Authorities"],
+			vec![b"SubstrateTest", b":__STORAGE_VERSION__:"],
+			vec![b"System", b"LastRuntimeUpgrade"],
+			vec![b"System", b"ParentHash"],
+			vec![b"System", b":__STORAGE_VERSION__:"],
+			vec![b"System", b"UpgradedToTripleRefCount"],
+			vec![b"System", b"UpgradedToU32RefCount"],
+		];
+
+		let mut expected_keys = keys.iter().map(concat_hashes).collect::<Vec<String>>();
+
+		expected_keys.extend(literals.into_iter().map(hex));
+
+		let balances_map_keys = (0..16_usize)
+			.into_iter()
+			.map(|i| AccountKeyring::numeric(i).public().to_vec())
+			.chain(vec![
+				AccountKeyring::Alice.public().to_vec(),
+				AccountKeyring::Bob.public().to_vec(),
+				AccountKeyring::Charlie.public().to_vec(),
+			])
+			.map(|pubkey| {
+				sp_core::hashing::blake2_128(&pubkey)
+					.iter()
+					.chain(pubkey.iter())
+					.cloned()
+					.collect::<Vec<u8>>()
+			})
+			.map(|hash_pubkey| {
+				[concat_hashes(&vec![b"System", b"Account"]), hex(hash_pubkey)].concat()
+			});
+
+		expected_keys.extend(balances_map_keys);
+
+		expected_keys.push(
+			[
+				concat_hashes(&vec![b"System", b"BlockHash"]),
+				hex(0u64.using_encoded(twox_64_concat)),
+			]
+			.concat(),
+		);
+
+		expected_keys.sort();
+		expected_keys
+	}
+
+	/// Provides the commented list of hashed keys. This contains a hard-coded list of hashed keys
+	/// that would be generated by `generate_expected_storage_hashed_keys`. This list is provided
+	/// for the debugging convenience only. Value of each hex-string is documented with the literal
+	/// origin.
+	pub fn get_expected_storage_hashed_keys() -> Vec<String> {
+		[
+			//System|:__STORAGE_VERSION__:
+			"00771836bebdd29870ff246d305c578c4e7b9012096b41c4eb3aaf947f6ea429",
+			//SubstrateTest|Authorities
+			"00771836bebdd29870ff246d305c578c5e0621c4869aa60c02be9adcc98a0d1d",
+			//Babe|:__STORAGE_VERSION__:
+			"1cb6f36e027abb2091cfb5110ab5087f4e7b9012096b41c4eb3aaf947f6ea429",
+			//Babe|Authorities
+			"1cb6f36e027abb2091cfb5110ab5087f5e0621c4869aa60c02be9adcc98a0d1d",
+			//Babe|SegmentIndex
+			"1cb6f36e027abb2091cfb5110ab5087f66e8f035c8adbe7f1547b43c51e6f8a4",
+			//Babe|NextAuthorities
+			"1cb6f36e027abb2091cfb5110ab5087faacf00b9b41fda7a9268821c2a2b3e4c",
+			//Babe|EpochConfig
+			"1cb6f36e027abb2091cfb5110ab5087fdc6b171b77304263c292cc3ea5ed31ef",
+			//System|:__STORAGE_VERSION__:
+			"26aa394eea5630e07c48ae0c9558cef74e7b9012096b41c4eb3aaf947f6ea429",
+			//System|UpgradedToU32RefCount
+			"26aa394eea5630e07c48ae0c9558cef75684a022a34dd8bfa2baaf44f172b710",
+			//System|ParentHash
+			"26aa394eea5630e07c48ae0c9558cef78a42f33323cb5ced3b44dd825fda9fcc",
+			//System::BlockHash|0
+			"26aa394eea5630e07c48ae0c9558cef7a44704b568d21667356a5a050c118746bb1bdbcacd6ac9340000000000000000",
+			//System|UpgradedToTripleRefCount
+			"26aa394eea5630e07c48ae0c9558cef7a7fd6c28836b9a28522dc924110cf439",
+
+			// System|Account|blake2_128Concat("//11")
+			"26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da901cae4e3edfbb32c91ed3f01ab964f4eeeab50338d8e5176d3141802d7b010a55dadcd5f23cf8aaafa724627e967e90e",
+			// System|Account|blake2_128Concat("//4")
+			"26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da91b614bd4a126f2d5d294e9a8af9da25248d7e931307afb4b68d8d565d4c66e00d856c6d65f5fed6bb82dcfb60e936c67",
+			// System|Account|blake2_128Concat("//7")
+			"26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da94b21aff9fe1e8b2fc4b0775b8cbeff28ba8e2c7594dd74730f3ca835e95455d199261897edc9735d602ea29615e2b10b",
+			// System|Account|blake2_128Concat("//Bob")
+			"26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da94f9aea1afa791265fae359272badc1cf8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48",
+			// System|Account|blake2_128Concat("//3")
+			"26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da95786a2916fcb81e1bd5dcd81e0d2452884617f575372edb5a36d85c04cdf2e4699f96fe33eb5f94a28c041b88e398d0c",
+			// System|Account|blake2_128Concat("//14")
+			"26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da95b8542d9672c7b7e779cc7c1e6b605691c2115d06120ea2bee32dd601d02f36367564e7ddf84ae2717ca3f097459652e",
+			// System|Account|blake2_128Concat("//6")
+			"26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da996c30bdbfab640838e6b6d3c33ab4adb4211b79e34ee8072eab506edd4b93a7b85a14c9a05e5cdd056d98e7dbca87730",
+			// System|Account|blake2_128Concat("//9")
+			"26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da99dc65b1339ec388fbf2ca0cdef51253512c6cfd663203ea16968594f24690338befd906856c4d2f4ef32dad578dba20c",
+			// System|Account|blake2_128Concat("//8")
+			"26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da99e6eb5abd62f5fd54793da91a47e6af6125d57171ff9241f07acaa1bb6a6103517965cf2cd00e643b27e7599ebccba70",
+			// System|Account|blake2_128Concat("//Charlie")
+			"26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9b0edae20838083f2cde1c4080db8cf8090b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22",
+			// System|Account|blake2_128Concat("//10")
+			"26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9d0052993b6f3bd0544fd1f5e4125b9fbde3e789ecd53431fe5c06c12b72137153496dace35c695b5f4d7b41f7ed5763b",
+			// System|Account|blake2_128Concat("//1")
+			"26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9d6b7e9a5f12bc571053265dade10d3b4b606fc73f57f03cdb4c932d475ab426043e429cecc2ffff0d2672b0df8398c48",
+			// System|Account|blake2_128Concat("//Alice")
+			"26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9de1e86a9a8c739864cf3cc5ec2bea59fd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d",
+			// System|Account|blake2_128Concat("//2")
+			"26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9e1a35f56ee295d39287cbffcfc60c4b346f136b564e1fad55031404dd84e5cd3fa76bfe7cc7599b39d38fd06663bbc0a",
+			// System|Account|blake2_128Concat("//5")
+			"26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9e2c1dc507e2035edbbd8776c440d870460c57f0008067cc01c5ff9eb2e2f9b3a94299a915a91198bd1021a6c55596f57",
+			// System|Account|blake2_128Concat("//0")
+			"26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9eca0e653a94f4080f6311b4e7b6934eb2afba9278e30ccf6a6ceb3a8b6e336b70068f045c666f2e7f4f9cc5f47db8972",
+			// System|Account|blake2_128Concat("//13")
+			"26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9ee8bf7ef90fc56a8aa3b90b344c599550c29b161e27ff8ba45bf6bad4711f326fc506a8803453a4d7e3158e993495f10",
+			// System|Account|blake2_128Concat("//12")
+			"26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9f5d6f1c082fe63eec7a71fcad00f4a892e3d43b7b0d04e776e69e7be35247cecdac65504c579195731eaf64b7940966e",
+			// System|Account|blake2_128Concat("//15")
+			"26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9fbf0818841edf110e05228a6379763c4fc3c37459d9bdc61f58a5ebc01e9e2305a19d390c0543dc733861ec3cf1de01f",
+			// System|LastRuntimeUpgrade
+			"26aa394eea5630e07c48ae0c9558cef7f9cce9c888469bb1a0dceaa129672ef8",
+			// :code
+			"3a636f6465",
+			// :extrinsic_index
+			"3a65787472696e7369635f696e646578",
+			// :heappages
+			"3a686561707061676573",
+			// Balances|:__STORAGE_VERSION__:
+			"c2261276cc9d1f8598ea4b6a74b15c2f4e7b9012096b41c4eb3aaf947f6ea429",
+			// Balances|TotalIssuance
+			"c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80",
+		].into_iter().map(String::from).collect::<Vec<_>>()
+	}
+
+	#[test]
+	fn expected_keys_vec_are_matching() {
+		assert_eq!(
+			storage_key_generator::get_expected_storage_hashed_keys(),
+			storage_key_generator::generate_expected_storage_hashed_keys(),
+		);
+	}
+}
+
 #[cfg(test)]
 mod tests {
+	use super::*;
 	use codec::Encode;
+	use frame_support::dispatch::DispatchInfo;
 	use sc_block_builder::BlockBuilderProvider;
 	use sp_api::ProvideRuntimeApi;
 	use sp_consensus::BlockOrigin;
 	use sp_core::{storage::well_known_keys::HEAP_PAGES, ExecutionContext};
+	use sp_keyring::AccountKeyring;
+	use sp_runtime::{traits::SignedExtension, transaction_validity::InvalidTransaction};
 	use sp_state_machine::ExecutionStrategy;
 	use substrate_test_runtime_client::{
 		prelude::*, runtime::TestAPI, DefaultTestClientBuilderExt, TestClientBuilder,
@@ -1374,7 +1009,7 @@ mod tests {
 
 	#[test]
 	fn heap_pages_is_respected() {
-		// This tests that the on-chain HEAP_PAGES parameter is respected.
+		// This tests that the on-chain `HEAP_PAGES` parameter is respected.
 
 		// Create a client devoting only 8 pages of wasm memory. This gives us ~512k of heap memory.
 		let mut client = TestClientBuilder::new()
@@ -1421,7 +1056,6 @@ mod tests {
 	}
 
 	fn witness_backend() -> (sp_trie::MemoryDB<crate::Hashing>, crate::Hash) {
-		use sp_trie::TrieMut;
 		let mut root = crate::Hash::default();
 		let mut mdb = sp_trie::MemoryDB::<crate::Hashing>::default();
 		{
@@ -1446,4 +1080,127 @@ mod tests {
 
 		runtime_api.test_witness(best_hash, proof, root).unwrap();
 	}
+
+	pub fn new_test_ext() -> sp_io::TestExternalities {
+		genesismap::GenesisStorageBuilder::new(
+			vec![AccountKeyring::One.public().into(), AccountKeyring::Two.public().into()],
+			vec![AccountKeyring::One.into(), AccountKeyring::Two.into()],
+			1000 * currency::DOLLARS,
+		)
+		.build_storage()
+		.into()
+	}
+
+	#[test]
+	fn validate_storage_keys() {
+		assert_eq!(
+			genesismap::GenesisStorageBuilder::default()
+				.build_storage()
+				.top
+				.keys()
+				.cloned()
+				.map(storage_key_generator::hex)
+				.collect::<Vec<_>>(),
+			storage_key_generator::get_expected_storage_hashed_keys()
+		);
+	}
+
+	#[test]
+	fn validate_unsigned_works() {
+		sp_tracing::try_init_simple();
+		new_test_ext().execute_with(|| {
+			assert_eq!(
+				<SubstrateTest as sp_runtime::traits::ValidateUnsigned>::validate_unsigned(
+					TransactionSource::External,
+					&substrate_test_pallet::Call::bench_call { transfer: Default::default() },
+				),
+				InvalidTransaction::Call.into(),
+			);
+
+			assert_eq!(
+				<SubstrateTest as sp_runtime::traits::ValidateUnsigned>::validate_unsigned(
+					TransactionSource::External,
+					&substrate_test_pallet::Call::include_data { data: vec![] },
+				),
+				InvalidTransaction::Call.into(),
+			);
+
+			assert_eq!(
+				<SubstrateTest as sp_runtime::traits::ValidateUnsigned>::validate_unsigned(
+					TransactionSource::External,
+					&substrate_test_pallet::Call::fill_block { ratio: Perbill::from_percent(50) },
+				),
+				InvalidTransaction::Call.into(),
+			);
+
+			assert_eq!(
+				<SubstrateTest as sp_runtime::traits::ValidateUnsigned>::validate_unsigned(
+					TransactionSource::External,
+					&substrate_test_pallet::Call::deposit_log_digest_item {
+						log: DigestItem::Other(vec![])
+					},
+				),
+				Ok(Default::default()),
+			);
+
+			assert_eq!(
+				<SubstrateTest as sp_runtime::traits::ValidateUnsigned>::validate_unsigned(
+					TransactionSource::External,
+					&substrate_test_pallet::Call::storage_change { key: vec![], value: None },
+				),
+				Ok(Default::default()),
+			);
+
+			assert_eq!(
+				<SubstrateTest as sp_runtime::traits::ValidateUnsigned>::validate_unsigned(
+					TransactionSource::External,
+					&substrate_test_pallet::Call::read { count: 0 },
+				),
+				Ok(Default::default()),
+			);
+
+			assert_eq!(
+				<SubstrateTest as sp_runtime::traits::ValidateUnsigned>::validate_unsigned(
+					TransactionSource::External,
+					&substrate_test_pallet::Call::read_and_panic { count: 0 },
+				),
+				Ok(Default::default()),
+			);
+		});
+	}
+
+	#[test]
+	fn check_substrate_check_signed_extension_works() {
+		sp_tracing::try_init_simple();
+		new_test_ext().execute_with(|| {
+			let x = sp_keyring::AccountKeyring::Alice.into();
+			let info = DispatchInfo::default();
+			let len = 0_usize;
+			assert_eq!(
+				CheckSubstrateCall {}
+					.validate(
+						&x,
+						&ExtrinsicBuilder::new_call_with_priority(16).build().function,
+						&info,
+						len
+					)
+					.unwrap()
+					.priority,
+				16
+			);
+
+			assert_eq!(
+				CheckSubstrateCall {}
+					.validate(
+						&x,
+						&ExtrinsicBuilder::new_call_do_not_propagate().build().function,
+						&info,
+						len
+					)
+					.unwrap()
+					.propagate,
+				false
+			);
+		})
+	}
 }
diff --git a/substrate/test-utils/runtime/src/substrate_test_pallet.rs b/substrate/test-utils/runtime/src/substrate_test_pallet.rs
new file mode 100644
index 00000000000..98ebd550b9e
--- /dev/null
+++ b/substrate/test-utils/runtime/src/substrate_test_pallet.rs
@@ -0,0 +1,244 @@
+// This file is part of Substrate.
+
+// Copyright (C) Parity Technologies (UK) Ltd.
+// SPDX-License-Identifier: Apache-2.0
+
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 	http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! # substrate-test pallet
+//!
+//! Provides functionality used in unit-tests of numerous modules across substrate that require
+//! functioning runtime. Some calls are allowed to be submitted as unsigned extrinsics, however most
+//! of them requires signing. Refer to `pallet::Call` for further details.
+
+use crate::AuthorityId;
+use frame_support::{pallet_prelude::*, storage};
+use sp_runtime::transaction_validity::{
+	InvalidTransaction, TransactionSource, TransactionValidity, ValidTransaction,
+};
+use sp_std::prelude::*;
+
+pub use self::pallet::*;
+
+const LOG_TARGET: &str = "substrate_test_pallet";
+
+#[frame_support::pallet(dev_mode)]
+pub mod pallet {
+	use super::*;
+	use crate::TransferData;
+	use frame_system::pallet_prelude::*;
+	use sp_core::storage::well_known_keys;
+	use sp_runtime::{transaction_validity::TransactionPriority, Perbill};
+
+	#[pallet::pallet]
+	#[pallet::without_storage_info]
+	pub struct Pallet<T>(PhantomData<T>);
+
+	#[pallet::config]
+	pub trait Config: frame_system::Config {}
+
+	#[pallet::storage]
+	#[pallet::getter(fn authorities)]
+	pub type Authorities<T> = StorageValue<_, Vec<AuthorityId>, ValueQuery>;
+
+	#[pallet::genesis_config]
+	#[cfg_attr(feature = "std", derive(Default))]
+	pub struct GenesisConfig {
+		pub authorities: Vec<AuthorityId>,
+	}
+
+	#[pallet::genesis_build]
+	impl<T: Config> GenesisBuild<T> for GenesisConfig {
+		fn build(&self) {
+			<Authorities<T>>::put(self.authorities.clone());
+		}
+	}
+
+	#[pallet::call]
+	impl<T: Config> Pallet<T> {
+		/// Legacy call used in transaction pool benchmarks.
+		#[pallet::call_index(0)]
+		#[pallet::weight(100)]
+		pub fn bench_call(_origin: OriginFor<T>, _transfer: TransferData) -> DispatchResult {
+			Ok(())
+		}
+
+		/// Implicitly fill a block body with some data.
+		#[pallet::call_index(1)]
+		#[pallet::weight(100)]
+		pub fn include_data(origin: OriginFor<T>, _data: Vec<u8>) -> DispatchResult {
+			frame_system::ensure_signed(origin)?;
+			Ok(())
+		}
+
+		/// Put/delete some data from storage. Intended to use as an unsigned extrinsic.
+		#[pallet::call_index(2)]
+		#[pallet::weight(100)]
+		pub fn storage_change(
+			_origin: OriginFor<T>,
+			key: Vec<u8>,
+			value: Option<Vec<u8>>,
+		) -> DispatchResult {
+			match value {
+				Some(value) => storage::unhashed::put_raw(&key, &value),
+				None => storage::unhashed::kill(&key),
+			}
+			Ok(())
+		}
+
+		/// Write a key value pair to the offchain database.
+		#[pallet::call_index(3)]
+		#[pallet::weight(100)]
+		pub fn offchain_index_set(
+			origin: OriginFor<T>,
+			key: Vec<u8>,
+			value: Vec<u8>,
+		) -> DispatchResult {
+			frame_system::ensure_signed(origin)?;
+			sp_io::offchain_index::set(&key, &value);
+			Ok(())
+		}
+
+		/// Remove a key and an associated value from the offchain database.
+		#[pallet::call_index(4)]
+		#[pallet::weight(100)]
+		pub fn offchain_index_clear(origin: OriginFor<T>, key: Vec<u8>) -> DispatchResult {
+			frame_system::ensure_signed(origin)?;
+			sp_io::offchain_index::clear(&key);
+			Ok(())
+		}
+
+		/// Create an index for this call.
+		#[pallet::call_index(5)]
+		#[pallet::weight(100)]
+		pub fn indexed_call(origin: OriginFor<T>, data: Vec<u8>) -> DispatchResult {
+			frame_system::ensure_signed(origin)?;
+			let content_hash = sp_io::hashing::blake2_256(&data);
+			let extrinsic_index: u32 =
+				storage::unhashed::get(well_known_keys::EXTRINSIC_INDEX).unwrap();
+			sp_io::transaction_index::index(extrinsic_index, data.len() as u32, content_hash);
+			Ok(())
+		}
+
+		/// Deposit given digest items into the system storage. They will be included in a header
+		/// during finalization.
+		#[pallet::call_index(6)]
+		#[pallet::weight(100)]
+		pub fn deposit_log_digest_item(
+			_origin: OriginFor<T>,
+			log: sp_runtime::generic::DigestItem,
+		) -> DispatchResult {
+			<frame_system::Pallet<T>>::deposit_log(log);
+			Ok(())
+		}
+
+		/// This call is validated as `ValidTransaction` with given priority.
+		#[pallet::call_index(7)]
+		#[pallet::weight(100)]
+		pub fn call_with_priority(
+			_origin: OriginFor<T>,
+			_priority: TransactionPriority,
+		) -> DispatchResult {
+			Ok(())
+		}
+
+		/// This call is validated as non-propagable `ValidTransaction`.
+		#[pallet::call_index(8)]
+		#[pallet::weight(100)]
+		pub fn call_do_not_propagate(_origin: OriginFor<T>) -> DispatchResult {
+			Ok(())
+		}
+
+		/// Fill the block weight up to the given ratio.
+		#[pallet::call_index(9)]
+		#[pallet::weight(*_ratio * T::BlockWeights::get().max_block)]
+		pub fn fill_block(origin: OriginFor<T>, _ratio: Perbill) -> DispatchResult {
+			ensure_signed(origin)?;
+			Ok(())
+		}
+
+		/// Read X times from the state some data.
+		///
+		/// Panics if it can not read `X` times.
+		#[pallet::call_index(10)]
+		#[pallet::weight(100)]
+		pub fn read(_origin: OriginFor<T>, count: u32) -> DispatchResult {
+			Self::execute_read(count, false)
+		}
+
+		/// Read X times from the state some data and then panic!
+		///
+		/// Returns `Ok` if it didn't read anything.
+		#[pallet::call_index(11)]
+		#[pallet::weight(100)]
+		pub fn read_and_panic(_origin: OriginFor<T>, count: u32) -> DispatchResult {
+			Self::execute_read(count, true)
+		}
+	}
+
+	impl<T: Config> Pallet<T> {
+		fn execute_read(read: u32, panic_at_end: bool) -> DispatchResult {
+			let mut next_key = vec![];
+			for _ in 0..(read as usize) {
+				if let Some(next) = sp_io::storage::next_key(&next_key) {
+					// Read the value
+					sp_io::storage::get(&next);
+
+					next_key = next;
+				} else {
+					if panic_at_end {
+						return Ok(())
+					} else {
+						panic!("Could not read {read} times from the state");
+					}
+				}
+			}
+
+			if panic_at_end {
+				panic!("BYE")
+			} else {
+				Ok(())
+			}
+		}
+	}
+
+	#[pallet::validate_unsigned]
+	impl<T: Config> ValidateUnsigned for Pallet<T> {
+		type Call = Call<T>;
+
+		fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity {
+			log::trace!(target: LOG_TARGET, "validate_unsigned {call:?}");
+			match call {
+				// Some tests do not need to be complicated with signer and nonce, some need
+				// reproducible block hash (call signature can't be there).
+				// Offchain testing requires storage_change.
+				Call::deposit_log_digest_item { .. } |
+				Call::storage_change { .. } |
+				Call::read { .. } |
+				Call::read_and_panic { .. } => Ok(Default::default()),
+				_ => Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
+			}
+		}
+	}
+}
+
+pub fn validate_runtime_call<T: pallet::Config>(call: &pallet::Call<T>) -> TransactionValidity {
+	log::trace!(target: LOG_TARGET, "validate_runtime_call {call:?}");
+	match call {
+		Call::call_do_not_propagate {} =>
+			Ok(ValidTransaction { propagate: false, ..Default::default() }),
+		Call::call_with_priority { priority } =>
+			Ok(ValidTransaction { priority: *priority, ..Default::default() }),
+		_ => Ok(Default::default()),
+	}
+}
diff --git a/substrate/test-utils/runtime/src/system.rs b/substrate/test-utils/runtime/src/system.rs
deleted file mode 100644
index caabad336c0..00000000000
--- a/substrate/test-utils/runtime/src/system.rs
+++ /dev/null
@@ -1,587 +0,0 @@
-// This file is part of Substrate.
-
-// Copyright (C) Parity Technologies (UK) Ltd.
-// SPDX-License-Identifier: Apache-2.0
-
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// 	http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-//! System manager: Handles all of the top-level stuff; executing block/transaction, setting code
-//! and depositing logs.
-
-use crate::{
-	AccountId, AuthorityId, Block, BlockNumber, Digest, Extrinsic, Header, Runtime, Transfer,
-	H256 as Hash,
-};
-use codec::{Decode, Encode, KeyedVec};
-use frame_support::storage;
-use sp_core::storage::well_known_keys;
-use sp_io::{hashing::blake2_256, storage::root as storage_root, trie};
-use sp_runtime::{
-	generic,
-	traits::Header as _,
-	transaction_validity::{
-		InvalidTransaction, TransactionValidity, TransactionValidityError, ValidTransaction,
-	},
-	ApplyExtrinsicResult,
-};
-use sp_std::prelude::*;
-
-const NONCE_OF: &[u8] = b"nonce:";
-const BALANCE_OF: &[u8] = b"balance:";
-
-pub use self::pallet::*;
-
-#[frame_support::pallet]
-mod pallet {
-	use super::*;
-	use frame_support::pallet_prelude::*;
-
-	#[pallet::pallet]
-	#[pallet::without_storage_info]
-	pub struct Pallet<T>(PhantomData<T>);
-
-	#[pallet::config]
-	pub trait Config: frame_system::Config {}
-
-	#[pallet::storage]
-	pub type ExtrinsicData<T> = StorageMap<_, Blake2_128Concat, u32, Vec<u8>, ValueQuery>;
-
-	// The current block number being processed. Set by `execute_block`.
-	#[pallet::storage]
-	pub type Number<T> = StorageValue<_, BlockNumber, OptionQuery>;
-
-	#[pallet::storage]
-	pub type ParentHash<T> = StorageValue<_, Hash, ValueQuery>;
-
-	#[pallet::storage]
-	pub type NewAuthorities<T> = StorageValue<_, Vec<AuthorityId>, OptionQuery>;
-
-	#[pallet::storage]
-	pub type StorageDigest<T> = StorageValue<_, Digest, OptionQuery>;
-
-	#[pallet::storage]
-	pub type Authorities<T> = StorageValue<_, Vec<AuthorityId>, ValueQuery>;
-
-	#[pallet::genesis_config]
-	#[cfg_attr(feature = "std", derive(Default))]
-	pub struct GenesisConfig {
-		pub authorities: Vec<AuthorityId>,
-	}
-
-	#[pallet::genesis_build]
-	impl<T: Config> GenesisBuild<T> for GenesisConfig {
-		fn build(&self) {
-			<Authorities<T>>::put(self.authorities.clone());
-		}
-	}
-}
-
-pub fn balance_of_key(who: AccountId) -> Vec<u8> {
-	who.to_keyed_vec(BALANCE_OF)
-}
-
-pub fn balance_of(who: AccountId) -> u64 {
-	storage::hashed::get_or(&blake2_256, &balance_of_key(who), 0)
-}
-
-pub fn nonce_of(who: AccountId) -> u64 {
-	storage::hashed::get_or(&blake2_256, &who.to_keyed_vec(NONCE_OF), 0)
-}
-
-pub fn initialize_block(header: &Header) {
-	// populate environment.
-	<Number<Runtime>>::put(&header.number);
-	<ParentHash<Runtime>>::put(&header.parent_hash);
-	<StorageDigest<Runtime>>::put(header.digest());
-	storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &0u32);
-
-	// try to read something that depends on current header digest
-	// so that it'll be included in execution proof
-	if let Some(generic::DigestItem::Other(v)) = header.digest().logs().iter().next() {
-		let _: Option<u32> = storage::unhashed::get(v);
-	}
-}
-
-pub fn authorities() -> Vec<AuthorityId> {
-	<Authorities<Runtime>>::get()
-}
-
-pub fn get_block_number() -> Option<BlockNumber> {
-	<Number<Runtime>>::get()
-}
-
-pub fn take_block_number() -> Option<BlockNumber> {
-	<Number<Runtime>>::take()
-}
-
-#[derive(Copy, Clone)]
-enum Mode {
-	Verify,
-	Overwrite,
-}
-
-/// Actually execute all transitioning for `block`.
-pub fn polish_block(block: &mut Block) {
-	execute_block_with_state_root_handler(block, Mode::Overwrite);
-}
-
-pub fn execute_block(mut block: Block) -> Header {
-	execute_block_with_state_root_handler(&mut block, Mode::Verify)
-}
-
-fn execute_block_with_state_root_handler(block: &mut Block, mode: Mode) -> Header {
-	let header = &mut block.header;
-
-	initialize_block(header);
-
-	// execute transactions
-	block.extrinsics.iter().for_each(|e| {
-		let _ = execute_transaction(e.clone()).unwrap_or_else(|_| panic!("Invalid transaction"));
-	});
-
-	let new_header = finalize_block();
-
-	if let Mode::Overwrite = mode {
-		header.state_root = new_header.state_root;
-	} else {
-		info_expect_equal_hash(&new_header.state_root, &header.state_root);
-		assert_eq!(
-			new_header.state_root, header.state_root,
-			"Storage root must match that calculated.",
-		);
-	}
-
-	if let Mode::Overwrite = mode {
-		header.extrinsics_root = new_header.extrinsics_root;
-	} else {
-		info_expect_equal_hash(&new_header.extrinsics_root, &header.extrinsics_root);
-		assert_eq!(
-			new_header.extrinsics_root, header.extrinsics_root,
-			"Transaction trie root must be valid.",
-		);
-	}
-
-	new_header
-}
-
-/// The block executor.
-pub struct BlockExecutor;
-
-impl frame_support::traits::ExecuteBlock<Block> for BlockExecutor {
-	fn execute_block(block: Block) {
-		execute_block(block);
-	}
-}
-
-/// Execute a transaction outside of the block execution function.
-/// This doesn't attempt to validate anything regarding the block.
-pub fn validate_transaction(utx: Extrinsic) -> TransactionValidity {
-	if check_signature(&utx).is_err() {
-		return InvalidTransaction::BadProof.into()
-	}
-
-	let tx = utx.transfer();
-	let nonce_key = tx.from.to_keyed_vec(NONCE_OF);
-	let expected_nonce: u64 = storage::hashed::get_or(&blake2_256, &nonce_key, 0);
-	if tx.nonce < expected_nonce {
-		return InvalidTransaction::Stale.into()
-	}
-	if tx.nonce > expected_nonce + 64 {
-		return InvalidTransaction::Future.into()
-	}
-
-	let encode = |from: &AccountId, nonce: u64| (from, nonce).encode();
-	let requires = if tx.nonce != expected_nonce && tx.nonce > 0 {
-		vec![encode(&tx.from, tx.nonce - 1)]
-	} else {
-		vec![]
-	};
-
-	let provides = vec![encode(&tx.from, tx.nonce)];
-
-	Ok(ValidTransaction { priority: tx.amount, requires, provides, longevity: 64, propagate: true })
-}
-
-/// Execute a transaction outside of the block execution function.
-/// This doesn't attempt to validate anything regarding the block.
-pub fn execute_transaction(utx: Extrinsic) -> ApplyExtrinsicResult {
-	let extrinsic_index: u32 =
-		storage::unhashed::get(well_known_keys::EXTRINSIC_INDEX).unwrap_or_default();
-	let result = execute_transaction_backend(&utx, extrinsic_index);
-	<ExtrinsicData<Runtime>>::insert(extrinsic_index, utx.encode());
-	storage::unhashed::put(well_known_keys::EXTRINSIC_INDEX, &(extrinsic_index + 1));
-	result
-}
-
-/// Finalize the block.
-pub fn finalize_block() -> Header {
-	use sp_core::storage::StateVersion;
-	let extrinsic_index: u32 = storage::unhashed::take(well_known_keys::EXTRINSIC_INDEX).unwrap();
-	let txs: Vec<_> = (0..extrinsic_index).map(<ExtrinsicData<Runtime>>::take).collect();
-	let extrinsics_root = trie::blake2_256_ordered_root(txs, StateVersion::V0);
-	let number = <Number<Runtime>>::take().expect("Number is set by `initialize_block`");
-	let parent_hash = <ParentHash<Runtime>>::take();
-	let mut digest =
-		<StorageDigest<Runtime>>::take().expect("StorageDigest is set by `initialize_block`");
-
-	let o_new_authorities = <NewAuthorities<Runtime>>::take();
-
-	// This MUST come after all changes to storage are done. Otherwise we will fail the
-	// “Storage root does not match that calculated” assertion.
-	let storage_root = Hash::decode(&mut &storage_root(StateVersion::V1)[..])
-		.expect("`storage_root` is a valid hash");
-
-	if let Some(new_authorities) = o_new_authorities {
-		digest.push(generic::DigestItem::Consensus(*b"aura", new_authorities.encode()));
-		digest.push(generic::DigestItem::Consensus(*b"babe", new_authorities.encode()));
-	}
-
-	Header { number, extrinsics_root, state_root: storage_root, parent_hash, digest }
-}
-
-#[inline(always)]
-fn check_signature(utx: &Extrinsic) -> Result<(), TransactionValidityError> {
-	use sp_runtime::traits::BlindCheckable;
-	utx.clone().check().map_err(|_| InvalidTransaction::BadProof.into()).map(|_| ())
-}
-
-fn execute_transaction_backend(utx: &Extrinsic, extrinsic_index: u32) -> ApplyExtrinsicResult {
-	check_signature(utx)?;
-	match utx {
-		Extrinsic::Transfer { exhaust_resources_when_not_first: true, .. }
-			if extrinsic_index != 0 =>
-			Err(InvalidTransaction::ExhaustsResources.into()),
-		Extrinsic::Transfer { ref transfer, .. } => execute_transfer_backend(transfer),
-		Extrinsic::AuthoritiesChange(ref new_auth) => execute_new_authorities_backend(new_auth),
-		Extrinsic::IncludeData(_) => Ok(Ok(())),
-		Extrinsic::StorageChange(key, value) =>
-			execute_storage_change(key, value.as_ref().map(|v| &**v)),
-		Extrinsic::OffchainIndexSet(key, value) => {
-			sp_io::offchain_index::set(key, value);
-			Ok(Ok(()))
-		},
-		Extrinsic::OffchainIndexClear(key) => {
-			sp_io::offchain_index::clear(key);
-			Ok(Ok(()))
-		},
-		Extrinsic::Store(data) => execute_store(data.clone()),
-		Extrinsic::ReadAndPanic(i) => execute_read(*i, true),
-		Extrinsic::Read(i) => execute_read(*i, false),
-	}
-}
-
-fn execute_read(read: u32, panic_at_end: bool) -> ApplyExtrinsicResult {
-	let mut next_key = vec![];
-	for _ in 0..(read as usize) {
-		if let Some(next) = sp_io::storage::next_key(&next_key) {
-			// Read the value
-			sp_io::storage::get(&next);
-
-			next_key = next;
-		} else {
-			if panic_at_end {
-				return Ok(Ok(()))
-			} else {
-				panic!("Could not read {read} times from the state");
-			}
-		}
-	}
-
-	if panic_at_end {
-		panic!("BYE")
-	} else {
-		Ok(Ok(()))
-	}
-}
-
-fn execute_transfer_backend(tx: &Transfer) -> ApplyExtrinsicResult {
-	// check nonce
-	let nonce_key = tx.from.to_keyed_vec(NONCE_OF);
-	let expected_nonce: u64 = storage::hashed::get_or(&blake2_256, &nonce_key, 0);
-	if tx.nonce != expected_nonce {
-		return Err(InvalidTransaction::Stale.into())
-	}
-
-	// increment nonce in storage
-	storage::hashed::put(&blake2_256, &nonce_key, &(expected_nonce + 1));
-
-	// check sender balance
-	let from_balance_key = tx.from.to_keyed_vec(BALANCE_OF);
-	let from_balance: u64 = storage::hashed::get_or(&blake2_256, &from_balance_key, 0);
-
-	// enact transfer
-	if tx.amount > from_balance {
-		return Err(InvalidTransaction::Payment.into())
-	}
-	let to_balance_key = tx.to.to_keyed_vec(BALANCE_OF);
-	let to_balance: u64 = storage::hashed::get_or(&blake2_256, &to_balance_key, 0);
-	storage::hashed::put(&blake2_256, &from_balance_key, &(from_balance - tx.amount));
-	storage::hashed::put(&blake2_256, &to_balance_key, &(to_balance + tx.amount));
-	Ok(Ok(()))
-}
-
-fn execute_store(data: Vec<u8>) -> ApplyExtrinsicResult {
-	let content_hash = sp_io::hashing::blake2_256(&data);
-	let extrinsic_index: u32 = storage::unhashed::get(well_known_keys::EXTRINSIC_INDEX).unwrap();
-	sp_io::transaction_index::index(extrinsic_index, data.len() as u32, content_hash);
-	Ok(Ok(()))
-}
-
-fn execute_new_authorities_backend(new_authorities: &[AuthorityId]) -> ApplyExtrinsicResult {
-	<NewAuthorities<Runtime>>::put(new_authorities.to_vec());
-	Ok(Ok(()))
-}
-
-fn execute_storage_change(key: &[u8], value: Option<&[u8]>) -> ApplyExtrinsicResult {
-	match value {
-		Some(value) => storage::unhashed::put_raw(key, value),
-		None => storage::unhashed::kill(key),
-	}
-	Ok(Ok(()))
-}
-
-#[cfg(feature = "std")]
-fn info_expect_equal_hash(given: &Hash, expected: &Hash) {
-	use sp_core::hexdisplay::HexDisplay;
-	if given != expected {
-		println!(
-			"Hash: given={}, expected={}",
-			HexDisplay::from(given.as_fixed_bytes()),
-			HexDisplay::from(expected.as_fixed_bytes()),
-		);
-	}
-}
-
-#[cfg(not(feature = "std"))]
-fn info_expect_equal_hash(given: &Hash, expected: &Hash) {
-	if given != expected {
-		sp_runtime::print("Hash not equal");
-		sp_runtime::print(given.as_bytes());
-		sp_runtime::print(expected.as_bytes());
-	}
-}
-
-#[cfg(test)]
-mod tests {
-	use super::*;
-
-	use crate::{wasm_binary_unwrap, Header, Transfer};
-	use sc_executor::{NativeElseWasmExecutor, WasmExecutor};
-	use sp_core::{
-		map,
-		traits::{CallContext, CodeExecutor, RuntimeCode},
-	};
-	use sp_io::{hashing::twox_128, TestExternalities};
-	use substrate_test_runtime_client::{AccountKeyring, Sr25519Keyring};
-
-	// Declare an instance of the native executor dispatch for the test runtime.
-	pub struct NativeDispatch;
-
-	impl sc_executor::NativeExecutionDispatch for NativeDispatch {
-		type ExtendHostFunctions = ();
-
-		fn dispatch(method: &str, data: &[u8]) -> Option<Vec<u8>> {
-			crate::api::dispatch(method, data)
-		}
-
-		fn native_version() -> sc_executor::NativeVersion {
-			crate::native_version()
-		}
-	}
-
-	fn executor() -> NativeElseWasmExecutor<NativeDispatch> {
-		NativeElseWasmExecutor::new_with_wasm_executor(WasmExecutor::builder().build())
-	}
-
-	fn new_test_ext() -> TestExternalities {
-		let authorities = vec![
-			Sr25519Keyring::Alice.to_raw_public(),
-			Sr25519Keyring::Bob.to_raw_public(),
-			Sr25519Keyring::Charlie.to_raw_public(),
-		];
-
-		TestExternalities::new_with_code(
-			wasm_binary_unwrap(),
-			sp_core::storage::Storage {
-				top: map![
-					twox_128(b"latest").to_vec() => vec![69u8; 32],
-					twox_128(b"sys:auth").to_vec() => authorities.encode(),
-					blake2_256(&AccountKeyring::Alice.to_raw_public().to_keyed_vec(b"balance:")).to_vec() => {
-						vec![111u8, 0, 0, 0, 0, 0, 0, 0]
-					},
-				],
-				children_default: map![],
-			},
-		)
-	}
-
-	fn block_import_works<F>(block_executor: F)
-	where
-		F: Fn(Block, &mut TestExternalities),
-	{
-		let h = Header {
-			parent_hash: [69u8; 32].into(),
-			number: 1,
-			state_root: Default::default(),
-			extrinsics_root: Default::default(),
-			digest: Default::default(),
-		};
-		let mut b = Block { header: h, extrinsics: vec![] };
-
-		new_test_ext().execute_with(|| polish_block(&mut b));
-
-		block_executor(b, &mut new_test_ext());
-	}
-
-	#[test]
-	fn block_import_works_native() {
-		block_import_works(|b, ext| {
-			ext.execute_with(|| {
-				execute_block(b);
-			})
-		});
-	}
-
-	#[test]
-	fn block_import_works_wasm() {
-		block_import_works(|b, ext| {
-			let mut ext = ext.ext();
-			let runtime_code = RuntimeCode {
-				code_fetcher: &sp_core::traits::WrappedRuntimeCode(wasm_binary_unwrap().into()),
-				hash: Vec::new(),
-				heap_pages: None,
-			};
-
-			executor()
-				.call(
-					&mut ext,
-					&runtime_code,
-					"Core_execute_block",
-					&b.encode(),
-					false,
-					CallContext::Offchain,
-				)
-				.0
-				.unwrap();
-		})
-	}
-
-	fn block_import_with_transaction_works<F>(block_executor: F)
-	where
-		F: Fn(Block, &mut TestExternalities),
-	{
-		let mut b1 = Block {
-			header: Header {
-				parent_hash: [69u8; 32].into(),
-				number: 1,
-				state_root: Default::default(),
-				extrinsics_root: Default::default(),
-				digest: Default::default(),
-			},
-			extrinsics: vec![Transfer {
-				from: AccountKeyring::Alice.into(),
-				to: AccountKeyring::Bob.into(),
-				amount: 69,
-				nonce: 0,
-			}
-			.into_signed_tx()],
-		};
-
-		let mut dummy_ext = new_test_ext();
-		dummy_ext.execute_with(|| polish_block(&mut b1));
-
-		let mut b2 = Block {
-			header: Header {
-				parent_hash: b1.header.hash(),
-				number: 2,
-				state_root: Default::default(),
-				extrinsics_root: Default::default(),
-				digest: Default::default(),
-			},
-			extrinsics: vec![
-				Transfer {
-					from: AccountKeyring::Bob.into(),
-					to: AccountKeyring::Alice.into(),
-					amount: 27,
-					nonce: 0,
-				}
-				.into_signed_tx(),
-				Transfer {
-					from: AccountKeyring::Alice.into(),
-					to: AccountKeyring::Charlie.into(),
-					amount: 69,
-					nonce: 1,
-				}
-				.into_signed_tx(),
-			],
-		};
-
-		dummy_ext.execute_with(|| polish_block(&mut b2));
-		drop(dummy_ext);
-
-		let mut t = new_test_ext();
-
-		t.execute_with(|| {
-			assert_eq!(balance_of(AccountKeyring::Alice.into()), 111);
-			assert_eq!(balance_of(AccountKeyring::Bob.into()), 0);
-		});
-
-		block_executor(b1, &mut t);
-
-		t.execute_with(|| {
-			assert_eq!(balance_of(AccountKeyring::Alice.into()), 42);
-			assert_eq!(balance_of(AccountKeyring::Bob.into()), 69);
-		});
-
-		block_executor(b2, &mut t);
-
-		t.execute_with(|| {
-			assert_eq!(balance_of(AccountKeyring::Alice.into()), 0);
-			assert_eq!(balance_of(AccountKeyring::Bob.into()), 42);
-			assert_eq!(balance_of(AccountKeyring::Charlie.into()), 69);
-		});
-	}
-
-	#[test]
-	fn block_import_with_transaction_works_native() {
-		block_import_with_transaction_works(|b, ext| {
-			ext.execute_with(|| {
-				execute_block(b);
-			})
-		});
-	}
-
-	#[test]
-	fn block_import_with_transaction_works_wasm() {
-		block_import_with_transaction_works(|b, ext| {
-			let mut ext = ext.ext();
-			let runtime_code = RuntimeCode {
-				code_fetcher: &sp_core::traits::WrappedRuntimeCode(wasm_binary_unwrap().into()),
-				hash: Vec::new(),
-				heap_pages: None,
-			};
-
-			executor()
-				.call(
-					&mut ext,
-					&runtime_code,
-					"Core_execute_block",
-					&b.encode(),
-					false,
-					CallContext::Offchain,
-				)
-				.0
-				.unwrap();
-		})
-	}
-}
diff --git a/substrate/test-utils/runtime/transaction-pool/src/lib.rs b/substrate/test-utils/runtime/transaction-pool/src/lib.rs
index 8a39b829504..8e284496616 100644
--- a/substrate/test-utils/runtime/transaction-pool/src/lib.rs
+++ b/substrate/test-utils/runtime/transaction-pool/src/lib.rs
@@ -35,7 +35,10 @@ use sp_runtime::{
 };
 use std::collections::{BTreeMap, HashMap, HashSet};
 use substrate_test_runtime_client::{
-	runtime::{AccountId, Block, BlockNumber, Extrinsic, Hash, Header, Index, Transfer},
+	runtime::{
+		AccountId, Block, BlockNumber, Extrinsic, ExtrinsicBuilder, Hash, Header, Index, Transfer,
+		TransferData,
+	},
 	AccountKeyring::{self, *},
 };
 
@@ -276,7 +279,7 @@ impl sc_transaction_pool::ChainApi for TestApi {
 			Err(e) => return ready(Err(e)),
 		}
 
-		let (requires, provides) = if let Some(transfer) = uxt.try_transfer() {
+		let (requires, provides) = if let Ok(transfer) = TransferData::try_from(&uxt) {
 			let chain_nonce = self.chain.read().nonces.get(&transfer.from).cloned().unwrap_or(0);
 			let requires =
 				if chain_nonce == transfer.nonce { vec![] } else { vec![vec![chain_nonce as u8]] };
@@ -377,6 +380,5 @@ impl sp_blockchain::HeaderMetadata<Block> for TestApi {
 pub fn uxt(who: AccountKeyring, nonce: Index) -> Extrinsic {
 	let dummy = codec::Decode::decode(&mut TrailingZeroInput::zeroes()).unwrap();
 	let transfer = Transfer { from: who.into(), to: dummy, nonce, amount: 1 };
-	let signature = transfer.using_encoded(|e| who.sign(e));
-	Extrinsic::Transfer { transfer, signature, exhaust_resources_when_not_first: false }
+	ExtrinsicBuilder::new_transfer(transfer).build()
 }
diff --git a/substrate/utils/frame/rpc/system/src/lib.rs b/substrate/utils/frame/rpc/system/src/lib.rs
index 46d8472b27f..26efa02970e 100644
--- a/substrate/utils/frame/rpc/system/src/lib.rs
+++ b/substrate/utils/frame/rpc/system/src/lib.rs
@@ -243,7 +243,7 @@ mod tests {
 				amount: 5,
 				nonce,
 			};
-			t.into_signed_tx()
+			t.into_unchecked_extrinsic()
 		};
 		// Populate the pool
 		let ext0 = new_transaction(0);
@@ -297,7 +297,7 @@ mod tests {
 			amount: 5,
 			nonce: 0,
 		}
-		.into_signed_tx();
+		.into_unchecked_extrinsic();
 
 		// when
 		let bytes = accounts.dry_run(tx.encode().into(), None).await.expect("Call is successful");
@@ -325,13 +325,13 @@ mod tests {
 			amount: 5,
 			nonce: 100,
 		}
-		.into_signed_tx();
+		.into_unchecked_extrinsic();
 
 		// when
 		let bytes = accounts.dry_run(tx.encode().into(), None).await.expect("Call is successful");
 
 		// then
 		let apply_res: ApplyExtrinsicResult = Decode::decode(&mut bytes.as_ref()).unwrap();
-		assert_eq!(apply_res, Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)));
+		assert_eq!(apply_res, Err(TransactionValidityError::Invalid(InvalidTransaction::Future)));
 	}
 }
-- 
GitLab