Skip to content

Commit

Permalink
fix(pallet-gear-program): Migrations version (#3903)
Browse files Browse the repository at this point in the history
  • Loading branch information
grishasobol authored Apr 27, 2024
1 parent e29d9c3 commit 0dbc1c2
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 30 deletions.
2 changes: 1 addition & 1 deletion pallets/gear-program/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ pub mod pallet {
use sp_runtime::DispatchError;

/// The current storage version.
pub(crate) const PROGRAM_STORAGE_VERSION: StorageVersion = StorageVersion::new(4);
pub(crate) const PROGRAM_STORAGE_VERSION: StorageVersion = StorageVersion::new(5);

#[pallet::config]
pub trait Config: frame_system::Config {
Expand Down
46 changes: 30 additions & 16 deletions pallets/gear-program/src/migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

use crate::{CodeStorage, Config, Pallet};
use frame_support::{
traits::{Get, GetStorageVersion, OnRuntimeUpgrade},
traits::{Get, GetStorageVersion, OnRuntimeUpgrade, StorageVersion},
weights::Weight,
};
use gear_core::code::InstrumentedCode;
Expand All @@ -34,27 +34,32 @@ use {
sp_std::vec::Vec,
};

const SUITABLE_CURRENT_STORAGE_VERSION: u16 = 4;
const SUITABLE_ONCHAIN_STORAGE_VERSION: u16 = 3;
const MIGRATE_FROM_VERSION: u16 = 3;
const MIGRATE_TO_VERSION: u16 = 4;
const ALLOWED_CURRENT_STORAGE_VERSION: u16 = 5;

pub struct AppendStackEndMigration<T: Config>(PhantomData<T>);

impl<T: Config> OnRuntimeUpgrade for AppendStackEndMigration<T> {
fn on_runtime_upgrade() -> Weight {
let current = Pallet::<T>::current_storage_version();
let onchain = Pallet::<T>::on_chain_storage_version();

log::info!(
"🚚 Running migration with current storage version {current:?} / onchain {onchain:?}"
);

// 1 read for onchain storage version
let mut weight = T::DbWeight::get().reads(1);
let mut counter = 0;

if current == SUITABLE_CURRENT_STORAGE_VERSION
&& onchain == SUITABLE_ONCHAIN_STORAGE_VERSION
{
// NOTE: in 1.3.0 release, current storage version == `MIGRATE_TO_VERSION` is checked,
// but we need to skip this check now, because storage version was increased.
if onchain == MIGRATE_FROM_VERSION {
let current = Pallet::<T>::current_storage_version();
if current != ALLOWED_CURRENT_STORAGE_VERSION {
log::error!("❌ Migration is not allowed for current storage version {current:?}.");
return weight;
}

let update_to = StorageVersion::new(MIGRATE_TO_VERSION);
log::info!("🚚 Running migration from {onchain:?} to {update_to:?}, current storage version is {current:?}.");

CodeStorage::<T>::translate(|_, code: onchain::InstrumentedCode| {
weight = weight.saturating_add(T::DbWeight::get().reads_writes(1, 1));
counter += 1;
Expand All @@ -77,22 +82,31 @@ impl<T: Config> OnRuntimeUpgrade for AppendStackEndMigration<T> {
// Put new storage version
weight = weight.saturating_add(T::DbWeight::get().writes(1));

current.put::<Pallet<T>>();
update_to.put::<Pallet<T>>();

log::info!("Successfully migrated storage. {counter} codes has been migrated");
log::info!("Successfully migrated storage. {counter} codes have been migrated");
} else {
log::info!(" Migration did not execute. This probably should be removed");
log::info!("🟠 Migration requires onchain version {MIGRATE_FROM_VERSION}, so was skipped for {onchain:?}");
}

weight
}

#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
let current = Pallet::<T>::current_storage_version();
let onchain = Pallet::<T>::on_chain_storage_version();

let res = (onchain == SUITABLE_ONCHAIN_STORAGE_VERSION)
.then(|| onchain::CodeStorage::<T>::iter().count() as u64);
let res = if onchain == MIGRATE_FROM_VERSION {
ensure!(
current == ALLOWED_CURRENT_STORAGE_VERSION,
"Current storage version is not allowed for migration, check migration code in order to allow it."
);

Some(onchain::CodeStorage::<T>::iter().count() as u64)
} else {
None
};

Ok(res.encode())
}
Expand Down
41 changes: 28 additions & 13 deletions pallets/gear/src/migrations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use common::{
Origin,
};
use frame_support::{
traits::{Get, GetStorageVersion, OnRuntimeUpgrade},
traits::{Get, GetStorageVersion, OnRuntimeUpgrade, StorageVersion},
weights::Weight,
};
use gear_core::ids::MessageId;
Expand All @@ -32,29 +32,38 @@ use sp_std::{marker::PhantomData, vec::Vec};
#[cfg(feature = "try-runtime")]
use {
common::storage::IterableMap,
frame_support::ensure,
parity_scale_codec::{Decode, Encode},
sp_runtime::TryRuntimeError,
};

pub struct MigrateWaitingInitList<T>(PhantomData<T>);

const MIGRATE_FROM_VERSION: u16 = 4;
const MIGRATE_TO_VERSION: u16 = 5;
const ALLOWED_CURRENT_STORAGE_VERSION: u16 = 5;

impl<T> OnRuntimeUpgrade for MigrateWaitingInitList<T>
where
T: Config + pallet_gear_program::Config,
T::AccountId: Origin,
{
fn on_runtime_upgrade() -> Weight {
let current = pallet_gear_program::Pallet::<T>::current_storage_version();
let onchain = pallet_gear_program::Pallet::<T>::on_chain_storage_version();

log::info!(
"🚚 Running migration with current storage version {current:?} / onchain {onchain:?}"
);

// 1 read for the on-chain storage version
let mut weight = T::DbWeight::get().reads(1);

if current == 4 && onchain == 3 {
if onchain == MIGRATE_FROM_VERSION {
let current = pallet_gear_program::Pallet::<T>::current_storage_version();
if current != ALLOWED_CURRENT_STORAGE_VERSION {
log::error!("❌ Migration is not allowed for current storage version {current:?}.");
return weight;
}

let update_to = StorageVersion::new(MIGRATE_TO_VERSION);
log::info!("🚚 Running migration from {onchain:?} to {update_to:?}, current storage version is {current:?}.");

waiting_init_list::WaitingInitStorage::<T>::translate(
|program_id, messages: Vec<MessageId>| {
// read and remove an element
Expand Down Expand Up @@ -82,21 +91,27 @@ where
},
);

current.put::<pallet_gear_program::Pallet<T>>();
update_to.put::<pallet_gear_program::Pallet<T>>();

log::info!("Successfully migrated storage");
log::info!("Successfully migrated storage");
} else {
log::info!(" Migration did not execute. This probably should be removed");
log::info!("🟠 Migration requires onchain version {MIGRATE_FROM_VERSION}, so was skipped for {onchain:?}");
}

weight
}

#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
let current = Pallet::<T>::current_storage_version();
let onchain = Pallet::<T>::on_chain_storage_version();

let data = if onchain == 3 {
let data = if onchain == MIGRATE_FROM_VERSION {
ensure!(
current == ALLOWED_CURRENT_STORAGE_VERSION,
"Current storage version is not allowed for migration, check migration code in order to allow it."
);

let init_msgs: usize = waiting_init_list::WaitingInitStorage::<T>::iter_values()
.map(|d| d.len())
.sum();
Expand Down Expand Up @@ -256,7 +271,7 @@ mod tests {
init_logger();

new_test_ext().execute_with(|| {
StorageVersion::new(3).put::<GearProgram>();
StorageVersion::new(MIGRATE_FROM_VERSION).put::<GearProgram>();

let multiplier = <Test as pallet_gear_bank::Config>::GasMultiplier::get();

Expand Down Expand Up @@ -329,7 +344,7 @@ mod tests {
assert!(!weight.is_zero());
MigrateWaitingInitList::<Test>::post_upgrade(state).unwrap();

assert_eq!(StorageVersion::get::<GearProgram>(), 4);
assert_eq!(StorageVersion::get::<GearProgram>(), MIGRATE_TO_VERSION);

assert_eq!(
waiting_init_list::WaitingInitStorage::<Test>::iter().count(),
Expand Down

0 comments on commit 0dbc1c2

Please sign in to comment.