2

I'm about to introduce several instances of a pallet that was previously used as a default instance. The question is: how do I migrate the storage of pallet_bags_list to pallet_bags_list::<Instance1>. Or does it happen automatically for the first instance? It seems like this does not happen automatically, because a DefaultInstance has an empty prefix, named instances have their name as prefix.

Some context could be found here and here.

2 Answers 2

1

Each pallet in a runtime has an index associate with it. When an extrinsic is scale encoded, this index is the first byte that identifies which pallet it belongs to. (The next byte identifies which pallet's Call variant is being called).

In the linked construct_runtime! there are no explicit indexes, so the first pallet will be 0 and its enumerated from there on. If people add new pallets / pallet instances on the end then nothing disrupts the existing index numbers. However for production chains it's recommended to explicitly specify the pallet indexes your using (E.g. statemint).

The pallet's storage is prefixed by the pallet's index to make its self contained.

0
1

The answer turned out to be pretty simple, the pallet storage is prefixed according to how it's defined in construct_runtime!.

So in order to migrate from

construct_runtime!(
    pub enum Runtime where
        Block = Block,
        NodeBlock = node_primitives::Block,
        UncheckedExtrinsic = UncheckedExtrinsic
    {
        System: frame_system,
        Utility: pallet_utility,
        Uniques: pallet_uniques,
        TransactionStorage: pallet_transaction_storage,
        BagsList: pallet_bags_list,
        ....
    }
);

to

construct_runtime!(
    pub enum Runtime where
        Block = Block,
        NodeBlock = node_primitives::Block,
        UncheckedExtrinsic = UncheckedExtrinsic
    {
        System: frame_system,
        Utility: pallet_utility,
        Uniques: pallet_uniques,
        TransactionStorage: pallet_transaction_storage,
        VoterBagsList: pallet_bags_list::<Instance1>,
        ....
    }
);

We simply need to use this function. A full example would look like this:

    pub fn migrate<T: Config, P: GetStorageVersion + PalletInfoAccess, N: AsRef<str>>(
        old_pallet_name: N,
    ) -> Weight {
        let old_pallet_name = old_pallet_name.as_ref();
        let new_pallet_name = <P as PalletInfoAccess>::name();

        if new_pallet_name == old_pallet_name {
            log!(warn, "new bags-list name is equal to the old one, no need to migrate");
            return 0
        }

        if StorageVersion::<T>::get() == Releases::V10_0_0 {
            move_pallet(old_pallet_name.as_bytes(), new_pallet_name.as_bytes());
            StorageVersion::<T>::put(Releases::V11_0_0);
            <T as frame_system::Config>::BlockWeights::get().max_block
        } else {
            log!(warn, "v11::migrate should be removed.");
            T::DbWeight::get().reads(1)
        }
    }

Where old_pallet_name would be BagsList.

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.