Skip to content
Oumuamua Labs

Hekate v0.37.0

Released Source v0.37.0 Mandatory upgrade
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 j hashes one codeword column of every table, H(0x02 ‖ d_0 ‖ … ‖ d_(T-1)) with d_i = H(0x00 ‖ part_i), where part_i is table i's symbols at column j over its grid rows; inner nodes stay H(0x01 ‖ l ‖ r). The LogUp helper columns h of 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 c from the absorbed table heights, the program and the configuration, and every table encodes at the same width. A table of 2^n rows with n < c packs 2^(c-n) columns of one class into each codeword row, zero blocks closing the last; a taller table keeps 2^(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 sets c.
  • 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 through eq(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 the h root, before any table's first challenge. Then each table's bus sums, ZeroCheck, h evaluations 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 by eq(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 - 1 batched units, for Σ slot roles and m masters, 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 + 1 and at least two messages weighted in the fold vector, every unopened symbol is uniform given the view and every data cell. Both sides reject ldt_support_size <= num_queries whenever min_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 data d. With S = t support cells and t distinct 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 ran S = t = 287 on 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_prepared replays a proof against it and rejects a pinned id that differs from the one computed at preparation, and VerifierScratch caches state between proofs, one per thread. verify_batch spreads proofs over the thread pool and returns the results in input order. verify keeps 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.

WorkloadProof, KiBVerify, msProvingPeak, MiB
Keccak 2^15858 → 85111.9 → 4.6195 → 163 ms164 → 143
Keccak 2^203,542 → 3,54417.1 → 7.13.73 → 3.23 s2,418 → 2,430
SHA-256 2^11540 → 5169.4 → 3.269 → 53 ms65 → 62
SHA-256 2^215,485 → 5,48522.7 → 11.310.65 → 8.72 s5,228 → 5,099
ML-DSA-442,867 → 1,54750.7 → 10.5549 → 432 ms296 → 219
ML-DSA-652,959 → 1,56852.0 → 10.3594 → 472 ms276 → 207
ML-DSA-873,336 → 1,81255.7 → 11.2766 → 618 ms422 → 308
RSA-204814,724 → 1,81029.4 → 8.2334 → 204 ms517 → 397
ML-KEM-768 sender3,508 → 1,54472.1 → 11.6567 → 408 ms262 → 204
ML-KEM-768 receiver3,902 → 1,88488.6 → 13.9754 → 552 ms332 → 292
AES-1284,665 → 2,97020.1 → 6.41.23 s → 920 ms1,215 → 770
AES-2564,960 → 3,19819.9 → 6.51.33 s → 975 ms1,499 → 961
Integer arithmetic 2^201,146 → 1,1436.8 → 3.7328 → 259 ms265 → 252
Integer arithmetic 2^244,098 → 4,09812.9 → 8.15.42 → 4.06 s3,573 → 3,321
Integer arithmetic 2^268,022 → 8,02121.3 → 12.423.32 → 19.27 s14,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_id and the bundle format (7) do not move.
  • Configuration. Config::prod() carries 288 support cells. check_security rejects ldt_support_size <= num_queries with InsufficientSupport whenever min_security_bits > 0; Config::dev() waives the floor.
  • Wire types. The trace commitment is a bare trace_root. InnerProof gains h_root, main_point_evaluation, chiplet_rows, chiplet_point_evaluations and the eval proof's masters, and loses the per-chiplet commitments and eval proofs, LogUpAux.h_commitment and the BrakedownCommitment and MasterEvals types.
  • Engine API. absorb_chiplet_header takes no root, cheapest_split_vars replaces compute_split_vars, and MAX_TABLE_VARS caps tables at 2^32 rows. RowEncoder::evaluate_at over sorted columns replaces RowEncoder::evaluate, and hash_column_leaves replaces hash_leaf_column_encoded. hekate-program gains PoolLayout and SlotLayout, and TableShape::from_air takes &TableStatics and no height. EvaluatorVerifier::verify takes the trace and h roots. 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::new returns a Result. 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 = 0 skips 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::verify binds neither the path length nor the leaf index. Open through verify_batch with the padded leaf count, as the protocol does.
  • Narrow column types. A Bit, B8 or B16 column 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.