Files

120 lines
7.0 KiB
Markdown

# Release & runtime-upgrade runbook
PezkuwiChain holds real user funds. A runtime upgrade is the single most dangerous
operation we perform — a bad migration or a wrong WASM can corrupt state or brick the
chain. This runbook is the required, repeatable process. Do not skip steps.
## What a release produces
- **Runtime WASM blobs** for the deployable runtimes (relay `pezkuwichain`, system
teyrchains `asset-hub-pezkuwichain`, `people-pezkuwichain`), built by
`.github/workflows/release.yml`.
- For each blob: the **blake2-256 hash** (the value `authorizeUpgrade` commits to),
the sha256, and an **SLSA build-provenance attestation**.
- A **draft GitHub release** (human review before publishing a fund-critical artifact).
The node binary is built from the same tag with the pinned toolchain.
## CI tiers (what gates what)
| Tier | When | Gates |
|---|---|---|
| Fast gate (`check`, `quick-checks`, `security`) | every push/PR | compile, 6-runtime WASM build, **try-runtime**, fmt, supply-chain (cargo-deny), zepter/taplo |
| Heavy suite (`test`) | nightly + `workflow_dispatch` | full nextest tests, workspace clippy, benches, doc-tests |
| Release (`release`) | tag `v*`/`runtime-*` + `workflow_dispatch` | builds WASM, hashes, attestation, draft release |
Before any mainnet upgrade the **heavy suite must be green on the release commit** —
trigger it with `workflow_dispatch` and wait for it; do not rely only on the fast gate.
## spec_version policy
- `spec_name` is the chain identity and **must never change** for a live chain.
- `spec_version` is a single monotonically increasing integer (schema `M_mmm_ppp`;
current relay `1_020_007`). Bump it on **every** runtime change that ships — nodes use
it to detect the upgrade.
- Bump `transaction_version` only when extrinsic encoding/call indices change.
- `impl_version` is informational.
## Runtime-upgrade procedure (mainnet, fund-critical)
1. **Freeze the change set** on `main`; fast gate green.
2. **Bump `spec_version`** (+ `transaction_version` if call encoding changed) in the
affected runtime(s).
3. **Run the heavy suite** (`workflow_dispatch` → `test.yml`) on that commit → all green.
4. **try-runtime against live state** — dry-run the migrations on a snapshot of the live
chain and confirm they succeed and post-upgrade invariants hold, *before* touching
mainnet. (Pre-upgrade gate.)
5. **Tag** `runtime-<name>-vX` → `release.yml` builds the WASM and publishes the
**blake2-256** hash + sha256 + attestation as a draft release.
6. **Reproduce & verify**: independently rebuild the tag with the pinned toolchain
(`rust-toolchain.toml`) + committed `Cargo.lock`; confirm the blake2-256 matches.
Publish the release only after the hash is confirmed.
7. **Authorize on-chain**: governance/sudo `system.authorizeUpgrade(<blake2-256>)`, then
`system.applyAuthorizedUpgrade(<wasm>)`. The hash authorized on-chain must equal the
one in the release.
8. **Watch**: confirm blocks are still produced and finalized after the upgrade.
## Shipped: 2026-07-10 mainnet upgrade (spec_version 1_020_010 / 1_020_011)
Deployed to all three teyrchains (relay, Asset Hub, People chain), each verified against
its own `System::LastRuntimeUpgrade` post-upgrade. Full account of what was found and
fixed along the way, including two release-pipeline bugs caught by independent
verification before anything reached mainnet: [docs/audits/2026-07-mainnet-upgrade.md](audits/2026-07-mainnet-upgrade.md).
The bundle:
- Token symbol standardized to **HEZ** (metadata-hash, claims `Prefix`, chain-spec).
- Claims statements repointed to **statement.pex.network** (hash-pinned; see
[statement/README.md](statement/README.md)).
- `tiki` pallet: 12 new functional/professional roles.
- RuntimeVersion identity cleanup (dropped `parity-*` / `westmint`).
- **Security-audit fix set** (AI-assisted internal review; commits `14cbf1a`, `9afd99a`
on `main`) — 11 findings closed across `identity-kyc`, `messaging`, `perwerde`,
`presale`, `tiki`, `welati`, plus the relay `SendXcmOrigin` narrowing in
`xcm_config.rs`. No storage migration required (all changes are new storage items or
Config/logic-only).
- `staking-score`: noter submissions now require a posted bond
(`register_as_noter`/`unregister_as_noter`) and sit in a 1-hour dispute window
(`DisputeWindow`) before taking effect, disputable by any Council member and
slashable by `RootOrDiwanOrTechnical` on confirmed fraud. Root/XCM-Transact
submissions are unaffected (chain-authenticated, not a personal key).
- Fixed `MONTH_IN_BLOCKS`/`HOUR_IN_BLOCKS` in `staking-score`: an earlier revision
had switched these to assume 12s blocks (5/min), citing an unused same-named
constant from a different crate. `people-pezkuwichain` actually wires its
`HOURS`/`DAYS`/`SlotDuration` from a 6s-block source — confirmed via live mainnet
empirical block time, the real import path, and a try-runtime dry-run that
panicked with an exact 2x slot mismatch under the wrong assumption. Every
duration-tier threshold was filling twice as fast as intended; restored to 10
blocks/min (6s), matching reality.
- `staking-score`'s weights are now real benchmark output (previously manual
estimates); `presale::withdraw_funds` had no benchmark case at all until
commit `dc6d29e` — real weight pending a benchmark run.
- Dependency-security cleanup: `rand`/`tar`/`rpassword` patched (commit `2cbf2b3`);
`wasmtime` (2 critical, aarch64-specific sandbox-escape CVEs; our fleet is x86_64)
and a handful of other client-networking deps (`hickory-proto`, `rustls-webpki`,
`yamux`) remain — each pinned by a deeper Substrate/Polkadot-SDK dependency and
needing a coordinated major-version bump plus real node testing. Tracked as a
separate task, not part of this bundle.
**Note on Zagros testnet validation:** the live "Zagros Testnet" chain (217.77.6.126)
runs the `pezkuwichain`/`asset-hub-pezkuwichain`/`people-pezkuwichain` runtime family
(spec_name confirmed via live RPC), not the `zagros`/`asset-hub-zagros`/`people-zagros`
family. The latter is a CI-checked-only reference implementation (never released — see
`release.yml`), left over from before this repo's clean-room rewrite. Bump
`spec_version` and build WASM from the `*-pezkuwichain` crates when validating a bundle
on Zagros before it ships to mainnet; the `*-zagros` crates are not deployed anywhere.
## Changing a claim statement
A statement edit changes its hash → changes the runtime → is a runtime upgrade and
invalidates prior signatures. Procedure: edit `docs/statement/*.html`, redeploy to
`statement.pex.network`, recompute sha256, update `StatementKind::to_text()`, bump
`spec_version`, ship. The repo copy, the served copy, and the runtime hash must stay
identical.
## Reproducibility note
Builds are pinned-toolchain reproducible (deterministic given `rust-toolchain.toml` +
`Cargo.lock` + flags). Fully hermetic srtool builds are pending a Rust 1.96 srtool image
(latest published is 1.93); the release pipeline will adopt srtool once available.