Hey guys I'm seeing a weird thing with the following migration code:
pub struct SomeMigration;
impl OnRuntimeUpgrade for SomeMigration {
fn on_runtime_upgrade() -> Weight {
let pallet_prefix: &[u8] = b"SomeName";
let storage_item_prefix: &[u8] = b"TestMe";
let value = match take_storage_value::<u32>(pallet_prefix, storage_item_prefix, &[]) {
Some(value) => value,
None => {
return 0;
}
};
let new_value: u128 = value as u128;
put_storage_value::<u128>(pallet_prefix, storage_item_prefix, &[], new_value);
1
}
#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<(), &'static str> {
let pallet_prefix: &[u8] = b"SomeName";
let storage_item_prefix: &[u8] = b"TestMe";
assert!(get_storage_value::<u32>(pallet_prefix, storage_item_prefix, &[]).is_none());
put_storage_value(pallet_prefix, storage_item_prefix, &[], 10u32);
assert!(get_storage_value::<u32>(pallet_prefix, storage_item_prefix, &[]).is_some());
Ok(())
}
#[cfg(feature = "try-runtime")]
fn post_upgrade() -> Result<(), &'static str> {
let pallet_prefix: &[u8] = b"SomeName";
let storage_item_prefix: &[u8] = b"TestMe";
assert!(get_storage_value::<u32>(pallet_prefix, storage_item_prefix, &[]).is_none());
Ok(())
}
}
What's happening here is is the following
- pre-upgrade: Check that no item exists for u32 storage value
TestMe
- pre-upgrade: Write a u32 storage value
TestMe
- pre-upgrade: Check that the u32 storage value is_some()
- on-runtime-upgrade: take_storage_value of the u32
TestMe
, expecting it to be drained - on-runtime-upgrade: write the same value back but as u128
- on-post-upgrade: check that the old u32 value is_none()
The problem is that when I use the try-runtime
tool the assert on step 6 fails, as if the value was not drained in step 4.
But if I actually perform this runtime upgrade on a local network I can see that the old storage key of the u32 storage value is empty after the upgrade and only the new u128 storage value exists.
This seems like some issue with the try-runtime tool, but I may be using it wrong.
Thanks for the attention.
EDIT:
storage_alias
minimal example:
pub mod old {
#[storage_alias]
pub type SomeName = StorageValue<PalletName, u32, ValueQuery>;
}
#[storage_alias]
pub type SomeName = StorageValue<PalletName, u128, ValueQuery>;
pub struct SomeMigration;
impl OnRuntimeUpgrade for SomeMigration {
fn on_runtime_upgrade() -> Weight {
let value = old::SomeName::take();
SomeName::set(value as u128);
1
}
#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<(), &'static str> {
old::SomeName::set(10u32);
Ok(())
}
#[cfg(feature = "try-runtime")]
fn post_upgrade() -> Result<(), &'static str> {
assert_eq!(old::SomeName::get(), 10u32);
Ok(())
}
}
u128
to storage and then decode it asu32
? This should work. You should probably use astorage_alias
here to make it easier to read.storage_alias
the same thing happens. I usetake()
on theold::SomeName
inon-runtime-upgrade
and then the value remains inpost-upgrade
when I useold::SomeName::get()
storage_alias
```