feat: add mmap-backed dumps for groth16 proving keys - #1780
Open
sergeytimoshin wants to merge 2 commits into
Open
feat: add mmap-backed dumps for groth16 proving keys#1780sergeytimoshin wants to merge 2 commits into
sergeytimoshin wants to merge 2 commits into
Conversation
sergeytimoshin
force-pushed
the
mmap-groth16-proving-keys
branch
from
June 14, 2026 20:06
ef4b446 to
fe24adc
Compare
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.
This PR adds file-backed unsafe dump support for Groth16 proving keys.
ProvingKey.WriteDump/ReadDumpalready provide an unsafe raw-memory proving-key serialization path, butReadDumpreconstructs the large proving-key slices on the Go heap. This change adds a parallel mmap-backed dump path:ProvingKey.WriteMmapDump(path);ReadMmapDump(path);backend/groth16package exposesgroth16.WriteMmapDump(pk, path)andgroth16.ReadMmapDump(curveID, path)so callers using the top-level Groth16 API do not need to import a concrete curve package;ReadMmapDumpreturns a closeableMmapProvingKeywhose large slices are backed by a read-only memory mapping;WithMmapDumpNoDomainPrecompute(threshold)optionally disables FFT domain precomputation on load for applications that prefer lower memory usage over precomputed-domain speed.This is useful for applications that repeatedly load large Groth16 proving keys, run on memory-constrained machines, or run multiple prover processes that can benefit from OS page-cache sharing instead of each process copying the full proving key into Go heap memory.
This does not claim to solve all low-memory proving cases by itself. Serialized R1CS loading can still be a large heap allocation and should be handled in a follow-up change. This PR focuses on the proving-key side because it extends the existing unsafe dump concept without changing constraint-system serialization.
This PR is also intentionally scoped to Groth16 proving keys. It applies to any gnark circuit proven with Groth16 on the supported curves, but it does not add mmap dumps for PLONK proving keys. PLONK has a different proving-key layout and should be reviewed separately if there is demand for the same loading mode there.
The mmap dump format is intentionally treated as unsafe and local-artifact-only. The reader validates the current process against metadata including curve, operating system, architecture, Go compiler/version, endianness, pointer size, relevant type sizes, and gnark / gnark-crypto versions when build info is available. It also checks section bounds/overlap and core proving-key length invariants before constructing unsafe slices. It does not validate curve points or subgroup membership, matching the unsafe dump model.
Type of change
How has this been tested?
Added generated tests for all Groth16 curve packages:
bls12-377bls12-381bn254bw6-761The tests cover:
backend/groth16API,MmapProvingKey.Focused commands run:
CI-equivalent checks also run locally:
golangci-lintwas run with the CI-pinned version,v2.10.1.go generate ./...was rerun after the template changes and produced only the intended mmap-related generated files.Additional compile-only checks for the touched Groth16/mmap packages:
How has this been benchmarked?
Added generated benchmarks comparing heap-backed unsafe dump loading with mmap-backed dump loading:
Sample result on Apple M4 Max / darwin arm64:
The benchmark is intentionally focused on loading, not proving. It demonstrates the standalone motivation for this PR: mmap-backed proving-key loading avoids most of the heap allocation from
ReadDump, even before adding a follow-up R1CS mmap loader.Main takeaways from this run:
ReadMmapDumpreduces heap allocation from about 1.25 MB/op to about 297 KB/op for this benchmark key, roughly a 76% allocation reduction.179 µs/opvs130 µs/op), so the primary benefit is lower heap pressure and file-backed sharing rather than lower load latency.ReadMmapDumpNoDomainPrecomputereduces allocation to about 4.4 KB/op, roughly a 99.6% reduction versusReadDump. This shows that most remaining allocation in the default mmap path comes from FFT domain precomputation rather than proving-key slice loading.Checklist:
go generate ./internal/generator/backend, andgo generate ./...was rerun afterward to verify generated-file cleanliness.golangci-lintdoes not output errors locallyFollow-up
Related follow-ups:
Note
Medium Risk
New unsafe, trusted-local serialization on the proving path: bad or mismatched dumps could corrupt proving behavior, though metadata checks and tests mitigate load-time mistakes.
Overview
Adds a file-backed mmap path for Groth16 proving keys so large
G1/G2slices can be loaded from disk without copying them onto the Go heap, alongside the existing unsafeWriteDump/ReadDumpflow.Per supported curve (BLS12-377/381, BN254, BW6-761),
WriteMmapDumpwrites aligned raw-memory sections plus JSON metadata (platform, versions, section layout), andReadMmapDumpreturns aMmapProvingKeythat must stay open untilClose. Load usesunsafeviews into the mapping; metadata and section bounds are checked, but curve points are not.WithMmapDumpNoDomainPrecomputecan strip FFT domain precompute on load to cut heap use at prove time.The top-level
backend/groth16package exposesWriteMmapDump,ReadMmapDump(curveID, …), andProvenow accepts both in-memory and mmap-backed keys. A smallinternal/backend/ioutils/mmaphelper implements Unix mmap with a non-Unix stub. Code is generated from new templates plus tests/benchmarks comparingReadDumpvs mmap load.Reviewed by Cursor Bugbot for commit 937ec00. Bugbot is set up for automated code reviews on this repo. Configure here.