From e7776746aecdf6933df766f3756e18b7af3c607f Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Thu, 17 Aug 2023 01:58:05 +1000 Subject: [PATCH] Free standing `elections-phragmen` and `tips` Gov V1 unlock/unreserve migrations (#14779) * standalone elections-phragmen migration * standalone tips migration * remove redundant comment --- .../unlock_and_unreserve_all_funds.rs | 126 ++++++++++++++---- .../tips/src/migrations/unreserve_deposits.rs | 106 ++++++++++++--- 2 files changed, 187 insertions(+), 45 deletions(-) diff --git a/frame/elections-phragmen/src/migrations/unlock_and_unreserve_all_funds.rs b/frame/elections-phragmen/src/migrations/unlock_and_unreserve_all_funds.rs index f566f84e51a2b..8be112ef55338 100644 --- a/frame/elections-phragmen/src/migrations/unlock_and_unreserve_all_funds.rs +++ b/frame/elections-phragmen/src/migrations/unlock_and_unreserve_all_funds.rs @@ -18,18 +18,75 @@ //! A migration that unreserves all deposit and unlocks all stake held in the context of this //! pallet. -use crate::BalanceOf; use core::iter::Sum; -use frame_support::traits::{LockableCurrency, OnRuntimeUpgrade, ReservableCurrency}; +use frame_support::{ + pallet_prelude::ValueQuery, + storage_alias, + traits::{Currency, LockIdentifier, LockableCurrency, OnRuntimeUpgrade, ReservableCurrency}, + weights::RuntimeDbWeight, + Parameter, Twox64Concat, +}; use sp_core::Get; use sp_runtime::traits::Zero; -use sp_std::collections::btree_map::BTreeMap; - -#[cfg(feature = "try-runtime")] -use sp_std::vec::Vec; +use sp_std::{collections::btree_map::BTreeMap, vec::Vec}; const LOG_TARGET: &str = "elections_phragmen::migrations::unlock_and_unreserve_all_funds"; +type BalanceOf = + <::Currency as Currency<::AccountId>>::Balance; + +/// The configuration for [`UnlockAndUnreserveAllFunds`]. +pub trait UnlockConfig: 'static { + /// The account ID used in the runtime. + type AccountId: Parameter + Ord; + /// The currency type used in the runtime. + /// + /// Should match the currency type previously used for the pallet, if applicable. + type Currency: LockableCurrency + ReservableCurrency; + /// The name of the pallet as previously configured in + /// [`construct_runtime!`](frame_support::construct_runtime). + type PalletName: Get<&'static str>; + /// The maximum number of votes per voter as configured previously in the previous runtime. + type MaxVotesPerVoter: Get; + /// Identifier for the elections-phragmen pallet's lock, as previously configured in the + /// runtime. + type PalletId: Get; + /// The DB weight as configured in the runtime to calculate the correct weight. + type DbWeight: Get; + /// The block number as configured in the runtime. + type BlockNumber: Parameter + Zero + Copy + Ord; +} + +#[storage_alias(dynamic)] +type Members = StorageValue< + ::PalletName, + Vec::AccountId, BalanceOf>>, + ValueQuery, +>; + +#[storage_alias(dynamic)] +type RunnersUp = StorageValue< + ::PalletName, + Vec::AccountId, BalanceOf>>, + ValueQuery, +>; + +#[storage_alias(dynamic)] +type Candidates = StorageValue< + ::PalletName, + Vec<(::AccountId, BalanceOf)>, + ValueQuery, +>; + +#[storage_alias(dynamic)] +type Voting = StorageMap< + ::PalletName, + Twox64Concat, + ::AccountId, + crate::Voter<::AccountId, BalanceOf>, + ValueQuery, +>; + /// A migration that unreserves all deposit and unlocks all stake held in the context of this /// pallet. /// @@ -38,9 +95,9 @@ const LOG_TARGET: &str = "elections_phragmen::migrations::unlock_and_unreserve_a /// The pallet should be made inoperable before this migration is run. /// /// (See also [`RemovePallet`][frame_support::migrations::RemovePallet]) -pub struct UnlockAndUnreserveAllFunds(sp_std::marker::PhantomData); +pub struct UnlockAndUnreserveAllFunds(sp_std::marker::PhantomData); -impl UnlockAndUnreserveAllFunds { +impl UnlockAndUnreserveAllFunds { /// Calculates and returns the total amounts deposited and staked by each account in the context /// of this pallet. /// @@ -66,12 +123,11 @@ impl UnlockAndUnreserveAllFunds { BTreeMap>, frame_support::weights::Weight, ) { - use crate::Voting; use sp_runtime::Saturating; - let members = crate::Members::::get(); - let runner_ups = crate::RunnersUp::::get(); - let candidates = crate::Candidates::::get(); + let members = Members::::get(); + let runner_ups = RunnersUp::::get(); + let candidates = Candidates::::get(); // Get the total amount deposited (Members, RunnerUps, Candidates and Voters all can have // deposits). @@ -115,7 +171,7 @@ impl UnlockAndUnreserveAllFunds { } } -impl OnRuntimeUpgrade for UnlockAndUnreserveAllFunds +impl OnRuntimeUpgrade for UnlockAndUnreserveAllFunds where BalanceOf: Sum, { @@ -268,13 +324,29 @@ where mod test { use super::*; use crate::{ - tests::{ExtBuilder, Test}, + tests::{Balances, ElectionsPhragmenPalletId, ExtBuilder, PhragmenMaxVoters, Test}, Candidates, Members, RunnersUp, SeatHolder, Voter, Voting, }; use frame_support::{ - assert_ok, + assert_ok, parameter_types, traits::{Currency, OnRuntimeUpgrade, ReservableCurrency, WithdrawReasons}, }; + use frame_system::pallet_prelude::BlockNumberFor; + + parameter_types! { + const PalletName: &'static str = "Elections"; + } + + struct UnlockConfigImpl; + impl super::UnlockConfig for UnlockConfigImpl { + type Currency = Balances; + type AccountId = u64; + type BlockNumber = BlockNumberFor; + type DbWeight = (); + type PalletName = PalletName; + type MaxVotesPerVoter = PhragmenMaxVoters; + type PalletId = ElectionsPhragmenPalletId; + } #[test] fn unreserve_works_for_candidate() { @@ -296,10 +368,10 @@ mod test { ); // Run the migration. - let bytes = UnlockAndUnreserveAllFunds::::pre_upgrade() + let bytes = UnlockAndUnreserveAllFunds::::pre_upgrade() .unwrap_or_else(|e| panic!("pre_upgrade failed: {:?}", e)); - UnlockAndUnreserveAllFunds::::on_runtime_upgrade(); - assert_ok!(UnlockAndUnreserveAllFunds::::post_upgrade(bytes)); + UnlockAndUnreserveAllFunds::::on_runtime_upgrade(); + assert_ok!(UnlockAndUnreserveAllFunds::::post_upgrade(bytes)); // Assert the candidate reserved balance was reduced by the expected amount. assert_eq!( @@ -329,10 +401,10 @@ mod test { ); // Run the migration. - let bytes = UnlockAndUnreserveAllFunds::::pre_upgrade() + let bytes = UnlockAndUnreserveAllFunds::::pre_upgrade() .unwrap_or_else(|e| panic!("pre_upgrade failed: {:?}", e)); - UnlockAndUnreserveAllFunds::::on_runtime_upgrade(); - assert_ok!(UnlockAndUnreserveAllFunds::::post_upgrade(bytes)); + UnlockAndUnreserveAllFunds::::on_runtime_upgrade(); + assert_ok!(UnlockAndUnreserveAllFunds::::post_upgrade(bytes)); // Assert the reserved balance was reduced by the expected amount. assert_eq!( @@ -362,10 +434,10 @@ mod test { ); // Run the migration. - let bytes = UnlockAndUnreserveAllFunds::::pre_upgrade() + let bytes = UnlockAndUnreserveAllFunds::::pre_upgrade() .unwrap_or_else(|e| panic!("pre_upgrade failed: {:?}", e)); - UnlockAndUnreserveAllFunds::::on_runtime_upgrade(); - assert_ok!(UnlockAndUnreserveAllFunds::::post_upgrade(bytes)); + UnlockAndUnreserveAllFunds::::on_runtime_upgrade(); + assert_ok!(UnlockAndUnreserveAllFunds::::post_upgrade(bytes)); // Assert the reserved balance was reduced by the expected amount. assert_eq!( @@ -422,10 +494,10 @@ mod test { ); // Run the migration. - let bytes = UnlockAndUnreserveAllFunds::::pre_upgrade() + let bytes = UnlockAndUnreserveAllFunds::::pre_upgrade() .unwrap_or_else(|e| panic!("pre_upgrade failed: {:?}", e)); - UnlockAndUnreserveAllFunds::::on_runtime_upgrade(); - assert_ok!(UnlockAndUnreserveAllFunds::::post_upgrade(bytes)); + UnlockAndUnreserveAllFunds::::on_runtime_upgrade(); + assert_ok!(UnlockAndUnreserveAllFunds::::post_upgrade(bytes)); // Assert the voter lock was removed and the reserved balance was reduced by the // expected amount. diff --git a/frame/tips/src/migrations/unreserve_deposits.rs b/frame/tips/src/migrations/unreserve_deposits.rs index 878d80fe1bb4e..16cb1a80e812b 100644 --- a/frame/tips/src/migrations/unreserve_deposits.rs +++ b/frame/tips/src/migrations/unreserve_deposits.rs @@ -19,13 +19,64 @@ //! pallet. use core::iter::Sum; -use frame_support::traits::{OnRuntimeUpgrade, ReservableCurrency}; -use pallet_treasury::BalanceOf; +use frame_support::{ + pallet_prelude::OptionQuery, + storage_alias, + traits::{Currency, LockableCurrency, OnRuntimeUpgrade, ReservableCurrency}, + weights::RuntimeDbWeight, + Parameter, Twox64Concat, +}; use sp_runtime::{traits::Zero, Saturating}; use sp_std::collections::btree_map::BTreeMap; #[cfg(feature = "try-runtime")] -use sp_std::vec::Vec; +const LOG_TARGET: &str = "runtime::tips::migrations::unreserve_deposits"; + +type BalanceOf = + <>::Currency as Currency<>::AccountId>>::Balance; + +/// The configuration for [`UnreserveDeposits`]. +pub trait UnlockConfig: 'static { + /// The hash used in the runtime. + type Hash: Parameter; + /// The account ID used in the runtime. + type AccountId: Parameter + Ord; + /// The currency type used in the runtime. + /// + /// Should match the currency type previously used for the pallet, if applicable. + type Currency: LockableCurrency + ReservableCurrency; + /// Base deposit to report a tip. + /// + /// Should match the currency type previously used for the pallet, if applicable. + type TipReportDepositBase: sp_core::Get>; + /// Deposit per byte to report a tip. + /// + /// Should match the currency type previously used for the pallet, if applicable. + type DataDepositPerByte: sp_core::Get>; + /// The name of the pallet as previously configured in + /// [`construct_runtime!`](frame_support::construct_runtime). + type PalletName: sp_core::Get<&'static str>; + /// The DB weight as configured in the runtime to calculate the correct weight. + type DbWeight: sp_core::Get; + /// The block number as configured in the runtime. + type BlockNumber: Parameter + Zero + Copy + Ord; +} + +/// An open tipping "motion". Retains all details of a tip including information on the finder +/// and the members who have voted. +#[storage_alias(dynamic)] +type Tips, I: 'static> = StorageMap< + >::PalletName, + Twox64Concat, + >::Hash, + crate::OpenTip< + >::AccountId, + BalanceOf, + >::BlockNumber, + >::Hash, + >, + OptionQuery, +>; /// A migration that unreserves all tip deposits. /// @@ -34,9 +85,9 @@ use sp_std::vec::Vec; /// The pallet should be made inoperable before or immediately after this migration is run. /// /// (See also the `RemovePallet` migration in `frame/support/src/migrations.rs`) -pub struct UnreserveDeposits, I: 'static>(sp_std::marker::PhantomData<(T, I)>); +pub struct UnreserveDeposits, I: 'static>(sp_std::marker::PhantomData<(T, I)>); -impl, I: 'static> UnreserveDeposits { +impl, I: 'static> UnreserveDeposits { /// Calculates and returns the total amount reserved by each account by this pallet from open /// tips. /// @@ -46,14 +97,14 @@ impl, I: 'static> UnreserveDeposits { /// reserved balance by this pallet /// * `frame_support::weights::Weight`: The weight of this operation. fn get_deposits() -> (BTreeMap>, frame_support::weights::Weight) { - use frame_support::traits::Get; + use sp_core::Get; let mut tips_len = 0; - let account_deposits: BTreeMap> = crate::Tips::::iter() + let account_deposits: BTreeMap> = Tips::::iter() .map(|(_hash, open_tip)| open_tip) .fold(BTreeMap::new(), |mut acc, tip| { // Count the total number of tips - tips_len.saturating_accrue(1); + tips_len.saturating_inc(); // Add the balance to the account's existing deposit in the accumulator acc.entry(tip.finder).or_insert(Zero::zero()).saturating_accrue(tip.deposit); @@ -64,7 +115,7 @@ impl, I: 'static> UnreserveDeposits { } } -impl, I: 'static> OnRuntimeUpgrade for UnreserveDeposits +impl, I: 'static> OnRuntimeUpgrade for UnreserveDeposits where BalanceOf: Sum, { @@ -82,7 +133,7 @@ where /// Fails with a `TryRuntimeError` if somehow the amount reserved by this pallet is greater than /// the actual total reserved amount for any accounts. #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, sp_runtime::TryRuntimeError> { + fn pre_upgrade() -> Result, sp_runtime::TryRuntimeError> { use codec::Encode; use frame_support::ensure; @@ -107,8 +158,8 @@ where // Print some summary stats let total_deposits_to_unreserve = account_deposits.clone().into_values().sum::>(); - log::info!("Total accounts: {}", account_deposits.keys().count()); - log::info!("Total amount to unreserve: {:?}", total_deposits_to_unreserve); + log::info!(target: LOG_TARGET, "Total accounts: {}", account_deposits.keys().count()); + log::info!(target: LOG_TARGET, "Total amount to unreserve: {:?}", total_deposits_to_unreserve); // Return the actual amount reserved before the upgrade to verify integrity of the upgrade // in the post_upgrade hook. @@ -138,7 +189,7 @@ where /// Verifies that the account reserved balances were reduced by the actual expected amounts. #[cfg(feature = "try-runtime")] fn post_upgrade( - account_reserved_before_bytes: Vec, + account_reserved_before_bytes: sp_std::vec::Vec, ) -> Result<(), sp_runtime::TryRuntimeError> { use codec::Decode; @@ -161,6 +212,7 @@ where if actual_reserved_after != expected_reserved_after { log::error!( + target: LOG_TARGET, "Reserved balance for {:?} is incorrect. actual before: {:?}, actual after, {:?}, expected deducted: {:?}", account, actual_reserved_before, @@ -180,9 +232,27 @@ mod test { use super::*; use crate::{ migrations::unreserve_deposits::UnreserveDeposits, - tests::{new_test_ext, RuntimeOrigin, Test, Tips}, + tests::{new_test_ext, Balances, RuntimeOrigin, Test, Tips}, }; - use frame_support::{assert_ok, traits::TypedGet}; + use frame_support::{assert_ok, parameter_types, traits::TypedGet}; + use frame_system::pallet_prelude::BlockNumberFor; + use sp_core::ConstU64; + + parameter_types! { + const PalletName: &'static str = "Tips"; + } + + struct UnlockConfigImpl; + impl super::UnlockConfig<()> for UnlockConfigImpl { + type Currency = Balances; + type TipReportDepositBase = ConstU64<1>; + type DataDepositPerByte = ConstU64<1>; + type Hash = sp_core::H256; + type AccountId = u128; + type BlockNumber = BlockNumberFor; + type DbWeight = (); + type PalletName = PalletName; + } #[test] fn unreserve_all_funds_works() { @@ -233,12 +303,12 @@ mod test { ); // Execute the migration - let bytes = match UnreserveDeposits::::pre_upgrade() { + let bytes = match UnreserveDeposits::::pre_upgrade() { Ok(bytes) => bytes, Err(e) => panic!("pre_upgrade failed: {:?}", e), }; - UnreserveDeposits::::on_runtime_upgrade(); - assert_ok!(UnreserveDeposits::::post_upgrade(bytes)); + UnreserveDeposits::::on_runtime_upgrade(); + assert_ok!(UnreserveDeposits::::post_upgrade(bytes)); // Check the deposits were were unreserved assert_eq!(