git.delta.rocks / unique-network / refs/commits / e08c117c75b4

difftreelog

source

pallets/identity/src/benchmarking.rs21.7 KiBsourcehistory
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617// Original license:18// This file is part of Substrate.1920// Copyright (C) 2020-2022 Parity Technologies (UK) Ltd.21// SPDX-License-Identifier: Apache-2.02223// Licensed under the Apache License, Version 2.0 (the "License");24// you may not use this file except in compliance with the License.25// You may obtain a copy of the License at26//27// 	http://www.apache.org/licenses/LICENSE-2.028//29// Unless required by applicable law or agreed to in writing, software30// distributed under the License is distributed on an "AS IS" BASIS,31// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.32// See the License for the specific language governing permissions and33// limitations under the License.3435//! Identity pallet benchmarking.3637#![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}5354// Adds `r` registrars to the Identity Pallet. These registrars will have set fees and fields.55fn 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(&registrar, 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}7980// Create `s` sub-accounts for the identity of `who` and return them.81// Each will have 32 bytes of raw data added to it.82fn 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	// Set identity so `set_subs` does not fail.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}104105// Adds `s` sub-accounts to the identity of `who`. Each will have 32 bytes of raw data added to it.106// This additionally returns the vector of sub-accounts so it can be modified if needed.107fn 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}118119// This creates an `IdentityInfo` object with `num_fields` extra fields.120// All data is pre-populated with some arbitrary bytes.121fn 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}138139/// `Currency::minimum_balance` was used originally, but in unique-chain, we have140/// zero existential deposit, thus triggering zero bond assertion.141fn 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			// The target user183			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			// Add an initial identity190			let initial_info = create_identity_info::<T>(1);191			Identity::<T>::set_identity(caller_origin.clone(), Box::new(initial_info.clone()))?;192193			// User requests judgement from all the registrars, and they approve194			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(&registrar, 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	// We need to split `set_subs` into two benchmarks to accurately isolate the potential223	// writes caused by new or old sub accounts. The actual weight should simply be224	// the sum of these two weights.225	#[benchmark]226	fn set_subs_new(s: Linear<0, MAX_SUB_ACCOUNTS>) -> Result<(), BenchmarkError> {227		let caller: T::AccountId = whitelisted_caller();228		// Create a new subs vec with s sub accounts229		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		// Give them p many previous sub accounts.250		let _ = add_sub_accounts::<T>(&caller, p)?;251		// Remove all subs.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			// Give them s many sub accounts280			let caller: T::AccountId = whitelisted_caller();281			let _ = add_sub_accounts::<T>(&caller, s)?;282		}283284		// Create their main identity with x additional fields285		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		// User requests judgement from all the registrars, and they approve292		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(&registrar, 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			// Create their main identity with x additional fields334			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			// Create their main identity with x additional fields369			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		// The user496		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		// User requests judgement from all the registrars, and they approve555		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(&registrar, 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}