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

Emit error when construct_runtime imports a non-existent pallet part #8949

Merged
48 commits merged into from
Jun 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
052ccf2
Emit error when construct_runtime imports a non-existent Call part
KiChjang May 30, 2021
8aec97b
Reword and display pallet name when emitting part not found error
KiChjang May 31, 2021
daaed4a
Merge remote-tracking branch 'origin/master' into kckyeung/pallet-par…
KiChjang Jun 1, 2021
d40b71e
Migrate decl_outer_dispatch to a proc macro
KiChjang Jun 1, 2021
f4d5fcf
Rename calls.rs to call.rs
KiChjang Jun 1, 2021
f4c6afe
Create new construct_runtime_v2 macro
KiChjang Jun 4, 2021
77fa5e8
Add UI test for importing non-existent call part in construct_runtime
KiChjang Jun 4, 2021
7d29261
Emit error when construct_runtime imports a non-existent Config part
KiChjang Jun 4, 2021
665f4b4
Emit error when construct_runtime imports a non-existent Event part
KiChjang Jun 5, 2021
7097ec0
Migrate decl_outer_inherent to a proc macro
KiChjang Jun 5, 2021
c22fa21
Emit error when construct_runtime imports a non-existent Inherent part
KiChjang Jun 5, 2021
a2790ef
Migrate decl_outer_validate_unsigned to a proc macro
KiChjang Jun 5, 2021
090dd14
Emit error when construct_runtime imports a non-existent ValidateUnsi…
KiChjang Jun 6, 2021
c1690d8
impl for old macro
gui1117 Jun 8, 2021
a5eeecc
fix line width
gui1117 Jun 8, 2021
57b4a5d
add doc
gui1117 Jun 8, 2021
d452eec
hide macroes and use unique counter everywhere
gui1117 Jun 8, 2021
4403724
Merge remote-tracking branch 'origin/master' into kckyeung/pallet-par…
KiChjang Jun 10, 2021
db15388
Remove construct_runtime_v2
KiChjang Jun 10, 2021
852bdf5
Encapsulate pallet part check macros in a module
KiChjang Jun 10, 2021
1012966
Fix macro definitions in dummy part checker
KiChjang Jun 10, 2021
d865fef
Tag ProvideInherent impl with #[pallet::inherent] properly for author…
KiChjang Jun 10, 2021
e291da7
Remove Call part from pallets that do not define it
KiChjang Jun 11, 2021
3273e33
Add Call part unit tests
KiChjang Jun 11, 2021
a0ea5d5
Remove undefined Call part import from offences pallet
KiChjang Jun 11, 2021
a8aea68
Add tests for expand_outer_inherent
KiChjang Jun 11, 2021
c03c299
Remove Call part from pallets that do not define them
KiChjang Jun 11, 2021
12343f9
Remove Call part imports from pallets that do not have it defined
KiChjang Jun 11, 2021
3c41aef
Remove Call part import of the offences pallet from grandpa pallet mocks
KiChjang Jun 11, 2021
143eccd
Update frame/support/test/tests/pallet.rs
KiChjang Jun 11, 2021
4559a6c
Remove Call part imports for pallets that do not define them
KiChjang Jun 11, 2021
517072c
Move inherent tests to inherent_expand
KiChjang Jun 12, 2021
2602374
Add unit tests for expand_outer_validate_unsigned
KiChjang Jun 12, 2021
1dfc27f
Merge remote-tracking branch 'origin/master' into kckyeung/pallet-par…
KiChjang Jun 12, 2021
b977dc7
Add newline at the end of file
KiChjang Jun 13, 2021
8432e45
fix ui test
gui1117 Jun 14, 2021
26fefef
Small prayer to RNGsus for fixing CI
KiChjang Jun 15, 2021
739f270
Merge remote-tracking branch 'origin/master' into kckyeung/pallet-par…
KiChjang Jun 15, 2021
938fddb
Remove Call part from construct_runtime for randomness collective fli…
KiChjang Jun 15, 2021
07507ad
Remove Call part import for randomness collective flip pallet
KiChjang Jun 15, 2021
e6ca013
Summon Laplace's demon instead of praying to RNGsus
KiChjang Jun 15, 2021
b05787b
Update test expectations
KiChjang Jun 15, 2021
362b688
fix ui test and make sure it's flaky
TriplEight Jun 15, 2021
5a3d244
Revert "fix ui test and make sure it's flaky"
TriplEight Jun 15, 2021
3a06de2
Comment out test instead of putting it in conditional compilation
KiChjang Jun 15, 2021
7789ac7
Update UI test expectations
KiChjang Jun 15, 2021
d4ad1c7
Update UI test expectations
KiChjang Jun 15, 2021
7f1ee06
Emit error when construct_runtime imports a non-existent Origin part
KiChjang Jun 16, 2021
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
2 changes: 1 addition & 1 deletion bin/node-template/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ construct_runtime!(
UncheckedExtrinsic = UncheckedExtrinsic
{
System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Call, Storage},
RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage},
Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent},
Aura: pallet_aura::{Pallet, Config<T>},
Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event},
Expand Down
6 changes: 3 additions & 3 deletions bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1159,10 +1159,10 @@ construct_runtime!(
Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>},
Sudo: pallet_sudo::{Pallet, Call, Config<T>, Storage, Event<T>},
ImOnline: pallet_im_online::{Pallet, Call, Storage, Event<T>, ValidateUnsigned, Config<T>},
AuthorityDiscovery: pallet_authority_discovery::{Pallet, Call, Config},
Offences: pallet_offences::{Pallet, Call, Storage, Event},
AuthorityDiscovery: pallet_authority_discovery::{Pallet, Config},
Offences: pallet_offences::{Pallet, Storage, Event},
Comment on lines +1162 to +1163
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Historical: pallet_session_historical::{Pallet},
RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Call, Storage},
RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage},
Identity: pallet_identity::{Pallet, Call, Storage, Event<T>},
Society: pallet_society::{Pallet, Call, Storage, Event<T>, Config<T>},
Recovery: pallet_recovery::{Pallet, Call, Storage, Event<T>},
Expand Down
2 changes: 1 addition & 1 deletion frame/aura/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ frame_support::construct_runtime!(
{
System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent},
Aura: pallet_aura::{Pallet, Call, Storage, Config<T>},
Aura: pallet_aura::{Pallet, Storage, Config<T>},
}
);

