You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: AGENTS.md
+19-17Lines changed: 19 additions & 17 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,8 +4,12 @@
4
4
5
5
A minimal (zero-knowledge Virtual Machine, which is actually not ZK in the real sense, i.e. it's only a snark, not a zk-snark).
6
6
7
-
-`misc/doc.tex` describes the machine, the arithmetization and the protocol
8
-
-`crates/lean_compiler/zkDSL.md` documents the zkDSL.
7
+
-`misc/doc.tex` describes the machine ISA, the snark that proves it.
8
+
-`crates/lean_compiler/zkDSL.md` documents the (pythonic) zkDSL (that compiles to the ISA that our VM runs, and that our snark proves).
9
+
10
+
Primary goal:
11
+
- Aggregate XMSS (stateful hash based signatures), via a snark proving knowledge soundness of the signatures, against a common message and a lust of public keys
12
+
- Further aggregate n previously aggregated signatures, which is performed by a recursive snark, that proves "I know n sub-proofs that are valid and the union of the public keys they handle contains the list of public keys I am given in public input".
`src/main.rs` is the CLI; guests are zkDSL under `crates/rec_aggregation/guests/`.
28
32
29
-
## Build and test
33
+
## Building / Testing / Formatting
30
34
31
-
`.cargo/config.toml` pins `-C target-cpu=native`. Always run in `--release` mode any test/benchmark touching the VM (the zkDSL compiler stack-overflows in `debug` mode).
35
+
-`.cargo/config.toml` pins `-C target-cpu=native`
36
+
- always run in `--release` mode any test or benchmark touching the VM (the zkDSL compiler stack-overflows in `debug` mode)
32
37
33
38
```bash
34
39
cargo testall # = test --all --release; 314 tests, seconds
@@ -40,20 +45,17 @@ Heavy benches are `#[ignore]`d; run by name with `-- --ignored --nocapture` (`bl
40
45
41
46
## Benchmarking
42
47
43
-
See README.md -> the benchmarks we care about are:
One proof is one **phase**, opened by `cpu::prove`. `ArenaVec` bumps a per-thread slab, freeing is a no-op, and the next `begin_phase()` reclaims everything. Worth 14% of prove time on M4 Max, 30% on Zen 4. Not a `#[global_allocator]`: `raw_dealloc` picks arena-vs-system by address range, so with no phase open `ArenaVec` is an ordinary system vector, which is what makes it safe in the verifierand in tests.
54
+
One proof is one **phase**, opened by `cpu::prove`. `ArenaVec` bumps a per-thread slab, freeing is a no-op, and the next `begin_phase()` reclaims everything. Not a `#[global_allocator]`: `raw_dealloc` picks arena-vs-system by address range, so with no phase open `ArenaVec` is an ordinary system vector (used in particular by the verifier, where correctness and simplicity matters much more than performance).
53
55
54
-
**The rule, and the only silent-corruption footgun in the repo:** an `ArenaVec` allocated in a phase dies at the next `begin_phase()`. A reset neither clears nor unmaps, so a buffer that outlives its phase reads the previous proof's plausible bytes, so the symptom is a proof that stops verifying, never a crash. Anything outliving a phase (a `Proof`, a cache, a table) must be a plain `Vec`. `rec_aggregation/tests/arena_prove.rs` guards this; it needs its own test binary because phases are process-global and refuse to nest.
56
+
**The rule:** an `ArenaVec` allocated in a phase dies at the next `begin_phase()`. A reset neither clears nor unmaps, so a buffer that outlives its phase reads the previous proof's plausible bytes, so the symptom is a proof that stops verifying, never a crash. Anything outliving a phase (a `Proof`, a cache, a table) must be a plain `Vec`.
55
57
56
-
`ZK_ALLOC_STATS=1` reports bytes/phase, per-slab high water, and overflow to the system allocator (nonzero ⇒ `SLAB_SIZE` undersized). `LEANVM_NO_ARENA=1` halves resident memory but is unoptmized (not our concern for now, we assume we have enough RAM).
58
+
`LEANVM_NO_ARENA=1` halves resident memory but is unoptmized (not our concern for now, we assume we have enough RAM).
57
59
58
60
## The thread pool (`parallel`)
59
61
@@ -67,11 +69,11 @@ No rayon. Every parallel site is "N independent items, each writing its own disj
67
69
68
70
## Three verifiers, one protocol
69
71
70
-
The same verification algorithm is written out three times, in three languages, against one transcript. Any change to the transcript order, the layout derivation, or a challenge derivation has to land in all three or the other two start rejecting valid proofs.
72
+
The same verification algorithm is written out three times, in three languages. Any change to snark protocol has to land in all three.
71
73
72
-
1.**Rust**, `lean_vm::cpu::verify`. The reference and the one every test calls.
73
-
2.**Python**, `python-verifier/verifier.py` (~2.5k lines, no dependencies). An independent re-derivation from the spec rather than a port, which is what makes it a real cross-check: it consumes only the public statement as JSON plus the bincode proof, never prover-side data. Pinned by `lean_compiler/tests/python_verifier.rs`, which proves a program, verifies it with `python3`, then corrupts the announcement and the commitment root and requires Python to reject both.
74
-
3.**In-circuit**, `crates/rec_aggregation/guests/recursion.py` (~2.4k lines of zkDSL). This one is the recursion: it replays `cpu::verify` for `NSUB` inner proofs *inside the VM*, so proving it yields one proof attesting that the inner proofs verified.
74
+
1.**Rust**, `lean_vm::cpu::verify`. The performant verifier implem.
75
+
2.**Python**, `python-verifier/verifier.py` (~2.5k lines, no dependencies). pure python, for readability and simplicity. Pinned by `lean_compiler/tests/python_verifier.rs`.
76
+
3.**Recursive verifier**, `crates/rec_aggregation/guests/recursion.py` (~2.4k lines of zkDSL). Written using our pythonic zkDSL (but it's not real python!), which then compiles to our custom ISA. Proving it result in recursion -> a snark of another snark.
75
77
76
78
The third is worth understanding before touching the verifier. `guests/recursion.py` is not Python that runs; it is the zkDSL, which `lean_compiler` lowers to the VM's seven-opcode ISA (`XOR`, `MUL`, `SET`, `DEREF`, `JUMP`, `BLAKE3`, `PACK64X2`) over write-once memory. So every verifier step, sponge absorption, sumcheck fold, Merkle path, field inverse, becomes VM instructions that the prover then proves the execution of, which is why the guest is ~500k instructions and why its opcode mix is what the recursion benchmark reports. Two consequences:
0 commit comments