mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-27 13:57:58 +00:00
Remove impl_outer_ macros (#9307)
* remove impl_outer_* * continue to reexport some unsigned in order not to break users
This commit is contained in:
committed by
GitHub
parent
c78c2892a4
commit
4856b6fcf4
@@ -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() {
|
||||
|
||||
@@ -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,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user