mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-27 20:57:59 +00:00
a0772117ac
* Disallow default weight * Fix build and test * Fix tests * Fix another beloved ui test. * fix beloved trybuild tests * fix treasury? * Final test fix * Fix build * Fix another one * Fix * More doctest fix
2273 lines
70 KiB
Rust
2273 lines
70 KiB
Rust
// Copyright 2017-2020 Parity Technologies (UK) Ltd.
|
|
// This file is part of Substrate.
|
|
|
|
// Substrate 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.
|
|
|
|
// Substrate 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 Substrate. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
//! Dispatch system. Contains a macro for defining runtime modules and
|
|
//! generating values representing lazy module function calls.
|
|
|
|
pub use crate::sp_std::{result, fmt, prelude::{Vec, Clone, Eq, PartialEq}, marker};
|
|
pub use crate::codec::{Codec, EncodeLike, Decode, Encode, Input, Output, HasCompact, EncodeAsRef};
|
|
pub use frame_metadata::{
|
|
FunctionMetadata, DecodeDifferent, DecodeDifferentArray, FunctionArgumentMetadata,
|
|
ModuleConstantMetadata, DefaultByte, DefaultByteGetter, ModuleErrorMetadata, ErrorMetadata
|
|
};
|
|
pub use crate::weights::{
|
|
SimpleDispatchInfo, GetDispatchInfo, DispatchInfo, WeighData, ClassifyDispatch,
|
|
TransactionPriority, Weight, PaysFee,
|
|
};
|
|
pub use sp_runtime::{traits::Dispatchable, DispatchError, DispatchResult};
|
|
pub use crate::traits::{CallMetadata, GetCallMetadata, GetCallName};
|
|
|
|
/// A type that cannot be instantiated.
|
|
pub enum Never {}
|
|
|
|
/// Serializable version of Dispatchable.
|
|
/// This value can be used as a "function" in an extrinsic.
|
|
pub trait Callable<T> {
|
|
type Call: Dispatchable + Codec + Clone + PartialEq + Eq;
|
|
}
|
|
|
|
// dirty hack to work around serde_derive issue
|
|
// https://github.com/rust-lang/rust/issues/51331
|
|
pub type CallableCallFor<A, T> = <A as Callable<T>>::Call;
|
|
|
|
/// A type that can be used as a parameter in a dispatchable function.
|
|
///
|
|
/// When using `decl_module` all arguments for call functions must implement this trait.
|
|
pub trait Parameter: Codec + EncodeLike + Clone + Eq + fmt::Debug {}
|
|
impl<T> Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug {}
|
|
|
|
/// Declares a `Module` struct and a `Call` enum, which implements the dispatch logic.
|
|
///
|
|
/// ## Declaration
|
|
///
|
|
/// ```
|
|
/// # #[macro_use]
|
|
/// # extern crate frame_support;
|
|
/// # use frame_support::dispatch;
|
|
/// # use frame_support::weights::SimpleDispatchInfo;
|
|
/// # use frame_system::{self as system, Trait, ensure_signed};
|
|
/// decl_module! {
|
|
/// pub struct Module<T: Trait> for enum Call where origin: T::Origin {
|
|
///
|
|
/// // Private functions are dispatchable, but not available to other
|
|
/// // FRAME pallets.
|
|
/// #[weight = SimpleDispatchInfo::default()]
|
|
/// fn my_function(origin, var: u64) -> dispatch::DispatchResult {
|
|
/// // Your implementation
|
|
/// Ok(())
|
|
/// }
|
|
///
|
|
/// // Public functions are both dispatchable and available to other
|
|
/// // FRAME pallets.
|
|
/// #[weight = SimpleDispatchInfo::default()]
|
|
/// pub fn my_public_function(origin) -> dispatch::DispatchResult {
|
|
/// // Your implementation
|
|
/// Ok(())
|
|
/// }
|
|
/// }
|
|
/// }
|
|
/// # fn main() {}
|
|
/// ```
|
|
///
|
|
/// The declaration is set with the header where:
|
|
///
|
|
/// * `Module`: The struct generated by the macro, with type `Trait`.
|
|
/// * `Call`: The enum generated for every pallet, which implements [`Callable`](./dispatch/trait.Callable.html).
|
|
/// * `origin`: Alias of `T::Origin`, declared by the [`impl_outer_origin!`](./macro.impl_outer_origin.html) macro.
|
|
/// * `Result`: The expected return type from pallet functions.
|
|
///
|
|
/// The first parameter of dispatchable functions must always be `origin`.
|
|
///
|
|
/// ### Shorthand Example
|
|
///
|
|
/// The macro automatically expands a shorthand function declaration to return the
|
|
/// [`DispatchResult`] type. These functions are the same:
|
|
///
|
|
/// ```
|
|
/// # #[macro_use]
|
|
/// # extern crate frame_support;
|
|
/// # use frame_support::dispatch;
|
|
/// # use frame_support::weights::SimpleDispatchInfo;
|
|
/// # use frame_system::{self as system, Trait, ensure_signed};
|
|
/// decl_module! {
|
|
/// pub struct Module<T: Trait> for enum Call where origin: T::Origin {
|
|
/// #[weight = SimpleDispatchInfo::default()]
|
|
/// fn my_long_function(origin) -> dispatch::DispatchResult {
|
|
/// // Your implementation
|
|
/// Ok(())
|
|
/// }
|
|
///
|
|
/// #[weight = SimpleDispatchInfo::default()]
|
|
/// fn my_short_function(origin) {
|
|
/// // Your implementation
|
|
/// }
|
|
/// }
|
|
/// }
|
|
/// # fn main() {}
|
|
/// ```
|
|
///
|
|
/// ### Privileged Function Example
|
|
///
|
|
/// A privileged function checks that the origin of the call is `ROOT`.
|
|
///
|
|
/// ```
|
|
/// # #[macro_use]
|
|
/// # extern crate frame_support;
|
|
/// # use frame_support::dispatch;
|
|
/// # use frame_support::weights::SimpleDispatchInfo;
|
|
/// # use frame_system::{self as system, Trait, ensure_signed, ensure_root};
|
|
/// decl_module! {
|
|
/// pub struct Module<T: Trait> for enum Call where origin: T::Origin {
|
|
/// #[weight = SimpleDispatchInfo::default()]
|
|
/// fn my_privileged_function(origin) -> dispatch::DispatchResult {
|
|
/// ensure_root(origin)?;
|
|
/// // Your implementation
|
|
/// Ok(())
|
|
/// }
|
|
/// }
|
|
/// }
|
|
/// # fn main() {}
|
|
/// ```
|
|
///
|
|
/// ## Multiple Module Instances Example
|
|
///
|
|
/// A Substrate module can be built such that multiple instances of the same module can be used within a single
|
|
/// runtime. For example, the [Balances module](../pallet_balances/index.html) can be added multiple times to your
|
|
/// runtime in order to support multiple, independent currencies for your blockchain. Here is an example of how
|
|
/// you would declare such a module using the `decl_module!` macro:
|
|
///
|
|
/// ```
|
|
/// # #[macro_use]
|
|
/// # extern crate frame_support;
|
|
/// # use frame_support::dispatch;
|
|
/// # use frame_system::{self as system, ensure_signed};
|
|
/// # pub struct DefaultInstance;
|
|
/// # pub trait Instance {}
|
|
/// # impl Instance for DefaultInstance {}
|
|
/// pub trait Trait<I: Instance=DefaultInstance>: system::Trait {}
|
|
///
|
|
/// decl_module! {
|
|
/// pub struct Module<T: Trait<I>, I: Instance = DefaultInstance> for enum Call where origin: T::Origin {
|
|
/// // Your implementation
|
|
/// }
|
|
/// }
|
|
/// # fn main() {}
|
|
/// ```
|
|
///
|
|
/// Note: `decl_storage` must be called to generate `Instance` trait and optionally
|
|
/// `DefaultInstance` type.
|
|
///
|
|
/// ## Where clause
|
|
///
|
|
/// Besides the default `origin: T::Origin`, you can also pass other bounds to the module declaration.
|
|
/// This where bound will be replicated to all types generated by this macro. The chaining of multiple
|
|
/// trait bounds with `+` is not supported. If multiple bounds for one type are required, it needs to
|
|
/// be split up into multiple bounds.
|
|
///
|
|
/// ```
|
|
/// # #[macro_use]
|
|
/// # extern crate frame_support;
|
|
/// # use frame_support::dispatch;
|
|
/// # use frame_system::{self as system, ensure_signed};
|
|
/// pub trait Trait: system::Trait where Self::AccountId: From<u32> {}
|
|
///
|
|
/// decl_module! {
|
|
/// pub struct Module<T: Trait> for enum Call where origin: T::Origin, T::AccountId: From<u32> {
|
|
/// // Your implementation
|
|
/// }
|
|
/// }
|
|
/// # fn main() {}
|
|
/// ```
|
|
///
|
|
/// ## Reserved Functions
|
|
///
|
|
/// The following are reserved function signatures:
|
|
///
|
|
/// * `deposit_event`: Helper function for depositing an [event](https://docs.substrate.dev/docs/event-enum).
|
|
/// The default behavior is to call `deposit_event` from the [System module](../frame_system/index.html).
|
|
/// However, you can write your own implementation for events in your runtime. To use the default behavior,
|
|
/// add `fn deposit_event() = default;` to your `Module`.
|
|
///
|
|
/// The following reserved functions also take the block number (with type `T::BlockNumber`) as an optional input:
|
|
///
|
|
/// * `on_runtime_upgrade`: Executes at the beginning of a block prior to on_initialize when there
|
|
/// is a runtime upgrade. This allows each module to upgrade its storage before the storage items are used.
|
|
/// As such, **calling other modules must be avoided**!! Using this function will implement the
|
|
/// [`OnRuntimeUpgrade`](../sp_runtime/traits/trait.OnRuntimeUpgrade.html) trait.
|
|
/// Function signature must be `fn on_runtime_upgrade() -> frame_support::weights::Weight`.
|
|
///
|
|
/// * `on_initialize`: Executes at the beginning of a block. Using this function will
|
|
/// implement the [`OnInitialize`](./trait.OnInitialize.html) trait.
|
|
/// Function signature can be either:
|
|
/// * `fn on_initialize(n: BlockNumber) -> frame_support::weights::Weight` or
|
|
/// * `fn on_initialize() -> frame_support::weights::Weight`
|
|
///
|
|
/// * `on_finalize`: Executes at the end of a block. Using this function will
|
|
/// implement the [`OnFinalize`](./traits/trait.OnFinalize.html) trait.
|
|
/// Function signature can be either:
|
|
/// * `fn on_finalize(n: BlockNumber) -> frame_support::weights::Weight` or
|
|
/// * `fn on_finalize() -> frame_support::weights::Weight`
|
|
///
|
|
/// * `offchain_worker`: Executes at the beginning of a block and produces extrinsics for a future block
|
|
/// upon completion. Using this function will implement the
|
|
/// [`OffchainWorker`](./traits/trait.OffchainWorker.html) trait.
|
|
#[macro_export]
|
|
macro_rules! decl_module {
|
|
// Entry point #1.
|
|
(
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident
|
|
$( <I>, I: $instantiable:path $( = $module_default_instance:path )? )?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty $(, $where_ty:ty: $where_bound:path )* {
|
|
$( $t:tt )*
|
|
}
|
|
) => {
|
|
$crate::decl_module!(@normalize
|
|
$(#[$attr])*
|
|
pub struct $mod_type<
|
|
$trait_instance: $trait_name $(<I>, I: $instantiable $(= $module_default_instance)?)?
|
|
>
|
|
for enum $call_type where origin: $origin_type, system = system
|
|
{ $( $where_ty: $where_bound ),* }
|
|
{}
|
|
{}
|
|
{}
|
|
{}
|
|
{}
|
|
{}
|
|
{}
|
|
[]
|
|
$($t)*
|
|
);
|
|
};
|
|
// Entry point #2.
|
|
(
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident
|
|
$( <I>, I: $instantiable:path $( = $module_default_instance:path )? )?
|
|
>
|
|
for enum $call_type:ident where
|
|
origin: $origin_type:ty,
|
|
system = $system:ident
|
|
$(, $where_ty:ty: $where_bound:path )*
|
|
{
|
|
$($t:tt)*
|
|
}
|
|
) => {
|
|
$crate::decl_module!(@normalize
|
|
$(#[$attr])*
|
|
pub struct $mod_type<
|
|
$trait_instance: $trait_name $(<I>, I: $instantiable $( = $module_default_instance )? )?
|
|
>
|
|
for enum $call_type where origin: $origin_type, system = $system
|
|
{ $( $where_ty: $where_bound ),* }
|
|
{}
|
|
{}
|
|
{}
|
|
{}
|
|
{}
|
|
{}
|
|
{}
|
|
[]
|
|
$($t)*
|
|
);
|
|
};
|
|
|
|
// Normalization expansions. Fills the defaults.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{}
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
$vis:vis fn deposit_event() = default;
|
|
$($rest:tt)*
|
|
) => {
|
|
$crate::decl_module!(@normalize
|
|
$(#[$attr])*
|
|
pub struct $mod_type<$trait_instance: $trait_name$(<I>, I: $instantiable $(= $module_default_instance)?)?>
|
|
for enum $call_type where origin: $origin_type, system = $system
|
|
{ $( $other_where_bounds )* }
|
|
{ $vis fn deposit_event() = default; }
|
|
{ $( $on_initialize )* }
|
|
{ $( $on_runtime_upgrade )* }
|
|
{ $( $on_finalize )* }
|
|
{ $( $offchain )* }
|
|
{ $( $constants )* }
|
|
{ $( $error_type )* }
|
|
[ $( $dispatchables )* ]
|
|
$($rest)*
|
|
);
|
|
};
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{}
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
$vis:vis fn deposit_event
|
|
$($rest:tt)*
|
|
) => {
|
|
compile_error!(
|
|
"`deposit_event` function is reserved and must follow the syntax: `$vis:vis fn deposit_event() = default;`"
|
|
);
|
|
};
|
|
// Add on_finalize
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{}
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
fn on_finalize( $( $param_name:ident : $param:ty ),* $(,)? ) { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
$crate::decl_module!(@normalize
|
|
$(#[$attr])*
|
|
pub struct $mod_type<$trait_instance: $trait_name$(<I>, I: $instantiable $(= $module_default_instance)?)?>
|
|
for enum $call_type where origin: $origin_type, system = $system
|
|
{ $( $other_where_bounds )* }
|
|
{ $( $deposit_event )* }
|
|
{ $( $on_initialize )* }
|
|
{ $( $on_runtime_upgrade )* }
|
|
{
|
|
fn on_finalize( $( $param_name : $param ),* ) { $( $impl )* }
|
|
}
|
|
{ $( $offchain )* }
|
|
{ $( $constants )* }
|
|
{ $( $error_type )* }
|
|
[ $( $dispatchables )* ]
|
|
$($rest)*
|
|
);
|
|
};
|
|
// compile_error on_finalize, given weight removed syntax.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{}
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
#[weight = $weight:expr]
|
|
fn on_finalize( $( $param_name:ident : $param:ty ),* $(,)? ) { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
compile_error!(
|
|
"`on_finalize` can't be given weight attribute anymore, weight must be returned by \
|
|
`on_initialize` or `on_runtime_upgrade` instead"
|
|
);
|
|
};
|
|
// compile_error on_runtime_upgrade, without a given weight removed syntax.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{}
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
fn on_runtime_upgrade( $( $param_name:ident : $param:ty ),* $(,)? ) { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
compile_error!(
|
|
"`on_runtime_upgrade` must return Weight, signature has changed."
|
|
);
|
|
};
|
|
// compile_error on_runtime_upgrade, given weight removed syntax.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{}
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
#[weight = $weight:expr]
|
|
fn on_runtime_upgrade( $( $param_name:ident : $param:ty ),* $(,)? ) { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
compile_error!(
|
|
"`on_runtime_upgrade` can't be given weight attribute anymore, weight must be returned \
|
|
by the function directly."
|
|
);
|
|
};
|
|
// Add on_runtime_upgrade
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{}
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
fn on_runtime_upgrade( $( $param_name:ident : $param:ty ),* $(,)? ) -> $return:ty { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
$crate::decl_module!(@normalize
|
|
$(#[$attr])*
|
|
pub struct $mod_type<$trait_instance: $trait_name$(<I>, I: $instantiable $(= $module_default_instance)?)?>
|
|
for enum $call_type where origin: $origin_type, system = $system
|
|
{ $( $other_where_bounds )* }
|
|
{ $( $deposit_event )* }
|
|
{ $( $on_initialize )* }
|
|
{
|
|
fn on_runtime_upgrade( $( $param_name : $param ),* ) -> $return { $( $impl )* }
|
|
}
|
|
{ $( $on_finalize )* }
|
|
{ $( $offchain )* }
|
|
{ $( $constants )* }
|
|
{ $( $error_type )* }
|
|
[ $( $dispatchables )* ]
|
|
$($rest)*
|
|
);
|
|
};
|
|
// compile_error on_initialize, without a given weight removed syntax.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{}
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
fn on_initialize( $( $param_name:ident : $param:ty ),* $(,)? ) { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
compile_error!(
|
|
"`on_initialize` must return Weight, signature has changed."
|
|
);
|
|
};
|
|
// compile_error on_initialize, with given weight removed syntax.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{}
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
#[weight = $weight:expr]
|
|
fn on_initialize( $( $param_name:ident : $param:ty ),* $(,)? ) { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
compile_error!(
|
|
"`on_initialize` can't be given weight attribute anymore, weight must be returned \
|
|
by the function directly."
|
|
);
|
|
};
|
|
// Add on_initialize
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{}
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
fn on_initialize( $( $param_name:ident : $param:ty ),* $(,)? ) -> $return:ty { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
$crate::decl_module!(@normalize
|
|
$(#[$attr])*
|
|
pub struct $mod_type<$trait_instance: $trait_name$(<I>, I: $instantiable $(= $module_default_instance)?)?>
|
|
for enum $call_type where origin: $origin_type, system = $system
|
|
{ $( $other_where_bounds )* }
|
|
{ $( $deposit_event )* }
|
|
{
|
|
fn on_initialize( $( $param_name : $param ),* ) -> $return { $( $impl )* }
|
|
}
|
|
{ $( $on_runtime_upgrade )* }
|
|
{ $( $on_finalize )* }
|
|
{ $( $offchain )* }
|
|
{ $( $constants )* }
|
|
{ $( $error_type )* }
|
|
[ $( $dispatchables )* ]
|
|
$($rest)*
|
|
);
|
|
};
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident
|
|
$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
fn offchain_worker( $( $param_name:ident : $param:ty ),* $(,)? ) { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
$crate::decl_module!(@normalize
|
|
$(#[$attr])*
|
|
pub struct $mod_type<
|
|
$trait_instance: $trait_name$(<I>, I: $instantiable $(= $module_default_instance)?)?
|
|
>
|
|
for enum $call_type where origin: $origin_type, system = $system
|
|
{ $( $other_where_bounds )* }
|
|
{ $( $deposit_event )* }
|
|
{ $( $on_initialize )* }
|
|
{ $( $on_runtime_upgrade )* }
|
|
{ $( $on_finalize )* }
|
|
{ fn offchain_worker( $( $param_name : $param ),* ) { $( $impl )* } }
|
|
{ $( $constants )* }
|
|
{ $( $error_type )* }
|
|
[ $( $dispatchables )* ]
|
|
$($rest)*
|
|
);
|
|
};
|
|
|
|
// This puts a constant in the parsed constants list.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident
|
|
$(<I>, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$( #[doc = $doc_attr:tt] )*
|
|
const $name:ident: $ty:ty = $value:expr;
|
|
$( $rest:tt )*
|
|
) => {
|
|
$crate::decl_module!(@normalize
|
|
$(#[$attr])*
|
|
pub struct $mod_type<
|
|
$trait_instance: $trait_name
|
|
$( <I>, $instance: $instantiable $(= $module_default_instance)? )?
|
|
>
|
|
for enum $call_type where origin: $origin_type, system = $system
|
|
{ $( $other_where_bounds )* }
|
|
{ $( $deposit_event )* }
|
|
{ $( $on_initialize )* }
|
|
{ $( $on_runtime_upgrade )* }
|
|
{ $( $on_finalize )* }
|
|
{ $( $offchain )* }
|
|
{
|
|
$( $constants )*
|
|
$( #[doc = $doc_attr ] )*
|
|
$name: $ty = $value;
|
|
}
|
|
{ $( $error_type )* }
|
|
[ $( $dispatchables )* ]
|
|
$($rest)*
|
|
);
|
|
};
|
|
|
|
// Parse error type
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident:
|
|
$trait_name:ident$(<I>, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
type Error = $error_type:ty;
|
|
$($rest:tt)*
|
|
) => {
|
|
$crate::decl_module!(@normalize
|
|
$(#[$attr])*
|
|
pub struct $mod_type<
|
|
$trait_instance: $trait_name$(<I>, $instance: $instantiable $(= $module_default_instance)?)?
|
|
>
|
|
for enum $call_type where origin: $origin_type, system = $system
|
|
{ $( $other_where_bounds )* }
|
|
{ $( $deposit_event )* }
|
|
{ $( $on_initialize )* }
|
|
{ $( $on_runtime_upgrade )* }
|
|
{ $( $on_finalize )* }
|
|
{ $( $offchain )* }
|
|
{ $( $constants )* }
|
|
{ $error_type }
|
|
[ $( $dispatchables )* ]
|
|
$($rest)*
|
|
);
|
|
};
|
|
// Add default Error if none supplied
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident:
|
|
$trait_name:ident$(<I>, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ }
|
|
[ $($t:tt)* ]
|
|
$($rest:tt)*
|
|
) => {
|
|
$crate::decl_module!(@normalize
|
|
$(#[$attr])*
|
|
pub struct $mod_type<
|
|
$trait_instance: $trait_name$(<I>, $instance: $instantiable $(= $module_default_instance)?)?
|
|
>
|
|
for enum $call_type where origin: $origin_type, system = $system
|
|
{ $( $other_where_bounds )* }
|
|
{ $( $deposit_event )* }
|
|
{ $( $on_initialize )* }
|
|
{ $( $on_runtime_upgrade )* }
|
|
{ $( $on_finalize )* }
|
|
{ $( $offchain )* }
|
|
{ $( $constants )* }
|
|
{ &'static str }
|
|
[ $($t)* ]
|
|
$($rest)*
|
|
);
|
|
};
|
|
|
|
// This puts the function statement into the [], decreasing `$rest` and moving toward finishing the parse.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident
|
|
$(<I>, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $error_type:ty }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
#[weight = $weight:expr]
|
|
$fn_vis:vis fn $fn_name:ident(
|
|
$origin:ident $( , $(#[$codec_attr:ident])* $param_name:ident : $param:ty )* $(,)?
|
|
) $( -> $result:ty )* { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
$crate::decl_module!(@normalize
|
|
$(#[$attr])*
|
|
pub struct $mod_type<
|
|
$trait_instance: $trait_name$(<I>, $instance: $instantiable $(= $module_default_instance)?)?
|
|
>
|
|
for enum $call_type where origin: $origin_type, system = $system
|
|
{ $( $other_where_bounds )* }
|
|
{ $( $deposit_event )* }
|
|
{ $( $on_initialize )* }
|
|
{ $( $on_runtime_upgrade )* }
|
|
{ $( $on_finalize )* }
|
|
{ $( $offchain )* }
|
|
{ $( $constants )* }
|
|
{ $error_type }
|
|
[
|
|
$( $dispatchables )*
|
|
$(#[doc = $doc_attr])*
|
|
#[weight = $weight]
|
|
$fn_vis fn $fn_name(
|
|
$origin $( , $(#[$codec_attr])* $param_name : $param )*
|
|
) $( -> $result )* { $( $impl )* }
|
|
{ $($instance: $instantiable)? }
|
|
]
|
|
$($rest)*
|
|
);
|
|
};
|
|
// Add #[weight] if none is defined.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident:
|
|
$trait_name:ident$(<I>, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
$fn_vis:vis fn $fn_name:ident(
|
|
$from:ident $( , $( #[$codec_attr:ident] )* $param_name:ident : $param:ty )* $(,)?
|
|
) $( -> $result:ty )* { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
compile_error!(concat!(
|
|
"Missing weight for ", stringify!($ident),
|
|
". Every dispatchable must have a #[weight] attribute."
|
|
)
|
|
);
|
|
};
|
|
// Ignore any ident which is not `origin` with type `T::Origin`.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
$(#[weight = $weight:expr])?
|
|
$fn_vis:vis fn $fn_name:ident(
|
|
$origin:ident : T::Origin $( , $( #[$codec_attr:ident] )* $param_name:ident : $param:ty )* $(,)?
|
|
) $( -> $result:ty )* { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
compile_error!(
|
|
"First parameter of dispatch should be marked `origin` only, with no type specified \
|
|
(a bit like `self`)."
|
|
);
|
|
};
|
|
// Ignore any ident which is `origin` but has a type, regardless of the type token itself.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
$(#[weight = $weight:expr])?
|
|
$fn_vis:vis fn $fn_name:ident(
|
|
origin : $origin:ty $( , $( #[$codec_attr:ident] )* $param_name:ident : $param:ty )* $(,)?
|
|
) $( -> $result:ty )* { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
compile_error!(
|
|
"First parameter of dispatch should be marked `origin` only, with no type specified \
|
|
(a bit like `self`)."
|
|
);
|
|
};
|
|
// Ignore any function missing `origin` as the first parameter.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
$(#[doc = $doc_attr:tt])*
|
|
$(#[weight = $weight:expr])?
|
|
$fn_vis:vis fn $fn_name:ident(
|
|
$( $(#[$codec_attr:ident])* $param_name:ident : $param:ty ),* $(,)?
|
|
) $( -> $result:ty )* { $( $impl:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
compile_error!(
|
|
"Implicit conversion to privileged function has been removed. \
|
|
First parameter of dispatch should be marked `origin`. \
|
|
For root-matching dispatch, also add `ensure_root(origin)?`."
|
|
);
|
|
};
|
|
// Last normalize step. Triggers `@imp` expansion which is the real expansion.
|
|
(@normalize
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path $(= $module_default_instance:path)?)?>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $( $error_type:tt )* }
|
|
[ $( $dispatchables:tt )* ]
|
|
) => {
|
|
$crate::decl_module!(@imp
|
|
$(#[$attr])*
|
|
pub struct $mod_type<$trait_instance: $trait_name$(<I>, I: $instantiable $(= $module_default_instance)?)?>
|
|
for enum $call_type where origin: $origin_type, system = $system {
|
|
$( $dispatchables )*
|
|
}
|
|
{ $( $other_where_bounds )* }
|
|
{ $( $deposit_event )* }
|
|
{ $( $on_initialize )* }
|
|
{ $( $on_runtime_upgrade )* }
|
|
{ $( $on_finalize )* }
|
|
{ $( $offchain )* }
|
|
{ $( $constants )* }
|
|
{ $( $error_type )* }
|
|
);
|
|
};
|
|
|
|
// Implementation of Call enum's .dispatch() method.
|
|
// TODO: this probably should be a different macro?
|
|
|
|
(@call
|
|
$ignore:ident
|
|
$mod_type:ident<$trait_instance:ident $(, $instance:ident)?> $fn_name:ident $origin:ident $system:ident [ $( $param_name:ident),* ]
|
|
) => {
|
|
<$mod_type<$trait_instance $(, $instance)?>>::$fn_name( $origin $(, $param_name )* )
|
|
};
|
|
|
|
// no `deposit_event` function wanted
|
|
(@impl_deposit_event
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, I: $instantiable:path)?>;
|
|
$system:ident;
|
|
{ $( $other_where_bounds:tt )* }
|
|
) => {};
|
|
|
|
(@impl_deposit_event
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
$system:ident;
|
|
{ $( $other_where_bounds:tt )* }
|
|
$vis:vis fn deposit_event$(<$event_trait_instance:ident $(, $event_instance:ident)?>)?() = default;
|
|
) => {
|
|
impl<$trait_instance: $trait_name$(<I>, $instance: $instantiable)?> $module<$trait_instance $(, $instance)?>
|
|
where $( $other_where_bounds )*
|
|
{
|
|
$vis fn deposit_event(
|
|
event: impl Into<< $trait_instance as $trait_name $(<$instance>)? >::Event>
|
|
) {
|
|
<$system::Module<$trait_instance>>::deposit_event(event.into())
|
|
}
|
|
}
|
|
};
|
|
|
|
(@impl_on_initialize
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
{ $( $other_where_bounds:tt )* }
|
|
fn on_initialize() -> $return:ty { $( $impl:tt )* }
|
|
) => {
|
|
impl<$trait_instance: $trait_name$(<I>, $instance: $instantiable)?>
|
|
$crate::traits::OnInitialize<$trait_instance::BlockNumber>
|
|
for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn on_initialize(_block_number_not_used: $trait_instance::BlockNumber) -> $return {
|
|
use $crate::sp_std::if_std;
|
|
if_std! {
|
|
use $crate::tracing;
|
|
let span = tracing::span!(tracing::Level::DEBUG, "on_initialize");
|
|
let _enter = span.enter();
|
|
}
|
|
{ $( $impl )* }
|
|
}
|
|
}
|
|
};
|
|
|
|
(@impl_on_initialize
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
{ $( $other_where_bounds:tt )* }
|
|
fn on_initialize($param:ident : $param_ty:ty) -> $return:ty { $( $impl:tt )* }
|
|
) => {
|
|
impl<$trait_instance: $trait_name$(<I>, $instance: $instantiable)?>
|
|
$crate::traits::OnInitialize<$trait_instance::BlockNumber>
|
|
for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn on_initialize($param: $param_ty) -> $return {
|
|
use $crate::sp_std::if_std;
|
|
if_std! {
|
|
use $crate::tracing;
|
|
let span = tracing::span!(tracing::Level::DEBUG, "on_initialize");
|
|
let _enter = span.enter();
|
|
}
|
|
{ $( $impl )* }
|
|
}
|
|
}
|
|
};
|
|
|
|
(@impl_on_initialize
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
{ $( $other_where_bounds:tt )* }
|
|
) => {
|
|
impl<$trait_instance: $trait_name$(<I>, $instance: $instantiable)?>
|
|
$crate::traits::OnInitialize<$trait_instance::BlockNumber>
|
|
for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )*
|
|
{}
|
|
};
|
|
|
|
(@impl_on_runtime_upgrade
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
{ $( $other_where_bounds:tt )* }
|
|
fn on_runtime_upgrade() -> $return:ty { $( $impl:tt )* }
|
|
) => {
|
|
impl<$trait_instance: $trait_name$(<I>, $instance: $instantiable)?>
|
|
$crate::traits::OnRuntimeUpgrade
|
|
for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn on_runtime_upgrade() -> $return {
|
|
use $crate::sp_std::if_std;
|
|
if_std! {
|
|
use $crate::tracing;
|
|
let span = tracing::span!(tracing::Level::DEBUG, "on_runtime_upgrade");
|
|
let _enter = span.enter();
|
|
}
|
|
{ $( $impl )* }
|
|
}
|
|
}
|
|
};
|
|
|
|
(@impl_on_runtime_upgrade
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
{ $( $other_where_bounds:tt )* }
|
|
) => {
|
|
impl<$trait_instance: $trait_name$(<I>, $instance: $instantiable)?>
|
|
$crate::traits::OnRuntimeUpgrade
|
|
for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )*
|
|
{}
|
|
};
|
|
|
|
|
|
(@impl_on_finalize
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
{ $( $other_where_bounds:tt )* }
|
|
fn on_finalize() { $( $impl:tt )* }
|
|
) => {
|
|
impl<$trait_instance: $trait_name$(<I>, $instance: $instantiable)?>
|
|
$crate::traits::OnFinalize<$trait_instance::BlockNumber>
|
|
for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn on_finalize(_block_number_not_used: $trait_instance::BlockNumber) {
|
|
use $crate::sp_std::if_std;
|
|
if_std! {
|
|
use $crate::tracing;
|
|
let span = tracing::span!(tracing::Level::DEBUG, "on_finalize");
|
|
let _enter = span.enter();
|
|
}
|
|
{ $( $impl )* }
|
|
}
|
|
}
|
|
};
|
|
|
|
(@impl_on_finalize
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
{ $( $other_where_bounds:tt )* }
|
|
fn on_finalize($param:ident : $param_ty:ty) { $( $impl:tt )* }
|
|
) => {
|
|
impl<$trait_instance: $trait_name$(<I>, $instance: $instantiable)?>
|
|
$crate::traits::OnFinalize<$trait_instance::BlockNumber>
|
|
for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn on_finalize($param: $param_ty) {
|
|
use $crate::sp_std::if_std;
|
|
if_std! {
|
|
use $crate::tracing;
|
|
let span = tracing::span!(tracing::Level::DEBUG, "on_finalize");
|
|
let _enter = span.enter();
|
|
}
|
|
{ $( $impl )* }
|
|
}
|
|
}
|
|
};
|
|
|
|
(@impl_on_finalize
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
{ $( $other_where_bounds:tt )* }
|
|
) => {
|
|
impl<$trait_instance: $trait_name$(<I>, $instance: $instantiable)?>
|
|
$crate::traits::OnFinalize<$trait_instance::BlockNumber>
|
|
for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
}
|
|
};
|
|
|
|
(@impl_offchain
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
{ $( $other_where_bounds:tt )* }
|
|
fn offchain_worker() { $( $impl:tt )* }
|
|
) => {
|
|
impl<$trait_instance: $trait_name$(<I>, $instance: $instantiable)?>
|
|
$crate::traits::OffchainWorker<$trait_instance::BlockNumber>
|
|
for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn offchain_worker(_block_number_not_used: $trait_instance::BlockNumber) { $( $impl )* }
|
|
}
|
|
};
|
|
|
|
(@impl_offchain
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
{ $( $other_where_bounds:tt )* }
|
|
fn offchain_worker($param:ident : $param_ty:ty) { $( $impl:tt )* }
|
|
) => {
|
|
impl<$trait_instance: $trait_name$(<I>, $instance: $instantiable)?>
|
|
$crate::traits::OffchainWorker<$trait_instance::BlockNumber>
|
|
for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn offchain_worker($param: $param_ty) { $( $impl )* }
|
|
}
|
|
};
|
|
|
|
(@impl_offchain
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
{ $( $other_where_bounds:tt )* }
|
|
) => {
|
|
impl<$trait_instance: $trait_name$(<I>, $instance: $instantiable)?>
|
|
$crate::traits::OffchainWorker<$trait_instance::BlockNumber>
|
|
for $module<$trait_instance$(, $instance)?> where $( $other_where_bounds )*
|
|
{}
|
|
};
|
|
|
|
// Expansion for _origin_ dispatch functions with no return type.
|
|
(@impl_function
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
$origin_ty:ty;
|
|
$error_type:ty;
|
|
$ignore:ident;
|
|
$(#[doc = $doc_attr:tt])*
|
|
$vis:vis fn $name:ident (
|
|
$origin:ident $(, $param:ident : $param_ty:ty )*
|
|
) { $( $impl:tt )* }
|
|
) => {
|
|
$(#[doc = $doc_attr])*
|
|
#[allow(unreachable_code)]
|
|
$vis fn $name(
|
|
$origin: $origin_ty $(, $param: $param_ty )*
|
|
) -> $crate::dispatch::DispatchResult {
|
|
$crate::sp_std::if_std! {
|
|
use $crate::tracing;
|
|
let span = tracing::span!(tracing::Level::DEBUG, stringify!($name));
|
|
let _enter = span.enter();
|
|
}
|
|
{
|
|
{ $( $impl )* }
|
|
Ok(())
|
|
}
|
|
}
|
|
};
|
|
|
|
// Expansion for _origin_ dispatch functions with explicit return type.
|
|
(@impl_function
|
|
$module:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>;
|
|
$origin_ty:ty;
|
|
$error_type:ty;
|
|
$ignore:ident;
|
|
$(#[doc = $doc_attr:tt])*
|
|
$vis:vis fn $name:ident (
|
|
$origin:ident $(, $param:ident : $param_ty:ty )*
|
|
) -> $result:ty { $( $impl:tt )* }
|
|
) => {
|
|
$(#[doc = $doc_attr])*
|
|
$vis fn $name($origin: $origin_ty $(, $param: $param_ty )* ) -> $result {
|
|
use $crate::sp_std::if_std;
|
|
if_std! {
|
|
use $crate::tracing;
|
|
let span = tracing::span!(tracing::Level::DEBUG, stringify!($name));
|
|
let _enter = span.enter();
|
|
}
|
|
{ $( $impl )* }
|
|
}
|
|
};
|
|
|
|
// Declare a `Call` variant parameter that should be encoded `compact`.
|
|
(@create_call_enum
|
|
$call_type:ident;
|
|
<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?>
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $generated_variants:tt )* }
|
|
{ $( $current_params:tt )* }
|
|
variant $fn_name:ident;
|
|
$( #[doc = $doc_attr:tt] )*
|
|
#[compact]
|
|
$type:ty;
|
|
$( $rest:tt )*
|
|
) => {
|
|
$crate::decl_module! {
|
|
@create_call_enum
|
|
$call_type;
|
|
<$trait_instance: $trait_name $(<I>, $instance: $instantiable $(= $module_default_instance)? )?>
|
|
{ $( $other_where_bounds )* }
|
|
{ $( $generated_variants )* }
|
|
{
|
|
$( $current_params )*
|
|
#[codec(compact)]
|
|
$type,
|
|
}
|
|
variant $fn_name;
|
|
$( #[doc = $doc_attr] )*
|
|
$( $rest )*
|
|
}
|
|
};
|
|
|
|
// Declare a `Call` variant parameter.
|
|
(@create_call_enum
|
|
$call_type:ident;
|
|
<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?>
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $generated_variants:tt )* }
|
|
{ $( $current_params:tt )* }
|
|
variant $fn_name:ident;
|
|
$(#[doc = $doc_attr:tt])*
|
|
$type:ty;
|
|
$( $rest:tt )*
|
|
) => {
|
|
$crate::decl_module! {
|
|
@create_call_enum
|
|
$call_type;
|
|
<$trait_instance: $trait_name $(<I>, $instance: $instantiable $(= $module_default_instance)? )?>
|
|
{ $( $other_where_bounds )* }
|
|
{ $( $generated_variants )* }
|
|
{
|
|
$( $current_params )*
|
|
$type,
|
|
}
|
|
variant $fn_name;
|
|
$( #[doc = $doc_attr] )*
|
|
$( $rest )*
|
|
}
|
|
};
|
|
|
|
(@create_call_enum
|
|
$call_type:ident;
|
|
<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?>
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $generated_variants:tt )* }
|
|
{ $( $current_params:tt )* }
|
|
variant $fn_name:ident;
|
|
$(#[doc = $doc_attr:tt])*
|
|
$(
|
|
variant $next_fn_name:ident;
|
|
$( $rest:tt )*
|
|
)?
|
|
) => {
|
|
$crate::decl_module! {
|
|
@create_call_enum
|
|
$call_type;
|
|
<$trait_instance: $trait_name $(<I>, $instance: $instantiable $(= $module_default_instance)? )?>
|
|
{ $( $other_where_bounds )* }
|
|
{
|
|
$( $generated_variants )*
|
|
#[allow(non_camel_case_types)]
|
|
$(#[doc = $doc_attr])*
|
|
$fn_name (
|
|
$( $current_params )*
|
|
),
|
|
}
|
|
{}
|
|
$(
|
|
variant $next_fn_name;
|
|
$( $rest )*
|
|
)?
|
|
}
|
|
};
|
|
|
|
(@create_call_enum
|
|
$call_type:ident;
|
|
<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?>
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $generated_variants:tt )* }
|
|
{}
|
|
) => {
|
|
/// Dispatchable calls.
|
|
///
|
|
/// Each variant of this enum maps to a dispatchable function from the associated module.
|
|
#[derive($crate::codec::Encode, $crate::codec::Decode)]
|
|
pub enum $call_type<$trait_instance: $trait_name$(<I>, $instance: $instantiable $( = $module_default_instance)?)?>
|
|
where $( $other_where_bounds )*
|
|
{
|
|
#[doc(hidden)]
|
|
#[codec(skip)]
|
|
__PhantomItem($crate::sp_std::marker::PhantomData<($trait_instance, $($instance)?)>, $crate::dispatch::Never),
|
|
$( $generated_variants )*
|
|
}
|
|
};
|
|
|
|
// The main macro expansion that actually renders the module code.
|
|
|
|
(@imp
|
|
$(#[$attr:meta])*
|
|
pub struct $mod_type:ident<
|
|
$trait_instance:ident: $trait_name:ident
|
|
$(<I>, $instance:ident: $instantiable:path $(= $module_default_instance:path)?)?
|
|
>
|
|
for enum $call_type:ident where origin: $origin_type:ty, system = $system:ident {
|
|
$(
|
|
$(#[doc = $doc_attr:tt])*
|
|
#[weight = $weight:expr]
|
|
$fn_vis:vis fn $fn_name:ident(
|
|
$from:ident $( , $(#[$codec_attr:ident])* $param_name:ident : $param:ty)*
|
|
) $( -> $result:ty )* { $( $impl:tt )* }
|
|
{ $($fn_instance:ident: $fn_instantiable:path)? }
|
|
)*
|
|
}
|
|
{ $( $other_where_bounds:tt )* }
|
|
{ $( $deposit_event:tt )* }
|
|
{ $( $on_initialize:tt )* }
|
|
{ $( $on_runtime_upgrade:tt )* }
|
|
{ $( $on_finalize:tt )* }
|
|
{ $( $offchain:tt )* }
|
|
{ $( $constants:tt )* }
|
|
{ $error_type:ty }
|
|
) => {
|
|
$crate::__check_reserved_fn_name! { $( $fn_name )* }
|
|
|
|
// Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
|
|
#[derive(Clone, Copy, PartialEq, Eq, $crate::RuntimeDebug)]
|
|
$( #[$attr] )*
|
|
pub struct $mod_type<
|
|
$trait_instance: $trait_name
|
|
$(<I>, $instance: $instantiable $( = $module_default_instance)?)?
|
|
>($crate::sp_std::marker::PhantomData<($trait_instance, $( $instance)?)>) where
|
|
$( $other_where_bounds )*;
|
|
|
|
$crate::decl_module! {
|
|
@impl_on_initialize
|
|
$mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>;
|
|
{ $( $other_where_bounds )* }
|
|
$( $on_initialize )*
|
|
}
|
|
|
|
$crate::decl_module! {
|
|
@impl_on_runtime_upgrade
|
|
$mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>;
|
|
{ $( $other_where_bounds )* }
|
|
$( $on_runtime_upgrade )*
|
|
}
|
|
|
|
|
|
$crate::decl_module! {
|
|
@impl_on_finalize
|
|
$mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>;
|
|
{ $( $other_where_bounds )* }
|
|
$( $on_finalize )*
|
|
}
|
|
|
|
$crate::decl_module! {
|
|
@impl_offchain
|
|
$mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>;
|
|
{ $( $other_where_bounds )* }
|
|
$( $offchain )*
|
|
}
|
|
$crate::decl_module! {
|
|
@impl_deposit_event
|
|
$mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>;
|
|
$system;
|
|
{ $( $other_where_bounds )* }
|
|
$( $deposit_event )*
|
|
}
|
|
|
|
/// Can also be called using [`Call`].
|
|
///
|
|
/// [`Call`]: enum.Call.html
|
|
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $mod_type<$trait_instance $(, $instance)?>
|
|
where $( $other_where_bounds )*
|
|
{
|
|
$(
|
|
$crate::decl_module! {
|
|
@impl_function
|
|
$mod_type<$trait_instance: $trait_name $(<I>, $fn_instance: $fn_instantiable)?>;
|
|
$origin_type;
|
|
$error_type;
|
|
$from;
|
|
$(#[doc = $doc_attr])*
|
|
$fn_vis fn $fn_name (
|
|
$from $(, $param_name : $param )*
|
|
) $( -> $result )* { $( $impl )* }
|
|
}
|
|
)*
|
|
}
|
|
|
|
$crate::decl_module! {
|
|
@create_call_enum
|
|
$call_type;
|
|
<$trait_instance: $trait_name $(<I>, $instance: $instantiable $(= $module_default_instance)? )?>
|
|
{ $( $other_where_bounds )* }
|
|
{}
|
|
{}
|
|
$(
|
|
variant $fn_name;
|
|
$(#[doc = $doc_attr])*
|
|
$(
|
|
$(#[$codec_attr])*
|
|
$param;
|
|
)*
|
|
)*
|
|
}
|
|
|
|
// Implement weight calculation function for Call
|
|
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::GetDispatchInfo
|
|
for $call_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn get_dispatch_info(&self) -> $crate::dispatch::DispatchInfo {
|
|
match *self {
|
|
$(
|
|
$call_type::$fn_name( $( ref $param_name ),* ) => {
|
|
let weight = <dyn $crate::dispatch::WeighData<( $( & $param, )* )>>::weigh_data(
|
|
&$weight,
|
|
($( $param_name, )*)
|
|
);
|
|
let class = <dyn $crate::dispatch::ClassifyDispatch<( $( & $param, )* )>>::classify_dispatch(
|
|
&$weight,
|
|
($( $param_name, )*)
|
|
);
|
|
let pays_fee = <dyn $crate::dispatch::PaysFee<( $( & $param, )* )>>::pays_fee(
|
|
&$weight,
|
|
($( $param_name, )*)
|
|
);
|
|
$crate::dispatch::DispatchInfo {
|
|
weight,
|
|
class,
|
|
pays_fee,
|
|
}
|
|
},
|
|
)*
|
|
$call_type::__PhantomItem(_, _) => unreachable!("__PhantomItem should never be used."),
|
|
}
|
|
}
|
|
}
|
|
|
|
// Implement GetCallName for the Call.
|
|
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::GetCallName
|
|
for $call_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn get_call_name(&self) -> &'static str {
|
|
match *self {
|
|
$(
|
|
$call_type::$fn_name( $( ref $param_name ),* ) => {
|
|
// Don't generate any warnings for unused variables
|
|
let _ = ( $( $param_name ),* );
|
|
stringify!($fn_name)
|
|
},
|
|
)*
|
|
$call_type::__PhantomItem(_, _) => unreachable!("__PhantomItem should never be used."),
|
|
}
|
|
}
|
|
|
|
fn get_call_names() -> &'static [&'static str] {
|
|
&[
|
|
$(
|
|
stringify!($fn_name),
|
|
)*
|
|
]
|
|
}
|
|
}
|
|
|
|
// manual implementation of clone/eq/partialeq because using derive erroneously requires
|
|
// clone/eq/partialeq from T.
|
|
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::Clone
|
|
for $call_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn clone(&self) -> Self {
|
|
match *self {
|
|
$(
|
|
$call_type::$fn_name( $( ref $param_name ),* ) =>
|
|
$call_type::$fn_name( $( (*$param_name).clone() ),* )
|
|
,)*
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
}
|
|
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::PartialEq
|
|
for $call_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn eq(&self, _other: &Self) -> bool {
|
|
match *self {
|
|
$(
|
|
$call_type::$fn_name( $( ref $param_name ),* ) => {
|
|
let self_params = ( $( $param_name, )* );
|
|
if let $call_type::$fn_name( $( ref $param_name ),* ) = *_other {
|
|
self_params == ( $( $param_name, )* )
|
|
} else {
|
|
match *_other {
|
|
$call_type::__PhantomItem(_, _) => unreachable!(),
|
|
_ => false,
|
|
}
|
|
}
|
|
}
|
|
)*
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
}
|
|
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::Eq
|
|
for $call_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
|
|
{}
|
|
|
|
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::fmt::Debug
|
|
for $call_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn fmt(
|
|
&self,
|
|
_f: &mut $crate::dispatch::fmt::Formatter,
|
|
) -> $crate::dispatch::result::Result<(), $crate::dispatch::fmt::Error> {
|
|
match *self {
|
|
$(
|
|
$call_type::$fn_name( $( ref $param_name ),* ) =>
|
|
write!(_f, "{}{:?}",
|
|
stringify!($fn_name),
|
|
( $( $param_name.clone(), )* )
|
|
)
|
|
,)*
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::Dispatchable
|
|
for $call_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
type Trait = $trait_instance;
|
|
type Origin = $origin_type;
|
|
fn dispatch(self, _origin: Self::Origin) -> $crate::sp_runtime::DispatchResult {
|
|
match self {
|
|
$(
|
|
$call_type::$fn_name( $( $param_name ),* ) => {
|
|
$crate::decl_module!(
|
|
@call
|
|
$from
|
|
$mod_type<$trait_instance $(, $fn_instance)?> $fn_name _origin $system [ $( $param_name ),* ]
|
|
)
|
|
},
|
|
)*
|
|
$call_type::__PhantomItem(_, _) => { unreachable!("__PhantomItem should never be used.") },
|
|
}
|
|
}
|
|
}
|
|
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::Callable<$trait_instance>
|
|
for $mod_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
type Call = $call_type<$trait_instance $(, $instance)?>;
|
|
}
|
|
|
|
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $mod_type<$trait_instance $(, $instance)?>
|
|
where $( $other_where_bounds )*
|
|
{
|
|
#[doc(hidden)]
|
|
pub fn dispatch<D: $crate::dispatch::Dispatchable<Trait = $trait_instance>>(
|
|
d: D,
|
|
origin: D::Origin
|
|
) -> $crate::sp_runtime::DispatchResult {
|
|
d.dispatch(origin)
|
|
}
|
|
}
|
|
$crate::__dispatch_impl_metadata! {
|
|
$mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>
|
|
{ $( $other_where_bounds )* }
|
|
$call_type $origin_type
|
|
{
|
|
$(
|
|
$(#[doc = $doc_attr])*
|
|
fn $fn_name($from $(, $(#[$codec_attr])* $param_name : $param )*);
|
|
)*
|
|
}
|
|
}
|
|
$crate::__impl_module_constants_metadata ! {
|
|
$mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>
|
|
{ $( $other_where_bounds )* }
|
|
$( $constants )*
|
|
}
|
|
|
|
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::ModuleErrorMetadata
|
|
for $mod_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
fn metadata() -> &'static [$crate::dispatch::ErrorMetadata] {
|
|
<$error_type as $crate::dispatch::ModuleErrorMetadata>::metadata()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub trait IsSubType<T: Callable<R>, R> {
|
|
fn is_sub_type(&self) -> Option<&CallableCallFor<T, R>>;
|
|
}
|
|
|
|
/// Implement a meta-dispatch module to dispatch to other dispatchers.
|
|
#[macro_export]
|
|
macro_rules! impl_outer_dispatch {
|
|
(
|
|
$(#[$attr:meta])*
|
|
pub enum $call_type:ident for $runtime:ident where origin: $origin:ty {
|
|
$(
|
|
$module:ident::$camelcase:ident,
|
|
)*
|
|
}
|
|
) => {
|
|
$(#[$attr])*
|
|
#[derive(
|
|
Clone, PartialEq, Eq,
|
|
$crate::codec::Encode,
|
|
$crate::codec::Decode,
|
|
$crate::RuntimeDebug,
|
|
)]
|
|
pub enum $call_type {
|
|
$(
|
|
$camelcase ( $crate::dispatch::CallableCallFor<$camelcase, $runtime> )
|
|
,)*
|
|
}
|
|
impl $crate::dispatch::GetDispatchInfo for $call_type {
|
|
fn get_dispatch_info(&self) -> $crate::dispatch::DispatchInfo {
|
|
match self {
|
|
$( $call_type::$camelcase(call) => call.get_dispatch_info(), )*
|
|
}
|
|
}
|
|
}
|
|
impl $crate::dispatch::GetCallMetadata for $call_type {
|
|
fn get_call_metadata(&self) -> $crate::dispatch::CallMetadata {
|
|
use $crate::dispatch::GetCallName;
|
|
match self {
|
|
$( $call_type::$camelcase(call) => {
|
|
let function_name = call.get_call_name();
|
|
let pallet_name = stringify!($camelcase);
|
|
$crate::dispatch::CallMetadata { function_name, pallet_name }
|
|
}, )*
|
|
}
|
|
}
|
|
|
|
fn get_module_names() -> &'static [&'static str] {
|
|
&[$(
|
|
stringify!($camelcase),
|
|
)*]
|
|
}
|
|
|
|
fn get_call_names(module: &str) -> &'static [&'static str] {
|
|
use $crate::dispatch::{Callable, GetCallName};
|
|
match module {
|
|
$(
|
|
stringify!($camelcase) =>
|
|
<<$camelcase as Callable<$runtime>>::Call
|
|
as GetCallName>::get_call_names(),
|
|
)*
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
}
|
|
impl $crate::dispatch::Dispatchable for $call_type {
|
|
type Origin = $origin;
|
|
type Trait = $call_type;
|
|
fn dispatch(
|
|
self,
|
|
origin: $origin,
|
|
) -> $crate::sp_runtime::DispatchResult {
|
|
$crate::impl_outer_dispatch! {
|
|
@DISPATCH_MATCH
|
|
self
|
|
$call_type
|
|
origin
|
|
{}
|
|
0;
|
|
$( $camelcase ),*
|
|
}
|
|
}
|
|
}
|
|
$(
|
|
impl $crate::dispatch::IsSubType<$camelcase, $runtime> for $call_type {
|
|
#[allow(unreachable_patterns)]
|
|
fn is_sub_type(&self) -> Option<&$crate::dispatch::CallableCallFor<$camelcase, $runtime>> {
|
|
match *self {
|
|
$call_type::$camelcase(ref r) => Some(r),
|
|
// May be unreachable
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<$crate::dispatch::CallableCallFor<$camelcase, $runtime>> for $call_type {
|
|
fn from(call: $crate::dispatch::CallableCallFor<$camelcase, $runtime>) -> Self {
|
|
$call_type::$camelcase(call)
|
|
}
|
|
}
|
|
)*
|
|
};
|
|
(@DISPATCH_MATCH
|
|
$self:ident
|
|
$call_type:ident
|
|
$origin:ident
|
|
{ $( $generated:tt )* }
|
|
$index:expr;
|
|
$name:ident
|
|
$( , $rest:ident )*
|
|
) => {
|
|
$crate::impl_outer_dispatch! {
|
|
@DISPATCH_MATCH
|
|
$self
|
|
$call_type
|
|
$origin
|
|
{
|
|
$( $generated )*
|
|
$call_type::$name(call) => call.dispatch($origin),
|
|
}
|
|
$index + 1;
|
|
$( $rest ),*
|
|
}
|
|
};
|
|
(@DISPATCH_MATCH
|
|
$self:ident
|
|
$call_type:ident
|
|
$origin:ident
|
|
{ $( $generated:tt )* }
|
|
$index:expr;
|
|
) => {
|
|
match $self {
|
|
$( $generated )*
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Implement metadata for dispatch.
|
|
#[macro_export]
|
|
#[doc(hidden)]
|
|
macro_rules! __dispatch_impl_metadata {
|
|
(
|
|
$mod_type:ident<$trait_instance:ident: $trait_name:ident$(<I>, $instance:ident: $instantiable:path)?>
|
|
{ $( $other_where_bounds:tt )* }
|
|
$($rest:tt)*
|
|
) => {
|
|
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $mod_type<$trait_instance $(, $instance)?>
|
|
where $( $other_where_bounds )*
|
|
{
|
|
#[doc(hidden)]
|
|
pub fn call_functions() -> &'static [$crate::dispatch::FunctionMetadata] {
|
|
$crate::__call_to_functions!($($rest)*)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Implement metadata for module constants.
|
|
#[macro_export]
|
|
#[doc(hidden)]
|
|
macro_rules! __impl_module_constants_metadata {
|
|
// Without instance
|
|
(
|
|
$mod_type:ident<$trait_instance:ident: $trait_name:ident>
|
|
{ $( $other_where_bounds:tt )* }
|
|
$(
|
|
$( #[doc = $doc_attr:tt] )*
|
|
$name:ident: $type:ty = $value:expr;
|
|
)*
|
|
) => {
|
|
$crate::paste::item! {
|
|
$crate::__impl_module_constants_metadata! {
|
|
GENERATE_CODE
|
|
$mod_type<$trait_instance: $trait_name>
|
|
{ $( $other_where_bounds )* }
|
|
$(
|
|
$( #[doc = $doc_attr] )*
|
|
[< $name DefaultByteGetter >]
|
|
$name<$trait_instance: $trait_name>: $type = $value;
|
|
)*
|
|
}
|
|
}
|
|
};
|
|
// With instance
|
|
(
|
|
$mod_type:ident<$trait_instance:ident: $trait_name:ident<I>, $instance:ident: $instantiable:path>
|
|
{ $( $other_where_bounds:tt )* }
|
|
$(
|
|
$( #[doc = $doc_attr:tt] )*
|
|
$name:ident: $type:ty = $value:expr;
|
|
)*
|
|
) => {
|
|
$crate::paste::item! {
|
|
$crate::__impl_module_constants_metadata! {
|
|
GENERATE_CODE
|
|
$mod_type<$trait_instance: $trait_name<I>, $instance: $instantiable>
|
|
{ $( $other_where_bounds )* }
|
|
$(
|
|
$( #[doc = $doc_attr] )*
|
|
[< $name DefaultByteGetter >]
|
|
$name<$trait_instance: $trait_name<I>, $instance: $instantiable>: $type = $value;
|
|
)*
|
|
}
|
|
}
|
|
};
|
|
// Do the code generation
|
|
(GENERATE_CODE
|
|
$mod_type:ident<$trait_instance:ident: $trait_name:ident $(<I>, $instance:ident: $instantiable:path)?>
|
|
{ $( $other_where_bounds:tt )* }
|
|
$(
|
|
$( #[doc = $doc_attr:tt] )*
|
|
$default_byte_name:ident
|
|
$name:ident<
|
|
$const_trait_instance:ident: $const_trait_name:ident $(
|
|
<I>, $const_instance:ident: $const_instantiable:path
|
|
)*
|
|
>: $type:ty = $value:expr;
|
|
)*
|
|
) => {
|
|
impl<$trait_instance: 'static + $trait_name $(<I>, $instance: $instantiable)?>
|
|
$mod_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
|
|
{
|
|
#[doc(hidden)]
|
|
pub fn module_constants_metadata() -> &'static [$crate::dispatch::ModuleConstantMetadata] {
|
|
// Create the `ByteGetter`s
|
|
$(
|
|
#[allow(non_upper_case_types)]
|
|
#[allow(non_camel_case_types)]
|
|
struct $default_byte_name<
|
|
$const_trait_instance: $const_trait_name $(
|
|
<I>, $const_instance: $const_instantiable
|
|
)?
|
|
>($crate::dispatch::marker::PhantomData<
|
|
($const_trait_instance, $( $const_instance)?)
|
|
>);
|
|
impl<$const_trait_instance: 'static + $const_trait_name $(
|
|
<I>, $const_instance: $const_instantiable)?
|
|
> $crate::dispatch::DefaultByte
|
|
for $default_byte_name <$const_trait_instance $(, $const_instance)?>
|
|
{
|
|
fn default_byte(&self) -> $crate::dispatch::Vec<u8> {
|
|
let value: $type = $value;
|
|
$crate::dispatch::Encode::encode(&value)
|
|
}
|
|
}
|
|
|
|
unsafe impl<$const_trait_instance: 'static + $const_trait_name $(
|
|
<I>, $const_instance: $const_instantiable)?
|
|
> Send for $default_byte_name <$const_trait_instance $(, $const_instance)?> {}
|
|
|
|
unsafe impl<$const_trait_instance: 'static + $const_trait_name $(
|
|
<I>, $const_instance: $const_instantiable)?
|
|
> Sync for $default_byte_name <$const_trait_instance $(, $const_instance)?> {}
|
|
)*
|
|
&[
|
|
$(
|
|
$crate::dispatch::ModuleConstantMetadata {
|
|
name: $crate::dispatch::DecodeDifferent::Encode(stringify!($name)),
|
|
ty: $crate::dispatch::DecodeDifferent::Encode(stringify!($type)),
|
|
value: $crate::dispatch::DecodeDifferent::Encode(
|
|
$crate::dispatch::DefaultByteGetter(
|
|
&$default_byte_name::<
|
|
$const_trait_instance $(, $const_instance)?
|
|
>(
|
|
$crate::dispatch::marker::PhantomData
|
|
)
|
|
)
|
|
),
|
|
documentation: $crate::dispatch::DecodeDifferent::Encode(
|
|
&[ $( $doc_attr ),* ]
|
|
),
|
|
}
|
|
),*
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Convert the list of calls into their JSON representation, joined by ",".
|
|
#[macro_export]
|
|
#[doc(hidden)]
|
|
macro_rules! __call_to_functions {
|
|
(
|
|
$call_type:ident $origin_type:ty
|
|
{
|
|
$(
|
|
$(#[doc = $doc_attr:tt])*
|
|
fn $fn_name:ident($from:ident
|
|
$(
|
|
, $(#[$codec_attr:ident])* $param_name:ident : $param:ty
|
|
)*
|
|
);
|
|
)*
|
|
}
|
|
) => {
|
|
$crate::__functions_to_metadata!(0; $origin_type;; $(
|
|
fn $fn_name( $($(#[$codec_attr])* $param_name: $param ),* );
|
|
$( $doc_attr ),*;
|
|
)*)
|
|
};
|
|
}
|
|
|
|
|
|
/// Convert a list of functions into a list of `FunctionMetadata` items.
|
|
#[macro_export]
|
|
#[doc(hidden)]
|
|
macro_rules! __functions_to_metadata{
|
|
(
|
|
$fn_id:expr;
|
|
$origin_type:ty;
|
|
$( $function_metadata:expr ),*;
|
|
fn $fn_name:ident(
|
|
$(
|
|
$(#[$codec_attr:ident])* $param_name:ident : $param:ty
|
|
),*
|
|
);
|
|
$( $fn_doc:expr ),*;
|
|
$( $rest:tt )*
|
|
) => {
|
|
$crate::__functions_to_metadata!(
|
|
$fn_id + 1; $origin_type;
|
|
$( $function_metadata, )* $crate::__function_to_metadata!(
|
|
fn $fn_name($( $(#[$codec_attr])* $param_name : $param ),*); $( $fn_doc ),*; $fn_id;
|
|
);
|
|
$($rest)*
|
|
)
|
|
};
|
|
(
|
|
$fn_id:expr;
|
|
$origin_type:ty;
|
|
$( $function_metadata:expr ),*;
|
|
) => {
|
|
&[ $( $function_metadata ),* ]
|
|
}
|
|
}
|
|
|
|
/// Convert a function into its metadata representation.
|
|
#[macro_export]
|
|
#[doc(hidden)]
|
|
macro_rules! __function_to_metadata {
|
|
(
|
|
fn $fn_name:ident(
|
|
$( $(#[$codec_attr:ident])* $param_name:ident : $param:ty),*
|
|
);
|
|
$( $fn_doc:expr ),*;
|
|
$fn_id:expr;
|
|
) => {
|
|
$crate::dispatch::FunctionMetadata {
|
|
name: $crate::dispatch::DecodeDifferent::Encode(stringify!($fn_name)),
|
|
arguments: $crate::dispatch::DecodeDifferent::Encode(&[
|
|
$(
|
|
$crate::dispatch::FunctionArgumentMetadata {
|
|
name: $crate::dispatch::DecodeDifferent::Encode(stringify!($param_name)),
|
|
ty: $crate::dispatch::DecodeDifferent::Encode(
|
|
$crate::__function_to_metadata!(@stringify_expand_attr
|
|
$(#[$codec_attr])* $param_name: $param
|
|
)
|
|
),
|
|
}
|
|
),*
|
|
]),
|
|
documentation: $crate::dispatch::DecodeDifferent::Encode(&[ $( $fn_doc ),* ]),
|
|
}
|
|
};
|
|
|
|
(@stringify_expand_attr #[compact] $param_name:ident : $param:ty) => {
|
|
concat!("Compact<", stringify!($param), ">")
|
|
};
|
|
|
|
(@stringify_expand_attr $param_name:ident : $param:ty) => { stringify!($param) };
|
|
|
|
(@stringify_expand_attr $(#[codec_attr:ident])* $param_name:ident : $param:ty) => {
|
|
compile_error!(concat!(
|
|
"Invalid attribute for parameter `", stringify!($param_name),
|
|
"`, the following attributes are supported: `#[compact]`"
|
|
));
|
|
}
|
|
}
|
|
|
|
#[macro_export]
|
|
#[doc(hidden)]
|
|
macro_rules! __check_reserved_fn_name {
|
|
(deposit_event $( $rest:ident )*) => {
|
|
$crate::__check_reserved_fn_name!(@compile_error deposit_event);
|
|
};
|
|
(on_initialize $( $rest:ident )*) => {
|
|
$crate::__check_reserved_fn_name!(@compile_error on_initialize);
|
|
};
|
|
(on_runtime_upgrade $( $rest:ident )*) => {
|
|
$crate::__check_reserved_fn_name!(@compile_error on_runtime_upgrade);
|
|
};
|
|
(on_finalize $( $rest:ident )*) => {
|
|
$crate::__check_reserved_fn_name!(@compile_error on_finalize);
|
|
};
|
|
(offchain_worker $( $rest:ident )*) => {
|
|
$crate::__check_reserved_fn_name!(@compile_error offchain_worker);
|
|
};
|
|
($t:ident $( $rest:ident )*) => {
|
|
$crate::__check_reserved_fn_name!($( $rest )*);
|
|
};
|
|
() => {};
|
|
(@compile_error $ident:ident) => {
|
|
compile_error!(
|
|
concat!(
|
|
"Invalid call fn name: `",
|
|
stringify!($ident),
|
|
"`, name is reserved and doesn't match expected signature, please refer to ",
|
|
"`decl_module!` documentation to see the appropriate usage, or rename it to an ",
|
|
"unreserved keyword."
|
|
),
|
|
);
|
|
};
|
|
(@compile_error_renamed $ident:ident $new_ident:ident) => {
|
|
compile_error!(
|
|
concat!(
|
|
"`",
|
|
stringify!($ident),
|
|
"` was renamed to `",
|
|
stringify!($new_ident),
|
|
"`. Please rename your function accordingly.",
|
|
),
|
|
);
|
|
};
|
|
}
|
|
|
|
#[cfg(test)]
|
|
// Do not complain about unused `dispatch` and `dispatch_aux`.
|
|
#[allow(dead_code)]
|
|
mod tests {
|
|
use super::*;
|
|
use crate::weights::{DispatchInfo, DispatchClass};
|
|
use crate::traits::{
|
|
CallMetadata, GetCallMetadata, GetCallName, OnInitialize, OnFinalize, OnRuntimeUpgrade
|
|
};
|
|
|
|
pub trait Trait: system::Trait + Sized where Self::AccountId: From<u32> {
|
|
type Origin;
|
|
type BlockNumber: Into<u32>;
|
|
type Call: From<Call<Self>>;
|
|
}
|
|
|
|
pub mod system {
|
|
use super::*;
|
|
|
|
pub trait Trait {
|
|
type AccountId;
|
|
}
|
|
|
|
pub fn ensure_root<R>(_: R) -> DispatchResult {
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
decl_module! {
|
|
pub struct Module<T: Trait> for enum Call where origin: T::Origin, T::AccountId: From<u32> {
|
|
/// Hi, this is a comment.
|
|
#[weight = SimpleDispatchInfo::default()]
|
|
fn aux_0(_origin) -> DispatchResult { unreachable!() }
|
|
|
|
#[weight = SimpleDispatchInfo::default()]
|
|
fn aux_1(_origin, #[compact] _data: u32,) -> DispatchResult { unreachable!() }
|
|
|
|
#[weight = SimpleDispatchInfo::default()]
|
|
fn aux_2(_origin, _data: i32, _data2: String) -> DispatchResult { unreachable!() }
|
|
|
|
#[weight = SimpleDispatchInfo::FixedNormal(3)]
|
|
fn aux_3(_origin) -> DispatchResult { unreachable!() }
|
|
|
|
#[weight = SimpleDispatchInfo::default()]
|
|
fn aux_4(_origin, _data: i32) -> DispatchResult { unreachable!() }
|
|
|
|
#[weight = SimpleDispatchInfo::default()]
|
|
fn aux_5(_origin, _data: i32, #[compact] _data2: u32,) -> DispatchResult { unreachable!() }
|
|
|
|
#[weight = SimpleDispatchInfo::FixedOperational(5)]
|
|
fn operational(_origin) { unreachable!() }
|
|
|
|
fn on_initialize(n: T::BlockNumber,) -> Weight { if n.into() == 42 { panic!("on_initialize") } 7 }
|
|
fn on_finalize(n: T::BlockNumber,) { if n.into() == 42 { panic!("on_finalize") } }
|
|
fn on_runtime_upgrade() -> Weight { 10 }
|
|
fn offchain_worker() {}
|
|
}
|
|
}
|
|
|
|
const EXPECTED_METADATA: &'static [FunctionMetadata] = &[
|
|
FunctionMetadata {
|
|
name: DecodeDifferent::Encode("aux_0"),
|
|
arguments: DecodeDifferent::Encode(&[]),
|
|
documentation: DecodeDifferent::Encode(&[
|
|
" Hi, this is a comment."
|
|
])
|
|
},
|
|
FunctionMetadata {
|
|
name: DecodeDifferent::Encode("aux_1"),
|
|
arguments: DecodeDifferent::Encode(&[
|
|
FunctionArgumentMetadata {
|
|
name: DecodeDifferent::Encode("_data"),
|
|
ty: DecodeDifferent::Encode("Compact<u32>")
|
|
}
|
|
]),
|
|
documentation: DecodeDifferent::Encode(&[]),
|
|
},
|
|
FunctionMetadata {
|
|
name: DecodeDifferent::Encode("aux_2"),
|
|
arguments: DecodeDifferent::Encode(&[
|
|
FunctionArgumentMetadata {
|
|
name: DecodeDifferent::Encode("_data"),
|
|
ty: DecodeDifferent::Encode("i32"),
|
|
},
|
|
FunctionArgumentMetadata {
|
|
name: DecodeDifferent::Encode("_data2"),
|
|
ty: DecodeDifferent::Encode("String"),
|
|
}
|
|
]),
|
|
documentation: DecodeDifferent::Encode(&[]),
|
|
},
|
|
FunctionMetadata {
|
|
name: DecodeDifferent::Encode("aux_3"),
|
|
arguments: DecodeDifferent::Encode(&[]),
|
|
documentation: DecodeDifferent::Encode(&[]),
|
|
},
|
|
FunctionMetadata {
|
|
name: DecodeDifferent::Encode("aux_4"),
|
|
arguments: DecodeDifferent::Encode(&[
|
|
FunctionArgumentMetadata {
|
|
name: DecodeDifferent::Encode("_data"),
|
|
ty: DecodeDifferent::Encode("i32"),
|
|
}
|
|
]),
|
|
documentation: DecodeDifferent::Encode(&[]),
|
|
},
|
|
FunctionMetadata {
|
|
name: DecodeDifferent::Encode("aux_5"),
|
|
arguments: DecodeDifferent::Encode(&[
|
|
FunctionArgumentMetadata {
|
|
name: DecodeDifferent::Encode("_data"),
|
|
ty: DecodeDifferent::Encode("i32"),
|
|
},
|
|
FunctionArgumentMetadata {
|
|
name: DecodeDifferent::Encode("_data2"),
|
|
ty: DecodeDifferent::Encode("Compact<u32>")
|
|
}
|
|
]),
|
|
documentation: DecodeDifferent::Encode(&[]),
|
|
},
|
|
FunctionMetadata {
|
|
name: DecodeDifferent::Encode("operational"),
|
|
arguments: DecodeDifferent::Encode(&[]),
|
|
documentation: DecodeDifferent::Encode(&[]),
|
|
},
|
|
];
|
|
|
|
pub struct TraitImpl {}
|
|
|
|
impl Trait for TraitImpl {
|
|
type Origin = u32;
|
|
type BlockNumber = u32;
|
|
type Call = OuterCall;
|
|
}
|
|
|
|
type Test = Module<TraitImpl>;
|
|
|
|
impl_outer_dispatch! {
|
|
pub enum OuterCall for TraitImpl where origin: u32 {
|
|
self::Test,
|
|
}
|
|
}
|
|
|
|
impl system::Trait for TraitImpl {
|
|
type AccountId = u32;
|
|
}
|
|
|
|
#[test]
|
|
fn module_json_metadata() {
|
|
let metadata = Module::<TraitImpl>::call_functions();
|
|
assert_eq!(EXPECTED_METADATA, metadata);
|
|
}
|
|
|
|
#[test]
|
|
fn compact_attr() {
|
|
let call: Call<TraitImpl> = Call::aux_1(1);
|
|
let encoded = call.encode();
|
|
assert_eq!(2, encoded.len());
|
|
assert_eq!(vec![1, 4], encoded);
|
|
|
|
let call: Call<TraitImpl> = Call::aux_5(1, 2);
|
|
let encoded = call.encode();
|
|
assert_eq!(6, encoded.len());
|
|
assert_eq!(vec![5, 1, 0, 0, 0, 8], encoded);
|
|
}
|
|
|
|
#[test]
|
|
fn encode_is_correct_and_decode_works() {
|
|
let call: Call<TraitImpl> = Call::aux_0();
|
|
let encoded = call.encode();
|
|
assert_eq!(vec![0], encoded);
|
|
let decoded = Call::<TraitImpl>::decode(&mut &encoded[..]).unwrap();
|
|
assert_eq!(decoded, call);
|
|
|
|
let call: Call<TraitImpl> = Call::aux_2(32, "hello".into());
|
|
let encoded = call.encode();
|
|
assert_eq!(vec![2, 32, 0, 0, 0, 20, 104, 101, 108, 108, 111], encoded);
|
|
let decoded = Call::<TraitImpl>::decode(&mut &encoded[..]).unwrap();
|
|
assert_eq!(decoded, call);
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic(expected = "on_initialize")]
|
|
fn on_initialize_should_work_1() {
|
|
<Module<TraitImpl> as OnInitialize<u32>>::on_initialize(42);
|
|
}
|
|
|
|
#[test]
|
|
fn on_initialize_should_work_2() {
|
|
assert_eq!(<Module<TraitImpl> as OnInitialize<u32>>::on_initialize(10), 7);
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic(expected = "on_finalize")]
|
|
fn on_finalize_should_work() {
|
|
<Module<TraitImpl> as OnFinalize<u32>>::on_finalize(42);
|
|
}
|
|
|
|
#[test]
|
|
fn on_runtime_upgrade_should_work() {
|
|
assert_eq!(<Module<TraitImpl> as OnRuntimeUpgrade>::on_runtime_upgrade(), 10);
|
|
}
|
|
|
|
#[test]
|
|
fn weight_should_attach_to_call_enum() {
|
|
// operational.
|
|
assert_eq!(
|
|
Call::<TraitImpl>::operational().get_dispatch_info(),
|
|
DispatchInfo { weight: 5, class: DispatchClass::Operational, pays_fee: true },
|
|
);
|
|
// default weight.
|
|
assert_eq!(
|
|
Call::<TraitImpl>::aux_0().get_dispatch_info(),
|
|
DispatchInfo { weight: 10_000, class: DispatchClass::Normal, pays_fee: true },
|
|
);
|
|
// custom basic
|
|
assert_eq!(
|
|
Call::<TraitImpl>::aux_3().get_dispatch_info(),
|
|
DispatchInfo { weight: 3, class: DispatchClass::Normal, pays_fee: true },
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn call_name() {
|
|
let name = Call::<TraitImpl>::aux_3().get_call_name();
|
|
assert_eq!("aux_3", name);
|
|
}
|
|
|
|
#[test]
|
|
fn call_metadata() {
|
|
let call = OuterCall::Test(Call::<TraitImpl>::aux_3());
|
|
let metadata = call.get_call_metadata();
|
|
let expected = CallMetadata { function_name: "aux_3".into(), pallet_name: "Test".into() };
|
|
assert_eq!(metadata, expected);
|
|
}
|
|
|
|
#[test]
|
|
fn get_call_names() {
|
|
let call_names = Call::<TraitImpl>::get_call_names();
|
|
assert_eq!(["aux_0", "aux_1", "aux_2", "aux_3", "aux_4", "aux_5", "operational"], call_names);
|
|
}
|
|
|
|
#[test]
|
|
fn get_module_names() {
|
|
let module_names = OuterCall::get_module_names();
|
|
assert_eq!(["Test"], module_names);
|
|
}
|
|
}
|