12345678910111213141516171819202122232425262728293031323334353637#![cfg(feature = "runtime-benchmarks")]38#![allow(clippy::no_effect)]3940use frame_benchmarking::v2::*;41use frame_support::{assert_ok, ensure, traits::EnsureOrigin};42use frame_system::RawOrigin;43use sp_runtime::traits::Bounded;4445use super::*;46use crate::Pallet as Identity;4748const SEED: u32 = 0;4950fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {51 frame_system::Pallet::<T>::assert_last_event(generic_event.into());52}535455fn add_registrars<T: Config>(r: u32) -> Result<(), &'static str> {56 for i in 0..r {57 let registrar: T::AccountId = account("registrar", i, SEED);58 let registrar_lookup = T::Lookup::unlookup(registrar.clone());59 let _ = T::Currency::make_free_balance_be(®istrar, BalanceOf::<T>::max_value());60 let registrar_origin = T::RegistrarOrigin::try_successful_origin().unwrap();61 Identity::<T>::add_registrar(registrar_origin, registrar_lookup)?;62 Identity::<T>::set_fee(RawOrigin::Signed(registrar.clone()).into(), i, 10u32.into())?;63 let fields = IdentityFields(64 IdentityField::Display65 | IdentityField::Legal66 | IdentityField::Web67 | IdentityField::Riot68 | IdentityField::Email69 | IdentityField::PgpFingerprint70 | IdentityField::Image71 | IdentityField::Twitter,72 );73 Identity::<T>::set_fields(RawOrigin::Signed(registrar.clone()).into(), i, fields)?;74 }7576 assert_eq!(Registrars::<T>::get().len(), r as usize);77 Ok(())78}79808182fn create_sub_accounts<T: Config>(83 who: &T::AccountId,84 s: u32,85) -> Result<Vec<(T::AccountId, Data)>, &'static str> {86 let mut subs = Vec::new();87 let who_origin = RawOrigin::Signed(who.clone());88 let data = Data::Raw(vec![0; 32].try_into().unwrap());8990 for i in 0..s {91 let sub_account = account("sub", i, SEED);92 subs.push((sub_account, data.clone()));93 }9495 96 if IdentityOf::<T>::get(who).is_none() {97 let _ = T::Currency::make_free_balance_be(who, BalanceOf::<T>::max_value() / 2u32.into());98 let info = create_identity_info::<T>(1);99 Identity::<T>::set_identity(who_origin.into(), Box::new(info))?;100 }101102 Ok(subs)103}104105106107fn add_sub_accounts<T: Config>(108 who: &T::AccountId,109 s: u32,110) -> Result<Vec<(T::AccountId, Data)>, &'static str> {111 let who_origin = RawOrigin::Signed(who.clone());112 let subs = create_sub_accounts::<T>(who, s)?;113114 Identity::<T>::set_subs(who_origin.into(), subs.clone())?;115116 Ok(subs)117}118119120121fn create_identity_info<T: Config>(num_fields: u32) -> IdentityInfo<T::MaxAdditionalFields> {122 let data = Data::Raw(vec![0; 32].try_into().unwrap());123124 IdentityInfo {125 additional: vec![(data.clone(), data.clone()); num_fields as usize]126 .try_into()127 .unwrap(),128 display: data.clone(),129 legal: data.clone(),130 web: data.clone(),131 riot: data.clone(),132 email: data.clone(),133 pgp_fingerprint: Some([0; 20]),134 image: data.clone(),135 twitter: data,136 }137}138139140141fn balance_unit<T: Config>() -> <T::Currency as Currency<T::AccountId>>::Balance {142 200u32.into()143}144145#[benchmarks]146mod benchmarks {147 use super::*;148149 const MAX_REGISTRARS: u32 = 20;150 const MAX_ADDITIONAL_FIELDS: u32 = 100;151 const MAX_SUB_ACCOUNTS: u32 = 100;152153 #[benchmark]154 fn add_registrar(r: Linear<2, MAX_REGISTRARS>) -> Result<(), BenchmarkError> {155 let r = r - 1;156 add_registrars::<T>(r)?;157 ensure!(158 Registrars::<T>::get().len() as u32 == r,159 "Registrars not set up correctly."160 );161 let origin = T::RegistrarOrigin::try_successful_origin().unwrap();162 let account = T::Lookup::unlookup(account("registrar", r + 1, SEED));163164 #[extrinsic_call]165 _(origin as T::RuntimeOrigin, account);166167 ensure!(168 Registrars::<T>::get().len() as u32 == r + 1,169 "Registrars not added."170 );171172 Ok(())173 }174175 #[benchmark]176 fn set_identity(177 x: Linear<0, MAX_ADDITIONAL_FIELDS>,178 r: Linear<1, MAX_REGISTRARS>,179 ) -> Result<(), BenchmarkError> {180 add_registrars::<T>(r)?;181 let caller = {182 183 let caller: T::AccountId = whitelisted_caller();184 let caller_lookup = T::Lookup::unlookup(caller.clone());185 let caller_origin: <T as frame_system::Config>::RuntimeOrigin =186 RawOrigin::Signed(caller.clone()).into();187 let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());188189 190 let initial_info = create_identity_info::<T>(1);191 Identity::<T>::set_identity(caller_origin.clone(), Box::new(initial_info.clone()))?;192193 194 for i in 0..r {195 let registrar: T::AccountId = account("registrar", i, SEED);196 let balance_to_use = balance_unit::<T>() * 10u32.into();197 let _ = T::Currency::make_free_balance_be(®istrar, balance_to_use);198199 Identity::<T>::request_judgement(caller_origin.clone(), i, 10u32.into())?;200 Identity::<T>::provide_judgement(201 RawOrigin::Signed(registrar).into(),202 i,203 caller_lookup.clone(),204 Judgement::Reasonable,205 T::Hashing::hash_of(&initial_info),206 )?;207 }208 caller209 };210211 #[extrinsic_call]212 _(213 RawOrigin::Signed(caller.clone()),214 Box::new(create_identity_info::<T>(x)),215 );216217 assert_last_event::<T>(Event::<T>::IdentitySet { who: caller }.into());218219 Ok(())220 }221222 223 224 225 #[benchmark]226 fn set_subs_new(s: Linear<0, MAX_SUB_ACCOUNTS>) -> Result<(), BenchmarkError> {227 let caller: T::AccountId = whitelisted_caller();228 229 let subs = create_sub_accounts::<T>(&caller, s)?;230 ensure!(231 SubsOf::<T>::get(&caller).1.len() == 0,232 "Caller already has subs"233 );234235 #[extrinsic_call]236 set_subs(RawOrigin::Signed(caller.clone()), subs);237238 ensure!(239 SubsOf::<T>::get(&caller).1.len() as u32 == s,240 "Subs not added"241 );242243 Ok(())244 }245246 #[benchmark]247 fn set_subs_old(p: Linear<0, MAX_SUB_ACCOUNTS>) -> Result<(), BenchmarkError> {248 let caller: T::AccountId = whitelisted_caller();249 250 let _ = add_sub_accounts::<T>(&caller, p)?;251 252 let subs = create_sub_accounts::<T>(&caller, 0)?;253 ensure!(254 SubsOf::<T>::get(&caller).1.len() as u32 == p,255 "Caller does have subs",256 );257258 #[extrinsic_call]259 set_subs(RawOrigin::Signed(caller.clone()), subs);260261 ensure!(SubsOf::<T>::get(&caller).1.len() == 0, "Subs not removed");262263 Ok(())264 }265266 #[benchmark]267 fn clear_identity(268 r: Linear<1, MAX_REGISTRARS>,269 s: Linear<0, MAX_SUB_ACCOUNTS>,270 x: Linear<0, MAX_ADDITIONAL_FIELDS>,271 ) -> Result<(), BenchmarkError> {272 let caller: T::AccountId = whitelisted_caller();273 let caller_lookup = <T::Lookup as StaticLookup>::unlookup(caller.clone());274 let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());275276 add_registrars::<T>(r)?;277278 {279 280 let caller: T::AccountId = whitelisted_caller();281 let _ = add_sub_accounts::<T>(&caller, s)?;282 }283284 285 let info = create_identity_info::<T>(x);286 let caller: T::AccountId = whitelisted_caller();287 let caller_origin =288 <T as frame_system::Config>::RuntimeOrigin::from(RawOrigin::Signed(caller.clone()));289 Identity::<T>::set_identity(caller_origin.clone(), Box::new(info.clone()))?;290291 292 for i in 0..r {293 let registrar: T::AccountId = account("registrar", i, SEED);294 let balance_to_use = balance_unit::<T>() * 10u32.into();295 let _ = T::Currency::make_free_balance_be(®istrar, balance_to_use);296297 Identity::<T>::request_judgement(caller_origin.clone(), i, 10u32.into())?;298 Identity::<T>::provide_judgement(299 RawOrigin::Signed(registrar).into(),300 i,301 caller_lookup.clone(),302 Judgement::Reasonable,303 T::Hashing::hash_of(&info),304 )?;305 }306 ensure!(307 IdentityOf::<T>::contains_key(&caller),308 "Identity does not exist."309 );310311 #[extrinsic_call]312 _(RawOrigin::Signed(caller.clone()));313314 ensure!(315 !IdentityOf::<T>::contains_key(&caller),316 "Identity not cleared."317 );318319 Ok(())320 }321322 #[benchmark]323 fn request_judgement(324 r: Linear<1, MAX_REGISTRARS>,325 x: Linear<0, MAX_ADDITIONAL_FIELDS>,326 ) -> Result<(), BenchmarkError> {327 let caller: T::AccountId = whitelisted_caller();328 let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());329330 add_registrars::<T>(r)?;331332 {333 334 let info = create_identity_info::<T>(x);335 let caller: T::AccountId = whitelisted_caller();336 let caller_origin =337 <T as frame_system::Config>::RuntimeOrigin::from(RawOrigin::Signed(caller));338 Identity::<T>::set_identity(caller_origin, Box::new(info))?;339 }340341 #[extrinsic_call]342 _(RawOrigin::Signed(caller.clone()), r - 1, 10u32.into());343344 assert_last_event::<T>(345 Event::<T>::JudgementRequested {346 who: caller,347 registrar_index: r - 1,348 }349 .into(),350 );351352 Ok(())353 }354355 #[benchmark]356 fn cancel_request(357 r: Linear<1, MAX_REGISTRARS>,358 x: Linear<0, MAX_ADDITIONAL_FIELDS>,359 ) -> Result<(), BenchmarkError> {360 let caller: T::AccountId = whitelisted_caller();361 let caller_origin =362 <T as frame_system::Config>::RuntimeOrigin::from(RawOrigin::Signed(caller.clone()));363 let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());364365 add_registrars::<T>(r)?;366367 {368 369 let info = create_identity_info::<T>(x);370 let caller: T::AccountId = whitelisted_caller();371 let caller_origin =372 <T as frame_system::Config>::RuntimeOrigin::from(RawOrigin::Signed(caller));373 Identity::<T>::set_identity(caller_origin, Box::new(info))?;374 }375376 Identity::<T>::request_judgement(caller_origin, r - 1, 10u32.into())?;377378 #[extrinsic_call]379 _(RawOrigin::Signed(caller.clone()), r - 1);380381 assert_last_event::<T>(382 Event::<T>::JudgementUnrequested {383 who: caller,384 registrar_index: r - 1,385 }386 .into(),387 );388389 Ok(())390 }391392 #[benchmark]393 fn set_fee(r: Linear<2, MAX_REGISTRARS>) -> Result<(), BenchmarkError> {394 let r = r - 1;395 let caller: T::AccountId = whitelisted_caller();396 let caller_lookup = T::Lookup::unlookup(caller.clone());397398 add_registrars::<T>(r)?;399400 let registrar_origin = T::RegistrarOrigin::try_successful_origin().unwrap();401 Identity::<T>::add_registrar(registrar_origin, caller_lookup)?;402 let registrars = Registrars::<T>::get();403 ensure!(404 registrars[r as usize].as_ref().unwrap().fee == 0u32.into(),405 "Fee already set."406 );407408 #[extrinsic_call]409 _(RawOrigin::Signed(caller), r, 100u32.into());410411 let registrars = Registrars::<T>::get();412 ensure!(413 registrars[r as usize].as_ref().unwrap().fee == 100u32.into(),414 "Fee not changed."415 );416417 Ok(())418 }419420 #[benchmark]421 fn set_account_id(r: Linear<2, MAX_REGISTRARS>) -> Result<(), BenchmarkError> {422 let r = r - 1;423 let caller: T::AccountId = whitelisted_caller();424 let caller_lookup = T::Lookup::unlookup(caller.clone());425 let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());426427 add_registrars::<T>(r)?;428429 let registrar_origin = T::RegistrarOrigin::try_successful_origin().unwrap();430 Identity::<T>::add_registrar(registrar_origin, caller_lookup)?;431 let registrars = Registrars::<T>::get();432 ensure!(433 registrars[r as usize].as_ref().unwrap().account == caller,434 "id not set."435 );436 let new_account = T::Lookup::unlookup(account("new", 0, SEED));437438 #[extrinsic_call]439 _(RawOrigin::Signed(caller), r, new_account);440441 let registrars = Registrars::<T>::get();442 ensure!(443 registrars[r as usize].as_ref().unwrap().account == account("new", 0, SEED),444 "id not changed."445 );446447 Ok(())448 }449450 #[benchmark]451 fn set_fields(r: Linear<2, MAX_REGISTRARS>) -> Result<(), BenchmarkError> {452 let r = r - 1;453 let caller: T::AccountId = whitelisted_caller();454 let caller_lookup = T::Lookup::unlookup(caller.clone());455 let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());456457 add_registrars::<T>(r)?;458459 let registrar_origin = T::RegistrarOrigin::try_successful_origin().unwrap();460 Identity::<T>::add_registrar(registrar_origin, caller_lookup)?;461 let fields = IdentityFields(462 IdentityField::Display463 | IdentityField::Legal464 | IdentityField::Web465 | IdentityField::Riot466 | IdentityField::Email467 | IdentityField::PgpFingerprint468 | IdentityField::Image469 | IdentityField::Twitter,470 );471 let registrars = Registrars::<T>::get();472 ensure!(473 registrars[r as usize].as_ref().unwrap().fields == Default::default(),474 "fields already set."475 );476477 #[extrinsic_call]478 _(RawOrigin::Signed(caller), r, fields);479480 let registrars = Registrars::<T>::get();481 ensure!(482 registrars[r as usize].as_ref().unwrap().fields != Default::default(),483 "fields not set."484 );485486 Ok(())487 }488489 #[benchmark]490 fn provide_judgement(491 r: Linear<2, MAX_REGISTRARS>,492 x: Linear<0, MAX_ADDITIONAL_FIELDS>,493 ) -> Result<(), BenchmarkError> {494 let r = r - 1;495 496 let user: T::AccountId = account("user", r, SEED);497 let user_origin =498 <T as frame_system::Config>::RuntimeOrigin::from(RawOrigin::Signed(user.clone()));499 let user_lookup = <T::Lookup as StaticLookup>::unlookup(user.clone());500 let _ = T::Currency::make_free_balance_be(&user, BalanceOf::<T>::max_value());501502 let caller: T::AccountId = whitelisted_caller();503 let caller_lookup = T::Lookup::unlookup(caller.clone());504 let _ = T::Currency::make_free_balance_be(&caller, BalanceOf::<T>::max_value());505506 add_registrars::<T>(r)?;507508 let info = create_identity_info::<T>(x);509 let info_hash = T::Hashing::hash_of(&info);510 Identity::<T>::set_identity(user_origin.clone(), Box::new(info))?;511512 let registrar_origin = T::RegistrarOrigin::try_successful_origin().unwrap();513 Identity::<T>::add_registrar(registrar_origin, caller_lookup)?;514 Identity::<T>::request_judgement(user_origin, r, 10u32.into())?;515516 #[extrinsic_call]517 _(518 RawOrigin::Signed(caller),519 r,520 user_lookup,521 Judgement::Reasonable,522 info_hash,523 );524525 assert_last_event::<T>(526 Event::<T>::JudgementGiven {527 target: user,528 registrar_index: r,529 }530 .into(),531 );532533 Ok(())534 }535536 #[benchmark]537 fn kill_identity(538 r: Linear<1, MAX_REGISTRARS>,539 s: Linear<0, MAX_SUB_ACCOUNTS>,540 x: Linear<0, MAX_ADDITIONAL_FIELDS>,541 ) -> Result<(), BenchmarkError> {542 add_registrars::<T>(r)?;543544 let target: T::AccountId = account("target", 0, SEED);545 let target_origin: <T as frame_system::Config>::RuntimeOrigin =546 RawOrigin::Signed(target.clone()).into();547 let target_lookup = T::Lookup::unlookup(target.clone());548 let _ = T::Currency::make_free_balance_be(&target, BalanceOf::<T>::max_value());549550 let info = create_identity_info::<T>(x);551 Identity::<T>::set_identity(target_origin.clone(), Box::new(info.clone()))?;552 let _ = add_sub_accounts::<T>(&target, s)?;553554 555 for i in 0..r {556 let registrar: T::AccountId = account("registrar", i, SEED);557 let balance_to_use = balance_unit::<T>() * 10u32.into();558 let _ = T::Currency::make_free_balance_be(®istrar, balance_to_use);559560 Identity::<T>::request_judgement(target_origin.clone(), i, 10u32.into())?;561 Identity::<T>::provide_judgement(562 RawOrigin::Signed(registrar).into(),563 i,564 target_lookup.clone(),565 Judgement::Reasonable,566 T::Hashing::hash_of(&info),567 )?;568 }569 ensure!(IdentityOf::<T>::contains_key(&target), "Identity not set");570 let origin = T::ForceOrigin::try_successful_origin().unwrap();571572 #[extrinsic_call]573 _(origin as T::RuntimeOrigin, target_lookup);574575 ensure!(576 !IdentityOf::<T>::contains_key(&target),577 "Identity not removed"578 );579580 Ok(())581 }582583 #[benchmark]584 fn force_insert_identities(585 x: Linear<0, MAX_ADDITIONAL_FIELDS>,586 n: Linear<0, 600>,587 ) -> Result<(), BenchmarkError> {588 use frame_benchmarking::account;589 let identities = (0..n)590 .map(|i| {591 (592 account("caller", i, SEED),593 Registration::<BalanceOf<T>, T::MaxRegistrars, T::MaxAdditionalFields> {594 judgements: Default::default(),595 deposit: Default::default(),596 info: create_identity_info::<T>(x),597 },598 )599 })600 .collect::<Vec<_>>();601 let origin = T::ForceOrigin::try_successful_origin().unwrap();602603 #[extrinsic_call]604 _(origin as T::RuntimeOrigin, identities);605606 Ok(())607 }608609 #[benchmark]610 fn force_remove_identities(611 x: Linear<0, MAX_ADDITIONAL_FIELDS>,612 n: Linear<0, 600>,613 ) -> Result<(), BenchmarkError> {614 use frame_benchmarking::account;615 let origin = T::ForceOrigin::try_successful_origin().unwrap();616 let identities = (0..n)617 .map(|i| {618 (619 account("caller", i, SEED),620 Registration::<BalanceOf<T>, T::MaxRegistrars, T::MaxAdditionalFields> {621 judgements: Default::default(),622 deposit: Default::default(),623 info: create_identity_info::<T>(x),624 },625 )626 })627 .collect::<Vec<_>>();628 assert_ok!(Identity::<T>::force_insert_identities(629 origin.clone(),630 identities.clone()631 ),);632 let identities = identities633 .into_iter()634 .map(|(acc, _)| acc)635 .collect::<Vec<_>>();636637 #[extrinsic_call]638 _(origin as T::RuntimeOrigin, identities);639640 Ok(())641 }642643 #[benchmark]644 fn force_set_subs(645 s: Linear<0, MAX_SUB_ACCOUNTS>,646 n: Linear<0, 600>,647 ) -> Result<(), BenchmarkError> {648 use frame_benchmarking::account;649 let identities = (0..n)650 .map(|i| {651 let caller: T::AccountId = account("caller", i, SEED);652 (653 caller.clone(),654 (655 BalanceOf::<T>::max_value(),656 create_sub_accounts::<T>(&caller, s)657 .unwrap()658 .try_into()659 .unwrap(),660 ),661 )662 })663 .collect::<Vec<_>>();664 let origin = T::ForceOrigin::try_successful_origin().unwrap();665666 #[extrinsic_call]667 _(origin as T::RuntimeOrigin, identities);668669 Ok(())670 }671672 #[benchmark]673 fn add_sub(s: Linear<1, MAX_SUB_ACCOUNTS>) -> Result<(), BenchmarkError> {674 let s = s - 1;675 let caller: T::AccountId = whitelisted_caller();676 let _ = add_sub_accounts::<T>(&caller, s)?;677 let sub = account("new_sub", 0, SEED);678 let data = Data::Raw(vec![0; 32].try_into().unwrap());679 ensure!(680 SubsOf::<T>::get(&caller).1.len() as u32 == s,681 "Subs not set."682 );683684 #[extrinsic_call]685 _(686 RawOrigin::Signed(caller.clone()),687 T::Lookup::unlookup(sub),688 data,689 );690691 ensure!(692 SubsOf::<T>::get(&caller).1.len() as u32 == s + 1,693 "Subs not added."694 );695696 Ok(())697 }698699 #[benchmark]700 fn rename_sub(s: Linear<1, MAX_SUB_ACCOUNTS>) -> Result<(), BenchmarkError> {701 let caller: T::AccountId = whitelisted_caller();702 let (sub, _) = add_sub_accounts::<T>(&caller, s)?.remove(0);703 let data = Data::Raw(vec![1; 32].try_into().unwrap());704 ensure!(705 SuperOf::<T>::get(&sub).unwrap().1 != data,706 "data already set"707 );708709 #[extrinsic_call]710 _(711 RawOrigin::Signed(caller),712 T::Lookup::unlookup(sub.clone()),713 data.clone(),714 );715716 ensure!(SuperOf::<T>::get(&sub).unwrap().1 == data, "data not set");717718 Ok(())719 }720721 #[benchmark]722 fn remove_sub(s: Linear<1, MAX_SUB_ACCOUNTS>) -> Result<(), BenchmarkError> {723 let caller: T::AccountId = whitelisted_caller();724 let (sub, _) = add_sub_accounts::<T>(&caller, s)?.remove(0);725 ensure!(SuperOf::<T>::contains_key(&sub), "Sub doesn't exists");726727 #[extrinsic_call]728 _(RawOrigin::Signed(caller), T::Lookup::unlookup(sub.clone()));729730 ensure!(!SuperOf::<T>::contains_key(&sub), "Sub not removed");731732 Ok(())733 }734735 #[benchmark]736 fn quit_sub(s: Linear<1, MAX_SUB_ACCOUNTS>) -> Result<(), BenchmarkError> {737 let s = s - 1;738 let caller: T::AccountId = whitelisted_caller();739 let sup = account("super", 0, SEED);740 let _ = add_sub_accounts::<T>(&sup, s)?;741 let sup_origin = RawOrigin::Signed(sup).into();742 Identity::<T>::add_sub(743 sup_origin,744 T::Lookup::unlookup(caller.clone()),745 Data::Raw(vec![0; 32].try_into().unwrap()),746 )?;747 ensure!(SuperOf::<T>::contains_key(&caller), "Sub doesn't exists");748749 #[extrinsic_call]750 _(RawOrigin::Signed(caller.clone()));751752 ensure!(!SuperOf::<T>::contains_key(&caller), "Sub not removed");753754 Ok(())755 }756757 impl_benchmark_test_suite!(Identity, crate::tests::new_test_ext(), crate::tests::Test);758}