referrerpolicy=no-referrer-when-downgrade

pallet_identity/
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//! Identity pallet benchmarking.
19
20#![cfg(feature = "runtime-benchmarks")]
21
22use super::*;
23
24use crate::{migration::v2::LazyMigrationV1ToV2, Pallet as Identity};
25use alloc::{vec, vec::Vec};
26use frame_benchmarking::{account, v2::*, whitelisted_caller, BenchmarkError};
27use frame_support::{
28	assert_ok, ensure,
29	traits::{EnsureOrigin, Get, OnFinalize, OnInitialize},
30};
31use frame_system::RawOrigin;
32use sp_runtime::traits::{Bounded, One};
33
34const SEED: u32 = 0;
35
36fn assert_has_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
37	frame_system::Pallet::<T>::assert_has_event(generic_event.into());
38}
39
40fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
41	frame_system::Pallet::<T>::assert_last_event(generic_event.into());
42}
43
44fn run_to_block<T: Config>(n: frame_system::pallet_prelude::BlockNumberFor<T>) {
45	while frame_system::Pallet::<T>::block_number() < n {
46		crate::Pallet::<T>::on_finalize(frame_system::Pallet::<T>::block_number());
47		frame_system::Pallet::<T>::on_finalize(frame_system::Pallet::<T>::block_number());
48		frame_system::Pallet::<T>::set_block_number(
49			frame_system::Pallet::<T>::block_number() + One::one(),
50		);
51		frame_system::Pallet::<T>::on_initialize(frame_system::Pallet::<T>::block_number());
52		crate::Pallet::<T>::on_initialize(frame_system::Pallet::<T>::block_number());
53	}
54}
55
56// Adds `r` registrars to the Identity Pallet. These registrars will have set fees and fields.
57fn add_registrars<T: Config>(r: u32) -> Result<(), &'static str> {
58	for i in 0..r {
59		let registrar: T::AccountId = account("registrar", i, SEED);
60		let registrar_lookup = T::Lookup::unlookup(registrar.clone());
61		let _ = T::Currency::make_free_balance_be(&registrar, BalanceOf::<T>::max_value());
62		let registrar_origin = T::RegistrarOrigin::try_successful_origin()
63			.expect("RegistrarOrigin has no successful origin required for the benchmark");
64		Identity::<T>::add_registrar(registrar_origin, registrar_lookup)?;
65		Identity::<T>::set_fee(RawOrigin::Signed(registrar.clone()).into(), i, 10u32.into())?;
66		let fields = T::IdentityInformation::all_fields();
67		Identity::<T>::set_fields(RawOrigin::Signed(registrar.clone()).into(), i, fields)?;
68	}
69
70	assert_eq!(Registrars::<T>::get().len(), r as usize);
71	Ok(())
72}
73
74// Create `s` sub-accounts for the identity of `who` and return them.
75// Each will have 32 bytes of raw data added to it.
76fn create_sub_accounts<T: Config>(
77	who: &T::AccountId,
78	s: u32,
79) -> Result<Vec<(T::AccountId, Data)>, &'static str> {
80	let mut subs = Vec::new();
81	let who_origin = RawOrigin::Signed(who.clone());
82	let data = Data::Raw(vec![0; 32].try_into().unwrap());
83
84	for i in 0..s {
85		let sub_account = account("sub", i, SEED);
86		subs.push((sub_account, data.clone()));
87	}
88
89	// Set identity so `set_subs` does not fail.
90	if IdentityOf::<T>::get(who).is_none() {
91		let _ = T::Currency::make_free_balance_be(who, BalanceOf::<T>::max_value() / 2u32.into());
92		let info = T::IdentityInformation::create_identity_info();
93		Identity::<T>::set_identity(who_origin.into(), Box::new(info))?;
94	}
95
96	Ok(subs)
97}
98
99// Adds `s` sub-accounts to the identity of `who`. Each will have 32 bytes of raw data added to it.
100// This additionally returns the vector of sub-accounts so it can be modified if needed.
101fn add_sub_accounts<T: Config>(
102	who: &T::AccountId,
103	s: u32,
104) -> Result<Vec<(T::AccountId, Data)>, &'static str> {
105	let who_origin = RawOrigin::Signed(who.clone());
106	let subs = create_sub_accounts::<T>(who, s)?;
107
108	Identity::<T>::set_subs(who_origin.into(), subs.clone())?;
109
110	Ok(subs)
111}
112
113fn bench_suffix() -> Vec<u8> {
114	b"bench".to_vec()
115}
116
117fn bench_username() -> Vec<u8> {
118	// len = 24
119	b"veryfastbenchmarkmachine".to_vec()
120}
121
122fn bounded_username<T: Config>(username: Vec<u8>, suffix: Vec<u8>) -> Username<T> {
123	let mut full_username = Vec::with_capacity(username.len() + suffix.len() + 1);
124	full_username.extend(username);
125	full_username.extend(b".");
126	full_username.extend(suffix);
127	Username::<T>::try_from(full_username).expect("test usernames should fit within bounds")
128}
129
130#[benchmarks]
131mod benchmarks {
132	use super::*;
133
134	#[benchmark]
135	fn add_registrar(r: Linear<1, { T::MaxRegistrars::get() - 1 }>) -> Result<(), BenchmarkError> {
136		add_registrars::<T>(r)?;
137		ensure!(Registrars::<T>::get().len() as u32 == r, "Registrars not set up correctly.");
138		let origin =
139			T::RegistrarOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
140		let account = T::Lookup::unlookup(account("registrar", r + 1, SEED));
141
142		#[extrinsic_call]
143		_(origin as T::RuntimeOrigin, account);
144
145		ensure!(Registrars::<T>::get().len() as u32 == r + 1, "Registrars not added.");
146		Ok(())
147	}
148
149	#[benchmark]
150	fn set_identity(r: Linear<1, { T::MaxRegistrars::get() }>) -> Result<(), BenchmarkError> {
151		add_registrars::<T>(r)?;
152
153		let caller: T::AccountId = whitelisted_caller();
154		let caller_lookup = T::Lookup::unlookup(caller.clone());
155		let caller_origin: <T as frame_system::Config>::RuntimeOrigin =
156			RawOrigin::Signed(caller.clone()).into();
157		let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
158
159		// Add an initial identity
160		let initial_info = T::IdentityInformation::create_identity_info();
161		Identity::<T>::set_identity(caller_origin.clone(), Box::new(initial_info.clone()))?;
162
163		// User requests judgement from all the registrars, and they approve
164		for i in 0..r {
165			let registrar: T::AccountId = account("registrar", i, SEED);
166			let _ = T::Lookup::unlookup(registrar.clone());
167			let balance_to_use = T::Currency::minimum_balance() * 10u32.into();
168			let _ = T::Currency::make_free_balance_be(&registrar, balance_to_use);
169
170			Identity::<T>::request_judgement(caller_origin.clone(), i, 10u32.into())?;
171			Identity::<T>::provide_judgement(
172				RawOrigin::Signed(registrar).into(),
173				i,
174				caller_lookup.clone(),
175				Judgement::Reasonable,
176				T::Hashing::hash_of(&initial_info),
177			)?;
178		}
179
180		#[extrinsic_call]
181		_(
182			RawOrigin::Signed(caller.clone()),
183			Box::new(T::IdentityInformation::create_identity_info()),
184		);
185
186		assert_last_event::<T>(Event::<T>::IdentitySet { who: caller }.into());
187		Ok(())
188	}
189
190	// We need to split `set_subs` into two benchmarks to accurately isolate the potential
191	// writes caused by new or old sub accounts. The actual weight should simply be
192	// the sum of these two weights.
193	#[benchmark]
194	fn set_subs_new(s: Linear<0, { T::MaxSubAccounts::get() }>) -> Result<(), BenchmarkError> {
195		let caller: T::AccountId = whitelisted_caller();
196
197		// Create a new subs vec with sub accounts
198		let subs = create_sub_accounts::<T>(&caller, s)?;
199		ensure!(SubsOf::<T>::get(&caller).1.len() == 0, "Caller already has subs");
200
201		#[extrinsic_call]
202		set_subs(RawOrigin::Signed(caller.clone()), subs);
203
204		ensure!(SubsOf::<T>::get(&caller).1.len() as u32 == s, "Subs not added");
205		Ok(())
206	}
207
208	#[benchmark]
209	fn set_subs_old(p: Linear<0, { T::MaxSubAccounts::get() }>) -> Result<(), BenchmarkError> {
210		let caller: T::AccountId = whitelisted_caller();
211
212		// Give them p many previous sub accounts.
213		add_sub_accounts::<T>(&caller, p)?;
214
215		// Remove all subs.
216		let subs = create_sub_accounts::<T>(&caller, 0)?;
217		ensure!(SubsOf::<T>::get(&caller).1.len() as u32 == p, "Caller does have subs",);
218
219		#[extrinsic_call]
220		set_subs(RawOrigin::Signed(caller.clone()), subs);
221
222		ensure!(SubsOf::<T>::get(&caller).1.len() == 0, "Subs not removed");
223		Ok(())
224	}
225
226	#[benchmark]
227	fn clear_identity(
228		r: Linear<1, { T::MaxRegistrars::get() }>,
229		s: Linear<0, { T::MaxSubAccounts::get() }>,
230	) -> Result<(), BenchmarkError> {
231		let caller: T::AccountId = whitelisted_caller();
232		let caller_origin =
233			<T as frame_system::Config>::RuntimeOrigin::from(RawOrigin::Signed(caller.clone()));
234		let caller_lookup = <T::Lookup as StaticLookup>::unlookup(caller.clone());
235		let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
236
237		// Register the registrars
238		add_registrars::<T>(r)?;
239
240		// Add sub accounts
241		add_sub_accounts::<T>(&caller, s)?;
242
243		// Create their main identity with x additional fields
244		let info = T::IdentityInformation::create_identity_info();
245		Identity::<T>::set_identity(caller_origin.clone(), Box::new(info.clone()))?;
246
247		// User requests judgement from all the registrars, and they approve
248		for i in 0..r {
249			let registrar: T::AccountId = account("registrar", i, SEED);
250			let balance_to_use = T::Currency::minimum_balance() * 10u32.into();
251			let _ = T::Currency::make_free_balance_be(&registrar, balance_to_use);
252
253			Identity::<T>::request_judgement(caller_origin.clone(), i, 10u32.into())?;
254			Identity::<T>::provide_judgement(
255				RawOrigin::Signed(registrar).into(),
256				i,
257				caller_lookup.clone(),
258				Judgement::Reasonable,
259				T::Hashing::hash_of(&info),
260			)?;
261		}
262
263		ensure!(IdentityOf::<T>::contains_key(&caller), "Identity does not exist.");
264
265		#[extrinsic_call]
266		_(RawOrigin::Signed(caller.clone()));
267
268		ensure!(!IdentityOf::<T>::contains_key(&caller), "Identity not cleared.");
269		Ok(())
270	}
271
272	#[benchmark]
273	fn request_judgement(r: Linear<1, { T::MaxRegistrars::get() }>) -> Result<(), BenchmarkError> {
274		let caller: T::AccountId = whitelisted_caller();
275		let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
276
277		// Register the registrars
278		add_registrars::<T>(r)?;
279
280		// Create their main identity with x additional fields
281		let info = T::IdentityInformation::create_identity_info();
282		let caller_origin =
283			<T as frame_system::Config>::RuntimeOrigin::from(RawOrigin::Signed(caller.clone()));
284		Identity::<T>::set_identity(caller_origin.clone(), Box::new(info))?;
285
286		#[extrinsic_call]
287		_(RawOrigin::Signed(caller.clone()), r - 1, 10u32.into());
288
289		assert_last_event::<T>(
290			Event::<T>::JudgementRequested { who: caller, registrar_index: r - 1 }.into(),
291		);
292
293		Ok(())
294	}
295
296	#[benchmark]
297	fn cancel_request(r: Linear<1, { T::MaxRegistrars::get() }>) -> Result<(), BenchmarkError> {
298		let caller: T::AccountId = whitelisted_caller();
299		let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
300
301		// Register the registrars
302		add_registrars::<T>(r)?;
303
304		// Create their main identity with x additional fields
305		let info = T::IdentityInformation::create_identity_info();
306		let caller_origin =
307			<T as frame_system::Config>::RuntimeOrigin::from(RawOrigin::Signed(caller.clone()));
308		Identity::<T>::set_identity(caller_origin.clone(), Box::new(info))?;
309
310		Identity::<T>::request_judgement(caller_origin.clone(), r - 1, 10u32.into())?;
311
312		#[extrinsic_call]
313		_(RawOrigin::Signed(caller.clone()), r - 1);
314
315		assert_last_event::<T>(
316			Event::<T>::JudgementUnrequested { who: caller, registrar_index: r - 1 }.into(),
317		);
318
319		Ok(())
320	}
321
322	#[benchmark]
323	fn set_fee(r: Linear<1, { T::MaxRegistrars::get() - 1 }>) -> Result<(), BenchmarkError> {
324		let caller: T::AccountId = whitelisted_caller();
325		let caller_lookup = T::Lookup::unlookup(caller.clone());
326
327		add_registrars::<T>(r)?;
328
329		let registrar_origin = T::RegistrarOrigin::try_successful_origin()
330			.expect("RegistrarOrigin has no successful origin required for the benchmark");
331		Identity::<T>::add_registrar(registrar_origin, caller_lookup)?;
332
333		let registrars = Registrars::<T>::get();
334		ensure!(registrars[r as usize].as_ref().unwrap().fee == 0u32.into(), "Fee already set.");
335
336		#[extrinsic_call]
337		_(RawOrigin::Signed(caller), r, 100u32.into());
338
339		let updated_registrars = Registrars::<T>::get();
340		ensure!(
341			updated_registrars[r as usize].as_ref().unwrap().fee == 100u32.into(),
342			"Fee not changed."
343		);
344
345		Ok(())
346	}
347
348	#[benchmark]
349	fn set_account_id(r: Linear<1, { T::MaxRegistrars::get() - 1 }>) -> Result<(), BenchmarkError> {
350		let caller: T::AccountId = whitelisted_caller();
351		let caller_lookup = T::Lookup::unlookup(caller.clone());
352		let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
353
354		add_registrars::<T>(r)?;
355
356		let registrar_origin = T::RegistrarOrigin::try_successful_origin()
357			.expect("RegistrarOrigin has no successful origin required for the benchmark");
358		Identity::<T>::add_registrar(registrar_origin, caller_lookup)?;
359
360		let registrars = Registrars::<T>::get();
361		ensure!(registrars[r as usize].as_ref().unwrap().account == caller, "id not set.");
362
363		let new_account = T::Lookup::unlookup(account("new", 0, SEED));
364
365		#[extrinsic_call]
366		_(RawOrigin::Signed(caller), r, new_account);
367
368		let updated_registrars = Registrars::<T>::get();
369		ensure!(
370			updated_registrars[r as usize].as_ref().unwrap().account == account("new", 0, SEED),
371			"id not changed."
372		);
373
374		Ok(())
375	}
376
377	#[benchmark]
378	fn set_fields(r: Linear<1, { T::MaxRegistrars::get() - 1 }>) -> Result<(), BenchmarkError> {
379		let caller: T::AccountId = whitelisted_caller();
380		let caller_lookup = T::Lookup::unlookup(caller.clone());
381		let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
382
383		add_registrars::<T>(r)?;
384
385		let registrar_origin = T::RegistrarOrigin::try_successful_origin()
386			.expect("RegistrarOrigin has no successful origin required for the benchmark");
387		Identity::<T>::add_registrar(registrar_origin, caller_lookup)?;
388
389		let registrars = Registrars::<T>::get();
390		ensure!(
391			registrars[r as usize].as_ref().unwrap().fields == Default::default(),
392			"fields already set."
393		);
394		let fields = T::IdentityInformation::all_fields();
395
396		#[extrinsic_call]
397		_(RawOrigin::Signed(caller), r, fields);
398
399		let updated_registrars = Registrars::<T>::get();
400		ensure!(
401			updated_registrars[r as usize].as_ref().unwrap().fields != Default::default(),
402			"fields not set."
403		);
404
405		Ok(())
406	}
407
408	#[benchmark]
409	fn provide_judgement(
410		r: Linear<1, { T::MaxRegistrars::get() - 1 }>,
411	) -> Result<(), BenchmarkError> {
412		// The user
413		let user: T::AccountId = account("user", r, SEED);
414		let user_origin =
415			<T as frame_system::Config>::RuntimeOrigin::from(RawOrigin::Signed(user.clone()));
416		let user_lookup = <T::Lookup as StaticLookup>::unlookup(user.clone());
417		let _ = T::Currency::make_free_balance_be(&user, BalanceOf::<T>::max_value());
418
419		let caller: T::AccountId = whitelisted_caller();
420		let caller_lookup = T::Lookup::unlookup(caller.clone());
421		let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());
422
423		add_registrars::<T>(r)?;
424
425		let info = T::IdentityInformation::create_identity_info();
426		let info_hash = T::Hashing::hash_of(&info);
427		Identity::<T>::set_identity(user_origin.clone(), Box::new(info))?;
428
429		let registrar_origin = T::RegistrarOrigin::try_successful_origin()
430			.expect("RegistrarOrigin has no successful origin required for the benchmark");
431		Identity::<T>::add_registrar(registrar_origin, caller_lookup)?;
432		Identity::<T>::request_judgement(user_origin, r, 10u32.into())?;
433
434		#[extrinsic_call]
435		_(RawOrigin::Signed(caller), r, user_lookup, Judgement::Reasonable, info_hash);
436
437		assert_last_event::<T>(
438			Event::<T>::JudgementGiven { target: user, registrar_index: r }.into(),
439		);
440
441		Ok(())
442	}
443
444	#[benchmark]
445	fn kill_identity(
446		r: Linear<1, { T::MaxRegistrars::get() }>,
447		s: Linear<0, { T::MaxSubAccounts::get() }>,
448	) -> Result<(), BenchmarkError> {
449		add_registrars::<T>(r)?;
450
451		let target: T::AccountId = account("target", 0, SEED);
452		let target_origin: <T as frame_system::Config>::RuntimeOrigin =
453			RawOrigin::Signed(target.clone()).into();
454		let target_lookup = T::Lookup::unlookup(target.clone());
455		let _ = T::Currency::make_free_balance_be(&target, BalanceOf::<T>::max_value());
456
457		let info = T::IdentityInformation::create_identity_info();
458		Identity::<T>::set_identity(target_origin.clone(), Box::new(info.clone()))?;
459		add_sub_accounts::<T>(&target, s)?;
460
461		// User requests judgement from all the registrars, and they approve
462		for i in 0..r {
463			let registrar: T::AccountId = account("registrar", i, SEED);
464			let balance_to_use = T::Currency::minimum_balance() * 10u32.into();
465			let _ = T::Currency::make_free_balance_be(&registrar, balance_to_use);
466
467			Identity::<T>::request_judgement(target_origin.clone(), i, 10u32.into())?;
468			Identity::<T>::provide_judgement(
469				RawOrigin::Signed(registrar).into(),
470				i,
471				target_lookup.clone(),
472				Judgement::Reasonable,
473				T::Hashing::hash_of(&info),
474			)?;
475		}
476
477		ensure!(IdentityOf::<T>::contains_key(&target), "Identity not set");
478
479		let origin =
480			T::ForceOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?;
481
482		#[extrinsic_call]
483		_(origin as T::RuntimeOrigin, target_lookup);
484
485		ensure!(!IdentityOf::<T>::contains_key(&target), "Identity not removed");
486
487		Ok(())
488	}
489
490	#[benchmark]
491	fn add_sub(s: Linear<0, { T::MaxSubAccounts::get() - 1 }>) -> Result<(), BenchmarkError> {
492		let caller: T::AccountId = whitelisted_caller();
493		add_sub_accounts::<T>(&caller, s)?;
494		let sub = account("new_sub", 0, SEED);
495		let data = Data::Raw(vec![0; 32].try_into().unwrap());
496
497		ensure!(SubsOf::<T>::get(&caller).1.len() as u32 == s, "Subs not set.");
498
499		#[extrinsic_call]
500		_(RawOrigin::Signed(caller.clone()), T::Lookup::unlookup(sub), data);
501
502		ensure!(SubsOf::<T>::get(&caller).1.len() as u32 == s + 1, "Subs not added.");
503
504		Ok(())
505	}
506
507	#[benchmark]
508	fn rename_sub(s: Linear<1, { T::MaxSubAccounts::get() }>) -> Result<(), BenchmarkError> {
509		let caller: T::AccountId = whitelisted_caller();
510		let (sub, _) = add_sub_accounts::<T>(&caller, s)?.remove(0);
511		let data = Data::Raw(vec![1; 32].try_into().unwrap());
512
513		ensure!(SuperOf::<T>::get(&sub).unwrap().1 != data, "data already set");
514
515		#[extrinsic_call]
516		_(RawOrigin::Signed(caller), T::Lookup::unlookup(sub.clone()), data.clone());
517
518		ensure!(SuperOf::<T>::get(&sub).unwrap().1 == data, "data not set");
519
520		Ok(())
521	}
522
523	#[benchmark]
524	fn remove_sub(s: Linear<1, { T::MaxSubAccounts::get() }>) -> Result<(), BenchmarkError> {
525		let caller: T::AccountId = whitelisted_caller();
526		let (sub, _) = add_sub_accounts::<T>(&caller, s)?.remove(0);
527		ensure!(SuperOf::<T>::contains_key(&sub), "Sub doesn't exists");
528
529		#[extrinsic_call]
530		_(RawOrigin::Signed(caller), T::Lookup::unlookup(sub.clone()));
531
532		ensure!(!SuperOf::<T>::contains_key(&sub), "Sub not removed");
533
534		Ok(())
535	}
536
537	#[benchmark]
538	fn quit_sub(s: Linear<0, { T::MaxSubAccounts::get() - 1 }>) -> Result<(), BenchmarkError> {
539		let caller: T::AccountId = whitelisted_caller();
540		let sup = account("super", 0, SEED);
541		add_sub_accounts::<T>(&sup, s)?;
542		let sup_origin = RawOrigin::Signed(sup).into();
543		Identity::<T>::add_sub(
544			sup_origin,
545			T::Lookup::unlookup(caller.clone()),
546			Data::Raw(vec![0; 32].try_into().unwrap()),
547		)?;
548		ensure!(SuperOf::<T>::contains_key(&caller), "Sub doesn't exists");
549
550		#[extrinsic_call]
551		_(RawOrigin::Signed(caller.clone()));
552
553		ensure!(!SuperOf::<T>::contains_key(&caller), "Sub not removed");
554
555		Ok(())
556	}
557
558	#[benchmark]
559	fn add_username_authority() -> Result<(), BenchmarkError> {
560		let origin =
561			T::UsernameAuthorityOrigin::try_successful_origin().expect("can generate origin");
562
563		let authority: T::AccountId = account("authority", 0, SEED);
564		let authority_lookup = T::Lookup::unlookup(authority.clone());
565		let suffix = bench_suffix();
566		let allocation = 10;
567
568		#[extrinsic_call]
569		_(origin as T::RuntimeOrigin, authority_lookup, suffix, allocation);
570
571		assert_last_event::<T>(Event::<T>::AuthorityAdded { authority }.into());
572		Ok(())
573	}
574
575	#[benchmark]
576	fn remove_username_authority() -> Result<(), BenchmarkError> {
577		let origin =
578			T::UsernameAuthorityOrigin::try_successful_origin().expect("can generate origin");
579
580		let authority: T::AccountId = account("authority", 0, SEED);
581		let authority_lookup = T::Lookup::unlookup(authority.clone());
582		let suffix = bench_suffix();
583		let allocation = 10;
584
585		assert_ok!(Identity::<T>::add_username_authority(
586			origin.clone(),
587			authority_lookup.clone(),
588			suffix.clone(),
589			allocation
590		));
591
592		#[extrinsic_call]
593		_(origin as T::RuntimeOrigin, suffix.into(), authority_lookup);
594
595		assert_last_event::<T>(Event::<T>::AuthorityRemoved { authority }.into());
596		Ok(())
597	}
598
599	#[benchmark]
600	fn set_username_for(p: Linear<0, 1>) -> Result<(), BenchmarkError> {
601		// Set up a username authority.
602		let auth_origin =
603			T::UsernameAuthorityOrigin::try_successful_origin().expect("can generate origin");
604		let authority: T::AccountId = account("authority", 0, SEED);
605		let authority_lookup = T::Lookup::unlookup(authority.clone());
606		let suffix = bench_suffix();
607		let allocation = 10;
608		let _ = T::Currency::make_free_balance_be(&authority, BalanceOf::<T>::max_value());
609
610		Identity::<T>::add_username_authority(
611			auth_origin,
612			authority_lookup,
613			suffix.clone(),
614			allocation,
615		)?;
616
617		let username = bench_username();
618		let bounded_username = bounded_username::<T>(username.clone(), suffix.clone());
619
620		let (public, signature) = T::BenchmarkHelper::sign_message(&bounded_username[..]);
621		let who_account = public.into_account();
622		let who_lookup = T::Lookup::unlookup(who_account.clone());
623
624		// Verify signature here to avoid surprise errors at runtime
625		assert!(signature.verify(&bounded_username[..], &who_account));
626		let use_allocation = match p {
627			0 => false,
628			1 => true,
629			_ => unreachable!(),
630		};
631
632		#[extrinsic_call]
633		set_username_for(
634			RawOrigin::Signed(authority.clone()),
635			who_lookup,
636			bounded_username.clone().into(),
637			Some(signature.into()),
638			use_allocation,
639		);
640
641		assert_has_event::<T>(
642			Event::<T>::UsernameSet {
643				who: who_account.clone(),
644				username: bounded_username.clone(),
645			}
646			.into(),
647		);
648		assert_has_event::<T>(
649			Event::<T>::PrimaryUsernameSet { who: who_account, username: bounded_username }.into(),
650		);
651		if use_allocation {
652			let suffix: Suffix<T> = suffix.try_into().unwrap();
653			assert_eq!(AuthorityOf::<T>::get(&suffix).unwrap().allocation, 9);
654		} else {
655			assert_eq!(
656				T::Currency::free_balance(&authority),
657				BalanceOf::<T>::max_value() - T::UsernameDeposit::get()
658			);
659		}
660		Ok(())
661	}
662
663	#[benchmark]
664	fn accept_username() -> Result<(), BenchmarkError> {
665		let caller: T::AccountId = whitelisted_caller();
666		let username = bounded_username::<T>(bench_username(), bench_suffix());
667
668		Identity::<T>::queue_acceptance(&caller, username.clone(), Provider::Allocation);
669
670		#[extrinsic_call]
671		_(RawOrigin::Signed(caller.clone()), username.clone());
672
673		assert_last_event::<T>(Event::<T>::UsernameSet { who: caller, username }.into());
674		Ok(())
675	}
676
677	#[benchmark]
678	fn remove_expired_approval(p: Linear<0, 1>) -> Result<(), BenchmarkError> {
679		// Set up a username authority.
680		let auth_origin =
681			T::UsernameAuthorityOrigin::try_successful_origin().expect("can generate origin");
682		let authority: T::AccountId = account("authority", 0, SEED);
683		let authority_lookup = T::Lookup::unlookup(authority.clone());
684		let suffix = bench_suffix();
685		let allocation = 10;
686		let _ = T::Currency::make_free_balance_be(&authority, BalanceOf::<T>::max_value());
687
688		Identity::<T>::add_username_authority(
689			auth_origin,
690			authority_lookup,
691			suffix.clone(),
692			allocation,
693		)?;
694
695		let caller: T::AccountId = whitelisted_caller();
696		let username = bounded_username::<T>(bench_username(), suffix.clone());
697		let username_deposit = T::UsernameDeposit::get();
698		let provider = match p {
699			0 => {
700				let _ = T::Currency::reserve(&authority, username_deposit);
701				Provider::AuthorityDeposit(username_deposit)
702			},
703			1 => Provider::Allocation,
704			_ => unreachable!(),
705		};
706		Identity::<T>::queue_acceptance(&caller, username.clone(), provider);
707
708		let expected_expiration =
709			frame_system::Pallet::<T>::block_number() + T::PendingUsernameExpiration::get();
710
711		run_to_block::<T>(expected_expiration + One::one());
712
713		#[extrinsic_call]
714		_(RawOrigin::Signed(caller.clone()), username);
715
716		assert_last_event::<T>(Event::<T>::PreapprovalExpired { whose: caller }.into());
717		match p {
718			0 => {
719				assert_eq!(T::Currency::free_balance(&authority), BalanceOf::<T>::max_value());
720			},
721			1 => {
722				let suffix: Suffix<T> = suffix.try_into().unwrap();
723				assert_eq!(AuthorityOf::<T>::get(&suffix).unwrap().allocation, 10);
724			},
725			_ => unreachable!(),
726		}
727		Ok(())
728	}
729
730	#[benchmark]
731	fn set_primary_username() -> Result<(), BenchmarkError> {
732		let caller: T::AccountId = whitelisted_caller();
733		let first_username = bounded_username::<T>(bench_username(), bench_suffix());
734		let second_username = bounded_username::<T>(b"slowbenchmark".to_vec(), bench_suffix());
735
736		// First one will be set as primary. Second will not be.
737		Identity::<T>::insert_username(&caller, first_username, Provider::Allocation);
738		Identity::<T>::insert_username(&caller, second_username.clone(), Provider::Allocation);
739
740		#[extrinsic_call]
741		_(RawOrigin::Signed(caller.clone()), second_username.clone());
742
743		assert_last_event::<T>(
744			Event::<T>::PrimaryUsernameSet { who: caller, username: second_username }.into(),
745		);
746		Ok(())
747	}
748
749	#[benchmark]
750	fn unbind_username() -> Result<(), BenchmarkError> {
751		// Set up a username authority.
752		let auth_origin =
753			T::UsernameAuthorityOrigin::try_successful_origin().expect("can generate origin");
754		let authority: T::AccountId = account("authority", 0, SEED);
755		let authority_lookup = T::Lookup::unlookup(authority.clone());
756		let suffix = bench_suffix();
757		let allocation = 10;
758		let _ = T::Currency::make_free_balance_be(&authority, BalanceOf::<T>::max_value());
759
760		Identity::<T>::add_username_authority(
761			auth_origin,
762			authority_lookup,
763			suffix.clone(),
764			allocation,
765		)?;
766
767		let caller: T::AccountId = whitelisted_caller();
768		let username = bounded_username::<T>(bench_username(), suffix.clone());
769
770		let username_deposit = T::UsernameDeposit::get();
771		Identity::<T>::insert_username(
772			&caller,
773			username.clone(),
774			Provider::AuthorityDeposit(username_deposit),
775		);
776
777		#[extrinsic_call]
778		_(RawOrigin::Signed(authority), username.clone());
779
780		assert_last_event::<T>(Event::<T>::UsernameUnbound { username }.into());
781		Ok(())
782	}
783
784	#[benchmark]
785	fn remove_username() -> Result<(), BenchmarkError> {
786		// Set up a username authority.
787		let authority: T::AccountId = account("authority", 0, SEED);
788		let suffix = bench_suffix();
789		let _ = T::Currency::make_free_balance_be(&authority, BalanceOf::<T>::max_value());
790		let caller: T::AccountId = whitelisted_caller();
791		let username = bounded_username::<T>(bench_username(), suffix.clone());
792
793		let username_deposit = T::UsernameDeposit::get();
794		Identity::<T>::insert_username(
795			&caller,
796			username.clone(),
797			Provider::AuthorityDeposit(username_deposit),
798		);
799		let now = frame_system::Pallet::<T>::block_number();
800		let expiry = now + T::UsernameGracePeriod::get();
801		UnbindingUsernames::<T>::insert(&username, expiry);
802
803		frame_system::Pallet::<T>::set_block_number(expiry);
804
805		#[extrinsic_call]
806		_(RawOrigin::Signed(caller), username.clone());
807
808		assert_last_event::<T>(Event::<T>::UsernameRemoved { username }.into());
809		Ok(())
810	}
811
812	#[benchmark]
813	fn kill_username(p: Linear<0, 1>) -> Result<(), BenchmarkError> {
814		// Set up a username authority.
815		let auth_origin =
816			T::UsernameAuthorityOrigin::try_successful_origin().expect("can generate origin");
817		let authority: T::AccountId = account("authority", 0, SEED);
818		let authority_lookup = T::Lookup::unlookup(authority.clone());
819		let suffix = bench_suffix();
820		let allocation = 10;
821		let _ = T::Currency::make_free_balance_be(&authority, BalanceOf::<T>::max_value());
822
823		Identity::<T>::add_username_authority(
824			auth_origin,
825			authority_lookup,
826			suffix.clone(),
827			allocation,
828		)?;
829
830		let caller: T::AccountId = whitelisted_caller();
831		let username = bounded_username::<T>(bench_username(), suffix.clone());
832		let username_deposit = T::UsernameDeposit::get();
833		let provider = match p {
834			0 => {
835				let _ = T::Currency::reserve(&authority, username_deposit);
836				Provider::AuthorityDeposit(username_deposit)
837			},
838			1 => Provider::Allocation,
839			_ => unreachable!(),
840		};
841		Identity::<T>::insert_username(&caller, username.clone(), provider);
842		UnbindingUsernames::<T>::insert(&username, frame_system::Pallet::<T>::block_number());
843
844		#[extrinsic_call]
845		_(RawOrigin::Root, username.clone());
846
847		assert_last_event::<T>(Event::<T>::UsernameKilled { username }.into());
848		match p {
849			0 => {
850				assert_eq!(
851					T::Currency::free_balance(&authority),
852					BalanceOf::<T>::max_value() - username_deposit
853				);
854			},
855			1 => {
856				let suffix: Suffix<T> = suffix.try_into().unwrap();
857				assert_eq!(AuthorityOf::<T>::get(&suffix).unwrap().allocation, 10);
858			},
859			_ => unreachable!(),
860		}
861		Ok(())
862	}
863
864	#[benchmark]
865	fn migration_v2_authority_step() -> Result<(), BenchmarkError> {
866		let setup = LazyMigrationV1ToV2::<T>::setup_benchmark_env_for_migration();
867		assert_eq!(AuthorityOf::<T>::iter().count(), 0);
868		#[block]
869		{
870			LazyMigrationV1ToV2::<T>::authority_step(None);
871		}
872		assert_eq!(AuthorityOf::<T>::get(&setup.suffix).unwrap().account_id, setup.authority);
873		Ok(())
874	}
875
876	#[benchmark]
877	fn migration_v2_username_step() -> Result<(), BenchmarkError> {
878		let setup = LazyMigrationV1ToV2::<T>::setup_benchmark_env_for_migration();
879		assert_eq!(UsernameInfoOf::<T>::iter().count(), 0);
880		#[block]
881		{
882			LazyMigrationV1ToV2::<T>::username_step(None);
883		}
884		assert_eq!(UsernameInfoOf::<T>::iter().next().unwrap().1.owner, setup.account);
885		Ok(())
886	}
887
888	#[benchmark]
889	fn migration_v2_identity_step() -> Result<(), BenchmarkError> {
890		let setup = LazyMigrationV1ToV2::<T>::setup_benchmark_env_for_migration();
891		#[block]
892		{
893			LazyMigrationV1ToV2::<T>::identity_step(None);
894		}
895		assert!(IdentityOf::<T>::get(&setup.account).is_some());
896		Ok(())
897	}
898
899	#[benchmark]
900	fn migration_v2_pending_username_step() -> Result<(), BenchmarkError> {
901		let setup = LazyMigrationV1ToV2::<T>::setup_benchmark_env_for_migration();
902		#[block]
903		{
904			LazyMigrationV1ToV2::<T>::pending_username_step(None);
905		}
906		assert!(PendingUsernames::<T>::get(&setup.username).is_some());
907		Ok(())
908	}
909
910	#[benchmark]
911	fn migration_v2_cleanup_authority_step() -> Result<(), BenchmarkError> {
912		let setup = LazyMigrationV1ToV2::<T>::setup_benchmark_env_for_cleanup();
913		#[block]
914		{
915			LazyMigrationV1ToV2::<T>::cleanup_authority_step(None);
916		}
917		LazyMigrationV1ToV2::<T>::check_authority_cleanup_validity(setup.suffix, setup.authority);
918		Ok(())
919	}
920
921	#[benchmark]
922	fn migration_v2_cleanup_username_step() -> Result<(), BenchmarkError> {
923		let setup = LazyMigrationV1ToV2::<T>::setup_benchmark_env_for_cleanup();
924		#[block]
925		{
926			LazyMigrationV1ToV2::<T>::cleanup_username_step(None);
927		}
928		LazyMigrationV1ToV2::<T>::check_username_cleanup_validity(setup.username, setup.account);
929		Ok(())
930	}
931
932	impl_benchmark_test_suite!(Identity, crate::tests::new_test_ext(), crate::tests::Test);
933}