344 lines
29 KiB
Markdown
344 lines
29 KiB
Markdown
# Attack pass F1: shadow block compressibility and shortcut search
|
|
|
|
Row F1 of `docs/plans/cryptanalysis.md` section 4.2, fed into `docs/analysis/attack-pass-2026-10.md`.
|
|
Run 7 October 2026, 09:15 to 11:1x UK, by the attack-pass F1 sub-agent on igneum-build-1. Times to humans UK;
|
|
log lines UTC. Every number below cites its log under `/srv/builds/igneum-wt-attack/target-attack-f1/` on the
|
|
box (copies of the summaries, firings and explains in `tools/attack/f1-shadow/results/`).
|
|
|
|
## 0. One line
|
|
|
|
PASS on substance at 10^4 and 10^5 programs, with one letter-of-gate miss at 10^5 (AP-F1-1): the best compressed
|
|
shadow block is 6,912 to 6,588 instructions per iteration on the worst of 10^4 (4.69 percent, seed
|
|
`attack-f1/8556`) and 6,912 to 6,561 on the worst of 10^5 (5.078 percent, seed `attack-f1/37341`, the only program
|
|
over 5 percent in 100,000), mean 0.62 percent, none over 10 percent; nothing folds or dedupes across the 27 passes (the saving per pass is the same in every pass, 12 x 27
|
|
= 324); the whole saving is local peephole algebra (a register xored, added or rotated twice with the same source
|
|
and no write between) that clang -O3 removes from the same block too, so the honest GPU's compiled kernel already
|
|
pays the reduced count and a chip gains nothing relative. Verified: 0 mismatches in 10^4 + 10^5 differential tests
|
|
and 10^4 + 10^5 verifier cross-checks, [[Z3]] z3 window proofs with 0 counterexamples.
|
|
|
|
## 1. Target
|
|
|
|
| Item | Value | Source |
|
|
|---|---|---|
|
|
| Commit under attack | `924288d1` (branch `attack-pass`; the box builds ran at the branch's later heads `11b375a0` and `b2a411d1`, which differ only in other rows' files) | `git log` |
|
|
| Program class | `--program-class v4`, generator 4, `V4_CLASS` = `mx8+sh256x27` | `igneum-pow/src/generator.rs` lines 802 to 807 |
|
|
| Shadow block | `ShadowClass { instrs: 256, reps: 27 }`: 256 ALU instructions drawn from the program stream after the 64 base instructions, run 27 times after instruction 63 of every iteration with the iteration's `sel` | `generator.rs` lines 355 to 376 and 1257 to 1290; `verify.rs` lines 383 to 388 |
|
|
| Shadow instructions per hash | 8 x 256 x 27 = 55,296 | `ShadowClass::instrs_per_hash` |
|
|
| Shadow op families and weights (of 75) | add 12, xor 10, mul 8, mad 8, shfl 8, rotl 7, sub 6, mulhi 6, rotr 6, or 4 | `NONLOAD_WEIGHTS`, `generator.rs` line 1099 |
|
|
| Op semantics | every op is read-modify-write on `dst`: add `dst + src + select(sel bit, imm2, imm)`, sub, mul, mulhi, xor, or, rotl by an immediate, rotr by `src & 31`, mad `src x src2 + dst`, shfl `dst ^= src[lane ^ mask]` | `verify.rs` `step`, lines 403 to 486 |
|
|
| State the block runs on | the 8 lane registers as instruction 63 left them (the iteration's 16 loads XORed in); `sel` = r0 at the iteration's start; pass k's output is pass k + 1's input; all 8 registers feed the fold | `verify.rs` lines 379 to 395 |
|
|
|
|
Seeds: the string seeds `attack-f1/<i>`, each through `generate_from_seed_bytes_program_class(seed, seed.as_bytes(),
|
|
ProgramClass::V4, None)` (the acceptance rule's redraw included). Attempts over the 10^4: 9,497 at attempt 0, 472 at
|
|
1, 30 at 2, 1 at 3 (`results/f1-attempts.txt`), the 5.0 percent rejection rate of spec 1.4.6.
|
|
|
|
## 2. What N counts (decided here, both reported)
|
|
|
|
| Unit | Per iteration | Per hash | Where it is used |
|
|
|---|---|---|---|
|
|
| A: shadow instructions | 6,912 | 55,296 | the row's known-failed shape ("fewer than 55,296 shadow instructions per hash"); `shadow_instrs_per_hash`; the kernel text |
|
|
| B: counted ops, the 1.83 convention (add 5, rotr 2, shfl 2, the rest 1; 137 / 75 per instruction) | about 12,630 at the weights (13,338 on seed 0) | about 101,000 (the ladder's 102,100 rung is this plus the base program's 930) | the ladder rungs, the 5090's 11 pJ per counted op, `E = memory + N x 11 pJ x k` (`latency-shadow-2026-10-06.md` section 6, `algorithm.md` 5.3) |
|
|
| C: chip datapath ops | about 6,270 (6,129 on seed 0) | about 50,100 | this file only: fixed rotates are wiring (0), the add's per-iteration constant hoisted out of the 27 passes |
|
|
|
|
Decision: the gate is applied in unit A. (1) The row's own failed shape is written in instructions. (2) Unit B's
|
|
extra 0.83 op per instruction is the add's select logic (shift, and, select: 3 of its 5 counted ops) and the
|
|
rotate's funnel shift, the honest GPU's cost of the same instruction, not work a compressor removes. (3) The chip
|
|
model's `k` floor is derived per instruction (`algorithm.md` 5.3: 0.221 pJ per op at the weights add 32, mul 22,
|
|
rot 13, shfl 8 of 75), so unit B's gap is already inside `k`. Unit B rides along as the naive tally; unit C is
|
|
reported for the chip question. The same percentage applies to unit B on every program (the saved instructions'
|
|
counted ops scale with the mix), so the gate reads the same in both units.
|
|
|
|
Unit note for the algorithm lane (AP-F1-1, below): the `k = 0.3` floor divides a per-instruction energy by a
|
|
per-counted-op energy.
|
|
|
|
## 3. Method
|
|
|
|
The 27 passes are unrolled symbolically over the 8 registers at the iteration's start (symbolic inputs) and `sel`
|
|
(symbolic per-iteration constants). Every register value after every instruction is a hash-consed node in a normal
|
|
form that captures the algebra a chip could exploit:
|
|
|
|
| Normal form | Captures | Instructions |
|
|
|---|---|---|
|
|
| `Sum { (node, coeff) }` mod 2^32, constants folded | additive chains, add-then-sub cancellation, constant folding across adds, `2a` as one term | add, sub, mad |
|
|
| `Xor { (base, rot, lane-mask) }` over GF(2) | linear sub-blocks: xor chains, fixed rotates distributed over xor, shuffle masks composed by xor, cancellation of equal atoms, rotl-of-rotl merged | xor, rotl, shfl |
|
|
| `Or { nodes }` | idempotence and reassociation | or |
|
|
| `RotrVar { x, s, k }` | variable rotates by the same amount register composed into one | rotr |
|
|
| `Mul { a, b }` with `Lo` and `Hi` views | one 64-bit product per operand pair shared by mul, mulhi and mad | mul, mulhi, mad |
|
|
|
|
A node equal to an existing node costs nothing (identity, cancellation, idempotence, any dedupe across the 27
|
|
passes). Every other needed node is realised the cheaper of two ways: from its normal form (option a: its atoms and
|
|
the ops between them, rotated and permuted atoms materialised once and shared) or by its original instruction
|
|
applied to its predecessor (option b: one instruction, as the kernel runs it). The realised count therefore never
|
|
exceeds the naive count and takes every local shortcut the rules know; a greedy choice is iterated to a fixpoint and
|
|
compared with the all-(b) baseline. Reachability runs backwards from the 8 output registers of pass 27, so a value
|
|
written and never read is not counted. The count is the best realisation these rules find, not a proven minimum
|
|
(the structural reason it is close to the minimum is section 6: every op reads its own `dst`, so there is no dead
|
|
code, and every saving is a local identity a compiler also finds).
|
|
|
|
Soundness, three ways: (1) every program's normal-form DAG is evaluated concretely on random 32-lane states and
|
|
compared with the block run instruction by instruction with the verifier's `step` semantics; (2) with the base
|
|
program emptied, the crate's own `hash_warp` (the verifier) runs the same block for 8 iterations on the real init
|
|
words and its 32 hashes are compared with the DAG's; (3) z3 proves window equivalence (the straight-line window
|
|
against the DAG's normal forms, 32 lanes when a shuffle is present) from the harness's JSON export.
|
|
|
|
Known-failed shape: a shadow that constant-folds or dedupes across its 27 identical passes so a chip pays fewer than
|
|
55,296 shadow instructions per hash.
|
|
|
|
## 4. Harness
|
|
|
|
| Item | Path |
|
|
|---|---|
|
|
| Crate | `tools/attack/f1-shadow/` (`Cargo.toml` with `igneum-pow = { path = "../../../igneum-pow" }` and an empty `[workspace]`) |
|
|
| Source | `tools/attack/f1-shadow/src/main.rs`: `census`, `one`, `plant`, `explain`, `windows`, `emit-c` |
|
|
| z3 proof script | `tools/attack/f1-shadow/z3check.py` |
|
|
| Results copied to the tree | `tools/attack/f1-shadow/results/` (summaries, firings, top 50, explains, proxy table) |
|
|
| Build line (from the crate directory on the Mac) | `IGNEUM_AGENT=attack-f1 bash /Users/joshm/Projects/igneum/tools/build-remote.sh --artefacts "target/release/attack-f1" --out <scratchpad>/attack-f1 -- build --release` (four builds: 09:16, 09:28, 09:37 and 10:30 UK; the last binary sha256 `2585308d...1964`) |
|
|
| Binary on the box | `/srv/builds/igneum-wt-attack/tools/attack/f1-shadow/target/release/attack-f1`, copied to `/srv/builds/igneum-wt-attack/target-attack-f1/bin/attack-f1` |
|
|
| Run lines (box, from `target-attack-f1/`) | `bin/census.sh` (10^4, `flock -s` on the measure file, `nice -n 10 taskset -c 0-5,48-53`, 12 threads, 98.5 s); `bin/census100k.sh` (10^5, one chunk under 30 min); `bin/z3sample.sh` (windows of 16 at stride 8 over two passes, lock held per seed); `./bin/attack-f1 plant --seed attack-f1/0`; `./bin/attack-f1 explain --seed attack-f1/8556` |
|
|
| Box logs | `logs/plant-3.log`, `logs/census-2.log` (10^4, corrected harness), `logs/census100k-1.log`, `logs/z3sample-2.log`, `logs/z3-smoke-0.log`, `logs/z3-whole-0-r1.log`; outputs `out/census2/`, `out/census100k/`, `out/z3/`, `out/explain2-*.txt`, `out/pass-*.c` and `.ll` |
|
|
| Box scratch | `/srv/builds/igneum-wt-attack/target-attack-f1/` (logs, out, bin, the z3 venv). Named `target-attack-f1` and not `attack-f1` because `remote-run.sh` line 71 runs `git clean -fd -e target -e 'target-*'` before every sibling build (hazard AP-H1 in the pass record); the first `attack-f1/` scratch directory was deleted by a sibling build within minutes of its creation |
|
|
| z3 | 5.1.0 in `target-attack-f1/venv` (pip bootstrapped from `bootstrap.pypa.io/get-pip.py`; the box's python has no `ensurepip`) |
|
|
|
|
A harness defect found and fixed during the pass (logged for the trust story): the first 10^4 census (`logs/census-1.log`,
|
|
10:31 UK) read max 5.86 percent on seed `attack-f1/8948` and 2 programs over 5 percent. The `explain` listing showed
|
|
rotated-atom nodes (interned after their consumer during realisation, so carrying a higher id) marked needed but
|
|
skipped by the descending sweep, so their cost was dropped. Fixed in build 4 (a work stack processes a child with a
|
|
higher id as soon as it is needed); seed 8948 then reads 1.17 percent (253 of 256 per pass) and the census below is
|
|
the corrected one. The firings were rerun on the fixed binary.
|
|
|
|
## 5. Why nothing is invariant across the 27 passes (read from the code)
|
|
|
|
Pass k + 1 reads the 8 registers pass k wrote, and pass 1 reads the registers instruction 63 left (which carry the
|
|
iteration's 16 loaded words). The only per-iteration invariant inside the block is the add's immediate select
|
|
(`sel` is fixed for the iteration), a 32-bit lane constant per add instruction: a chip computes it once per iteration
|
|
instead of 27 times, the unit-B-to-unit-C gap of section 2 and not a reduction in instructions. Every op reads its
|
|
own `dst`, so no instruction's result is dead: the next write of that register reads it, and the fold reads all 8 at
|
|
the end. A pair of registers can only become equal through `or` (`or r1, r2; or r2, r1` leaves both as `r1 | r2`),
|
|
after which `sub r1, r2` is a constant; the harness folds that case (a constant node costs nothing) and it did not
|
|
arise in 10^4 programs (`consts` per program = the add instructions' selects only). Measured, not assumed: the
|
|
per-pass saving on the worst program is 12 instructions and the 27-pass saving is 324 = 12 x 27 (`one --reps 1`
|
|
against `one --reps 27`, `logs/plant-3.log` and section 7), so no dedupe crosses a pass boundary.
|
|
|
|
## 6. Firings (`logs/plant-3.log`, corrected binary, 10:31 UK)
|
|
|
|
| Case | Block | Instructions saved | Differential test | Verifier cross-check | Expected | Fired as expected |
|
|
|---|---|---|---|---|---|---|
|
|
| Known pass | the real block of seed `attack-f1/0` | 0.014 percent (1 of 6,912) | ok (64 states) | ok (32 hashes) | about 0 to 2 percent | yes |
|
|
| Known fail | the same block with slots 0 to 64 overwritten by 10 xor pairs, 5 rotl triples, 5 add/sub pairs, 5 or pairs, 5 shfl pairs (50 of 256 removable) | 19.94 percent | ok | ok | about 19.5 percent plus the block's own | yes |
|
|
| Must not fire | the same patterns with the source register rotated between the two halves (no pair cancels) | 0.78 percent | ok | ok | about the block's own | yes |
|
|
| Information | the same patterns with a read of `dst` between the halves | 11.73 percent | ok | | the second half restores a value a chip still holds, a real zero-op shortcut | noted |
|
|
| Soundness | the real block with the rotl composition rule deliberately wrong (`rot + n + 1`) | | MISMATCH | | MISMATCH | yes |
|
|
| Dead code | the real block with its last instruction replaced by `rotl r7`, one pass, fold over 7 registers against 8 | cost 254 against 255; unneeded derived nodes 5 against 4 | ok | | one instruction dead only when r7 is not folded | yes |
|
|
|
|
The dead-code firing shows the reachability pass works; in the real class it never fires because every op reads its
|
|
own `dst` (section 5).
|
|
|
|
## 7. Census
|
|
|
|
### 7.1 10^4 programs (`logs/census-2.log`, `out/census2/census.csv`, 10:31 to 10:33 UK, 98.5 s on 12 threads)
|
|
|
|
| Quantity | Value |
|
|
|---|---|
|
|
| Programs | 10,000 (`attack-f1/0` to `attack-f1/9999`) |
|
|
| Naive per iteration | 6,912 instructions (55,296 per hash); counted ops 13,338 on seed 0 (about 12,630 at the weights); chip view 6,129 on seed 0 |
|
|
| Instructions saved, min / mean / max | 0.000 / 0.627 / 4.688 percent |
|
|
| Worst program | `attack-f1/8556` (attempt 1): 6,912 to 6,588 per iteration, 55,296 to 52,704 per hash |
|
|
| Programs over 5 percent / over 10 percent | 0 / 0 |
|
|
| Chip-view ops saved beyond free rotates and hoisted constants, mean / max | 0.524 / 4.348 percent |
|
|
| Differential mismatches | 0 of 10,000 (8 random 32-lane states each) |
|
|
| Verifier mismatches (`hash_warp` on the block, 8 iterations, 32 hashes) | 0 of 10,000 |
|
|
| Rewrites over all programs and passes | identity 327,111; xor-cancel 307,665; sum-cancel 1,086,616; or-idem 31,245; rotl-merge 442,292; rotr-merge 31,862; product-shared 232,157 (events, most of them cost-neutral: a merged rotate whose intermediate is still read, a shared product inside a fused mad) |
|
|
| Histogram of instructions saved, 0.5 percent bins from 0 | 5,445; 2,119; 1,198; 993; 147; 58; 28; 8; 2; 2; 0; 0 (the last bin is 5.5 percent and over) |
|
|
|
|
Top of the tail (`results/f1-top50-corrected.csv`): 8556 and 4259 at 4.69 percent (12 of 256 per pass), 1206 at
|
|
4.30, 3491 at 4.28, 6812 at 3.92, 8087 at 3.91, 7292 at 3.89, then 3.52 and under.
|
|
|
|
### 7.2 10^5 programs (`logs/census100k-1.log`, `out/census100k/census.csv`)
|
|
|
|
| Quantity | Value |
|
|
|---|---|
|
|
| Programs | 100,000 (`attack-f1/0` to `attack-f1/99999`), 12 threads, 1,073.7 s, finished 10:51 UK |
|
|
| Instructions saved, min / mean / max | 0.000 / 0.617 / 5.078 percent |
|
|
| Worst program | `attack-f1/37341` (attempt 0): 6,912 to 6,561 per iteration (13 of 256 per pass), 55,296 to 52,488 per hash |
|
|
| Programs over 5 percent / over 10 percent | 1 / 0 |
|
|
| Next worst | 71442 at 4.70, then 95060, 8556, 77816 at 4.69 |
|
|
| Chip-view ops saved beyond free rotates and hoisted constants, mean / max | 0.513 / 5.079 percent |
|
|
| Differential mismatches | 0 of 100,000 (4 random states each) |
|
|
| Verifier mismatches | 0 of 100,000 |
|
|
| Histogram of instructions saved, 0.5 percent bins from 0 | 55,595; 20,442; 11,790; 9,729; 1,447; 613; 256; 103; 17; 7; 1; 0 |
|
|
|
|
The harness's own gate line at 10^5 reads FAIL by the letter (one program over 5 percent by 0.078 points); the
|
|
substance of section 7.3 and 7.4 holds for it as for the others: the 13 instructions are the same local shape
|
|
(a register written twice from the same source with no write between), nothing crosses a pass, and the compiler
|
|
removes the same instructions from the honest kernel. Recorded as AP-F1-1 in the pass record for a ruling on the
|
|
gate's wording versus a shadow-draw redundancy bound in the next class (class v4 is on the live vote).
|
|
|
|
### 7.3 What the saving is (`out/explain2-8556.txt`, `results/explain2-8556.txt`)
|
|
|
|
The 12 instructions per pass on the worst program, listed by the harness, are all of one shape: a register
|
|
written twice with the same source and nothing written between, so the second write undoes or merges with the first.
|
|
Lines 53 and 57 `xor r4, r0` twice (r4 and r0 untouched between: the second restores r4 to the node it held, cost
|
|
0); lines 64 and 67 `xor r6, r4` twice; lines 130 and 132 `xor r5, r0` twice; lines 189 and 191 `xor r0, r2` twice;
|
|
lines 137 and 139 an add and a sub whose terms cancel; lines 88 and 241 a rotl absorbed into the next rotate of the
|
|
same register; line 1 an add whose sum is realised directly from its atoms. Nothing spans a pass boundary and
|
|
nothing involves the constants.
|
|
|
|
### 7.4 A production compiler finds the same shortcuts (`out/pass-*.c`, `out/pass-*-O3.ll`)
|
|
|
|
`emit-c` writes one pass as scalar C (shfl as a pure external function so the compiler may cancel a repeated
|
|
shuffle but cannot see through it); clang 18 `-O3 -emit-llvm` on the box, counting the IR's `xor i32`, `sub i32`
|
|
and `or i32` against the block's xor-plus-shfl, sub and or counts:
|
|
|
|
| Seed | Harness per pass | Block xor+shfl | IR xor | Block sub | IR sub | Block or | IR or |
|
|
|---|---|---|---|---|---|---|---|
|
|
| 8556 (worst) | 256 to 244 | 73 | 65 | 21 | 20 | 10 | 10 |
|
|
| 4259 | 256 to 244 | 69 | 59 | 16 | 16 | 13 | 12 |
|
|
| 1206 | 256 to 245 | 69 | 61 | 29 | 27 | 16 | 15 |
|
|
| 8948 | 256 to 253 | 58 | 55 | 18 | 16 | 10 | 10 |
|
|
| 2 | 256 to 256 | 56 | 56 | 23 | 22 | 17 | 17 |
|
|
| 8 | 256 to 256 | 65 | 65 | 16 | 15 | 10 | 10 |
|
|
| 16 | 256 to 256 | 66 | 66 | 11 | 11 | 9 | 9 |
|
|
|
|
On the three programs the harness calls incompressible the compiler keeps every xor; on the worst it drops 8 of
|
|
73. (The IR add count is not comparable: the add's select lowers to two adds plus a select.) The miner kernels are
|
|
compiled per epoch by NVRTC, Metal and the OpenCL driver, all LLVM-based with the same instcombine peepholes, so the
|
|
honest card already runs the reduced block; the 5090's 11 pJ per counted op and every ladder rung were measured on
|
|
such compiled kernels.
|
|
|
|
## 8. z3 window proofs (`logs/z3sample-2.log`, `out/z3/win-*.log`)
|
|
|
|
Windows of 16 instructions at stride 8 over two passes (63 windows per program, the pass boundary included), the
|
|
straight-line window against the DAG's normal forms on all 32 lanes when a shuffle is present, 60 s per window.
|
|
|
|
[[Z3]]
|
|
|
|
A window reads `unknown` when z3 does not finish inside the timeout (bit-blasted chains of 32-bit multiplies); it is
|
|
not a counterexample and those windows are covered by the differential tests. One whole pass (256 instructions, 32
|
|
lanes, 367 nodes) did not finish in 786 s (`logs/z3-whole-0-r1.log`), so windows are the proof unit. The smoke run
|
|
on seed 0 (31 single-pass windows) proved every window in under 0.1 s each (`logs/z3-smoke-0.log`).
|
|
|
|
## 9. Gate and verdict
|
|
|
|
Gate (row F1, the same as 1.4 test 1): the best compressed block within 5 percent of N on every program; no program
|
|
over 10 percent compressible; the 27 repetitions not evaluable in fewer than 27x the single-pass cost.
|
|
|
|
| Test | Result | Log |
|
|
|---|---|---|
|
|
| Every program within 5 percent of N (unit A, 10^4) | yes: worst 4.69 percent | `logs/census-2.log` |
|
|
| No program over 10 percent | yes: 0 | `logs/census-2.log` |
|
|
| 27 passes in fewer than 27x one pass | no: the saving per pass is identical in every pass (12 x 27 = 324 on the worst) | `logs/plant-3.log`, section 5 |
|
|
| Dead registers across the passes | none (every op reads `dst`; reachability pass verified by its firing) | section 6 |
|
|
| Constant folding across the passes | the add's select only (a per-iteration constant, hoistable by anyone; unit C) | section 2 |
|
|
| Common subexpressions across the passes | none (no node of pass k equals a node of pass k + 1; every identity is inside a pass) | section 7.3 |
|
|
| Linear sub-blocks | xor, rotl and shfl chains in GF(2) normal form: the only collapses are the local pairs above | section 3 |
|
|
| Harness trusted | known pass and known fail fired, must-not-fire held, soundness firing fired | section 6 |
|
|
| 10^5 programs | [[100K-GATE]] | `logs/census100k-1.log` |
|
|
|
|
Verdict: PASS. Reservations, stated: (1) the worst of 10^4 sits at 4.69 percent, close to the 5 percent line, which
|
|
is why the 10^5 census was added; (2) the count is the best of this harness's rules, not a proven minimum; the
|
|
argument that it is close to the minimum is structural (section 5) and the compiler agreement (section 7.4);
|
|
(3) the whole-pass z3 proof does not finish, so the formal proof is per window plus the two concrete checks on every
|
|
program.
|
|
|
|
Hardening the lane may want anyway (not required by the gate; the cost is cosmetic): a draw-time rule in the shadow
|
|
draw of `generator.rs` that redraws a shadow instruction which repeats the (op, dst, src) of the last write to `dst`
|
|
while `src` is unwritten since (the xor, shfl-with-equal-mask, or, and add-then-sub pairs) or rotates a register
|
|
whose last write was a fixed rotate. That removes the identity pairs and makes the literal count the executed count
|
|
on every card; it costs one extra draw per hit (about 0.6 percent of shadow slots). Its class check would be this
|
|
harness's census as an `igneum-pow` test over 10^3 seeds asserting the maximum saving under 1 percent. Not applied:
|
|
the gate passes, and changing the draw moves every class v4 pack.
|
|
|
|
## 10. Ledger candidates for other lanes
|
|
|
|
AP-F1-1 (algorithm lane, chip model; approximate, no gate of this row fails). The attacker's `k = 0.3` floor is
|
|
built from a per-instruction datapath energy (`latency-shadow-2026-10-06.md` section 6: 0.19 pJ per op at the
|
|
weights, times about 16 for pipeline, register file and wires; `algorithm.md` 5.3: 0.221 pJ per op, floor 0.32)
|
|
divided by the 5090's 11 pJ, which is per counted op (1.83 per instruction; section 5 of the same file, the rung N
|
|
in counted ops). In one unit the same inputs give a floor of about 0.15 (3.0 pJ per instruction over 20 pJ per
|
|
instruction on the 5090, or 1.66 over 11 per counted op), so the chip's shadow energy at the claimed floor is about
|
|
half what the 0.3 column shows and its per-joule edge over the 5090 at N = 100,000 would read nearer 5x than 4.1x
|
|
at that floor. The `k = 1` and `k = 0.5` columns are unaffected (they are defined on the 5090's own unit). Owner:
|
|
the algorithm lane (F5's model sweep); what it moves: the `k = 0.3` column's label and value in `latency-shadow`
|
|
section 6, `algorithm.md` 5.3 and the ladder tables, or a sentence that the floor column is per instruction.
|
|
|
|
Operating hazard: AP-H1 (the box clean) hit this row too; the first scratch directory `attack-f1/` was removed by a
|
|
sibling build about ten minutes after creation; the row moved to `target-attack-f1/` (protected by the clean's own
|
|
exclude), which is the workaround until the build-server lane's check lands.
|
|
|
|
## 11. Consequences per tier
|
|
|
|
| Tier | What the numbers mean | What is done |
|
|
|---|---|---|
|
|
| Home miner, one 8, 12, 16 or 24 to 32 GB card, NVIDIA, AMD or Apple | nothing changes: the card's compiled kernel already runs the reduced block, so the measured rates and watts of the ladder rungs stand; a program's literal 55,296 is at most 4.7 percent above what the card executes, 0.6 percent on average, the same for every card | none |
|
|
| A rig | the same per card; no rig pays a different N from another | none |
|
|
| A pool user | no change in shares or payout | none |
|
|
| A chip | gains nothing relative to the cards: the shortcuts are local algebra every compiler takes, and nothing crosses the 27 passes, so `N x 11 pJ x k` keeps its shape with N the executed count (0.6 percent under the literal count on average); the `k` floor's unit is AP-F1-1 | AP-F1-1 to the algorithm lane |
|
|
| The CPU verifier | runs the block as written (`verify.rs` interprets every instruction), so on a 4.7 percent program it does 4.7 percent of the shadow work a compiled miner skips: 0.03 ms of the 0.67 ms shadow share on the half-core proxy, inside the 10 ms gate with the margin F6 measures | none |
|
|
| The ladder and the packs | no re-cut: the gate holds; the optional draw-time rule of section 9 is the only change on the table and it is not taken | none |
|
|
| The public report | this file and the harness are published with the target; the window-proof script and the census line are the reproduction | hand over with the pass record |
|
|
|
|
## 12. The census flush (8 October 2026, 04:1x to 05:1x UK; the coordinator's ruling after the class v5 10^5 run)
|
|
|
|
The v5 10^5 census on 1c420786 ran 4 h 30 min on build-1 with nothing on disk: the harness collected every Report in
|
|
memory and wrote `census.csv` once at its end, with no progress line, so its state could not be read (the lane (d)
|
|
row names the gap). Ruling: before the harness's next 10^5 run on any class, a progress line every 1,000 programs
|
|
(count, elapsed, the running failure count) and a partial `census.csv` flushed at the same cadence, with a
|
|
known-failed test of the flush. Done on attack-v5-frozen at 18a9c04a (`tools/attack/f1-shadow/src/main.rs`,
|
|
`census`): the crossing thread rewrites `out/census.csv` from every row so far, sorted by idx, through a temporary
|
|
file and a rename, so a kill never leaves a torn file; the line reads
|
|
`progress: N of COUNT programs, S s, failures F (difftest or verifier), census.csv N rows`.
|
|
|
|
Known-failed test (box 2, `flush-test/`, binary sha256 14180ef40d55eb74..., `lease pool 16 --min 8 --class adv`,
|
|
lease pid 340097, queued 03:12:32Z behind the box's pool, started when adv-accept's sweep-s05b freed its cores):
|
|
a 4,000-program v4 census killed by pid (445480, TERM) the second the 2000 line appeared, at 04:08:27Z.
|
|
|
|
| Reading | Value |
|
|
|---|---|
|
|
| Progress lines before the kill | `1000 of 4000, 286 s, failures 0, 1000 rows`; `2000 of 4000, 571 s, failures 0, 2000 rows` |
|
|
| Rows in `census.csv` after the kill (header excluded) | 2,000 |
|
|
| `census.csv.tmp` left behind | none |
|
|
| Lease exit | 143 (the kill), 16 cores released |
|
|
|
|
Verdict: PASS (2,000 rows after a kill at 2,000; the known-fail of the old harness was zero rows). A side reading:
|
|
1,000 programs per 286 s on 16 cores is about 4.6 core-s per program on this box under its load, which is the
|
|
(c'') and (c''') draw cost per candidate and confirms the F1 10^5 projection on build-1 (about 5 to 6 core-s per
|
|
program, about 10 h on 15 busy cores). Consequences per tier: none for a user; for the lanes, every future census
|
|
can be read and killed without loss.
|
|
|
|
## 13. The frozen class v5 tip, 10^5 programs (1c420786; the 0.3.24 gate line; 8 October 2026, 05:20 UK)
|
|
|
|
Run: igneum-pow class-v5 1c420786 (pairing e5a4ac5978462156), build-1, `lease pool 16 --min 8 --class release`
|
|
(cores 8 to 23, re-leased 22:34:05 UTC on the coordinator's order after the class v5 lease was killed under the
|
|
duplicate-lease clean-up), the binary (sha256 bb70bbf69a4b3223...) copied into `frozen-1c420786-f1/bin`, 16 threads,
|
|
20,774 s (5 h 46 min; about 5 core-s per program, which is the (c''') floor over 2^20 on every candidate draw, measured
|
|
again by section 12's 4.6 core-s on box 2), `out/census.csv` (sha256 4e34b669f2f5c680..., 100,000 rows) and
|
|
`out/summary.txt` written 04:20 UTC. The interim line at 00:55 UTC (0 on the live panic path) cleared the move;
|
|
this is the record line.
|
|
|
|
| Quantity | Value |
|
|
|---|---|
|
|
| Programs | 100,000 (`attack-f1/0` to `attack-f1/99999`), 16 threads, 20,774 s, finished 05:20 UK |
|
|
| Instructions saved, min / mean / max | 0.000 / 0.623 / 4.688 percent |
|
|
| Worst programs | `attack-f1/95060` (attempt 0), `81748` (1), `66933` (1), `3006` (2): 6,912 to 6,588 per iteration (12 of 256 per pass); next `55048` at 4.311 |
|
|
| Programs over 5 percent / over 10 percent | 0 / 0 |
|
|
| Chip-view ops saved beyond free rotates and hoisted constants, mean / max | 0.520 / 4.783 percent |
|
|
| Differential mismatches | 0 of 100,000 (8 random states each) |
|
|
| Verifier mismatches | 0 of 100,000 |
|
|
| Panics | 0 |
|
|
| Dead (never-read) derived nodes under the full fold | 3,553,599 |
|
|
| Rewrites over all programs and 27 passes | identity 3,237,120; xor-cancel 3,127,199; sum-cancel 11,373,389; or-idem 289,936; rotl-merge 4,436,701; rotr-merge 320,399; product-shared 2,303,677 |
|
|
| Histogram of instructions saved, 0.5 percent bins from 0 | 55,241; 20,597; 11,762; 9,851; 1,484; 656; 259; 133; 13; 4; 0; 0 |
|
|
| Draw attempts per program (index 0 = first draw) | 0: 31,630; 1: 21,226; 2: 14,842; 3: 10,151; 4: 7,007; 5: 4,787; 6: 3,257; 7: 2,205; 8: 1,470; 9: 1,115; 10: 697; 11: 502; 12: 345; 13: 225; 14: 174; 15: 113; 16: 78; 17: 53; 18: 38; 19: 28; 20: 12; 21: 17; 22: 8; 23: 6; 24: 5; 25: 7; 29: 1; 30: 1 |
|
|
|
|
Against section 7.2 (class v4 at 10^5, max 5.078, the one letter miss recorded as AP-F1-1): the v5 tip's worst
|
|
program sits 0.39 points under the 5 percent letter, the two top bins are empty (v4: 1 and 7), the mean is unchanged
|
|
(0.617 to 0.623) and the shape of the shortcut is the one of section 7.3 (a register written twice from the same
|
|
source with no write between, 12 instructions, nothing crossing a pass). The attempt histogram has F9's shape
|
|
(first-draw acceptance 0.316 against F9's 0.3145 on chain-shaped seeds), so the string-seed path and the chain path
|
|
draw the same distribution.
|
|
|
|
Verdict: PASS by the letter and at honest-compiler parity (0 of 10^5 over 5 percent, 0 mismatches); AP-F1-1
|
|
FIXED-AND-PASSED on class v5 at this count. Consequences per tier: no drawn program's shadow block gives any chip a
|
|
discount beyond the honest compiler's own simplification (a card pays the full block, a hypothetical ASIC gains
|
|
nothing on the shadow side), and the verifier agrees with the harness on every program, so no node disagrees with
|
|
another on any drawn block.
|