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