perf(zkatdlog): reduce CPU time and allocations in CSP range-proof crypto - #1997
Open
adecaro wants to merge 1 commit into
Open
perf(zkatdlog): reduce CPU time and allocations in CSP range-proof crypto#1997adecaro wants to merge 1 commit into
adecaro wants to merge 1 commit into
Conversation
…ypto Optimizes the Compressed Sigma Protocol (CSP) range-proof package (crypto/rp/csp) with no change to its public API, wire format, or verification semantics: - crypto/rp/csp/msm.go (new): dispatches small, fixed-size multi-scalar multiplications to direct Mul/Mul2 instead of gnark-crypto's MultiScalarMul. CSP's folding rounds shrink every vector down to length 2 and then 1 in their last two rounds, and several call sites always operate on exactly 2 generators/scalars; MultiScalarMul's goroutine fan-out (sized for runtime.NumCPU()*2) costs more than it saves at n<=2. Benchmarked on BLS12-381 (M1 Max): direct Mul is ~2.5x faster than MultiScalarMul at n=1, Mul2 ~25-29% faster at n=2; from n=3 the two are at parity or MultiScalarMul wins, so smallMSM only special-cases n=1/n=2 and falls through to MultiScalarMul otherwise (strictly non-regressive). Applied at all 6 production MultiScalarMul call sites in csp.go/rp.go. - crypto/math/native.go: adds NativeBatchInverseInto, a batch field-inversion helper that writes into caller-supplied buffers instead of allocating fresh ones on every call. - crypto/rp/csp/lagrange_native.go: interpolateNative's outer loop previously allocated 5 fresh same-size slices/scalars per iteration (partly via NativeBatchInverse's internal allocations, partly its own per-iteration scratch). Rewritten to hoist every per-x buffer and scalar scratch outside the outer loop via NativeBatchInverseInto, so each is allocated once per call instead of once per iteration. - crypto/rp/csp/transcript.go: Transcript.Absorb is called many times per proving/verification round; reuses a scratch buffer across calls instead of growing a fresh slice on every Absorb. Benchmarked on BenchmarkBFProver (n=32/n=64, BLS12_381_BBS_GURVY, count=8, benchstat): combined effect of the MSM dispatch and batch- inversion changes is roughly -6% ns/op and -35-40% allocs/op (geomean), each individually significant at p<0.01. No public API, wire format, or verification behavior changed. Signed-off-by: Angelo De Caro <adc@zurich.ibm.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.
Fixes #1994
Summary
Optimizes the Compressed Sigma Protocol (CSP) range-proof package
(
crypto/rp/csp) with no change to its public API, wire format, or verificationsemantics:
crypto/rp/csp/msm.go(new): dispatches small, fixed-size multi-scalarmultiplications to direct
Mul/Mul2instead of gnark-crypto'sMultiScalarMul. CSP's folding rounds shrink every vector down to length 2and then 1 in their last two rounds, and several call sites always operate
on exactly 2 generators/scalars;
MultiScalarMul's goroutine fan-out (sizedfor
runtime.NumCPU()*2) costs more than it saves at n<=2. Benchmarked onBLS12-381 (M1 Max): direct
Mulis ~2.5x faster thanMultiScalarMulatn=1,
Mul2~25-29% faster at n=2; from n=3 the two are at parity orMultiScalarMulwins, sosmallMSMonly special-cases n=1/n=2 and fallsthrough to
MultiScalarMulotherwise (strictly non-regressive). Applied atall 6 production
MultiScalarMulcall sites incsp.go/rp.go.crypto/math/native.go: addsNativeBatchInverseInto, a batchfield-inversion helper that writes into caller-supplied buffers instead of
allocating fresh ones on every call.
crypto/rp/csp/lagrange_native.go:interpolateNative's outer looppreviously allocated 5 fresh same-size slices/scalars per iteration.
Rewritten to hoist every per-x buffer and scalar scratch outside the outer
loop via
NativeBatchInverseInto, so each is allocated once per callinstead of once per iteration.
crypto/rp/csp/transcript.go:Transcript.Absorbis called many times perproving/verification round; reuses a scratch buffer across calls instead of
growing a fresh slice on every
Absorb.Benchmarked on
BenchmarkBFProver(n=32/n=64,BLS12_381_BBS_GURVY, count=8,benchstat): combined effect of the MSM dispatch and batch-inversion changesis roughly -6% ns/op and -35-40% allocs/op (geomean), each individually
significant at p<0.01. No public API, wire format, or verification behavior
changed.
Test plan
make checksmake lint-auto-fixmake unit-testsgo test ./token/core/zkatdlog/nogh/v1/crypto/rp/csp/... ./token/core/zkatdlog/nogh/v1/crypto/math/... ./token/core/zkatdlog/nogh/v1/crypto/rp/bulletproof/...benchstatbefore/after onBenchmarkBFProver, count=8