19 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 017e70376489251e18564c0abce7e466e606c8b3 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).
2. The candidate moved to 21d8f454 (16:43:11Z); every box gate GREEN by 16:48:48Z (17:49 BST)
21d8f454 = one test-only commit on fa7f854f (the signalling integration tests read object 7 as 1794, the pow pairing test allows sub-version 3's retried draw, the miner's pool test fills the era fields); every gate runs on the exact commit, so fa7f854f's build (1db7c6ac) is void. On 21d8f454: the release build on build-1 GREEN 16:45:19Z (igneumd sha256 b96b424c7b284501306dbf4a76657fd1e359c0c6532c59a0daf431547fcca21d, carrying 21d8f45; igneum-miner c29f33bb…; the artefact at /srv/artefacts/0322-21d8f454/, handed to the fleet); igneum-exec 36 of 36 (16:45:31Z); kaspa-consensus-core 151 of 151 (16:48:25Z, the parent's fast-time file carrying the era fields); kaspa-pow 17 of 17 with the sub-version 3 pairing id a785001687d8688a (16:47:10Z); kaspa-consensus whole 120 + 1 + 1 at object 7 (16:47:54Z); igneum-miner 25 of 25 against the sub-version 3 packs (16:48:48Z; cpu_recheck reads a785001687d8688a). The canary set from the artefact on build-1 (16:45:53 to 16:47:11Z): the empty-datadir start GREEN (data dir igneum-devnet-3; "stamps object version 7 into its headers (block version 1794)"; "Era VDF active from DAA 0: scheme 0 (class-group), T 108000000, era 15552000 DAA, lead 7200"; the ladder at rung 0 with 27 shadow passes; calibrated v1 fees from DAA 0; proving v0 and v1 from DAA 0 with the embedded keys resolving both ids on the bare node); the igneum-devnet-3 digest with no file ab9af79f40cd9b5fbed2577406d6b32e103bd86a7dd26df2aabceb7b673ced23; shutdown under 1 s (571 ms); the override file refused on devnet-3 with exit 1 (the known-failed case) while the shared devnet still takes it (eada4bda unchanged); two empty devnet-3 nodes handshake on protocol 17 with equal digests; a shared-devnet node dialling devnet-3 rejected "Network mismatch - local: igneum-devnet-3, remote: igneum-devnet". The node side is ready at 17:49 BST. Remaining before genesis, the fleet's: the fresh-genesis agreement on dn3-g1 and dn3-g2 from empty, the late joiner's sync; then the genesis clock. The prover pair stands (21d8f454:igneum/evm-types = fe4145b9, the exec pin's tree).
The app side (release-0.3.22 at 5f1652c0 on origin): the package names the network (igneum-app.json node_devnet_suffix and node_peers; Runtime::from_env_with when the environment is silent; node_dir devnet-3 beside devnet-v4, the old chain's datadir kept for the way back); no override file on a suffixed devnet from 3 (the manifest's consensus override ignored with one log line); the version strings 0.3.22; the app gate on build-2 258 + 32 + 8. Packaged peers for devnet-3 (the fleet, 16:50Z): build-1's seed 188.40.146.49:26631 and node1-dn3 188.40.146.49:26671 only (dn3-g1's and dn3-g2's mapped ports are not stable across a pod restart; they stay the fleet's seeds for the fleet's nodes); a third static peer would be a Hetzner box or the project lead's GEX45-1, outside the fleet's rent. Next on the app side: packaged-config.sh and make-payload.sh writing the two fields for the 0.3.22 DMG and installer; the manifest's channel "devnet-3"; the publish by signed update when Devnet 3 has 24 hours.
3. Devnet 3's first node (the fleet, 16:50:21Z, 17:50 BST)
The 21d8f454 pair pulled from /srv/artefacts/0322-21d8f454/ at 16:49:56Z (igneumd b96b424c…, the string read back on the Mac and the box; the miner c29f33bb…). dn3-g1 (the Devnet 3 hub, 64.119.209.250:21703): appdir wiped and the node up at 16:50:21Z, "igneumd/2.1.0-21d8f454", "Consensus params digest: ab9af79f40cd9b5fbed2577406d6b32e103bd86a7dd26df2aabceb7b673ced23" (the node lane's build-1 read agreed), "genesis a6fa348e2a0fc6a5fa0ae3cb080160f5e2be865af71bac0068ca2fb8d1fcfd7b executed: chain id 4463, registry at 0x…0210", "Program class signal active: object version 7 (block version 1794)", "Era VDF active from DAA 0: scheme 0, T 108000000, era 15552000 DAA, lead 7200", "Latency ladder active: rungs 27, 35, 53, [88], [173], [267] shadow passes, this node signals none", "Fees on igneum-devnet-3: pgas table v0 … calibrated v1 from DAA score 0", "exec sync: no snapshot to resume from; the follower starts at genesis"; network igneum-devnet-3, no override file. At 16:50:41Z blocks 0, daa 0, tips 1, peers 0; the miner started 16:50:42Z (unsynced mining on, the genesis box). dn3-g2 (154.64.230.67:27017) starting with dn3-g1 and build-1's seed as peers; next: the pair's digest agreement, their handshake, the first common lock (the genesis clock), then the late joiner.
4. The start incident and the ruling (16:55Z; 17:5x BST)
Two pairs sat under /srv/artefacts/0322-21d8f454/: at the root the node lane's gate build (igneumd b96b424c, 57,816,736 B, placed 16:45:30Z, the string 21d8f454 twice, ZERO igneum-pow/src/ paths) and under hands/ the build-server lane's pair built from 21d8f454 inside the app tree with igneum-pow at 017e7037 (igneumd d208b86721587484f8ab3cd6d73a417d14cdd879348daf652b75519ddd2c742b 57,817,120 B with 6 pow paths; igneum-miner 07246920fd9fe895ec0d9cf2e07e27663f69c2d0804a7ee20fb90c3689fe0299 with 9; the seed/ twin 50a56e9c37469940ccf7860c20425a5bc71fb2eb94c738a8038b09d678f9db11 / f8c40e1c7206e0ef9f38af30658c35b6b65f99e29e412806df8dd63437d512af, GLIBC_2.34). dn3-g1 started on the root pair at 16:50:21Z and rejected every block its own igneum-pow miner found ("Reject(BlockInvalid)" from 16:50:42Z, 0 PoW accepted in five minutes) while igneum_getNodeInfo printed powEngine "igneum-pow". The fleet stopped the go before dn3-g2 or the joiners started. Main's ruling: the root binaries are a stub-engine build and are deleted; the hands/ pair and its seed/ twin are the 0.3.22 artefact and the publish's sha lines name them; the engine link check becomes mechanical on every artefact fetch, canary start and fleet placement (release-rules.md 6a); the node lane never builds a release binary outside an app worktree. dn3-g1 wiped and restarted on the hands/ pair (sha, string and pow-path count read back first), the go rerun from there, the gate sequence unchanged; the genesis clock moves about ten minutes and is reported as a reading when the pair locks. The prover pair stands (evm-types fe4145b9).