diff --git a/docs/plans/counter-asic-3-gate/class-v4-20261006-id-failed-case.json b/docs/plans/counter-asic-3-gate/class-v4-20261006-id-failed-case.json new file mode 100644 index 000000000..97d8ed4a0 --- /dev/null +++ b/docs/plans/counter-asic-3-gate/class-v4-20261006-id-failed-case.json @@ -0,0 +1,428 @@ +{ + "pass": false, + "checks": { + "v4_switch_line_on_every_node": true, + "v4_switch_line_names_the_rounded_epoch": true, + "v3_switch_line_on_every_node": true, + "template_switched_at_the_first_v4_epoch": true, + "template_switched_at_the_first_v3_epoch": true, + "blocks_before_the_boundary": true, + "blocks_after_the_boundary": true, + "v3_and_v4_programs_seen": true, + "v2_programs_seen_when_v3_starts_later": true, + "program_ids_differ_across_the_switch": true, + "miners_agree_on_every_program": true, + "v4_ids_equal_the_cli_v4_id_of_the_seed_and_era": true, + "v4_ids_differ_from_the_same_seed_v3_id": false, + "zero_rejected_by_miners": true, + "zero_rejected_by_nodes": true, + "sinks_agree": true, + "block_counts_agree": true + }, + "activation": 150, + "v3_activation": 60, + "epoch_blocks": 60, + "first_v3_epoch": 1, + "first_v4_epoch": 3, + "boundary_daa": 180, + "secs": 420, + "threads": 1, + "node": "/Users/joshm/Projects/igneum-wt-ca3-v4-node/vendor/igneum-node-ca3v4/target-ca3v4/release/igneumd", + "miner": "/Users/joshm/Projects/igneum-wt-ca3-v4-node/vendor/igneum-node-ca3v4/target-ca3v4/release/igneum-miner", + "metal_worker": null, + "genesis_bits": "0x1f010000", + "template_switch_v3": { + "epoch": 1, + "daa": 60, + "at": 21.7 + }, + "template_switch": { + "epoch": 3, + "daa": 183, + "at": 150.9 + }, + "run_ended_at_s": 292.6, + "final_daa": 300, + "blocks": { + "total": 302, + "before_boundary": 181, + "after_boundary": 121, + "chain_before": 176, + "chain_after": 116 + }, + "programs": [ + { + "epoch": 0, + "class": "v2", + "program_id": "8f8806638d59850f", + "seed": "234e082d653dc69d", + "miners": 3, + "disagree": false, + "ready_ms": [ + 187, + 187, + 188 + ] + }, + { + "epoch": 1, + "class": "v3", + "program_id": "12c480a41d694eec", + "seed": "073015e2426b7478", + "miners": 3, + "disagree": false, + "ready_ms": [ + 180, + 180, + 182 + ] + }, + { + "epoch": 2, + "class": "v3", + "program_id": "54ecf947e4e612a1", + "seed": "12657fe0d85fe42c", + "miners": 3, + "disagree": false, + "ready_ms": [ + 2, + 2, + 2 + ] + }, + { + "epoch": 3, + "class": "v4", + "program_id": "36f9dcd74e70596d", + "seed": "847996eafeffbd70", + "miners": 3, + "disagree": false, + "ready_ms": [ + 2, + 2, + 2 + ] + }, + { + "epoch": 4, + "class": "v4", + "program_id": "1545bab5a403eccf", + "seed": "4a94d31e8a52581d", + "miners": 3, + "disagree": false, + "ready_ms": [ + 4, + 5, + 4 + ] + }, + { + "epoch": 5, + "class": "v4", + "program_id": "aba85d2c6dc6ffc9", + "seed": "c287ce10159b1db9", + "miners": 3, + "disagree": false, + "ready_ms": [ + 2, + 2, + 2 + ] + } + ], + "program_id_rows": [ + { + "epoch": 3, + "seed": "847996eafeffbd70", + "era": "234e082d653dc69d", + "miners_id": "36f9dcd74e70596d", + "miners": 3, + "cli_v3": "1f2f009b97feb262", + "cli_v4": "36f9dcd74e70596d" + }, + { + "epoch": 4, + "seed": "4a94d31e8a52581d", + "era": "234e082d653dc69d", + "miners_id": "1545bab5a403eccf", + "miners": 3, + "cli_v3": "03361a4502a63c74", + "cli_v4": "1545bab5a403eccf" + }, + { + "epoch": 5, + "seed": "c287ce10159b1db9", + "era": "234e082d653dc69d", + "miners_id": "aba85d2c6dc6ffc9", + "miners": 3, + "cli_v3": "7b611b1937afceda", + "cli_v4": "aba85d2c6dc6ffc9" + } + ], + "id_check_against": "v4", + "igneum_pow": "/Users/joshm/Projects/igneum-wt-ca3-v4-node/igneum-pow/target/release/igneum-pow", + "accepted_per_miner": [ + 104, + 100, + 97 + ], + "rejected_by_miners": [ + 0, + 0, + 0 + ], + "rejected_by_nodes": [ + 0, + 0, + 0 + ], + "rejected_lines": [], + "sinks": [ + "62063c7467754a12", + "62063c7467754a12", + "62063c7467754a12" + ], + "block_counts": [ + 301, + 301, + 301 + ], + "tips_per_node": [ + 1, + 1, + 1 + ], + "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)", + "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)", + "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)" + ], + "v3_switch_lines": [ + "Program class v3 from the override file: active from epoch 1 (DAA score 60 rounded up to the epoch boundary at 60, epochs of 60 DAA)", + "Program class v3 from the override file: active from epoch 1 (DAA score 60 rounded up to the epoch boundary at 60, epochs of 60 DAA)", + "Program class v3 from the override file: active from epoch 1 (DAA score 60 rounded up to the epoch boundary at 60, epochs of 60 DAA)" + ], + "samples": [ + { + "t": 4.7, + "daa": 0, + "epoch": 0, + "class": 2, + "nodes": [ + "0/234e082d", + "0/234e082d", + "0/234e082d" + ] + }, + { + "t": 19.7, + "daa": 58, + "epoch": 0, + "class": 2, + "nodes": [ + "58/a84095cc", + "58/a84095cc", + "58/a84095cc" + ] + }, + { + "t": 34.7, + "daa": 63, + "epoch": 1, + "class": 3, + "nodes": [ + "63/be44e234", + "63/be44e234", + "63/be44e234" + ] + }, + { + "t": 49.7, + "daa": 67, + "epoch": 1, + "class": 3, + "nodes": [ + "67/7d67b214", + "67/7d67b214", + "67/7d67b214" + ] + }, + { + "t": 64.7, + "daa": 82, + "epoch": 1, + "class": 3, + "nodes": [ + "82/5f8c918b", + "82/5f8c918b", + "82/5f8c918b" + ] + }, + { + "t": 79.8, + "daa": 98, + "epoch": 1, + "class": 3, + "nodes": [ + "98/570ffe55", + "98/570ffe55", + "98/570ffe55" + ] + }, + { + "t": 94.8, + "daa": 120, + "epoch": 2, + "class": 3, + "nodes": [ + "120/97036960", + "120/97036960", + "120/97036960" + ] + }, + { + "t": 109.8, + "daa": 134, + "epoch": 2, + "class": 3, + "nodes": [ + "134/2a68fcfe", + "134/2a68fcfe", + "134/2a68fcfe" + ] + }, + { + "t": 124.8, + "daa": 153, + "epoch": 2, + "class": 3, + "nodes": [ + "153/67bd5a28", + "153/67bd5a28", + "153/67bd5a28" + ] + }, + { + "t": 139.8, + "daa": 167, + "epoch": 2, + "class": 3, + "nodes": [ + "167/19f33cf7", + "167/19f33cf7", + "167/19f33cf7" + ] + }, + { + "t": 154.9, + "daa": 187, + "epoch": 3, + "class": 4, + "nodes": [ + "187/d12f7ba0", + "187/d12f7ba0", + "187/d12f7ba0" + ] + }, + { + "t": 169.9, + "daa": 199, + "epoch": 3, + "class": 4, + "nodes": [ + "199/55400a2a", + "199/55400a2a", + "199/55400a2a" + ] + }, + { + "t": 185, + "daa": 203, + "epoch": 3, + "class": 4, + "nodes": [ + "203/7bf0378d", + "203/7bf0378d", + "203/7bf0378d" + ] + }, + { + "t": 200.2, + "daa": 206, + "epoch": 3, + "class": 4, + "nodes": [ + "206/96a0b5c4", + "206/96a0b5c4", + "206/96a0b5c4" + ] + }, + { + "t": 215.4, + "daa": 211, + "epoch": 3, + "class": 4, + "nodes": [ + "211/9127929f", + "211/9127929f", + "211/9127929f" + ] + }, + { + "t": 230.4, + "daa": 223, + "epoch": 3, + "class": 4, + "nodes": [ + "223/55ff00a1", + "223/55ff00a1", + "223/55ff00a1" + ] + }, + { + "t": 245.5, + "daa": 243, + "epoch": 4, + "class": 4, + "nodes": [ + "243/676c1129", + "243/676c1129", + "243/676c1129" + ] + }, + { + "t": 260.5, + "daa": 266, + "epoch": 4, + "class": 4, + "nodes": [ + "266/a7b8fca9", + "266/a7b8fca9", + "266/a7b8fca9" + ] + }, + { + "t": 275.6, + "daa": 282, + "epoch": 4, + "class": 4, + "nodes": [ + "282/d88a6d7f", + "282/d88a6d7f", + "282/d88a6d7f" + ] + }, + { + "t": 290.6, + "daa": 298, + "epoch": 4, + "class": 4, + "nodes": [ + "298/03728b1d", + "298/03728b1d", + "298/03728b1d" + ] + } + ], + "metal": null +} \ No newline at end of file diff --git a/docs/plans/counter-asic-3-gate/class-v4-20261006-id-rerun.json b/docs/plans/counter-asic-3-gate/class-v4-20261006-id-rerun.json new file mode 100644 index 000000000..e599893ab --- /dev/null +++ b/docs/plans/counter-asic-3-gate/class-v4-20261006-id-rerun.json @@ -0,0 +1,439 @@ +{ + "pass": true, + "checks": { + "v4_switch_line_on_every_node": true, + "v4_switch_line_names_the_rounded_epoch": true, + "v3_switch_line_on_every_node": true, + "template_switched_at_the_first_v4_epoch": true, + "template_switched_at_the_first_v3_epoch": true, + "blocks_before_the_boundary": true, + "blocks_after_the_boundary": true, + "v3_and_v4_programs_seen": true, + "v2_programs_seen_when_v3_starts_later": true, + "program_ids_differ_across_the_switch": true, + "miners_agree_on_every_program": true, + "v4_ids_equal_the_cli_v4_id_of_the_seed_and_era": true, + "v4_ids_differ_from_the_same_seed_v3_id": true, + "zero_rejected_by_miners": true, + "zero_rejected_by_nodes": true, + "sinks_agree": true, + "block_counts_agree": true + }, + "activation": 150, + "v3_activation": 60, + "epoch_blocks": 60, + "first_v3_epoch": 1, + "first_v4_epoch": 3, + "boundary_daa": 180, + "secs": 420, + "threads": 1, + "node": "/Users/joshm/Projects/igneum-wt-ca3-v4-node/vendor/igneum-node-ca3v4/target-ca3v4/release/igneumd", + "miner": "/Users/joshm/Projects/igneum-wt-ca3-v4-node/vendor/igneum-node-ca3v4/target-ca3v4/release/igneum-miner", + "metal_worker": null, + "genesis_bits": "0x1f010000", + "template_switch_v3": { + "epoch": 1, + "daa": 61, + "at": 59.9 + }, + "template_switch": { + "epoch": 3, + "daa": 180, + "at": 221.6 + }, + "run_ended_at_s": 325.5, + "final_daa": 300, + "blocks": { + "total": 306, + "before_boundary": 181, + "after_boundary": 125, + "chain_before": 168, + "chain_after": 120 + }, + "programs": [ + { + "epoch": 0, + "class": "v2", + "program_id": "8f8806638d59850f", + "seed": "234e082d653dc69d", + "miners": 3, + "disagree": false, + "ready_ms": [ + 1099, + 1102, + 992 + ] + }, + { + "epoch": 1, + "class": "v3", + "program_id": "f7c4fcecb144374c", + "seed": "572eda48409be64f", + "miners": 3, + "disagree": false, + "ready_ms": [ + 729, + 733, + 737 + ] + }, + { + "epoch": 2, + "class": "v3", + "program_id": "13ddb6eb8765d557", + "seed": "81ee8ae7b054e6b6", + "miners": 3, + "disagree": false, + "ready_ms": [ + 8, + 8, + 9 + ] + }, + { + "epoch": 3, + "class": "v4", + "program_id": "30544487d1289d6e", + "seed": "bd597eca7205d564", + "miners": 3, + "disagree": false, + "ready_ms": [ + 7, + 7, + 17 + ] + }, + { + "epoch": 4, + "class": "v4", + "program_id": "53e36801cc6fafcf", + "seed": "782b6b0d5526692c", + "miners": 3, + "disagree": false, + "ready_ms": [ + 11, + 13, + 10 + ] + }, + { + "epoch": 5, + "class": "v4", + "program_id": "876e155e3fb59983", + "seed": "2d307b520f54995e", + "miners": 3, + "disagree": false, + "ready_ms": [ + 3, + 2, + 3 + ] + } + ], + "program_id_rows": [ + { + "epoch": 3, + "seed": "bd597eca7205d564", + "era": "234e082d653dc69d", + "miners_id": "30544487d1289d6e", + "miners": 3, + "cli_v3": "1ae1c9f0eda0cef5", + "cli_v4": "30544487d1289d6e" + }, + { + "epoch": 4, + "seed": "782b6b0d5526692c", + "era": "234e082d653dc69d", + "miners_id": "53e36801cc6fafcf", + "miners": 3, + "cli_v3": "af81f6e844959460", + "cli_v4": "53e36801cc6fafcf" + }, + { + "epoch": 5, + "seed": "2d307b520f54995e", + "era": "234e082d653dc69d", + "miners_id": "876e155e3fb59983", + "miners": 3, + "cli_v3": "b4f25c4678496a78", + "cli_v4": "876e155e3fb59983" + } + ], + "id_check_against": "v3", + "igneum_pow": "/Users/joshm/Projects/igneum-wt-ca3-v4-node/igneum-pow/target/release/igneum-pow", + "accepted_per_miner": [ + 93, + 118, + 94 + ], + "rejected_by_miners": [ + 0, + 0, + 0 + ], + "rejected_by_nodes": [ + 0, + 0, + 0 + ], + "rejected_lines": [], + "sinks": [ + "b7881306c83b1206", + "b7881306c83b1206", + "b7881306c83b1206" + ], + "block_counts": [ + 305, + 305, + 305 + ], + "tips_per_node": [ + 1, + 1, + 1 + ], + "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)", + "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)", + "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)" + ], + "v3_switch_lines": [ + "Program class v3 from the override file: active from epoch 1 (DAA score 60 rounded up to the epoch boundary at 60, epochs of 60 DAA)", + "Program class v3 from the override file: active from epoch 1 (DAA score 60 rounded up to the epoch boundary at 60, epochs of 60 DAA)", + "Program class v3 from the override file: active from epoch 1 (DAA score 60 rounded up to the epoch boundary at 60, epochs of 60 DAA)" + ], + "samples": [ + { + "t": 5.8, + "daa": 0, + "epoch": 0, + "class": 2, + "nodes": [ + "0/234e082d", + "0/234e082d", + "0/234e082d" + ] + }, + { + "t": 21.2, + "daa": 8, + "epoch": 0, + "class": 2, + "nodes": [ + "8/6bc9f901", + "8/6bc9f901", + "8/6bc9f901" + ] + }, + { + "t": 36.6, + "daa": 20, + "epoch": 0, + "class": 2, + "nodes": [ + "20/91c3a67c", + "20/91c3a67c", + "20/91c3a67c" + ] + }, + { + "t": 51.9, + "daa": 44, + "epoch": 0, + "class": 2, + "nodes": [ + "44/31889c03", + "44/31889c03", + "44/31889c03" + ] + }, + { + "t": 66.9, + "daa": 63, + "epoch": 1, + "class": 3, + "nodes": [ + "63/edf7c0c8", + "63/edf7c0c8", + "63/edf7c0c8" + ] + }, + { + "t": 82, + "daa": 75, + "epoch": 1, + "class": 3, + "nodes": [ + "75/cac30a72", + "75/cac30a72", + "75/cac30a72" + ] + }, + { + "t": 97.1, + "daa": 86, + "epoch": 1, + "class": 3, + "nodes": [ + "86/bcc7f156", + "86/bcc7f156", + "86/bcc7f156" + ] + }, + { + "t": 112.2, + "daa": 98, + "epoch": 1, + "class": 3, + "nodes": [ + "98/4c9feb88", + "98/4c9feb88", + "98/4c9feb88" + ] + }, + { + "t": 127.3, + "daa": 107, + "epoch": 1, + "class": 3, + "nodes": [ + "107/a762e33c", + "107/a762e33c", + "107/a762e33c" + ] + }, + { + "t": 142.8, + "daa": 118, + "epoch": 1, + "class": 3, + "nodes": [ + "118/d6d66723", + "118/d6d66723", + "118/d6d66723" + ] + }, + { + "t": 158.1, + "daa": 133, + "epoch": 2, + "class": 3, + "nodes": [ + "133/c87e971c", + "133/c87e971c", + "133/c87e971c" + ] + }, + { + "t": 173.3, + "daa": 144, + "epoch": 2, + "class": 3, + "nodes": [ + "144/ffbcbc89", + "144/ffbcbc89", + "144/ffbcbc89" + ] + }, + { + "t": 188.7, + "daa": 150, + "epoch": 2, + "class": 3, + "nodes": [ + "150/75c2cb97", + "150/75c2cb97", + "150/75c2cb97" + ] + }, + { + "t": 204.1, + "daa": 166, + "epoch": 2, + "class": 3, + "nodes": [ + "166/02d121fc", + "166/02d121fc", + "166/02d121fc" + ] + }, + { + "t": 219.5, + "daa": 178, + "epoch": 2, + "class": 3, + "nodes": [ + "178/ffb90ce2", + "178/ffb90ce2", + "178/ffb90ce2" + ] + }, + { + "t": 235.1, + "daa": 199, + "epoch": 3, + "class": 4, + "nodes": [ + "199/bc36a6c5", + "199/bc36a6c5", + "199/bc36a6c5" + ] + }, + { + "t": 250.5, + "daa": 207, + "epoch": 3, + "class": 4, + "nodes": [ + "207/0a33e0ad", + "207/0a33e0ad", + "207/0a33e0ad" + ] + }, + { + "t": 265.8, + "daa": 216, + "epoch": 3, + "class": 4, + "nodes": [ + "216/8dee9231", + "216/8dee9231", + "216/8dee9231" + ] + }, + { + "t": 281.1, + "daa": 235, + "epoch": 3, + "class": 4, + "nodes": [ + "235/ec4dfc5a", + "235/ec4dfc5a", + "235/ec4dfc5a" + ] + }, + { + "t": 296.4, + "daa": 254, + "epoch": 4, + "class": 4, + "nodes": [ + "254/778065f4", + "254/778065f4", + "254/778065f4" + ] + }, + { + "t": 311.4, + "daa": 282, + "epoch": 4, + "class": 4, + "nodes": [ + "282/d1f26207", + "282/d1f26207", + "282/d1f26207" + ] + } + ], + "metal": null +} \ No newline at end of file diff --git a/docs/plans/counter-asic-3-gate/node-gates.md b/docs/plans/counter-asic-3-gate/node-gates.md index 350824785..88a0e4bd9 100644 --- a/docs/plans/counter-asic-3-gate/node-gates.md +++ b/docs/plans/counter-asic-3-gate/node-gates.md @@ -4,9 +4,9 @@ | # | 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` | +| 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|v4 --era-hex `): e3 seed `bd597eca...` miners `30544487d1289d6e` (3 of 3) = cli v4 `30544487d1289d6e`, cli v3 `1ae1c9f0eda0cef5`; e4 `782b6b0d...` miners `53e36801cc6fafcf` = cli v4, cli v3 `af81f6e844959460`; e5 `2d307b52...` miners `876e155e3fb59983` = cli v4, cli v3 `b4f25c4678496a78`: every v4 id equals the chain's class v4 id and differs from the v3 id of the same seed and era. Summary `class-v4-20261006-id-rerun.json`. The assertion's known-failed case (`--id-check-against v4`, 16:38 to 16:43:05Z): the same network shape PASSES every other check (181 / 121 blocks, 0 rejected, one sink 301/301/301, the three PROGRAM ID rows OK) and the harness reports `SUMMARY FAIL` with exactly `FAILED CHECK v4_ids_differ_from_the_same_seed_v3_id`, exit 1. Summary `class-v4-20261006-id-failed-case.json` | | 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 --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=` (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, with one gap named: 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 | +| 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) | -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). +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). diff --git a/docs/plans/counter-asic-3-node.md b/docs/plans/counter-asic-3-node.md index 3e4e0849c..6d3ab1e73 100644 --- a/docs/plans/counter-asic-3-node.md +++ b/docs/plans/counter-asic-3-node.md @@ -49,11 +49,24 @@ See `docs/plans/counter-asic-3-gate/node-gates.md` for the rows in the rollout's | Gate | State | The line that decides it | |---|---|---| -| G4 | GREEN | run 1: 3 of 3 switch lines, 181 / 128 blocks across DAA 180, ids agree on all three miners, rejected 0/0/0, one sink 308/308/308; run 2 (`--activation never`): `SUMMARY FAIL: NO v4 epoch seen`, exit 1 | +| G4 | GREEN | run 1: 3 of 3 switch lines, 181 / 128 blocks across DAA 180, ids agree on all three miners, rejected 0/0/0, one sink 308/308/308; run 2 (`--activation never`): `SUMMARY FAIL: NO v4 epoch seen`, exit 1; re-run on 7c22d0d with the id assertion: PASS, every v4 epoch's id (3 of 3 miners) equals the CLI's class v4 id and differs from the same-seed v3 id (e3 `30544487d1289d6e` against `1ae1c9f0eda0cef5`); its failed case (`--id-check-against v4`) fails on exactly that check | | G4b | GREEN | three `prepared ... class v4` lines (430, 139, 175 ms), every swap with no pause, 123 blocks accepted on v4, re-check mismatched 0, need 0, no mismatch, no exit 42 or 44 | | G5 | GREEN | the two Windows workers e563126e... and 7fce1249... with the resource block, the Mac worker 30c70754..., the job's igneumd.exe 140be25e..., every sha256 listed | | G6 | GREEN | PC 2 job build-20261006-155958, every stage ok, 392 s; kaspa-pow 15 with the v4 engine test, no flake | +## 3a. The program id carries the class (the coordinator's blocker, 7c22d0d) + +The hash lane found the seven gate packs under `proto-cuda/packs-ca3-v4` carrying the v3 control's program id `73bcbfe8ccf988f1`. The cause was not the chain seam (the fork's kaspa-pow test asserts a v3 and a v4 program of one seed and era have different ids, generator 4 in the preimage) but the CLI's `--era` path: `stamp_era` in `igneum-pow/src/main.rs` stamped generator 3 on any class, and `program_id(3, seed, attempt)` is class-independent inside a generator (spec 01 section 1.4.6, the 2.0 rule: every era of one epoch seed shares one id), so a `mx8+sh256x27` pack exported under an era read as a class v3 pack with the v3 id. A worker given such a pack would mine the v4 program under the v3 id and class token. + +| Piece | What | +|---|---| +| igneum-pow `generator.rs` | `era_generator_of(base)` (4 when the base minus its era is `V4_CLASS`, else 3), used by `generate_era`; `ProgramClass::of_load_class` (V2, V3_CLASS, V4_CLASS, else none); the v4 test asserts the `--era` path and the chain path make the same v4 program, generator 4, and a measurement class (`mx8+sh256x13`) stays generator 3 | +| igneum-pow `main.rs` | `stamp_era` and `show` stamp from the class; `show` honours `--program-class` and `--era-hex` (the harness's same-seed v3 and v4 ids come from it) | +| igneum-pow `packcheck.rs`, `proto-cuda/nvrtc/packfile.h`, `proto-metal/main.swift` | the shadow block marks class v4: a generator 3 pack with `IGNEUM_SHADOW_INSTRS` is refused ("a class v4 program is generator 4 (export the pack as class v4)"), a generator 4 pack without it is refused; a generator 2 pack with a shadow (the ladder of `packs-ca3-shadow`, class-bearing ids) stays loadable; tests in `packcheck.rs` and `emu/packfile-test.c` (4 new checks, 0 failures) | +| `proto-cuda/packs-ca3-v4/*` (7) | re-exported with the same seeds, day and eras: generator 4, class "v4", id `c120d7963abdcd96` (one id per epoch seed across its eras); every other line of every file byte-identical (kernels, memhard, program*.metal, every vector value); measured on the re-exported packs with `proto-metal/packbench --batches 60 --batch-log2 24 --group 256` under `with-lock.sh run` (16:30 to 16:37Z, load average 90 from other agents' builds, a fingerprint is load-independent): v4-devnet-epoch0 f410c731b6bc2d31, v4-era-0 b115c410e08be6ca, v4-era-1 edc2b18fc67e9d1c, v4-era-2 604ed87109570559, v4-era-3 9541e2a41dde2ee6, v4-era-4 a9ffa2b67bd2e366, v4-era-5 1f34e9c465945249, every one equal to the hash lane's table (`hash-gates.md`); the control `mx8-devnet-epoch0` untouched | +| `infra/fast-time/class-v4.mjs` | two new checks: every v4 epoch's id (the three miners agreeing) equals the CLI's class v4 id of that seed and era and differs from the CLI's class v3 id of the same seed and era; `--id-check-against v4` is the assertion's own failed case | +| the fork | no change: the chain path stamped 4 from the first commit; the miner's job line names the class, the workers key a pair on (seeds, class, era), and the id is a pack label, not an identity, which is why the pack rule above is the guard | + ## 4. Tests | Where | What | State |