diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index c0ad9bb006c92..570abe53ed01f 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -226,6 +226,7 @@ impl pallet_randomness_collective_flip::Config for Runtime {} impl pallet_utility::Config for Runtime { type Event = Event; type Call = Call; + type PalletsOrigin = OriginCaller; type WeightInfo = pallet_utility::weights::SubstrateWeight; } diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index 310c1d4cb2dd9..bd5dbae5b34a6 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -244,6 +244,7 @@ impl pallet_timestamp::Config for Test { impl pallet_utility::Config for Test { type Event = Event; type Call = Call; + type PalletsOrigin = OriginCaller; type WeightInfo = (); } parameter_types! { diff --git a/frame/proxy/src/tests.rs b/frame/proxy/src/tests.rs index 20efd085fe882..93a0e4ce7d622 100644 --- a/frame/proxy/src/tests.rs +++ b/frame/proxy/src/tests.rs @@ -96,6 +96,7 @@ impl pallet_balances::Config for Test { impl pallet_utility::Config for Test { type Event = Event; type Call = Call; + type PalletsOrigin = OriginCaller; type WeightInfo = (); } parameter_types! { diff --git a/frame/utility/src/benchmarking.rs b/frame/utility/src/benchmarking.rs index 70cc61f87b9c9..ce59d7e898eb1 100644 --- a/frame/utility/src/benchmarking.rs +++ b/frame/utility/src/benchmarking.rs @@ -30,6 +30,7 @@ fn assert_last_event(generic_event: ::Event) { } benchmarks! { + where_clause { where ::PalletsOrigin: Clone } batch { let c in 0 .. 1000; let mut calls: Vec<::Call> = Vec::new(); @@ -64,5 +65,13 @@ benchmarks! { assert_last_event::(Event::BatchCompleted.into()) } + dispatch_as { + let caller = account("caller", SEED, SEED); + let call = Box::new(frame_system::Call::remark { remark: vec![] }.into()); + let origin: T::Origin = RawOrigin::Signed(caller).into(); + let pallets_origin: ::PalletsOrigin = origin.caller().clone(); + let pallets_origin = Into::::into(pallets_origin.clone()); + }: _(RawOrigin::Root, Box::new(pallets_origin), call) + impl_benchmark_test_suite!(Pallet, crate::tests::new_test_ext(), crate::tests::Test); } diff --git a/frame/utility/src/lib.rs b/frame/utility/src/lib.rs index 8712cf74f451b..241526cef2230 100644 --- a/frame/utility/src/lib.rs +++ b/frame/utility/src/lib.rs @@ -96,6 +96,11 @@ pub mod pallet { + IsSubType> + IsType<::Call>; + /// The caller origin, overarching type of all pallets origins. + type PalletsOrigin: Parameter + + Into<::Origin> + + IsType<<::Origin as frame_support::traits::OriginTrait>::PalletsOrigin>; + /// Weight information for extrinsics in this pallet. type WeightInfo: WeightInfo; } @@ -110,6 +115,8 @@ pub mod pallet { BatchCompleted, /// A single item within a Batch of dispatches has completed with no error. ItemCompleted, + /// A call was dispatched. \[result\] + DispatchedAs(DispatchResult), } // Align the call size to 1KB. As we are currently compiling the runtime for native/wasm @@ -342,6 +349,37 @@ pub mod pallet { let base_weight = T::WeightInfo::batch_all(calls_len as u32); Ok(Some(base_weight + weight).into()) } + + /// Dispatches a function call with a provided origin. + /// + /// The dispatch origin for this call must be _Root_. + /// + /// # + /// - O(1). + /// - Limited storage reads. + /// - One DB write (event). + /// - Weight of derivative `call` execution + T::WeightInfo::dispatch_as(). + /// # + #[pallet::weight({ + let dispatch_info = call.get_dispatch_info(); + ( + T::WeightInfo::dispatch_as() + .saturating_add(dispatch_info.weight), + dispatch_info.class, + ) + })] + pub fn dispatch_as( + origin: OriginFor, + as_origin: Box, + call: Box<::Call>, + ) -> DispatchResult { + ensure_root(origin)?; + + let res = call.dispatch_bypass_filter((*as_origin).into()); + + Self::deposit_event(Event::DispatchedAs(res.map(|_| ()).map_err(|e| e.error))); + Ok(()) + } } } diff --git a/frame/utility/src/tests.rs b/frame/utility/src/tests.rs index cb7a3d9a21e29..f4d09a30ec078 100644 --- a/frame/utility/src/tests.rs +++ b/frame/utility/src/tests.rs @@ -168,6 +168,7 @@ impl Contains for TestBaseCallFilter { impl Config for Test { type Event = Event; type Call = Call; + type PalletsOrigin = OriginCaller; type WeightInfo = (); } diff --git a/frame/utility/src/weights.rs b/frame/utility/src/weights.rs index 6ac23419e3ef7..bce18271684bc 100644 --- a/frame/utility/src/weights.rs +++ b/frame/utility/src/weights.rs @@ -18,7 +18,7 @@ //! Autogenerated weights for pallet_utility //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-08-07, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2021-10-30, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 // Executed Command: @@ -48,39 +48,46 @@ pub trait WeightInfo { fn batch(c: u32, ) -> Weight; fn as_derivative() -> Weight; fn batch_all(c: u32, ) -> Weight; + fn dispatch_as() -> Weight; } /// Weights for pallet_utility using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { fn batch(c: u32, ) -> Weight { - (30_319_000 as Weight) + (18_293_000 as Weight) // Standard Error: 3_000 - .saturating_add((6_759_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((5_530_000 as Weight).saturating_mul(c as Weight)) } fn as_derivative() -> Weight { - (4_030_000 as Weight) + (3_387_000 as Weight) } fn batch_all(c: u32, ) -> Weight { - (26_621_000 as Weight) - // Standard Error: 3_000 - .saturating_add((7_251_000 as Weight).saturating_mul(c as Weight)) + (19_223_000 as Weight) + // Standard Error: 4_000 + .saturating_add((5_998_000 as Weight).saturating_mul(c as Weight)) + } + fn dispatch_as() -> Weight { + (14_340_000 as Weight) } } // For backwards compatibility and tests impl WeightInfo for () { fn batch(c: u32, ) -> Weight { - (30_319_000 as Weight) + (18_293_000 as Weight) // Standard Error: 3_000 - .saturating_add((6_759_000 as Weight).saturating_mul(c as Weight)) + .saturating_add((5_530_000 as Weight).saturating_mul(c as Weight)) } fn as_derivative() -> Weight { - (4_030_000 as Weight) + (3_387_000 as Weight) } fn batch_all(c: u32, ) -> Weight { - (26_621_000 as Weight) - // Standard Error: 3_000 - .saturating_add((7_251_000 as Weight).saturating_mul(c as Weight)) + (19_223_000 as Weight) + // Standard Error: 4_000 + .saturating_add((5_998_000 as Weight).saturating_mul(c as Weight)) + } + fn dispatch_as() -> Weight { + (14_340_000 as Weight) } }