diff --git a/docs/plans/cryptanalysis/in-house-pass.md b/docs/plans/cryptanalysis/in-house-pass.md new file mode 100644 index 000000000..8e4bd9e30 --- /dev/null +++ b/docs/plans/cryptanalysis/in-house-pass.md @@ -0,0 +1,220 @@ +# The in-house adversarial pass on the lottery hash + +> Internal adversarial pass, not an independent review. 7 October 2026, 19:1x BST (nine lanes from 19:2x BST on the founder's word through main: "push the cryptanalysis tonight, we have the capacity"), the crypto-engage lane on the founder's correction through main: nothing goes outside. No firms, no paid lots, no briefs to anyone. The three targets of Counter ASIC 3.0 item 3 (the mixer `M_r`, the chained cache, the acceptance rule) are attacked by three lanes that have never worked on the hash code, under the outsider rule below. The only outside check that remains is the disclosure prize, staged (section 10). + +## 0. One page + +| Item | State | +|---|---| +| What was planned until 18:5x BST | Three external lots (`docs/plans/cryptanalysis.md` on branch `cryptanalysis`, `docs/plans/funding.md` row "Independent cryptanalysis") with firm shortlists and price rows | +| The founder's correction (through main, 7 October, evening) | Nothing goes outside. No firms, no paid lots, no briefs to anyone. The lane becomes the in-house adversarial pass on the same three targets | +| The pass | Nine adversarial lanes, three per target on three question classes each, each given only what an outsider would have, each writing an attack plan first and then a report in the attack-pass shape | +| The defender | The Counter ASIC lane; main rules disputes | +| The clock | Plans within two hours of start (the first three) or one hour (the six of 19:2x BST); first results from every lane by 00:00 BST tonight | +| The label | "internal adversarial pass, not an independent review" on every public sentence | +| The outside check | The disclosure prize, USD 50,000, approved 7 October 09:5x UK, STAGED until escrow, the entity address and the founder's publish word; nothing public names it until then | + +## 1. The target, exactly + +| Piece | Value | +|---|---| +| The frozen object | `igneum-pow` at commit `017e70376489251e18564c0abce7e466e606c8b3` on branch `ca3-v4-amend` (tag `audit-freeze-2026-10-07`); byte-identical on `master` since `cf7d6ccb` | +| The class | Class v4 sub-version 3: `PROGRAM_SUBVERSION_V4 = 3`, object byte 7 | +| The rules in the object | (a') dataflow freshness to a fixpoint; the shared-operand rule in the draw; (c'') the per-site distinct-index ratio at 0.98 over 2^20 evaluations; the 256-attempt cap and the deterministic last-resort draw | +| Program ids | The shared devnet's epoch-0 id `a785001687d8688a` (the kaspa-pow pairing pin); Devnet 3's epoch-0 id `fce15bf61030be57` (attempt 0, sub-version 3) | +| The kit | `packs-ca3-v4-sub3` zip, sha256 `4f2445c50c58d76a5544023492d8b858d0b07c5e372d31f9c90c4ce51f829154`, eight packs: the contents of `proto-cuda/packs-ca3-v4/` at the frozen commit (`mx8-devnet-epoch0` the class v3 control, `v4-devnet-epoch0`, `v4-era-0` to `v4-era-5`) | +| The Devnet 3 pack | `v4-devnet3-epoch0` (zip sha256 `e025750f71175ed14d6e2a24e387ebbf1979b1cd0faee9139c41a7671165b334`, 12 files, program.json `0xfce15bf61030be57` at attempt 0), on build-1 at `/srv/artefacts/packs/v4-devnet3-epoch0/` and `.zip`; Metal and Apple OpenCL fingerprint `e510ad92b4d24846` at 2^24 from base 0; exported under igneum-pow `874e945d` (byte-identical to `017e7037`) over Devnet 3's genesis with day bytes le64(20733); public-kit class, verified by this lane on build-1 at 19:1x BST | +| The dataset under attack | Spec `docs/spec/01-lottery-hash.md` 1.8: ChaCha12 cache fill in 2^16 segments of 64 chained lines; the ARX-multiply mixer with per-day `ROT`, `MUL`, `RC` from a 64-bit SplitMix64 seed; `m = 8`, 72 applications per item, 8 dependent cache reads | +| The acceptance rule under attack | Spec 1.4.6 as the code `igneum-pow/src/accept.rs` implements it at the frozen commit (the code is the truth where the spec lags it) | + +## 2. The nine lanes + +Three per target, one question class each, from funding.md's ranked list for that target. The first three were spawned at 19:1x BST and re-scoped at 19:2x BST; the six others were spawned at 19:2x BST. + +| Lane | Target | Question class | Branch | Worktree | Plan | Report | Plan due (BST) | +|---|---|---|---|---|---|---|---| +| adv-mixer | mixer `M_r` | the algebraic structure: the fold of the multiply layer, the composition of 8 applications | `adv-mixer` | `igneum-wt-adv-mixer` | `plan-mixer.md` | `report-mixer.md` | 21:10 | +| adv-mixer-2 | mixer `M_r` | the day-key weakness class: weak `ROT`, `MUL`, `RC` draws, the 2^24 census, the calendar | `adv-mixer-2` | `igneum-wt-adv-mixer-2` | `plan-mixer-2.md` | `report-mixer-2.md` | 20:25 | +| adv-mixer-3 | mixer `M_r` | the statistical distinguisher and the round margin: differential, linear, rotational-XOR, SAT or MILP on reduced applications | `adv-mixer-3` | `igneum-wt-adv-mixer-3` | `plan-mixer-3.md` | `report-mixer-3.md` | 20:25 | +| adv-cache | chained cache | the recompute shortcut: the honest curve from `f = 1/64` to 1, a cheaper fill, the chip's recompute cost | `adv-cache` | `igneum-wt-adv-cache` | `plan-chained-cache.md` | `report-chained-cache.md` | 21:10 | +| adv-cache-2 | chained cache | the partial-state or hot-set attack: line-index uniformity over 2^28, hot lines and items, steering | `adv-cache-2` | `igneum-wt-adv-cache-2` | `plan-chained-cache-2.md` | `report-chained-cache-2.md` | 20:25 | +| adv-cache-3 | chained cache | the chain-break or skip: a line under `j + 1` blocks, relations through the chaining and the feed-forward, pebbling | `adv-cache-3` | `igneum-wt-adv-cache-3` | `plan-chained-cache-3.md` | `report-chained-cache-3.md` | NOT YET SPAWNED at 19:26 BST (the session's 20-subagent cap); spawned when a slot frees, plan due one hour after | +| adv-accept | acceptance rule | the bypass: passes (a) to (c'') on the stand-in with locality on the live dataset; the stand-in gap; distinguishers that pass | `adv-accept` | `igneum-wt-adv-accept` | `plan-acceptance-rule.md` | `report-acceptance-rule.md` | 21:10 | +| adv-accept-2 | acceptance rule | header grinding for locality: header bytes and nonce against DRAM rows, lines and items; cost against gain | `adv-accept-2` | `igneum-wt-adv-accept-2` | `plan-acceptance-rule-2.md` | `report-acceptance-rule-2.md` | 20:25 | +| adv-accept-3 | acceptance rule | exhaustion or steering of the draw: the 256-attempt cap, the last-resort draw, seed steering, the program id | `adv-accept-3` | `igneum-wt-adv-accept-3` | `plan-acceptance-rule-3.md` | `report-acceptance-rule-3.md` | NOT YET SPAWNED at 19:26 BST (the session's 20-subagent cap); spawned when a slot frees, plan due one hour after | + +Plans live in `docs/plans/cryptanalysis/`, reports in `docs/analysis/cryptanalysis/`. Each lane's branch was cut from the build mirror's `master` and is pushed to the build mirror only; GitHub is dark tonight. BASE CORRECTION (main, 19:4x BST, from the hash lane): build-2's mirror master was stale (`a4bca198`, pre-fix) until 18:25:42Z, and the first branches were cut from `3f0afcd5`, whose `igneum-pow` differs from the frozen object by 6 files (verified by this lane: 30 insertions, 635 deletions). Every lane merges build-1's `master` (`7a7caa34` or later; `001e32ec` is the earliest good tip) before any run or report and proves `git diff --quiet 017e7037 HEAD -- igneum-pow` identical, stating the commit in its plan; anything built or measured on a stale tree is void. `crypto-engage` itself merged `7a7caa34` at 19:27 BST (355ac2ae, identical). + +## 3. The rule set + +### 3.1 What a lane receives (the outsider's inputs, and nothing else) + +| Input | Where the lane reads it | +|---|---| +| The crate `igneum-pow/` (src, tests, Cargo files) at the frozen commit | `master`'s copy, verified byte-identical with `git diff --stat 017e7037 HEAD -- igneum-pow` printing nothing; the result stated in the plan | +| The spec `docs/spec/01-lottery-hash.md` at the frozen commit | `git show 017e7037:docs/spec/01-lottery-hash.md` | +| The chip model `docs/analysis/chip-model-v3.md` sections 1, 2, 5 and 6 | the worktree's HEAD | +| The public kit: the eight packs | `proto-cuda/packs-ca3-v4/` at the frozen commit; the zip sha256 above | +| The two program ids and the Devnet 3 pack | stated in the lane's prompt; the pack read from build-1 (`/srv/artefacts/packs/v4-devnet3-epoch0/`, sha256 above), handed to the lanes at 19:1x BST after their start | +| The attack harnesses `tools/attack/f8-uniform` and the F4 census `tools/attack/f4-weakday` | f4-weakday from `build/attack-pass`; f8-uniform from the Mac worktree `igneum-wt-attack-regate` (that branch is not on the mirror); copied, never edited in place | +| The operating files needed to run anything | `tools/build-remote.sh`, `infra/build-server/lib.sh`, `infra/build-server/remote-run.sh` | +| Sibling lanes' plans and reports | `git fetch build adv--`, the files under `docs/plans/cryptanalysis/` and `docs/analysis/cryptanalysis/` only; siblings are outsiders too | + +### 3.2 What a lane does not receive + +| Withheld | Why | +|---|---| +| `docs/plans/counter-asic-3-status.md` (section 7c and all) | the defender's reasoning on AP-F8-1, the localisation, the cost lines | +| `docs/fud-ledger.md`, `docs/fud-fixes.md` | the ledger entries on AP-F8 and every earlier finding | +| `docs/analysis/attack-pass/*` and `docs/analysis/attack-pass-2026-10.md` | the hash lane's and the attack-pass lane's notes and results | +| `docs/analysis/ca3-v4-uniform.md`, `docs/plans/mixer-x4.md`, `docs/analysis/weak-program-census-2026-10-03.md`, `proto-metal/MEMHARD.md` | defender's analyses | +| `docs/plans/funding.md`, `docs/plans/cryptanalysis.md`, this file | the ranked questions as the defender ranked them, the known gaps as the defender knows them | +| `git log`, commit messages, other branches and worktrees, `site/` | commit messages carry the defender's reasoning; the site carries the defender's numbers | + +Known leaks, stated: `CLAUDE.md` loads on its own in every lane (operating rules; the lane follows no pointer from it into other docs); the harness sources carry doc comments written by the attack-pass lane. Each plan lists every file the lane opened, so the defender can read what the lane knew. + +### 3.3 How a lane states a result + +A result is a BREAK (a method with a measured or counted gain, reproducible from the command and the seed) or a BOUND (what was searched, with what tools, how far it reached, the margin left). "Nothing found" counts only with its effort stated in box-hours and tools. Every number carries its command, its seed and its log path on the box. + +## 4. The budget and the no-gaps rule + +Standing rule from the founder through main (7 October 2026, 19:1x BST), binding: no gaps between tasks. + +| Rule | What it means for a lane | +|---|---| +| Every idle core on both boxes | A lane runs on build-1 and build-2 together, on every idle core, at nice 10, no core band; release builds and the class v5 suites keep priority. the founder's read at 19:4x BST: build-1 at 11 percent, build-2 at 56; his word is both near max, so CPU-bound sweeps go to build-1 explicitly (`--box 1`) and both boxes stay above 80 percent until the queue is empty; the build-server lane raises the lease pool to about 88 cores per box | +| Yield to builds | RETIRED at 19:3x BST (adv-accept's exception: a build slot is held nearly continuously on both boxes, so the SIGSTOP yield of the capacity layer kept every sweep in state T and "both boxes above 80 percent" was unreachable). In its place the build-server lane's rule (19:4x BST): every bounded run at nice 10 on cores 8 to 95 only (`taskset -c 8-95`; cores 0 to 7 reserved for release builds, the seed and the observer), `-j 88` through `tools/build-remote.sh`, the router spilling to the other box at no free slot or a 1-minute load above 80, a pinned measurement leasing its exact cores with `/srv/builds/_bin/lease cores --label "..." --owner adv- -- ` (no measure flock), every adversarial worktree merged to the mirror's master at `04c4d9bc` or later; each lane notes the change and its time in its report | +| Back to back | Question `n + 1`'s sweep starts the minute question `n`'s ends; no waiting for a human to read; each result row lands in the report and is pushed as it lands | +| Lease pool only | ADDED 20:1x BST by main (build-1 at load 601, build-2 at 401): no sweep, census or verdict run starts on a box except through the build-server lane's `lease pool -- cmd` (from the same 88-core pool as the builds, waiting when none are free); every hand-started binary at 64 to 89 threads killed by its pid file NOW and re-queued through the lease; release builds and the class v5 suites outrank every sweep tonight; each lane reports its kill and re-queue in one line to the build-server lane. Relayed verbatim to all eight live lanes at 20:1x BST; the pod is not a box and adv-accept-2's measurement continues. LIVE since 20:22 BST (`/srv/builds/_bin/lease`, sha f814b447, self-test green, verified by this lane on build-2): `lease pool --label "" --owner -- --threads {cores}` takes up to free cores from the bounded pool (cores 8 to 95, shared with the builds), never fewer than --min (default min(threads, 16)), waits in 10 s steps up to 2 h, runs at nice 10 pinned to the cores taken, "{cores}" the count and "{cpuset}" the set; the pooled sum on a box never passes 88; lanes ask 32 to 48 so two or three sweeps share a box; the sweep.lock is dropped. Load after the kills: build-1 224, build-2 121 at 20:22 BST. Relayed to all eight live lanes at 20:2x BST. POOL RANKING (main, 20:2x BST): the release builds and the class v5 suites outrank every sweep; an adversarial lease asks for at most 48 cores with --min at the least usable, and yields (finishes the shard in hand, releases) whenever `lease status` shows a waiter labelled "v5 gate" or "v5 kit"; widened at 20:30 BST (the v5 census queued as "class v5 c3 census" with no gate label and nobody yielded) and then fixed to the OWNER at 20:3x BST (the word "v5" also matched adv-accept's own exemplar sweep): yield to a waiter whose owner is class-v5, or whose owner is attack-pass with "v5" in the label, never to an adv-* waiter; BOX 2 CLOSED to adv-* at 20:4x BST by main's order (the (c''') census, owner class-v5, 88 cores, about 9 minutes, the 0.3.24 critical path, blocked by adv-accept at 32 + 31 + 23 cores and adv-mixer at 1, with eleven adv-* waiters): every adv-* holder on box 2 releases at its shard end (partials kept), every adv-* waiter withdraws, no adv-* lease on box 2 until the v5 lane reports the census running, then resume in order; build-1 the same if the v5 lane asks; from now the yield is MECHANICAL: an adv-* lane that sees a class-v5 waiter releases at its shard end unasked; relayed to all nine lanes in one line each; the census RUNNING at 20:41:55 BST on 48 of 88 cores; every adv-* lane confirmed 0 holders and 0 waiters on box 2 except adv-cache-2's 40-core lease taken 19 s before it (ordered released); box 2 stays closed to adv-* until the census ENDS. At 20:49 BST the coordinator ended adv-cache-2's 40-core lease by its exact pids (seven minutes past the order, the lane silent since 20:23), then its box 2 drain (drain.pid; it had started the next 40-core item the moment the first died) and that lease; box 2 read 0 adv-* holders at 20:49 BST with the census alone on the pool; logged in /srv/builds/_adv/coordinator.log. The census ENDED by 21:12 BST (no pool lease on box 2, load 11); box 2 REOPENED to adv-* at 21:12 BST: every lane re-submits at `lease pool 32 --min 16`, class adv, with the mechanical yield; adv-mixer-2 and adv-accept-2 move their build-1-starved runs there (build-1's pool held by attack-pass's class-v5 chunks). 22:17 BST, main: the attack-pass F8 gate on the frozen class v5 tip (two class v5 halves of 32, min 24, the 0.3.24 critical path) waits on build-2 behind adv-accept's three shards at 30, 32 and 26 cores, which the pool does not pre-empt (pre-emption applies above 32 threads only); adv-accept ordered to release all three at shard end now and re-queue after F8 starts; RULE from here, mechanical for every lane: on a box where `lease status` shows a class v5 waiter, an adv-* lease releases at its shard end whatever its size. The F8 halves RUNNING on build-2 from 22:17:41 BST (32 and 30 of 32 cores) after adv-accept yielded its three shards by pgid file at 22:17:57 (rows kept). POOL RULE 22:21 BST (lease sha ce30e357): a release or v5 waiter that has waited 120 s pre-empts adv-class holders at ANY size (the 32-thread floor gone), oldest first, as many as cover its ask, one pass per 120 s, SIGTERM at the shard boundary and the lane re-queues the same line; measure-class holders above 32 threads after 300 s, below 32 never; `lease status` shows the last ten minutes' pre-emptions; relayed to the five active lanes. POOL CLASSES (the build-server lane, 20:40 BST, lease sha 5d84d644): release > v5 > measure > adv; a higher class is served first whatever the arrival order; an adv holder above 32 threads is pre-empted by SIGTERM after a higher class has waited 120 s (newest first, one per 120 s, /srv/builds/_log/preempt.log) and the lane re-queues the same line; holders at 32 threads or fewer are never pre-empted; old waiters re-submitted once; no sweep label carries "release", "canary", "pair", "v5 gate", "v5 kit" or "measure"; adv-cache-3, holding 87 of build-2's 88 pool cores since 20:22 BST, ordered to release at the end of its current shard so the v5 (c''') census takes build-2 | +| One sweep per box | SUPERSEDED by the lease rule above at 20:1x BST. Was: added 19:5x BST (build-1 at load 496, build-2 at 527 on 96 cores: oversubscription, not the near max asked for; the bounded class is 88 cores per box in total, not per sweep): every new sweep from every lane runs under `flock /srv/builds/_adv/locks/sweep.lock -c "nice -n 10 taskset -c 8-95 > 2>&1"` on its box, so one sweep runs per box at a time with up to 88 threads and the rest wait in order; running processes finish; duplicates are killed by pid file and re-queued | +| No lane idle | Every planned sweep is a self-contained executable in `/srv/builds/_adv//queue/NN--.sh` on build-2 (binary path, args, log path, pid file); a lane claims a file before running it with `mkdir /srv/builds/_adv//claims/` (atomic) and then writes its name into `/owner` (added 19:5x BST after three claims landed with no name); a lane whose own queue is empty claims the next unclaimed file of any sibling on its target, runs it, and names the owner in its report The held lanes' sweeps are in the queue as DEFINITION ONLY files (`90-` to `92-adv-cache-3-*`, `90-` to `92-adv-accept-3-*`, 19:3x BST): an idle lane claims one, implements it in its own crate, runs it and reports it, naming the owner | +| Pods | Second resort after the boxes' idle cores. The fleet's rules (the fleet lane, 18:26Z): no CPU-only pod type exists; every pod is a RunPod GPU pod (secure, or a 3090 or 4090 community; Vast unreliable tonight), image nvidia/cuda 12.8.1 on Ubuntu 24.04, 40 GB disk, vCPUs with the card (4 to 16), rented by `oneshot.py rent