Counter ASIC 3.0 gates (node): the rehearsal's miners are the GPU workers (the object inherits the devnet genesis bits); the id assertion on a worker box reads the pack's program.h

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
igneum-josh 2026-10-06 19:38:26 +01:00
parent c541fcfc4d
commit ff92dab83e
2 changed files with 4 additions and 4 deletions

View file

@ -13,7 +13,7 @@
| # | Gate | Evidence required | State | | # | 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 on the devnet network id `65a42ab2e63d93ac02acf761b411b31acac6c9413bbd0c6a2f4cced10509efdf` at the worked example N6 = 219,600, fork 0562a7f2), the rehearsal object (every earlier switch at 0, window 3,600, floor 14,400; digest on suffix 400 `aef46983dfd121d5ecbefd056ff02d001b89315bd0547b4e1007b0b0ee7eee2c`) and the re-cut for the hour (600-DAA epochs, window 600, floor 2,400; digest on suffix 400 `a15db4f0d6a5cc891582760ef5593e69014a5133261def84647cb7617528764f`, the value the 16 fleet boxes printed); CORRECTED 18:4xZ: the digest folds the network id in, and the first values (`ac8e60ce`, `bc2142b1`, `d23394e7`) were read on throwaway suffixes; `override-v4-publish-example.json` and `override-v4-rehearsal.json` in this directory | | 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 on the devnet network id `65a42ab2e63d93ac02acf761b411b31acac6c9413bbd0c6a2f4cced10509efdf` at the worked example N6 = 219,600, fork 0562a7f2), the rehearsal object (every earlier switch at 0, window 3,600, floor 14,400; digest on suffix 400 `aef46983dfd121d5ecbefd056ff02d001b89315bd0547b4e1007b0b0ee7eee2c`) and the re-cut for the hour (600-DAA epochs, window 600, floor 2,400; digest on suffix 400 `a15db4f0d6a5cc891582760ef5593e69014a5133261def84647cb7617528764f`, the value the 16 fleet boxes printed); CORRECTED 18:4xZ: the digest folds the network id in, and the first values (`ac8e60ce`, `bc2142b1`, `d23394e7`) were read on throwaway suffixes; CORRECTED 18:5xZ: the rehearsal chain inherits the devnet's genesis bits (the object sets none; the fast-time harness lowers them), so its miners are the GPU workers, not 1-thread CPU miners (the fleet's 16 CPU miners at about 80 kH/s against about 2^27 hashes a block held the height at 0 for 20 minutes); the id assertion on a worker box reads the id from the exported pack's program.h (the `program pack checked ... <dir>` line names it), the Mac side unchanged; `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` | | 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 | | 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 |

View file

