From 7325891fb9b11f3fca607b896e36a063583f3ac2 Mon Sep 17 00:00:00 2001 From: Alexander Popiak Date: Tue, 23 Jun 2020 17:42:00 +0200 Subject: [PATCH] Migrations necessary for Edgeware Node Upgrade (#6) * Revert "Remove balances migration. (#5224)" This reverts commit e1fcc9796a576a9fb78e0a5e23830ae87171015b. * adjust type imports and remove test * Assign unique storage names to pallets. (#5010) * Assign unique storage names to pallets. * Bump spec * Upgrade logic for finality tracker (untested) * Logic for migrating Identity (untested) * Logic for migrating transaction-payment * Fix tests * Fix `decl_storage` build * Contract -> Contracts * Update Cargo.lock * bump spec * update migration * Fix merge error * Migration for contracts * Remove serde * Remove some illegal spaces and Options * Fix types in identity. * Minor variable rename Co-authored-by: Gavin Wood * add weights to runtime migrations * use max block weight for balances migration * temporarily remove failing contracts migration * add more logging for migrations * fix transaction-payment migration by converting multiplier type * add more logging to balance migration * more balance migration logging * format balance migration * even more balance migration logging * remove logging in loop and change upgrade flag type to bool * cherry-pick #5226 (dd97b1478b31a4715df7e88a5ebc6664425fb6c6) massage the code and fix anything failing compilation * use test accounts for account migration * move balances and accounts migrations out for custom calling * make migration mods public * fix transaction-payment migration based on https://github.com/paritytech/substrate/pull/5673 Co-authored-by: Shawn Tabrizi Co-authored-by: Gavin Wood --- .../pallets/template/src/mock.rs | 2 +- bin/node-template/runtime/src/lib.rs | 2 +- bin/node/runtime/src/lib.rs | 1 + frame/assets/src/lib.rs | 2 +- frame/aura/src/mock.rs | 2 +- frame/authority-discovery/src/lib.rs | 2 +- frame/authorship/src/lib.rs | 2 +- frame/babe/src/lib.rs | 8 + frame/babe/src/mock.rs | 2 +- frame/balances/Cargo.toml | 1 + frame/balances/src/lib.rs | 38 ++++- frame/balances/src/migration.rs | 145 ++++++++++++++++++ frame/balances/src/tests_composite.rs | 2 +- frame/balances/src/tests_local.rs | 2 +- frame/benchmarking/src/tests.rs | 2 +- frame/collective/src/lib.rs | 18 ++- frame/contracts/src/lib.rs | 5 + frame/contracts/src/migration.rs | 81 ++++++++++ frame/contracts/src/tests.rs | 1 + frame/democracy/src/lib.rs | 118 ++++++++++++-- frame/democracy/src/tests.rs | 1 + frame/elections-phragmen/src/lib.rs | 28 +++- frame/elections/src/mock.rs | 2 +- frame/example-offchain-worker/src/tests.rs | 2 +- frame/example/src/lib.rs | 2 +- frame/executive/src/lib.rs | 1 + frame/finality-tracker/src/lib.rs | 10 +- frame/finality-tracker/src/migration.rs | 70 +++++++++ frame/generic-asset/src/lib.rs | 2 +- frame/generic-asset/src/mock.rs | 2 +- frame/grandpa/src/lib.rs | 24 ++- frame/grandpa/src/mock.rs | 1 + frame/identity/src/lib.rs | 24 ++- frame/identity/src/migration.rs | 61 ++++++++ frame/im-online/src/lib.rs | 30 +++- frame/im-online/src/mock.rs | 2 +- frame/indices/src/mock.rs | 2 +- frame/membership/src/lib.rs | 2 +- frame/nicks/src/lib.rs | 2 +- frame/offences/benchmarking/src/mock.rs | 1 + frame/offences/src/lib.rs | 8 + frame/offences/src/mock.rs | 2 +- frame/randomness-collective-flip/src/lib.rs | 2 +- frame/recovery/src/lib.rs | 8 + frame/recovery/src/mock.rs | 2 +- frame/scheduler/src/lib.rs | 1 + frame/scored-pool/src/mock.rs | 2 +- frame/session/benchmarking/src/mock.rs | 1 + frame/session/src/historical.rs | 27 +++- frame/session/src/lib.rs | 13 ++ frame/session/src/mock.rs | 2 +- frame/society/src/lib.rs | 8 +- frame/society/src/mock.rs | 2 +- frame/staking/fuzzer/src/mock.rs | 1 + frame/staking/src/lib.rs | 32 +++- frame/staking/src/mock.rs | 1 + frame/sudo/src/mock.rs | 1 + frame/support/src/traits.rs | 7 + frame/system/benches/bench.rs | 2 +- frame/system/benchmarking/src/mock.rs | 1 + frame/system/src/accounts.scale | 1 + frame/system/src/lib.rs | 34 +++- frame/system/src/migration.rs | 55 +++++++ frame/timestamp/src/lib.rs | 2 +- frame/transaction-payment/src/lib.rs | 8 +- frame/transaction-payment/src/migration.rs | 55 +++++++ frame/treasury/src/lib.rs | 16 ++ frame/treasury/src/tests.rs | 1 + frame/utility/src/tests.rs | 1 + frame/vesting/src/lib.rs | 16 +- test-utils/runtime/src/lib.rs | 2 +- 71 files changed, 957 insertions(+), 62 deletions(-) create mode 100644 frame/balances/src/migration.rs create mode 100644 frame/contracts/src/migration.rs create mode 100644 frame/finality-tracker/src/migration.rs create mode 100644 frame/identity/src/migration.rs create mode 100644 frame/system/src/accounts.scale create mode 100644 frame/system/src/migration.rs create mode 100644 frame/transaction-payment/src/migration.rs diff --git a/bin/node-template/pallets/template/src/mock.rs b/bin/node-template/pallets/template/src/mock.rs index 4eed0e1e75c3e..0da96c10dcc5a 100644 --- a/bin/node-template/pallets/template/src/mock.rs +++ b/bin/node-template/pallets/template/src/mock.rs @@ -45,7 +45,7 @@ impl system::Trait for Test { type Version = (); type ModuleToIndex = (); type AccountData = (); - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } impl Trait for Test { diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 68d4eeeb7ad3a..2fe50ee25e44f 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -182,7 +182,7 @@ impl system::Trait for Runtime { /// This type is being generated by `construct_runtime!`. type ModuleToIndex = ModuleToIndex; /// What to do if a new account is created. - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); /// What to do if an account is fully reaped from the system. type OnKilledAccount = (); /// The data to be stored in an account. diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 229aa3a9bed4f..6f95d82a53559 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -164,6 +164,7 @@ impl frame_system::Trait for Runtime { type Version = Version; type ModuleToIndex = ModuleToIndex; type AccountData = pallet_balances::AccountData; + type MigrateAccount = (Balances, Identity, Democracy, Elections, ImOnline, Recovery, Session, Society, Staking, Vesting); type OnNewAccount = (); type OnKilledAccount = (); } diff --git a/frame/assets/src/lib.rs b/frame/assets/src/lib.rs index 2c67a320c1eae..f6a042a320a20 100644 --- a/frame/assets/src/lib.rs +++ b/frame/assets/src/lib.rs @@ -325,7 +325,7 @@ mod tests { type Version = (); type ModuleToIndex = (); type AccountData = (); - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } impl Trait for Test { diff --git a/frame/aura/src/mock.rs b/frame/aura/src/mock.rs index 84d895cd06099..09c8e596d1aee 100644 --- a/frame/aura/src/mock.rs +++ b/frame/aura/src/mock.rs @@ -67,7 +67,7 @@ impl frame_system::Trait for Test { type Version = (); type ModuleToIndex = (); type AccountData = (); - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } diff --git a/frame/authority-discovery/src/lib.rs b/frame/authority-discovery/src/lib.rs index 1b7915ce3a4d4..80dbaeb8699ed 100644 --- a/frame/authority-discovery/src/lib.rs +++ b/frame/authority-discovery/src/lib.rs @@ -164,7 +164,7 @@ mod tests { type Version = (); type ModuleToIndex = (); type AccountData = (); - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } diff --git a/frame/authorship/src/lib.rs b/frame/authorship/src/lib.rs index b9b30bf41111a..2661d5e3cf2ab 100644 --- a/frame/authorship/src/lib.rs +++ b/frame/authorship/src/lib.rs @@ -439,7 +439,7 @@ mod tests { type Version = (); type ModuleToIndex = (); type AccountData = (); - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } diff --git a/frame/babe/src/lib.rs b/frame/babe/src/lib.rs index 91421739327ab..75c4a53ed4f37 100644 --- a/frame/babe/src/lib.rs +++ b/frame/babe/src/lib.rs @@ -208,6 +208,14 @@ decl_module! { // remove temporary "environment" entry from storage Lateness::::kill(); } + + fn on_runtime_upgrade() -> Weight { + for i in 0..=SegmentIndex::get() { + UnderConstruction::migrate_key_from_blake(i); + } + // TODO: determine weight + 0 + } } } diff --git a/frame/babe/src/mock.rs b/frame/babe/src/mock.rs index de00928171494..61f7565736641 100644 --- a/frame/babe/src/mock.rs +++ b/frame/babe/src/mock.rs @@ -78,7 +78,7 @@ impl frame_system::Trait for Test { type MaximumBlockLength = MaximumBlockLength; type ModuleToIndex = (); type AccountData = (); - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } diff --git a/frame/balances/Cargo.toml b/frame/balances/Cargo.toml index ae69fb17c2acd..1c763b3ff1cd1 100644 --- a/frame/balances/Cargo.toml +++ b/frame/balances/Cargo.toml @@ -16,6 +16,7 @@ serde = { version = "1.0.101", optional = true } codec = { package = "parity-scale-codec", version = "1.3.0", default-features = false, features = ["derive"] } sp-std = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/std" } sp-runtime = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/runtime" } +sp-io = { version = "2.0.0-rc2", default-features = false, path = "../../primitives/io" } frame-benchmarking = { version = "2.0.0-rc2", default-features = false, path = "../benchmarking", optional = true } frame-support = { version = "2.0.0-rc2", default-features = false, path = "../support" } frame-system = { version = "2.0.0-rc2", default-features = false, path = "../system" } diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index d5f9aab37bc95..c1bbb25e985b7 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -154,6 +154,7 @@ mod tests; mod tests_local; mod tests_composite; mod benchmarking; +pub mod migration; use sp_std::prelude::*; use sp_std::{cmp, result, mem, fmt::Debug, ops::BitOr, convert::Infallible}; @@ -164,8 +165,9 @@ use frame_support::{ Currency, OnKilledAccount, OnUnbalanced, TryDrop, StoredMap, WithdrawReason, WithdrawReasons, LockIdentifier, LockableCurrency, ExistenceRequirement, Imbalance, SignedImbalance, ReservableCurrency, Get, ExistenceRequirement::KeepAlive, - ExistenceRequirement::AllowDeath, IsDeadAccount, BalanceStatus as Status, - } + ExistenceRequirement::AllowDeath, IsDeadAccount, BalanceStatus as Status, MigrateAccount + }, + weights::Weight, }; use sp_runtime::{ RuntimeDebug, DispatchResult, DispatchError, @@ -542,6 +544,36 @@ decl_module! { let dest = T::Lookup::lookup(dest)?; >::transfer(&transactor, &dest, value, KeepAlive)?; } + + fn on_runtime_upgrade() -> Weight { + // Moved to custom runtime upgrade + // migration::on_runtime_upgrade::() + 0 + } + } +} + +#[derive(Decode)] +struct OldBalanceLock { + id: LockIdentifier, + amount: Balance, + until: BlockNumber, + reasons: WithdrawReasons, +} + +impl OldBalanceLock { + fn upgraded(self) -> (BalanceLock, BlockNumber) { + (BalanceLock { + id: self.id, + amount: self.amount, + reasons: self.reasons.into(), + }, self.until) + } +} + +impl, I: Instance> MigrateAccount for Module { + fn migrate_account(account: &T::AccountId) { + Locks::::migrate_key_from_blake(account); } } @@ -868,7 +900,7 @@ impl, I: Instance> frame_system::Trait for ElevatedTrait { type AvailableBlockRatio = T::AvailableBlockRatio; type Version = T::Version; type ModuleToIndex = T::ModuleToIndex; - type OnNewAccount = T::OnNewAccount; + type MigrateAccount = (); type OnNewAccount = T::OnNewAccount; type OnKilledAccount = T::OnKilledAccount; type AccountData = T::AccountData; } diff --git a/frame/balances/src/migration.rs b/frame/balances/src/migration.rs new file mode 100644 index 0000000000000..05f84a45e325e --- /dev/null +++ b/frame/balances/src/migration.rs @@ -0,0 +1,145 @@ +// Copyright 2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Temporary migrations of the balances module. + +use super::*; + +use frame_support::storage::migration::{ + get_storage_value, have_storage_value, put_storage_value, take_storage_value, StorageIterator, +}; +use frame_support::weights::Weight; +use sp_io::hashing::twox_64; + +pub fn on_runtime_upgrade, I: Instance>() -> Weight { + match StorageVersion::::get() { + Releases::V2_0_0 => T::DbWeight::get().reads(1), + Releases::V1_0_0 => upgrade_v1_to_v2::(), + } +} + +// Upgrade from the pre-#4649 balances/vesting into the new balances. +fn upgrade_v1_to_v2, I: Instance>() -> Weight { + sp_runtime::print("Upgrading Account Balances..."); + // First, migrate from old FreeBalance to new Account. + // We also move all locks across since only accounts with FreeBalance values have locks. + // FreeBalance: map T::AccountId => T::Balance + sp_runtime::print("Balances: FreeBalance -> Account"); + for (hash, free) in StorageIterator::::new(b"Balances", b"FreeBalance").drain() { + let mut account = AccountData { + free, + ..Default::default() + }; + // Locks: map T::AccountId => Vec + let old_locks = get_storage_value::>>( + b"Balances", + b"Locks", + &hash, + ); + if let Some(locks) = old_locks { + let locks = locks + .into_iter() + .map(|i| { + let (result, expiry) = i.upgraded(); + if expiry != T::BlockNumber::max_value() { + // Any `until`s that are not T::BlockNumber::max_value come from + // democracy and need to be migrated over there. + // Democracy: Locks get(locks): map T::AccountId => Option; + put_storage_value(b"Democracy", b"Locks", &hash, expiry); + } + result + }) + .collect::>(); + for l in locks.iter() { + if l.reasons == Reasons::All || l.reasons == Reasons::Misc { + account.misc_frozen = account.misc_frozen.max(l.amount); + } + if l.reasons == Reasons::All || l.reasons == Reasons::Fee { + account.fee_frozen = account.fee_frozen.max(l.amount); + } + } + put_storage_value(b"Balances", b"Locks", &hash, locks); + } + put_storage_value(b"Balances", b"Account", &hash, account); + } + // Second, migrate old ReservedBalance into new Account. + // ReservedBalance: map T::AccountId => T::Balance + sp_runtime::print("Balances: ReservedBalance -> Account"); + for (hash, reserved) in StorageIterator::::new(b"Balances", b"ReservedBalance").drain() { + let mut account = + get_storage_value::>(b"Balances", b"Account", &hash).unwrap_or_default(); + account.reserved = reserved; + put_storage_value(b"Balances", b"Account", &hash, account); + } + + // Finally, migrate vesting and ensure locks are in place. We will be lazy and just lock + // for the maximum amount (i.e. at genesis). Users will need to call "vest" to reduce the + // lock to something sensible. + // pub Vesting: map T::AccountId => Option; + sp_runtime::print("Balances: Vesting"); + for (hash, vesting) in + StorageIterator::<(T::Balance, T::Balance, T::BlockNumber)>::new(b"Balances", b"Vesting").drain() + { + let mut account = + get_storage_value::>(b"Balances", b"Account", &hash).unwrap_or_default(); + let mut locks = get_storage_value::>>(b"Balances", b"Locks", &hash) + .unwrap_or_default(); + locks.push(BalanceLock { + id: *b"vesting ", + amount: vesting.0.clone(), + reasons: Reasons::Misc, + }); + account.misc_frozen = account.misc_frozen.max(vesting.0.clone()); + put_storage_value(b"Vesting", b"Vesting", &hash, vesting); + put_storage_value(b"Balances", b"Locks", &hash, locks); + put_storage_value(b"Balances", b"Account", &hash, account); + } + + let prefix = { + let encoded_prefix_key_hash = b":session:keys".to_vec().encode(); + let mut h = twox_64(&encoded_prefix_key_hash[..]).to_vec(); + h.extend(&encoded_prefix_key_hash[..]); + h + }; + + sp_runtime::print("Balances: Balance::Account -> System::Account"); + for (hash, balances) in StorageIterator::>::new(b"Balances", b"Account").drain() { + let nonce = take_storage_value::(b"System", b"AccountNonce", &hash).unwrap_or_default(); + let mut refs: system::RefCount = 0; + // The items in Kusama that would result in a ref count being incremented. + if have_storage_value(b"Democracy", b"Proxy", &hash) { + refs += 1 + } + // We skip Recovered since it's being replaced anyway. + let mut prefixed_hash = prefix.clone(); + prefixed_hash.extend(&hash[..]); + if have_storage_value(b"Session", b"NextKeys", &prefixed_hash) { + refs += 1 + } + if have_storage_value(b"Staking", b"Bonded", &hash) { + refs += 1 + } + put_storage_value(b"System", b"Account", &hash, (nonce, refs, &balances)); + } + + take_storage_value::(b"Balances", b"IsUpgraded", &[]); + + StorageVersion::::put(Releases::V2_0_0); + + sp_runtime::print("Done Account Balances."); + // TODO determine actual weight + T::MaximumBlockWeight::get() +} diff --git a/frame/balances/src/tests_composite.rs b/frame/balances/src/tests_composite.rs index 7b9ec1f91eade..e952cbb953731 100644 --- a/frame/balances/src/tests_composite.rs +++ b/frame/balances/src/tests_composite.rs @@ -77,7 +77,7 @@ impl frame_system::Trait for Test { type Version = (); type ModuleToIndex = (); type AccountData = super::AccountData; - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } parameter_types! { diff --git a/frame/balances/src/tests_local.rs b/frame/balances/src/tests_local.rs index 9ff76839f4cb2..86745769e6634 100644 --- a/frame/balances/src/tests_local.rs +++ b/frame/balances/src/tests_local.rs @@ -77,7 +77,7 @@ impl frame_system::Trait for Test { type Version = (); type ModuleToIndex = (); type AccountData = super::AccountData; - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = Module; } parameter_types! { diff --git a/frame/benchmarking/src/tests.rs b/frame/benchmarking/src/tests.rs index dc9d160b5ee92..f262b6ba0459e 100644 --- a/frame/benchmarking/src/tests.rs +++ b/frame/benchmarking/src/tests.rs @@ -88,7 +88,7 @@ impl frame_system::Trait for Test { type Version = (); type ModuleToIndex = (); type AccountData = (); - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } diff --git a/frame/collective/src/lib.rs b/frame/collective/src/lib.rs index 3d6e41d98d561..6fdf3d52d928e 100644 --- a/frame/collective/src/lib.rs +++ b/frame/collective/src/lib.rs @@ -334,6 +334,16 @@ fn get_result_weight(result: DispatchResultWithPostInfo) -> Option { } } +mod migration { + use super::*; + + pub fn migrate, I: Instance>() { + for p in Proposals::::get().into_iter() { + ProposalOf::::migrate_key_from_blake(&p); + Voting::::migrate_key_from_blake(&p); + } + } +} // Note that councillor operations are assigned to the operational class. decl_module! { @@ -342,6 +352,12 @@ decl_module! { fn deposit_event() = default; + fn on_runtime_upgrade() -> Weight { + migration::migrate::(); + // TODO: determine actual weight + 0 + } + /// Set the collective's membership. /// /// - `new_members`: The new member list. Be nice to the chain and provide it sorted. @@ -990,7 +1006,7 @@ mod tests { type Version = (); type ModuleToIndex = (); type AccountData = (); - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } impl Trait for Test { diff --git a/frame/contracts/src/lib.rs b/frame/contracts/src/lib.rs index 509229cd96cde..b637ee22313fc 100644 --- a/frame/contracts/src/lib.rs +++ b/frame/contracts/src/lib.rs @@ -89,6 +89,7 @@ mod rent; #[cfg(test)] mod tests; +mod migration; use crate::exec::ExecutionContext; use crate::account_db::{AccountDb, DirectAccountDb}; @@ -578,6 +579,10 @@ decl_module! { T::Currency::deposit_into_existing(&rewarded, T::SurchargeReward::get())?; } } + + fn on_runtime_upgrade() -> Weight { + migration::on_runtime_upgrade::() + } } } diff --git a/frame/contracts/src/migration.rs b/frame/contracts/src/migration.rs new file mode 100644 index 0000000000000..089187afce152 --- /dev/null +++ b/frame/contracts/src/migration.rs @@ -0,0 +1,81 @@ +// Copyright 2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Migration code to update storage. + +use super::*; +use frame_support::storage::migration::{put_storage_value, take_storage_value, StorageIterator}; +use frame_support::weights::Weight; + +pub fn on_runtime_upgrade() -> Weight { + // TODO: removed for now because it's failing + // change_name_contract_to_contracts::() + 0 +} + +// Change the storage name used by this pallet from `Contract` to `Contracts`. +// +// Since the format of the storage items themselves have not changed, we do not +// need to keep track of a storage version. If the runtime does not need to be +// upgraded, nothing here will happen anyway. + +fn change_name_contract_to_contracts() -> Weight { + sp_runtime::print("Migrating Contracts."); + + let mut weight = 0; + let db = T::DbWeight::get(); + if let Some(gas_spent) = take_storage_value::(b"Contract", b"GasSpent", &[]) { + put_storage_value(b"Contracts", b"GasSpent", &[], gas_spent); + weight += db.writes(2); + } + weight += db.reads(1); + + if let Some(current_schedule) = take_storage_value::(b"Contract", b"CurrentSchedule", &[]) { + put_storage_value(b"Contracts", b"CurrentSchedule", &[], current_schedule); + weight += db.writes(2); + } + weight += db.reads(1); + + for (hash, pristine_code) in StorageIterator::>::new(b"Contract", b"PristineCode").drain() { + put_storage_value(b"Contracts", b"PristineCode", &hash, pristine_code); + weight += db.reads_writes(1, 2); + } + + for (hash, code_storage) in StorageIterator::::new(b"Contract", b"CodeStorage").drain() { + put_storage_value(b"Contracts", b"CodeStorage", &hash, code_storage); + weight += db.reads_writes(1, 2); + } + + if let Some(current_schedule) = take_storage_value::(b"Contract", b"AccountCounter", &[]) { + put_storage_value(b"Contracts", b"AccountCounter", &[], current_schedule); + weight += db.writes(2); + } + weight += db.reads(1); + + for (hash, contract_info_of) in StorageIterator::>::new(b"Contract", b"ContractInfoOf").drain() { + put_storage_value(b"Contracts", b"ContractInfoOf", &hash, contract_info_of); + weight += db.reads_writes(1, 2); + } + + if let Some(get_price) = take_storage_value::>(b"Contract", b"GetPrice", &[]) { + put_storage_value(b"Contracts", b"GetPrice", &[], get_price); + weight += db.writes(2); + } + weight += db.reads(1); + + sp_runtime::print("Done Contracts."); + weight +} diff --git a/frame/contracts/src/tests.rs b/frame/contracts/src/tests.rs index 944bca622bfd2..e8268e7a1f277 100644 --- a/frame/contracts/src/tests.rs +++ b/frame/contracts/src/tests.rs @@ -103,6 +103,7 @@ impl frame_system::Trait for Test { type Version = (); type ModuleToIndex = (); type AccountData = pallet_balances::AccountData; + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } diff --git a/frame/democracy/src/lib.rs b/frame/democracy/src/lib.rs index 580e80cce0e67..060858be8c714 100644 --- a/frame/democracy/src/lib.rs +++ b/frame/democracy/src/lib.rs @@ -16,12 +16,12 @@ // limitations under the License. //! # Democracy Pallet -//! +//! //! - [`democracy::Trait`](./trait.Trait.html) //! - [`Call`](./enum.Call.html) //! //! ## Overview -//! +//! //! The Democracy pallet handles the administration of general stakeholder voting. //! //! There are two different queues that a proposal can be added to before it @@ -29,7 +29,7 @@ //! and 2) the external queue consisting of a single proposal that originates //! from one of the _external_ origins (such as a collective group). //! -//! Every launch period - a length defined in the runtime - the Democracy pallet +//! Every launch period - a length defined in the runtime - the Democracy pallet //! launches a referendum from a proposal that it takes from either the proposal //! queue or the external queue in turn. Any token holder in the system can vote //! on referenda. The voting system @@ -40,7 +40,7 @@ //! ### Terminology //! //! - **Enactment Period:** The minimum period of locking and the period between a proposal being -//! approved and enacted. +//! approved and enacted. //! - **Lock Period:** A period of time after proposal enactment that the tokens of _winning_ voters //! will be locked. //! - **Conviction:** An indication of a voter's strength of belief in their vote. An increase @@ -50,7 +50,7 @@ //! of a particular referendum. //! - **Proposal:** A submission to the chain that represents an action that a proposer (either an //! account or an external origin) suggests that the system adopt. -//! - **Referendum:** A proposal that is in the process of being voted on for +//! - **Referendum:** A proposal that is in the process of being voted on for //! either acceptance or rejection as a change to the system. //! - **Proxy:** An account that has full voting power on behalf of a separate "Stash" account //! that holds the funds. @@ -62,7 +62,7 @@ //! A _referendum_ can be either simple majority-carries in which 50%+1 of the //! votes decide the outcome or _adaptive quorum biased_. Adaptive quorum biasing //! makes the threshold for passing or rejecting a referendum higher or lower -//! depending on how the referendum was originally proposed. There are two types of +//! depending on how the referendum was originally proposed. There are two types of //! adaptive quorum biasing: 1) _positive turnout bias_ makes a referendum //! require a super-majority to pass that decreases as turnout increases and //! 2) _negative turnout bias_ makes a referendum require a super-majority to @@ -113,7 +113,7 @@ //! Does not require a deposit, but the proposal must be in the dispatch queue. //! - `note_imminent_preimage_operational` - same but provided by `T::OperationalPreimageOrigin`. //! - `reap_preimage` - Removes the preimage for an expired proposal. Will only -//! work under the condition that it's the same account that noted it and +//! work under the condition that it's the same account that noted it and //! after the voting period, OR it's a different account after the enactment period. //! //! #### Cancellation Origin @@ -152,7 +152,7 @@ //! is "majority-carries" to become a referendum immediately. //! //! #### Veto Origin -//! +//! //! This call can only be made by the `VetoOrigin`. //! //! - `veto_external` - Vetoes and blacklists the external proposal hash. @@ -178,7 +178,7 @@ use frame_support::{ weights::{Weight, DispatchClass}, traits::{ Currency, ReservableCurrency, LockableCurrency, WithdrawReason, LockIdentifier, Get, - OnUnbalanced, BalanceStatus, schedule::Named as ScheduleNamed, EnsureOrigin + OnUnbalanced, BalanceStatus, schedule::Named as ScheduleNamed, EnsureOrigin, MigrateAccount, }, dispatch::DispatchResultWithPostInfo, }; @@ -623,6 +623,99 @@ mod weight_for { } } +impl MigrateAccount for Module { + fn migrate_account(a: &T::AccountId) { + mod deprecated { + use sp_std::prelude::*; + + use codec::{Encode, EncodeLike, Decode, Input, Output}; + use frame_support::{decl_module, decl_storage}; + use sp_runtime::RuntimeDebug; + use sp_std::convert::TryFrom; + + use crate::{Trait, ReferendumIndex, Conviction}; + + #[derive(Copy, Clone, Eq, PartialEq, Default, RuntimeDebug)] + pub struct Vote { + pub aye: bool, + pub conviction: Conviction, + } + + impl Encode for Vote { + fn encode_to(&self, output: &mut T) { + output.push_byte(u8::from(self.conviction) | if self.aye { 0b1000_0000 } else { 0 }); + } + } + + impl EncodeLike for Vote {} + + impl Decode for Vote { + fn decode(input: &mut I) -> core::result::Result { + let b = input.read_byte()?; + Ok(Vote { + aye: (b & 0b1000_0000) == 0b1000_0000, + conviction: Conviction::try_from(b & 0b0111_1111) + .map_err(|_| codec::Error::from("Invalid conviction"))?, + }) + } + } + + decl_module! { + pub struct Module for enum Call where origin: T::Origin { } + } + decl_storage! { + trait Store for Module as Democracy { + pub VoteOf get(fn vote_of): + map hasher(opaque_blake2_256) (ReferendumIndex, T::AccountId) => Vote; + pub Delegations get(fn delegations): + map hasher(opaque_blake2_256) T::AccountId => (T::AccountId, Conviction); + } + } + } + + Proxy::::migrate_key_from_blake(a); + Locks::::migrate_key_from_blake(a); + // TODO: will not actually do any useful migration + deprecated::Delegations::::migrate_key_from_blake(a); + for i in LowestUnbaked::get()..ReferendumCount::get() { + // TODO: will not actually do any useful migration + deprecated::VoteOf::::migrate_key_from_blake((i, a)); + } + } +} + +mod migration { + use super::*; + + pub fn migrate() { + mod deprecated { + use super::*; + + decl_module! { + pub struct Module for enum Call where origin: T::Origin { } + } + decl_storage! { + trait Store for Module as Democracy { + pub VotersFor get(fn voters_for): + map hasher(opaque_blake2_256) ReferendumIndex => Vec; + } + } + } + + Blacklist::::remove_all(); + Cancellations::::remove_all(); + for i in LowestUnbaked::get()..ReferendumCount::get() { + // TODO: will not actually do any useful migration + deprecated::VotersFor::::migrate_key_from_blake(i); + ReferendumInfoOf::::migrate_key_from_blake(i); + } + for (p, h, _) in PublicProps::::get().into_iter() { + DepositOf::::migrate_key_from_blake(p); + Preimages::::migrate_key_from_blake(h); + } + } +} + decl_module! { pub struct Module for enum Call where origin: T::Origin { type Error = Error; @@ -658,6 +751,9 @@ decl_module! { fn deposit_event() = default; fn on_runtime_upgrade() -> Weight { + // TODO: determine correct weight + migration::migrate::(); + if let None = StorageVersion::get() { StorageVersion::put(Releases::V1); @@ -851,7 +947,7 @@ decl_module! { /// an external referendum. /// /// The dispatch of this call must be `ExternalMajorityOrigin`. - /// + /// /// - `proposal_hash`: The preimage hash of the proposal. /// /// Unlike `external_propose`, blacklisting has no effect on this and it may replace a @@ -948,7 +1044,7 @@ decl_module! { /// Veto and blacklist the external proposal hash. /// /// The dispatch origin of this call must be `VetoOrigin`. - /// + /// /// - `proposal_hash`: The preimage hash of the proposal to veto and blacklist. /// /// Emits `Vetoed`. diff --git a/frame/democracy/src/tests.rs b/frame/democracy/src/tests.rs index 103ac6a84b6b8..f34ef08a4cd4f 100644 --- a/frame/democracy/src/tests.rs +++ b/frame/democracy/src/tests.rs @@ -106,6 +106,7 @@ impl frame_system::Trait for Test { type Version = (); type ModuleToIndex = (); type AccountData = pallet_balances::AccountData; + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } diff --git a/frame/elections-phragmen/src/lib.rs b/frame/elections-phragmen/src/lib.rs index 5d7d2bf503bc2..6bb8b6b7ff02b 100644 --- a/frame/elections-phragmen/src/lib.rs +++ b/frame/elections-phragmen/src/lib.rs @@ -102,6 +102,7 @@ use frame_support::{ }; use sp_phragmen::{build_support_map, ExtendedBalance, VoteWeight, PhragmenResult}; use frame_system::{self as system, ensure_signed, ensure_root}; +use frame_support::traits::MigrateAccount; mod benchmarking; @@ -694,6 +695,31 @@ decl_event!( } ); +impl MigrateAccount for Module { + fn migrate_account(a: &T::AccountId) { + mod deprecated { + use super::*; + + decl_module! { + pub struct Module for enum Call where origin: T::Origin { } + } + decl_storage! { + trait Store for Module as PhragmenElection { + pub VotesOf get(fn votes_of): + map hasher(opaque_blake2_256) T::AccountId => Vec; + pub StakeOf get(fn stake_of): + map hasher(opaque_blake2_256) T::AccountId => BalanceOf; + } + } + } + + // TODO: will not actually do any useful migration + if deprecated::StakeOf::::migrate_key_from_blake(a).is_some() { + deprecated::VotesOf::::migrate_key_from_blake(a); + } + } +} + impl Module { /// Attempts to remove a member `who`. If a runner-up exists, it is used as the replacement and /// Ok(true). is returned. @@ -1095,7 +1121,7 @@ mod tests { type Version = (); type ModuleToIndex = (); type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } diff --git a/frame/elections/src/mock.rs b/frame/elections/src/mock.rs index 9971dac572187..51395d4cb467d 100644 --- a/frame/elections/src/mock.rs +++ b/frame/elections/src/mock.rs @@ -60,7 +60,7 @@ impl frame_system::Trait for Test { type Version = (); type ModuleToIndex = (); type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } diff --git a/frame/example-offchain-worker/src/tests.rs b/frame/example-offchain-worker/src/tests.rs index 30c9c22593035..6984c0b56d300 100644 --- a/frame/example-offchain-worker/src/tests.rs +++ b/frame/example-offchain-worker/src/tests.rs @@ -75,7 +75,7 @@ impl frame_system::Trait for Test { type Version = (); type ModuleToIndex = (); type AccountData = (); - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } diff --git a/frame/example/src/lib.rs b/frame/example/src/lib.rs index 6b3d6b5e5fc9f..c0021fb1c50fe 100644 --- a/frame/example/src/lib.rs +++ b/frame/example/src/lib.rs @@ -760,7 +760,7 @@ mod tests { type Version = (); type ModuleToIndex = (); type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } parameter_types! { diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index 04e095fec4364..4506f406a370c 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -566,6 +566,7 @@ mod tests { type Version = RuntimeVersion; type ModuleToIndex = (); type AccountData = pallet_balances::AccountData; + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } diff --git a/frame/finality-tracker/src/lib.rs b/frame/finality-tracker/src/lib.rs index a9cf9c2b70f6d..d288dc9da3020 100644 --- a/frame/finality-tracker/src/lib.rs +++ b/frame/finality-tracker/src/lib.rs @@ -24,13 +24,15 @@ use sp_runtime::traits::{One, Zero, SaturatedConversion}; use sp_std::{prelude::*, result, cmp, vec}; use frame_support::{decl_module, decl_storage, decl_error, ensure}; use frame_support::traits::Get; -use frame_support::weights::{DispatchClass}; +use frame_support::weights::{DispatchClass, Weight}; use frame_system::{ensure_none, Trait as SystemTrait}; use sp_finality_tracker::{INHERENT_IDENTIFIER, FinalizedInherentData}; pub const DEFAULT_WINDOW_SIZE: u32 = 101; pub const DEFAULT_REPORT_LATENCY: u32 = 1000; +mod migration; + pub trait Trait: SystemTrait { /// Something which can be notified when the timestamp is set. Set this to `()` /// if not needed. @@ -92,6 +94,10 @@ decl_module! { fn on_finalize() { Self::update_hint(::Update::take()) } + + fn on_runtime_upgrade() -> Weight { + migration::on_runtime_upgrade::() + } } } @@ -273,7 +279,7 @@ mod tests { type Version = (); type ModuleToIndex = (); type AccountData = (); - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } parameter_types! { diff --git a/frame/finality-tracker/src/migration.rs b/frame/finality-tracker/src/migration.rs new file mode 100644 index 0000000000000..0ec33d3fd32e0 --- /dev/null +++ b/frame/finality-tracker/src/migration.rs @@ -0,0 +1,70 @@ +// Copyright 2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +// Migration code to update storage. + +use super::*; +use frame_support::storage::migration::{put_storage_value, take_storage_value}; +use frame_support::weights::Weight; + +pub fn on_runtime_upgrade() -> Weight { + change_name_timestamp_to_finality_tracker::() +} + +// Change the storage name used by this pallet from `Timestamp` to `FinalityTracker`. +// +// Since the format of the storage items themselves have not changed, we do not +// need to keep track of a storage version. If the runtime does not need to be +// upgraded, nothing here will happen anyway. + +fn change_name_timestamp_to_finality_tracker() -> Weight { + sp_runtime::print("Migrating Finality Tracker."); + + let mut reads = 0; + let mut writes = 0; + if let Some(recent_hints) = take_storage_value::>(b"Timestamp", b"RecentHints", &[]) { + put_storage_value(b"FinalityTracker", b"RecentHints", &[], recent_hints); + writes += 2; + } + reads += 1; + + if let Some(ordered_hints) = take_storage_value::>(b"Timestamp", b"OrderedHints", &[]) { + put_storage_value(b"FinalityTracker", b"OrderedHints", &[], ordered_hints); + writes += 2; + } + reads += 1; + + if let Some(median) = take_storage_value::(b"Timestamp", b"Median", &[]) { + put_storage_value(b"FinalityTracker", b"Median", &[], median); + writes += 2; + } + reads += 1; + + if let Some(update) = take_storage_value::(b"Timestamp", b"Update", &[]) { + put_storage_value(b"FinalityTracker", b"Update", &[], update); + writes += 2; + } + reads += 1; + + if let Some(initialized) = take_storage_value::(b"Timestamp", b"Initialized", &[]) { + put_storage_value(b"FinalityTracker", b"Initialized", &[], initialized); + writes += 2; + } + reads += 1; + + sp_runtime::print("Done Finality Tracker."); + T::DbWeight::get().reads_writes(reads, writes) +} diff --git a/frame/generic-asset/src/lib.rs b/frame/generic-asset/src/lib.rs index f94c83b5ed59f..28f603fb7c845 100644 --- a/frame/generic-asset/src/lib.rs +++ b/frame/generic-asset/src/lib.rs @@ -1141,7 +1141,7 @@ impl frame_system::Trait for ElevatedTrait { type Version = T::Version; type ModuleToIndex = (); type AccountData = (); - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } impl Trait for ElevatedTrait { diff --git a/frame/generic-asset/src/mock.rs b/frame/generic-asset/src/mock.rs index 04fd565091b29..04d38ade524dc 100644 --- a/frame/generic-asset/src/mock.rs +++ b/frame/generic-asset/src/mock.rs @@ -67,7 +67,7 @@ impl frame_system::Trait for Test { type Version = (); type ModuleToIndex = (); type AccountData = (); - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } diff --git a/frame/grandpa/src/lib.rs b/frame/grandpa/src/lib.rs index 3432c1102008b..51d5241e33c3c 100644 --- a/frame/grandpa/src/lib.rs +++ b/frame/grandpa/src/lib.rs @@ -41,7 +41,7 @@ use fg_primitives::{ }; use frame_support::{ decl_error, decl_event, decl_module, decl_storage, storage, traits::KeyOwnerProofSystem, - Parameter, + Parameter, weights::Weight, }; use frame_system::{self as system, ensure_signed, DigestOf}; use sp_runtime::{ @@ -224,12 +224,34 @@ decl_storage! { } } +mod migration { + use super::*; + pub fn migrate() { + for i in 0..=CurrentSetId::get() { + SetIdSession::migrate_key_from_blake(i); + } + } +} + decl_module! { pub struct Module for enum Call where origin: T::Origin { type Error = Error; fn deposit_event() = default; + fn on_runtime_upgrade() -> Weight { + migration::migrate::(); + // TODO: determine actual weight + 0 + } + + fn on_initialize() -> Weight { + #[cfg(feature = "migrate-authorities")] + Self::migrate_authorities(); + // TODO: determine actual weight + 0 + } + /// Report voter equivocation/misbehavior. This method will verify the /// equivocation proof and validate the given key ownership proof /// against the extracted offender. If both are valid, the offence diff --git a/frame/grandpa/src/mock.rs b/frame/grandpa/src/mock.rs index 08329fbb70b59..553d52b169f39 100644 --- a/frame/grandpa/src/mock.rs +++ b/frame/grandpa/src/mock.rs @@ -115,6 +115,7 @@ impl frame_system::Trait for Test { type Version = (); type ModuleToIndex = (); type AccountData = balances::AccountData; + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } diff --git a/frame/identity/src/lib.rs b/frame/identity/src/lib.rs index 2b58437685556..22459d368bddc 100644 --- a/frame/identity/src/lib.rs +++ b/frame/identity/src/lib.rs @@ -79,8 +79,12 @@ use frame_support::{ weights::Weight, }; use frame_system::{self as system, ensure_signed, ensure_root}; +use frame_support::traits::MigrateAccount; -mod benchmarking; +#[cfg(feature = "runtime-benchmarks")] +pub mod benchmarking; + +mod migration; type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; type NegativeImbalanceOf = <::Currency as Currency<::AccountId>>::NegativeImbalance; @@ -1132,6 +1136,10 @@ decl_module! { id.info.additional.len() as Weight // X )).into()) } + + fn on_runtime_upgrade() -> Weight { + migration::on_runtime_upgrade::() + } } } @@ -1145,6 +1153,18 @@ impl Module { } } +impl MigrateAccount for Module { + fn migrate_account(a: &T::AccountId) { + if IdentityOf::::migrate_key_from_blake(a).is_some() { + if let Some((_, subs)) = SubsOf::::migrate_key_from_blake(a) { + for sub in subs.into_iter() { + SuperOf::::migrate_key_from_blake(sub); + } + } + } + } +} + #[cfg(test)] mod tests { use super::*; @@ -1199,7 +1219,7 @@ mod tests { type Version = (); type ModuleToIndex = (); type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } parameter_types! { diff --git a/frame/identity/src/migration.rs b/frame/identity/src/migration.rs new file mode 100644 index 0000000000000..7f69f4ad7ff9c --- /dev/null +++ b/frame/identity/src/migration.rs @@ -0,0 +1,61 @@ +// Copyright 2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Migration code to update storage. + +use super::*; +use frame_support::storage::migration::{put_storage_value, take_storage_value, StorageIterator}; +use frame_support::weights::Weight; + +pub fn on_runtime_upgrade() -> Weight { + change_name_sudo_to_identity::() +} + +// Change the storage name used by this pallet from `Sudo` to `Identity`. +// +// Since the format of the storage items themselves have not changed, we do not +// need to keep track of a storage version. If the runtime does not need to be +// upgraded, nothing here will happen anyway. + +fn change_name_sudo_to_identity() -> Weight { + sp_runtime::print("Migrating Identity."); + + let mut weight = 0; + let db = T::DbWeight::get(); + for (hash, identity_of) in StorageIterator::>>::new(b"Sudo", b"IdentityOf").drain() { + put_storage_value(b"Identity", b"IdentityOf", &hash, identity_of); + weight += db.reads_writes(1, 2); + } + + for (hash, super_of) in StorageIterator::<(T::AccountId, Data)>::new(b"Sudo", b"SuperOf").drain() { + put_storage_value(b"Identity", b"SuperOf", &hash, super_of); + weight += db.reads_writes(1, 2); + } + + for (hash, subs_of) in StorageIterator::<(BalanceOf, Vec)>::new(b"Sudo", b"SubsOf").drain() { + put_storage_value(b"Identity", b"SubsOf", &hash, subs_of); + weight += db.reads_writes(1, 2); + } + + if let Some(registrars) = take_storage_value::, T::AccountId>>>>(b"Sudo", b"Registrars", &[]) { + put_storage_value(b"Identity", b"Registrars", &[], registrars); + weight += db.writes(2); + } + weight += db.reads(1); + + sp_runtime::print("Done Identity."); + weight +} diff --git a/frame/im-online/src/lib.rs b/frame/im-online/src/lib.rs index c1c93910ece22..4c279be54cabf 100644 --- a/frame/im-online/src/lib.rs +++ b/frame/im-online/src/lib.rs @@ -94,7 +94,7 @@ use sp_staking::{ }; use frame_support::{ decl_module, decl_event, decl_storage, Parameter, debug, decl_error, - traits::Get, + traits::{Get, MigrateAccount}, weights::Weight, }; use frame_system::{self as system, ensure_none}; @@ -311,12 +311,40 @@ decl_error! { } } +mod migration { + use super::*; + use frame_support::Blake2_256; + pub fn migrate() { + let current_index = >::current_index(); + let key_count = Keys::::get().len() as AuthIndex; + for i in 0..key_count { + ReceivedHeartbeats::migrate_keys::(current_index, i); + } + } +} + +impl MigrateAccount for Module { + fn migrate_account(a: &T::AccountId) { + use frame_support::Blake2_256; + let current_index = >::current_index(); + if let Ok(v) = a.using_encoded(|mut d| T::ValidatorId::decode(&mut d)) { + AuthoredBlocks::::migrate_keys::(current_index, v); + } + } +} + decl_module! { pub struct Module for enum Call where origin: T::Origin { type Error = Error; fn deposit_event() = default; + fn on_runtime_upgrade() -> Weight { + migration::migrate::(); + // TODO: determine actual weight + 0 + } + /// # /// - Complexity: `O(K + E)` where K is length of `Keys` and E is length of /// `Heartbeat.network_state.external_address` diff --git a/frame/im-online/src/mock.rs b/frame/im-online/src/mock.rs index 01e84102b1a5c..12a3a0f6aa7bc 100644 --- a/frame/im-online/src/mock.rs +++ b/frame/im-online/src/mock.rs @@ -125,7 +125,7 @@ impl frame_system::Trait for Runtime { type Version = (); type ModuleToIndex = (); type AccountData = (); - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } diff --git a/frame/indices/src/mock.rs b/frame/indices/src/mock.rs index 90ac1ae81b595..8a8fd98c2ab0f 100644 --- a/frame/indices/src/mock.rs +++ b/frame/indices/src/mock.rs @@ -71,7 +71,7 @@ impl frame_system::Trait for Test { type Version = (); type ModuleToIndex = (); type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } diff --git a/frame/membership/src/lib.rs b/frame/membership/src/lib.rs index 669964c70c177..0cc3dc526cb9c 100644 --- a/frame/membership/src/lib.rs +++ b/frame/membership/src/lib.rs @@ -324,7 +324,7 @@ mod tests { type Version = (); type ModuleToIndex = (); type AccountData = (); - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } ord_parameter_types! { diff --git a/frame/nicks/src/lib.rs b/frame/nicks/src/lib.rs index 11b23443d68b9..304063d6cef24 100644 --- a/frame/nicks/src/lib.rs +++ b/frame/nicks/src/lib.rs @@ -291,7 +291,7 @@ mod tests { type Version = (); type ModuleToIndex = (); type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } parameter_types! { diff --git a/frame/offences/benchmarking/src/mock.rs b/frame/offences/benchmarking/src/mock.rs index 28263a5292cb5..b4c2a8f627b63 100644 --- a/frame/offences/benchmarking/src/mock.rs +++ b/frame/offences/benchmarking/src/mock.rs @@ -60,6 +60,7 @@ impl frame_system::Trait for Test { type Version = (); type ModuleToIndex = (); type AccountData = pallet_balances::AccountData; + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (Balances,); type BlockExecutionWeight = (); diff --git a/frame/offences/src/lib.rs b/frame/offences/src/lib.rs index a42f09697e3b4..40b8be2b12375 100644 --- a/frame/offences/src/lib.rs +++ b/frame/offences/src/lib.rs @@ -141,6 +141,14 @@ decl_module! { consumed } + + fn on_runtime_upgrade() -> Weight { + Reports::::remove_all(); + ConcurrentReportsIndex::::remove_all(); + ReportsByKindIndex::remove_all(); + // TODO: determine actual weight + 0 + } } } diff --git a/frame/offences/src/mock.rs b/frame/offences/src/mock.rs index 30d2409a00194..3aea787726b28 100644 --- a/frame/offences/src/mock.rs +++ b/frame/offences/src/mock.rs @@ -117,7 +117,7 @@ impl frame_system::Trait for Runtime { type Version = (); type ModuleToIndex = (); type AccountData = (); - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } diff --git a/frame/randomness-collective-flip/src/lib.rs b/frame/randomness-collective-flip/src/lib.rs index 4a851c926fb74..d3f960d436732 100644 --- a/frame/randomness-collective-flip/src/lib.rs +++ b/frame/randomness-collective-flip/src/lib.rs @@ -179,7 +179,7 @@ mod tests { type Version = (); type ModuleToIndex = (); type AccountData = (); - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } diff --git a/frame/recovery/src/lib.rs b/frame/recovery/src/lib.rs index cd3ba76b37012..808e8c8d323bb 100644 --- a/frame/recovery/src/lib.rs +++ b/frame/recovery/src/lib.rs @@ -165,6 +165,7 @@ use frame_support::{ dispatch::PostDispatchInfo, }; use frame_system::{self as system, ensure_signed, ensure_root}; +use frame_support::traits::MigrateAccount; #[cfg(test)] mod mock; @@ -259,6 +260,13 @@ decl_storage! { } } +impl MigrateAccount for Module { + fn migrate_account(a: &T::AccountId) { + Recoverable::::migrate_key_from_blake(a); + Proxy::::migrate_key_from_blake(a); + } +} + decl_event! { /// Events type. pub enum Event where diff --git a/frame/recovery/src/mock.rs b/frame/recovery/src/mock.rs index aae9b2b75cf8c..2632511a8c341 100644 --- a/frame/recovery/src/mock.rs +++ b/frame/recovery/src/mock.rs @@ -85,7 +85,7 @@ impl frame_system::Trait for Test { type Version = (); type ModuleToIndex = (); type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } diff --git a/frame/scheduler/src/lib.rs b/frame/scheduler/src/lib.rs index 687fe46d16a67..2c7cc6a8aa3e6 100644 --- a/frame/scheduler/src/lib.rs +++ b/frame/scheduler/src/lib.rs @@ -508,6 +508,7 @@ mod tests { type Version = (); type ModuleToIndex = (); type AccountData = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } diff --git a/frame/scored-pool/src/mock.rs b/frame/scored-pool/src/mock.rs index 1b61bb18846f4..23107b5ae6b0f 100644 --- a/frame/scored-pool/src/mock.rs +++ b/frame/scored-pool/src/mock.rs @@ -76,7 +76,7 @@ impl frame_system::Trait for Test { type Version = (); type ModuleToIndex = (); type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } diff --git a/frame/session/benchmarking/src/mock.rs b/frame/session/benchmarking/src/mock.rs index 5c0e40096eaf8..0a19c581513d5 100644 --- a/frame/session/benchmarking/src/mock.rs +++ b/frame/session/benchmarking/src/mock.rs @@ -79,6 +79,7 @@ impl frame_system::Trait for Test { type Version = (); type ModuleToIndex = (); type AccountData = pallet_balances::AccountData; + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (Balances,); } diff --git a/frame/session/src/historical.rs b/frame/session/src/historical.rs index a1c286eb39245..84a86781c942c 100644 --- a/frame/session/src/historical.rs +++ b/frame/session/src/historical.rs @@ -32,7 +32,7 @@ use sp_runtime::KeyTypeId; use sp_runtime::traits::{Convert, OpaqueKeys}; use sp_session::{MembershipProof, ValidatorCount}; use frame_support::{decl_module, decl_storage}; -use frame_support::{Parameter, print}; +use frame_support::{Parameter, print, weights::Weight}; use sp_trie::{MemoryDB, Trie, TrieMut, Recorder, EMPTY_PREFIX}; use sp_trie::trie_types::{TrieDBMut, TrieDB}; use super::{SessionIndex, Module as SessionModule}; @@ -67,7 +67,30 @@ decl_storage! { } decl_module! { - pub struct Module for enum Call where origin: T::Origin {} + pub struct Module for enum Call where origin: T::Origin { + fn on_initialize(_n: T::BlockNumber) -> Weight { + CachedObsolete::::remove_all(); + // TODO: determine actual weight + 0 + } + + fn on_runtime_upgrade() -> Weight { + migration::migrate::(); + // TODO: determine actual weight + 0 + } + } +} + +mod migration { + use super::*; + pub fn migrate() { + if let Some((begin, end)) = StoredRange::get() { + for i in begin..end { + HistoricalSessions::::migrate_key_from_blake(i); + } + } + } } impl Module { diff --git a/frame/session/src/lib.rs b/frame/session/src/lib.rs index 47517702cc57a..f41821a3abf11 100644 --- a/frame/session/src/lib.rs +++ b/frame/session/src/lib.rs @@ -114,6 +114,7 @@ use frame_support::{ weights::Weight, }; use frame_system::{self as system, ensure_signed}; +use frame_support::traits::MigrateAccount; #[cfg(test)] mod mock; @@ -559,6 +560,18 @@ decl_module! { } } +impl MigrateAccount for Module { + fn migrate_account(a: &T::AccountId) { + if let Some(v) = T::ValidatorIdOf::convert(a.clone()) { + if let Some(keys) = NextKeys::::migrate_key_from_blake(v) { + for id in T::Keys::key_ids() { + KeyOwner::::migrate_key_from_blake((*id, keys.get_raw(*id))); + } + } + } + } +} + impl Module { /// Move on to next session. Register new validator set and session keys. Changes /// to the validator set have a session of delay to take effect. This allows for diff --git a/frame/session/src/mock.rs b/frame/session/src/mock.rs index e7a9896064844..a7e43d6a11948 100644 --- a/frame/session/src/mock.rs +++ b/frame/session/src/mock.rs @@ -194,7 +194,7 @@ impl frame_system::Trait for Test { type Version = (); type ModuleToIndex = (); type AccountData = (); - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } diff --git a/frame/society/src/lib.rs b/frame/society/src/lib.rs index 122ed06b29119..b329b12ea68e7 100644 --- a/frame/society/src/lib.rs +++ b/frame/society/src/lib.rs @@ -264,7 +264,7 @@ use frame_support::{decl_error, decl_module, decl_storage, decl_event, ensure, d use frame_support::weights::Weight; use frame_support::traits::{ Currency, ReservableCurrency, Randomness, Get, ChangeMembers, BalanceStatus, - ExistenceRequirement::AllowDeath, EnsureOrigin + ExistenceRequirement::AllowDeath, EnsureOrigin, MigrateAccount, }; use frame_system::{self as system, ensure_signed, ensure_root}; @@ -1140,6 +1140,12 @@ decl_event! { } } +impl MigrateAccount for Module { + fn migrate_account(a: &T::AccountId) { + Payouts::::migrate_key_from_blake(a); + } +} + /// Simple ensure origin struct to filter for the founder account. pub struct EnsureFounder(sp_std::marker::PhantomData); impl EnsureOrigin for EnsureFounder { diff --git a/frame/society/src/mock.rs b/frame/society/src/mock.rs index 7ddd25ee6a09b..042c4d3794643 100644 --- a/frame/society/src/mock.rs +++ b/frame/society/src/mock.rs @@ -85,7 +85,7 @@ impl frame_system::Trait for Test { type AvailableBlockRatio = AvailableBlockRatio; type Version = (); type ModuleToIndex = (); - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); type AccountData = pallet_balances::AccountData; } diff --git a/frame/staking/fuzzer/src/mock.rs b/frame/staking/fuzzer/src/mock.rs index 0e3b6cb13fbb7..5da529499c470 100644 --- a/frame/staking/fuzzer/src/mock.rs +++ b/frame/staking/fuzzer/src/mock.rs @@ -78,6 +78,7 @@ impl frame_system::Trait for Test { type Version = (); type ModuleToIndex = (); type AccountData = pallet_balances::AccountData; + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (Balances,); } diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index 4e9a8918c5ad7..1ebae2aca1cae 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -296,7 +296,7 @@ use frame_support::{ dispatch::{IsSubType, DispatchResult, DispatchResultWithPostInfo, WithPostDispatchInfo}, traits::{ Currency, LockIdentifier, LockableCurrency, WithdrawReasons, OnUnbalanced, Imbalance, Get, - UnixTime, EstimateNextNewSession, EnsureOrigin, + UnixTime, EstimateNextNewSession, EnsureOrigin, MigrateAccount, } }; use pallet_session::historical; @@ -1337,6 +1337,12 @@ decl_module! { } } } + + fn on_runtime_upgrade() -> Weight { + migrate::(); + // TODO: determine actual weight + 0 + } fn on_finalize() { // Set the start of the first era. @@ -2207,6 +2213,30 @@ decl_module! { } } +impl MigrateAccount for Module { + fn migrate_account(a: &T::AccountId) { + if let Some(controller) = Bonded::::migrate_key_from_blake(a) { + Ledger::::migrate_key_from_blake(controller); + Payee::::migrate_key_from_blake(a); + Validators::::migrate_key_from_blake(a); + Nominators::::migrate_key_from_blake(a); + SlashingSpans::::migrate_key_from_blake(a); + } + } +} + +fn migrate() { + if let Some(current_era) = CurrentEra::get() { + let history_depth = HistoryDepth::get(); + for era in current_era.saturating_sub(history_depth)..=current_era { + ErasStartSessionIndex::migrate_key_from_blake(era); + ErasValidatorReward::::migrate_key_from_blake(era); + ErasRewardPoints::::migrate_key_from_blake(era); + ErasTotalStake::::migrate_key_from_blake(era); + } + } +} + impl Module { /// The total balance that can be slashed from a stash account as of right now. pub fn slashable_balance_of(stash: &T::AccountId) -> BalanceOf { diff --git a/frame/staking/src/mock.rs b/frame/staking/src/mock.rs index 094ab6375ca0e..bf39173a62d2f 100644 --- a/frame/staking/src/mock.rs +++ b/frame/staking/src/mock.rs @@ -221,6 +221,7 @@ impl frame_system::Trait for Test { type Version = (); type ModuleToIndex = (); type AccountData = pallet_balances::AccountData; + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } diff --git a/frame/sudo/src/mock.rs b/frame/sudo/src/mock.rs index a270787da66ec..b4df4b0bea490 100644 --- a/frame/sudo/src/mock.rs +++ b/frame/sudo/src/mock.rs @@ -142,6 +142,7 @@ impl frame_system::Trait for Test { type Version = (); type ModuleToIndex = (); type AccountData = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } diff --git a/frame/support/src/traits.rs b/frame/support/src/traits.rs index 0b48ac7f410e8..a352b953958c9 100644 --- a/frame/support/src/traits.rs +++ b/frame/support/src/traits.rs @@ -43,6 +43,13 @@ impl Filter for () { fn filter(_: &T) -> bool { true } } +/// Migrate a given account. +#[impl_trait_for_tuples::impl_for_tuples(30)] +pub trait MigrateAccount { + /// Migrate the `account`. + fn migrate_account(account: &A); +} + /// An abstraction of a value stored within storage, but possibly as part of a larger composite /// item. pub trait StoredMap { diff --git a/frame/system/benches/bench.rs b/frame/system/benches/bench.rs index 95b9b88c705fb..9a2364fcb535f 100644 --- a/frame/system/benches/bench.rs +++ b/frame/system/benches/bench.rs @@ -82,7 +82,7 @@ impl system::Trait for Runtime { type Version = (); type ModuleToIndex = (); type AccountData = (); - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } diff --git a/frame/system/benchmarking/src/mock.rs b/frame/system/benchmarking/src/mock.rs index 1e904302e3b9e..a4509f6d03933 100644 --- a/frame/system/benchmarking/src/mock.rs +++ b/frame/system/benchmarking/src/mock.rs @@ -72,6 +72,7 @@ impl frame_system::Trait for Test { type Version = (); type ModuleToIndex = (); type AccountData = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } diff --git a/frame/system/src/accounts.scale b/frame/system/src/accounts.scale new file mode 100644 index 0000000000000..ece43ea3762db --- /dev/null +++ b/frame/system/src/accounts.scale @@ -0,0 +1 @@ +5aւ,XLVm}sc&~%Ra6&GjH \ No newline at end of file diff --git a/frame/system/src/lib.rs b/frame/system/src/lib.rs index 8360f6c4cb46e..02bf5a55364b5 100644 --- a/frame/system/src/lib.rs +++ b/frame/system/src/lib.rs @@ -122,7 +122,7 @@ use frame_support::{ storage, traits::{ Contains, Get, ModuleToIndex, OnNewAccount, OnKilledAccount, IsDeadAccount, Happened, - StoredMap, EnsureOrigin, + StoredMap, EnsureOrigin, MigrateAccount, }, weights::{ Weight, RuntimeDbWeight, DispatchInfo, PostDispatchInfo, DispatchClass, @@ -136,6 +136,7 @@ use codec::{Encode, Decode, FullCodec, EncodeLike}; use sp_io::TestExternalities; pub mod offchain; +pub mod migration; /// Compute the trie root of a list of extrinsics. pub fn extrinsics_root(extrinsics: &[E]) -> H::Output { @@ -245,6 +246,9 @@ pub trait Trait: 'static + Eq + Clone { /// /// All resources should be cleaned up associated with the given account. type OnKilledAccount: OnKilledAccount; + + /// Migrate an account. + type MigrateAccount: MigrateAccount; } pub type DigestOf = generic::Digest<::Hash>; @@ -561,6 +565,17 @@ decl_module! { /// The maximum length of a block (in bytes). const MaximumBlockLength: u32 = T::MaximumBlockLength::get(); + + fn on_runtime_upgrade() -> Weight { + migration::migrate::(); + + // Remove the old `RuntimeUpgraded` storage entry. + let mut runtime_upgraded_key = sp_io::hashing::twox_128(b"System").to_vec(); + runtime_upgraded_key.extend(&sp_io::hashing::twox_128(b"RuntimeUpgraded")); + sp_io::storage::clear(&runtime_upgraded_key); + // TODO: determine actual weight + 0 + } /// A dispatch that will fill the block weight up to the given ratio. // TODO: This should only be available for testing, rather than in general usage, but @@ -748,6 +763,21 @@ decl_module! { ensure!(account.data == T::AccountData::default(), Error::::NonDefaultComposite); Account::::remove(who); } + + #[weight = FunctionOf( + |(accounts,): (&Vec,)| accounts.len() as Weight * 10_000, + DispatchClass::Normal, + Pays::Yes, + )] + fn migrate_accounts(origin, accounts: Vec) { + let _ = ensure_signed(origin)?; + for a in &accounts { + if Account::::migrate_key_from_blake(a).is_some() { + // Inform other modules about the account. + T::MigrateAccount::migrate_account(a); + } + } + } } } @@ -1939,7 +1969,7 @@ pub(crate) mod tests { type Version = Version; type ModuleToIndex = (); type AccountData = u32; - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = RecordKilled; } diff --git a/frame/system/src/migration.rs b/frame/system/src/migration.rs new file mode 100644 index 0000000000000..19db37f875039 --- /dev/null +++ b/frame/system/src/migration.rs @@ -0,0 +1,55 @@ +use super::*; +use frame_support::weights::Weight; +use sp_runtime::traits::SaturatedConversion; + +pub fn migrate() -> Weight{ + migrate_block_hash::() +} + +pub fn migrate_block_hash() -> Weight { + // Number is current block - we obviously don't know that hash. + // Number - 1 is the parent block, who hash we record in this block, but then that's already + // with the new storage so we don't migrate it. + // Number - 2 is therefore the most recent block's hash that needs migrating. + let db = T::DbWeight::get(); + let block_num = Number::::get(); + if block_num > One::one() { + sp_runtime::print("Migrating BlockHashes..."); + BlockHash::::migrate_key_from_blake(T::BlockNumber::zero()); + let mut n = block_num - One::one() - One::one(); + let mut migrations = 1; + while !n.is_zero() { + sp_runtime::print(n.saturated_into::()); + migrations += 1; + if BlockHash::::migrate_key_from_blake(n).is_none() { + break; + } + n -= One::one(); + } + sp_runtime::print("Done BlockHashes"); + db.reads_writes(migrations + 1, migrations) + } else { + sp_runtime::print("No BlockHashes to migrate..."); + db.reads(1) + } +} + +pub fn migrate_accounts() -> Weight { + sp_runtime::print("Migrating Accounts..."); + let mut count = 0u32; + if let Ok(accounts) = Vec::::decode(&mut &include_bytes!("accounts.scale")[..]) { + for a in &accounts { + if Account::::migrate_key_from_blake(a).is_some() { + // Inform other modules about the account. + T::MigrateAccount::migrate_account(a); + count += 1; + if count % 1000 == 0 { + sp_runtime::print(count); + } + } + } + } + sp_runtime::print(count); + sp_runtime::print("Done Accounts."); + T::MaximumBlockWeight::get() +} \ No newline at end of file diff --git a/frame/timestamp/src/lib.rs b/frame/timestamp/src/lib.rs index 6d38919f31b1b..94048cb148e6e 100644 --- a/frame/timestamp/src/lib.rs +++ b/frame/timestamp/src/lib.rs @@ -335,7 +335,7 @@ mod tests { type Version = (); type ModuleToIndex = (); type AccountData = (); - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } parameter_types! { diff --git a/frame/transaction-payment/src/lib.rs b/frame/transaction-payment/src/lib.rs index c52d698756684..c38d9545471e7 100644 --- a/frame/transaction-payment/src/lib.rs +++ b/frame/transaction-payment/src/lib.rs @@ -56,6 +56,8 @@ use sp_runtime::{ }; use pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo; +mod migration; + type Multiplier = Fixed128; type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; @@ -101,6 +103,10 @@ decl_module! { *fm = T::FeeMultiplierUpdate::convert(*fm); }); } + + fn on_runtime_upgrade() -> Weight { + migration::on_runtime_upgrade::() + } } } @@ -404,7 +410,7 @@ mod tests { type Version = (); type ModuleToIndex = (); type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } diff --git a/frame/transaction-payment/src/migration.rs b/frame/transaction-payment/src/migration.rs new file mode 100644 index 0000000000000..fd7e5cfc34f5d --- /dev/null +++ b/frame/transaction-payment/src/migration.rs @@ -0,0 +1,55 @@ +// Copyright 2020 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Migration code to update storage. + +use super::*; +use frame_support::storage::migration::{put_storage_value, take_storage_value}; +use frame_support::weights::Weight; +use sp_runtime::Fixed64; + +type OldMultiplier = Fixed64; + +pub fn on_runtime_upgrade() -> Weight { + rename_and_convert::() +} + +// Change the storage name used by this pallet from `Balances` to `TransactionPayment`. +// +// Since the format of the storage items themselves have not changed, we do not +// need to keep track of a storage version. If the runtime does not need to be +// upgraded, nothing here will happen anyway. + +fn rename_and_convert() -> Weight { + sp_runtime::print("Migrating Transaction Payment."); + + let mut reads = 0; + let mut writes = 0; + if let Some(next_fee_multiplier) = + take_storage_value::(b"Balances", b"NextFeeMultiplier", &[]) + { + let raw_multiplier = next_fee_multiplier.into_inner() as i128; + // Fixed64 used 10^9 precision, where Fixed128 uses 10^18, so we need to add 9 zeros. + let new_raw_multiplier: i128 = raw_multiplier.saturating_mul(1_000_000_000); + let mult = Multiplier::from(new_raw_multiplier); + put_storage_value(b"TransactionPayment", b"NextFeeMultiplier", &[], mult); + writes += 2; + } + reads += 1; + + sp_runtime::print("Done Transaction Payment."); + T::DbWeight::get().reads_writes(reads, writes) +} diff --git a/frame/treasury/src/lib.rs b/frame/treasury/src/lib.rs index d1fed8fa2860a..62555adffe357 100644 --- a/frame/treasury/src/lib.rs +++ b/frame/treasury/src/lib.rs @@ -290,6 +290,16 @@ decl_error! { } } +mod migration { + use super::*; + pub fn migrate() { + for i in 0..ProposalCount::get() { + Proposals::::migrate_key_from_blake(i); + } + Reasons::::remove_all(); + } +} + decl_module! { pub struct Module for enum Call where origin: T::Origin { /// Fraction of a proposal's value that should be bonded in order to place the proposal. @@ -324,6 +334,12 @@ decl_module! { fn deposit_event() = default; + fn on_runtime_upgrade() -> Weight { + migration::migrate::(); + // TODO: determine actual weight + 0 + } + /// Put forward a suggestion for spending. A deposit proportional to the value /// is reserved and slashed if the proposal is rejected. It is returned once the /// proposal is awarded. diff --git a/frame/treasury/src/tests.rs b/frame/treasury/src/tests.rs index 0b68c51a1080c..95303b9241cf0 100644 --- a/frame/treasury/src/tests.rs +++ b/frame/treasury/src/tests.rs @@ -81,6 +81,7 @@ impl frame_system::Trait for Test { type Version = (); type ModuleToIndex = (); type AccountData = pallet_balances::AccountData; + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } diff --git a/frame/utility/src/tests.rs b/frame/utility/src/tests.rs index daf3d6c53ade3..892f738bc9d4b 100644 --- a/frame/utility/src/tests.rs +++ b/frame/utility/src/tests.rs @@ -81,6 +81,7 @@ impl frame_system::Trait for Test { type Version = (); type ModuleToIndex = (); type AccountData = pallet_balances::AccountData; + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } diff --git a/frame/vesting/src/lib.rs b/frame/vesting/src/lib.rs index 371fdca69188e..4bb1e49c5b867 100644 --- a/frame/vesting/src/lib.rs +++ b/frame/vesting/src/lib.rs @@ -56,7 +56,7 @@ use sp_runtime::{DispatchResult, RuntimeDebug, traits::{ use frame_support::{decl_module, decl_event, decl_storage, decl_error, ensure}; use frame_support::traits::{ Currency, LockableCurrency, VestingSchedule, WithdrawReason, LockIdentifier, - ExistenceRequirement, Get + ExistenceRequirement, Get, MigrateAccount, }; use frame_system::{self as system, ensure_signed}; @@ -230,7 +230,7 @@ decl_module! { Self::update_lock(T::Lookup::lookup(target)?) } - /// Create a vested transfer. + /// Create a vested transfer. /// /// The dispatch origin for this call must be _Signed_. /// @@ -259,17 +259,23 @@ decl_module! { let who = T::Lookup::lookup(target)?; ensure!(!Vesting::::contains_key(&who), Error::::ExistingVestingSchedule); - + T::Currency::transfer(&transactor, &who, schedule.locked, ExistenceRequirement::AllowDeath)?; Self::add_vesting_schedule(&who, schedule.locked, schedule.per_block, schedule.starting_block) .expect("user does not have an existing vesting schedule; q.e.d."); - + Ok(()) } } } +impl MigrateAccount for Module { + fn migrate_account(a: &T::AccountId) { + Vesting::::migrate_key_from_blake(a); + } +} + impl Module { /// (Re)set or remove the module's currency lock on `who`'s account in accordance with their /// current unvested amount. @@ -402,7 +408,7 @@ mod tests { type Version = (); type ModuleToIndex = (); type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); } impl pallet_balances::Trait for Test { diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index eaceef2defb49..7e6c7774aab51 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -420,7 +420,7 @@ impl frame_system::Trait for Runtime { type Version = (); type ModuleToIndex = (); type AccountData = (); - type OnNewAccount = (); + type MigrateAccount = (); type OnNewAccount = (); type OnKilledAccount = (); }