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 },
280 Some(MigrationState::FinishedAuthorities) => Self::username_step(None),
283 Some(MigrationState::Username(maybe_last_username)) => {
285 Self::username_step(Some(maybe_last_username))
286 },
287 Some(MigrationState::FinishedUsernames) => Self::identity_step(None),
292 Some(MigrationState::Identity(last_key)) => {
294 Self::identity_step(Some(last_key.clone()))
295 },
296 Some(MigrationState::FinishedIdentities) => Self::pending_username_step(None),
299 Some(MigrationState::PendingUsername(last_key)) => {
301 Self::pending_username_step(Some(last_key.clone()))
302 },
303 Some(MigrationState::FinishedPendingUsernames) => {
306 Self::cleanup_authority_step(None)
307 },
308 Some(MigrationState::CleanupAuthorities(maybe_last_username)) => {
310 Self::cleanup_authority_step(Some(maybe_last_username))
311 },
312 Some(MigrationState::FinishedCleanupAuthorities) => {
315 Self::cleanup_username_step(None)
316 },
317 Some(MigrationState::CleanupUsernames(maybe_last_username)) => {
319 Self::cleanup_username_step(Some(maybe_last_username))
320 },
321 Some(MigrationState::Finished) => {
324 StorageVersion::new(Self::id().version_to as u16).put::<Pallet<T>>();
325 return Ok(None);
326 },
327 };
328
329 cursor = Some(next);
330 meter.consume(required_weight);
331 }
332
333 Ok(cursor)
334 }
335
336 #[cfg(feature = "try-runtime")]
337 fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
338 let authorities: BTreeMap<Suffix<T>, (T::AccountId, u32)> =
339 types_v1::UsernameAuthorities::<T>::iter()
340 .map(|(account, authority_properties)| {
341 (
342 authority_properties.account_id,
343 (account, authority_properties.allocation),
344 )
345 })
346 .collect();
347 let mut primary_usernames: BTreeMap<_, _> = Default::default();
348 let identities = types_v1::IdentityOf::<T>::iter()
349 .map(|(account, (identity, maybe_username))| {
350 if let Some(username) = maybe_username {
351 primary_usernames.insert(account.clone(), username);
352 }
353 (account, identity)
354 })
355 .collect::<BTreeMap<_, _>>();
356 let usernames = types_v1::AccountOfUsername::<T>::iter().collect::<BTreeMap<_, _>>();
357 let pending_usernames: BTreeMap<Username<T>, (T::AccountId, BlockNumberFor<T>)> =
358 types_v1::PendingUsernames::<T>::iter().collect();
359 let state: TryRuntimeState<T> = TryRuntimeState {
360 authorities,
361 identities,
362 primary_usernames,
363 usernames,
364 pending_usernames,
365 };
366
367 Ok(state.encode())
368 }
369
370 #[cfg(feature = "try-runtime")]
371 fn post_upgrade(state: Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
372 let mut prev_state: TryRuntimeState<T> = TryRuntimeState::<T>::decode(&mut &state[..])
373 .expect("Failed to decode the previous storage state");
374
375 for (suffix, authority_properties) in AuthorityOf::<T>::iter() {
376 let (prev_account, prev_allocation) = prev_state
377 .authorities
378 .remove(&suffix)
379 .expect("should have authority in previous state");
380 assert_eq!(prev_account, authority_properties.account_id);
381 assert_eq!(prev_allocation, authority_properties.allocation);
382 }
383 assert!(prev_state.authorities.is_empty());
384
385 for (account, identity) in IdentityOf::<T>::iter() {
386 assert!(identity.deposit > 0u32.into());
387 let prev_identity = prev_state
388 .identities
389 .remove(&account)
390 .expect("should have identity in previous state");
391 assert_eq!(identity, prev_identity);
392 }
393
394 for (account, free_identity) in prev_state.identities.iter() {
395 assert_eq!(free_identity.deposit, 0u32.into());
396 assert!(UsernameOf::<T>::contains_key(&account));
397 }
398 prev_state.identities.clear();
399
400 for (account, primary_username) in UsernameOf::<T>::iter() {
401 let prev_primary_username = prev_state
402 .primary_usernames
403 .remove(&account)
404 .expect("should have primary username in previous state");
405 assert_eq!(prev_primary_username, primary_username);
406 }
407
408 for (username, username_info) in UsernameInfoOf::<T>::iter() {
409 let prev_account = prev_state
410 .usernames
411 .remove(&username)
412 .expect("should have username info in previous state");
413 assert_eq!(prev_account, username_info.owner);
414 assert_eq!(username_info.provider, Provider::Allocation);
415 }
416 assert!(prev_state.usernames.is_empty());
417
418 for (username, (account, expiration, provider)) in PendingUsernames::<T>::iter() {
419 let (prev_account, prev_expiration) = prev_state
420 .pending_usernames
421 .remove(&username)
422 .expect("should have pending username in previous state");
423 assert_eq!(prev_account, account);
424 assert_eq!(prev_expiration, expiration);
425 assert_eq!(provider, Provider::Allocation);
426 }
427 assert!(prev_state.pending_usernames.is_empty());
428
429 Ok(())
430 }
431 }
432
433 impl<T: Config> LazyMigrationV1ToV2<T> {
434 pub(crate) fn required_weight(
435 step: &MigrationState<T::AccountId, Username<T>, Suffix<T>>,
436 ) -> Weight {
437 match step {
438 MigrationState::Authority(_) => T::WeightInfo::migration_v2_authority_step(),
439 MigrationState::FinishedAuthorities | MigrationState::Username(_) => {
440 T::WeightInfo::migration_v2_username_step()
441 },
442 MigrationState::FinishedUsernames | MigrationState::Identity(_) => {
443 T::WeightInfo::migration_v2_identity_step()
444 },
445 MigrationState::FinishedIdentities | MigrationState::PendingUsername(_) => {
446 T::WeightInfo::migration_v2_pending_username_step()
447 },
448 MigrationState::FinishedPendingUsernames |
449 MigrationState::CleanupAuthorities(_) => T::WeightInfo::migration_v2_cleanup_authority_step(),
450 MigrationState::FinishedCleanupAuthorities |
451 MigrationState::CleanupUsernames(_) => T::WeightInfo::migration_v2_cleanup_username_step(),
452 MigrationState::Finished => Weight::zero(),
453 }
454 }
455
456 pub(crate) fn authority_step(maybe_last_key: Option<&T::AccountId>) -> StepResultOf<T> {
458 let mut iter = if let Some(last_key) = maybe_last_key {
459 types_v1::UsernameAuthorities::<T>::iter_from(
460 types_v1::UsernameAuthorities::<T>::hashed_key_for(last_key),
461 )
462 } else {
463 types_v1::UsernameAuthorities::<T>::iter()
464 };
465 if let Some((authority_account, properties)) = iter.next() {
466 let suffix = properties.account_id;
467 let allocation = properties.allocation;
468 let new_properties =
469 AuthorityProperties { account_id: authority_account.clone(), allocation };
470 AuthorityOf::<T>::insert(&suffix, new_properties);
471 MigrationState::Authority(authority_account)
472 } else {
473 MigrationState::FinishedAuthorities
474 }
475 }
476
477 pub(crate) fn username_step(maybe_last_key: Option<&Username<T>>) -> StepResultOf<T> {
479 let mut iter = if let Some(last_key) = maybe_last_key {
480 types_v1::AccountOfUsername::<T>::iter_from(
481 types_v1::AccountOfUsername::<T>::hashed_key_for(last_key),
482 )
483 } else {
484 types_v1::AccountOfUsername::<T>::iter()
485 };
486
487 if let Some((username, owner_account)) = iter.next() {
488 let username_info = UsernameInformation {
489 owner: owner_account,
490 provider: Provider::new_with_allocation(),
491 };
492 UsernameInfoOf::<T>::insert(&username, username_info);
493
494 MigrationState::Username(username)
495 } else {
496 MigrationState::FinishedUsernames
497 }
498 }
499
500 pub(crate) fn identity_step(maybe_last_key: Option<HashedKey>) -> StepResultOf<T> {
503 if let Some(mut last_key) =
504 IdentityOf::<T>::translate_next::<
505 (
506 Registration<
507 BalanceOf<T>,
508 <T as pallet::Config>::MaxRegistrars,
509 <T as pallet::Config>::IdentityInformation,
510 >,
511 Option<Username<T>>,
512 ),
513 _,
514 >(maybe_last_key.map(|b| b.to_vec()), |account, (identity, maybe_username)| {
515 if let Some(primary_username) = maybe_username {
516 UsernameOf::<T>::insert(&account, primary_username);
517 }
518 if identity.deposit > BalanceOf::<T>::zero() {
519 Some(identity)
520 } else {
521 None
522 }
523 }) {
524 last_key.truncate(HashedKey::bound());
525 MigrationState::Identity(
526 HashedKey::try_from(last_key)
527 .expect("truncated to bound so the conversion must succeed; qed"),
528 )
529 } else {
530 MigrationState::FinishedIdentities
531 }
532 }
533
534 pub(crate) fn pending_username_step(maybe_last_key: Option<HashedKey>) -> StepResultOf<T> {
536 if let Some(mut last_key) =
537 PendingUsernames::<T>::translate_next::<(T::AccountId, BlockNumberFor<T>), _>(
538 maybe_last_key.map(|b| b.to_vec()),
539 |_, (owner_account, since)| {
540 Some((owner_account, since, Provider::new_with_allocation()))
541 },
542 ) {
543 last_key.truncate(HashedKey::bound());
544 MigrationState::PendingUsername(
545 HashedKey::try_from(last_key)
546 .expect("truncated to bound so the conversion must succeed; qed"),
547 )
548 } else {
549 MigrationState::FinishedPendingUsernames
550 }
551 }
552
553 pub(crate) fn cleanup_authority_step(
555 maybe_last_key: Option<&Suffix<T>>,
556 ) -> StepResultOf<T> {
557 let mut iter = if let Some(last_key) = maybe_last_key {
558 AuthorityOf::<T>::iter_from(AuthorityOf::<T>::hashed_key_for(last_key))
559 } else {
560 AuthorityOf::<T>::iter()
561 };
562
563 if let Some((suffix, properties)) = iter.next() {
564 let _ = types_v1::UsernameAuthorities::<T>::take(&properties.account_id);
565 MigrationState::CleanupAuthorities(suffix)
566 } else {
567 MigrationState::FinishedCleanupAuthorities
568 }
569 }
570
571 pub(crate) fn cleanup_username_step(
573 maybe_last_key: Option<&Username<T>>,
574 ) -> StepResultOf<T> {
575 let mut iter = if let Some(last_key) = maybe_last_key {
576 UsernameInfoOf::<T>::iter_from(UsernameInfoOf::<T>::hashed_key_for(last_key))
577 } else {
578 UsernameInfoOf::<T>::iter()
579 };
580
581 if let Some((username, _)) = iter.next() {
582 let _ = types_v1::AccountOfUsername::<T>::take(&username);
583 MigrationState::CleanupUsernames(username)
584 } else {
585 MigrationState::Finished
586 }
587 }
588 }
589
590 #[cfg(feature = "runtime-benchmarks")]
591 pub(crate) struct BenchmarkingSetup<S, A, U> {
592 pub(crate) suffix: S,
593 pub(crate) authority: A,
594 pub(crate) account: A,
595 pub(crate) username: U,
596 }
597
598 #[cfg(feature = "runtime-benchmarks")]
599 impl<T: Config> LazyMigrationV1ToV2<T> {
600 pub(crate) fn setup_benchmark_env_for_migration() -> BenchmarkingSetupOf<T> {
601 use frame_support::Hashable;
602 let suffix: Suffix<T> = b"bench".to_vec().try_into().unwrap();
603 let authority: T::AccountId = frame_benchmarking::account("authority", 0, 0);
604 let account_id: T::AccountId = frame_benchmarking::account("account", 1, 0);
605
606 let prop: AuthorityProperties<Suffix<T>> =
607 AuthorityProperties { account_id: suffix.clone(), allocation: 10 };
608 types_v1::UsernameAuthorities::<T>::insert(&authority, &prop);
609
610 let username: Username<T> = b"account.bench".to_vec().try_into().unwrap();
611 let info = T::IdentityInformation::create_identity_info();
612 let registration: Registration<
613 BalanceOf<T>,
614 <T as Config>::MaxRegistrars,
615 <T as Config>::IdentityInformation,
616 > = Registration { judgements: Default::default(), deposit: 10u32.into(), info };
617 frame_support::migration::put_storage_value(
618 b"Identity",
619 b"IdentityOf",
620 &account_id.twox_64_concat(),
621 (®istration, Some(username.clone())),
622 );
623 types_v1::AccountOfUsername::<T>::insert(&username, &account_id);
624 let since: BlockNumberFor<T> = 0u32.into();
625 frame_support::migration::put_storage_value(
626 b"Identity",
627 b"PendingUsernames",
628 &username.blake2_128_concat(),
629 (&account_id, since),
630 );
631 BenchmarkingSetup { suffix, authority, account: account_id, username }
632 }
633
634 pub(crate) fn setup_benchmark_env_for_cleanup() -> BenchmarkingSetupOf<T> {
635 let suffix: Suffix<T> = b"bench".to_vec().try_into().unwrap();
636 let authority: T::AccountId = frame_benchmarking::account("authority", 0, 0);
637 let account_id: T::AccountId = frame_benchmarking::account("account", 1, 0);
638
639 let prop: AuthorityProperties<Suffix<T>> =
640 AuthorityProperties { account_id: suffix.clone(), allocation: 10 };
641 types_v1::UsernameAuthorities::<T>::insert(&authority, &prop);
642 let prop: AuthorityProperties<T::AccountId> =
643 AuthorityProperties { account_id: authority.clone(), allocation: 10 };
644 AuthorityOf::<T>::insert(&suffix, &prop);
645
646 let username: Username<T> = b"account.bench".to_vec().try_into().unwrap();
647 let info = T::IdentityInformation::create_identity_info();
648 let registration: Registration<
649 BalanceOf<T>,
650 <T as Config>::MaxRegistrars,
651 <T as Config>::IdentityInformation,
652 > = Registration { judgements: Default::default(), deposit: 10u32.into(), info };
653 IdentityOf::<T>::insert(&account_id, ®istration);
654 UsernameOf::<T>::insert(&account_id, &username);
655 let username_info = UsernameInformation {
656 owner: account_id.clone(),
657 provider: Provider::new_with_allocation(),
658 };
659 UsernameInfoOf::<T>::insert(&username, username_info);
660 types_v1::AccountOfUsername::<T>::insert(&username, &account_id);
661 let since: BlockNumberFor<T> = 0u32.into();
662 PendingUsernames::<T>::insert(
663 &username,
664 (&account_id, since, Provider::new_with_allocation()),
665 );
666 BenchmarkingSetup { suffix, authority, account: account_id, username }
667 }
668
669 pub(crate) fn check_authority_cleanup_validity(suffix: Suffix<T>, authority: T::AccountId) {
670 assert_eq!(types_v1::UsernameAuthorities::<T>::iter().count(), 0);
671 assert_eq!(AuthorityOf::<T>::get(&suffix).unwrap().account_id, authority);
672 }
673
674 pub(crate) fn check_username_cleanup_validity(
675 username: Username<T>,
676 account_id: T::AccountId,
677 ) {
678 assert_eq!(types_v1::AccountOfUsername::<T>::iter().count(), 0);
679 assert_eq!(UsernameInfoOf::<T>::get(&username).unwrap().owner, account_id);
680 }
681 }
682
683 #[cfg(test)]
684 mod tests {
685 use frame_support::Hashable;
686
687 use super::*;
688 use crate::tests::{new_test_ext, Test};
689
690 fn registration(
691 with_deposit: bool,
692 ) -> Registration<
693 BalanceOf<Test>,
694 <Test as Config>::MaxRegistrars,
695 <Test as Config>::IdentityInformation,
696 > {
697 Registration {
698 judgements: Default::default(),
699 deposit: if with_deposit { 10u32.into() } else { 0u32.into() },
700 info: Default::default(),
701 }
702 }
703
704 fn account_from_u8(byte: u8) -> <Test as frame_system::Config>::AccountId {
705 [byte; 32].into()
706 }
707
708 #[test]
709 fn migrate_to_v2() {
710 new_test_ext().execute_with(|| {
711 StorageVersion::new(1).put::<Pallet<Test>>();
712 let authority_1 = account_from_u8(151);
714 let suffix_1: Suffix<Test> = b"evn".to_vec().try_into().unwrap();
715 let prop = AuthorityProperties { account_id: suffix_1.clone(), allocation: 10 };
716 types_v1::UsernameAuthorities::<Test>::insert(&authority_1, &prop);
717 let authority_2 = account_from_u8(152);
719 let suffix_2: Suffix<Test> = b"odd".to_vec().try_into().unwrap();
720 let prop = AuthorityProperties { account_id: suffix_2.clone(), allocation: 10 };
721 types_v1::UsernameAuthorities::<Test>::insert(&authority_2, &prop);
722
723 let mut usernames = vec![];
727 for i in 0u8..100u8 {
728 let account_id = account_from_u8(i);
729 let bare_username = format!("acc{}.", i).as_bytes().to_vec();
730 let mut username_1 = bare_username.clone();
731 username_1.extend(suffix_1.iter());
732 let username_1: Username<Test> = username_1.try_into().unwrap();
733 types_v1::AccountOfUsername::<Test>::insert(&username_1, &account_id);
734
735 if i % 2 == 0 {
736 let has_identity = i % 4 == 0;
737 let reg = registration(has_identity);
738 frame_support::migration::put_storage_value(
739 b"Identity",
740 b"IdentityOf",
741 &account_id.twox_64_concat(),
742 (reg, Some(username_1.clone())),
743 );
744 usernames.push((account_id, username_1, None, has_identity));
745 } else {
746 let has_identity = i % 3 == 0;
747 let mut username_2 = bare_username.clone();
748 username_2.extend(suffix_2.iter());
749 let username_2: Username<Test> = username_2.try_into().unwrap();
750 types_v1::AccountOfUsername::<Test>::insert(&username_2, &account_id);
751 let reg = registration(has_identity);
752 frame_support::migration::put_storage_value(
753 b"Identity",
754 b"IdentityOf",
755 &account_id.twox_64_concat(),
756 (reg, Some(username_2.clone())),
757 );
758 usernames.push((account_id, username_2, Some(username_1), has_identity));
759 }
760 }
761
762 let mut pending = vec![];
764 for i in 100u8..110u8 {
765 let account_id = account_from_u8(i);
766 let mut bare_username = format!("acc{}.", i).as_bytes().to_vec();
767 bare_username.extend(suffix_1.iter());
768 let username: Username<Test> = bare_username.try_into().unwrap();
769 let since: BlockNumberFor<Test> = i.into();
770 frame_support::migration::put_storage_value(
771 b"Identity",
772 b"PendingUsernames",
773 &username.blake2_128_concat(),
774 (&account_id, since),
775 );
776 pending.push((username, account_id, since));
777 }
778
779 let mut identity_only = vec![];
780 for i in 120u8..130u8 {
781 let account_id = account_from_u8(i);
782 let reg = registration(true);
783 frame_support::migration::put_storage_value(
784 b"Identity",
785 b"IdentityOf",
786 &account_id.twox_64_concat(),
787 (reg, None::<Username<Test>>),
788 );
789 identity_only.push(account_id);
790 }
791
792 let mut weight_meter = WeightMeter::new();
794 let mut cursor = None;
795 while let Some(new_cursor) =
796 LazyMigrationV1ToV2::<Test>::step(cursor, &mut weight_meter).unwrap()
797 {
798 cursor = Some(new_cursor);
799 }
800 assert_eq!(Pallet::<Test>::on_chain_storage_version(), 2);
801
802 let expected_prop =
804 AuthorityProperties { account_id: authority_1.clone(), allocation: 10 };
805 assert_eq!(AuthorityOf::<Test>::get(&suffix_1), Some(expected_prop));
806
807 let expected_prop =
808 AuthorityProperties { account_id: authority_2.clone(), allocation: 10 };
809 assert_eq!(AuthorityOf::<Test>::get(&suffix_2), Some(expected_prop));
810
811 let count_of_usernames_without_identities =
813 usernames.iter().filter(|(_, _, _, has_id)| *has_id).count();
814 assert_eq!(UsernameOf::<Test>::iter().count(), usernames.len());
815 assert_eq!(
817 UsernameInfoOf::<Test>::iter().count(),
818 usernames.len() + usernames.len() / 2
819 );
820 for (owner, primary, maybe_secondary, has_identity) in usernames.iter() {
821 let username_info = UsernameInfoOf::<Test>::get(primary).unwrap();
822 assert_eq!(&username_info.owner, owner);
823 let actual_primary = UsernameOf::<Test>::get(owner).unwrap();
824 assert_eq!(primary, &actual_primary);
825 assert_eq!(IdentityOf::<Test>::contains_key(owner), *has_identity);
826 if let Some(secondary) = maybe_secondary {
827 let expected_info = UsernameInformation {
828 owner: owner.clone(),
829 provider: Provider::new_with_allocation(),
830 };
831 assert_eq!(UsernameInfoOf::<Test>::get(secondary), Some(expected_info));
832 }
833 }
834
835 for id in identity_only.iter() {
837 let expected_reg = registration(true);
838 assert_eq!(IdentityOf::<Test>::get(id), Some(expected_reg));
839 assert!(!UsernameOf::<Test>::contains_key(id));
840 }
841 let identity_count = IdentityOf::<Test>::iter().count();
842 assert_eq!(
843 identity_count,
844 count_of_usernames_without_identities + identity_only.len()
845 );
846
847 let pending_count = PendingUsernames::<Test>::iter().count();
849 assert_eq!(pending_count, pending.len());
850 for (username, owner, since) in pending.iter() {
851 let expected_pending = (owner.clone(), *since, Provider::Allocation);
852 assert_eq!(PendingUsernames::<Test>::get(username), Some(expected_pending));
853 }
854
855 assert_eq!(types_v1::AccountOfUsername::<Test>::iter().count(), 0);
857 assert_eq!(types_v1::UsernameAuthorities::<Test>::iter().count(), 0);
858 });
859 }
860 }
861}