referrerpolicy=no-referrer-when-downgrade

pallet_meta_tx/
benchmarking.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18#![cfg(feature = "runtime-benchmarks")]
19
20use super::*;
21use frame_benchmarking::v2::*;
22use frame_support::traits::UnfilteredDispatchable;
23use sp_runtime::impl_tx_ext_default;
24
25pub mod types {
26	use super::*;
27	use frame_support::traits::OriginTrait;
28	use sp_runtime::traits::DispatchInfoOf;
29
30	type CallOf<T> = <T as frame_system::Config>::RuntimeCall;
31
32	/// A weightless extension to facilitate the bare dispatch benchmark.
33	#[derive(TypeInfo, Eq, PartialEq, Clone, Encode, Decode, DecodeWithMemTracking)]
34	#[scale_info(skip_type_params(T))]
35	pub struct WeightlessExtension<T>(core::marker::PhantomData<T>);
36	impl<T: Config + Send + Sync> core::fmt::Debug for WeightlessExtension<T> {
37		fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
38			write!(f, "WeightlessExtension")
39		}
40	}
41	impl<T: Config + Send + Sync> Default for WeightlessExtension<T> {
42		fn default() -> Self {
43			WeightlessExtension(Default::default())
44		}
45	}
46	impl<T: Config + Send + Sync> TransactionExtension<CallOf<T>> for WeightlessExtension<T> {
47		const IDENTIFIER: &'static str = "WeightlessExtension";
48		type Implicit = ();
49		type Pre = ();
50		type Val = ();
51		fn weight(&self, _call: &CallOf<T>) -> Weight {
52			Weight::from_all(0)
53		}
54		fn validate(
55			&self,
56			mut origin: <CallOf<T> as Dispatchable>::RuntimeOrigin,
57			_: &CallOf<T>,
58			_: &DispatchInfoOf<CallOf<T>>,
59			_: usize,
60			_: (),
61			_: &impl Encode,
62			_: TransactionSource,
63		) -> Result<
64			(ValidTransaction, Self::Val, <CallOf<T> as Dispatchable>::RuntimeOrigin),
65			TransactionValidityError,
66		> {
67			origin.set_caller_from_signed(whitelisted_caller());
68			Ok((ValidTransaction::default(), (), origin))
69		}
70
71		impl_tx_ext_default!(CallOf<T>; prepare);
72	}
73}
74
75fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
76	frame_system::Pallet::<T>::assert_last_event(generic_event.into());
77}
78
79#[benchmarks(
80	where
81		T: Config,
82		<T as Config>::Extension: Default,
83	)]
84mod benchmarks {
85	use super::*;
86
87	#[benchmark]
88	fn bare_dispatch() {
89		let meta_call = frame_system::Call::<T>::remark { remark: vec![] }.into();
90		let meta_ext = T::Extension::default();
91		let meta_ext_weight = meta_ext.weight(&meta_call);
92
93		#[cfg(not(test))]
94		assert!(
95			meta_ext_weight.is_zero(),
96			"meta tx extension weight for the benchmarks must be zero. \
97			use `pallet_meta_tx::WeightlessExtension` as `pallet_meta_tx::Config::Extension` \
98			with the `runtime-benchmarks` feature enabled.",
99		);
100
101		let meta_tx = MetaTxFor::<T>::new(meta_call.clone(), 0u8, meta_ext.clone());
102
103		let caller = whitelisted_caller();
104		let origin: <T as frame_system::Config>::RuntimeOrigin =
105			frame_system::RawOrigin::Signed(caller).into();
106		let call = Call::<T>::dispatch { meta_tx: Box::new(meta_tx) };
107
108		#[block]
109		{
110			let _ = call.dispatch_bypass_filter(origin);
111		}
112
113		let info = meta_call.get_dispatch_info();
114		assert_last_event::<T>(
115			Event::Dispatched {
116				result: Ok(PostDispatchInfo {
117					actual_weight: Some(info.call_weight + meta_ext_weight),
118					pays_fee: Pays::Yes,
119				}),
120			}
121			.into(),
122		);
123	}
124
125	impl_benchmark_test_suite! {
126		Pallet,
127		crate::mock::new_test_ext(),
128		crate::mock::Runtime,
129	}
130}