Try   HackMD

Testing runtime upgrades for system parachains in Chopsticks

Overview

We need the ability to test governance proposals that depend on runtime upgrades that have not yet executed.

Runtime upgrades for system parachains can take up to 4 weeks to execute.

We therefore need to execute the runtime upgrade and the subsequent governance proposal in a simulated Chopsticks environment.

Steps

In the following scenario, we will simulate execution of the 1.2.0 upgrade: https://github.com/polkadot-fellows/runtimes/releases/tag/v1.2.0

  1. Install opengov-cli

  2. Build the preimage for the upgrade:

opengov-cli build-upgrade --network polkadot --relay-version 1.2.0 --filename preimage.hex
  1. Convert the preimage from hex to binary
xxd -r -p preimage.hex > preimage.bin
  1. Determine the size of the of preimage, save as PREIMAGE_SIZE
$ stat -c%s preimage.bin
1567371
  1. Compute blake2-256 hash of preimage, save as PREIMAGE_HASH
$ b2sum -l 256 preimage.bin | awk '{print "0x"$1}'
0x15165c85152568b7f523e374ce1a5172f2aa148721d5dae0441f86c201c1a77b
  1. Prepend compact-encoded length prefix to preimage, and convert back to hex, save as PREIMAGE_WITH_LENGTH_PREFIX:
use codec::Encode; use std::fs::File; fn main() { let mut file = File::open("preimage.bin")?; let mut buf: Vec<u8> = Vec::new(); file.read_to_end(&mut buf)?; let bytes_encoded = buf.encode(); println!("0x{}", hex::encode(bytes_encoded)); }
  1. Create a chopsticks configuration file for the Polkadot relay chain, substituting the values generated previously:

polkadot.yml

endpoint: wss://polkadot-rpc.dwellir.com mock-signature-host: true block: ${env.POLKADOT_BLOCK_NUMBER} db: ./polkadot.sqlite import-storage: System: Account: - - - 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY - providers: 1 data: free: '10000000000000000000' ParasDisputes: $removePrefix: ['disputes'] # those can makes block building super slow Preimage: { PreimageFor: [[[[PREIMAGE_HASH, PREIMAGE_SIZE]], PREIMAGE_WITH_LENGTH_PREFIX]], StatusFor: [[[PREIMAGE_HASH], { Requested: { count: 1, len: PREIMAGE_SIZE } }]], }
  1. Use these Chopstics config files for AssetHub and BridgeHub

polkadot-asset-hub.yml:

endpoint: wss://statemint-rpc.dwellir.com
mock-signature-host: true
block: ${env.POLKADOT_ASSET_HUB_BLOCK_NUMBER}
db: ./assethub.sqlite

import-storage:
  System:
    Account:
      - - - 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
        - providers: 1
          data:
            free: 1000000000000000

polkadot-bridge-hub.yml:

endpoint: wss://polkadot-bridge-hub-rpc.dwellir.com
mock-signature-host: true
block: ${env.POLKADOT_BRIDGEHUB_BLOCK_NUMBER}
db: ./bridgehub.sqlite

import-storage:
  System:
    Account:
      - - - 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
        - providers: 1
          data:
            free: 1000000000000000
  1. Run Chopsticks
yarn start xcm -r polkadot.yml -p polkadot-asset-hub.yml -p polkadot-bridge-hub.yml
  1. Execute the upgrade on the relay chain using Polkadot-JS:
const number = (await api.rpc.chain.getHeader()).number.toNumber() await api.rpc('dev_setStorage', { Scheduler: { Agenda: [ [ [number + 1], [ { call: { Lookup: { hash: PREIMAGE_HASH, len: PREIMAGE_SIZE, }, }, origin: { system: 'Root', }, }, ], ], ], }, }) await api.rpc('dev_newBlock', { count: 1 })
  1. Advance a few blocks on the relay chain
await api.rpc('dev_newBlock', { count: 2 })
  1. Advance by one block on bridgehub (not sure if necessary, need to experiment)
await api.rpc('dev_newBlock', { count: 1 })
  1. Now that the upgrade has been authorized on BridgeHub, we can execute the upgrade by calling parachainSystem.enactAuthorizedUpgrade, passing the parachain WASM blob previously generated by opengov-cli:

69887a907ad4f027c14651c6b8ba9fa0

  1. Advance a few blocks on both bridgehub AND the relay chain
await api.rpc('dev_newBlock', { count: 1 })
  1. The parachain should now be upgraded.

Caveats

Some polkadot API endpoints aggressively timeout connections, causing Chopsticks to die:

API-WS: disconnected from wss://polkadot-rpc.dwellir.com: 1006:: Abnormal Closure

The usual remedy is to restart chopsticks and pray the API connections don't die again.