1use super::*;
21use frame_support::{
22 migrations::VersionedMigration,
23 pallet_prelude::ValueQuery,
24 storage_alias,
25 traits::{GetStorageVersion, OnRuntimeUpgrade, UncheckedOnRuntimeUpgrade},
26};
27
28#[cfg(feature = "try-runtime")]
29use sp_runtime::TryRuntimeError;
30
31#[derive(Encode, Decode, Clone, Copy, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
35enum ObsoleteReleases {
36 V5_0_0, V6_0_0, V7_0_0, V8_0_0, V9_0_0, V10_0_0, V11_0_0, V12_0_0, }
45
46impl Default for ObsoleteReleases {
47 fn default() -> Self {
48 ObsoleteReleases::V12_0_0
49 }
50}
51
52#[storage_alias]
54type StorageVersion<T: Config> = StorageValue<Pallet<T>, ObsoleteReleases, ValueQuery>;
55
56pub mod v17 {
58 use super::*;
59
60 #[frame_support::storage_alias]
61 pub type DisabledValidators<T: Config> =
62 StorageValue<Pallet<T>, BoundedVec<(u32, OffenceSeverity), ConstU32<333>>, ValueQuery>;
63
64 pub struct MigrateDisabledToSession<T>(core::marker::PhantomData<T>);
65 impl<T: Config> pallet_session::migrations::v1::MigrateDisabledValidators
66 for MigrateDisabledToSession<T>
67 {
68 #[cfg(feature = "try-runtime")]
69 fn peek_disabled() -> Vec<(u32, OffenceSeverity)> {
70 DisabledValidators::<T>::get().into()
71 }
72
73 fn take_disabled() -> Vec<(u32, OffenceSeverity)> {
74 DisabledValidators::<T>::take().into()
75 }
76 }
77}
78
79pub mod v16 {
82 use super::*;
83 use sp_staking::offence::OffenceSeverity;
84
85 #[frame_support::storage_alias]
86 pub(crate) type DisabledValidators<T: Config> =
87 StorageValue<Pallet<T>, Vec<(u32, OffenceSeverity)>, ValueQuery>;
88
89 pub struct VersionUncheckedMigrateV15ToV16<T>(core::marker::PhantomData<T>);
90 impl<T: Config> UncheckedOnRuntimeUpgrade for VersionUncheckedMigrateV15ToV16<T> {
91 #[cfg(feature = "try-runtime")]
92 fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
93 let old_disabled_validators = v15::DisabledValidators::<T>::get();
94 Ok(old_disabled_validators.encode())
95 }
96
97 fn on_runtime_upgrade() -> Weight {
98 let max_offence = OffenceSeverity(Perbill::from_percent(100));
103 let migrated = v15::DisabledValidators::<T>::take()
105 .into_iter()
106 .map(|v| (v, max_offence))
107 .collect::<Vec<_>>();
108
109 v16::DisabledValidators::<T>::set(migrated);
110
111 log!(info, "v16 applied successfully.");
112 T::DbWeight::get().reads_writes(1, 1)
113 }
114
115 #[cfg(feature = "try-runtime")]
116 fn post_upgrade(state: Vec<u8>) -> Result<(), TryRuntimeError> {
117 let old_disabled_validators =
119 Vec::<u32>::decode(&mut state.as_slice()).expect("Failed to decode state");
120 let new_disabled_validators = v17::DisabledValidators::<T>::get();
121
122 frame_support::ensure!(
124 old_disabled_validators.len() == new_disabled_validators.len(),
125 "DisabledValidators length mismatch"
126 );
127
128 let new_disabled_validators =
130 new_disabled_validators.into_iter().map(|(v, _)| v).collect::<Vec<_>>();
131 frame_support::ensure!(
132 old_disabled_validators == new_disabled_validators,
133 "DisabledValidator ids mismatch"
134 );
135
136 let max_severity = OffenceSeverity(Perbill::from_percent(100));
138 let new_disabled_validators = v17::DisabledValidators::<T>::get();
139 for (_, severity) in new_disabled_validators {
140 frame_support::ensure!(severity == max_severity, "Severity mismatch");
141 }
142
143 Ok(())
144 }
145 }
146
147 pub type MigrateV15ToV16<T> = VersionedMigration<
148 15,
149 16,
150 VersionUncheckedMigrateV15ToV16<T>,
151 Pallet<T>,
152 <T as frame_system::Config>::DbWeight,
153 >;
154}
155
156pub mod v15 {
158 use super::*;
159
160 type DefaultDisablingStrategy = pallet_session::disabling::UpToLimitDisablingStrategy;
162
163 #[storage_alias]
164 pub(crate) type DisabledValidators<T: Config> = StorageValue<Pallet<T>, Vec<u32>, ValueQuery>;
165
166 pub struct VersionUncheckedMigrateV14ToV15<T>(core::marker::PhantomData<T>);
167 impl<T: Config> UncheckedOnRuntimeUpgrade for VersionUncheckedMigrateV14ToV15<T> {
168 fn on_runtime_upgrade() -> Weight {
169 let mut migrated = v14::OffendingValidators::<T>::take()
170 .into_iter()
171 .filter(|p| p.1) .map(|p| p.0)
173 .collect::<Vec<_>>();
174
175 migrated.truncate(DefaultDisablingStrategy::disable_limit(
177 T::SessionInterface::validators().len(),
178 ));
179
180 DisabledValidators::<T>::set(migrated);
181
182 log!(info, "v15 applied successfully.");
183 T::DbWeight::get().reads_writes(1, 1)
184 }
185
186 #[cfg(feature = "try-runtime")]
187 fn post_upgrade(_state: Vec<u8>) -> Result<(), TryRuntimeError> {
188 frame_support::ensure!(
189 v14::OffendingValidators::<T>::decode_len().is_none(),
190 "OffendingValidators is not empty after the migration"
191 );
192 Ok(())
193 }
194 }
195
196 pub type MigrateV14ToV15<T> = VersionedMigration<
197 14,
198 15,
199 VersionUncheckedMigrateV14ToV15<T>,
200 Pallet<T>,
201 <T as frame_system::Config>::DbWeight,
202 >;
203}
204
205pub mod v14 {
208 use super::*;
209
210 #[frame_support::storage_alias]
211 pub(crate) type OffendingValidators<T: Config> =
212 StorageValue<Pallet<T>, Vec<(u32, bool)>, ValueQuery>;
213
214 pub struct MigrateToV14<T>(core::marker::PhantomData<T>);
215 impl<T: Config> OnRuntimeUpgrade for MigrateToV14<T> {
216 fn on_runtime_upgrade() -> Weight {
217 let in_code = Pallet::<T>::in_code_storage_version();
218 let on_chain = Pallet::<T>::on_chain_storage_version();
219
220 if in_code == 14 && on_chain == 13 {
221 in_code.put::<Pallet<T>>();
222
223 log!(info, "staking v14 applied successfully.");
224 T::DbWeight::get().reads_writes(1, 1)
225 } else {
226 log!(warn, "staking v14 not applied.");
227 T::DbWeight::get().reads(1)
228 }
229 }
230
231 #[cfg(feature = "try-runtime")]
232 fn post_upgrade(_state: Vec<u8>) -> Result<(), TryRuntimeError> {
233 frame_support::ensure!(
234 Pallet::<T>::on_chain_storage_version() >= 14,
235 "v14 not applied"
236 );
237 Ok(())
238 }
239 }
240}
241
242pub mod v13 {
243 use super::*;
244
245 pub struct MigrateToV13<T>(core::marker::PhantomData<T>);
246 impl<T: Config> OnRuntimeUpgrade for MigrateToV13<T> {
247 #[cfg(feature = "try-runtime")]
248 fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
249 frame_support::ensure!(
250 StorageVersion::<T>::get() == ObsoleteReleases::V12_0_0,
251 "Required v12 before upgrading to v13"
252 );
253
254 Ok(Default::default())
255 }
256
257 fn on_runtime_upgrade() -> Weight {
258 let in_code = Pallet::<T>::in_code_storage_version();
259 let onchain = StorageVersion::<T>::get();
260
261 if in_code == 13 && onchain == ObsoleteReleases::V12_0_0 {
262 StorageVersion::<T>::kill();
263 in_code.put::<Pallet<T>>();
264
265 log!(info, "v13 applied successfully");
266 T::DbWeight::get().reads_writes(1, 2)
267 } else {
268 log!(warn, "Skipping v13, should be removed");
269 T::DbWeight::get().reads(1)
270 }
271 }
272
273 #[cfg(feature = "try-runtime")]
274 fn post_upgrade(_state: Vec<u8>) -> Result<(), TryRuntimeError> {
275 frame_support::ensure!(
276 Pallet::<T>::on_chain_storage_version() == 13,
277 "v13 not applied"
278 );
279
280 frame_support::ensure!(
281 !StorageVersion::<T>::exists(),
282 "Storage version not migrated correctly"
283 );
284
285 Ok(())
286 }
287 }
288}
289
290pub mod v12 {
291 use super::*;
292 use frame_support::{pallet_prelude::ValueQuery, storage_alias};
293
294 #[storage_alias]
295 type HistoryDepth<T: Config> = StorageValue<Pallet<T>, u32, ValueQuery>;
296
297 pub struct MigrateToV12<T>(core::marker::PhantomData<T>);
302 impl<T: Config> OnRuntimeUpgrade for MigrateToV12<T> {
303 #[cfg(feature = "try-runtime")]
304 fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
305 frame_support::ensure!(
306 StorageVersion::<T>::get() == ObsoleteReleases::V11_0_0,
307 "Expected v11 before upgrading to v12"
308 );
309
310 if HistoryDepth::<T>::exists() {
311 frame_support::ensure!(
312 T::HistoryDepth::get() == HistoryDepth::<T>::get(),
313 "Provided value of HistoryDepth should be same as the existing storage value"
314 );
315 } else {
316 log::info!("No HistoryDepth in storage; nothing to remove");
317 }
318
319 Ok(Default::default())
320 }
321
322 fn on_runtime_upgrade() -> frame_support::weights::Weight {
323 if StorageVersion::<T>::get() == ObsoleteReleases::V11_0_0 {
324 HistoryDepth::<T>::kill();
325 StorageVersion::<T>::put(ObsoleteReleases::V12_0_0);
326
327 log!(info, "v12 applied successfully");
328 T::DbWeight::get().reads_writes(1, 2)
329 } else {
330 log!(warn, "Skipping v12, should be removed");
331 T::DbWeight::get().reads(1)
332 }
333 }
334
335 #[cfg(feature = "try-runtime")]
336 fn post_upgrade(_state: Vec<u8>) -> Result<(), TryRuntimeError> {
337 frame_support::ensure!(
338 StorageVersion::<T>::get() == ObsoleteReleases::V12_0_0,
339 "v12 not applied"
340 );
341 Ok(())
342 }
343 }
344}
345
346pub mod v11 {
347 use super::*;
348 use frame_support::{
349 storage::migration::move_pallet,
350 traits::{GetStorageVersion, PalletInfoAccess},
351 };
352 #[cfg(feature = "try-runtime")]
353 use sp_io::hashing::twox_128;
354
355 pub struct MigrateToV11<T, P, N>(core::marker::PhantomData<(T, P, N)>);
356 impl<T: Config, P: GetStorageVersion + PalletInfoAccess, N: Get<&'static str>> OnRuntimeUpgrade
357 for MigrateToV11<T, P, N>
358 {
359 #[cfg(feature = "try-runtime")]
360 fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
361 frame_support::ensure!(
362 StorageVersion::<T>::get() == ObsoleteReleases::V10_0_0,
363 "must upgrade linearly"
364 );
365 let old_pallet_prefix = twox_128(N::get().as_bytes());
366
367 frame_support::ensure!(
368 sp_io::storage::next_key(&old_pallet_prefix).is_some(),
369 "no data for the old pallet name has been detected"
370 );
371
372 Ok(Default::default())
373 }
374
375 fn on_runtime_upgrade() -> Weight {
384 let old_pallet_name = N::get();
385 let new_pallet_name = <P as PalletInfoAccess>::name();
386
387 if StorageVersion::<T>::get() == ObsoleteReleases::V10_0_0 {
388 StorageVersion::<T>::put(ObsoleteReleases::V11_0_0);
390 if new_pallet_name == old_pallet_name {
391 log!(
392 warn,
393 "new bags-list name is equal to the old one, only bumping the version"
394 );
395 return T::DbWeight::get().reads(1).saturating_add(T::DbWeight::get().writes(1))
396 }
397
398 move_pallet(old_pallet_name.as_bytes(), new_pallet_name.as_bytes());
399 <T as frame_system::Config>::BlockWeights::get().max_block
400 } else {
401 log!(warn, "v11::migrate should be removed.");
402 T::DbWeight::get().reads(1)
403 }
404 }
405
406 #[cfg(feature = "try-runtime")]
407 fn post_upgrade(_state: Vec<u8>) -> Result<(), TryRuntimeError> {
408 frame_support::ensure!(
409 StorageVersion::<T>::get() == ObsoleteReleases::V11_0_0,
410 "wrong version after the upgrade"
411 );
412
413 let old_pallet_name = N::get();
414 let new_pallet_name = <P as PalletInfoAccess>::name();
415
416 if new_pallet_name == old_pallet_name {
418 return Ok(())
419 }
420
421 let old_pallet_prefix = twox_128(N::get().as_bytes());
422 frame_support::ensure!(
423 sp_io::storage::next_key(&old_pallet_prefix).is_none(),
424 "old pallet data hasn't been removed"
425 );
426
427 let new_pallet_name = <P as PalletInfoAccess>::name();
428 let new_pallet_prefix = twox_128(new_pallet_name.as_bytes());
429 frame_support::ensure!(
430 sp_io::storage::next_key(&new_pallet_prefix).is_some(),
431 "new pallet data hasn't been created"
432 );
433
434 Ok(())
435 }
436 }
437}