chore: Update multi stark - #588
Draft
samuelburnham wants to merge 4 commits into
Draft
Conversation
samuelburnham
force-pushed
the
update-multi-stark
branch
2 times, most recently
from
August 24, 2026 20:57
7a91539 to
10d1cda
Compare
- rust-toolchain.toml channel: 1.92 → 1.98, with the matching fenix toolchain hash in flake.nix. The pinned fenix already carries the 1.98 release manifest, so flake.lock needs no change (fenix's nixpkgs stays pinned via its lean4-nix follows, so the Lean toolchain is untouched). - Drop clippy::from_iter_instead_of_collect from the workspace lints: removed in clippy 1.98 and now warns as unknown. - Fix the warnings new clippy 1.98 lints surface across the workspace: chunks_exact(N) → as_chunks::<N>() where the chunk size is constant, descending sort_by → sort_by_key(Reverse(..)), iteration over map values via .values(), map().unwrap_or() → map_or(), a checked division, an unwrap-after-is_some restructured into if-let, and assorted redundant-reference/pattern cleanups (mostly cargo clippy --fix). The two byte-gadget files keep their chunks_exact warnings until the next commit, which rewrites those regions anyway. CI derives its Rust version from rust-toolchain.toml, so no workflow changes are needed.
Companion to multi-stark's update-p3 branch (c72d321 → 249b740), which carries four soundness/robustness fixes and the Plonky3 v0.6.0 bump (pruned FRI Merkle multiproofs: ~2x faster verification, 40-70% smaller proofs; canonical Goldilocks serde removes proof-byte malleability). Proofs and verifying keys are not compatible with the previous pin. Integration: - Lookup gained max_multiplicity, a declared per-row bound on the multiplicity's integer magnitude feeding the newly enforced logUp height bound Σ wᵢ·hᵢ + |claims| < p. Function-circuit slots accumulate mutually-exclusive branch selectors, so they declare 1; committed count columns (function return slots, the memory circuit, the byte gadget tables) declare the new COUNT_COLUMN_BUDGET (2^32 queries per entry). - The VK wire format carries the bound: u64 LE max_multiplicity per lookup, between the multiplicity node id and the arg count. The in-circuit VK deserializer (Ix/MultiStark/SystemDeserialize.lean) parses past it; the value is bound through the vk digest but the height bound itself is not yet enforced in-circuit (the native verifier enforces it). - Message fingerprints are width-bound by default upstream (the slot width seeds the Horner fold), which is incompatible with aiur's branch-shared lookup slots: mutually exclusive branches superpose messages of different natural widths into one slot at the maximum width, so a narrow call is sent zero-padded to a width its callee's return slot never provides, and proving fails with UnbalancedChannel (pinned as the prove_verify_mismatched_call_widths regression). Aiur instead declares WidthBinding::ByConstruction — the plain Horner fold, restoring zero-padding transparency — and takes on the prefix-freeness contract that makes it sound: every message's natural width is a function of its constant-constrained leading prefix (channel tag plus discriminator: fun_idx fixes 2+in+out, the memory size coordinate fixes 3+size, each gadget tag fixes its table width), so zero-extension can only equate a padded message with its own natural form. The contract is documented at the channel constants in lib.rs; the declaration is applied in AiurSystem::build and mirrored in the vk_codec decoder so decoded VKs replay the same transcript. ByConstruction is also exactly the fold the in-circuit verifier's logup_fingerprint already computes, so the recursive verifier needs no fingerprint change. - The policy is Fiat-Shamir-bound as the first observe_shape word; the in-circuit transcript replay prepends the matching limb. - aiur_multi_stark.rs regenerated (ix codegen) for the deserializer and transcript changes. - P3 v0.6.0 ships FRI query openings as pruned Merkle multiproofs, while the in-circuit verifier consumes one authentication path per query (its per-query control flow is a far smaller circuit than the amortized multiproof walk). Rather than porting the walk into the DSL, the proof advice stays in the per-query transport: multi-stark's new advice module re-encodes a natively-verified proof by running p3's own verification with a recording compression function and reading each query's path back out of the recorded digest map. The advice bytes are untrusted verifier input, never digest-bound — the transcript binds the commitments and every expanded sibling is authenticated against them per query — so pruning vs expansion is pure transport and the encoding choice is sound. AiurSystem gains proof_to_advice_bytes (FFI: AiurSystem.proofToAdviceBytes); the recursive-verifier test feeds it instead of Proof.toBytes, whose native wire format is still round-tripped separately. The Lean-side proof grammar and the codegen'd verifier are byte-identical to before — no in-circuit changes. Claim layout, the VK wire format above and aiur's public semantics are otherwise unchanged; the policy adds no prover or verifier work over the previous pin. Still open, native-verifier-only: the logUp height bound is parsed past but not yet enforced in-circuit (a wide-arithmetic check, tracked separately).
The Lean v4.33.1 update pinned both dependencies at revisions that predate their Rust 1.98 bumps; their heads now carry those bumps, which this workspace needs since rust-toolchain.toml moved to 1.98. Both revisions stay on leanprover/lean4:v4.33.1. - Blake3.lean 1b0fbd2 → e6e908b (Rust 1.98, plus a case-insensitive source-directory fix), updated in lakefile.lean, lake-manifest.json and the blake3-lean flake input. The revision keeps the `blake3_rs_shared` target the `ix_native_decide_dynlib` pin requires. The inherited entry in Benchmarks/Compile/lake-manifest.json was still on the pre-4.33.1 revision and now tracks the root pin. - lean-ffi 2a9c91e → 93c7e52 (Rust 1.98). Only bignat reaches the sp1 and zisk workspaces, so their lock files move that one package.
samuelburnham
force-pushed
the
update-multi-stark
branch
from
August 24, 2026 21:18
10d1cda to
74f9809
Compare
Member
Author
|
!benchmark |
Contributor
|
| constant | execute-time (main) | execute-time (PR) | Δ% | prove-time (main) | prove-time (PR) | Δ% | throughput (const/s) (main) | throughput (const/s) (PR) | Δ% | peak-ram (main) | peak-ram (PR) | Δ% | proof-size (main) | proof-size (PR) | Δ% | verify-time (main) | verify-time (PR) | Δ% | fft-cost (main) | fft-cost (PR) | Δ% |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ByteArray.utf8DecodeChar?_utf8EncodeChar_append |
9.014 s | 9.125 s | +1.2% | 30.764 s | 29.486 s | -4.2% 🟢 | 90.200 | 94.110 | +4.3% 🟢 | 70.68 GiB | 72.32 GiB | +2.3% | 11.33 MiB | 11.07 MiB | -2.3% | 69.0 ms | 64.1 ms | -7.1% (1.08× faster) 🟢 | 134.35B | 134.35B | +0.0% |
Char.ofOrdinal_le_of_le |
6.963 s | 6.853 s | -1.6% | 26.602 s | 24.797 s | -6.8% (1.07× faster) 🟢 | 103.860 | 111.420 | +7.3% (1.07× faster) 🟢 | 63.85 GiB | 65.39 GiB | +2.4% | 11.33 MiB | 11.07 MiB | -2.3% | 79.9 ms | 66.8 ms | -16.4% (1.20× faster) 🟢 | 102.60B | 102.60B | +0.0% |
Array.extract_append |
6.631 s | 6.685 s | +0.8% | 23.297 s | 22.392 s | -3.9% 🟢 | 68.940 | 71.720 | +4.0% 🟢 | 52.00 GiB | 52.76 GiB | +1.5% | 11.24 MiB | 10.99 MiB | -2.2% | 74.5 ms | 65.2 ms | -12.5% (1.14× faster) 🟢 | 97.08B | 97.08B | +0.0% |
Std.HashMap |
4.057 s | 4.083 s | +0.6% | 16.120 s | 14.987 s | -7.0% (1.08× faster) 🟢 | 126.680 | 136.250 | +7.6% (1.08× faster) 🟢 | 36.28 GiB | 37.04 GiB | +2.1% | 11.26 MiB | 11.01 MiB | -2.1% | 76.5 ms | 62.5 ms | -18.2% (1.22× faster) 🟢 | 61.88B | 61.88B | +0.0% |
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq |
3.618 s | 3.612 s | -0.2% | 14.534 s | 13.846 s | -4.7% 🟢 | 128.460 | 134.840 | +5.0% 🟢 | 33.93 GiB | 34.72 GiB | +2.3% | 11.26 MiB | 11.01 MiB | -2.2% | 70.9 ms | 62.7 ms | -11.5% (1.13× faster) 🟢 | 55.68B | 55.68B | +0.0% |
String.append |
433.8 ms | 426.8 ms | -1.6% | 2.285 s | 2.127 s | -6.9% (1.07× faster) 🟢 | 143.100 | 153.740 | +7.4% (1.07× faster) 🟢 | 4.88 GiB | 4.92 GiB | +0.8% | 9.94 MiB | 9.73 MiB | -2.1% | 63.4 ms | 51.1 ms | -19.5% (1.24× faster) 🟢 | 3.37B | 3.37B | +0.0% |
Nat.add_comm |
262.5 ms | 260.5 ms | -0.8% | 1.061 s | 999.5 ms | -5.8% (1.06× faster) 🟢 | 43.360 | 46.030 | +6.2% (1.06× faster) 🟢 | 4.61 GiB | 4.57 GiB | -1.0% | 9.09 MiB | 8.91 MiB | -2.0% | 54.7 ms | 45.3 ms | -17.1% (1.21× faster) 🟢 | 308.40M | 308.40M | +0.0% |
FRI verifier on FRI (7 constants)
| constant | execute-time (main) | execute-time (PR) | Δ% | prove-time (main) | prove-time (PR) | Δ% | throughput (const/s) (main) | throughput (const/s) (PR) | Δ% | peak-ram (main) | peak-ram (PR) | Δ% | proof-size (main) | proof-size (PR) | Δ% | verify-time (main) | verify-time (PR) | Δ% | fft-cost (main) | fft-cost (PR) | Δ% |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
ByteArray.utf8DecodeChar?_utf8EncodeChar_append |
5.646 s | n/a | n/a | 31.929 s | n/a | n/a | 86.910 | n/a | n/a | 100.08 GiB | n/a | n/a | 3.97 MiB | n/a | n/a | 26.1 ms | n/a | n/a | 210.23B | n/a | n/a |
Char.ofOrdinal_le_of_le |
5.466 s | n/a | n/a | 32.052 s | n/a | n/a | 86.200 | n/a | n/a | 99.25 GiB | n/a | n/a | 3.97 MiB | n/a | n/a | 25.0 ms | n/a | n/a | 207.18B | n/a | n/a |
Array.extract_append |
5.297 s | n/a | n/a | 30.552 s | n/a | n/a | 52.570 | n/a | n/a | 94.65 GiB | n/a | n/a | 3.97 MiB | n/a | n/a | 24.7 ms | n/a | n/a | 200.65B | n/a | n/a |
Std.HashMap |
5.326 s | n/a | n/a | 30.546 s | n/a | n/a | 66.850 | n/a | n/a | 94.70 GiB | n/a | n/a | 3.97 MiB | n/a | n/a | 24.6 ms | n/a | n/a | 203.35B | n/a | n/a |
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq |
5.427 s | n/a | n/a | 31.479 s | n/a | n/a | 59.310 | n/a | n/a | 98.48 GiB | n/a | n/a | 3.97 MiB | n/a | n/a | 25.3 ms | n/a | n/a | 205.59B | n/a | n/a |
String.append |
4.426 s | n/a | n/a | 27.931 s | n/a | n/a | 11.710 | n/a | n/a | 87.81 GiB | n/a | n/a | 3.97 MiB | n/a | n/a | 24.5 ms | n/a | n/a | 168.67B | n/a | n/a |
Nat.add_comm |
3.559 s | n/a | n/a | 18.907 s | n/a | n/a | 2.430 | n/a | n/a | 58.66 GiB | n/a | n/a | 3.97 MiB | n/a | n/a | 24.7 ms | n/a | n/a | 130.84B | n/a | n/a |
Pipeline total (7 constants)
| constant | total-time (main) | total-time (PR) | Δ% | pipeline-throughput (const/s) (main) | pipeline-throughput (const/s) (PR) | Δ% | pipeline-peak-ram (main) | pipeline-peak-ram (PR) | Δ% |
|---|---|---|---|---|---|---|---|---|---|
ByteArray.utf8DecodeChar?_utf8EncodeChar_append |
1m 2.7s | n/a | n/a | 44.260 | n/a | n/a | 100.08 GiB | n/a | n/a |
Char.ofOrdinal_le_of_le |
58.654 s | n/a | n/a | 47.110 | n/a | n/a | 99.25 GiB | n/a | n/a |
Array.extract_append |
53.850 s | n/a | n/a | 29.820 | n/a | n/a | 94.65 GiB | n/a | n/a |
Std.HashMap |
46.666 s | n/a | n/a | 43.760 | n/a | n/a | 94.70 GiB | n/a | n/a |
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq |
46.013 s | n/a | n/a | 40.580 | n/a | n/a | 98.48 GiB | n/a | n/a |
String.append |
30.216 s | n/a | n/a | 10.820 | n/a | n/a | 87.81 GiB | n/a | n/a |
Nat.add_comm |
19.967 s | n/a | n/a | 2.300 | n/a | n/a | 58.66 GiB | n/a | n/a |
The !benchmark recursive phase reported n/a for every fri-verifier metric: Benchmarks/Typecheck.lean still fed Proof.toBytes — the pruned multiproof wire format — to executeMultiStark/proveMultiStark, so the in-circuit verifier rejected on parse and the harness (correctly) left the recursive fields absent rather than emit a fake datum. The in-circuit verifier consumes the per-query advice transport (AiurSystem.proofToAdviceBytes); proofBytes stays the reported proof-size metric. bench-recursion-debug had the same advice-format gap plus a stale claim recipe: it still built the public input as 32 raw digest bytes, predating the ClaimHarness.packedDigestKey packing bench-typecheck uses (its own out-of-circuit sanity check failed with InvalidPowWitness — a wrong claim diverges every challenge — and the advice re-encoder refused the proof for the same reason). Both aligned with the typecheck flow. Validated end-to-end at production parameters (numQueries 100, query PoW 20, blowup 2) on Nat.add_comm: inner prove, advice re-encoding, and the codegen'd in-circuit verifier accepting.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Companion PR for argumentcomputer/multi-stark#74