r1cs to qap over finite field

This commit is contained in:
arnaucube
2018-12-02 19:13:18 +01:00
parent e889b8b7dc
commit b1df15a497
16 changed files with 1060 additions and 45 deletions

View File

@@ -1,5 +1,5 @@
## Bn128
Implementation of the bn128 pairing.
Implementation of the bn128 pairing in Go.
Implementation followng the information and the implementations from:

View File

@@ -1,21 +1,23 @@
package bn128
import (
"bytes"
"errors"
"math/big"
"github.com/arnaucube/go-snark/fields"
)
type Bn128 struct {
Q *big.Int
R *big.Int
Gg1 [2]*big.Int
Gg2 [2][2]*big.Int
NonResidueFq2 *big.Int
NonResidueFq6 [2]*big.Int
Fq1 Fq
Fq2 Fq2
Fq6 Fq6
Fq12 Fq12
Fq1 fields.Fq
Fq2 fields.Fq2
Fq6 fields.Fq6
Fq12 fields.Fq12
G1 G1
G2 G2
LoopCount *big.Int
@@ -33,12 +35,18 @@ type Bn128 struct {
func NewBn128() (Bn128, error) {
var b Bn128
q, ok := new(big.Int).SetString("21888242871839275222246405745257275088696311157297823662689037894645226208583", 10) // i
q, ok := new(big.Int).SetString("21888242871839275222246405745257275088696311157297823662689037894645226208583", 10)
if !ok {
return b, errors.New("err with q")
}
b.Q = q
r, ok := new(big.Int).SetString("21888242871839275222246405745257275088548364400416034343698204186575808495617", 10)
if !ok {
return b, errors.New("err with r")
}
b.R = r
b.Gg1 = [2]*big.Int{
big.NewInt(int64(1)),
big.NewInt(int64(2)),
@@ -72,7 +80,7 @@ func NewBn128() (Bn128, error) {
},
}
b.Fq1 = NewFq(q)
b.Fq1 = fields.NewFq(q)
b.NonResidueFq2, ok = new(big.Int).SetString("21888242871839275222246405745257275088696311157297823662689037894645226208582", 10) // i
if !ok {
return b, errors.New("err with nonResidueFq2")
@@ -82,9 +90,9 @@ func NewBn128() (Bn128, error) {
big.NewInt(int64(1)),
}
b.Fq2 = NewFq2(b.Fq1, b.NonResidueFq2)
b.Fq6 = NewFq6(b.Fq2, b.NonResidueFq6)
b.Fq12 = NewFq12(b.Fq6, b.Fq2, b.NonResidueFq6)
b.Fq2 = fields.NewFq2(b.Fq1, b.NonResidueFq2)
b.Fq6 = fields.NewFq6(b.Fq2, b.NonResidueFq6)
b.Fq12 = fields.NewFq12(b.Fq6, b.Fq2, b.NonResidueFq6)
b.G1 = NewG1(b.Fq1, b.Gg1)
b.G2 = NewG2(b.Fq2, b.Gg2)
@@ -97,12 +105,6 @@ func NewBn128() (Bn128, error) {
return b, nil
}
func BigIsOdd(n *big.Int) bool {
one := big.NewInt(int64(1))
and := new(big.Int).And(n, one)
return bytes.Equal(and.Bytes(), big.NewInt(int64(1)).Bytes())
}
func (bn128 *Bn128) preparePairing() error {
var ok bool
bn128.LoopCount, ok = new(big.Int).SetString("29793968203157093288", 10)

View File

@@ -1,6 +1,7 @@
package bn128
import (
"bytes"
"math/big"
"testing"
@@ -61,6 +62,8 @@ func TestBN128Pairing(t *testing.T) {
assert.True(t, bn128.Fq12.Equal(pA, pB))
assert.Equal(t, pA[0][0][0].String(), "73680848340331011700282047627232219336104151861349893575958589557226556635706")
assert.Equal(t, bn128.Fq12.Affine(pA)[0][0][0].String(), "8016119724813186033542830391460394070015218389456422587891475873290878009957")
assert.True(t, !bytes.Equal(pA[0][0][0].Bytes(), big.NewInt(int64(0)).Bytes()))
assert.True(t, !bytes.Equal(bn128.Fq12.Affine(pA)[0][0][0].Bytes(), big.NewInt(int64(0)).Bytes()))
// assert.Equal(t, pA[0][0][0].String(), "73680848340331011700282047627232219336104151861349893575958589557226556635706")
// assert.Equal(t, bn128.Fq12.Affine(pA)[0][0][0].String(), "8016119724813186033542830391460394070015218389456422587891475873290878009957")
}

View File

@@ -1,129 +0,0 @@
package bn128
import (
"bytes"
"math/big"
)
// Fq is the Z field over modulus Q
type Fq struct {
Q *big.Int // Q
}
// NewFq generates a new Fq
func NewFq(q *big.Int) Fq {
return Fq{
q,
}
}
// Zero returns a Zero value on the Fq
func (fq Fq) Zero() *big.Int {
return big.NewInt(int64(0))
}
// One returns a One value on the Fq
func (fq Fq) One() *big.Int {
return big.NewInt(int64(1))
}
// Add performs an addition on the Fq
func (fq Fq) Add(a, b *big.Int) *big.Int {
r := new(big.Int).Add(a, b)
// return new(big.Int).Mod(r, fq.Q)
return r
}
// Double performs a doubling on the Fq
func (fq Fq) Double(a *big.Int) *big.Int {
r := new(big.Int).Add(a, a)
// return new(big.Int).Mod(r, fq.Q)
return r
}
// Sub performs a subtraction on the Fq
func (fq Fq) Sub(a, b *big.Int) *big.Int {
r := new(big.Int).Sub(a, b)
// return new(big.Int).Mod(r, fq.Q)
return r
}
// Neg performs a negation on the Fq
func (fq Fq) Neg(a *big.Int) *big.Int {
m := new(big.Int).Neg(a)
// return new(big.Int).Mod(m, fq.Q)
return m
}
// Mul performs a multiplication on the Fq
func (fq Fq) Mul(a, b *big.Int) *big.Int {
m := new(big.Int).Mul(a, b)
return new(big.Int).Mod(m, fq.Q)
// return m
}
func (fq Fq) MulScalar(base, e *big.Int) *big.Int {
return fq.Mul(base, e)
}
// Inverse returns the inverse on the Fq
func (fq Fq) Inverse(a *big.Int) *big.Int {
return new(big.Int).ModInverse(a, fq.Q)
// q := bigCopy(fq.Q)
// t := big.NewInt(int64(0))
// r := fq.Q
// newt := big.NewInt(int64(0))
// newr := fq.Affine(a)
// for !bytes.Equal(newr.Bytes(), big.NewInt(int64(0)).Bytes()) {
// q := new(big.Int).Div(bigCopy(r), bigCopy(newr))
//
// t = bigCopy(newt)
// newt = fq.Sub(t, fq.Mul(q, newt))
//
// r = bigCopy(newr)
// newr = fq.Sub(r, fq.Mul(q, newr))
// }
// if t.Cmp(big.NewInt(0)) == -1 { // t< 0
// t = fq.Add(t, q)
// }
// return t
}
// Square performs a square operation on the Fq
func (fq Fq) Square(a *big.Int) *big.Int {
m := new(big.Int).Mul(a, a)
return new(big.Int).Mod(m, fq.Q)
}
func (fq Fq) IsZero(a *big.Int) bool {
return bytes.Equal(a.Bytes(), fq.Zero().Bytes())
}
func (fq Fq) Copy(a *big.Int) *big.Int {
return new(big.Int).SetBytes(a.Bytes())
}
func (fq Fq) Affine(a *big.Int) *big.Int {
nq := fq.Neg(fq.Q)
aux := a
if aux.Cmp(big.NewInt(int64(0))) == -1 { // negative value
if aux.Cmp(nq) != 1 { // aux less or equal nq
aux = new(big.Int).Mod(aux, fq.Q)
}
if aux.Cmp(big.NewInt(int64(0))) == -1 { // negative value
aux = new(big.Int).Add(aux, fq.Q)
}
} else {
if aux.Cmp(fq.Q) != -1 { // aux greater or equal nq
aux = new(big.Int).Mod(aux, fq.Q)
}
}
return aux
}
func (fq Fq) Equal(a, b *big.Int) bool {
aAff := fq.Affine(a)
bAff := fq.Affine(b)
return bytes.Equal(aAff.Bytes(), bAff.Bytes())
}

View File

@@ -1,161 +0,0 @@
package bn128
import (
"bytes"
"math/big"
)
// Fq12 uses the same algorithms than Fq2, but with [2][3][2]*big.Int data structure
// Fq12 is Field 12
type Fq12 struct {
F Fq6
Fq2 Fq2
NonResidue [2]*big.Int
}
// NewFq12 generates a new Fq12
func NewFq12(f Fq6, fq2 Fq2, nonResidue [2]*big.Int) Fq12 {
fq12 := Fq12{
f,
fq2,
nonResidue,
}
return fq12
}
// Zero returns a Zero value on the Fq12
func (fq12 Fq12) Zero() [2][3][2]*big.Int {
return [2][3][2]*big.Int{fq12.F.Zero(), fq12.F.Zero()}
}
// One returns a One value on the Fq12
func (fq12 Fq12) One() [2][3][2]*big.Int {
return [2][3][2]*big.Int{fq12.F.One(), fq12.F.Zero()}
}
func (fq12 Fq12) mulByNonResidue(a [3][2]*big.Int) [3][2]*big.Int {
return [3][2]*big.Int{
fq12.Fq2.Mul(fq12.NonResidue, a[2]),
a[0],
a[1],
}
}
// Add performs an addition on the Fq12
func (fq12 Fq12) Add(a, b [2][3][2]*big.Int) [2][3][2]*big.Int {
return [2][3][2]*big.Int{
fq12.F.Add(a[0], b[0]),
fq12.F.Add(a[1], b[1]),
}
}
// Double performs a doubling on the Fq12
func (fq12 Fq12) Double(a [2][3][2]*big.Int) [2][3][2]*big.Int {
return fq12.Add(a, a)
}
// Sub performs a subtraction on the Fq12
func (fq12 Fq12) Sub(a, b [2][3][2]*big.Int) [2][3][2]*big.Int {
return [2][3][2]*big.Int{
fq12.F.Sub(a[0], b[0]),
fq12.F.Sub(a[1], b[1]),
}
}
// Neg performs a negation on the Fq12
func (fq12 Fq12) Neg(a [2][3][2]*big.Int) [2][3][2]*big.Int {
return fq12.Sub(fq12.Zero(), a)
}
// Mul performs a multiplication on the Fq12
func (fq12 Fq12) Mul(a, b [2][3][2]*big.Int) [2][3][2]*big.Int {
// Multiplication and Squaring on Pairing-Friendly .pdf; Section 3 (Karatsuba)
v0 := fq12.F.Mul(a[0], b[0])
v1 := fq12.F.Mul(a[1], b[1])
return [2][3][2]*big.Int{
fq12.F.Add(v0, fq12.mulByNonResidue(v1)),
fq12.F.Sub(
fq12.F.Mul(
fq12.F.Add(a[0], a[1]),
fq12.F.Add(b[0], b[1])),
fq12.F.Add(v0, v1)),
}
}
func (fq12 Fq12) MulScalar(base [2][3][2]*big.Int, e *big.Int) [2][3][2]*big.Int {
// for more possible implementations see g2.go file, at the function g2.MulScalar()
res := fq12.Zero()
rem := e
exp := base
for !bytes.Equal(rem.Bytes(), big.NewInt(int64(0)).Bytes()) {
// if rem % 2 == 1
if bytes.Equal(new(big.Int).Rem(rem, big.NewInt(int64(2))).Bytes(), big.NewInt(int64(1)).Bytes()) {
res = fq12.Add(res, exp)
}
exp = fq12.Double(exp)
rem = rem.Rsh(rem, 1) // rem = rem >> 1
}
return res
}
// Inverse returns the inverse on the Fq12
func (fq12 Fq12) Inverse(a [2][3][2]*big.Int) [2][3][2]*big.Int {
t0 := fq12.F.Square(a[0])
t1 := fq12.F.Square(a[1])
t2 := fq12.F.Sub(t0, fq12.mulByNonResidue(t1))
t3 := fq12.F.Inverse(t2)
return [2][3][2]*big.Int{
fq12.F.Mul(a[0], t3),
fq12.F.Neg(fq12.F.Mul(a[1], t3)),
}
}
// Div performs a division on the Fq12
func (fq12 Fq12) Div(a, b [2][3][2]*big.Int) [2][3][2]*big.Int {
return fq12.Mul(a, fq12.Inverse(b))
}
// Square performs a square operation on the Fq12
func (fq12 Fq12) Square(a [2][3][2]*big.Int) [2][3][2]*big.Int {
ab := fq12.F.Mul(a[0], a[1])
return [2][3][2]*big.Int{
fq12.F.Sub(
fq12.F.Mul(
fq12.F.Add(a[0], a[1]),
fq12.F.Add(
a[0],
fq12.mulByNonResidue(a[1]))),
fq12.F.Add(
ab,
fq12.mulByNonResidue(ab))),
fq12.F.Add(ab, ab),
}
}
func (fq12 Fq12) Exp(base [2][3][2]*big.Int, e *big.Int) [2][3][2]*big.Int {
res := fq12.One()
rem := fq12.Fq2.F.Copy(e)
exp := base
for !bytes.Equal(rem.Bytes(), big.NewInt(int64(0)).Bytes()) {
if BigIsOdd(rem) {
res = fq12.Mul(res, exp)
}
exp = fq12.Square(exp)
rem = new(big.Int).Rsh(rem, 1)
}
return res
}
func (fq12 Fq12) Affine(a [2][3][2]*big.Int) [2][3][2]*big.Int {
return [2][3][2]*big.Int{
fq12.F.Affine(a[0]),
fq12.F.Affine(a[1]),
}
}
func (fq12 Fq12) Equal(a, b [2][3][2]*big.Int) bool {
return fq12.F.Equal(a[0], b[0]) && fq12.F.Equal(a[1], b[1])
}

View File

@@ -1,154 +0,0 @@
package bn128
import (
"math/big"
)
// Fq2 is Field 2
type Fq2 struct {
F Fq
NonResidue *big.Int
}
// NewFq2 generates a new Fq2
func NewFq2(f Fq, nonResidue *big.Int) Fq2 {
fq2 := Fq2{
f,
nonResidue,
}
return fq2
}
// Zero returns a Zero value on the Fq2
func (fq2 Fq2) Zero() [2]*big.Int {
return [2]*big.Int{fq2.F.Zero(), fq2.F.Zero()}
}
// One returns a One value on the Fq2
func (fq2 Fq2) One() [2]*big.Int {
return [2]*big.Int{fq2.F.One(), fq2.F.Zero()}
}
func (fq2 Fq2) mulByNonResidue(a *big.Int) *big.Int {
return fq2.F.Mul(fq2.NonResidue, a)
}
// Add performs an addition on the Fq2
func (fq2 Fq2) Add(a, b [2]*big.Int) [2]*big.Int {
return [2]*big.Int{
fq2.F.Add(a[0], b[0]),
fq2.F.Add(a[1], b[1]),
}
}
// Double performs a doubling on the Fq2
func (fq2 Fq2) Double(a [2]*big.Int) [2]*big.Int {
return fq2.Add(a, a)
}
// Sub performs a subtraction on the Fq2
func (fq2 Fq2) Sub(a, b [2]*big.Int) [2]*big.Int {
return [2]*big.Int{
fq2.F.Sub(a[0], b[0]),
fq2.F.Sub(a[1], b[1]),
}
}
// Neg performs a negation on the Fq2
func (fq2 Fq2) Neg(a [2]*big.Int) [2]*big.Int {
return fq2.Sub(fq2.Zero(), a)
}
// Mul performs a multiplication on the Fq2
func (fq2 Fq2) Mul(a, b [2]*big.Int) [2]*big.Int {
// Multiplication and Squaring on Pairing-Friendly.pdf; Section 3 (Karatsuba)
// https://pdfs.semanticscholar.org/3e01/de88d7428076b2547b60072088507d881bf1.pdf
v0 := fq2.F.Mul(a[0], b[0])
v1 := fq2.F.Mul(a[1], b[1])
return [2]*big.Int{
fq2.F.Add(v0, fq2.mulByNonResidue(v1)),
fq2.F.Sub(
fq2.F.Mul(
fq2.F.Add(a[0], a[1]),
fq2.F.Add(b[0], b[1])),
fq2.F.Add(v0, v1)),
}
}
func (fq2 Fq2) MulScalar(p [2]*big.Int, e *big.Int) [2]*big.Int {
// for more possible implementations see g2.go file, at the function g2.MulScalar()
q := fq2.Zero()
d := fq2.F.Copy(e)
r := p
foundone := false
for i := d.BitLen(); i >= 0; i-- {
if foundone {
q = fq2.Double(q)
}
if d.Bit(i) == 1 {
foundone = true
q = fq2.Add(q, r)
}
}
return q
}
// Inverse returns the inverse on the Fq2
func (fq2 Fq2) Inverse(a [2]*big.Int) [2]*big.Int {
// High-Speed Software Implementation of the Optimal Ate Pairing over BarretoNaehrig Curves .pdf
// https://eprint.iacr.org/2010/354.pdf , algorithm 8
t0 := fq2.F.Square(a[0])
t1 := fq2.F.Square(a[1])
t2 := fq2.F.Sub(t0, fq2.mulByNonResidue(t1))
t3 := fq2.F.Inverse(t2)
return [2]*big.Int{
fq2.F.Mul(a[0], t3),
fq2.F.Neg(fq2.F.Mul(a[1], t3)),
}
}
// Div performs a division on the Fq2
func (fq2 Fq2) Div(a, b [2]*big.Int) [2]*big.Int {
return fq2.Mul(a, fq2.Inverse(b))
}
// Square performs a square operation on the Fq2
func (fq2 Fq2) Square(a [2]*big.Int) [2]*big.Int {
// https://pdfs.semanticscholar.org/3e01/de88d7428076b2547b60072088507d881bf1.pdf , complex squaring
ab := fq2.F.Mul(a[0], a[1])
return [2]*big.Int{
fq2.F.Sub(
fq2.F.Mul(
fq2.F.Add(a[0], a[1]),
fq2.F.Add(
a[0],
fq2.mulByNonResidue(a[1]))),
fq2.F.Add(
ab,
fq2.mulByNonResidue(ab))),
fq2.F.Add(ab, ab),
}
}
func (fq2 Fq2) IsZero(a [2]*big.Int) bool {
return fq2.F.IsZero(a[0]) && fq2.F.IsZero(a[1])
}
func (fq2 Fq2) Affine(a [2]*big.Int) [2]*big.Int {
return [2]*big.Int{
fq2.F.Affine(a[0]),
fq2.F.Affine(a[1]),
}
}
func (fq2 Fq2) Equal(a, b [2]*big.Int) bool {
return fq2.F.Equal(a[0], b[0]) && fq2.F.Equal(a[1], b[1])
}
func (fq2 Fq2) Copy(a [2]*big.Int) [2]*big.Int {
return [2]*big.Int{
fq2.F.Copy(a[0]),
fq2.F.Copy(a[1]),
}
}

View File

@@ -1,192 +0,0 @@
package bn128
import (
"bytes"
"math/big"
)
// Fq6 is Field 6
type Fq6 struct {
F Fq2
NonResidue [2]*big.Int
}
// NewFq6 generates a new Fq6
func NewFq6(f Fq2, nonResidue [2]*big.Int) Fq6 {
fq6 := Fq6{
f,
nonResidue,
}
return fq6
}
// Zero returns a Zero value on the Fq6
func (fq6 Fq6) Zero() [3][2]*big.Int {
return [3][2]*big.Int{fq6.F.Zero(), fq6.F.Zero(), fq6.F.Zero()}
}
// One returns a One value on the Fq6
func (fq6 Fq6) One() [3][2]*big.Int {
return [3][2]*big.Int{fq6.F.One(), fq6.F.Zero(), fq6.F.Zero()}
}
func (fq6 Fq6) mulByNonResidue(a [2]*big.Int) [2]*big.Int {
return fq6.F.Mul(fq6.NonResidue, a)
}
// Add performs an addition on the Fq6
func (fq6 Fq6) Add(a, b [3][2]*big.Int) [3][2]*big.Int {
return [3][2]*big.Int{
fq6.F.Add(a[0], b[0]),
fq6.F.Add(a[1], b[1]),
fq6.F.Add(a[2], b[2]),
}
}
func (fq6 Fq6) Double(a [3][2]*big.Int) [3][2]*big.Int {
return fq6.Add(a, a)
}
// Sub performs a subtraction on the Fq6
func (fq6 Fq6) Sub(a, b [3][2]*big.Int) [3][2]*big.Int {
return [3][2]*big.Int{
fq6.F.Sub(a[0], b[0]),
fq6.F.Sub(a[1], b[1]),
fq6.F.Sub(a[2], b[2]),
}
}
// Neg performs a negation on the Fq6
func (fq6 Fq6) Neg(a [3][2]*big.Int) [3][2]*big.Int {
return fq6.Sub(fq6.Zero(), a)
}
// Mul performs a multiplication on the Fq6
func (fq6 Fq6) Mul(a, b [3][2]*big.Int) [3][2]*big.Int {
v0 := fq6.F.Mul(a[0], b[0])
v1 := fq6.F.Mul(a[1], b[1])
v2 := fq6.F.Mul(a[2], b[2])
return [3][2]*big.Int{
fq6.F.Add(
v0,
fq6.mulByNonResidue(
fq6.F.Sub(
fq6.F.Mul(
fq6.F.Add(a[1], a[2]),
fq6.F.Add(b[1], b[2])),
fq6.F.Add(v1, v2)))),
fq6.F.Add(
fq6.F.Sub(
fq6.F.Mul(
fq6.F.Add(a[0], a[1]),
fq6.F.Add(b[0], b[1])),
fq6.F.Add(v0, v1)),
fq6.mulByNonResidue(v2)),
fq6.F.Add(
fq6.F.Sub(
fq6.F.Mul(
fq6.F.Add(a[0], a[2]),
fq6.F.Add(b[0], b[2])),
fq6.F.Add(v0, v2)),
v1),
}
}
func (fq6 Fq6) MulScalar(base [3][2]*big.Int, e *big.Int) [3][2]*big.Int {
// for more possible implementations see g2.go file, at the function g2.MulScalar()
res := fq6.Zero()
rem := e
exp := base
for !bytes.Equal(rem.Bytes(), big.NewInt(int64(0)).Bytes()) {
// if rem % 2 == 1
if bytes.Equal(new(big.Int).Rem(rem, big.NewInt(int64(2))).Bytes(), big.NewInt(int64(1)).Bytes()) {
res = fq6.Add(res, exp)
}
exp = fq6.Double(exp)
rem = rem.Rsh(rem, 1) // rem = rem >> 1
}
return res
}
// Inverse returns the inverse on the Fq6
func (fq6 Fq6) Inverse(a [3][2]*big.Int) [3][2]*big.Int {
t0 := fq6.F.Square(a[0])
t1 := fq6.F.Square(a[1])
t2 := fq6.F.Square(a[2])
t3 := fq6.F.Mul(a[0], a[1])
t4 := fq6.F.Mul(a[0], a[2])
t5 := fq6.F.Mul(a[1], a[2])
c0 := fq6.F.Sub(t0, fq6.mulByNonResidue(t5))
c1 := fq6.F.Sub(fq6.mulByNonResidue(t2), t3)
c2 := fq6.F.Sub(t1, t4)
t6 := fq6.F.Inverse(
fq6.F.Add(
fq6.F.Mul(a[0], c0),
fq6.mulByNonResidue(
fq6.F.Add(
fq6.F.Mul(a[2], c1),
fq6.F.Mul(a[1], c2)))))
return [3][2]*big.Int{
fq6.F.Mul(t6, c0),
fq6.F.Mul(t6, c1),
fq6.F.Mul(t6, c2),
}
}
// Div performs a division on the Fq6
func (fq6 Fq6) Div(a, b [3][2]*big.Int) [3][2]*big.Int {
return fq6.Mul(a, fq6.Inverse(b))
}
// Square performs a square operation on the Fq6
func (fq6 Fq6) Square(a [3][2]*big.Int) [3][2]*big.Int {
s0 := fq6.F.Square(a[0])
ab := fq6.F.Mul(a[0], a[1])
s1 := fq6.F.Add(ab, ab)
s2 := fq6.F.Square(
fq6.F.Add(
fq6.F.Sub(a[0], a[1]),
a[2]))
bc := fq6.F.Mul(a[1], a[2])
s3 := fq6.F.Add(bc, bc)
s4 := fq6.F.Square(a[2])
return [3][2]*big.Int{
fq6.F.Add(
s0,
fq6.mulByNonResidue(s3)),
fq6.F.Add(
s1,
fq6.mulByNonResidue(s4)),
fq6.F.Sub(
fq6.F.Add(
fq6.F.Add(s1, s2),
s3),
fq6.F.Add(s0, s4)),
}
}
func (fq6 Fq6) Affine(a [3][2]*big.Int) [3][2]*big.Int {
return [3][2]*big.Int{
fq6.F.Affine(a[0]),
fq6.F.Affine(a[1]),
fq6.F.Affine(a[2]),
}
}
func (fq6 Fq6) Equal(a, b [3][2]*big.Int) bool {
return fq6.F.Equal(a[0], b[0]) && fq6.F.Equal(a[1], b[1]) && fq6.F.Equal(a[2], b[2])
}
func (fq6 Fq6) Copy(a [3][2]*big.Int) [3][2]*big.Int {
return [3][2]*big.Int{
fq6.F.Copy(a[0]),
fq6.F.Copy(a[1]),
fq6.F.Copy(a[2]),
}
}

View File

@@ -1,160 +0,0 @@
package bn128
import (
"math/big"
"testing"
"github.com/stretchr/testify/assert"
)
func iToBig(a int) *big.Int {
return big.NewInt(int64(a))
}
func iiToBig(a, b int) [2]*big.Int {
return [2]*big.Int{iToBig(a), iToBig(b)}
}
func iiiToBig(a, b int) [2]*big.Int {
return [2]*big.Int{iToBig(a), iToBig(b)}
}
func TestFq1(t *testing.T) {
fq1 := NewFq(iToBig(7))
res := fq1.Add(iToBig(4), iToBig(4))
assert.Equal(t, iToBig(1), fq1.Affine(res))
res = fq1.Double(iToBig(5))
assert.Equal(t, iToBig(3), fq1.Affine(res))
res = fq1.Sub(iToBig(5), iToBig(7))
assert.Equal(t, iToBig(5), fq1.Affine(res))
res = fq1.Neg(iToBig(5))
assert.Equal(t, iToBig(2), fq1.Affine(res))
res = fq1.Mul(iToBig(5), iToBig(11))
assert.Equal(t, iToBig(6), fq1.Affine(res))
res = fq1.Inverse(iToBig(4))
assert.Equal(t, iToBig(2), res)
res = fq1.Square(iToBig(5))
assert.Equal(t, iToBig(4), res)
}
func TestFq2(t *testing.T) {
fq1 := NewFq(iToBig(7))
nonResidueFq2str := "-1" // i/j
nonResidueFq2, ok := new(big.Int).SetString(nonResidueFq2str, 10)
assert.True(t, ok)
assert.Equal(t, nonResidueFq2.String(), nonResidueFq2str)
fq2 := Fq2{fq1, nonResidueFq2}
res := fq2.Add(iiToBig(4, 4), iiToBig(3, 4))
assert.Equal(t, iiToBig(0, 1), fq2.Affine(res))
res = fq2.Double(iiToBig(5, 3))
assert.Equal(t, iiToBig(3, 6), fq2.Affine(res))
res = fq2.Sub(iiToBig(5, 3), iiToBig(7, 2))
assert.Equal(t, iiToBig(5, 1), fq2.Affine(res))
res = fq2.Neg(iiToBig(4, 4))
assert.Equal(t, iiToBig(3, 3), fq2.Affine(res))
res = fq2.Mul(iiToBig(4, 4), iiToBig(3, 4))
assert.Equal(t, iiToBig(3, 0), fq2.Affine(res))
res = fq2.Inverse(iiToBig(4, 4))
assert.Equal(t, iiToBig(1, 6), fq2.Affine(res))
res = fq2.Square(iiToBig(4, 4))
assert.Equal(t, iiToBig(0, 4), fq2.Affine(res))
res2 := fq2.Mul(iiToBig(4, 4), iiToBig(4, 4))
assert.Equal(t, fq2.Affine(res), fq2.Affine(res2))
assert.True(t, fq2.Equal(res, res2))
res = fq2.Square(iiToBig(3, 5))
assert.Equal(t, iiToBig(5, 2), fq2.Affine(res))
res2 = fq2.Mul(iiToBig(3, 5), iiToBig(3, 5))
assert.Equal(t, fq2.Affine(res), fq2.Affine(res2))
}
func TestFq6(t *testing.T) {
bn128, err := NewBn128()
assert.Nil(t, err)
a := [3][2]*big.Int{
iiToBig(1, 2),
iiToBig(3, 4),
iiToBig(5, 6)}
b := [3][2]*big.Int{
iiToBig(12, 11),
iiToBig(10, 9),
iiToBig(8, 7)}
mulRes := bn128.Fq6.Mul(a, b)
divRes := bn128.Fq6.Div(mulRes, b)
assert.Equal(t, bn128.Fq6.Affine(a), bn128.Fq6.Affine(divRes))
}
func TestFq12(t *testing.T) {
q, ok := new(big.Int).SetString("21888242871839275222246405745257275088696311157297823662689037894645226208583", 10) // i
assert.True(t, ok)
fq1 := NewFq(q)
nonResidueFq2, ok := new(big.Int).SetString("21888242871839275222246405745257275088696311157297823662689037894645226208582", 10) // i
assert.True(t, ok)
nonResidueFq6 := iiToBig(9, 1)
fq2 := Fq2{fq1, nonResidueFq2}
fq6 := Fq6{fq2, nonResidueFq6}
fq12 := Fq12{fq6, fq2, nonResidueFq6}
a := [2][3][2]*big.Int{
{
iiToBig(1, 2),
iiToBig(3, 4),
iiToBig(5, 6),
},
{
iiToBig(7, 8),
iiToBig(9, 10),
iiToBig(11, 12),
},
}
b := [2][3][2]*big.Int{
{
iiToBig(12, 11),
iiToBig(10, 9),
iiToBig(8, 7),
},
{
iiToBig(6, 5),
iiToBig(4, 3),
iiToBig(2, 1),
},
}
res := fq12.Add(a, b)
assert.Equal(t,
[2][3][2]*big.Int{
{
iiToBig(13, 13),
iiToBig(13, 13),
iiToBig(13, 13),
},
{
iiToBig(13, 13),
iiToBig(13, 13),
iiToBig(13, 13),
},
},
res)
mulRes := fq12.Mul(a, b)
divRes := fq12.Div(mulRes, b)
assert.Equal(t, fq12.Affine(a), fq12.Affine(divRes))
}

View File

@@ -2,14 +2,16 @@ package bn128
import (
"math/big"
"github.com/arnaucube/go-snark/fields"
)
type G1 struct {
F Fq
F fields.Fq
G [3]*big.Int
}
func NewG1(f Fq, g [2]*big.Int) G1 {
func NewG1(f fields.Fq, g [2]*big.Int) G1 {
var g1 G1
g1.F = f
g1.G = [3]*big.Int{

View File

@@ -2,14 +2,16 @@ package bn128
import (
"math/big"
"github.com/arnaucube/go-snark/fields"
)
type G2 struct {
F Fq2
F fields.Fq2
G [3][2]*big.Int
}
func NewG2(f Fq2, g [2][2]*big.Int) G2 {
func NewG2(f fields.Fq2, g [2][2]*big.Int) G2 {
var g2 G2
g2.F = f
g2.G = [3][2]*big.Int{