Skip to content

Commit 7faf8c3

Browse files
committed
accounts migration
1 parent a354d02 commit 7faf8c3

File tree

1 file changed

+124
-7
lines changed

1 file changed

+124
-7
lines changed

runtime/src/lib.rs

Lines changed: 124 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,17 @@
66
#[cfg(feature = "std")]
77
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
88

9-
use codec::Encode;
9+
use codec::{Decode, Encode};
1010

1111
use pallet_commitments::CanCommit;
1212
use pallet_grandpa::{
1313
fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList,
1414
};
1515

16-
use frame_support::pallet_prelude::{DispatchError, DispatchResult, Get};
16+
use frame_support::{
17+
pallet_prelude::{DispatchError, DispatchResult, Get},
18+
traits::OnRuntimeUpgrade,
19+
};
1720
use frame_system::{EnsureNever, EnsureRoot, RawOrigin};
1821

1922
use pallet_registry::CanRegisterIdentity;
@@ -263,7 +266,7 @@ pub const EXISTENTIAL_DEPOSIT: u64 = 500;
263266

264267
impl pallet_balances::Config for Runtime {
265268
type MaxLocks = ConstU32<50>;
266-
type MaxReserves = ();
269+
type MaxReserves = ConstU32<50>;
267270
type ReserveIdentifier = [u8; 8];
268271
// The type for recording an account's balance.
269272
type Balance = Balance;
@@ -274,10 +277,10 @@ impl pallet_balances::Config for Runtime {
274277
type AccountStore = System;
275278
type WeightInfo = pallet_balances::weights::SubstrateWeight<Runtime>;
276279

277-
type RuntimeHoldReason = ();
278-
type FreezeIdentifier = ();
279-
type MaxHolds = ();
280-
type MaxFreezes = ();
280+
type RuntimeHoldReason = RuntimeHoldReason;
281+
type FreezeIdentifier = RuntimeFreezeReason;
282+
type MaxHolds = ConstU32<50>;
283+
type MaxFreezes = ConstU32<50>;
281284
}
282285

283286
pub struct LinearWeightToFee<C>(sp_std::marker::PhantomData<C>);
@@ -1017,6 +1020,119 @@ pub type SignedExtra = (
10171020
pallet_commitments::CommitmentsSignedExtension<Runtime>,
10181021
);
10191022

1023+
mod account_data_migration {
1024+
use super::*;
1025+
use frame_support::log;
1026+
use pallet_balances::ExtraFlags;
1027+
1028+
mod prev {
1029+
use super::*;
1030+
use frame_support::{pallet_prelude::ValueQuery, storage_alias, Blake2_128Concat};
1031+
1032+
#[derive(Encode, Decode, Clone, PartialEq, Eq, Default, Debug)]
1033+
pub struct AccountData<Balance> {
1034+
pub free: Balance,
1035+
pub reserved: Balance,
1036+
pub misc_frozen: Balance,
1037+
pub fee_frozen: Balance,
1038+
}
1039+
1040+
#[storage_alias]
1041+
pub type Account<T: frame_system::pallet::Config> = StorageMap<
1042+
frame_system::pallet::Pallet<T>,
1043+
Blake2_128Concat,
1044+
AccountId,
1045+
AccountData<Balance>,
1046+
ValueQuery,
1047+
>;
1048+
}
1049+
1050+
const TARGET: &'static str = "runtime::account_data_migration";
1051+
pub struct Migration;
1052+
impl OnRuntimeUpgrade for Migration {
1053+
/// Save pre-upgrade account ids to check are decodable post-upgrade.
1054+
#[cfg(feature = "try-runtime")]
1055+
fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
1056+
let account_ids = prev::Account::<Runtime>::iter_keys().collect::<Vec<_>>();
1057+
log::info!(target: TARGET, "pre-upgrade");
1058+
1059+
Ok(account_ids.encode())
1060+
}
1061+
1062+
/// Ensures post-upgrade that
1063+
/// 1. Number of accounts has not changed.
1064+
/// 2. Each account exists in storage and decodes.
1065+
/// 3. Each account has a provider val >0.
1066+
#[cfg(feature = "try-runtime")]
1067+
fn post_upgrade(state: Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
1068+
use frame_support::ensure;
1069+
log::info!(target: TARGET, "Running post-upgrade...");
1070+
1071+
let pre_upgrade_account_ids: Vec<<Runtime as frame_system::Config>::AccountId> =
1072+
Decode::decode(&mut &state[..]).expect("pre_upgrade provides a valid state; qed");
1073+
1074+
// Ensure number of accounts has not changed.
1075+
let account_ids = prev::Account::<Runtime>::iter_keys().collect::<Vec<_>>();
1076+
ensure!(
1077+
pre_upgrade_account_ids.len() == account_ids.len(),
1078+
"number of accounts has changed"
1079+
);
1080+
1081+
for acc in account_ids {
1082+
// Ensure account exists in storage and decodes.
1083+
ensure!(
1084+
frame_system::pallet::Account::<Runtime>::try_get(&acc).is_ok(),
1085+
"account not found"
1086+
);
1087+
1088+
// Ensure account provider is >0.
1089+
ensure!(
1090+
frame_system::Pallet::<Runtime>::providers(&acc) > 0,
1091+
"provider == 0"
1092+
);
1093+
}
1094+
1095+
log::info!(target: TARGET, "post-upgrade success ✅");
1096+
Ok(())
1097+
}
1098+
1099+
/// Migrates AccountData storage to the new format, bumping providers where required.
1100+
fn on_runtime_upgrade() -> Weight {
1101+
// Pull the storage in the previous format into memory
1102+
let accounts = prev::Account::<Runtime>::iter().collect::<Vec<_>>();
1103+
log::info!(target: TARGET, "Migrating {} accounts...", accounts.len());
1104+
1105+
for (acc, data) in accounts.clone().into_iter() {
1106+
// Move account to new data format
1107+
let new_data = pallet_balances::AccountData {
1108+
free: data.free,
1109+
reserved: data.reserved,
1110+
frozen: data.misc_frozen.saturating_add(data.fee_frozen),
1111+
flags: ExtraFlags::old_logic(),
1112+
};
1113+
frame_system::pallet::Account::<Runtime>::mutate(acc.clone(), |a| {
1114+
a.data = new_data;
1115+
});
1116+
1117+
// Ensure provider
1118+
if frame_system::Pallet::<Runtime>::providers(&acc) == 0 {
1119+
frame_system::Pallet::<Runtime>::inc_providers(&acc);
1120+
}
1121+
1122+
// Ensure upgraded
1123+
pallet_balances::Pallet::<Runtime, ()>::ensure_upgraded(&acc);
1124+
}
1125+
1126+
log::info!(target: TARGET, "Migrated ✅");
1127+
1128+
// R/W not important for solo chain.
1129+
return <Runtime as frame_system::Config>::DbWeight::get().reads_writes(0u64, 0u64);
1130+
}
1131+
}
1132+
}
1133+
1134+
type Migrations = account_data_migration::Migration;
1135+
10201136
// Unchecked extrinsic type as expected by this runtime.
10211137
pub type UncheckedExtrinsic =
10221138
generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, SignedExtra>;
@@ -1029,6 +1145,7 @@ pub type Executive = frame_executive::Executive<
10291145
frame_system::ChainContext<Runtime>,
10301146
Runtime,
10311147
AllPalletsWithSystem,
1148+
Migrations,
10321149
>;
10331150

10341151
#[cfg(feature = "runtime-benchmarks")]

0 commit comments

Comments
 (0)