Skip to content

feat: commit the R1CS witness with zook - #485

Draft
BornPsych wants to merge 10 commits into
zkfr/integrate-buffer-abstractionfrom
ys/zook-witness-commitment
Draft

feat: commit the R1CS witness with zook#485
BornPsych wants to merge 10 commits into
zkfr/integrate-buffer-abstractionfrom
ys/zook-witness-commitment

Conversation

@BornPsych

@BornPsych BornPsych commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

Switches the R1CS witness commitment from plain WHIR to zook (RateSchedule::Adaptive, Mode::Standard), and bumps whir to 8804e80.

On the passport circuit this is ~37% off the R1CS proving core and ~17% off total prove time, for ~26% larger proofs.

Do not merge yet. Blocked on:

gnark parameter export and the Go recursive verifier are intentionally left disabled here; they need a paired update once the above land.

Collects a slice of concrete covectors into the `Vec<&dyn LinearForm<F>>`
shape whir's opening APIs take. The prover and verifier both build this
vector by hand at several call sites; a shared helper removes the
repetition and keeps the trait-object cast in one place.
Moves the `whir` pin from 33fbecf to 8804e80 (worldfnd/whir, PR #270).
That rev replaces the `Messages` + separate-mask Reed-Solomon interface
with segmented `Polynomials`, and adds the `zook` protocol module the
following commits switch the witness commitment over to.

Also enables serde_json's `float_roundtrip` feature: zook's `KneeWeight`
and `ListSize` wrap `OrderedFloat<f64>`, and the default fast float
parser is off by one ULP on read-back, which breaks scheme JSON
roundtrips.

Cargo.lock additionally picks up a `zeroize` edge for whir and a batch of
incidental `windows-sys` version moves from re-resolving the graph; none
of those affect the build on our targets.
whir replaced `Messages` plus a separate `masks` buffer with
`Polynomials::from_segments`, where each `PolynomialSegment` contributes a
contiguous run of coefficient columns. `interleaved_encode` now walks the
segments and transposes each one into the interleaved layout `ntt_nr`
consumes, instead of copying masks in as a tail block.

`evaluation_points` takes the full polynomial length rather than the
unmasked message length. The `codeword_length % coset_size != 0` loop
condition stays spelled out: `is_multiple_of` needs Rust 1.87 and the
workspace MSRV is 1.85.

The proptest now also covers a zero-length mask segment, which is what
`Mode::Standard` produces, and the single-buffer message layout the
prover actually commits.
`WhirR1CSScheme::whir_witness` becomes a zook `ProtocolConfig` derived
from an explicit `SecuritySpec`/`TuningSpec` pair rather than a plain
`whir::Config`. The tuning knobs move to named constants: `Mode::Standard`
for the commitment mode, and `RateSchedule::Adaptive` at the default
0.5 knee, which plans per-round inverse rates against the prover-time /
proof-size pareto knee instead of stepping the rate unboundedly.

`ProtocolConfig::derive` is fallible, so `new_for_r1cs`,
`new_from_dimensions` and `new_witness_config_for_size` now return
`anyhow::Result`, and the two dimension invariants become `ensure!`
instead of `assert!` — library code should not panic on caller error.

The blinding commitment stays a plain `whir::Config`: the Spartan mask `g`
is extension-valued and does not go through the base-field zook path.
`WhirR1CSCommitment::witness` holds a zook `CommittedWitness`, and the
padded witness length now comes from the config's `tuning().vector_size`
rather than `initial_num_variables()`.

zook's `commit` consumes the buffer but the prove stage still needs the
message for the covector evaluations, so the padded witness is cloned;
an upstream `commit(&Buffer)` or a message accessor would remove that.

Both the single- and dual-commitment opening paths hand zook borrowed
linear forms via `linear_form_refs` instead of boxing each covector, and
the SPARK covector snapshots go away with them: zook's `prove` returns
`()`, so there is no final evaluation point to re-evaluate the alpha
weights at.
zook's `verify` takes the linear forms and their claimed evaluations up
front and returns a `FinalClaim` whose `verify` now takes a slice rather
than an iterator. Its sumcheck also draws extension-field randomness, so
the impl picks up a `Standard: Distribution<Ext<P>>` bound.

All three weight-reference sites switch to `linear_form_refs`.
A SPARK query needs the final WHIR evaluation point to re-evaluate the A,
B, C covectors at. zook's `prove` returns `()` and keeps that point
internal, so the query cannot be built. Rather than silently emitting
nothing, both the generic and the Mavros prove paths now fail fast with
an explanatory error, and `ProveFromAlphasCtx::spark_row` is documented
as reserved.

Restoring this needs a whir-side change that exposes the prover's final
claim; the call sites are marked with a TODO pointing at it.
Scheme construction can now fail while deriving the zook config, so the
Noir and Mavros compilers propagate the error and `MavrosSchemeBuilder`
returns `anyhow::Result<Self>`.

`assert_configs_secure` no longer reads a security level off the witness
config — zook owns that calculation. It runs zook's own `validate` and
asserts the target stays at 128 bits. The blinding half still checks
`security_level` directly, since it remains a plain whir config.
`prove_setup` returns `Result<ProveInputs<P>>` and the harness builders
propagate the scheme-construction error.
The gnark exporter serialises a plain whir `Config`; it has no way to
describe zook's `ProtocolConfig`, and the Go recursive verifier would
have to be updated in lockstep to consume one. Until that paired change
lands, both entry points — the `generate-gnark-inputs` CLI command and
the verifier server's parameter preparation — fail with an error that
says so, and `provekit-gnark` drops out of the two crates' dependencies
so `cargo machete` stays quiet.

Also drops two `return` statements from the verifier server's
cancellation branches; they are the last statement in their `select!`
arm and clippy flags them.
@vercel

vercel Bot commented Aug 20, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs-provekit-org Ready Ready Preview Aug 20, 2026 3:42pm

Request Review

@github-actions

Copy link
Copy Markdown

CSP benchmarks

Metric Value
Workflow status [PASS] success
Commit 5bcb6a5c6495
Run #32387757153
Circuits benchmarked 21
Iterations averaged per circuit 3

Prover time, peak RSS, peak heap, and verifier time are arithmetic means across the iterations. Peak heap comes from the largest peak memory entry in provekit-cli prove's tracing output; peak RSS is reported by /usr/bin/time -v (max-resident-set-size).

No baseline available yet — deltas will appear once this workflow has produced at least one successful main run.

Results
Circuit Constraints Witnesses Prover time Peak RSS Peak heap Verifier time Proof size PKP size
ecdsa_p256 143,321 258,215 1.52 s 237 MB 196 MB 90 ms 387 KB 811 KB
keccak_1024 788,814 1,490,812 4.12 s 929 MB 905 MB 447 ms 462 KB 5.88 MB
keccak_128 157,522 304,529 993 ms 253 MB 210 MB 110 ms 392 KB 1.26 MB
keccak_2048 1,507,374 2,840,532 8.07 s 1.76 GB 1.74 GB 847 ms 500 KB 11.97 MB
keccak_256 247,782 474,010 1.19 s 291 MB 257 MB 150 ms 413 KB 1.88 MB
keccak_512 428,126 812,944 2.16 s 525 MB 470 MB 247 ms 432 KB 3.32 MB
poseidon2_12 479 563 30 ms 13.51 MB 3.35 MB 10 ms 76.71 KB 437 KB
poseidon2_16 556 719 30 ms 14.00 MB 3.62 MB 10 ms 80.56 KB 530 KB
poseidon2_2 231 278 20 ms 12.20 MB 2.45 MB 69.59 KB 108 KB
poseidon2_4 529 535 20 ms 12.27 MB 2.64 MB 74.14 KB 31.76 KB
poseidon2_8 363 423 30 ms 13.25 MB 3.14 MB 71.20 KB 365 KB
poseidon_12 504 524 30 ms 14.15 MB 3.78 MB 10 ms 78.71 KB 569 KB
poseidon_16 609 633 30 ms 14.40 MB 4.23 MB 10 ms 77.17 KB 717 KB
poseidon_2 240 249 20 ms 11.94 MB 2.40 MB 65.81 KB 59.28 KB
poseidon_4 297 309 20 ms 13.12 MB 3.06 MB 71.04 KB 333 KB
poseidon_8 402 418 27 ms 13.41 MB 3.41 MB 10 ms 71.92 KB 448 KB
sha256_1024 196,940 339,764 1.09 s 283 MB 244 MB 170 ms 397 KB 1.89 MB
sha256_128 46,398 80,974 270 ms 75.76 MB 57.51 MB 40 ms 314 KB 507 KB
sha256_2048 345,399 612,724 2.13 s 500 MB 452 MB 300 ms 426 KB 3.05 MB
sha256_256 67,904 117,944 460 ms 124 MB 102 MB 60 ms 343 KB 723 KB
sha256_512 110,916 191,884 590 ms 151 MB 131 MB 100 ms 356 KB 1.11 MB

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant