From 2dc281b48289f5aa6ec17ba00fad72da16da1c24 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastian=20K=C3=B6cher?= <bkchr@users.noreply.github.com>
Date: Sat, 12 Jun 2021 19:21:46 +0100
Subject: [PATCH] Bring support for calling `check_inherents` (#490)

* Start

* More work

* Add proc-macro for `validate_block`

* Make everything compile

* Add some test
---
 cumulus/Cargo.lock                            | 232 +++++++++---------
 cumulus/Cargo.toml                            |   1 +
 cumulus/pallets/aura-ext/src/lib.rs           |  10 +-
 cumulus/pallets/parachain-system/Cargo.toml   |   8 +-
 .../parachain-system/proc-macro/Cargo.toml    |  19 ++
 .../parachain-system/proc-macro/src/lib.rs    | 144 +++++++++++
 cumulus/pallets/parachain-system/src/lib.rs   |  67 +++--
 .../src/relay_state_snapshot.rs               | 198 ++++++++-------
 .../src/validate_block/implementation.rs      |  76 ++++--
 .../src/validate_block/mod.rs                 |  61 -----
 .../src/validate_block/tests.rs               |  49 +++-
 .../rococo-runtime/src/lib.rs                 |  20 +-
 .../shell-runtime/src/lib.rs                  |  17 +-
 .../statemine-runtime/src/lib.rs              |  20 +-
 .../statemint-runtime/src/lib.rs              |  20 +-
 .../westmint-runtime/src/lib.rs               |  20 +-
 .../parachain-inherent/src/client_side.rs     |   7 +-
 .../primitives/parachain-inherent/src/lib.rs  |   1 +
 cumulus/test/relay-sproof-builder/src/lib.rs  |  11 +-
 cumulus/test/runtime/src/lib.rs               |  27 +-
 20 files changed, 683 insertions(+), 325 deletions(-)
 create mode 100644 cumulus/pallets/parachain-system/proc-macro/Cargo.toml
 create mode 100644 cumulus/pallets/parachain-system/proc-macro/src/lib.rs

diff --git a/cumulus/Cargo.lock b/cumulus/Cargo.lock
index 6d34b3fca95..a4416fa1d1d 100644
--- a/cumulus/Cargo.lock
+++ b/cumulus/Cargo.lock
@@ -204,7 +204,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5"
 dependencies = [
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -357,9 +357,9 @@ version = "0.1.50"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0b98e84bbb4cbcdd97da190ba0c58a1bb0de2c1fdf67d159e192ed766aeca722"
 dependencies = [
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -557,7 +557,7 @@ dependencies = [
  "lazy_static",
  "lazycell",
  "peeking_take_while",
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
  "regex",
  "rustc-hash",
@@ -1380,7 +1380,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e8f45d9ad417bcef4817d614a501ab55cdd96a6fdb24f49aab89a54acfd66b19"
 dependencies = [
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -1651,6 +1651,7 @@ dependencies = [
 name = "cumulus-pallet-parachain-system"
 version = "0.1.0"
 dependencies = [
+ "cumulus-pallet-parachain-system-proc-macro",
  "cumulus-primitives-core",
  "cumulus-primitives-parachain-inherent",
  "cumulus-test-client",
@@ -1659,11 +1660,9 @@ dependencies = [
  "environmental",
  "frame-support",
  "frame-system",
- "hash-db",
  "hex-literal 0.2.1",
  "lazy_static",
  "log",
- "memory-db",
  "pallet-balances",
  "parity-scale-codec",
  "polkadot-parachain",
@@ -1684,10 +1683,19 @@ dependencies = [
  "sp-trie",
  "sp-version",
  "substrate-test-runtime-client",
- "trie-db",
  "xcm",
 ]
 
+[[package]]
+name = "cumulus-pallet-parachain-system-proc-macro"
+version = "0.1.0"
+dependencies = [
+ "proc-macro-crate 1.0.0",
+ "proc-macro2 1.0.27",
+ "quote 1.0.9",
+ "syn 1.0.73",
+]
+
 [[package]]
 name = "cumulus-pallet-xcm"
 version = "0.1.0"
@@ -2088,7 +2096,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f0f83e699727abca3c56e187945f303389590305ab2f0185ea445aa66e8d5f2a"
 dependencies = [
  "data-encoding",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -2097,9 +2105,9 @@ version = "2.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
 dependencies = [
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -2122,9 +2130,9 @@ version = "0.99.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "41cb0e6161ad61ed084a36ba71fbba9e3ac5aee3606fb607fe08da6acbcf3d8c"
 dependencies = [
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -2230,9 +2238,9 @@ version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "558e40ea573c374cf53507fd240b7ee2f5477df7cfebdb97323ec61c719399c5"
 dependencies = [
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -2277,9 +2285,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595"
 dependencies = [
  "heck",
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -2297,9 +2305,9 @@ version = "0.6.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "946ee94e3dbf58fdd324f9ce245c7b238d46a66f00e86a020b71996349e46cce"
 dependencies = [
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -2308,9 +2316,9 @@ version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4e58b112d5099aa0857c5d05f0eacab86406dd8c0f85fe5d320a13256d29ecf4"
 dependencies = [
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -2455,9 +2463,9 @@ version = "0.1.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
 dependencies = [
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
  "synstructure",
 ]
 
@@ -2686,9 +2694,9 @@ source = "git+https://github.com/paritytech/substrate?branch=master#a2f48bf96eec
 dependencies = [
  "Inflector",
  "frame-support-procedural-tools",
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -2698,9 +2706,9 @@ source = "git+https://github.com/paritytech/substrate?branch=master#a2f48bf96eec
 dependencies = [
  "frame-support-procedural-tools-derive",
  "proc-macro-crate 1.0.0",
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -2708,9 +2716,9 @@ name = "frame-support-procedural-tools-derive"
 version = "3.0.0"
 source = "git+https://github.com/paritytech/substrate?branch=master#a2f48bf96eecbb5cd1f45bd5319ba814595eaaef"
 dependencies = [
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -2924,9 +2932,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "668c6733a182cd7deb4f1de7ba3bf2120823835b3bcfbeacf7d2c4a773c1bb8b"
 dependencies = [
  "proc-macro-hack",
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -3554,9 +3562,9 @@ version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d5dacb10c5b3bb92d46ba347505a9041e676bb20ad220101326bffb0c93031ee"
 dependencies = [
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -3724,9 +3732,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "99a847f9ec7bb52149b2786a17c9cb260d6effc6b8eeb8c16b343a487a7563a3"
 dependencies = [
  "proc-macro-crate 0.1.5",
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -3809,9 +3817,9 @@ checksum = "3b4c85cfa6767333f3e5f3b2f2f765dad2727b0033ee270ae07c599bf43ed5ae"
 dependencies = [
  "Inflector",
  "proc-macro-crate 1.0.0",
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -4412,7 +4420,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "365b0a699fea5168676840567582a012ea297b1ca02eee467e58301b9c9c5eed"
 dependencies = [
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -4684,9 +4692,9 @@ version = "3.0.0"
 source = "git+https://github.com/paritytech/substrate?branch=master#a2f48bf96eecbb5cd1f45bd5319ba814595eaaef"
 dependencies = [
  "proc-macro-crate 1.0.0",
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -4802,9 +4810,9 @@ version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "19ce18b5423c573a13e80cb3046ea0af6379ef725dc3af4886bdb8f4e5093068"
 dependencies = [
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -4935,9 +4943,9 @@ checksum = "85ee3c48cb9d9b275ad967a0e96715badc13c6029adb92f34fa17b9ff28fd81f"
 dependencies = [
  "proc-macro-crate 0.1.5",
  "proc-macro-error",
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
  "synstructure",
 ]
 
@@ -5791,9 +5799,9 @@ version = "3.0.0"
 source = "git+https://github.com/paritytech/substrate?branch=master#a2f48bf96eecbb5cd1f45bd5319ba814595eaaef"
 dependencies = [
  "proc-macro-crate 1.0.0",
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -6035,9 +6043,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f44c5f94427bd0b5076e8f7e15ca3f60a4d8ac0077e4793884e6fdfd8915344e"
 dependencies = [
  "proc-macro-crate 0.1.5",
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -6089,8 +6097,8 @@ version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f557c32c6d268a07c921471619c0295f5efad3a0e76d4f97a05c091a51d110b2"
 dependencies = [
- "proc-macro2 1.0.26",
- "syn 1.0.68",
+ "proc-macro2 1.0.27",
+ "syn 1.0.73",
  "synstructure",
 ]
 
@@ -6326,9 +6334,9 @@ checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55"
 dependencies = [
  "pest",
  "pest_meta",
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -6376,9 +6384,9 @@ version = "0.4.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "65ad2ae56b6abe3a1ee25f15ee605bacadb9a764edaba9c2bf4103800d4a1895"
 dependencies = [
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -6387,9 +6395,9 @@ version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "caa25a6393f22ce819b0f50e0be89287292fda8d425be38ee0ca14c4931d9e71"
 dependencies = [
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -7116,9 +7124,9 @@ version = "0.1.0"
 source = "git+https://github.com/paritytech/polkadot?branch=master#a803f87252b82f66df3c3ec1c23b94b50090ef8d"
 dependencies = [
  "assert_matches",
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -7127,9 +7135,9 @@ version = "0.1.0"
 source = "git+https://github.com/paritytech/polkadot?branch=master#a803f87252b82f66df3c3ec1c23b94b50090ef8d"
 dependencies = [
  "assert_matches",
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -7685,9 +7693,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
 dependencies = [
  "proc-macro-error-attr",
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
  "version_check",
 ]
 
@@ -7697,7 +7705,7 @@ version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
 dependencies = [
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
  "version_check",
 ]
@@ -7725,9 +7733,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.26"
+version = "1.0.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
+checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038"
 dependencies = [
  "unicode-xid 0.2.1",
 ]
@@ -7782,9 +7790,9 @@ checksum = "169a15f3008ecb5160cba7d37bcd690a7601b6d30cfb87a117d45e59d52af5d4"
 dependencies = [
  "anyhow",
  "itertools 0.9.0",
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -7855,7 +7863,7 @@ version = "1.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
 dependencies = [
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
 ]
 
 [[package]]
@@ -8197,9 +8205,9 @@ version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4c38e3aecd2b21cb3959637b883bb3714bc7e43f0268b9a29d3743ee3e55cdd2"
 dependencies = [
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -8646,9 +8654,9 @@ version = "3.0.0"
 source = "git+https://github.com/paritytech/substrate?branch=master#a2f48bf96eecbb5cd1f45bd5319ba814595eaaef"
 dependencies = [
  "proc-macro-crate 1.0.0",
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -9500,9 +9508,9 @@ version = "3.0.0"
 source = "git+https://github.com/paritytech/substrate?branch=master#a2f48bf96eecbb5cd1f45bd5319ba814595eaaef"
 dependencies = [
  "proc-macro-crate 1.0.0",
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -9615,9 +9623,9 @@ version = "0.10.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b12bd20b94c7cdfda8c7ba9b92ad0d9a56e3fa018c25fca83b51aa664c9b4c0d"
 dependencies = [
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -9743,9 +9751,9 @@ version = "1.0.126"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43"
 dependencies = [
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -10031,9 +10039,9 @@ source = "git+https://github.com/paritytech/substrate?branch=master#a2f48bf96eec
 dependencies = [
  "blake2-rfc",
  "proc-macro-crate 1.0.0",
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -10273,9 +10281,9 @@ name = "sp-debug-derive"
 version = "3.0.0"
 source = "git+https://github.com/paritytech/substrate?branch=master#a2f48bf96eecbb5cd1f45bd5319ba814595eaaef"
 dependencies = [
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -10401,9 +10409,9 @@ version = "3.0.0"
 source = "git+https://github.com/paritytech/substrate?branch=master#a2f48bf96eecbb5cd1f45bd5319ba814595eaaef"
 dependencies = [
  "proc-macro-crate 1.0.0",
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -10481,9 +10489,9 @@ source = "git+https://github.com/paritytech/substrate?branch=master#a2f48bf96eec
 dependencies = [
  "Inflector",
  "proc-macro-crate 1.0.0",
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -10697,9 +10705,9 @@ source = "git+https://github.com/paritytech/substrate?branch=master#a2f48bf96eec
 dependencies = [
  "parity-scale-codec",
  "proc-macro-crate 1.0.0",
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -10903,9 +10911,9 @@ checksum = "f2261c91034a1edc3fc4d1b80e89d82714faede0515c14a75da10cb941546bbf"
 dependencies = [
  "cfg_aliases",
  "memchr",
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -10973,9 +10981,9 @@ checksum = "5ba9cdfda491b814720b6b06e0cac513d922fc407582032e8706e9f137976f90"
 dependencies = [
  "heck",
  "proc-macro-error",
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -10994,9 +11002,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ee8bc6b87a5112aeeab1f4a9f7ab634fe6cbefc4850006df31267f4cfb9e3149"
 dependencies = [
  "heck",
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -11165,7 +11173,7 @@ source = "git+https://github.com/paritytech/substrate?branch=master#5d89967d7cc1
 dependencies = [
  "proc-macro-crate 1.0.0",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -11225,11 +11233,11 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "1.0.68"
+version = "1.0.73"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ce15dd3ed8aa2f8eeac4716d6ef5ab58b6b9256db41d7e1a0224c2788e8fd87"
+checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7"
 dependencies = [
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
  "unicode-xid 0.2.1",
 ]
@@ -11240,9 +11248,9 @@ version = "0.12.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
 dependencies = [
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
  "unicode-xid 0.2.1",
 ]
 
@@ -11311,9 +11319,9 @@ version = "1.0.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0"
 dependencies = [
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -11527,9 +11535,9 @@ version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e44da00bfc73a25f814cd8d7e57a68a5c31b74b3152a0a1d1f590c97ed06265a"
 dependencies = [
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -11732,9 +11740,9 @@ version = "0.1.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c42e6fa53307c8a17e4ccd4dc81cf5ec38db9209f59b222210375b54ee40d1e2"
 dependencies = [
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
 ]
 
 [[package]]
@@ -12179,9 +12187,9 @@ dependencies = [
  "bumpalo",
  "lazy_static",
  "log",
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
  "wasm-bindgen-shared",
 ]
 
@@ -12213,9 +12221,9 @@ version = "0.2.73"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d53739ff08c8a68b0fdbcd54c372b8ab800b1449ab3c9d706503bc7dd1621b2c"
 dependencies = [
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
@@ -12861,9 +12869,9 @@ version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c3f369ddb18862aba61aa49bf31e74d29f0f162dec753063200e1dc084345d16"
 dependencies = [
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.27",
  "quote 1.0.9",
- "syn 1.0.68",
+ "syn 1.0.73",
  "synstructure",
 ]
 
diff --git a/cumulus/Cargo.toml b/cumulus/Cargo.toml
index a1bbff9c537..ae32d360658 100644
--- a/cumulus/Cargo.toml
+++ b/cumulus/Cargo.toml
@@ -11,6 +11,7 @@ members = [
 	"pallets/collator-selection",
 	"pallets/dmp-queue",
 	"pallets/parachain-system",
+	"pallets/parachain-system/proc-macro",
 	"pallets/session-benchmarking",
 	"pallets/xcm",
 	"pallets/xcmp-queue",
diff --git a/cumulus/pallets/aura-ext/src/lib.rs b/cumulus/pallets/aura-ext/src/lib.rs
index 3638f5d9181..3ea994f42cb 100644
--- a/cumulus/pallets/aura-ext/src/lib.rs
+++ b/cumulus/pallets/aura-ext/src/lib.rs
@@ -25,10 +25,12 @@
 //! ```
 //!# struct Runtime;
 //!# struct Executive;
-//! cumulus_pallet_parachain_system::register_validate_block!(
-//!     Runtime,
-//!     cumulus_pallet_aura_ext::BlockExecutor::<Runtime, Executive>,
-//! );
+//!# struct CheckInherents;
+//! cumulus_pallet_parachain_system::register_validate_block! {
+//!     Runtime = Runtime,
+//!     BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::<Runtime, Executive>,
+//!     CheckInherents = CheckInherents,
+//! }
 //! ```
 
 #![cfg_attr(not(feature = "std"), no_std)]
diff --git a/cumulus/pallets/parachain-system/Cargo.toml b/cumulus/pallets/parachain-system/Cargo.toml
index 5202fd0518e..f265fcaf68c 100644
--- a/cumulus/pallets/parachain-system/Cargo.toml
+++ b/cumulus/pallets/parachain-system/Cargo.toml
@@ -9,6 +9,7 @@ description = "Base pallet for cumulus-based parachains"
 # Cumulus dependencies
 cumulus-primitives-core = { path = "../../primitives/core", default-features = false }
 cumulus-primitives-parachain-inherent = { path = "../../primitives/parachain-inherent", default-features = false }
+cumulus-pallet-parachain-system-proc-macro = { path = "proc-macro", default-features = false }
 
 # Polkadot dependencies
 polkadot-parachain = { git = "https://github.com/paritytech/polkadot", default-features = false, features = [ "wasm-api" ], branch = "master" }
@@ -31,10 +32,7 @@ sp-externalities = { git = "https://github.com/paritytech/substrate", default-fe
 # Other Dependencies
 codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = ["derive"]}
 serde = { version = "1.0.101", optional = true, features = ["derive"] }
-hash-db = { version = "0.15.2", default-features = false }
 log = { version = "0.4.14", default-features = false }
-memory-db = { version = "0.26.0", default-features = false }
-trie-db = { version = "0.22.0", default-features = false }
 environmental = { version = "1.1.2", default-features = false }
 
 [dev-dependencies]
@@ -63,16 +61,14 @@ std = [
 	"sp-runtime/std",
 	"sp-io/std",
 	"sp-std/std",
-	"hash-db/std",
 	"log/std",
-	"memory-db/std",
-	"trie-db/std",
 	"sp-state-machine/std",
 	"sp-trie/std",
 	"sp-externalities/std",
 	"frame-system/std",
 	"cumulus-primitives-core/std",
 	"cumulus-primitives-parachain-inherent/std",
+	"cumulus-pallet-parachain-system-proc-macro/std",
 	"environmental/std",
 	"xcm/std"
 ]
diff --git a/cumulus/pallets/parachain-system/proc-macro/Cargo.toml b/cumulus/pallets/parachain-system/proc-macro/Cargo.toml
new file mode 100644
index 00000000000..ea47cfdfc44
--- /dev/null
+++ b/cumulus/pallets/parachain-system/proc-macro/Cargo.toml
@@ -0,0 +1,19 @@
+[package]
+name = "cumulus-pallet-parachain-system-proc-macro"
+version = "0.1.0"
+authors = ["Parity Technologies <admin@parity.io>"]
+edition = "2018"
+description = "Proc macros provided by the parachain-system pallet"
+
+[lib]
+proc-macro = true
+
+[dependencies]
+syn = "1.0.73"
+proc-macro2 = "1.0.27"
+quote = "1.0.9"
+proc-macro-crate = "1.0.0"
+
+[features]
+default = [ "std" ]
+std = []
diff --git a/cumulus/pallets/parachain-system/proc-macro/src/lib.rs b/cumulus/pallets/parachain-system/proc-macro/src/lib.rs
new file mode 100644
index 00000000000..c56387707d9
--- /dev/null
+++ b/cumulus/pallets/parachain-system/proc-macro/src/lib.rs
@@ -0,0 +1,144 @@
+// Copyright 2021 Parity Technologies (UK) Ltd.
+// This file is part of Cumulus.
+
+// Cumulus is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Cumulus is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Cumulus.  If not, see <http://www.gnu.org/licenses/>.
+
+use proc_macro2::{Span, TokenStream};
+use proc_macro_crate::{crate_name, FoundCrate};
+use syn::{
+	parse::{Parse, ParseStream},
+	spanned::Spanned,
+	token, Error, Ident, Path,
+};
+
+mod keywords {
+	syn::custom_keyword!(Runtime);
+	syn::custom_keyword!(BlockExecutor);
+	syn::custom_keyword!(CheckInherents);
+}
+
+struct Input {
+	runtime: Path,
+	block_executor: Path,
+	check_inherents: Path,
+}
+
+impl Parse for Input {
+	fn parse(input: ParseStream) -> Result<Self, Error> {
+		let mut runtime = None;
+		let mut block_executor = None;
+		let mut check_inherents = None;
+
+		fn parse_inner<KW: Parse + Spanned>(
+			input: ParseStream,
+			result: &mut Option<Path>,
+		) -> Result<(), Error> {
+			let kw = input.parse::<KW>()?;
+
+			if result.is_none() {
+				input.parse::<token::Eq>()?;
+				*result = Some(input.parse::<Path>()?);
+				if input.peek(token::Comma) {
+					input.parse::<token::Comma>()?;
+				}
+
+				Ok(())
+			} else {
+				Err(Error::new(kw.span(), "Is only allowed to be passed once"))
+			}
+		}
+
+		while runtime.is_none() || block_executor.is_none() || check_inherents.is_none() {
+			let lookahead = input.lookahead1();
+
+			if lookahead.peek(keywords::Runtime) {
+				parse_inner::<keywords::Runtime>(input, &mut runtime)?;
+			} else if lookahead.peek(keywords::BlockExecutor) {
+				parse_inner::<keywords::BlockExecutor>(input, &mut block_executor)?;
+			} else if lookahead.peek(keywords::CheckInherents) {
+				parse_inner::<keywords::CheckInherents>(input, &mut check_inherents)?;
+			} else {
+				return Err(lookahead.error());
+			}
+		}
+
+		let rest = input.parse::<TokenStream>()?;
+		if !rest.is_empty() {
+			return Err(Error::new(rest.span(), "Unexpected input data"));
+		}
+
+		Ok(Self {
+			runtime: runtime.expect("Everything is parsed before; qed"),
+			block_executor: block_executor.expect("Everything is parsed before; qed"),
+			check_inherents: check_inherents.expect("Everything is parsed before; qed"),
+		})
+	}
+}
+
+fn crate_() -> Result<Ident, Error> {
+	match crate_name("cumulus-pallet-parachain-system") {
+		Ok(FoundCrate::Itself) => Ok(syn::Ident::new(
+			"cumulus_pallet_parachain_system",
+			Span::call_site(),
+		)),
+		Ok(FoundCrate::Name(name)) => Ok(Ident::new(&name, Span::call_site())),
+		Err(e) => Err(Error::new(Span::call_site(), e)),
+	}
+}
+
+#[proc_macro]
+pub fn register_validate_block(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+	let Input {
+		runtime,
+		check_inherents,
+		block_executor,
+	} = match syn::parse(input) {
+		Ok(t) => t,
+		Err(e) => return e.into_compile_error().into(),
+	};
+
+	let crate_ = match crate_() {
+		Ok(c) => c,
+		Err(e) => return e.into_compile_error().into(),
+	};
+
+	if cfg!(not(feature = "std")) {
+		quote::quote! {
+			#[doc(hidden)]
+			mod parachain_validate_block {
+				use super::*;
+
+				#[no_mangle]
+				unsafe fn validate_block(arguments: *const u8, arguments_len: usize) -> u64 {
+					let params = #crate_::validate_block::polkadot_parachain::load_params(
+						arguments,
+						arguments_len,
+					);
+
+					let res = #crate_::validate_block::implementation::validate_block::<
+						<#runtime as #crate_::validate_block::GetRuntimeBlockType>::RuntimeBlock,
+						#block_executor,
+						#runtime,
+						#check_inherents,
+					>(params);
+
+					#crate_::validate_block::polkadot_parachain::write_result(&res)
+				}
+			}
+		}
+	} else {
+		quote::quote!()
+	}
+	.into()
+}
diff --git a/cumulus/pallets/parachain-system/src/lib.rs b/cumulus/pallets/parachain-system/src/lib.rs
index eb03bb0feda..2e2a9b8e34f 100644
--- a/cumulus/pallets/parachain-system/src/lib.rs
+++ b/cumulus/pallets/parachain-system/src/lib.rs
@@ -30,8 +30,8 @@
 use cumulus_primitives_core::{
 	relay_chain, AbridgedHostConfiguration, ChannelStatus, CollationInfo, DmpMessageHandler,
 	GetChannelInfo, InboundDownwardMessage, InboundHrmpMessage, MessageSendError, OnValidationData,
-	OutboundHrmpMessage, ParaId, PersistedValidationData, UpwardMessage, UpwardMessageSender,
-	XcmpMessageHandler, XcmpMessageSource,
+	OutboundHrmpMessage, ParaId, UpwardMessage, UpwardMessageSender, XcmpMessageHandler,
+	XcmpMessageSource, PersistedValidationData,
 };
 use cumulus_primitives_parachain_inherent::ParachainInherentData;
 use frame_support::{
@@ -46,7 +46,7 @@ use frame_system::{ensure_none, ensure_root};
 use polkadot_parachain::primitives::RelayChainBlockNumber;
 use relay_state_snapshot::MessagingStateSnapshot;
 use sp_runtime::{
-	traits::{BlakeTwo256, Hash},
+	traits::{BlakeTwo256, Block as BlockT, Hash},
 	transaction_validity::{
 		InvalidTransaction, TransactionLongevity, TransactionSource, TransactionValidity,
 		ValidTransaction,
@@ -60,6 +60,31 @@ pub mod validate_block;
 #[cfg(test)]
 mod tests;
 
+/// Register the `validate_block` function that is used by parachains to validate blocks on a
+/// validator.
+///
+/// Does *nothing* when `std` feature is enabled.
+///
+/// Expects as parameters the runtime, a block executor and an inherent checker.
+///
+/// # Example
+///
+/// ```
+///     struct BlockExecutor;
+///     struct Runtime;
+///     struct CheckInherents;
+///
+///     cumulus_pallet_parachain_system::register_validate_block! {
+///         Runtime = Runtime,
+///         BlockExecutor = Executive,
+///         CheckInherents = CheckInherents,
+///     }
+///
+/// # fn main() {}
+/// ```
+pub use cumulus_pallet_parachain_system_proc_macro::register_validate_block;
+pub use relay_state_snapshot::RelayChainStateProof;
+
 pub use pallet::*;
 
 #[frame_support::pallet]
@@ -309,17 +334,19 @@ pub mod pallet {
 				}
 			}
 
-			let (host_config, relevant_messaging_state) =
-				match relay_state_snapshot::extract_from_proof(
-					T::SelfParaId::get(),
-					vfp.relay_parent_storage_root,
-					relay_chain_state,
-				) {
-					Ok(r) => r,
-					Err(err) => {
-						panic!("invalid relay chain merkle proof: {:?}", err);
-					}
-				};
+			let relay_state_proof = RelayChainStateProof::new(
+				T::SelfParaId::get(),
+				vfp.relay_parent_storage_root,
+				relay_chain_state,
+			)
+			.expect("Invalid relay chain state proof");
+
+			let host_config = relay_state_proof
+				.read_abridged_host_configuration()
+				.expect("Invalid host configuration in relay chain state proof");
+			let relevant_messaging_state = relay_state_proof
+				.read_messaging_state_snapshot()
+				.expect("Invalid messaging state in relay chain state proof");
 
 			<ValidationData<T>>::put(&vfp);
 			<RelevantMessagingState<T>>::put(relevant_messaging_state.clone());
@@ -999,3 +1026,15 @@ impl<T: Config> UpwardMessageSender for Pallet<T> {
 		Self::send_upward_message(message)
 	}
 }
+
+/// Something that can check the inherents of a block.
+pub trait CheckInherents<Block: BlockT> {
+	/// Check all inherents of the block.
+	///
+	/// This function gets passed all the extrinsics of the block, so it is up to the callee to
+	/// identify the inherents. The `validation_data` can be used to access the
+	fn check_inherents(
+		extrinsics: &[Block::Extrinsic],
+		validation_data: &RelayChainStateProof,
+	) -> frame_support::inherent::CheckInherentsResult;
+}
diff --git a/cumulus/pallets/parachain-system/src/relay_state_snapshot.rs b/cumulus/pallets/parachain-system/src/relay_state_snapshot.rs
index 1bfe478e329..d2ad2c45a06 100644
--- a/cumulus/pallets/parachain-system/src/relay_state_snapshot.rs
+++ b/cumulus/pallets/parachain-system/src/relay_state_snapshot.rs
@@ -14,13 +14,15 @@
 // You should have received a copy of the GNU General Public License
 // along with Cumulus.  If not, see <http://www.gnu.org/licenses/>.
 
-use codec::{Encode, Decode};
-use cumulus_primitives_core::{relay_chain, AbridgedHostConfiguration, AbridgedHrmpChannel, ParaId};
-use hash_db::{HashDB, EMPTY_PREFIX};
+use codec::{Decode, Encode};
+use cumulus_primitives_core::{
+	relay_chain, AbridgedHostConfiguration, AbridgedHrmpChannel, ParaId,
+};
+use sp_trie::{MemoryDB, HashDBT, EMPTY_PREFIX};
 use sp_runtime::traits::HashFor;
 use sp_state_machine::{Backend, TrieBackend};
-use sp_trie::StorageProof;
 use sp_std::vec::Vec;
+use sp_trie::StorageProof;
 
 /// A snapshot of some messaging related state of relay chain pertaining to the current parachain.
 ///
@@ -61,6 +63,8 @@ pub struct MessagingStateSnapshot {
 pub enum Error {
 	/// The provided proof was created against unexpected storage root.
 	RootMismatch,
+	/// The slot cannot be extracted.
+	Slot(ReadEntryErr),
 	/// The host configuration cannot be extracted.
 	Config(ReadEntryErr),
 	/// The DMQ MQC head cannot be extracted.
@@ -105,94 +109,122 @@ where
 		.ok_or(ReadEntryErr::Absent)
 }
 
-/// Extract the relay chain state from the given storage proof. This function accepts the `para_id`
-/// of the current parachain and the expected storage root the proof should stem from.
-pub fn extract_from_proof(
+/// A state proof extracted from the relay chain.
+///
+/// This state proof is extracted from the relay chain block we are building on top of.
+pub struct RelayChainStateProof {
 	para_id: ParaId,
-	relay_parent_storage_root: relay_chain::v1::Hash,
-	proof: StorageProof,
-) -> Result<(AbridgedHostConfiguration, MessagingStateSnapshot), Error> {
-	let db = proof.into_memory_db::<HashFor<relay_chain::Block>>();
-	if !db.contains(&relay_parent_storage_root, EMPTY_PREFIX) {
-		return Err(Error::RootMismatch);
+	trie_backend: TrieBackend<MemoryDB<HashFor<relay_chain::Block>>, HashFor<relay_chain::Block>>,
+}
+
+impl RelayChainStateProof {
+	/// Create a new instance of `Self`.
+	///
+	/// Returns an error if the given `relay_parent_storage_root` is not the root of the given
+	/// `proof`.
+	pub fn new(
+		para_id: ParaId,
+		relay_parent_storage_root: relay_chain::v1::Hash,
+		proof: StorageProof,
+	) -> Result<Self, Error> {
+		let db = proof.into_memory_db::<HashFor<relay_chain::Block>>();
+		if !db.contains(&relay_parent_storage_root, EMPTY_PREFIX) {
+			return Err(Error::RootMismatch);
+		}
+		let trie_backend = TrieBackend::new(db, relay_parent_storage_root);
+
+		Ok(Self {
+			para_id,
+			trie_backend,
+		})
 	}
-	let backend = TrieBackend::new(db, relay_parent_storage_root);
-
-	let host_config: AbridgedHostConfiguration = read_entry(
-		&backend,
-		relay_chain::well_known_keys::ACTIVE_CONFIG,
-		None,
-	)
-	.map_err(Error::Config)?;
-
-	let dmq_mqc_head: relay_chain::Hash = read_entry(
-		&backend,
-		&relay_chain::well_known_keys::dmq_mqc_head(para_id),
-		Some(Default::default()),
-	)
-	.map_err(Error::DmqMqcHead)?;
-
-	let relay_dispatch_queue_size: (u32, u32) = read_entry(
-		&backend,
-		&relay_chain::well_known_keys::relay_dispatch_queue_size(para_id),
-		Some((0, 0)),
-	)
-	.map_err(Error::RelayDispatchQueueSize)?;
-
-	let ingress_channel_index: Vec<ParaId> = read_entry(
-		&backend,
-		&relay_chain::well_known_keys::hrmp_ingress_channel_index(para_id),
-		Some(Vec::new()),
-	)
-	.map_err(Error::HrmpIngressChannelIndex)?;
-
-	let egress_channel_index: Vec<ParaId> = read_entry(
-		&backend,
-		&relay_chain::well_known_keys::hrmp_egress_channel_index(para_id),
-		Some(Vec::new()),
-	)
-	.map_err(Error::HrmpEgressChannelIndex)?;
-
-	let mut ingress_channels = Vec::with_capacity(ingress_channel_index.len());
-	for sender in ingress_channel_index {
-		let channel_id = relay_chain::v1::HrmpChannelId {
-			sender,
-			recipient: para_id,
-		};
-		let hrmp_channel: AbridgedHrmpChannel = read_entry(
-			&backend,
-			&relay_chain::well_known_keys::hrmp_channels(channel_id),
-			None,
+
+	/// Read the [`MessagingStateSnapshot`] from the relay chain state proof.
+	///
+	/// Returns an error if anything failed at reading or decoding.
+	pub fn read_messaging_state_snapshot(&self) -> Result<MessagingStateSnapshot, Error> {
+		let dmq_mqc_head: relay_chain::Hash = read_entry(
+			&self.trie_backend,
+			&relay_chain::well_known_keys::dmq_mqc_head(self.para_id),
+			Some(Default::default()),
 		)
-		.map_err(|read_err| Error::HrmpChannel(sender, para_id, read_err))?;
-		ingress_channels.push((sender, hrmp_channel));
-	}
+		.map_err(Error::DmqMqcHead)?;
 
-	let mut egress_channels = Vec::with_capacity(egress_channel_index.len());
-	for recipient in egress_channel_index {
-		let channel_id = relay_chain::v1::HrmpChannelId {
-			sender: para_id,
-			recipient,
-		};
-		let hrmp_channel: AbridgedHrmpChannel = read_entry(
-			&backend,
-			&relay_chain::well_known_keys::hrmp_channels(channel_id),
-			None,
+		let relay_dispatch_queue_size: (u32, u32) = read_entry(
+			&self.trie_backend,
+			&relay_chain::well_known_keys::relay_dispatch_queue_size(self.para_id),
+			Some((0, 0)),
 		)
-		.map_err(|read_err| Error::HrmpChannel(para_id, recipient, read_err))?;
-		egress_channels.push((recipient, hrmp_channel));
-	}
+		.map_err(Error::RelayDispatchQueueSize)?;
 
-	// NOTE that ingress_channels and egress_channels promise to be sorted. We satisfy this property
-	// by relying on the fact that `ingress_channel_index` and `egress_channel_index` are themselves sorted.
+		let ingress_channel_index: Vec<ParaId> = read_entry(
+			&self.trie_backend,
+			&relay_chain::well_known_keys::hrmp_ingress_channel_index(self.para_id),
+			Some(Vec::new()),
+		)
+		.map_err(Error::HrmpIngressChannelIndex)?;
 
-	Ok((
-		host_config,
-		MessagingStateSnapshot {
+		let egress_channel_index: Vec<ParaId> = read_entry(
+			&self.trie_backend,
+			&relay_chain::well_known_keys::hrmp_egress_channel_index(self.para_id),
+			Some(Vec::new()),
+		)
+		.map_err(Error::HrmpEgressChannelIndex)?;
+
+		let mut ingress_channels = Vec::with_capacity(ingress_channel_index.len());
+		for sender in ingress_channel_index {
+			let channel_id = relay_chain::v1::HrmpChannelId {
+				sender,
+				recipient: self.para_id,
+			};
+			let hrmp_channel: AbridgedHrmpChannel = read_entry(
+				&self.trie_backend,
+				&relay_chain::well_known_keys::hrmp_channels(channel_id),
+				None,
+			)
+			.map_err(|read_err| Error::HrmpChannel(sender, self.para_id, read_err))?;
+			ingress_channels.push((sender, hrmp_channel));
+		}
+
+		let mut egress_channels = Vec::with_capacity(egress_channel_index.len());
+		for recipient in egress_channel_index {
+			let channel_id = relay_chain::v1::HrmpChannelId {
+				sender: self.para_id,
+				recipient,
+			};
+			let hrmp_channel: AbridgedHrmpChannel = read_entry(
+				&self.trie_backend,
+				&relay_chain::well_known_keys::hrmp_channels(channel_id),
+				None,
+			)
+			.map_err(|read_err| Error::HrmpChannel(self.para_id, recipient, read_err))?;
+			egress_channels.push((recipient, hrmp_channel));
+		}
+
+		// NOTE that ingress_channels and egress_channels promise to be sorted. We satisfy this property
+		// by relying on the fact that `ingress_channel_index` and `egress_channel_index` are themselves sorted.
+		Ok(MessagingStateSnapshot {
 			dmq_mqc_head,
 			relay_dispatch_queue_size,
 			ingress_channels,
 			egress_channels,
-		},
-	))
+		})
+	}
+
+	/// Read the [`AbridgedHostConfiguration`] from the relay chain state proof.
+	///
+	/// Returns an error if anything failed at reading or decoding.
+	pub fn read_abridged_host_configuration(&self) -> Result<AbridgedHostConfiguration, Error> {
+		read_entry(&self.trie_backend, relay_chain::well_known_keys::ACTIVE_CONFIG, None)
+			.map_err(Error::Config)
+	}
+
+	/// Read the [`Slot`](relay_chain::v1::Slot) from the relay chain state proof.
+	///
+	/// The slot is slot of the relay chain block this state proof was extracted from.
+	///
+	/// Returns an error if anything failed at reading or decoding.
+	pub fn read_slot(&self) -> Result<relay_chain::v1::Slot, Error> {
+		read_entry(&self.trie_backend, relay_chain::well_known_keys::CURRENT_SLOT, None).map_err(Error::Slot)
+	}
 }
diff --git a/cumulus/pallets/parachain-system/src/validate_block/implementation.rs b/cumulus/pallets/parachain-system/src/validate_block/implementation.rs
index 2caacb97869..37643a8497e 100644
--- a/cumulus/pallets/parachain-system/src/validate_block/implementation.rs
+++ b/cumulus/pallets/parachain-system/src/validate_block/implementation.rs
@@ -16,14 +16,12 @@
 
 //! The actual implementation of the validate block functionality.
 
-use frame_support::traits::ExecuteBlock;
-use sp_runtime::traits::{Block as BlockT, HashFor, Header as HeaderT, NumberFor};
+use frame_support::traits::{ExecuteBlock, ExtrinsicCall, IsSubType, Get};
+use sp_runtime::traits::{Block as BlockT, Extrinsic, HashFor, Header as HeaderT, NumberFor};
 
 use sp_io::KillChildStorageResult;
 use sp_std::prelude::*;
 
-use hash_db::{HashDB, EMPTY_PREFIX};
-
 use polkadot_parachain::primitives::{HeadData, ValidationParams, ValidationResult};
 
 use codec::{Decode, Encode};
@@ -32,12 +30,9 @@ use sp_core::storage::ChildInfo;
 use sp_externalities::{set_and_run_with_externalities, Externalities};
 use sp_trie::MemoryDB;
 
-type Ext<'a, B> = sp_state_machine::Ext<
-	'a,
-	HashFor<B>,
-	NumberFor<B>,
-	sp_state_machine::TrieBackend<MemoryDB<HashFor<B>>, HashFor<B>>,
->;
+type TrieBackend<B> = sp_state_machine::TrieBackend<MemoryDB<HashFor<B>>, HashFor<B>>;
+
+type Ext<'a, B> = sp_state_machine::Ext<'a, HashFor<B>, NumberFor<B>, TrieBackend<B>>;
 
 fn with_externalities<F: FnOnce(&mut dyn Externalities) -> R, R>(f: F) -> R {
 	sp_externalities::with_externalities(f).expect("Environmental externalities not set.")
@@ -45,9 +40,18 @@ fn with_externalities<F: FnOnce(&mut dyn Externalities) -> R, R>(f: F) -> R {
 
 /// Validate a given parachain block on a validator.
 #[doc(hidden)]
-pub fn validate_block<B: BlockT, E: ExecuteBlock<B>, PSC: crate::Config>(
+pub fn validate_block<
+	B: BlockT,
+	E: ExecuteBlock<B>,
+	PSC: crate::Config,
+	CI: crate::CheckInherents<B>,
+>(
 	params: ValidationParams,
-) -> ValidationResult {
+) -> ValidationResult
+where
+	B::Extrinsic: ExtrinsicCall,
+	<B::Extrinsic as Extrinsic>::Call: IsSubType<crate::Call<PSC>>,
+{
 	let block_data =
 		cumulus_primitives_core::ParachainBlockData::<B>::decode(&mut &params.block_data.0[..])
 			.expect("Invalid parachain block data");
@@ -77,9 +81,6 @@ pub fn validate_block<B: BlockT, E: ExecuteBlock<B>, PSC: crate::Config>(
 	};
 
 	let backend = sp_state_machine::TrieBackend::new(db, root);
-	let mut overlay = sp_state_machine::OverlayedChanges::default();
-	let mut cache = Default::default();
-	let mut ext = Ext::<B>::new(&mut overlay, &mut cache, &backend);
 
 	let _guard = (
 		// Replace storage calls with our own implementations
@@ -121,7 +122,38 @@ pub fn validate_block<B: BlockT, E: ExecuteBlock<B>, PSC: crate::Config>(
 		sp_io::offchain_index::host_clear.replace_implementation(host_offchain_index_clear),
 	);
 
-	set_and_run_with_externalities(&mut ext, || {
+	let inherent_data = block
+		.extrinsics()
+		.iter()
+		.filter_map(|e| e.call().is_sub_type())
+		.find_map(|c| match c {
+			crate::Call::set_validation_data(validation_data) => Some(validation_data.clone()),
+			_ => None,
+		})
+		.expect("Could not find `set_validation_data` inherent");
+
+	run_with_externalities::<B, _, _>(&backend, || {
+		let relay_chain_proof = crate::RelayChainStateProof::new(
+			PSC::SelfParaId::get(),
+			inherent_data.validation_data.relay_parent_storage_root,
+			inherent_data.relay_chain_state.clone(),
+		)
+		.expect("Invalid relay chain state proof");
+
+		let res = CI::check_inherents(block.extrinsics(), &relay_chain_proof);
+
+		if !res.ok() {
+			if log::log_enabled!(log::Level::Error) {
+				res.into_errors().for_each(|e| {
+					log::error!("Checking inherent with identifier `{:?}` failed", e.0)
+				});
+			}
+
+			panic!("Checking inherents failed");
+		}
+	});
+
+	run_with_externalities::<B, _, _>(&backend, || {
 		super::set_and_run_with_validation_params(params, || {
 			E::execute_block(block);
 
@@ -143,6 +175,18 @@ pub fn validate_block<B: BlockT, E: ExecuteBlock<B>, PSC: crate::Config>(
 	})
 }
 
+/// Run the given closure with the externalities set.
+fn run_with_externalities<B: BlockT, R, F: FnOnce() -> R>(
+	backend: &TrieBackend<B>,
+	execute: F,
+) -> R {
+	let mut overlay = sp_state_machine::OverlayedChanges::default();
+	let mut cache = Default::default();
+	let mut ext = Ext::<B>::new(&mut overlay, &mut cache, backend);
+
+	set_and_run_with_externalities(&mut ext, || execute())
+}
+
 fn host_storage_read(key: &[u8], value_out: &mut [u8], value_offset: u32) -> Option<u32> {
 	match with_externalities(|ext| ext.storage(key)) {
 		Some(value) => {
diff --git a/cumulus/pallets/parachain-system/src/validate_block/mod.rs b/cumulus/pallets/parachain-system/src/validate_block/mod.rs
index 72bbb09ec60..44886efd4fe 100644
--- a/cumulus/pallets/parachain-system/src/validate_block/mod.rs
+++ b/cumulus/pallets/parachain-system/src/validate_block/mod.rs
@@ -49,64 +49,3 @@ pub(crate) fn with_validation_params<R>(f: impl FnOnce(&ValidationParams) -> R)
 fn set_and_run_with_validation_params<R>(mut params: ValidationParams, f: impl FnOnce() -> R) -> R {
 	VALIDATION_PARAMS::using(&mut params, f)
 }
-
-/// Register the `validate_block` function that is used by parachains to validate blocks on a
-/// validator.
-///
-/// Does *nothing* when `std` feature is enabled.
-///
-/// Expects as parameters the runtime and a block executor.
-///
-/// # Example
-///
-/// ```
-///     struct BlockExecutor;
-///     struct Runtime;
-///
-///     cumulus_pallet_parachain_system::register_validate_block!(Runtime, BlockExecutor);
-///
-/// # fn main() {}
-/// ```
-#[macro_export]
-macro_rules! register_validate_block {
-	($runtime:ty, $block_executor:ty $( , )? ) => {
-		$crate::register_validate_block_impl!($runtime, $block_executor);
-	};
-}
-
-/// The actual implementation of `register_validate_block` for `no_std`.
-#[cfg(not(feature = "std"))]
-#[doc(hidden)]
-#[macro_export]
-macro_rules! register_validate_block_impl {
-	($runtime:ty, $block_executor:ty) => {
-		#[doc(hidden)]
-		mod parachain_validate_block {
-			use super::*;
-
-			#[no_mangle]
-			unsafe fn validate_block(arguments: *const u8, arguments_len: usize) -> u64 {
-				let params = $crate::validate_block::polkadot_parachain::load_params(
-					arguments,
-					arguments_len,
-				);
-
-				let res = $crate::validate_block::implementation::validate_block::<
-					<$runtime as $crate::validate_block::GetRuntimeBlockType>::RuntimeBlock,
-					$block_executor,
-					$runtime,
-				>(params);
-
-				$crate::validate_block::polkadot_parachain::write_result(&res)
-			}
-		}
-	};
-}
-
-/// The actual implementation of `register_validate_block` for `std`.
-#[cfg(feature = "std")]
-#[doc(hidden)]
-#[macro_export]
-macro_rules! register_validate_block_impl {
-	($runtime:ty, $block_executor:ty) => {};
-}
diff --git a/cumulus/pallets/parachain-system/src/validate_block/tests.rs b/cumulus/pallets/parachain-system/src/validate_block/tests.rs
index d2aa547b21d..575b5101a3f 100644
--- a/cumulus/pallets/parachain-system/src/validate_block/tests.rs
+++ b/cumulus/pallets/parachain-system/src/validate_block/tests.rs
@@ -94,8 +94,8 @@ fn build_block_with_witness(
 	client: &Client,
 	extra_extrinsics: Vec<UncheckedExtrinsic>,
 	parent_head: Header,
+	sproof_builder: RelayStateSproofBuilder,
 ) -> TestBlockData {
-	let sproof_builder = RelayStateSproofBuilder::default();
 	let (relay_parent_storage_root, _) = sproof_builder.clone().into_state_root_and_proof();
 	let block_id = BlockId::Hash(client.info().best_hash);
 	let mut validation_data = PersistedValidationData {
@@ -137,7 +137,7 @@ fn validate_block_no_extra_extrinsics() {
 		block,
 		witness,
 		validation_data,
-	} = build_block_with_witness(&client, vec![], parent_head.clone());
+	} = build_block_with_witness(&client, vec![], parent_head.clone(), Default::default());
 	let (header, extrinsics) = block.deconstruct();
 
 	let block_data = ParachainBlockData::new(header.clone(), extrinsics, witness);
@@ -167,7 +167,12 @@ fn validate_block_with_extra_extrinsics() {
 		block,
 		witness,
 		validation_data,
-	} = build_block_with_witness(&client, extra_extrinsics, parent_head.clone());
+	} = build_block_with_witness(
+		&client,
+		extra_extrinsics,
+		parent_head.clone(),
+		Default::default(),
+	);
 	let (header, extrinsics) = block.deconstruct();
 
 	let block_data = ParachainBlockData::new(header.clone(), extrinsics, witness);
@@ -192,7 +197,7 @@ fn validate_block_invalid_parent_hash() {
 		block,
 		witness,
 		validation_data,
-	} = build_block_with_witness(&client, vec![], parent_head.clone());
+	} = build_block_with_witness(&client, vec![], parent_head.clone(), Default::default());
 	let (mut header, extrinsics) = block.deconstruct();
 	header.set_parent_hash(Hash::from_low_u64_be(1));
 
@@ -212,18 +217,44 @@ fn validate_block_fails_on_invalid_validation_data() {
 
 	let (client, longest_chain) = create_test_client();
 	let parent_head = longest_chain.best_chain().expect("Best block exists");
+	let TestBlockData { block, witness, .. } =
+		build_block_with_witness(&client, vec![], parent_head.clone(), Default::default());
+	let (header, extrinsics) = block.deconstruct();
+
+	let block_data = ParachainBlockData::new(header, extrinsics, witness);
+	call_validate_block(parent_head, block_data, Hash::random()).expect("Calls `validate_block`");
+}
+
+#[test]
+#[should_panic(expected = "Calls `validate_block`: Other(\"Trap: Trap { kind: Unreachable }\")")]
+fn check_inherent_fails_on_validate_block_as_expected() {
+	let _ = env_logger::try_init();
+
+	let (client, longest_chain) = create_test_client();
+	let parent_head = longest_chain.best_chain().expect("Best block exists");
+
 	let TestBlockData {
 		block,
 		witness,
-		..
-	} = build_block_with_witness(&client, vec![], parent_head.clone());
+		validation_data,
+	} = build_block_with_witness(
+		&client,
+		vec![],
+		parent_head.clone(),
+		RelayStateSproofBuilder {
+			current_slot: 1337.into(),
+			..Default::default()
+		},
+	);
 	let (header, extrinsics) = block.deconstruct();
 
-	let block_data = ParachainBlockData::new(header, extrinsics, witness);
-	call_validate_block(
+	let block_data = ParachainBlockData::new(header.clone(), extrinsics, witness);
+
+	let res_header = call_validate_block(
 		parent_head,
 		block_data,
-		Hash::random(),
+		validation_data.relay_parent_storage_root,
 	)
 	.expect("Calls `validate_block`");
+	assert_eq!(header, res_header);
 }
diff --git a/cumulus/polkadot-parachains/rococo-runtime/src/lib.rs b/cumulus/polkadot-parachains/rococo-runtime/src/lib.rs
index 1cc30fdace2..bc103209776 100644
--- a/cumulus/polkadot-parachains/rococo-runtime/src/lib.rs
+++ b/cumulus/polkadot-parachains/rococo-runtime/src/lib.rs
@@ -591,7 +591,19 @@ impl_runtime_apis! {
 	}
 }
 
-cumulus_pallet_parachain_system::register_validate_block!(
-	Runtime,
-	cumulus_pallet_aura_ext::BlockExecutor::<Runtime, Executive>,
-);
+struct CheckInherents;
+
+impl cumulus_pallet_parachain_system::CheckInherents<Block> for CheckInherents {
+	fn check_inherents(
+		_: &[UncheckedExtrinsic],
+		_: &cumulus_pallet_parachain_system::RelayChainStateProof,
+	) -> sp_inherents::CheckInherentsResult {
+		sp_inherents::CheckInherentsResult::new()
+	}
+}
+
+cumulus_pallet_parachain_system::register_validate_block! {
+	Runtime = Runtime,
+	BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::<Runtime, Executive>,
+	CheckInherents = CheckInherents,
+}
diff --git a/cumulus/polkadot-parachains/shell-runtime/src/lib.rs b/cumulus/polkadot-parachains/shell-runtime/src/lib.rs
index 547115cafe4..7b88ee9ce42 100644
--- a/cumulus/polkadot-parachains/shell-runtime/src/lib.rs
+++ b/cumulus/polkadot-parachains/shell-runtime/src/lib.rs
@@ -369,4 +369,19 @@ impl_runtime_apis! {
 	}
 }
 
-cumulus_pallet_parachain_system::register_validate_block!(Runtime, Executive);
+struct CheckInherents;
+
+impl cumulus_pallet_parachain_system::CheckInherents<Block> for CheckInherents {
+	fn check_inherents(
+		_: &[UncheckedExtrinsic],
+		_: &cumulus_pallet_parachain_system::RelayChainStateProof,
+	) -> sp_inherents::CheckInherentsResult {
+		sp_inherents::CheckInherentsResult::new()
+	}
+}
+
+cumulus_pallet_parachain_system::register_validate_block! {
+	Runtime = Runtime,
+	BlockExecutor = Executive,
+	CheckInherents = CheckInherents,
+}
diff --git a/cumulus/polkadot-parachains/statemine-runtime/src/lib.rs b/cumulus/polkadot-parachains/statemine-runtime/src/lib.rs
index 9677d0057f8..cd83cc34b16 100644
--- a/cumulus/polkadot-parachains/statemine-runtime/src/lib.rs
+++ b/cumulus/polkadot-parachains/statemine-runtime/src/lib.rs
@@ -897,7 +897,19 @@ impl_runtime_apis! {
 	}
 }
 
-cumulus_pallet_parachain_system::register_validate_block!(
-Runtime,
-cumulus_pallet_aura_ext::BlockExecutor::<Runtime, Executive>,
-);
+struct CheckInherents;
+
+impl cumulus_pallet_parachain_system::CheckInherents<Block> for CheckInherents {
+	fn check_inherents(
+		_: &[UncheckedExtrinsic],
+		_: &cumulus_pallet_parachain_system::RelayChainStateProof,
+	) -> sp_inherents::CheckInherentsResult {
+		sp_inherents::CheckInherentsResult::new()
+	}
+}
+
+cumulus_pallet_parachain_system::register_validate_block! {
+	Runtime = Runtime,
+	BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::<Runtime, Executive>,
+	CheckInherents = CheckInherents,
+}
diff --git a/cumulus/polkadot-parachains/statemint-runtime/src/lib.rs b/cumulus/polkadot-parachains/statemint-runtime/src/lib.rs
index 7913f189bdd..b95033d4d6f 100644
--- a/cumulus/polkadot-parachains/statemint-runtime/src/lib.rs
+++ b/cumulus/polkadot-parachains/statemint-runtime/src/lib.rs
@@ -827,7 +827,19 @@ impl_runtime_apis! {
 	}
 }
 
-cumulus_pallet_parachain_system::register_validate_block!(
-Runtime,
-cumulus_pallet_aura_ext::BlockExecutor::<Runtime, Executive>,
-);
+struct CheckInherents;
+
+impl cumulus_pallet_parachain_system::CheckInherents<Block> for CheckInherents {
+	fn check_inherents(
+		_: &[UncheckedExtrinsic],
+		_: &cumulus_pallet_parachain_system::RelayChainStateProof,
+	) -> sp_inherents::CheckInherentsResult {
+		sp_inherents::CheckInherentsResult::new()
+	}
+}
+
+cumulus_pallet_parachain_system::register_validate_block! {
+	Runtime = Runtime,
+	BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::<Runtime, Executive>,
+	CheckInherents = CheckInherents,
+}
diff --git a/cumulus/polkadot-parachains/westmint-runtime/src/lib.rs b/cumulus/polkadot-parachains/westmint-runtime/src/lib.rs
index e4d5db3b9f9..8875d09e01c 100644
--- a/cumulus/polkadot-parachains/westmint-runtime/src/lib.rs
+++ b/cumulus/polkadot-parachains/westmint-runtime/src/lib.rs
@@ -827,7 +827,19 @@ impl_runtime_apis! {
 	}
 }
 
-cumulus_pallet_parachain_system::register_validate_block!(
-Runtime,
-cumulus_pallet_aura_ext::BlockExecutor::<Runtime, Executive>,
-);
+struct CheckInherents;
+
+impl cumulus_pallet_parachain_system::CheckInherents<Block> for CheckInherents {
+	fn check_inherents(
+		_: &[UncheckedExtrinsic],
+		_: &cumulus_pallet_parachain_system::RelayChainStateProof,
+	) -> sp_inherents::CheckInherentsResult {
+		sp_inherents::CheckInherentsResult::new()
+	}
+}
+
+cumulus_pallet_parachain_system::register_validate_block! {
+	Runtime = Runtime,
+	BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::<Runtime, Executive>,
+	CheckInherents = CheckInherents,
+}
diff --git a/cumulus/primitives/parachain-inherent/src/client_side.rs b/cumulus/primitives/parachain-inherent/src/client_side.rs
index 7f183639a36..1ab6a1847b6 100644
--- a/cumulus/primitives/parachain-inherent/src/client_side.rs
+++ b/cumulus/primitives/parachain-inherent/src/client_side.rs
@@ -166,6 +166,7 @@ fn collect_relay_storage_proof(
 		.unwrap_or_default();
 
 	let mut relevant_keys = vec![];
+	relevant_keys.push(relay_well_known_keys::CURRENT_SLOT.to_vec());
 	relevant_keys.push(relay_well_known_keys::ACTIVE_CONFIG.to_vec());
 	relevant_keys.push(relay_well_known_keys::dmq_mqc_head(para_id));
 	relevant_keys.push(relay_well_known_keys::relay_dispatch_queue_size(para_id));
@@ -279,7 +280,11 @@ where
 	fn execute_with_client<Client, Api, Backend>(
 		self,
 		client: std::sync::Arc<Client>,
-	) -> Self::Output where Client: ProvideRuntimeApi<PBlock>, Client::Api: ParachainHost<PBlock> {
+	) -> Self::Output
+	where
+		Client: ProvideRuntimeApi<PBlock>,
+		Client::Api: ParachainHost<PBlock>,
+	{
 		ParachainInherentData::create_at(
 			self.relay_parent,
 			&*client,
diff --git a/cumulus/primitives/parachain-inherent/src/lib.rs b/cumulus/primitives/parachain-inherent/src/lib.rs
index 3ef23dea48e..fd678af13e0 100644
--- a/cumulus/primitives/parachain-inherent/src/lib.rs
+++ b/cumulus/primitives/parachain-inherent/src/lib.rs
@@ -50,6 +50,7 @@ pub struct ParachainInherentData {
 	///
 	/// Specifically this witness contains the data for:
 	///
+	/// - the current slot number at the given relay parent
 	/// - active host configuration as per the relay parent,
 	/// - the relay dispatch queue sizes
 	/// - the list of egress HRMP channels (in the list of recipients form)
diff --git a/cumulus/test/relay-sproof-builder/src/lib.rs b/cumulus/test/relay-sproof-builder/src/lib.rs
index 693106b3943..2c7ad67ba5e 100644
--- a/cumulus/test/relay-sproof-builder/src/lib.rs
+++ b/cumulus/test/relay-sproof-builder/src/lib.rs
@@ -14,7 +14,9 @@
 // You should have received a copy of the GNU General Public License
 // along with Cumulus.  If not, see <http://www.gnu.org/licenses/>.
 
-use cumulus_primitives_core::{relay_chain, AbridgedHostConfiguration, AbridgedHrmpChannel, ParaId};
+use cumulus_primitives_core::{
+	relay_chain, AbridgedHostConfiguration, AbridgedHrmpChannel, ParaId,
+};
 use sp_runtime::traits::HashFor;
 use sp_state_machine::MemoryDB;
 use sp_std::collections::btree_map::BTreeMap;
@@ -38,6 +40,7 @@ pub struct RelayStateSproofBuilder {
 	pub hrmp_ingress_channel_index: Option<Vec<ParaId>>,
 	pub hrmp_egress_channel_index: Option<Vec<ParaId>>,
 	pub hrmp_channels: BTreeMap<relay_chain::v1::HrmpChannelId, AbridgedHrmpChannel>,
+	pub current_slot: relay_chain::v1::Slot,
 }
 
 impl Default for RelayStateSproofBuilder {
@@ -60,6 +63,7 @@ impl Default for RelayStateSproofBuilder {
 			hrmp_ingress_channel_index: None,
 			hrmp_egress_channel_index: None,
 			hrmp_channels: BTreeMap::new(),
+			current_slot: 0.into(),
 		}
 	}
 }
@@ -151,6 +155,11 @@ impl RelayStateSproofBuilder {
 					metadata.encode(),
 				);
 			}
+
+			insert(
+				relay_chain::well_known_keys::CURRENT_SLOT.to_vec(),
+				self.current_slot.encode(),
+			);
 		}
 
 		let root = backend.root().clone();
diff --git a/cumulus/test/runtime/src/lib.rs b/cumulus/test/runtime/src/lib.rs
index 339c2369c89..2a90cba758a 100644
--- a/cumulus/test/runtime/src/lib.rs
+++ b/cumulus/test/runtime/src/lib.rs
@@ -427,4 +427,29 @@ impl_runtime_apis! {
 	}
 }
 
-cumulus_pallet_parachain_system::register_validate_block!(Runtime, Executive);
+struct CheckInherents;
+
+impl cumulus_pallet_parachain_system::CheckInherents<Block> for CheckInherents {
+	fn check_inherents(
+		_: &[UncheckedExtrinsic],
+		relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof,
+	) -> sp_inherents::CheckInherentsResult {
+		if relay_state_proof.read_slot().expect("Reads slot") == 1337u64 {
+			let mut res = sp_inherents::CheckInherentsResult::new();
+			res.put_error(
+				[1u8; 8],
+				&sp_inherents::MakeFatalError::from("You are wrong"),
+			)
+			.expect("Puts error");
+			res
+		} else {
+			sp_inherents::CheckInherentsResult::new()
+		}
+	}
+}
+
+cumulus_pallet_parachain_system::register_validate_block! {
+	Runtime = Runtime,
+	BlockExecutor = Executive,
+	CheckInherents = CheckInherents,
+}
-- 
GitLab