Expand Down
2 changes: 1 addition & 1 deletion frame/authority-discovery/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ mod tests {
{
System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
Session: pallet_session::{Pallet, Call, Storage, Event, Config<T>},
AuthorityDiscovery: pallet_authority_discovery::{Pallet, Call, Config},
AuthorityDiscovery: pallet_authority_discovery::{Pallet, Config},
}
);

Expand Down
124 changes: 62 additions & 62 deletions frame/authorship/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
use sp_std::{result, prelude::*, collections::btree_set::BTreeSet};
use frame_support::{
dispatch, traits::{FindAuthor, VerifySeal, Get},
inherent::{InherentData, ProvideInherent, InherentIdentifier},
};
use codec::{Encode, Decode};
use sp_runtime::traits::{Header as HeaderT, One, Saturating};
Expand Down Expand Up @@ -238,6 +237,68 @@ pub mod pallet {
Self::verify_and_import_uncles(new_uncles)
}
}

#[pallet::inherent]
impl<T: Config> ProvideInherent for Pallet<T> {
type Call = Call<T>;
type Error = InherentError;
const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER;

fn create_inherent(data: &InherentData) -> Option<Self::Call> {
let uncles = data.uncles().unwrap_or_default();
let mut set_uncles = Vec::new();

if !uncles.is_empty() {
let prev_uncles = <Uncles<T>>::get();
let mut existing_hashes: Vec<_> = prev_uncles.into_iter().filter_map(|entry|
match entry {
UncleEntryItem::InclusionHeight(_) => None,
UncleEntryItem::Uncle(h, _) => Some(h),
}
).collect();

let mut acc: <T::FilterUncle as FilterUncle<_, _>>::Accumulator = Default::default();

for uncle in uncles {
match Self::verify_uncle(&uncle, &existing_hashes, &mut acc) {
Ok(_) => {
let hash = uncle.hash();
set_uncles.push(uncle);
existing_hashes.push(hash);

if set_uncles.len() == MAX_UNCLES {
break
}
}
Err(_) => {
// skip this uncle
}
}
}
}

if set_uncles.is_empty() {
None
} else {
Some(Call::set_uncles(set_uncles))
}
}

fn check_inherent(call: &Self::Call, _data: &InherentData) -> result::Result<(), Self::Error> {
match call {
Call::set_uncles(ref uncles) if uncles.len() > MAX_UNCLES => {
Err(InherentError::Uncles(Error::<T>::TooManyUncles.as_str().into()))
},
_ => {
Ok(())
},
}
}

fn is_inherent(call: &Self::Call) -> bool {
matches!(call, Call::set_uncles(_))
}
}
}

impl<T: Config> Pallet<T> {
Expand Down Expand Up @@ -348,67 +409,6 @@ impl<T: Config> Pallet<T> {
}
}

impl<T: Config> ProvideInherent for Pallet<T> {
type Call = Call<T>;
type Error = InherentError;
const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER;

fn create_inherent(data: &InherentData) -> Option<Self::Call> {
let uncles = data.uncles().unwrap_or_default();
let mut set_uncles = Vec::new();

if !uncles.is_empty() {
let prev_uncles = <Uncles<T>>::get();
let mut existing_hashes: Vec<_> = prev_uncles.into_iter().filter_map(|entry|
match entry {
UncleEntryItem::InclusionHeight(_) => None,
UncleEntryItem::Uncle(h, _) => Some(h),
}
).collect();

let mut acc: <T::FilterUncle as FilterUncle<_, _>>::Accumulator = Default::default();

for uncle in uncles {
match Self::verify_uncle(&uncle, &existing_hashes, &mut acc) {
Ok(_) => {
let hash = uncle.hash();
set_uncles.push(uncle);
existing_hashes.push(hash);

if set_uncles.len() == MAX_UNCLES {
break
}
}
Err(_) => {
// skip this uncle
}
}
}
}

if set_uncles.is_empty() {
None
} else {
Some(Call::set_uncles(set_uncles))
}
}

fn check_inherent(call: &Self::Call, _data: &InherentData) -> result::Result<(), Self::Error> {
match call {
Call::set_uncles(ref uncles) if uncles.len() > MAX_UNCLES => {
Err(InherentError::Uncles(Error::<T>::TooManyUncles.as_str().into()))
},
_ => {
Ok(())
},
}
}

fn is_inherent(call: &Self::Call) -> bool {
matches!(call, Call::set_uncles(_))
}
}

#[cfg(test)]
mod tests {
use crate as pallet_authorship;
Expand Down
2 changes: 1 addition & 1 deletion frame/babe/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ frame_support::construct_runtime!(
Authorship: pallet_authorship::{Pallet, Call, Storage, Inherent},
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
Historical: pallet_session_historical::{Pallet},
Offences: pallet_offences::{Pallet, Call, Storage, Event},
Offences: pallet_offences::{Pallet, Storage, Event},
Babe: pallet_babe::{Pallet, Call, Storage, Config, ValidateUnsigned},
Staking: pallet_staking::{Pallet, Call, Storage, Config<T>, Event<T>},
Session: pallet_session::{Pallet, Call, Storage, Event, Config<T>},
Expand Down
2 changes: 1 addition & 1 deletion frame/contracts/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ frame_support::construct_runtime!(
System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent},
Randomness: pallet_randomness_collective_flip::{Pallet, Call, Storage},
Randomness: pallet_randomness_collective_flip::{Pallet, Storage},
Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>},
}
);
Expand Down
2 changes: 1 addition & 1 deletion frame/grandpa/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ frame_support::construct_runtime!(
Staking: pallet_staking::{Pallet, Call, Config<T>, Storage, Event<T>},
Session: pallet_session::{Pallet, Call, Storage, Event, Config<T>},
Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event, ValidateUnsigned},
Offences: pallet_offences::{Pallet, Call, Storage, Event},
Offences: pallet_offences::{Pallet, Storage, Event},
Historical: pallet_session_historical::{Pallet},
}
);
Expand Down
2 changes: 1 addition & 1 deletion frame/offences/benchmarking/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ frame_support::construct_runtime!(
Staking: pallet_staking::{Pallet, Call, Config<T>, Storage, Event<T>},
Session: pallet_session::{Pallet, Call, Storage, Event, Config<T>},
ImOnline: pallet_im_online::{Pallet, Call, Storage, Event<T>, ValidateUnsigned, Config<T>},
Offences: pallet_offences::{Pallet, Call, Storage, Event},
Offences: pallet_offences::{Pallet, Storage, Event},
Historical: pallet_session_historical::{Pallet},
}
);
Expand Down
2 changes: 1 addition & 1 deletion frame/offences/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ frame_support::construct_runtime!(
UncheckedExtrinsic = UncheckedExtrinsic,
{
System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
Offences: offences::{Pallet, Call, Storage, Event},
Offences: offences::{Pallet, Storage, Event},
}
);

Expand Down
2 changes: 1 addition & 1 deletion frame/randomness-collective-flip/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ mod tests {
UncheckedExtrinsic = UncheckedExtrinsic,
{
System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
CollectiveFlip: pallet_randomness_collective_flip::{Pallet, Call, Storage},
CollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage},
}
);

Expand Down
145 changes: 145 additions & 0 deletions frame/support/procedural/src/construct_runtime/expand/call.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
// This file is part of Substrate.

// Copyright (C) 2021 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

use crate::construct_runtime::Pallet;
use proc_macro2::TokenStream;
use quote::quote;
use syn::Ident;

pub fn expand_outer_dispatch(
runtime: &Ident,
pallet_decls: &[Pallet],
scrate: &TokenStream,
) -> TokenStream {
let mut variant_defs = TokenStream::new();
let mut variant_patterns = Vec::new();
let mut query_call_part_macros = Vec::new();
let mut pallet_names = Vec::new();

let pallets_with_call = pallet_decls
.iter()
.filter(|decl| decl.exists_part("Call"));

for pallet_declaration in pallets_with_call {
let name = &pallet_declaration.name;
let path = &pallet_declaration.path;
let index = pallet_declaration.index;

variant_defs.extend(quote!(#[codec(index = #index)] #name( #scrate::dispatch::CallableCallFor<#name, #runtime> ),));
variant_patterns.push(quote!(Call::#name(call)));
pallet_names.push(name);
query_call_part_macros.push(quote! {
#path::__substrate_call_check::is_call_part_defined!(#name);
});
}

quote! {
#( #query_call_part_macros )*

#[derive(
Clone, PartialEq, Eq,
#scrate::codec::Encode,
#scrate::codec::Decode,
#scrate::RuntimeDebug,
)]
pub enum Call {
#variant_defs
}
impl #scrate::dispatch::GetDispatchInfo for Call {
fn get_dispatch_info(&self) -> #scrate::dispatch::DispatchInfo {
match self {
#( #variant_patterns => call.get_dispatch_info(), )*
}
}
}
impl #scrate::dispatch::GetCallMetadata for Call {
fn get_call_metadata(&self) -> #scrate::dispatch::CallMetadata {
use #scrate::dispatch::GetCallName;
match self {
#(
#variant_patterns => {
let function_name = call.get_call_name();
let pallet_name = stringify!(#pallet_names);
#scrate::dispatch::CallMetadata { function_name, pallet_name }
}
)*
}
}

fn get_module_names() -> &'static [&'static str] {
&[#(
stringify!(#pallet_names),
)*]
}

fn get_call_names(module: &str) -> &'static [&'static str] {
use #scrate::dispatch::{Callable, GetCallName};
match module {
#(
stringify!(#pallet_names) =>
<<#pallet_names as Callable<#runtime>>::Call
as GetCallName>::get_call_names(),
)*
_ => unreachable!(),
}
}
}
impl #scrate::dispatch::Dispatchable for Call {
type Origin = Origin;
type Config = Call;
type Info = #scrate::weights::DispatchInfo;
type PostInfo = #scrate::weights::PostDispatchInfo;
fn dispatch(self, origin: Origin) -> #scrate::dispatch::DispatchResultWithPostInfo {
if !<Self::Origin as #scrate::traits::OriginTrait>::filter_call(&origin, &self) {
return #scrate::sp_std::result::Result::Err(#scrate::dispatch::DispatchError::BadOrigin.into());
}

#scrate::traits::UnfilteredDispatchable::dispatch_bypass_filter(self, origin)
}
}
impl #scrate::traits::UnfilteredDispatchable for Call {
type Origin = Origin;
fn dispatch_bypass_filter(self, origin: Origin) -> #scrate::dispatch::DispatchResultWithPostInfo {
match self {
#(
#variant_patterns =>
#scrate::traits::UnfilteredDispatchable::dispatch_bypass_filter(call, origin),
)*
}
}
}

#(
impl #scrate::traits::IsSubType<#scrate::dispatch::CallableCallFor<#pallet_names, #runtime>> for Call {
#[allow(unreachable_patterns)]
fn is_sub_type(&self) -> Option<&#scrate::dispatch::CallableCallFor<#pallet_names, #runtime>> {
match self {
#variant_patterns => Some(call),
// May be unreachable
_ => None,
shawntabrizi marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

impl From<#scrate::dispatch::CallableCallFor<#pallet_names, #runtime>> for Call {
fn from(call: #scrate::dispatch::CallableCallFor<#pallet_names, #runtime>) -> Self {
#variant_patterns
}
}
)*
KiChjang marked this conversation as resolved.
Show resolved Hide resolved
}
}
Loading