Skip to content

Commit

Permalink
Merge pull request #182 from ConsenSys/std/pairing
Browse files Browse the repository at this point in the history
Pairing + Groth16 verifier std gadgets
  • Loading branch information
ThomasPiellard authored Nov 22, 2021
2 parents 0652866 + 0913017 commit 4d853c7
Show file tree
Hide file tree
Showing 10 changed files with 382 additions and 166 deletions.
12 changes: 6 additions & 6 deletions std/algebra/fields/e12.go
Original file line number Diff line number Diff line change
Expand Up @@ -330,18 +330,18 @@ func (e *E12) Conjugate(api frontend.API, e1 E12) *E12 {
}

// MulBy034 multiplication by sparse element
func (e *E12) MulBy034(api frontend.API, c0, c3, c4 E2, ext Extension) *E12 {
func (e *E12) MulBy034(api frontend.API, c3, c4 E2, ext Extension) *E12 {

var a, b, d E6
var d E6

a.MulByE2(api, e.C0, c0, ext)
a := e.C0
b := e.C1

b = e.C1
b.MulBy01(api, c3, c4, ext)

c0.Add(api, c0, c3)
c3.Add(api, E2{A0: 1, A1: 0}, c3)
d.Add(api, e.C0, e.C1)
d.MulBy01(api, c0, c4, ext)
d.MulBy01(api, c3, c4, ext)

e.C1.Add(api, a, b).Neg(api, e.C1).Add(api, e.C1, d)
e.C0.MulByNonResidue(api, b, ext).Add(api, e.C0, a)
Expand Down
16 changes: 7 additions & 9 deletions std/algebra/fields/e12_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,14 +364,14 @@ func TestExpFinalExpoFp12(t *testing.T) {
}

type fp12MulBy034 struct {
A E12 `gnark:",public"`
W E12
B, C, D E2
A E12 `gnark:",public"`
W E12
B, C E2
}

func (circuit *fp12MulBy034) Define(api frontend.API) error {
ext := GetBLS377ExtensionFp12(api)
circuit.A.MulBy034(api, circuit.B, circuit.C, circuit.D, ext)
circuit.A.MulBy034(api, circuit.B, circuit.C, ext)
circuit.A.MustBeEqual(api, circuit.W)
return nil
}
Expand All @@ -381,7 +381,8 @@ func TestFp12MulBy034(t *testing.T) {
var circuit, witness fp12MulBy034

var a bls12377.E12
var b, c, d bls12377.E2
var b, c, one bls12377.E2
one.SetOne()
a.SetRandom()
witness.A.Assign(&a)

Expand All @@ -391,10 +392,7 @@ func TestFp12MulBy034(t *testing.T) {
c.SetRandom()
witness.C.Assign(&c)

d.SetRandom()
witness.D.Assign(&d)

a.MulBy034(&b, &c, &d)
a.MulBy034(&one, &b, &c)

witness.W.Assign(&a)

Expand Down
33 changes: 33 additions & 0 deletions std/algebra/sw/g1.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,3 +252,36 @@ func (p *G1Affine) MustBeEqual(api frontend.API, other G1Affine) {
api.AssertIsEqual(p.X, other.X)
api.AssertIsEqual(p.Y, other.Y)
}

// DoubleAndAdd computes 2*p1+p in affine coords
func (p *G1Affine) DoubleAndAdd(api frontend.API, p1, p2 *G1Affine) *G1Affine {

// compute lambda1 = (y2-y1)/(x2-x1)
l1 := api.DivUnchecked(api.Sub(p1.Y, p2.Y), api.Sub(p1.X, p2.X))

// compute x3 = lambda1**2-x1-x2
x3 := api.Mul(l1, l1)
x3 = api.Sub(x3, p1.X)
x3 = api.Sub(x3, p2.X)

// omit y3 computation
// compute lambda2 = -lambda1-2*y1/(x3-x1)
l2 := api.DivUnchecked(api.Add(p1.Y, p1.Y), api.Sub(x3, p1.X))
l2 = api.Add(l2, l1)
l2 = api.Neg(l2)

// compute x4 =lambda2**2-x1-x3
x4 := api.Mul(l2, l2)
x4 = api.Sub(x4, p1.X)
x4 = api.Sub(x4, x3)

// compute y4 = lambda2*(x1 - x4)-y1
y4 := api.Sub(p1.X, x4)
y4 = api.Mul(l2, y4)
y4 = api.Sub(y4, p1.Y)

p.X = x4
p.Y = y4

return p
}
41 changes: 41 additions & 0 deletions std/algebra/sw/g1_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,47 @@ func TestDoubleAffineG1(t *testing.T) {

}

// -------------------------------------------------------------------------------------------------
// DoubleAndAdd affine

type g1DoubleAndAddAffine struct {
A, B G1Affine
C G1Affine `gnark:",public"`
}

func (circuit *g1DoubleAndAddAffine) Define(api frontend.API) error {
expected := circuit.A
expected.DoubleAndAdd(api, &circuit.A, &circuit.B)
expected.MustBeEqual(api, circuit.C)
return nil
}

func TestDoubleAndAddAffineG1(t *testing.T) {

// sample 2 random points
_a := randomPointG1()
_b := randomPointG1()
var a, b, c bls12377.G1Affine
a.FromJacobian(&_a)
b.FromJacobian(&_b)

// create the cs
var circuit, witness g1DoubleAndAddAffine

// assign the inputs
witness.A.Assign(&a)
witness.B.Assign(&b)

// compute the result
_a.Double(&_a).AddAssign(&_b)
c.FromJacobian(&_a)
witness.C.Assign(&c)

assert := test.NewAssert(t)
assert.SolvingSucceeded(&circuit, &witness, test.WithCurves(ecc.BW6_761))

}

// -------------------------------------------------------------------------------------------------
// Neg

Expand Down
38 changes: 38 additions & 0 deletions std/algebra/sw/g2.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,3 +224,41 @@ func (p *G2Affine) MustBeEqual(api frontend.API, other G2Affine) {
p.X.MustBeEqual(api, other.X)
p.Y.MustBeEqual(api, other.Y)
}

// DoubleAndAdd computes 2*p1+p2 in affine coords
func (p *G2Affine) DoubleAndAdd(api frontend.API, p1, p2 *G2Affine, ext fields.Extension) *G2Affine {

var n, d, l1, l2, x3, x4, y4 fields.E2

// compute lambda1 = (y2-y1)/(x2-x1)
n.Sub(api, p1.Y, p2.Y)
d.Sub(api, p1.X, p2.X)
l1.Inverse(api, d, ext).Mul(api, l1, n, ext)

// compute x3 = lambda1**2-x1-x2
x3.Square(api, l1, ext).
Sub(api, x3, p1.X).
Sub(api, x3, p2.X)

// omit y3 computation
// compute lambda2 = -lambda1-2*y1/(x3-x1)
n.Double(api, p1.Y)
d.Sub(api, x3, p1.X)
l2.Inverse(api, d, ext).Mul(api, l2, n, ext)
l2.Add(api, l2, l1).Neg(api, l2)

// compute x4 =lambda2**2-x1-x3
x4.Square(api, l2, ext).
Sub(api, x4, p1.X).
Sub(api, x4, x3)

// compute y4 = lambda2*(x1 - x4)-y1
y4.Sub(api, p1.X, x4).
Mul(api, l2, y4, ext).
Sub(api, y4, p1.Y)

p.X = x4
p.Y = y4

return p
}
76 changes: 76 additions & 0 deletions std/algebra/sw/g2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (

"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark-crypto/ecc/bls12-377/fr"
"github.com/consensys/gnark/backend"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/std/algebra/fields"
"github.com/consensys/gnark/test"
Expand Down Expand Up @@ -142,6 +143,47 @@ func TestDoubleAssignG2(t *testing.T) {

}

// -------------------------------------------------------------------------------------------------
// DoubleAndAdd affine

type g2DoubleAndAddAffine struct {
A, B G2Affine
C G2Affine `gnark:",public"`
}

func (circuit *g2DoubleAndAddAffine) Define(api frontend.API) error {
expected := circuit.A
expected.DoubleAndAdd(api, &circuit.A, &circuit.B, fields.GetBLS377ExtensionFp12(api))
expected.MustBeEqual(api, circuit.C)
return nil
}

func TestDoubleAndAddAffineG2(t *testing.T) {

// sample 2 random points
_a := randomPointG2()
_b := randomPointG2()
var a, b, c bls12377.G2Affine
a.FromJacobian(&_a)
b.FromJacobian(&_b)

// create the cs
var circuit, witness g2DoubleAndAddAffine

// assign the inputs
witness.A.Assign(&a)
witness.B.Assign(&b)

// compute the result
_a.Double(&_a).AddAssign(&_b)
c.FromJacobian(&_a)
witness.C.Assign(&c)

assert := test.NewAssert(t)
assert.SolvingSucceeded(&circuit, &witness, test.WithCurves(ecc.BW6_761))

}

// -------------------------------------------------------------------------------------------------
// Double affine

Expand Down Expand Up @@ -224,3 +266,37 @@ func randomPointG2() bls12377.G2Jac {
p2.ScalarMultiplication(&p2, r1.ToBigIntRegular(&b))
return p2
}

// benches
func BenchmarkDoubleAffineG2(b *testing.B) {
var c g2DoubleAffine
b.Run("groth16", func(b *testing.B) {
for i := 0; i < b.N; i++ {
ccsBench, _ = frontend.Compile(ecc.BW6_761, backend.GROTH16, &c)
}

})
b.Log("groth16", ccsBench.GetNbConstraints())
}

func BenchmarkAddAssignAffineG2(b *testing.B) {
var c g2AddAssignAffine
b.Run("groth16", func(b *testing.B) {
for i := 0; i < b.N; i++ {
ccsBench, _ = frontend.Compile(ecc.BW6_761, backend.GROTH16, &c)
}

})
b.Log("groth16", ccsBench.GetNbConstraints())
}

func BenchmarkDoubleAndAddAffineG2(b *testing.B) {
var c g2DoubleAndAddAffine
b.Run("groth16", func(b *testing.B) {
for i := 0; i < b.N; i++ {
ccsBench, _ = frontend.Compile(ecc.BW6_761, backend.GROTH16, &c)
}

})
b.Log("groth16", ccsBench.GetNbConstraints())
}
Loading

0 comments on commit 4d853c7

Please sign in to comment.