diff --git a/bin/node-template/pallets/template/src/mock.rs b/bin/node-template/pallets/template/src/mock.rs index 4eed0e1e75c3e..0d9ae7cff7753 100644 --- a/bin/node-template/pallets/template/src/mock.rs +++ b/bin/node-template/pallets/template/src/mock.rs @@ -24,6 +24,7 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); } impl system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Call = (); type Index = u64; diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 68d4eeeb7ad3a..c58c478d92bdf 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -135,6 +135,8 @@ parameter_types! { } impl system::Trait for Runtime { + /// The basic call filter to use in dispatchable. + type BaseCallFilter = (); /// The identifier used to distinguish between accounts. type AccountId = AccountId; /// The aggregated dispatch type that is available for extrinsics. diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index d64f641ea9d5a..d776d72e2b4cf 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -33,7 +33,7 @@ use frame_support::{ traits::{Currency, Imbalance, KeyOwnerProofSystem, OnUnbalanced, Randomness, LockIdentifier}, }; use frame_system::{EnsureRoot, EnsureOneOf}; -use frame_support::traits::{Filter, InstanceFilter}; +use frame_support::traits::InstanceFilter; use codec::{Encode, Decode}; use sp_core::{ crypto::KeyTypeId, @@ -113,15 +113,6 @@ pub fn native_version() -> NativeVersion { type NegativeImbalance = >::NegativeImbalance; -pub struct BaseFilter; -impl Filter for BaseFilter { - fn filter(_call: &Call) -> bool { - true - } -} -pub struct IsCallable; -frame_support::impl_filter_stack!(IsCallable, BaseFilter, Call, is_callable); - pub struct DealWithFees; impl OnUnbalanced for DealWithFees { fn on_unbalanceds(mut fees_then_tips: impl Iterator) { @@ -155,6 +146,7 @@ parameter_types! { const_assert!(AvailableBlockRatio::get().deconstruct() >= AVERAGE_ON_INITIALIZE_WEIGHT.deconstruct()); impl frame_system::Trait for Runtime { + type BaseCallFilter = (); type Origin = Origin; type Call = Call; type Index = Index; @@ -183,7 +175,6 @@ impl frame_system::Trait for Runtime { impl pallet_utility::Trait for Runtime { type Event = Event; type Call = Call; - type IsCallable = IsCallable; } parameter_types! { @@ -201,7 +192,6 @@ impl pallet_multisig::Trait for Runtime { type DepositBase = DepositBase; type DepositFactor = DepositFactor; type MaxSignatories = MaxSignatories; - type IsCallable = IsCallable; } parameter_types! { @@ -251,7 +241,6 @@ impl pallet_proxy::Trait for Runtime { type Event = Event; type Call = Call; type Currency = Balances; - type IsCallable = IsCallable; type ProxyType = ProxyType; type ProxyDepositBase = ProxyDepositBase; type ProxyDepositFactor = ProxyDepositFactor; diff --git a/frame/assets/src/lib.rs b/frame/assets/src/lib.rs index 2c67a320c1eae..d428f435b6ad3 100644 --- a/frame/assets/src/lib.rs +++ b/frame/assets/src/lib.rs @@ -304,6 +304,7 @@ mod tests { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type Call = (); diff --git a/frame/aura/src/mock.rs b/frame/aura/src/mock.rs index 84d895cd06099..db2c86492f5eb 100644 --- a/frame/aura/src/mock.rs +++ b/frame/aura/src/mock.rs @@ -46,6 +46,7 @@ parameter_types! { } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; diff --git a/frame/authority-discovery/src/lib.rs b/frame/authority-discovery/src/lib.rs index 1b7915ce3a4d4..f6008c9719d74 100644 --- a/frame/authority-discovery/src/lib.rs +++ b/frame/authority-discovery/src/lib.rs @@ -143,6 +143,7 @@ mod tests { } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = BlockNumber; diff --git a/frame/authorship/src/lib.rs b/frame/authorship/src/lib.rs index b9b30bf41111a..3023f8a2d399b 100644 --- a/frame/authorship/src/lib.rs +++ b/frame/authorship/src/lib.rs @@ -418,6 +418,7 @@ mod tests { } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; diff --git a/frame/babe/src/mock.rs b/frame/babe/src/mock.rs index de00928171494..b977ea90448f3 100644 --- a/frame/babe/src/mock.rs +++ b/frame/babe/src/mock.rs @@ -57,6 +57,7 @@ parameter_types! { } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index 48b2d425f1032..e882bdf349683 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -848,6 +848,7 @@ impl, I: Instance> PartialEq for ElevatedTrait { } impl, I: Instance> Eq for ElevatedTrait {} impl, I: Instance> frame_system::Trait for ElevatedTrait { + type BaseCallFilter = T::BaseCallFilter; type Origin = T::Origin; type Call = T::Call; type Index = T::Index; diff --git a/frame/balances/src/tests_composite.rs b/frame/balances/src/tests_composite.rs index 42036e624e6a3..81cb3449a8237 100644 --- a/frame/balances/src/tests_composite.rs +++ b/frame/balances/src/tests_composite.rs @@ -67,6 +67,7 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; diff --git a/frame/balances/src/tests_local.rs b/frame/balances/src/tests_local.rs index 30143a6c7edd1..54ab22af33c6c 100644 --- a/frame/balances/src/tests_local.rs +++ b/frame/balances/src/tests_local.rs @@ -67,6 +67,7 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; diff --git a/frame/benchmarking/src/lib.rs b/frame/benchmarking/src/lib.rs index ae9ef90764cd2..47e83cffbcd3e 100644 --- a/frame/benchmarking/src/lib.rs +++ b/frame/benchmarking/src/lib.rs @@ -29,7 +29,8 @@ pub use utils::*; pub use analysis::Analysis; #[doc(hidden)] 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; /// Construct pallet benchmarks for weighing dispatchables. @@ -242,7 +243,9 @@ macro_rules! benchmarks_iter { { $( $common )* } ( $( $names )* ) $name { $( $code )* }: { - as $crate::Dispatchable>::dispatch(Call::::$dispatch($($arg),*), $origin.into())?; + < + Call as $crate::frame_support::traits::UnfilteredDispatchable + >::dispatch_bypass_filter(Call::::$dispatch($($arg),*), $origin.into())?; } verify $postcode $( $rest )* @@ -262,7 +265,9 @@ macro_rules! benchmarks_iter { { $( $common )* } ( $( $names )* ) $name { $( $code )* }: { - as $crate::Dispatchable>::dispatch(Call::::$dispatch($($arg),*), $origin.into())?; + < + Call as $crate::frame_support::traits::UnfilteredDispatchable + >::dispatch_bypass_filter(Call::::$dispatch($($arg),*), $origin.into())?; } verify $postcode $( $rest )* diff --git a/frame/benchmarking/src/tests.rs b/frame/benchmarking/src/tests.rs index dc9d160b5ee92..85e8bf5a5c1db 100644 --- a/frame/benchmarking/src/tests.rs +++ b/frame/benchmarking/src/tests.rs @@ -67,6 +67,7 @@ pub trait Trait { pub struct Test; impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; diff --git a/frame/collective/src/lib.rs b/frame/collective/src/lib.rs index 3192ef0fc1c55..4551f4917a1e2 100644 --- a/frame/collective/src/lib.rs +++ b/frame/collective/src/lib.rs @@ -1015,10 +1015,11 @@ mod tests { pub const MaxProposals: u32 = 100; } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; - type Call = (); + type Call = Call; type Hash = H256; type Hashing = BlakeTwo256; type AccountId = u64; @@ -1167,7 +1168,7 @@ mod tests { let proposal_len: u32 = proposal.using_encoded(|p| p.len() as u32); let proposal_weight = proposal.get_dispatch_info().weight; 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::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_weight = proposal.get_dispatch_info().weight; 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::vote(Origin::signed(2), hash.clone(), 0, true)); @@ -1260,7 +1261,7 @@ mod tests { Collective::voting(&hash), 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!( Collective::voting(&hash), Some(Votes { index: 0, threshold: 3, ayes: vec![2], nays: vec![], end }) @@ -1275,7 +1276,7 @@ mod tests { Collective::voting(&hash), 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!( Collective::voting(&hash), Some(Votes { index: 1, threshold: 2, ayes: vec![2], nays: vec![], end }) @@ -1618,7 +1619,7 @@ mod tests { // Proposal would normally succeed assert_ok!(Collective::vote(Origin::signed(2), hash.clone(), 0, true)); // 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![] }; assert_eq!(System::events(), vec![ record(Event::collective_Instance1(RawEvent::Proposed(1, 0, hash.clone(), 2))), diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index 307b3118890b0..a98fdf2d25804 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -82,11 +82,12 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; type Hash = H256; - type Call = (); + type Call = Call; type Hashing = BlakeTwo256; type AccountId = u64; type Lookup = IdentityLookup; @@ -936,7 +937,7 @@ fn call_contract_removals() { #[test] 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] @@ -947,10 +948,10 @@ fn signed_claim_surcharge_contract_removals() { #[test] fn claim_surcharge_malus() { // Test surcharge malus for inherent - 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(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(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(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); // Test surcharge malus for signed claim_surcharge(4, || Contracts::claim_surcharge(Origin::signed(ALICE), BOB, None).is_ok(), true); diff --git a/frame/democracy/src/benchmarking.rs b/frame/democracy/src/benchmarking.rs index 3957b38f42926..d0bd73244825e 100644 --- a/frame/democracy/src/benchmarking.rs +++ b/frame/democracy/src/benchmarking.rs @@ -22,7 +22,7 @@ use super::*; use frame_benchmarking::{benchmarks, account}; use frame_support::{ IterableStorageMap, - traits::{Currency, Get, EnsureOrigin, OnInitialize}, + traits::{Currency, Get, EnsureOrigin, OnInitialize, UnfilteredDispatchable}, }; use frame_system::{RawOrigin, Module as System, self, EventRecord}; use sp_runtime::traits::{Bounded, One}; @@ -212,14 +212,14 @@ benchmarks! { for i in 0 .. r { let ref_idx = add_referendum::(i)?; let call = Call::::emergency_cancel(ref_idx); - call.dispatch(origin.clone())?; + call.dispatch_bypass_filter(origin.clone())?; } // Lets now measure one more let referendum_index = add_referendum::(r)?; let call = Call::::emergency_cancel(referendum_index); assert!(Democracy::::referendum_status(referendum_index).is_ok()); - }: { call.dispatch(origin)? } + }: { call.dispatch_bypass_filter(origin)? } verify { // Referendum has been canceled assert!(Democracy::::referendum_status(referendum_index).is_err()); @@ -239,7 +239,7 @@ benchmarks! { ); let call = Call::::external_propose(proposal_hash); - }: { call.dispatch(origin)? } + }: { call.dispatch_bypass_filter(origin)? } verify { // External proposal created ensure!(>::exists(), "External proposal didn't work"); @@ -251,7 +251,7 @@ benchmarks! { let origin = T::ExternalMajorityOrigin::successful_origin(); let proposal_hash = T::Hashing::hash_of(&p); let call = Call::::external_propose_majority(proposal_hash); - }: { call.dispatch(origin)? } + }: { call.dispatch_bypass_filter(origin)? } verify { // External proposal created ensure!(>::exists(), "External proposal didn't work"); @@ -263,7 +263,7 @@ benchmarks! { let origin = T::ExternalDefaultOrigin::successful_origin(); let proposal_hash = T::Hashing::hash_of(&p); let call = Call::::external_propose_default(proposal_hash); - }: { call.dispatch(origin)? } + }: { call.dispatch_bypass_filter(origin)? } verify { // External proposal created ensure!(>::exists(), "External proposal didn't work"); @@ -282,7 +282,7 @@ benchmarks! { let delay = 0; let call = Call::::fast_track(proposal_hash, voting_period.into(), delay.into()); - }: { call.dispatch(origin_fast_track)? } + }: { call.dispatch_bypass_filter(origin_fast_track)? } verify { assert_eq!(Democracy::::referendum_count(), 1, "referendum not created") } @@ -306,7 +306,7 @@ benchmarks! { let call = Call::::veto_external(proposal_hash); let origin = T::VetoOrigin::successful_origin(); ensure!(NextExternal::::get().is_some(), "no external proposal"); - }: { call.dispatch(origin)? } + }: { call.dispatch_bypass_filter(origin)? } verify { assert!(NextExternal::::get().is_none()); let (_, new_vetoers) = >::get(&proposal_hash).ok_or("no blacklist")?; @@ -347,7 +347,7 @@ benchmarks! { let origin = T::ExternalMajorityOrigin::successful_origin(); let proposal_hash = T::Hashing::hash_of(&r); let call = Call::::external_propose_majority(proposal_hash); - call.dispatch(origin)?; + call.dispatch_bypass_filter(origin)?; // External proposal created ensure!(>::exists(), "External proposal didn't work"); diff --git a/frame/democracy/src/tests.rs b/frame/democracy/src/tests.rs index 36c2b7093b626..85bb1ffcfb76e 100644 --- a/frame/democracy/src/tests.rs +++ b/frame/democracy/src/tests.rs @@ -84,6 +84,7 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; diff --git a/frame/democracy/src/tests/cancellation.rs b/frame/democracy/src/tests/cancellation.rs index e75fd28109163..4221865a3e5b0 100644 --- a/frame/democracy/src/tests/cancellation.rs +++ b/frame/democracy/src/tests/cancellation.rs @@ -29,7 +29,7 @@ fn cancel_referendum_should_work() { 0 ); 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(); @@ -53,8 +53,8 @@ fn cancel_queued_should_work() { assert!(pallet_scheduler::Agenda::::get(6)[0].is_some()); - assert_noop!(Democracy::cancel_queued(Origin::ROOT, 1), Error::::ProposalMissing); - assert_ok!(Democracy::cancel_queued(Origin::ROOT, 0)); + assert_noop!(Democracy::cancel_queued(Origin::root(), 1), Error::::ProposalMissing); + assert_ok!(Democracy::cancel_queued(Origin::root(), 0)); assert!(pallet_scheduler::Agenda::::get(6)[0].is_none()); }); } diff --git a/frame/elections-phragmen/src/lib.rs b/frame/elections-phragmen/src/lib.rs index c155c08cafef2..9436a15d5c749 100644 --- a/frame/elections-phragmen/src/lib.rs +++ b/frame/elections-phragmen/src/lib.rs @@ -1070,10 +1070,11 @@ mod tests { } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; - type Call = (); + type Call = Call; type Hash = H256; type Hashing = BlakeTwo256; 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 // call was changing. Currently it is a wrapper for the original call and does not do much. // Nonetheless, totally harmless. - if let Origin::system(frame_system::RawOrigin::Signed(_account)) = origin { - Elections::vote(origin, votes, stake) - } else { - panic!("vote origin must be signed"); - } + ensure_signed(origin.clone()).expect("vote origin must be signed"); + Elections::vote(origin, votes, stake) } fn votes_of(who: &u64) -> Vec { @@ -2358,7 +2356,7 @@ mod tests { assert_ok!(submit_candidacy(Origin::signed(3))); 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!(Elections::election_rounds(), 2); // new election round @@ -2381,7 +2379,7 @@ mod tests { // no replacement yet. assert_err_with_weight!( - Elections::remove_member(Origin::ROOT, 4, true), + Elections::remove_member(Origin::root(), 4, true), Error::::InvalidReplacement, Some(6000000), ); @@ -2403,7 +2401,7 @@ mod tests { // there is a replacement! and this one needs a weight refund. assert_err_with_weight!( - Elections::remove_member(Origin::ROOT, 4, false), + Elections::remove_member(Origin::root(), 4, false), Error::::InvalidReplacement, 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()); 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]); }); } diff --git a/frame/elections/src/mock.rs b/frame/elections/src/mock.rs index 9971dac572187..b0be542ab75a2 100644 --- a/frame/elections/src/mock.rs +++ b/frame/elections/src/mock.rs @@ -39,8 +39,9 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; - type Call = (); + type Call = Call; type Index = u64; type BlockNumber = u64; type Hash = H256; diff --git a/frame/elections/src/tests.rs b/frame/elections/src/tests.rs index 8a9f58b54a265..247b6272524b1 100644 --- a/frame/elections/src/tests.rs +++ b/frame/elections/src/tests.rs @@ -671,7 +671,7 @@ fn retracting_active_voter_should_slash_reporter() { assert_ok!(Elections::end_block(System::block_number())); 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())); System::set_block_number(10); @@ -1245,7 +1245,7 @@ fn election_second_tally_should_use_runners_up() { 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_desired_seats(Origin::ROOT, 3)); + assert_ok!(Elections::set_desired_seats(Origin::root(), 3)); assert_ok!(Elections::end_block(System::block_number())); System::set_block_number(10); diff --git a/frame/example-offchain-worker/src/tests.rs b/frame/example-offchain-worker/src/tests.rs index 30c9c22593035..ef910b95ff5b9 100644 --- a/frame/example-offchain-worker/src/tests.rs +++ b/frame/example-offchain-worker/src/tests.rs @@ -54,6 +54,7 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Call = (); type Index = u64; diff --git a/frame/example/src/lib.rs b/frame/example/src/lib.rs index 6b3d6b5e5fc9f..c8799cb62cb33 100644 --- a/frame/example/src/lib.rs +++ b/frame/example/src/lib.rs @@ -256,7 +256,7 @@ use sp_std::marker::PhantomData; 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}, }; use sp_std::prelude::*; @@ -609,14 +609,13 @@ impl sp_std::fmt::Debug for WatchDummy { } } -impl SignedExtension for WatchDummy { +impl SignedExtension for WatchDummy +where + ::Call: IsSubType, T>, +{ const IDENTIFIER: &'static str = "WatchDummy"; type AccountId = T::AccountId; - // Note that this could also be assigned to the top-level call enum. It is passed into the - // 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; + type Call = ::Call; type AdditionalSigned = (); type Pre = (); @@ -635,8 +634,8 @@ impl SignedExtension for WatchDummy { } // check for `set_dummy` - match call { - Call::set_dummy(..) => { + match call.is_sub_type() { + Some(Call::set_dummy(..)) => { sp_runtime::print("set_dummy was received."); let mut valid_tx = ValidTransaction::default(); @@ -711,8 +710,8 @@ mod tests { use super::*; use frame_support::{ - assert_ok, impl_outer_origin, parameter_types, weights::{DispatchInfo, GetDispatchInfo}, - traits::{OnInitialize, OnFinalize} + assert_ok, impl_outer_origin, parameter_types, impl_outer_dispatch, + weights::{DispatchInfo, GetDispatchInfo}, traits::{OnInitialize, OnFinalize} }; use sp_core::H256; // 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 {} } + 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 // first constructing a configuration type (`Test`) which `impl`s each of the // configuration traits of pallets we want to use. @@ -739,11 +744,12 @@ mod tests { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; type Hash = H256; - type Call = (); + type Call = OuterCall; type Hashing = BlakeTwo256; type AccountId = u64; type Lookup = IdentityLookup; @@ -827,7 +833,7 @@ mod tests { #[test] fn signed_ext_watch_dummy_works() { new_test_ext().execute_with(|| { - let call = >::set_dummy(10); + let call = >::set_dummy(10).into(); let info = DispatchInfo::default(); assert_eq!( diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index 04e095fec4364..c6371d914a3b8 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -545,6 +545,7 @@ mod tests { }; } impl frame_system::Trait for Runtime { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type Call = Call; diff --git a/frame/finality-tracker/src/lib.rs b/frame/finality-tracker/src/lib.rs index a9cf9c2b70f6d..e5ed9574e5b78 100644 --- a/frame/finality-tracker/src/lib.rs +++ b/frame/finality-tracker/src/lib.rs @@ -252,6 +252,7 @@ mod tests { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; @@ -337,10 +338,7 @@ mod tests { &Default::default(), Default::default(), ); - assert_ok!(FinalityTracker::dispatch( - Call::final_hint(i-1), - Origin::NONE, - )); + assert_ok!(FinalityTracker::final_hint(Origin::none(), i - 1)); FinalityTracker::on_finalize(i); let hdr = System::finalize(); parent_hash = hdr.hash(); diff --git a/frame/generic-asset/src/lib.rs b/frame/generic-asset/src/lib.rs index f94c83b5ed59f..403d9f8444673 100644 --- a/frame/generic-asset/src/lib.rs +++ b/frame/generic-asset/src/lib.rs @@ -1120,6 +1120,7 @@ impl PartialEq for ElevatedTrait { } impl Eq for ElevatedTrait {} impl frame_system::Trait for ElevatedTrait { + type BaseCallFilter = T::BaseCallFilter; type Origin = T::Origin; type Call = T::Call; type Index = T::Index; diff --git a/frame/generic-asset/src/mock.rs b/frame/generic-asset/src/mock.rs index 04fd565091b29..a928c9d67b2bd 100644 --- a/frame/generic-asset/src/mock.rs +++ b/frame/generic-asset/src/mock.rs @@ -46,6 +46,7 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; diff --git a/frame/generic-asset/src/tests.rs b/frame/generic-asset/src/tests.rs index d5c0a877dfe75..a094f69ba1fc5 100644 --- a/frame/generic-asset/src/tests.rs +++ b/frame/generic-asset/src/tests.rs @@ -598,7 +598,7 @@ fn create_reserved_should_create_a_default_account_with_the_balance_given() { let created_asset_id = 9; 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. assert_eq!(>::get(created_asset_id), expected_total_issuance); diff --git a/frame/grandpa/src/mock.rs b/frame/grandpa/src/mock.rs index 6cd7fddf9262f..0f3122c860dd0 100644 --- a/frame/grandpa/src/mock.rs +++ b/frame/grandpa/src/mock.rs @@ -94,6 +94,7 @@ parameter_types! { } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; diff --git a/frame/grandpa/src/tests.rs b/frame/grandpa/src/tests.rs index e15021733ffa0..2337e00e8d203 100644 --- a/frame/grandpa/src/tests.rs +++ b/frame/grandpa/src/tests.rs @@ -25,7 +25,7 @@ use codec::{Decode, Encode}; use fg_primitives::ScheduledChange; use frame_support::{ assert_err, assert_ok, - traits::{Currency, OnFinalize}, + traits::{Currency, OnFinalize, UnfilteredDispatchable}, }; use frame_system::{EventRecord, Phase}; use sp_core::H256; @@ -376,7 +376,7 @@ fn report_equivocation_current_set_works() { // report the equivocation and the tx should be dispatched successfully 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); @@ -457,7 +457,7 @@ fn report_equivocation_old_set_works() { // report the equivocation using the key ownership proof generated on // the old set, the tx should be dispatched successfully 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); diff --git a/frame/identity/src/lib.rs b/frame/identity/src/lib.rs index eddf89997f9f9..d657e3d793741 100644 --- a/frame/identity/src/lib.rs +++ b/frame/identity/src/lib.rs @@ -1174,6 +1174,7 @@ mod tests { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; diff --git a/frame/im-online/src/benchmarking.rs b/frame/im-online/src/benchmarking.rs index 63457168b3638..92d9b9d5a5364 100644 --- a/frame/im-online/src/benchmarking.rs +++ b/frame/im-online/src/benchmarking.rs @@ -24,8 +24,9 @@ use super::*; use frame_system::RawOrigin; use frame_benchmarking::benchmarks; 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 frame_support::traits::UnfilteredDispatchable; use crate::Module as ImOnline; @@ -85,7 +86,7 @@ benchmarks! { let call = Call::heartbeat(input_heartbeat, signature); }: { ImOnline::::validate_unsigned(TransactionSource::InBlock, &call)?; - call.dispatch(RawOrigin::None.into())?; + call.dispatch_bypass_filter(RawOrigin::None.into())?; } } diff --git a/frame/im-online/src/mock.rs b/frame/im-online/src/mock.rs index 01e84102b1a5c..d313646b28935 100644 --- a/frame/im-online/src/mock.rs +++ b/frame/im-online/src/mock.rs @@ -104,6 +104,7 @@ parameter_types! { } impl frame_system::Trait for Runtime { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; diff --git a/frame/im-online/src/tests.rs b/frame/im-online/src/tests.rs index 7619781b68df0..835d8440e6d5b 100644 --- a/frame/im-online/src/tests.rs +++ b/frame/im-online/src/tests.rs @@ -135,7 +135,7 @@ fn heartbeat( e @ _ => <&'static str>::from(e), })?; ImOnline::heartbeat( - Origin::system(frame_system::RawOrigin::None), + Origin::none(), heartbeat, signature, ) diff --git a/frame/indices/src/mock.rs b/frame/indices/src/mock.rs index 90ac1ae81b595..da30c129c3949 100644 --- a/frame/indices/src/mock.rs +++ b/frame/indices/src/mock.rs @@ -50,6 +50,7 @@ parameter_types! { } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Call = (); type Index = u64; diff --git a/frame/indices/src/tests.rs b/frame/indices/src/tests.rs index c5fc2b4735d16..e288871d55307 100644 --- a/frame/indices/src/tests.rs +++ b/frame/indices/src/tests.rs @@ -101,7 +101,7 @@ fn transfer_index_on_accounts_should_work() { fn force_transfer_index_on_preowned_should_work() { new_test_ext().execute_with(|| { 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(3), 0); assert_eq!(Indices::lookup_index(0), Some(3)); @@ -111,7 +111,7 @@ fn force_transfer_index_on_preowned_should_work() { #[test] fn force_transfer_index_on_free_should_work() { 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!(Indices::lookup_index(0), Some(3)); }); diff --git a/frame/membership/src/lib.rs b/frame/membership/src/lib.rs index cfcc17238ae27..62b1217c83500 100644 --- a/frame/membership/src/lib.rs +++ b/frame/membership/src/lib.rs @@ -291,6 +291,7 @@ mod tests { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; diff --git a/frame/multisig/src/lib.rs b/frame/multisig/src/lib.rs index bde0a06de60fb..672e6bed205e2 100644 --- a/frame/multisig/src/lib.rs +++ b/frame/multisig/src/lib.rs @@ -50,7 +50,7 @@ use sp_std::prelude::*; use codec::{Encode, Decode}; use sp_io::hashing::blake2_256; 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}, dispatch::{DispatchResultWithPostInfo, DispatchErrorWithPostInfo, PostDispatchInfo}, }; @@ -87,9 +87,6 @@ pub trait Trait: frame_system::Trait { /// The maximum amount of signatories allowed in the multisig. type MaxSignatories: Get; - - /// Is a given call compatible with the proxying subsystem? - type IsCallable: FilterStack<::Call>; } /// A global extrinsic index, formed as the extrinsic index within a block, together with that @@ -151,8 +148,6 @@ decl_error! { WrongTimepoint, /// A timepoint was given, yet no multisig operation is underway. 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 /// cancelling, third is the multisig account, fourth is hash of the call. MultisigCancelled(AccountId, Timepoint, 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 /// approved by a total of `threshold - 1` of `other_signatories`. /// - /// If there are enough, then dispatch the call. Calls must each fulfil the `IsCallable` - /// filter. + /// If there are enough, then dispatch the call. /// /// Payment: `DepositBase` will be reserved if this is the first approval, plus /// `threshold` times `DepositFactor`. It is returned once this dispatch happens or @@ -280,10 +272,6 @@ decl_module! { call: Box<::Call>, ) -> DispatchResultWithPostInfo { 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::::Call>::new(); - ensure!(T::IsCallable::filter(call.as_ref()), Error::::Uncallable); ensure!(threshold >= 1, Error::::ZeroThreshold); let max_sigs = T::MaxSignatories::get() as usize; ensure!(!other_signatories.is_empty(), Error::::TooFewSignatories); diff --git a/frame/multisig/src/tests.rs b/frame/multisig/src/tests.rs index 067ef4cf98e68..4b1395476db31 100644 --- a/frame/multisig/src/tests.rs +++ b/frame/multisig/src/tests.rs @@ -23,7 +23,7 @@ use super::*; use frame_support::{ 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_runtime::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header}; @@ -60,6 +60,7 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = TestBaseCallFilter; type Origin = Origin; type Index = u64; type BlockNumber = u64; @@ -99,8 +100,8 @@ parameter_types! { pub const DepositFactor: u64 = 1; pub const MaxSignatories: u16 = 3; } -pub struct TestIsCallable; -impl Filter for TestIsCallable { +pub struct TestBaseCallFilter; +impl Filter for TestBaseCallFilter { fn filter(c: &Call) -> bool { match *c { Call::Balances(_) => true, @@ -110,13 +111,6 @@ impl Filter for TestIsCallable { } } } -impl FilterStack 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 { type Event = TestEvent; type Call = Call; @@ -124,7 +118,6 @@ impl Trait for Test { type DepositBase = DepositBase; type DepositFactor = DepositFactor; type MaxSignatories = MaxSignatories; - type IsCallable = TestIsCallable; } type System = frame_system::Module; type Balances = pallet_balances::Module; @@ -403,8 +396,8 @@ fn multisig_filters() { new_test_ext().execute_with(|| { let call = Box::new(Call::System(frame_system::Call::set_code(vec![]))); assert_noop!( - Multisig::as_multi(Origin::signed(1), 1, vec![], None, call.clone()), - Error::::Uncallable, + Multisig::as_multi(Origin::signed(1), 1, vec![2], None, call.clone()), + DispatchError::BadOrigin, ); }); } diff --git a/frame/nicks/src/lib.rs b/frame/nicks/src/lib.rs index 35416aa8ebe57..8a130da2ae255 100644 --- a/frame/nicks/src/lib.rs +++ b/frame/nicks/src/lib.rs @@ -266,6 +266,7 @@ mod tests { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; diff --git a/frame/offences/benchmarking/src/mock.rs b/frame/offences/benchmarking/src/mock.rs index c228acdf404d9..90ad7eeb3cfcb 100644 --- a/frame/offences/benchmarking/src/mock.rs +++ b/frame/offences/benchmarking/src/mock.rs @@ -42,6 +42,7 @@ parameter_types! { } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = AccountIndex; type BlockNumber = BlockNumber; diff --git a/frame/offences/src/mock.rs b/frame/offences/src/mock.rs index 30d2409a00194..6c89072a0f5bd 100644 --- a/frame/offences/src/mock.rs +++ b/frame/offences/src/mock.rs @@ -96,6 +96,7 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Runtime { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; diff --git a/frame/proxy/src/lib.rs b/frame/proxy/src/lib.rs index 60305dfc74bed..14c7ced151758 100644 --- a/frame/proxy/src/lib.rs +++ b/frame/proxy/src/lib.rs @@ -41,8 +41,8 @@ use sp_runtime::{DispatchResult, traits::{Dispatchable, Zero}}; use sp_runtime::traits::Member; use frame_support::{ decl_module, decl_event, decl_error, decl_storage, Parameter, ensure, traits::{ - Get, ReservableCurrency, Currency, Filter, FilterStack, FilterStackGuard, - ClearFilterGuard, InstanceFilter + Get, ReservableCurrency, Currency, InstanceFilter, + OriginTrait, IsType, }, weights::{GetDispatchInfo, constants::{WEIGHT_PER_MICROS, WEIGHT_PER_NANOS}}, dispatch::{PostDispatchInfo, IsSubType}, }; @@ -60,14 +60,12 @@ pub trait Trait: frame_system::Trait { /// The overarching call type. type Call: Parameter + Dispatchable - + GetDispatchInfo + From> + IsSubType, Self>; + + GetDispatchInfo + From> + IsSubType, Self> + + IsType<::Call>; /// The currency mechanism. type Currency: ReservableCurrency; - /// Is a given call compatible with the proxying subsystem? - type IsCallable: FilterStack<::Call>; - /// 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. type ProxyType: Parameter + Member + Ord + PartialOrd + InstanceFilter<::Call> @@ -105,8 +103,6 @@ decl_error! { NotFound, /// Sender is not a proxy of the account to be proxied. NotProxy, - /// A call with a `false` `IsCallable` filter was attempted. - Uncallable, /// A call which is incompatible with the proxy type's filter was attempted. Unproxyable, /// 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)) .ok_or(Error::::NotProxy)?; - // We're now executing as a freshly authenticated new account, so the previous call - // restrictions no longer apply. - let _clear_guard = ClearFilterGuard::::Call>::new(); - let _filter_guard = FilterStackGuard::::Call>::new( - move |c| match c.is_sub_type() { + // This is a freshly authenticated new account, the origin restrictions doesn't apply. + let mut origin: T::Origin = frame_system::RawOrigin::Signed(real).into(); + origin.add_filter(move |c: &::Call| { + let c = ::Call::from_ref(c); + match c.is_sub_type() { Some(Call::add_proxy(_, ref pt)) | Some(Call::remove_proxy(_, ref pt)) if !proxy_type.is_superset(&pt) => false, - _ => proxy_type.filter(&c) + _ => proxy_type.filter(c) } - ); - ensure!(T::IsCallable::filter(&call), Error::::Uncallable); - - let e = call.dispatch(frame_system::RawOrigin::Signed(real).into()); + }); + let e = call.dispatch(origin); Self::deposit_event(RawEvent::ProxyExecuted(e.map(|_| ()).map_err(|e| e.error))); } diff --git a/frame/proxy/src/tests.rs b/frame/proxy/src/tests.rs index 93529317f6707..be99e9424a62b 100644 --- a/frame/proxy/src/tests.rs +++ b/frame/proxy/src/tests.rs @@ -23,7 +23,7 @@ use super::*; use frame_support::{ 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 sp_core::H256; @@ -62,6 +62,7 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = BaseFilter; type Origin = Origin; type Index = u64; type BlockNumber = u64; @@ -99,15 +100,12 @@ impl pallet_balances::Trait for Test { impl pallet_utility::Trait for Test { type Event = TestEvent; type Call = Call; - type IsCallable = IsCallable; } parameter_types! { pub const ProxyDepositBase: u64 = 1; pub const ProxyDepositFactor: u64 = 1; 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)] pub enum ProxyType { Any, @@ -142,7 +140,6 @@ impl Trait for Test { type Event = TestEvent; type Call = Call; type Currency = Balances; - type IsCallable = IsCallable; type ProxyType = ProxyType; type ProxyDepositBase = ProxyDepositBase; type ProxyDepositFactor = ProxyDepositFactor; @@ -158,7 +155,6 @@ use frame_system::Call as SystemCall; use pallet_balances::Call as BalancesCall; use pallet_balances::Error as BalancesError; use pallet_utility::Call as UtilityCall; -use pallet_utility::Error as UtilityError; use pallet_utility::Event as UtilityEvent; use super::Call as ProxyCall; @@ -201,7 +197,8 @@ fn filtering_works() { expect_event(RawEvent::ProxyExecuted(Ok(()))); assert_ok!(Proxy::proxy(Origin::signed(3), 1, None, call.clone())); expect_event(RawEvent::ProxyExecuted(Ok(()))); - assert_noop!(Proxy::proxy(Origin::signed(4), 1, None, call.clone()), Error::::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); 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()))); assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone())); expect_event(RawEvent::ProxyExecuted(Ok(()))); - assert_noop!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()), Error::::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())); expect_event(RawEvent::ProxyExecuted(Ok(()))); let call = Box::new(Call::Utility(UtilityCall::as_limited_sub(0, inner.clone()))); assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone())); expect_event(RawEvent::ProxyExecuted(Ok(()))); - assert_noop!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()), Error::::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())); - let de = DispatchError::from(UtilityError::::Uncallable).stripped(); - expect_event(RawEvent::ProxyExecuted(Err(de))); + expect_event(RawEvent::ProxyExecuted(Err(DispatchError::BadOrigin))); let call = Box::new(Call::Utility(UtilityCall::batch(vec![*inner]))); assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone())); expect_events(vec![UtilityEvent::BatchCompleted.into(), RawEvent::ProxyExecuted(Ok(())).into()]); - assert_noop!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()), Error::::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())); - 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 call = Box::new(Call::Utility(UtilityCall::batch(vec![*inner]))); assert_ok!(Proxy::proxy(Origin::signed(2), 1, None, call.clone())); expect_events(vec![UtilityEvent::BatchCompleted.into(), RawEvent::ProxyExecuted(Ok(())).into()]); - assert_noop!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()), Error::::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())); - 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); let call = Box::new(Call::System(SystemCall::set_code(vec![]))); - assert_noop!(Proxy::proxy(Origin::signed(3), 1, None, call.clone()), Error::::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))); - assert_noop!(Proxy::proxy(Origin::signed(2), 1, None, call.clone()), Error::::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())); expect_event(RawEvent::ProxyExecuted(Ok(()))); assert_eq!(Balances::free_balance(6), 2); diff --git a/frame/randomness-collective-flip/src/lib.rs b/frame/randomness-collective-flip/src/lib.rs index 4a851c926fb74..0cf44de679c33 100644 --- a/frame/randomness-collective-flip/src/lib.rs +++ b/frame/randomness-collective-flip/src/lib.rs @@ -158,6 +158,7 @@ mod tests { } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; diff --git a/frame/recovery/src/mock.rs b/frame/recovery/src/mock.rs index aae9b2b75cf8c..101778f3ea21b 100644 --- a/frame/recovery/src/mock.rs +++ b/frame/recovery/src/mock.rs @@ -64,6 +64,7 @@ parameter_types! { } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Call = Call; type Index = u64; diff --git a/frame/recovery/src/tests.rs b/frame/recovery/src/tests.rs index 5192bdaca85e2..8e9484f0fb089 100644 --- a/frame/recovery/src/tests.rs +++ b/frame/recovery/src/tests.rs @@ -46,7 +46,7 @@ fn set_recovered_works() { // Not accessible by a normal user assert_noop!(Recovery::set_recovered(Origin::signed(1), 5, 1), BadOrigin); // 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 let call = Box::new(Call::Balances(BalancesCall::transfer(1, 100))); assert_ok!(Recovery::as_recovered(Origin::signed(1), 5, call)); diff --git a/frame/scheduler/src/lib.rs b/frame/scheduler/src/lib.rs index cd3aba45ed5ff..00189c6b5d778 100644 --- a/frame/scheduler/src/lib.rs +++ b/frame/scheduler/src/lib.rs @@ -481,8 +481,9 @@ mod tests { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; - type Call = (); + type Call = Call; type Index = u64; type BlockNumber = u64; type Hash = H256; @@ -702,14 +703,14 @@ mod tests { new_test_ext().execute_with(|| { let call = Box::new(Call::Logger(logger::Call::log(69, 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(Origin::ROOT, 4, None, 127, call2)); + assert_ok!(Scheduler::schedule_named(Origin::root(), 1u32.encode(), 4, None, 127, call)); + assert_ok!(Scheduler::schedule(Origin::root(), 4, None, 127, call2)); run_to_block(3); // Scheduled calls are in the agenda. assert_eq!(Agenda::::get(4).len(), 2); assert!(logger::log().is_empty()); - assert_ok!(Scheduler::cancel_named(Origin::ROOT, 1u32.encode())); - assert_ok!(Scheduler::cancel(Origin::ROOT, 4, 1)); + assert_ok!(Scheduler::cancel_named(Origin::root(), 1u32.encode())); + assert_ok!(Scheduler::cancel(Origin::root(), 4, 1)); // Scheduled calls are made NONE, so should not effect state run_to_block(100); assert!(logger::log().is_empty()); diff --git a/frame/scored-pool/src/mock.rs b/frame/scored-pool/src/mock.rs index 1b61bb18846f4..87a56ca27dba0 100644 --- a/frame/scored-pool/src/mock.rs +++ b/frame/scored-pool/src/mock.rs @@ -55,6 +55,7 @@ ord_parameter_types! { } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; diff --git a/frame/session/benchmarking/src/mock.rs b/frame/session/benchmarking/src/mock.rs index bed6509732ffc..ee04f1a04645d 100644 --- a/frame/session/benchmarking/src/mock.rs +++ b/frame/session/benchmarking/src/mock.rs @@ -58,6 +58,7 @@ impl Convert for CurrencyToVoteHandler { pub struct Test; impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = AccountIndex; type BlockNumber = BlockNumber; diff --git a/frame/session/src/mock.rs b/frame/session/src/mock.rs index e7a9896064844..51ca3bc790aad 100644 --- a/frame/session/src/mock.rs +++ b/frame/session/src/mock.rs @@ -173,6 +173,7 @@ parameter_types! { } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; diff --git a/frame/society/src/mock.rs b/frame/society/src/mock.rs index 7ddd25ee6a09b..89a0691b93fed 100644 --- a/frame/society/src/mock.rs +++ b/frame/society/src/mock.rs @@ -65,6 +65,7 @@ ord_parameter_types! { } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; diff --git a/frame/society/src/tests.rs b/frame/society/src/tests.rs index 8f18ecba469b6..0374c7bcd7a60 100644 --- a/frame/society/src/tests.rs +++ b/frame/society/src/tests.rs @@ -813,7 +813,7 @@ fn max_limits_work() { // No candidates because full assert_eq!(Society::candidates().len(), 0); // Increase member limit - assert_ok!(Society::set_max_members(Origin::ROOT, 200)); + assert_ok!(Society::set_max_members(Origin::root(), 200)); // Rotate period run_to_block(16); // Candidates are back! diff --git a/frame/staking/fuzzer/src/mock.rs b/frame/staking/fuzzer/src/mock.rs index 3783415630bc4..d1e471fadb7f7 100644 --- a/frame/staking/fuzzer/src/mock.rs +++ b/frame/staking/fuzzer/src/mock.rs @@ -57,6 +57,7 @@ impl Convert for CurrencyToVoteHandler { pub struct Test; impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type DbWeight = (); type BlockExecutionWeight = (); diff --git a/frame/staking/fuzzer/src/submit_solution.rs b/frame/staking/fuzzer/src/submit_solution.rs index fafd686c9d802..7094c7ed888b2 100644 --- a/frame/staking/fuzzer/src/submit_solution.rs +++ b/frame/staking/fuzzer/src/submit_solution.rs @@ -23,9 +23,9 @@ use honggfuzz::fuzz; use mock::Test; 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 sp_runtime::{traits::Dispatchable, DispatchError}; +use sp_runtime::DispatchError; use sp_core::offchain::{testing::TestOffchainExt, OffchainExt}; use pallet_staking::{EraElectionStatus, ElectionStatus, Module as Staking, Call as StakingCall}; @@ -159,7 +159,7 @@ fn main() { match mode { Mode::WeakerSubmission => { assert_eq!( - call.dispatch(origin.clone().into()).unwrap_err().error, + call.dispatch_bypass_filter(origin.clone().into()).unwrap_err().error, DispatchError::Module { index: 0, error: 16, @@ -170,7 +170,7 @@ fn main() { // NOTE: so exhaustive pattern doesn't work here.. maybe some rust issue? // or due to `#[repr(u32)]`? Mode::InitialSubmission | Mode::StrongerSubmission => { - assert_ok!(call.dispatch(origin.into())); + assert_ok!(call.dispatch_bypass_filter(origin.into())); } }; }) diff --git a/frame/staking/src/benchmarking.rs b/frame/staking/src/benchmarking.rs index 44fc90240380c..1dfa621033362 100644 --- a/frame/staking/src/benchmarking.rs +++ b/frame/staking/src/benchmarking.rs @@ -21,7 +21,7 @@ use super::*; use crate::Module as Staking; use testing_utils::*; -use sp_runtime::{traits::{Dispatchable, One}}; +use sp_runtime::traits::One; use frame_system::RawOrigin; pub use frame_benchmarking::{benchmarks, account}; const SEED: u32 = 0; @@ -379,12 +379,12 @@ benchmarks! { let current_era = CurrentEra::get().unwrap(); let mut points_total = 0; 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() { points_total += 10; points_individual.push((validator.clone(), 10)); - payout_calls.push(Call::::payout_stakers(validator.clone(), current_era)) + payout_calls_arg.push((validator.clone(), current_era)); } // Give Era Points @@ -401,8 +401,8 @@ benchmarks! { let caller: T::AccountId = account("caller", 0, SEED); }: { - for call in payout_calls { - call.dispatch(RawOrigin::Signed(caller.clone()).into())?; + for arg in payout_calls_arg { + >::payout_stakers(RawOrigin::Signed(caller.clone()).into(), arg.0, arg.1)?; } } diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index ef3d2c43bc34b..3860dba90f350 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -200,6 +200,7 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = AccountIndex; type BlockNumber = BlockNumber; diff --git a/frame/staking/src/tests.rs b/frame/staking/src/tests.rs index 078f5e0a79927..eeac2c5c90e38 100644 --- a/frame/staking/src/tests.rs +++ b/frame/staking/src/tests.rs @@ -47,7 +47,7 @@ fn force_unstake_works() { // Force unstake needs correct number of slashing spans (for weight calculation) assert_noop!(Staking::force_unstake(Origin::signed(11), 11, 0), BadOrigin); // 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. assert_eq!(Staking::bonded(&11), None); // Transfer works. @@ -1477,7 +1477,7 @@ fn on_free_balance_zero_stash_removes_validator() { assert_eq!(Balances::total_balance(&11), 0); // 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 assert!(!>::contains_key(&10)); @@ -1533,7 +1533,7 @@ fn on_free_balance_zero_stash_removes_nominator() { assert_eq!(Balances::total_balance(&11), 0); // 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 assert!(!>::contains_key(&10)); @@ -1928,7 +1928,7 @@ fn offence_forces_new_era() { #[test] fn offence_ensures_new_era_without_clobbering() { 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); on_offence_now( @@ -2302,8 +2302,8 @@ fn garbage_collection_after_slashing() { assert_eq!(slashing_spans.iter().count(), 2); // reap_stash respects num_slashing_spans so that weight is accurate - assert_noop!(Staking::reap_stash(Origin::NONE, 11, 0), Error::::IncorrectSlashingSpans); - assert_ok!(Staking::reap_stash(Origin::NONE, 11, 2)); + assert_noop!(Staking::reap_stash(Origin::none(), 11, 0), Error::::IncorrectSlashingSpans); + assert_ok!(Staking::reap_stash(Origin::none(), 11, 2)); assert!(::SlashingSpans::get(&11).is_none()); assert_eq!(::SpanSlash::get(&(11, 0)).amount_slashed(), &0); @@ -2591,11 +2591,11 @@ fn remove_deferred() { // fails if empty assert_noop!( - Staking::cancel_deferred_slash(Origin::ROOT, 1, vec![]), + Staking::cancel_deferred_slash(Origin::root(), 1, vec![]), Error::::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(101), 2000); @@ -2692,21 +2692,21 @@ fn remove_multi_deferred() { // fails if list is not sorted 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::::NotSortedAndUnique ); // fails if list is not unique 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::::NotSortedAndUnique ); // fails if bad index 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::::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 = ::UnappliedSlashes::get(&1); 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() { ExtBuilder::default().build_and_execute(|| { mock::start_era(10); - Staking::set_history_depth(Origin::ROOT, 20, 0).unwrap(); + Staking::set_history_depth(Origin::root(), 20, 0).unwrap(); assert!(::ErasTotalStake::contains_key(10 - 4)); assert!(::ErasTotalStake::contains_key(10 - 5)); - Staking::set_history_depth(Origin::ROOT, 4, 0).unwrap(); + Staking::set_history_depth(Origin::root(), 4, 0).unwrap(); assert!(::ErasTotalStake::contains_key(10 - 4)); assert!(!::ErasTotalStake::contains_key(10 - 5)); - Staking::set_history_depth(Origin::ROOT, 3, 0).unwrap(); + Staking::set_history_depth(Origin::root(), 3, 0).unwrap(); assert!(!::ErasTotalStake::contains_key(10 - 4)); assert!(!::ErasTotalStake::contains_key(10 - 5)); - Staking::set_history_depth(Origin::ROOT, 8, 0).unwrap(); + Staking::set_history_depth(Origin::root(), 8, 0).unwrap(); assert!(!::ErasTotalStake::contains_key(10 - 4)); assert!(!::ErasTotalStake::contains_key(10 - 5)); }); diff --git a/frame/sudo/src/mock.rs b/frame/sudo/src/mock.rs index 54b9100d61961..73c3609d3f6b5 100644 --- a/frame/sudo/src/mock.rs +++ b/frame/sudo/src/mock.rs @@ -113,6 +113,7 @@ parameter_types! { } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Call = Call; type Index = u64; diff --git a/frame/support/src/dispatch.rs b/frame/support/src/dispatch.rs index dd4b6d0b862f9..70a552ce3a5d5 100644 --- a/frame/support/src/dispatch.rs +++ b/frame/support/src/dispatch.rs @@ -29,7 +29,7 @@ pub use crate::weights::{ PaysFee, PostDispatchInfo, WithPostDispatchInfo, }; 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 /// a dispatchable function it allows overriding the default `PostDispatchInfo` @@ -47,10 +47,9 @@ pub type DispatchResult = Result<(), sp_runtime::DispatchError>; pub type DispatchErrorWithPostInfo = sp_runtime::DispatchErrorWithPostInfo; -/// Serializable version of Dispatchable. -/// This value can be used as a "function" in an extrinsic. +/// Serializable version of pallet dispatchable. pub trait Callable { - type Call: Dispatchable + Codec + Clone + PartialEq + Eq; + type Call: UnfilteredDispatchable + Codec + Clone + PartialEq + Eq; } // dirty hack to work around serde_derive issue @@ -1005,6 +1004,7 @@ macro_rules! decl_module { impl<$trait_instance: $trait_name$(, $instance: $instantiable)?> $module<$trait_instance $(, $instance)?> where $( $other_where_bounds )* { + /// Deposits an event using `frame_system::Module::deposit_event`. $vis fn deposit_event( event: impl Into<< $trait_instance as $trait_name $(<$instance>)? >::Event> ) { @@ -1402,6 +1402,8 @@ macro_rules! decl_module { $error_type; $from; $(#[doc = $doc_attr])* + /// + /// NOTE: Calling this function will bypass origin filters. $fn_vis fn $fn_name ( $from $(, $param_name : $param )* ) $( -> $result )* { $( $impl )* } @@ -1546,14 +1548,11 @@ macro_rules! decl_module { } } - impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $crate::dispatch::Dispatchable + impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $crate::traits::UnfilteredDispatchable for $call_type<$trait_instance $(, $instance)?> where $( $other_where_bounds )* { - type Trait = $trait_instance; type Origin = $origin_type; - type Info = $crate::weights::DispatchInfo; - type PostInfo = $crate::weights::PostDispatchInfo; - fn dispatch(self, _origin: Self::Origin) -> $crate::dispatch::DispatchResultWithPostInfo { + fn dispatch_bypass_filter(self, _origin: Self::Origin) -> $crate::dispatch::DispatchResultWithPostInfo { match self { $( $call_type::$fn_name( $( $param_name ),* ) => { @@ -1574,17 +1573,6 @@ macro_rules! decl_module { type Call = $call_type<$trait_instance $(, $instance)?>; } - impl<$trait_instance: $trait_name $(, $instance: $instantiable)?> $mod_type<$trait_instance $(, $instance)?> - where $( $other_where_bounds )* - { - #[doc(hidden)] - pub fn dispatch>( - d: D, - origin: D::Origin - ) -> $crate::dispatch::DispatchResultWithPostInfo { - d.dispatch(origin) - } - } $crate::__dispatch_impl_metadata! { $mod_type<$trait_instance: $trait_name $(, $instance: $instantiable)?> { $( $other_where_bounds )* } @@ -1684,6 +1672,20 @@ macro_rules! impl_outer_dispatch { fn dispatch( self, origin: $origin, + ) -> $crate::dispatch::DispatchResultWithPostInfo { + if !::filter_call(&origin, &self) { + return $crate::sp_std::result::Result::Err($crate::dispatch::DispatchError::BadOrigin.into()) + } + + $crate::traits::UnfilteredDispatchable::dispatch_bypass_filter(self, origin) + } + } + + impl $crate::traits::UnfilteredDispatchable for $call_type { + type Origin = $origin; + fn dispatch_bypass_filter( + self, + origin: $origin, ) -> $crate::dispatch::DispatchResultWithPostInfo { $crate::impl_outer_dispatch! { @DISPATCH_MATCH @@ -1696,6 +1698,7 @@ macro_rules! impl_outer_dispatch { } } } + $( impl $crate::dispatch::IsSubType<$camelcase, $runtime> for $call_type { #[allow(unreachable_patterns)] @@ -1731,7 +1734,8 @@ macro_rules! impl_outer_dispatch { $origin { $( $generated )* - $call_type::$name(call) => call.dispatch($origin), + $call_type::$name(call) => + $crate::traits::UnfilteredDispatchable::dispatch_bypass_filter(call, $origin), } $index + 1; $( $rest ),* @@ -2050,21 +2054,34 @@ mod tests { }; pub trait Trait: system::Trait + Sized where Self::AccountId: From { - type Origin; type BlockNumber: Into; - type Call: From>; } pub mod system { - use super::*; - pub trait Trait { type AccountId; + type Call; + type BaseCallFilter; + type Origin: crate::traits::OriginTrait; } - pub fn ensure_root(_: R) -> DispatchResult { - Ok(()) + #[derive(Clone, PartialEq, Eq, Debug)] + pub enum RawOrigin { + Root, + Signed(AccountId), + None, } + + impl From> for RawOrigin { + fn from(s: Option) -> RawOrigin { + match s { + Some(who) => RawOrigin::Signed(who), + None => RawOrigin::None, + } + } + } + + pub type Origin = RawOrigin<::AccountId>; } decl_module! { @@ -2169,21 +2186,26 @@ mod tests { pub struct TraitImpl {} impl Trait for TraitImpl { - type Origin = u32; type BlockNumber = u32; - type Call = OuterCall; } type Test = Module; + impl_outer_origin!{ + pub enum OuterOrigin for TraitImpl where system = system {} + } + impl_outer_dispatch! { - pub enum OuterCall for TraitImpl where origin: u32 { + pub enum OuterCall for TraitImpl where origin: OuterOrigin { self::Test, } } impl system::Trait for TraitImpl { + type Origin = OuterOrigin; type AccountId = u32; + type Call = OuterCall; + type BaseCallFilter = (); } #[test] diff --git a/frame/support/src/lib.rs b/frame/support/src/lib.rs index 316e356759a17..196bddbdf5bce 100644 --- a/frame/support/src/lib.rs +++ b/frame/support/src/lib.rs @@ -51,14 +51,14 @@ pub use sp_runtime::RuntimeDebug; #[macro_use] pub mod debug; #[macro_use] +mod origin; +#[macro_use] pub mod dispatch; pub mod storage; mod hash; #[macro_use] pub mod event; #[macro_use] -mod origin; -#[macro_use] pub mod metadata; #[macro_use] pub mod inherent; diff --git a/frame/support/src/metadata.rs b/frame/support/src/metadata.rs index 7248d6bc4df5c..d6ec9a7373952 100644 --- a/frame/support/src/metadata.rs +++ b/frame/support/src/metadata.rs @@ -290,6 +290,7 @@ mod tests { use super::*; pub trait Trait: 'static { + type BaseCallFilter; const ASSOCIATED_CONST: u64 = 500; type Origin: Into, Self::Origin>> + From>; @@ -297,6 +298,7 @@ mod tests { type BlockNumber: From + Encode; type SomeValue: Get; type ModuleToIndex: crate::traits::ModuleToIndex; + type Call; } decl_module! { @@ -436,11 +438,13 @@ mod tests { } impl system::Trait for TestRuntime { + type BaseCallFilter = (); type Origin = Origin; type AccountId = u32; type BlockNumber = u32; type SomeValue = SystemValue; type ModuleToIndex = (); + type Call = Call; } impl_runtime_metadata!( diff --git a/frame/support/src/origin.rs b/frame/support/src/origin.rs index f96ec07af0a9c..038c8540f6eca 100644 --- a/frame/support/src/origin.rs +++ b/frame/support/src/origin.rs @@ -45,19 +45,23 @@ macro_rules! impl_outer_origin { $( $rest_with_system:tt )* } ) => { - $crate::impl_outer_origin!( - $( #[$attr] )*; - $name; - $runtime; - $system; - Modules { $( $rest_with_system )* }; - ); + $crate::paste::item! { + $crate::impl_outer_origin!( + $( #[$attr] )*; + $name; + [< $name Caller >]; + $runtime; + $system; + Modules { $( $rest_with_system )* }; + ); + } }; // Generic + Instance ( $(#[$attr:meta])*; $name:ident; + $caller_name:ident; $runtime:ident; $system:ident; Modules { @@ -69,6 +73,7 @@ macro_rules! impl_outer_origin { $crate::impl_outer_origin!( $( #[$attr] )*; $name; + $caller_name; $runtime; $system; Modules { $( $( $rest_module )* )? }; @@ -80,6 +85,7 @@ macro_rules! impl_outer_origin { ( $(#[$attr:meta])*; $name:ident; + $caller_name:ident; $runtime:ident; $system:ident; Modules { @@ -91,6 +97,7 @@ macro_rules! impl_outer_origin { $crate::impl_outer_origin!( $( #[$attr] )*; $name; + $caller_name; $runtime; $system; Modules { $( $rest_module )* }; @@ -102,6 +109,7 @@ macro_rules! impl_outer_origin { ( $(#[$attr:meta])*; $name:ident; + $caller_name:ident; $runtime:ident; $system:ident; Modules { @@ -113,6 +121,7 @@ macro_rules! impl_outer_origin { $crate::impl_outer_origin!( $( #[$attr] )*; $name; + $caller_name; $runtime; $system; Modules { $( $( $rest_module )* )? }; @@ -124,6 +133,7 @@ macro_rules! impl_outer_origin { ( $(#[$attr:meta])*; $name:ident; + $caller_name:ident; $runtime:ident; $system:ident; Modules { @@ -135,6 +145,7 @@ macro_rules! impl_outer_origin { $crate::impl_outer_origin!( $( #[$attr] )*; $name; + $caller_name; $runtime; $system; Modules { $( $( $rest_module )* )? }; @@ -146,16 +157,78 @@ macro_rules! impl_outer_origin { ( $(#[$attr:meta])*; $name:ident; + $caller_name:ident; $runtime:ident; $system:ident; Modules { }; $( $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::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("") + } + } + + #[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.caller = other.into().caller + } + + fn filter_call(&self, call: &Self::Call) -> bool { + (self.filter)(call) + } + } + $crate::paste::item! { #[derive(Clone, PartialEq, Eq, $crate::RuntimeDebug)] $(#[$attr])* #[allow(non_camel_case_types)] - pub enum $name { + pub enum $caller_name { system($system::Origin<$runtime>), $( [< $module $( _ $generic_instance )? >] @@ -168,20 +241,30 @@ macro_rules! impl_outer_origin { #[allow(dead_code)] impl $name { - pub const NONE: Self = $name::system($system::RawOrigin::None); - pub const ROOT: Self = $name::system($system::RawOrigin::Root); + pub fn none() -> Self { + $system::RawOrigin::None.into() + } + pub fn root() -> Self { + $system::RawOrigin::Root.into() + } 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 { 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 { 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) } else { Err(self) @@ -197,7 +280,12 @@ macro_rules! impl_outer_origin { $crate::paste::item! { impl From<$module::Origin < $( $generic )? $(, $module::$generic_instance )? > > for $name { 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< @@ -210,7 +298,7 @@ macro_rules! impl_outer_origin { $module::Origin < $( $generic )? $(, $module::$generic_instance )? >, Self, > { - if let $name::[< $module $( _ $generic_instance )? >](l) = self { + if let $caller_name::[< $module $( _ $generic_instance )? >](l) = self.caller { Ok(l) } else { Err(self) @@ -224,9 +312,12 @@ macro_rules! impl_outer_origin { #[cfg(test)] mod tests { + use crate::traits::{Filter, OriginTrait}; mod system { pub trait Trait { type AccountId; + type Call; + type BaseCallFilter; } #[derive(Clone, PartialEq, Eq, Debug)] @@ -263,8 +354,17 @@ mod tests { #[derive(Clone, PartialEq, Eq, Debug)] pub struct TestRuntime; + pub struct BaseCallFilter; + impl Filter for BaseCallFilter { + fn filter(c: &u32) -> bool { + *c % 2 == 0 + } + } + impl system::Trait for TestRuntime { type AccountId = u32; + type Call = u32; + type BaseCallFilter = BaseCallFilter; } impl_outer_origin!( @@ -298,4 +398,35 @@ mod tests { impl_outer_origin!( 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); + } } diff --git a/frame/support/src/traits.rs b/frame/support/src/traits.rs index 67eff71daf230..833160b61cf00 100644 --- a/frame/support/src/traits.rs +++ b/frame/support/src/traits.rs @@ -1550,6 +1550,63 @@ pub trait EnsureOrigin { 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); + + /// 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: Into + From { + /// 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 IsType 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)] mod tests { use super::*; diff --git a/frame/support/test/tests/decl_error.rs b/frame/support/test/tests/decl_error.rs index 9536d4e8195d4..937e27873b0c7 100644 --- a/frame/support/test/tests/decl_error.rs +++ b/frame/support/test/tests/decl_error.rs @@ -89,12 +89,14 @@ pub type BlockNumber = u64; pub type Index = u64; impl system::Trait for Runtime { + type BaseCallFilter = (); type Hash = H256; type Origin = Origin; type BlockNumber = BlockNumber; type AccountId = AccountId; type Event = Event; type ModuleToIndex = ModuleToIndex; + type Call = Call; } frame_support::construct_runtime!( diff --git a/frame/support/test/tests/instance.rs b/frame/support/test/tests/instance.rs index 45e280902a268..920554346f73e 100644 --- a/frame/support/test/tests/instance.rs +++ b/frame/support/test/tests/instance.rs @@ -233,12 +233,14 @@ pub type BlockNumber = u64; pub type Index = u64; impl system::Trait for Runtime { + type BaseCallFilter= (); type Hash = H256; type Origin = Origin; type BlockNumber = BlockNumber; type AccountId = AccountId; type Event = Event; type ModuleToIndex = (); + type Call = Call; } frame_support::construct_runtime!( diff --git a/frame/support/test/tests/issue2219.rs b/frame/support/test/tests/issue2219.rs index cd357ba2667cb..7166f202c7325 100644 --- a/frame/support/test/tests/issue2219.rs +++ b/frame/support/test/tests/issue2219.rs @@ -158,12 +158,14 @@ pub type Block = generic::Block; pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; impl system::Trait for Runtime { + type BaseCallFilter = (); type Hash = H256; type Origin = Origin; type BlockNumber = BlockNumber; type AccountId = AccountId; type Event = Event; type ModuleToIndex = (); + type Call = Call; } impl module::Trait for Runtime {} diff --git a/frame/support/test/tests/system.rs b/frame/support/test/tests/system.rs index 821224d0a29cf..c3c47d2065130 100644 --- a/frame/support/test/tests/system.rs +++ b/frame/support/test/tests/system.rs @@ -21,9 +21,11 @@ pub trait Trait: 'static + Eq + Clone { type Origin: Into, Self::Origin>> + From>; + type BaseCallFilter: frame_support::traits::Filter; type BlockNumber: Decode + Encode + EncodeLike + Clone + Default; type Hash; type AccountId: Encode + EncodeLike + Decode; + type Call; type Event: From>; type ModuleToIndex: frame_support::traits::ModuleToIndex; } diff --git a/frame/system/benches/bench.rs b/frame/system/benches/bench.rs index 95b9b88c705fb..56fd4b8c35200 100644 --- a/frame/system/benches/bench.rs +++ b/frame/system/benches/bench.rs @@ -61,6 +61,7 @@ frame_support::parameter_types! { #[derive(Clone, Eq, PartialEq)] pub struct Runtime; impl system::Trait for Runtime { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; diff --git a/frame/system/benchmarking/src/mock.rs b/frame/system/benchmarking/src/mock.rs index 1e904302e3b9e..9e41ff20164cd 100644 --- a/frame/system/benchmarking/src/mock.rs +++ b/frame/system/benchmarking/src/mock.rs @@ -51,6 +51,7 @@ impl Dispatchable for Call { pub struct Test; impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = AccountIndex; type BlockNumber = BlockNumber; diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index 1943256651a4d..b38b8c8a4a1ec 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -123,7 +123,7 @@ use frame_support::{ storage, traits::{ Contains, Get, ModuleToIndex, OnNewAccount, OnKilledAccount, IsDeadAccount, Happened, - StoredMap, EnsureOrigin, + StoredMap, EnsureOrigin, OriginTrait, Filter, }, weights::{ Weight, RuntimeDbWeight, DispatchInfo, PostDispatchInfo, DispatchClass, @@ -149,11 +149,15 @@ pub fn extrinsics_data_root(xts: Vec>) -> H::Output { } 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; + + /// The `Origin` type used by dispatchable calls. type Origin: Into, Self::Origin>> + From> - + Clone; + + Clone + + OriginTrait; /// The aggregated `Call` type. type Call: Dispatchable + Debug; @@ -1890,7 +1894,7 @@ pub(crate) mod tests { use sp_core::H256; use sp_runtime::{traits::{BlakeTwo256, IdentityLookup, SignedExtension}, testing::Header, DispatchError}; 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}, }; @@ -1937,7 +1941,7 @@ pub(crate) mod tests { pub struct Call; impl Dispatchable for Call { - type Origin = (); + type Origin = Origin; type Trait = (); type Info = DispatchInfo; type PostInfo = PostDispatchInfo; @@ -1948,6 +1952,7 @@ pub(crate) mod tests { } impl Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Call = Call; type Index = u64; @@ -1997,7 +2002,7 @@ pub(crate) mod tests { fn origin_works() { let o = Origin::from(RawOrigin::::Signed(1u64)); let x: Result, Origin> = o.into(); - assert_eq!(x, Ok(RawOrigin::::Signed(1u64))); + assert_eq!(x.unwrap(), RawOrigin::::Signed(1u64)); } #[test] @@ -2719,8 +2724,8 @@ pub(crate) mod tests { EnsureOneOf::, EnsureSigned>::try_origin(o.into()) } - assert_ok!(ensure_root_or_signed(RawOrigin::Root), Either::Left(())); - assert_ok!(ensure_root_or_signed(RawOrigin::Signed(0)), Either::Right(0)); - assert_err!(ensure_root_or_signed(RawOrigin::None), Origin::from(RawOrigin::None)); + assert_eq!(ensure_root_or_signed(RawOrigin::Root).unwrap(), Either::Left(())); + assert_eq!(ensure_root_or_signed(RawOrigin::Signed(0)).unwrap(), Either::Right(0)); + assert!(ensure_root_or_signed(RawOrigin::None).is_err()) } } diff --git a/frame/timestamp/src/lib.rs b/frame/timestamp/src/lib.rs index 6d38919f31b1b..63456100a5e02 100644 --- a/frame/timestamp/src/lib.rs +++ b/frame/timestamp/src/lib.rs @@ -314,6 +314,7 @@ mod tests { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; @@ -352,7 +353,7 @@ mod tests { fn timestamp_works() { new_test_ext().execute_with(|| { 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); }); } @@ -362,8 +363,8 @@ mod tests { fn double_timestamp_should_fail() { new_test_ext().execute_with(|| { Timestamp::set_timestamp(42); - assert_ok!(Timestamp::dispatch(Call::set(69), Origin::NONE)); - let _ = Timestamp::dispatch(Call::set(70), Origin::NONE); + assert_ok!(Timestamp::set(Origin::none(), 69)); + let _ = Timestamp::set(Origin::none(), 70); }); } @@ -372,7 +373,7 @@ mod tests { fn block_period_minimum_enforced() { new_test_ext().execute_with(|| { Timestamp::set_timestamp(42); - let _ = Timestamp::dispatch(Call::set(46), Origin::NONE); + let _ = Timestamp::set(Origin::none(), 46); }); } } diff --git a/frame/transaction-payment/src/lib.rs b/frame/transaction-payment/src/lib.rs index 8355a58c525d0..740fec099d4a9 100644 --- a/frame/transaction-payment/src/lib.rs +++ b/frame/transaction-payment/src/lib.rs @@ -428,6 +428,7 @@ mod tests { } impl frame_system::Trait for Runtime { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; diff --git a/frame/treasury/src/tests.rs b/frame/treasury/src/tests.rs index 0b68c51a1080c..027e52c1bfb76 100644 --- a/frame/treasury/src/tests.rs +++ b/frame/treasury/src/tests.rs @@ -60,6 +60,7 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; @@ -271,7 +272,7 @@ fn close_tip_works() { assert_noop!(Treasury::close_tip(Origin::signed(0), h.into()), Error::::Premature); 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_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); 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)); >::on_initialize(1); 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); 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)); >::on_initialize(2); 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); assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); - assert_ok!(Treasury::reject_proposal(Origin::ROOT, 0)); - assert_noop!(Treasury::reject_proposal(Origin::ROOT, 0), Error::::InvalidProposalIndex); + assert_ok!(Treasury::reject_proposal(Origin::root(), 0)); + assert_noop!(Treasury::reject_proposal(Origin::root(), 0), Error::::InvalidProposalIndex); }); } #[test] fn reject_non_existent_spend_proposal_fails() { new_test_ext().execute_with(|| { - assert_noop!(Treasury::reject_proposal(Origin::ROOT, 0), Error::::InvalidProposalIndex); + assert_noop!(Treasury::reject_proposal(Origin::root(), 0), Error::::InvalidProposalIndex); }); } #[test] fn accept_non_existent_spend_proposal_fails() { new_test_ext().execute_with(|| { - assert_noop!(Treasury::approve_proposal(Origin::ROOT, 0), Error::::InvalidProposalIndex); + assert_noop!(Treasury::approve_proposal(Origin::root(), 0), Error::::InvalidProposalIndex); }); } @@ -447,8 +448,8 @@ fn accept_already_rejected_spend_proposal_fails() { Balances::make_free_balance_be(&Treasury::account_id(), 101); assert_ok!(Treasury::propose_spend(Origin::signed(0), 100, 3)); - assert_ok!(Treasury::reject_proposal(Origin::ROOT, 0)); - assert_noop!(Treasury::approve_proposal(Origin::ROOT, 0), Error::::InvalidProposalIndex); + assert_ok!(Treasury::reject_proposal(Origin::root(), 0)); + assert_noop!(Treasury::approve_proposal(Origin::root(), 0), Error::::InvalidProposalIndex); }); } @@ -459,7 +460,7 @@ fn accepted_spend_proposal_enacted_on_spend_period() { assert_eq!(Treasury::pot(), 100); 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)); >::on_initialize(2); assert_eq!(Balances::free_balance(3), 100); @@ -474,7 +475,7 @@ fn pot_underflow_should_not_diminish() { assert_eq!(Treasury::pot(), 100); 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)); >::on_initialize(2); 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()); 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)); >::on_initialize(2); assert_eq!(Treasury::pot(), 100); // Pot hasn't changed 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)); >::on_initialize(4); 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_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::approve_proposal(Origin::ROOT, 1)); + assert_ok!(Treasury::approve_proposal(Origin::root(), 1)); >::on_initialize(2); assert_eq!(Treasury::pot(), 0); // Pot hasn't changed assert_eq!(Balances::free_balance(3), 0); // Balance of `3` hasn't changed diff --git a/frame/utility/src/lib.rs b/frame/utility/src/lib.rs index add1049b26c51..3759a2afcd814 100644 --- a/frame/utility/src/lib.rs +++ b/frame/utility/src/lib.rs @@ -54,8 +54,9 @@ use sp_std::prelude::*; use codec::{Encode, Decode}; use sp_core::TypeId; use sp_io::hashing::blake2_256; -use frame_support::{decl_module, decl_event, decl_error, decl_storage, Parameter, ensure}; -use frame_support::{traits::{Filter, FilterStack, ClearFilterGuard}, +use frame_support::{decl_module, decl_event, decl_storage, Parameter}; +use frame_support::{ + traits::{OriginTrait, UnfilteredDispatchable}, weights::{Weight, GetDispatchInfo, DispatchClass}, dispatch::PostDispatchInfo, }; use frame_system::{self as system, ensure_signed, ensure_root}; @@ -71,23 +72,14 @@ pub trait Trait: frame_system::Trait { /// The overarching call type. type Call: Parameter + Dispatchable - + GetDispatchInfo + From>; - - /// Is a given call compatible with the proxying subsystem? - type IsCallable: FilterStack<::Call>; + + GetDispatchInfo + From> + + UnfilteredDispatchable; } decl_storage! { trait Store for Module as Utility {} } -decl_error! { - pub enum Error for Module { - /// A call with a `false` `IsCallable` filter was attempted. - Uncallable, - } -} - decl_event! { /// Events type. pub enum Event { @@ -96,8 +88,6 @@ decl_event! { BatchInterrupted(u32, DispatchError), /// Batch of dispatches completed fully with no error. BatchCompleted, - /// A call with a `false` IsCallable filter was attempted. - Uncallable(u32), } } @@ -111,20 +101,18 @@ impl TypeId for IndexedUtilityModuleId { decl_module! { pub struct Module for enum Call where origin: T::Origin { - type Error = Error; - /// Deposit one of this module's events by using the default implementation. fn deposit_event() = default; /// 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. /// /// - `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`). + /// /// # /// - Base weight: 14.39 + .987 * c µs /// - Plus the sum of the weights of the `calls`. @@ -154,11 +142,11 @@ decl_module! { fn batch(origin, calls: Vec<::Call>) { let is_root = ensure_root(origin.clone()).is_ok(); for (index, call) in calls.into_iter().enumerate() { - if !is_root && !T::IsCallable::filter(&call) { - Self::deposit_event(Event::Uncallable(index as u32)); - return Ok(()) - } - let result = call.dispatch(origin.clone()); + let result = if is_root { + call.dispatch_bypass_filter(origin.clone()) + } else { + call.dispatch(origin.clone()) + }; if let Err(e) = result { Self::deposit_event(Event::BatchInterrupted(index as u32, e.error)); return Ok(()); @@ -169,9 +157,6 @@ decl_module! { /// 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 /// 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. @@ -188,10 +173,8 @@ decl_module! { )] fn as_sub(origin, index: u16, call: Box<::Call>) -> DispatchResult { 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::::Call>::new(); - ensure!(T::IsCallable::filter(&call), Error::::Uncallable); + + // This is a freshly authenticated new account, the origin restrictions doesn't apply. let pseudonym = Self::sub_account_id(who, index); call.dispatch(frame_system::RawOrigin::Signed(pseudonym).into()) .map(|_| ()).map_err(|e| e.error) @@ -199,7 +182,8 @@ decl_module! { /// 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. /// 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, )] fn as_limited_sub(origin, index: u16, call: Box<::Call>) -> DispatchResult { - let who = ensure_signed(origin)?; - ensure!(T::IsCallable::filter(&call), Error::::Uncallable); + let mut origin = origin; + let who = ensure_signed(origin.clone())?; let pseudonym = Self::sub_account_id(who, index); - call.dispatch(frame_system::RawOrigin::Signed(pseudonym).into()) - .map(|_| ()).map_err(|e| e.error) + origin.set_caller_from(frame_system::RawOrigin::Signed(pseudonym)); + call.dispatch(origin).map(|_| ()).map_err(|e| e.error) } } } diff --git a/frame/utility/src/tests.rs b/frame/utility/src/tests.rs index 66a663a38509c..e0f8426d28941 100644 --- a/frame/utility/src/tests.rs +++ b/frame/utility/src/tests.rs @@ -23,7 +23,7 @@ use super::*; use frame_support::{ 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_runtime::{Perbill, traits::{BlakeTwo256, IdentityLookup}, testing::Header}; @@ -59,6 +59,7 @@ parameter_types! { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = TestBaseCallFilter; type Origin = Origin; type Index = u64; type BlockNumber = u64; @@ -98,8 +99,8 @@ parameter_types! { pub const MultisigDepositFactor: u64 = 1; pub const MaxSignatories: u16 = 3; } -pub struct TestIsCallable; -impl Filter for TestIsCallable { +pub struct TestBaseCallFilter; +impl Filter for TestBaseCallFilter { fn filter(c: &Call) -> bool { match *c { Call::Balances(_) => true, @@ -107,17 +108,9 @@ impl Filter for TestIsCallable { } } } -impl FilterStack 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 { type Event = TestEvent; type Call = Call; - type IsCallable = TestIsCallable; } type System = frame_system::Module; type Balances = pallet_balances::Module; @@ -171,21 +164,26 @@ fn as_sub_filters() { Origin::signed(1), 1, Box::new(Call::System(frame_system::Call::remark(vec![]))), - ), Error::::Uncallable); + ), DispatchError::BadOrigin); }); } #[test] fn batch_with_root_works() { 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(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, // Check filters are correctly bypassed ])); assert_eq!(Balances::free_balance(1), 0); 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![])) ]), ); - expect_event(Event::Uncallable(0)); + expect_event(Event::BatchInterrupted(0, DispatchError::BadOrigin)); }); } diff --git a/frame/vesting/src/lib.rs b/frame/vesting/src/lib.rs index 63a092da309c6..5893869c91042 100644 --- a/frame/vesting/src/lib.rs +++ b/frame/vesting/src/lib.rs @@ -380,6 +380,7 @@ mod tests { pub const AvailableBlockRatio: Perbill = Perbill::one(); } impl frame_system::Trait for Test { + type BaseCallFilter = (); type Origin = Origin; type Index = u64; type BlockNumber = u64; diff --git a/primitives/runtime/src/traits.rs b/primitives/runtime/src/traits.rs index fb46ba1dfa92b..b1739269e66be 100644 --- a/primitives/runtime/src/traits.rs +++ b/primitives/runtime/src/traits.rs @@ -144,7 +144,7 @@ impl< } /// An error type that indicates that the origin is invalid. -#[derive(Encode, Decode)] +#[derive(Encode, Decode, RuntimeDebug)] pub struct BadOrigin; impl From for &'static str { diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index bf6c7450c5086..eaac618b44e38 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -184,7 +184,7 @@ impl ExtrinsicT for Extrinsic { } impl sp_runtime::traits::Dispatchable for Extrinsic { - type Origin = (); + type Origin = Origin; type Trait = (); type Info = (); type PostInfo = (); @@ -401,6 +401,7 @@ parameter_types! { } impl frame_system::Trait for Runtime { + type BaseCallFilter = (); type Origin = Origin; type Call = Extrinsic; type Index = u64;