// Copyright 2018-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 .
pub use frame_metadata::{
DecodeDifferent, FnEncode, RuntimeMetadata, ModuleMetadata, RuntimeMetadataLastVersion,
DefaultByteGetter, RuntimeMetadataPrefixed, StorageEntryMetadata, StorageMetadata,
StorageEntryType, StorageEntryModifier, DefaultByte, StorageHasher, ModuleErrorMetadata,
ExtrinsicMetadata,
};
/// Implements the metadata support for the given runtime and all its modules.
///
/// Example:
/// ```
///# mod module0 {
///# pub trait Trait {
///# type Origin;
///# type BlockNumber;
///# }
///# frame_support::decl_module! {
///# pub struct Module for enum Call where origin: T::Origin {}
///# }
///#
///# frame_support::decl_storage! {
///# trait Store for Module as TestStorage {}
///# }
///# }
///# use module0 as module1;
///# use module0 as module2;
///# impl module0::Trait for Runtime {
///# type Origin = u32;
///# type BlockNumber = u32;
///# }
///#
///# type UncheckedExtrinsic = sp_runtime::generic::UncheckedExtrinsic<(), (), (), ()>;
///
/// struct Runtime;
/// frame_support::impl_runtime_metadata! {
/// for Runtime with modules where Extrinsic = UncheckedExtrinsic
/// module0::Module as Module0 with,
/// module1::Module as Module1 with,
/// module2::Module as Module2 with Storage,
/// };
/// ```
///
/// In this example, just `MODULE3` implements the `Storage` trait.
#[macro_export]
macro_rules! impl_runtime_metadata {
(
for $runtime:ident with modules where Extrinsic = $ext:ident
$( $rest:tt )*
) => {
impl $runtime {
pub fn metadata() -> $crate::metadata::RuntimeMetadataPrefixed {
$crate::metadata::RuntimeMetadataLastVersion {
modules: $crate::__runtime_modules_to_metadata!($runtime;; $( $rest )*),
extrinsic: $crate::metadata::ExtrinsicMetadata {
version: <$ext as $crate::sp_runtime::traits::ExtrinsicMetadata>::VERSION,
signed_extensions: <
<
$ext as $crate::sp_runtime::traits::ExtrinsicMetadata
>::SignedExtensions as $crate::sp_runtime::traits::SignedExtension
>::identifier()
.into_iter()
.map($crate::metadata::DecodeDifferent::Encode)
.collect(),
},
}.into()
}
}
}
}
#[macro_export]
#[doc(hidden)]
macro_rules! __runtime_modules_to_metadata {
(
$runtime: ident;
$( $metadata:expr ),*;
$mod:ident::$module:ident $( < $instance:ident > )? as $name:ident $(with)+ $($kw:ident)*,
$( $rest:tt )*
) => {
$crate::__runtime_modules_to_metadata!(
$runtime;
$( $metadata, )* $crate::metadata::ModuleMetadata {
name: $crate::metadata::DecodeDifferent::Encode(stringify!($name)),
storage: $crate::__runtime_modules_to_metadata_calls_storage!(
$mod, $module $( <$instance> )?, $runtime, $(with $kw)*
),
calls: $crate::__runtime_modules_to_metadata_calls_call!(
$mod, $module $( <$instance> )?, $runtime, $(with $kw)*
),
event: $crate::__runtime_modules_to_metadata_calls_event!(
$mod, $module $( <$instance> )?, $runtime, $(with $kw)*
),
constants: $crate::metadata::DecodeDifferent::Encode(
$crate::metadata::FnEncode(
$mod::$module::<$runtime $(, $mod::$instance )?>::module_constants_metadata
)
),
errors: $crate::metadata::DecodeDifferent::Encode(
$crate::metadata::FnEncode(
<$mod::$module::<$runtime $(, $mod::$instance )?> as $crate::metadata::ModuleErrorMetadata>::metadata
)
)
};
$( $rest )*
)
};
(
$runtime:ident;
$( $metadata:expr ),*;
) => {
$crate::metadata::DecodeDifferent::Encode(&[ $( $metadata ),* ])
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! __runtime_modules_to_metadata_calls_call {
(
$mod: ident,
$module: ident $( <$instance:ident> )?,
$runtime: ident,
with Call
$(with $kws:ident)*
) => {
Some($crate::metadata::DecodeDifferent::Encode(
$crate::metadata::FnEncode(
$mod::$module::<$runtime $(, $mod::$instance )?>::call_functions
)
))
};
(
$mod: ident,
$module: ident $( <$instance:ident> )?,
$runtime: ident,
with $_:ident
$(with $kws:ident)*
) => {
$crate::__runtime_modules_to_metadata_calls_call! {
$mod, $module $( <$instance> )?, $runtime, $(with $kws)*
};
};
(
$mod: ident,
$module: ident $( <$instance:ident> )?,
$runtime: ident,
) => {
None
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! __runtime_modules_to_metadata_calls_event {
(
$mod: ident,
$module: ident $( <$instance:ident> )?,
$runtime: ident,
with Event
$(with $kws:ident)*
) => {
Some($crate::metadata::DecodeDifferent::Encode(
$crate::metadata::FnEncode(
$crate::paste::expr!{
$runtime:: [< __module_events_ $mod $(_ $instance)?>]
}
)
))
};
(
$mod: ident,
$module: ident $( <$instance:ident> )?,
$runtime: ident,
with $_:ident
$(with $kws:ident)*
) => {
$crate::__runtime_modules_to_metadata_calls_event!( $mod, $module $( <$instance> )?, $runtime, $(with $kws)* );
};
(
$mod: ident,
$module: ident $( <$instance:ident> )?,
$runtime: ident,
) => {
None
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! __runtime_modules_to_metadata_calls_storage {
(
$mod: ident,
$module: ident $( <$instance:ident> )?,
$runtime: ident,
with Storage
$(with $kws:ident)*
) => {
Some($crate::metadata::DecodeDifferent::Encode(
$crate::metadata::FnEncode(
$mod::$module::<$runtime $(, $mod::$instance )?>::storage_metadata
)
))
};
(
$mod: ident,
$module: ident $( <$instance:ident> )?,
$runtime: ident,
with $_:ident
$(with $kws:ident)*
) => {
$crate::__runtime_modules_to_metadata_calls_storage! {
$mod, $module $( <$instance> )?, $runtime, $(with $kws)*
};
};
(
$mod: ident,
$module: ident $( <$instance:ident> )?,
$runtime: ident,
) => {
None
};
}
#[cfg(test)]
// Do not complain about unused `dispatch` and `dispatch_aux`.
#[allow(dead_code)]
mod tests {
use super::*;
use frame_metadata::{
EventMetadata, StorageEntryModifier, StorageEntryType, FunctionMetadata, StorageEntryMetadata,
ModuleMetadata, RuntimeMetadataPrefixed, DefaultByte, ModuleConstantMetadata, DefaultByteGetter,
ErrorMetadata, ExtrinsicMetadata,
};
use codec::{Encode, Decode};
use crate::traits::Get;
use sp_runtime::transaction_validity::TransactionValidityError;
#[derive(Clone, Eq, Debug, PartialEq, Encode, Decode)]
struct TestExtension;
impl sp_runtime::traits::SignedExtension for TestExtension {
type AccountId = u32;
type Call = ();
type AdditionalSigned = u32;
type Pre = ();
const IDENTIFIER: &'static str = "testextension";
fn additional_signed(&self) -> Result {
Ok(1)
}
}
#[derive(Clone, Eq, Debug, PartialEq, Encode, Decode)]
struct TestExtension2;
impl sp_runtime::traits::SignedExtension for TestExtension2 {
type AccountId = u32;
type Call = ();
type AdditionalSigned = u32;
type Pre = ();
const IDENTIFIER: &'static str = "testextension2";
fn additional_signed(&self) -> Result {
Ok(1)
}
}
struct TestExtrinsic;
impl sp_runtime::traits::ExtrinsicMetadata for TestExtrinsic {
const VERSION: u8 = 1;
type SignedExtensions = (TestExtension, TestExtension2);
}
mod system {
use super::*;
pub trait Trait: 'static {
const ASSOCIATED_CONST: u64 = 500;
type Origin: Into, Self::Origin>>
+ From>;
type AccountId: From + Encode;
type BlockNumber: From + Encode;
type SomeValue: Get;
type ModuleToIndex: crate::traits::ModuleToIndex;
}
decl_module! {
pub struct Module for enum Call where origin: T::Origin {
/// Hi, I am a comment.
const BlockNumber: T::BlockNumber = 100.into();
const GetType: T::AccountId = T::SomeValue::get().into();
const ASSOCIATED_CONST: u64 = T::ASSOCIATED_CONST.into();
}
}
decl_event!(
pub enum Event {
SystemEvent,
}
);
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum RawOrigin {
Root,
Signed(AccountId),
None,
}
impl From