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: BN254 pairing #411

Merged
merged 5 commits into from
Mar 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions std/algebra/pairing_bn254/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Package pairing_bn254 implements pairing over BN254 curve.
//
// The implementation follows very closely the implementation of its out-circuit
// counterpart in [gnark-crypto].
//
// [gnark-crypto]: https://github.com/ConsenSys/gnark-crypto/tree/master/ecc/bn254
package pairing_bn254
101 changes: 101 additions & 0 deletions std/algebra/pairing_bn254/doc_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package pairing_bn254_test

import (
"crypto/rand"
"fmt"

"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark-crypto/ecc/bn254"
"github.com/consensys/gnark/backend/groth16"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/frontend/cs/r1cs"
"github.com/consensys/gnark/std/algebra/pairing_bn254"
)

type PairCircuit struct {
InG1 pairing_bn254.G1Affine
InG2 pairing_bn254.G2Affine
Res pairing_bn254.GTEl
}

func (c *PairCircuit) Define(api frontend.API) error {
pairing, err := pairing_bn254.NewPairing(api)
if err != nil {
return fmt.Errorf("new pairing: %w", err)
}
res, err := pairing.Pair([]*pairing_bn254.G1Affine{&c.InG1}, []*pairing_bn254.G2Affine{&c.InG2})
if err != nil {
return fmt.Errorf("pair: %w", err)
}
pairing.AssertIsEqual(res, &c.Res)
return nil
}

func ExamplePairing() {
p, q, err := randomG1G2Affines()
if err != nil {
panic(err)
}
res, err := bn254.Pair([]bn254.G1Affine{p}, []bn254.G2Affine{q})
if err != nil {
panic(err)
}
circuit := PairCircuit{}
witness := PairCircuit{
InG1: pairing_bn254.NewG1Affine(p),
InG2: pairing_bn254.NewG2Affine(q),
Res: pairing_bn254.NewGTEl(res),
}
ccs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit)
if err != nil {
panic(err)
} else {
fmt.Println("compiled")
}
pk, vk, err := groth16.Setup(ccs)
if err != nil {
panic(err)
} else {
fmt.Println("setup done")
}
secretWitness, err := frontend.NewWitness(&witness, ecc.BN254.ScalarField())
if err != nil {
panic(err)
} else {
fmt.Println("secret witness")
}
publicWitness, err := secretWitness.Public()
if err != nil {
panic(err)
} else {
fmt.Println("public witness")
}
proof, err := groth16.Prove(ccs, pk, secretWitness)
if err != nil {
panic(err)
} else {
fmt.Println("proof")
}
err = groth16.Verify(proof, vk, publicWitness)
if err != nil {
panic(err)
} else {
fmt.Println("verify")
}
}

func randomG1G2Affines() (p bn254.G1Affine, q bn254.G2Affine, err error) {
_, _, G1AffGen, G2AffGen := bn254.Generators()
mod := bn254.ID.ScalarField()
s1, err := rand.Int(rand.Reader, mod)
if err != nil {
return p, q, err
}
s2, err := rand.Int(rand.Reader, mod)
if err != nil {
return p, q, err
}
p.ScalarMultiplication(&G1AffGen, s1)
q.ScalarMultiplication(&G2AffGen, s2)
return
}
16 changes: 16 additions & 0 deletions std/algebra/pairing_bn254/g1.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package pairing_bn254

import (
"github.com/consensys/gnark-crypto/ecc/bn254"
"github.com/consensys/gnark/std/algebra/weierstrass"
"github.com/consensys/gnark/std/math/emulated"
)

type G1Affine = weierstrass.AffinePoint[emulated.BN254Fp]

func NewG1Affine(v bn254.G1Affine) G1Affine {
return G1Affine{
X: emulated.ValueOf[emulated.BN254Fp](v.X),
Y: emulated.ValueOf[emulated.BN254Fp](v.Y),
}
}
31 changes: 31 additions & 0 deletions std/algebra/pairing_bn254/g2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package pairing_bn254

import (
"github.com/consensys/gnark-crypto/ecc/bn254"
"github.com/consensys/gnark/std/math/emulated"
)

type G2Affine struct {
X, Y e2
}

type g2Jacobian struct {
X, Y, Z e2
}

type g2Projective struct {
X, Y, Z e2
}

func NewG2Affine(v bn254.G2Affine) G2Affine {
return G2Affine{
X: e2{
A0: emulated.ValueOf[emulated.BN254Fp](v.X.A0),
A1: emulated.ValueOf[emulated.BN254Fp](v.X.A1),
},
Y: e2{
A0: emulated.ValueOf[emulated.BN254Fp](v.Y.A0),
A1: emulated.ValueOf[emulated.BN254Fp](v.Y.A1),
},
}
}
41 changes: 41 additions & 0 deletions std/algebra/pairing_bn254/gt.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package pairing_bn254

import (
"github.com/consensys/gnark-crypto/ecc/bn254"
"github.com/consensys/gnark/std/math/emulated"
)

type GTEl = e12

func NewGTEl(v bn254.GT) GTEl {
return GTEl{
C0: e6{
B0: e2{
A0: emulated.ValueOf[emulated.BN254Fp](v.C0.B0.A0),
A1: emulated.ValueOf[emulated.BN254Fp](v.C0.B0.A1),
},
B1: e2{
A0: emulated.ValueOf[emulated.BN254Fp](v.C0.B1.A0),
A1: emulated.ValueOf[emulated.BN254Fp](v.C0.B1.A1),
},
B2: e2{
A0: emulated.ValueOf[emulated.BN254Fp](v.C0.B2.A0),
A1: emulated.ValueOf[emulated.BN254Fp](v.C0.B2.A1),
},
},
C1: e6{
B0: e2{
A0: emulated.ValueOf[emulated.BN254Fp](v.C1.B0.A0),
A1: emulated.ValueOf[emulated.BN254Fp](v.C1.B0.A1),
},
B1: e2{
A0: emulated.ValueOf[emulated.BN254Fp](v.C1.B1.A0),
A1: emulated.ValueOf[emulated.BN254Fp](v.C1.B1.A1),
},
B2: e2{
A0: emulated.ValueOf[emulated.BN254Fp](v.C1.B2.A0),
A1: emulated.ValueOf[emulated.BN254Fp](v.C1.B2.A1),
},
},
}
}
Loading