Skip to content

perf(bn254): include G2 membership check in ML#1387

Merged
yelhousni merged 5 commits intomasterfrom
perf/g2-membership-in-pairing
Jan 15, 2025
Merged

perf(bn254): include G2 membership check in ML#1387
yelhousni merged 5 commits intomasterfrom
perf/g2-membership-in-pairing

Conversation

@yelhousni
Copy link
Copy Markdown
Contributor

@yelhousni yelhousni commented Jan 7, 2025

Description

Including G2 subgroup membership in the pairing computations saves a lot of constraints. For Linea zkEVM, gnark circuit has only to check G2 membership as the arithemtization does the check for G1.

In computeLines the accumulated point is [6x₀+2]Q (x₀ being the curve seed). We can tweak* the subgroup membership to check [6x₀+2]Q + ψ(Q) + ψ³(Q) == ψ²(Q) instead of ψ³([2x₀]Q) - ψ²([x₀]Q) - ψ([x₀]Q) - [x₀]Q == Q. This saves the multiplication by 6x₀+2 and enforces G2 membership check systematically in pairing calls, simplifying probably the Wizard glue.

* since x₀ ≠ 4 mod 13 and x₀ ≠ 92 mod 97 for BN254, V=(6x₀+ 2,1,−1,1) is also a valid short vector.

TL;DR: G2 subgroup membership becomes ~2 point additions instead of ~81 point additions.

Type of change

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

How has this been tested?

All current tests pass.

How has this been benchmarked?

On one hand a product of 2 pairings check increases by 18,857 scs but on the other hand the G2 membership which costs (for 2 points) 407,729 scs is removed.

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 type: perf dep: linea Issues affecting Linea downstream labels Jan 7, 2025
@yelhousni yelhousni added this to the v0.11.N milestone Jan 7, 2025
@yelhousni yelhousni requested a review from ivokub January 7, 2025 22:30
@yelhousni yelhousni self-assigned this Jan 7, 2025
@ivokub
Copy link
Copy Markdown
Collaborator

ivokub commented Jan 15, 2025

Suggested edit:

diff --git a/std/algebra/emulated/sw_bn254/pairing.go b/std/algebra/emulated/sw_bn254/pairing.go
index 4798876a..6d9d170c 100644
--- a/std/algebra/emulated/sw_bn254/pairing.go
+++ b/std/algebra/emulated/sw_bn254/pairing.go
@@ -81,10 +81,10 @@ func NewPairing(api frontend.API) (*Pairing, error) {
 	}, nil
 }
 
-// Pair calculates the reduced pairing for a set of points
-// ∏ᵢ e(Pᵢ, Qᵢ).
+// Pair calculates the reduced pairing for a set of points ∏ᵢ e(Pᵢ, Qᵢ).
 //
-// This function checks that the Qᵢ are in the correct subgroupsi, but does not check Pᵢ. See AssertIsOnG1.
+// This function checks that the Qᵢ are in the correct subgroup, but does not
+// check Pᵢ. See AssertIsOnG1.
 func (pr Pairing) Pair(P []*G1Affine, Q []*G2Affine) (*GTEl, error) {
 	res, err := pr.MillerLoop(P, Q)
 	if err != nil {
@@ -206,10 +206,13 @@ func (pr Pairing) AssertFinalExponentiationIsOne(a *GTEl) {
 	pr.AssertIsEqual(t0, t2)
 }
 
-// PairingCheck calculates the reduced pairing for a set of points and asserts if the result is One
-// ∏ᵢ e(Pᵢ, Qᵢ) =? 1
+// PairingCheck calculates the reduced pairing for a set of points and asserts
+// if the result is one:
 //
-// This function checks that the Qᵢ are in the correct subgroupsi, but does not check Pᵢ. See AssertIsOnG1.
+//	∏ᵢ e(Pᵢ, Qᵢ) =? 1
+//
+// This function checks that the Qᵢ are in the correct subgroup, but does not
+// check Pᵢ. See AssertIsOnG1.
 func (pr Pairing) PairingCheck(P []*G1Affine, Q []*G2Affine) error {
 	f, err := pr.MillerLoop(P, Q)
 	if err != nil {

@ivokub
Copy link
Copy Markdown
Collaborator

ivokub commented Jan 15, 2025

Suggested edit:

diff --git a/std/evmprecompiles/08-bnpairing.go b/std/evmprecompiles/08-bnpairing.go
index b5bd7a54..f4ff6b1b 100644
--- a/std/evmprecompiles/08-bnpairing.go
+++ b/std/evmprecompiles/08-bnpairing.go
@@ -76,7 +76,6 @@ func ECPairMillerLoopAndMul(api frontend.API, accumulator *sw_bn254.GTEl, P *sw_
 	if err != nil {
 		return fmt.Errorf("new pairing: %w", err)
 	}
-	pairing.AssertIsOnG2(Q)
 	ml, err := pairing.MillerLoopAndMul(P, Q, accumulator)
 	if err != nil {
 		return fmt.Errorf("miller loop and mul: %w", err)
@@ -94,7 +93,6 @@ func ECPairMillerLoopAndFinalExpCheck(api frontend.API, accumulator *sw_bn254.GT
 	if err != nil {
 		return fmt.Errorf("new pairing: %w", err)
 	}
-	pairing.AssertIsOnG2(Q)
 
 	isSuccess := pairing.IsMillerLoopAndFinalExpOne(P, Q, accumulator)
 	api.AssertIsEqual(expectedIsSuccess, isSuccess)

Copy link
Copy Markdown
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.

Looks very good. However, in the context of Linea we also need to remove the G2 subgroup checks from the ECPairMillerLoopAndMul and ECPairMillerLoopAndFinalExpCheck methods. These are the ones called from the precompile glue.

I created suggested edits for that and also for some method comments. If you can include them then good to merge from my side.

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

Labels

dep: linea Issues affecting Linea downstream type: perf

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants