igneum/docs/analysis/cryptanalysis/report-mixer-3.md
igneum-labs cd60de23de adv-mixer-3 report: ledger row for the ranked lease and the 32-thread re-submission, log copies
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-07 19:44:38 +00:00

316 lines
28 KiB
Markdown

# Report: the statistical distinguisher and the round margin of M_r
Internal adversarial pass, not an independent review. Every sentence here that could be quoted in public carries
that label. Lane adv-mixer-3, branch adv-mixer-3. First results 7 October 2026, 19:0x UTC; rows are appended as
they land.
## Header
| Field | Value |
|---|---|
| Target commit | 017e70376489251e18564c0abce7e466e606c8b3 (class v4 sub-version 3, object byte 7) |
| Target | the mixer M_r (spec 01 section 1.8.4), class v4 (`V4_CLASS` = `MX8`): 72 applications per item, 8 between dependent cache reads |
| Base commit | build/master 7a7caa34, merged 04c4d9bc; `git diff --quiet 017e7037 HEAD -- igneum-pow && echo IDENTICAL` prints IDENTICAL |
| Harness | tools/attack/adv-mixer-3 (igneum-pow by path); binary sha256 bdd8432f6181bcc9e77885cf840c83e2a6ffe5ae027182a1d9181710bbb06e70 (commands index, sac, diff, lin, lin0, rx, cnf), identical on both boxes; v2 8153dbafa4540c796ae5a76e31258dbb1323724465aa4709d9cecd050dea5c40 adds sac0 |
| SAT solver | CaDiCaL 3.0.1, built from the GitHub source into ~/adv-mixer-3-tools on each box (user directory, nothing system-wide) |
| Boxes | igneum-build-1 (queue 01, 03, 05, 09) and igneum-build-2 (queue 02, 04, 06, 08), nice 10, cores 8 to 95, 64 threads per sweep; the boxes ran at load 160 to 460 on 96 cores throughout, so every wall time here is a loaded-box time |
| Logs | /srv/builds/_adv-mixer-3/logs/ on each box (outside the worktree mirror); copies under docs/analysis/cryptanalysis/logs/adv-mixer-3/ on this branch |
| Days | 20729 (genesis, 3 October 2026), 20733 (Devnet 3 epoch 0), plus 8 fixed day indices in queue 07 |
| Band | 6 sigma at the sample count of each row; a cell beyond it is a distinguisher, a cell inside it is invisible to that row |
Plant rule: a tool is trusted once it has fired on a known-failed shape. Which shape fired is in each row.
## Status board
| Q | Method | Known-failed shape | Gate | Result (numbers) | Status |
|---|---|---|---|---|---|
| Q1 | exhaustive round-0 line-index census, all 2^32 t, k = 0..8 | k = 0 (the init: one bin holds 2^32, fired on both days) | chi-square z within 6, no empty bin | day 20729: uniform at k = 1 (z -1.13), 2 (-0.68), 3 (-0.39), 4 (-0.47), 5 (-1.47), 6 (-0.30), 7 (-1.04), 8 (1.13, the real first read); day 20733 uniform at k = 1 (z -0.71), its k = 2..8 running under the lock; day 20730 (queue 07) uniform at k = 2, 3, 4, 8 | PASS to k = 8 on day 20729 (BOUND: the index histogram is uniform from k = 1), RUNNING |
| Q2 | single-bit avalanche, random states, 2^24 (and 2^27) states | `one` at k = 8 (fired: 1959 holes); `weak` fires at k = 1 only, not at k = 8 (see Q2) | no cell beyond 6 sigma | day 20729 k = 1: 354 holes, 129,726 cells beyond 6 sigma, worst p = 1.000; day 20733 k = 1: 266 holes, 136,797 cells; day 20729 k = 2 at 2^24: 0 holes, 0 cells beyond 6 sigma, worst z -4.74 (band 0.0015); k = 3: 0 and 0, worst z -5.28; k = 4: 0 and 0, worst z 5.28; day 20733 k = 2: 0 and 0, worst z -4.59; k = 3: 0 and 0, worst z 4.61; k = 4: 0 and 0, worst z 4.67; k = 5..8 and the 2^27 rows running | FINDING at k = 1, PASS from k = 2 on both days (margin: 1 of 8 on random states) |
| Q2b | t-bit avalanche on the round-0 input (32 bits in), 2^24 (and 2^28) states | k = 0 (the init alone, fired: 12,439 holes) | no cell beyond 6 sigma | k = 1: 0 holes, 218 cells beyond 6 sigma, worst p = 0.7427 (t bit 31 to state bit 53), 18 line-index cells beyond 6 sigma. k = 2..8 at 2^24: 0 cells beyond 6 sigma, worst z 3.7 to 4.7 (the maximum of 16,384 normals is about 4.1); k = 2, 3, 4 at 2^28 states: 0 cells beyond 6 sigma, worst z -4.30, 4.76, -4.64, band 0.00018. Day 20733: k = 1 has 502 cells beyond 6 sigma, worst p = 0.7595 (t bit 31 to state bit 127); k = 2..8 at 2^24: 0 cells, worst z 3.9 to 4.6; its 2^28 rows running | FINDING at k = 1 on both days, PASS from k = 2 on both days (margin: 1 of 8) |
| Q3 | differential multiplicity, 576 low-weight input differences, 2^20 pairs each | `nomul` at k = 1 (fired: 17,289 deterministic output bits at 4,096 pairs) | no multiplicity 4 or more, no deterministic bit | k = 1: 695 deterministic output bits over the 576 differences (max 35 in one difference) on day 20729, 537 (max 40) on 20733; k = 2..7: 0 deterministic bits, max multiplicity 1, no pair with 2 zero words, both days; k = 8 running | FINDING at k = 1 (deterministic bits), PASS from k = 2 |
| Q4 | single-bit linear correlations, random states, 2^26 samples | k = 0 (the identity, fired: c = 1.0 on the diagonal) | no cell beyond 6 sigma (band 0.00073) | day 20729 k = 1..7 and day 20733 k = 1..8: worst c between 0.00055 and 0.00062 (z 4.5 to 5.1; the expected maximum of 262,144 normals is 4.8), 0 cells beyond 6 sigma on every row; day 20729 k = 8 running | PASS from k = 1 (BOUND) |
| Q4b | t-bit linear correlations on the round-0 input, 2^26 samples | k = 0 (fired: c = 1.0, t bit 0 to s[8] bit 0) | no cell beyond 6 sigma | both days, k = 1..8: worst c 0.00046 to 0.00059 (z 3.7 to 4.9 over 16,384 cells), 0 cells beyond 6 sigma | PASS from k = 1 (BOUND) |
| Q5 | rotational-XOR, rotations 1, 8, 16, 2^22 samples | `weak0` at k = 1 (fired: 740 zero-difference words of 2^20 at r = 1, 245 at r = 16) | no zero-difference word above 2 of N, no repeated difference above 3 | both days, k = 1, 2, 3, 4 at 2^22 samples: 0 zero-difference words at every rotation (random expects about 0.001), most frequent per-word difference multiplicity 3 (the birthday expectation at 2^22 draws of 32 bits) | PASS from k = 1 (BOUND: the XOR constants and the odd multiply kill the rotational property inside one application) |
| Q6 | SAT (CaDiCaL) on the round-0 input: find t with a given 22-bit index after k applications | k = 1 solved and verified | solve inside one hour per k, time against the honest 2^10 x k x 130 ops | k = 1: SATISFIABLE in 137 s wall on build-1 (load about 160) and 1,593 s on build-2 (load about 500), the same model t = 0x49880000 both times, verified to the target 0x20eb79 through the real code. Honest: 2^10 trials of one application is under a millisecond. The solver is five orders slower than brute force at k = 1 | PASS at k = 1 (BOUND); k = 2..4 RUNNING (one-hour cap each) |
| Q7 | days: 20733 on every row, 8 fixed day indices on Q1 and Q2 (queue 07, run by the sibling adv-mixer from the shared queue) | as above | as above | day 20733: every row above; day 20730: index uniform at k = 2, 3, 4, 8, sac clean at k = 2, 3; the other seven days pending in queue 07 | RUNNING |
| GPU | any GPU row | n/a | n/a | no GPU on either box | BLOCKED |
The round margin so far (internal adversarial pass, not an independent review): every single-bit statistic that
reaches beyond k = 1 is listed with its k in the rows below. Where the table says "pending" the row is not yet in.
## Q1: the round-0 line-index census (exhaustive)
The input to round 0 is 8 fixed words K and 8 words affine in one 32-bit t, so the first line index is a map of
32 bits to 22 bits and can be censused over its whole domain. For k applications with keys round_key(0..k-1):
Command (build-1), per k: `adv-mixer-3 index --day 20729 --apps k --threads 64`. Logs: index-20729-k<k>.log.
| Day | k | chi-square z (df 2^22 - 1) | empty bins | min | max | segment z | line z | s[0] bit balance worst z | verdict |
|---|---|---|---|---|---|---|---|---|---|
| 20729 | 0 | 6.2e12 | 4194303 | 0 | 2^32 | 7.8e11 | 2.4e10 | n/a | NON-UNIFORM (the plant: one bin) |
| 20729 | 1 | -1.13 | 0 | 871 | 1191 | -2.00 | -0.26 | pending | uniform within the band |
| 20729 | 2 | -0.68 | 0 | 874 | 1191 | 0.56 | -0.14 | pending | uniform |
| 20729 | 3 | -0.39 | 0 | 853 | 1187 | -0.03 | -1.15 | pending | uniform |
| 20729 | 4 | -0.47 | 0 | 857 | 1190 | 1.07 | -0.25 | pending | uniform |
| 20729 | 5 | -1.47 | 0 | 872 | 1202 | 0.99 | -0.11 | pending | uniform |
| 20729 | 6 | -0.30 | 0 | 867 | 1185 | 0.01 | -1.62 | pending | uniform |
| 20729 | 7 | -1.04 | 0 | 862 | 1191 | -0.45 | -0.88 | pending | uniform |
| 20729 | 8 | 1.13 | 0 | 863 | 1202 | 1.46 | -0.63 | pending | uniform (the real first read) |
| 20730 | 2 | -0.53 | 0 | 864 | 1217 | -0.36 | -0.19 | pending | uniform (queue 07, run by adv-mixer) |
| 20730 | 3 | -0.78 | 0 | 866 | 1189 | -0.26 | 1.05 | pending | uniform |
| 20730 | 4 | 0.25 | 0 | 865 | 1187 | -0.01 | -0.30 | pending | uniform |
| 20730 | 8 | -1.29 | 0 | 867 | 1188 | 0.73 | 1.00 | pending | uniform |
| 20733 | 0 | 6.2e12 | 4194303 | 0 | 2^32 | 7.8e11 | 2.4e10 | n/a | NON-UNIFORM (plant) |
| 20733 | 1 | -0.71 | 0 | 863 | 1202 | 0.11 | -0.60 | pending | uniform |
Reading: after one application the 2^32 round-0 inputs already spread over the 2^22 lines as a uniform draw
would (Poisson 1024 per bin: min 871, max 1191 are the expected extremes over 4 million bins). The multiply layer
on the 8 affine words and one double round are enough for the line index as a histogram. This is a histogram
test, not an independence test: Q2b measures whether individual t bits still leak into individual index bits.
## Q2: single-bit avalanche on random states (the regime of rounds 1 to 8)
Command (build-1), per k: `adv-mixer-3 sac --day 20729 --apps k --start 8 --states 2^24 --threads 64`.
Keys round_key(8..8+k-1) (round 1's keys). Logs: sac-20729-k<k>.log.
Plants: `--plant one --apps 8` (one application in place of eight) fired with 1,959 holes and 89,129 cells
beyond 6 sigma at 65,536 states. `--plant weak --apps 8` (MUL 1, RC 0, ROT 16) did NOT fire at k = 8: 0 holes,
worst z 4.88. Eight double rounds of a constant-free ARX permutation on random 512-bit inputs diffuse fully, so
"weak" is a known-failed shape at k = 1 only (a sibling's census fired it there; this lane's 4,096-state smoke
run at k = 1 fired it too: 14,364 holes). The `one` plant is the firing check of this row.
| Day | k | states | holes | cells beyond 6 sigma | worst cell | worst p | line-index cells beyond 6 sigma (of 11,264) | verdict |
|---|---|---|---|---|---|---|---|---|
| 20729 | 1 | 2^24 | 354 | 129,726 | in 279 (word 8) to out 64 (word 2) | 1.0000 | 7,930 | DISTINGUISHED |
| 20729 | 2 | 2^24 | 0 | 0 | in 322 (word 10) to out 373 (word 11) | 0.49942 (z -4.74) | 0 | inside the band |
| 20729 | 3 | 2^24 | 0 | 0 | in 370 (word 11) to out 88 (word 2) | 0.49936 (z -5.28) | 0 | inside |
| 20733 | 1 | 2^24 | 266 | 136,797 | in 30 (word 0) to out 32 (word 1) | 1.0000 | pending | DISTINGUISHED |
| 20729 | 4 | 2^24 | 0 | 0 | in 295 (word 9) to out 346 (word 10) | 0.50064 (z 5.28) | 0 | inside |
| 20733 | 2 | 2^24 | 0 | 0 | in 260 (word 8) to out 450 (word 14) | 0.49944 (z -4.59) | 0 | inside |
| 20733 | 3 | 2^24 | 0 | 0 | in 61 (word 1) to out 495 (word 15) | 0.50056 (z 4.61) | 0 | inside |
| 20733 | 4 | 2^24 | 0 | 0 | in 350 (word 10) to out 23 (word 0) | 0.50057 (z 4.67) | 0 | inside |
| 20730 | 2 | 2^24 | 0 | 0 | queue 07, run by adv-mixer | mean flip 0.50000 | pending | inside |
| 20730 | 3 | 2^24 | 0 | 0 | queue 07, run by adv-mixer | mean flip 0.50000 | pending | inside |
Reading: one application on a random 512-bit state leaves 354 deterministic cells (an input bit that always
or never flips a given output bit) and 129,726 of 262,144 cells beyond 6 sigma; 7,930 of the 11,264 cells that
feed the line index are among them. Two applications leave no cell beyond 6 sigma at 2^24 states (band 0.0015).
The worst z of -4.74 is the expected extreme of 262,144 standard normals. The margin on this statistic is 1 of
the 8 applications between reads, the same as on the round-0 input (Q2b).
## Q2b: t-bit avalanche on the round-0 input
Command (build-1), per k: `adv-mixer-3 sac0 --day 20729 --apps k --states 2^24 --threads 64` (v2 binary).
Logs: sac0-20729-k<k>.log. Plant k = 0 (the init alone) fired: 12,439 holes of 16,384 cells.
| Day | k | states | holes | cells beyond 6 sigma (of 16,384) | worst cell | worst p | line-index cells beyond 6 sigma (of 704) | verdict |
|---|---|---|---|---|---|---|---|---|
| 20729 | 1 | 2^24 | 0 | 218 | t bit 31 to state bit 53 (word 1) | 0.7427 | 18 | DISTINGUISHED |
| 20729 | 2 | 2^24 | 0 | 0 | t bit 23 to bit 147 | 0.49949 (z -4.19) | 0 | inside the band |
| 20729 | 3 | 2^24 | 0 | 0 | t bit 26 to bit 219 | 0.49955 (z -3.73) | 0 | inside |
| 20729 | 4 | 2^24 | 0 | 0 | t bit 30 to bit 329 | 0.50051 (z 4.15) | 0 | inside |
| 20729 | 5 | 2^24 | 0 | 0 | t bit 31 to bit 162 | 0.49947 (z -4.32) | 0 | inside |
| 20729 | 6 | 2^24 | 0 | 0 | t bit 26 to bit 194 | 0.50050 (z 4.08) | 0 | inside |
| 20729 | 7 | 2^24 | 0 | 0 | t bit 6 to bit 390 | 0.49943 (z -4.69) | 0 | inside |
| 20729 | 8 | 2^24 | 0 | 0 | t bit 13 to bit 9 | 0.49947 (z -4.33) | 0 | inside |
| 20729 | 2 | 2^28 | 0 | 0 | t bit 8 to bit 352 | 0.49987 (z -4.30) | 0 | inside (band 0.00018) |
| 20729 | 3 | 2^28 | 0 | 0 | t bit 26 to bit 97 | 0.50015 (z 4.76) | 0 | inside (band 0.00018) |
| 20729 | 4 | 2^28 | 0 | 0 | t bit 17 to bit 8 | 0.49986 (z -4.64) | 0 | inside (band 0.00018) |
| 20733 | 0 | 65,536 | 12,448 | 16,094 | t bit 0 to bit 0 | 0.0000 | 704 of 704 | DISTINGUISHED (plant) |
| 20733 | 1 | 2^24 | 0 | 502 | t bit 31 to state bit 127 (word 3) | 0.7595 | pending | DISTINGUISHED |
| 20733 | 2 | 2^24 | 0 | 0 | t bit 11 to bit 337 | 0.49946 (z -4.45) | 0 | inside |
| 20733 | 3 | 2^24 | 0 | 0 | t bit 23 to bit 219 | 0.49952 (z -3.97) | 0 | inside |
| 20733 | 4 | 2^24 | 0 | 0 | t bit 23 to bit 220 | 0.50051 (z 4.19) | 0 | inside |
| 20733 | 5 | 2^24 | 0 | 0 | t bit 29 to bit 48 | 0.49948 (z -4.25) | 0 | inside |
| 20733 | 6 | 2^24 | 0 | 0 | t bit 20 to bit 404 | 0.49950 (z -4.13) | 0 | inside |
| 20733 | 7 | 2^24 | 0 | 0 | t bit 29 to bit 239 | 0.49953 (z -3.86) | 0 | inside |
| 20733 | 8 | 2^24 | 0 | 0 | t bit 2 to bit 370 | 0.50056 (z 4.62) | 0 | inside |
Why k = 1 has deterministic cells and k = 2 has none (read from the code, `memhard::qr` and `mixer`): a
difference whose lowest set bit is at position j keeps that lowest bit through an XOR with a constant, through a
multiply by an odd constant (the product difference is odd times the difference, so its lowest set bit stays at
j) and through an addition (the lowest changed bit of a sum is the lowest changed bit of the addends when only
one addend changes). So a single flipped bit walks one application as a deterministic lowest-bit trail: a += b
fixes bit j of a, d ^= a fixes bit j of d, the rotation moves it to j + r1, and so on through the 8 quarter
rounds (the 35 to 40 fixed bits per difference that Q3 counts). After one application the difference sits in
every word with several set bits, both addends of every add now carry a difference, and the lowest-bit rule no
longer applies: the trail ends. That is the mechanism behind the margin of 1 in every avalanche row.
Reading: on the real input of round 0 (one 32-bit t), one application leaves a 24 percent bias on 218 of the
16,384 (t bit, state bit) cells and on 18 of the 704 cells that feed the first line index. Two applications leave
nothing at 2^24 states (band 0.0015). The margin on this statistic is 1 of the 8 applications before the first
read: the first read's address is not predictable from t after 2 of its 8 applications, at this band.
## Q3: differential multiplicity
Command (build-1), per k: `adv-mixer-3 diff --day 20729 --apps k --start 8 --samples 2^20 --threads 64`.
576 input differences (512 single bits, 64 random two-bit), 2^20 random pairs each, the 512-bit output difference
hashed to 64 bits; the band for one output difference is 2^-19 (multiplicity 2 or more). Plant `nomul` at k = 1
fired: 7,992 deterministic output bits (day 20729), 7,189 (day 20733). Logs: diff-<day>-k<k>.log.
| Day | k | max multiplicity of one output difference | deterministic output bits (all 576 differences) | max in one difference | pairs with 2 or more zero output words | verdict |
|---|---|---|---|---|---|---|
| 20729 | 1 | 1 | 695 | 35 of 512 | 0 | DISTINGUISHED (deterministic bits) |
| 20729 | 2 | 1 | 0 | 0 | 0 | inside the band |
| 20729 | 3 to 7 | 1 | 0 | 0 | 0 | inside |
| 20733 | 1 | 1 | 537 | 40 of 512 | 0 | DISTINGUISHED (deterministic bits) |
| 20733 | 2 to 7 | 1 | 0 | 0 | 0 | inside |
Reading: at k = 1 a single-bit input difference fixes 35 to 40 output bits (the quarter-round structure: the
first add and XOR of a column pass a flipped bit on deterministically before the rotations spread it), but no
full output difference repeats even once in 2^20 pairs, because the other 470 bits of the difference are
spread. At k = 2 no output bit is fixed by any of the 576 input differences. Differentials of probability above
2^-19 do not exist for these input differences past k = 1. The truncated form (whole output words unchanged)
never beats the random rate at any k.
## Q4: single-bit linear correlations
Command (build-1), per k: `adv-mixer-3 lin --day 20729 --apps k --start 8 --samples 2^26 --threads 64`.
Band: 6 sigma = 0.00073. Plant k = 0 fired (c = 1.0 on the 512 diagonal cells).
| Day | k | samples | worst c | worst z | cells beyond 6 sigma (of 262,144) | line-index worst z | output balance worst z | verdict |
|---|---|---|---|---|---|---|---|---|
| 20729 | 1 | 2^26 | -0.00056 | -4.61 | 0 | -3.72 | 3.82 | inside the band |
| 20729 | 2 | 2^26 | 0.00058 | 4.73 | 0 | 4.09 | 3.47 | inside |
| 20729 | 3 | 2^26 | 0.00056 | 4.61 | 0 | -3.95 | 3.17 | inside |
| 20729 | 4 | 2^26 | -0.00056 | -4.61 | 0 | 4.18 | 3.08 | inside |
| 20729 | 5 | 2^26 | 0.00057 | 4.64 | 0 | 4.14 | 3.27 | inside |
| 20729 | 6 | 2^26 | -0.00055 | -4.54 | 0 | pending | pending | inside |
| 20729 | 7 | 2^26 | -0.00055 | -4.51 | 0 | pending | pending | inside |
| 20733 | 1 | 2^26 | -0.00056 | -4.60 | 0 | pending | pending | inside |
| 20733 | 2 | 2^26 | -0.00056 | -4.60 | 0 | pending | pending | inside |
| 20733 | 3 | 2^26 | -0.00062 | -5.10 | 0 | pending | pending | inside |
| 20733 | 4 | 2^26 | 0.00060 | 4.95 | 0 | pending | pending | inside |
| 20733 | 5 | 2^26 | -0.00060 | -4.94 | 0 | pending | pending | inside |
| 20733 | 6 | 2^26 | -0.00056 | -4.58 | 0 | pending | pending | inside |
| 20733 | 7 | 2^26 | 0.00059 | 4.83 | 0 | pending | pending | inside |
| 20733 | 8 | 2^26 | -0.00060 | -4.95 | 0 | pending | pending | inside |
Reading: a single input bit and a single output bit have no measurable linear correlation after one application
on random states. The worst z of 4.6 to 4.7 over 262,144 cells is what 262,144 draws of a standard normal give
(expected maximum about 4.8). This is the single-bit mask family only; multi-bit masks are owed work.
## Q4b: t-bit linear correlations on the round-0 input
Command (build-1), per k: `adv-mixer-3 lin0 --day 20729 --apps k --samples 2^26 --threads 64` (x = the 32 bits
of t, y = the state after the init and k applications). Plant k = 0 fired: c = 1.0 between t bit 0 and s[8] bit 0
(the init's `t * MUL[0] + RC[0]` has bit 0 = t bit 0 XOR RC bit 0), 65 cells beyond 6 sigma.
| Day | k | worst c | worst z | cells beyond 6 sigma (of 16,384) |
|---|---|---|---|---|
| 20729 | 1 | 0.00048 | 3.93 | 0 |
| 20729 | 2 | 0.00059 | 4.85 | 0 |
| 20729 | 3 | 0.00051 | 4.14 | 0 |
| 20729 | 4 | 0.00049 | 4.04 | 0 |
| 20729 | 5 | -0.00057 | -4.67 | 0 |
| 20729 | 6 | -0.00048 | -3.97 | 0 |
| 20729 | 7 | 0.00058 | 4.76 | 0 |
| 20729 | 8 | -0.00051 | -4.15 | 0 |
| 20733 | 1 | 0.00047 | 3.82 | 0 |
| 20733 | 2 | 0.00056 | 4.60 | 0 |
| 20733 | 3 | 0.00051 | 4.19 | 0 |
| 20733 | 4 | 0.00052 | 4.25 | 0 |
| 20733 | 5 | 0.00049 | 4.02 | 0 |
| 20733 | 6 | -0.00050 | -4.08 | 0 |
| 20733 | 7 | -0.00046 | -3.74 | 0 |
| 20733 | 8 | -0.00058 | -4.75 | 0 |
Reading: no t bit has a linear correlation with any state bit after one application, at a band of 0.00073. The
24 percent avalanche bias of Q2b at k = 1 is a differential effect (a flipped t bit flips a state bit with
probability 0.74), not a linear one.
## Q5: rotational-XOR
Command (build-1): `adv-mixer-3 rx --day 20729 --apps k --start 8 --samples 2^22`. Plant `weak0` (MUL 1, RC 0,
ROT 16, round key 0: a constant-free ARX round) at k = 1 fired on both days (day 20733: 739, 222): at r = 1, 740 of 2^20 samples had a zero
rotational-XOR difference in one word and the difference 0x00000001 repeated 784 times; at r = 16, 245 zero
differences. Real day:
| Day | k | samples | zero-difference words, max over 16 words, at r = 1 / 8 / 16 | most frequent per-word difference, multiplicity | verdict |
|---|---|---|---|---|---|
| 20729 | 1 | 2^22 | 0 / 0 / 0 (random expects 0.001) | 3 / 3 / 3 (birthday expectation at 2^22 draws of 32 bits: 3) | no RX property |
| 20729 | 2 | 2^22 | 0 / 0 / 0 | 3 / 3 / 3 | no RX property |
| 20729 | 3 | 2^22 | 0 / 0 / 0 | 3 / 3 / 3 | no RX property |
| 20729 | 4 | 2^22 | 0 / 0 / 0 | 3 / 3 / 3 | no RX property |
| 20733 | 1 to 4 | 2^22 | 0 / 0 / 0 on every row | 3 / 3 / 3 on every row | no RX property |
Reading: rotational-XOR cryptanalysis needs the constants to be rotation-friendly; here every word is XORed with
a drawn 32-bit constant plus the round key and then multiplied by a drawn odd constant before the ARX layer, so
the rotational pair (x, x <<< r) loses its relation inside the first layer. No RX property reaches k = 1.
## Q6: SAT on the round-0 input
Command (build-1, smoke run): `adv-mixer-3 cnf --day 20729 --apps 1 --t0 0x12345678 --out k1.cnf` then
`cadical -q k1.cnf`. CNF: 33,873 variables, 112,328 clauses (Tseitin: t is 32 variables; each constant multiply
is a shift-add chain of 32-bit ripple adders over the set bits of MUL; each quarter round four adders; rotations
are wires; constants are folded). Result: `s SATISFIABLE`, 137.06 s wall on the loaded box; the model gives
t = 0x49880000; `adv-mixer-3 verify --day 20729 --apps 1 --t 0x49880000` prints index 0x20eb79, the target.
Honest cost of the same task: about 2^10 random t each through one application, under 2^18 integer operations,
under a millisecond on one core. The solver at k = 1 is five orders slower than the honest search.
| Day | k | CNF variables | CNF clauses | result | wall | model verified |
|---|---|---|---|---|---|---|
| 20729 | 1 (smoke, build-1) | 33,873 | 112,328 | SATISFIABLE | 137 s | t = 0x49880000, index 0x20eb79 = target |
| 20729 | 1 (queue 08, build-2) | 33,873 | 112,328 | SATISFIABLE | 1,593 s (box at load 500) | the same t |
| 20729 | 2 | 68,624 | 227,767 | not run (the lease was withdrawn before it was granted) | | |
Reading: the one-application model is a 32-variable problem with 112 k clauses of ripple-carry adders (16
constant multiplies of up to 32 adders each dominate). CaDiCaL needs minutes on it where the honest search needs
a millisecond, and the k = 2 model doubles the clause count. The SAT route to the first read's address is not a
shortcut at k = 1; the rows for k = 2 to 4 say how fast it gets worse.
## Box-hours
Rule changes during the pass (so the hours stay honest): 18:4x UTC the build-server lane dropped the SIGSTOP
yield-to-builds rule and set every sweep to nice 10 on cores 8 to 95; the same lane moved every log, pid file and
CNF out of the worktree mirror into /srv/builds/_adv-mixer-3/. Both applied before the first sweep started. 18:56 UTC the same lane set one bounded sweep per box across all lanes (`flock /srv/builds/_adv/locks/sweep.lock`, 88 threads): queue 01 (index 20729, k = 5..8 left) and 02 (index 20733, k = 2..8 left) were killed by pid file at 18:57 and 18:58 UTC as the lowest-value runs and re-queued as queue 10 under the lock; the six other sweeps that had started were left to finish; nothing new starts outside the lock.
| Step | Box | Start (UTC) | Wall | Note |
|---|---|---|---|---|
| Build harness (two builds, one fix) | build-1 | 18:36 | 29 s | |
| Build harness | build-2 | 18:44 | 14 s | |
| CaDiCaL from source | build-1, build-2 | 18:42, 18:44 | about 1 min each | |
| Smoke plants and k = 1 SAT | build-1 | 18:38 | 3 min | |
| Queue 01, 03, 05 | build-1 | 18:42 | running | |
| Queue 02, 04, 06, 08 | build-2 | 18:47 | running | |
| Queue 09 (sac0) | build-1 | 18:50 | running | |
| Queue 01 and 02 killed | build-1, build-2 | 18:57, 18:58 | 15 min, 11 min | the one-sweep-per-box rule; re-queued as 10 |
| Queue 10 (index 20729 k = 5..8, 20733 k = 5..8) under the sweep lock | build-1 | 19:00 | 21 min | 20729 k = 5..8 done; 20733 k = 5 was running when killed |
| Queue 16 (index 20733 k = 2..4) under the sweep lock | build-2 | 19:13 | 7 min | k = 2 was running when killed |
| Every adv-mixer-3 process killed | build-1, build-2 | 19:20:51 to 19:21:01 | | main's rule (relayed by the coordinator at 19:20 UTC): no sweep starts except through the build-server lane's `lease pool`; everything hand-started is killed now. Killed by pid file, process group: 03 (sac 20729: k = 5 at 2^24 and the 2^27 rows lost), 09 (sac0: the day 20733 2^28 rows lost), 10 (index 20733 k = 5..8 lost), 04 (sac 20733 k = 5..8 lost), 08 (CaDiCaL on k = 2 for 20729, about 7 min in, lost; k = 3, 4 and day 20733 not started), 16 (index 20733 k = 2..4 lost). Zero processes of this lane remained on either box at 19:21:01 UTC. Nothing of this lane ran until `lease pool` existed |
| Re-queue through `lease pool` | build-1 (queue 17: sac 20729 k = 5..8 and 2^27 rows, sac 20733 k = 5..8, index 20733 k = 2..8, sac0 20733 2^28 rows), build-2 (queue 18: CaDiCaL k = 2..4, both days) | 19:24 UTC (relaunched 19:2x after a guard line refused on the first start) | running | `lease pool 48 --min 16` per census (the lease sizes the harness threads to the cores it took), `lease pool 1 --min 1` per CaDiCaL; waits behind the release builds and the class v5 suites, which outrank every sweep tonight |
| v5 yield | both | 19:26, widened 19:31 | | before every lease the driver sleeps while any waiter in `lease status` is owned by class-v5 or labelled v5; both drivers restarted with the rule before their first lease was granted; refined 19:32 to yield by owner (class-v5, or attack-pass with v5), never to another adv- lane |
| Queue 18 withdrawn from build-2 | build-2 | 19:35 | 0 (no lease was ever granted) | main's order: every adv-* waiter leaves box 2 until the class v5 census runs; the SAT rows k = 2..4 re-queue there afterwards |
| Priority classes in the lease (release > v5 > measure > adv) | build-1 | 19:42 | | queue 17 killed and re-submitted once under the ranked tool as `lease pool 32 --min 16` (an adv holder at 32 threads or fewer is never pre-empted); waiting on free cores at 19:43 UTC |
| Queue 07 (8 random days) | build-1 | 18:5x | running | claimed and run by the sibling lane adv-mixer from the shared queue; its logs are index-<day>-k<k>.log and sac-<day>-k<k>.log under /srv/builds/_adv-mixer-3/logs/ on build-1, read by this lane |
## The round margin, stated
Internal adversarial pass, not an independent review. Against the 8 applications between dependent cache reads
and the 72 per item, on the two real days 20729 and 20733:
| Statistic | Reaches k = 1 | Reaches k = 2 | Margin between reads | Margin per item |
|---|---|---|---|---|
| Single-bit avalanche on random 512-bit states (Q2), 2^24 states | yes (354 and 266 deterministic cells, 130 k cells beyond 6 sigma) | no (0 cells at band 0.0015) | 8 - 1 = 7 | 71 |
| t-bit avalanche on the round-0 input (Q2b), 2^24 and 2^28 states | yes (24 to 26 percent bias on 218 and 502 cells) | no (0 cells at band 0.00018) | 7 | 71 |
| Deterministic output bits of a low-weight input difference (Q3), 2^20 pairs | yes (35 to 40 bits fixed per single-bit difference) | no | 7 | 71 |
| Any repeating full output difference (Q3), band 2^-19 | no | no | 8 | 72 |
| Single-bit linear correlation (Q4, Q4b), band 0.00073 | no | no | 8 | 72 |
| Rotational-XOR (Q5), 2^22 samples | no | no | 8 | 72 |
| Round-0 line-index histogram over all 2^32 t (Q1) | no (uniform from k = 1, through k = 8) | no | 8 | 72 |
| SAT preimage of the round-0 line index (Q6) | k = 1 solved, 137 s, five orders slower than the honest 2^10 trials | not run (killed at 19:20 UTC) | not a shortcut at k = 1 | |
Every statistic that reaches k = 1 is the lowest-set-bit trail through one application (the mechanism in Q2);
none reaches k = 2 at the bands above. The bound: no distinguisher in this pass survives 2 of the 8 keyed
applications between reads, so 6 of the 8 are margin on every measured statistic, and 70 of the 72 per item. A
shortcut was not found: no method here saves even one application against the honest 9,360 ops per item of
chip-model-v3.md. What the bands do not cover: biases below 0.00018 (Q2b) or 0.0015 (Q2), correlations below
0.00073 with multi-bit masks, differentials below 2^-19, and any structure a SAT model of 2 or more applications
would expose. Unknown: whether the sibling lanes' censuses over random days change any row.
## What a longer pass would add
Multi-bit linear masks and a MILP trail bound; the SAT model on the full 512-bit state with a cache-line XOR
between applications; 2^30 states on the k that sits at the band. None of these is a reason to wait on the
numbers above.