use super::*;
use crate::types::RegionRecord;
use codec::{Decode, Encode};
use core::marker::PhantomData;
use frame_support::traits::{Get, UncheckedOnRuntimeUpgrade};
use sp_runtime::Saturating;
#[cfg(feature = "try-runtime")]
use alloc::vec::Vec;
#[cfg(feature = "try-runtime")]
use frame_support::ensure;
mod v1 {
use super::*;
#[derive(Encode, Decode)]
struct RegionRecordV0<AccountId, Balance> {
pub end: Timeslice,
pub owner: AccountId,
pub paid: Option<Balance>,
}
pub struct MigrateToV1Impl<T>(PhantomData<T>);
impl<T: Config> UncheckedOnRuntimeUpgrade for MigrateToV1Impl<T> {
fn on_runtime_upgrade() -> frame_support::weights::Weight {
let mut count: u64 = 0;
<Regions<T>>::translate::<RegionRecordV0<T::AccountId, BalanceOf<T>>, _>(|_, v0| {
count.saturating_inc();
Some(RegionRecord { end: v0.end, owner: Some(v0.owner), paid: v0.paid })
});
log::info!(
target: LOG_TARGET,
"Storage migration v1 for pallet-broker finished.",
);
T::DbWeight::get().reads_writes(count as u64 + 1, count as u64 + 1)
}
#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
Ok((Regions::<T>::iter_keys().count() as u32).encode())
}
#[cfg(feature = "try-runtime")]
fn post_upgrade(state: Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
let old_count = u32::decode(&mut &state[..]).expect("Known good");
let new_count = Regions::<T>::iter_values().count() as u32;
ensure!(old_count == new_count, "Regions count should not change");
Ok(())
}
}
}
mod v2 {
use super::*;
use frame_support::{
pallet_prelude::{OptionQuery, Twox64Concat},
storage_alias,
};
#[storage_alias]
pub type AllowedRenewals<T: Config> = StorageMap<
Pallet<T>,
Twox64Concat,
PotentialRenewalId,
PotentialRenewalRecordOf<T>,
OptionQuery,
>;
pub struct MigrateToV2Impl<T>(PhantomData<T>);
impl<T: Config> UncheckedOnRuntimeUpgrade for MigrateToV2Impl<T> {
fn on_runtime_upgrade() -> frame_support::weights::Weight {
let mut count = 0;
for (renewal_id, renewal) in AllowedRenewals::<T>::drain() {
PotentialRenewals::<T>::insert(renewal_id, renewal);
count += 1;
}
log::info!(
target: LOG_TARGET,
"Storage migration v2 for pallet-broker finished.",
);
T::DbWeight::get().reads_writes(count as u64 + 1, count as u64 + 1)
}
#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
Ok((AllowedRenewals::<T>::iter_keys().count() as u32).encode())
}
#[cfg(feature = "try-runtime")]
fn post_upgrade(state: Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
let old_count = u32::decode(&mut &state[..]).expect("Known good");
let new_count = PotentialRenewals::<T>::iter_values().count() as u32;
ensure!(old_count == new_count, "Renewal count should not change");
Ok(())
}
}
}
mod v3 {
use super::*;
use codec::MaxEncodedLen;
use frame_support::{
pallet_prelude::{OptionQuery, RuntimeDebug, TypeInfo},
storage_alias,
};
use frame_system::Pallet as System;
use sp_arithmetic::Perbill;
pub struct MigrateToV3Impl<T>(PhantomData<T>);
impl<T: Config> UncheckedOnRuntimeUpgrade for MigrateToV3Impl<T> {
fn on_runtime_upgrade() -> frame_support::weights::Weight {
let acc = Pallet::<T>::account_id();
System::<T>::inc_providers(&acc);
T::DbWeight::get().writes(1)
}
#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
Ok(System::<T>::providers(&Pallet::<T>::account_id()).encode())
}
#[cfg(feature = "try-runtime")]
fn post_upgrade(state: Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
let old_providers = u32::decode(&mut &state[..]).expect("Known good");
let new_providers = System::<T>::providers(&Pallet::<T>::account_id()) as u32;
ensure!(new_providers == old_providers + 1, "Providers count should increase by one");
Ok(())
}
}
#[storage_alias]
pub type Configuration<T: Config> = StorageValue<Pallet<T>, ConfigRecordOf<T>, OptionQuery>;
pub type ConfigRecordOf<T> =
ConfigRecord<frame_system::pallet_prelude::BlockNumberFor<T>, RelayBlockNumberOf<T>>;
#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
pub struct ConfigRecord<BlockNumber, RelayBlockNumber> {
pub advance_notice: RelayBlockNumber,
pub interlude_length: BlockNumber,
pub leadin_length: BlockNumber,
pub region_length: Timeslice,
pub ideal_bulk_proportion: Perbill,
pub limit_cores_offered: Option<CoreIndex>,
pub renewal_bump: Perbill,
pub contribution_timeout: Timeslice,
}
#[storage_alias]
pub type SaleInfo<T: Config> = StorageValue<Pallet<T>, SaleInfoRecordOf<T>, OptionQuery>;
pub type SaleInfoRecordOf<T> =
SaleInfoRecord<BalanceOf<T>, frame_system::pallet_prelude::BlockNumberFor<T>>;
#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
pub struct SaleInfoRecord<Balance, BlockNumber> {
pub sale_start: BlockNumber,
pub leadin_length: BlockNumber,
pub price: Balance,
pub region_begin: Timeslice,
pub region_end: Timeslice,
pub ideal_cores_sold: CoreIndex,
pub cores_offered: CoreIndex,
pub first_core: CoreIndex,
pub sellout_price: Option<Balance>,
pub cores_sold: CoreIndex,
}
}
pub mod v4 {
use super::*;
type BlockNumberFor<T> = frame_system::pallet_prelude::BlockNumberFor<T>;
pub trait BlockToRelayHeightConversion<T: Config> {
fn convert_block_number_to_relay_height(
block_number: BlockNumberFor<T>,
) -> RelayBlockNumberOf<T>;
fn convert_block_length_to_relay_length(
block_number: BlockNumberFor<T>,
) -> RelayBlockNumberOf<T>;
}
pub struct MigrateToV4Impl<T, BlockConversion>(PhantomData<T>, PhantomData<BlockConversion>);
impl<T: Config, BlockConversion: BlockToRelayHeightConversion<T>> UncheckedOnRuntimeUpgrade
for MigrateToV4Impl<T, BlockConversion>
{
#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, sp_runtime::TryRuntimeError> {
let (interlude_length, configuration_leadin_length) =
if let Some(config_record) = v3::Configuration::<T>::get() {
(config_record.interlude_length, config_record.leadin_length)
} else {
((0 as u32).into(), (0 as u32).into())
};
let updated_interlude_length: RelayBlockNumberOf<T> =
BlockConversion::convert_block_length_to_relay_length(interlude_length);
let updated_leadin_length: RelayBlockNumberOf<T> =
BlockConversion::convert_block_length_to_relay_length(configuration_leadin_length);
log::info!(target: LOG_TARGET, "Configuration Pre-Migration: Interlude Length {:?}->{:?} Leadin Length {:?}->{:?}", interlude_length, updated_interlude_length, configuration_leadin_length, updated_leadin_length);
let (sale_start, sale_info_leadin_length) =
if let Some(sale_info_record) = v3::SaleInfo::<T>::get() {
(sale_info_record.sale_start, sale_info_record.leadin_length)
} else {
((0 as u32).into(), (0 as u32).into())
};
let updated_sale_start: RelayBlockNumberOf<T> =
BlockConversion::convert_block_number_to_relay_height(sale_start);
let updated_sale_info_leadin_length: RelayBlockNumberOf<T> =
BlockConversion::convert_block_length_to_relay_length(sale_info_leadin_length);
log::info!(target: LOG_TARGET, "SaleInfo Pre-Migration: Sale Start {:?}->{:?} Interlude Length {:?}->{:?}", sale_start, updated_sale_start, sale_info_leadin_length, updated_sale_info_leadin_length);
Ok((interlude_length, configuration_leadin_length, sale_start, sale_info_leadin_length)
.encode())
}
fn on_runtime_upgrade() -> frame_support::weights::Weight {
let mut weight = T::DbWeight::get().reads(1);
if let Some(config_record) = v3::Configuration::<T>::take() {
log::info!(target: LOG_TARGET, "migrating Configuration record");
let updated_interlude_length: RelayBlockNumberOf<T> =
BlockConversion::convert_block_length_to_relay_length(
config_record.interlude_length,
);
let updated_leadin_length: RelayBlockNumberOf<T> =
BlockConversion::convert_block_length_to_relay_length(
config_record.leadin_length,
);
let updated_config_record = ConfigRecord {
interlude_length: updated_interlude_length,
leadin_length: updated_leadin_length,
advance_notice: config_record.advance_notice,
region_length: config_record.region_length,
ideal_bulk_proportion: config_record.ideal_bulk_proportion,
limit_cores_offered: config_record.limit_cores_offered,
renewal_bump: config_record.renewal_bump,
contribution_timeout: config_record.contribution_timeout,
};
Configuration::<T>::put(updated_config_record);
}
weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 1));
if let Some(sale_info) = v3::SaleInfo::<T>::take() {
log::info!(target: LOG_TARGET, "migrating SaleInfo record");
let updated_sale_start: RelayBlockNumberOf<T> =
BlockConversion::convert_block_number_to_relay_height(sale_info.sale_start);
let updated_leadin_length: RelayBlockNumberOf<T> =
BlockConversion::convert_block_length_to_relay_length(sale_info.leadin_length);
let updated_sale_info = SaleInfoRecord {
sale_start: updated_sale_start,
leadin_length: updated_leadin_length,
end_price: sale_info.price,
region_begin: sale_info.region_begin,
region_end: sale_info.region_end,
ideal_cores_sold: sale_info.ideal_cores_sold,
cores_offered: sale_info.cores_offered,
first_core: sale_info.first_core,
sellout_price: sale_info.sellout_price,
cores_sold: sale_info.cores_sold,
};
SaleInfo::<T>::put(updated_sale_info);
}
weight.saturating_add(T::DbWeight::get().reads_writes(1, 2))
}
#[cfg(feature = "try-runtime")]
fn post_upgrade(state: Vec<u8>) -> Result<(), sp_runtime::TryRuntimeError> {
let (
old_interlude_length,
old_configuration_leadin_length,
old_sale_start,
old_sale_info_leadin_length,
): (BlockNumberFor<T>, BlockNumberFor<T>, BlockNumberFor<T>, BlockNumberFor<T>) =
Decode::decode(&mut &state[..]).expect("pre_upgrade provides a valid state; qed");
if let Some(config_record) = Configuration::<T>::get() {
ensure!(
Self::verify_updated_block_length(
old_configuration_leadin_length,
config_record.leadin_length
),
"must migrate configuration leadin_length"
);
ensure!(
Self::verify_updated_block_length(
old_interlude_length,
config_record.interlude_length
),
"must migrate configuration interlude_length"
);
}
if let Some(sale_info) = SaleInfo::<T>::get() {
ensure!(
Self::verify_updated_block_time(old_sale_start, sale_info.sale_start),
"must migrate sale info sale_start"
);
ensure!(
Self::verify_updated_block_length(
old_sale_info_leadin_length,
sale_info.leadin_length
),
"must migrate sale info leadin_length"
);
}
Ok(())
}
}
#[cfg(feature = "try-runtime")]
impl<T: Config, BlockConversion: BlockToRelayHeightConversion<T>>
MigrateToV4Impl<T, BlockConversion>
{
fn verify_updated_block_time(
old_value: BlockNumberFor<T>,
new_value: RelayBlockNumberOf<T>,
) -> bool {
BlockConversion::convert_block_number_to_relay_height(old_value) == new_value
}
fn verify_updated_block_length(
old_value: BlockNumberFor<T>,
new_value: RelayBlockNumberOf<T>,
) -> bool {
BlockConversion::convert_block_length_to_relay_length(old_value) == new_value
}
}
}
pub type MigrateV0ToV1<T> = frame_support::migrations::VersionedMigration<
0,
1,
v1::MigrateToV1Impl<T>,
Pallet<T>,
<T as frame_system::Config>::DbWeight,
>;
pub type MigrateV1ToV2<T> = frame_support::migrations::VersionedMigration<
1,
2,
v2::MigrateToV2Impl<T>,
Pallet<T>,
<T as frame_system::Config>::DbWeight,
>;
pub type MigrateV2ToV3<T> = frame_support::migrations::VersionedMigration<
2,
3,
v3::MigrateToV3Impl<T>,
Pallet<T>,
<T as frame_system::Config>::DbWeight,
>;
pub type MigrateV3ToV4<T, BlockConversion> = frame_support::migrations::VersionedMigration<
3,
4,
v4::MigrateToV4Impl<T, BlockConversion>,
Pallet<T>,
<T as frame_system::Config>::DbWeight,
>;