igneum/docs/analysis/cryptanalysis/report-mixer.md
igneum-labs 5bddb289c3 adv-mixer: report with Q3 census (BOUND+tail), Q1 fold (BOUND), Q2 running
Internal adversarial pass, not an independent review. Q3 census over 2^24 day
keys: largest per-day M1 FPGA-datapath gain 1.1726x on one day, 3.26e-4 of days
over 1.1x, zero days with any DSP or wall-time gain, ROT-all-equal never seen.
Q1 fold probe: 1e6/1e6 affinity violations, 0 dead word pairs, 0 key-order
agreements, so no cheap composition of the 8 keyed applications. Q2 diffusion
sweep and the f4 analytic tail are running; numbers land as they finish.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-07 18:24:11 +00:00

10 KiB

Report: adversarial cryptanalysis of the mixer M_r

Internal adversarial pass, not an independent review.

The label "internal adversarial pass, not an independent review" applies to every sentence here that could be quoted in public. This is such a pass. It is not an outside review.

Header

Field Value
Target commit 017e703764 (class v4 sub-version 3, object byte 7)
Target the mixer M_r (spec 01 section 1.8.4), 8 keyed applications between reads, 72 per item, class v4 (m = 8)
Branch adv-mixer, from build/master
Byte-identity memhard.rs, seed.rs, bind.rs, derive.rs, Cargo.toml, Cargo.lock are byte-identical to the frozen commit; accept.rs, emit.rs, generator.rs, packcheck.rs and the two mixer/recheck test files differ and are NOT M_r (plan section 0)
Harness attack-adv-mixer sha256 a01bf61016a8bda530468f081442131f1bff4a7b6401dd84cbcde83c78bb48f3 (box 2 release)
Harness attack-f4 census sha256 d51df6caab338b0165485c3ce6d6379c0af7180bf2b72fc0a1531beabeaf2d22 (box 2 release)
Box igneum-build-2 (box 2), nice 10; the f4 expect tail on igneum-build-1 (box 1), nice 10
Toolchain rustc 1.99.0 both sides
Day under test chain day index 20729 (genesis, 3 October 2026), bind::day_bytes(20729)

Status board

Q Method Known-failed shape Gate Result (numbers) Status
Q3 weak draws f4 census over 2^24 days, M1/M2 datapath cost plant alleq/mul1/mul1all/rc0/rcrk0 (all fired) any class >= 1.1x on a non-negligible fraction largest per-day M1 gain 1.1726x on 1 day in 2^24; 5476 days (3.26e-4) over 1.1x on the generous M1 metric; 0 days with any M2 DSP gain; 0 ops from ROT or RC on any day; ROT-all-equal never occurred FINDING (tail), BOUNDED
Q2 round margin adv-mixer diffusion census, K = 1..8, 2e6 states diffusion --plant weak (fired: 7894 holes, 236269 strong cells at K=1) full diffusion (no hole, no strong bias at 8 sigma) at K running RUNNING
Q1 shortcut adv-mixer fold probe, 1e6 trials the probes are their own control affinity violations > 0, dead pairs = 0, key agreements = 0 1e6/1e6 affinity violations, 0 of 256 dead word pairs, 0 of 1e6 key-order agreements PASS (BOUND: no fold)
Q4 other watched while the above ran n/a n/a fixed round keys and MUL/RC reuse in item init are covered by Q3 classes; nothing further yet RUNNING

Q3: weak parameter draws (BOUND with a measured tail)

Command (box 2):

nice -n 10 taskset -c 64-95 attack-f4 census --from 20729 --count 16777216 --threads 32

Seed: MixParams::with_shape(seed_words_from_bytes(bind::day_bytes(d)), Shape::for_class(&V4_CLASS)) for consecutive chain day indices d from 20729. No external seed. 16,777,216 days (2^24), 4.4 s wall. Log: /srv/builds/igneum-wt-adv-mixer/adv/census-20261007T181830Z.log on box 2.

The gain metric M1 is the per-day LUT datapath: an FPGA bitstream synthesised for one day, the only per-day attacker that exists. A constant XOR folds into the next LUT, a constant rotation is routing, a 32-bit add or XOR is one adder-equivalent, a multiply by a constant is NAF(MUL) - 1 adders. M1 cost per application is 64 + sum(NAF(MUL_i) - 1). The 64 is the 8 quarter rounds' adds and xors. Gain is the census median over the day's cost. This is the generous bound: real single-constant multipliers beat NAF and a DSP multiply is value-independent.

Headline numbers:

Quantity Value
M1 cost mean 231.11 adders per application (sd 6.19)
M1 cost median 231
M1 cost min (best attacker day) 197, day 4819563
M1 cost max 263, day 15262713
Largest M1 gain 1.1726x (231 / 197), 1 day in 2^24
Days with M1 gain over 1.1x (cost < 210) 5476 of 16,777,216 = 3.26e-4 (about 1 in 3064 days)
Days with any M2 DSP-bound gain, k >= 2 0
Days with a ROT or RC wall-time gain 0 (a bit-exact verifier never skips an application; ROT is wiring, RC is inverters)

What this means for the honest miner and the verifier. The M1 gain is the adder count of an FPGA datapath synthesised for one calendar day. It is not a wall-time shortcut against the honest GPU and not a skipped application at the bit-exact verifier. The chip model prices the mixer at 9,360 ops per item hoisted; a 1.17x cut in the multiply layer's adder count on the single best day in 2^24 does not move the chip rows, which are bound by the 8 cache reads and the fixed op count, not by the FPGA adder count of one day. Over 2^24 days (about 45,900 years of calendar days) the worst day hands a per-day FPGA a 1.17x smaller multiply datapath, once.

The spec's open worry (1.8.4: a ROT draw of eight equal values is possible and untested). ROT all equal did NOT occur in 2^24 days. The analytic rate is 1 in 2.751e10 days (about 1 day in 75 million years). The worst realized ROT concentration is 2 days with all eight ROT in {1,2,30,31}, at M1 gain 1.0645x.

Class table, the members that matter (full table in the log):

Class Count / 2^24 Fraction Analytic expected Worst day: M1 cost, gain
ROT all equal 0 0 3.64e-11 none
ROT distinct <= 3 534 3.18e-5 3.07e-5 day 11482247: 208, 1.1106x
ROT max multiplicity >= 4 35631 2.12e-3 2.35e-3 day 9506389: 206, 1.1214x
ROT any pair sums to 32 10022037 5.97e-1 6.01e-1 day 4819563: 197, 1.1726x
ROT all 8 in {1,2,30,31} 2 1.19e-7 7.68e-8 day 14330190: 217, 1.0645x
MUL any = 1 0 0 7.45e-9 none
MUL any popcount <= 4 612 3.65e-5 3.72e-5 day 7275755: 200, 1.1550x
MUL any NAF weight <= 2 4 2.38e-7 (expect run) day 7786546: 221, M2 1.067x
MUL any NAF weight <= 3 216 1.29e-5 (expect run) day 332924: 207, M2 1.067x
MUL two equal 0 0 5.59e-8 none
MUL M2 k >= 2 (gain >= 1.14x) 0 0 (expect run) none
RC any = 0 0 0 3.73e-9 none
RC + rk = 0 for any of 72 keys 10 5.96e-7 2.68e-7 day 3194363: 218, 1.0596x

Every counted fraction tracks the analytic expectation (the draw is unbiased). The M2 DSP metric found zero days with two or more low-NAF multiplies, so no day frees a second DSP block. The analytic expect run (box 1) is cross-checking the NAF-weight tail; its numbers land in this section when it finishes.

Verdict for Q3. A measured weak-day tail exists on the generous M1 FPGA-adder metric: 3.26e-4 of days beat 1.1x, the single best day reaches 1.1726x. It is bounded and small, zero on the DSP metric and zero on any wall-time metric, and the spec's untested ROT-all-equal case never occurs and is astronomically rare. A weak day is a public calendar, so an FPGA attacker could target day 4819563 of the chain for a 1.17x smaller multiply datapath, which the chip model does not credit as a hash-rate gain. This is a FINDING in that the tail is nonzero, a BOUND in that the worst case is 1.17x on a metric that does not move the honest or verifier cost.

Q2: the round margin (RUNNING)

Command (box 2), per K in 1..8:

nice -n 10 attack-adv-mixer diffusion --day 20729 --apps K --states 2000000 --threads 32

Seed: probe states from the harness SplitMix64 seeded per thread from the day index; mixer params the real day 20729 draw. Log: /srv/builds/igneum-wt-adv-mixer/adv/diffusion-20261007T181948Z.log on box 2.

The census band at 2e6 states is 8 sigma = 0.00566, so a per-cell bias below 0.57 percent is invisible; this limit is quoted with every row. The plant fired: the degenerate day (MUL all 1, RC all 0, ROT all 16) at K = 1 gave 7894 dependency holes and 236269 strong-bias cells of 262144, mean flip 0.1739, worst cell 223.6 sigma. A real day must clear to zero holes and zero strong cells to call the distinguisher out at that K. Results land here per K as the sweep runs.

Q1: the structural shortcut (BOUND, no fold)

Command (box 2):

attack-adv-mixer fold --day 20729 --trials 1000000

Seed: harness SplitMix64 seeded from the day index; mixer params the real day 20729 draw.

Probe Result Reading
(a) GF(2) affinity of the 2-application map 1,000,000 of 1,000,000 quadruples violate affinity the two multiply layers do not fold through the double round; the map is far from affine
(b) dead (in_word, out_word) pairs over the full 8-application block 0 of 256 every output word depends on every input word after 8 applications
(c) key-order agreements M(M(.,rk1),rk2) == M(M(.,rk2),rk1) 0 of 1,000,000 key order matters; the 8 round keys cannot be folded

Verdict for Q1. On these probes the 8 keyed applications show no cheap composition. The multiply layers of adjacent applications are separated by a nonlinear double round, so they do not merge (candidate 1 fails). The drawn double round gives no surviving commutation that would fold keys (candidate 3 fails). The word-dependency is complete at 8 applications (no separability). This bounds the cheapest folds. It does not rule out a high-order algebraic or integral distinguisher below the probe's reach; that is owed work (plan section 7). No gain is priced against the 9,360 ops per item: the 8 applications cost 8x on this evidence.

Q4: anything else (RUNNING)

Two structural notes, both covered by Q3 classes. The 72 round keys are fixed multiples of 0x9E3779B9, not drawn, so a bad round key is the same every day; the RC + rk = 0 class counts the one interaction (10 days in 2^24). The item init s[8+i] = t*MUL[i] + RC[i] reuses MUL and RC, so a MUL[i] = 1 would collapse an init word to t + RC[i]; MUL any = 1 occurred on 0 days. Nothing further found yet.

Box-hours spent (so far)

Step Box Wall Slot-hours
Build adv-mixer box 2 21 s 0.006
Build f4-weakday box 2 4 s 0.001
adv-mixer diffusion plant K=1 (50k) box 2 5 s 0.001
adv-mixer fold 1e6 box 2 ~6 s 0.002
f4 five plant firings box 2 ~3 min 0.05
f4 census 2^24 box 2 4.4 s 0.001
Build f4 on box 1 box 1 39 s 0.011
Q2 diffusion sweep K=1..8 box 2 running tracked at end
f4 expect tail box 1 running tracked at end

Spent before the two running sweeps: about 0.08 box-hours of the 8-hour first-results budget.