@ -55,12 +55,12 @@ With this object the step-7 line reads `epoch 2 (share 10000 bps over 600 DAA ..
| 1 | Fetch the signalling commit's Linux binaries from the G6 build job (the shas in node-gates.md), verify every sha256, place `igneumd` and `igneum-miner` on every box; the 0.3.13 Linux `igneumd` on the stale box | every sha matches | | 1 | Fetch the signalling commit's Linux binaries from the G6 build job (the shas in node-gates.md), verify every sha256, place `igneumd` and `igneum-miner` on every box; the 0.3.13 Linux `igneumd` on the stale box | every sha matches |
| 2 | Write the rehearsal object (2b) as `override.json` on every box, byte for byte (sha256 the file on each box and compare) | one sha on every box | | 2 | Write the rehearsal object (2b) as `override.json` on every box, byte for byte (sha256 the file on each box and compare) | one sha on every box |
| 3 | Start the seed box: `igneumd --devnet --devnet-suffix=400 --nodnsseed --disable-upnp --listen=0.0.0.0:16411 --rpclisten=127.0.0.1:16410 --rpclisten-json=127.0.0.1:16412 --override-params-file=override.json --utxoindex --enable-unsynced-mining --yes --appdir=<fresh dir>` (ports of the box's choosing, never the live devnet's 26610/26611); read its first lines: `Consensus params digest` equals 2b's, `Program class v4 from the override file: active from epoch 4 (DAA score 14400 ...)`, `Program class v4 signal window from the override file: 3600 DAA ...` | the three lines | | 3 | Start the seed box: `igneumd --devnet --devnet-suffix=400 --nodnsseed --disable-upnp --listen=0.0.0.0:16411 --rpclisten=127.0.0.1:16410 --rpclisten-json=127.0.0.1:16412 --override-params-file=override.json --utxoindex --enable-unsynced-mining --yes --appdir=<fresh dir>` (ports of the box's choosing, never the live devnet's 26610/26611); read its first lines: `Consensus params digest` equals 2b's, `Program class v4 from the override file: active from epoch 4 (DAA score 14400 ...)`, `Program class v4 signal window from the override file: 3600 DAA ...` | the three lines |
| 4 | Start every mining box the same way with `--connect=<seed>:16411`, then its miner: `igneum-miner mine grpc://127.0.0.1:16410 1 100000000 <label> --engine igneum-pow --no-vote --payout-label <label>` (a CPU miner; a GPU box uses `--worker <path> --prepare-packs packs/prepare --exit-on-seed-change`, the app's shape) | every box's node prints the same digest and the two switch lines; every miner prints `epoch seed ... class v3 program id ...` for epoch 0 | | 4 | Start every mining box the same way with `--connect=<seed>:16411`, then its miner on the box's GPU worker, the app's shape: `igneum-miner mine grpc://127.0.0.1:16410 1 100000000 <label> --engine igneum-pow --worker <igneum-worker-cuda> --worker-args "--pack packs/devnet" --prepare-packs packs/prepare --exit-on-seed-change --no-vote --payout-label <label>`. CORRECTED 18:5xZ from the run: the rehearsal object inherits the devnet's genesis bits (the fast-time harness lowers `genesis_bits` to 0x1f010000, 2^16 hashes a block; the object does not), so a 1-thread CPU miner (about 5 kH/s a box, 80 kH/s for 16, the fleet agent's reading) against the genesis difficulty (about 2^27 hashes a block, the fleet agent's figure) finds a block every 28 minutes for the whole fleet and the height stayed 0 for 20 minutes; the GPU workers find blocks at the chain's 1 a second | every box's node prints the same digest and the two switch lines; every miner prints `program pack checked for epoch seed <E> day <D>: attempt <A>, <dir>` for epoch 0 and the worker's `ready ... self-test PASS` |
| 5 | Start the stale box last, the same command on the 0.3.13 node, `--connect=<seed>:16411` | its log shows the handshake refusal (a digest mismatch line or `0 peers` after 60 s with connection attempts in the log) and its chain stays at its own genesis (block count 1 or its own lonely blocks if it mines; it must NOT mine: no miner on it) | | 5 | Start the stale box last, the same command on the 0.3.13 node, `--connect=<seed>:16411` | its log shows the handshake refusal (a digest mismatch line or `0 peers` after 60 s with connection attempts in the log) and its chain stays at its own genesis (block count 1 or its own lonely blocks if it mines; it must NOT mine: no miner on it) |
| 6 | Every 15 minutes, on every mining box: `getBlockDagInfo` (block count, sink, virtual DAA) and one `getBlockTemplate` (`powEpoch.programClass`, `nextProgramClass`, `programClassV4SignalBps`, `programClassV4SignalEpoch`); keep the lines | the shares read 10,000 bps on every box from the first template; sinks agree across boxes at each sample | | 6 | Every 15 minutes, on every mining box: `getBlockDagInfo` (block count, sink, virtual DAA) and one `getBlockTemplate` (`powEpoch.programClass`, `nextProgramClass`, `programClassV4SignalBps`, `programClassV4SignalEpoch`); keep the lines | the shares read 10,000 bps on every box from the first template; sinks agree across boxes at each sample |
| 7 | At DAA 7,200 (about 2 h): every box's node prints `Program class v4 by miner signal: epoch 2 (share 10000 bps over 3600 DAA ending at seed block <hash>, threshold 9500 bps, N of N blue blocks)` with the SAME seed block hash and the same N on every box; the templates read class 4 from epoch 2; every miner prints `epoch seed <S2> ... class v4 program id <id>` | the same `<S2>`, the same `<id>` on every box | | 7 | At DAA 7,200 (about 2 h): every box's node prints `Program class v4 by miner signal: epoch 2 (share 10000 bps over 3600 DAA ending at seed block <hash>, threshold 9500 bps, N of N blue blocks)` with the SAME seed block hash and the same N on every box; the templates read class 4 from epoch 2; every miner prints `epoch seed <S2> ... class v4 program id <id>` | the same `<S2>`, the same `<id>` on every box |
| 8 | Run to DAA 10,800 (epoch 3, one epoch after the flip; two epochs after is 14,400, the floor, so the run stops at 10,800 plus 600) | the final sample | | 8 | Run to DAA 10,800 (epoch 3, one epoch after the flip; two epochs after is 14,400, the floor, so the run stops at 10,800 plus 600) | the final sample |
| 9 | Collect every miner's `program and 256 MiB cache ready` lines (seed, class, id) and the template's `eraSeed` for epochs 2 and 3, and send them to the node lane; the Mac computes `igneum-pow show --epoch-hex <seed> --program-class v3|v4 --era-hex <era>` for each (the id assertion of the G4 harness, no binary needed on a box) | every box's v4 id equals the CLI's v4 id and differs from the CLI's v3 id of the same seed and era | | 9 | The id assertion, the same Mac-side procedure with the box's id read from the pack, not a log line (a worker-mode miner prints no `program id` line; the Metal run of G4b showed the same): on every box, for epochs 2 and 3, take the `program pack checked for epoch seed <E> day <D>: attempt <A>, <dir>` line and read `<dir>/program.h`'s `IGNEUM_GENERATOR` (must be 4), `IGNEUM_PROGRAM_CLASS` ("v4"), `IGNEUM_PROGRAM_ID`, `IGNEUM_SEED_BYTES_HEX` and `IGNEUM_ERA_SEED_HEX` (the miner's `PREPARE sent ... class v4 era=<hex>` line carries the same era), and send the five values per box and epoch to the node lane; the Mac computes `igneum-pow show --epoch-hex <IGNEUM_SEED_BYTES_HEX> --program-class v4 --era-hex <IGNEUM_ERA_SEED_HEX>` and the same with `v3` | every box's `IGNEUM_PROGRAM_ID` equals the CLI's v4 id and differs from the CLI's v3 id of the same seed and era; one id per epoch across boxes |
| 10 | Stop every node and miner; destroy the instances by the fleet plan's rule | the report in section 4 is in | | 10 | Stop every node and miner; destroy the instances by the fleet plan's rule | the report in section 4 is in |
Never: no live-devnet port, no live override file, no manifest, no `update-now`; the boxes' app installs (if any) are not touched (the rule of 5 October: a job never quits or restarts an app it did not start). Never: no live-devnet port, no live override file, no manifest, no `update-now`; the boxes' app installs (if any) are not touched (the rule of 5 October: a job never quits or restarts an app it did not start).
@ -77,7 +77,7 @@ Never: no live-devnet port, no live override file, no manifest, no `update-now`;
| `blocks_before`, `blocks_after` | `getBlocks` from any box, split at DAA 7,200 | both over 0 | | `blocks_before`, `blocks_after` | `getBlocks` from any box, split at DAA 7,200 | both over 0 |
| `rejected` | every miner's `rejected=` STATUS count and every node's `PoW rejected` lines | 0 on every box | | `rejected` | every miner's `rejected=` STATUS count and every node's `PoW rejected` lines | 0 on every box |
| `sinks` at the end | `getBlockDagInfo` | one value on every signalling box | | `sinks` at the end | `getBlockDagInfo` | one value on every signalling box |
| `program_ids` per epoch per box | the miners' lines | one id per epoch across boxes; epochs 2 and 3 class v4; the Mac's CLI check (step 9) holds | | `program_ids` per epoch per box | the packs' `program.h` named by the miners' `program pack checked` lines (step 9) | one id per epoch across boxes; epochs 2 and 3 generator 4, class v4; the Mac's CLI check holds |
| `stale_box` | its log and `getBlockDagInfo` | refused (no peer), block count 1, no block of its ever appears on any signalling box's chain (its own genesis-state chain and the fleet's never merge) | | `stale_box` | its log and `getBlockDagInfo` | refused (no peer), block count 1, no block of its ever appears on any signalling box's chain (its own genesis-state chain and the fleet's never merge) |
| `shares` per sample | step 6 | 10,000 bps on every box at every sample | | `shares` per sample | step 6 | 10,000 bps on every box at every sample |