diff --git a/bouncer/commands/noop_runtime_upgrade.ts b/bouncer/commands/noop_runtime_upgrade.ts new file mode 100755 index 0000000000..59a05a052b --- /dev/null +++ b/bouncer/commands/noop_runtime_upgrade.ts @@ -0,0 +1,31 @@ +#!/usr/bin/env -S pnpm tsx +// INSTRUCTIONS +// +// Performs a noop runtime upgrade. You will bump the runtime `spec_version` and nothing else. +// This should not affect the CFEs in any way. Everything should just function straight through the upgrade. +// For example ./commands/noop_runtime_upgrade.ts +// NB: It *must* be run from the bouncer directory. + +import { noopRuntimeUpgrade } from '../shared/noop_runtime_upgrade'; +import { promptUser } from '../shared/prompt_user'; +import { testAllSwaps } from '../shared/swapping'; +import { runWithTimeout } from '../shared/utils'; + +async function main(): Promise { + await noopRuntimeUpgrade(); + + await promptUser( + 'Would you like to test all swaps after the upgrade now? The vaults and liquidity must be set up already.', + ); + + await testAllSwaps(); + + process.exit(0); +} + +// 15 minutes. We need to wait for user input, compile, and potentially run tests. This is deliberatly quite long. +// This won't be run on CI, so it's not a problem if it takes a while. +runWithTimeout(main(), 15 * 60 * 1000).catch((error) => { + console.error(error); + process.exit(-1); +}); diff --git a/bouncer/shared/noop_runtime_upgrade.ts b/bouncer/shared/noop_runtime_upgrade.ts new file mode 100755 index 0000000000..fb34b76b1c --- /dev/null +++ b/bouncer/shared/noop_runtime_upgrade.ts @@ -0,0 +1,52 @@ +// Do a runtime upgrade that does nothing - the runtime should be identical except for the `spec_version` field. +// Needs to be run from the bouncer directory. +import { execSync } from 'node:child_process'; + +import { submitRuntimeUpgrade } from './submit_runtime_upgrade'; +import { jsonRpc } from './json_rpc'; +import { getChainflipApi, observeEvent } from './utils'; +import { promptUser } from './prompt_user'; + +async function getCurrentSpecVersion(): Promise { + return Number((await jsonRpc('state_getRuntimeVersion', [], 9944)).specVersion); +} + +export async function noopRuntimeUpgrade(): Promise { + const chainflip = await getChainflipApi(); + + const currentSpecVersion = await getCurrentSpecVersion(); + + console.log('Current spec_version: ' + currentSpecVersion); + + const nextSpecVersion = currentSpecVersion + 1; + + await promptUser( + 'Go to state-chain/runtime/src/lib.rs and then in that file go to #[sp_version::runtime_version]. Set the `spec_version` to ' + + nextSpecVersion + + ' and save the file.', + ); + + console.log('Building the new runtime'); + execSync('cd ../state-chain/runtime && cargo build --release'); + + console.log('Built the new runtime. Applying runtime upgrade.'); + await submitRuntimeUpgrade( + '../target/release/wbuild/state-chain-runtime/state_chain_runtime.compact.compressed.wasm', + ); + + await observeEvent('system:CodeUpdated', chainflip); + + const newSpecVersion = await getCurrentSpecVersion(); + console.log('New spec_version: ' + newSpecVersion); + + if (newSpecVersion !== nextSpecVersion) { + console.error( + 'After submitting the runtime upgrade, the new spec_version is not what we expected. Expected: ' + + nextSpecVersion + + ' Got: ' + + newSpecVersion, + ); + } + + console.log('Runtime upgrade complete.'); +} diff --git a/bouncer/shared/prompt_user.ts b/bouncer/shared/prompt_user.ts new file mode 100644 index 0000000000..7228fbcd0a --- /dev/null +++ b/bouncer/shared/prompt_user.ts @@ -0,0 +1,17 @@ +import { createInterface } from 'readline/promises'; + +export async function promptUser(prompt: string) { + const rl = createInterface({ + input: process.stdin, + output: process.stdout, + }); + + try { + const completePrompt = prompt + '\nEnter to continue. Ctrl + C to exit.\n'; + const ans = await rl.question(completePrompt); + rl.close(); + return ans; + } finally { + rl.close(); + } +}