Skip to content

Conversation

@yelhousni
Copy link
Collaborator

@yelhousni yelhousni commented Jan 29, 2026

Description

In fixed-argument pairing we use affine coordinates to pre-compute all the lines. The pre-computation loop iterates over a fixed constant with low-Hamming weight. For consecutive zeros, this PR computes k doubleStep more efficiently as manyDoubleSteps(k) following "Efficient Scalar Multiplications on Elliptic Curves without Repeated Doublings and Their Practical Performance" (Alg. 1) by Sakai and Sakurai. Then we merge manyDoubleSteps(k) with doubleAndAddStep (from #797) in manyDoubleStepsAndAdd(k) by batching their respective inverse computations.
Following Table 1 in the paper, and benchmarking the cost ratio of inverse and multiplication in Fp2 for each curve, we choose k=3 as the crossover point to use manyDoubleSteps. For BLS24, it is faster to use a loop-based version with doubleStep and doubleAndAddStep.

Type of change

  • New feature (non-breaking change which adds functionality)

How has this been tested?

Refactored test into TestFixedPairing.

How has this been benchmarked?

Curve Old (µs) New (µs) Speedup
BLS12-381 220.5 142.3 35.5%
BLS12-377 217.7 157.4 27.7%
BN254 118.1 108.1 8.5%
BW6-761 2758.4 1273.6 53.8%
  • BN254 loop counter does not have many consecutive zeros.
  • BLS24 do not use manyDoubleSteps but only doubleAndAddStep (not implemented before).
  • BW6-633 shows similar results but it is less optimized

Checklist:

  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • I have added tests that prove my fix is effective or that my feature works
  • I did not modify files generated from templates
  • golangci-lint does not output errors locally
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules

Note

High Risk
High risk because it changes core pairing precomputation and line evaluation logic across multiple curves using new batch-inversion recurrences; any mistake can silently break cryptographic correctness despite added tests.

Overview
Speeds up fixed-argument pairings by introducing manyDoubleSteps (batch k doublings with one inversion) and, where beneficial, manyDoublesAndAdd (fuse k doublings + doubleAndAddStep into one batch inversion) and wiring these into PrecomputeLines for bls12-377, bls12-381, bn254, bw6-633, and bw6-761.

For bls24-315/bls24-317, updates PrecomputeLines to use doubleAndAddStep (ELM-based, single-inversion) for non-zero loop counter steps, and adds manyDoubleSteps where applicable.

Testing is reorganized and strengthened: removes pairing_compatibility_test.go files, moves reference implementations into pairing_test.go, adds property tests comparing optimized vs reference PrecomputeLines/manyDoubleSteps, and updates the test generator template to match the new test structure.

Written by Cursor Bugbot for commit 30030d0. This will update automatically on new commits. Configure here.

@yelhousni yelhousni added this to the v0.19.N milestone Jan 29, 2026
@yelhousni yelhousni requested review from Copilot and ivokub January 29, 2026 23:29
@yelhousni yelhousni added type: perf dep: linea Issues affecting downstream Linea labels Jan 29, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR optimizes fixed-argument pairing operations by implementing a batch doubling algorithm (manyDoubleSteps) that reduces the number of field inversions. The optimization applies to consecutive zero bits in the loop counter by computing k doublings with a single batch inversion instead of k individual inversions.

Changes:

  • Implements manyDoubleSteps function for bn254, bls12-381, bls12-377, bw6-761, bw6-633 curves
  • Adds doubleAndAddStep function for bls24-315 and bls24-317 curves
  • Refactors test structure into separate test functions (TestPairing, TestFixedPairing, TestMillerLoop, TestExponentiation, TestTorusCompression)
  • Moves reference implementations from separate compatibility test files into main test files
  • Unrolls PrecomputeLines loops for better performance

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 1 comment.

File Description
internal/generator/pairing/template/tests/pairing.go.tmpl Test refactoring and reference implementations
ecc/*/pairing.go Implements manyDoubleSteps and unrolled PrecomputeLines
ecc/*/pairing_test.go Reorganized tests with new structure
ecc/*/pairing_compatibility_test.go Deleted (moved to main test file)

@gbotrel gbotrel requested a review from YaoJGalteland January 30, 2026 18:22
@yelhousni yelhousni self-assigned this Jan 30, 2026

// manyDoubleSteps performs k consecutive doublings on p and returns the line evaluations.
// It uses a recurrence to compute 2^k*P with a single batch inversion.
func (p *G2Affine) manyDoubleSteps(k int, evaluations []LineEvaluationAff) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this unused? Additionally, PrecomputeLines is missing manyDoublesAndAdd, is the batching double not applied to all curves? This seems like an incomplete optimization.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dep: linea Issues affecting downstream Linea type: perf

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants