Hekate v0.37.0
On this page
This release puts every table of a proof under one commitment and closes a zero-knowledge gap of
0.35.0 and 0.36.0. One trace tree, one tree for the LogUp helper columns, one fold vector, one set
of 287 query columns and one evaluation sumcheck now cover every table, and zero-knowledge proofs
of ML-KEM-768, ML-DSA and AES shrink by 36 to 56%, RSA-2048 by 88%. The LDT support grows to 288
cells over 287 queries: at equal counts, a zero-knowledge proof whose query columns were pairwise
distinct let anyone check a guess of its witness against the unsalted leaves of its helper tree.
The verifier now evaluates codewords only at the columns a proof opens and gains prepared and
batch verification. On an Apple M3 Max with zero knowledge, 0.37.0 verifies an ML-KEM-768
receiver proof in 13.9 ms against 88.6 ms under 0.36.0. The proof wire moves to v7 with a new transcript order, and a 0.36.0
proof does not verify. program_id does not move. Pair with the signed prover cdylib 0.15.0.
Upgrade is mandatory for any deployment that relies on zero knowledge.
Full analysis of the gap, its exposure and the fix: postmortem. The construction, its soundness and the measurements: One Tensor Commitment for Tables of Every Height.
§ One commitment for every table (#43)
- One tree per oracle. Every table of a proof shares one trace tree. Leaf
jhashes one codeword column of every table,H(0x02 ‖ d_0 ‖ … ‖ d_(T-1))withd_i = H(0x00 ‖ part_i), wherepart_iis tablei's symbols at columnjover its grid rows; inner nodes stayH(0x01 ‖ l ‖ r). The LogUp helper columnshof every bus-carrying table share a second tree of the same shape, present only when some table carries a bus. The verifier checks each opened column's length against the tables' parts before it hashes them. - One grid for every height. Both sides derive one split
cfrom the absorbed table heights, the program and the configuration, and every table encodes at the same width. A table of2^nrows withn < cpacks2^(c-n)columns of one class into each codeword row, zero blocks closing the last; a taller table keeps2^(n-c)grid rows. The split minimizes an integer byte count of the fold vector, the opened symbols and the claims on packed blind columns, over the splits that hold the LDT support and clear 100 proven bits. Nothing in the proof setsc. - One evaluation argument. Each table keeps its own ZeroCheck and LogUp argument. Their column
claims then enter one sumcheck over
max(c, tallest table)variables: a short table's block bits are sumcheck variables, and a table with fewer variables enters the remaining rounds througheq(z, 0). The final check combines every table's master evaluations, and the line⟨q[..2^c], eq(r[..c])⟩ = Σ_k λ^k M_k, one power ofλper master, ties them to the fold vector that the 287 query columns check. - Transcript order. Program id, sizes, configuration, public inputs and boundary pins; every
chiplet header, which no longer carries a root;
trace_root, and with zero knowledge the pad root; the bus challenges and thehroot, before any table's first challenge. Then each table's bus sums, ZeroCheck,hevaluations and column claims, and last the pool's challenges, sumcheck, masters, fold vector, query columns and openings. - Four rules.
ηfollows every table's claims, every master carries its own power ofλ, a shorter table is extended byeq(z, 0)and never by a constant, and a packed table's block bits are sumcheck variables. Breaking any of them admits a forgery or fails an honest proof; the note gives each case, and the release's verifier rejects forging provers for the first two in both modes. - Soundness. To the verifier the pool is one table: its proximity error is the single-table
error with
Σ + m - 1batched units, forΣslot roles andmmasters, and the query term is unchanged. Both sides compute the shape from absorbed data and reject one below 100 bits. On the shipped examples the proximity term reads 102 to 108 bits and the query term 109 to 118. - Verifier bounds. A table above 2^32 rows is rejected, each table's claim count must match the layout before the layout is built, and the trace commitment is a bare root, with main's height taken from the instance and its width from the program.
§ Support one cell above the query count (#43)
- The fix. 288 support cells over 287 queries. With
S ≥ t + 1and at least two messages weighted in the fold vector, every unopened symbol is uniform given the view and every data cell. Both sides rejectldt_support_size <= num_querieswhenevermin_security_bits > 0. The cost is one field element per proof, 16 bytes on the wire. - The gap. A codeword symbol at a point
αisΣ_(k<S) ξ_k X_k(α) + Σ_(k<L) d_k X_(S+k)(α), with supportξand datad. WithS = tsupport cells andtdistinct opened columns, the support is an affine function of the data and the opened symbols, and every unopened symbol follows. The helper tree carries no blind and its leaves no salt: a guess of the bus keys rebuilds every leaf and the root, and the multiproof ships sibling digests to test against. 0.35.0 and 0.36.0 ranS = t = 287on every grid of 2^11 columns and more. - Exposure. A proof was exposed only when its draws for a table were pairwise distinct, which happens on 0.003% of proofs at 2^12 codeword columns and on 85.5% at 2^18. On 0.36.0 the ML-DSA-87, AES-128, AES-256 and SHA-256 2^21 examples each produced such a proof, and one main table on a single grid row exposed its trace tree on about one proof in 28,600. No shipped example is recoverable, because the smallest private input behind an exposed table is a 256-bit seed. A statement about a short secret, such as a PIN or a choice among a few options, was.
- Soundness unaffected. The gap concerns what a valid proof reveals, and no forgery follows from it.
§ Verifier throughput (#42)
- Outer weights in one pass. With zero knowledge, the verifier weighs each table's predicate rows for the outer argument's linear test in one reverse pass over the constraint AST, without building the rows. A constraint AST must list every child ahead of its parent, and table shapes and the bundle decoder reject one that does not.
- Codewords at the opened columns. The row-code encodings behind the outer tests and the table
openings are evaluated only at the columns a proof opens, through hekate-math 0.12's
CantorBasis::evaluate_at, and the vanishing polynomials in closed form. The verifier no longer transforms the whole domain. - Byte tables for F₂-linear maps. The ring-switching target, from 300 claims up, and the ring gadget's tie weights run through tables indexed by byte, fed with public values only.
- Shared fixed-column sums. A table's fixed columns evaluate at one point on shared prefix and residue sums.
- Prepared and batch verification.
PreparedProgram::new(program, config)computes once what verifying one program needs before any proof: chiplet definitions, constraint ASTs, buses, pins, ring-switch plans, table shapes and the program id.verify_preparedreplays a proof against it and rejects a pinned id that differs from the one computed at preparation, andVerifierScratchcaches state between proofs, one per thread.verify_batchspreads proofs over the thread pool and returns the results in input order.verifykeeps its signature and recomputes the id on every call. - Batched hashing. Hashing and transcript absorption are batched without changing any digest or transcript byte.
§ Documentation
- Every crate README states what the crate does and carries a usage block that compiles against this release, and READMEs and docs.rs pages link the crate's guides on oumuamua.dev.
- The workspace README lists the guides in reading order and every example. Its quick example and performance tables move to the documentation and the benchmarks.
§ Performance
Zero-knowledge proof size changes by -36 to -56% on ML-KEM-768, ML-DSA and AES and by -88% on RSA-2048, and in base mode by -37 to -67% and -90%. On the seven single-table workloads proof size moves -0.8 to +0.1%, except SHA-256 at 2^11 rows, 540 to 516 KiB, while verification falls 37 to 66% with the verifier work of #42 and proving falls 13 to 25%. Peak memory falls 12 to 37% on the multi-table workloads and moves -13 to +0.5% on the single-table ones. Each PR describes its change in detail.
Each release with the signed prover its tag pins, public variant for aarch64-apple-darwin: 0.36.0
with prover 0.14.0 (6f09b831…), 0.37.0 with prover 0.15.0 (4e72a3c1…). Apple M3 Max,
--release with fat LTO and one codegen unit, features std parallel blake3 table-math public,
Config::prod(), best of three, zero-knowledge mode.
| Workload | Proof, KiB | Verify, ms | Proving | Peak, MiB |
|---|---|---|---|---|
| Keccak 2^15 | 858 → 851 | 11.9 → 4.6 | 195 → 163 ms | 164 → 143 |
| Keccak 2^20 | 3,542 → 3,544 | 17.1 → 7.1 | 3.73 → 3.23 s | 2,418 → 2,430 |
| SHA-256 2^11 | 540 → 516 | 9.4 → 3.2 | 69 → 53 ms | 65 → 62 |
| SHA-256 2^21 | 5,485 → 5,485 | 22.7 → 11.3 | 10.65 → 8.72 s | 5,228 → 5,099 |
| ML-DSA-44 | 2,867 → 1,547 | 50.7 → 10.5 | 549 → 432 ms | 296 → 219 |
| ML-DSA-65 | 2,959 → 1,568 | 52.0 → 10.3 | 594 → 472 ms | 276 → 207 |
| ML-DSA-87 | 3,336 → 1,812 | 55.7 → 11.2 | 766 → 618 ms | 422 → 308 |
| RSA-2048 | 14,724 → 1,810 | 29.4 → 8.2 | 334 → 204 ms | 517 → 397 |
| ML-KEM-768 sender | 3,508 → 1,544 | 72.1 → 11.6 | 567 → 408 ms | 262 → 204 |
| ML-KEM-768 receiver | 3,902 → 1,884 | 88.6 → 13.9 | 754 → 552 ms | 332 → 292 |
| AES-128 | 4,665 → 2,970 | 20.1 → 6.4 | 1.23 s → 920 ms | 1,215 → 770 |
| AES-256 | 4,960 → 3,198 | 19.9 → 6.5 | 1.33 s → 975 ms | 1,499 → 961 |
| Integer arithmetic 2^20 | 1,146 → 1,143 | 6.8 → 3.7 | 328 → 259 ms | 265 → 252 |
| Integer arithmetic 2^24 | 4,098 → 4,098 | 12.9 → 8.1 | 5.42 → 4.06 s | 3,573 → 3,321 |
| Integer arithmetic 2^26 | 8,022 → 8,021 | 21.3 → 12.4 | 23.32 → 19.27 s | 14,079 → 13,003 |
§ Breaking
- Proofs. Wire v6 to v7 and a new transcript order. A 0.36.0 proof does not verify under
0.37.0, and a 0.37.0 proof does not verify under 0.36.0. Re-prove.
program_idand the bundle format (7) do not move. - Configuration.
Config::prod()carries 288 support cells.check_securityrejectsldt_support_size <= num_querieswithInsufficientSupportwhenevermin_security_bits > 0;Config::dev()waives the floor. - Wire types. The trace commitment is a bare
trace_root.InnerProofgainsh_root,main_point_evaluation,chiplet_rows,chiplet_point_evaluationsand the eval proof's masters, and loses the per-chiplet commitments and eval proofs,LogUpAux.h_commitmentand theBrakedownCommitmentandMasterEvalstypes. - Engine API.
absorb_chiplet_headertakes no root,cheapest_split_varsreplacescompute_split_vars, andMAX_TABLE_VARScaps tables at 2^32 rows.RowEncoder::evaluate_atover sorted columns replacesRowEncoder::evaluate, andhash_column_leavesreplaceshash_leaf_column_encoded. hekate-program gainsPoolLayoutandSlotLayout, andTableShape::from_airtakes&TableStaticsand no height.EvaluatorVerifier::verifytakes the trace andhroots. Each PR's Compatibility section lists the rest. - Prover cdylib 0.15.0, signed (SHA-256, Ed25519, ML-DSA-65). An older cdylib cannot produce a v7 proof.
- Dependencies. hekate-math 0.12.0, whose
AdditiveFft::newreturns aResult. Every crate declares Rust 1.88. - Versions. Workspace 0.36.0 to 0.37.0; hekate-keccak and hekate-aes 0.10.0, hekate-pqc 0.11.0, hekate-sha2 and hekate-rsa 0.3.0.
§ Not promised
- Published proofs. Upgrading does not reach a zero-knowledge proof published under 0.35.0 or 0.36.0: where its query columns were pairwise distinct, it stays checkable against a guess of its witness.
- Zero knowledge at a zero security floor.
min_security_bits = 0skips the support check, also with zero knowledge on. - The rest of the zero-knowledge argument. The fix covers the leaves. The linear part of the view rests on the blinds and on the outer argument, whose zero knowledge is argued separately.
- Single-leaf Merkle openings.
MerkleTree::verifybinds neither the path length nor the leaf index. Open throughverify_batchwith the padded leaf count, as the protocol does. - Narrow column types. A
Bit,B8orB16column that is neither pinned nor bit-expanded is bound by the commitment to GF(2^32) only, and its AIR has to hold it to its declared width. - Circuit semantics. Whether a host program computes what its name says stays with its author.
- Independent audit. This workspace has not had one.