1extern crate alloc;
19
20use super::*;
21use frame_support::{
22 migrations::VersionedMigration, pallet_prelude::*, storage_alias,
23 traits::UncheckedOnRuntimeUpgrade, IterableStorageMap,
24};
25
26#[cfg(feature = "try-runtime")]
27use alloc::collections::BTreeMap;
28#[cfg(feature = "try-runtime")]
29use codec::{Decode, Encode};
30#[cfg(feature = "try-runtime")]
31use sp_runtime::TryRuntimeError;
32
33pub const PALLET_MIGRATIONS_ID: &[u8; 15] = b"pallet-identity";
34
35pub mod versioned {
36 use super::*;
37
38 pub type V0ToV1<T, const KL: u64> = VersionedMigration<
39 0,
40 1,
41 v1::VersionUncheckedMigrateV0ToV1<T, KL>,
42 crate::pallet::Pallet<T>,
43 <T as frame_system::Config>::DbWeight,
44 >;
45}
46
47mod types_v0 {
49 use super::*;
50
51 #[storage_alias]
52 pub type IdentityOf<T: Config> = StorageMap<
53 Pallet<T>,
54 Twox64Concat,
55 <T as frame_system::Config>::AccountId,
56 Registration<
57 BalanceOf<T>,
58 <T as pallet::Config>::MaxRegistrars,
59 <T as pallet::Config>::IdentityInformation,
60 >,
61 OptionQuery,
62 >;
63}
64
65mod types_v1 {
67 use super::*;
68
69 #[storage_alias]
70 pub type IdentityOf<T: Config> = StorageMap<
71 Pallet<T>,
72 Twox64Concat,
73 <T as frame_system::Config>::AccountId,
74 (
75 Registration<
76 BalanceOf<T>,
77 <T as pallet::Config>::MaxRegistrars,
78 <T as pallet::Config>::IdentityInformation,
79 >,
80 Option<Username<T>>,
81 ),
82 OptionQuery,
83 >;
84
85 #[storage_alias]
86 pub type UsernameAuthorities<T: Config> = StorageMap<
87 Pallet<T>,
88 Twox64Concat,
89 <T as frame_system::Config>::AccountId,
90 AuthorityProperties<Suffix<T>>,
91 OptionQuery,
92 >;
93
94 #[storage_alias]
95 pub type AccountOfUsername<T: Config> = StorageMap<
96 Pallet<T>,
97 Blake2_128Concat,
98 Username<T>,
99 <T as frame_system::Config>::AccountId,
100 OptionQuery,
101 >;
102
103 #[cfg(feature = "try-runtime")]
104 #[storage_alias]
105 pub type PendingUsernames<T: Config> = StorageMap<
106 Pallet<T>,
107 Blake2_128Concat,
108 Username<T>,
109 (<T as frame_system::Config>::AccountId, BlockNumberFor<T>),
110 OptionQuery,
111 >;
112}
113
114pub mod v1 {
115 use super::*;
116
117 const TARGET: &'static str = "runtime::identity::migration::v1";
119 pub struct VersionUncheckedMigrateV0ToV1<T, const KL: u64>(PhantomData<T>);
125 impl<T: Config, const KL: u64> UncheckedOnRuntimeUpgrade for VersionUncheckedMigrateV0ToV1<T, KL> {
126 #[cfg(feature = "try-runtime")]
127 fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
128 let identities = types_v0::IdentityOf::<T>::iter().count();
129 log::info!(
130 target: TARGET,
131 "pre-upgrade state contains '{}' identities.",
132 identities
133 );
134 ensure!((identities as u64) < KL, "too many identities to migrate");
135 Ok((identities as u64).encode())
136 }
137
138 fn on_runtime_upgrade() -> Weight {
139 log::info!(
140 target: TARGET,
141 "running storage migration from version 0 to version 1."
142 );
143
144 let mut weight = T::DbWeight::get().reads(1);
145 let mut translated: u64 = 0;
146 let mut interrupted = false;
147
148 for (account, registration) in types_v0::IdentityOf::<T>::iter() {
149 types_v1::IdentityOf::<T>::insert(account, (registration, None::<Username<T>>));
150 translated.saturating_inc();
151 if translated >= KL {
152 log::warn!(
153 "Incomplete! Migration limit reached. Only {} identities migrated.",
154 translated
155 );
156 interrupted = true;
157 break
158 }
159 }
160 if !interrupted {
161 log::info!("all {} identities migrated", translated);
162 }
163
164 weight.saturating_accrue(T::DbWeight::get().reads_writes(translated, translated));
165 weight.saturating_accrue(T::DbWeight::get().writes(1));
166 weight
167 }
168
169 #[cfg(feature = "try-runtime")]
170 fn post_upgrade(state: Vec<u8>) -> Result<(), TryRuntimeError> {
171 let identities_to_migrate: u64 = Decode::decode(&mut &state[..])
172 .expect("failed to decode the state from pre-upgrade.");
173 let identities = types_v1::IdentityOf::<T>::iter().count() as u64;
174 log::info!("post-upgrade expects '{}' identities to have been migrated.", identities);
175 ensure!(identities_to_migrate == identities, "must migrate all identities.");
176 log::info!(target: TARGET, "migrated all identities.");
177 Ok(())
178 }
179 }
180}
181
182pub mod v2 {
183 use super::*;
184 use frame_support::{
185 migrations::{MigrationId, SteppedMigration, SteppedMigrationError},
186 weights::WeightMeter,
187 };
188
189 type HashedKey = BoundedVec<u8, ConstU32<256>>;
190 type StepResultOf<T> =
192 MigrationState<<T as frame_system::Config>::AccountId, Username<T>, Suffix<T>>;
193
194 #[cfg(feature = "runtime-benchmarks")]
195 pub(crate) type BenchmarkingSetupOf<T> =
196 BenchmarkingSetup<Suffix<T>, <T as frame_system::Config>::AccountId, Username<T>>;
197
198 #[derive(Decode, Encode, MaxEncodedLen, Eq, PartialEq)]
201 pub enum MigrationState<A, U, S> {
202 Authority(A),
203 FinishedAuthorities,
204 Identity(HashedKey),
205 FinishedIdentities,
206 Username(U),
207 FinishedUsernames,
208 PendingUsername(HashedKey),
209 FinishedPendingUsernames,
210 CleanupAuthorities(S),
211 FinishedCleanupAuthorities,
212 CleanupUsernames(U),
213 Finished,
214 }
215
216 #[cfg(feature = "try-runtime")]
217 #[derive(Encode, Decode)]
218 struct TryRuntimeState<T: Config> {
219 authorities: BTreeMap<Suffix<T>, (T::AccountId, u32)>,
220 identities: BTreeMap<
221 T::AccountId,
222 Registration<
223 BalanceOf<T>,
224 <T as Config>::MaxRegistrars,
225 <T as Config>::IdentityInformation,
226 >,
227 >,
228 primary_usernames: BTreeMap<T::AccountId, Username<T>>,
229 usernames: BTreeMap<Username<T>, T::AccountId>,
230 pending_usernames: BTreeMap<Username<T>, (T::AccountId, BlockNumberFor<T>)>,
231 }
232
233 pub struct LazyMigrationV1ToV2<T: Config>(PhantomData<T>);
234 impl<T: Config> SteppedMigration for LazyMigrationV1ToV2<T> {
235 type Cursor = MigrationState<T::AccountId, Username<T>, Suffix<T>>;
236 type Identifier = MigrationId<15>;
237
238 fn id() -> Self::Identifier {
239 MigrationId { pallet_id: *PALLET_MIGRATIONS_ID, version_from: 1, version_to: 2 }
240 }
241
242 fn step(
243 mut cursor: Option<Self::Cursor>,
244 meter: &mut WeightMeter,
245 ) -> Result<Option<Self::Cursor>, SteppedMigrationError> {
246 if Pallet::<T>::on_chain_storage_version() != Self::id().version_from as u16 {
247 return Ok(None);
248 }
249
250 let required = match &cursor {
253 Some(state) => Self::required_weight(&state),
254 None => T::WeightInfo::migration_v2_authority_step(),
256 };
257 if meter.remaining().any_lt(required) {
258 return Err(SteppedMigrationError::InsufficientWeight { required });
259 }
260
261 loop {
262 let required_weight = match &cursor {
265 Some(state) => Self::required_weight(&state),
266 None => T::WeightInfo::migration_v2_authority_step(),
268 };
269 if !meter.can_consume(required_weight) {
270 break;
271 }
272
273 let next = match &cursor {
274 None => Self::authority_step(None),
276 Some(MigrationState::Authority(maybe_last_authority)) =>
278 Self::authority_step(Some(maybe_last_authority)),
279 Some(MigrationState::FinishedAuthorities) => Self::username_step(None),
282 Some(MigrationState::Username(maybe_last_username)) =>
284 Self::username_step(Some(maybe_last_username)),
285 Some(MigrationState::FinishedUsernames) => Self::identity_step(None),
290 Some(MigrationState::Identity(last_key)) =>
292 Self::identity_step(Some(last_key.clone())),
293 Some(MigrationState::FinishedIdentities) => Self::pending_username_step(None),
296 Some(MigrationState::PendingUsername(last_key)) =>
298 Self::pending_username_step(Some(last_key.clone())),
299 Some(MigrationState::FinishedPendingUsernames) =>
302 Self::cleanup_authority_step(None),
303 Some(MigrationState::CleanupAuthorities(maybe_last_username)) =>
305 Self::cleanup_authority_step(Some(maybe_last_username)),
306 Some(MigrationState::FinishedCleanupAuthorities) =>
309 Self::cleanup_username_step(None),
310 Some(MigrationState::CleanupUsernames(maybe_last_username)) =>
312 Self::cleanup_username_step(Some(maybe_last_username)),
313 Some(MigrationState::Finished) => {
316 StorageVersion::new(Self::id().version_to as u16).put::<Pallet<T>>();
317 return Ok(None)
318 },
319 };
320
321 cursor = Some(next);
322 meter.consume(required_weight);
323 }
324
325 Ok(cursor)
326 }
327
328 #[cfg(feature = "try-runtime")]
329 fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
330 let authorities: BTreeMap<Suffix<T>, (T::AccountId, u32)> =
331 types_v1::UsernameAuthorities::<T>::iter()
332 .map(|(account, authority_properties)| {
333 (
334 authority_properties.account_id,
335 (account, authority_properties.allocation),
336 )
337 })
338 .collect();
339 let mut primary_usernames: BTreeMap<_, _> = Default::default();
340 let identities = types_v1::IdentityOf::<T>::iter()
341 .map(|(account, (identity, maybe_username))| {
342 if let Some(username) = maybe_username {
343 primary_usernames.insert(account.clone(), username);
344 }
345 (account, identity)
346 })
347 .collect::<BTreeMap<_, _>>();
348 let usernames = types_v1::AccountOfUsername::<T>::iter().collect::<BTreeMap<_, _>>();
349 let pending_usernames: BTreeMap<Username<T>, (T::AccountId, BlockNumberFor<T>)> =
350 types_v1::PendingUsernames::<T>::iter().collect();
351 let state: TryRuntimeState<T> = TryRuntimeState {
352 authorities,
353 identities,
354 primary_usernames,
355 usernames,
356 pending_usernames,
357 };
358
359 Ok(state.encode())
360 }
361
362 #[cfg(feature = "try-runtime")]
363 fn post_upgrade(state: Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
364 let mut prev_state: TryRuntimeState<T> = TryRuntimeState::<T>::decode(&mut &state[..])
365 .expect("Failed to decode the previous storage state");
366
367 for (suffix, authority_properties) in AuthorityOf::<T>::iter() {
368 let (prev_account, prev_allocation) = prev_state
369 .authorities
370 .remove(&suffix)
371 .expect("should have authority in previous state");
372 assert_eq!(prev_account, authority_properties.account_id);
373 assert_eq!(prev_allocation, authority_properties.allocation);
374 }
375 assert!(prev_state.authorities.is_empty());
376
377 for (account, identity) in IdentityOf::<T>::iter() {
378 assert!(identity.deposit > 0u32.into());
379 let prev_identity = prev_state
380 .identities
381 .remove(&account)
382 .expect("should have identity in previous state");
383 assert_eq!(identity, prev_identity);
384 }
385
386 for (account, free_identity) in prev_state.identities.iter() {
387 assert_eq!(free_identity.deposit, 0u32.into());
388 assert!(UsernameOf::<T>::contains_key(&account));
389 }
390 prev_state.identities.clear();
391
392 for (account, primary_username) in UsernameOf::<T>::iter() {
393 let prev_primary_username = prev_state
394 .primary_usernames
395 .remove(&account)
396 .expect("should have primary username in previous state");
397 assert_eq!(prev_primary_username, primary_username);
398 }
399
400 for (username, username_info) in UsernameInfoOf::<T>::iter() {
401 let prev_account = prev_state
402 .usernames
403 .remove(&username)
404 .expect("should have username info in previous state");
405 assert_eq!(prev_account, username_info.owner);
406 assert_eq!(username_info.provider, Provider::Allocation);
407 }
408 assert!(prev_state.usernames.is_empty());
409
410 for (username, (account, expiration, provider)) in PendingUsernames::<T>::iter() {
411 let (prev_account, prev_expiration) = prev_state
412 .pending_usernames
413 .remove(&username)
414 .expect("should have pending username in previous state");
415 assert_eq!(prev_account, account);
416 assert_eq!(prev_expiration, expiration);
417 assert_eq!(provider, Provider::Allocation);
418 }
419 assert!(prev_state.pending_usernames.is_empty());
420
421 Ok(())
422 }
423 }
424
425 impl<T: Config> LazyMigrationV1ToV2<T> {
426 pub(crate) fn required_weight(
427 step: &MigrationState<T::AccountId, Username<T>, Suffix<T>>,
428 ) -> Weight {
429 match step {
430 MigrationState::Authority(_) => T::WeightInfo::migration_v2_authority_step(),
431 MigrationState::FinishedAuthorities | MigrationState::Username(_) =>
432 T::WeightInfo::migration_v2_username_step(),
433 MigrationState::FinishedUsernames | MigrationState::Identity(_) =>
434 T::WeightInfo::migration_v2_identity_step(),
435 MigrationState::FinishedIdentities | MigrationState::PendingUsername(_) =>
436 T::WeightInfo::migration_v2_pending_username_step(),
437 MigrationState::FinishedPendingUsernames |
438 MigrationState::CleanupAuthorities(_) => T::WeightInfo::migration_v2_cleanup_authority_step(),
439 MigrationState::FinishedCleanupAuthorities |
440 MigrationState::CleanupUsernames(_) => T::WeightInfo::migration_v2_cleanup_username_step(),
441 MigrationState::Finished => Weight::zero(),
442 }
443 }
444
445 pub(crate) fn authority_step(maybe_last_key: Option<&T::AccountId>) -> StepResultOf<T> {
447 let mut iter = if let Some(last_key) = maybe_last_key {
448 types_v1::UsernameAuthorities::<T>::iter_from(
449 types_v1::UsernameAuthorities::<T>::hashed_key_for(last_key),
450 )
451 } else {
452 types_v1::UsernameAuthorities::<T>::iter()
453 };
454 if let Some((authority_account, properties)) = iter.next() {
455 let suffix = properties.account_id;
456 let allocation = properties.allocation;
457 let new_properties =
458 AuthorityProperties { account_id: authority_account.clone(), allocation };
459 AuthorityOf::<T>::insert(&suffix, new_properties);
460 MigrationState::Authority(authority_account)
461 } else {
462 MigrationState::FinishedAuthorities
463 }
464 }
465
466 pub(crate) fn username_step(maybe_last_key: Option<&Username<T>>) -> StepResultOf<T> {
468 let mut iter = if let Some(last_key) = maybe_last_key {
469 types_v1::AccountOfUsername::<T>::iter_from(
470 types_v1::AccountOfUsername::<T>::hashed_key_for(last_key),
471 )
472 } else {
473 types_v1::AccountOfUsername::<T>::iter()
474 };
475
476 if let Some((username, owner_account)) = iter.next() {
477 let username_info = UsernameInformation {
478 owner: owner_account,
479 provider: Provider::new_with_allocation(),
480 };
481 UsernameInfoOf::<T>::insert(&username, username_info);
482
483 MigrationState::Username(username)
484 } else {
485 MigrationState::FinishedUsernames
486 }
487 }
488
489 pub(crate) fn identity_step(maybe_last_key: Option<HashedKey>) -> StepResultOf<T> {
492 if let Some(mut last_key) =
493 IdentityOf::<T>::translate_next::<
494 (
495 Registration<
496 BalanceOf<T>,
497 <T as pallet::Config>::MaxRegistrars,
498 <T as pallet::Config>::IdentityInformation,
499 >,
500 Option<Username<T>>,
501 ),
502 _,
503 >(maybe_last_key.map(|b| b.to_vec()), |account, (identity, maybe_username)| {
504 if let Some(primary_username) = maybe_username {
505 UsernameOf::<T>::insert(&account, primary_username);
506 }
507 if identity.deposit > BalanceOf::<T>::zero() {
508 Some(identity)
509 } else {
510 None
511 }
512 }) {
513 last_key.truncate(HashedKey::bound());
514 MigrationState::Identity(
515 HashedKey::try_from(last_key)
516 .expect("truncated to bound so the conversion must succeed; qed"),
517 )
518 } else {
519 MigrationState::FinishedIdentities
520 }
521 }
522
523 pub(crate) fn pending_username_step(maybe_last_key: Option<HashedKey>) -> StepResultOf<T> {
525 if let Some(mut last_key) =
526 PendingUsernames::<T>::translate_next::<(T::AccountId, BlockNumberFor<T>), _>(
527 maybe_last_key.map(|b| b.to_vec()),
528 |_, (owner_account, since)| {
529 Some((owner_account, since, Provider::new_with_allocation()))
530 },
531 ) {
532 last_key.truncate(HashedKey::bound());
533 MigrationState::PendingUsername(
534 HashedKey::try_from(last_key)
535 .expect("truncated to bound so the conversion must succeed; qed"),
536 )
537 } else {
538 MigrationState::FinishedPendingUsernames
539 }
540 }
541
542 pub(crate) fn cleanup_authority_step(
544 maybe_last_key: Option<&Suffix<T>>,
545 ) -> StepResultOf<T> {
546 let mut iter = if let Some(last_key) = maybe_last_key {
547 AuthorityOf::<T>::iter_from(AuthorityOf::<T>::hashed_key_for(last_key))
548 } else {
549 AuthorityOf::<T>::iter()
550 };
551
552 if let Some((suffix, properties)) = iter.next() {
553 let _ = types_v1::UsernameAuthorities::<T>::take(&properties.account_id);
554 MigrationState::CleanupAuthorities(suffix)
555 } else {
556 MigrationState::FinishedCleanupAuthorities
557 }
558 }
559
560 pub(crate) fn cleanup_username_step(
562 maybe_last_key: Option<&Username<T>>,
563 ) -> StepResultOf<T> {
564 let mut iter = if let Some(last_key) = maybe_last_key {
565 UsernameInfoOf::<T>::iter_from(UsernameInfoOf::<T>::hashed_key_for(last_key))
566 } else {
567 UsernameInfoOf::<T>::iter()
568 };
569
570 if let Some((username, _)) = iter.next() {
571 let _ = types_v1::AccountOfUsername::<T>::take(&username);
572 MigrationState::CleanupUsernames(username)
573 } else {
574 MigrationState::Finished
575 }
576 }
577 }
578
579 #[cfg(feature = "runtime-benchmarks")]
580 pub(crate) struct BenchmarkingSetup<S, A, U> {
581 pub(crate) suffix: S,
582 pub(crate) authority: A,
583 pub(crate) account: A,
584 pub(crate) username: U,
585 }
586
587 #[cfg(feature = "runtime-benchmarks")]
588 impl<T: Config> LazyMigrationV1ToV2<T> {
589 pub(crate) fn setup_benchmark_env_for_migration() -> BenchmarkingSetupOf<T> {
590 use frame_support::Hashable;
591 let suffix: Suffix<T> = b"bench".to_vec().try_into().unwrap();
592 let authority: T::AccountId = frame_benchmarking::account("authority", 0, 0);
593 let account_id: T::AccountId = frame_benchmarking::account("account", 1, 0);
594
595 let prop: AuthorityProperties<Suffix<T>> =
596 AuthorityProperties { account_id: suffix.clone(), allocation: 10 };
597 types_v1::UsernameAuthorities::<T>::insert(&authority, &prop);
598
599 let username: Username<T> = b"account.bench".to_vec().try_into().unwrap();
600 let info = T::IdentityInformation::create_identity_info();
601 let registration: Registration<
602 BalanceOf<T>,
603 <T as Config>::MaxRegistrars,
604 <T as Config>::IdentityInformation,
605 > = Registration { judgements: Default::default(), deposit: 10u32.into(), info };
606 frame_support::migration::put_storage_value(
607 b"Identity",
608 b"IdentityOf",
609 &account_id.twox_64_concat(),
610 (®istration, Some(username.clone())),
611 );
612 types_v1::AccountOfUsername::<T>::insert(&username, &account_id);
613 let since: BlockNumberFor<T> = 0u32.into();
614 frame_support::migration::put_storage_value(
615 b"Identity",
616 b"PendingUsernames",
617 &username.blake2_128_concat(),
618 (&account_id, since),
619 );
620 BenchmarkingSetup { suffix, authority, account: account_id, username }
621 }
622
623 pub(crate) fn setup_benchmark_env_for_cleanup() -> BenchmarkingSetupOf<T> {
624 let suffix: Suffix<T> = b"bench".to_vec().try_into().unwrap();
625 let authority: T::AccountId = frame_benchmarking::account("authority", 0, 0);
626 let account_id: T::AccountId = frame_benchmarking::account("account", 1, 0);
627
628 let prop: AuthorityProperties<Suffix<T>> =
629 AuthorityProperties { account_id: suffix.clone(), allocation: 10 };
630 types_v1::UsernameAuthorities::<T>::insert(&authority, &prop);
631 let prop: AuthorityProperties<T::AccountId> =
632 AuthorityProperties { account_id: authority.clone(), allocation: 10 };
633 AuthorityOf::<T>::insert(&suffix, &prop);
634
635 let username: Username<T> = b"account.bench".to_vec().try_into().unwrap();
636 let info = T::IdentityInformation::create_identity_info();
637 let registration: Registration<
638 BalanceOf<T>,
639 <T as Config>::MaxRegistrars,
640 <T as Config>::IdentityInformation,
641 > = Registration { judgements: Default::default(), deposit: 10u32.into(), info };
642 IdentityOf::<T>::insert(&account_id, ®istration);
643 UsernameOf::<T>::insert(&account_id, &username);
644 let username_info = UsernameInformation {
645 owner: account_id.clone(),
646 provider: Provider::new_with_allocation(),
647 };
648 UsernameInfoOf::<T>::insert(&username, username_info);
649 types_v1::AccountOfUsername::<T>::insert(&username, &account_id);
650 let since: BlockNumberFor<T> = 0u32.into();
651 PendingUsernames::<T>::insert(
652 &username,
653 (&account_id, since, Provider::new_with_allocation()),
654 );
655 BenchmarkingSetup { suffix, authority, account: account_id, username }
656 }
657
658 pub(crate) fn check_authority_cleanup_validity(suffix: Suffix<T>, authority: T::AccountId) {
659 assert_eq!(types_v1::UsernameAuthorities::<T>::iter().count(), 0);
660 assert_eq!(AuthorityOf::<T>::get(&suffix).unwrap().account_id, authority);
661 }
662
663 pub(crate) fn check_username_cleanup_validity(
664 username: Username<T>,
665 account_id: T::AccountId,
666 ) {
667 assert_eq!(types_v1::AccountOfUsername::<T>::iter().count(), 0);
668 assert_eq!(UsernameInfoOf::<T>::get(&username).unwrap().owner, account_id);
669 }
670 }
671
672 #[cfg(test)]
673 mod tests {
674 use frame_support::Hashable;
675
676 use super::*;
677 use crate::tests::{new_test_ext, Test};
678
679 fn registration(
680 with_deposit: bool,
681 ) -> Registration<
682 BalanceOf<Test>,
683 <Test as Config>::MaxRegistrars,
684 <Test as Config>::IdentityInformation,
685 > {
686 Registration {
687 judgements: Default::default(),
688 deposit: if with_deposit { 10u32.into() } else { 0u32.into() },
689 info: Default::default(),
690 }
691 }
692
693 fn account_from_u8(byte: u8) -> <Test as frame_system::Config>::AccountId {
694 [byte; 32].into()
695 }
696
697 #[test]
698 fn migrate_to_v2() {
699 new_test_ext().execute_with(|| {
700 StorageVersion::new(1).put::<Pallet<Test>>();
701 let authority_1 = account_from_u8(151);
703 let suffix_1: Suffix<Test> = b"evn".to_vec().try_into().unwrap();
704 let prop = AuthorityProperties { account_id: suffix_1.clone(), allocation: 10 };
705 types_v1::UsernameAuthorities::<Test>::insert(&authority_1, &prop);
706 let authority_2 = account_from_u8(152);
708 let suffix_2: Suffix<Test> = b"odd".to_vec().try_into().unwrap();
709 let prop = AuthorityProperties { account_id: suffix_2.clone(), allocation: 10 };
710 types_v1::UsernameAuthorities::<Test>::insert(&authority_2, &prop);
711
712 let mut usernames = vec![];
716 for i in 0u8..100u8 {
717 let account_id = account_from_u8(i);
718 let bare_username = format!("acc{}.", i).as_bytes().to_vec();
719 let mut username_1 = bare_username.clone();
720 username_1.extend(suffix_1.iter());
721 let username_1: Username<Test> = username_1.try_into().unwrap();
722 types_v1::AccountOfUsername::<Test>::insert(&username_1, &account_id);
723
724 if i % 2 == 0 {
725 let has_identity = i % 4 == 0;
726 let reg = registration(has_identity);
727 frame_support::migration::put_storage_value(
728 b"Identity",
729 b"IdentityOf",
730 &account_id.twox_64_concat(),
731 (reg, Some(username_1.clone())),
732 );
733 usernames.push((account_id, username_1, None, has_identity));
734 } else {
735 let has_identity = i % 3 == 0;
736 let mut username_2 = bare_username.clone();
737 username_2.extend(suffix_2.iter());
738 let username_2: Username<Test> = username_2.try_into().unwrap();
739 types_v1::AccountOfUsername::<Test>::insert(&username_2, &account_id);
740 let reg = registration(has_identity);
741 frame_support::migration::put_storage_value(
742 b"Identity",
743 b"IdentityOf",
744 &account_id.twox_64_concat(),
745 (reg, Some(username_2.clone())),
746 );
747 usernames.push((account_id, username_2, Some(username_1), has_identity));
748 }
749 }
750
751 let mut pending = vec![];
753 for i in 100u8..110u8 {
754 let account_id = account_from_u8(i);
755 let mut bare_username = format!("acc{}.", i).as_bytes().to_vec();
756 bare_username.extend(suffix_1.iter());
757 let username: Username<Test> = bare_username.try_into().unwrap();
758 let since: BlockNumberFor<Test> = i.into();
759 frame_support::migration::put_storage_value(
760 b"Identity",
761 b"PendingUsernames",
762 &username.blake2_128_concat(),
763 (&account_id, since),
764 );
765 pending.push((username, account_id, since));
766 }
767
768 let mut identity_only = vec![];
769 for i in 120u8..130u8 {
770 let account_id = account_from_u8(i);
771 let reg = registration(true);
772 frame_support::migration::put_storage_value(
773 b"Identity",
774 b"IdentityOf",
775 &account_id.twox_64_concat(),
776 (reg, None::<Username<Test>>),
777 );
778 identity_only.push(account_id);
779 }
780
781 let mut weight_meter = WeightMeter::new();
783 let mut cursor = None;
784 while let Some(new_cursor) =
785 LazyMigrationV1ToV2::<Test>::step(cursor, &mut weight_meter).unwrap()
786 {
787 cursor = Some(new_cursor);
788 }
789 assert_eq!(Pallet::<Test>::on_chain_storage_version(), 2);
790
791 let expected_prop =
793 AuthorityProperties { account_id: authority_1.clone(), allocation: 10 };
794 assert_eq!(AuthorityOf::<Test>::get(&suffix_1), Some(expected_prop));
795
796 let expected_prop =
797 AuthorityProperties { account_id: authority_2.clone(), allocation: 10 };
798 assert_eq!(AuthorityOf::<Test>::get(&suffix_2), Some(expected_prop));
799
800 let count_of_usernames_without_identities =
802 usernames.iter().filter(|(_, _, _, has_id)| *has_id).count();
803 assert_eq!(UsernameOf::<Test>::iter().count(), usernames.len());
804 assert_eq!(
806 UsernameInfoOf::<Test>::iter().count(),
807 usernames.len() + usernames.len() / 2
808 );
809 for (owner, primary, maybe_secondary, has_identity) in usernames.iter() {
810 let username_info = UsernameInfoOf::<Test>::get(primary).unwrap();
811 assert_eq!(&username_info.owner, owner);
812 let actual_primary = UsernameOf::<Test>::get(owner).unwrap();
813 assert_eq!(primary, &actual_primary);
814 assert_eq!(IdentityOf::<Test>::contains_key(owner), *has_identity);
815 if let Some(secondary) = maybe_secondary {
816 let expected_info = UsernameInformation {
817 owner: owner.clone(),
818 provider: Provider::new_with_allocation(),
819 };
820 assert_eq!(UsernameInfoOf::<Test>::get(secondary), Some(expected_info));
821 }
822 }
823
824 for id in identity_only.iter() {
826 let expected_reg = registration(true);
827 assert_eq!(IdentityOf::<Test>::get(id), Some(expected_reg));
828 assert!(!UsernameOf::<Test>::contains_key(id));
829 }
830 let identity_count = IdentityOf::<Test>::iter().count();
831 assert_eq!(
832 identity_count,
833 count_of_usernames_without_identities + identity_only.len()
834 );
835
836 let pending_count = PendingUsernames::<Test>::iter().count();
838 assert_eq!(pending_count, pending.len());
839 for (username, owner, since) in pending.iter() {
840 let expected_pending = (owner.clone(), *since, Provider::Allocation);
841 assert_eq!(PendingUsernames::<Test>::get(username), Some(expected_pending));
842 }
843
844 assert_eq!(types_v1::AccountOfUsername::<Test>::iter().count(), 0);
846 assert_eq!(types_v1::UsernameAuthorities::<Test>::iter().count(), 0);
847 });
848 }
849 }
850}