@@ -478,9 +478,22 @@ pub mod v4 {
478
478
}
479
479
}
480
480
481
+ /// Migrates from `v3` directly to `v5` to avoid the broken `v4` migration.
482
+ #[ allow( deprecated) ]
483
+ pub type MigrateV3ToV5 < T , U > = ( v4:: MigrateToV4 < T , U > , v5:: MigrateToV5 < T > ) ;
484
+
485
+ /// # Warning
486
+ ///
487
+ /// To avoid mangled storage please use `MigrateV3ToV5` instead.
488
+ /// See: github.com/paritytech/substrate/pull/13715
489
+ ///
481
490
/// This migration adds a `commission` field to every `BondedPoolInner`, if
482
491
/// any.
492
+ #[ deprecated(
493
+ note = "To avoid mangled storage please use `MigrateV3ToV5` instead. See: github.com/paritytech/substrate/pull/13715"
494
+ ) ]
483
495
pub struct MigrateToV4 < T , U > ( sp_std:: marker:: PhantomData < ( T , U ) > ) ;
496
+ #[ allow( deprecated) ]
484
497
impl < T : Config , U : Get < Perbill > > OnRuntimeUpgrade for MigrateToV4 < T , U > {
485
498
fn on_runtime_upgrade ( ) -> Weight {
486
499
let current = Pallet :: < T > :: current_storage_version ( ) ;
@@ -493,7 +506,8 @@ pub mod v4 {
493
506
onchain
494
507
) ;
495
508
496
- if current == 4 && onchain == 3 {
509
+ if onchain == 3 {
510
+ log ! ( warn, "Please run MigrateToV5 immediately after this migration. See github.com/paritytech/substrate/pull/13715" ) ;
497
511
let initial_global_max_commission = U :: get ( ) ;
498
512
GlobalMaxCommission :: < T > :: set ( Some ( initial_global_max_commission) ) ;
499
513
log ! (
@@ -508,7 +522,7 @@ pub mod v4 {
508
522
Some ( old_value. migrate_to_v4 ( ) )
509
523
} ) ;
510
524
511
- current . put :: < Pallet < T > > ( ) ;
525
+ StorageVersion :: new ( 4 ) . put :: < Pallet < T > > ( ) ;
512
526
log ! ( info, "Upgraded {} pools, storage to version {:?}" , translated, current) ;
513
527
514
528
// reads: translated + onchain version.
@@ -548,3 +562,147 @@ pub mod v4 {
548
562
}
549
563
}
550
564
}
565
+
566
+ pub mod v5 {
567
+ use super :: * ;
568
+
569
+ #[ derive( Decode ) ]
570
+ pub struct OldRewardPool < T : Config > {
571
+ last_recorded_reward_counter : T :: RewardCounter ,
572
+ last_recorded_total_payouts : BalanceOf < T > ,
573
+ total_rewards_claimed : BalanceOf < T > ,
574
+ }
575
+
576
+ impl < T : Config > OldRewardPool < T > {
577
+ fn migrate_to_v5 ( self ) -> RewardPool < T > {
578
+ RewardPool {
579
+ last_recorded_reward_counter : self . last_recorded_reward_counter ,
580
+ last_recorded_total_payouts : self . last_recorded_total_payouts ,
581
+ total_rewards_claimed : self . total_rewards_claimed ,
582
+ total_commission_pending : Zero :: zero ( ) ,
583
+ total_commission_claimed : Zero :: zero ( ) ,
584
+ }
585
+ }
586
+ }
587
+
588
+ /// This migration adds `total_commission_pending` and `total_commission_claimed` field to every
589
+ /// `RewardPool`, if any.
590
+ pub struct MigrateToV5 < T > ( sp_std:: marker:: PhantomData < T > ) ;
591
+ impl < T : Config > OnRuntimeUpgrade for MigrateToV5 < T > {
592
+ fn on_runtime_upgrade ( ) -> Weight {
593
+ let current = Pallet :: < T > :: current_storage_version ( ) ;
594
+ let onchain = Pallet :: < T > :: on_chain_storage_version ( ) ;
595
+
596
+ log ! (
597
+ info,
598
+ "Running migration with current storage version {:?} / onchain {:?}" ,
599
+ current,
600
+ onchain
601
+ ) ;
602
+
603
+ if current == 5 && onchain == 4 {
604
+ let mut translated = 0u64 ;
605
+ RewardPools :: < T > :: translate :: < OldRewardPool < T > , _ > ( |_id, old_value| {
606
+ translated. saturating_inc ( ) ;
607
+ Some ( old_value. migrate_to_v5 ( ) )
608
+ } ) ;
609
+
610
+ current. put :: < Pallet < T > > ( ) ;
611
+ log ! ( info, "Upgraded {} pools, storage to version {:?}" , translated, current) ;
612
+
613
+ // reads: translated + onchain version.
614
+ // writes: translated + current.put.
615
+ T :: DbWeight :: get ( ) . reads_writes ( translated + 1 , translated + 1 )
616
+ } else {
617
+ log ! ( info, "Migration did not execute. This probably should be removed" ) ;
618
+ T :: DbWeight :: get ( ) . reads ( 1 )
619
+ }
620
+ }
621
+
622
+ #[ cfg( feature = "try-runtime" ) ]
623
+ fn pre_upgrade ( ) -> Result < Vec < u8 > , & ' static str > {
624
+ ensure ! (
625
+ Pallet :: <T >:: current_storage_version( ) > Pallet :: <T >:: on_chain_storage_version( ) ,
626
+ "the on_chain version is equal or more than the current one"
627
+ ) ;
628
+
629
+ let rpool_keys = RewardPools :: < T > :: iter_keys ( ) . count ( ) ;
630
+ let rpool_values = RewardPools :: < T > :: iter_values ( ) . count ( ) ;
631
+ if rpool_keys != rpool_values {
632
+ log ! ( info, "🔥 There are {} undecodable RewardPools in storage. This migration will try to correct them. keys: {}, values: {}" , rpool_keys. saturating_sub( rpool_values) , rpool_keys, rpool_values) ;
633
+ }
634
+
635
+ ensure ! (
636
+ PoolMembers :: <T >:: iter_keys( ) . count( ) == PoolMembers :: <T >:: iter_values( ) . count( ) ,
637
+ "There are undecodable PoolMembers in storage. This migration will not fix that."
638
+ ) ;
639
+ ensure ! (
640
+ BondedPools :: <T >:: iter_keys( ) . count( ) == BondedPools :: <T >:: iter_values( ) . count( ) ,
641
+ "There are undecodable BondedPools in storage. This migration will not fix that."
642
+ ) ;
643
+ ensure ! (
644
+ SubPoolsStorage :: <T >:: iter_keys( ) . count( ) ==
645
+ SubPoolsStorage :: <T >:: iter_values( ) . count( ) ,
646
+ "There are undecodable SubPools in storage. This migration will not fix that."
647
+ ) ;
648
+ ensure ! (
649
+ Metadata :: <T >:: iter_keys( ) . count( ) == Metadata :: <T >:: iter_values( ) . count( ) ,
650
+ "There are undecodable Metadata in storage. This migration will not fix that."
651
+ ) ;
652
+
653
+ Ok ( ( rpool_values as u64 ) . encode ( ) )
654
+ }
655
+
656
+ #[ cfg( feature = "try-runtime" ) ]
657
+ fn post_upgrade ( data : Vec < u8 > ) -> Result < ( ) , & ' static str > {
658
+ let old_rpool_values: u64 = Decode :: decode ( & mut & data[ ..] ) . unwrap ( ) ;
659
+ let rpool_keys = RewardPools :: < T > :: iter_keys ( ) . count ( ) as u64 ;
660
+ let rpool_values = RewardPools :: < T > :: iter_values ( ) . count ( ) as u64 ;
661
+ ensure ! (
662
+ rpool_keys == rpool_values,
663
+ "There are STILL undecodable RewardPools - migration failed"
664
+ ) ;
665
+
666
+ if old_rpool_values != rpool_values {
667
+ log ! (
668
+ info,
669
+ "🎉 Fixed {} undecodable RewardPools." ,
670
+ rpool_values. saturating_sub( old_rpool_values)
671
+ ) ;
672
+ }
673
+
674
+ // ensure all RewardPools items now contain `total_commission_pending` and
675
+ // `total_commission_claimed` field.
676
+ ensure ! (
677
+ RewardPools :: <T >:: iter( ) . all( |( _, reward_pool) | reward_pool
678
+ . total_commission_pending
679
+ . is_zero( ) && reward_pool
680
+ . total_commission_claimed
681
+ . is_zero( ) ) ,
682
+ "a commission value has been incorrectly set"
683
+ ) ;
684
+ ensure ! ( Pallet :: <T >:: on_chain_storage_version( ) == 5 , "wrong storage version" ) ;
685
+
686
+ // These should not have been touched - just in case.
687
+ ensure ! (
688
+ PoolMembers :: <T >:: iter_keys( ) . count( ) == PoolMembers :: <T >:: iter_values( ) . count( ) ,
689
+ "There are undecodable PoolMembers in storage."
690
+ ) ;
691
+ ensure ! (
692
+ BondedPools :: <T >:: iter_keys( ) . count( ) == BondedPools :: <T >:: iter_values( ) . count( ) ,
693
+ "There are undecodable BondedPools in storage."
694
+ ) ;
695
+ ensure ! (
696
+ SubPoolsStorage :: <T >:: iter_keys( ) . count( ) ==
697
+ SubPoolsStorage :: <T >:: iter_values( ) . count( ) ,
698
+ "There are undecodable SubPools in storage."
699
+ ) ;
700
+ ensure ! (
701
+ Metadata :: <T >:: iter_keys( ) . count( ) == Metadata :: <T >:: iter_values( ) . count( ) ,
702
+ "There are undecodable Metadata in storage."
703
+ ) ;
704
+
705
+ Ok ( ( ) )
706
+ }
707
+ }
708
+ }
0 commit comments