Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
Bring support for calling check_inherents (#490)
Browse files Browse the repository at this point in the history
* Start

* More work

* Add proc-macro for `validate_block`

* Make everything compile

* Add some test
  • Loading branch information
bkchr authored Jun 12, 2021
1 parent 2f88be0 commit d54fdd7
Show file tree
Hide file tree
Showing 20 changed files with 683 additions and 325 deletions.
232 changes: 120 additions & 112 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
10 changes: 6 additions & 4 deletions pallets/aura-ext/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
8 changes: 2 additions & 6 deletions pallets/parachain-system/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand All @@ -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]
Expand Down Expand Up @@ -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"
]
19 changes: 19 additions & 0 deletions pallets/parachain-system/proc-macro/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "cumulus-pallet-parachain-system-proc-macro"
version = "0.1.0"
authors = ["Parity Technologies <[email protected]>"]
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 = []
144 changes: 144 additions & 0 deletions pallets/parachain-system/proc-macro/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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()
}
67 changes: 53 additions & 14 deletions pallets/parachain-system/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand All @@ -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,
Expand All @@ -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]
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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;
}
Loading

0 comments on commit d54fdd7

Please sign in to comment.