pallet_meta_tx/
benchmarking.rs1#![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 #[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 codec::Compact;
86
87 use super::*;
88
89 #[benchmark]
90 fn bare_dispatch(n: Linear<8, 100>) {
91 let meta_call = frame_system::Call::<T>::remark { remark: vec![] }.into();
92 let meta_ext = T::Extension::default();
93 let meta_ext_weight = meta_ext.weight(&meta_call);
94
95 #[cfg(not(test))]
96 assert!(
97 meta_ext_weight.is_zero(),
98 "meta tx extension weight for the benchmarks must be zero. \
99 use `pallet_meta_tx::WeightlessExtension` as `pallet_meta_tx::Config::Extension` \
100 with the `runtime-benchmarks` feature enabled.",
101 );
102
103 let meta_tx = MetaTxFor::<T>::new(meta_call.clone(), 0u8, meta_ext.clone());
104
105 let caller = whitelisted_caller();
106 let origin: <T as frame_system::Config>::RuntimeOrigin =
107 frame_system::RawOrigin::Signed(caller).into();
108 let call = Call::<T>::dispatch {
109 meta_tx: Box::new(meta_tx.clone()),
110 meta_tx_encoded_len: meta_tx.encoded_size() as u32,
111 };
112
113 let length_of_compact_vec = ((n - 4) / 4) as usize;
116 let mut compact_vec = Vec::<Compact<u16>>::with_capacity(length_of_compact_vec);
117 for _ in 0..length_of_compact_vec {
118 compact_vec.push(Compact::from(0xffff));
119 }
120
121 #[block]
122 {
123 let _ = compact_vec.encode();
124 let _ = call.dispatch_bypass_filter(origin);
125 }
126
127 let info = meta_call.get_dispatch_info();
128 assert_last_event::<T>(
129 Event::Dispatched {
130 result: Ok(PostDispatchInfo {
131 actual_weight: Some(info.call_weight + meta_ext_weight),
132 pays_fee: Pays::Yes,
133 }),
134 }
135 .into(),
136 );
137 }
138
139 impl_benchmark_test_suite! {
140 Pallet,
141 crate::mock::new_test_ext(),
142 crate::mock::Runtime,
143 }
144}