Skip to content

Commit eb88717

Browse files
committed
add OrmlVestingStorageMigration
1 parent c2b3484 commit eb88717

File tree

5 files changed

+216
-20
lines changed

5 files changed

+216
-20
lines changed

runtime/heiko/Cargo.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ sp-session = { git = 'https://github.com/parityt
5656
sp-std = { git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.11', default-features = false }
5757
sp-transaction-pool = { git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.11', default-features = false }
5858
sp-version = { git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.11', default-features = false }
59+
sp-io = { git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.11', default-features = false }
5960

6061
# Polkadot dependencies
6162
pallet-xcm = { git = 'https://github.com/paritytech/polkadot.git', branch = 'release-v0.9.11', default-features = false }
@@ -102,9 +103,6 @@ primitives = { package = 'parallel-primitives', path = '../../
102103
branch = 'polkadot-v0.9.11'
103104
git = 'https://github.com/paritytech/substrate.git'
104105

105-
[dev-dependencies]
106-
sp-io = { git = 'https://github.com/paritytech/substrate.git', branch = 'polkadot-v0.9.11', default-features = false }
107-
108106
[features]
109107
default = ['std']
110108
runtime-benchmarks = [
@@ -132,6 +130,7 @@ std = [
132130
'sp-api/std',
133131
'sp-std/std',
134132
'sp-core/std',
133+
'sp-io/std',
135134
'sp-runtime/std',
136135
'sp-version/std',
137136
'sp-offchain/std',

runtime/heiko/src/lib.rs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ use xcm_executor::{Config, XcmExecutor};
7575

7676
pub mod constants;
7777
pub mod impls;
78+
mod vesting_migration;
7879
// A few exports that help ease life for downstream crates.
7980
// re-exports
8081
pub use constants::{currency, fee, time};
@@ -130,7 +131,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
130131
spec_name: create_runtime_str!("heiko"),
131132
impl_name: create_runtime_str!("heiko"),
132133
authoring_version: 1,
133-
spec_version: 172,
134+
spec_version: 173,
134135
impl_version: 20,
135136
apis: RUNTIME_API_VERSIONS,
136137
transaction_version: 2,
@@ -1386,14 +1387,25 @@ pub type Executive = frame_executive::Executive<
13861387
frame_system::ChainContext<Runtime>,
13871388
Runtime,
13881389
AllPallets,
1389-
SetSafeXcmVersion,
1390+
OrmlVestingStorageMigration,
13901391
>;
13911392

1392-
pub struct SetSafeXcmVersion;
1393-
impl OnRuntimeUpgrade for SetSafeXcmVersion {
1394-
fn on_runtime_upgrade() -> u64 {
1395-
let _ = PolkadotXcm::force_default_xcm_version(Origin::root(), Some(2));
1396-
RocksDbWeight::get().writes(1)
1393+
pub struct OrmlVestingStorageMigration;
1394+
impl OnRuntimeUpgrade for OrmlVestingStorageMigration {
1395+
fn on_runtime_upgrade() -> frame_support::weights::Weight {
1396+
vesting_migration::migrate::<Runtime>()
1397+
}
1398+
1399+
#[cfg(feature = "try-runtime")]
1400+
fn pre_upgrade() -> Result<(), &'static str> {
1401+
vesting_migration::pre_migrate::<Runtime>();
1402+
Ok(())
1403+
}
1404+
1405+
#[cfg(feature = "try-runtime")]
1406+
fn post_upgrade() -> Result<(), &'static str> {
1407+
vesting_migration::post_migrate::<Runtime>();
1408+
Ok(())
13971409
}
13981410
}
13991411

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
use codec::{Decode, Encode};
2+
use frame_support::{
3+
log,
4+
storage::{unhashed, StoragePrefixedMap},
5+
traits::{Currency, Get},
6+
weights::Weight,
7+
BoundedVec,
8+
};
9+
use sp_runtime::traits::CheckedDiv;
10+
pub(crate) type BalanceOf<T> = <<T as orml_vesting::Config>::Currency as Currency<
11+
<T as frame_system::Config>::AccountId,
12+
>>::Balance;
13+
pub(crate) type VestingScheduleOf<T> =
14+
orml_vesting::VestingSchedule<<T as frame_system::Config>::BlockNumber, BalanceOf<T>>;
15+
16+
const OLD_START: u32 = 231619;
17+
const OLD_PERIOD_COUNT: u32 = 2628000;
18+
19+
const NEW_START: u32 = 0;
20+
const NEW_PERIOD: u32 = 1;
21+
const NEW_PERIOD_COUNT: u32 = 2160000;
22+
// total_update_schedules include 10731 items, plan to do two times' runtime upgrade
23+
const MIGRATION_LIMIT: u32 = 5500;
24+
25+
pub fn migrate<T: orml_vesting::Config>() -> Weight {
26+
translate_values::<T, BoundedVec<VestingScheduleOf<T>, T::MaxVestingSchedules>, _>(|v| {
27+
let mut new_v = BoundedVec::default();
28+
v.iter().for_each(|vesting_schedule| {
29+
update_schedule::<T>(vesting_schedule)
30+
.and_then(|new_schedule| new_v.try_push(new_schedule).ok());
31+
});
32+
if !new_v.is_empty() && !new_v.len().eq(&v.len()) {
33+
log::warn!(target: "runtime::orml_vesting", "new schedule is not equal to old");
34+
return None;
35+
}
36+
if !new_v.is_empty() {
37+
return Some(new_v);
38+
}
39+
None
40+
});
41+
<T as frame_system::Config>::BlockWeights::get().max_block
42+
}
43+
44+
// https://github.com/paritytech/substrate/blob/polkadot-v0.9.12/frame/support/src/storage/mod.rs#L1168-L1188
45+
fn translate_values<
46+
T: orml_vesting::Config,
47+
Value: Decode + Encode,
48+
F: FnMut(Value) -> Option<Value>,
49+
>(
50+
mut f: F,
51+
) {
52+
log::info!(target: "runtime::orml_vesting", "migrate orml_vesting schedule");
53+
let mut count_write = 0u32;
54+
let mut count_read = 0u32;
55+
let prefix = orml_vesting::VestingSchedules::<T>::final_prefix();
56+
let mut previous_key = prefix.clone().to_vec();
57+
while let Some(next) =
58+
sp_io::storage::next_key(&previous_key).filter(|n| n.starts_with(&prefix))
59+
{
60+
if count_write.eq(&MIGRATION_LIMIT) {
61+
// Avoid terminate block production, so migrate the two within two runtime upgrade
62+
// refer to https://github.com/paritytech/substrate/issues/10407
63+
break;
64+
}
65+
count_read += 1;
66+
previous_key = next;
67+
let maybe_value = unhashed::get::<Value>(&previous_key);
68+
match maybe_value {
69+
Some(value) => match f(value) {
70+
Some(new) => {
71+
unhashed::put::<Value>(&previous_key, &new);
72+
count_write += 1;
73+
}
74+
None => continue,
75+
},
76+
None => {
77+
log::error!("old key failed to decode at {:?}", previous_key);
78+
continue;
79+
}
80+
}
81+
}
82+
log::info!(
83+
target: "runtime::orml_vesting",
84+
"count_read: {}, count_write: {}",
85+
count_read, count_write
86+
);
87+
}
88+
89+
fn update_schedule<T: orml_vesting::Config>(
90+
vesting_schedule: &VestingScheduleOf<T>,
91+
) -> Option<VestingScheduleOf<T>> {
92+
if !vesting_schedule.start.eq(&OLD_START.into())
93+
|| !vesting_schedule.period_count.eq(&OLD_PERIOD_COUNT)
94+
{
95+
return None;
96+
}
97+
98+
vesting_schedule
99+
.total_amount()
100+
.and_then(|total| total.checked_div(&NEW_PERIOD_COUNT.into()))
101+
.and_then(|per_period| {
102+
Some(VestingScheduleOf::<T> {
103+
start: NEW_START.into(),
104+
period: NEW_PERIOD.into(),
105+
period_count: NEW_PERIOD_COUNT,
106+
per_period,
107+
})
108+
})
109+
}
110+
111+
/// Some checks prior to migration. This can be linked to
112+
/// [`frame_support::traits::OnRuntimeUpgrade::pre_upgrade`] for further testing.
113+
///
114+
/// Panics if anything goes wrong.
115+
#[cfg(feature = "try-runtime")]
116+
pub fn pre_migrate<T: frame_system::Config + orml_vesting::Config>()
117+
where
118+
u128: From<BalanceOf<T>>,
119+
{
120+
let mut count_total = 0u64;
121+
let mut count_one = 0u64;
122+
let mut count_two = 0u64;
123+
let mut count_more = 0u64;
124+
let mut count_need_update = 0u64;
125+
let mut total_amount: BalanceOf<T> = 0u32.into();
126+
orml_vesting::VestingSchedules::<T>::iter().for_each(|(_k, v)| {
127+
count_total += 1;
128+
let length = v.len();
129+
if length == 1 {
130+
count_one += 1;
131+
} else if length == 2 {
132+
count_two += 1;
133+
} else if length > 2 {
134+
count_more += 1;
135+
}
136+
v.iter().for_each(|s| {
137+
if s.start.eq(&OLD_START.into()) && s.period_count.eq(&OLD_PERIOD_COUNT) {
138+
count_need_update += 1;
139+
}
140+
total_amount += s.per_period * s.period_count.into();
141+
});
142+
});
143+
144+
// total accounts: 10680, one schedule: 10628, two schedule: 52, more schedule: 0, schedule need update: 10731, total_amount: 31450977794836396000
145+
log::info!(
146+
target: "runtime::orml_vesting",
147+
"{}, total accounts: {}, one schedule: {}, two schedule: {}, more schedule: {}, schedule need update: {}, total_amount: {:?}",
148+
"pre-migration", count_total, count_one, count_two, count_more, count_need_update,total_amount
149+
);
150+
}
151+
152+
/// Some checks for after migration. This can be linked to
153+
/// [`frame_support::traits::OnRuntimeUpgrade::post_upgrade`] for further testing.
154+
///
155+
/// Panics if anything goes wrong.
156+
#[cfg(feature = "try-runtime")]
157+
pub fn post_migrate<T: frame_system::Config + orml_vesting::Config>()
158+
where
159+
u128: From<BalanceOf<T>>,
160+
{
161+
let mut count_total = 0u64;
162+
let mut count_one = 0u64;
163+
let mut count_two = 0u64;
164+
let mut count_more = 0u64;
165+
let mut count_success_update = 0u64;
166+
let mut total_amount: BalanceOf<T> = 0u32.into();
167+
orml_vesting::VestingSchedules::<T>::iter().for_each(|(_k, v)| {
168+
count_total += 1;
169+
let length = v.len();
170+
if length == 1 {
171+
count_one += 1;
172+
} else if length == 2 {
173+
count_two += 1;
174+
} else if length > 2 {
175+
count_more += 1;
176+
}
177+
v.iter().for_each(|s| {
178+
if s.start.eq(&NEW_START.into()) && s.period_count.eq(&NEW_PERIOD_COUNT) {
179+
count_success_update += 1;
180+
}
181+
total_amount += s.per_period * s.period_count.into();
182+
});
183+
});
184+
185+
// total accounts: 10680, one schedule: 10628, two schedule: 52, more schedule: 0, schedule success update: 10731, total_amount: 31450977784297360000
186+
log::info!(
187+
target: "runtime::orml_vesting",
188+
"{}, total accounts: {}, one schedule: {}, two schedule: {}, more schedule: {}, schedule success update: {}, total_amount: {:?}",
189+
"post-migration", count_total, count_one, count_two, count_more, count_success_update, total_amount
190+
);
191+
}

runtime/parallel/src/lib.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,7 @@ use sp_core::{
3939
};
4040
use sp_runtime::{
4141
create_runtime_str, generic, impl_opaque_keys,
42-
traits::{
43-
self, AccountIdConversion, AccountIdLookup, BlakeTwo256, Block as BlockT,
44-
BlockNumberProvider, Convert,
45-
},
42+
traits::{self, AccountIdConversion, AccountIdLookup, BlakeTwo256, Block as BlockT, Convert},
4643
transaction_validity::{TransactionSource, TransactionValidity},
4744
ApplyExtrinsicResult, DispatchError, KeyTypeId, Perbill, Permill, RuntimeDebug,
4845
SaturatedConversion,
@@ -131,7 +128,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
131128
spec_name: create_runtime_str!("parallel"),
132129
impl_name: create_runtime_str!("parallel"),
133130
authoring_version: 1,
134-
spec_version: 172,
131+
spec_version: 173,
135132
impl_version: 20,
136133
apis: RUNTIME_API_VERSIONS,
137134
transaction_version: 2,

runtime/vanilla/src/lib.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,7 @@ use sp_core::{
5454
};
5555
use sp_runtime::{
5656
create_runtime_str, generic, impl_opaque_keys,
57-
traits::{
58-
self, AccountIdConversion, AccountIdLookup, BlakeTwo256, Block as BlockT,
59-
BlockNumberProvider, Convert,
60-
},
57+
traits::{self, AccountIdConversion, AccountIdLookup, BlakeTwo256, Block as BlockT, Convert},
6158
transaction_validity::{TransactionSource, TransactionValidity},
6259
ApplyExtrinsicResult, DispatchError, KeyTypeId, Perbill, Permill, RuntimeDebug,
6360
SaturatedConversion,
@@ -131,7 +128,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
131128
spec_name: create_runtime_str!("vanilla"),
132129
impl_name: create_runtime_str!("vanilla"),
133130
authoring_version: 1,
134-
spec_version: 172,
131+
spec_version: 173,
135132
impl_version: 20,
136133
apis: RUNTIME_API_VERSIONS,
137134
transaction_version: 2,

0 commit comments

Comments
 (0)