Skip to content

perf(crypto): optimize bn128 arithmetic and subgroup checks - #64

Open
Federico2014 wants to merge 4 commits into
release_v4.8.3from
perf/fp2-arithmetic-v4.8.3
Open

Federico2014 wants to merge 4 commits into
release_v4.8.3from
perf/fp2-arithmetic-v4.8.3

Conversation

@Federico2014

@Federico2014 Federico2014 commented Oct 27, 2026 •

Copy link
Copy Markdown
Owner

What does this PR do?

Optimizes BN128 field arithmetic and G2 input validation:

  • Specializes Fp2.squared(), mul(), inverse(), and multiplication by 9+i; corrects its documentation and diagnostic toString() to use a+bi.
  • Defines extension non-residues in their coefficient fields, removes the duplicate Fp6.NON_RESIDUE, and reuses Fp2.mulByNonResidue() throughout Fp6 and Fp12. Documents that the Fp2 helper multiplies by 9+i, while the Fp6 helper multiplies by v, with v^3=9+i.
  • Replaces the 254-bit G2 subgroup multiplication with one multiplication by the 63-bit BN seed and three Frobenius applications. Preserves the infinity fast path and compares Jacobian points by subtraction.

Why are these changes required?

The fixed BN128 parameters permit equivalent arithmetic with fewer BigInteger multiplications. The G2 subgroup check runs for every decoded pairing term and can exploit the existing twist endomorphism.

For z=4965661367192848881 and psi=mulByP, the criterion is [z+1]P + psi([z]P) + psi^2([z]P) = psi^3([2z]P) (paper, Sections 3 and 5.1). On this sextic twist, g(psi)=0 for g(X)=X^4-X^2+1; the integer resultant of g and f(X)=z+1+zX+zX^2-2zX^3 is exactly r. The resulting integral Bezout identity excludes additional torsion in the acceptance set. Conversely, psi=[p] on G2 and f(p)=0 mod r.

This PR has been tested by:

  • 30 focused BN128 tests passed on x86_64/JDK8: independent arithmetic formulas, full-order subgroup oracles, arbitrary twist points, all four prime cofactor components, projective Frobenius behavior, sparse/cyclotomic arithmetic, precompile outputs and invalid inputs, and deadlines.
  • 3,793 baseline/final comparisons matched with all zksnark classes overridden: arithmetic, derived parameters, precompile outputs/failures/Energy, and CPU-policy branches. The intentional diagnostic-text correction was checked separately.
  • Local clean build, the exact framework/plugins CI Checkstyle gate, and Math checks passed.
  • The full-suite attempt was interrupted after 1,341 logged passes and five integration timeouts (RPC HTTP/2, native-library loading, and LevelDB/RocksDB node tests). All five failed cases passed when rerun with one Gradle worker. A complete full-suite pass is still pending.

Follow up

Historical replay, mixed-version producer/validator testing near CPU deadlines, and ARM64/JDK17 performance measurements remain pending.

Extra details

Compatibility and consensus

The intended point acceptance set, coordinate validation, input encoding, binary results, public method signatures, and Energy pricing are unchanged. Fp2.toString() intentionally corrects diagnostic text; protocol serialization does not use it. The removed Fp6 constant is internal to a package-private implementation.

Faster execution can change outcomes near local CPU deadlines. Signed-block replay has configurable CPU allowances, retry, and receipt matching, but an older validator can still reject a result it cannot reproduce within its allowance. No deterministic arithmetic or validation-rule change was identified; mixed-version timeout compatibility has not been fully validated.

Performance comparison (final combined implementation)

Baseline: release_v4.8.3 at 409a33f21e6341e31dff5a6341f34f6d0b212d50. Final source tree: 273858d778a1519f9639c28a0c152a074f0ba9f1. Host: Intel i7-9750H, macOS x86_64, Oracle JDK 1.8.0_221, 512 MiB heap, Parallel GC, -Xbatch.

Three fresh JVMs compared isolated baseline/final runtimes after warmup, using five paired rounds with alternating order and varied inputs. All zksnark classes were overridden together; the remaining runtime was identical. Input/output corpus hashes matched across both variants and all forks. Source hashes were recorded and the published Git tree was verified against the staged, tested tree.

Before/after are medians of per-JVM median latencies. Reduction is the median of within-JVM paired reductions, so it is not the ratio of the displayed medians.

Precompile / workload Before (ms/op) After (ms/op) Median paired latency reduction
BN128Addition 0.047435 0.048366 -0.31%
BN128Multiplication 4.388712 4.846322 -0.06%
BN128Pairing, 1 pair 70.813124 45.357372 37.95%
BN128Pairing, 2 pairs 78.437754 43.266948 44.84%
BN128Pairing, 4 pairs 149.592134 81.610406 46.88%

Pairing improved in all three JVMs. Allocated bytes/op decreased by 26.19%, 36.29%, 38.49% for 1/2/4 terms. Addition and multiplication use Fp and serve as controls; their allocations were identical. Individual multiplication control timings varied by roughly -10% to +6%, indicating host noise. The host had background activity, so absolute timings should not be compared with the earlier Fp2-only run.

These are single-host, warmed execute() measurements including decoding and subgroup checks, rather than transaction TPS or Energy reductions. The table replaces the earlier Fp2-only measurements. Benchmark tooling and raw data remain outside the PR.

@coderabbitai

coderabbitai Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: e2885600-ec0f-4037-8eef-8a18642c44ed

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 7 files

Reply with feedback, questions, or to request a fix.

View guided diff | Turn on auto-fix | Re-trigger cubic

Comment thread .github/scripts/benchmark_bn128.py Resolved
Comment thread .github/scripts/benchmark_bn128.py Resolved
Federico2014 and others added 3 commits October 27, 2026 17:58
Replace the full-order G2 subgroup multiplication with the equivalent BN
Frobenius criterion and preserve the infinity fast path.

Remove the duplicate Fp6 non-residue, document the extension parameters,
and reuse specialized Fp2 constant multiplication throughout Fp6/Fp12.

Add full-order subgroup oracles, cofactor torsion rejection, sparse and
cyclotomic arithmetic regressions, and precompile invalid-point coverage.
@Federico2014 Federico2014 changed the title perf(crypto): specialize fp2 arithmetic for bn128 perf(crypto): optimize bn128 arithmetic and subgroup checks Oct 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant