diff --git a/doc/mainnet-cutover.md b/doc/mainnet-cutover.md new file mode 100644 index 0000000..3b8b79b --- /dev/null +++ b/doc/mainnet-cutover.md @@ -0,0 +1,71 @@ +# Mainnet cutover runbook + +Launch announced for **2026-09-10 09:09 UTC** (12:09 EEST). The foundation's +sequence: node binary release on GitHub, genesis hash published, their +bootnodes up, then chain spec + bootnodes + verification instructions shared, +then a later release with the spec embedded. Nothing of ours is switched until +the genesis hash and chain spec come through the official channel. + +Keys: the planck reward key (bob's `inner_hash` in the deploy matrix) is reused +on mainnet — decided 2026-09-09. + +## Before the announcement (done 2026-09-09) + +- lair/quantus#24: node deploy runs from a chain spec file, asserts the genesis + hash, prints the spec id, dials bootnodes as reserved peers, out/in peers + 32/64. Soaked on planck overnight. +- quantus/miner#19: miner deploy takes a `chain` input for the credential path. +- bob's sudoers grant the runner `/etc/quantus-node/chainspec.json`. + +## Cutover, in order + +1. **Collect** from the official channel: release version `vX.Y.Z`, chain spec + URL, genesis hash, bootnode multiaddrs. Verify the spec the way their + instructions say (checksum against the release). Do not proceed on a + spec or hash from anywhere else — see their scam warning. +2. **Node.** Dispatch lair/quantus `deploy` with: + - `mode`: deploy + - `node_version`: `X.Y.Z` (no `v`) + - `chainspec_url`: the spec URL + - `expected_genesis`: the published 0x hash + - `bootnodes`: the multiaddrs, space-separated + Validate must print `genesis matches expected` and + `miner credentials present under chains//`. A genesis mismatch fails + the run and leaves the node on the wrong spec: re-dispatch with + `node_version: 0.11.1` and every other input empty to return to planck + (the node deploy has no automatic rollback; the miner deploy does). + Note ``. +3. **Miners.** Dispatch quantus/miner `deploy` with `chain: `. The binary + is unchanged; the new token and TLS pin trigger the checksum-gated restart. + Validate waits for the miner to connect and for the hash counter to move. + A wrong `` shows within a minute as a restart loop on benjy and + quadbrat (permanent connection error on certificate mismatch). +4. **beast** (if joining): stop `neuron.service` on beast, uncomment the beast + row in quantus/miner's deploy matrix, merge; the push deploys it. +5. **Commit the values** so push-triggered deploys keep them: in lair/quantus + `deploy.yaml` set `CHAIN: `, `NODE_VERSION`, `CHAINSPEC_URL`, + `EXPECTED_GENESIS`, `BOOTNODES`; in quantus/miner `deploy.yaml` set + `CHAIN: `. Once the foundation ships the release with the spec + embedded, `CHAINSPEC_URL` can go back to empty with `CHAIN` as the built-in + name, keeping `EXPECTED_GENESIS`. +6. **Watch**: the arena dashboard follows the new genesis on its own (the + exporter discovers it from the node). If `quantus_telemetry_up` drops or + the node population looks like planck's, the feed URL differs for mainnet: + update `TELEMETRY_URL` in `deploy.yaml`. + +## What does not change + +- Miner binaries: a node upgrade on the same chain is invisible to them (they + reconnect with a 1–30 s backoff). Only the chain switch needs step 3. +- The arena exporter, Prometheus rules and dashboards. Leaderboard history + simply starts over at the new genesis; attribution state is kept on disk. + +## Rollback + +Node: no automatic rollback. A failed validate leaves the new binary and +config in place; re-dispatch with the previous `node_version` and empty +spec/genesis/bootnodes to return to planck (planck's state under +`chains/planck/` is untouched by a mainnet attempt, which lives under its own +spec id). Miners: keep planck credentials until step 3 succeeds, so a failed +node cutover leaves them reconnecting, not mining a wrong chain; the miner +deploy itself restores `quantus-miner.prev` on a failed validate.