From ca61dec38204a515a61e2a0da41836cf57ab13a0 Mon Sep 17 00:00:00 2001 From: igneum-josh <337424239+igneum-josh@users.noreply.github.com> Date: Tue, 6 Oct 2026 17:38:48 +0100 Subject: [PATCH] Counter ASIC 3.0 gates (hash): follow-up 1 on the program-id fix (7c22d0d merged): crate suite 97 of 97, the seven v4 packs re-exported byte-identical (generator 4, id c120d7963abdcd96), fingerprints unchanged on Metal and Apple OpenCL, Mac G2 16 x 1,024 of 1,024 through the v4 class token, the harness 4 of 4 on the class and on the era with the id assert_ne holding; the job scripts take the class token from the pack Co-Authored-By: Claude Fable 5.1 --- ...ss-v4-20261006-1632Z-followup1-id-fix.json | 65 +++++++++++++++++++ docs/plans/counter-asic-3-gate/hash-gates.md | 15 +++++ igneum-pow/tests/mixer.rs | 11 +++- tools/ca3-v4/pc2-v4-gates.ps1 | 5 +- 4 files changed, 91 insertions(+), 5 deletions(-) create mode 100644 docs/plans/counter-asic-3-gate/class-v4-20261006-1632Z-followup1-id-fix.json diff --git a/docs/plans/counter-asic-3-gate/class-v4-20261006-1632Z-followup1-id-fix.json b/docs/plans/counter-asic-3-gate/class-v4-20261006-1632Z-followup1-id-fix.json new file mode 100644 index 000000000..02f322162 --- /dev/null +++ b/docs/plans/counter-asic-3-gate/class-v4-20261006-1632Z-followup1-id-fix.json @@ -0,0 +1,65 @@ +{ + "pass": true, + "gate": "follow-up 1: G3 and the fingerprints on the program-id fix (ca3-v4-node 7c22d0d merged as 5314771)", + "checks": { + "crate_suite_97_of_97_on_the_merged_tree": true, + "seven_v4_packs_re_exported_byte_identical_to_the_tree": true, + "v4_packs_generator_4_class_v4_id_c120d7963abdcd96": true, + "v3_control_keeps_id_73bcbfe8ccf988f1": true, + "fingerprints_unchanged_metal_and_apple_opencl_eight_packs": true, + "mac_g2_serve_16_x_1024_of_1024_through_the_v4_class_token": true, + "harness_fuzz_edge_stats_determinism_4_of_4_on_the_class": true, + "harness_4_of_4_with_era_test_0_and_the_id_assert_ne_holding": true + }, + "when_utc": "2026-10-06T16:25:16Z to 16:37:58Z", + "load_average": "144 at the start of the runs, 68 at the end (other agents' suites; every run here is functional: counts, digests and fingerprints, no timing taken)", + "crate_suite": "60 + 0 + 7 + 4 + 19 + 7 + 0 = 97 passed, 0 failed (with-lock.sh build, nice 19, -j4, release)", + "packs": { + "mx8-devnet-epoch0": { + "fingerprint_metal_and_apple_opencl": "90f794dd556f7a3b", + "program_id": "73bcbfe8ccf988f1", + "generator": 3 + }, + "v4-devnet-epoch0": { + "fingerprint_metal_and_apple_opencl": "f410c731b6bc2d31", + "program_id": "c120d7963abdcd96", + "generator": 4 + }, + "v4-era-0": { + "fingerprint_metal_and_apple_opencl": "b115c410e08be6ca", + "program_id": "c120d7963abdcd96", + "generator": 4 + }, + "v4-era-1": { + "fingerprint_metal_and_apple_opencl": "edc2b18fc67e9d1c", + "program_id": "c120d7963abdcd96", + "generator": 4 + }, + "v4-era-2": { + "fingerprint_metal_and_apple_opencl": "604ed87109570559", + "program_id": "c120d7963abdcd96", + "generator": 4 + }, + "v4-era-3": { + "fingerprint_metal_and_apple_opencl": "9541e2a41dde2ee6", + "program_id": "c120d7963abdcd96", + "generator": 4 + }, + "v4-era-4": { + "fingerprint_metal_and_apple_opencl": "a9ffa2b67bd2e366", + "program_id": "c120d7963abdcd96", + "generator": 4 + }, + "v4-era-5": { + "fingerprint_metal_and_apple_opencl": "1f34e9c465945249", + "program_id": "c120d7963abdcd96", + "generator": 4 + } + }, + "re_export": "igneum-pow export --epoch-hex --day-hex --class mx8+sh256x27 --era : on the merged tree: 0 differing files against proto-cuda/packs-ca3-v4/ for each of the seven (seeds.txt excluded)", + "harness": { + "class": "fuzz 200 programs 800 units, stats 49.96 and 49.98 percent (z 2.65, 3.56), edge pass, determinism equal to packs-ca3-shadow/sh256x27, 4 of 4 in 8.23 s", + "era_test_0": "fuzz 50 programs 200 units, stats 50.03 and 50.11 percent (z 2.65, 3.76), determinism two builds equal, 4 of 4 in 4.40 s; the program id now differs from the generator-3 id of the same seeds (assert_ne, no \"same with and without the shadow\" line)" + }, + "mac_g2": "Metal serve (prepare and job lines with class=v4 era=) and Apple OpenCL serve: 1,024 of 1,024 on all eight packs, 16:35:31Z to 16:37:45Z" +} \ No newline at end of file diff --git a/docs/plans/counter-asic-3-gate/hash-gates.md b/docs/plans/counter-asic-3-gate/hash-gates.md index 45584b641..daea5c9b6 100644 --- a/docs/plans/counter-asic-3-gate/hash-gates.md +++ b/docs/plans/counter-asic-3-gate/hash-gates.md @@ -52,3 +52,18 @@ G4, G5 and G6 are not this worker's (the node seam, the release build, the fork - AMD (the RX 9070 XT, gfx1201): G1 and G2 on PC 1 inside another job later ("PC 1 job 1"); the OpenCL kernels are in every pack and pass on Apple OpenCL. - The 2019-class core (O-1.14): the 2.5x rule stands in. + +## Follow-up 1 (16:25 to 16:38 UTC): the program-id fix, re-run + +The node lane's fix (ca3-v4-node 7c22d0d, merged here as 5314771): a class v4 program is generator 4 wherever it is made, so its id differs from the generator-3 id of the same seeds. Re-run on the merged tree, every run functional (load 144 to 68, other agents' suites; no timing taken): + +| Check | Result | +|---|---| +| The crate suite | 60 + 7 + 4 + 19 + 7 = 97 of 97, 0 failed | +| The seven v4 packs re-exported (`--class mx8+sh256x27 --era :`) against the tree's | 0 differing files each; generator 4, class "v4", id c120d7963abdcd96 (one id per epoch seed across its eras); the v3 control keeps 73bcbfe8ccf988f1 | +| The fingerprints on the rebuilt Metal and Apple OpenCL harnesses | unchanged on all eight packs (the table above), self-tests PASS: the id is not a hash input | +| The Mac G2 serve through the v4 class token (`class=v4 era=` on the prepare and job lines) | 1,024 of 1,024 on all eight packs, Metal and Apple OpenCL | +| The harness on `mx8+sh256x27` (fuzz 200, stats, edge, determinism) | 4 of 4; avalanche 49.96 and 49.98 percent, determinism equal to the pinned sh256x27 | +| The harness with era test/0 composed (fuzz 50, stats, edge, determinism) | 4 of 4; the id now differs from the generator-3 id (`assert_ne`), the "same with and without the shadow" line gone | + +`class-v4-20261006-1632Z-followup1-id-fix.json`. The cut-stopper of the first run is closed on the hash side; the node lane's G4 re-run with the id assertion is its own evidence. The RTX 5090 and AMD rows need the re-exported packs (the 5090 run of 15:52Z used the generator-3 packs; the kernels and vectors are byte-identical, so its fingerprints stand, and only the id and class lines of program.h differ). The G2 job script now takes the class token from the pack (v3 or v4). diff --git a/igneum-pow/tests/mixer.rs b/igneum-pow/tests/mixer.rs index cb458156f..b6b3b8bfc 100644 --- a/igneum-pow/tests/mixer.rs +++ b/igneum-pow/tests/mixer.rs @@ -18,7 +18,7 @@ //! shadow, draw for draw. The edge test is the dataset's alone (the shadow touches no dataset word) and takes no class. use igneum_pow::emit::{export_pack, vectors_json}; -use igneum_pow::generator::{generate_era, generate_from_seed_bytes, generate_from_seed_bytes_class, generate_from_seed_bytes_program_class, EraParams, LoadClass, Op, Program, ProgramClass, GENERATOR_VERSION_V3, INSTR_COUNT, V3_ALLOWED, V3_CLASS}; +use igneum_pow::generator::{era_generator_of, generate_era, generate_from_seed_bytes, generate_from_seed_bytes_class, generate_from_seed_bytes_program_class, EraParams, LoadClass, Op, Program, ProgramClass, GENERATOR_VERSION_V3, GENERATOR_VERSION_V4, INSTR_COUNT, V3_ALLOWED, V3_CLASS}; use igneum_pow::memhard::{derive_item, mixer, round_key, Cache, MixParams, Shape}; use igneum_pow::seed::{day_key, SplitMix64}; use igneum_pow::verify::{DatasetMode, DatasetSource, Epoch}; @@ -52,8 +52,11 @@ fn program_of(seed: &str, class: LoadClass, era: Option<[u8; 32]>) -> Program { } fn contract(p: &Program, seed: &str, class: LoadClass, era: Option<[u8; 32]>) { - if class == V3_CLASS || era.is_some() { + if class == V3_CLASS { assert_eq!(p.generator, GENERATOR_VERSION_V3); + } else if era.is_some() { + // the generator of an era class is the class's (ca3-v4-node 7c22d0d): 4 on V4_CLASS, 3 otherwise + assert_eq!(p.generator, era_generator_of(&LoadClass { era: None, ..class })); } assert_eq!(p.class, class); assert_eq!(p.instrs.len(), INSTR_COUNT); @@ -91,7 +94,9 @@ fn contract(p: &Program, seed: &str, class: LoadClass, era: Option<[u8; 32]>) { let base = program_of(seed, LoadClass { shadow: None, ..class }, era); assert_eq!(p.instrs, base.instrs, "{seed}: the base program is the class's without the shadow"); assert_eq!(p.attempt, base.attempt); - if era.is_none() { + if era.is_none() || p.generator == GENERATOR_VERSION_V4 { + // a generator-2 program carries the shadow in its id bytes; a class v4 program is generator 4 + // (ca3-v4-node 7c22d0d), so its id differs from the generator-3 id of the same seeds assert_ne!(p.program_id(), base.program_id(), "{seed}: the shadow is in the program id"); } else { // a generator-3 program's id is program_id(3, seed, attempt), class-independent by construction diff --git a/tools/ca3-v4/pc2-v4-gates.ps1 b/tools/ca3-v4/pc2-v4-gates.ps1 index c2f9575ce..a0c652769 100644 --- a/tools/ca3-v4/pc2-v4-gates.ps1 +++ b/tools/ca3-v4/pc2-v4-gates.ps1 @@ -75,9 +75,10 @@ function G2-JobLines([string] $d) { $epoch = ([regex]::Match($ph, '#define IGNEUM_SEED_BYTES_HEX "([0-9a-f]+)"')).Groups[1].Value $day = ([regex]::Match($ph, '#define IGNEUM_DAY_BYTES_HEX "([0-9a-f]+)"')).Groups[1].Value $tokens = '' - $cls = [regex]::Match($ph, '#define IGNEUM_PROGRAM_CLASS "(v[23])"') + $cls = [regex]::Match($ph, '#define IGNEUM_PROGRAM_CLASS "(v[234])"') $era = [regex]::Match($ph, '#define IGNEUM_ERA_SEED_HEX "([0-9a-f]+)"') - if ($cls.Success -and $cls.Groups[1].Value -eq 'v3') { $tokens = ' class=v3'; if ($era.Success) { $tokens += ' era=' + $era.Groups[1].Value } } + # the class token is the pack's own (v3 or v4 since ca3-v4-node 7c22d0d: a class v4 pack is generator 4 and says "v4") + if ($cls.Success -and $cls.Groups[1].Value -ne 'v2') { $tokens = ' class=' + $cls.Groups[1].Value; if ($era.Success) { $tokens += ' era=' + $era.Groups[1].Value } } return @("job g2 $g2Pre ffffffffffffffff 0 1024 $epoch $day$tokens", 'quit') } foreach ($pk in $order) {