perf: optimize LogUp for constant single-column tables (range checks)#1717
Merged
perf: optimize LogUp for constant single-column tables (range checks)#1717
Conversation
ivokub
approved these changes
Feb 18, 2026
Collaborator
ivokub
left a comment
There was a problem hiding this comment.
Beautiful! I didn't think there was room for optimizing logderivarg package any further :) (actually there is I think for small-field case we don't need to use linear combination but can pack the values into the extension accumulators, but this can do in another PR)
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.
Description
Optimizes PLONK (SCS) constraint count for range checks by merging
Sub+DivUncheckedinto a singleAddPlonkConstraintgate on the table side of the log-derivative argument.In the LogUp verification equation
sum count(f,S)/(x-f) == sum 1/(x-s), the left-hand (table) side previously required 3 PLONK gates per table entry:Sub:denom = challenge - table_val(1 gate)DivUnchecked:quotient * denom = exps[i](1 gate)Add:lp += quotient(1 gate)For constant single-column tables (which range checks always are), the constant table value can be folded into the PLONK gate coefficients. A batch hint computes quotients, then a single
AddPlonkConstraintverifiesquotient * (challenge - c) = exps[i]by encoding it asqM*q*ch + qL*q + qO*exps + qC = 0withqM=1, qL=-c, qO=-1, qC=0. This reduces the table side to 2 gates per entry:AddPlonkConstraint: verify quotient (1 gate)Add:lp += quotient(1 gate)Saving:
2^baseLength - 1PLONK constraints per circuit (thei=0entry whereSub(challenge, 0)was already free).R1CS is unaffected. The base-length selection heuristic is intentionally left unchanged since it implicitly accounts for commitment overhead not modeled in the cost formula.
Type of change
How has this been tested?
All existing tests pass across all backends (Groth16/R1CS, PLONK/SCS) and curves (BN254, BLS12-381), including small-field (KoalaBear):
go test ./std/rangecheck/ -count=1— TestCheck, TestCheckSmallField, TestBaseLengthOptiongo test ./std/lookup/logderivlookup/ -count=1— TestLookup, Example (uses logderivarg internally)How has this been benchmarked?
Range check micro-benchmark (100 values, 64-bit, BN254)
EVM precompiles
PLONK recursion
Savings are exactly
2^baseLength - 1per circuit, confirming the optimization applies correctly.Checklist:
golangci-lintdoes not output errors locallyNote
Medium Risk
Touches core constraint-generation logic and introduces a new hint/optimization path specific to PLONK, so incorrect gating or edge cases (non-int constants, zero denominators) could cause subtle proof failures despite the guarded fallback.
Overview
Improves PLONK performance of
std/internal/logderivargwhen the lookup table is a constant single-column table (typical for range checks) by verifyingquotient*(challenge-c)=exps[i]via oneAddPlonkConstraintper entry instead of buildingSub+DivUncheckedconstraints.Adds and registers a new solver hint
batchDivBySubHintto compute the quotients for this optimized path, while keeping the existing fallback behavior for non-constant/multi-column tables and for small-field (wide commitment) mode unchanged. Updatesinternal/stats/latest_stats.csvto reflect reduced PLONK constraint counts in affected benchmarks.Written by Cursor Bugbot for commit 4ea74d9. This will update automatically on new commits. Configure here.