feat(ppsnark): improve ppsnark memory-check with Logup-GKR#501
Open
Sun-Jc wants to merge 2 commits into
Open
Conversation
Replace the ppSNARK inverse-logup memory-check with a Logup-GKR fractional-sum argument, selectable by cargo feature. - Default: Logup-GKR. A fractional-sum GKR argument (src/spartan/logup_gkr/) folds the four row/col x table/access sub-instances into per-instance trees, with Horner lambda-batching (distinct powers per num/den) and MSB-first fold. - logup-no-gkr: the original inverse-logup memory-check (main's behaviour). The two paths are mutually exclusive and each compiles only its own code, so the GKR default drops the four inverse-oracle commitments and the six-route sumcheck. - Host bridge (src/spartan/mem_check_logup_gkr.rs) reconciles the claimed fingerprint columns against the GKR-reduced input claims (component-wise equality), runs the row/col balance check with a nonzero-denominator guard, and carries the seven reconcile columns into the inner batched sumcheck via a RerandomizeSumcheckInstance landing at r_inner_batched. - Verifier binds GKR depth to log N (rejects mismatched depth with NovaError instead of panicking) and uses exact fraction equality at the root gate and host reconcile to close the (0,0) projective-claim bypass. test_ivc_nontrivial_with_compression passes on both feature paths.
clippy 1.97 adds `useless_borrows_in_formatting` and `manual_clear`: - drop redundant `&` in write!/writeln! args (test_shape_cs pretty_print) - use Vec::clear() instead of truncate(0) (num gadget)
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.
Summary
This PR improves preprocessing Spartan (ppSNARK), primarily by replacing its inverse-logup memory-check with a Logup-GKR argument. The new default avoids committing to four inverse-oracle polynomials and reduces the final batched PCS opening from 15 polynomials to 11.
The trade-off is proof size: Logup-GKR adds a field-only proof whose size is quadratic in
log N. In return, the measured end-to-end prover is about 1.3x faster at medium and large circuit sizes, corresponding to roughly 23-24% less wall time in the current A/B benchmark.The original inverse-logup implementation remains available behind the
logup-no-gkrfeature for compatibility, comparison, and deployments that prefer the smaller proof.Motivation
The previous ppSNARK memory-check proves, independently for the row and column memories,
Its prover materializes four inverse-oracle vectors through two batch inversions, commits to all four vectors, proves four inverse-validity claims in addition to the two balance claims, and includes the four inverse polynomials in the final batched PCS opening. At large
N, the four length-Ncommitments dominate the memory-check wall time.Logup-GKR keeps the fractions in projective form and proves their reduction through fractional-add trees. It therefore removes the need to materialize or commit to the inverse polynomials.
Protocol changes
Logup-GKR memory-check
The new memory-check builds four equal-height input layers:
Each layer is folded with the projective fractional-add gate
The prover and verifier batch the four trees at every layer. The verifier then:
eval_pointand reconciles them with the GKR result;The GKR reduction adds
O(log N)layer sumchecks, with a decreasing number of rounds per layer. It contributesO(log^2 N)field elements to the proof.Opening-point reduction
GKR finishes at its own
eval_point, while the existing ppSNARK inner sumcheck finishes atr_inner_batched. A rerandomization sumcheck carries the seven columns needed by the host reconciliation fromeval_pointtor_inner_batched:This rerandomization claim is included in the existing batched inner sumcheck, so all committed polynomials are still opened once at
r_inner_batched.What is removed and added
Removed from the default path:
Ninverse-oracle commitments;15 -> 11polynomials).Added to the default path:
O(log N)layer sumchecks;eval_point;r_inner_batched.The evaluation engine still receives one RLC-batched length-
Npolynomial, so the IPA, HyperKZG, or Mercury evaluation argument itself does not become smaller. The15 -> 11reduction saves construction work beforeEvaluationEngine::prove; the main wall-time saving comes from removing the four inverse-oracle commitments.Feature gate
Logup-GKR is the default memory-check. The original inverse-logup protocol can be selected at compile time:
The two configurations have different ppSNARK proof layouts. A proof must be verified with the same feature configuration that produced it.
Sumcheck optimizations
Reuse cached multilinear deltas
For a multilinear polynomial split into low and high halves, both round evaluation and binding need the slope
The evaluation pass now stores
deltain the high half. After the transcript produces the round challenge, binding reuses it directly:This avoids recomputing the subtraction during the bind pass without changing the round polynomial, transcript, or proof. The optimization is applied to:
L_row * L_col * val) and itsEevaluation claim;The default Logup-GKR path fuses the rerandomization columns as described below, so that path binds one combined polynomial instead of seven cached polynomials.
Fuse the seven rerandomization columns
Once
prove_helpersamples the inner-batch coefficients, the seven rerandomization columns and claims are collapsed into one random linear combination. This reduces the rerandomization state from approximately7Nfield elements toNand changes each inner-sumcheck round from seven column scans/binds to one.The fusion is linear in the same coefficients already used by the batched sumcheck. It preserves the transcript and proof bytes. In the focused A/B measurement, it reduced the inner-batch phase by approximately 25-33% at
2^18and2^20constraints.Optimize GKR layer sumchecks
The GKR prover also:
EqSumCheckInstanceinstead of materializing and rebinding a full equality MLE;N-scaling sums instead of three in the common case;lambdabatching.Memory management
This PR shortens the lifetime of large prover buffers before later ppSNARK phases allocate their own length-
Ndata:Here,
mis the constraint count used by the shortened outer sumcheck andNis the padded inner-domain size.poly_Az,poly_Bz,poly_uCz_E, andCzafter the outer claims are computed (approximately4mfield elements);NEandWvectors are materialized (approximately2mfield elements);zafterevaluation_oracles;These lifetime changes do not affect the transcript or proof.
Performance
The following numbers compare the current default Logup-GKR path with
--features logup-no-gkrusingBn256EngineKZG+ HyperKZG on an Apple M-series machine with 14 cores. Each row is the median of 10 sequential repetitions after one warm-up.2^162^182^20At
2^20, the isolated memory-check phase improves from 3.649 s to 0.834 s, or approximately 4.4x. This phase accounts for essentially the entire end-to-end difference; the twoLcommitments and the final HyperKZG opening are shared costs.The same
2^20run measured peak RSS at 9.09 GB for Logup-GKR and 10.92 GB for inverse-logup. RSS remains high because ppSNARK and HyperKZG retain several length-Nbuffers; this PR reduces it but does not claim to solve the full prover-memory problem.Proof-size trade-off
Logup-GKR deliberately exchanges proof size for prover time. Let
d = log2(N). For four GKR sub-instances, its memory-check-specific payload is approximatelyAt
N = 2^20, this is 905 field elements, or about 28 KiB for 32-byte field elements, before container and serialization metadata. The inverse-logup memory-check instead carries four commitments and four field evaluations.The shared evaluation argument has the same size in both modes because all PCS inputs are RLC-batched before the evaluation engine is invoked. Users for whom proof bytes, network transfer, or calldata dominate can retain inverse-logup through
logup-no-gkr.Correctness and review notes
num_varsand does not add generic padding machinery.lambda; per-instance batching uses distinct Horner powers.logup-no-gkris the explicit legacy fallback.Validation
Validated during development under both memory-check configurations:
cargo fmt --all -- --checkcargo clippy --all-targets -- -D warningscargo clippy --all-targets --features logup-no-gkr -- -D warningscargo test --release test_ivc_nontrivial_with_compressioncargo test --release --features logup-no-gkr test_ivc_nontrivial_with_compression