Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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