diff --git a/pallets/parachain-system/Cargo.toml b/pallets/parachain-system/Cargo.toml
index 8990a848ad0..03f52a022fc 100644
--- a/pallets/parachain-system/Cargo.toml
+++ b/pallets/parachain-system/Cargo.toml
@@ -80,4 +80,6 @@ runtime-benchmarks = [
try-runtime = ["frame-support/try-runtime"]
-parameterized-consensus-hook = []
+parameterized-consensus-hook = [
+ "cumulus-pallet-parachain-system-proc-macro/parameterized-consensus-hook",
+]
diff --git a/pallets/parachain-system/proc-macro/Cargo.toml b/pallets/parachain-system/proc-macro/Cargo.toml
index 8ff664b0284..7719b075817 100644
--- a/pallets/parachain-system/proc-macro/Cargo.toml
+++ b/pallets/parachain-system/proc-macro/Cargo.toml
@@ -17,3 +17,4 @@ proc-macro-crate = "1.3.1"
[features]
default = [ "std" ]
std = []
+parameterized-consensus-hook = []
diff --git a/pallets/parachain-system/proc-macro/src/lib.rs b/pallets/parachain-system/proc-macro/src/lib.rs
index 3c6fb21e5f3..9d5ac12a898 100644
--- a/pallets/parachain-system/proc-macro/src/lib.rs
+++ b/pallets/parachain-system/proc-macro/src/lib.rs
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Cumulus. If not, see .
-use proc_macro2::{Span, TokenStream};
+use proc_macro2::Span;
use proc_macro_crate::{crate_name, FoundCrate};
use syn::{
parse::{Parse, ParseStream},
@@ -25,17 +25,20 @@ use syn::{
mod keywords {
syn::custom_keyword!(Runtime);
syn::custom_keyword!(BlockExecutor);
+ syn::custom_keyword!(CheckInherents);
}
struct Input {
runtime: Path,
block_executor: Path,
+ check_inherents: Option,
}
impl Parse for Input {
fn parse(input: ParseStream) -> Result {
let mut runtime = None;
let mut block_executor = None;
+ let mut check_inherents = None;
fn parse_inner(
input: ParseStream,
@@ -56,26 +59,24 @@ impl Parse for Input {
}
}
- while runtime.is_none() || block_executor.is_none() {
+ while !input.is_empty() || runtime.is_none() || block_executor.is_none() {
let lookahead = input.lookahead1();
if lookahead.peek(keywords::Runtime) {
parse_inner::(input, &mut runtime)?;
} else if lookahead.peek(keywords::BlockExecutor) {
parse_inner::(input, &mut block_executor)?;
+ } else if lookahead.peek(keywords::CheckInherents) {
+ parse_inner::(input, &mut check_inherents)?;
} else {
return Err(lookahead.error())
}
}
- let rest = input.parse::()?;
- 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,
})
}
}
@@ -91,7 +92,7 @@ fn crate_() -> Result {
#[proc_macro]
pub fn register_validate_block(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
- let Input { runtime, block_executor } = match syn::parse(input) {
+ let Input { runtime, block_executor, check_inherents } = match syn::parse(input) {
Ok(t) => t,
Err(e) => return e.into_compile_error().into(),
};
@@ -101,6 +102,28 @@ pub fn register_validate_block(input: proc_macro::TokenStream) -> proc_macro::To
Err(e) => return e.into_compile_error().into(),
};
+ let check_inherents = match check_inherents {
+ Some(_check_inherents) => {
+ #[cfg(not(feature = "parameterized-consensus-hook"))]
+ quote::quote! { #_check_inherents }
+ #[cfg(feature = "parameterized-consensus-hook")]
+ return Error::new(
+ Span::call_site(),
+ "CheckInherents is incompatible with consensus hook feature",
+ )
+ .into_compile_error()
+ .into()
+ },
+ None => {
+ #[cfg(feature = "parameterized-consensus-hook")]
+ quote::quote! { #crate_::DummyCheckInherents<<#runtime as #crate_::validate_block::GetRuntimeBlockType>::RuntimeBlock> }
+ #[cfg(not(feature = "parameterized-consensus-hook"))]
+ return Error::new(Span::call_site(), "missing CheckInherents input")
+ .into_compile_error()
+ .into()
+ },
+ };
+
if cfg!(not(feature = "std")) {
quote::quote! {
#[doc(hidden)]
@@ -127,6 +150,7 @@ pub fn register_validate_block(input: proc_macro::TokenStream) -> proc_macro::To
<#runtime as #crate_::validate_block::GetRuntimeBlockType>::RuntimeBlock,
#block_executor,
#runtime,
+ #check_inherents,
>(params);
#crate_::validate_block::polkadot_parachain::write_result(&res)
diff --git a/pallets/parachain-system/src/lib.rs b/pallets/parachain-system/src/lib.rs
index 83954995678..cf63aee64da 100644
--- a/pallets/parachain-system/src/lib.rs
+++ b/pallets/parachain-system/src/lib.rs
@@ -48,7 +48,7 @@ use frame_system::{ensure_none, ensure_root, pallet_prelude::HeaderFor};
use polkadot_parachain::primitives::RelayChainBlockNumber;
use scale_info::TypeInfo;
use sp_runtime::{
- traits::{BlockNumberProvider, Hash},
+ traits::{Block as BlockT, BlockNumberProvider, Hash},
transaction_validity::{
InvalidTransaction, TransactionLongevity, TransactionSource, TransactionValidity,
ValidTransaction,
@@ -1497,6 +1497,33 @@ impl UpwardMessageSender for Pallet {
}
}
+/// Something that can check the inherents of a block.
+#[deprecated = "use `cumulus-pallet-aura-ext::FixedVelocityConsensusHook` instead"]
+pub trait CheckInherents {
+ /// 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(
+ block: &Block,
+ validation_data: &RelayChainStateProof,
+ ) -> frame_support::inherent::CheckInherentsResult;
+}
+
+/// Struct that always returns `Ok` on inherents check, needed for backwards-compatibility.
+#[doc(hidden)]
+pub struct DummyCheckInherents(sp_std::marker::PhantomData);
+
+#[allow(deprecated)]
+impl CheckInherents for DummyCheckInherents {
+ fn check_inherents(
+ _: &Block,
+ _: &RelayChainStateProof,
+ ) -> frame_support::inherent::CheckInherentsResult {
+ sp_inherents::CheckInherentsResult::new()
+ }
+}
+
/// Something that should be informed about system related events.
///
/// This includes events like [`on_validation_data`](Self::on_validation_data) that is being
diff --git a/pallets/parachain-system/src/validate_block/implementation.rs b/pallets/parachain-system/src/validate_block/implementation.rs
index 6945362394f..9f08819c5ac 100644
--- a/pallets/parachain-system/src/validate_block/implementation.rs
+++ b/pallets/parachain-system/src/validate_block/implementation.rs
@@ -70,7 +70,12 @@ fn with_externalities R, R>(f: F) -> R {
/// ensuring that the final storage root matches the storage root in the header of the block. In the
/// end we return back the [`ValidationResult`] with all the required information for the validator.
#[doc(hidden)]
-pub fn validate_block, PSC: crate::Config>(
+pub fn validate_block<
+ B: BlockT,
+ E: ExecuteBlock,
+ PSC: crate::Config,
+ CI: crate::CheckInherents,
+>(
MemoryOptimizedValidationParams {
block_data,
parent_head,
@@ -159,6 +164,28 @@ where
sp_io::offchain_index::host_clear.replace_implementation(host_offchain_index_clear),
);
+ #[cfg(not(feature = "parameterized-consensus-hook"))]
+ run_with_externalities::(&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, &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::(&backend, || {
let head_data = HeadData(block.header().encode());