fix(aiur): correct lookup constraints and strengthen proof validation - #634
Merged
Merged
Conversation
Require function and memory provider multiplicities to vanish on inactive rows, including each member of a grouped circuit. Preserve lookup widths and linear multiplicities. Port the activity repair from PR #631's first commit without its call ranks. The supplied-trace regression accepted 3 * 5 = 16 before the fix; it now rejects. All four acceptance tests pass in the release parallel test suite. Co-authored-by: John C. Burnham <john@agathic.com>
Only omit argument gates for a single function with terminal control and one selector. An empty branch still emits operation lookups even though it allocates no terminal selector. Use the same condition for lookup grouping so the gated expressions fit the quotient degree. Port this independent repair from PR #631 without call-order columns. Before the fix, an inactive store redirected a live call into memory and proved a false result; honest execution also failed proof verification. Both regressions now pass. Strict release parallel Clippy passes. Co-authored-by: John C. Burnham <john@agathic.com>
Validate constrained call input/output arities and continuation yields at construction. Check the public claim channel, entry visibility, and exact input/output shape before proof verification. Preserve the claim encoding. Adapt PR #631's message-shape checks without its rank field. A supplied trace for an empty return previously verified a claim returning zero due to lookup zero-padding; the new regression rejects it. A mismatched call with sufficient allocated columns is now rejected at construction too. All five shape regressions and strict release parallel Clippy pass. Co-authored-by: John C. Burnham <john@agathic.com>
Check circuit member indices, bounded control counts, and selector capacity before constructing constraints. Count continuation-consumed yields and empty matches correctly. This ports PR #631's structural guard without changing compiler layouts or adding call-order constraints. Tests cover malformed selector counts, continuation accounting, machine overflow and field bounds. The missing-selector fixture now fails at the Aiur validation boundary rather than downstream column compilation. All three count tests and strict release parallel Clippy pass. Co-authored-by: John C. Burnham <john@agathic.com>
Require every fixed preprocessed circuit to be active at its exact height before entering PCS verification. Align proof degrees by active position and reject malformed metadata without shifting by unchecked amounts. Port PR #631's fixed-table guard without rank lookups. The tests distinguish early InvalidProofShape rejection from later opening failures, cover absent byte tables and incorrect heights, and preserve honest verification. All three fixed-table tests and strict release parallel Clippy pass. Co-authored-by: John C. Burnham <john@agathic.com>
Bound one public claim plus every lookup slot in every active trace row below the Goldilocks characteristic. Count slots in canonical circuit order and degrees in active order; reject metadata mismatches, shifts and arithmetic overflow before verifying openings. Port this supporting bound from PR #631 without call-rank machinery. Tests cover alignment, active/inactive circuits, machine and field bounds, serialized-key limits, and public verifier metadata rejection. All five tests and strict release parallel Clippy pass. This guard makes the count assumption explicit; it is not another demonstrated false-result exploit. Co-authored-by: John C. Burnham <john@agathic.com>
Require the effective native MMCS cap to cover every trace matrix after LDE blowup. Reject uncovered short matrices before verifying openings; root caps take the constant-time path and trace layouts are unchanged. Distill the third commit of PR #631. Reproduce native single- and multi-opening acceptance of altered short-matrix values and identical commitments for different short matrices. The public-verifier regression fails before the guard and passes afterward; valid boundary caps still verify. Compare the guard against direct injection geometry across 288225 boundary cases. All 35 Aiur tests and strict release parallel Clippy pass. Co-authored-by: John C. Burnham <john@agathic.com>
Member
Author
|
!benchmark fresh |
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 |
8.757 s | 9.000 s | +2.8% | 37.224 s | 37.492 s | +0.7% | 74.550 | 74.020 | -0.7% | 72.44 GiB | 72.65 GiB | +0.3% | 5.16 MiB | 5.20 MiB | +0.7% | 31.8 ms | 33.1 ms | +4.3% |
132.99B | 133.40B | +0.3% |
Char.ofOrdinal_le_of_le |
6.453 s | 6.479 s | +0.4% | 31.054 s | 30.812 s | -0.8% | 88.970 | 89.670 | +0.8% | 62.75 GiB | 62.94 GiB | +0.3% | 5.16 MiB | 5.20 MiB | +0.7% | 30.8 ms | 30.2 ms | -2.1% | 95.52B | 95.82B | +0.3% |
Array.extract_append |
6.527 s | 6.392 s | -2.1% | 28.145 s | 27.851 s | -1.0% | 57.060 | 57.660 | +1.1% | 53.13 GiB | 53.26 GiB | +0.3% | 5.01 MiB | 5.06 MiB | +1.0% | 29.5 ms | 32.2 ms | +9.3% (1.09× slower) |
95.20B | 95.44B | +0.3% |
Std.HashMap |
3.999 s | 4.009 s | +0.3% | 17.980 s | 17.919 s | -0.3% | 113.570 | 113.960 | +0.3% | 36.41 GiB | 36.39 GiB | -0.0% | 5.08 MiB | 5.13 MiB | +0.9% | 30.1 ms | 31.0 ms | +3.2% |
61.01B | 61.21B | +0.3% |
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq |
3.680 s | 3.655 s | -0.7% | 16.972 s | 16.871 s | -0.6% | 110 | 110.660 | +0.6% | 35.03 GiB | 35.26 GiB | +0.7% | 5.05 MiB | 5.09 MiB | +0.8% | 29.9 ms | 29.9 ms | +0.1% | 55.56B | 55.75B | +0.3% |
String.append |
449.8 ms | 441.7 ms | -1.8% | 1.906 s | 1.878 s | -1.5% | 171.600 | 174.120 | +1.5% | 5.75 GiB | 4.88 GiB | -15.2% (1.18× smaller) 🟢 | 4.80 MiB | 4.84 MiB | +0.9% | 29.0 ms | 27.9 ms | -3.7% 🟢 | 3.45B | 3.46B | +0.3% |
Nat.add_comm |
270.8 ms | 267.8 ms | -1.1% | 772.2 ms | 779.4 ms | +0.9% | 59.570 | 59.020 | -0.9% | 4.90 GiB | 4.02 GiB | -17.9% (1.22× smaller) 🟢 | 4.60 MiB | 4.65 MiB | +1.1% | 26.7 ms | 27.1 ms | +1.7% | 320.32M | 321.01M | +0.2% |
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 |
2.600 s | 2.596 s | -0.1% | 22.893 s | 22.887 s | -0.0% | 121.220 | 121.250 | +0.0% | 56.50 GiB | 56.56 GiB | +0.1% | 2.20 MiB | 2.21 MiB | +0.5% | 13.0 ms | 13.4 ms | +3.4% |
110.55B | 111.05B | +0.5% |
Char.ofOrdinal_le_of_le |
2.566 s | 2.624 s | +2.3% | 22.998 s | 22.968 s | -0.1% | 120.140 | 120.300 | +0.1% | 56.45 GiB | 56.63 GiB | +0.3% | 2.21 MiB | 2.20 MiB | -0.5% | 14.1 ms | 13.7 ms | -3.0% | 110.68B | 110.96B | +0.2% |
Array.extract_append |
2.437 s | 2.513 s | +3.1% |
22.159 s | 22.529 s | +1.7% | 72.480 | 71.290 | -1.6% | 54.42 GiB | 55.13 GiB | +1.3% | 2.20 MiB | 2.21 MiB | +0.4% | 12.7 ms | 13.4 ms | +5.9% (1.06× slower) |
105.50B | 107.38B | +1.8% |
Std.HashMap |
2.535 s | 2.604 s | +2.7% | 22.411 s | 23.018 s | +2.7% | 91.120 | 88.710 | -2.6% | 54.99 GiB | 55.78 GiB | +1.4% | 2.20 MiB | 2.21 MiB | +0.2% | 12.9 ms | 12.9 ms | -0.1% | 108.13B | 109.21B | +1.0% |
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq |
2.469 s | 2.592 s | +5.0% (1.05× slower) |
22.398 s | 22.505 s | +0.5% | 83.360 | 82.960 | -0.5% | 54.64 GiB | 55.12 GiB | +0.9% | 2.19 MiB | 2.21 MiB | +0.7% | 12.9 ms | 13.1 ms | +1.5% | 107.01B | 108.09B | +1.0% |
String.append |
2.338 s | 2.375 s | +1.6% | 21.102 s | 21.013 s | -0.4% | 15.500 | 15.560 | +0.4% | 50.49 GiB | 51.44 GiB | +1.9% | 2.21 MiB | 2.21 MiB | -0.1% | 13.6 ms | 13.0 ms | -4.6% 🟢 | 96.08B | 98.51B | +2.5% |
Nat.add_comm |
2.217 s | 2.264 s | +2.1% | 20.979 s | 20.742 s | -1.1% | 2.190 | 2.220 | +1.4% | 50.54 GiB | 50.67 GiB | +0.3% | 2.21 MiB | 2.20 MiB | -0.5% | 12.9 ms | 13.9 ms | +8.4% (1.08× slower) |
90.48B | 93.37B | +3.2% |
Aggregate flat join (7 constants)
| constant | execute-time (main) | execute-time (PR) | Δ% | prove-time (main) | prove-time (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 |
n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a |
Char.ofOrdinal_le_of_le |
n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a |
Array.extract_append |
n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a |
Std.HashMap |
n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a |
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq |
n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a |
String.append |
n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a |
Nat.add_comm |
n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | n/a | 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 0.1s | 1m 0.4s | +0.4% | 46.160 | 45.960 | -0.4% | 72.44 GiB | 72.65 GiB | +0.3% |
Char.ofOrdinal_le_of_le |
54.052 s | 53.780 s | -0.5% | 51.120 | 51.380 | +0.5% | 62.75 GiB | 62.94 GiB | +0.3% |
Array.extract_append |
50.304 s | 50.380 s | +0.2% | 31.930 | 31.880 | -0.2% | 54.42 GiB | 55.13 GiB | +1.3% |
Std.HashMap |
40.390 s | 40.936 s | +1.4% | 50.560 | 49.880 | -1.3% | 54.99 GiB | 55.78 GiB | +1.4% |
_private.Init.Data.Range.Polymorphic.SInt.0.Int64.instRxcHasSize_eq |
39.370 s | 39.376 s | +0.0% | 47.420 | 47.410 | -0.0% | 54.64 GiB | 55.12 GiB | +0.9% |
String.append |
23.007 s | 22.891 s | -0.5% | 14.210 | 14.290 | +0.6% | 50.49 GiB | 51.44 GiB | +1.9% |
Nat.add_comm |
21.751 s | 21.521 s | -1.1% | 2.110 | 2.140 | +1.4% | 50.54 GiB | 50.67 GiB | +0.3% |
(cherry picked from commit b189530)
arthurpaulino
enabled auto-merge
September 15, 2026 17:47
gabriel-barrett
approved these changes
Sep 15, 2026
samuelburnham
added a commit
that referenced
this pull request
Sep 15, 2026
…p soundness and proof-shape validation Conflicts and how they were resolved: - Ix/Aiur/Stages/Source.lean: both sides fixed inlining's statement ordering; main's #628 (freshening plus prefix hoisting with tests in Tests/Aiur/Cross.lean) replaces the branch's statement-frame hoisting (13fada3), which nothing else referenced. - crates/aiur/src/constraints.rs, memory.rs: both sides closed the same hole, a padding row pulling a return or memory message with a multiplicity of its own. Main's #634 form is kept (linear lookup multiplicity plus a `multiplicity * (1 - selector)` constraint) and the branch's memory-segment boundary lookups stay on top of it. - crates/aiur/src/synthesis.rs: main's structural validation runs in build_on_device; main's proof-shape guards (claim shape, fixed trace heights, Merkle cap coverage, lookup query bound) now run on every shard header of a batch proof before the batch policy and verify_batch. - Main's new synthesis tests (#634) are ported to the batch API: a hand-built witness is proven as a one-shard batch, shape fields live on the shard header, and Aiur's verify wraps multi-stark's errors. - crates/ixvm-codegen/src/*.rs: the branch's generated kernels are kept provisionally; they are regenerated with `ix codegen` in the next commit from the merged Lean sources.
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.
Aiur could accept false public results through inactive provider rows, incorrectly combined lookup messages, and ambiguous function-message boundaries. The lookup-gating bug also prevented an honest execution from verifying. This PR fixes those failures, rejects Merkle-cap configurations that fail to bind every trace matrix, and adds explicit structural validation at the Aiur boundary.
The changes distill the first and third commits of #631 into seven atomic commits. Call-rank machinery, cyclic-trace defenses, and performance improvements from that PR are excluded. Cyclic call traces remain outside this PR's scope.
The fixes distinguish soundness (rejecting proofs of false claims) from completeness (allowing honest executions to prove and verify):
2897d6b53 * 5 = 16. Additional constraint tests cover inactive memory rows and every grouped member.9d5d0fe9c852ccce15be618ee6046b4e58a6ce66e9048e89The adversarial regressions use the existing Rust Aiur test infrastructure and supplied trace rows, independently of honest witness generation. The Merkle-cap guard is also checked against direct injection geometry across 288,225 boundary cases. Honest proofs using unsafe cap configurations are intentionally rejected; the normal root-cap setting remains supported.
The lookup-gating fix has a conservative proving-cost tradeoff: only a single-selector, single-function circuit with terminal control retains raw lookup arguments and grouped accumulators. Some safe functions containing matches therefore lose that optimization. Execution counts and main trace widths are unchanged, but stage-2 width and potentially quotient degree increase. Measured FFT estimates rise by 0.22% for
Nat.add_command 0.38% for the shard pipeline. The corresponding exact pins are updated in the gating commit. These are FFT-model changes, not measured wall-clock slowdowns; a more precise lookup-writer analysis is deferred.Validation passed:
cargo test --locked --release -p aiur --features parallel.cargo clippy --locked --release --workspace --all-targets --features ix-ffi/parallel,ix-ffi/net,ix-ffi/test-ffi -- -D warnings.cargo fmt --all -- --check.lake exe ix codegen --check; all three generated programs are unchanged.lake test --wfail -- aiur-cross aiur-cost aiur-prove aiur-hashes rbtree-map multi-stark recursive-verifier ix-aggr.lake test --wfail -- --ignored ixvm.