moonbeam_runtime_common/
migrations.rsuse core::marker::PhantomData;
use frame_support::migrations::SteppedMigrationError;
use frame_support::weights::WeightMeter;
use frame_support::{migrations::SteppedMigration, parameter_types};
use pallet_migrations::WeightInfo;
use parity_scale_codec::Encode;
use sp_core::{twox_128, Get};
use sp_io::{storage::clear_prefix, KillStorageResult};
use sp_runtime::SaturatedConversion;
pub struct RemovePallet<T, P>(PhantomData<(T, P)>);
impl<T, P> RemovePallet<T, P>
where
P: Get<&'static str>,
{
#[cfg(feature = "try-runtime")]
fn num_keys() -> u64 {
let prefix = twox_128(P::get().as_bytes()).to_vec();
frame_support::storage::KeyPrefixIterator::new(prefix.clone(), prefix, |_| Ok(())).count()
as _
}
}
impl<T, P> SteppedMigration for RemovePallet<T, P>
where
T: pallet_migrations::Config,
P: Get<&'static str>,
{
type Cursor = bool;
type Identifier = [u8; 16];
fn id() -> Self::Identifier {
("RemovePallet::", P::get()).using_encoded(twox_128)
}
fn step(
cursor: Option<Self::Cursor>,
meter: &mut WeightMeter,
) -> Result<Option<Self::Cursor>, SteppedMigrationError> {
if cursor.unwrap_or(false) {
let required = T::DbWeight::get().writes(1);
meter
.try_consume(required)
.map_err(|_| SteppedMigrationError::InsufficientWeight { required })?;
return Ok(None);
}
let base_weight = T::WeightInfo::reset_pallet_migration(0);
let weight_per_key = T::WeightInfo::reset_pallet_migration(1).saturating_sub(base_weight);
let key_budget = meter
.remaining()
.saturating_sub(base_weight)
.checked_div_per_component(&weight_per_key)
.unwrap_or_default()
.saturated_into();
if key_budget == 0 {
return Err(SteppedMigrationError::InsufficientWeight {
required: T::WeightInfo::reset_pallet_migration(1),
});
}
let (keys_removed, is_done) =
match clear_prefix(&twox_128(P::get().as_bytes()), Some(key_budget)) {
KillStorageResult::AllRemoved(value) => (value, true),
KillStorageResult::SomeRemaining(value) => (value, false),
};
meter.consume(T::WeightInfo::reset_pallet_migration(keys_removed));
Ok(Some(is_done))
}
#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<sp_std::vec::Vec<u8>, sp_runtime::TryRuntimeError> {
let num_keys: u64 = Self::num_keys();
log::info!(
"RemovePallet<{}>: Trying to remove {num_keys} keys.",
P::get()
);
Ok(num_keys.encode())
}
#[cfg(feature = "try-runtime")]
fn post_upgrade(state: sp_std::vec::Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
use parity_scale_codec::Decode;
let keys_before = u64::decode(&mut state.as_ref()).expect("We encoded as u64 above; qed");
let keys_now = Self::num_keys();
log::info!(
"RemovePallet<{}>: Keys remaining after migration: {keys_now}",
P::get()
);
if keys_before <= keys_now {
log::error!("RemovePallet<{}>: Did not remove any keys.", P::get());
Err("RemovePallet failed")?;
}
if keys_now != 1 {
log::error!("RemovePallet<{}>: Should have a single key after", P::get());
Err("RemovePallet failed")?;
}
Ok(())
}
}
pub type UnreleasedSingleBlockMigrations = ();
pub type PermanentSingleBlockMigrations<Runtime> =
(pallet_xcm::migration::MigrateToLatestXcmVersion<Runtime>,);
pub type SingleBlockMigrations<Runtime> = (
UnreleasedSingleBlockMigrations,
PermanentSingleBlockMigrations<Runtime>,
);
parameter_types! {
pub const MigrationsPalletName: &'static str = "Migrations";
}
pub type MultiBlockMigrations<Runtime> = (RemovePallet<Runtime, MigrationsPalletName>,);