Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add Pectra BLS12-381 elliptic curve precompiles #1447

Open
wants to merge 56 commits into
base: master
Choose a base branch
from

Conversation

yelhousni
Copy link
Contributor

@yelhousni yelhousni commented Mar 14, 2025

Description

This PR adds gnark circuits corresponding to precompiles for BLS12-381 curve operations https://eips.ethereum.org/EIPS/eip-2537.

TODO:

  • BLS12_PAIRING_CHECK: inlcude G2 memerbship in Miller loop (lines computation).
  • BLS12_G2ADD: check the two addends are on G2.
  • BLS12_G2MSM: optimized ScalarMul() with GLV
    • GLS? fakeGLS? GLV/S+fakeGLV/S?
  • BLS12_G1MSM and BLS12_G2MSM: optimize MSM algorithm.

Type of change

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

How has this been tested?

Tests are implemented in std/evmprecompiles/bls_test.go.

How has this been benchmarked?

PLONK (on BLS12-377) number of constraints (scs):

precompile curve membership test? subgroup membership test? constraints (scs)
BLS12_G1ADD Yes No 9 641
BLS12_G2ADD Yes No 23 668
precompile curve membership test? subgroup membership test? constraints (scs)
BLS12_G1MSM (1 pair)
Scalar Multiplication
Yes Yes 590 418
BLS12_G1MSM (2 pairs) Yes Yes 1 132 727
BLS12_G1MSM (3 pairs) Yes Yes 1 569 303
BLS12_G1MSM (5 pairs) Yes Yes 2 442 455
BLS12_G1MSM (10 pairs) Yes Yes 4 625 335
BLS12_G1MSM (20 pairs) Yes Yes 8 991 095
BLS12_G1MSM (100 pairs) Yes Yes 43 917 175
precompile curve membership test? subgroup membership test? constraints (scs)
BLS12_G2MSM (1 pair)
Scalar Multiplication
Yes Yes 1 225 743
BLS12_G2MSM (2 pairs) Yes Yes 2 196 208
BLS12_G2MSM (3 pairs) Yes Yes 3 166 673
BLS12_G2MSM (5 pairs) Yes Yes 5 107 603
BLS12_G2MSM (10 pairs) Yes Yes 9 959 981
BLS12_G2MSM (20 pairs) Yes Yes 19 665 567
BLS12_G2MSM (50 pairs) Yes Yes 48 794 236
precompile curve membership test? subgroup membership test? constraints (scs)
BLS12_PAIRING_CHECK (2 pairs) Yes Yes 2 821 323
BLS12_PAIRING_CHECK (4 pairs) Yes Yes 4 993 571
BLS12_PAIRING_CHECK (9 pairs) Yes Yes 10 424 481
BLS12_PAIRING_CHECK (20 pairs) Yes Yes 22 371 551

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

@yelhousni yelhousni added this to the v0.11.N milestone Mar 14, 2025
@yelhousni yelhousni self-assigned this Mar 14, 2025
Copy link
Collaborator

@ivokub ivokub left a comment

Choose a reason for hiding this comment

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

In principle looks good. But had a few comments about optimizing some computations and refactoring a bit.

Map to G1 is still ongoing. I'll rewrite a bit to have less duplication and better interfaces. Also need to add tests in the evmprecompiles packages.

return left, right
}

func (g1 *G1) AssertIsOnCurve(P *G1Affine) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

We have now two duplicate methods imo for AssertIsOnCurve depending how we initialize BLS12 curve - if through the generic factory in std/algebra, then we get the implementation of sw_emulated and if we initialize G1 here then we get the current implementation. Imo it is not perfect and may have confusion and mismatch.

One approach we could take is to have AssertIsOnCurve and AssertIsOnG1 in the std/algebra.Curve interface, but this would require implementing it also for 2-chain curves. Maybe we can right now mark them TODO by panicking and then implementing later? Then in the precompile packages can use sw_emulated for Curve ops instead of G1 here.

g1.curveF.AssertIsEqual(&p.Y, &q.Y)
}

func (g1 *G1) IsEqual(p, q *G1Affine) frontend.Variable {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same for AssertIsOnCurve and AssertIsOnG1. It could be part of Curve interface and we can implement in sw_emulated instead

@ivokub
Copy link
Collaborator

ivokub commented Apr 7, 2025

I added Consensys/gnark-crypto#674 - I'll go over G2 map to curve to see that it is also useful for #1040.

Otherwise the map to curve also looks good. @yelhousni - please re-request review when you have addressed all the comments and I'll re-review. I had to merge master because there were some changes due to gnark-crypto API changes.

@yelhousni yelhousni requested a review from ivokub April 8, 2025 16:11
@yelhousni
Copy link
Contributor Author

I added Consensys/gnark-crypto#674 - I'll go over G2 map to curve to see that it is also useful for #1040.

Otherwise the map to curve also looks good. @yelhousni - please re-request review when you have addressed all the comments and I'll re-review. I had to merge master because there were some changes due to gnark-crypto API changes.

Addressed all the points except the AssertIsOnCurve and AssertIsOnG1 in the std/algebra.Curve interface. No strong opinion here.

@ivokub
Copy link
Collaborator

ivokub commented Apr 9, 2025

I added Consensys/gnark-crypto#674 - I'll go over G2 map to curve to see that it is also useful for #1040.
Otherwise the map to curve also looks good. @yelhousni - please re-request review when you have addressed all the comments and I'll re-review. I had to merge master because there were some changes due to gnark-crypto API changes.

Addressed all the points except the AssertIsOnCurve and AssertIsOnG1 in the std/algebra.Curve interface. No strong opinion here.

Yup - I think we could try to keep it simple for now. The only thing I'm worried about when having duplicate implementations (in sw_emulated and sw_bls12381) is that it may cause confusion when auditing or debugging bugs. I'll have another look, maybe I can come up with some idea while @ThomasPiellard is addressing the missing test comment.

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

Successfully merging this pull request may close these issues.

4 participants