Skip to content

Commit

Permalink
perf(bn254): include G2 membership check in ML (#1387)
Browse files Browse the repository at this point in the history
  • Loading branch information
yelhousni authored Jan 15, 2025
1 parent dcd7cb3 commit cfa30d9
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 19 deletions.
4 changes: 2 additions & 2 deletions internal/stats/latest_stats.csv
Original file line number Diff line number Diff line change
Expand Up @@ -181,14 +181,14 @@ pairing_bls24315,bls24_315,plonk,0,0
pairing_bls24315,bls24_317,plonk,0,0
pairing_bls24315,bw6_761,plonk,0,0
pairing_bls24315,bw6_633,plonk,141249,141249
pairing_bn254,bn254,groth16,604783,990919
pairing_bn254,bn254,groth16,607378,995098
pairing_bn254,bls12_377,groth16,0,0
pairing_bn254,bls12_381,groth16,0,0
pairing_bn254,bls24_315,groth16,0,0
pairing_bn254,bls24_317,groth16,0,0
pairing_bn254,bw6_761,groth16,0,0
pairing_bn254,bw6_633,groth16,0,0
pairing_bn254,bn254,plonk,2319665,2030447
pairing_bn254,bn254,plonk,2329131,2039205
pairing_bn254,bls12_377,plonk,0,0
pairing_bn254,bls12_381,plonk,0,0
pairing_bn254,bls24_315,plonk,0,0
Expand Down
2 changes: 1 addition & 1 deletion std/algebra/emulated/sw_bn254/g2.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func (g2 *G2) phi(q *G2Affine) *G2Affine {
return &G2Affine{
P: g2AffP{
X: *x,
Y: q.P.Y,
Y: *g2.Ext2.Neg(&q.P.Y),
},
}
}
Expand Down
1 change: 0 additions & 1 deletion std/algebra/emulated/sw_bn254/g2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ type endomorphismG2Circuit struct {
func (c *endomorphismG2Circuit) Define(api frontend.API) error {
g2 := NewG2(api)
res1 := g2.phi(&c.In1)
res1 = g2.neg(res1)
res2 := g2.psi(&c.In1)
res2 = g2.psi(res2)
g2.AssertIsEqual(res1, res2)
Expand Down
22 changes: 14 additions & 8 deletions std/algebra/emulated/sw_bn254/pairing.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 doesn't check that the inputs are in the correct subgroups. See AssertIsOnG1 and AssertIsOnG2.
// 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 {
Expand Down Expand Up @@ -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 doesn't check that the inputs are in the correct subgroups. See AssertIsOnG1 and AssertIsOnG2.
// ∏ᵢ 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 {
Expand Down Expand Up @@ -266,6 +269,7 @@ func (pr Pairing) AssertIsOnG1(P *G1Affine) {
pr.AssertIsOnCurve(P)
}

// computeG2ShortVector computes ψ³([2x₀]Q) - ψ²([x₀]Q) - ψ([x₀]Q) - [x₀]Q
func (pr Pairing) computeG2ShortVector(Q *G2Affine) (_Q *G2Affine) {
// [x₀]Q
xQ := pr.g2.scalarMulBySeed(Q)
Expand All @@ -278,7 +282,7 @@ func (pr Pairing) computeG2ShortVector(Q *G2Affine) (_Q *G2Affine) {
psi3xxQ = pr.g2.psi(psi3xxQ)

// _Q = ψ³([2x₀]Q) - ψ²([x₀]Q) - ψ([x₀]Q) - [x₀]Q
_Q = pr.g2.sub(psi2xQ, psi3xxQ)
_Q = pr.g2.sub(psi3xxQ, psi2xQ)
_Q = pr.g2.sub(_Q, psixQ)
_Q = pr.g2.sub(_Q, xQ)
return _Q
Expand All @@ -289,8 +293,10 @@ func (pr Pairing) AssertIsOnG2(Q *G2Affine) {
pr.AssertIsOnTwist(Q)

// 2- Check Q has the right subgroup order
// [r]Q == 0 <==> ψ³([2x₀]Q) - ψ²([x₀]Q) - ψ([x₀]Q) - [x₀]Q == Q
// This is a valid short vector since x₀ ≠ 5422 mod 2196.
// See Sec. 3.1.2 (Example 1) in https://eprint.iacr.org/2022/348.
_Q := pr.computeG2ShortVector(Q)
// [r]Q == 0 <==> _Q == Q
pr.g2.AssertIsEqual(Q, _Q)
}

Expand Down
18 changes: 18 additions & 0 deletions std/algebra/emulated/sw_bn254/precomputations.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ func precomputeLines(Q bn254.G2Affine) lineEvaluations {

func (p *Pairing) computeLines(Q *g2AffP) lineEvaluations {

// check Q is on curve
Qaff := G2Affine{P: *Q, Lines: nil}
p.IsOnTwist(&Qaff)

var cLines lineEvaluations
Qacc := Q
n := len(bn254.LoopCounter)
Expand All @@ -50,6 +54,20 @@ func (p *Pairing) computeLines(Q *g2AffP) lineEvaluations {
}
}

// Check that Q is on G2 subgroup:
// [r]Q == 0 <==> [6x₀+2]Q + ψ(Q) + ψ³(Q) = ψ²(Q).
// This is a valid short vector since x₀ ≠ 4 mod 13 and x₀ ≠ 92 mod 97.
// See Sec. 3.1.2 (Remark 2) in https://eprint.iacr.org/2022/348.
// This test is equivalent to [computeG2ShortVector] in [AssertIsOnG2].
//
// At this point Qacc = [6x₀+2]Q.
psiQ := p.g2.psi(&Qaff) // ψ(Q)
psi2Q := p.g2.phi(&Qaff) // ϕ(Q)=ψ²(Q)
psi3Q := p.g2.psi(psi2Q) // ψ³(Q)
lhs := p.g2.add(&G2Affine{P: *Qacc, Lines: nil}, psiQ)
lhs = p.g2.add(lhs, psi3Q)
p.g2.AssertIsEqual(lhs, psi2Q)

Q1X := p.Ext2.Conjugate(&Q.X)
Q1X = p.Ext2.MulByNonResidue1Power2(Q1X)
Q1Y := p.Ext2.Conjugate(&Q.Y)
Expand Down
9 changes: 2 additions & 7 deletions std/evmprecompiles/08-bnpairing.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,8 @@ func ECPair(api frontend.API, P []*sw_bn254.G1Affine, Q []*sw_bn254.G2Affine) {
if err != nil {
panic(err)
}
// 1- Check that Pᵢ are on G1 (done in the zkEVM ⚠️ )
// 2- Check that Qᵢ are on G2
for i := 0; i < len(Q); i++ {
pair.AssertIsOnG2(Q[i])
}
// 1- Check that Pᵢ are on G1 (done in the zkEVM ⚠️
// 2- Check that Qᵢ are on G2 (done in `computeLines` in `MillerLoopAndMul` and `MillerLoopAndFinalExpCheck)

// 3- Check that ∏ᵢ e(Pᵢ, Qᵢ) == 1
ml := pair.Ext12.One()
Expand Down Expand Up @@ -79,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)
Expand All @@ -97,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)
Expand Down

0 comments on commit cfa30d9

Please sign in to comment.