Input checks#5
Merged
Merged
Conversation
* Separate types for Relaxed R1CS and R1CS instances and witnesses * Allows creating default values for Relaxed R1CS types * StepSNARK now folds a regular R1CS instance-witness into a running Relaxed R1CS instance-witness * We additionally enforce input chaining checks: the incoming instance must have input that matches the output of the incremental computation thus far
asn-d6
pushed a commit
to asn-d6/Nova
that referenced
this pull request
Apr 23, 2023
…et/bug/test_fix Fixes a bug with the tests
huitseeker
added a commit
to huitseeker/Nova
that referenced
this pull request
Jul 3, 2023
* abomonation for public params * update .gitignore * remove unneeded file * fix: adjust to upstream --------- Co-authored-by: François Garillot <francois@garillot.net>
huitseeker
added a commit
to huitseeker/Nova
that referenced
this pull request
Jul 14, 2023
* abomonation for public params * update .gitignore * remove unneeded file * fix: adjust to upstream --------- Co-authored-by: François Garillot <francois@garillot.net>
github-actions Bot
pushed a commit
to huitseeker/Nova
that referenced
this pull request
Jul 14, 2023
* abomonation for public params * update .gitignore * remove unneeded file * fix: adjust to upstream --------- Co-authored-by: François Garillot <francois@garillot.net>
github-actions Bot
pushed a commit
to huitseeker/Nova
that referenced
this pull request
Jul 17, 2023
* abomonation for public params * update .gitignore * remove unneeded file * fix: adjust to upstream --------- Co-authored-by: François Garillot <francois@garillot.net>
github-actions Bot
pushed a commit
to huitseeker/Nova
that referenced
this pull request
Jul 21, 2023
* abomonation for public params * update .gitignore * remove unneeded file * fix: adjust to upstream --------- Co-authored-by: François Garillot <francois@garillot.net>
huitseeker
added a commit
to huitseeker/Nova
that referenced
this pull request
Aug 14, 2023
* abomonation for public params * update .gitignore * remove unneeded file * fix: adjust to upstream --------- Co-authored-by: François Garillot <francois@garillot.net>
huitseeker
added a commit
to huitseeker/Nova
that referenced
this pull request
Aug 15, 2023
* abomonation for public params * update .gitignore * remove unneeded file * fix: adjust to upstream --------- Co-authored-by: François Garillot <francois@garillot.net>
huitseeker
added a commit
to huitseeker/Nova
that referenced
this pull request
Aug 23, 2023
…rameter (microsoft#5) * feat: Make commitment key generation configurable with an optional parameter - Implemented the `Len` trait within `CommitmentKey` to allow length quantification in terms of group generators. Made ppSnark fail setup if given commitment key with insufficient length, as measured by its own commitment_key_floor() (see below) - Made RelaxedR1CSTrait include a fn commitment_key_floor() -> Box<dyn for<'a> Fn(&'a R1CSShape<G>) -> usize> with default implementation to quantify the Snark's commitment key size requirements in the shape of a closure, - Made PublicParameters accept optional Box<dyn for<'a> Fn(&'a R1CSShape<G>) -> usize> parameters for each circuit's group, to parametrize the CommitmentKey creation. Implementation details: - defined type alias CommitmentKeyHint<G> = Box<dyn Fn(&R1CSShape<G>) -> usize>; - Modified numerous function calls and parameter setups to include optional parameter `CommitmentKeyHint` that gives a more flexible commitment key generation. - Added the `CommitmentKeyHint` to the `r1cs` import list and expanded `NovaShape` trait to optionally accept it. * fix: rename Len::len -> Len::length to avoid unrelated clippy lint
marcus-sa
added a commit
to marcus-sa/Nova
that referenced
this pull request
May 9, 2026
…ookup_per_table absorb extension Lands the (W1) §1.4 binding fix per the GH-microsoft#5 design pin (`docs/research/cryptography/microsoftgh-5-augmented-circuit-wireup-design-pin-2026-05-08.md`). Vendor surface changes (both gated `#[cfg(feature = "lookup-fold")]`): `src/neutron/circuit/relation.rs::AllocatedFoldedInstance`: - New field: `T_lookup_per_table: Option<Vec<AllocatedNum<E::Scalar>>>` per pin §3.2 (W3 verdict). - `alloc(...)` extended to populate from `inst.t_lookup()` (length implicit, `None` at outer base). - New `default_with_lookup_k(cs, k)` constructor allocating `[alloc_zero(); k]` per pin §2.3 / §3.2; marked `#[allow(dead_code)]` until M.GH5.3 wires it into `synthesize_base_case`. - `default()` extended with `T_lookup_per_table: None`. - `absorb_in_ro` extended (the W1 §1.4 binding fix): each `T_lookup_per_table[j]` absorbed in `table_id`-canonical order BETWEEN `T` and `u`, empty-not-skipped at outer base. - `fold(...)` extended with passthrough. - `conditionally_select` extended with per-element select on matched-shape `Option<Vec<...>>`; mismatched shapes return `SynthesisError::Unsatisfiable` (fail-closed). `src/neutron/relation.rs::FoldedInstance`: - `AbsorbInRO2Trait::absorb_in_ro2` mirror: each `T_lookup[j]` absorbed in `table_id`-canonical order BETWEEN `T` and `u`, empty-not-skipped at outer base. Native side byte-equivalent to in-circuit by construction. Cryptographer (Halpert / `@nw-cryptographer`) ratification 2026-05-09: APPROVE byte-order parity per pin §1.4 (verbatim contract: comm_W → comm_E → T → T_lookup_per_table[*] → u → X). High confidence on parity. Empty-not-skipped behavior at outer base structurally identical on both sides. No corrigendum required on §1.4. Test posture: 146/146 vendor lib tests pass + 3 ignored release-only. 40/40 `neutron::*` tests with `--features lookup-fold` pass. Zero regression — existing tests use outer-base running U (`T_lookup == None` / `T_lookup_per_table == None`); the new branch absorbs no extra scalars and the existing FS-transcript schedule is preserved verbatim. Empirical validation of the (W1) binding-via-hash claim follows in M.GH5.0 STAGE 0 spike (next dispatch). Per pin §6.2 / §6.1 W1 falsifier: STAGE 0 byte-equivalence test is the hard gate before any further GH-microsoft#5 milestone proceeds. Reviewed by `@nw-cryptographer` (Halpert) per the GH-microsoft#5 per-step pre-commit review pattern. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
marcus-sa
added a commit
to marcus-sa/Nova
that referenced
this pull request
May 9, 2026
…alloc fail-close + X-arity invariant Closes M.GH5.0 STAGE 0 hard gate per the GH-microsoft#5 design pin (`docs/research/cryptography/microsoftgh-5-augmented-circuit-wireup-design-pin-2026-05-08.md`), honoring the §1.4 + §6.2 corrigenda (Halpert ruling 2026-05-09 on the prior-dispatch's empirical falsifier). ## Background First M.GH5.0 dispatch (vendor commit absent — uncommitted) authored a STAGE 0 fixture using `DirectCircuit::<E, NonTrivialCircuit<Scalar>>` which produces `num_io == 2`. The byte-equivalence test failed at step 1: `cs.is_satisfied() == true` but `h_native != h_circuit`. Halpert re-derivation 2026-05-09 (case (a) — pin §1.4 incompleteness): the (W1) binding-via-hash extension implicitly required `FoldedInstance::X.len() == 1` to hold byte-equivalence between native (`for x in &self.X { ro.absorb(*x); }`) and in-circuit (single `AllocatedNum`). The pin §1.4 pseudocode elided this precondition; the silent `inst.X[0]` truncation in `AllocatedFoldedInstance::alloc` made the violation undetectable. The (W1) soundness reduction at §1.5 holds at the production shape (`circuit/mod.rs:428` calls `hash.inputize` exactly once → `num_io == 1`). No soundness-class halt; pin amendment + impl fail-close + fixture re-shape closes STAGE 0. ## Vendor changes (this commit) `src/neutron/circuit/relation.rs`: 1. **Fail-closed `AllocatedFoldedInstance::alloc`** (lines ~69-86): when `inst.is_some() && inst.X.len() != 1`, return `SynthesisError::Unsatisfiable("...num_io == 1...")`. Outer-base (`inst == None`) unchanged. Mirrors `conditionally_select`'s T_lookup_per_table shape-mismatch fail-close. 2. **STAGE 0 fixture re-shape** (path A per pin §6.2 + §1.4 corrigendum): `m_gh5_0_stage0_absorb_in_ro_byte_equivalence_at_fold_depth_1_and_2` uses `NeutronAugmentedCircuit<'_, E, NonTrivialCircuit<Scalar>>` for shape build (production shape). Asserts `shape.num_io() == 1` at fixture-build. Preserves k=2 multi-table fold-of-two structure, T_lookup pre-check (`Some(&[non-zero, non-zero])`) at both steps, and squeeze-output equality framing (per Halpert Q3 ratification) — `h_native == h_circuit_witness_value` AND `cs.is_satisfied() == true` at both fold steps. 3. **Negative-arity sibling test** `m_gh5_0_alloc_rejects_x_arity_two`: constructs `FoldedInstance` with `X.len() == 2`, asserts `Err(SynthesisError::Unsatisfiable(msg))` with `msg.contains("num_io == 1")`. Documents the X-arity invariant fail-closed at the impl level. ChaCha20Rng seed: `0xC1BE_5BAD_C0DE_0050` (preserved from prior dispatch for reproducibility). ## Empirical results (release-mode mandatory) ``` cd vendor/nova && cargo test --release --features lookup-fold \ stage0_byte_equivalence_tests -- --nocapture ``` `m_gh5_0_stage0_absorb_in_ro_byte_equivalence_at_fold_depth_1_and_2`: PASS `m_gh5_0_alloc_rejects_x_arity_two`: PASS `cargo check --tests --features lookup-fold` clean. ## Wider regression surfaced (handled in sibling commit M.GH5.0a) The fail-close correctly (per the §6.2 corrigendum) rejects 4 pre-existing tests in `src/neutron/circuit/lookup.rs` that use `DirectCircuit::<NonTrivialCircuit>` (`num_io == 2`) and silently relied on the prior allocator truncating `inst.X[0]`: - `m6_in_circuit_per_table_c_binding_hard_rejects_corrupted_t_lookup` - `m6_in_circuit_verify_multi_table_matches_native_k2` - `stage_g_in_circuit_verify_with_lookup_matches_native` - `stage_i_pri_in_circuit_verify_multi_column_matches_native` Per Halpert ruling Q2 (Path Z) + §6.2 propagation corrigendum: these re-shape on a sibling **M.GH5.0a** commit ahead of M.GH5.1, with attribution to this M.GH5.0 dispatch. Mirror's the spike-era latent-failure discipline (`.claude/rules/testing.md`). Reviewed by `@nw-cryptographer` (Halpert) per the GH-microsoft#5 per-step pre-commit review pattern. APPROVE-FOR-COMMIT verdict, High confidence on the fix's faithfulness to the §1.4 + §6.2 corrigenda. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
marcus-sa
added a commit
to marcus-sa/Nova
that referenced
this pull request
May 9, 2026
… per Corrigenda microsoft#2/microsoft#3/microsoft#4/microsoft#4-A Closes M.GH5.0 STAGE 0 hard gate per the GH-microsoft#5 design pin's Halpert ratification chain (Corrigenda microsoft#1 → microsoft#4-A) following Marcus's correctness-over-minimalism mandate (Core Principle 7, codified at `5e5e951`). ## Ratification chain The path from STAGE 0 first-attempt failure to close walked through five cryptographer rulings, each correcting a prior over-narrowing or implementation gap: - **Corrigendum microsoft#1** (2026-05-09): X-arity invariant `num_io == 1` + alloc fail-close. Closed the original STAGE 0 byte-disagreement at `num_io == 2` (DirectCircuit fixture). Empirically valid; ratified Path-X re-shape. (RETIRED by microsoft#2 under Principle 7.) - **Corrigendum microsoft#2** (2026-05-09): Path W. Extends `AllocatedFoldedInstance::X` from `AllocatedNum` to `Vec<AllocatedNum>` mirroring native. Retires the `num_io == 1` invariant on simplicity grounds (Principle 7 forbids simplicity-based rejection of more-general options). The 4 pre-existing M.6 / Stage G / Stage I.pri lookup-circuit tests are routed to STAY at single-IO via `MinimalSingleIOCircuit`. - **Corrigendum microsoft#3** (2026-05-09): γ.1 fold-arity invariant. `AllocatedFoldedInstance::fold` is N==1-only because U2 (`AllocatedNonnativeR1CSInstance`) is structurally single-IO per §1.6 anchor. Path W's Vec-shape applies to absorb_in_ro / select / alloc; fold fail-closes at N≥2 with twin-substring error message. - **Corrigendum microsoft#4** (2026-05-09): Path Y. Restores upstream microsoft/Nova's `let X = T.clone()` pattern in `default(cs, num_io)` and `default_with_lookup_k(cs, num_io, k)` X allocation. Path W's `AllocatedNum::alloc(... || Ok(ZERO))` lost the `(0)·(0) = T` binding constraint (`alloc_zero` emits the row; `T.clone()` shares the variable, inheriting the binding). Without this restoration, a malicious base-case prover could populate the unconstrained aux variable with any value — `.claude/rules/cryptography.md`'s "missing constraint is a forgery vector". - **Corrigendum microsoft#4-A** (2026-05-09): negative-test shape adaptation under Path Y's variable-aliasing semantics. Path W's malicious-X[0] test shape is structurally meaningless under Path Y because X[i] IS T (variable-aliased via T.clone()). Setting X[0]=N≠0 would require T=N≠0, which `alloc_zero` rejects directly. The negative test adapts to a structural-binding test asserting variable-identity (X[i].get_variable() == T.get_variable()) plus constraint-count floor plus positive is_satisfied — catches the only regression class capable of re-opening the forgery vector. ## Implementation surface (this commit) `vendor/nova/src/neutron/circuit/relation.rs`: - `AllocatedFoldedInstance::X`: `AllocatedNum<E::Scalar>` → `Vec<AllocatedNum<E::Scalar>>` (Path W). - `alloc(cs, inst)`: per-element from `inst.X.iter()` for `Some`; length-1 Vec of `AllocatedNum::alloc(... || Ok(ZERO))?` for `None` (alloc-None length-1 fix; restores byte-equivalence with prior single-AllocatedNum at outer base). - `default(cs, num_io)`: NEW signature with `num_io: usize` parameter. Body uses `T.clone()` per Path Y / Corrigendum microsoft#4 to share T's `alloc_zero`-bound variable into every X[i]. - `default_with_lookup_k(cs, num_io, k)`: same pattern. - `absorb_in_ro`: per-element X loop matching native `for x in &self.X { ro.absorb(x) }`. - `fold`: γ.1 fail-close at top of body returns `SynthesisError::Unsatisfiable("...self.X.len() != 1...§1.6...")` on `self.X.len() != 1`. Existing single-scalar fold algebra preserved at N==1, wrapped as length-1 Vec. - `conditionally_select`: per-element matched-shape select with length-mismatch fail-close. - STAGE 0 test module: 0a (NeutronAugmentedCircuit num_io==1 byte-equivalence — preserved); 0b (NEW direct-fixture num_io==2 byte-equivalence — Path W validation at non-trivial X-arity, exercises only absorb_in_ro); 0c (NEW γ.1 fold-arity fail-close negative test with twin-substring assertion); plus the NEW Path Y structural-binding test (`m_gh5_0_path_y_x_t_aliasing_binding`) asserting X[i].get_variable() == T.get_variable() across 5 cases × 3 engines = 15 invocations. Removed the Corrigendum-microsoft#1-era `m_gh5_0_alloc_rejects_x_arity_two` negative test (alloc no longer fail-closes on X.len() != 1). `vendor/nova/src/neutron/circuit/mod.rs`: - Single in-vendor call site of `AllocatedFoldedInstance::default` updated to pass `num_io: 1` per the augmented-circuit's structural invariant (`hash.inputize` once at line 431). `vendor/nova/src/neutron/circuit/lookup.rs`: - `MinimalSingleIOCircuit` introduced (test-only) to give the 4 pre-existing lookup-circuit tests a `num_io == 1` shape. Per Corrigendum microsoft#3 these tests STAY at single-IO; the `arity ≤ 1` workaround comment at the FS-replay site is now codified as the fold-arity invariant. - Tests re-shaped: `m6_in_circuit_per_table_c_binding_hard_rejects_corrupted_t_lookup`, `m6_in_circuit_verify_multi_table_matches_native_k2`, `stage_g_in_circuit_verify_with_lookup_matches_native`, `stage_i_pri_in_circuit_verify_multi_column_matches_native`. ## Test posture `cargo test --release --features lookup-fold -p nova-snark`: - **146 passed, 4 failed, 3 ignored** in 157.15s - 4 failures: all Cluster A (`MinimalSingleIOCircuit` + hyperkzg CK sizing mismatch — `assertion failed: ck.ck.len() >= v.len()`). Separate M.GH5.0b scope per Halpert's triage. `cargo check --tests --features lookup-fold`: clean. ## What this commit does NOT include - Cluster A fix (CK-floor sizing in the 4 lookup-circuit tests' fixtures). M.GH5.0b dispatch covers it. - UPDATE_EXPECT on `pp_digest` literals. The literals at `vendor/nova/src/neutron/mod.rs:553/558/563` already coincide with the post-Path-Y digest (LookupShape envelope refresh at `048ac29` happens to align with Path Y's clone-of-T shape). No refresh needed. ## Audit-trail Five Halpert dispatches across Corrigenda microsoft#1 → microsoft#4-A. Each ruling documented in pin §1.4 with original text preserved per override discipline. Path-W → Path-Y refinement chain demonstrates Core Principle 7 in action: simplicity arguments rejected at every step where a more-general or more-soundness-bearing option was available. Reviewed by `@nw-cryptographer` (Halpert) per the GH-microsoft#5 per-step pre-commit review pattern (5 dispatches, 5 ratifications). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
marcus-sa
added a commit
to marcus-sa/Nova
that referenced
this pull request
May 9, 2026
…l≥2 fixture fixes Closes the 4 lookup-circuit test failures that were the only remaining Cluster A residue after M.GH5.0 (Path W + γ.1 + Path Y) closed at `fc0de8e`. Two structurally-distinct fixture fixes, applied together because they share a single fixture file and were exposed by the same M.GH5.0a-fix-up regression chain: ## M.GH5.0b — CK-floor sizing fix Per Halpert's third-dispatch Cluster A diagnosis: the M.GH5.0a fix-up re-shaped the 4 affected tests to use `MinimalSingleIOCircuit` (`num_cons=0`, `num_vars=1`, `num_io=1`), but kept the upstream CK construction `R1CSShape::commitment_key(&[&shape], &[&*S::ck_floor()])` which gives `max(0, 1, 0) = 1`. The tests then commit lookup tables of size 16, panicking at `hyperkzg.rs:567` with `assertion failed: ck.ck.len() >= v.len()`. Fix: replace the CK construction with explicit `setup` at size 16: ```rust let ck = <E as Engine>::CE::setup(b"lookup_test", 16).expect(...); ``` Applied uniformly across: - `m6_in_circuit_per_table_c_binding_hard_rejects_corrupted_t_lookup` - `m6_in_circuit_verify_multi_table_matches_native_k2` - `stage_g_in_circuit_verify_with_lookup_matches_native` - `stage_i_pri_in_circuit_verify_multi_column_matches_native` ## M.GH5.0c — `ell >= 2` α-fixture enrichment per Corrigendum microsoft#5 After M.GH5.0b unblocked the CK panic, the same 4 tests panicked at a STRUCTURALLY DISTINCT site: `vendor/nova/src/spartan/polys/power.rs:67` (`self.t_pow[0]` on empty Vec) reached via `nifs.rs:646` (`PowPolynomial::new(&tau, S.ell).split_evals(S.left, S.right)`). Root cause: `S.ell = num_cons.next_power_of_two().log_2()` per `relation.rs:492`. With `MinimalSingleIOCircuit`'s `num_cons == 0`, `ell == 0`, `t_pow.len() == 0`, indexing panics. The R1CS-side eq machinery requires `ell >= 2` to be panic-safe (at `ell == 1`, `right[1]` indexes a length-1 Vec; verified by reading `power.rs:62-86`). Halpert's fourth-dispatch ruling (Corrigendum microsoft#5, just landed in pin §1.4): `num_cons == 0` was INCIDENTAL to M.GH5.0a's narrowing, NOT pin-load-bearing. The pin's binding invariants on the fixture are `num_io == 1` (§1.6 anchor + Corrigendum microsoft#3 fold-arity) and `default()` body's variable-aliasing (Corrigendum microsoft#4 / microsoft#4-A) — neither is touched by enriching `num_cons`. Fix: emit ≥3 enforced constraints (`0 * 0 == 0` triples on freshly- allocated zero witnesses) so `next_power_of_two(num_cons) == 4` and `ell == 2`. Constraints are content-irrelevant — they exist only to size the R1CS hypercube. The fixture remains single-IO and trivially satisfiable across both `ShapeCS` (shape extraction) and `SatisfyingAssignment` (witness materialisation). Applied 4 dummy constraints (`z_0 == 0` through `z_3 == 0`) in `MinimalSingleIOCircuit::synthesize`. Each of the 4 affected tests now asserts both `shape.num_io == 1` AND `shape.num_cons >= 3` adjacent, with twin-substring `"ell >= 2"` AND `"Corrigendum microsoft#5"` per pin §3.5 discipline. ## Why these are fixture-side fixes, not soundness-class Halpert's third-dispatch Cluster A diagnosis: "The lookup verifier's algebra is unchanged; the tests cannot reach the algebra under their current fixture because the CK construction panics before any prove/verify runs. No constraint family is silently mis-shaped; nothing has been elevated to a different soundness reduction." Same applies to M.GH5.0c — `ell == 0` is a structural-shape underflow, not a constraint-system soundness gap. The pin's algebraic content (§1.4 absorption order, §1.5 soundness reduction, §1.6 single-IO anchor) is unchanged. Only the fixture's under-narrowing is corrected. ## Test posture `cargo test --release --features lookup-fold -p nova-snark`: - **150 passed, 0 failed, 3 ignored** in 88.51s. - All previously-failing Cluster A tests GREEN. - All M.GH5.0 STAGE 0 tests (0a/0b/0c + binding) still GREEN. - All `test_pp_digest` (3 engines) still GREEN — `TrivialCircuit`- shaped, not affected by `MinimalSingleIOCircuit` enrichment. - All IVC and recursive-circuit tests still GREEN. `cargo check --tests --features lookup-fold`: clean. `UPDATE_EXPECT=1` not needed — `test_pp_digest` baselines unchanged because the test uses `TrivialCircuit::default()`, not `MinimalSingleIOCircuit`. Halpert's hedged prediction ("likely needs refresh") was correctly cautious; the actual outcome is cleaner. ## Audit-trail - M.GH5.0a fix-up (uncommitted in working tree until this commit) re-shaped 4 tests to `MinimalSingleIOCircuit` per Corrigendum microsoft#1's `num_io == 1` invariant. - M.GH5.0b dispatch identified the CK-floor regression that the M.GH5.0a fix-up surfaced. - Halpert's fourth dispatch authored Corrigendum microsoft#5 ratifying α-fixture enrichment with `ell >= 2` precondition stated. - This commit lands both fixes together (M.GH5.0b CK + M.GH5.0c α-enrichment) plus the M.GH5.0a `MinimalSingleIOCircuit` introduction itself, since all three are scoped to the same fixture file and form a single coherent regression-fix unit. Reviewed by `@nw-cryptographer` (Halpert) per the GH-microsoft#5 per-step pre-commit review pattern (third-dispatch Cluster A diagnosis + fourth-dispatch Corrigendum microsoft#5 ratification). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
marcus-sa
added a commit
to marcus-sa/Nova
that referenced
this pull request
May 9, 2026
… §5.5 row M.GH5.1
- src/neutron/mod.rs: pub mod lookup_sumcheck (was pub(crate))
- src/neutron/nifs.rs: pub on NIFS::{poly, poly_lookup, comm_E, comm_inv_w, comm_inv_t}
(was pub(crate); added missing-docs comments per vendor #![deny(missing_docs)])
Closes (W6) prerequisite for M.GH5.6 off-circuit running-scalar
reference differential. Zero-algebra / zero-FS / zero-digest —
visibility surface only.
Roadmap: docs/feature/microsoftgh-5-augmented-circuit-wireup/deliver/roadmap.json row 01-02
Pin: docs/research/cryptography/microsoftgh-5-augmented-circuit-wireup-design-pin-2026-05-08.md §5.5 row M.GH5.1
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
marcus-sa
added a commit
to marcus-sa/Nova
that referenced
this pull request
May 9, 2026
…h Y extension to T_lookup_per_table - default_with_lookup_k: allocate T_lookup_zero = alloc_zero(...) once, clone across k slots; each T_lookup_per_table[j] inherits (0)·(0) = T_lookup_zero zero-binding constraint - Variable-identity binding test (extends M.GH5.0 STAGE 0 module) - pp_digest baselines unchanged (default_with_lookup_k is #[allow(dead_code)] until M.GH5.3 wires synthesize_base_case through this constructor; the production augmented circuit's R1CS shape is not affected at this milestone — Pallas/Bn256IPA/Secp256k1 expects all hold) Closes the IVC-anchor constraint-binding gap surfaced during M.GH5.2 review. Same class as Corrigendum microsoft#4's X-side fix; same precedent for test-shape adaptation. Halpert-ratified per Corrigendum microsoft#6. Test extension (m_gh5_0_path_y_x_t_aliasing_binding): + Cases (1, Some(2)) and (2, Some(2)) — k=2 production arity per ADR-0021 + Variable-identity binding: T_lookup_per_table[j].get_variable() == T_lookup_per_table[0].get_variable() for all j ∈ [1, k) — intra-Vec aliasing form (TestConstraintSystem does not support post-allocation witness mutation; Corrigendum microsoft#4-A precedent for adapted assertion) + Distinctness from T: T_lookup_per_table[0].get_variable() != T.get_variable() — confirms Halpert's recommended SEPARATE T_lookup_zero (not aliased to T) + Constraint-count floor: default_with_lookup_k MUST emit ≥ 6 constraints (default(num_io) baseline 5 + 1 from T_lookup_zero alloc_zero), strictly exceeding the default(num_io) baseline Pre/post numbers (TestConstraintSystem at num_io=1, k=2, Bn256EngineKZG): pre-fix: num_constraints=5, T_lookup_per_table[0]=Aux(5), T_lookup_per_table[1]=Aux(6) — distinct fresh aux per slot, ZERO new constraints (the gap Corrigendum microsoft#6 closes) post-fix: num_constraints=6, T_lookup_per_table[0]=Aux(5), T_lookup_per_table[1]=Aux(5) — shared T_lookup_zero, (0)·(0) = T_lookup_zero constraint enforced Adversary-side: TestConstraintSystem does not expose post-allocation witness mutation; per Corrigendum microsoft#4-A precedent the witness-injection negative test is a structural counterfactual under Path Y. The variable-identity assertion algebraically subsumes it: a malicious prover attempting T_lookup_per_table[j] = N ≠ 0 would attempt T_lookup_zero = N, rejected directly by alloc_zero's row at synthesis. Pin: docs/research/cryptography/microsoftgh-5-augmented-circuit-wireup-design-pin-2026-05-08.md §1.4 Corrigendum microsoft#6 Roadmap: docs/feature/microsoftgh-5-augmented-circuit-wireup/deliver/roadmap.json row 01-03 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
marcus-sa
added a commit
to marcus-sa/Nova
that referenced
this pull request
May 10, 2026
…p-fold wire-up Wires NeutronAugmentedCircuit::synthesize_non_base_case through verify_with_multi_table_lookup and synthesize_base_case through default_with_lookup_k under the lookup-fold cfg + runtime gate. Closes (W3) plumbing and (W4) confirmation per pin §1.4. Vendor-side surface: - NeutronAugmentedCircuitInputs: +public_bundles_multi_table field (Option<Vec<LookupPayloadPublicMultiTable<E>>>) per pin §3.1 - NeutronAugmentedCircuit struct: +shape_registry, +lookup_fold_k, +index_n_bits fields; with_lookup_fold(k, registry, bits) builder (#[allow(dead_code)] until M.GH5.4 inumbra-side wire-up) - alloc_with_k_hint: T_lookup_per_table allocation branches on inst.t_lookup() Some/None × k > 0 hint - synthesize_base_case: under #[cfg(feature = "lookup-fold")] dispatches to default_with_lookup_k(cs, 1, k) when lookup_fold_k > 0; else default(cs, 1) - synthesize_non_base_case: under same cfg dispatches to new private synthesize_non_base_case_lookup_fold method when lookup_fold_k > 0; else legacy nifs.verify - synthesize_non_base_case_lookup_fold: allocates chunk_index_in_z = U.X[0], shape_registry, AllocatedLookupNIFSMultiTable, per-bundle AllocatedLookupPayloadPublicMultiTable; invokes verify_with_multi_table_lookup; rebinds post-fold T_lookup_per_table via from_lookup_fold_output (no-constraint structural rewire) - AllocatedLookupPayloadPublicMultiTable::alloc helper Halpert ratification (2026-05-09 dispatch, all 6 questions RATIFY, High confidence): - Q1 Option B (cfg + runtime lookup_fold_k > 0 gate): selected per Principle 7 + ADR-0023 vendor-fork separability. lookup_fold_k is construction-time pinned and pp_digest-shape-bound; no downgrade attack possible. - Q2 Argument-order canonical, table_id-traversal mechanical (Vec iter preserves order at every fold depth). - Q3 lookup_fold_k as usize correct at M.GH5.3; per-position uniformity assertion deferred to M.GH5.4 per Auditor Obligation 10. - Q4 M.7 shape-registry assertion fires BEFORE pp_digest.absorb per pin §2.5 (vendor/nova/src/neutron/circuit/nifs.rs:689-698 direct verification). Dispatch text's "AFTER" formulation was a misstatement; STOP-AND-ASK NOT triggered. - Q5 (W4) Phase-1↔Phase-2 binding closed: clone() on AllocatedNum preserves Variable identity, so Phase-1 hash binding of U.T_lookup_per_table transitively binds Phase-2 verifier inputs. - Q6 from_lookup_fold_output no-constraint rewire is sound; (C)-binding at nifs.rs:872-897 takes the binding role at fold-depth ≥ 1 that alloc_zero plays at base case. Path Y / microsoft#4-A invariants are base-case-only. Test posture preserved at M.GH5.2 close baseline: - vendor --release --features lookup-fold: 152/0/7 - vendor --release (default): 80/0/6 - inumbra-spend-circuits: 87/0/9 lib + 4 RED scaffolds - inumbra-spend-harness: 13/0 - M.GH5.0 STAGE 0 + Corrigendum microsoft#4-A + Corrigendum microsoft#6 tests: pass - pp_digest baselines unchanged (vendor IVC tests on legacy path; refresh deferred to M.GH5.4 when inumbra-side wires with_lookup_fold(2, ...)) - Determinism verified across 2 consecutive runs. Pin: docs/research/cryptography/microsoftgh-5-augmented-circuit-wireup-design-pin-2026-05-08.md §3.1 + §3.2 + §3.4 + §5.1 + §5.5 row M.GH5.3 Roadmap: docs/feature/microsoftgh-5-augmented-circuit-wireup/deliver/roadmap.json row 01-04 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
marcus-sa
added a commit
to marcus-sa/Nova
that referenced
this pull request
May 11, 2026
… threads shape_registry to NeutronAugmentedCircuit::new Per pin §5.5 row M.GH5.4 (post-Corrigendum-microsoft#8 reverted scope) sub- deliverable 2: - Extend `PublicParams::setup` and `setup_with_ptau_dir` under `feature = "lookup-fold"` to accept `(shape_registry: Vec<E1::Scalar>, lookup_fold_k: usize, index_n_bits: usize)`. Threaded to the shape- derivation `NeutronAugmentedCircuit::new` call via `with_lookup_fold(...)`. Non-`lookup-fold` builds keep the pre-M.GH5.4 signature (vendor examples / benches build unchanged). - Store the registry triple on `PublicParams` under `lookup-fold`, `#[serde(skip)]`-gated so the bincode encoding (and therefore `pp_digest`) is byte-equivalent to pre-M.GH5.4 at the default `(vec![], 0, 0)` state. Vendor-internal `test_pp_digest` baselines do NOT refresh — confirmed empirically: 152/0/7 release sweep matches pre-M.GH5.4 baseline byte-for-byte. - `RecursiveSNARK::new` (base case) and `RecursiveSNARK::prove_step` read the triple from `pp` and chain `with_lookup_fold(pp.lookup_fold_k, &pp.shape_registry, pp.index_n_bits)` on each `NeutronAugmentedCircuit::new`. This closes the four invocation sites the pin §3.1 binding requires (the augmented-circuit shape-derivation site + the prove-step site must emit byte-equivalent R1CS, which they do because both threads the same triple from `pp`). - Lift `#[allow(dead_code)] until M.GH5.4` on `NeutronAugmentedCircuit::with_lookup_fold` (vendor `circuit/mod.rs:268`). The `with_multi_table_bundles` annotation (`circuit/mod.rs:139`) stays — its per-step consumer wires up at M.GH5.5 (the inumbra-side fold-of-N happy-path differential). - Vendor-internal `TrivialCircuit` / `CubicCircuit` test sites updated to pass `(vec![], 0, 0)` under `lookup-fold` (the default lookup- fold-OFF state); shape and `pp_digest` byte-equivalent to pre-M.GH5.4. Sub-deliverable 1 (inumbra-side consumer wire-up) is a no-op at this milestone: there is no inumbra-side consumer of `neutron::PublicParams::setup` yet (wrap.rs is on `nova_snark::nova::*` per Corrigendum microsoft#8; will stay through M.GH5.9; Stage K migration dispatched as separate GH-microsoft#7). `build_chunk_step_registry` (M.10 / `shape_registry.rs:224`) is ready to be invoked by M.GH5.5 when the inumbra-side fold-of-N differential dispatches against the augmented-circuit IVC. Auditor Obligation 10 confirmed by construction at `shape_registry.rs:347`: `vec![merged_mc, chunk_mc]` (length 2) inside the `0..NUM_CHUNK_POSITIONS=16` loop — k=2 uniform across all 16 chunked-Strauss-Shamir positions per ADR-0021. Test results (release-mode per `.claude/rules/testing.md`): - vendor `cargo test --release -p nova-snark --features lookup-fold`: 152/0/7 (matches pre-M.GH5.4 baseline; no `pp_digest` refresh needed — the `#[serde(skip)]` design preserves the bincode encoding). - inumbra-spend-circuits lib: 87/0/9 + 4 RED scaffolds (baseline). - inumbra-spend-harness: 13/0 (baseline). - M.GH5.0 STAGE 0 + Corrigendum microsoft#4-A + Corrigendum microsoft#6 tests pass. Closes (W4) plumbing per pin §5.5. Wire-up consumer at M.GH5.5. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
marcus-sa
added a commit
to marcus-sa/Nova
that referenced
this pull request
May 11, 2026
…e-tag — Corrigendum microsoft#9 Re-tag #[allow(dead_code)] from "until M.GH5.4" to "until GH-microsoft#7" per Halpert Corrigendum microsoft#9 (2026-05-10). The chunk_index_in_z routing question carry-forwards to GH-microsoft#7 (Stage K); inumbra-side wiring of RecursiveSNARK::prove_step through with_multi_table_bundles is GH-microsoft#7 scope, not M.GH5.4 / M.GH5.5. Pin: docs/research/cryptography/microsoftgh-5-augmented-circuit-wireup-design-pin-2026-05-08.md §1.4 Corrigendum microsoft#9 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
marcus-sa
added a commit
to marcus-sa/Nova
that referenced
this pull request
May 11, 2026
…hape differential — Corrigendum microsoft#9 Per Pin Corrigendum microsoft#9 (2026-05-10) §5.5 row M.GH5.5 (re-scoped from RecursiveSNARK-IVC to direct-NIFS pattern after the 2026-05-10 dispatch verified that `RecursiveSNARK::prove_step` calls `NIFS::prove` not `prove_with_multi_table_lookup`, AND `with_multi_table_bundles` has zero callers, AND `chunk_index_in_z = U.X[0]` conflicts with standard IVC output-hash binding-via-hash semantics — the chunk_index_in_z routing question carries forward to GH-microsoft#7 / Stage K). This milestone delivers the FIRST end-to-end exercise of the augmented- circuit lookup-fold path at fold-depth ≥ 4 with multi-table k=2 absent- table coverage. M.GH5.0 STAGE 0 was 2-step; M.11 was 4-step but native- only (no augmented-circuit synthesis); M.GH5.5 combines them. ## What this commit adds Single new vendor-internal test at `vendor/nova/src/neutron/circuit/relation.rs::stage0_byte_equivalence_tests::m_gh5_5_fold_of_n_augmented_circuit_shape_differential` (lines 1785-2241; +535 lines into the existing module). The test drives 4 fold steps via direct `NIFS::prove_with_multi_table_lookup` + `verify_with_multi_table_lookup` (M.11 + M.GH5.0 STAGE 0 pattern), with k=2 multi-table absent-table shape (T_2 absent at steps 1 and 4, queried at steps 2 and 3 — M.11 §D.1). The R1CS shape comes from `NeutronAugmentedCircuit` so `num_io == 1` (production-shape invariant per pin §1.6 anchor). At each fold step ≥ 1 the test asserts: - (a) `cs.is_satisfied() == true` on in-circuit `absorb_in_ro` synthesis. - (b) `T_lookup_per_table` is `Some(&[..])` of length k=2 with at least one non-zero entry (empirically validates that the (W1) binding-via- hash extension is being exercised — not the trivial all-zero case). - (c) byte-equivalent native ↔ in-circuit hash output (the §1.4 absorption-order invariant survives at fold-depth ≥ 4). Plus a defensive cross-step audit assertion that T_1's running scalar visibly evolves across consecutive fold steps (T_1 is queried at every step with random per-step indices; all-equal T_1 across 4 steps would indicate the (W1) running-scalar pipeline silently dropped state). ## Discharges per pin §5.3 microsoft#1 - (W1) binding-via-hash extension: T_lookup_per_table absorption in `U.absorb_in_ro` AT fold-depth ≥ 1 with non-zero entries — assertion (b) at every step + assertion (c) ensures the per-table running scalar participates in the hash that becomes `u.X[0]`. - (W2) cross-table absorption order: T_lookup_per_table absorbed in `table_id`-canonical order; mismatched ordering between native `FoldedInstance::absorb_in_ro2` and in-circuit `AllocatedFoldedInstance::absorb_in_ro` would falsify (c) at the first fold step. - (W3) fold-depth ≥ 1 propagation: 4 sequential fold steps, with the running U from step n+1 carrying the cumulative T_lookup from steps ≤ n; the cross-step audit assertion confirms running-scalar evolution. ## Why this lives in the vendor (not in inumbra-spend-harness) The dispatch's "no vendor edits expected" expectation was unverified. Verify-don't-assume on the vendor public-API surface: - `mod circuit;` at `vendor/nova/src/neutron/mod.rs:25` is private (no `pub` modifier). `AllocatedFoldedInstance`, `circuit_absorb_squeeze`, `native_absorb_squeeze`, `NeutronAugmentedCircuit`, and `NeutronAugmentedCircuitInputs` are all vendor-internal. - `pub use` re-exports of `AllocatedFoldedInstance` are absent (verified via Grep across `vendor/nova/src/`). - The byte-equivalence assertion REQUIRES augmented-circuit synthesis through `AllocatedFoldedInstance` mirroring + `RO2Circuit` squeeze, which is structurally vendor-internal. The Halpert-authored M.11 file header established the precedent (Finding 1 ruling §1.4) of deferring vendor visibility bumps until consumers exist. The natural sequencing for M.GH5.5 — augmented-circuit- shape byte-equivalence at fold-depth ≥ 4 — is to extend the vendor- internal STAGE 0 fixture (which already has the helpers and the 2-step template) rather than introduce a new vendor public-API visibility surface that has no consumer outside this single test. ## Empirical signals - All four fold steps GREEN at first run; assertions (a), (b), (c) hold at every step. - T_lookup_per_table is non-zero at every fold-depth ≥ 1 (T_1's running scalar accumulates because T_1 is queried at every step with random per-step indices; T_2's running scalar accumulates from the n_j / r_logup_j contribution even on the absent-shape side). - Native ↔ in-circuit hash output byte-equivalent at every fold step (the §1.4 absorption-order pin survives at fold-depth ≥ 4). - Cross-step audit: T_1's running scalar visibly evolves across consecutive fold steps. ## Test results - New test: `cargo test --release --features lookup-fold --lib m_gh5_5_fold_of_n_augmented_circuit_shape_differential` → 1 passed, 0 failed. - Vendor `--release --features lookup-fold` baseline: 152/0/7 → 153/0/7 (+1 from this test). - inumbra-spend-circuits `--release --lib`: 87/0/9 (preserved). - inumbra-spend-harness `--release`: 13/0 (preserved; M.GH5.5 lives in vendor, not harness). ## Out of scope (per Corrigendum microsoft#9) - `RecursiveSNARK::prove_step` IVC integration (carry-forward to GH-microsoft#7). - chunk_index_in_z routing resolution (carry-forward to GH-microsoft#7 / Stage K). - Off-circuit running-scalar reference differential (M.GH5.6). - Negative-test discharge (M.GH5.7 / M.GH5.8). - Inumbra-side `pp_digest` baseline refresh (wrap pipeline isn't migrating).
marcus-sa
added a commit
to marcus-sa/Nova
that referenced
this pull request
May 11, 2026
…nobs feature + corrupt_t_lookup_at_index knob + AO 17 visibility bump Per design pin Corrigendum microsoft#10 (Halpert, 2026-05-10) and Corrigendum microsoft#11 (Halpert, 2026-05-10), this commit lands the vendor-side surface for M.GH5.7's three negative tests (cryptographer-gated soundness gating). Cargo.toml — adds `test-debug-knobs = []` opt-in feature flag. Strict additive; production builds without `test-debug-knobs` remain byte- identical to vendor HEAD. src/neutron/circuit/mod.rs: - `NeutronAugmentedCircuitInputs` gains `#[cfg(any(test, feature = "test-debug-knobs"))] pub corrupt_t_lookup_at_index: Option<(usize, E::Scalar)>` field + `with_corrupt_t_lookup_at_index` builder method. - Corruption injection at the augmented-circuit allocation site so the IN-CIRCUIT `t_lookup_running_per_table[idx]` allocation is perturbed AFTER honest U.T_lookup_per_table allocation but BEFORE feeding into `verify_with_multi_table_lookup` (Pin §3.5 shape (a) + Corrigendum microsoft#10 Q2 dispatch shape). - `let mut U` cfg-split so the production build (`lookup-fold` without `test-debug-knobs`) does not trip `#[deny(unused_mut)]`. src/neutron/mod.rs — re-exports `NeutronAugmentedCircuit`, `NeutronAugmentedCircuitInputs`, `AllocatedNIFS`, `AllocatedFoldedInstance`, `AllocatedLookupNIFSMultiTable`, `AllocatedLookupPayloadPublicMultiTable`, `AllocatedNonnativeR1CSInstance` so M.GH5.7's harness-side tests can construct fixtures via direct vendor-internal types per Pin §5.2 + Corrigendum microsoft#10 Q2 Option A.2. src/neutron/nifs.rs — `pub fn prove_with_multi_table_lookup_inner` visibility bump (Auditor Obligation 17 — byte-equivalence verification of synthetic-Some(vec![ZERO; k]) running U vs default-None running U). Lemma α-Q1 (Corrigendum microsoft#10) is exercised by the harness-side AO 17 smoke test asserting prove-call equivalence. src/neutron/relation.rs — exposes `Structure::shape()`, `FoldedInstance::comm_W()`, `FoldedInstance::comm_E()` accessors required by harness-side fixture construction. All `pub` visibility under existing crate-public types; no new layout / no soundness implications. Soundness disposition (Corrigendum microsoft#11): test (i) rejects via dual-path (Path A §1.5 binding-via-hash, Path B §3.3 clone → (C)-binding); per declaration-order at vendor HEAD, Path B declares first and is the asserted twin-substring. AO 9 / (W1)-direct discharged via end-to-end corruption-detection (both paths reject). Pin §5.3 microsoft#3, microsoft#4, microsoft#5 discharged. Pin §D.4 microsoft#5, microsoft#3' discharged. Auditor Obligations 9, 12, 14, 17 status: discharged at vendor HEAD. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
marcus-sa
added a commit
to marcus-sa/Nova
that referenced
this pull request
May 12, 2026
…commitment Vec extension
Widens `FoldedInstance::{comm_L, comm_ts, comm_inv_w, comm_inv_t}` at
`vendor/nova/src/neutron/relation.rs:246-264` from scalar
`Option<Commitment<E>>` to per-table `Option<Vec<Commitment<E>>>`,
mirroring the already-landed `T_lookup: Option<Vec<E::Scalar>>` extension
at line 265 (GH-microsoft#2 M.2 structural mirror). Lifts the per-`X` scalar
`fold_one` body at `relation.rs:802-826` to a per-`j` loop running the
linear-combination `comm_X_j_fold = (1 - r_b) * comm_X_j_running + r_b *
payload_per_table[j].comm_X` independently for each
`(X, j) ∈ {L, ts, inv_w, inv_t} × {0, ..., k-1}` under common `r_b`.
This is a **HARD PREREQUISITE** for M.GH7.0 — without the per-table Vec
extension, the §1.2(b)/(c) Spartan bridge-reduction has no per-table
running commitments to consume.
## Soundness sketch (Corrigendum microsoft#6 §1.3 lines 166-241)
FoldedInstance-level per-table-independent-fold-under-common-`r_b`
binding reduces to four paper-grounded primitives composed:
1. **PCS binding at each `(X, j)` pair independently** — Pedersen
homomorphism (1991) + KZG eprint 2010/096.
2. **RO2 collision-resistance over `table_id`-canonical absorption
ordering** — Fischlin 2005 / Lasso §2.3 FS analysis. Per-step NIFS
absorbs `comm_inv_w_vec[0..k]` then `comm_inv_t_vec[0..k]` in
canonical order at `nifs.rs:1497-1556` BEFORE `r_b` is squeezed; the
FoldedInstance-level fold preserves the order.
3. **No cross-`j` term under common `r_b`** — the fold body
`comm_X_j_fold = (1 - r_b) * comm_X_j_1 + r_b * comm_X_j_2` is a
linear combination over a SINGLE table's commitments at each `j`
(Falsifier B verified-absent at the algebra).
4. **Path β per-step binding composes into FoldedInstance level** —
GH-microsoft#2 Path β at `c1-beta-multi-table-fold-design-pin-2026-05-08.md`
§A.2.4 (per-step ratified) extended upward via Nova binding-by-hash
composition (eprint 2021/370 v3 §4).
Both falsifiers verified-absent at vendor HEAD per Corrigendum microsoft#6: (A)
per-step NIFS-message Vec-typed inverse commitments persist across
steps at `nifs.rs:256-260`; (B) primitive 3's per-`j` independence is
structural at the algebra level. Confidence promoted Medium → Medium-
High per §6.1 row M.GH7.0a.
## Implementation
- `relation.rs:246-264`: four `comm_X` fields widened to
`Option<Vec<Commitment<E>>>`. `T_lookup_per_table` at line 265
unchanged (already Vec-typed since GH-microsoft#2 M.2).
- `relation.rs:fold_with_lookup`: signature change from singular
`payload: &LookupPayload<E>` to per-table `payload_per_table:
&[LookupPayload<E>]`; body lifted from per-`X` scalar to per-`(X, j)`
Vec loop. Length-mismatch fails-closed with `NovaError::InvalidStructure`.
- `relation.rs:fold` (R1CS-only): per-table Vecs passed through via
`.clone()` (Vec is not `Copy`).
- `nifs.rs:prove_with_multi_table_lookup_inner` + `verify_with_multi_table_lookup`:
replaced the singular `effective_payload = bundles[0]` collapse (k=1
byte-equivalence routing per pre-M.GH7.0a M.3 commentary at
`nifs.rs:2039-2045`) with per-table construction in `table_id`-canonical
order. K=1 single-table degenerates byte-identically via
`std::slice::from_ref(&effective_payload)`.
- Single-table callers (`prove_with_lookup`, `verify_with_lookup`,
`prove_with_multi_column_lookup`, `verify_with_multi_column_lookup`):
wrap singular `effective_payload` with `std::slice::from_ref` at the
fold-with-lookup call site.
**No `AllocatedFoldedInstance` extension needed** per Corrigendum microsoft#1 —
binding-via-hash at GH-microsoft#5 (W1) carries the four `comm_X` fields through
`u.X[0]`; `AllocatedFoldedInstance` at `circuit/relation.rs:26-56` does
not hold the four commitments and does not need to.
## Tests
Three tests added to `neutron::relation::tests` module
(`vendor/nova/src/neutron/relation.rs`):
- `test_folded_instance_per_table_vec_extension_binding` — k=2 single
fold from outer base; asserts `FoldedInstance::{comm_L, comm_ts,
comm_inv_w, comm_inv_t}` are populated as `Some(Vec<Commitment<E>>)`
of length 2; per-`j` outer-base body `comm_X_j_fold = r_b *
fresh_per_table[j].comm_X`.
- `fold_with_lookup_per_table_no_cross_j_interference` — Falsifier B
negative test: corrupting `fresh_per_table[1].comm_X` for each
`X ∈ {L, ts, inv_w, inv_t}` leaves `folded.comm_X_per_table[0]`
unchanged (Corrigendum microsoft#6 primitive 3). Includes counter-check that
`comm_X_per_table[1]` DOES change (homomorphic propagation of the
corrupted fresh input).
- `fold_with_lookup_per_table_differential_against_reference_1000_iter`
— 1000-iter ChaCha20Rng-seeded differential against the off-circuit
reference formula per Gadget contract (`.claude/rules/cryptography.md`
≥ 1000-iter behavioural earned-trust threshold). Single fixed seed
`0xC1BE_5BAD_C0DE_700A` for US-05 reviewer-reproducibility. Runs
~7.6s in release mode.
Pre-existing `fold_with_lookup_threads_per_table_running_scalars_k2`
test (GH-microsoft#2 M.2 regression) updated to pass per-table payload slice
through the new signature; semantics unchanged.
## Verification
- `cargo check -p nova-snark --features lookup-fold --all-targets
--release`: clean.
- `cargo check -p nova-snark --all-targets --release` (without
lookup-fold): clean — the widening is fully `#[cfg(feature =
"lookup-fold")]` gated; non-lookup-fold builds unaffected.
- `cargo test -p nova-snark --features lookup-fold --release`: 156
passed, 7 ignored, 0 failures. Includes all 5 tests in
`neutron::relation::tests`.
- `cargo test --workspace --release`: clean except 4 pre-existing
`arity_envelope_acceptance.rs` RED scaffold `unimplemented!()` panics
(verified pre-existing via `git stash` cross-check; unrelated to
M.GH7.0a; downstream feature work).
- `cargo test -p inumbra-spend-harness --release --test
m11_fold_of_four_absent_table_differential`: 2 passed (1000-iter
fold-of-four 21min).
- `cargo test -p inumbra-spend-harness --release --test
m_gh5_6_running_scalar_reference_differential`: 1 passed (1000-iter
running-scalar 6min).
- `cargo test -p inumbra-spend-harness --release --test
m_gh5_7_negative_test_triple`: 4 passed.
- `cargo test -p inumbra-spend-harness --release --test
multi_table_lookup_fold_differential --test
lookup_fold_differential`: 5 passed.
Step-ID: 01-01
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
marcus-sa
added a commit
to marcus-sa/Nova
that referenced
this pull request
May 15, 2026
… prove_step_with_lookup_fold sibling (positive-path; Corrigendum microsoft#14 + sub-ratifications microsoft#1+microsoft#2) Corrigendum microsoft#14 re-typed disposition (option β sibling method) for the M.GH7.3 trait + sibling-method + RecursiveSNARK field surface, refined by 2026-05-12 sub-ratification microsoft#1 (dropped decorative `r_logup_per_table` argument from trait method per r-independence audit at nifs.rs:202-227 + lookup_sumcheck.rs:146-221) and sub-ratification microsoft#2 (extended `PublicParams::setup` signature with `Option<LookupShape<E>>` parameter prerequisite + `running_lws` field on `RecursiveSNARK`). Positive-path implementation only; negative-test triple deferred to M.GH7.3b per the 2026-05-12 Option α split (Halpert-authoring pending). Vendor-side authoring: - `PublicParams::setup` + `setup_with_ptau_dir` (mod.rs:240-296, :360-418): extended `#[cfg(feature = "lookup-fold")]` variants with trailing `lookup_shape: Option<LookupShape<E1>>` parameter; body match-branch `Some → Structure::new_with_lookups(&r1cs_shape, shape)` vs `None → Structure::new(&r1cs_shape)`. Cascade: 6 vendor-internal callsites in mod.rs test module (test_pp_digest_with × 1, test_ivc_* × 3, test_setup × 2) supply `None`; 2 callsites in compressed_snark.rs STAGE 0 (HyperKZG + IPA-PC trivial-circuit) supply `None`. Non-lookup-fold cfg variants UNCHANGED. - `RecursiveSNARK::running_lws: Vec<LookupRunningWitness<E1>>` field (mod.rs:484-533): added under `#[cfg(feature = "lookup-fold")]`, bootstrap at `RecursiveSNARK::new` from `LookupRunningWitness::default(&shape)` per registered `multi_column_tables[j]` when `pp.lookup_fold_k > 0`; `vec![]` otherwise. `LookupRunningWitness<E>` is `Serialize, Deserialize` per relation.rs:409, so the existing `#[derive(Serialize, Deserialize)]` on `RecursiveSNARK` typechecks unchanged (sub-ratification microsoft#2 STOP-AND-ASK gate microsoft#3 clean). - `LookupStepCircuit<E: Engine>: StepCircuit<E::Scalar>` trait (mod.rs:838-913): two methods, NO `r_logup_per_table` argument per sub-ratification microsoft#1 (gate microsoft#1 dissolved by the r-independence audit). `per_table_bundles_at_step(&self, ck, i, prior_running_lws) -> Result< Vec<PerTableBundle<E>>, NovaError>` constructs fully-committed prover-side per-table bundles in `table_id`-canonical order; `public_bundles(bundles) -> Vec<LookupPayloadPublicMultiTable<E>>` projects to verifier-public hints. Trait dispatch accepts associated function without `&self` parameter — fallback free-function `public_bundles_of<E: Engine>(...)` not needed at M.GH7.3a (gate microsoft#4 clean). - `RecursiveSNARK::prove_step_with_lookup_fold` sibling method (mod.rs:914-1013): separate `#[cfg(feature = "lookup-fold")] impl<E1, E2, C> ... where C: StepCircuit + LookupStepCircuit<E1>` block, structurally parallel to the existing `impl ... where C: StepCircuit` block at line 514. Body per pin §5.5 row M.GH7.3a + sub-ratification microsoft#1: bootstrap at i=0 mirrors `prove_step:580-583` byte-identically; otherwise (i) construct bundles via `c.per_table_bundles_at_step(&pp.ck, self.i, &self.running_lws)`; (ii) invoke `NIFS::prove_with_multi_table_lookup` with the 9-arg public wrapper at nifs.rs:1301-1316; (iii) project bundles via `C::public_bundles(&bundles)`; (iv) build `NeutronAugmentedCircuitInputs` byte-identical to `prove_step:599-624` with `.with_multi_table_bundles(Some(public_bundles))`; (v) synthesise augmented circuit byte-identical to `prove_step:615-624` with same `with_lookup_fold` threading; (vi) update `self.{r_U, r_W, l_u, l_w, zi, ri, running_lws, i}`. Existing `prove_step` at mod.rs:578-637 is UNCHANGED (preserves vendor upstream-tracking + classical-Nova consumers + STAGE 0 non-lookup path per Corrigendum microsoft#13). Acceptance test (mod.rs `#[cfg(test)] mod tests`): `m_gh7_3a_prove_step_with_lookup_fold_sibling_threads_running_lws_witness_alloc_preserved_positive_path` — N=3 honest sibling-method invocations (bootstrap + 2 real folds) against a trivial `LookupStepCircuit` fixture mirroring the M.11 §D.1 absent-table pattern at vendor-test-fixture scope (does NOT depend on inumbra-side `build_canonical_lookup_shape` per gate microsoft#2 / STOP-AND-ASK microsoft#2 clean — the fixture inlines the absent-bundle constructor from m11_fold_of_four_absent_table_differential.rs:466-525). Assertions: 1. `prove_step_with_lookup_fold` returns Ok for each of 3 invocations. 2. `r_U.T_lookup` accumulates from `None` (outer base) to `Some(Vec)` of length K after fold microsoft#1, preserved after fold microsoft#2 (§1.2 algebra). 3. **Byte-equal threading**: at fold microsoft#2's `per_table_bundles_at_step`, the observed `prior_running_lws` is byte-equal to fold microsoft#1's `next_running_lws` output — the load-bearing `self.running_lws = next_running_lws;` field-mutation contract. 4. `prove_step` (non-lookup) regression invariant clean — captured by the `test_pp_digest` + `test_ivc_*` + `test_setup` tests continuing to pass byte-identically (verified at this commit). STOP-AND-ASK verdict (PREPARE-level, per pin §5.5 row M.GH7.3a): - Gate microsoft#1 (`pp_digest` byte-divergence at `lookup_fold_k = 0` + `lookup_shape = None`): **CLEAN**. `test_pp_digest_with` at mod.rs:830, :834, :838 pass unchanged with `None` appended. - Gate microsoft#2 (vendor-test fixture cannot construct minimal `LookupShape<E>`): **CLEAN**. The fixture inlines a one-off absent-bundle constructor at vendor-test-fixture scope (single-column-degenerate path: `multi_column_tables[0].columns = vec![]`, `payload.comm_values = vec![]` per nifs.rs:1404-1411 bundle-validation). - Gate microsoft#3 (`running_lws` field surfaces serialisation incompatibility): **CLEAN**. `LookupRunningWitness<E>` is `Serialize, Deserialize` per relation.rs:409; existing `#[derive(Serialize, Deserialize)]` on `RecursiveSNARK` typechecks unchanged. - Gate microsoft#4 (`LookupStepCircuit::public_bundles` ergonomic issues): **CLEAN**. Rust trait dispatch accepts the associated function without `&self` parameter — fallback to free-function lift not needed. - Gate microsoft#5 (production-shape `LookupStepCircuit` impl complication): N/A at M.GH7.3a (deferred to M.GH7.5a wrap-pipeline retarget). Vendor-test verdict (release-mode per `.claude/rules/testing.md`): - `cargo test --release -p nova-snark --features lookup-fold --lib neutron::tests`: 6 passed; 0 failed; 0 ignored — includes `test_pp_digest` (3 expect-tests at mod.rs:830-841), `test_ivc_trivial`, `test_ivc_base`, `test_ivc_nontrivial_neutron`, `test_setup`, AND `m_gh7_3a_*` acceptance test. Inumbra-side cascade (one-line cosmetic, supplied at superproject pointer-bump commit): `tests/gh7_stage_k_compressor.rs:149, :270` get trailing `None,` appended (STAGE 0 stays on non-lookup `prove_step` path per Corrigendum microsoft#13; the `Some(build_canonical_lookup_shape::<...>)` flip lands at M.GH7.5a per Corrigendum microsoft#5). Discharges AO 19 PARTIALLY (positive-path routing; full discharge at M.GH7.3b negative-test triple, cryptographer-authoring-pending). Negative-test triple deferred to M.GH7.3b per 2026-05-12 Option α split. See pin §5.5 row M.GH7.3a + §3.1 + Corrigendum microsoft#14 + sub-ratifications microsoft#1 + microsoft#2 in §0; roadmap step 02-02a. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
marcus-sa
added a commit
to marcus-sa/Nova
that referenced
this pull request
May 15, 2026
…ld negative-test triple per Corrigendum microsoft#15 + sub-ratification (Constraint hygiene §70-78 discharge; AO 19 FULL) Three #[test] functions in vendor/nova/src/neutron/mod.rs #[cfg(test)] mod tests, sibling to the M.GH7.3a positive-path acceptance test at mod.rs:1466-1900. Discharges .claude/rules/cryptography.md §70-78 ("Constraint hygiene; a missing constraint is a forgery vector") for the M.GH7.3a public prover API surface: RecursiveSNARK::prove_step_with_lookup_fold sibling + LookupStepCircuit<E> trait + RecursiveSNARK::running_lws field + PublicParams::setup lookup_shape parameter, landed at e3fe75d. Per Corrigendum microsoft#15 + 2026-05-12 late-evening Sub-ratification in docs/research/cryptography/microsoftgh-7-stage-k-compressed-snark-design-pin-2026-05-11.md §0 entry 15 + §3.1.1 + §5.5 row M.GH7.3b: test (i) `prove_step_with_lookup_fold_corrupt_t_at_index_in_consumed_u1 _rejects_at_r1cs_c_binding` Corrupt verifier-input U1.T += Scalar::ONE; reject at R1CS-side (C)-binding (nifs.rs:2000-2001, Step 7). Anchored on Nova 2021/370 v3 §3 R1CS sumcheck soundness. (RE-TARGETED per Sub-ratification — Corrigendum microsoft#15's original bundles[j].running_lw corruption was structurally inadequate at the (C)-binding rejection mechanism because LookupSumcheckInstance::prove_step at lookup_sumcheck.rs:278-285 sets evals[1] := t_lookup_running − evals[0] BY CONSTRUCTION, making poly_lookup_j(0)+poly_lookup_j(1) = t_lookup_running_j a TAUTOLOGY for any honestly-produced polynomial. Fifth Halpert-class verify-don't-assume failure named.) test (ii) `prove_step_with_lookup_fold_post_prove_mutate_poly_lookup _via_nifs_rebuild_rejects_at_lookup_c_binding` Mutate nifs.poly_lookup[0].coeffs[0] += Scalar::ONE (ADDITIVE, per Sub-ratification — replaces Corrigendum microsoft#15's original multiplicative × 2 which preserved the (C)-binding tautology under all-zero T_lookup_running = 0); reject at lookup-side (C)-binding (nifs.rs:2025-2028, Step 8). Anchored on FS-NIZK soundness (Fischlin-Fischlin 2005). test (iii) `prove_step_with_lookup_fold_corrupt_t_lookup_at_index_in _consumed_u1_rejects_at_lookup_c_binding` Corrupt verifier-input U1.T_lookup[0] += Scalar::ONE; reject at lookup-side (C)-binding (nifs.rs:2025-2028, Step 8). Anchored on Nova 2021/370 v3 §4 binding-by-hash composition. (STANDS verbatim from Corrigendum microsoft#15.) All three reject with NovaError::InvalidSumcheckProof, asserted via the M.14 typed-variant pattern at nifs.rs:6140. Implementation pattern follows the M.14 precedent at nifs.rs:5719-6149 (direct NIFS::prove_with_multi_table_lookup at vendor-test scope) — per Sub-ratification Gap-2 clarification, RecursiveSNARK has no `nifs` field at vendor HEAD e3fe75d so extraction is structurally impossible; the direct-NIFS pattern routes through the same (C)-binding algebra that prove_step_with_lookup_fold invokes internally. Fixture: AbsentTableStepCircuit-style — K=1, TABLE_SIZE=4, TABLE_LOG2=2, Bn256EngineKZG + GrumpkinEngine, single empty-columns multi_column_table — inherited from the M.GH7.3a positive-path acceptance test. No fixture amendment required (NEITHER Option A NOR Option B from the original dispatch brief). The three algebraic preconditions (BN254 scalar field characteristic odd; rho ≠ ONE w.o.p. under RO-squeeze; prime field of size ≥ 2) hold under this fixture. Deterministic seeds 0xC1BE_5BAD_C0DE_703{1,2,3} per US-05. Test verdicts (release-mode, scoped, by name): test (i) 1 passed (0.19s) test (ii) 1 passed (0.19s) test (iii) 1 passed (0.18s) M.GH7.3a positive-path regression 1 passed (0.70s) Empirical-close of STOP-AND-ASK triggers: microsoft#1 accessor-surface gap verified absent (NIFS::poly_lookup and UniPoly::coeffs are pub; FoldedInstance.T and .T_lookup pub(crate) accessible from sibling test module). microsoft#2 rejection-variant divergence verified absent (all three reject with InvalidSumcheckProof). microsoft#3 loop-iteration-order verified absent (K=1, single iteration). microsoft#4 positive-baseline regression verified absent (M.GH7.3a positive-path still GREEN). microsoft#5 (NEW) test (i) rejection-locus empirically confirmed at R1CS-side (C)-binding (nifs.rs:2001:7) via distinguishing-panic probe (probe removed before commit; vendor working tree clean at nifs.rs). microsoft#6 (NEW) test (ii) additive-mutation effectiveness empirically confirmed (in-test assert that mutated_sum = honest_sum + 2·ONE in BN254 scalar field of odd characteristic). AO 19 FULL discharge: completes the partial discharge from M.GH7.3a's positive-path round-trip per Corrigendum microsoft#15 §6.3 AO 19 boundary refinement (unchanged by Sub-ratification). No new Pass Criterion at M.GH7.0.5; no new auditor obligation; no algebra change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
marcus-sa
added a commit
to marcus-sa/Nova
that referenced
this pull request
May 15, 2026
…ing via batch_eval_reduce extension (per Corrigendum microsoft#16; AO 15 Tier-2 part 1 discharge positive-path) Authors the M.GH7.4 subdivision's second sub-milestone (M.GH7.4b per Corrigendum microsoft#16 §5.5 row split). Two new vendor-side surfaces; one struct extension; one new helper. Inner sumcheck + outer sumcheck UNCHANGED from M.GH7.4a — M.GH7.4b extends the batch-eval-reduce PCS-opening layer only. 1. `RelaxedR1CSSNARK::per_table_outer_evals: Option<Vec<PerTableOuterEvals>>` at `src/spartan/snark.rs` — new struct field on the existing Spartan-side SNARK struct under `#[serde(default = "Option::default")]` (preserves the existing serialised proof shape for β'/M.GH7.0.0 paths verbatim). Populated by `prove_with_T_claim_split_error_with_logup`; read by `verify_with_T_claim_split_error_with_logup` to reconstruct the unified outer-sumcheck residue claim. `PerTableOuterEvals<F>` at `src/spartan/sumcheck.rs` gains `Serialize`/`Deserialize` derives under `#[serde(bound = "F: Serialize + serde::de::DeserializeOwned")]`. 2. `RelaxedR1CSSNARK::prove_with_T_claim_split_error_with_logup` extended at `src/spartan/snark.rs` — signature appends four per-table commitment slices (`per_table_comm_L`, `per_table_comm_ts`, `per_table_comm_inv_w`, `per_table_comm_inv_t`); `u_vec`/`w_vec` extended from 3 entries to `3 + 4·k` entries by appending per-table openings at evaluation point `r_x` (full length-`ell` outer-sumcheck challenge, per Corrigendum microsoft#16 Finding F flat-embedding disposition). PCS-opened subset per j is `(w_j, ts_j, inv_w_j, inv_t_j)` consuming the four corresponding `PerTableOuterEvals` fields as `PolyEvalInstance::e` values. The `batch_eval_reduce` call site is otherwise byte-identical; the Corrigendum microsoft#12 zero-pad fix at `PolyEvalWitness::batch_diff_size` handles the heterogeneous-size openings (W.W at length `num_vars`; E1 at `left`; E2 at `right`; per-table polys at `num_cons`; W.W and the per-table polys are the asymmetric pair at the test fixture where `num_vars < num_cons`). Per-table outer evals are duplicated into the proof envelope via `per_table_outer_evals: Some(per_table_outer_evals .clone())` so the verifier can deserialise them without a separate out-of-band carry; the existing pass-through return tuple is preserved verbatim for M.GH7.4a byte-identical regression. 3. `RelaxedR1CSSNARK::verify_with_T_claim_split_error_with_logup` at `src/spartan/snark.rs` — new verifier-side sibling, the M.GH7.4b dual of the prover. FS-transcript discipline byte-identical to β'/with-logup prover (Primitive 5: absorb vk → U → T_claim before any squeeze). Verifies outer sumcheck at degree-3 with claim = `U_bridged.T` (matches prover under Corrigendum microsoft#16 Finding C additive composition degree-3). Reconstructs `claim_outer_final_expected` as the additive composition of the R1CS-side residue (`eval_E1·eval_E2·(claim_Az·claim_Bz − claim_Cz)`) plus per-table (A) `eval_eq_w_j·(eval_inv_w_j·(eval_w_j + r_logup_j) − 1)` and (B) `eval_eq_t_j·(eval_inv_t_j·(eval_T_j + r_logup_j) − eval_ts_j)` residues per Corrigendum microsoft#16 Finding B (no gamma-RLC). Verifies the prover-supplied `eval_T_j` against the public table-data MLE at `r_x` (rejecting a forged `eval_T_j` is the discipline that pins (B)-side correctness — without this check, an adversarial prover could supply any `eval_T_j` and trivially satisfy (B)). Extends batch_eval_verify u_vec to `3 + 4·k` entries symmetric with the prover. 4. `build_per_table_commitments` test helper at the `m_gh7_4a` module — commits the four PCS-opened per-table polys against the test `CommitmentKey` with zero blindings (matches the M.GH7.4a fixture's derandomised E1/E2 commitment discipline). STOP-AND-ASK gates (Corrigendum microsoft#16 §5.5 row M.GH7.4b) — NONE RAISED: Gate microsoft#4 (PCS opening evaluation-point partition / Finding F): RESOLVED via flat embedding at `r_x`. M.GH7.4a's `prove_neutron_outer_with_logup` binds per-table polys uniformly with R1CS-side polys via `bind_poly_var_top` over the full `ell = log2(num_cons)` rounds; after the outer sumcheck closes, each per-table poly reduces to a single scalar at `r_x` (full length-`ell` challenge). `batch_eval_reduce` requires `w.p.len() == 1 << x.len()` per `mod.rs:417`; for per-table polys `(num_cons, ell)`, the equality `num_cons = 1 << ell` holds by construction. No sub-vector partition needed; Corrigendum microsoft#9 (2-A) `r_x_high`/`r_x_low` partition is preserved verbatim and is consumed ONLY by `comm_E1`/`comm_E2` (rank-1 tensor factorisation), NOT by the per-table entries (which open at full `r_x`). Gate microsoft#5 (`batch_eval_reduce` heterogeneous-size capacity): RESOLVED at the algebra + via empirical close. The existing β' u_vec already carries heterogeneous-size openings (comm_W at length `num_vars`; comm_E1 at `left`; comm_E2 at `right`). M.GH7.4b appends `4·k` per-table entries at length `num_cons`. The Corrigendum microsoft#12 zero-pad fix at `PolyEvalWitness::batch_diff_size` (`src/spartan/mod.rs:186-198`) uses `.get(..).unwrap_or(&[])` bounds-checking on chunks past a smaller polynomial's end; chunks that straddle the boundary use `.zip` truncation; both handle the per-table extensions structurally without re-authoring. Verifier-side `PolyEvalInstance::batch_diff_size` (`mod.rs:320-362`) Lagrange-extends the smaller-domain claims via the `(1 − r_lo).product()` correction so the heterogeneity is bookkept symmetrically. Empirically closed by the M.GH7.4b acceptance test below (both Bn256EngineKZG + PallasEngine engines round-trip). Additional structural STOP-AND-ASK gates raised by the dispatch: - `FoldedWitness<E>` per-table blindings: NOT NEEDED. The dispatch assumed `PolyEvalWitness<E>` carries blindings (`r:` field) and that M.GH7.4b would need per-table `r_L_per_table`/etc. Verified at vendor HEAD: `PolyEvalWitness<E>` is `{ p: Vec<E::Scalar> }` — blinding-less. No `FoldedWitness` extension required. - Per-table commitment source / dispatch's "r_U.comm_L.as_ref()" claim: INCONSISTENT with M.GH7.4a's authored signature. M.GH7.4a's sibling consumes `BridgedNeutronInstance` (which lacks per-table fields per Corrigendum microsoft#16 Finding D — M.GH7.4c lands envelope-struct extensions). Resolution: M.GH7.4b accepts per-table commitments as direct slice parameters (parallel to per-table polynomial slices). Envelope-Spartan FS isolation per Corrigendum microsoft#11 preserved (commitments NOT absorbed into this transcript; envelope absorbs them BEFORE squeezing the `r_logup_j` scalars passed in). Routing via `BridgedNeutronInstance` extension fields is M.GH7.4c scope; M.GH7.4b is invariant under that decision. Test coverage: - `m_gh7_4b_prove_with_T_claim_split_error_with_logup_pcs_opening_batched_round_trip`: Positive-path round-trip at fixture `num_cons=4, k=2, table_size=4`, seed `0xC1BE_5BAD_C0DE_704B`. Constructs honest per-table LogUp witnesses, commits the four PCS-opened polys, invokes prover and asserts (i) prover succeeds with the extended 3+4·k=11 PCS-opening entries, (ii) verifier accepts the proof (closes STOP-AND-ASK gates microsoft#4 + microsoft#5), (iii) β' sibling regression — `prove_with_T_claim_split_error` + `verify_with_T_claim _split_error` continue to round-trip byte-identically at the same fixture shape. Regression invariants preserved (release-mode `cargo test --release --features lookup-fold --lib <test_name>` per `.claude/rules/testing.md`): - M.GH7.0.5 STAGE 0: `test_pp_digest` (2/2 ok), `test_ivc_*` family (9 passed + 1 ignored byte-identically), `test_setup` (2/2 ok). - M.GH7.0.0b: 3 tests ok (round-trip byte-equal + weighting differential 1000-iter + negative T corruption rejected). - M.GH7.3a + M.GH7.3b: 4 tests ok (`prove_step_with_lookup_fold` family). - M.GH7.4a: 4 tests ok (round-trip + degree-3 empirical close + `PerTableOuterEvals` field shape + the M.GH7.4b co-located test). LOC: ~+700 lines in `snark.rs` (verifier sibling + extended prover signature + struct field + new acceptance test + `build_per_table_commitments` helper); ~+18 lines in `sumcheck.rs` (serde derives + documentation cascade). Discharges AO 15 Tier-2 part 1 positive-path (PCS opening of `comm_L_j` against the witness `w_j` at the Spartan-FS-head per pin §3.4 + §1.2(c)). Negative-path (corrupt-`comm_L_1` test, AO 15 Tier-2 part 2) lands at M.GH7.5 per Corrigendum microsoft#16 §5.5 row M.GH7.5. Refs: docs/research/cryptography/microsoftgh-7-stage-k-compressed-snark-design-pin-2026-05-11.md Corrigendum microsoft#16 (M.GH7.4 subdivision into M.GH7.4a/b/c) §5.5 row M.GH7.4b, §6.1 row M.GH7.4b, §6.3 AO 15 Tier-2 part 1 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
No description provided.