Remove impl_outer_ macros (#9307)

* remove impl_outer_*

* continue to reexport some unsigned in order not to break users
This commit is contained in:
Guillaume Thiolliere
2021-07-12 10:50:50 +02:00
committed by GitHub
parent c78c2892a4
commit 4856b6fcf4
9 changed files with 166 additions and 1847 deletions
+49 -179
View File
@@ -101,8 +101,7 @@ impl<T> Parameter for T where T: Codec + EncodeLike + Clone + Eq + fmt::Debug {}
/// * `Module`: The struct generated by the macro, with type `Config`.
/// * `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.
/// * `origin`: Alias of `T::Origin`.
/// * `Result`: The expected return type from pallet functions.
///
/// The first parameter of dispatchable functions must always be `origin`.
@@ -2164,157 +2163,6 @@ macro_rules! decl_module {
}
}
/// 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 {
$(
$( #[codec(index = $index:tt)] )? $module:ident::$camelcase:ident,
)*
}
) => {
$(#[$attr])*
#[derive(
Clone, PartialEq, Eq,
$crate::codec::Encode,
$crate::codec::Decode,
$crate::RuntimeDebug,
)]
pub enum $call_type {
$(
$( #[codec(index = $index)] )?
$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 Config = $call_type;
type Info = $crate::weights::DispatchInfo;
type PostInfo = $crate::weights::PostDispatchInfo;
fn dispatch(
self,
origin: $origin,
) -> $crate::dispatch::DispatchResultWithPostInfo {
if !<Self::Origin as $crate::traits::OriginTrait>::filter_call(&origin, &self) {
return $crate::sp_std::result::Result::Err($crate::dispatch::DispatchError::BadOrigin.into())
}
$crate::traits::UnfilteredDispatchable::dispatch_bypass_filter(self, origin)
}
}
impl $crate::traits::UnfilteredDispatchable for $call_type {
type Origin = $origin;
fn dispatch_bypass_filter(
self,
origin: $origin,
) -> $crate::dispatch::DispatchResultWithPostInfo {
$crate::impl_outer_dispatch! {
@DISPATCH_MATCH
self
$call_type
origin
{}
0;
$( $camelcase ),*
}
}
}
$(
impl $crate::traits::IsSubType<$crate::dispatch::CallableCallFor<$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) =>
$crate::traits::UnfilteredDispatchable::dispatch_bypass_filter(call, $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)]
@@ -2619,7 +2467,7 @@ mod tests {
use super::*;
use crate::weights::{DispatchInfo, DispatchClass, Pays, RuntimeDbWeight};
use crate::traits::{
CallMetadata, GetCallMetadata, GetCallName, OnInitialize, OnFinalize, OnIdle, OnRuntimeUpgrade,
GetCallName, OnInitialize, OnFinalize, OnIdle, OnRuntimeUpgrade,
IntegrityTest, Get, PalletInfo,
};
@@ -2767,16 +2615,6 @@ mod tests {
type Test = Module<TraitImpl>;
impl_outer_origin!{
pub enum OuterOrigin for TraitImpl where system = system {}
}
impl_outer_dispatch! {
pub enum OuterCall for TraitImpl where origin: OuterOrigin {
self::Test,
}
}
impl PalletInfo for TraitImpl {
fn index<P: 'static>() -> Option<usize> {
let type_id = sp_std::any::TypeId::of::<P>();
@@ -2796,10 +2634,56 @@ mod tests {
}
}
pub struct OuterOrigin;
impl crate::traits::OriginTrait for OuterOrigin {
type Call = <TraitImpl as system::Config>::Call;
type PalletsOrigin = OuterOrigin;
type AccountId = <TraitImpl as system::Config>::AccountId;
fn add_filter(&mut self, _filter: impl Fn(&Self::Call) -> bool + 'static) {
unimplemented!("Not required in tests!")
}
fn reset_filter(&mut self) {
unimplemented!("Not required in tests!")
}
fn set_caller_from(&mut self, _other: impl Into<Self>) {
unimplemented!("Not required in tests!")
}
fn filter_call(&self, _call: &Self::Call) -> bool {
unimplemented!("Not required in tests!")
}
fn caller(&self) -> &Self::PalletsOrigin {
unimplemented!("Not required in tests!")
}
fn try_with_caller<R>(
self,
_f: impl FnOnce(Self::PalletsOrigin) -> Result<R, Self::PalletsOrigin>,
) -> Result<R, Self> {
unimplemented!("Not required in tests!")
}
fn none() -> Self {
unimplemented!("Not required in tests!")
}
fn root() -> Self {
unimplemented!("Not required in tests!")
}
fn signed(_by: <TraitImpl as system::Config>::AccountId) -> Self {
unimplemented!("Not required in tests!")
}
}
impl system::Config for TraitImpl {
type Origin = OuterOrigin;
type AccountId = u32;
type Call = OuterCall;
type Call = ();
type BaseCallFilter = ();
type BlockNumber = u32;
type PalletInfo = Self;
@@ -2901,26 +2785,12 @@ mod tests {
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);
}
#[test]
#[should_panic(expected = "integrity_test")]
fn integrity_test_should_work() {
+48 -327
View File
@@ -333,220 +333,6 @@ macro_rules! __events_to_metadata {
}
}
/// Constructs an Event type for a runtime. This is usually called automatically by the
/// construct_runtime macro.
#[macro_export]
macro_rules! impl_outer_event {
// Macro transformations (to convert invocations with incomplete parameters to the canonical
// form)
(
$(#[$attr:meta])*
pub enum $name:ident for $runtime:ident {
$( $rest_events:tt )*
}
) => {
$crate::impl_outer_event!(
$( #[$attr] )*;
$name;
$runtime;
Modules { $( $rest_events )* };
{};
);
};
// Generic + Instance
(
$(#[$attr:meta])*;
$name:ident;
$runtime:ident;
Modules {
$( #[codec(index = $index:tt)] )? $module:ident $instance:ident<T>,
$( $rest_event_generic_instance:tt )*
};
{ $( $parsed:tt )* };
) => {
$crate::impl_outer_event!(
$( #[$attr] )*;
$name;
$runtime;
Modules { $( $rest_event_generic_instance )* };
{ $( $parsed )* $module::Event<$runtime>{ $instance } index { $( $index )? }, };
);
};
// Instance
(
$(#[$attr:meta])*;
$name:ident;
$runtime:ident;
Modules {
$( #[codec(index = $index:tt)] )? $module:ident $instance:ident,
$( $rest_event_instance:tt )*
};
{ $( $parsed:tt )* };
) => {
$crate::impl_outer_event!(
$( #[$attr] )*;
$name;
$runtime;
Modules { $( $rest_event_instance )* };
{ $( $parsed )* $module::Event { $instance } index { $( $index )? }, };
);
};
// Generic
(
$(#[$attr:meta])*;
$name:ident;
$runtime:ident;
Modules {
$( #[codec(index = $index:tt)] )? $module:ident<T>,
$( $rest_event_generic:tt )*
};
{ $( $parsed:tt )* };
) => {
$crate::impl_outer_event!(
$( #[$attr] )*;
$name;
$runtime;
Modules { $( $rest_event_generic )* };
{ $( $parsed )* $module::Event<$runtime> index { $( $index )? }, };
);
};
// No Generic and no Instance
(
$(#[$attr:meta])*;
$name:ident;
$runtime:ident;
Modules {
$( #[codec(index = $index:tt)] )? $module:ident,
$( $rest_event_no_generic_no_instance:tt )*
};
{ $( $parsed:tt )* };
) => {
$crate::impl_outer_event!(
$( #[$attr] )*;
$name;
$runtime;
Modules { $( $rest_event_no_generic_no_instance )* };
{ $( $parsed )* $module::Event index { $( $index )? }, };
);
};
// The main macro expansion that actually renders the Event enum code.
(
$(#[$attr:meta])*;
$name:ident;
$runtime:ident;
Modules {};
{
$(
$module_name:ident::Event
$( <$generic_param:ident> )?
$( { $generic_instance:ident } )?
index { $( $index:tt )? },
)*
};
) => {
$crate::paste::item! {
#[derive(
Clone, PartialEq, Eq,
$crate::codec::Encode,
$crate::codec::Decode,
$crate::RuntimeDebug,
)]
$(#[$attr])*
#[allow(non_camel_case_types)]
pub enum $name {
$(
$( #[codec(index = $index)] )?
[< $module_name $(_ $generic_instance )? >](
$module_name::Event < $( $generic_param )? $(, $module_name::$generic_instance )? >
),
)*
}
$(
impl From<$module_name::Event < $( $generic_param, )? $( $module_name::$generic_instance )? >> for $name {
fn from(x: $module_name::Event < $( $generic_param, )? $( $module_name::$generic_instance )? >) -> Self {
$name::[< $module_name $(_ $generic_instance )? >](x)
}
}
impl $crate::sp_std::convert::TryInto<
$module_name::Event < $( $generic_param, )? $( $module_name::$generic_instance )? >
> for $name {
type Error = ();
fn try_into(self) -> $crate::sp_std::result::Result<
$module_name::Event < $( $generic_param, )? $( $module_name::$generic_instance )? >, Self::Error
> {
match self {
Self::[< $module_name $(_ $generic_instance )? >](evt) => Ok(evt),
_ => Err(()),
}
}
}
)*
}
$crate::__impl_outer_event_json_metadata!(
$runtime;
$name;
$(
$module_name::Event
< $( $generic_param )? $(, $module_name::$generic_instance )? >
$( $generic_instance )?,
)*;
);
}
}
#[macro_export]
#[doc(hidden)]
macro_rules! __impl_outer_event_json_metadata {
(
$runtime:ident;
$event_name:ident;
$( $module_name:ident::Event < $( $generic_params:path ),* > $( $instance:ident )?, )*;
) => {
impl $runtime {
#[allow(dead_code)]
pub fn outer_event_metadata() -> $crate::event::OuterEventMetadata {
$crate::event::OuterEventMetadata {
name: $crate::event::DecodeDifferent::Encode(stringify!($event_name)),
events: $crate::event::DecodeDifferent::Encode(&[
$(
(
stringify!($module_name),
$crate::event::FnEncode(
$module_name::Event ::< $( $generic_params ),* > ::metadata
)
)
),*
])
}
}
$crate::__impl_outer_event_json_metadata! {
@DECL_MODULE_EVENT_FNS
$( $module_name < $( $generic_params ),* > $( $instance )? ; )*
}
}
};
(@DECL_MODULE_EVENT_FNS
$(
$module_name:ident < $( $generic_params:path ),* > $( $instance:ident )? ;
)*
) => {
$crate::paste::item! {
$(
#[allow(dead_code)]
pub fn [< __module_events_ $module_name $( _ $instance )? >] () ->
&'static [$crate::event::EventMetadata]
{
$module_name::Event ::< $( $generic_params ),* > ::metadata()
}
)*
}
}
}
#[cfg(test)]
#[allow(dead_code)]
mod tests {
@@ -697,27 +483,9 @@ mod tests {
#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, Serialize)]
pub struct TestRuntime;
impl_outer_event! {
pub enum TestEvent for TestRuntime {
system,
event_module<T>,
event_module2<T>,
event_module3,
}
}
#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode, Serialize)]
pub struct TestRuntime2;
impl_outer_event! {
pub enum TestEventSystemRenamed for TestRuntime2 {
system_renamed,
event_module<T>,
#[codec(index = 5)] event_module2<T>,
event_module3,
}
}
impl event_module::Config for TestRuntime {
type Balance = u32;
}
@@ -733,104 +501,57 @@ mod tests {
type DbWeight = ();
}
impl event_module::Config for TestRuntime2 {
type Balance = u32;
}
impl event_module2::Config for TestRuntime2 {
type Balance = u32;
}
impl system_renamed::Config for TestRuntime2 {
type Origin = u32;
type BlockNumber = u32;
type PalletInfo = crate::tests::PanicPalletInfo;
type DbWeight = ();
}
impl system::Config for TestRuntime2 {
type Origin = u32;
type BlockNumber = u32;
type PalletInfo = crate::tests::PanicPalletInfo;
type DbWeight = ();
}
const EXPECTED_METADATA: OuterEventMetadata = OuterEventMetadata {
name: DecodeDifferent::Encode("TestEvent"),
events: DecodeDifferent::Encode(&[
(
"system",
FnEncode(|| &[
EventMetadata {
name: DecodeDifferent::Encode("SystemEvent"),
arguments: DecodeDifferent::Encode(&[]),
documentation: DecodeDifferent::Encode(&[]),
}
])
),
(
"event_module",
FnEncode(|| &[
EventMetadata {
name: DecodeDifferent::Encode("TestEvent"),
arguments: DecodeDifferent::Encode(&[ "Balance", "Origin" ]),
documentation: DecodeDifferent::Encode(&[ " Hi, I am a comment." ])
},
EventMetadata {
name: DecodeDifferent::Encode("EventWithoutParams"),
arguments: DecodeDifferent::Encode(&[]),
documentation: DecodeDifferent::Encode(&[ " Dog" ]),
},
])
),
(
"event_module2",
FnEncode(|| &[
EventMetadata {
name: DecodeDifferent::Encode("TestEvent"),
arguments: DecodeDifferent::Encode(&[ "BalanceRenamed" ]),
documentation: DecodeDifferent::Encode(&[])
},
EventMetadata {
name: DecodeDifferent::Encode("TestOrigin"),
arguments: DecodeDifferent::Encode(&[ "OriginRenamed" ]),
documentation: DecodeDifferent::Encode(&[]),
},
])
),
(
"event_module3",
FnEncode(|| &[
EventMetadata {
name: DecodeDifferent::Encode("HiEvent"),
arguments: DecodeDifferent::Encode(&[]),
documentation: DecodeDifferent::Encode(&[])
}
])
)
])
};
#[test]
fn outer_event_metadata() {
assert_eq!(EXPECTED_METADATA, TestRuntime::outer_event_metadata());
}
#[test]
fn test_codec() {
let runtime_1_event_module_2 = TestEvent::event_module2(
event_module2::Event::<TestRuntime>::TestEvent(3)
fn event_metadata() {
assert_eq!(
system_renamed::Event::metadata(),
&[
EventMetadata {
name: DecodeDifferent::Encode("SystemEvent"),
arguments: DecodeDifferent::Encode(&[]),
documentation: DecodeDifferent::Encode(&[]),
},
]
);
assert_eq!(runtime_1_event_module_2.encode()[0], 2);
let runtime_2_event_module_2 = TestEventSystemRenamed::event_module2(
event_module2::Event::<TestRuntime2>::TestEvent(3)
assert_eq!(
event_module::Event::<TestRuntime>::metadata(),
&[
EventMetadata {
name: DecodeDifferent::Encode("TestEvent"),
arguments: DecodeDifferent::Encode(&[ "Balance", "Origin" ]),
documentation: DecodeDifferent::Encode(&[ " Hi, I am a comment." ])
},
EventMetadata {
name: DecodeDifferent::Encode("EventWithoutParams"),
arguments: DecodeDifferent::Encode(&[]),
documentation: DecodeDifferent::Encode(&[ " Dog" ]),
},
]
);
assert_eq!(runtime_2_event_module_2.encode()[0], 5);
let runtime_2_event_module_3 = TestEventSystemRenamed::event_module3(
event_module3::Event::HiEvent
assert_eq!(
event_module2::Event::<TestRuntime>::metadata(),
&[
EventMetadata {
name: DecodeDifferent::Encode("TestEvent"),
arguments: DecodeDifferent::Encode(&[ "BalanceRenamed" ]),
documentation: DecodeDifferent::Encode(&[])
},
EventMetadata {
name: DecodeDifferent::Encode("TestOrigin"),
arguments: DecodeDifferent::Encode(&[ "OriginRenamed" ]),
documentation: DecodeDifferent::Encode(&[]),
},
]
);
assert_eq!(
event_module3::Event::metadata(),
&[
EventMetadata {
name: DecodeDifferent::Encode("HiEvent"),
arguments: DecodeDifferent::Encode(&[]),
documentation: DecodeDifferent::Encode(&[])
}
],
);
assert_eq!(runtime_2_event_module_3.encode()[0], 3);
}
}
@@ -1,142 +0,0 @@
// This file is part of Substrate.
// Copyright (C) 2020-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.
//! Macros for generating the runtime genesis config.
/// Helper macro for `impl_outer_config`
#[macro_export]
macro_rules! __impl_outer_config_types {
// Generic + Instance
(
$concrete:ident $config:ident $snake:ident { $instance:ident } < $ignore:ident >;
$( $rest:tt )*
) => {
#[cfg(any(feature = "std", test))]
pub type $config = $snake::GenesisConfig<$concrete, $snake::$instance>;
$crate::__impl_outer_config_types! { $concrete $( $rest )* }
};
// Generic
(
$concrete:ident $config:ident $snake:ident < $ignore:ident >;
$( $rest:tt )*
) => {
#[cfg(any(feature = "std", test))]
pub type $config = $snake::GenesisConfig<$concrete>;
$crate::__impl_outer_config_types! { $concrete $( $rest )* }
};
// No Generic and maybe Instance
(
$concrete:ident $config:ident $snake:ident $( { $instance:ident } )?;
$( $rest:tt )*
) => {
#[cfg(any(feature = "std", test))]
pub type $config = $snake::GenesisConfig;
$crate::__impl_outer_config_types! { $concrete $( $rest )* }
};
($concrete:ident) => ()
}
/// Implement the runtime genesis configuration.
///
/// This combines all pallet genesis configurations into one runtime
/// specific genesis configuration.
///
/// ```ignore
/// pub struct GenesisConfig for Runtime where AllPalletsWithSystem = AllPalletsWithSystem {
/// rust_module_one: Option<ModuleOneConfig>,
/// ...
/// }
/// ```
#[macro_export]
macro_rules! impl_outer_config {
(
pub struct $main:ident for $concrete:ident where
AllPalletsWithSystem = $all_pallets_with_system:ident
{
$( $config:ident =>
$snake:ident $( $instance:ident )? $( <$generic:ident> )*, )*
}
) => {
$crate::__impl_outer_config_types! {
$concrete $( $config $snake $( { $instance } )? $( <$generic> )*; )*
}
$crate::paste::item! {
#[cfg(any(feature = "std", test))]
use $crate::serde as __genesis_config_serde_import__;
#[cfg(any(feature = "std", test))]
#[derive($crate::serde::Serialize, $crate::serde::Deserialize, Default)]
#[serde(rename_all = "camelCase")]
#[serde(deny_unknown_fields)]
#[serde(crate = "__genesis_config_serde_import__")]
pub struct $main {
$(
pub [< $snake $(_ $instance )? >]: $config,
)*
}
#[cfg(any(feature = "std", test))]
impl $crate::sp_runtime::BuildStorage for $main {
fn assimilate_storage(
&self,
storage: &mut $crate::sp_runtime::Storage,
) -> std::result::Result<(), String> {
$(
$crate::impl_outer_config! {
@CALL_FN
$concrete;
$snake;
$( $instance )?;
&self.[< $snake $(_ $instance )? >];
storage;
}
)*
$crate::BasicExternalities::execute_with_storage(storage, || {
<$all_pallets_with_system as $crate::traits::OnGenesis>::on_genesis();
});
Ok(())
}
}
}
};
(@CALL_FN
$runtime:ident;
$module:ident;
$instance:ident;
$extra:expr;
$storage:ident;
) => {
$crate::sp_runtime::BuildModuleGenesisStorage::<$runtime, $module::$instance>::build_module_genesis_storage(
$extra,
$storage,
)?;
};
(@CALL_FN
$runtime:ident;
$module:ident;
;
$extra:expr;
$storage:ident;
) => {
$crate::sp_runtime::BuildModuleGenesisStorage::
<$runtime, $module::__InherentHiddenInstance>::build_module_genesis_storage(
$extra,
$storage,
)?;
}
}
+2 -447
View File
@@ -43,8 +43,8 @@ pub trait ProvideInherent {
/// - `Ok(None)` indicates that this inherent is not required in this block. The default
/// implementation returns this.
///
/// - `Ok(Some(e))` indicates that this inherent is required in this block. The
/// `impl_outer_inherent!`, will call this function from its `check_extrinsics`.
/// - `Ok(Some(e))` indicates that this inherent is required in this block. `construct_runtime!`
/// will call this function from in its implementation of `fn check_extrinsics`.
/// If the inherent is not present, it will return `e`.
///
/// - `Err(_)` indicates that this function failed and further operations should be aborted.
@@ -80,448 +80,3 @@ pub trait ProvideInherent {
/// Otherwise block producer can produce invalid blocks by including them after non inherent.
fn is_inherent(call: &Self::Call) -> bool;
}
/// Implement the outer inherent.
/// All given modules need to implement [`ProvideInherent`].
///
/// # Example
///
/// ```nocompile
/// impl_outer_inherent! {
/// impl Inherents where
/// Block = Block,
/// UncheckedExtrinsic = UncheckedExtrinsic,
/// Runtime = Runtime,
/// {
/// timestamp,
/// consensus,
/// aura,
/// }
/// }
/// ```
#[macro_export]
macro_rules! impl_outer_inherent {
(
impl Inherents where
Block = $block:ident,
UncheckedExtrinsic = $uncheckedextrinsic:ident,
Runtime = $runtime:ident,
{
$( $module:ident, )*
}
) => {
trait InherentDataExt {
fn create_extrinsics(&self) ->
$crate::inherent::Vec<<$block as $crate::inherent::BlockT>::Extrinsic>;
fn check_extrinsics(&self, block: &$block) -> $crate::inherent::CheckInherentsResult;
}
impl InherentDataExt for $crate::inherent::InherentData {
fn create_extrinsics(&self) ->
$crate::inherent::Vec<<$block as $crate::inherent::BlockT>::Extrinsic> {
use $crate::inherent::ProvideInherent;
let mut inherents = Vec::new();
$(
if let Some(inherent) = $module::create_inherent(self) {
let inherent = <$uncheckedextrinsic as $crate::inherent::Extrinsic>::new(
inherent.into(),
None,
).expect("Runtime UncheckedExtrinsic is not Opaque, so it has to return \
`Some`; qed");
inherents.push(inherent);
}
)*
inherents
}
fn check_extrinsics(&self, block: &$block) -> $crate::inherent::CheckInherentsResult {
use $crate::inherent::{ProvideInherent, IsFatalError};
use $crate::traits::{IsSubType, ExtrinsicCall};
use $crate::sp_runtime::traits::Block as _;
let mut result = $crate::inherent::CheckInherentsResult::new();
for xt in block.extrinsics() {
// Inherents are before any other extrinsics.
// And signed extrinsics are not inherents.
if $crate::inherent::Extrinsic::is_signed(xt).unwrap_or(false) {
break
}
let mut is_inherent = false;
$({
let call = <$uncheckedextrinsic as ExtrinsicCall>::call(xt);
if let Some(call) = IsSubType::<_>::is_sub_type(call) {
if $module::is_inherent(call) {
is_inherent = true;
if let Err(e) = $module::check_inherent(call, self) {
result.put_error(
$module::INHERENT_IDENTIFIER, &e
).expect("There is only one fatal error; qed");
if e.is_fatal_error() {
return result
}
}
}
}
})*
// Inherents are before any other extrinsics.
// No module marked it as inherent thus it is not.
if !is_inherent {
break
}
}
$(
match $module::is_inherent_required(self) {
Ok(Some(e)) => {
let found = block.extrinsics().iter().any(|xt| {
let is_signed = $crate::inherent::Extrinsic::is_signed(xt)
.unwrap_or(false);
if !is_signed {
let call = <
$uncheckedextrinsic as ExtrinsicCall
>::call(xt);
if let Some(call) = IsSubType::<_>::is_sub_type(call) {
$module::is_inherent(&call)
} else {
false
}
} else {
// Signed extrinsics are not inherents.
false
}
});
if !found {
result.put_error(
$module::INHERENT_IDENTIFIER, &e
).expect("There is only one fatal error; qed");
if e.is_fatal_error() {
return result
}
}
},
Ok(None) => (),
Err(e) => {
result.put_error(
$module::INHERENT_IDENTIFIER, &e
).expect("There is only one fatal error; qed");
if e.is_fatal_error() {
return result
}
},
}
)*
result
}
}
impl $crate::traits::EnsureInherentsAreFirst<$block> for $runtime {
fn ensure_inherents_are_first(block: &$block) -> Result<(), u32> {
use $crate::inherent::ProvideInherent;
use $crate::traits::{IsSubType, ExtrinsicCall};
use $crate::sp_runtime::traits::Block as _;
let mut first_signed_observed = false;
for (i, xt) in block.extrinsics().iter().enumerate() {
let is_signed = $crate::inherent::Extrinsic::is_signed(xt).unwrap_or(false);
let is_inherent = if is_signed {
// Signed extrinsics are not inherents.
false
} else {
let mut is_inherent = false;
$({
let call = <$uncheckedextrinsic as ExtrinsicCall>::call(xt);
if let Some(call) = IsSubType::<_>::is_sub_type(call) {
if $module::is_inherent(&call) {
is_inherent = true;
}
}
})*
is_inherent
};
if !is_inherent {
first_signed_observed = true;
}
if first_signed_observed && is_inherent {
return Err(i as u32)
}
}
Ok(())
}
}
};
}
#[cfg(test)]
mod tests {
use super::*;
use sp_runtime::{traits, testing::{Header, self}};
#[derive(codec::Encode, codec::Decode, Clone, PartialEq, Eq, Debug, serde::Serialize)]
enum Call {
Test(CallTest),
Test2(CallTest2),
}
impl From<CallTest> for Call {
fn from(call: CallTest) -> Self {
Self::Test(call)
}
}
impl From<CallTest2> for Call {
fn from(call: CallTest2) -> Self {
Self::Test2(call)
}
}
impl crate::traits::IsSubType<CallTest> for Call {
fn is_sub_type(&self) -> Option<&CallTest> {
match self {
Self::Test(test) => Some(test),
_ => None,
}
}
}
impl crate::traits::IsSubType<CallTest2> for Call {
fn is_sub_type(&self) -> Option<&CallTest2> {
match self {
Self::Test2(test) => Some(test),
_ => None,
}
}
}
#[derive(codec::Encode, codec::Decode, Clone, PartialEq, Eq, Debug, serde::Serialize)]
enum CallTest {
OptionalInherent(bool),
NotInherent,
}
#[derive(codec::Encode, codec::Decode, Clone, PartialEq, Eq, Debug, serde::Serialize)]
enum CallTest2 {
RequiredInherent,
}
struct ModuleTest;
impl ProvideInherent for ModuleTest {
type Call = CallTest;
type Error = sp_inherents::MakeFatalError<()>;
const INHERENT_IDENTIFIER: sp_inherents::InherentIdentifier = *b"test1235";
fn create_inherent(_: &InherentData) -> Option<Self::Call> {
Some(CallTest::OptionalInherent(true))
}
fn check_inherent(call: &Self::Call, _: &InherentData) -> Result<(), Self::Error> {
match call {
CallTest::OptionalInherent(true) => Ok(()),
CallTest::OptionalInherent(false) => Err(().into()),
_ => unreachable!("other calls are not inherents"),
}
}
fn is_inherent(call: &Self::Call) -> bool {
matches!(call, CallTest::OptionalInherent(_))
}
}
struct ModuleTest2;
impl ProvideInherent for ModuleTest2 {
type Call = CallTest2;
type Error = sp_inherents::MakeFatalError<()>;
const INHERENT_IDENTIFIER: sp_inherents::InherentIdentifier = *b"test1234";
fn create_inherent(_: &InherentData) -> Option<Self::Call> {
Some(CallTest2::RequiredInherent)
}
fn is_inherent_required(_: &InherentData) -> Result<Option<Self::Error>, Self::Error> {
Ok(Some(().into()))
}
fn is_inherent(call: &Self::Call) -> bool {
matches!(call, CallTest2::RequiredInherent)
}
}
type Block = testing::Block<Extrinsic>;
#[derive(codec::Encode, codec::Decode, Clone, PartialEq, Eq, Debug, serde::Serialize)]
struct Extrinsic {
signed: bool,
function: Call,
}
impl traits::Extrinsic for Extrinsic {
type Call = Call;
type SignaturePayload = ();
fn new(function: Call, signed_data: Option<()>) -> Option<Self> {
Some(Self {
function,
signed: signed_data.is_some(),
})
}
fn is_signed(&self) -> Option<bool> {
Some(self.signed)
}
}
impl crate::traits::ExtrinsicCall for Extrinsic {
fn call(&self) -> &Self::Call {
&self.function
}
}
parity_util_mem::malloc_size_of_is_0!(Extrinsic);
struct Runtime;
impl_outer_inherent! {
impl Inherents where
Block = Block,
UncheckedExtrinsic = Extrinsic,
Runtime = Runtime,
{
ModuleTest,
ModuleTest2,
}
}
#[test]
fn create_inherents_works() {
let inherents = InherentData::new().create_extrinsics();
let expected = vec![
Extrinsic { function: Call::Test(CallTest::OptionalInherent(true)), signed: false },
Extrinsic { function: Call::Test2(CallTest2::RequiredInherent), signed: false },
];
assert_eq!(expected, inherents);
}
#[test]
fn check_inherents_works() {
let block = Block::new(
Header::new_from_number(1),
vec![
Extrinsic { function: Call::Test2(CallTest2::RequiredInherent), signed: false },
Extrinsic { function: Call::Test(CallTest::OptionalInherent(true)), signed: false },
],
);
assert!(InherentData::new().check_extrinsics(&block).ok());
let block = Block::new(
Header::new_from_number(1),
vec![
Extrinsic { function: Call::Test2(CallTest2::RequiredInherent), signed: false },
Extrinsic { function: Call::Test(CallTest::OptionalInherent(false)), signed: false },
],
);
assert!(InherentData::new().check_extrinsics(&block).fatal_error());
}
#[test]
fn required_inherents_enforced() {
let block = Block::new(
Header::new_from_number(1),
vec![
Extrinsic { function: Call::Test(CallTest::OptionalInherent(true)), signed: false }
],
);
assert!(InherentData::new().check_extrinsics(&block).fatal_error());
}
#[test]
fn signed_are_not_inherent() {
let block = Block::new(
Header::new_from_number(1),
vec![
Extrinsic { function: Call::Test2(CallTest2::RequiredInherent), signed: false },
// NOTE: checking this call would fail, but it is not checked as it is not an
// inherent, because it is signed.
Extrinsic { function: Call::Test(CallTest::OptionalInherent(false)), signed: true },
],
);
assert!(InherentData::new().check_extrinsics(&block).ok());
let block = Block::new(
Header::new_from_number(1),
vec![
// NOTE: this is not considered an inherent, thus block is failing because of
// missing required inherent.
Extrinsic { function: Call::Test2(CallTest2::RequiredInherent), signed: true },
],
);
assert_eq!(
InherentData::new().check_extrinsics(&block).into_errors().collect::<Vec<_>>(),
vec![(*b"test1234", vec![])],
);
}
#[test]
fn inherent_first_works() {
use crate::traits::EnsureInherentsAreFirst;
let block = Block::new(
Header::new_from_number(1),
vec![
Extrinsic { function: Call::Test2(CallTest2::RequiredInherent), signed: false },
Extrinsic { function: Call::Test(CallTest::OptionalInherent(true)), signed: false },
Extrinsic { function: Call::Test(CallTest::NotInherent), signed: false },
Extrinsic { function: Call::Test(CallTest::NotInherent), signed: false },
],
);
assert!(Runtime::ensure_inherents_are_first(&block).is_ok());
}
#[test]
fn inherent_cannot_be_placed_after_non_inherent() {
use crate::traits::EnsureInherentsAreFirst;
let block = Block::new(
Header::new_from_number(1),
vec![
Extrinsic { function: Call::Test2(CallTest2::RequiredInherent), signed: false },
Extrinsic { function: Call::Test(CallTest::NotInherent), signed: false },
// This inherent is placed after non inherent: invalid
Extrinsic { function: Call::Test(CallTest::OptionalInherent(true)), signed: false },
],
);
assert_eq!(Runtime::ensure_inherents_are_first(&block).err().unwrap(), 2);
let block = Block::new(
Header::new_from_number(1),
vec![
Extrinsic { function: Call::Test2(CallTest2::RequiredInherent), signed: false },
Extrinsic { function: Call::Test(CallTest::OptionalInherent(true)), signed: true },
// This inherent is placed after non inherent: invalid
Extrinsic { function: Call::Test(CallTest::OptionalInherent(true)), signed: false },
],
);
assert_eq!(Runtime::ensure_inherents_are_first(&block).err().unwrap(), 2);
}
}
+10 -7
View File
@@ -49,26 +49,29 @@ pub use log;
#[doc(hidden)]
pub use frame_metadata as metadata;
#[macro_use]
mod origin;
#[macro_use]
pub mod dispatch;
pub mod storage;
mod hash;
#[macro_use]
pub mod event;
#[macro_use]
pub mod genesis_config;
#[macro_use]
pub mod inherent;
#[macro_use]
pub mod unsigned;
#[macro_use]
pub mod error;
pub mod traits;
pub mod weights;
pub mod instances;
#[doc(hidden)]
pub mod unsigned {
#[doc(hidden)]
pub use crate::sp_runtime::traits::ValidateUnsigned;
#[doc(hidden)]
pub use crate::sp_runtime::transaction_validity::{
TransactionValidity, UnknownTransaction, TransactionValidityError, TransactionSource,
};
}
pub use self::hash::{
Twox256, Twox128, Blake2_256, Blake2_128, Identity, Twox64Concat, Blake2_128Concat, Hashable,
StorageHasher, ReversibleStorageHasher
-569
View File
@@ -1,569 +0,0 @@
// This file is part of Substrate.
// Copyright (C) 2018-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.
//! Macros that define an Origin type. Every function call to your runtime has an origin which
//! specifies where the extrinsic was generated from.
/// Constructs an Origin type for a runtime. This is usually called automatically by the
/// construct_runtime macro. See also __create_decl_macro.
#[macro_export]
macro_rules! impl_outer_origin {
// Macro transformations (to convert invocations with incomplete parameters to the canonical
// form)
(
$(#[$attr:meta])*
pub enum $name:ident for $runtime:ident {
$( $rest_without_system:tt )*
}
) => {
$crate::impl_outer_origin! {
$(#[$attr])*
pub enum $name for $runtime where system = frame_system {
$( $rest_without_system )*
}
}
};
(
$(#[$attr:meta])*
pub enum $name:ident for $runtime:ident where
system = $system:ident
$(, system_index = $system_index:tt)?
{
$( $rest_with_system:tt )*
}
) => {
$crate::paste::item! {
$crate::impl_outer_origin!(
$( #[$attr] )*;
$name;
[< $name Caller >];
$runtime;
$system;
system_index { $( $system_index )? };
Modules { $( $rest_with_system )* };
);
}
};
// Generic + Instance
(
$(#[$attr:meta])*;
$name:ident;
$caller_name:ident;
$runtime:ident;
$system:ident;
system_index { $( $system_index:tt )? };
Modules {
$( #[codec(index = $index:tt)] )? $module:ident $instance:ident <T>
$(, $( $rest_module:tt )* )?
};
$( $parsed:tt )*
) => {
$crate::impl_outer_origin!(
$( #[$attr] )*;
$name;
$caller_name;
$runtime;
$system;
system_index { $( $system_index )? };
Modules { $( $( $rest_module )* )? };
$( $parsed )* $module <$runtime> { $instance } index { $( $index )? },
);
};
// Instance
(
$(#[$attr:meta])*;
$name:ident;
$caller_name:ident;
$runtime:ident;
$system:ident;
system_index { $( $system_index:tt )? };
Modules {
$( #[codec(index = $index:tt )] )? $module:ident $instance:ident
$(, $rest_module:tt )*
};
$( $parsed:tt )*
) => {
$crate::impl_outer_origin!(
$( #[$attr] )*;
$name;
$caller_name;
$runtime;
$system;
system_index { $( $system_index )? };
Modules { $( $rest_module )* };
$( $parsed )* $module { $instance } index { $( $index )? },
);
};
// Generic
(
$(#[$attr:meta])*;
$name:ident;
$caller_name:ident;
$runtime:ident;
$system:ident;
system_index { $( $system_index:tt )? };
Modules {
$( #[codec(index = $index:tt )] )? $module:ident <T>
$(, $( $rest_module:tt )* )?
};
$( $parsed:tt )*
) => {
$crate::impl_outer_origin!(
$( #[$attr] )*;
$name;
$caller_name;
$runtime;
$system;
system_index { $( $system_index )? };
Modules { $( $( $rest_module )* )? };
$( $parsed )* $module <$runtime> index { $( $index )? },
);
};
// No Generic and no Instance
(
$(#[$attr:meta])*;
$name:ident;
$caller_name:ident;
$runtime:ident;
$system:ident;
system_index { $( $system_index:tt )? };
Modules {
$( #[codec(index = $index:tt )] )? $module:ident
$(, $( $rest_module:tt )* )?
};
$( $parsed:tt )*
) => {
$crate::impl_outer_origin!(
$( #[$attr] )*;
$name;
$caller_name;
$runtime;
$system;
system_index { $( $system_index )? };
Modules { $( $( $rest_module )* )? };
$( $parsed )* $module index { $( $index )? },
);
};
// The main macro expansion that actually renders the Origin enum code.
(
$(#[$attr:meta])*;
$name:ident;
$caller_name:ident;
$runtime:ident;
$system:ident;
system_index { $( $system_index:tt )? };
Modules { };
$(
$module:ident
$( < $generic:ident > )?
$( { $generic_instance:ident } )?
index { $( $index:tt )? },
)*
) => {
// WARNING: All instance must hold the filter `frame_system::Config::BaseCallFilter`, except
// when caller is system Root. One can use `OriginTrait::reset_filter` to do so.
#[derive(Clone)]
pub struct $name {
caller: $caller_name,
filter: $crate::sp_std::rc::Rc<Box<dyn Fn(&<$runtime as $system::Config>::Call) -> bool>>,
}
#[cfg(not(feature = "std"))]
impl $crate::sp_std::fmt::Debug for $name {
fn fmt(
&self,
fmt: &mut $crate::sp_std::fmt::Formatter
) -> $crate::sp_std::result::Result<(), $crate::sp_std::fmt::Error> {
fmt.write_str("<wasm:stripped>")
}
}
#[cfg(feature = "std")]
impl $crate::sp_std::fmt::Debug for $name {
fn fmt(
&self,
fmt: &mut $crate::sp_std::fmt::Formatter
) -> $crate::sp_std::result::Result<(), $crate::sp_std::fmt::Error> {
fmt.debug_struct(stringify!($name))
.field("caller", &self.caller)
.field("filter", &"[function ptr]")
.finish()
}
}
impl $crate::traits::OriginTrait for $name {
type Call = <$runtime as $system::Config>::Call;
type PalletsOrigin = $caller_name;
type AccountId = <$runtime as $system::Config>::AccountId;
fn add_filter(&mut self, filter: impl Fn(&Self::Call) -> bool + 'static) {
let f = self.filter.clone();
self.filter = $crate::sp_std::rc::Rc::new(Box::new(move |call| {
f(call) && filter(call)
}));
}
fn reset_filter(&mut self) {
let filter = <
<$runtime as $system::Config>::BaseCallFilter
as $crate::traits::Filter<<$runtime as $system::Config>::Call>
>::filter;
self.filter = $crate::sp_std::rc::Rc::new(Box::new(filter));
}
fn set_caller_from(&mut self, other: impl Into<Self>) {
self.caller = other.into().caller
}
fn filter_call(&self, call: &Self::Call) -> bool {
(self.filter)(call)
}
fn caller(&self) -> &Self::PalletsOrigin {
&self.caller
}
fn try_with_caller<R>(
mut self,
f: impl FnOnce(Self::PalletsOrigin) -> Result<R, Self::PalletsOrigin>,
) -> Result<R, Self> {
match f(self.caller) {
Ok(r) => Ok(r),
Err(caller) => { self.caller = caller; Err(self) }
}
}
/// Create with system none origin and `frame-system::Config::BaseCallFilter`.
fn none() -> Self {
$system::RawOrigin::None.into()
}
/// Create with system root origin and no filter.
fn root() -> Self {
$system::RawOrigin::Root.into()
}
/// Create with system signed origin and `frame-system::Config::BaseCallFilter`.
fn signed(by: <$runtime as $system::Config>::AccountId) -> Self {
$system::RawOrigin::Signed(by).into()
}
}
$crate::paste::item! {
#[derive(Clone, PartialEq, Eq, $crate::RuntimeDebug, $crate::codec::Encode, $crate::codec::Decode)]
$(#[$attr])*
#[allow(non_camel_case_types)]
pub enum $caller_name {
$( #[codec(index = $system_index)] )?
system($system::Origin<$runtime>),
$(
$( #[codec(index = $index)] )?
[< $module $( _ $generic_instance )? >]
($module::Origin < $( $generic, )? $( $module::$generic_instance )? > ),
)*
#[allow(dead_code)]
Void($crate::Void)
}
}
// For backwards compatibility and ease of accessing these functions.
#[allow(dead_code)]
impl $name {
/// Create with system none origin and `frame-system::Config::BaseCallFilter`.
pub fn none() -> Self {
<$name as $crate::traits::OriginTrait>::none()
}
/// Create with system root origin and no filter.
pub fn root() -> Self {
<$name as $crate::traits::OriginTrait>::root()
}
/// Create with system signed origin and `frame-system::Config::BaseCallFilter`.
pub fn signed(by: <$runtime as $system::Config>::AccountId) -> Self {
<$name as $crate::traits::OriginTrait>::signed(by)
}
}
impl From<$system::Origin<$runtime>> for $caller_name {
fn from(x: $system::Origin<$runtime>) -> Self {
$caller_name::system(x)
}
}
impl $crate::sp_std::convert::TryFrom<$caller_name> for $system::Origin<$runtime> {
type Error = $caller_name;
fn try_from(x: $caller_name)
-> $crate::sp_std::result::Result<$system::Origin<$runtime>, $caller_name>
{
if let $caller_name::system(l) = x {
Ok(l)
} else {
Err(x)
}
}
}
impl From<$system::Origin<$runtime>> for $name {
/// Convert to runtime origin:
/// * root origin is built with no filter
/// * others use `frame-system::Config::BaseCallFilter`
fn from(x: $system::Origin<$runtime>) -> Self {
let o: $caller_name = x.into();
o.into()
}
}
impl From<$caller_name> for $name {
fn from(x: $caller_name) -> Self {
let mut o = $name {
caller: x,
filter: $crate::sp_std::rc::Rc::new(Box::new(|_| true)),
};
// Root has no filter
if !matches!(o.caller, $caller_name::system($system::Origin::<$runtime>::Root)) {
$crate::traits::OriginTrait::reset_filter(&mut o);
}
o
}
}
impl From<$name> for $crate::sp_std::result::Result<$system::Origin<$runtime>, $name>{
/// NOTE: converting to pallet origin loses the origin filter information.
fn from(val: $name) -> Self {
if let $caller_name::system(l) = val.caller {
Ok(l)
} else {
Err(val)
}
}
}
impl From<Option<<$runtime as $system::Config>::AccountId>> for $name {
/// Convert to runtime origin with caller being system signed or none and use filter
/// `frame-system::Config::BaseCallFilter`.
fn from(x: Option<<$runtime as $system::Config>::AccountId>) -> Self {
<$system::Origin<$runtime>>::from(x).into()
}
}
$(
$crate::paste::item! {
impl From<$module::Origin < $( $generic )? $(, $module::$generic_instance )? > > for $caller_name {
fn from(x: $module::Origin < $( $generic )? $(, $module::$generic_instance )? >) -> Self {
$caller_name::[< $module $( _ $generic_instance )? >](x)
}
}
impl From<$module::Origin < $( $generic )? $(, $module::$generic_instance )? > > for $name {
/// Convert to runtime origin using `frame-system::Config::BaseCallFilter`.
fn from(x: $module::Origin < $( $generic )? $(, $module::$generic_instance )? >) -> Self {
let x: $caller_name = x.into();
x.into()
}
}
impl From<$name> for $crate::sp_std::result::Result<
$module::Origin < $( $generic )? $(, $module::$generic_instance )? >,
$name,
>
{
/// NOTE: converting to pallet origin loses the origin filter information.
fn from(val: $name) -> Self {
if let $caller_name::[< $module $( _ $generic_instance )? >](l) = val.caller {
Ok(l)
} else {
Err(val)
}
}
}
impl $crate::sp_std::convert::TryFrom<
$caller_name
> for $module::Origin < $( $generic )? $(, $module::$generic_instance )? > {
type Error = $caller_name;
fn try_from(x: $caller_name) -> $crate::sp_std::result::Result<
$module::Origin < $( $generic )? $(, $module::$generic_instance )? >,
$caller_name,
> {
if let $caller_name::[< $module $( _ $generic_instance )? >](l) = x {
Ok(l)
} else {
Err(x)
}
}
}
}
)*
}
}
#[cfg(test)]
mod tests {
use codec::{Encode, Decode};
use crate::traits::{Filter, OriginTrait};
mod frame_system {
use super::*;
pub trait Config {
type AccountId;
type Call;
type BaseCallFilter;
}
#[derive(Clone, PartialEq, Eq, Debug, Encode, Decode)]
pub enum RawOrigin<AccountId> {
Root,
Signed(AccountId),
None,
}
impl<AccountId> From<Option<AccountId>> for RawOrigin<AccountId> {
fn from(s: Option<AccountId>) -> RawOrigin<AccountId> {
match s {
Some(who) => RawOrigin::Signed(who),
None => RawOrigin::None,
}
}
}
pub type Origin<T> = RawOrigin<<T as Config>::AccountId>;
}
mod origin_without_generic {
use super::*;
#[derive(Clone, PartialEq, Eq, Debug, Encode, Decode)]
pub struct Origin;
}
mod origin_with_generic {
use super::*;
#[derive(Clone, PartialEq, Eq, Debug, Encode, Decode)]
pub struct Origin<T> {
t: T
}
}
#[derive(Clone, PartialEq, Eq, Debug, Encode, Decode)]
pub struct TestRuntime;
pub struct BaseCallFilter;
impl Filter<u32> for BaseCallFilter {
fn filter(c: &u32) -> bool {
*c % 2 == 0
}
}
impl frame_system::Config for TestRuntime {
type AccountId = u32;
type Call = u32;
type BaseCallFilter = BaseCallFilter;
}
impl_outer_origin!(
pub enum OriginWithoutSystem for TestRuntime {
origin_without_generic,
origin_with_generic<T>,
}
);
impl_outer_origin!(
pub enum OriginWithoutSystem2 for TestRuntime {
origin_with_generic<T>,
origin_without_generic
}
);
impl_outer_origin!(
pub enum OriginWithSystem for TestRuntime where system = frame_system {
origin_without_generic,
origin_with_generic<T>
}
);
impl_outer_origin!(
pub enum OriginWithSystem2 for TestRuntime where system = frame_system {
origin_with_generic<T>,
origin_without_generic,
}
);
impl_outer_origin!(
pub enum OriginEmpty for TestRuntime where system = frame_system {}
);
impl_outer_origin!(
pub enum OriginIndices for TestRuntime where system = frame_system, system_index = 11 {
origin_with_generic<T>,
#[codec(index = 10)] origin_without_generic,
}
);
#[test]
fn test_default_filter() {
assert_eq!(OriginWithSystem::root().filter_call(&0), true);
assert_eq!(OriginWithSystem::root().filter_call(&1), true);
assert_eq!(OriginWithSystem::none().filter_call(&0), true);
assert_eq!(OriginWithSystem::none().filter_call(&1), false);
assert_eq!(OriginWithSystem::signed(0).filter_call(&0), true);
assert_eq!(OriginWithSystem::signed(0).filter_call(&1), false);
assert_eq!(OriginWithSystem::from(Some(0)).filter_call(&0), true);
assert_eq!(OriginWithSystem::from(Some(0)).filter_call(&1), false);
assert_eq!(OriginWithSystem::from(None).filter_call(&0), true);
assert_eq!(OriginWithSystem::from(None).filter_call(&1), false);
assert_eq!(OriginWithSystem::from(origin_without_generic::Origin).filter_call(&0), true);
assert_eq!(OriginWithSystem::from(origin_without_generic::Origin).filter_call(&1), false);
let mut origin = OriginWithSystem::from(Some(0));
origin.add_filter(|c| *c % 2 == 1);
assert_eq!(origin.filter_call(&0), false);
assert_eq!(origin.filter_call(&1), false);
origin.set_caller_from(OriginWithSystem::root());
assert!(matches!(origin.caller, OriginWithSystemCaller::system(frame_system::RawOrigin::Root)));
assert_eq!(origin.filter_call(&0), false);
assert_eq!(origin.filter_call(&1), false);
origin.reset_filter();
assert_eq!(origin.filter_call(&0), true);
assert_eq!(origin.filter_call(&1), false);
}
#[test]
fn test_codec() {
use codec::Encode;
assert_eq!(OriginIndices::root().caller.encode()[0], 11);
let without_generic_variant = OriginIndicesCaller::origin_without_generic(
origin_without_generic::Origin
);
assert_eq!(without_generic_variant.encode()[0], 10);
assert_eq!(OriginWithoutSystem::root().caller.encode()[0], 0);
let without_generic_variant = OriginWithoutSystemCaller::origin_without_generic(
origin_without_generic::Origin
);
assert_eq!(without_generic_variant.encode()[0], 1);
}
}
@@ -41,7 +41,7 @@ pub trait EnsureOrigin<OuterOrigin> {
/// Type that can be dispatched with an origin but without checking the origin filter.
///
/// Implemented for pallet dispatchable type by `decl_module` and for runtime dispatchable by
/// `construct_runtime` and `impl_outer_dispatch`.
/// `construct_runtime`.
pub trait UnfilteredDispatchable {
/// The origin type of the runtime, (i.e. `frame_system::Config::Origin`).
type Origin;
-172
View File
@@ -1,172 +0,0 @@
// This file is part of Substrate.
// Copyright (C) 2019-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.
#[doc(hidden)]
pub use crate::sp_runtime::traits::ValidateUnsigned;
#[doc(hidden)]
pub use crate::sp_runtime::transaction_validity::{
TransactionValidity, UnknownTransaction, TransactionValidityError, TransactionSource,
};
/// Implement `ValidateUnsigned` for `Runtime`.
/// All given modules need to implement `ValidateUnsigned`.
///
/// # Example
///
/// ```
/// # mod timestamp {
/// # pub struct Module;
/// #
/// # impl frame_support::unsigned::ValidateUnsigned for Module {
/// # type Call = Call;
/// #
/// # fn validate_unsigned(_source: frame_support::unsigned::TransactionSource, _call: &Self::Call)
/// -> frame_support::unsigned::TransactionValidity {
/// # unimplemented!();
/// # }
/// # }
/// #
/// # pub enum Call {
/// # }
/// # }
/// #
/// # pub type Timestamp = timestamp::Module;
/// #
/// #
/// # pub enum Call {
/// # Timestamp(timestamp::Call),
/// # }
/// # #[allow(unused)]
/// pub struct Runtime;
///
/// frame_support::impl_outer_validate_unsigned! {
/// impl ValidateUnsigned for Runtime {
/// Timestamp
/// }
/// }
/// ```
#[macro_export]
macro_rules! impl_outer_validate_unsigned {
(
impl ValidateUnsigned for $runtime:ident {
$( $module:ident )*
}
) => {
impl $crate::unsigned::ValidateUnsigned for $runtime {
type Call = Call;
fn pre_dispatch(call: &Self::Call) -> Result<(), $crate::unsigned::TransactionValidityError> {
#[allow(unreachable_patterns)]
match call {
$( Call::$module(inner_call) => $module::pre_dispatch(inner_call), )*
// pre-dispatch should not stop inherent extrinsics, validation should prevent
// including arbitrary (non-inherent) extrinsics to blocks.
_ => Ok(()),
}
}
fn validate_unsigned(
#[allow(unused_variables)]
source: $crate::unsigned::TransactionSource,
call: &Self::Call,
) -> $crate::unsigned::TransactionValidity {
#[allow(unreachable_patterns)]
match call {
$( Call::$module(inner_call) => $module::validate_unsigned(source, inner_call), )*
_ => $crate::unsigned::UnknownTransaction::NoUnsignedValidator.into(),
}
}
}
};
}
#[cfg(test)]
mod test_empty_call {
pub enum Call {}
#[allow(unused)]
pub struct Runtime;
impl_outer_validate_unsigned! {
impl ValidateUnsigned for Runtime {
}
}
}
#[cfg(test)]
mod test_partial_and_full_call {
pub mod timestamp {
pub struct Module;
impl super::super::ValidateUnsigned for Module {
type Call = Call;
fn validate_unsigned(
_source: super::super::TransactionSource,
_call: &Self::Call
) -> super::super::TransactionValidity {
unimplemented!();
}
}
pub enum Call {
Foo,
}
}
mod test_full_unsigned {
pub type Timestamp = super::timestamp::Module;
pub enum Call {
Timestamp(super::timestamp::Call),
}
pub struct Runtime;
impl_outer_validate_unsigned! {
impl ValidateUnsigned for Runtime {
Timestamp
}
}
#[test]
fn used() {
let _ = Call::Timestamp(super::timestamp::Call::Foo);
let _ = Runtime;
}
}
mod test_not_full_unsigned {
pub enum Call {
Timestamp(super::timestamp::Call),
}
pub struct Runtime;
impl_outer_validate_unsigned! {
impl ValidateUnsigned for Runtime {
}
}
#[test]
fn used() {
let _ = Call::Timestamp(super::timestamp::Call::Foo);
let _ = Runtime;
}
}
}