frame_system_benchmarking/
inner.rs1use alloc::{vec, vec::Vec};
21use codec::Encode;
22use frame_benchmarking::v2::*;
23use frame_support::{dispatch::DispatchClass, storage, traits::Get};
24use frame_system::{Call, Pallet as System, RawOrigin};
25use sp_core::storage::well_known_keys;
26use sp_runtime::traits::Hash;
27
28pub struct Pallet<T: Config>(System<T>);
29pub trait Config: frame_system::Config {
30 fn prepare_set_code_data() -> Vec<u8> {
34 include_bytes!("../res/kitchensink_runtime.compact.compressed.wasm").to_vec()
35 }
36
37 fn setup_set_code_requirements(_code: &Vec<u8>) -> Result<(), BenchmarkError> {
39 Ok(())
40 }
41
42 fn verify_set_code() {
46 let code = Self::prepare_set_code_data();
47 let hash = Self::Hashing::hash(&code);
48 let want: Self::RuntimeEvent = frame_system::Event::<Self>::CodeUpdated { hash }.into();
49
50 System::<Self>::assert_last_event(want);
51 }
52}
53
54#[benchmarks]
55mod benchmarks {
56 use super::*;
57
58 #[benchmark]
59 fn remark(
60 b: Linear<0, { *T::BlockLength::get().max.get(DispatchClass::Normal) as u32 }>,
61 ) -> Result<(), BenchmarkError> {
62 let remark_message = vec![1; b as usize];
63 let caller = whitelisted_caller();
64
65 #[extrinsic_call]
66 remark(RawOrigin::Signed(caller), remark_message);
67
68 Ok(())
69 }
70
71 #[benchmark]
72 fn remark_with_event(
73 b: Linear<0, { *T::BlockLength::get().max.get(DispatchClass::Normal) as u32 }>,
74 ) -> Result<(), BenchmarkError> {
75 let remark_message = vec![1; b as usize];
76 let caller: T::AccountId = whitelisted_caller();
77 let hash = T::Hashing::hash(&remark_message[..]);
78
79 #[extrinsic_call]
80 remark_with_event(RawOrigin::Signed(caller.clone()), remark_message);
81
82 System::<T>::assert_last_event(
83 frame_system::Event::<T>::Remarked { sender: caller, hash }.into(),
84 );
85 Ok(())
86 }
87
88 #[benchmark]
89 fn set_heap_pages() -> Result<(), BenchmarkError> {
90 #[extrinsic_call]
91 set_heap_pages(RawOrigin::Root, Default::default());
92
93 Ok(())
94 }
95
96 #[benchmark]
97 fn set_code() -> Result<(), BenchmarkError> {
98 let runtime_blob = T::prepare_set_code_data();
99 T::setup_set_code_requirements(&runtime_blob)?;
100
101 #[extrinsic_call]
102 set_code(RawOrigin::Root, runtime_blob);
103
104 T::verify_set_code();
105 Ok(())
106 }
107
108 #[benchmark(extra)]
109 fn set_code_without_checks() -> Result<(), BenchmarkError> {
110 let code = vec![1; 4_000_000 as usize];
112 T::setup_set_code_requirements(&code)?;
113
114 #[block]
115 {
116 System::<T>::set_code_without_checks(RawOrigin::Root.into(), code)?;
117 }
118
119 let code = storage::unhashed::get_raw(well_known_keys::CODE).ok_or("Code not stored.")?;
120 assert_eq!(code.len(), 4_000_000 as usize);
121 Ok(())
122 }
123
124 #[benchmark(skip_meta)]
125 fn set_storage(i: Linear<0, { 1_000 }>) -> Result<(), BenchmarkError> {
126 let mut items = Vec::new();
128 for j in 0..i {
129 let hash = (i, j).using_encoded(T::Hashing::hash).as_ref().to_vec();
130 items.push((hash.clone(), hash.clone()));
131 }
132
133 let items_to_verify = items.clone();
134
135 #[extrinsic_call]
136 set_storage(RawOrigin::Root, items);
137
138 for (item, _) in items_to_verify {
140 let value = storage::unhashed::get_raw(&item).ok_or("No value stored")?;
141 assert_eq!(value, *item);
142 }
143 Ok(())
144 }
145
146 #[benchmark(skip_meta)]
147 fn kill_storage(i: Linear<0, { 1_000 }>) -> Result<(), BenchmarkError> {
148 let mut items = Vec::with_capacity(i as usize);
150 for j in 0..i {
151 let hash = (i, j).using_encoded(T::Hashing::hash).as_ref().to_vec();
152 storage::unhashed::put_raw(&hash, &hash);
153 items.push(hash);
154 }
155
156 for item in &items {
158 let value = storage::unhashed::get_raw(item).ok_or("No value stored")?;
159 assert_eq!(value, *item);
160 }
161
162 let items_to_verify = items.clone();
163
164 #[extrinsic_call]
165 kill_storage(RawOrigin::Root, items);
166
167 for item in items_to_verify {
169 assert!(storage::unhashed::get_raw(&item).is_none());
170 }
171 Ok(())
172 }
173
174 #[benchmark(skip_meta)]
175 fn kill_prefix(p: Linear<0, { 1_000 }>) -> Result<(), BenchmarkError> {
176 let prefix = p.using_encoded(T::Hashing::hash).as_ref().to_vec();
177 let mut items = Vec::with_capacity(p as usize);
178 for i in 0..p {
180 let hash = (p, i).using_encoded(T::Hashing::hash).as_ref().to_vec();
181 let key = [&prefix[..], &hash[..]].concat();
182 storage::unhashed::put_raw(&key, &key);
183 items.push(key);
184 }
185
186 for item in &items {
188 let value = storage::unhashed::get_raw(item).ok_or("No value stored")?;
189 assert_eq!(value, *item);
190 }
191
192 #[extrinsic_call]
193 kill_prefix(RawOrigin::Root, prefix, p);
194
195 for item in items {
197 assert!(storage::unhashed::get_raw(&item).is_none());
198 }
199 Ok(())
200 }
201
202 #[benchmark]
203 fn authorize_upgrade() -> Result<(), BenchmarkError> {
204 let runtime_blob = T::prepare_set_code_data();
205 T::setup_set_code_requirements(&runtime_blob)?;
206 let hash = T::Hashing::hash(&runtime_blob);
207
208 #[extrinsic_call]
209 authorize_upgrade(RawOrigin::Root, hash);
210
211 assert_eq!(System::<T>::authorized_upgrade().unwrap().code_hash(), &hash);
212 Ok(())
213 }
214
215 #[benchmark]
216 fn apply_authorized_upgrade() -> Result<(), BenchmarkError> {
217 let runtime_blob = T::prepare_set_code_data();
218 T::setup_set_code_requirements(&runtime_blob)?;
219 let hash = T::Hashing::hash(&runtime_blob);
220 System::<T>::authorize_upgrade(RawOrigin::Root.into(), hash)?;
222
223 #[extrinsic_call]
224 apply_authorized_upgrade(RawOrigin::Root, runtime_blob);
225
226 assert!(System::<T>::authorized_upgrade().is_none());
229 Ok(())
230 }
231
232 impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test);
233}