16 KiB
Counter ASIC 3.0: the node-side gates for class v4 (mx8+sh256x27)
6 October 2026, worker "ca3-v4-node". The rows in the shape of docs/plans/counter-asic-2-rollout.md section 7. Trees: main ca3-v4-node a522d04 (igneum-pow, the workers, the harness, on ca3-coord 3213ee9), fork ca3-v4-node 5f7e0543 (on release-0.3.13-node bb43e9a8, the current release tip, which contains release-0.3.12-node). Builds: the Mac built igneumd and igneum-miner (target-ca3v4/release, --features kaspad/igneum-pow, warm from an APFS clone of the 0.3.13 target dir, under with-lock.sh build, nice 19, 4 jobs) and igneum-bench (the Metal worker, swiftc -O); the suites went to PC 2. The Mac's installed app was not touched (its miner stays paused); nothing was published; the live devnet was not touched. The Mac's load average during the runs: 5 to 12 (other agents' builds); the gates here count blocks, lines and ids, not rates, so the load does not move them.
| # | Gate | Evidence required | State |
|---|---|---|---|
| G4 | the fast-time 3-node network mining across a v4 activation | 0 rejected blocks, 0 forks, every node's first lines show the switch, blocks on both sides of the boundary; the gate fires on one finished and one failed case | GREEN. Run 1 (15:54:32 to 15:59:21Z, node infra/fast-time/class-v4.mjs --secs 420 --activation 150 --v3-activation 60 --epochs-after 2 under with-lock.sh run; three nodes, one real CPU miner each with --engine igneum-pow, every node verifying the other two): 3 of 3 nodes print both switch lines (Program class v4 from the override file: active from epoch 3 (DAA score 150 rounded up to the epoch boundary at 180, epochs of 60 DAA) and the v3 line for epoch 1 at DAA 60); templates class 2 for epoch 0, class 3 for epochs 1 and 2, class 4 for epochs 3 to 5; the switch seen at DAA 180, 163.9 s wall; 181 blocks before and 128 after DAA 180 (309 in all, selected chain 177 / 127); program ids agree on all three miners (e0 v2 8f8806638d59850f, the same v2 id as 2.0's three runs; e1 v3 29ced0d031cc121b, e2 v3 341fd4076256cd7b, e3 v4 070ca0f94e7f8f88, e4 v4 b8cbe1ef7ab1d748, e5 v4 9321cbd9c54c0b83; no v2 or v3 id reappears under v4); rejected 0/0/0 on the miners and 0/0/0 on the nodes (103, 103, 102 accepted); one sink 4da9ac669effdfab on all three at 308/308/308 blocks, one tip each; digest 59a3eb5383bfbf23... on all three; program and cache ready on one core: v2 epoch 0 199 ms, the first v3 epoch 187 ms (its own day cache), the first v4 epoch 2 ms (the v3 day cache reused across the N5 boundary, no rebuild). Summary class-v4-20261006-1553Z-cpu.json. Run 2, the known-failed case (15:59:46 to 16:02:17Z, --activation never --v3-activation 60 --secs 150): every node prints Program class v4 from the override file: never; the harness reports SUMMARY FAIL: NO v4 epoch seen with five checks down (v4_switch_line_names_the_rounded_epoch, template_switched_at_the_first_v4_epoch, blocks_after_the_boundary, v3_and_v4_programs_seen, program_ids_differ_across_the_switch), exit 1; the v3 side of that run was clean (epochs 0 v2, 1 and 2 v3; 0 rejected; one sink 166/166/166). Summary class-v4-20261006-never-failed-case.json. Re-run on the program-id fix 7c22d0d (16:32:39 to 16:38:08Z, igneumd and igneum-miner rebuilt on the fixed igneum-pow, the harness with the id assertion; load average about 90 from other agents' builds, which moves the wall times, not the counts): PASS, every check true; 3 of 3 v4 and v3 switch lines; 181 / 125 blocks across DAA 180 (305, selected chain 168 / 120); rejected 0/0/0 and 0/0/0; one sink b7881306c83b1206 at 305/305/305; the PROGRAM ID rows, one per v4 epoch, the three miners' id against the CLI's same-seed, same-era class v4 and class v3 ids (`igneum-pow show --epoch-hex --program-class v3 |
| G4b | the Mac mines v4: a real Metal miner across a v4 boundary through the miner's --prepare-packs flow, and the app passes that flag to the Metal worker |
the prepare lines on both sides, the worker's prepared line for the v4 pack, found or accepted blocks on v4, no need or mismatch line, no exit 42 or 44; the app's miner_args pushes --prepare-packs for every worker |
GREEN. Run 3 (16:02:37 to 16:07:58Z, --metal proto-metal/igneum-bench --genesis-bits 0x1e010000 --secs 480 --activation 150 --v3-activation 60; node 0's miner is igneum-miner --worker igneum-bench --prepare-packs <dir> --exit-on-seed-change, the app's own shape; igneum-bench built from this tree at a522d04's main.swift, sha256 30c70754...; CPU miners on nodes 1 and 2): 5 PREPARE lines, each 5 to 6 DAA before its boundary, two class v3 (DAA 60, 120) and three class v4 with the pack directory and class=v4 era=<hex> (DAA 180, 240, 300); the worker's prepared lines for the three v4 packs: prepared ca4245b5... 430.2 program 193.9 dataset 236.2 race 0.0 variant base class v4 loads/hash 128 cache-fill 1.4 build 70.1 (the first, the v4 day built from the pack's memhard.metal on the GPU: 1.4 ms cache fill, 70.1 ms build), then 138.6 and 175.3 ms with the day resident (program compile alone, the 256-instruction shadow block in the kernel text; a v3 prepare was 61.7 ms); every swap swapped with no pause at DAA 60, 120, 180, 240, 300 (prepared 2 to 5 s earlier); 301 blocks accepted by the Metal miner, 123 after the switch, every one re-checked on the CPU: mismatched=0; need 0; no class or era mismatch line, no PACK OUT OF DATE, no prepare-failed, no exit 42 or 44 (0 such lines in the miner's log); the chain 182 / 122 blocks across DAA 180 (304), rejected 0/0/0 and 0/0/0, one sink 4e1aa3fbf1f4a54b on all three at 303/303/303, 3 of 3 v4 switch lines; program ids e3 v4 2bcecca6f867c3b5, e4 21b78e63fc0e9251, e5 3855570a5ba12fc9 agreed by the Metal miner and the CPU miners; the Metal miner's STATUS at 309 s: 18.58 MH/s wall, 293 accepted, 0 rejected (a rate under a load average of 5 to 12 with the CPU miners and other agents' builds beside it: an order of magnitude, not a measurement). The app side: app/igneum-app/src/engine.rs miner_args pushes --prepare-packs for every worker (line 1478, the 0.3.11 fix; unit test every_worker_gets_the_prepare_directory_in_the_platform_form), confirmed unchanged on ca3-coord 3213ee9. Summary class-v4-20261006-metal.json |
| G5 | the PC-built Windows workers and the Mac workers from the same commit | every sha256 listed; the two Windows workers carry the resource block; no packaging, no DMG, no manifest | GREEN on the program-id fix 7c22d0d (packfile.h and main.swift moved, so the workers were rebuilt from it; the earlier pair from a522d04 is superseded): igneum-worker-cuda.exe 3bc8ad8f69ad97d6a9491a734ef16e3cf10b3884d442fb1e5a490c751ae578c5 (1,536,512 bytes), igneum-worker-opencl.exe 16ef015470d7a45c5af5488dcc68a29c5e95f94487eb05e26f1bf418e6dd511f (478,208), verify-exe.py: both carry the coin icon and the version block; the Mac worker igneum-bench f9ca4b075a9a9c25afd8feeccd1339fbb6bb4c3728ffeddab9f549cd3c1725a4 (665,128, the binary of the G4 re-run); the node and app binaries of job build-20261006-155958 stand (the fork did not change). The a522d04 row for the record: the build job builds the node and the app only (push-build-inputs.sh writes two build units, jobbuild.rs has no worker unit), so the Windows workers were cross-built on the Mac from the committed tree a522d04 with proto-cuda/nvrtc/build-windows.sh under the build lock (mingw-w64, static, windres resource block), as 0.3.11's G5 row was: igneum-worker-cuda.exe e563126ed1d8ab8f6803ead89acca5b6fcb03203e6b87b70e0aec85e8e1046e4 (1,536,512 bytes), igneum-worker-opencl.exe 7fce1249d443aaf73a29b7474c1ef4084f3529b5bec3a2dc6bb97e624561a5e8 (478,208), verify-exe.py: both carry the coin icon and the version block (a first build of the same sources before the commit gave 26400edf... and 438e608a...: mingw stamps a link time, so the pair is not bit-reproducible; the sizes match the 0.3.11 pair, 1,536,512 and 478,208, and the sha256s differ from 0.3.11's 2b3b8c92... and edc4a75d...: the generator-4 rule is in them). The Mac worker from the same tree: igneum-bench 30c70754097dafbc3144a0c0f192526a0638089e5dde49ce46abb7a948dceade (665,128 bytes, built 16:47Z from main.swift as committed in a522d04, the binary G4b mined with). The same build job's (build-20261006-155958) node and app outputs from fork 5f7e0543, every sha256 verified against the PC's lines on fetch: igneumd.exe 140be25e486fe1634500b6e66eedfaca9fa6561d652f3e219b5a7a2bc377e766 (51,752,448), igneum-miner.exe ceb1e691ad57f58d09d5a0ff4cb5658aea0604d23ceb90b6a847a2c36a0bf81c (11,118,080), igneum-app.exe bfa3b871f17b69fd0c0c01a6f9fcac8964efb54dc10fd25db13422ba8f96d51f (3,065,344, PE and resource block ok); Linux igneumd d44b735869b129401d68f18786b4a5f16c22d00b682bd41a8e5022a01f7d7527 (49,603,112), igneum-miner a7985111d4972f4b67a9409b831a8c7af746508ebb3b19fc927aaddcfa2e2413, igneum-app 222f30c00bb9725f3127452f3d52403b380e25abaf9fba5c925839574cf1dabc; kept under the job's --out dir with --no-place. No packaging, no DMG, no manifest |
| G6 | the node change on a fork branch from the current release tip with suites green on PC 2, with the igneum-pow feature | the build job id and its SUMMARY line; the v4 engine test named in the output | GREEN. PC 2 job build-20261006-155958 (fork ca3-v4-node 5f7e0543, main a522d04; published 15:59:58Z after the clear file and under the mkdir lock, taken 15:58:50Z, released 16:08:06Z after the closing report; the installed app untouched, the prover left on), node tools/build-job.mjs run --target 1ccfe586 --node vendor/igneum-node-ca3v4 --node-tests "kaspa-consensus kaspa-consensus-core igneum-exec kaspa-pow igneum-miner kaspa-p2p-flows" --app-tests igneum-app --no-place: done exit 0 after 392 s: node ca3-v4-node 5f7e0543 app 0.3.11: every stage ok; 9 files uploaded (46 MB); 6 min of 40; the test stage 50 s, exit 0 on both units: kaspa-consensus 98 passed (3 ignored; ban_is_decided_by_the_carrying_block_so_nodes_agree_on_every_voter_list ... ok, so 2.0's flake did not recur and no re-run was needed), kaspa-consensus-core 109 + 7 (override_params_carry_the_program_class_v4_activation ... ok), igneum-exec (its per-crate line is not in the relay's upload of the report, which keeps the stage's tail; the unit exited 0, so it passed), kaspa-pow 15 (program_class_v3_seeds_hash_their_own_program_over_their_own_cache ... ok and program_class_v4_seeds_hash_the_shadow_program_over_the_v3_day_cache ... ok, both #[cfg(feature = "igneum-pow")]), igneum-miner (the same: not in the upload, in the exit-0 unit), kaspa-p2p-flows 33, igneum-app 112 + 26 + 8. The feature: build-job.mjs and push-build-inputs.sh carry no --features for the test units (the manifest's tests entries are dir and packages only; the build units have kaspad/igneum-pow), and the PC's jobbuild.rs runs cargo test --release -p ... in ONE invocation per unit, where igneum-miner depends on kaspa-pow with features = ["igneum-pow"], so cargo's feature unification turns the feature on for kaspa-pow's test target in that invocation: the two engine tests above ran on PC 2 with the feature, named in the report, which is the evidence main asked for. The same two suites also pass on the Mac with the flag explicit (cargo test --release -p kaspa-pow --features igneum-pow: 15; -p kaspa-consensus-core: 109 + 7). What the tool lacks: a features key on a test unit; not added here (a change to the PC's installed app would be needed to honour it) |
The cut preconditions (the coordinator's second brief, 6 October 2026 evening)
| # | Gate | Evidence required | State |
|---|---|---|---|
| P1 | the rehearsal plan and the v4 override object for the rented fleet | docs/plans/counter-asic-3-rehearsal.md; the objects with their digests |
WRITTEN (not run: the fleet agent runs it): the publish object (the live 13 fields plus the floor N6 and the window 86,400; digest ac8e60ce205852bdda6b554f8cbfbd9dbb040187f487cbd8affe8103633dfd56 at the worked example N6 = 219,600) and the rehearsal object (every earlier switch at 0, window 3,600, floor 14,400; digest bc2142b178ff367ae84ff0699ff523760d8878f883375da21864ed8d3ad39237), both read from the signalling node's start lines on throwaway private networks; override-v4-publish-example.json and override-v4-rehearsal.json in this directory |
| P2 | miner-signalled class activation, implemented behind the override, the fast-time gate with three cases and the failed case | docs/plans/counter-asic-3-node.md section 6; infra/fast-time/class-v4-signal.mjs |
GREEN on the Mac: two of three signalling never flips (7 epochs, 6,166 to 7,583 bps), all three flips at epoch 3 (the first full window, 10,000 bps, the same line on 3 of 3 nodes, the id assertion), nobody signalling flips at the floor epoch 5 and not before; the known-failed case fails on eight checks. Rows and summary files: node doc section 6.4; class-v4-signal-{no-flip,flip,floor,failed-case}.json |
| G6 (signalling) | the fork change on PC 2 with the igneum-pow feature | the job ids and their lines | GREEN on fork 0562a7f2 (main f39a8eb), three PC 2 jobs under one clearance ("PC 2 open for G6", 17:27Z), the mkdir lock taken 17:28:15Z and released 17:38:58Z, then 17:39:41Z to 17:55:31Z; prover on, app untouched. Job 1 build-20261006-173017 (the six crates and the app): every build stage ok, the app tests 112 + 26 + 8, but kaspa-consensus 97 passed and 1 FAILED on 2.0's known flake ban_is_decided_by_the_carrying_block_so_nodes_agree_on_every_voter_list (UnexpectedDifficulty(.., 487111630, 487128802) in mine_on_all, the 0.3.10 cut's section 11 case, which also passed on the Mac and in this morning's job 155958), and cargo stopped the unit there. Treated as 2.0 did: job 2 build-20261006-174027 (kaspa-consensus alone, 17:40 to 17:46Z): RESULT test node [kaspa-consensus] exit 0 19 s, done exit 0 after 345 s ... every stage ok. Job 3 build-20261006-174823 (the five crates and the app, 17:48 to 17:55Z): RESULT test node [kaspa-consensus-core igneum-exec kaspa-pow igneum-miner kaspa-p2p-flows] exit 0 35 s and RESULT test app/igneum-app [igneum-app] exit 0 5 s: kaspa-consensus-core 110 + 7 (override_params_carry_the_program_class_v4_activation ... ok, the signal window test inside it), igneum-exec 18, kaspa-pow 15 (program_class_signal_rule ... ok is consensus-core's; kaspa-pow's program_class_v4_seeds_hash_the_shadow_program_over_the_v3_day_cache ... ok, the feature on), igneum-miner 18, kaspa-p2p-flows 33, igneum-app 112 + 26 + 8; the job's own closing line reads failed ... upload incomplete because the relay's blob service refused one of the nine uploads (igneum-app.exe.zst FAILED: blob PUT: no url in the reply: service_unavailable, the shipper's 17:25Z fault) AFTER both test stages had closed with exit 0, so the STAGE and RESULT lines are the evidence, as the shipper's warning said. Where the runs went: these three on PC 2 under the clearance given before the build-server rule arrived (18:0xZ); no further Linux build or suite is needed by this brief; the next one from this lane goes to igneum-build-1 through tools/build-remote.sh |
Summary files in this directory: class-v4-20261006-1553Z-cpu.json (G4 run 1), class-v4-20261006-never-failed-case.json (G4 run 2, the failed case), class-v4-20261006-metal.json (G4b), class-v4-20261006-id-rerun.json (G4 on the program-id fix, with the id assertion), class-v4-20261006-id-failed-case.json (the id assertion's failed case).