Merge branch 'ca3-crypto-brief' into ca3-coord

This commit is contained in:
igneum-labs 2026-10-06 07:30:42 +00:00
commit 265749d557

View file

@ -28,6 +28,7 @@ Columns: estimated cost with its basis; what is funded today; what depends on fu
| Development: the second independent node client | Not in the 13-month plan (`docs/fud-fixes.md` rows 31, 47). Basis: decision pending | Not funded | Yes, entirely | Does not start |
| Independent review: finality rule v2 (gate 3, phase 4, the rule external review is paid to break) | USD 50,000 to 100,000. Basis: a focused review of one consensus rule plus its simulation by two reviewers over a few weeks, from memory, approximate | Founder's own means | No | Not pausable: the roadmap says the phase 4 gate is "finality design passes external review". If it cannot be paid, phase 4 does not close and the dates move |
| Independent audit: the node fork (consensus delta, p2p, difficulty, header validation, the pow engine) before public testnet | USD 60,000 to 120,000. Basis: the delta is listed row by row in `docs/fork-divergence.md`; the base is rusty-kaspa, already audited upstream, approximate | Founder's own means, second in order after the finality review | Partly: a second pass after the attack harness closes its stubs | The single pass is kept; the second pass waits. Public testnet does not open without the first pass |
| Independent cryptanalysis: the mixer `M_r`, the chained cache and the acceptance rule of the lottery hash, with the class v3 x8 shape as the target (Counter ASIC 3.0 item 3; the brief is the last section of this file) | USD 80,000 to 160,000 for two independent reviews: one firm at USD 50,000 to 100,000 for 25 to 40 person-days, one academic group at USD 30,000 to 60,000 for a comparable effort, both approximate. Basis: the four RandomX reviews of 2019, the only public price points for a proof-of-work hash review: Trail of Bits USD 28,000 for two person-weeks, X41 EUR 42,000 for 30 person-days by three testers, Kudelski CHF 18,250 for 6 person-days, Quarkslab USD 52,800 for 32 person-days by three engineers (the RandomX README section "Audits" and the four reports in its `audits/` directory, https://github.com/tevador/RandomX, read 6 October 2026; `vendor/RandomX` is not checked out in this worktree, so the web copy is the source); about USD 145,000 together at 2019 rates, approximate, and USD 1,650 to 3,000 per person-day then, raised here by about a third for 2026, approximate. Engagement length is the firm's, not ours: 3 to 6 weeks of calendar per review (X41 ran 3 to 28 June 2019; Quarkslab "about three weeks"), 8 to 10 weeks from commission to both final reports with a re-run after any parameter change, approximate | Proposed: founder's own means, third in order after the finality review and the first node pass (the history audit raised it to a genesis gate, `docs/analysis/asic-resistance-history.md` section 4.3 addition 3; the project lead confirms) | No | The academic review alone (USD 30,000 to 60,000), timeboxed to the ranked questions 1 to 3 of the brief; testnet-1 opens with the report's absence stated on the download page and announces no reset-free period until the report is in; mainnet does not open without it (rule 2: the report is published whole, pass or fail) |
| Independent audit: execution layer and proving integration (revm driver, two-dimensional gas, proof records, the veto, the `ProofSystem` version 1 integration) before mainnet | USD 80,000 to 150,000. Basis: an EVM-integration audit of a new client's execution path, from memory, approximate | Not funded | Yes | Mainnet moves until it is paid. Mainnet does not ship with an unaudited execution layer |
| Independent audit: the official client and release process (spec 08: reproducible builds, release key, update path) | USD 20,000 to 40,000. Basis: a short application security review, from memory, approximate | Not funded | Yes | The one-click app ships at testnet unaudited and says so on the download page; the audit lands before mainnet or the app does not carry the mainnet release key |
| Infrastructure: the 20-node cloud devnet | USD 476 per month for 20 nodes (Hetzner API prices of 3 October 2026, net, `docs/plans/cloud-devnet.md`); about USD 6,000 for the 13 months, plus rented GPU hours for the hourly-compile and shard measurements at USD 0.22 to 0.74 per card hour (RunPod, 3 October 2026): under USD 1,000 over phase 2 | Founder's own means | No | Node count drops to 8 (two per location); the rented GPU hours are replaced by the project's own cards |
@ -62,3 +63,127 @@ The fee is 1% of rewards on the official client. Rewards in year one are 963 mil
2. A review or audit that is paid for is published whole, pass or fail, and linked from `docs/evidence.md`.
3. A bounty is announced only when it is escrowed.
4. This plan is revised when a number changes; the git history of this file is the record.
## The mixer cryptanalysis brief (Counter ASIC 3.0 item 3)
6 October 2026, worker `ca3-crypto-brief`. This is the scope a reviewer is sent. It is a document: nothing here is commissioned, paid or mailed. Every figure cites its source or is marked approximate. Code references are to the commit this brief was written on (`50df751`).
### B1. The target, precisely
The lottery hash's memory-hard dataset (spec `docs/spec/01-lottery-hash.md` section 1.8; code `igneum-pow/src/memhard.rs`). The reviewer gets the spec, the crate, the pinned packs and vectors, and this table.
| Piece | Exact definition | Source |
|---|---|---|
| Day key `K[0..7]` | `seed_words_from_bytes(day_bytes)`: FNV-1a 64 plus SplitMix64 into eight 32-bit words (spec 1.3). On the chain today (interim rule O-1.10) `day_bytes = "igneum-day/" \|\| day_le64` with `day = header.timestamp_ms / 86,400,000`: a pure function of the calendar day, so every future day's key and mixer parameters are computable now. The proposed final rule ties the day to the first epoch seed of the day (a VDF output), which is not in the node yet | spec 1.8.1, 1.12; `igneum-pow/src/bind.rs` lines 17, 62 to 71 |
| Block function `B` | ChaCha12 core with feed-forward: six double rounds of the standard quarter round with rotations (16, 12, 8, 7), then `y[i] = y[i] + x[i]`. Twelve rounds, no key schedule beyond the input block | spec 1.8.2; `memhard.rs` `chacha_block`, lines 151 to 169 |
| The cache | 2^26 words (256 MiB at genesis; 2^27 from chain day 1,460 and 2^28 from day 4,380 under the growth rule), 2^22 lines of 16 words, in 2^16 independent segments of 64 chained lines. Segment `s`, line `j`: `x_j = prev XOR (sigma[0..3] \|\| K[0..7] \|\| s \|\| j \|\| tag[0..1])`, `line_j = B(x_j)`, `prev = line_j`, `prev_0 = 0^16`, `tag = ("Igne", "umMH")`. Line `j` costs `j + 1` block evaluations from nothing, 32.5 on average. The feed-forward means `line_j = C(x_j) + x_j` where `x_j` carries `line_{j-1}` by XOR | spec 1.8.3; `memhard.rs` `fill_segment_tagged`, lines 322 to 341; `cache_log2_words`, line 112 |
| Mixer parameters | One SplitMix64 stream seeded with `K[0] \| (K[1] << 32)`: only 64 bits of the day key reach the parameters (`K[2..7]` enter the item through its initial state only). Draw order: `ROT[0..7] = 1 + below(31)` (eight draws, range 1 to 31), `MUL[0..15] = low32(next()) OR 1` (sixteen, odd), `RC[0..15] = low32(next())` (sixteen) | spec 1.8.4; `memhard.rs` `MixParams::with_shape`, lines 187 to 202 |
| The mixer `M(s, rk)` on 16 words | Layer 1, per word `i` in 0..15: `s[i] = (s[i] XOR (RC[i] + rk)) * MUL[i]` (an odd multiply, a bijection per word). Layer 2, one ChaCha-shaped double round: four column quarter rounds `QR(s0, s4, s8, s12)`, `(s1, s5, s9, s13)`, `(s2, s6, s10, s14)`, `(s3, s7, s11, s15)` with rotations `ROT[0..3]`, then four diagonal quarter rounds `(s0, s5, s10, s15)`, `(s1, s6, s11, s12)`, `(s2, s7, s8, s13)`, `(s3, s4, s9, s14)` with rotations `ROT[4..7]`. `QR(a, b, c, d; r1..r4)` is the standard ChaCha quarter round with those rotations. Structure: an ARX-multiply round, one multiply layer then one ChaCha double round, with the rotation amounts and the multiply and add constants drawn per day and the round key `rk` the only difference between applications | `memhard.rs` `mixer`, lines 290 to 303; `qr`, lines 136 to 149 |
| Op count of one application | Counted from the code: layer 1 is 16 x (add, xor, mul) = 48; layer 2 is 8 quarter rounds x 12 (4 add, 4 xor, 4 rotate) = 96; 144 as written, 128 with `RC[i] + rk` hoisted into a per-application constant. The spec says "about 130"; the chip model prices 130 | `memhard.rs` lines 290 to 303; spec 1.8.4; `docs/analysis/chip-model-v3.md` section 1 |
| Round keys | `rk = (r * m + j + 1) * 0x9E3779B9 mod 2^32` for round `r` in 0..8 and application `j` in 0..m-1: the first `9 m` multiples of an odd constant, all distinct | `memhard.rs` `round_key`, `round_key_mult`, lines 276 to 285 |
| Class v3 multiplier | `m = 8` (`LoadClass::MX8`, `V3_CLASS`), so 9 x 8 = 72 applications per item: 8 before each of the 8 cache reads and 8 after the last. `mixers_per_item = (ITEM_ROUNDS + 1) x m`. Decided 5 October 2026 22:05 UTC under the delegated rule (verify 2.1 ms per unit on one M5 Max core against the 10 ms gate; the daily 1 GiB build 23 to 77 ms on the two discrete cards) | `igneum-pow/src/generator.rs` lines 403 to 407, 704; `memhard.rs` line 87; `docs/plans/mixer-x4.md` section 6.5. Note for the editor: spec 1.13.1's table and `mixer-x4.md` section 2 still print `m = 4`; the code and spec 1.8.5 say 8 |
| Item derivation `item(t)` | `s[0..7] = K[0..7]`; `s[8 + i] = t * MUL[i] + RC[i]` for `i` in 0..7 (linear in `t` per word). For `r` in 0..7: apply `M` eight times with the round keys above; `a = s[0] AND (2^(C - 4) - 1)` (the cache line index, `C = 26` at genesis: 2^22 lines); `s[i] = s[i] XOR cache[line a][i]` for all sixteen words. Then eight more applications. Eight dependent reads: read `r`'s address depends on every earlier read. The chip model's cost per item: 72 x 130 = 9,360 integer operations, plus 16 for the init and 128 XORs | spec 1.8.5; `memhard.rs` `derive_items_mask`, lines 503 to 536 |
| Dataset and the hash's reads | `dataset[w] = item(w >> 4)[w AND 15]` under the linear layout; the era layout permutes four address bits below 16, so an item keeps its value. A program makes exactly 16 loads x 8 iterations = 128 loads per hash, each a 4-byte dataset word at `rotl(x * M, R)` masked into a drawn window of at least 2^26 words; the verifier derives at most 4,096 items per 32-lane unit | spec 1.8.5, 1.9, 1.11, 1.13.1; `docs/analysis/chip-model-v3.md` section 1 (128 items per hash, median 128.00 distinct) |
| Program acceptance (what the reviewer checks as a filter, not a proof) | (a) every `load` reads a register written since the previous `load` from it; (b) every register has an injecting write; (c) 64 units x 32 lanes = 2,048 evaluations against a closed-form stand-in dataset at 2^28 words: no register bit constant, no lane-constant load site, under 164 saturated finals (1 percent), every output bit within 136 of 1,024 ones (6 sigma), distinct masked addresses per lane summed above 245,760 (mean above 120 of 128). Attempt `k` redraws from `seed \|\| k_le32`. Measured rejection 5.14 percent over 100,000 seeds (3.93 static, 2.05 dynamic); the closed-form verdict agrees with the live-dataset verdict on all but 39 threshold-edge programs of 100,000 | spec 1.4.6; `igneum-pow/src/accept.rs` lines 1 to 36; `docs/analysis/weak-program-census-2026-10-03.md` sections 1, 6, 7.3 |
| Era draws that touch the program, not the derivation | Per era: op weights perturbed by up to 2 points, output fold rotations redrawn in 1..31, the stride multiplier `M` (odd), the stride rotation `R`, the four interleave positions; `epoch_len` by miner signal. Not drawn: the load count (16), the mixer round count (8), `mixer_mult`. So no era changes `item(t)`; the chip model prices the era draws at zero for the recompute chip | spec 1.13.1; `docs/analysis/chip-model-v3.md` section 2 |
| What exists in place of a proof | The soundness suite (B4) and three measurements: an inline kernel that recomputes every word runs at 0.21 of the honest rate on the M5 Max (0.10 against a 256 MiB honest dataset); the stats run on three programs; the x8 verifier at 2.08 ms per unit. No cryptanalysis of `M_r`, of the chain, or of the draws has been done; MEMHARD.md names the all-equal `ROT` draw as untested | `proto-metal/MEMHARD.md` sections 2.2 and 3 items 3 to 5; spec 1.8.4 |
### B2. What a break looks like, ranked by what it hands a chip
The chip is the on-die-cache recompute chip of `docs/analysis/chip-model-v3.md`: the whole cache in SRAM (128 mm^2, USD 46 per good die at N5 headline density, approximate), every item derived, 50 T op/s (approximate), scored against the RTX 5090's measured 136.1 MH/s. Today's row: 1,198,080 ops per hash (128 x 72 x 130), 41.7 MH/s, 0.31x bare, 0.92x with the 3x fixed-function factor, 0.76x at equal silicon. Each break names the number it moves.
| Rank | Break | What it hands a chip | The chip-model number it moves | Precedent |
|---|---|---|---|---|
| 1 | A structural shortcut in `M_r`: the 72 keyed applications of one fixed ARX-multiply round compose into something cheaper than 72 x 130 ops. Candidates the reviewer prices: the per-word multiply layer commuting or folding across applications because only `rk` changes; a differential, linear or rotational property of one ChaCha double round with drawn rotations that survives 8 applications; an algebraic form of the 8 applications between two cache reads (the one block of work a chip pipelines) | Ops per item below 9,360. At 4,680 (a 2x shortcut) the chip reads 83.5 MH/s, 0.61x bare, 1.84x with the factor: the x4 row. At 2,340 (4x): 167 MH/s, 1.23x, 3.7x. At 1,170 (8x, the class v2 cost): 334 MH/s, 2.45x, 7.4x with the factor, 6.1x at equal silicon. x8 multiplies the weight of this break: the same shortcut was worth one eighth as much under v2 | "Ops per hash" and every gain column of `chip-model-v3.md` section 2 | Catena's proofs flawed, 25x area-time cut (Biryukov and Khovratovich, ASIACRYPT 2015, history [P10]); Lyra2REv2's chip at 20x after the cryptanalysis found the shortcut first (history row 7) |
| 2 | A time-memory trade-off on the chained cache under 256 MiB: deriving line `(s, j)` in fewer than `j + 1` block evaluations without holding an earlier line of segment `s`, or a relation between lines through the XOR chaining and the feed-forward. The honest trade-off is not a break: holding every 8th line (32 MiB) costs 3.5 blocks per read on average, about 2,450 ops per line and 19,600 per item on top of the mixer (ChaCha12 at about 700 ops per block, MEMHARD.md item 4, approximate), which reads 13.5 MH/s, 0.10x bare, 0.30x with the factor; the full mirror beats it. A break is anything that beats this arithmetic | The SRAM column: 128 mm^2 and USD 46 toward zero, and the node class with it: a 256 MiB mirror forces a 7 nm-class die (a USD 50M-class project); a chip with no mirror can be a 28 nm part (USD 5M to 30M, history section 2.5, the cited articles disagree by 2x). Equal silicon 0.76x rises toward the 0.92x with-factor row | "SRAM the chip holds", "Equal silicon", the node class of history 2.5 | MTP: 2 GB to under 1 MB at a 170x compute penalty before launch, by steering Argon2d's data-dependent addresses (Dinur and Nadler, CRYPTO 2017, [P18]); Argon2i's parameters at O(n^1.75 log n) (Alwen and Blocki, [P5] [P6]) |
| 3 | A weak-key class in the draws: `ROT` values that make a quarter round weak (eight equal, probability 31^-7 = 3.6 x 10^-11 per day, approximate arithmetic; pairs summing to 32; small amounts), `MUL = 1` or low-weight multipliers (2^-31 per word), `RC + rk` structure. Only 64 bits of `K` seed the draw. Under the interim day rule the weak days are a public calendar computable today for every future day, so a chip built to run only on weak days can be planned in advance | On a weak day the ops per item fall as in rank 1 for that day. The chip's yearly gain is the weak-day fraction times the per-day gain: at one weak day in a thousand nothing moves; at one in twenty a chip that idles 95 percent of the time still mines the other days at rank 1's gain | "Ops per hash" on the weak days; the fraction is the number the review must produce | MEMHARD.md section 3 item 3 (the all-equal `ROT` draw, untested); RandomX's Kudelski scope named "weaker authorized parameters" as a goal (Report-Kudelski.pdf, 2 July 2019) |
| 4 | Non-uniformity of the item distribution: (a) the line index `s[0] AND mask` after the mixer not uniform over 2^22 lines, so a hot subset of lines covers most reads; (b) across all nonces of an epoch, a hot subset of the 2^24 items covers most of the program's 128 loads. The acceptance rule bounds distinct addresses within one hash, not the cross-hash distribution | (a) The SRAM column shrinks to the hot lines: a chip holding 10 percent of the lines at 90 percent hit rate pays the chain recompute on 10 percent of reads only. (b) A chip or a card holds items, not the cache, and the 128-items-per-hash input falls | "SRAM the chip holds"; "Items per hash" | Distinct cache lines per hash never censused (MEMHARD.md item 5: analytically at most 1,024 of 4,194,304 lines per hash under 128 loads, a warp's working set 32,768 lines, approximate); the daily build is latency-bound, so a hot set would also speed the honest build |
| 5 | An acceptance-rule bypass that lets a miner steer addresses: a program that passes (a) to (c) on the closed-form stand-in and has exploitable locality on the live dataset (the 39 edge disagreements of 100,000 are the known gap); and header grinding for locality (history check 1): the miner chooses the header bytes behind the pre-PoW hash and searches for 32-lane groups whose 128 loads cluster into fewer DRAM rows or lines, at a search cost below the gain | A software gain to the grinder on every card: it breaks the fair-lottery property of spec 1.1 before it helps a chip; a chip adds the hot set of rank 4 (b) | "Items per hash"; the honest denominator (a grinder's card reads above 136.1 MH/s) | Kik's ProgPoW exploit: a 64-bit seed let a chip skip memory with a cooperating node, patched in 0.9.4 (history [S71]); MTP as above |
| 6 | Day-key or era-seed grinding: influencing the block that feeds the day's first epoch seed or the era VDF to pick a favourable day key (rank 3 made selectable) or era draw. The era draws do not touch the derivation, so grinding the era moves the program only | Converts rank 3 from a calendar into a choice; nothing else. Under the interim day rule there is nothing to grind because the key is the calendar | None directly; the probability in rank 3 | Spec 1.12 O-1.10 (the proposed derivation), 4.4 (the VDF); history [S71] |
### B3. Deliverables, with a timebox
| Deliverable | Content | When |
|---|---|---|
| The written report | One verdict per question of B2, ranks 1 to 6, each with the effort spent on it (person-days, tools, the reduced-round or reduced-size margin reached) and a severity in the firm's own scale; published whole, pass or fail, under rule 2 of this plan | End of the timebox |
| Attack code | Any shortcut, trade-off, weak-key census or address-steering search the reviewer wrote, runnable against `igneum-pow` on the pinned packs `mx8-genesis` and `mx8-devnet-epoch0`, with the measured gain beside the honest path | With the report |
| A re-run of the soundness suite | B4, on the reviewer's machine, with the counts; any test the reviewer adds goes into `igneum-pow/tests/` | With the report |
| A recommendation on `mixer_mult` | Keep 8, or move to 16 (the chip model's next lever: 0.16x bare, 0.46x with the factor; verifier about 3.7 ms per unit, approximate, under the 10 ms gate on the M5 Max core, unmeasured on a 2019-class laptop core, O-1.14), or change the mixer's shape; stated against ranks 1 and 3 | With the report |
| A recommendation on the rotation draw bounds | Keep `1 + below(31)` for all eight, or restrict (distinct amounts, no complementary pairs, a rejection-and-redraw rule like the program acceptance rule), with the weak-day fraction before and after; the same for `MUL` and `RC` | With the report |
| Timebox | 25 to 40 person-days per reviewer, 3 to 6 weeks of calendar each, both in parallel; one further week for the re-run if a parameter moves (the external firm's calendar, cited from the RandomX pattern in the funding row above) | 8 to 10 weeks from commission to both reports, approximate |
### B4. The soundness suite the reviewer re-runs
| Suite | What it checks | Last result | Source |
|---|---|---|---|
| `cargo test -j4 --release` in `igneum-pow` | the growth schedule table, the by-hand multiplied mixer against `derive_item` at `m` = 1, 2, 4 on a 2^16-word cache, the seam, the generator | 44 of 44 (53 on the release tree) | `docs/plans/mixer-x4.md` 6.3; `counter-asic-2-rollout.md` G3 |
| `tests/packs.rs` | pinned packs v2 and v3: programs, ids, dataset words, 96 vectors per pack, every emitted file byte for byte | 12 of 12 | same |
| `tests/mixer.rs` fuzz | 200 programs through the seam, 4 units each across the 32-bit range, interpreted twice | 200 of 200, 800 of 800 units | same |
| `tests/mixer.rs` stats | 8,192 outputs per seed: bit balance, single-bit avalanche within and across units, duplicates | avalanche 49.99 percent, worst bit z 1.92, 0 duplicates (igneum-genesis v3) | same |
| `tests/mixer.rs` edge and determinism | items 0, 1, 2^28 - 1, 2^32 - 1 at `m` = 1, 2, 4, 8; the index wrap; two independent epochs equal to the pinned pack | pass | same |
| `tests/scratch.rs` | bijections, re-hit rates, 56 edge units, 42 emitted kernels (layer 3, not adopted; kept in the suite) | 7 of 7 | `docs/analysis/scratch-soundness.md` 7.1 |
| Metal and OpenCL on the pinned v3 packs | 200 packs standalone and inside a wrapping 512-nonce batch; every tenth pack on Apple OpenCL | 200 of 200; 20 of 20 | `mixer-x4.md` 6.2, 6.3 |
| Cross-vendor bit-exactness | seven final-class packs' 2^24 fingerprints equal on the RTX 5090 (CUDA), the RX 9070 XT (OpenCL) and the M5 Max (Metal) | GREEN | `counter-asic-2-rollout.md` G1 |
| The acceptance census | 100,000 programs under the live generator on 4,096 nonces each with the 1 GiB dataset; 100,000 under the closed form; the 39 disagreements | 5.14 percent rejected | `weak-program-census-2026-10-03.md` sections 1 and 7 |
| The shortcut ratio | the inline recompute kernel against the honest kernel on the M5 Max | 0.21 (0.10 against 256 MiB) | `proto-metal/MEMHARD.md` 2.2 |
What the suite does not do, and the review must: nothing above bounds the cost of `M_r` from below, draws the partial-store curve, censuses the parameter draws, or looks across hashes for a hot set.
### B5. Acceptance criteria for the engagement
"No shortcut found" counts only with its effort bound, in the style of the RandomX reports (Trail of Bits: "two person-week engagement", 2 July 2019; X41: "30 days, 2019-06-10 to 2019-06-28", three testers; Quarkslab: "about three weeks for a total of 32 days with three engineers"; Kudelski: "6 person-days"; from the four reports in the RandomX `audits/` directory, read 6 October 2026).
| Question | The engagement passes on it when the report states |
|---|---|
| Rank 1, `M_r` | No method found to evaluate 8 keyed applications in fewer than 8 x the single-application cost, after a stated search with named tools (differential and linear trails, rotational-XOR, SAT or MILP on reduced rounds); the round margin: the largest number of applications the best found distinguisher or shortcut reaches, against the 8 between reads and the 72 per item |
| Rank 2, the chain | No method found to derive line `(s, j)` in fewer than `j + 1` block evaluations without an earlier line of segment `s`; the storage-against-recompute curve drawn from `f` = 1/64 to 1 with ops per item at each point, so the chip model gets the row MEMHARD.md item 2 never had |
| Rank 3, the draws | A census of the draw space (the SplitMix64 seed is 64 bits; a sample of at least 2^24 day keys): the fraction of days whose `ROT`, `MUL` or `RC` fall in every class the reviewer names weak, each class with its measured per-day gain; a rejection rule proposed if the fraction with any gain above 1.1x exceeds 2^-20 per day (the threshold is proposed here, not decided) |
| Rank 4, uniformity | The line-index distribution over 2^22 lines on at least 2^28 derivations with the largest bucket within 6 sigma of uniform; the distinct-lines census per hash and per warp on at least 10^6 nonces of three programs; the cross-hash item histogram of one epoch |
| Rank 5, acceptance and grinding | The 39 edge disagreements reproduced and bounded; a search over at least 10^6 seeds for programs that pass (c) with a hot set under 1 percent of items fails; the header-grinding search cost against its DRAM-locality gain measured on one card or bounded analytically |
| Rank 6, seed grinding | A written argument on the proposed day-key rule and the VDF, or a finding |
| The whole | Every verdict carries person-days and tools; the report is publishable whole; the attack code, if any, runs on the pinned packs |
### B6. Candidate reviewers
| Reviewer | What they did | Citation | Why they fit |
|---|---|---|---|
| Trail of Bits | RandomX 2019: two person-weeks, algorithm and code; two low and one informational finding; the single-AES-round diffusion concern that produced `AesGenerator4R`; the 47-parameter brittleness note | https://blog.trailofbits.com/2019/07/02/state/ (2 July 2019, read 6 October 2026); RandomX README "Audits": USD 28,000 | Fast, the algorithm-plus-code shape; the firm's own post says cryptographic validation "would require several person-weeks alone", so scope them for ranks 4 and 5 or buy the longer engagement |
| Quarkslab | RandomX 2019: 32 person-days, three engineers, about three weeks; the fourth review, aimed at the areas the first three left | Report-Quarkslab.pdf, 30 July 2019 (RandomX `audits/`); USD 52,800 | The deepest of the four by person-days; the one to send rank 1 and rank 2 |
| X41 D-Sec | RandomX 2019: 30 person-days, three testers, 3 to 28 June 2019; four medium findings (out-of-bounds accesses in non-standard configurations), eleven side findings | Report-X41.pdf, 10 July 2019; EUR 42,000 | Code-level depth; the right firm for the acceptance rule's implementation (rank 5) and the verifier, less for the cryptanalysis |
| Kudelski Security | RandomX 2019: 6 person-days, final report 2 July 2019; the scope named identifying "weaker authorized parameters" as a goal | Report-Kudelski.pdf; CHF 18,250 | Short and design-level; rank 3 (the weak draws) is their stated kind of question |
| Itai Dinur and Niv Nadler (Ben-Gurion University, approximate affiliation) | Broke MTP's 2 GB instance to under 1 MB at a 170x compute penalty before launch by steering Argon2d's addresses | "Time-memory tradeoff attacks on the MTP proof-of-work scheme", CRYPTO 2017, https://eprint.iacr.org/2017/497 (history [P18]) | Rank 2 and rank 5 are their attack, on a chained memory with data-dependent reads |
| Joel Alwen, Jeremiah Blocki, Krzysztof Pietrzak (IST Austria and Purdue, approximate) | The parallel cumulative-memory model; the practical attacks on Argon2i, Catena and Balloon at real parameters; depth-robust graphs as the characterisation of memory-hardness | https://eprint.iacr.org/2016/115 [P5], https://eprint.iacr.org/2016/759 [P6], "Depth-robust graphs and their cumulative memory complexity", https://eprint.iacr.org/2016/875 (read 6 October 2026) | The model for rank 2: a chip is a parallel amortising adversary and the partial-store curve is a pebbling question |
| Alex Biryukov, Daniel Dinu, Dmitry Khovratovich (University of Luxembourg; Khovratovich now elsewhere, approximate) | Argon2's authors; the ranking trade-off attack on Lyra2, yescrypt and Argon2; Equihash; MTP's design | Argon2, EuroS&P 2016 [P8]; https://eprint.iacr.org/2015/227 [P10]; https://eprint.iacr.org/2015/946 [P16]; https://arxiv.org/abs/1606.03588 [P17] | The designer's side of rank 2; they have been on both ends of a memory-hard break |
| Jean-Philippe Aumasson | SipHash with Bernstein (an ARX PRF); BLAKE; the Kudelski Security crypto practice in 2019, approximate | "SipHash: a fast short-input PRF", https://eprint.iacr.org/2012/351 (2012, read 6 October 2026) | Rank 1 and rank 3: the mixer is an ARX round with drawn rotations and a multiply layer, the design space SipHash and BLAKE live in |
| The ARX-ChaCha cryptanalysis groups (Leurent, Inria; the authors of the ChaCha linear-approximation line) | Tools for differential attacks in ARX constructions; improved linear approximations and attacks against reduced-round ChaCha | https://who.rocq.inria.fr/Gaetan.Leurent/files/ARX_AC12_full.pdf ; https://eprint.iacr.org/2021/224 (read 6 October 2026) | Rank 1's round margin: how many applications of a ChaCha-shaped double round with odd rotations a distinguisher reaches is their published question |
| Least Authority | ProgPoW algorithm audit, 9 September 2019: no issues, five suggestions, the light-evaluation attack named as a future risk | https://leastauthority.com/static/publications/LeastAuthority-ProgPow-Algorithm-Final-Audit-Report.pdf (history [S69]) | A proof-of-work algorithm review that named Igneum's M16 chip before Igneum did; rank 2 and rank 4 |
Recommended pairing: one firm with person-days (Quarkslab or X41 at 25 to 40 person-days) for ranks 1, 2 and 5, and one academic group (Dinur, or Alwen and Blocki) for rank 2's model and rank 3's census, in parallel; Aumasson or the ARX groups for a short rank 1 opinion if the firm's round margin comes back thin. Every name here is a candidate; nobody has been contacted.
### B7. Risk: what finding something late moves, and what not finding it moves
| Case | What moves | Cost |
|---|---|---|
| A break found before the public testnet's vectors freeze | A parameter or a shape: `mixer_mult` 16, restricted rotation draws, a redraw rule, or a new mixer shape. The pinned packs and the 96-vector sets are re-cut through the seam, the verifier re-measured against the 10 ms gate, the soundness suite re-run, the cross-vendor fingerprints re-taken | Hours of Claude-side work (the x8 re-cut was one commit, `mixer-x4.md` section 9); one PC job per vendor; no chain event |
| A break found after the testnet's first miner but before mainnet | A class v4 behind `program_class_v4_activation_daa` with the six gates G1 to G6 and the two-publish rollout of `docs/plans/counter-asic-2-rollout.md`: publish 1 flips the consensus digest with the field at never on every node (hand nodes and the seed first, then the apps machine by machine, a node without the field refused at its next handshake), publish 2 sets the height at least 10,800 DAA seconds ahead, rounded to an epoch; before the height a rollback is a restart, after it there is none except a further switch. The 5 October devnet run of that rollout cost an 11-minute block gap on step 1 (section 7d) | A chain event every miner must take within the lead: on the testnet a reset is announced seven days ahead, so the cost is one announced reset; on mainnet it is the ProgPoW-shaped governance event the plan exists to avoid |
| A break found after mainnet | The same class v4 path, on a chain whose issuance is paying for the floor fleet (B8) | The chip is on the chain before the announcement (history lesson 10) |
| Not found in time | Nothing moves: the vectors stand, the x8 row stands, and the report's absence is stated on the download page until it lands | The spend only |
| The review finds nothing | The x8 row carries an effort bound in place of "no cryptanalysis"; the chip model's "ops per hash" input becomes a reviewed number | The spend only; the history says four such reports were worth about USD 145,000 to Monero in 2019 |
### B8. Timing, and the consequences per user tier
Timing. Before the public testnet genesis is the plan's placement (item 3 of `docs/plans/counter-asic-3.md`, "commission before genesis"). The go checklist `docs/plans/testnet-go.md` has the seeds at height 0 and the genesis hash final; this engagement becomes a new row of its go table between step 9 (the announcement) and step 10 (the first miner): "9a. The mixer cryptanalysis commissioned, scope = funding plan section B, contract signed; the reports in hand before the last announced reset of testnet-1, so the vectors the testnet freezes are the reviewed ones; mainnet never opens without the published reports." If step 10 is pressed first, the announcement text states that the review is in progress and that a reset may follow it.
What a found shortcut means per tier. A found shortcut does not change any card's hash rate. It changes the card's share of the issuance and the chain's safety margin. The case shown is rank 1 at the class v2 cost (the worst row: a chip at 7.4x with the factor), landing after mainnet, with the Monero precedent that chips held 85 percent of the hashrate within four months of a fork (history row 16, approximate).
| Tier | Measured rate today | Share of issuance if chips take 85 percent | What is being done |
|---|---|---|---|
| Home miner, RTX 5090 (32 GB), Windows or Linux | 135.9 to 137.7 MH/s at about 326 W (bench-log "Counter ASIC 2.0, the numbers") | about 0.15x of today's reward per card, approximate | This review before the vectors freeze; x16 or a shape change costs this card nothing per hash (the daily build is latency-bound: 23 to 25 ms at x1, x4 and x8) |
| Home miner, RX 9070 XT (16 GB), AMD | 18.59 to 19.18 MH/s (bench-log; the AMD rows against the 5090 are owed, PC 1 not released) | the same 0.15x, on a card already 7.1x behind the 5090 | the same; the daily build 72 to 77 ms at every `m` |
| Home miner, 8 or 12 GB card | about a tenth of the 5090's rate, approximate (not owned) | the same 0.15x | the same; at x16 the 8 GB-class daily build is about 2 s, approximate, above the 1 s rule of `mixer-x4.md` 6.5, which is why the recommendation on `mixer_mult` is a deliverable and not a default |
| Mac, M5 Max, Metal | 27.85 to 27.98 MH/s (bench-log) | the same 0.15x | the same; the Mac's build is latency-bound (21 ms at every `m`) |
| A rig or a pool user | the sum of its cards | the same share per card; a pool's fee base shrinks with it | the same |
| A verifier (any node, any pool core) | 2.08 ms per unit at x8 on one M5 Max core, worst cold 2.15 | unchanged | at x16 about 3.7 ms per unit on this core and about 9 ms on a 2.5x slower laptop core, approximate: the 2019-class core measurement (O-1.14) decides x16, not this review |
| The chain's security budget | USD 3.85M, 15.4M and 77.0M to miners in year 1 at the low, base and high price inputs (`docs/analysis/security-budget.md` section 3) | unchanged in dollars; paid to chips. The floor of USD 1M a year buys about 3,000 cards' electricity, sized so that one 1,000-card operator stays under one third of the vote weight (section 6); at 7.4x per board, one third of that fleet's hashrate is about 135 chip boards, approximate, so one chip maker holds the partition threshold of spec 3.7 | the review, the class v4 path, the chip bounty (USD 50,000 standing, unfunded) and the share-pattern detector of Counter ASIC 3.0 item 4 |
What the spend means against this file's totals. USD 80,000 to 160,000 added to the review-and-audit bucket (USD 210,000 to 410,000) takes it to USD 290,000 to 570,000, and the plan's total (USD 440,000 to 740,000 through the first mainnet quarter) to USD 520,000 to 900,000. If it is founder-funded, the funded share rises from USD 220,000 to 430,000 to about USD 300,000 to 590,000. All approximate; section 3 is not re-totalled here, the coordinator re-totals when the row is confirmed. Against the issuance: year-1 emission to miners is USD 3.85M, 15.4M and 77.0M at the low, base and high price inputs, so USD 10,500, 42,000 and 211,000 a day; the history's clock for a chip is about USD 50,000 of daily issuance (section 2.5), so the base input sits just under that clock and the high input is past it from day one. The whole engagement is one to two weeks of year-1 miner emission at the low input.