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

Commit

Permalink
Migrate decl_outer_dispatch to a proc macro
Browse files Browse the repository at this point in the history
  • Loading branch information
KiChjang committed Jun 1, 2021
1 parent daaed4a commit d40b71e
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 24 deletions.
144 changes: 144 additions & 0 deletions frame/support/procedural/src/construct_runtime/expand/calls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
// 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 pallet_names = Vec::new();
let mut pallet_paths = 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 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);
pallet_paths.push(&pallet_declaration.pallet);
}

quote! {
#(
#pallet_paths::__is_call_part_defined!(#pallet_names);
)*

#[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,
}
}
}

impl From<#scrate::dispatch::CallableCallFor<#pallet_names, #runtime>> for Call {
fn from(call: #scrate::dispatch::CallableCallFor<#pallet_names, #runtime>) -> Self {
#variant_patterns
}
}
)*
}
}
2 changes: 2 additions & 0 deletions frame/support/procedural/src/construct_runtime/expand/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@
// See the License for the specific language governing permissions and
// limitations under the License

mod calls;
mod config;
mod event;
mod metadata;
mod origin;

pub use calls::expand_outer_dispatch;
pub use config::expand_outer_config;
pub use event::expand_outer_event;
pub use metadata::expand_runtime_metadata;
Expand Down
25 changes: 1 addition & 24 deletions frame/support/procedural/src/construct_runtime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ fn construct_runtime_parsed(definition: RuntimeDefinition) -> Result<TokenStream
let all_pallets = decl_all_pallets(&name, pallets.iter());
let pallet_to_index = decl_pallet_runtime_setup(&pallets, &scrate);

let dispatch = decl_outer_dispatch(&name, pallets.iter(), &scrate);
let dispatch = expand::expand_outer_dispatch(&name, &pallets, &scrate);
let metadata = expand::expand_runtime_metadata(&name, &pallets, &scrate, &unchecked_extrinsic);
let outer_config = expand::expand_outer_config(&name, &pallets, &scrate);
let inherent = decl_outer_inherent(
Expand Down Expand Up @@ -244,29 +244,6 @@ fn decl_outer_inherent<'a>(
)
}

fn decl_outer_dispatch<'a>(
runtime: &'a Ident,
pallet_declarations: impl Iterator<Item = &'a Pallet>,
scrate: &'a TokenStream2,
) -> TokenStream2 {
let pallets_tokens = pallet_declarations
.filter(|pallet_declaration| pallet_declaration.exists_part("Call"))
.map(|pallet_declaration| {
let pallet = &pallet_declaration.pallet.inner.segments.last().unwrap();
let name = &pallet_declaration.name;
let index = pallet_declaration.index;
quote!(#[codec(index = #index)] #pallet::#name)
});

quote!(
#scrate::impl_outer_dispatch! {
pub enum Call for #runtime where origin: Origin {
#(#pallets_tokens,)*
}
}
)
}

fn decl_all_pallets<'a>(
runtime: &'a Ident,
pallet_declarations: impl Iterator<Item = &'a Pallet>,
Expand Down

0 comments on commit d40b71e

Please sign in to comment.