2

If defining migrations in structs that impl OnRuntimeUpgrade. And these structs are then put into a Tuple migration, pre and post-upgrade hooks are noops on the tuple. See this issue.

The idea being that we should use try_on_runtime_upgrade instead.

  1. This is poorly documented.
  2. If we want to call try_on_runtime_upgrade from the pallet, it's not exposed in the Hooks, only the pre_upgrade and post_upgrade hooks are exposed. See here.

Is there something I'm missing here? How should they be called?

Edit for some more info:

In our pallets we have (just using pre_upgrade for simplicity, but post is the same):

#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<sp_std::vec::Vec<u8>, DispatchError> {
    migrations::PalletMigration::<T>::pre_upgrade()
}

// in migrations .rs

pub type PalletMigration<T> = (
    VersionedMigration<crate::Pallet<T>, v4::Migration<T>, 3, 4>,
    VersionedMigration<crate::Pallet<T>, v5::Migration<T>, 4, 5>,
    VersionedMigration<crate::Pallet<T>, v6::Migration<T>, 5, 6>,
    VersionedMigration<crate::Pallet<T>, v7::Migration<T>, 6, 7>,
);

VersionedMigration impls OnRuntimeUpgrade, with on_runtime_upgrade, pre_upgrade and post_upgrade definitions.

Which then calls the inner migration e.g. v5::Migration. So it's just a wrapper which does a couple of things like version checking.

v5::Migration impls OnRuntimeUpgrade, and contains the storage migration logic.

So, in the pallet, if we just call pre_upgrade on the tuple migration, (aliased to PalletMigration it doesn't work. It's a noop.

So we're only implementing the pre and post upgrade hooks, but they don't trigger.

Our Executive definition looks like:

pub type Executive = frame_executive::Executive<
    Runtime,
    Block,
    frame_system::ChainContext<Runtime>,
    Runtime,
    AllPalletsWithSystem,
    (),
>;
6
  • My understanding is pre and post hooks are to implements tests for try-runtime and the upgrade code to execute on chain goes into OnRuntimeUpgrade
    – Simson
    Nov 16, 2023 at 9:37
  • @Simson yeah, that's how we're using it. The upgrade code is in on_runtime_upgrade() part of the hook, and just the pre and post checks are in the pre_upgrade and post_upgrade hooks. Currently if I run try-runtime on_runtime_upgrade the upgrade runs, but the hooks do not.
    – Kyle
    Nov 16, 2023 at 9:39
  • Did you put it in the pub type Executive = frame_executive::Executive< ?
    – Simson
    Nov 16, 2023 at 9:46
  • Put what in there? I added our Executive definition to the OP
    – Kyle
    Nov 16, 2023 at 9:48
  • 1
    Perfect @liamaharon updated their answer
    – Simson
    Nov 16, 2023 at 10:28

1 Answer 1

4

try_on_runtime_upgrade is used only internally by the Executive pallet: (https://github.com/paritytech/polkadot-sdk/blob/ea4085ab7448bb557a1558a25af164cf364e88d6/substrate/frame/executive/src/lib.rs#L372).

You should not try to override this method. You only need to implement pre_upgrade post_upgrade and on_runtime_upgrade. Executive handles the rest.

Edit based on extra info you provided

You need to pass PalletMigration as the last parameter to Executive

pub type Executive = frame_executive::Executive<
    Runtime,
    Block,
    frame_system::ChainContext<Runtime>,
    Runtime,
    AllPalletsWithSystem,
    PalletMigration, // <-- here
>;

// can nest them if you like

pub type Executive = frame_executive::Executive<
    Runtime,
    Block,
    frame_system::ChainContext<Runtime>,
    Runtime,
    AllPalletsWithSystem,
    Migrations,
>;

pub type Migrations = (
    PalletMigration,
    OtherMigrations,
    SomeMoreMigrations
)
1
  • Added some more context in an edit to the issue, as this is what we're doing currently.
    – Kyle
    Nov 16, 2023 at 9:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.