Moving a parachain between relay chains

This guide will give some insights in how to move a parachain from one relay chain to another relay chain. While this already happened between Kusama and Polkadot, this guide mainly assumes that the move is done between two test relay chain networks.

  1. The parachain needs to prepare a runtime upgrade that kills LastHrmpMqcHeads, LastDmqMqcHead and either remove LastRelayChainBlockNumber or set CheckAssociatedRelayNumber to AnyRelayNumber. If the parachain is also changing its ParaId on the new relay chain, this also needs to be changed by this runtime upgrade.

    struct PrepareForMove;
    impl OnRuntimeUpgrade for PrepareForMove {
    	fn on_runtime_upgrade() -> Weight {
    		cumulus_pallet_parachain_system::LastHrmpMqcHeads::<Runtime>::kill();
    		cumulus_pallet_parachain_system::LastDmqMqcHead::<Runtime>::kill();
    
    		// Either remove this storage or change the `CheckAssociatedRelayNumber` type.
    		cumulus_pallet_parachain_system::LastRelayChainBlockNumber::<Runtime>::kill();
    
    		// Weight negligible as the block will always fail to build
    		Weight::zero()
    	}
    } 
    
  2. Apply the runtime upgrade at the parachain. The first block that will be build with the new runtime will always fail as LastDmqMqcHead and LastHrmpMqcHeads will not match the values at the relay chain. However, this is the expected behavior.

  3. Now the parachain can be registered on the new relay chain. The registration is done as for every other parachain on this relay chain. The only difference is that the initial validation_code used for the registration is the validation_code that is currently registered on the old relay chain (basically being the runtime that was upgraded to in step 2). The genesis_head to use for the registration is the latest head (paras:heads) of the parachain on the old relay chain.

  4. While the parachain is being registered on the relay chain, the parachain chainspec on all nodes (most importantly the collators) needs to be updated. The chainspec needs to change the relay_chain field to point to the new relay chain. After the nodes are restarted with the new chainspec, they will start to sync the new relay chain. When the parachain is registered on the new relay chain and the collators have finished syncing the new relay chain, the parachain should start producing blocks again.