Introduce in-origin filtering (#6318)

* impl filter in origin

* remove IsCallable usage. Breaking: utility::batch(root, calls) no longer bypass BasicCallFilter

* rename BasicCallFilter -> BaseCallFilter

* refactor code

* Apply suggestions from code review

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>

* remove forgotten temporar comment

* better add suggestion in another PR

* refactor: use Clone instead of mem::replace

* fix tests

* fix tests

* fix tests

* fix benchmarks

* Make root bypass filter in utility::batch

* fix unused imports

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
This commit is contained in:
Guillaume Thiolliere
2020-06-15 17:05:41 +02:00
committed by GitHub
parent 97cac4ce8b
commit c2ad27271b
79 changed files with 536 additions and 302 deletions
@@ -24,6 +24,7 @@ parameter_types! {
pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
} }
impl system::Trait for Test { impl system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Call = (); type Call = ();
type Index = u64; type Index = u64;
@@ -135,6 +135,8 @@ parameter_types! {
} }
impl system::Trait for Runtime { impl system::Trait for Runtime {
/// The basic call filter to use in dispatchable.
type BaseCallFilter = ();
/// The identifier used to distinguish between accounts. /// The identifier used to distinguish between accounts.
type AccountId = AccountId; type AccountId = AccountId;
/// The aggregated dispatch type that is available for extrinsics. /// The aggregated dispatch type that is available for extrinsics.
+2 -13
View File
@@ -33,7 +33,7 @@ use frame_support::{
traits::{Currency, Imbalance, KeyOwnerProofSystem, OnUnbalanced, Randomness, LockIdentifier}, traits::{Currency, Imbalance, KeyOwnerProofSystem, OnUnbalanced, Randomness, LockIdentifier},
}; };
use frame_system::{EnsureRoot, EnsureOneOf}; use frame_system::{EnsureRoot, EnsureOneOf};
use frame_support::traits::{Filter, InstanceFilter}; use frame_support::traits::InstanceFilter;
use codec::{Encode, Decode}; use codec::{Encode, Decode};
use sp_core::{ use sp_core::{
crypto::KeyTypeId, crypto::KeyTypeId,
@@ -113,15 +113,6 @@ pub fn native_version() -> NativeVersion {
type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance; type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;
pub struct BaseFilter;
impl Filter<Call> for BaseFilter {
fn filter(_call: &Call) -> bool {
true
}
}
pub struct IsCallable;
frame_support::impl_filter_stack!(IsCallable, BaseFilter, Call, is_callable);
pub struct DealWithFees; pub struct DealWithFees;
impl OnUnbalanced<NegativeImbalance> for DealWithFees { impl OnUnbalanced<NegativeImbalance> for DealWithFees {
fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item=NegativeImbalance>) { fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item=NegativeImbalance>) {
@@ -155,6 +146,7 @@ parameter_types! {
const_assert!(AvailableBlockRatio::get().deconstruct() >= AVERAGE_ON_INITIALIZE_WEIGHT.deconstruct()); const_assert!(AvailableBlockRatio::get().deconstruct() >= AVERAGE_ON_INITIALIZE_WEIGHT.deconstruct());
impl frame_system::Trait for Runtime { impl frame_system::Trait for Runtime {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Call = Call; type Call = Call;
type Index = Index; type Index = Index;
@@ -183,7 +175,6 @@ impl frame_system::Trait for Runtime {
impl pallet_utility::Trait for Runtime { impl pallet_utility::Trait for Runtime {
type Event = Event; type Event = Event;
type Call = Call; type Call = Call;
type IsCallable = IsCallable;
} }
parameter_types! { parameter_types! {
@@ -201,7 +192,6 @@ impl pallet_multisig::Trait for Runtime {
type DepositBase = DepositBase; type DepositBase = DepositBase;
type DepositFactor = DepositFactor; type DepositFactor = DepositFactor;
type MaxSignatories = MaxSignatories; type MaxSignatories = MaxSignatories;
type IsCallable = IsCallable;
} }
parameter_types! { parameter_types! {
@@ -251,7 +241,6 @@ impl pallet_proxy::Trait for Runtime {
type Event = Event; type Event = Event;
type Call = Call; type Call = Call;
type Currency = Balances; type Currency = Balances;
type IsCallable = IsCallable;
type ProxyType = ProxyType; type ProxyType = ProxyType;
type ProxyDepositBase = ProxyDepositBase; type ProxyDepositBase = ProxyDepositBase;
type ProxyDepositFactor = ProxyDepositFactor; type ProxyDepositFactor = ProxyDepositFactor;
+1
View File
@@ -304,6 +304,7 @@ mod tests {
pub const AvailableBlockRatio: Perbill = Perbill::one(); pub const AvailableBlockRatio: Perbill = Perbill::one();
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type Call = (); type Call = ();
+1
View File
@@ -46,6 +46,7 @@ parameter_types! {
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
@@ -143,6 +143,7 @@ mod tests {
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = BlockNumber; type BlockNumber = BlockNumber;
+1
View File
@@ -418,6 +418,7 @@ mod tests {
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
+1
View File
@@ -57,6 +57,7 @@ parameter_types! {
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
+1
View File
@@ -848,6 +848,7 @@ impl<T: Subtrait<I>, I: Instance> PartialEq for ElevatedTrait<T, I> {
} }
impl<T: Subtrait<I>, I: Instance> Eq for ElevatedTrait<T, I> {} impl<T: Subtrait<I>, I: Instance> Eq for ElevatedTrait<T, I> {}
impl<T: Subtrait<I>, I: Instance> frame_system::Trait for ElevatedTrait<T, I> { impl<T: Subtrait<I>, I: Instance> frame_system::Trait for ElevatedTrait<T, I> {
type BaseCallFilter = T::BaseCallFilter;
type Origin = T::Origin; type Origin = T::Origin;
type Call = T::Call; type Call = T::Call;
type Index = T::Index; type Index = T::Index;
@@ -67,6 +67,7 @@ parameter_types! {
pub const AvailableBlockRatio: Perbill = Perbill::one(); pub const AvailableBlockRatio: Perbill = Perbill::one();
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
@@ -67,6 +67,7 @@ parameter_types! {
pub const AvailableBlockRatio: Perbill = Perbill::one(); pub const AvailableBlockRatio: Perbill = Perbill::one();
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
+8 -3
View File
@@ -29,7 +29,8 @@ pub use utils::*;
pub use analysis::Analysis; pub use analysis::Analysis;
#[doc(hidden)] #[doc(hidden)]
pub use sp_io::storage::root as storage_root; pub use sp_io::storage::root as storage_root;
pub use sp_runtime::traits::{Dispatchable, Zero}; pub use sp_runtime::traits::Zero;
pub use frame_support;
pub use paste; pub use paste;
/// Construct pallet benchmarks for weighing dispatchables. /// Construct pallet benchmarks for weighing dispatchables.
@@ -242,7 +243,9 @@ macro_rules! benchmarks_iter {
{ $( $common )* } { $( $common )* }
( $( $names )* ) ( $( $names )* )
$name { $( $code )* }: { $name { $( $code )* }: {
<Call<T> as $crate::Dispatchable>::dispatch(Call::<T>::$dispatch($($arg),*), $origin.into())?; <
Call<T> as $crate::frame_support::traits::UnfilteredDispatchable
>::dispatch_bypass_filter(Call::<T>::$dispatch($($arg),*), $origin.into())?;
} }
verify $postcode verify $postcode
$( $rest )* $( $rest )*
@@ -262,7 +265,9 @@ macro_rules! benchmarks_iter {
{ $( $common )* } { $( $common )* }
( $( $names )* ) ( $( $names )* )
$name { $( $code )* }: { $name { $( $code )* }: {
<Call<T, I> as $crate::Dispatchable>::dispatch(Call::<T, I>::$dispatch($($arg),*), $origin.into())?; <
Call<T, I> as $crate::frame_support::traits::UnfilteredDispatchable
>::dispatch_bypass_filter(Call::<T, I>::$dispatch($($arg),*), $origin.into())?;
} }
verify $postcode verify $postcode
$( $rest )* $( $rest )*
@@ -67,6 +67,7 @@ pub trait Trait {
pub struct Test; pub struct Test;
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
+7 -6
View File
@@ -1015,10 +1015,11 @@ mod tests {
pub const MaxProposals: u32 = 100; pub const MaxProposals: u32 = 100;
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
type Call = (); type Call = Call;
type Hash = H256; type Hash = H256;
type Hashing = BlakeTwo256; type Hashing = BlakeTwo256;
type AccountId = u64; type AccountId = u64;
@@ -1167,7 +1168,7 @@ mod tests {
let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32);
let proposal_weight = proposal.get_dispatch_info().weight; let proposal_weight = proposal.get_dispatch_info().weight;
let hash = BlakeTwo256::hash_of(&proposal); let hash = BlakeTwo256::hash_of(&proposal);
assert_ok!(Collective::set_members(Origin::ROOT, vec![1, 2, 3], Some(3), MAX_MEMBERS)); assert_ok!(Collective::set_members(Origin::root(), vec![1, 2, 3], Some(3), MAX_MEMBERS));
assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len)); assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len));
assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, true)); assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, true));
@@ -1192,7 +1193,7 @@ mod tests {
let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32);
let proposal_weight = proposal.get_dispatch_info().weight; let proposal_weight = proposal.get_dispatch_info().weight;
let hash = BlakeTwo256::hash_of(&proposal); let hash = BlakeTwo256::hash_of(&proposal);
assert_ok!(Collective::set_members(Origin::ROOT, vec![1, 2, 3], Some(1), MAX_MEMBERS)); assert_ok!(Collective::set_members(Origin::root(), vec![1, 2, 3], Some(1), MAX_MEMBERS));
assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len)); assert_ok!(Collective::propose(Origin::signed(1), 3, Box::new(proposal.clone()), proposal_len));
assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, true)); assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, true));
@@ -1260,7 +1261,7 @@ mod tests {
Collective::voting(&hash), Collective::voting(&hash),
Some(Votes { index: 0, threshold: 3, ayes: vec![1, 2], nays: vec![], end }) Some(Votes { index: 0, threshold: 3, ayes: vec![1, 2], nays: vec![], end })
); );
assert_ok!(Collective::set_members(Origin::ROOT, vec![2, 3, 4], None, MAX_MEMBERS)); assert_ok!(Collective::set_members(Origin::root(), vec![2, 3, 4], None, MAX_MEMBERS));
assert_eq!( assert_eq!(
Collective::voting(&hash), Collective::voting(&hash),
Some(Votes { index: 0, threshold: 3, ayes: vec![2], nays: vec![], end }) Some(Votes { index: 0, threshold: 3, ayes: vec![2], nays: vec![], end })
@@ -1275,7 +1276,7 @@ mod tests {
Collective::voting(&hash), Collective::voting(&hash),
Some(Votes { index: 1, threshold: 2, ayes: vec![2], nays: vec![3], end }) Some(Votes { index: 1, threshold: 2, ayes: vec![2], nays: vec![3], end })
); );
assert_ok!(Collective::set_members(Origin::ROOT, vec![2, 4], None, MAX_MEMBERS)); assert_ok!(Collective::set_members(Origin::root(), vec![2, 4], None, MAX_MEMBERS));
assert_eq!( assert_eq!(
Collective::voting(&hash), Collective::voting(&hash),
Some(Votes { index: 1, threshold: 2, ayes: vec![2], nays: vec![], end }) Some(Votes { index: 1, threshold: 2, ayes: vec![2], nays: vec![], end })
@@ -1618,7 +1619,7 @@ mod tests {
// Proposal would normally succeed // Proposal would normally succeed
assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, true)); assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, true));
// But Root can disapprove and remove it anyway // But Root can disapprove and remove it anyway
assert_ok!(Collective::disapprove_proposal(Origin::ROOT, hash.clone())); assert_ok!(Collective::disapprove_proposal(Origin::root(), hash.clone()));
let record = |event| EventRecord { phase: Phase::Initialization, event, topics: vec![] }; let record = |event| EventRecord { phase: Phase::Initialization, event, topics: vec![] };
assert_eq!(System::events(), vec![ assert_eq!(System::events(), vec![
record(Event::collective_Instance1(RawEvent::Proposed(1, 0, hash.clone(), 2))), record(Event::collective_Instance1(RawEvent::Proposed(1, 0, hash.clone(), 2))),
+7 -6
View File
@@ -82,11 +82,12 @@ parameter_types! {
pub const AvailableBlockRatio: Perbill = Perbill::one(); pub const AvailableBlockRatio: Perbill = Perbill::one();
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
type Hash = H256; type Hash = H256;
type Call = (); type Call = Call;
type Hashing = BlakeTwo256; type Hashing = BlakeTwo256;
type AccountId = u64; type AccountId = u64;
type Lookup = IdentityLookup<Self::AccountId>; type Lookup = IdentityLookup<Self::AccountId>;
@@ -936,7 +937,7 @@ fn call_contract_removals() {
#[test] #[test]
fn inherent_claim_surcharge_contract_removals() { fn inherent_claim_surcharge_contract_removals() {
removals(|| Contracts::claim_surcharge(Origin::NONE, BOB, Some(ALICE)).is_ok()); removals(|| Contracts::claim_surcharge(Origin::none(), BOB, Some(ALICE)).is_ok());
} }
#[test] #[test]
@@ -947,10 +948,10 @@ fn signed_claim_surcharge_contract_removals() {
#[test] #[test]
fn claim_surcharge_malus() { fn claim_surcharge_malus() {
// Test surcharge malus for inherent // Test surcharge malus for inherent
claim_surcharge(4, || Contracts::claim_surcharge(Origin::NONE, BOB, Some(ALICE)).is_ok(), true); claim_surcharge(4, || Contracts::claim_surcharge(Origin::none(), BOB, Some(ALICE)).is_ok(), true);
claim_surcharge(3, || Contracts::claim_surcharge(Origin::NONE, BOB, Some(ALICE)).is_ok(), true); claim_surcharge(3, || Contracts::claim_surcharge(Origin::none(), BOB, Some(ALICE)).is_ok(), true);
claim_surcharge(2, || Contracts::claim_surcharge(Origin::NONE, BOB, Some(ALICE)).is_ok(), true); claim_surcharge(2, || Contracts::claim_surcharge(Origin::none(), BOB, Some(ALICE)).is_ok(), true);
claim_surcharge(1, || Contracts::claim_surcharge(Origin::NONE, BOB, Some(ALICE)).is_ok(), false); claim_surcharge(1, || Contracts::claim_surcharge(Origin::none(), BOB, Some(ALICE)).is_ok(), false);
// Test surcharge malus for signed // Test surcharge malus for signed
claim_surcharge(4, || Contracts::claim_surcharge(Origin::signed(ALICE), BOB, None).is_ok(), true); claim_surcharge(4, || Contracts::claim_surcharge(Origin::signed(ALICE), BOB, None).is_ok(), true);
@@ -22,7 +22,7 @@ use super::*;
use frame_benchmarking::{benchmarks, account}; use frame_benchmarking::{benchmarks, account};
use frame_support::{ use frame_support::{
IterableStorageMap, IterableStorageMap,
traits::{Currency, Get, EnsureOrigin, OnInitialize}, traits::{Currency, Get, EnsureOrigin, OnInitialize, UnfilteredDispatchable},
}; };
use frame_system::{RawOrigin, Module as System, self, EventRecord}; use frame_system::{RawOrigin, Module as System, self, EventRecord};
use sp_runtime::traits::{Bounded, One}; use sp_runtime::traits::{Bounded, One};
@@ -212,14 +212,14 @@ benchmarks! {
for i in 0 .. r { for i in 0 .. r {
let ref_idx = add_referendum::<T>(i)?; let ref_idx = add_referendum::<T>(i)?;
let call = Call::<T>::emergency_cancel(ref_idx); let call = Call::<T>::emergency_cancel(ref_idx);
call.dispatch(origin.clone())?; call.dispatch_bypass_filter(origin.clone())?;
} }
// Lets now measure one more // Lets now measure one more
let referendum_index = add_referendum::<T>(r)?; let referendum_index = add_referendum::<T>(r)?;
let call = Call::<T>::emergency_cancel(referendum_index); let call = Call::<T>::emergency_cancel(referendum_index);
assert!(Democracy::<T>::referendum_status(referendum_index).is_ok()); assert!(Democracy::<T>::referendum_status(referendum_index).is_ok());
}: { call.dispatch(origin)? } }: { call.dispatch_bypass_filter(origin)? }
verify { verify {
// Referendum has been canceled // Referendum has been canceled
assert!(Democracy::<T>::referendum_status(referendum_index).is_err()); assert!(Democracy::<T>::referendum_status(referendum_index).is_err());
@@ -239,7 +239,7 @@ benchmarks! {
); );
let call = Call::<T>::external_propose(proposal_hash); let call = Call::<T>::external_propose(proposal_hash);
}: { call.dispatch(origin)? } }: { call.dispatch_bypass_filter(origin)? }
verify { verify {
// External proposal created // External proposal created
ensure!(<NextExternal<T>>::exists(), "External proposal didn't work"); ensure!(<NextExternal<T>>::exists(), "External proposal didn't work");
@@ -251,7 +251,7 @@ benchmarks! {
let origin = T::ExternalMajorityOrigin::successful_origin(); let origin = T::ExternalMajorityOrigin::successful_origin();
let proposal_hash = T::Hashing::hash_of(&p); let proposal_hash = T::Hashing::hash_of(&p);
let call = Call::<T>::external_propose_majority(proposal_hash); let call = Call::<T>::external_propose_majority(proposal_hash);
}: { call.dispatch(origin)? } }: { call.dispatch_bypass_filter(origin)? }
verify { verify {
// External proposal created // External proposal created
ensure!(<NextExternal<T>>::exists(), "External proposal didn't work"); ensure!(<NextExternal<T>>::exists(), "External proposal didn't work");
@@ -263,7 +263,7 @@ benchmarks! {
let origin = T::ExternalDefaultOrigin::successful_origin(); let origin = T::ExternalDefaultOrigin::successful_origin();
let proposal_hash = T::Hashing::hash_of(&p); let proposal_hash = T::Hashing::hash_of(&p);
let call = Call::<T>::external_propose_default(proposal_hash); let call = Call::<T>::external_propose_default(proposal_hash);
}: { call.dispatch(origin)? } }: { call.dispatch_bypass_filter(origin)? }
verify { verify {
// External proposal created // External proposal created
ensure!(<NextExternal<T>>::exists(), "External proposal didn't work"); ensure!(<NextExternal<T>>::exists(), "External proposal didn't work");
@@ -282,7 +282,7 @@ benchmarks! {
let delay = 0; let delay = 0;
let call = Call::<T>::fast_track(proposal_hash, voting_period.into(), delay.into()); let call = Call::<T>::fast_track(proposal_hash, voting_period.into(), delay.into());
}: { call.dispatch(origin_fast_track)? } }: { call.dispatch_bypass_filter(origin_fast_track)? }
verify { verify {
assert_eq!(Democracy::<T>::referendum_count(), 1, "referendum not created") assert_eq!(Democracy::<T>::referendum_count(), 1, "referendum not created")
} }
@@ -306,7 +306,7 @@ benchmarks! {
let call = Call::<T>::veto_external(proposal_hash); let call = Call::<T>::veto_external(proposal_hash);
let origin = T::VetoOrigin::successful_origin(); let origin = T::VetoOrigin::successful_origin();
ensure!(NextExternal::<T>::get().is_some(), "no external proposal"); ensure!(NextExternal::<T>::get().is_some(), "no external proposal");
}: { call.dispatch(origin)? } }: { call.dispatch_bypass_filter(origin)? }
verify { verify {
assert!(NextExternal::<T>::get().is_none()); assert!(NextExternal::<T>::get().is_none());
let (_, new_vetoers) = <Blacklist<T>>::get(&proposal_hash).ok_or("no blacklist")?; let (_, new_vetoers) = <Blacklist<T>>::get(&proposal_hash).ok_or("no blacklist")?;
@@ -347,7 +347,7 @@ benchmarks! {
let origin = T::ExternalMajorityOrigin::successful_origin(); let origin = T::ExternalMajorityOrigin::successful_origin();
let proposal_hash = T::Hashing::hash_of(&r); let proposal_hash = T::Hashing::hash_of(&r);
let call = Call::<T>::external_propose_majority(proposal_hash); let call = Call::<T>::external_propose_majority(proposal_hash);
call.dispatch(origin)?; call.dispatch_bypass_filter(origin)?;
// External proposal created // External proposal created
ensure!(<NextExternal<T>>::exists(), "External proposal didn't work"); ensure!(<NextExternal<T>>::exists(), "External proposal didn't work");
+1
View File
@@ -84,6 +84,7 @@ parameter_types! {
pub const AvailableBlockRatio: Perbill = Perbill::one(); pub const AvailableBlockRatio: Perbill = Perbill::one();
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
@@ -29,7 +29,7 @@ fn cancel_referendum_should_work() {
0 0
); );
assert_ok!(Democracy::vote(Origin::signed(1), r, aye(1))); assert_ok!(Democracy::vote(Origin::signed(1), r, aye(1)));
assert_ok!(Democracy::cancel_referendum(Origin::ROOT, r.into())); assert_ok!(Democracy::cancel_referendum(Origin::root(), r.into()));
next_block(); next_block();
next_block(); next_block();
@@ -53,8 +53,8 @@ fn cancel_queued_should_work() {
assert!(pallet_scheduler::Agenda::<Test>::get(6)[0].is_some()); assert!(pallet_scheduler::Agenda::<Test>::get(6)[0].is_some());
assert_noop!(Democracy::cancel_queued(Origin::ROOT, 1), Error::<Test>::ProposalMissing); assert_noop!(Democracy::cancel_queued(Origin::root(), 1), Error::<Test>::ProposalMissing);
assert_ok!(Democracy::cancel_queued(Origin::ROOT, 0)); assert_ok!(Democracy::cancel_queued(Origin::root(), 0));
assert!(pallet_scheduler::Agenda::<Test>::get(6)[0].is_none()); assert!(pallet_scheduler::Agenda::<Test>::get(6)[0].is_none());
}); });
} }
+8 -10
View File
@@ -1070,10 +1070,11 @@ mod tests {
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
type Call = (); type Call = Call;
type Hash = H256; type Hash = H256;
type Hashing = BlakeTwo256; type Hashing = BlakeTwo256;
type AccountId = u64; type AccountId = u64;
@@ -1376,11 +1377,8 @@ mod tests {
// historical note: helper function was created in a period of time in which the API of vote // historical note: helper function was created in a period of time in which the API of vote
// call was changing. Currently it is a wrapper for the original call and does not do much. // call was changing. Currently it is a wrapper for the original call and does not do much.
// Nonetheless, totally harmless. // Nonetheless, totally harmless.
if let Origin::system(frame_system::RawOrigin::Signed(_account)) = origin { ensure_signed(origin.clone()).expect("vote origin must be signed");
Elections::vote(origin, votes, stake) Elections::vote(origin, votes, stake)
} else {
panic!("vote origin must be signed");
}
} }
fn votes_of(who: &u64) -> Vec<u64> { fn votes_of(who: &u64) -> Vec<u64> {
@@ -2358,7 +2356,7 @@ mod tests {
assert_ok!(submit_candidacy(Origin::signed(3))); assert_ok!(submit_candidacy(Origin::signed(3)));
assert_ok!(vote(Origin::signed(3), vec![3], 30)); assert_ok!(vote(Origin::signed(3), vec![3], 30));
assert_ok!(Elections::remove_member(Origin::ROOT, 4, false)); assert_ok!(Elections::remove_member(Origin::root(), 4, false));
assert_eq!(balances(&4), (35, 2)); // slashed assert_eq!(balances(&4), (35, 2)); // slashed
assert_eq!(Elections::election_rounds(), 2); // new election round assert_eq!(Elections::election_rounds(), 2); // new election round
@@ -2381,7 +2379,7 @@ mod tests {
// no replacement yet. // no replacement yet.
assert_err_with_weight!( assert_err_with_weight!(
Elections::remove_member(Origin::ROOT, 4, true), Elections::remove_member(Origin::root(), 4, true),
Error::<Test>::InvalidReplacement, Error::<Test>::InvalidReplacement,
Some(6000000), Some(6000000),
); );
@@ -2403,7 +2401,7 @@ mod tests {
// there is a replacement! and this one needs a weight refund. // there is a replacement! and this one needs a weight refund.
assert_err_with_weight!( assert_err_with_weight!(
Elections::remove_member(Origin::ROOT, 4, false), Elections::remove_member(Origin::root(), 4, false),
Error::<Test>::InvalidReplacement, Error::<Test>::InvalidReplacement,
Some(6000000) // only thing that matters for now is that it is NOT the full block. Some(6000000) // only thing that matters for now is that it is NOT the full block.
); );
@@ -2562,7 +2560,7 @@ mod tests {
Elections::end_block(System::block_number()); Elections::end_block(System::block_number());
assert_eq!(Elections::members_ids(), vec![2, 4]); assert_eq!(Elections::members_ids(), vec![2, 4]);
assert_ok!(Elections::remove_member(Origin::ROOT, 2, true)); assert_ok!(Elections::remove_member(Origin::root(), 2, true));
assert_eq!(Elections::members_ids(), vec![4, 5]); assert_eq!(Elections::members_ids(), vec![4, 5]);
}); });
} }
+2 -1
View File
@@ -39,8 +39,9 @@ parameter_types! {
pub const AvailableBlockRatio: Perbill = Perbill::one(); pub const AvailableBlockRatio: Perbill = Perbill::one();
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Call = (); type Call = Call;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
type Hash = H256; type Hash = H256;
+2 -2
View File
@@ -671,7 +671,7 @@ fn retracting_active_voter_should_slash_reporter() {
assert_ok!(Elections::end_block(System::block_number())); assert_ok!(Elections::end_block(System::block_number()));
System::set_block_number(8); System::set_block_number(8);
assert_ok!(Elections::set_desired_seats(Origin::ROOT, 3)); assert_ok!(Elections::set_desired_seats(Origin::root(), 3));
assert_ok!(Elections::end_block(System::block_number())); assert_ok!(Elections::end_block(System::block_number()));
System::set_block_number(10); System::set_block_number(10);
@@ -1245,7 +1245,7 @@ fn election_second_tally_should_use_runners_up() {
System::set_block_number(8); System::set_block_number(8);
assert_ok!(Elections::set_approvals(Origin::signed(6), vec![false, false, true, false], 1, 0, 60)); assert_ok!(Elections::set_approvals(Origin::signed(6), vec![false, false, true, false], 1, 0, 60));
assert_ok!(Elections::set_desired_seats(Origin::ROOT, 3)); assert_ok!(Elections::set_desired_seats(Origin::root(), 3));
assert_ok!(Elections::end_block(System::block_number())); assert_ok!(Elections::end_block(System::block_number()));
System::set_block_number(10); System::set_block_number(10);
@@ -54,6 +54,7 @@ parameter_types! {
pub const AvailableBlockRatio: Perbill = Perbill::one(); pub const AvailableBlockRatio: Perbill = Perbill::one();
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Call = (); type Call = ();
type Index = u64; type Index = u64;
+19 -13
View File
@@ -256,7 +256,7 @@
use sp_std::marker::PhantomData; use sp_std::marker::PhantomData;
use frame_support::{ use frame_support::{
dispatch::DispatchResult, decl_module, decl_storage, decl_event, dispatch::{DispatchResult, IsSubType}, decl_module, decl_storage, decl_event,
weights::{DispatchClass, ClassifyDispatch, WeighData, Weight, PaysFee, Pays}, weights::{DispatchClass, ClassifyDispatch, WeighData, Weight, PaysFee, Pays},
}; };
use sp_std::prelude::*; use sp_std::prelude::*;
@@ -609,14 +609,13 @@ impl<T: Trait + Send + Sync> sp_std::fmt::Debug for WatchDummy<T> {
} }
} }
impl<T: Trait + Send + Sync> SignedExtension for WatchDummy<T> { impl<T: Trait + Send + Sync> SignedExtension for WatchDummy<T>
where
<T as frame_system::Trait>::Call: IsSubType<Module<T>, T>,
{
const IDENTIFIER: &'static str = "WatchDummy"; const IDENTIFIER: &'static str = "WatchDummy";
type AccountId = T::AccountId; type AccountId = T::AccountId;
// Note that this could also be assigned to the top-level call enum. It is passed into the type Call = <T as frame_system::Trait>::Call;
// Balances Pallet directly and since `Trait: pallet_balances::Trait`, you could also use `T::Call`.
// In that case, you would have had access to all call variants and could match on variants from
// other pallets.
type Call = Call<T>;
type AdditionalSigned = (); type AdditionalSigned = ();
type Pre = (); type Pre = ();
@@ -635,8 +634,8 @@ impl<T: Trait + Send + Sync> SignedExtension for WatchDummy<T> {
} }
// check for `set_dummy` // check for `set_dummy`
match call { match call.is_sub_type() {
Call::set_dummy(..) => { Some(Call::set_dummy(..)) => {
sp_runtime::print("set_dummy was received."); sp_runtime::print("set_dummy was received.");
let mut valid_tx = ValidTransaction::default(); let mut valid_tx = ValidTransaction::default();
@@ -711,8 +710,8 @@ mod tests {
use super::*; use super::*;
use frame_support::{ use frame_support::{
assert_ok, impl_outer_origin, parameter_types, weights::{DispatchInfo, GetDispatchInfo}, assert_ok, impl_outer_origin, parameter_types, impl_outer_dispatch,
traits::{OnInitialize, OnFinalize} weights::{DispatchInfo, GetDispatchInfo}, traits::{OnInitialize, OnFinalize}
}; };
use sp_core::H256; use sp_core::H256;
// The testing primitives are very useful for avoiding having to work with signatures // The testing primitives are very useful for avoiding having to work with signatures
@@ -727,6 +726,12 @@ mod tests {
pub enum Origin for Test where system = frame_system {} pub enum Origin for Test where system = frame_system {}
} }
impl_outer_dispatch! {
pub enum OuterCall for Test where origin: Origin {
self::Example,
}
}
// For testing the pallet, we construct most of a mock runtime. This means // For testing the pallet, we construct most of a mock runtime. This means
// first constructing a configuration type (`Test`) which `impl`s each of the // first constructing a configuration type (`Test`) which `impl`s each of the
// configuration traits of pallets we want to use. // configuration traits of pallets we want to use.
@@ -739,11 +744,12 @@ mod tests {
pub const AvailableBlockRatio: Perbill = Perbill::one(); pub const AvailableBlockRatio: Perbill = Perbill::one();
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
type Hash = H256; type Hash = H256;
type Call = (); type Call = OuterCall;
type Hashing = BlakeTwo256; type Hashing = BlakeTwo256;
type AccountId = u64; type AccountId = u64;
type Lookup = IdentityLookup<Self::AccountId>; type Lookup = IdentityLookup<Self::AccountId>;
@@ -827,7 +833,7 @@ mod tests {
#[test] #[test]
fn signed_ext_watch_dummy_works() { fn signed_ext_watch_dummy_works() {
new_test_ext().execute_with(|| { new_test_ext().execute_with(|| {
let call = <Call<Test>>::set_dummy(10); let call = <Call<Test>>::set_dummy(10).into();
let info = DispatchInfo::default(); let info = DispatchInfo::default();
assert_eq!( assert_eq!(
+1
View File
@@ -545,6 +545,7 @@ mod tests {
}; };
} }
impl frame_system::Trait for Runtime { impl frame_system::Trait for Runtime {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type Call = Call; type Call = Call;
+2 -4
View File
@@ -252,6 +252,7 @@ mod tests {
pub const AvailableBlockRatio: Perbill = Perbill::one(); pub const AvailableBlockRatio: Perbill = Perbill::one();
} }
impl system::Trait for Test { impl system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
@@ -337,10 +338,7 @@ mod tests {
&Default::default(), &Default::default(),
Default::default(), Default::default(),
); );
assert_ok!(FinalityTracker::dispatch( assert_ok!(FinalityTracker::final_hint(Origin::none(), i - 1));
Call::final_hint(i-1),
Origin::NONE,
));
FinalityTracker::on_finalize(i); FinalityTracker::on_finalize(i);
let hdr = System::finalize(); let hdr = System::finalize();
parent_hash = hdr.hash(); parent_hash = hdr.hash();
+1
View File
@@ -1120,6 +1120,7 @@ impl<T: Subtrait> PartialEq for ElevatedTrait<T> {
} }
impl<T: Subtrait> Eq for ElevatedTrait<T> {} impl<T: Subtrait> Eq for ElevatedTrait<T> {}
impl<T: Subtrait> frame_system::Trait for ElevatedTrait<T> { impl<T: Subtrait> frame_system::Trait for ElevatedTrait<T> {
type BaseCallFilter = T::BaseCallFilter;
type Origin = T::Origin; type Origin = T::Origin;
type Call = T::Call; type Call = T::Call;
type Index = T::Index; type Index = T::Index;
@@ -46,6 +46,7 @@ parameter_types! {
pub const AvailableBlockRatio: Perbill = Perbill::one(); pub const AvailableBlockRatio: Perbill = Perbill::one();
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
+1 -1
View File
@@ -598,7 +598,7 @@ fn create_reserved_should_create_a_default_account_with_the_balance_given() {
let created_asset_id = 9; let created_asset_id = 9;
let created_account_id = 0; let created_account_id = 0;
assert_ok!(GenericAsset::create_reserved(Origin::ROOT, created_asset_id, options)); assert_ok!(GenericAsset::create_reserved(Origin::root(), created_asset_id, options));
// Tests for side effects. // Tests for side effects.
assert_eq!(<TotalIssuance<Test>>::get(created_asset_id), expected_total_issuance); assert_eq!(<TotalIssuance<Test>>::get(created_asset_id), expected_total_issuance);
+1
View File
@@ -94,6 +94,7 @@ parameter_types! {
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
+3 -3
View File
@@ -25,7 +25,7 @@ use codec::{Decode, Encode};
use fg_primitives::ScheduledChange; use fg_primitives::ScheduledChange;
use frame_support::{ use frame_support::{
assert_err, assert_ok, assert_err, assert_ok,
traits::{Currency, OnFinalize}, traits::{Currency, OnFinalize, UnfilteredDispatchable},
}; };
use frame_system::{EventRecord, Phase}; use frame_system::{EventRecord, Phase};
use sp_core::H256; use sp_core::H256;
@@ -376,7 +376,7 @@ fn report_equivocation_current_set_works() {
// report the equivocation and the tx should be dispatched successfully // report the equivocation and the tx should be dispatched successfully
let inner = report_equivocation(equivocation_proof, key_owner_proof).unwrap(); let inner = report_equivocation(equivocation_proof, key_owner_proof).unwrap();
assert_ok!(Grandpa::dispatch(inner, Origin::signed(1))); assert_ok!(inner.dispatch_bypass_filter(Origin::signed(1)));
start_era(2); start_era(2);
@@ -457,7 +457,7 @@ fn report_equivocation_old_set_works() {
// report the equivocation using the key ownership proof generated on // report the equivocation using the key ownership proof generated on
// the old set, the tx should be dispatched successfully // the old set, the tx should be dispatched successfully
let inner = report_equivocation(equivocation_proof, key_owner_proof).unwrap(); let inner = report_equivocation(equivocation_proof, key_owner_proof).unwrap();
assert_ok!(Grandpa::dispatch(inner, Origin::signed(1))); assert_ok!(inner.dispatch_bypass_filter(Origin::signed(1)));
start_era(3); start_era(3);
+1
View File
@@ -1174,6 +1174,7 @@ mod tests {
pub const AvailableBlockRatio: Perbill = Perbill::one(); pub const AvailableBlockRatio: Perbill = Perbill::one();
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
@@ -24,8 +24,9 @@ use super::*;
use frame_system::RawOrigin; use frame_system::RawOrigin;
use frame_benchmarking::benchmarks; use frame_benchmarking::benchmarks;
use sp_core::offchain::{OpaquePeerId, OpaqueMultiaddr}; use sp_core::offchain::{OpaquePeerId, OpaqueMultiaddr};
use sp_runtime::traits::{ValidateUnsigned, Zero, Dispatchable}; use sp_runtime::traits::{ValidateUnsigned, Zero};
use sp_runtime::transaction_validity::TransactionSource; use sp_runtime::transaction_validity::TransactionSource;
use frame_support::traits::UnfilteredDispatchable;
use crate::Module as ImOnline; use crate::Module as ImOnline;
@@ -85,7 +86,7 @@ benchmarks! {
let call = Call::heartbeat(input_heartbeat, signature); let call = Call::heartbeat(input_heartbeat, signature);
}: { }: {
ImOnline::<T>::validate_unsigned(TransactionSource::InBlock, &call)?; ImOnline::<T>::validate_unsigned(TransactionSource::InBlock, &call)?;
call.dispatch(RawOrigin::None.into())?; call.dispatch_bypass_filter(RawOrigin::None.into())?;
} }
} }
+1
View File
@@ -104,6 +104,7 @@ parameter_types! {
} }
impl frame_system::Trait for Runtime { impl frame_system::Trait for Runtime {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
+1 -1
View File
@@ -135,7 +135,7 @@ fn heartbeat(
e @ _ => <&'static str>::from(e), e @ _ => <&'static str>::from(e),
})?; })?;
ImOnline::heartbeat( ImOnline::heartbeat(
Origin::system(frame_system::RawOrigin::None), Origin::none(),
heartbeat, heartbeat,
signature, signature,
) )
+1
View File
@@ -50,6 +50,7 @@ parameter_types! {
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Call = (); type Call = ();
type Index = u64; type Index = u64;
+2 -2
View File
@@ -101,7 +101,7 @@ fn transfer_index_on_accounts_should_work() {
fn force_transfer_index_on_preowned_should_work() { fn force_transfer_index_on_preowned_should_work() {
new_test_ext().execute_with(|| { new_test_ext().execute_with(|| {
assert_ok!(Indices::claim(Some(1).into(), 0)); assert_ok!(Indices::claim(Some(1).into(), 0));
assert_ok!(Indices::force_transfer(Origin::ROOT, 3, 0, false)); assert_ok!(Indices::force_transfer(Origin::root(), 3, 0, false));
assert_eq!(Balances::reserved_balance(1), 0); assert_eq!(Balances::reserved_balance(1), 0);
assert_eq!(Balances::reserved_balance(3), 0); assert_eq!(Balances::reserved_balance(3), 0);
assert_eq!(Indices::lookup_index(0), Some(3)); assert_eq!(Indices::lookup_index(0), Some(3));
@@ -111,7 +111,7 @@ fn force_transfer_index_on_preowned_should_work() {
#[test] #[test]
fn force_transfer_index_on_free_should_work() { fn force_transfer_index_on_free_should_work() {
new_test_ext().execute_with(|| { new_test_ext().execute_with(|| {
assert_ok!(Indices::force_transfer(Origin::ROOT, 3, 0, false)); assert_ok!(Indices::force_transfer(Origin::root(), 3, 0, false));
assert_eq!(Balances::reserved_balance(3), 0); assert_eq!(Balances::reserved_balance(3), 0);
assert_eq!(Indices::lookup_index(0), Some(3)); assert_eq!(Indices::lookup_index(0), Some(3));
}); });
+1
View File
@@ -291,6 +291,7 @@ mod tests {
pub const AvailableBlockRatio: Perbill = Perbill::one(); pub const AvailableBlockRatio: Perbill = Perbill::one();
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
+2 -14
View File
@@ -50,7 +50,7 @@ use sp_std::prelude::*;
use codec::{Encode, Decode}; use codec::{Encode, Decode};
use sp_io::hashing::blake2_256; use sp_io::hashing::blake2_256;
use frame_support::{decl_module, decl_event, decl_error, decl_storage, Parameter, ensure, RuntimeDebug}; use frame_support::{decl_module, decl_event, decl_error, decl_storage, Parameter, ensure, RuntimeDebug};
use frame_support::{traits::{Get, ReservableCurrency, Currency, Filter, FilterStack, ClearFilterGuard}, use frame_support::{traits::{Get, ReservableCurrency, Currency},
weights::{Weight, GetDispatchInfo, DispatchClass, Pays}, weights::{Weight, GetDispatchInfo, DispatchClass, Pays},
dispatch::{DispatchResultWithPostInfo, DispatchErrorWithPostInfo, PostDispatchInfo}, dispatch::{DispatchResultWithPostInfo, DispatchErrorWithPostInfo, PostDispatchInfo},
}; };
@@ -87,9 +87,6 @@ pub trait Trait: frame_system::Trait {
/// The maximum amount of signatories allowed in the multisig. /// The maximum amount of signatories allowed in the multisig.
type MaxSignatories: Get<u16>; type MaxSignatories: Get<u16>;
/// Is a given call compatible with the proxying subsystem?
type IsCallable: FilterStack<<Self as Trait>::Call>;
} }
/// A global extrinsic index, formed as the extrinsic index within a block, together with that /// A global extrinsic index, formed as the extrinsic index within a block, together with that
@@ -151,8 +148,6 @@ decl_error! {
WrongTimepoint, WrongTimepoint,
/// A timepoint was given, yet no multisig operation is underway. /// A timepoint was given, yet no multisig operation is underway.
UnexpectedTimepoint, UnexpectedTimepoint,
/// A call with a `false` `IsCallable` filter was attempted.
Uncallable,
} }
} }
@@ -175,8 +170,6 @@ decl_event! {
/// A multisig operation has been cancelled. First param is the account that is /// A multisig operation has been cancelled. First param is the account that is
/// cancelling, third is the multisig account, fourth is hash of the call. /// cancelling, third is the multisig account, fourth is hash of the call.
MultisigCancelled(AccountId, Timepoint<BlockNumber>, AccountId, CallHash), MultisigCancelled(AccountId, Timepoint<BlockNumber>, AccountId, CallHash),
/// A call with a `false` IsCallable filter was attempted.
Uncallable(u32),
} }
} }
@@ -220,8 +213,7 @@ decl_module! {
/// Register approval for a dispatch to be made from a deterministic composite account if /// Register approval for a dispatch to be made from a deterministic composite account if
/// approved by a total of `threshold - 1` of `other_signatories`. /// approved by a total of `threshold - 1` of `other_signatories`.
/// ///
/// If there are enough, then dispatch the call. Calls must each fulfil the `IsCallable` /// If there are enough, then dispatch the call.
/// filter.
/// ///
/// Payment: `DepositBase` will be reserved if this is the first approval, plus /// Payment: `DepositBase` will be reserved if this is the first approval, plus
/// `threshold` times `DepositFactor`. It is returned once this dispatch happens or /// `threshold` times `DepositFactor`. It is returned once this dispatch happens or
@@ -280,10 +272,6 @@ decl_module! {
call: Box<<T as Trait>::Call>, call: Box<<T as Trait>::Call>,
) -> DispatchResultWithPostInfo { ) -> DispatchResultWithPostInfo {
let who = ensure_signed(origin)?; let who = ensure_signed(origin)?;
// We're now executing as a freshly authenticated new account, so the previous call
// restrictions no longer apply.
let _guard = ClearFilterGuard::<T::IsCallable, <T as Trait>::Call>::new();
ensure!(T::IsCallable::filter(call.as_ref()), Error::<T>::Uncallable);
ensure!(threshold >= 1, Error::<T>::ZeroThreshold); ensure!(threshold >= 1, Error::<T>::ZeroThreshold);
let max_sigs = T::MaxSignatories::get() as usize; let max_sigs = T::MaxSignatories::get() as usize;
ensure!(!other_signatories.is_empty(), Error::<T>::TooFewSignatories); ensure!(!other_signatories.is_empty(), Error::<T>::TooFewSignatories);
+6 -13
View File
@@ -23,7 +23,7 @@ use super::*;
use frame_support::{ use frame_support::{
assert_ok, assert_noop, impl_outer_origin, parameter_types, impl_outer_dispatch, assert_ok, assert_noop, impl_outer_origin, parameter_types, impl_outer_dispatch,
weights::Weight, impl_outer_event weights::Weight, impl_outer_event, traits::Filter,
}; };
use sp_core::H256; use sp_core::H256;
use sp_runtime::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header}; use sp_runtime::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header};
@@ -60,6 +60,7 @@ parameter_types! {
pub const AvailableBlockRatio: Perbill = Perbill::one(); pub const AvailableBlockRatio: Perbill = Perbill::one();
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = TestBaseCallFilter;
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
@@ -99,8 +100,8 @@ parameter_types! {
pub const DepositFactor: u64 = 1; pub const DepositFactor: u64 = 1;
pub const MaxSignatories: u16 = 3; pub const MaxSignatories: u16 = 3;
} }
pub struct TestIsCallable; pub struct TestBaseCallFilter;
impl Filter<Call> for TestIsCallable { impl Filter<Call> for TestBaseCallFilter {
fn filter(c: &Call) -> bool { fn filter(c: &Call) -> bool {
match *c { match *c {
Call::Balances(_) => true, Call::Balances(_) => true,
@@ -110,13 +111,6 @@ impl Filter<Call> for TestIsCallable {
} }
} }
} }
impl FilterStack<Call> for TestIsCallable {
type Stack = ();
fn push(_: impl Fn(&Call) -> bool + 'static) {}
fn pop() {}
fn take() -> Self::Stack { () }
fn restore(_: Self::Stack) {}
}
impl Trait for Test { impl Trait for Test {
type Event = TestEvent; type Event = TestEvent;
type Call = Call; type Call = Call;
@@ -124,7 +118,6 @@ impl Trait for Test {
type DepositBase = DepositBase; type DepositBase = DepositBase;
type DepositFactor = DepositFactor; type DepositFactor = DepositFactor;
type MaxSignatories = MaxSignatories; type MaxSignatories = MaxSignatories;
type IsCallable = TestIsCallable;
} }
type System = frame_system::Module<Test>; type System = frame_system::Module<Test>;
type Balances = pallet_balances::Module<Test>; type Balances = pallet_balances::Module<Test>;
@@ -403,8 +396,8 @@ fn multisig_filters() {
new_test_ext().execute_with(|| { new_test_ext().execute_with(|| {
let call = Box::new(Call::System(frame_system::Call::set_code(vec![]))); let call = Box::new(Call::System(frame_system::Call::set_code(vec![])));
assert_noop!( assert_noop!(
Multisig::as_multi(Origin::signed(1), 1, vec![], None, call.clone()), Multisig::as_multi(Origin::signed(1), 1, vec![2], None, call.clone()),
Error::<Test>::Uncallable, DispatchError::BadOrigin,
); );
}); });
} }
+1
View File
@@ -266,6 +266,7 @@ mod tests {
pub const AvailableBlockRatio: Perbill = Perbill::one(); pub const AvailableBlockRatio: Perbill = Perbill::one();
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
@@ -42,6 +42,7 @@ parameter_types! {
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = AccountIndex; type Index = AccountIndex;
type BlockNumber = BlockNumber; type BlockNumber = BlockNumber;
+1
View File
@@ -96,6 +96,7 @@ parameter_types! {
pub const AvailableBlockRatio: Perbill = Perbill::one(); pub const AvailableBlockRatio: Perbill = Perbill::one();
} }
impl frame_system::Trait for Runtime { impl frame_system::Trait for Runtime {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
+12 -18
View File
@@ -41,8 +41,8 @@ use sp_runtime::{DispatchResult, traits::{Dispatchable, Zero}};
use sp_runtime::traits::Member; use sp_runtime::traits::Member;
use frame_support::{ use frame_support::{
decl_module, decl_event, decl_error, decl_storage, Parameter, ensure, traits::{ decl_module, decl_event, decl_error, decl_storage, Parameter, ensure, traits::{
Get, ReservableCurrency, Currency, Filter, FilterStack, FilterStackGuard, Get, ReservableCurrency, Currency, InstanceFilter,
ClearFilterGuard, InstanceFilter OriginTrait, IsType,
}, weights::{GetDispatchInfo, constants::{WEIGHT_PER_MICROS, WEIGHT_PER_NANOS}}, }, weights::{GetDispatchInfo, constants::{WEIGHT_PER_MICROS, WEIGHT_PER_NANOS}},
dispatch::{PostDispatchInfo, IsSubType}, dispatch::{PostDispatchInfo, IsSubType},
}; };
@@ -60,14 +60,12 @@ pub trait Trait: frame_system::Trait {
/// The overarching call type. /// The overarching call type.
type Call: Parameter + Dispatchable<Origin=Self::Origin, PostInfo=PostDispatchInfo> type Call: Parameter + Dispatchable<Origin=Self::Origin, PostInfo=PostDispatchInfo>
+ GetDispatchInfo + From<frame_system::Call<Self>> + IsSubType<Module<Self>, Self>; + GetDispatchInfo + From<frame_system::Call<Self>> + IsSubType<Module<Self>, Self>
+ IsType<<Self as frame_system::Trait>::Call>;
/// The currency mechanism. /// The currency mechanism.
type Currency: ReservableCurrency<Self::AccountId>; type Currency: ReservableCurrency<Self::AccountId>;
/// Is a given call compatible with the proxying subsystem?
type IsCallable: FilterStack<<Self as Trait>::Call>;
/// A kind of proxy; specified with the proxy and passed in to the `IsProxyable` fitler. /// A kind of proxy; specified with the proxy and passed in to the `IsProxyable` fitler.
/// The instance filter determines whether a given call may be proxied under this type. /// The instance filter determines whether a given call may be proxied under this type.
type ProxyType: Parameter + Member + Ord + PartialOrd + InstanceFilter<<Self as Trait>::Call> type ProxyType: Parameter + Member + Ord + PartialOrd + InstanceFilter<<Self as Trait>::Call>
@@ -105,8 +103,6 @@ decl_error! {
NotFound, NotFound,
/// Sender is not a proxy of the account to be proxied. /// Sender is not a proxy of the account to be proxied.
NotProxy, NotProxy,
/// A call with a `false` `IsCallable` filter was attempted.
Uncallable,
/// A call which is incompatible with the proxy type's filter was attempted. /// A call which is incompatible with the proxy type's filter was attempted.
Unproxyable, Unproxyable,
/// Account is already a proxy. /// Account is already a proxy.
@@ -171,19 +167,17 @@ decl_module! {
.find(|x| &x.0 == &who && force_proxy_type.as_ref().map_or(true, |y| &x.1 == y)) .find(|x| &x.0 == &who && force_proxy_type.as_ref().map_or(true, |y| &x.1 == y))
.ok_or(Error::<T>::NotProxy)?; .ok_or(Error::<T>::NotProxy)?;
// We're now executing as a freshly authenticated new account, so the previous call // This is a freshly authenticated new account, the origin restrictions doesn't apply.
// restrictions no longer apply. let mut origin: T::Origin = frame_system::RawOrigin::Signed(real).into();
let _clear_guard = ClearFilterGuard::<T::IsCallable, <T as Trait>::Call>::new(); origin.add_filter(move |c: &<T as frame_system::Trait>::Call| {
let _filter_guard = FilterStackGuard::<T::IsCallable, <T as Trait>::Call>::new( let c = <T as Trait>::Call::from_ref(c);
move |c| match c.is_sub_type() { match c.is_sub_type() {
Some(Call::add_proxy(_, ref pt)) | Some(Call::remove_proxy(_, ref pt)) Some(Call::add_proxy(_, ref pt)) | Some(Call::remove_proxy(_, ref pt))
if !proxy_type.is_superset(&pt) => false, if !proxy_type.is_superset(&pt) => false,
_ => proxy_type.filter(&c) _ => proxy_type.filter(c)
} }
); });
ensure!(T::IsCallable::filter(&call), Error::<T>::Uncallable); let e = call.dispatch(origin);
let e = call.dispatch(frame_system::RawOrigin::Signed(real).into());
Self::deposit_event(RawEvent::ProxyExecuted(e.map(|_| ()).map_err(|e| e.error))); Self::deposit_event(RawEvent::ProxyExecuted(e.map(|_| ()).map_err(|e| e.error)));
} }
+25 -17
View File
@@ -23,7 +23,7 @@ use super::*;
use frame_support::{ use frame_support::{
assert_ok, assert_noop, impl_outer_origin, parameter_types, impl_outer_dispatch, assert_ok, assert_noop, impl_outer_origin, parameter_types, impl_outer_dispatch,
impl_filter_stack, weights::Weight, impl_outer_event, RuntimeDebug, dispatch::DispatchError weights::Weight, impl_outer_event, RuntimeDebug, dispatch::DispatchError, traits::Filter,
}; };
use codec::{Encode, Decode}; use codec::{Encode, Decode};
use sp_core::H256; use sp_core::H256;
@@ -62,6 +62,7 @@ parameter_types! {
pub const AvailableBlockRatio: Perbill = Perbill::one(); pub const AvailableBlockRatio: Perbill = Perbill::one();
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = BaseFilter;
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
@@ -99,15 +100,12 @@ impl pallet_balances::Trait for Test {
impl pallet_utility::Trait for Test { impl pallet_utility::Trait for Test {
type Event = TestEvent; type Event = TestEvent;
type Call = Call; type Call = Call;
type IsCallable = IsCallable;
} }
parameter_types! { parameter_types! {
pub const ProxyDepositBase: u64 = 1; pub const ProxyDepositBase: u64 = 1;
pub const ProxyDepositFactor: u64 = 1; pub const ProxyDepositFactor: u64 = 1;
pub const MaxProxies: u16 = 4; pub const MaxProxies: u16 = 4;
} }
pub struct IsCallable;
impl_filter_stack!(crate::tests::IsCallable, crate::tests::BaseFilter, crate::tests::Call, is_callable);
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug)] #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug)]
pub enum ProxyType { pub enum ProxyType {
Any, Any,
@@ -142,7 +140,6 @@ impl Trait for Test {
type Event = TestEvent; type Event = TestEvent;
type Call = Call; type Call = Call;
type Currency = Balances; type Currency = Balances;
type IsCallable = IsCallable;
type ProxyType = ProxyType; type ProxyType = ProxyType;
type ProxyDepositBase = ProxyDepositBase; type ProxyDepositBase = ProxyDepositBase;
type ProxyDepositFactor = ProxyDepositFactor; type ProxyDepositFactor = ProxyDepositFactor;
@@ -158,7 +155,6 @@ use frame_system::Call as SystemCall;
use pallet_balances::Call as BalancesCall; use pallet_balances::Call as BalancesCall;
use pallet_balances::Error as BalancesError; use pallet_balances::Error as BalancesError;
use pallet_utility::Call as UtilityCall; use pallet_utility::Call as UtilityCall;
use pallet_utility::Error as UtilityError;
use pallet_utility::Event as UtilityEvent; use pallet_utility::Event as UtilityEvent;
use super::Call as ProxyCall; use super::Call as ProxyCall;
@@ -201,7 +197,8 @@ fn filtering_works() {
expect_event(RawEvent::ProxyExecuted(Ok(()))); expect_event(RawEvent::ProxyExecuted(Ok(())));
assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone())); assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()));
expect_event(RawEvent::ProxyExecuted(Ok(()))); expect_event(RawEvent::ProxyExecuted(Ok(())));
assert_noop!(Proxy::proxy(Origin::signed(4), 1, None, call.clone()), Error::<Test>::Uncallable); assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone()));
expect_event(RawEvent::ProxyExecuted(Err(DispatchError::BadOrigin)));
let sub_id = Utility::sub_account_id(1, 0); let sub_id = Utility::sub_account_id(1, 0);
Balances::mutate_account(&sub_id, |a| a.free = 1000); Balances::mutate_account(&sub_id, |a| a.free = 1000);
@@ -210,32 +207,41 @@ fn filtering_works() {
let call = Box::new(Call::Utility(UtilityCall::as_sub(0, inner.clone()))); let call = Box::new(Call::Utility(UtilityCall::as_sub(0, inner.clone())));
assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone())); assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone()));
expect_event(RawEvent::ProxyExecuted(Ok(()))); expect_event(RawEvent::ProxyExecuted(Ok(())));
assert_noop!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()), Error::<Test>::Uncallable); assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()));
expect_event(RawEvent::ProxyExecuted(Err(DispatchError::BadOrigin)));
assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone())); assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone()));
expect_event(RawEvent::ProxyExecuted(Ok(()))); expect_event(RawEvent::ProxyExecuted(Ok(())));
let call = Box::new(Call::Utility(UtilityCall::as_limited_sub(0, inner.clone()))); let call = Box::new(Call::Utility(UtilityCall::as_limited_sub(0, inner.clone())));
assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone())); assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone()));
expect_event(RawEvent::ProxyExecuted(Ok(()))); expect_event(RawEvent::ProxyExecuted(Ok(())));
assert_noop!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()), Error::<Test>::Uncallable); assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()));
expect_event(RawEvent::ProxyExecuted(Err(DispatchError::BadOrigin)));
assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone())); assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone()));
let de = DispatchError::from(UtilityError::<Test>::Uncallable).stripped(); expect_event(RawEvent::ProxyExecuted(Err(DispatchError::BadOrigin)));
expect_event(RawEvent::ProxyExecuted(Err(de)));
let call = Box::new(Call::Utility(UtilityCall::batch(vec![*inner]))); let call = Box::new(Call::Utility(UtilityCall::batch(vec![*inner])));
assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone())); assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone()));
expect_events(vec![UtilityEvent::BatchCompleted.into(), RawEvent::ProxyExecuted(Ok(())).into()]); expect_events(vec![UtilityEvent::BatchCompleted.into(), RawEvent::ProxyExecuted(Ok(())).into()]);
assert_noop!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()), Error::<Test>::Uncallable); assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()));
expect_event(RawEvent::ProxyExecuted(Err(DispatchError::BadOrigin)));
assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone())); assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone()));
expect_events(vec![UtilityEvent::Uncallable(0).into(), RawEvent::ProxyExecuted(Ok(())).into()]); expect_events(vec![
UtilityEvent::BatchInterrupted(0, DispatchError::BadOrigin).into(),
RawEvent::ProxyExecuted(Ok(())).into(),
]);
let inner = Box::new(Call::Proxy(ProxyCall::add_proxy(5, ProxyType::Any))); let inner = Box::new(Call::Proxy(ProxyCall::add_proxy(5, ProxyType::Any)));
let call = Box::new(Call::Utility(UtilityCall::batch(vec![*inner]))); let call = Box::new(Call::Utility(UtilityCall::batch(vec![*inner])));
assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone())); assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone()));
expect_events(vec![UtilityEvent::BatchCompleted.into(), RawEvent::ProxyExecuted(Ok(())).into()]); expect_events(vec![UtilityEvent::BatchCompleted.into(), RawEvent::ProxyExecuted(Ok(())).into()]);
assert_noop!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()), Error::<Test>::Uncallable); assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()));
expect_event(RawEvent::ProxyExecuted(Err(DispatchError::BadOrigin)));
assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone())); assert_ok!(Proxy::proxy(Origin::signed(4), 1, None, call.clone()));
expect_events(vec![UtilityEvent::Uncallable(0).into(), RawEvent::ProxyExecuted(Ok(())).into()]); expect_events(vec![
UtilityEvent::BatchInterrupted(0, DispatchError::BadOrigin).into(),
RawEvent::ProxyExecuted(Ok(())).into(),
]);
}); });
} }
@@ -293,10 +299,12 @@ fn proxying_works() {
assert_eq!(Balances::free_balance(6), 1); assert_eq!(Balances::free_balance(6), 1);
let call = Box::new(Call::System(SystemCall::set_code(vec![]))); let call = Box::new(Call::System(SystemCall::set_code(vec![])));
assert_noop!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()), Error::<Test>::Uncallable); assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()));
expect_event(RawEvent::ProxyExecuted(Err(DispatchError::BadOrigin)));
let call = Box::new(Call::Balances(BalancesCall::transfer_keep_alive(6, 1))); let call = Box::new(Call::Balances(BalancesCall::transfer_keep_alive(6, 1)));
assert_noop!(Proxy::proxy(Origin::signed(2), 1, None, call.clone()), Error::<Test>::Uncallable); assert_ok!(Call::Proxy(super::Call::proxy(1, None, call.clone())).dispatch(Origin::signed(2)));
expect_event(RawEvent::ProxyExecuted(Err(DispatchError::BadOrigin)));
assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone())); assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()));
expect_event(RawEvent::ProxyExecuted(Ok(()))); expect_event(RawEvent::ProxyExecuted(Ok(())));
assert_eq!(Balances::free_balance(6), 2); assert_eq!(Balances::free_balance(6), 2);
@@ -158,6 +158,7 @@ mod tests {
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
+1
View File
@@ -64,6 +64,7 @@ parameter_types! {
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Call = Call; type Call = Call;
type Index = u64; type Index = u64;
+1 -1
View File
@@ -46,7 +46,7 @@ fn set_recovered_works() {
// Not accessible by a normal user // Not accessible by a normal user
assert_noop!(Recovery::set_recovered(Origin::signed(1), 5, 1), BadOrigin); assert_noop!(Recovery::set_recovered(Origin::signed(1), 5, 1), BadOrigin);
// Root can set a recovered account though // Root can set a recovered account though
assert_ok!(Recovery::set_recovered(Origin::ROOT, 5, 1)); assert_ok!(Recovery::set_recovered(Origin::root(), 5, 1));
// Account 1 should now be able to make a call through account 5 // Account 1 should now be able to make a call through account 5
let call = Box::new(Call::Balances(BalancesCall::transfer(1, 100))); let call = Box::new(Call::Balances(BalancesCall::transfer(1, 100)));
assert_ok!(Recovery::as_recovered(Origin::signed(1), 5, call)); assert_ok!(Recovery::as_recovered(Origin::signed(1), 5, call));
+6 -5
View File
@@ -481,8 +481,9 @@ mod tests {
pub const AvailableBlockRatio: Perbill = Perbill::one(); pub const AvailableBlockRatio: Perbill = Perbill::one();
} }
impl system::Trait for Test { impl system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Call = (); type Call = Call;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
type Hash = H256; type Hash = H256;
@@ -702,14 +703,14 @@ mod tests {
new_test_ext().execute_with(|| { new_test_ext().execute_with(|| {
let call = Box::new(Call::Logger(logger::Call::log(69, 1000))); let call = Box::new(Call::Logger(logger::Call::log(69, 1000)));
let call2 = Box::new(Call::Logger(logger::Call::log(42, 1000))); let call2 = Box::new(Call::Logger(logger::Call::log(42, 1000)));
assert_ok!(Scheduler::schedule_named(Origin::ROOT, 1u32.encode(), 4, None, 127, call)); assert_ok!(Scheduler::schedule_named(Origin::root(), 1u32.encode(), 4, None, 127, call));
assert_ok!(Scheduler::schedule(Origin::ROOT, 4, None, 127, call2)); assert_ok!(Scheduler::schedule(Origin::root(), 4, None, 127, call2));
run_to_block(3); run_to_block(3);
// Scheduled calls are in the agenda. // Scheduled calls are in the agenda.
assert_eq!(Agenda::<Test>::get(4).len(), 2); assert_eq!(Agenda::<Test>::get(4).len(), 2);
assert!(logger::log().is_empty()); assert!(logger::log().is_empty());
assert_ok!(Scheduler::cancel_named(Origin::ROOT, 1u32.encode())); assert_ok!(Scheduler::cancel_named(Origin::root(), 1u32.encode()));
assert_ok!(Scheduler::cancel(Origin::ROOT, 4, 1)); assert_ok!(Scheduler::cancel(Origin::root(), 4, 1));
// Scheduled calls are made NONE, so should not effect state // Scheduled calls are made NONE, so should not effect state
run_to_block(100); run_to_block(100);
assert!(logger::log().is_empty()); assert!(logger::log().is_empty());
+1
View File
@@ -55,6 +55,7 @@ ord_parameter_types! {
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
@@ -58,6 +58,7 @@ impl Convert<u128, u64> for CurrencyToVoteHandler {
pub struct Test; pub struct Test;
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = AccountIndex; type Index = AccountIndex;
type BlockNumber = BlockNumber; type BlockNumber = BlockNumber;
+1
View File
@@ -173,6 +173,7 @@ parameter_types! {
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
+1
View File
@@ -65,6 +65,7 @@ ord_parameter_types! {
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
+1 -1
View File
@@ -813,7 +813,7 @@ fn max_limits_work() {
// No candidates because full // No candidates because full
assert_eq!(Society::candidates().len(), 0); assert_eq!(Society::candidates().len(), 0);
// Increase member limit // Increase member limit
assert_ok!(Society::set_max_members(Origin::ROOT, 200)); assert_ok!(Society::set_max_members(Origin::root(), 200));
// Rotate period // Rotate period
run_to_block(16); run_to_block(16);
// Candidates are back! // Candidates are back!
@@ -57,6 +57,7 @@ impl Convert<u128, u64> for CurrencyToVoteHandler {
pub struct Test; pub struct Test;
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type DbWeight = (); type DbWeight = ();
type BlockExecutionWeight = (); type BlockExecutionWeight = ();
@@ -23,9 +23,9 @@ use honggfuzz::fuzz;
use mock::Test; use mock::Test;
use pallet_staking::testing_utils::*; use pallet_staking::testing_utils::*;
use frame_support::{assert_ok, storage::StorageValue}; use frame_support::{assert_ok, storage::StorageValue, traits::UnfilteredDispatchable};
use frame_system::RawOrigin; use frame_system::RawOrigin;
use sp_runtime::{traits::Dispatchable, DispatchError}; use sp_runtime::DispatchError;
use sp_core::offchain::{testing::TestOffchainExt, OffchainExt}; use sp_core::offchain::{testing::TestOffchainExt, OffchainExt};
use pallet_staking::{EraElectionStatus, ElectionStatus, Module as Staking, Call as StakingCall}; use pallet_staking::{EraElectionStatus, ElectionStatus, Module as Staking, Call as StakingCall};
@@ -159,7 +159,7 @@ fn main() {
match mode { match mode {
Mode::WeakerSubmission => { Mode::WeakerSubmission => {
assert_eq!( assert_eq!(
call.dispatch(origin.clone().into()).unwrap_err().error, call.dispatch_bypass_filter(origin.clone().into()).unwrap_err().error,
DispatchError::Module { DispatchError::Module {
index: 0, index: 0,
error: 16, error: 16,
@@ -170,7 +170,7 @@ fn main() {
// NOTE: so exhaustive pattern doesn't work here.. maybe some rust issue? // NOTE: so exhaustive pattern doesn't work here.. maybe some rust issue?
// or due to `#[repr(u32)]`? // or due to `#[repr(u32)]`?
Mode::InitialSubmission | Mode::StrongerSubmission => { Mode::InitialSubmission | Mode::StrongerSubmission => {
assert_ok!(call.dispatch(origin.into())); assert_ok!(call.dispatch_bypass_filter(origin.into()));
} }
}; };
}) })
+5 -5
View File
@@ -21,7 +21,7 @@ use super::*;
use crate::Module as Staking; use crate::Module as Staking;
use testing_utils::*; use testing_utils::*;
use sp_runtime::{traits::{Dispatchable, One}}; use sp_runtime::traits::One;
use frame_system::RawOrigin; use frame_system::RawOrigin;
pub use frame_benchmarking::{benchmarks, account}; pub use frame_benchmarking::{benchmarks, account};
const SEED: u32 = 0; const SEED: u32 = 0;
@@ -379,12 +379,12 @@ benchmarks! {
let current_era = CurrentEra::get().unwrap(); let current_era = CurrentEra::get().unwrap();
let mut points_total = 0; let mut points_total = 0;
let mut points_individual = Vec::new(); let mut points_individual = Vec::new();
let mut payout_calls = Vec::new(); let mut payout_calls_arg = Vec::new();
for validator in new_validators.iter() { for validator in new_validators.iter() {
points_total += 10; points_total += 10;
points_individual.push((validator.clone(), 10)); points_individual.push((validator.clone(), 10));
payout_calls.push(Call::<T>::payout_stakers(validator.clone(), current_era)) payout_calls_arg.push((validator.clone(), current_era));
} }
// Give Era Points // Give Era Points
@@ -401,8 +401,8 @@ benchmarks! {
let caller: T::AccountId = account("caller", 0, SEED); let caller: T::AccountId = account("caller", 0, SEED);
}: { }: {
for call in payout_calls { for arg in payout_calls_arg {
call.dispatch(RawOrigin::Signed(caller.clone()).into())?; <Staking<T>>::payout_stakers(RawOrigin::Signed(caller.clone()).into(), arg.0, arg.1)?;
} }
} }
+1
View File
@@ -200,6 +200,7 @@ parameter_types! {
pub const AvailableBlockRatio: Perbill = Perbill::one(); pub const AvailableBlockRatio: Perbill = Perbill::one();
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = AccountIndex; type Index = AccountIndex;
type BlockNumber = BlockNumber; type BlockNumber = BlockNumber;
+16 -16
View File
@@ -47,7 +47,7 @@ fn force_unstake_works() {
// Force unstake needs correct number of slashing spans (for weight calculation) // Force unstake needs correct number of slashing spans (for weight calculation)
assert_noop!(Staking::force_unstake(Origin::signed(11), 11, 0), BadOrigin); assert_noop!(Staking::force_unstake(Origin::signed(11), 11, 0), BadOrigin);
// We now force them to unstake // We now force them to unstake
assert_ok!(Staking::force_unstake(Origin::ROOT, 11, 2)); assert_ok!(Staking::force_unstake(Origin::root(), 11, 2));
// No longer bonded. // No longer bonded.
assert_eq!(Staking::bonded(&11), None); assert_eq!(Staking::bonded(&11), None);
// Transfer works. // Transfer works.
@@ -1477,7 +1477,7 @@ fn on_free_balance_zero_stash_removes_validator() {
assert_eq!(Balances::total_balance(&11), 0); assert_eq!(Balances::total_balance(&11), 0);
// Reap the stash // Reap the stash
assert_ok!(Staking::reap_stash(Origin::NONE, 11, 0)); assert_ok!(Staking::reap_stash(Origin::none(), 11, 0));
// Check storage items do not exist // Check storage items do not exist
assert!(!<Ledger<Test>>::contains_key(&10)); assert!(!<Ledger<Test>>::contains_key(&10));
@@ -1533,7 +1533,7 @@ fn on_free_balance_zero_stash_removes_nominator() {
assert_eq!(Balances::total_balance(&11), 0); assert_eq!(Balances::total_balance(&11), 0);
// Reap the stash // Reap the stash
assert_ok!(Staking::reap_stash(Origin::NONE, 11, 0)); assert_ok!(Staking::reap_stash(Origin::none(), 11, 0));
// Check storage items do not exist // Check storage items do not exist
assert!(!<Ledger<Test>>::contains_key(&10)); assert!(!<Ledger<Test>>::contains_key(&10));
@@ -1928,7 +1928,7 @@ fn offence_forces_new_era() {
#[test] #[test]
fn offence_ensures_new_era_without_clobbering() { fn offence_ensures_new_era_without_clobbering() {
ExtBuilder::default().build_and_execute(|| { ExtBuilder::default().build_and_execute(|| {
assert_ok!(Staking::force_new_era_always(Origin::ROOT)); assert_ok!(Staking::force_new_era_always(Origin::root()));
assert_eq!(Staking::force_era(), Forcing::ForceAlways); assert_eq!(Staking::force_era(), Forcing::ForceAlways);
on_offence_now( on_offence_now(
@@ -2302,8 +2302,8 @@ fn garbage_collection_after_slashing() {
assert_eq!(slashing_spans.iter().count(), 2); assert_eq!(slashing_spans.iter().count(), 2);
// reap_stash respects num_slashing_spans so that weight is accurate // reap_stash respects num_slashing_spans so that weight is accurate
assert_noop!(Staking::reap_stash(Origin::NONE, 11, 0), Error::<Test>::IncorrectSlashingSpans); assert_noop!(Staking::reap_stash(Origin::none(), 11, 0), Error::<Test>::IncorrectSlashingSpans);
assert_ok!(Staking::reap_stash(Origin::NONE, 11, 2)); assert_ok!(Staking::reap_stash(Origin::none(), 11, 2));
assert!(<Staking as crate::Store>::SlashingSpans::get(&11).is_none()); assert!(<Staking as crate::Store>::SlashingSpans::get(&11).is_none());
assert_eq!(<Staking as crate::Store>::SpanSlash::get(&(11, 0)).amount_slashed(), &0); assert_eq!(<Staking as crate::Store>::SpanSlash::get(&(11, 0)).amount_slashed(), &0);
@@ -2591,11 +2591,11 @@ fn remove_deferred() {
// fails if empty // fails if empty
assert_noop!( assert_noop!(
Staking::cancel_deferred_slash(Origin::ROOT, 1, vec![]), Staking::cancel_deferred_slash(Origin::root(), 1, vec![]),
Error::<Test>::EmptyTargets Error::<Test>::EmptyTargets
); );
assert_ok!(Staking::cancel_deferred_slash(Origin::ROOT, 1, vec![0])); assert_ok!(Staking::cancel_deferred_slash(Origin::root(), 1, vec![0]));
assert_eq!(Balances::free_balance(11), 1000); assert_eq!(Balances::free_balance(11), 1000);
assert_eq!(Balances::free_balance(101), 2000); assert_eq!(Balances::free_balance(101), 2000);
@@ -2692,21 +2692,21 @@ fn remove_multi_deferred() {
// fails if list is not sorted // fails if list is not sorted
assert_noop!( assert_noop!(
Staking::cancel_deferred_slash(Origin::ROOT, 1, vec![2, 0, 4]), Staking::cancel_deferred_slash(Origin::root(), 1, vec![2, 0, 4]),
Error::<Test>::NotSortedAndUnique Error::<Test>::NotSortedAndUnique
); );
// fails if list is not unique // fails if list is not unique
assert_noop!( assert_noop!(
Staking::cancel_deferred_slash(Origin::ROOT, 1, vec![0, 2, 2]), Staking::cancel_deferred_slash(Origin::root(), 1, vec![0, 2, 2]),
Error::<Test>::NotSortedAndUnique Error::<Test>::NotSortedAndUnique
); );
// fails if bad index // fails if bad index
assert_noop!( assert_noop!(
Staking::cancel_deferred_slash(Origin::ROOT, 1, vec![1, 2, 3, 4, 5]), Staking::cancel_deferred_slash(Origin::root(), 1, vec![1, 2, 3, 4, 5]),
Error::<Test>::InvalidSlashIndex Error::<Test>::InvalidSlashIndex
); );
assert_ok!(Staking::cancel_deferred_slash(Origin::ROOT, 1, vec![0, 2, 4])); assert_ok!(Staking::cancel_deferred_slash(Origin::root(), 1, vec![0, 2, 4]));
let slashes = <Staking as Store>::UnappliedSlashes::get(&1); let slashes = <Staking as Store>::UnappliedSlashes::get(&1);
assert_eq!(slashes.len(), 2); assert_eq!(slashes.len(), 2);
@@ -4243,16 +4243,16 @@ fn test_max_nominator_rewarded_per_validator_and_cant_steal_someone_else_reward(
fn set_history_depth_works() { fn set_history_depth_works() {
ExtBuilder::default().build_and_execute(|| { ExtBuilder::default().build_and_execute(|| {
mock::start_era(10); mock::start_era(10);
Staking::set_history_depth(Origin::ROOT, 20, 0).unwrap(); Staking::set_history_depth(Origin::root(), 20, 0).unwrap();
assert!(<Staking as Store>::ErasTotalStake::contains_key(10 - 4)); assert!(<Staking as Store>::ErasTotalStake::contains_key(10 - 4));
assert!(<Staking as Store>::ErasTotalStake::contains_key(10 - 5)); assert!(<Staking as Store>::ErasTotalStake::contains_key(10 - 5));
Staking::set_history_depth(Origin::ROOT, 4, 0).unwrap(); Staking::set_history_depth(Origin::root(), 4, 0).unwrap();
assert!(<Staking as Store>::ErasTotalStake::contains_key(10 - 4)); assert!(<Staking as Store>::ErasTotalStake::contains_key(10 - 4));
assert!(!<Staking as Store>::ErasTotalStake::contains_key(10 - 5)); assert!(!<Staking as Store>::ErasTotalStake::contains_key(10 - 5));
Staking::set_history_depth(Origin::ROOT, 3, 0).unwrap(); Staking::set_history_depth(Origin::root(), 3, 0).unwrap();
assert!(!<Staking as Store>::ErasTotalStake::contains_key(10 - 4)); assert!(!<Staking as Store>::ErasTotalStake::contains_key(10 - 4));
assert!(!<Staking as Store>::ErasTotalStake::contains_key(10 - 5)); assert!(!<Staking as Store>::ErasTotalStake::contains_key(10 - 5));
Staking::set_history_depth(Origin::ROOT, 8, 0).unwrap(); Staking::set_history_depth(Origin::root(), 8, 0).unwrap();
assert!(!<Staking as Store>::ErasTotalStake::contains_key(10 - 4)); assert!(!<Staking as Store>::ErasTotalStake::contains_key(10 - 4));
assert!(!<Staking as Store>::ErasTotalStake::contains_key(10 - 5)); assert!(!<Staking as Store>::ErasTotalStake::contains_key(10 - 5));
}); });
+1
View File
@@ -113,6 +113,7 @@ parameter_types! {
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Call = Call; type Call = Call;
type Index = u64; type Index = u64;
+52 -30
View File
@@ -29,7 +29,7 @@ pub use crate::weights::{
PaysFee, PostDispatchInfo, WithPostDispatchInfo, PaysFee, PostDispatchInfo, WithPostDispatchInfo,
}; };
pub use sp_runtime::{traits::Dispatchable, DispatchError}; pub use sp_runtime::{traits::Dispatchable, DispatchError};
pub use crate::traits::{CallMetadata, GetCallMetadata, GetCallName}; pub use crate::traits::{CallMetadata, GetCallMetadata, GetCallName, UnfilteredDispatchable};
/// The return typ of a `Dispatchable` in frame. When returned explicitly from /// The return typ of a `Dispatchable` in frame. When returned explicitly from
/// a dispatchable function it allows overriding the default `PostDispatchInfo` /// a dispatchable function it allows overriding the default `PostDispatchInfo`
@@ -47,10 +47,9 @@ pub type DispatchResult = Result<(), sp_runtime::DispatchError>;
pub type DispatchErrorWithPostInfo = pub type DispatchErrorWithPostInfo =
sp_runtime::DispatchErrorWithPostInfo<crate::weights::PostDispatchInfo>; sp_runtime::DispatchErrorWithPostInfo<crate::weights::PostDispatchInfo>;
/// Serializable version of Dispatchable. /// Serializable version of pallet dispatchable.
/// This value can be used as a "function" in an extrinsic.
pub trait Callable<T> { pub trait Callable<T> {
type Call: Dispatchable<Info=DispatchInfo, PostInfo=PostDispatchInfo> + Codec + Clone + PartialEq + Eq; type Call: UnfilteredDispatchable + Codec + Clone + PartialEq + Eq;
} }
// dirty hack to work around serde_derive issue // dirty hack to work around serde_derive issue
@@ -1005,6 +1004,7 @@ macro_rules! decl_module {
impl<$trait_instance: $trait_name$(<I>, $instance: $instantiable)?> $module<$trait_instance $(, $instance)?> impl<$trait_instance: $trait_name$(<I>, $instance: $instantiable)?> $module<$trait_instance $(, $instance)?>
where $( $other_where_bounds )* where $( $other_where_bounds )*
{ {
/// Deposits an event using `frame_system::Module::deposit_event`.
$vis fn deposit_event( $vis fn deposit_event(
event: impl Into<< $trait_instance as $trait_name $(<$instance>)? >::Event> event: impl Into<< $trait_instance as $trait_name $(<$instance>)? >::Event>
) { ) {
@@ -1402,6 +1402,8 @@ macro_rules! decl_module {
$error_type; $error_type;
$from; $from;
$(#[doc = $doc_attr])* $(#[doc = $doc_attr])*
///
/// NOTE: Calling this function will bypass origin filters.
$fn_vis fn $fn_name ( $fn_vis fn $fn_name (
$from $(, $param_name : $param )* $from $(, $param_name : $param )*
) $( -> $result )* { $( $impl )* } ) $( -> $result )* { $( $impl )* }
@@ -1546,14 +1548,11 @@ macro_rules! decl_module {
} }
} }
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::dispatch::Dispatchable impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $crate::traits::UnfilteredDispatchable
for $call_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )* for $call_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )*
{ {
type Trait = $trait_instance;
type Origin = $origin_type; type Origin = $origin_type;
type Info = $crate::weights::DispatchInfo; fn dispatch_bypass_filter(self, _origin: Self::Origin) -> $crate::dispatch::DispatchResultWithPostInfo {
type PostInfo = $crate::weights::PostDispatchInfo;
fn dispatch(self, _origin: Self::Origin) -> $crate::dispatch::DispatchResultWithPostInfo {
match self { match self {
$( $(
$call_type::$fn_name( $( $param_name ),* ) => { $call_type::$fn_name( $( $param_name ),* ) => {
@@ -1574,17 +1573,6 @@ macro_rules! decl_module {
type Call = $call_type<$trait_instance $(, $instance)?>; type Call = $call_type<$trait_instance $(, $instance)?>;
} }
impl<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $mod_type<$trait_instance $(, $instance)?>
where $( $other_where_bounds )*
{
#[doc(hidden)]
pub fn dispatch<D: $crate::dispatch::Dispatchable<Trait = $trait_instance, PostInfo = $crate::weights::PostDispatchInfo>>(
d: D,
origin: D::Origin
) -> $crate::dispatch::DispatchResultWithPostInfo {
d.dispatch(origin)
}
}
$crate::__dispatch_impl_metadata! { $crate::__dispatch_impl_metadata! {
$mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?> $mod_type<$trait_instance: $trait_name $(<I>, $instance: $instantiable)?>
{ $( $other_where_bounds )* } { $( $other_where_bounds )* }
@@ -1684,6 +1672,20 @@ macro_rules! impl_outer_dispatch {
fn dispatch( fn dispatch(
self, self,
origin: $origin, 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::dispatch::DispatchResultWithPostInfo {
$crate::impl_outer_dispatch! { $crate::impl_outer_dispatch! {
@DISPATCH_MATCH @DISPATCH_MATCH
@@ -1696,6 +1698,7 @@ macro_rules! impl_outer_dispatch {
} }
} }
} }
$( $(
impl $crate::dispatch::IsSubType<$camelcase, $runtime> for $call_type { impl $crate::dispatch::IsSubType<$camelcase, $runtime> for $call_type {
#[allow(unreachable_patterns)] #[allow(unreachable_patterns)]
@@ -1731,7 +1734,8 @@ macro_rules! impl_outer_dispatch {
$origin $origin
{ {
$( $generated )* $( $generated )*
$call_type::$name(call) => call.dispatch($origin), $call_type::$name(call) =>
$crate::traits::UnfilteredDispatchable::dispatch_bypass_filter(call, $origin),
} }
$index + 1; $index + 1;
$( $rest ),* $( $rest ),*
@@ -2050,21 +2054,34 @@ mod tests {
}; };
pub trait Trait: system::Trait + Sized where Self::AccountId: From<u32> { pub trait Trait: system::Trait + Sized where Self::AccountId: From<u32> {
type Origin;
type BlockNumber: Into<u32>; type BlockNumber: Into<u32>;
type Call: From<Call<Self>>;
} }
pub mod system { pub mod system {
use super::*;
pub trait Trait { pub trait Trait {
type AccountId; type AccountId;
type Call;
type BaseCallFilter;
type Origin: crate::traits::OriginTrait<Call = Self::Call>;
} }
pub fn ensure_root<R>(_: R) -> DispatchResult { #[derive(Clone, PartialEq, Eq, Debug)]
Ok(()) 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 Trait>::AccountId>;
} }
decl_module! { decl_module! {
@@ -2169,21 +2186,26 @@ mod tests {
pub struct TraitImpl {} pub struct TraitImpl {}
impl Trait for TraitImpl { impl Trait for TraitImpl {
type Origin = u32;
type BlockNumber = u32; type BlockNumber = u32;
type Call = OuterCall;
} }
type Test = Module<TraitImpl>; type Test = Module<TraitImpl>;
impl_outer_origin!{
pub enum OuterOrigin for TraitImpl where system = system {}
}
impl_outer_dispatch! { impl_outer_dispatch! {
pub enum OuterCall for TraitImpl where origin: u32 { pub enum OuterCall for TraitImpl where origin: OuterOrigin {
self::Test, self::Test,
} }
} }
impl system::Trait for TraitImpl { impl system::Trait for TraitImpl {
type Origin = OuterOrigin;
type AccountId = u32; type AccountId = u32;
type Call = OuterCall;
type BaseCallFilter = ();
} }
#[test] #[test]
+2 -2
View File
@@ -51,14 +51,14 @@ pub use sp_runtime::RuntimeDebug;
#[macro_use] #[macro_use]
pub mod debug; pub mod debug;
#[macro_use] #[macro_use]
mod origin;
#[macro_use]
pub mod dispatch; pub mod dispatch;
pub mod storage; pub mod storage;
mod hash; mod hash;
#[macro_use] #[macro_use]
pub mod event; pub mod event;
#[macro_use] #[macro_use]
mod origin;
#[macro_use]
pub mod metadata; pub mod metadata;
#[macro_use] #[macro_use]
pub mod inherent; pub mod inherent;
+4
View File
@@ -290,6 +290,7 @@ mod tests {
use super::*; use super::*;
pub trait Trait: 'static { pub trait Trait: 'static {
type BaseCallFilter;
const ASSOCIATED_CONST: u64 = 500; const ASSOCIATED_CONST: u64 = 500;
type Origin: Into<Result<RawOrigin<Self::AccountId>, Self::Origin>> type Origin: Into<Result<RawOrigin<Self::AccountId>, Self::Origin>>
+ From<RawOrigin<Self::AccountId>>; + From<RawOrigin<Self::AccountId>>;
@@ -297,6 +298,7 @@ mod tests {
type BlockNumber: From<u32> + Encode; type BlockNumber: From<u32> + Encode;
type SomeValue: Get<u32>; type SomeValue: Get<u32>;
type ModuleToIndex: crate::traits::ModuleToIndex; type ModuleToIndex: crate::traits::ModuleToIndex;
type Call;
} }
decl_module! { decl_module! {
@@ -436,11 +438,13 @@ mod tests {
} }
impl system::Trait for TestRuntime { impl system::Trait for TestRuntime {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type AccountId = u32; type AccountId = u32;
type BlockNumber = u32; type BlockNumber = u32;
type SomeValue = SystemValue; type SomeValue = SystemValue;
type ModuleToIndex = (); type ModuleToIndex = ();
type Call = Call;
} }
impl_runtime_metadata!( impl_runtime_metadata!(
+146 -15
View File
@@ -45,19 +45,23 @@ macro_rules! impl_outer_origin {
$( $rest_with_system:tt )* $( $rest_with_system:tt )*
} }
) => { ) => {
$crate::impl_outer_origin!( $crate::paste::item! {
$( #[$attr] )*; $crate::impl_outer_origin!(
$name; $( #[$attr] )*;
$runtime; $name;
$system; [< $name Caller >];
Modules { $( $rest_with_system )* }; $runtime;
); $system;
Modules { $( $rest_with_system )* };
);
}
}; };
// Generic + Instance // Generic + Instance
( (
$(#[$attr:meta])*; $(#[$attr:meta])*;
$name:ident; $name:ident;
$caller_name:ident;
$runtime:ident; $runtime:ident;
$system:ident; $system:ident;
Modules { Modules {
@@ -69,6 +73,7 @@ macro_rules! impl_outer_origin {
$crate::impl_outer_origin!( $crate::impl_outer_origin!(
$( #[$attr] )*; $( #[$attr] )*;
$name; $name;
$caller_name;
$runtime; $runtime;
$system; $system;
Modules { $( $( $rest_module )* )? }; Modules { $( $( $rest_module )* )? };
@@ -80,6 +85,7 @@ macro_rules! impl_outer_origin {
( (
$(#[$attr:meta])*; $(#[$attr:meta])*;
$name:ident; $name:ident;
$caller_name:ident;
$runtime:ident; $runtime:ident;
$system:ident; $system:ident;
Modules { Modules {
@@ -91,6 +97,7 @@ macro_rules! impl_outer_origin {
$crate::impl_outer_origin!( $crate::impl_outer_origin!(
$( #[$attr] )*; $( #[$attr] )*;
$name; $name;
$caller_name;
$runtime; $runtime;
$system; $system;
Modules { $( $rest_module )* }; Modules { $( $rest_module )* };
@@ -102,6 +109,7 @@ macro_rules! impl_outer_origin {
( (
$(#[$attr:meta])*; $(#[$attr:meta])*;
$name:ident; $name:ident;
$caller_name:ident;
$runtime:ident; $runtime:ident;
$system:ident; $system:ident;
Modules { Modules {
@@ -113,6 +121,7 @@ macro_rules! impl_outer_origin {
$crate::impl_outer_origin!( $crate::impl_outer_origin!(
$( #[$attr] )*; $( #[$attr] )*;
$name; $name;
$caller_name;
$runtime; $runtime;
$system; $system;
Modules { $( $( $rest_module )* )? }; Modules { $( $( $rest_module )* )? };
@@ -124,6 +133,7 @@ macro_rules! impl_outer_origin {
( (
$(#[$attr:meta])*; $(#[$attr:meta])*;
$name:ident; $name:ident;
$caller_name:ident;
$runtime:ident; $runtime:ident;
$system:ident; $system:ident;
Modules { Modules {
@@ -135,6 +145,7 @@ macro_rules! impl_outer_origin {
$crate::impl_outer_origin!( $crate::impl_outer_origin!(
$( #[$attr] )*; $( #[$attr] )*;
$name; $name;
$caller_name;
$runtime; $runtime;
$system; $system;
Modules { $( $( $rest_module )* )? }; Modules { $( $( $rest_module )* )? };
@@ -146,16 +157,78 @@ macro_rules! impl_outer_origin {
( (
$(#[$attr:meta])*; $(#[$attr:meta])*;
$name:ident; $name:ident;
$caller_name:ident;
$runtime:ident; $runtime:ident;
$system:ident; $system:ident;
Modules { }; Modules { };
$( $module:ident $( < $generic:ident > )? $( { $generic_instance:ident } )? ,)* $( $module:ident $( < $generic:ident > )? $( { $generic_instance:ident } )? ,)*
) => { ) => {
// WARNING: All instance must hold the filter `frame_system::Trait::BaseCallFilter`.
// 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::Trait>::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::Trait>::Call;
type PalletsOrigin = $caller_name;
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::Trait>::BaseCallFilter
as $crate::traits::Filter<<$runtime as $system::Trait>::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)
}
}
$crate::paste::item! { $crate::paste::item! {
#[derive(Clone, PartialEq, Eq, $crate::RuntimeDebug)] #[derive(Clone, PartialEq, Eq, $crate::RuntimeDebug)]
$(#[$attr])* $(#[$attr])*
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub enum $name { pub enum $caller_name {
system($system::Origin<$runtime>), system($system::Origin<$runtime>),
$( $(
[< $module $( _ $generic_instance )? >] [< $module $( _ $generic_instance )? >]
@@ -168,20 +241,30 @@ macro_rules! impl_outer_origin {
#[allow(dead_code)] #[allow(dead_code)]
impl $name { impl $name {
pub const NONE: Self = $name::system($system::RawOrigin::None); pub fn none() -> Self {
pub const ROOT: Self = $name::system($system::RawOrigin::Root); $system::RawOrigin::None.into()
}
pub fn root() -> Self {
$system::RawOrigin::Root.into()
}
pub fn signed(by: <$runtime as $system::Trait>::AccountId) -> Self { pub fn signed(by: <$runtime as $system::Trait>::AccountId) -> Self {
$name::system($system::RawOrigin::Signed(by)) $system::RawOrigin::Signed(by).into()
} }
} }
impl From<$system::Origin<$runtime>> for $name { impl From<$system::Origin<$runtime>> for $name {
fn from(x: $system::Origin<$runtime>) -> Self { fn from(x: $system::Origin<$runtime>) -> Self {
$name::system(x) let mut o = $name {
caller: $caller_name::system(x),
filter: $crate::sp_std::rc::Rc::new(Box::new(|_| true)),
};
$crate::traits::OriginTrait::reset_filter(&mut o);
o
} }
} }
impl Into<$crate::sp_std::result::Result<$system::Origin<$runtime>, $name>> for $name { impl Into<$crate::sp_std::result::Result<$system::Origin<$runtime>, $name>> for $name {
fn into(self) -> $crate::sp_std::result::Result<$system::Origin<$runtime>, Self> { fn into(self) -> $crate::sp_std::result::Result<$system::Origin<$runtime>, Self> {
if let $name::system(l) = self { if let $caller_name::system(l) = self.caller {
Ok(l) Ok(l)
} else { } else {
Err(self) Err(self)
@@ -197,7 +280,12 @@ macro_rules! impl_outer_origin {
$crate::paste::item! { $crate::paste::item! {
impl From<$module::Origin < $( $generic )? $(, $module::$generic_instance )? > > for $name { impl From<$module::Origin < $( $generic )? $(, $module::$generic_instance )? > > for $name {
fn from(x: $module::Origin < $( $generic )? $(, $module::$generic_instance )? >) -> Self { fn from(x: $module::Origin < $( $generic )? $(, $module::$generic_instance )? >) -> Self {
$name::[< $module $( _ $generic_instance )? >](x) let mut o = $name {
caller: $caller_name::[< $module $( _ $generic_instance )? >](x),
filter: $crate::sp_std::rc::Rc::new(Box::new(|_| true)),
};
$crate::traits::OriginTrait::reset_filter(&mut o);
o
} }
} }
impl Into< impl Into<
@@ -210,7 +298,7 @@ macro_rules! impl_outer_origin {
$module::Origin < $( $generic )? $(, $module::$generic_instance )? >, $module::Origin < $( $generic )? $(, $module::$generic_instance )? >,
Self, Self,
> { > {
if let $name::[< $module $( _ $generic_instance )? >](l) = self { if let $caller_name::[< $module $( _ $generic_instance )? >](l) = self.caller {
Ok(l) Ok(l)
} else { } else {
Err(self) Err(self)
@@ -224,9 +312,12 @@ macro_rules! impl_outer_origin {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::traits::{Filter, OriginTrait};
mod system { mod system {
pub trait Trait { pub trait Trait {
type AccountId; type AccountId;
type Call;
type BaseCallFilter;
} }
#[derive(Clone, PartialEq, Eq, Debug)] #[derive(Clone, PartialEq, Eq, Debug)]
@@ -263,8 +354,17 @@ mod tests {
#[derive(Clone, PartialEq, Eq, Debug)] #[derive(Clone, PartialEq, Eq, Debug)]
pub struct TestRuntime; pub struct TestRuntime;
pub struct BaseCallFilter;
impl Filter<u32> for BaseCallFilter {
fn filter(c: &u32) -> bool {
*c % 2 == 0
}
}
impl system::Trait for TestRuntime { impl system::Trait for TestRuntime {
type AccountId = u32; type AccountId = u32;
type Call = u32;
type BaseCallFilter = BaseCallFilter;
} }
impl_outer_origin!( impl_outer_origin!(
@@ -298,4 +398,35 @@ mod tests {
impl_outer_origin!( impl_outer_origin!(
pub enum OriginEmpty for TestRuntime where system = system {} pub enum OriginEmpty for TestRuntime where system = system {}
); );
#[test]
fn test_default_filter() {
assert_eq!(OriginWithSystem::root().filter_call(&0), true);
assert_eq!(OriginWithSystem::root().filter_call(&1), false);
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(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);
}
} }
+57
View File
@@ -1550,6 +1550,63 @@ pub trait EnsureOrigin<OuterOrigin> {
fn successful_origin() -> OuterOrigin; fn successful_origin() -> 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`.
pub trait UnfilteredDispatchable {
/// The origin type of the runtime, (i.e. `frame_system::Trait::Origin`).
type Origin;
/// Dispatch this call but do not check the filter in origin.
fn dispatch_bypass_filter(self, origin: Self::Origin) -> crate::dispatch::DispatchResultWithPostInfo;
}
/// Methods available on `frame_system::Trait::Origin`.
pub trait OriginTrait: Sized {
/// Runtime call type, as in `frame_system::Trait::Call`
type Call;
/// The caller origin, overarching type of all pallets origins.
type PalletsOrigin;
/// Add a filter to the origin.
fn add_filter(&mut self, filter: impl Fn(&Self::Call) -> bool + 'static);
/// Reset origin filters to default one, i.e `frame_system::Trait::BaseCallFilter`.
fn reset_filter(&mut self);
/// Replace the caller with caller from the other origin
fn set_caller_from(&mut self, other: impl Into<Self>);
/// Filter the call, if false then call is filtered out.
fn filter_call(&self, call: &Self::Call) -> bool;
}
/// Trait to be used when types are exactly same.
///
/// This allow to convert back and forth from type, a reference and a mutable reference.
pub trait IsType<T>: Into<T> + From<T> {
/// Cast reference.
fn from_ref(t: &T) -> &Self;
/// Cast reference.
fn into_ref(&self) -> &T;
/// Cast mutable reference.
fn from_mut(t: &mut T) -> &mut Self;
/// Cast mutable reference.
fn into_mut(&mut self) -> &mut T;
}
impl<T> IsType<T> for T {
fn from_ref(t: &T) -> &Self { t }
fn into_ref(&self) -> &T { self }
fn from_mut(t: &mut T) -> &mut Self { t }
fn into_mut(&mut self) -> &mut T { self }
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
@@ -89,12 +89,14 @@ pub type BlockNumber = u64;
pub type Index = u64; pub type Index = u64;
impl system::Trait for Runtime { impl system::Trait for Runtime {
type BaseCallFilter = ();
type Hash = H256; type Hash = H256;
type Origin = Origin; type Origin = Origin;
type BlockNumber = BlockNumber; type BlockNumber = BlockNumber;
type AccountId = AccountId; type AccountId = AccountId;
type Event = Event; type Event = Event;
type ModuleToIndex = ModuleToIndex; type ModuleToIndex = ModuleToIndex;
type Call = Call;
} }
frame_support::construct_runtime!( frame_support::construct_runtime!(
@@ -233,12 +233,14 @@ pub type BlockNumber = u64;
pub type Index = u64; pub type Index = u64;
impl system::Trait for Runtime { impl system::Trait for Runtime {
type BaseCallFilter= ();
type Hash = H256; type Hash = H256;
type Origin = Origin; type Origin = Origin;
type BlockNumber = BlockNumber; type BlockNumber = BlockNumber;
type AccountId = AccountId; type AccountId = AccountId;
type Event = Event; type Event = Event;
type ModuleToIndex = (); type ModuleToIndex = ();
type Call = Call;
} }
frame_support::construct_runtime!( frame_support::construct_runtime!(
@@ -158,12 +158,14 @@ pub type Block = generic::Block<Header, UncheckedExtrinsic>;
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<u32, Call, Signature, ()>; pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<u32, Call, Signature, ()>;
impl system::Trait for Runtime { impl system::Trait for Runtime {
type BaseCallFilter = ();
type Hash = H256; type Hash = H256;
type Origin = Origin; type Origin = Origin;
type BlockNumber = BlockNumber; type BlockNumber = BlockNumber;
type AccountId = AccountId; type AccountId = AccountId;
type Event = Event; type Event = Event;
type ModuleToIndex = (); type ModuleToIndex = ();
type Call = Call;
} }
impl module::Trait for Runtime {} impl module::Trait for Runtime {}
@@ -21,9 +21,11 @@ pub trait Trait: 'static + Eq + Clone {
type Origin: Into<Result<RawOrigin<Self::AccountId>, Self::Origin>> type Origin: Into<Result<RawOrigin<Self::AccountId>, Self::Origin>>
+ From<RawOrigin<Self::AccountId>>; + From<RawOrigin<Self::AccountId>>;
type BaseCallFilter: frame_support::traits::Filter<Self::Call>;
type BlockNumber: Decode + Encode + EncodeLike + Clone + Default; type BlockNumber: Decode + Encode + EncodeLike + Clone + Default;
type Hash; type Hash;
type AccountId: Encode + EncodeLike + Decode; type AccountId: Encode + EncodeLike + Decode;
type Call;
type Event: From<Event<Self>>; type Event: From<Event<Self>>;
type ModuleToIndex: frame_support::traits::ModuleToIndex; type ModuleToIndex: frame_support::traits::ModuleToIndex;
} }
+1
View File
@@ -61,6 +61,7 @@ frame_support::parameter_types! {
#[derive(Clone, Eq, PartialEq)] #[derive(Clone, Eq, PartialEq)]
pub struct Runtime; pub struct Runtime;
impl system::Trait for Runtime { impl system::Trait for Runtime {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
@@ -51,6 +51,7 @@ impl Dispatchable for Call {
pub struct Test; pub struct Test;
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = AccountIndex; type Index = AccountIndex;
type BlockNumber = BlockNumber; type BlockNumber = BlockNumber;
+14 -9
View File
@@ -123,7 +123,7 @@ use frame_support::{
storage, storage,
traits::{ traits::{
Contains, Get, ModuleToIndex, OnNewAccount, OnKilledAccount, IsDeadAccount, Happened, Contains, Get, ModuleToIndex, OnNewAccount, OnKilledAccount, IsDeadAccount, Happened,
StoredMap, EnsureOrigin, StoredMap, EnsureOrigin, OriginTrait, Filter,
}, },
weights::{ weights::{
Weight, RuntimeDbWeight, DispatchInfo, PostDispatchInfo, DispatchClass, Weight, RuntimeDbWeight, DispatchInfo, PostDispatchInfo, DispatchClass,
@@ -149,11 +149,15 @@ pub fn extrinsics_data_root<H: Hash>(xts: Vec<Vec<u8>>) -> H::Output {
} }
pub trait Trait: 'static + Eq + Clone { pub trait Trait: 'static + Eq + Clone {
/// The aggregated `Origin` type used by dispatchable calls. /// The basic call filter to use in Origin.
type BaseCallFilter: Filter<Self::Call>;
/// The `Origin` type used by dispatchable calls.
type Origin: type Origin:
Into<Result<RawOrigin<Self::AccountId>, Self::Origin>> Into<Result<RawOrigin<Self::AccountId>, Self::Origin>>
+ From<RawOrigin<Self::AccountId>> + From<RawOrigin<Self::AccountId>>
+ Clone; + Clone
+ OriginTrait<Call = Self::Call>;
/// The aggregated `Call` type. /// The aggregated `Call` type.
type Call: Dispatchable + Debug; type Call: Dispatchable + Debug;
@@ -1890,7 +1894,7 @@ pub(crate) mod tests {
use sp_core::H256; use sp_core::H256;
use sp_runtime::{traits::{BlakeTwo256, IdentityLookup, SignedExtension}, testing::Header, DispatchError}; use sp_runtime::{traits::{BlakeTwo256, IdentityLookup, SignedExtension}, testing::Header, DispatchError};
use frame_support::{ use frame_support::{
impl_outer_origin, parameter_types, assert_ok, assert_noop, assert_err, impl_outer_origin, parameter_types, assert_ok, assert_noop,
weights::{WithPostDispatchInfo, Pays}, weights::{WithPostDispatchInfo, Pays},
}; };
@@ -1937,7 +1941,7 @@ pub(crate) mod tests {
pub struct Call; pub struct Call;
impl Dispatchable for Call { impl Dispatchable for Call {
type Origin = (); type Origin = Origin;
type Trait = (); type Trait = ();
type Info = DispatchInfo; type Info = DispatchInfo;
type PostInfo = PostDispatchInfo; type PostInfo = PostDispatchInfo;
@@ -1948,6 +1952,7 @@ pub(crate) mod tests {
} }
impl Trait for Test { impl Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Call = Call; type Call = Call;
type Index = u64; type Index = u64;
@@ -1997,7 +2002,7 @@ pub(crate) mod tests {
fn origin_works() { fn origin_works() {
let o = Origin::from(RawOrigin::<u64>::Signed(1u64)); let o = Origin::from(RawOrigin::<u64>::Signed(1u64));
let x: Result<RawOrigin<u64>, Origin> = o.into(); let x: Result<RawOrigin<u64>, Origin> = o.into();
assert_eq!(x, Ok(RawOrigin::<u64>::Signed(1u64))); assert_eq!(x.unwrap(), RawOrigin::<u64>::Signed(1u64));
} }
#[test] #[test]
@@ -2719,8 +2724,8 @@ pub(crate) mod tests {
EnsureOneOf::<u64, EnsureRoot<u64>, EnsureSigned<u64>>::try_origin(o.into()) EnsureOneOf::<u64, EnsureRoot<u64>, EnsureSigned<u64>>::try_origin(o.into())
} }
assert_ok!(ensure_root_or_signed(RawOrigin::Root), Either::Left(())); assert_eq!(ensure_root_or_signed(RawOrigin::Root).unwrap(), Either::Left(()));
assert_ok!(ensure_root_or_signed(RawOrigin::Signed(0)), Either::Right(0)); assert_eq!(ensure_root_or_signed(RawOrigin::Signed(0)).unwrap(), Either::Right(0));
assert_err!(ensure_root_or_signed(RawOrigin::None), Origin::from(RawOrigin::None)); assert!(ensure_root_or_signed(RawOrigin::None).is_err())
} }
} }
+5 -4
View File
@@ -314,6 +314,7 @@ mod tests {
pub const AvailableBlockRatio: Perbill = Perbill::one(); pub const AvailableBlockRatio: Perbill = Perbill::one();
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
@@ -352,7 +353,7 @@ mod tests {
fn timestamp_works() { fn timestamp_works() {
new_test_ext().execute_with(|| { new_test_ext().execute_with(|| {
Timestamp::set_timestamp(42); Timestamp::set_timestamp(42);
assert_ok!(Timestamp::dispatch(Call::set(69), Origin::NONE)); assert_ok!(Timestamp::set(Origin::none(), 69));
assert_eq!(Timestamp::now(), 69); assert_eq!(Timestamp::now(), 69);
}); });
} }
@@ -362,8 +363,8 @@ mod tests {
fn double_timestamp_should_fail() { fn double_timestamp_should_fail() {
new_test_ext().execute_with(|| { new_test_ext().execute_with(|| {
Timestamp::set_timestamp(42); Timestamp::set_timestamp(42);
assert_ok!(Timestamp::dispatch(Call::set(69), Origin::NONE)); assert_ok!(Timestamp::set(Origin::none(), 69));
let _ = Timestamp::dispatch(Call::set(70), Origin::NONE); let _ = Timestamp::set(Origin::none(), 70);
}); });
} }
@@ -372,7 +373,7 @@ mod tests {
fn block_period_minimum_enforced() { fn block_period_minimum_enforced() {
new_test_ext().execute_with(|| { new_test_ext().execute_with(|| {
Timestamp::set_timestamp(42); Timestamp::set_timestamp(42);
let _ = Timestamp::dispatch(Call::set(46), Origin::NONE); let _ = Timestamp::set(Origin::none(), 46);
}); });
} }
} }
@@ -428,6 +428,7 @@ mod tests {
} }
impl frame_system::Trait for Runtime { impl frame_system::Trait for Runtime {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
+16 -15
View File
@@ -60,6 +60,7 @@ parameter_types! {
pub const AvailableBlockRatio: Perbill = Perbill::one(); pub const AvailableBlockRatio: Perbill = Perbill::one();
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
@@ -271,7 +272,7 @@ fn close_tip_works() {
assert_noop!(Treasury::close_tip(Origin::signed(0), h.into()), Error::<Test>::Premature); assert_noop!(Treasury::close_tip(Origin::signed(0), h.into()), Error::<Test>::Premature);
System::set_block_number(2); System::set_block_number(2);
assert_noop!(Treasury::close_tip(Origin::NONE, h.into()), BadOrigin); assert_noop!(Treasury::close_tip(Origin::none(), h.into()), BadOrigin);
assert_ok!(Treasury::close_tip(Origin::signed(0), h.into())); assert_ok!(Treasury::close_tip(Origin::signed(0), h.into()));
assert_eq!(Balances::free_balance(3), 10); assert_eq!(Balances::free_balance(3), 10);
@@ -381,7 +382,7 @@ fn accepted_spend_proposal_ignored_outside_spend_period() {
Balances::make_free_balance_be(&Treasury::account_id(), 101); Balances::make_free_balance_be(&Treasury::account_id(), 101);
assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3));
assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); assert_ok!(Treasury::approve_proposal(Origin::root(), 0));
<Treasury as OnInitialize<u64>>::on_initialize(1); <Treasury as OnInitialize<u64>>::on_initialize(1);
assert_eq!(Balances::free_balance(3), 0); assert_eq!(Balances::free_balance(3), 0);
@@ -408,7 +409,7 @@ fn rejected_spend_proposal_ignored_on_spend_period() {
Balances::make_free_balance_be(&Treasury::account_id(), 101); Balances::make_free_balance_be(&Treasury::account_id(), 101);
assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3));
assert_ok!(Treasury::reject_proposal(Origin::ROOT, 0)); assert_ok!(Treasury::reject_proposal(Origin::root(), 0));
<Treasury as OnInitialize<u64>>::on_initialize(2); <Treasury as OnInitialize<u64>>::on_initialize(2);
assert_eq!(Balances::free_balance(3), 0); assert_eq!(Balances::free_balance(3), 0);
@@ -422,22 +423,22 @@ fn reject_already_rejected_spend_proposal_fails() {
Balances::make_free_balance_be(&Treasury::account_id(), 101); Balances::make_free_balance_be(&Treasury::account_id(), 101);
assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3));
assert_ok!(Treasury::reject_proposal(Origin::ROOT, 0)); assert_ok!(Treasury::reject_proposal(Origin::root(), 0));
assert_noop!(Treasury::reject_proposal(Origin::ROOT, 0), Error::<Test>::InvalidProposalIndex); assert_noop!(Treasury::reject_proposal(Origin::root(), 0), Error::<Test>::InvalidProposalIndex);
}); });
} }
#[test] #[test]
fn reject_non_existent_spend_proposal_fails() { fn reject_non_existent_spend_proposal_fails() {
new_test_ext().execute_with(|| { new_test_ext().execute_with(|| {
assert_noop!(Treasury::reject_proposal(Origin::ROOT, 0), Error::<Test>::InvalidProposalIndex); assert_noop!(Treasury::reject_proposal(Origin::root(), 0), Error::<Test>::InvalidProposalIndex);
}); });
} }
#[test] #[test]
fn accept_non_existent_spend_proposal_fails() { fn accept_non_existent_spend_proposal_fails() {
new_test_ext().execute_with(|| { new_test_ext().execute_with(|| {
assert_noop!(Treasury::approve_proposal(Origin::ROOT, 0), Error::<Test>::InvalidProposalIndex); assert_noop!(Treasury::approve_proposal(Origin::root(), 0), Error::<Test>::InvalidProposalIndex);
}); });
} }
@@ -447,8 +448,8 @@ fn accept_already_rejected_spend_proposal_fails() {
Balances::make_free_balance_be(&Treasury::account_id(), 101); Balances::make_free_balance_be(&Treasury::account_id(), 101);
assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3));
assert_ok!(Treasury::reject_proposal(Origin::ROOT, 0)); assert_ok!(Treasury::reject_proposal(Origin::root(), 0));
assert_noop!(Treasury::approve_proposal(Origin::ROOT, 0), Error::<Test>::InvalidProposalIndex); assert_noop!(Treasury::approve_proposal(Origin::root(), 0), Error::<Test>::InvalidProposalIndex);
}); });
} }
@@ -459,7 +460,7 @@ fn accepted_spend_proposal_enacted_on_spend_period() {
assert_eq!(Treasury::pot(), 100); assert_eq!(Treasury::pot(), 100);
assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3));
assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); assert_ok!(Treasury::approve_proposal(Origin::root(), 0));
<Treasury as OnInitialize<u64>>::on_initialize(2); <Treasury as OnInitialize<u64>>::on_initialize(2);
assert_eq!(Balances::free_balance(3), 100); assert_eq!(Balances::free_balance(3), 100);
@@ -474,7 +475,7 @@ fn pot_underflow_should_not_diminish() {
assert_eq!(Treasury::pot(), 100); assert_eq!(Treasury::pot(), 100);
assert_ok!(Treasury::propose_spend(Origin::signed(0), 150, 3)); assert_ok!(Treasury::propose_spend(Origin::signed(0), 150, 3));
assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); assert_ok!(Treasury::approve_proposal(Origin::root(), 0));
<Treasury as OnInitialize<u64>>::on_initialize(2); <Treasury as OnInitialize<u64>>::on_initialize(2);
assert_eq!(Treasury::pot(), 100); // Pot hasn't changed assert_eq!(Treasury::pot(), 100); // Pot hasn't changed
@@ -496,13 +497,13 @@ fn treasury_account_doesnt_get_deleted() {
let treasury_balance = Balances::free_balance(&Treasury::account_id()); let treasury_balance = Balances::free_balance(&Treasury::account_id());
assert_ok!(Treasury::propose_spend(Origin::signed(0), treasury_balance, 3)); assert_ok!(Treasury::propose_spend(Origin::signed(0), treasury_balance, 3));
assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); assert_ok!(Treasury::approve_proposal(Origin::root(), 0));
<Treasury as OnInitialize<u64>>::on_initialize(2); <Treasury as OnInitialize<u64>>::on_initialize(2);
assert_eq!(Treasury::pot(), 100); // Pot hasn't changed assert_eq!(Treasury::pot(), 100); // Pot hasn't changed
assert_ok!(Treasury::propose_spend(Origin::signed(0), Treasury::pot(), 3)); assert_ok!(Treasury::propose_spend(Origin::signed(0), Treasury::pot(), 3));
assert_ok!(Treasury::approve_proposal(Origin::ROOT, 1)); assert_ok!(Treasury::approve_proposal(Origin::root(), 1));
<Treasury as OnInitialize<u64>>::on_initialize(4); <Treasury as OnInitialize<u64>>::on_initialize(4);
assert_eq!(Treasury::pot(), 0); // Pot is emptied assert_eq!(Treasury::pot(), 0); // Pot is emptied
@@ -526,9 +527,9 @@ fn inexistent_account_works() {
assert_eq!(Treasury::pot(), 0); // Pot is empty assert_eq!(Treasury::pot(), 0); // Pot is empty
assert_ok!(Treasury::propose_spend(Origin::signed(0), 99, 3)); assert_ok!(Treasury::propose_spend(Origin::signed(0), 99, 3));
assert_ok!(Treasury::approve_proposal(Origin::ROOT, 0)); assert_ok!(Treasury::approve_proposal(Origin::root(), 0));
assert_ok!(Treasury::propose_spend(Origin::signed(0), 1, 3)); assert_ok!(Treasury::propose_spend(Origin::signed(0), 1, 3));
assert_ok!(Treasury::approve_proposal(Origin::ROOT, 1)); assert_ok!(Treasury::approve_proposal(Origin::root(), 1));
<Treasury as OnInitialize<u64>>::on_initialize(2); <Treasury as OnInitialize<u64>>::on_initialize(2);
assert_eq!(Treasury::pot(), 0); // Pot hasn't changed assert_eq!(Treasury::pot(), 0); // Pot hasn't changed
assert_eq!(Balances::free_balance(3), 0); // Balance of `3` hasn't changed assert_eq!(Balances::free_balance(3), 0); // Balance of `3` hasn't changed
+21 -37
View File
@@ -54,8 +54,9 @@ use sp_std::prelude::*;
use codec::{Encode, Decode}; use codec::{Encode, Decode};
use sp_core::TypeId; use sp_core::TypeId;
use sp_io::hashing::blake2_256; use sp_io::hashing::blake2_256;
use frame_support::{decl_module, decl_event, decl_error, decl_storage, Parameter, ensure}; use frame_support::{decl_module, decl_event, decl_storage, Parameter};
use frame_support::{traits::{Filter, FilterStack, ClearFilterGuard}, use frame_support::{
traits::{OriginTrait, UnfilteredDispatchable},
weights::{Weight, GetDispatchInfo, DispatchClass}, dispatch::PostDispatchInfo, weights::{Weight, GetDispatchInfo, DispatchClass}, dispatch::PostDispatchInfo,
}; };
use frame_system::{self as system, ensure_signed, ensure_root}; use frame_system::{self as system, ensure_signed, ensure_root};
@@ -71,23 +72,14 @@ pub trait Trait: frame_system::Trait {
/// The overarching call type. /// The overarching call type.
type Call: Parameter + Dispatchable<Origin=Self::Origin, PostInfo=PostDispatchInfo> type Call: Parameter + Dispatchable<Origin=Self::Origin, PostInfo=PostDispatchInfo>
+ GetDispatchInfo + From<frame_system::Call<Self>>; + GetDispatchInfo + From<frame_system::Call<Self>>
+ UnfilteredDispatchable<Origin=Self::Origin>;
/// Is a given call compatible with the proxying subsystem?
type IsCallable: FilterStack<<Self as Trait>::Call>;
} }
decl_storage! { decl_storage! {
trait Store for Module<T: Trait> as Utility {} trait Store for Module<T: Trait> as Utility {}
} }
decl_error! {
pub enum Error for Module<T: Trait> {
/// A call with a `false` `IsCallable` filter was attempted.
Uncallable,
}
}
decl_event! { decl_event! {
/// Events type. /// Events type.
pub enum Event { pub enum Event {
@@ -96,8 +88,6 @@ decl_event! {
BatchInterrupted(u32, DispatchError), BatchInterrupted(u32, DispatchError),
/// Batch of dispatches completed fully with no error. /// Batch of dispatches completed fully with no error.
BatchCompleted, BatchCompleted,
/// A call with a `false` IsCallable filter was attempted.
Uncallable(u32),
} }
} }
@@ -111,20 +101,18 @@ impl TypeId for IndexedUtilityModuleId {
decl_module! { decl_module! {
pub struct Module<T: Trait> for enum Call where origin: T::Origin { pub struct Module<T: Trait> for enum Call where origin: T::Origin {
type Error = Error<T>;
/// Deposit one of this module's events by using the default implementation. /// Deposit one of this module's events by using the default implementation.
fn deposit_event() = default; fn deposit_event() = default;
/// Send a batch of dispatch calls. /// Send a batch of dispatch calls.
/// ///
/// This will execute until the first one fails and then stop. Calls must fulfil the
/// `IsCallable` filter unless the origin is `Root`.
///
/// May be called from any origin. /// May be called from any origin.
/// ///
/// - `calls`: The calls to be dispatched from the same origin. /// - `calls`: The calls to be dispatched from the same origin.
/// ///
/// If origin is root then call are dispatch without checking origin filter. (This includes
/// bypassing `frame_system::Trait::BaseCallFilter`).
///
/// # <weight> /// # <weight>
/// - Base weight: 14.39 + .987 * c µs /// - Base weight: 14.39 + .987 * c µs
/// - Plus the sum of the weights of the `calls`. /// - Plus the sum of the weights of the `calls`.
@@ -154,11 +142,11 @@ decl_module! {
fn batch(origin, calls: Vec<<T as Trait>::Call>) { fn batch(origin, calls: Vec<<T as Trait>::Call>) {
let is_root = ensure_root(origin.clone()).is_ok(); let is_root = ensure_root(origin.clone()).is_ok();
for (index, call) in calls.into_iter().enumerate() { for (index, call) in calls.into_iter().enumerate() {
if !is_root && !T::IsCallable::filter(&call) { let result = if is_root {
Self::deposit_event(Event::Uncallable(index as u32)); call.dispatch_bypass_filter(origin.clone())
return Ok(()) } else {
} call.dispatch(origin.clone())
let result = call.dispatch(origin.clone()); };
if let Err(e) = result { if let Err(e) = result {
Self::deposit_event(Event::BatchInterrupted(index as u32, e.error)); Self::deposit_event(Event::BatchInterrupted(index as u32, e.error));
return Ok(()); return Ok(());
@@ -169,9 +157,6 @@ decl_module! {
/// Send a call through an indexed pseudonym of the sender. /// Send a call through an indexed pseudonym of the sender.
/// ///
/// The call must fulfil only the pre-cleared `IsCallable` filter (i.e. only the level of
/// filtering that remains after calling `take()`).
///
/// NOTE: If you need to ensure that any account-based filtering is honored (i.e. because /// NOTE: If you need to ensure that any account-based filtering is honored (i.e. because
/// you expect `proxy` to have been used prior in the call stack and you want it to apply to /// you expect `proxy` to have been used prior in the call stack and you want it to apply to
/// any sub-accounts), then use `as_limited_sub` instead. /// any sub-accounts), then use `as_limited_sub` instead.
@@ -188,10 +173,8 @@ decl_module! {
)] )]
fn as_sub(origin, index: u16, call: Box<<T as Trait>::Call>) -> DispatchResult { fn as_sub(origin, index: u16, call: Box<<T as Trait>::Call>) -> DispatchResult {
let who = ensure_signed(origin)?; let who = ensure_signed(origin)?;
// We're now executing as a freshly authenticated new account, so the previous call
// restrictions no longer apply. // This is a freshly authenticated new account, the origin restrictions doesn't apply.
let _guard = ClearFilterGuard::<T::IsCallable, <T as Trait>::Call>::new();
ensure!(T::IsCallable::filter(&call), Error::<T>::Uncallable);
let pseudonym = Self::sub_account_id(who, index); let pseudonym = Self::sub_account_id(who, index);
call.dispatch(frame_system::RawOrigin::Signed(pseudonym).into()) call.dispatch(frame_system::RawOrigin::Signed(pseudonym).into())
.map(|_| ()).map_err(|e| e.error) .map(|_| ()).map_err(|e| e.error)
@@ -199,7 +182,8 @@ decl_module! {
/// Send a call through an indexed pseudonym of the sender. /// Send a call through an indexed pseudonym of the sender.
/// ///
/// Calls must each fulfil the `IsCallable` filter; it is not cleared before. /// Filter from origin are passed along. The call will be dispatched with an origin which
/// use the same filter as the origin of this call.
/// ///
/// NOTE: If you need to ensure that any account-based filtering is not honored (i.e. /// NOTE: If you need to ensure that any account-based filtering is not honored (i.e.
/// because you expect `proxy` to have been used prior in the call stack and you do not want /// because you expect `proxy` to have been used prior in the call stack and you do not want
@@ -216,11 +200,11 @@ decl_module! {
call.get_dispatch_info().class, call.get_dispatch_info().class,
)] )]
fn as_limited_sub(origin, index: u16, call: Box<<T as Trait>::Call>) -> DispatchResult { fn as_limited_sub(origin, index: u16, call: Box<<T as Trait>::Call>) -> DispatchResult {
let who = ensure_signed(origin)?; let mut origin = origin;
ensure!(T::IsCallable::filter(&call), Error::<T>::Uncallable); let who = ensure_signed(origin.clone())?;
let pseudonym = Self::sub_account_id(who, index); let pseudonym = Self::sub_account_id(who, index);
call.dispatch(frame_system::RawOrigin::Signed(pseudonym).into()) origin.set_caller_from(frame_system::RawOrigin::Signed(pseudonym));
.map(|_| ()).map_err(|e| e.error) call.dispatch(origin).map(|_| ()).map_err(|e| e.error)
} }
} }
} }
+13 -15
View File
@@ -23,7 +23,7 @@ use super::*;
use frame_support::{ use frame_support::{
assert_ok, assert_noop, impl_outer_origin, parameter_types, impl_outer_dispatch, assert_ok, assert_noop, impl_outer_origin, parameter_types, impl_outer_dispatch,
weights::Weight, impl_outer_event weights::Weight, impl_outer_event, dispatch::DispatchError, traits::Filter, storage,
}; };
use sp_core::H256; use sp_core::H256;
use sp_runtime::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header}; use sp_runtime::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header};
@@ -59,6 +59,7 @@ parameter_types! {
pub const AvailableBlockRatio: Perbill = Perbill::one(); pub const AvailableBlockRatio: Perbill = Perbill::one();
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = TestBaseCallFilter;
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
@@ -98,8 +99,8 @@ parameter_types! {
pub const MultisigDepositFactor: u64 = 1; pub const MultisigDepositFactor: u64 = 1;
pub const MaxSignatories: u16 = 3; pub const MaxSignatories: u16 = 3;
} }
pub struct TestIsCallable; pub struct TestBaseCallFilter;
impl Filter<Call> for TestIsCallable { impl Filter<Call> for TestBaseCallFilter {
fn filter(c: &Call) -> bool { fn filter(c: &Call) -> bool {
match *c { match *c {
Call::Balances(_) => true, Call::Balances(_) => true,
@@ -107,17 +108,9 @@ impl Filter<Call> for TestIsCallable {
} }
} }
} }
impl FilterStack<Call> for TestIsCallable {
type Stack = ();
fn push(_: impl Fn(&Call) -> bool + 'static) {}
fn pop() {}
fn take() -> Self::Stack { () }
fn restore(_: Self::Stack) {}
}
impl Trait for Test { impl Trait for Test {
type Event = TestEvent; type Event = TestEvent;
type Call = Call; type Call = Call;
type IsCallable = TestIsCallable;
} }
type System = frame_system::Module<Test>; type System = frame_system::Module<Test>;
type Balances = pallet_balances::Module<Test>; type Balances = pallet_balances::Module<Test>;
@@ -171,21 +164,26 @@ fn as_sub_filters() {
Origin::signed(1), Origin::signed(1),
1, 1,
Box::new(Call::System(frame_system::Call::remark(vec![]))), Box::new(Call::System(frame_system::Call::remark(vec![]))),
), Error::<Test>::Uncallable); ), DispatchError::BadOrigin);
}); });
} }
#[test] #[test]
fn batch_with_root_works() { fn batch_with_root_works() {
new_test_ext().execute_with(|| { new_test_ext().execute_with(|| {
let k = b"a".to_vec();
let call = Call::System(frame_system::Call::set_storage(vec![(k.clone(), k.clone())]));
assert!(!TestBaseCallFilter::filter(&call));
assert_eq!(Balances::free_balance(1), 10); assert_eq!(Balances::free_balance(1), 10);
assert_eq!(Balances::free_balance(2), 10); assert_eq!(Balances::free_balance(2), 10);
assert_ok!(Utility::batch(Origin::ROOT, vec![ assert_ok!(Utility::batch(Origin::root(), vec![
Call::Balances(BalancesCall::force_transfer(1, 2, 5)), Call::Balances(BalancesCall::force_transfer(1, 2, 5)),
Call::Balances(BalancesCall::force_transfer(1, 2, 5)) Call::Balances(BalancesCall::force_transfer(1, 2, 5)),
call, // Check filters are correctly bypassed
])); ]));
assert_eq!(Balances::free_balance(1), 0); assert_eq!(Balances::free_balance(1), 0);
assert_eq!(Balances::free_balance(2), 20); assert_eq!(Balances::free_balance(2), 20);
assert_eq!(storage::unhashed::get_raw(&k), Some(k));
}); });
} }
@@ -213,7 +211,7 @@ fn batch_with_signed_filters() {
Call::System(frame_system::Call::remark(vec![])) Call::System(frame_system::Call::remark(vec![]))
]), ]),
); );
expect_event(Event::Uncallable(0)); expect_event(Event::BatchInterrupted(0, DispatchError::BadOrigin));
}); });
} }
+1
View File
@@ -380,6 +380,7 @@ mod tests {
pub const AvailableBlockRatio: Perbill = Perbill::one(); pub const AvailableBlockRatio: Perbill = Perbill::one();
} }
impl frame_system::Trait for Test { impl frame_system::Trait for Test {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Index = u64; type Index = u64;
type BlockNumber = u64; type BlockNumber = u64;
+1 -1
View File
@@ -144,7 +144,7 @@ impl<
} }
/// An error type that indicates that the origin is invalid. /// An error type that indicates that the origin is invalid.
#[derive(Encode, Decode)] #[derive(Encode, Decode, RuntimeDebug)]
pub struct BadOrigin; pub struct BadOrigin;
impl From<BadOrigin> for &'static str { impl From<BadOrigin> for &'static str {
+2 -1
View File
@@ -184,7 +184,7 @@ impl ExtrinsicT for Extrinsic {
} }
impl sp_runtime::traits::Dispatchable for Extrinsic { impl sp_runtime::traits::Dispatchable for Extrinsic {
type Origin = (); type Origin = Origin;
type Trait = (); type Trait = ();
type Info = (); type Info = ();
type PostInfo = (); type PostInfo = ();
@@ -401,6 +401,7 @@ parameter_types! {
} }
impl frame_system::Trait for Runtime { impl frame_system::Trait for Runtime {
type BaseCallFilter = ();
type Origin = Origin; type Origin = Origin;
type Call = Extrinsic; type Call = Extrinsic;
type Index = u64; type Index = u64;