Skip to content

Commit

Permalink
Merge pull request #613 from ConsenSys/fix-605
Browse files Browse the repository at this point in the history
Fix(emulated pairing): edge cases in torus-based final exp
  • Loading branch information
yelhousni authored Apr 4, 2023
2 parents 17e2743 + 5b819fe commit 6939cf5
Show file tree
Hide file tree
Showing 17 changed files with 613 additions and 239 deletions.
40 changes: 37 additions & 3 deletions std/algebra/emulated/fields_bls12381/e12.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package fields_bls12381

import (
bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381"
"github.com/consensys/gnark/frontend"
)

type E12 struct {
Expand All @@ -12,8 +13,8 @@ type Ext12 struct {
*Ext6
}

func NewExt12(baseField *curveF) *Ext12 {
return &Ext12{Ext6: NewExt6(baseField)}
func NewExt12(api frontend.API) *Ext12 {
return &Ext12{Ext6: NewExt6(api)}
}

func (e Ext12) Add(x, y *E12) *E12 {
Expand Down Expand Up @@ -58,6 +59,22 @@ func (e Ext12) Mul(x, y *E12) *E12 {
}
}

func (e Ext12) Zero() *E12 {
zero := e.fp.Zero()
return &E12{
C0: E6{
B0: E2{A0: *zero, A1: *zero},
B1: E2{A0: *zero, A1: *zero},
B2: E2{A0: *zero, A1: *zero},
},
C1: E6{
B0: E2{A0: *zero, A1: *zero},
B1: E2{A0: *zero, A1: *zero},
B2: E2{A0: *zero, A1: *zero},
},
}
}

func (e Ext12) One() *E12 {
z000 := e.fp.One()
zero := e.fp.Zero()
Expand All @@ -75,6 +92,12 @@ func (e Ext12) One() *E12 {
}
}

func (e Ext12) IsZero(z *E12) frontend.Variable {
c0 := e.Ext6.IsZero(&z.C0)
c1 := e.Ext6.IsZero(&z.C1)
return e.api.And(c0, c1)
}

func (e Ext12) Square(x *E12) *E12 {
c0 := e.Ext6.Sub(&x.C0, &x.C1)
c3 := e.Ext6.MulByNonResidue(&x.C1)
Expand Down Expand Up @@ -135,7 +158,6 @@ func (e Ext12) Inverse(x *E12) *E12 {

}

// DivUnchecked e2 elmts
func (e Ext12) DivUnchecked(x, y *E12) *E12 {
res, err := e.fp.NewHint(divE12Hint, 12, &x.C0.B0.A0, &x.C0.B0.A1, &x.C0.B1.A0, &x.C0.B1.A1, &x.C0.B2.A0, &x.C0.B2.A1, &x.C1.B0.A0, &x.C1.B0.A1, &x.C1.B1.A0, &x.C1.B1.A1, &x.C1.B2.A0, &x.C1.B2.A1, &y.C0.B0.A0, &y.C0.B0.A1, &y.C0.B1.A0, &y.C0.B1.A1, &y.C0.B2.A0, &y.C0.B2.A1, &y.C1.B0.A0, &y.C1.B0.A1, &y.C1.B1.A0, &y.C1.B1.A1, &y.C1.B2.A0, &y.C1.B2.A1)

Expand Down Expand Up @@ -163,3 +185,15 @@ func (e Ext12) DivUnchecked(x, y *E12) *E12 {

return &div
}

func (e Ext12) Select(selector frontend.Variable, z1, z0 *E12) *E12 {
c0 := e.Ext6.Select(selector, &z1.C0, &z0.C0)
c1 := e.Ext6.Select(selector, &z1.C1, &z0.C1)
return &E12{C0: *c0, C1: *c1}
}

func (e Ext12) Lookup2(s1, s2 frontend.Variable, a, b, c, d *E12) *E12 {
c0 := e.Ext6.Lookup2(s1, s2, &a.C0, &b.C0, &c.C0, &d.C0)
c1 := e.Ext6.Lookup2(s1, s2, &a.C1, &b.C1, &c.C1, &d.C1)
return &E12{C0: *c0, C1: *c1}
}
53 changes: 16 additions & 37 deletions std/algebra/emulated/fields_bls12381/e12_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"github.com/consensys/gnark-crypto/ecc"
bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/std/math/emulated"
"github.com/consensys/gnark/test"
)

Expand All @@ -15,8 +14,7 @@ type e12Add struct {
}

func (circuit *e12Add) Define(api frontend.API) error {
ba, _ := emulated.NewField[emulated.BLS12381Fp](api)
e := NewExt12(ba)
e := NewExt12(api)
expected := e.Add(&circuit.A, &circuit.B)
e.AssertIsEqual(expected, &circuit.C)
return nil
Expand Down Expand Up @@ -47,8 +45,7 @@ type e12Sub struct {
}

func (circuit *e12Sub) Define(api frontend.API) error {
ba, _ := emulated.NewField[emulated.BLS12381Fp](api)
e := NewExt12(ba)
e := NewExt12(api)
expected := e.Sub(&circuit.A, &circuit.B)
e.AssertIsEqual(expected, &circuit.C)
return nil
Expand Down Expand Up @@ -79,9 +76,7 @@ type e12Mul struct {
}

func (circuit *e12Mul) Define(api frontend.API) error {
ba, _ := emulated.NewField[emulated.BLS12381Fp](api)
e := NewExt12(ba)

e := NewExt12(api)
expected := e.Mul(&circuit.A, &circuit.B)
e.AssertIsEqual(expected, &circuit.C)
return nil
Expand Down Expand Up @@ -112,9 +107,7 @@ type e12Div struct {
}

func (circuit *e12Div) Define(api frontend.API) error {
ba, _ := emulated.NewField[emulated.BLS12381Fp](api)
e := NewExt12(ba)

e := NewExt12(api)
expected := e.DivUnchecked(&circuit.A, &circuit.B)
e.AssertIsEqual(expected, &circuit.C)
return nil
Expand Down Expand Up @@ -145,9 +138,7 @@ type e12Square struct {
}

func (circuit *e12Square) Define(api frontend.API) error {
ba, _ := emulated.NewField[emulated.BLS12381Fp](api)
e := NewExt12(ba)

e := NewExt12(api)
expected := e.Square(&circuit.A)
e.AssertIsEqual(expected, &circuit.C)
return nil
Expand Down Expand Up @@ -177,8 +168,7 @@ type e12Conjugate struct {
}

func (circuit *e12Conjugate) Define(api frontend.API) error {
ba, _ := emulated.NewField[emulated.BLS12381Fp](api)
e := NewExt12(ba)
e := NewExt12(api)
expected := e.Conjugate(&circuit.A)
e.AssertIsEqual(expected, &circuit.C)

Expand Down Expand Up @@ -208,8 +198,7 @@ type e12Inverse struct {
}

func (circuit *e12Inverse) Define(api frontend.API) error {
ba, _ := emulated.NewField[emulated.BLS12381Fp](api)
e := NewExt12(ba)
e := NewExt12(api)
expected := e.Inverse(&circuit.A)
e.AssertIsEqual(expected, &circuit.C)

Expand Down Expand Up @@ -239,8 +228,7 @@ type e12ExptTorus struct {
}

func (circuit *e12ExptTorus) Define(api frontend.API) error {
ba, _ := emulated.NewField[emulated.BLS12381Fp](api)
e := NewExt12(ba)
e := NewExt12(api)
z := e.ExptTorus(&circuit.A)
expected := e.DecompressTorus(z)
e.AssertIsEqual(expected, &circuit.C)
Expand Down Expand Up @@ -280,9 +268,7 @@ type e12MulBy014 struct {
}

func (circuit *e12MulBy014) Define(api frontend.API) error {

ba, _ := emulated.NewField[emulated.BLS12381Fp](api)
e := NewExt12(ba)
e := NewExt12(api)
res := e.MulBy014(&circuit.A, &circuit.B, &circuit.C)
e.AssertIsEqual(res, &circuit.W)
return nil
Expand Down Expand Up @@ -320,8 +306,7 @@ type torusCompress struct {
}

func (circuit *torusCompress) Define(api frontend.API) error {
ba, _ := emulated.NewField[emulated.BLS12381Fp](api)
e := NewExt12(ba)
e := NewExt12(api)
expected := e.CompressTorus(&circuit.A)
e.Ext6.AssertIsEqual(expected, &circuit.C)
return nil
Expand Down Expand Up @@ -358,8 +343,7 @@ type torusDecompress struct {
}

func (circuit *torusDecompress) Define(api frontend.API) error {
ba, _ := emulated.NewField[emulated.BLS12381Fp](api)
e := NewExt12(ba)
e := NewExt12(api)
compressed := e.CompressTorus(&circuit.A)
expected := e.DecompressTorus(compressed)
e.AssertIsEqual(expected, &circuit.C)
Expand Down Expand Up @@ -399,8 +383,7 @@ type torusMul struct {
}

func (circuit *torusMul) Define(api frontend.API) error {
ba, _ := emulated.NewField[emulated.BLS12381Fp](api)
e := NewExt12(ba)
e := NewExt12(api)
compressedA := e.CompressTorus(&circuit.A)
compressedB := e.CompressTorus(&circuit.B)
compressedAB := e.MulTorus(compressedA, compressedB)
Expand Down Expand Up @@ -447,8 +430,7 @@ type torusInverse struct {
}

func (circuit *torusInverse) Define(api frontend.API) error {
ba, _ := emulated.NewField[emulated.BLS12381Fp](api)
e := NewExt12(ba)
e := NewExt12(api)
compressed := e.CompressTorus(&circuit.A)
compressed = e.InverseTorus(compressed)
expected := e.DecompressTorus(compressed)
Expand Down Expand Up @@ -487,8 +469,7 @@ type torusFrobenius struct {
}

func (circuit *torusFrobenius) Define(api frontend.API) error {
ba, _ := emulated.NewField[emulated.BLS12381Fp](api)
e := NewExt12(ba)
e := NewExt12(api)
compressed := e.CompressTorus(&circuit.A)
compressed = e.FrobeniusTorus(compressed)
expected := e.DecompressTorus(compressed)
Expand Down Expand Up @@ -527,8 +508,7 @@ type torusFrobeniusSquare struct {
}

func (circuit *torusFrobeniusSquare) Define(api frontend.API) error {
ba, _ := emulated.NewField[emulated.BLS12381Fp](api)
e := NewExt12(ba)
e := NewExt12(api)
compressed := e.CompressTorus(&circuit.A)
compressed = e.FrobeniusSquareTorus(compressed)
expected := e.DecompressTorus(compressed)
Expand Down Expand Up @@ -567,8 +547,7 @@ type torusSquare struct {
}

func (circuit *torusSquare) Define(api frontend.API) error {
ba, _ := emulated.NewField[emulated.BLS12381Fp](api)
e := NewExt12(ba)
e := NewExt12(api)
compressed := e.CompressTorus(&circuit.A)
compressed = e.SquareTorus(compressed)
expected := e.DecompressTorus(compressed)
Expand Down
28 changes: 25 additions & 3 deletions std/algebra/emulated/fields_bls12381/e2.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"math/big"

bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/std/math/emulated"
)

Expand All @@ -15,11 +16,16 @@ type E2 struct {
}

type Ext2 struct {
api frontend.API
fp *curveF
nonResidues map[int]map[int]*E2
}

func NewExt2(baseField *curveF) *Ext2 {
func NewExt2(api frontend.API) *Ext2 {
fp, err := emulated.NewField[emulated.BLS12381Fp](api)
if err != nil {
panic(err)
}
pwrs := map[int]map[int]struct {
A0 string
A1 string
Expand Down Expand Up @@ -49,7 +55,7 @@ func NewExt2(baseField *curveF) *Ext2 {
nonResidues[pwr][coeff] = &el
}
}
return &Ext2{fp: baseField, nonResidues: nonResidues}
return &Ext2{api: api, fp: fp, nonResidues: nonResidues}
}

func (e Ext2) MulByElement(x *E2, y *baseEl) *E2 {
Expand Down Expand Up @@ -236,6 +242,11 @@ func (e Ext2) Zero() *E2 {
A1: *z1,
}
}
func (e Ext2) IsZero(z *E2) frontend.Variable {
a0 := e.fp.IsZero(&z.A0)
a1 := e.fp.IsZero(&z.A1)
return e.api.And(a0, a1)
}

// returns 1+u
func (e Ext2) NonResidue() *E2 {
Expand Down Expand Up @@ -301,7 +312,6 @@ func (e Ext2) Inverse(x *E2) *E2 {

}

// DivUnchecked e2 elmts
func (e Ext2) DivUnchecked(x, y *E2) *E2 {
res, err := e.fp.NewHint(divE2Hint, 2, &x.A0, &x.A1, &y.A0, &y.A1)
if err != nil {
Expand All @@ -320,3 +330,15 @@ func (e Ext2) DivUnchecked(x, y *E2) *E2 {

return &div
}

func (e Ext2) Select(selector frontend.Variable, z1, z0 *E2) *E2 {
a0 := e.fp.Select(selector, &z1.A0, &z0.A0)
a1 := e.fp.Select(selector, &z1.A1, &z0.A1)
return &E2{A0: *a0, A1: *a1}
}

func (e Ext2) Lookup2(s1, s2 frontend.Variable, a, b, c, d *E2) *E2 {
a0 := e.fp.Lookup2(s1, s2, &a.A0, &b.A0, &c.A0, &d.A0)
a1 := e.fp.Lookup2(s1, s2, &a.A1, &b.A1, &c.A1, &d.A1)
return &E2{A0: *a0, A1: *a1}
}
Loading

0 comments on commit 6939cf5

Please sign in to comment.