23 KiB
Release 0.3.22: Devnet 3 (ordered 7 October 2026, 17:2x BST; genesis by 18:30 BST on the project lead's word)
Main's order (17:26 BST): Devnet 3 goes now, not after 0.3.21. 0.3.22's node = the release-0.3.21-node worktree on build-1 (96161037, both node gates PASS) + the sub-version 3 igneum-pow pin (the 017e7037 line, byte 7, pairing id a785001687d8688a; the Counter lane's handoff by 17:40 BST, else the node lane takes it from the audit-freeze-2026-10-07 tag) + the igneum-devnet-3 network object (its own network id and p2p port, every activation at 0: program_class_v4, difficulty_v2, finality_v3, fees_v1, proving_v1, latency_ladder rung 0; the genesis cut; NO override file on the new chain) + era VDF f2ecf452 only if its merge is clean and green in the same run (else 0.3.23 by an activation height; era_vdf_activation_daa stays at never on devnet-3 unless main's object names it). Built as an incremental on build-1's lease ahead of the 0.3.21 app gate.
Gates before genesis: the box suite on the exact commit (the consensus crate whole, consensus-core, the miner against sub-version 3's packs, kaspa-pow, the exec suite, the three checks); from the build on the fleet's pods: the empty-datadir canary, the fresh-genesis digest agreement on two fleet boxes from empty (the same digest and the first lock between them), the late joiner's sync from them, the shutdown under 1 s, the proving ids present on a bare node. After genesis on the live chain: the relay cases (with a relay kept synced before the window, the warm rule) and the hands. Genesis on green with the fleet's two genesis boxes (the standing-fleet shape: supervisor, kill file, vote key, miner); the old devnet keeps running until Devnet 3 has 24 hours; the apps move by signed update after that. The genesis is reported as a clock reading.
Staged (the build-server lane, 17:27 BST): the Devnet 3 seed on build-1 as a bare process (p2p 0.0.0.0:26631, gRPC 27630, JSON 27632, EVM 27810, empty datadir /home/build/dn3seed); the hands' second instances node1-dn3 (p2p 26651, rpc 26650, json 28650, evm 26830, --enable-unsynced-mining, peers the seed) and observer-dn3 (p2p 127.0.0.1:26661, rpc 26660, json 28660, evm 26860); ufw allows 26631 and 26651 since 17:27 BST; provision.sh's P2P_PORTS carries both; infra/build-server/devnet3/devnet3.{env,sh} with the NET_FLAGS placeholder until the node lane names the flag; read-back by the first log line, the commit-string count, the digest line, the "[igneum-exec] genesis executed" line and the server lines. The hands' nodes take no vote key (the miner's label is the key). The fleet: four gate pods on separate hosts renting with DESTROY=0; the fresh-genesis form, dn3_ tables, pay-by-key on the new chain and the no-stop cutover script follow; the capacity plan (a second node per standing box or a parallel set, the Devnet 3 hub) by 19:00 BST.
The app side: the app must start its node on igneum-devnet-3 (the network flag the node lane names; the manifest's channel; no override object), the chain scene and the ladder reading the new chain's facts, the first-block and earnings rows from zero: 0.3.22's app cut after the node is live, by signed update when Devnet 3 has 24 hours.
Era VDF (the era lane, 17:3x BST): f2ecf452 on 96161037, one round; the consensus crate whole 120 + 1 + 1, consensus-core 142, kaspa-pow 7; with the fields unset the digest is unchanged (the pinned devnet digest c562d70e read with the fields present; era_vdf_fields_enter_the_digest_only_when_set); at 0 it costs a node nothing for 180 days, then one core for an hour once; O-4.10 owed before any era 1.
The frozen sub-version 3 object (the Counter lane, 17:3x BST, handed to the node lane): igneum-pow 017e703764 on ca3-v4-amend (the audit-freeze-2026-10-07 tag; 2a111fb1 and 6941da1d above it are docs only). Object byte 7, PROGRAM_SUBVERSION_V4 = 3, the devnet epoch-0 program id a785001687d8688a (must-differ c120d7963abdcd96, 1a4230699a6b9c60, a788661687db4bb3); the kit packs-ca3-v4-sub3 zip sha256 4f2445c50c58d76a5544023492d8b858d0b07c5e372d31f9c90c4ce51f829154 (eight packs); fingerprints equal on Metal, Apple OpenCL, the fleet's 5090 (Linux CUDA) and PC 2 (Windows CUDA): mx8-devnet-epoch0 90f794dd556f7a3b (the v3 control), v4-devnet-epoch0 e370fb2080b7dbb1, era-0 b7237555d31fc3cf, era-1 b6b167fa15dfe2c9, era-2 28bdf65eff33f2c4, era-3 e26d38c46f3f1b16, era-4 dd8fdf6ff4f59eed, era-5 8bf40f5cb858d835. Both attack-pass gates GREEN on 017e7037 (the 64-seed hot-set census at 2^24: 60 of 64 under 1.2x; the exhaustion gate by construction and 0 of 24,631 chain-shaped seeds, max attempt 29); suite 103 of 103; CI success. Open, stated as open: the four-seed tail (p10 1.50x, p8 1.38x, p34 1.25x, p4 1.22x; main's ruling: the window model's unattributed residue with nil chip consequence; attribution for 0.3.23); the 10^6 chain-path count runs on as a strengthening line; the epoch draw costs about two attempts at 2.2 s once an hour; the owed measurements (G2, G3, the ladder, AMD on PC 1, the 2019-class core) do not gate Devnet 3. No further hash change rides 0.3.22. Devnet 3's object sets program_class_v4_activation_daa 0 and signals byte 7 from genesis.
1. The candidate: release-0.3.22-node = fa7f854f (16:37:50Z, 17:37 BST)
Three commits on 96161037: bd710a36 the sub-version 3 re-pin (byte 7, igneum-pow 017e7037, epoch-0 id a785001687d8688a, must-differ c120d796 / 1a423069 / a7886616); aded4620 era VDF (the era lane's f2ecf452, clean); fa7f854f the Devnet 3 object. The object: network igneum-devnet-3, flag --devnet --devnet-suffix=3, default p2p 26631 (ten above the previous suffix; gRPC, JSON and EVM on the devnet defaults unless passed); genesis 2026-10-07T00:00:00Z, payload "igneum-devnet-3 | 2026-10-07 | every upgrade on from block zero | coins here have no value | resets are announced", hash a6fa348e2a0fc6a5fa0ae3cb080160f5e2be865af71bac0068ca2fb8d1fcfd7b, bits 0x1d100000 (the DAA takes over after 600 blocks); active from DAA 0: difficulty v2, proving v0 and v1 (8 blocks a segment, 600 DAA, aggregator 1,000 bps, the fresh rule), finality v3, program class v3 and v4 (byte 7 from genesis, a one-day signal window), the latency ladder at rung 0, calibrated v1 fees, era VDF (main's ruling); at never (as on the live devnet, not in main's list): difficulty v3, the finality DAA-seconds rule, fork gate, peer directory, signing bonus, finality leave, pool split, consensus proof verify, exec restart (the chain executes from genesis). The node refuses --override-params-file on igneum-devnet-3 (mainnet, testnet, devnet suffixes 3 to 99; harness suffixes above 99 keep the file) and prints the digest with no file. Not in it: the N15 kept-datadir numbering class (p12-vast and pool-1 off by 2), 0.3.23's, the release note names it. Gates from 16:38Z: the release build on build-1 (gate priority); on build-2 the consensus crate whole, consensus-core, kaspa-pow with 017e7037's packs, the miner, the exec suite; then from the build the empty-datadir canary, the fresh-genesis digest agreement on two boxes, the late joiner, the shutdown under 1 s, the proving ids on a bare node.
build-1 for Devnet 3 (the build-server lane and the fleet, reconciled 17:40 BST), nothing started: the seed a bare process on p2p 0.0.0.0:26631 (rpc 27630, json 27632, evm 27810, empty datadir /home/build/dn3seed); the observer node on Devnet 3 is the fleet's instance (/srv/hands/bin/run-observer-node-dn3.sh, appdir /srv/hands/observer-node-dn3, rpc 26650, json 28650, p2p 26651, evm 26850, its observer.mjs on dn3_ tables running); the second node1 on p2p 0.0.0.0:26671 (rpc 26670, json 28670, evm 26870, appdir /srv/hands/node1-dn3, --enable-unsynced-mining); ufw allows 26631, 26651 and 26671; four units installed and DISABLED (igneum-observer-node-dn3, igneum-observer-dn3, igneum-hash-origin-dn3.service and .timer at 08:30 UTC with --prefix dn3_). On the go, in order: the 0.3.22 pairs under /srv/artefacts/0322-fa7f854f/ with the evm-types read, devnet3.env and dn3.env pointed at that igneumd, then seed --go, node1 --go, observer-node --go, each read back by the first log line, the string count, the devnet-3 digest line, the genesis line and the server lines.
Main (17:4x BST): fa7f854f accepted; the nine switches at never stay at never for the genesis (nothing untested flips under this clock); Devnet 3 is the chain they go live on by activation height, one at a time, each after its own gate, no further reset; consensus proof verify stays off until the proven share reads one. After genesis: the table of the nine (built and gated, built and ungated, not built; the owning lane; the earliest height) for the project lead.
The fleet's Devnet 3 set, STANDING at 16:44Z: five boxes on five hosts (the hive package, the kill file, box-dn3.sh, a vote key each, the binary slot empty until the artefact lands): dn3-g1 RunPod 3070 (64.119.209.250, p2p mapped 21703) = the Devnet 3 HUB and default peer; dn3-g2 Vast 3070 Utah (154.64.230.67, p2p 27017) = the second genesis node; dn3-j1 Vast 3060 12 GB = the late joiner from empty; dn3-c1 Vast 3060 12 GB = the empty-datadir canary (12 GB, so the prover statement reads there); dn3-x1 Vast 3060 12 GB = spare and second joiner; hairpin checked (every Vast box reaches dn3-g1's mapped port and build-1's 26631). The cutover dn3-genesis.py (per box: the binary with its sha read back, box-dn3.sh with --devnet --devnet-suffix=3, appdir /root/fleet/dn3, no override, FRESH=1, UNSYNCED=1 on the two genesis boxes only, seeds dn3-g1, dn3-g2, build-1's 26631 and 26671; read back the string, the devnet-3 digest, the genesis hash line, synced, the first lock; nothing named on the old devnet), dry-tested. The gate dn3-gate.py: digest agreement g1/g2, the same first lock on both, the late joiner synced from them, the canary mining ten minutes with its blocks held by dn3-g1 and 0 rejects, shutdown under 1 s then the restart on the kept datadir, the proving ids on a bare node; one line per check with its UTC time, DN3 GATE PASS/FAIL. hub-1's second node staged (36610/36611/36790, outbound only, FRESH, MINE=0). Pay-by-key on the new chain through dn3-g1. The watcher on /srv/artefacts/0322-*/ starts the gate within the minute of the binary. Capacity for day one: a SECOND NODE PER STANDING BOX (box-dn3.sh on 36610/36611/36790, FRESH from empty, the box's existing key label on the new chain, MINE=1 with a second miner on the same card), rolled in three waves of 5/5/4 after the genesis pair locks, nothing stopped on the old chain; plus the five gate boxes and hub-1's and build-1's second nodes: about 22 voters; cost USD 9.2/day for the five gate boxes, the second nodes USD 0, the 0.3.21 warm set 11.52/day; the fallback a parallel set of fourteen 3070 pods (USD 44/day) only if the first wave shows card contention (the read: the live miner's rate and the dn3 node's template timing). Spend at 16:40Z: 406.49 of 1,000.
The 0.3.21 set, running on: c22-1's wipe in IBD; the warm-set cases' window running; N15's live line: p2-4090-1b's kept snapshot tips were side-tip blocks on the hub's DAG, the node refused them rightly and loaded the hub's snapshot, healthy, no discontinuity line (the node lane holds the reading); p1-5090 now; roll lines p2-3090-2 2.3314 and p2-3090-3 2.8553 IGN verified by key.
Main (17:4x BST): yes to the second node per standing box, three waves of 5/5/4 after the genesis pair locks, nothing stopped on the old chain, with two conditions: (1) a 24-hour exception to the one-miner-per-GPU rule, not a new rule: when the apps move to Devnet 3 and the old chain's miners stop, each box is back to one miner (written as an exception with its end in the fleet notes); (2) the contention read on wave 1 decides the fallback mechanically: a live miner's rate on any of the five down more than 10 percent against its hour-before mean, or the dn3 node's template latency above the 0.3.20 gate figure, takes the 3070 set for the remaining waves without asking; spend under the USD 1,000 ceiling either way.
The app side of 0.3.22 (the shipper): the app's node starts on igneum-devnet-3 through its packaged config (Runtime.network "devnet" with devnet_suffix 3, read from igneum-app.json in the 0.3.22 package; the OTA update replaces the package, so the signed 0.3.22 update is the move), with node_dir devnet-3 (a fresh datadir beside devnet-v4, the old chain's kept for the way back), the node_override_file None on a suffixed devnet (the node refuses the file; the OTA manifest's consensus.override is ignored with a log line on devnet-3), the chain scene, the ladder, first-block and earnings reading the new chain from zero, the prover on the new chain's records; the manifest for the 0.3.22 publish carries channel "devnet-3". Cut after the genesis on its own branch release-0.3.22 off release-0.3.21's tip; published by signed update when Devnet 3 has 24 hours (main's clock).
5. The genesis: 69d1b56e, 18:06:19 BST
The timestamp fault and the fix: fa7f854f and 21d8f454 carried a genesis timestamp of 2026-10-08T00:00:00Z, so every block read "too far into the future"; the node lane's 69d1b56e sets 2026-10-07T00:00:00Z (genesis hash 4020cb4382e3fe4b…b925, test every_compiled_genesis_lies_in_the_past_of_the_clock). ab9af79f is void with it; the igneum-devnet-3 digest with no override file on 69d1b56e is 83eb50cdf2eda4cb…22b2.
Gates on 69d1b56e, every one green: build-1 release build 18:03:03 BST; box suites on build-2 (kaspa-consensus whole 120 + 1 + 1 at 18:02:17, igneum-exec 36 at 18:03:09, kaspa-consensus-core 152 at 18:03:40, kaspa-pow 17 at 18:04:31, igneum-miner 25 at 18:05:22 against the sub-version 3 packs); the canary set from the artefact (object 7 / 1794, era VDF from 0, ladder rung 0, fees v1, shutdown 677 ms after SIGTERM, the override file refused exit 1 while the shared devnet still takes it, two empty nodes handshaking with equal digests, the shared-devnet node rejected with the network mismatch); the pack gate PASS by construction on dn3-g1 (miner c29f33bb = the pair's, the pack exported on the box, the hive 0.3.20 miner 4050c255 refused); the program id read back fce15bf61030be57 (see the correction below).
The pairs: node-lane pair igneumd 0751598f (57,816,736 B) and igneum-miner c29f33bb under /srv/artefacts/0322-69d1b56e/node-lane/; the build-server lane's hands pair igneumd efb54938 (57,817,120 B, GLIBC_2.39) and igneum-miner 07246920 under /hands/, seed pair fb15cecf and f8c40e1c under /seed/ (the miners byte-identical to 21d8f454's: the miner does not embed the genesis). The shipper's ruling: the node-lane bytes stand as the genesis pair on dn3-g1 and dn3-g2; the hands pair goes on the joiners, hub-1 and build-1.
The genesis reading: dn3-g1 (the Devnet 3 hub, 64.119.209.250:21703) up 18:04:55 BST, "igneumd/2.1.0-69d1b56e", digest 83eb50cd, "genesis 4020cb43… executed: chain id 4463", miner from 18:05:19, FIRST BLOCK ACCEPTED 18:06:19.920 BST ("PoW accepted c313ddac… by igneum-lottery-v2-bound, daa 0, epoch seed 4020cb43…"), 85 of 85 GPU blocks by 18:10, 287 by 18:14, 0 rejected. dn3-g2 (154.64.230.67:27017) up 18:17:58 BST on the same pair, synced from g1 (639 blocks at 18:18:52), mining from 18:18:15; 702 blocks, daa 702 at 18:19:08, 0 rejected on either; finality checkpoints 20 (985353b4…), 21 (e788fac0…, blue score 631), 22 (f45336bd…, blue score 660) identical on both logs. The genesis declared on that agreement at 18:25 BST (main noted it at 18:18 BST). The object's finality window is 7,200 DAA, so no checkpoint can lock before about 20:10 BST; the first lock is a follow-up line, not a gate (the fleet's check 2 re-lettered to "first common lock within 30 minutes of DAA 7200"). The go to build-1's seed (26631), node1-dn3 (26671) and the observer unit on the hands pair went at 18:24 BST; the joiners dn3-j1, dn3-c1 (ten-minute canary) and dn3-x1 place on the hands pair. Nothing in the go path reads GitHub (both lanes confirmed: /srv/artefacts, the box mirror for the observer clone, the dl host for the hive package and the kit zip). The executor on a fresh devnet-3 node logs "waiting for consensus to sync before the executor starts (the sink is 61,000 s old)" until the first block, then executes genesis: expected (the genesis is 17 hours old by design), not a fault; runbook row.
Program id correction (the Counter lane, 18:1x BST): Devnet 3's epoch-0 class v4 program id is fce15bf61030be57 (read in the 0.3.22 miner's "cache ready" line on build-1 at 18:10:39 BST and on dn3-g1); a785001687d8688a is the SHARED devnet's epoch-0 id (genesis edc4fa84) and the kaspa-pow pairing pin, which is unchanged because the id follows the seed. Every Devnet 3 box's gate wants fce15bf61030be57 at epoch 0 and stops the miner on 1a4230699a6b9c60 or a785001687d8688a; the per-epoch form (the miner's line equals the node's seed-derived id, read each 3,600 DAA) is for after tonight. Both paired miners on dn3-g1 printed fce15bf61030be57, so the node drew Devnet 3's seed and the record is right.
The nine switches: recorded as section 6.11 of docs/plans/counter-asic-3-node.md (branch ca3-v4-node e70535fc on the box mirror, 18:15 BST), one row per switch with state, owner, gate and the earliest Devnet 3 height; signing bonus is not gateable on 69d1b56e (c7ea1e21 silent_split missing) and is 0.3.23's; every height reads as lock time + DAA seconds at 1 block/s.
Found by the 0.3.21 wipe canary, fixed 18:14:35 BST: the Hetzner live seed 188.245.5.161:26611 was still on the old sixteen-field object (digest eada4bda) one hour forty after the 0.3.20 sweep; it was never in a wave (the 15:56 go listed the hands and bps-seed, not it). Per tier: fleet voters, hub and pool-1 unaffected (they peer on the hub); every 0.3.20 app on the floor file saw a reject line at each dial of the seed and synced through the hub and node1 instead (c22-1 did); a fresh joiner configured with only the seed could not join. The build-server lane (infra/devnet/restart-seed.sh over the ops key) installed the c4459193 seed-class igneumd 4a2d8a8d and the floor file 294f1f80, unit igneumd-v4 down about 3 s, read-back "igneumd/2.1.0-c4459193", digest 4bbbe816 MATCH, 278 blocks accepted in the first minute. Rule 5 now names the seeds with a read-back line.
6. After the genesis: the clocks, the rulings, the 0.3.22 tree (18:3x to 18:5x BST)
DN3 GATE PASS (the fleet, 18:36 BST): digest and checkpoint agreement on dn3-g1/g2 (checkpoints 20 to 29 identical, lock line 855414eb identical), late joiner twice (dn3-j1, 911 then 1,099 blocks), canary blocks held (dn3-c1, 15 of dn3-g1's last 900), shutdown 589 ms, bare-node proving ids present; two of the six lines read by hand after script faults of the fleet's (inspect arguments reversed; a token read broken by spaces), both fixed and recorded. Eight nodes on five hosts plus build-1's seed, node1-dn3 and observer, all on 83eb50cd, about 1,900 blocks at 18:36 BST. The relay set dn3-relay, dn3-poison, dn3-twin rented for the cases. The first finality lock at DAA 7,200, about 20:10 BST; the second-node wave 1 on the standing boxes starts on that line (main's two conditions).
The two clocks (main): the 0.3.22 apps publish at 18:30 BST on 8 October on green (the 24-hour line is 18:06 BST); the first Discord card (Devnet 3 + 0.3.22) publishes after the fleet's relay run on Devnet 3 reads CASES END with the relay cell read AND the 0.3.22 apps are out; the card names the first-block time, the chain id and the launch-first chip line from master 9b996d06, no prize; staged at scratchpad/r0322/discord-card-devnet3-0322.md, main reads it after the relay run.
The 0.3.22 app tree and its order (accepted by main): release-0.3.22 at 27ab317e on the box mirror = release-0.3.21 44b63ac9 merged (7f07a37f) + driver-check 46cc41e9 (27ab317e; the eGPU driver-install hold and warning); app gate GREEN on build-2 at 18:33 BST (259 + 33 + 8, pre-push 56). Missing, in closing order: (a) the node pin = N15 dfae08e5 rebased onto 69d1b56e on release-0.3.22-node, gated, plus whichever switch heights are green by the cut; (b) the Windows node pair from build-1's cross and the payload inputs, the installer by the PC 2 job shape while GitHub is out, the Mac node pair and DMG on the Mac under the lock; (c) the hive 0.3.22 package with the sub-version 3 kit inside; (d) the manifest on channel devnet-3, KEEPING the floor file for the 0.3.20 and 0.3.21 apps until the intake shows no app below 0.3.22 for 24 hours (main's ruling; the 0.3.22 app ignores the file by construction); (e) the app's vote key hash to the intake and the publisher's --public ui arm; (f) node_peers adds dn3-g1 64.119.209.250:21703 and dn3-g2 154.64.230.67:27017 beside build-1.
the project lead's ruling on the nine switches (through main, 18:4x BST), executed by the node lane on Devnet 3 by activation height, each with its gate line and a read-back on every node, no reset, one at a time: (1) peer directory, pool split, fork gate ON in that order, each height set the moment its 6.11 condition reads true; (2) difficulty v3, the finality DAA-seconds rule, finality leave up: mid-chain crossing tests on the fast-time harness tonight, each height set as its test goes green; (3) signing bonus: one paragraph for the project lead on whether it changes total minted supply or only who is paid, with the number; (4) mandatory proof verification ON after 24 hours of every Devnet 3 block proven on the hash-origin report, the fleet's provers on Devnet 3 from tonight, the share reported hourly; (5) exec restart never. Mechanics (main): a height is a constant in the igneum-devnet-3 Params of a node commit, rolled out by the sweep (one box at a time, commit string and height line read back, the hub first); never a file, no new signed-record mechanism; one commit may carry several heights staggered so the chain crosses them one at a time; a node that misses the commit forks off at the height, as designed, which is the test; each commit is a release of the node line (0.3.22, 0.3.23) and reaches the apps by the signed update. Recorded in 6.11 by the node lane as heights are set; each height to main as a clock reading.
Testnet re-arm (main, through the build-server lane): the arming on fork e6dd3afd (digest 4fbb2152, genesis 01294fd3) is void (old object; a go on it hard-forks at sub-version 3). The node lane cuts a testnet genesis object on release-0.3.22-node in the Devnet 3 shape (byte 7 from genesis, every activation at 0 that Devnet 3 has at 0, era VDF at 0, a past genesis timestamp with the future-genesis test beside it, no override file, the testnet's seeds and chain id as they are); the build-server lane builds the seed-class pair under /srv/artefacts/testnet-/seed/ and dry-runs wave1-0320.sh against seed1/2/3 at height 0; nothing onto a seed and nothing mines before the project lead's word (not before 15 October, LG-2).
0.3.21 Windows, the toolchain finding (18:37 BST): PC 2's installer job (take 2, 68 s) verified the payload (igneum-app.exe 151803c7 prints "igneum-app 0.3.21", igneumd.exe 49502cc7 "igneumd 2.1.0") and stopped on PC 2's toolchain: no MSVC (no window host "Igneum Miner.exe", whose host.cpp changed in update-return-21) and no Inno Setup 6 (no installer; winget refused by the job as told). Three shapes put to main at 18:45 BST: the Mac entry now and Windows later (the manifest carries a platform that lands later; 0.3.20 Windows apps do nothing until their entry arrives); winget Inno Setup on PC 2 (still no 0.3.21 host); the host by mingw on the box (dry compile asked) or Windows held until GitHub returns and windows.yml runs. deploy.sh carries --mac-only for shape (1); the full preflight stands for the Windows entry.