123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990#![cfg_attr(not(feature = "std"), no_std)]9192mod benchmarking;93#[cfg(test)]94mod tests;95mod types;96pub mod weights;9798use frame_support::traits::{BalanceStatus, Currency, OnUnbalanced, ReservableCurrency};99use sp_runtime::traits::{AppendZerosInput, Hash, Saturating, StaticLookup, Zero};100use sp_std::prelude::*;101pub use weights::WeightInfo;102103pub use pallet::*;104pub use types::{105 Data, IdentityField, IdentityFields, IdentityInfo, Judgement, RegistrarIndex, RegistrarInfo,106 Registration,107};108109pub type BalanceOf<T> =110 <<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;111type NegativeImbalanceOf<T> = <<T as Config>::Currency as Currency<112 <T as frame_system::Config>::AccountId,113>>::NegativeImbalance;114type AccountIdLookupOf<T> = <<T as frame_system::Config>::Lookup as StaticLookup>::Source;115116#[frame_support::pallet]117pub mod pallet {118 use super::*;119 use frame_support::pallet_prelude::*;120 use frame_system::pallet_prelude::*;121122 #[pallet::config]123 pub trait Config: frame_system::Config {124 125 type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;126127 128 type Currency: ReservableCurrency<Self::AccountId>;129130 131 #[pallet::constant]132 type BasicDeposit: Get<BalanceOf<Self>>;133134 135 #[pallet::constant]136 type FieldDeposit: Get<BalanceOf<Self>>;137138 139 140 141 #[pallet::constant]142 type SubAccountDeposit: Get<BalanceOf<Self>>;143144 145 #[pallet::constant]146 type MaxSubAccounts: Get<u32>;147148 149 150 #[pallet::constant]151 type MaxAdditionalFields: Get<u32>;152153 154 155 #[pallet::constant]156 type MaxRegistrars: Get<u32>;157158 159 type Slashed: OnUnbalanced<NegativeImbalanceOf<Self>>;160161 162 type ForceOrigin: EnsureOrigin<Self::RuntimeOrigin>;163164 165 type RegistrarOrigin: EnsureOrigin<Self::RuntimeOrigin>;166167 168 type WeightInfo: WeightInfo;169 }170171 #[pallet::pallet]172 #[pallet::generate_store(pub(super) trait Store)]173 pub struct Pallet<T>(_);174175 176 177 178 #[pallet::storage]179 #[pallet::getter(fn identity)]180 pub(super) type IdentityOf<T: Config> = StorageMap<181 _,182 Twox64Concat,183 T::AccountId,184 Registration<BalanceOf<T>, T::MaxRegistrars, T::MaxAdditionalFields>,185 OptionQuery,186 >;187188 189 190 #[pallet::storage]191 #[pallet::getter(fn super_of)]192 pub(super) type SuperOf<T: Config> =193 StorageMap<_, Blake2_128Concat, T::AccountId, (T::AccountId, Data), OptionQuery>;194195 196 197 198 199 200 #[pallet::storage]201 #[pallet::getter(fn subs_of)]202 pub(super) type SubsOf<T: Config> = StorageMap<203 _,204 Twox64Concat,205 T::AccountId,206 (BalanceOf<T>, BoundedVec<T::AccountId, T::MaxSubAccounts>),207 ValueQuery,208 >;209210 211 212 213 214 #[pallet::storage]215 #[pallet::getter(fn registrars)]216 pub(super) type Registrars<T: Config> = StorageValue<217 _,218 BoundedVec<Option<RegistrarInfo<BalanceOf<T>, T::AccountId>>, T::MaxRegistrars>,219 ValueQuery,220 >;221222 #[pallet::error]223 pub enum Error<T> {224 225 TooManySubAccounts,226 227 NotFound,228 229 NotNamed,230 231 EmptyIndex,232 233 FeeChanged,234 235 NoIdentity,236 237 StickyJudgement,238 239 JudgementGiven,240 241 InvalidJudgement,242 243 InvalidIndex,244 245 InvalidTarget,246 247 TooManyFields,248 249 TooManyRegistrars,250 251 AlreadyClaimed,252 253 NotSub,254 255 NotOwned,256 257 JudgementForDifferentIdentity,258 259 JudgementPaymentFailed,260 }261262 #[pallet::event]263 #[pallet::generate_deposit(pub(super) fn deposit_event)]264 pub enum Event<T: Config> {265 266 IdentitySet { who: T::AccountId },267 268 IdentityCleared {269 who: T::AccountId,270 deposit: BalanceOf<T>,271 },272 273 IdentityKilled {274 who: T::AccountId,275 deposit: BalanceOf<T>,276 },277 278 IdentitiesInserted { amount: u32 },279 280 IdentitiesRemoved { amount: u32 },281 282 JudgementRequested {283 who: T::AccountId,284 registrar_index: RegistrarIndex,285 },286 287 JudgementUnrequested {288 who: T::AccountId,289 registrar_index: RegistrarIndex,290 },291 292 JudgementGiven {293 target: T::AccountId,294 registrar_index: RegistrarIndex,295 },296 297 RegistrarAdded { registrar_index: RegistrarIndex },298 299 SubIdentityAdded {300 sub: T::AccountId,301 main: T::AccountId,302 deposit: BalanceOf<T>,303 },304 305 SubIdentityRemoved {306 sub: T::AccountId,307 main: T::AccountId,308 deposit: BalanceOf<T>,309 },310 311 312 SubIdentityRevoked {313 sub: T::AccountId,314 main: T::AccountId,315 deposit: BalanceOf<T>,316 },317 }318319 #[pallet::call]320 321 impl<T: Config> Pallet<T> {322 323 324 325 326 327 328 329 330 331 332 333 334 335 #[pallet::call_index(0)]336 #[pallet::weight(T::WeightInfo::add_registrar(T::MaxRegistrars::get()))]337 pub fn add_registrar(338 origin: OriginFor<T>,339 account: AccountIdLookupOf<T>,340 ) -> DispatchResultWithPostInfo {341 T::RegistrarOrigin::ensure_origin(origin)?;342 let account = T::Lookup::lookup(account)?;343344 let (i, registrar_count) = <Registrars<T>>::try_mutate(345 |registrars| -> Result<(RegistrarIndex, usize), DispatchError> {346 registrars347 .try_push(Some(RegistrarInfo {348 account,349 fee: Zero::zero(),350 fields: Default::default(),351 }))352 .map_err(|_| Error::<T>::TooManyRegistrars)?;353 Ok(((registrars.len() - 1) as RegistrarIndex, registrars.len()))354 },355 )?;356357 Self::deposit_event(Event::RegistrarAdded { registrar_index: i });358359 Ok(Some(T::WeightInfo::add_registrar(registrar_count as u32)).into())360 }361362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 #[pallet::call_index(1)]382 #[pallet::weight( T::WeightInfo::set_identity(383 T::MaxRegistrars::get(), 384 T::MaxAdditionalFields::get(), 385 ))]386 pub fn set_identity(387 origin: OriginFor<T>,388 info: Box<IdentityInfo<T::MaxAdditionalFields>>,389 ) -> DispatchResultWithPostInfo {390 let sender = ensure_signed(origin)?;391 let extra_fields = info.additional.len() as u32;392 ensure!(393 extra_fields <= T::MaxAdditionalFields::get(),394 Error::<T>::TooManyFields395 );396 let fd = <BalanceOf<T>>::from(extra_fields) * T::FieldDeposit::get();397398 let mut id = match <IdentityOf<T>>::get(&sender) {399 Some(mut id) => {400 401 id.judgements.retain(|j| j.1.is_sticky());402 id.info = *info;403 id404 }405 None => Registration {406 info: *info,407 judgements: BoundedVec::default(),408 deposit: Zero::zero(),409 },410 };411412 let old_deposit = id.deposit;413 id.deposit = T::BasicDeposit::get() + fd;414 if id.deposit > old_deposit {415 T::Currency::reserve(&sender, id.deposit - old_deposit)?;416 }417 if old_deposit > id.deposit {418 let err_amount = T::Currency::unreserve(&sender, old_deposit - id.deposit);419 debug_assert!(err_amount.is_zero());420 }421422 let judgements = id.judgements.len();423 <IdentityOf<T>>::insert(&sender, id);424 Self::deposit_event(Event::IdentitySet { who: sender });425426 Ok(Some(T::WeightInfo::set_identity(427 judgements as u32, 428 extra_fields, 429 ))430 .into())431 }432433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 #[pallet::call_index(2)]461 #[pallet::weight(T::WeightInfo::set_subs_old(T::MaxSubAccounts::get()) 462 .saturating_add(T::WeightInfo::set_subs_new(subs.len() as u32)) 463 )]464 pub fn set_subs(465 origin: OriginFor<T>,466 subs: Vec<(T::AccountId, Data)>,467 ) -> DispatchResultWithPostInfo {468 let sender = ensure_signed(origin)?;469 ensure!(<IdentityOf<T>>::contains_key(&sender), Error::<T>::NotFound);470 ensure!(471 subs.len() <= T::MaxSubAccounts::get() as usize,472 Error::<T>::TooManySubAccounts473 );474475 let (old_deposit, old_ids) = <SubsOf<T>>::get(&sender);476 let new_deposit = T::SubAccountDeposit::get() * <BalanceOf<T>>::from(subs.len() as u32);477478 let not_other_sub = subs479 .iter()480 .filter_map(|i| SuperOf::<T>::get(&i.0))481 .all(|i| i.0 == sender);482 ensure!(not_other_sub, Error::<T>::AlreadyClaimed);483484 if old_deposit < new_deposit {485 T::Currency::reserve(&sender, new_deposit - old_deposit)?;486 } else if old_deposit > new_deposit {487 let err_amount = T::Currency::unreserve(&sender, old_deposit - new_deposit);488 debug_assert!(err_amount.is_zero());489 }490 491492 for s in old_ids.iter() {493 <SuperOf<T>>::remove(s);494 }495 let mut ids = BoundedVec::<T::AccountId, T::MaxSubAccounts>::default();496 for (id, name) in subs {497 <SuperOf<T>>::insert(&id, (sender.clone(), name));498 ids.try_push(id)499 .expect("subs length is less than T::MaxSubAccounts; qed");500 }501 let new_subs = ids.len();502503 if ids.is_empty() {504 <SubsOf<T>>::remove(&sender);505 } else {506 <SubsOf<T>>::insert(&sender, (new_deposit, ids));507 }508509 Ok(Some(510 T::WeightInfo::set_subs_old(old_ids.len() as u32) 511 512 .saturating_add(T::WeightInfo::set_subs_new(new_subs as u32)),513 )514 .into())515 }516517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 #[pallet::call_index(3)]536 #[pallet::weight(T::WeightInfo::clear_identity(537 T::MaxRegistrars::get(), 538 T::MaxSubAccounts::get(), 539 T::MaxAdditionalFields::get(), 540 ))]541 pub fn clear_identity(origin: OriginFor<T>) -> DispatchResultWithPostInfo {542 let sender = ensure_signed(origin)?;543544 let (subs_deposit, sub_ids) = <SubsOf<T>>::take(&sender);545 let id = <IdentityOf<T>>::take(&sender).ok_or(Error::<T>::NotNamed)?;546 let deposit = id.total_deposit() + subs_deposit;547 for sub in sub_ids.iter() {548 <SuperOf<T>>::remove(sub);549 }550551 let err_amount = T::Currency::unreserve(&sender, deposit);552 debug_assert!(err_amount.is_zero());553554 Self::deposit_event(Event::IdentityCleared {555 who: sender,556 deposit,557 });558559 Ok(Some(T::WeightInfo::clear_identity(560 id.judgements.len() as u32, 561 sub_ids.len() as u32, 562 id.info.additional.len() as u32, 563 ))564 .into())565 }566567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 #[pallet::call_index(4)]591 #[pallet::weight(T::WeightInfo::request_judgement(592 T::MaxRegistrars::get(), 593 T::MaxAdditionalFields::get(), 594 ))]595 pub fn request_judgement(596 origin: OriginFor<T>,597 #[pallet::compact] reg_index: RegistrarIndex,598 #[pallet::compact] max_fee: BalanceOf<T>,599 ) -> DispatchResultWithPostInfo {600 let sender = ensure_signed(origin)?;601 let registrars = <Registrars<T>>::get();602 let registrar = registrars603 .get(reg_index as usize)604 .and_then(Option::as_ref)605 .ok_or(Error::<T>::EmptyIndex)?;606 ensure!(max_fee >= registrar.fee, Error::<T>::FeeChanged);607 let mut id = <IdentityOf<T>>::get(&sender).ok_or(Error::<T>::NoIdentity)?;608609 let item = (reg_index, Judgement::FeePaid(registrar.fee));610 match id.judgements.binary_search_by_key(®_index, |x| x.0) {611 Ok(i) => {612 if id.judgements[i].1.is_sticky() {613 return Err(Error::<T>::StickyJudgement.into());614 } else {615 id.judgements[i] = item616 }617 }618 Err(i) => id619 .judgements620 .try_insert(i, item)621 .map_err(|_| Error::<T>::TooManyRegistrars)?,622 }623624 T::Currency::reserve(&sender, registrar.fee)?;625626 let judgements = id.judgements.len();627 let extra_fields = id.info.additional.len();628 <IdentityOf<T>>::insert(&sender, id);629630 Self::deposit_event(Event::JudgementRequested {631 who: sender,632 registrar_index: reg_index,633 });634635 Ok(Some(T::WeightInfo::request_judgement(636 judgements as u32,637 extra_fields as u32,638 ))639 .into())640 }641642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 #[pallet::call_index(5)]660 #[pallet::weight(T::WeightInfo::cancel_request(661 T::MaxRegistrars::get(), 662 T::MaxAdditionalFields::get(), 663 ))]664 pub fn cancel_request(665 origin: OriginFor<T>,666 reg_index: RegistrarIndex,667 ) -> DispatchResultWithPostInfo {668 let sender = ensure_signed(origin)?;669 let mut id = <IdentityOf<T>>::get(&sender).ok_or(Error::<T>::NoIdentity)?;670671 let pos = id672 .judgements673 .binary_search_by_key(®_index, |x| x.0)674 .map_err(|_| Error::<T>::NotFound)?;675 let fee = if let Judgement::FeePaid(fee) = id.judgements.remove(pos).1 {676 fee677 } else {678 return Err(Error::<T>::JudgementGiven.into());679 };680681 let err_amount = T::Currency::unreserve(&sender, fee);682 debug_assert!(err_amount.is_zero());683 let judgements = id.judgements.len();684 let extra_fields = id.info.additional.len();685 <IdentityOf<T>>::insert(&sender, id);686687 Self::deposit_event(Event::JudgementUnrequested {688 who: sender,689 registrar_index: reg_index,690 });691692 Ok(Some(T::WeightInfo::cancel_request(693 judgements as u32,694 extra_fields as u32,695 ))696 .into())697 }698699 700 701 702 703 704 705 706 707 708 709 710 711 712 #[pallet::call_index(6)]713 #[pallet::weight(T::WeightInfo::set_fee(T::MaxRegistrars::get()))] 714 pub fn set_fee(715 origin: OriginFor<T>,716 #[pallet::compact] index: RegistrarIndex,717 #[pallet::compact] fee: BalanceOf<T>,718 ) -> DispatchResultWithPostInfo {719 let who = ensure_signed(origin)?;720721 let registrars = <Registrars<T>>::mutate(|rs| -> Result<usize, DispatchError> {722 rs.get_mut(index as usize)723 .and_then(|x| x.as_mut())724 .and_then(|r| {725 if r.account == who {726 r.fee = fee;727 Some(())728 } else {729 None730 }731 })732 .ok_or_else(|| DispatchError::from(Error::<T>::InvalidIndex))?;733 Ok(rs.len())734 })?;735 Ok(Some(T::WeightInfo::set_fee(registrars as u32)).into()) 736 }737738 739 740 741 742 743 744 745 746 747 748 749 750 751 #[pallet::call_index(7)]752 #[pallet::weight(T::WeightInfo::set_account_id(T::MaxRegistrars::get()))] 753 pub fn set_account_id(754 origin: OriginFor<T>,755 #[pallet::compact] index: RegistrarIndex,756 new: AccountIdLookupOf<T>,757 ) -> DispatchResultWithPostInfo {758 let who = ensure_signed(origin)?;759 let new = T::Lookup::lookup(new)?;760761 let registrars = <Registrars<T>>::mutate(|rs| -> Result<usize, DispatchError> {762 rs.get_mut(index as usize)763 .and_then(|x| x.as_mut())764 .and_then(|r| {765 if r.account == who {766 r.account = new;767 Some(())768 } else {769 None770 }771 })772 .ok_or_else(|| DispatchError::from(Error::<T>::InvalidIndex))?;773 Ok(rs.len())774 })?;775 Ok(Some(T::WeightInfo::set_account_id(registrars as u32)).into()) 776 }777778 779 780 781 782 783 784 785 786 787 788 789 790 791 #[pallet::call_index(8)]792 #[pallet::weight(T::WeightInfo::set_fields(T::MaxRegistrars::get()))] 793 pub fn set_fields(794 origin: OriginFor<T>,795 #[pallet::compact] index: RegistrarIndex,796 fields: IdentityFields,797 ) -> DispatchResultWithPostInfo {798 let who = ensure_signed(origin)?;799800 let registrars = <Registrars<T>>::mutate(|rs| -> Result<usize, DispatchError> {801 rs.get_mut(index as usize)802 .and_then(|x| x.as_mut())803 .and_then(|r| {804 if r.account == who {805 r.fields = fields;806 Some(())807 } else {808 None809 }810 })811 .ok_or_else(|| DispatchError::from(Error::<T>::InvalidIndex))?;812 Ok(rs.len())813 })?;814 Ok(Some(T::WeightInfo::set_fields(815 registrars as u32, 816 ))817 .into())818 }819820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 #[pallet::call_index(9)]841 #[pallet::weight(T::WeightInfo::provide_judgement(842 T::MaxRegistrars::get(), 843 T::MaxAdditionalFields::get(), 844 ))]845 pub fn provide_judgement(846 origin: OriginFor<T>,847 #[pallet::compact] reg_index: RegistrarIndex,848 target: AccountIdLookupOf<T>,849 judgement: Judgement<BalanceOf<T>>,850 identity: T::Hash,851 ) -> DispatchResultWithPostInfo {852 let sender = ensure_signed(origin)?;853 let target = T::Lookup::lookup(target)?;854 ensure!(!judgement.has_deposit(), Error::<T>::InvalidJudgement);855 <Registrars<T>>::get()856 .get(reg_index as usize)857 .and_then(Option::as_ref)858 .filter(|r| r.account == sender)859 .ok_or(Error::<T>::InvalidIndex)?;860 let mut id = <IdentityOf<T>>::get(&target).ok_or(Error::<T>::InvalidTarget)?;861862 if T::Hashing::hash_of(&id.info) != identity {863 return Err(Error::<T>::JudgementForDifferentIdentity.into());864 }865866 let item = (reg_index, judgement);867 match id.judgements.binary_search_by_key(®_index, |x| x.0) {868 Ok(position) => {869 if let Judgement::FeePaid(fee) = id.judgements[position].1 {870 T::Currency::repatriate_reserved(871 &target,872 &sender,873 fee,874 BalanceStatus::Free,875 )876 .map_err(|_| Error::<T>::JudgementPaymentFailed)?;877 }878 id.judgements[position] = item879 }880 Err(position) => id881 .judgements882 .try_insert(position, item)883 .map_err(|_| Error::<T>::TooManyRegistrars)?,884 }885886 let judgements = id.judgements.len();887 let extra_fields = id.info.additional.len();888 <IdentityOf<T>>::insert(&target, id);889 Self::deposit_event(Event::JudgementGiven {890 target,891 registrar_index: reg_index,892 });893894 Ok(Some(T::WeightInfo::provide_judgement(895 judgements as u32,896 extra_fields as u32,897 ))898 .into())899 }900901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 #[pallet::call_index(10)]921 #[pallet::weight(T::WeightInfo::kill_identity(922 T::MaxRegistrars::get(), 923 T::MaxSubAccounts::get(), 924 T::MaxAdditionalFields::get(), 925 ))]926 pub fn kill_identity(927 origin: OriginFor<T>,928 target: AccountIdLookupOf<T>,929 ) -> DispatchResultWithPostInfo {930 T::ForceOrigin::ensure_origin(origin)?;931932 933 let target = T::Lookup::lookup(target)?;934 935 let (subs_deposit, sub_ids) = <SubsOf<T>>::take(&target);936 let id = <IdentityOf<T>>::take(&target).ok_or(Error::<T>::NotNamed)?;937 let deposit = id.total_deposit() + subs_deposit;938 for sub in sub_ids.iter() {939 <SuperOf<T>>::remove(sub);940 }941 942 T::Slashed::on_unbalanced(T::Currency::slash_reserved(&target, deposit).0);943944 Self::deposit_event(Event::IdentityKilled {945 who: target,946 deposit,947 });948949 Ok(Some(T::WeightInfo::kill_identity(950 id.judgements.len() as u32, 951 sub_ids.len() as u32, 952 id.info.additional.len() as u32, 953 ))954 .into())955 }956957 958 959 960 961 962 963 964 #[pallet::call_index(11)]965 #[pallet::weight(T::WeightInfo::add_sub(T::MaxSubAccounts::get()))]966 pub fn add_sub(967 origin: OriginFor<T>,968 sub: AccountIdLookupOf<T>,969 data: Data,970 ) -> DispatchResult {971 let sender = ensure_signed(origin)?;972 let sub = T::Lookup::lookup(sub)?;973 ensure!(974 IdentityOf::<T>::contains_key(&sender),975 Error::<T>::NoIdentity976 );977978 979 ensure!(980 !SuperOf::<T>::contains_key(&sub),981 Error::<T>::AlreadyClaimed982 );983984 SubsOf::<T>::try_mutate(&sender, |(ref mut subs_deposit, ref mut sub_ids)| {985 986 ensure!(987 sub_ids.len() < T::MaxSubAccounts::get() as usize,988 Error::<T>::TooManySubAccounts989 );990 let deposit = T::SubAccountDeposit::get();991 T::Currency::reserve(&sender, deposit)?;992993 SuperOf::<T>::insert(&sub, (sender.clone(), data));994 sub_ids995 .try_push(sub.clone())996 .expect("sub ids length checked above; qed");997 *subs_deposit = subs_deposit.saturating_add(deposit);998999 Self::deposit_event(Event::SubIdentityAdded {1000 sub,1001 main: sender.clone(),1002 deposit,1003 });1004 Ok(())1005 })1006 }10071008 1009 1010 1011 1012 #[pallet::call_index(12)]1013 #[pallet::weight(T::WeightInfo::rename_sub(T::MaxSubAccounts::get()))]1014 pub fn rename_sub(1015 origin: OriginFor<T>,1016 sub: AccountIdLookupOf<T>,1017 data: Data,1018 ) -> DispatchResult {1019 let sender = ensure_signed(origin)?;1020 let sub = T::Lookup::lookup(sub)?;1021 ensure!(1022 IdentityOf::<T>::contains_key(&sender),1023 Error::<T>::NoIdentity1024 );1025 ensure!(1026 SuperOf::<T>::get(&sub).map_or(false, |x| x.0 == sender),1027 Error::<T>::NotOwned1028 );1029 SuperOf::<T>::insert(&sub, (sender, data));1030 Ok(())1031 }10321033 1034 1035 1036 1037 1038 1039 1040 #[pallet::call_index(13)]1041 #[pallet::weight(T::WeightInfo::remove_sub(T::MaxSubAccounts::get()))]1042 pub fn remove_sub(origin: OriginFor<T>, sub: AccountIdLookupOf<T>) -> DispatchResult {1043 let sender = ensure_signed(origin)?;1044 ensure!(1045 IdentityOf::<T>::contains_key(&sender),1046 Error::<T>::NoIdentity1047 );1048 let sub = T::Lookup::lookup(sub)?;1049 let (sup, _) = SuperOf::<T>::get(&sub).ok_or(Error::<T>::NotSub)?;1050 ensure!(sup == sender, Error::<T>::NotOwned);1051 SuperOf::<T>::remove(&sub);1052 SubsOf::<T>::mutate(&sup, |(ref mut subs_deposit, ref mut sub_ids)| {1053 sub_ids.retain(|x| x != &sub);1054 let deposit = T::SubAccountDeposit::get().min(*subs_deposit);1055 *subs_deposit -= deposit;1056 let err_amount = T::Currency::unreserve(&sender, deposit);1057 debug_assert!(err_amount.is_zero());1058 Self::deposit_event(Event::SubIdentityRemoved {1059 sub,1060 main: sender,1061 deposit,1062 });1063 });1064 Ok(())1065 }10661067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 #[pallet::call_index(14)]1078 #[pallet::weight(T::WeightInfo::quit_sub(T::MaxSubAccounts::get()))]1079 pub fn quit_sub(origin: OriginFor<T>) -> DispatchResult {1080 let sender = ensure_signed(origin)?;1081 let (sup, _) = SuperOf::<T>::take(&sender).ok_or(Error::<T>::NotSub)?;1082 SubsOf::<T>::mutate(&sup, |(ref mut subs_deposit, ref mut sub_ids)| {1083 sub_ids.retain(|x| x != &sender);1084 let deposit = T::SubAccountDeposit::get().min(*subs_deposit);1085 *subs_deposit -= deposit;1086 let _ =1087 T::Currency::repatriate_reserved(&sup, &sender, deposit, BalanceStatus::Free);1088 Self::deposit_event(Event::SubIdentityRevoked {1089 sub: sender,1090 main: sup.clone(),1091 deposit,1092 });1093 });1094 Ok(())1095 }10961097 1098 1099 1100 1101 1102 #[pallet::call_index(15)]1103 #[pallet::weight(T::WeightInfo::force_insert_identities(1104 T::MaxAdditionalFields::get(), 1105 identities.len() as u32, 1106 ))]1107 pub fn force_insert_identities(1108 origin: OriginFor<T>,1109 identities: Vec<(1110 T::AccountId,1111 Registration<BalanceOf<T>, T::MaxRegistrars, T::MaxAdditionalFields>,1112 )>,1113 ) -> DispatchResult {1114 T::ForceOrigin::ensure_origin(origin)?;1115 for identity in identities.clone() {1116 IdentityOf::<T>::insert(identity.0, identity.1);1117 }1118 Self::deposit_event(Event::IdentitiesInserted {1119 amount: identities.len() as u32,1120 });1121 Ok(())1122 }11231124 1125 1126 1127 1128 1129 #[pallet::call_index(16)]1130 #[pallet::weight(T::WeightInfo::force_remove_identities(1131 T::MaxAdditionalFields::get(), 1132 identities.len() as u32, 1133 ))]1134 pub fn force_remove_identities(1135 origin: OriginFor<T>,1136 identities: Vec<T::AccountId>,1137 ) -> DispatchResult {1138 T::ForceOrigin::ensure_origin(origin)?;1139 for identity in identities.clone() {1140 IdentityOf::<T>::set(identity, None);1141 }1142 Self::deposit_event(Event::IdentitiesRemoved {1143 amount: identities.len() as u32,1144 });1145 Ok(())1146 }1147 }1148}11491150impl<T: Config> Pallet<T> {1151 1152 pub fn subs(who: &T::AccountId) -> Vec<(T::AccountId, Data)> {1153 SubsOf::<T>::get(who)1154 .11155 .into_iter()1156 .filter_map(|a| SuperOf::<T>::get(&a).map(|x| (a, x.1)))1157 .collect()1158 }11591160 1161 pub fn has_identity(who: &T::AccountId, fields: u64) -> bool {1162 IdentityOf::<T>::get(who).map_or(false, |registration| {1163 (registration.info.fields().0.bits() & fields) == fields1164 })1165 }1166}