diff --git a/bls377/e6.go b/bls377/e6.go index 6e00966446..be08a25307 100644 --- a/bls377/e6.go +++ b/bls377/e6.go @@ -139,13 +139,15 @@ func (z *E6) String() string { return (z.B0.String() + "+(" + z.B1.String() + ")*v+(" + z.B2.String() + ")*v**2") } -// Mul multiplies two numbers in E6 +// Mul sets z to the E6-product of x,y, returns z func (z *E6) Mul(x, y *E6) *E6 { + // Algorithm 13 from https://eprint.iacr.org/2010/354.pdf var rb0, b0, b1, b2, b3, b4 E2 b0.Mul(&x.B0, &y.B0) // step 1 b1.Mul(&x.B1, &y.B1) // step 2 b2.Mul(&x.B2, &y.B2) // step 3 + // step 4 b3.Add(&x.B1, &x.B2) b4.Add(&y.B1, &y.B2) @@ -161,6 +163,7 @@ func (z *E6) Mul(x, y *E6) *E6 { (rb0).A1 = buf } // end: inline rb0.MulByNonResidue(&rb0) rb0.AddAssign(&b0) + // step 5 b3.Add(&x.B0, &x.B1) b4.Add(&y.B0, &y.B1) @@ -176,6 +179,7 @@ func (z *E6) Mul(x, y *E6) *E6 { (b3).A1 = buf } // end: inline b3.MulByNonResidue(&b2) z.B1.AddAssign(&b3) + // step 6 b3.Add(&x.B0, &x.B2) b4.Add(&y.B0, &y.B2) @@ -187,6 +191,58 @@ func (z *E6) Mul(x, y *E6) *E6 { return z } +// MulAssign sets z to the E6-product of z,x returns z +func (z *E6) MulAssign(x *E6) *E6 { + + // Algorithm 13 from https://eprint.iacr.org/2010/354.pdf + var rb0, b0, b1, b2, b3, b4 E2 + b0.Mul(&z.B0, &x.B0) // step 1 + b1.Mul(&z.B1, &x.B1) // step 2 + b2.Mul(&z.B2, &x.B2) // step 3 + + // step 4 + b3.Add(&z.B1, &z.B2) + b4.Add(&x.B1, &x.B2) + rb0.Mul(&b3, &b4). + SubAssign(&b1). + SubAssign(&b2) + { // begin: inline rb0.MulByNonResidue(&rb0) + buf := (&rb0).A0 + { // begin: inline MulByNonResidue(&(rb0).A0, &(&rb0).A1) + buf := *(&(&rb0).A1) + (&(rb0).A0).Double(&buf).Double(&(rb0).A0).AddAssign(&buf) + } // end: inline MulByNonResidue(&(rb0).A0, &(&rb0).A1) + (rb0).A1 = buf + } // end: inline rb0.MulByNonResidue(&rb0) + rb0.AddAssign(&b0) + + // step 5 + b3.Add(&z.B0, &z.B1) + b4.Add(&x.B0, &x.B1) + z.B1.Mul(&b3, &b4). + SubAssign(&b0). + SubAssign(&b1) + { // begin: inline b3.MulByNonResidue(&b2) + buf := (&b2).A0 + { // begin: inline MulByNonResidue(&(b3).A0, &(&b2).A1) + buf := *(&(&b2).A1) + (&(b3).A0).Double(&buf).Double(&(b3).A0).AddAssign(&buf) + } // end: inline MulByNonResidue(&(b3).A0, &(&b2).A1) + (b3).A1 = buf + } // end: inline b3.MulByNonResidue(&b2) + z.B1.AddAssign(&b3) + + // step 6 + b3.Add(&z.B0, &z.B2) + b4.Add(&x.B0, &x.B2) + z.B2.Mul(&b3, &b4). + SubAssign(&b0). + SubAssign(&b2). + AddAssign(&b1) + z.B0 = rb0 + return z +} + // MulByE2 multiplies x by an elements of E2 func (z *E6) MulByE2(x *E6, y *E2) *E6 { var yCopy E2 @@ -229,8 +285,9 @@ func (z *E6) MulByNotv2(x, y *E6) *E6 { return z } -// Square squares a E6 +// Square sets z to the E6-product of x,x, returns z func (z *E6) Square(x *E6) *E6 { + // Algorithm 16 from https://eprint.iacr.org/2010/354.pdf var b0, b1, b2, b3, b4 E2 b3.Mul(&x.B0, &x.B1).Double(&b3) // step 1 @@ -269,6 +326,47 @@ func (z *E6) Square(x *E6) *E6 { return z } +// SquareAssign sets z to the E6-product of z,z returns z +func (z *E6) SquareAssign() *E6 { + + // Algorithm 16 from https://eprint.iacr.org/2010/354.pdf + var b0, b1, b2, b3, b4 E2 + b3.Mul(&z.B0, &z.B1).Double(&b3) // step 1 + b4.Square(&z.B2) // step 2 + + // step 3 + { // begin: inline b0.MulByNonResidue(&b4) + buf := (&b4).A0 + { // begin: inline MulByNonResidue(&(b0).A0, &(&b4).A1) + buf := *(&(&b4).A1) + (&(b0).A0).Double(&buf).Double(&(b0).A0).AddAssign(&buf) + } // end: inline MulByNonResidue(&(b0).A0, &(&b4).A1) + (b0).A1 = buf + } // end: inline b0.MulByNonResidue(&b4) + b0.AddAssign(&b3) + b1.Sub(&b3, &b4) // step 4 + b2.Square(&z.B0) // step 5 + b3.Sub(&z.B0, &z.B1).AddAssign(&z.B2).Square(&b3) // steps 6 and 8 + b4.Mul(&z.B1, &z.B2).Double(&b4) // step 7 + // step 9 + { // begin: inline z.B0.MulByNonResidue(&b4) + buf := (&b4).A0 + { // begin: inline MulByNonResidue(&(z.B0).A0, &(&b4).A1) + buf := *(&(&b4).A1) + (&(z.B0).A0).Double(&buf).Double(&(z.B0).A0).AddAssign(&buf) + } // end: inline MulByNonResidue(&(z.B0).A0, &(&b4).A1) + (z.B0).A1 = buf + } // end: inline z.B0.MulByNonResidue(&b4) + z.B0.AddAssign(&b2) + + // step 10 + z.B2.Add(&b1, &b3). + AddAssign(&b4). + SubAssign(&b2) + z.B1 = b0 + return z +} + // SquarE2 squares a E6 func (z *E6) SquarE2(x *E6) *E6 { // Karatsuba from Section 4 of https://eprint.iacr.org/2006/471.pdf diff --git a/bls377/frobenius.go b/bls377/frobenius.go new file mode 100644 index 0000000000..39f0a11ae4 --- /dev/null +++ b/bls377/frobenius.go @@ -0,0 +1,329 @@ +// Copyright 2020 ConsenSys AG +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by gurvy/internal/generators DO NOT EDIT + +package bls377 + +import "github.com/consensys/gurvy/bls377/fp" + +// Frobenius set z to Frobenius(x), return z +func (z *PairingResult) Frobenius(x *PairingResult) *PairingResult { + // Algorithm 28 from https://eprint.iacr.org/2010/354.pdf (beware typos!) + var t [6]E2 + + // Frobenius acts on fp2 by conjugation + t[0].Conjugate(&x.C0.B0) + t[1].Conjugate(&x.C0.B1) + t[2].Conjugate(&x.C0.B2) + t[3].Conjugate(&x.C1.B0) + t[4].Conjugate(&x.C1.B1) + t[5].Conjugate(&x.C1.B2) + + t[1].MulByNonResidue1Power2(&t[1]) + t[2].MulByNonResidue1Power4(&t[2]) + t[3].MulByNonResidue1Power1(&t[3]) + t[4].MulByNonResidue1Power3(&t[4]) + t[5].MulByNonResidue1Power5(&t[5]) + + z.C0.B0 = t[0] + z.C0.B1 = t[1] + z.C0.B2 = t[2] + z.C1.B0 = t[3] + z.C1.B1 = t[4] + z.C1.B2 = t[5] + + return z +} + +// FrobeniusSquare set z to Frobenius^2(x), and return z +func (z *PairingResult) FrobeniusSquare(x *PairingResult) *PairingResult { + // Algorithm 29 from https://eprint.iacr.org/2010/354.pdf (beware typos!) + var t [6]E2 + + t[1].MulByNonResidue2Power2(&x.C0.B1) + t[2].MulByNonResidue2Power4(&x.C0.B2) + t[3].MulByNonResidue2Power1(&x.C1.B0) + t[4].MulByNonResidue2Power3(&x.C1.B1) + t[5].MulByNonResidue2Power5(&x.C1.B2) + + z.C0.B0 = x.C0.B0 + z.C0.B1 = t[1] + z.C0.B2 = t[2] + z.C1.B0 = t[3] + z.C1.B1 = t[4] + z.C1.B2 = t[5] + + return z +} + +// FrobeniusCube set z to Frobenius^3(x), return z +func (z *PairingResult) FrobeniusCube(x *PairingResult) *PairingResult { + // Algorithm 30 from https://eprint.iacr.org/2010/354.pdf (beware typos!) + var t [6]E2 + + // Frobenius^3 acts on fp2 by conjugation + t[0].Conjugate(&x.C0.B0) + t[1].Conjugate(&x.C0.B1) + t[2].Conjugate(&x.C0.B2) + t[3].Conjugate(&x.C1.B0) + t[4].Conjugate(&x.C1.B1) + t[5].Conjugate(&x.C1.B2) + + t[1].MulByNonResidue3Power2(&t[1]) + t[2].MulByNonResidue3Power4(&t[2]) + t[3].MulByNonResidue3Power1(&t[3]) + t[4].MulByNonResidue3Power3(&t[4]) + t[5].MulByNonResidue3Power5(&t[5]) + + z.C0.B0 = t[0] + z.C0.B1 = t[1] + z.C0.B2 = t[2] + z.C1.B0 = t[3] + z.C1.B1 = t[4] + z.C1.B2 = t[5] + + return z +} + +// MulByNonResidue1Power1 set z=x*(0,1)^(1*(p^1-1)/6) and return z +func (z *E2) MulByNonResidue1Power1(x *E2) *E2 { + // 92949345220277864758624960506473182677953048909283248980960104381795901929519566951595905490535835115111760994353 + b := fp.Element{ + 7981638599956744862, + 11830407261614897732, + 6308788297503259939, + 10596665404780565693, + 11693741422477421038, + 61545186993886319, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} + +// MulByNonResidue1Power2 set z=x*(0,1)^(2*(p^1-1)/6) and return z +func (z *E2) MulByNonResidue1Power2(x *E2) *E2 { + // 80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410946 + b := fp.Element{ + 6382252053795993818, + 1383562296554596171, + 11197251941974877903, + 6684509567199238270, + 6699184357838251020, + 19987743694136192, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} + +// MulByNonResidue1Power3 set z=x*(0,1)^(3*(p^1-1)/6) and return z +func (z *E2) MulByNonResidue1Power3(x *E2) *E2 { + // 216465761340224619389371505802605247630151569547285782856803747159100223055385581585702401816380679166954762214499 + b := fp.Element{ + 10965161018967488287, + 18251363109856037426, + 7036083669251591763, + 16109345360066746489, + 4679973768683352764, + 96952949334633821, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} + +// MulByNonResidue1Power4 set z=x*(0,1)^(4*(p^1-1)/6) and return z +func (z *E2) MulByNonResidue1Power4(x *E2) *E2 { + // 80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410945 + b := fp.Element{ + 15766275933608376691, + 15635974902606112666, + 1934946774703877852, + 18129354943882397960, + 15437979634065614942, + 101285514078273488, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} + +// MulByNonResidue1Power5 set z=x*(0,1)^(5*(p^1-1)/6) and return z +func (z *E2) MulByNonResidue1Power5(x *E2) *E2 { + // 123516416119946754630746545296132064952198520638002533875843642777304321125866014634106496325844844051843001220146 + b := fp.Element{ + 2983522419010743425, + 6420955848241139694, + 727295371748331824, + 5512679955286180796, + 11432976419915483342, + 35407762340747501, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} + +// MulByNonResidue2Power1 set z=x*(0,1)^(1*(p^2-1)/6) and return z +func (z *E2) MulByNonResidue2Power1(x *E2) *E2 { + // 80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410946 + b := fp.Element{ + 6382252053795993818, + 1383562296554596171, + 11197251941974877903, + 6684509567199238270, + 6699184357838251020, + 19987743694136192, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} + +// MulByNonResidue2Power2 set z=x*(0,1)^(2*(p^2-1)/6) and return z +func (z *E2) MulByNonResidue2Power2(x *E2) *E2 { + // 80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410945 + b := fp.Element{ + 15766275933608376691, + 15635974902606112666, + 1934946774703877852, + 18129354943882397960, + 15437979634065614942, + 101285514078273488, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} + +// MulByNonResidue2Power3 set z=x*(0,1)^(3*(p^2-1)/6) and return z +func (z *E2) MulByNonResidue2Power3(x *E2) *E2 { + // 258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458176 + b := fp.Element{ + 9384023879812382873, + 14252412606051516495, + 9184438906438551565, + 11444845376683159689, + 8738795276227363922, + 81297770384137296, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} + +// MulByNonResidue2Power4 set z=x*(0,1)^(4*(p^2-1)/6) and return z +func (z *E2) MulByNonResidue2Power4(x *E2) *E2 { + // 258664426012969093929703085429980814127835149614277183275038967946009968870203535512256352201271898244626862047231 + b := fp.Element{ + 3203870859294639911, + 276961138506029237, + 9479726329337356593, + 13645541738420943632, + 7584832609311778094, + 101110569012358506, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} + +// MulByNonResidue2Power5 set z=x*(0,1)^(5*(p^2-1)/6) and return z +func (z *E2) MulByNonResidue2Power5(x *E2) *E2 { + // 258664426012969093929703085429980814127835149614277183275038967946009968870203535512256352201271898244626862047232 + b := fp.Element{ + 12266591053191808654, + 4471292606164064357, + 295287422898805027, + 2200696361737783943, + 17292781406793965788, + 19812798628221209, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} + +// MulByNonResidue3Power1 set z=x*(0,1)^(1*(p^3-1)/6) and return z +func (z *E2) MulByNonResidue3Power1(x *E2) *E2 { + // 216465761340224619389371505802605247630151569547285782856803747159100223055385581585702401816380679166954762214499 + b := fp.Element{ + 10965161018967488287, + 18251363109856037426, + 7036083669251591763, + 16109345360066746489, + 4679973768683352764, + 96952949334633821, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} + +// MulByNonResidue3Power2 set z=x*(0,1)^(2*(p^3-1)/6) and return z +func (z *E2) MulByNonResidue3Power2(x *E2) *E2 { + // 258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458176 + b := fp.Element{ + 9384023879812382873, + 14252412606051516495, + 9184438906438551565, + 11444845376683159689, + 8738795276227363922, + 81297770384137296, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} + +// MulByNonResidue3Power3 set z=x*(0,1)^(3*(p^3-1)/6) and return z +func (z *E2) MulByNonResidue3Power3(x *E2) *E2 { + // 42198664672744474621281227892288285906241943207628877683080515507620245292955241189266486323192680957485559243678 + b := fp.Element{ + 17067705967832697058, + 1855904398914139597, + 13640894602060642732, + 4220705945553435413, + 9604043198466676350, + 24145363371860877, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} + +// MulByNonResidue3Power4 set z=x*(0,1)^(4*(p^3-1)/6) and return z +func (z *E2) MulByNonResidue3Power4(x *E2) *E2 { + // 1 + // nothing to do + return z +} + +// MulByNonResidue3Power5 set z=x*(0,1)^(5*(p^3-1)/6) and return z +func (z *E2) MulByNonResidue3Power5(x *E2) *E2 { + // 216465761340224619389371505802605247630151569547285782856803747159100223055385581585702401816380679166954762214499 + b := fp.Element{ + 10965161018967488287, + 18251363109856037426, + 7036083669251591763, + 16109345360066746489, + 4679973768683352764, + 96952949334633821, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} diff --git a/bls377/g1.go b/bls377/g1.go index fa40561ce1..831840cc80 100644 --- a/bls377/g1.go +++ b/bls377/g1.go @@ -30,19 +30,21 @@ import ( "github.com/consensys/gurvy/utils/parallel" ) -// G1Jac is a point with fp.Element coordinates +type G1CoordType = fp.Element + +// G1Jac is a point with G1CoordType coordinates type G1Jac struct { - X, Y, Z fp.Element + X, Y, Z G1CoordType } // G1Affine point in affine coordinates type G1Affine struct { - X, Y fp.Element + X, Y G1CoordType } // g1JacExtended parameterized jacobian coordinates (x=X/ZZ, y=Y/ZZZ, ZZ**3=ZZZ**2) type g1JacExtended struct { - X, Y, ZZ, ZZZ fp.Element + X, Y, ZZ, ZZZ G1CoordType } // SetInfinity sets p to O @@ -86,7 +88,7 @@ func (p *g1JacExtended) mAdd(a *G1Affine) *g1JacExtended { return p } - var U2, S2, P, R, PP, PPP, Q, Q2, RR, X3, Y3 fp.Element + var U2, S2, P, R, PP, PPP, Q, Q2, RR, X3, Y3 G1CoordType // p2: a, p1: p U2.Mul(&a.X, &p.ZZ) @@ -116,7 +118,7 @@ func (p *g1JacExtended) mAdd(a *G1Affine) *g1JacExtended { // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1 func (p *g1JacExtended) double(q *G1Affine) *g1JacExtended { - var U, S, M, _M, Y3 fp.Element + var U, S, M, _M, Y3 G1CoordType U.Double(&q.Y) p.ZZ.Square(&U) @@ -195,7 +197,7 @@ func (p *G1Jac) Sub(curve *Curve, a G1Jac) *G1Jac { // WARNING super slow function (due to the division) func (p *G1Jac) ToAffineFromJac(res *G1Affine) *G1Affine { - var bufs [3]fp.Element + var bufs [3]G1CoordType if p.Z.IsZero() { res.X.SetZero() @@ -216,7 +218,7 @@ func (p *G1Jac) ToAffineFromJac(res *G1Affine) *G1Affine { // ToProjFromJac converts a point from Jacobian to projective coordinates func (p *G1Jac) ToProjFromJac() *G1Jac { // memalloc - var buf fp.Element + var buf G1CoordType buf.Square(&p.Z) p.X.Mul(&p.X, &p.Z) @@ -251,7 +253,7 @@ func (p *G1Affine) ToJacobian(Q *G1Jac) *G1Jac { } func (p *G1Affine) String(curve *Curve) string { - var x, y fp.Element + var x, y G1CoordType x.Set(&p.X) y.Set(&p.Y) return "E([" + x.String() + "," + y.String() + "])," @@ -279,7 +281,7 @@ func (p *G1Jac) Add(curve *Curve, a *G1Jac) *G1Jac { } // get some Element from our pool - var Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V fp.Element + var Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V G1CoordType // Z1Z1 = a.Z ^ 2 Z1Z1.Square(&a.Z) @@ -364,7 +366,7 @@ func (p *G1Jac) AddMixed(a *G1Affine) *G1Jac { } // get some Element from our pool - var Z1Z1, U2, S2, H, HH, I, J, r, V fp.Element + var Z1Z1, U2, S2, H, HH, I, J, r, V G1CoordType // Z1Z1 = p.Z ^ 2 Z1Z1.Square(&p.Z) @@ -422,7 +424,7 @@ func (p *G1Jac) AddMixed(a *G1Affine) *G1Jac { // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl func (p *G1Jac) Double() *G1Jac { // get some Element from our pool - var XX, YY, YYYY, ZZ, S, M, T fp.Element + var XX, YY, YYYY, ZZ, S, M, T G1CoordType // XX = a.X^2 XX.Square(&p.X) diff --git a/bls377/g2.go b/bls377/g2.go index e5b1f63bfa..a40caddaa1 100644 --- a/bls377/g2.go +++ b/bls377/g2.go @@ -27,19 +27,21 @@ import ( "github.com/consensys/gurvy/utils/parallel" ) -// G2Jac is a point with E2 coordinates +type G2CoordType = E2 + +// G2Jac is a point with G2CoordType coordinates type G2Jac struct { - X, Y, Z E2 + X, Y, Z G2CoordType } // G2Affine point in affine coordinates type G2Affine struct { - X, Y E2 + X, Y G2CoordType } // g2JacExtended parameterized jacobian coordinates (x=X/ZZ, y=Y/ZZZ, ZZ**3=ZZZ**2) type g2JacExtended struct { - X, Y, ZZ, ZZZ E2 + X, Y, ZZ, ZZZ G2CoordType } // SetInfinity sets p to O @@ -83,7 +85,7 @@ func (p *g2JacExtended) mAdd(a *G2Affine) *g2JacExtended { return p } - var U2, S2, P, R, PP, PPP, Q, Q2, RR, X3, Y3 E2 + var U2, S2, P, R, PP, PPP, Q, Q2, RR, X3, Y3 G2CoordType // p2: a, p1: p U2.Mul(&a.X, &p.ZZ) @@ -113,7 +115,7 @@ func (p *g2JacExtended) mAdd(a *G2Affine) *g2JacExtended { // http://www.hyperelliptic.org/EFD/g2p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1 func (p *g2JacExtended) double(q *G2Affine) *g2JacExtended { - var U, S, M, _M, Y3 E2 + var U, S, M, _M, Y3 G2CoordType U.Double(&q.Y) p.ZZ.Square(&U) @@ -192,7 +194,7 @@ func (p *G2Jac) Sub(curve *Curve, a G2Jac) *G2Jac { // WARNING super slow function (due to the division) func (p *G2Jac) ToAffineFromJac(res *G2Affine) *G2Affine { - var bufs [3]E2 + var bufs [3]G2CoordType if p.Z.IsZero() { res.X.SetZero() @@ -213,7 +215,7 @@ func (p *G2Jac) ToAffineFromJac(res *G2Affine) *G2Affine { // ToProjFromJac converts a point from Jacobian to projective coordinates func (p *G2Jac) ToProjFromJac() *G2Jac { // memalloc - var buf E2 + var buf G2CoordType buf.Square(&p.Z) p.X.Mul(&p.X, &p.Z) @@ -248,7 +250,7 @@ func (p *G2Affine) ToJacobian(Q *G2Jac) *G2Jac { } func (p *G2Affine) String(curve *Curve) string { - var x, y E2 + var x, y G2CoordType x.Set(&p.X) y.Set(&p.Y) return "E([" + x.String() + "," + y.String() + "])," @@ -276,7 +278,7 @@ func (p *G2Jac) Add(curve *Curve, a *G2Jac) *G2Jac { } // get some Element from our pool - var Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V E2 + var Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V G2CoordType // Z1Z1 = a.Z ^ 2 Z1Z1.Square(&a.Z) @@ -361,7 +363,7 @@ func (p *G2Jac) AddMixed(a *G2Affine) *G2Jac { } // get some Element from our pool - var Z1Z1, U2, S2, H, HH, I, J, r, V E2 + var Z1Z1, U2, S2, H, HH, I, J, r, V G2CoordType // Z1Z1 = p.Z ^ 2 Z1Z1.Square(&p.Z) @@ -419,7 +421,7 @@ func (p *G2Jac) AddMixed(a *G2Affine) *G2Jac { // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl func (p *G2Jac) Double() *G2Jac { // get some Element from our pool - var XX, YY, YYYY, ZZ, S, M, T E2 + var XX, YY, YYYY, ZZ, S, M, T G2CoordType // XX = a.X^2 XX.Square(&p.X) diff --git a/bls377/pairing.go b/bls377/pairing.go index fbc152b6e1..56c86ad55d 100644 --- a/bls377/pairing.go +++ b/bls377/pairing.go @@ -16,8 +16,6 @@ package bls377 -import "github.com/consensys/gurvy/bls377/fp" - // FinalExponentiation computes the final expo x**(p**6-1)(p**2+1)(p**4 - p**2 +1)/r func (curve *Curve) FinalExponentiation(z *PairingResult, _z ...*PairingResult) PairingResult { var result PairingResult @@ -34,7 +32,6 @@ func (curve *Curve) FinalExponentiation(z *PairingResult, _z ...*PairingResult) } // FinalExponentiation sets z to the final expo x**((p**12 - 1)/r), returns z -// TODO customize this comment for the curve func (z *PairingResult) FinalExponentiation(x *PairingResult) *PairingResult { // For BLS curves use Section 3 of https://eprint.iacr.org/2016/130.pdf; "hard part" is Algorithm 1 of https://eprint.iacr.org/2016/130.pdf var result PairingResult @@ -118,6 +115,7 @@ func (curve *Curve) MillerLoop(P G1Affine, Q G2Affine, result *PairingResult) *P // Miller loop for i := len(curve.loopCounter) - 2; i >= 0; i-- { + QNext.Set(&QCur) QNext.Double() QNextNeg.Neg(&QNext) @@ -208,9 +206,9 @@ func lineEvalAffine(Q G2Jac, R G2Affine, P *G1Affine, result *lineEvalRes) { } type lineEvalRes struct { - r0 E2 // c0.b1 - r1 E2 // c1.b1 - r2 E2 // c1.b2 + r0 G2CoordType // c0.b1 + r1 G2CoordType // c1.b1 + r2 G2CoordType // c1.b2 } func (l *lineEvalRes) mulAssign(z *PairingResult) *PairingResult { @@ -224,336 +222,12 @@ func (l *lineEvalRes) mulAssign(z *PairingResult) *PairingResult { return z } -// Frobenius set z to Frobenius(x) in E12 and return z -func (z *E12) Frobenius(x *E12) *E12 { - // Algorithm 28 from https://eprint.iacr.org/2010/354.pdf (beware typos!) - var t [6]E2 - - // Frobenius acts on fp2 by conjugation - t[0].Conjugate(&x.C0.B0) - t[1].Conjugate(&x.C0.B1) - t[2].Conjugate(&x.C0.B2) - t[3].Conjugate(&x.C1.B0) - t[4].Conjugate(&x.C1.B1) - t[5].Conjugate(&x.C1.B2) - - t[1].MulByNonResiduePower2(&t[1]) - t[2].MulByNonResiduePower4(&t[2]) - t[3].MulByNonResiduePower1(&t[3]) - t[4].MulByNonResiduePower3(&t[4]) - t[5].MulByNonResiduePower5(&t[5]) - - z.C0.B0 = t[0] - z.C0.B1 = t[1] - z.C0.B2 = t[2] - z.C1.B0 = t[3] - z.C1.B1 = t[4] - z.C1.B2 = t[5] - - return z -} - -// FrobeniusSquare set z to Frobenius^2(x) in E12 and return z -func (z *E12) FrobeniusSquare(x *E12) *E12 { - // Algorithm 29 from https://eprint.iacr.org/2010/354.pdf (beware typos!) - var t [6]E2 - - t[1].MulByNonResiduePowerSquare2(&x.C0.B1) - t[2].MulByNonResiduePowerSquare4(&x.C0.B2) - t[3].MulByNonResiduePowerSquare1(&x.C1.B0) - t[4].MulByNonResiduePowerSquare3(&x.C1.B1) - t[5].MulByNonResiduePowerSquare5(&x.C1.B2) - - z.C0.B0 = x.C0.B0 - z.C0.B1 = t[1] - z.C0.B2 = t[2] - z.C1.B0 = t[3] - z.C1.B1 = t[4] - z.C1.B2 = t[5] - - return z -} - -// FrobeniusCube set z to Frobenius^3(x) in E12 and return z -func (z *E12) FrobeniusCube(x *E12) *E12 { - // Algorithm 30 from https://eprint.iacr.org/2010/354.pdf (beware typos!) - var t [6]E2 - - // Frobenius^3 acts on fp2 by conjugation - t[0].Conjugate(&x.C0.B0) - t[1].Conjugate(&x.C0.B1) - t[2].Conjugate(&x.C0.B2) - t[3].Conjugate(&x.C1.B0) - t[4].Conjugate(&x.C1.B1) - t[5].Conjugate(&x.C1.B2) - - t[1].MulByNonResiduePowerCube2(&t[1]) - t[2].MulByNonResiduePowerCube4(&t[2]) - t[3].MulByNonResiduePowerCube1(&t[3]) - t[4].MulByNonResiduePowerCube3(&t[4]) - t[5].MulByNonResiduePowerCube5(&t[5]) - - z.C0.B0 = t[0] - z.C0.B1 = t[1] - z.C0.B2 = t[2] - z.C1.B0 = t[3] - z.C1.B1 = t[4] - z.C1.B2 = t[5] - - return z -} - -// MulByNonResiduePower1 set z=x*(0,1)^(1*(p-1)/6) and return z -func (z *E2) MulByNonResiduePower1(x *E2) *E2 { - // (0,1)^(1*(p-1)/6) - // 92949345220277864758624960506473182677953048909283248980960104381795901929519566951595905490535835115111760994353 - b := fp.Element{ - 7981638599956744862, - 11830407261614897732, - 6308788297503259939, - 10596665404780565693, - 11693741422477421038, - 61545186993886319, - } - z.A0.Mul(&x.A0, &b) - z.A1.Mul(&x.A1, &b) - return z -} - -// MulByNonResiduePower2 set z=x*(0,1)^(2*(p-1)/6) and return z -func (z *E2) MulByNonResiduePower2(x *E2) *E2 { - // (0,1)^(2*(p-1)/6) - // 80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410946 - b := fp.Element{ - 6382252053795993818, - 1383562296554596171, - 11197251941974877903, - 6684509567199238270, - 6699184357838251020, - 19987743694136192, - } - z.A0.Mul(&x.A0, &b) - z.A1.Mul(&x.A1, &b) - return z -} - -// MulByNonResiduePower3 set z=x*(0,1)^(3*(p-1)/6) and return z -func (z *E2) MulByNonResiduePower3(x *E2) *E2 { - // (0,1)^(3*(p-1)/6) - // 216465761340224619389371505802605247630151569547285782856803747159100223055385581585702401816380679166954762214499 - b := fp.Element{ - 10965161018967488287, - 18251363109856037426, - 7036083669251591763, - 16109345360066746489, - 4679973768683352764, - 96952949334633821, - } - z.A0.Mul(&x.A0, &b) - z.A1.Mul(&x.A1, &b) - return z -} - -// MulByNonResiduePower4 set z=x*(0,1)^(4*(p-1)/6) and return z -func (z *E2) MulByNonResiduePower4(x *E2) *E2 { - // (0,1)^(4*(p-1)/6) - // 80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410945 - b := fp.Element{ - 15766275933608376691, - 15635974902606112666, - 1934946774703877852, - 18129354943882397960, - 15437979634065614942, - 101285514078273488, - } - z.A0.Mul(&x.A0, &b) - z.A1.Mul(&x.A1, &b) - return z -} - -// MulByNonResiduePower5 set z=x*(0,1)^(5*(p-1)/6) and return z -func (z *E2) MulByNonResiduePower5(x *E2) *E2 { - // (0,1)^(5*(p-1)/6) - // 123516416119946754630746545296132064952198520638002533875843642777304321125866014634106496325844844051843001220146 - b := fp.Element{ - 2983522419010743425, - 6420955848241139694, - 727295371748331824, - 5512679955286180796, - 11432976419915483342, - 35407762340747501, - } - z.A0.Mul(&x.A0, &b) - z.A1.Mul(&x.A1, &b) - return z -} - -// MulByNonResiduePowerSquare1 set z=x*(0,1)^(1*(p^2-1)/6) and return z -func (z *E2) MulByNonResiduePowerSquare1(x *E2) *E2 { - // (0,1)^(1*(p^2-1)/6) - // 80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410946 - b := fp.Element{ - 6382252053795993818, - 1383562296554596171, - 11197251941974877903, - 6684509567199238270, - 6699184357838251020, - 19987743694136192, - } - z.A0.Mul(&x.A0, &b) - z.A1.Mul(&x.A1, &b) - return z -} - -// MulByNonResiduePowerSquare2 set z=x*(0,1)^(2*(p^2-1)/6) and return z -func (z *E2) MulByNonResiduePowerSquare2(x *E2) *E2 { - // (0,1)^(2*(p^2-1)/6) - // 80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410945 - b := fp.Element{ - 15766275933608376691, - 15635974902606112666, - 1934946774703877852, - 18129354943882397960, - 15437979634065614942, - 101285514078273488, - } - z.A0.Mul(&x.A0, &b) - z.A1.Mul(&x.A1, &b) - return z -} - -// MulByNonResiduePowerSquare3 set z=x*(0,1)^(3*(p^2-1)/6) and return z -func (z *E2) MulByNonResiduePowerSquare3(x *E2) *E2 { - // (0,1)^(3*(p^2-1)/6) - // 258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458176 - b := fp.Element{ - 9384023879812382873, - 14252412606051516495, - 9184438906438551565, - 11444845376683159689, - 8738795276227363922, - 81297770384137296, - } - z.A0.Mul(&x.A0, &b) - z.A1.Mul(&x.A1, &b) - return z -} - -// MulByNonResiduePowerSquare4 set z=x*(0,1)^(4*(p^2-1)/6) and return z -func (z *E2) MulByNonResiduePowerSquare4(x *E2) *E2 { - // (0,1)^(4*(p^2-1)/6) - // 258664426012969093929703085429980814127835149614277183275038967946009968870203535512256352201271898244626862047231 - b := fp.Element{ - 3203870859294639911, - 276961138506029237, - 9479726329337356593, - 13645541738420943632, - 7584832609311778094, - 101110569012358506, - } - z.A0.Mul(&x.A0, &b) - z.A1.Mul(&x.A1, &b) - return z -} - -// MulByNonResiduePowerSquare5 set z=x*(0,1)^(5*(p^2-1)/6) and return z -func (z *E2) MulByNonResiduePowerSquare5(x *E2) *E2 { - // (0,1)^(5*(p^2-1)/6) - // 258664426012969093929703085429980814127835149614277183275038967946009968870203535512256352201271898244626862047232 - b := fp.Element{ - 12266591053191808654, - 4471292606164064357, - 295287422898805027, - 2200696361737783943, - 17292781406793965788, - 19812798628221209, - } - z.A0.Mul(&x.A0, &b) - z.A1.Mul(&x.A1, &b) - return z -} - -// MulByNonResiduePowerCube1 set z=x*(0,1)^(1*(p^3-1)/6) and return z -func (z *E2) MulByNonResiduePowerCube1(x *E2) *E2 { - // (0,1)^(1*(p^3-1)/6) - // 216465761340224619389371505802605247630151569547285782856803747159100223055385581585702401816380679166954762214499 - b := fp.Element{ - 10965161018967488287, - 18251363109856037426, - 7036083669251591763, - 16109345360066746489, - 4679973768683352764, - 96952949334633821, - } - z.A0.Mul(&x.A0, &b) - z.A1.Mul(&x.A1, &b) - return z -} - -// MulByNonResiduePowerCube2 set z=x*(0,1)^(2*(p^3-1)/6) and return z -func (z *E2) MulByNonResiduePowerCube2(x *E2) *E2 { - // (0,1)^(2*(p^3-1)/6) - // 258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458176 - b := fp.Element{ - 9384023879812382873, - 14252412606051516495, - 9184438906438551565, - 11444845376683159689, - 8738795276227363922, - 81297770384137296, - } - z.A0.Mul(&x.A0, &b) - z.A1.Mul(&x.A1, &b) - return z -} - -// MulByNonResiduePowerCube3 set z=x*(0,1)^(3*(p^3-1)/6) and return z -func (z *E2) MulByNonResiduePowerCube3(x *E2) *E2 { - // (0,1)^(3*(p^3-1)/6) - // 42198664672744474621281227892288285906241943207628877683080515507620245292955241189266486323192680957485559243678 - b := fp.Element{ - 17067705967832697058, - 1855904398914139597, - 13640894602060642732, - 4220705945553435413, - 9604043198466676350, - 24145363371860877, - } - z.A0.Mul(&x.A0, &b) - z.A1.Mul(&x.A1, &b) - return z -} - -// MulByNonResiduePowerCube4 set z=x*(0,1)^(4*(p^3-1)/6) and return z -func (z *E2) MulByNonResiduePowerCube4(x *E2) *E2 { - // (0,1)^(4*(p^3-1)/6) - // the value is 1; nothing to do - return z -} - -// MulByNonResiduePowerCube5 set z=x*(0,1)^(5*(p^3-1)/6) and return z -func (z *E2) MulByNonResiduePowerCube5(x *E2) *E2 { - // (0,1)^(5*(p^3-1)/6) - // 216465761340224619389371505802605247630151569547285782856803747159100223055385581585702401816380679166954762214499 - b := fp.Element{ - 10965161018967488287, - 18251363109856037426, - 7036083669251591763, - 16109345360066746489, - 4679973768683352764, - 96952949334633821, - } - z.A0.Mul(&x.A0, &b) - z.A1.Mul(&x.A1, &b) - return z -} - const tAbsVal uint64 = 9586122913090633729 -// Expt set z to x^t in E12 and return z +// Expt set z to x^t in PairingResult and return z // TODO make a ExptAssign method that assigns the result to self; then this method can assert fail if z != x // TODO Expt is the only method that depends on tAbsVal. The rest of the tower does not depend on this value. Logically, Expt should be separated from the rest of the tower. -func (z *E12) Expt(x *E12) *E12 { +func (z *PairingResult) Expt(x *PairingResult) *PairingResult { // TODO what if x==0? // TODO make this match Element.Exp: x is a non-pointer? @@ -561,7 +235,7 @@ func (z *E12) Expt(x *E12) *E12 { // drop the low 46 bits (all 0 except the least significant bit): 100001010000100011 = 136227 // Shortest addition chains can be found at https://wwwhomes.uni-bielefeld.de/achim/addition_chain.html - var result, x33 E12 + var result, x33 PairingResult // a shortest addition chain for 136227 result.Set(x) // 0 1 diff --git a/bls381/e6.go b/bls381/e6.go index bf9a5e37f0..9f3edf360d 100644 --- a/bls381/e6.go +++ b/bls381/e6.go @@ -140,13 +140,15 @@ func (z *E6) String() string { return (z.B0.String() + "+(" + z.B1.String() + ")*v+(" + z.B2.String() + ")*v**2") } -// Mul multiplies two numbers in E6 +// Mul sets z to the E6-product of x,y, returns z func (z *E6) Mul(x, y *E6) *E6 { + // Algorithm 13 from https://eprint.iacr.org/2010/354.pdf var rb0, b0, b1, b2, b3, b4 E2 b0.Mul(&x.B0, &y.B0) // step 1 b1.Mul(&x.B1, &y.B1) // step 2 b2.Mul(&x.B2, &y.B2) // step 3 + // step 4 b3.Add(&x.B1, &x.B2) b4.Add(&y.B1, &y.B2) @@ -163,6 +165,7 @@ func (z *E6) Mul(x, y *E6) *E6 { rb0.A0.AddAssign(&buf.A0) } // end: inline rb0.MulByNonResidue(&rb0) rb0.AddAssign(&b0) + // step 5 b3.Add(&x.B0, &x.B1) b4.Add(&y.B0, &y.B1) @@ -179,6 +182,7 @@ func (z *E6) Mul(x, y *E6) *E6 { b3.A0.AddAssign(&buf.A0) } // end: inline b3.MulByNonResidue(&b2) z.B1.AddAssign(&b3) + // step 6 b3.Add(&x.B0, &x.B2) b4.Add(&y.B0, &y.B2) @@ -190,6 +194,60 @@ func (z *E6) Mul(x, y *E6) *E6 { return z } +// MulAssign sets z to the E6-product of z,x returns z +func (z *E6) MulAssign(x *E6) *E6 { + + // Algorithm 13 from https://eprint.iacr.org/2010/354.pdf + var rb0, b0, b1, b2, b3, b4 E2 + b0.Mul(&z.B0, &x.B0) // step 1 + b1.Mul(&z.B1, &x.B1) // step 2 + b2.Mul(&z.B2, &x.B2) // step 3 + + // step 4 + b3.Add(&z.B1, &z.B2) + b4.Add(&x.B1, &x.B2) + rb0.Mul(&b3, &b4). + SubAssign(&b1). + SubAssign(&b2) + { // begin: inline rb0.MulByNonResidue(&rb0) + var buf E2 + buf.Set(&rb0) + rb0.A1.Add(&buf.A0, &buf.A1) + { // begin: inline MulByNonResidue(&(rb0).A0, &buf.A1) + (&(rb0).A0).Neg(&buf.A1) + } // end: inline MulByNonResidue(&(rb0).A0, &buf.A1) + rb0.A0.AddAssign(&buf.A0) + } // end: inline rb0.MulByNonResidue(&rb0) + rb0.AddAssign(&b0) + + // step 5 + b3.Add(&z.B0, &z.B1) + b4.Add(&x.B0, &x.B1) + z.B1.Mul(&b3, &b4). + SubAssign(&b0). + SubAssign(&b1) + { // begin: inline b3.MulByNonResidue(&b2) + var buf E2 + buf.Set(&b2) + b3.A1.Add(&buf.A0, &buf.A1) + { // begin: inline MulByNonResidue(&(b3).A0, &buf.A1) + (&(b3).A0).Neg(&buf.A1) + } // end: inline MulByNonResidue(&(b3).A0, &buf.A1) + b3.A0.AddAssign(&buf.A0) + } // end: inline b3.MulByNonResidue(&b2) + z.B1.AddAssign(&b3) + + // step 6 + b3.Add(&z.B0, &z.B2) + b4.Add(&x.B0, &x.B2) + z.B2.Mul(&b3, &b4). + SubAssign(&b0). + SubAssign(&b2). + AddAssign(&b1) + z.B0 = rb0 + return z +} + // MulByE2 multiplies x by an elements of E2 func (z *E6) MulByE2(x *E6, y *E2) *E6 { var yCopy E2 @@ -233,8 +291,9 @@ func (z *E6) MulByNotv2(x, y *E6) *E6 { return z } -// Square squares a E6 +// Square sets z to the E6-product of x,x, returns z func (z *E6) Square(x *E6) *E6 { + // Algorithm 16 from https://eprint.iacr.org/2010/354.pdf var b0, b1, b2, b3, b4 E2 b3.Mul(&x.B0, &x.B1).Double(&b3) // step 1 @@ -275,6 +334,49 @@ func (z *E6) Square(x *E6) *E6 { return z } +// SquareAssign sets z to the E6-product of z,z returns z +func (z *E6) SquareAssign() *E6 { + + // Algorithm 16 from https://eprint.iacr.org/2010/354.pdf + var b0, b1, b2, b3, b4 E2 + b3.Mul(&z.B0, &z.B1).Double(&b3) // step 1 + b4.Square(&z.B2) // step 2 + + // step 3 + { // begin: inline b0.MulByNonResidue(&b4) + var buf E2 + buf.Set(&b4) + b0.A1.Add(&buf.A0, &buf.A1) + { // begin: inline MulByNonResidue(&(b0).A0, &buf.A1) + (&(b0).A0).Neg(&buf.A1) + } // end: inline MulByNonResidue(&(b0).A0, &buf.A1) + b0.A0.AddAssign(&buf.A0) + } // end: inline b0.MulByNonResidue(&b4) + b0.AddAssign(&b3) + b1.Sub(&b3, &b4) // step 4 + b2.Square(&z.B0) // step 5 + b3.Sub(&z.B0, &z.B1).AddAssign(&z.B2).Square(&b3) // steps 6 and 8 + b4.Mul(&z.B1, &z.B2).Double(&b4) // step 7 + // step 9 + { // begin: inline z.B0.MulByNonResidue(&b4) + var buf E2 + buf.Set(&b4) + z.B0.A1.Add(&buf.A0, &buf.A1) + { // begin: inline MulByNonResidue(&(z.B0).A0, &buf.A1) + (&(z.B0).A0).Neg(&buf.A1) + } // end: inline MulByNonResidue(&(z.B0).A0, &buf.A1) + z.B0.A0.AddAssign(&buf.A0) + } // end: inline z.B0.MulByNonResidue(&b4) + z.B0.AddAssign(&b2) + + // step 10 + z.B2.Add(&b1, &b3). + AddAssign(&b4). + SubAssign(&b2) + z.B1 = b0 + return z +} + // SquarE2 squares a E6 func (z *E6) SquarE2(x *E6) *E6 { // Karatsuba from Section 4 of https://eprint.iacr.org/2006/471.pdf diff --git a/bls381/frobenius.go b/bls381/frobenius.go new file mode 100644 index 0000000000..f5f7e8036d --- /dev/null +++ b/bls381/frobenius.go @@ -0,0 +1,410 @@ +// Copyright 2020 ConsenSys AG +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by gurvy/internal/generators DO NOT EDIT + +package bls381 + +import "github.com/consensys/gurvy/bls381/fp" + +// Frobenius set z to Frobenius(x), return z +func (z *PairingResult) Frobenius(x *PairingResult) *PairingResult { + // Algorithm 28 from https://eprint.iacr.org/2010/354.pdf (beware typos!) + var t [6]E2 + + // Frobenius acts on fp2 by conjugation + t[0].Conjugate(&x.C0.B0) + t[1].Conjugate(&x.C0.B1) + t[2].Conjugate(&x.C0.B2) + t[3].Conjugate(&x.C1.B0) + t[4].Conjugate(&x.C1.B1) + t[5].Conjugate(&x.C1.B2) + + t[1].MulByNonResidue1Power2(&t[1]) + t[2].MulByNonResidue1Power4(&t[2]) + t[3].MulByNonResidue1Power1(&t[3]) + t[4].MulByNonResidue1Power3(&t[4]) + t[5].MulByNonResidue1Power5(&t[5]) + + z.C0.B0 = t[0] + z.C0.B1 = t[1] + z.C0.B2 = t[2] + z.C1.B0 = t[3] + z.C1.B1 = t[4] + z.C1.B2 = t[5] + + return z +} + +// FrobeniusSquare set z to Frobenius^2(x), and return z +func (z *PairingResult) FrobeniusSquare(x *PairingResult) *PairingResult { + // Algorithm 29 from https://eprint.iacr.org/2010/354.pdf (beware typos!) + var t [6]E2 + + t[1].MulByNonResidue2Power2(&x.C0.B1) + t[2].MulByNonResidue2Power4(&x.C0.B2) + t[3].MulByNonResidue2Power1(&x.C1.B0) + t[4].MulByNonResidue2Power3(&x.C1.B1) + t[5].MulByNonResidue2Power5(&x.C1.B2) + + z.C0.B0 = x.C0.B0 + z.C0.B1 = t[1] + z.C0.B2 = t[2] + z.C1.B0 = t[3] + z.C1.B1 = t[4] + z.C1.B2 = t[5] + + return z +} + +// FrobeniusCube set z to Frobenius^3(x), return z +func (z *PairingResult) FrobeniusCube(x *PairingResult) *PairingResult { + // Algorithm 30 from https://eprint.iacr.org/2010/354.pdf (beware typos!) + var t [6]E2 + + // Frobenius^3 acts on fp2 by conjugation + t[0].Conjugate(&x.C0.B0) + t[1].Conjugate(&x.C0.B1) + t[2].Conjugate(&x.C0.B2) + t[3].Conjugate(&x.C1.B0) + t[4].Conjugate(&x.C1.B1) + t[5].Conjugate(&x.C1.B2) + + t[1].MulByNonResidue3Power2(&t[1]) + t[2].MulByNonResidue3Power4(&t[2]) + t[3].MulByNonResidue3Power1(&t[3]) + t[4].MulByNonResidue3Power3(&t[4]) + t[5].MulByNonResidue3Power5(&t[5]) + + z.C0.B0 = t[0] + z.C0.B1 = t[1] + z.C0.B2 = t[2] + z.C1.B0 = t[3] + z.C1.B1 = t[4] + z.C1.B2 = t[5] + + return z +} + +// MulByNonResidue1Power1 set z=x*(1,1)^(1*(p^1-1)/6) and return z +func (z *E2) MulByNonResidue1Power1(x *E2) *E2 { + // (3850754370037169011952147076051364057158807420970682438676050522613628423219637725072182697113062777891589506424760,151655185184498381465642749684540099398075398968325446656007613510403227271200139370504932015952886146304766135027) + b := E2{ + A0: fp.Element{ + 506819140503852133, + 14297063575771579155, + 10946065744702939791, + 11771194236670323182, + 2081670087578406477, + 644615147456521963, + }, + A1: fp.Element{ + 12895611875574011462, + 6359822009455181036, + 14936352902570693524, + 13914887797453940944, + 3330433690892295817, + 1229183470191017903, + }, + } + z.Mul(x, &b) + return z +} + +// MulByNonResidue1Power2 set z=x*(1,1)^(2*(p^1-1)/6) and return z +func (z *E2) MulByNonResidue1Power2(x *E2) *E2 { + // (0,4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436) + b := E2{ + A0: fp.Element{ + 0, + 0, + 0, + 0, + 0, + 0, + }, + A1: fp.Element{ + 14772873186050699377, + 6749526151121446354, + 6372666795664677781, + 10283423008382700446, + 286397964926079186, + 1796971870900422465, + }, + } + z.Mul(x, &b) + return z +} + +// MulByNonResidue1Power3 set z=x*(1,1)^(3*(p^1-1)/6) and return z +func (z *E2) MulByNonResidue1Power3(x *E2) *E2 { + // (1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257,1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257) + b := E2{ + A0: fp.Element{ + 8921533702591418330, + 15859389534032789116, + 3389114680249073393, + 15116930867080254631, + 3288288975085550621, + 1021049300055853010, + }, + A1: fp.Element{ + 8921533702591418330, + 15859389534032789116, + 3389114680249073393, + 15116930867080254631, + 3288288975085550621, + 1021049300055853010, + }, + } + z.Mul(x, &b) + return z +} + +// MulByNonResidue1Power4 set z=x*(1,1)^(4*(p^1-1)/6) and return z +func (z *E2) MulByNonResidue1Power4(x *E2) *E2 { + // 4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939437 + b := fp.Element{ + 9875771541238924739, + 3094855109658912213, + 5802897354862067244, + 11677019699073781796, + 1505592401347711080, + 1505729768134575418, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} + +// MulByNonResidue1Power5 set z=x*(1,1)^(5*(p^1-1)/6) and return z +func (z *E2) MulByNonResidue1Power5(x *E2) *E2 { + // (877076961050607968509681729531255177986764537961432449499635504522207616027455086505066378536590128544573588734230,3125332594171059424908108096204648978570118281977575435832422631601824034463382777937621250592425535493320683825557) + b := E2{ + A0: fp.Element{ + 9428352843095270463, + 11709709036094816655, + 14335180424952013185, + 8441381030041026197, + 5369959062663957099, + 1665664447512374973, + }, + A1: fp.Element{ + 3974078172982593132, + 8947176549131943536, + 11547238222321620130, + 17244701004083237929, + 42144715806745195, + 208134170135164893, + }, + } + z.Mul(x, &b) + return z +} + +// MulByNonResidue2Power1 set z=x*(1,1)^(1*(p^2-1)/6) and return z +func (z *E2) MulByNonResidue2Power1(x *E2) *E2 { + // 793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620351 + b := fp.Element{ + 17076301903736715834, + 13907359434105313836, + 1063007777899403918, + 15402659025741563681, + 5125705813544623108, + 76826746747117401, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} + +// MulByNonResidue2Power2 set z=x*(1,1)^(2*(p^2-1)/6) and return z +func (z *E2) MulByNonResidue2Power2(x *E2) *E2 { + // 793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350 + b := fp.Element{ + 3526659474838938856, + 17562030475567847978, + 1632777218702014455, + 14009062335050482331, + 3906511377122991214, + 368068849512964448, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} + +// MulByNonResidue2Power3 set z=x*(1,1)^(3*(p^2-1)/6) and return z +func (z *E2) MulByNonResidue2Power3(x *E2) *E2 { + // 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559786 + b := fp.Element{ + 4897101644811774638, + 3654671041462534141, + 569769440802610537, + 17053147383018470266, + 17227549637287919721, + 291242102765847046, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} + +// MulByNonResidue2Power4 set z=x*(1,1)^(4*(p^2-1)/6) and return z +func (z *E2) MulByNonResidue2Power4(x *E2) *E2 { + // 4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436 + b := fp.Element{ + 14772873186050699377, + 6749526151121446354, + 6372666795664677781, + 10283423008382700446, + 286397964926079186, + 1796971870900422465, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} + +// MulByNonResidue2Power5 set z=x*(1,1)^(5*(p^2-1)/6) and return z +func (z *E2) MulByNonResidue2Power5(x *E2) *E2 { + // 4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939437 + b := fp.Element{ + 9875771541238924739, + 3094855109658912213, + 5802897354862067244, + 11677019699073781796, + 1505592401347711080, + 1505729768134575418, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} + +// MulByNonResidue3Power1 set z=x*(1,1)^(1*(p^3-1)/6) and return z +func (z *E2) MulByNonResidue3Power1(x *E2) *E2 { + // (2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530,1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257) + b := E2{ + A0: fp.Element{ + 4480897313486445265, + 4797496051193971075, + 4046559893315008306, + 10569151167044009496, + 2123814803385151673, + 852749317591686856, + }, + A1: fp.Element{ + 8921533702591418330, + 15859389534032789116, + 3389114680249073393, + 15116930867080254631, + 3288288975085550621, + 1021049300055853010, + }, + } + z.Mul(x, &b) + return z +} + +// MulByNonResidue3Power2 set z=x*(1,1)^(2*(p^3-1)/6) and return z +func (z *E2) MulByNonResidue3Power2(x *E2) *E2 { + // (0,1) + b := E2{ + A0: fp.Element{ + 0, + 0, + 0, + 0, + 0, + 0, + }, + A1: fp.Element{ + 8505329371266088957, + 17002214543764226050, + 6865905132761471162, + 8632934651105793861, + 6631298214892334189, + 1582556514881692819, + }, + } + z.Mul(x, &b) + return z +} + +// MulByNonResidue3Power3 set z=x*(1,1)^(3*(p^3-1)/6) and return z +func (z *E2) MulByNonResidue3Power3(x *E2) *E2 { + // (2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530,2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530) + b := E2{ + A0: fp.Element{ + 4480897313486445265, + 4797496051193971075, + 4046559893315008306, + 10569151167044009496, + 2123814803385151673, + 852749317591686856, + }, + A1: fp.Element{ + 4480897313486445265, + 4797496051193971075, + 4046559893315008306, + 10569151167044009496, + 2123814803385151673, + 852749317591686856, + }, + } + z.Mul(x, &b) + return z +} + +// MulByNonResidue3Power4 set z=x*(1,1)^(4*(p^3-1)/6) and return z +func (z *E2) MulByNonResidue3Power4(x *E2) *E2 { + // 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559786 + b := fp.Element{ + 4897101644811774638, + 3654671041462534141, + 569769440802610537, + 17053147383018470266, + 17227549637287919721, + 291242102765847046, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} + +// MulByNonResidue3Power5 set z=x*(1,1)^(5*(p^3-1)/6) and return z +func (z *E2) MulByNonResidue3Power5(x *E2) *E2 { + // (1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257,2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530) + b := E2{ + A0: fp.Element{ + 8921533702591418330, + 15859389534032789116, + 3389114680249073393, + 15116930867080254631, + 3288288975085550621, + 1021049300055853010, + }, + A1: fp.Element{ + 4480897313486445265, + 4797496051193971075, + 4046559893315008306, + 10569151167044009496, + 2123814803385151673, + 852749317591686856, + }, + } + z.Mul(x, &b) + return z +} diff --git a/bls381/g1.go b/bls381/g1.go index b185e153e3..c8c345bf58 100644 --- a/bls381/g1.go +++ b/bls381/g1.go @@ -30,19 +30,21 @@ import ( "github.com/consensys/gurvy/utils/parallel" ) -// G1Jac is a point with fp.Element coordinates +type G1CoordType = fp.Element + +// G1Jac is a point with G1CoordType coordinates type G1Jac struct { - X, Y, Z fp.Element + X, Y, Z G1CoordType } // G1Affine point in affine coordinates type G1Affine struct { - X, Y fp.Element + X, Y G1CoordType } // g1JacExtended parameterized jacobian coordinates (x=X/ZZ, y=Y/ZZZ, ZZ**3=ZZZ**2) type g1JacExtended struct { - X, Y, ZZ, ZZZ fp.Element + X, Y, ZZ, ZZZ G1CoordType } // SetInfinity sets p to O @@ -86,7 +88,7 @@ func (p *g1JacExtended) mAdd(a *G1Affine) *g1JacExtended { return p } - var U2, S2, P, R, PP, PPP, Q, Q2, RR, X3, Y3 fp.Element + var U2, S2, P, R, PP, PPP, Q, Q2, RR, X3, Y3 G1CoordType // p2: a, p1: p U2.Mul(&a.X, &p.ZZ) @@ -116,7 +118,7 @@ func (p *g1JacExtended) mAdd(a *G1Affine) *g1JacExtended { // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1 func (p *g1JacExtended) double(q *G1Affine) *g1JacExtended { - var U, S, M, _M, Y3 fp.Element + var U, S, M, _M, Y3 G1CoordType U.Double(&q.Y) p.ZZ.Square(&U) @@ -195,7 +197,7 @@ func (p *G1Jac) Sub(curve *Curve, a G1Jac) *G1Jac { // WARNING super slow function (due to the division) func (p *G1Jac) ToAffineFromJac(res *G1Affine) *G1Affine { - var bufs [3]fp.Element + var bufs [3]G1CoordType if p.Z.IsZero() { res.X.SetZero() @@ -216,7 +218,7 @@ func (p *G1Jac) ToAffineFromJac(res *G1Affine) *G1Affine { // ToProjFromJac converts a point from Jacobian to projective coordinates func (p *G1Jac) ToProjFromJac() *G1Jac { // memalloc - var buf fp.Element + var buf G1CoordType buf.Square(&p.Z) p.X.Mul(&p.X, &p.Z) @@ -251,7 +253,7 @@ func (p *G1Affine) ToJacobian(Q *G1Jac) *G1Jac { } func (p *G1Affine) String(curve *Curve) string { - var x, y fp.Element + var x, y G1CoordType x.Set(&p.X) y.Set(&p.Y) return "E([" + x.String() + "," + y.String() + "])," @@ -279,7 +281,7 @@ func (p *G1Jac) Add(curve *Curve, a *G1Jac) *G1Jac { } // get some Element from our pool - var Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V fp.Element + var Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V G1CoordType // Z1Z1 = a.Z ^ 2 Z1Z1.Square(&a.Z) @@ -364,7 +366,7 @@ func (p *G1Jac) AddMixed(a *G1Affine) *G1Jac { } // get some Element from our pool - var Z1Z1, U2, S2, H, HH, I, J, r, V fp.Element + var Z1Z1, U2, S2, H, HH, I, J, r, V G1CoordType // Z1Z1 = p.Z ^ 2 Z1Z1.Square(&p.Z) @@ -422,7 +424,7 @@ func (p *G1Jac) AddMixed(a *G1Affine) *G1Jac { // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl func (p *G1Jac) Double() *G1Jac { // get some Element from our pool - var XX, YY, YYYY, ZZ, S, M, T fp.Element + var XX, YY, YYYY, ZZ, S, M, T G1CoordType // XX = a.X^2 XX.Square(&p.X) diff --git a/bls381/g2.go b/bls381/g2.go index 7883740b1c..22a65d7b5a 100644 --- a/bls381/g2.go +++ b/bls381/g2.go @@ -27,19 +27,21 @@ import ( "github.com/consensys/gurvy/utils/parallel" ) -// G2Jac is a point with E2 coordinates +type G2CoordType = E2 + +// G2Jac is a point with G2CoordType coordinates type G2Jac struct { - X, Y, Z E2 + X, Y, Z G2CoordType } // G2Affine point in affine coordinates type G2Affine struct { - X, Y E2 + X, Y G2CoordType } // g2JacExtended parameterized jacobian coordinates (x=X/ZZ, y=Y/ZZZ, ZZ**3=ZZZ**2) type g2JacExtended struct { - X, Y, ZZ, ZZZ E2 + X, Y, ZZ, ZZZ G2CoordType } // SetInfinity sets p to O @@ -83,7 +85,7 @@ func (p *g2JacExtended) mAdd(a *G2Affine) *g2JacExtended { return p } - var U2, S2, P, R, PP, PPP, Q, Q2, RR, X3, Y3 E2 + var U2, S2, P, R, PP, PPP, Q, Q2, RR, X3, Y3 G2CoordType // p2: a, p1: p U2.Mul(&a.X, &p.ZZ) @@ -113,7 +115,7 @@ func (p *g2JacExtended) mAdd(a *G2Affine) *g2JacExtended { // http://www.hyperelliptic.org/EFD/g2p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1 func (p *g2JacExtended) double(q *G2Affine) *g2JacExtended { - var U, S, M, _M, Y3 E2 + var U, S, M, _M, Y3 G2CoordType U.Double(&q.Y) p.ZZ.Square(&U) @@ -192,7 +194,7 @@ func (p *G2Jac) Sub(curve *Curve, a G2Jac) *G2Jac { // WARNING super slow function (due to the division) func (p *G2Jac) ToAffineFromJac(res *G2Affine) *G2Affine { - var bufs [3]E2 + var bufs [3]G2CoordType if p.Z.IsZero() { res.X.SetZero() @@ -213,7 +215,7 @@ func (p *G2Jac) ToAffineFromJac(res *G2Affine) *G2Affine { // ToProjFromJac converts a point from Jacobian to projective coordinates func (p *G2Jac) ToProjFromJac() *G2Jac { // memalloc - var buf E2 + var buf G2CoordType buf.Square(&p.Z) p.X.Mul(&p.X, &p.Z) @@ -248,7 +250,7 @@ func (p *G2Affine) ToJacobian(Q *G2Jac) *G2Jac { } func (p *G2Affine) String(curve *Curve) string { - var x, y E2 + var x, y G2CoordType x.Set(&p.X) y.Set(&p.Y) return "E([" + x.String() + "," + y.String() + "])," @@ -276,7 +278,7 @@ func (p *G2Jac) Add(curve *Curve, a *G2Jac) *G2Jac { } // get some Element from our pool - var Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V E2 + var Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V G2CoordType // Z1Z1 = a.Z ^ 2 Z1Z1.Square(&a.Z) @@ -361,7 +363,7 @@ func (p *G2Jac) AddMixed(a *G2Affine) *G2Jac { } // get some Element from our pool - var Z1Z1, U2, S2, H, HH, I, J, r, V E2 + var Z1Z1, U2, S2, H, HH, I, J, r, V G2CoordType // Z1Z1 = p.Z ^ 2 Z1Z1.Square(&p.Z) @@ -419,7 +421,7 @@ func (p *G2Jac) AddMixed(a *G2Affine) *G2Jac { // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl func (p *G2Jac) Double() *G2Jac { // get some Element from our pool - var XX, YY, YYYY, ZZ, S, M, T E2 + var XX, YY, YYYY, ZZ, S, M, T G2CoordType // XX = a.X^2 XX.Square(&p.X) diff --git a/bls381/pairing.go b/bls381/pairing.go index 6806182a96..dc419bd963 100644 --- a/bls381/pairing.go +++ b/bls381/pairing.go @@ -16,11 +16,7 @@ package bls381 -import ( - "math/bits" - - "github.com/consensys/gurvy/bls381/fp" -) +import "math/bits" // FinalExponentiation computes the final expo x**(p**6-1)(p**2+1)(p**4 - p**2 +1)/r func (curve *Curve) FinalExponentiation(z *PairingResult, _z ...*PairingResult) PairingResult { @@ -38,7 +34,6 @@ func (curve *Curve) FinalExponentiation(z *PairingResult, _z ...*PairingResult) } // FinalExponentiation sets z to the final expo x**((p**12 - 1)/r), returns z -// TODO customize this comment for the curve func (z *PairingResult) FinalExponentiation(x *PairingResult) *PairingResult { // For BLS curves use Section 3 of https://eprint.iacr.org/2016/130.pdf; "hard part" is Algorithm 1 of https://eprint.iacr.org/2016/130.pdf var result PairingResult @@ -212,9 +207,9 @@ func lineEvalAffine(Q G2Jac, R G2Affine, P *G1Affine, result *lineEvalRes) { } type lineEvalRes struct { - r0 E2 // c0.b1 - r1 E2 // c1.b1 - r2 E2 // c1.b2 + r0 G2CoordType // c0.b1 + r1 G2CoordType // c1.b1 + r2 G2CoordType // c1.b2 } func (l *lineEvalRes) mulAssign(z *PairingResult) *PairingResult { @@ -228,421 +223,15 @@ func (l *lineEvalRes) mulAssign(z *PairingResult) *PairingResult { return z } -// Frobenius set z to Frobenius(x) in E12 and return z -func (z *E12) Frobenius(x *E12) *E12 { - // Algorithm 28 from https://eprint.iacr.org/2010/354.pdf (beware typos!) - var t [6]E2 - - // Frobenius acts on fp2 by conjugation - t[0].Conjugate(&x.C0.B0) - t[1].Conjugate(&x.C0.B1) - t[2].Conjugate(&x.C0.B2) - t[3].Conjugate(&x.C1.B0) - t[4].Conjugate(&x.C1.B1) - t[5].Conjugate(&x.C1.B2) - - t[1].MulByNonResiduePower2(&t[1]) - t[2].MulByNonResiduePower4(&t[2]) - t[3].MulByNonResiduePower1(&t[3]) - t[4].MulByNonResiduePower3(&t[4]) - t[5].MulByNonResiduePower5(&t[5]) - - z.C0.B0 = t[0] - z.C0.B1 = t[1] - z.C0.B2 = t[2] - z.C1.B0 = t[3] - z.C1.B1 = t[4] - z.C1.B2 = t[5] - - return z -} - -// FrobeniusSquare set z to Frobenius^2(x) in E12 and return z -func (z *E12) FrobeniusSquare(x *E12) *E12 { - // Algorithm 29 from https://eprint.iacr.org/2010/354.pdf (beware typos!) - var t [6]E2 - - t[1].MulByNonResiduePowerSquare2(&x.C0.B1) - t[2].MulByNonResiduePowerSquare4(&x.C0.B2) - t[3].MulByNonResiduePowerSquare1(&x.C1.B0) - t[4].MulByNonResiduePowerSquare3(&x.C1.B1) - t[5].MulByNonResiduePowerSquare5(&x.C1.B2) - - z.C0.B0 = x.C0.B0 - z.C0.B1 = t[1] - z.C0.B2 = t[2] - z.C1.B0 = t[3] - z.C1.B1 = t[4] - z.C1.B2 = t[5] - - return z -} - -// FrobeniusCube set z to Frobenius^3(x) in E12 and return z -func (z *E12) FrobeniusCube(x *E12) *E12 { - // Algorithm 30 from https://eprint.iacr.org/2010/354.pdf (beware typos!) - var t [6]E2 - - // Frobenius^3 acts on fp2 by conjugation - t[0].Conjugate(&x.C0.B0) - t[1].Conjugate(&x.C0.B1) - t[2].Conjugate(&x.C0.B2) - t[3].Conjugate(&x.C1.B0) - t[4].Conjugate(&x.C1.B1) - t[5].Conjugate(&x.C1.B2) - - t[1].MulByNonResiduePowerCube2(&t[1]) - t[2].MulByNonResiduePowerCube4(&t[2]) - t[3].MulByNonResiduePowerCube1(&t[3]) - t[4].MulByNonResiduePowerCube3(&t[4]) - t[5].MulByNonResiduePowerCube5(&t[5]) - - z.C0.B0 = t[0] - z.C0.B1 = t[1] - z.C0.B2 = t[2] - z.C1.B0 = t[3] - z.C1.B1 = t[4] - z.C1.B2 = t[5] - - return z -} - -// MulByNonResiduePower1 set z=x*(1,1)^(1*(p-1)/6) and return z -func (z *E2) MulByNonResiduePower1(x *E2) *E2 { - // (1,1)^(1*(p-1)/6) - // 3850754370037169011952147076051364057158807420970682438676050522613628423219637725072182697113062777891589506424760 + u*151655185184498381465642749684540099398075398968325446656007613510403227271200139370504932015952886146304766135027 - b := E2{ - A0: fp.Element{ - 506819140503852133, - 14297063575771579155, - 10946065744702939791, - 11771194236670323182, - 2081670087578406477, - 644615147456521963, - }, - A1: fp.Element{ - 12895611875574011462, - 6359822009455181036, - 14936352902570693524, - 13914887797453940944, - 3330433690892295817, - 1229183470191017903, - }, - } - z.Mul(x, &b) - return z -} - -// MulByNonResiduePower2 set z=x*(1,1)^(2*(p-1)/6) and return z -func (z *E2) MulByNonResiduePower2(x *E2) *E2 { - // (1,1)^(2*(p-1)/6) - // 0 + u*4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436 - b := E2{ - A0: fp.Element{ - 0, - 0, - 0, - 0, - 0, - 0, - }, - A1: fp.Element{ - 14772873186050699377, - 6749526151121446354, - 6372666795664677781, - 10283423008382700446, - 286397964926079186, - 1796971870900422465, - }, - } - z.Mul(x, &b) - return z -} - -// MulByNonResiduePower3 set z=x*(1,1)^(3*(p-1)/6) and return z -func (z *E2) MulByNonResiduePower3(x *E2) *E2 { - // (1,1)^(3*(p-1)/6) - // 1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257 + u*1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257 - b := E2{ - A0: fp.Element{ - 8921533702591418330, - 15859389534032789116, - 3389114680249073393, - 15116930867080254631, - 3288288975085550621, - 1021049300055853010, - }, - A1: fp.Element{ - 8921533702591418330, - 15859389534032789116, - 3389114680249073393, - 15116930867080254631, - 3288288975085550621, - 1021049300055853010, - }, - } - z.Mul(x, &b) - return z -} - -// MulByNonResiduePower4 set z=x*(1,1)^(4*(p-1)/6) and return z -func (z *E2) MulByNonResiduePower4(x *E2) *E2 { - // (1,1)^(4*(p-1)/6) - // 4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939437 - b := fp.Element{ - 9875771541238924739, - 3094855109658912213, - 5802897354862067244, - 11677019699073781796, - 1505592401347711080, - 1505729768134575418, - } - z.A0.Mul(&x.A0, &b) - z.A1.Mul(&x.A1, &b) - return z -} - -// MulByNonResiduePower5 set z=x*(1,1)^(5*(p-1)/6) and return z -func (z *E2) MulByNonResiduePower5(x *E2) *E2 { - // (1,1)^(5*(p-1)/6) - // 877076961050607968509681729531255177986764537961432449499635504522207616027455086505066378536590128544573588734230 + u*3125332594171059424908108096204648978570118281977575435832422631601824034463382777937621250592425535493320683825557 - b := E2{ - A0: fp.Element{ - 9428352843095270463, - 11709709036094816655, - 14335180424952013185, - 8441381030041026197, - 5369959062663957099, - 1665664447512374973, - }, - A1: fp.Element{ - 3974078172982593132, - 8947176549131943536, - 11547238222321620130, - 17244701004083237929, - 42144715806745195, - 208134170135164893, - }, - } - z.Mul(x, &b) - return z -} - -// MulByNonResiduePowerSquare1 set z=x*(1,1)^(1*(p^2-1)/6) and return z -func (z *E2) MulByNonResiduePowerSquare1(x *E2) *E2 { - // (1,1)^(1*(p^2-1)/6) - // 793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620351 - b := fp.Element{ - 17076301903736715834, - 13907359434105313836, - 1063007777899403918, - 15402659025741563681, - 5125705813544623108, - 76826746747117401, - } - z.A0.Mul(&x.A0, &b) - z.A1.Mul(&x.A1, &b) - return z -} - -// MulByNonResiduePowerSquare2 set z=x*(1,1)^(2*(p^2-1)/6) and return z -func (z *E2) MulByNonResiduePowerSquare2(x *E2) *E2 { - // (1,1)^(2*(p^2-1)/6) - // 793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350 - b := fp.Element{ - 3526659474838938856, - 17562030475567847978, - 1632777218702014455, - 14009062335050482331, - 3906511377122991214, - 368068849512964448, - } - z.A0.Mul(&x.A0, &b) - z.A1.Mul(&x.A1, &b) - return z -} - -// MulByNonResiduePowerSquare3 set z=x*(1,1)^(3*(p^2-1)/6) and return z -func (z *E2) MulByNonResiduePowerSquare3(x *E2) *E2 { - // (1,1)^(3*(p^2-1)/6) - // 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559786 - b := fp.Element{ - 4897101644811774638, - 3654671041462534141, - 569769440802610537, - 17053147383018470266, - 17227549637287919721, - 291242102765847046, - } - z.A0.Mul(&x.A0, &b) - z.A1.Mul(&x.A1, &b) - return z -} - -// MulByNonResiduePowerSquare4 set z=x*(1,1)^(4*(p^2-1)/6) and return z -func (z *E2) MulByNonResiduePowerSquare4(x *E2) *E2 { - // (1,1)^(4*(p^2-1)/6) - // 4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436 - b := fp.Element{ - 14772873186050699377, - 6749526151121446354, - 6372666795664677781, - 10283423008382700446, - 286397964926079186, - 1796971870900422465, - } - z.A0.Mul(&x.A0, &b) - z.A1.Mul(&x.A1, &b) - return z -} - -// MulByNonResiduePowerSquare5 set z=x*(1,1)^(5*(p^2-1)/6) and return z -func (z *E2) MulByNonResiduePowerSquare5(x *E2) *E2 { - // (1,1)^(5*(p^2-1)/6) - // 4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939437 - b := fp.Element{ - 9875771541238924739, - 3094855109658912213, - 5802897354862067244, - 11677019699073781796, - 1505592401347711080, - 1505729768134575418, - } - z.A0.Mul(&x.A0, &b) - z.A1.Mul(&x.A1, &b) - return z -} - -// MulByNonResiduePowerCube1 set z=x*(1,1)^(1*(p^3-1)/6) and return z -func (z *E2) MulByNonResiduePowerCube1(x *E2) *E2 { - // (1,1)^(1*(p^3-1)/6) - // 2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530 + u*1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257 - b := E2{ - A0: fp.Element{ - 4480897313486445265, - 4797496051193971075, - 4046559893315008306, - 10569151167044009496, - 2123814803385151673, - 852749317591686856, - }, - A1: fp.Element{ - 8921533702591418330, - 15859389534032789116, - 3389114680249073393, - 15116930867080254631, - 3288288975085550621, - 1021049300055853010, - }, - } - z.Mul(x, &b) - return z -} - -// MulByNonResiduePowerCube2 set z=x*(1,1)^(2*(p^3-1)/6) and return z -func (z *E2) MulByNonResiduePowerCube2(x *E2) *E2 { - // (1,1)^(2*(p^3-1)/6) - // 0 + u*1 - b := E2{ - A0: fp.Element{ - 0, - 0, - 0, - 0, - 0, - 0, - }, - A1: fp.Element{ - 8505329371266088957, - 17002214543764226050, - 6865905132761471162, - 8632934651105793861, - 6631298214892334189, - 1582556514881692819, - }, - } - z.Mul(x, &b) - return z -} - -// MulByNonResiduePowerCube3 set z=x*(1,1)^(3*(p^3-1)/6) and return z -func (z *E2) MulByNonResiduePowerCube3(x *E2) *E2 { - // (1,1)^(3*(p^3-1)/6) - // 2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530 + u*2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530 - b := E2{ - A0: fp.Element{ - 4480897313486445265, - 4797496051193971075, - 4046559893315008306, - 10569151167044009496, - 2123814803385151673, - 852749317591686856, - }, - A1: fp.Element{ - 4480897313486445265, - 4797496051193971075, - 4046559893315008306, - 10569151167044009496, - 2123814803385151673, - 852749317591686856, - }, - } - z.Mul(x, &b) - return z -} - -// MulByNonResiduePowerCube4 set z=x*(1,1)^(4*(p^3-1)/6) and return z -func (z *E2) MulByNonResiduePowerCube4(x *E2) *E2 { - // (1,1)^(4*(p^3-1)/6) - // 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559786 - b := fp.Element{ - 4897101644811774638, - 3654671041462534141, - 569769440802610537, - 17053147383018470266, - 17227549637287919721, - 291242102765847046, - } - z.A0.Mul(&x.A0, &b) - z.A1.Mul(&x.A1, &b) - return z -} - -// MulByNonResiduePowerCube5 set z=x*(1,1)^(5*(p^3-1)/6) and return z -func (z *E2) MulByNonResiduePowerCube5(x *E2) *E2 { - // (1,1)^(5*(p^3-1)/6) - // 1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257 + u*2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530 - b := E2{ - A0: fp.Element{ - 8921533702591418330, - 15859389534032789116, - 3389114680249073393, - 15116930867080254631, - 3288288975085550621, - 1021049300055853010, - }, - A1: fp.Element{ - 4480897313486445265, - 4797496051193971075, - 4046559893315008306, - 10569151167044009496, - 2123814803385151673, - 852749317591686856, - }, - } - z.Mul(x, &b) - return z -} - const tAbsVal uint64 = 15132376222941642752 // negative -// Expt set z to x^t in E12 and return z +// Expt set z to x^t in PairingResult and return z // TODO make a ExptAssign method that assigns the result to self; then this method can assert fail if z != x // TODO Expt is the only method that depends on tAbsVal. The rest of the tower does not depend on this value. Logically, Expt should be separated from the rest of the tower. -func (z *E12) Expt(x *E12) *E12 { +func (z *PairingResult) Expt(x *PairingResult) *PairingResult { // TODO what if x==0? // TODO make this match Element.Exp: x is a non-pointer? - var result E12 + var result PairingResult result.Set(x) l := bits.Len64(tAbsVal) - 2 diff --git a/bn256/e6.go b/bn256/e6.go index 6295e9cb4f..b3d7a36d6a 100644 --- a/bn256/e6.go +++ b/bn256/e6.go @@ -144,13 +144,15 @@ func (z *E6) String() string { return (z.B0.String() + "+(" + z.B1.String() + ")*v+(" + z.B2.String() + ")*v**2") } -// Mul multiplies two numbers in E6 +// Mul sets z to the E6-product of x,y, returns z func (z *E6) Mul(x, y *E6) *E6 { + // Algorithm 13 from https://eprint.iacr.org/2010/354.pdf var rb0, b0, b1, b2, b3, b4 E2 b0.Mul(&x.B0, &y.B0) // step 1 b1.Mul(&x.B1, &y.B1) // step 2 b2.Mul(&x.B2, &y.B2) // step 3 + // step 4 b3.Add(&x.B1, &x.B2) b4.Add(&y.B1, &y.B2) @@ -171,6 +173,7 @@ func (z *E6) Mul(x, y *E6) *E6 { rb0.A0.AddAssign(&buf9.A0) } // end: inline rb0.MulByNonResidue(&rb0) rb0.AddAssign(&b0) + // step 5 b3.Add(&x.B0, &x.B1) b4.Add(&y.B0, &y.B1) @@ -191,6 +194,7 @@ func (z *E6) Mul(x, y *E6) *E6 { b3.A0.AddAssign(&buf9.A0) } // end: inline b3.MulByNonResidue(&b2) z.B1.AddAssign(&b3) + // step 6 b3.Add(&x.B0, &x.B2) b4.Add(&y.B0, &y.B2) @@ -202,6 +206,68 @@ func (z *E6) Mul(x, y *E6) *E6 { return z } +// MulAssign sets z to the E6-product of z,x returns z +func (z *E6) MulAssign(x *E6) *E6 { + + // Algorithm 13 from https://eprint.iacr.org/2010/354.pdf + var rb0, b0, b1, b2, b3, b4 E2 + b0.Mul(&z.B0, &x.B0) // step 1 + b1.Mul(&z.B1, &x.B1) // step 2 + b2.Mul(&z.B2, &x.B2) // step 3 + + // step 4 + b3.Add(&z.B1, &z.B2) + b4.Add(&x.B1, &x.B2) + rb0.Mul(&b3, &b4). + SubAssign(&b1). + SubAssign(&b2) + { // begin: inline rb0.MulByNonResidue(&rb0) + var buf, buf9 E2 + buf.Set(&rb0) + buf9.Double(&buf). + Double(&buf9). + Double(&buf9). + Add(&buf9, &buf) + rb0.A1.Add(&buf.A0, &buf9.A1) + { // begin: inline MulByNonResidue(&(rb0).A0, &buf.A1) + (&(rb0).A0).Neg(&buf.A1) + } // end: inline MulByNonResidue(&(rb0).A0, &buf.A1) + rb0.A0.AddAssign(&buf9.A0) + } // end: inline rb0.MulByNonResidue(&rb0) + rb0.AddAssign(&b0) + + // step 5 + b3.Add(&z.B0, &z.B1) + b4.Add(&x.B0, &x.B1) + z.B1.Mul(&b3, &b4). + SubAssign(&b0). + SubAssign(&b1) + { // begin: inline b3.MulByNonResidue(&b2) + var buf, buf9 E2 + buf.Set(&b2) + buf9.Double(&buf). + Double(&buf9). + Double(&buf9). + Add(&buf9, &buf) + b3.A1.Add(&buf.A0, &buf9.A1) + { // begin: inline MulByNonResidue(&(b3).A0, &buf.A1) + (&(b3).A0).Neg(&buf.A1) + } // end: inline MulByNonResidue(&(b3).A0, &buf.A1) + b3.A0.AddAssign(&buf9.A0) + } // end: inline b3.MulByNonResidue(&b2) + z.B1.AddAssign(&b3) + + // step 6 + b3.Add(&z.B0, &z.B2) + b4.Add(&x.B0, &x.B2) + z.B2.Mul(&b3, &b4). + SubAssign(&b0). + SubAssign(&b2). + AddAssign(&b1) + z.B0 = rb0 + return z +} + // MulByE2 multiplies x by an elements of E2 func (z *E6) MulByE2(x *E6, y *E2) *E6 { var yCopy E2 @@ -249,8 +315,9 @@ func (z *E6) MulByNotv2(x, y *E6) *E6 { return z } -// Square squares a E6 +// Square sets z to the E6-product of x,x, returns z func (z *E6) Square(x *E6) *E6 { + // Algorithm 16 from https://eprint.iacr.org/2010/354.pdf var b0, b1, b2, b3, b4 E2 b3.Mul(&x.B0, &x.B1).Double(&b3) // step 1 @@ -299,6 +366,57 @@ func (z *E6) Square(x *E6) *E6 { return z } +// SquareAssign sets z to the E6-product of z,z returns z +func (z *E6) SquareAssign() *E6 { + + // Algorithm 16 from https://eprint.iacr.org/2010/354.pdf + var b0, b1, b2, b3, b4 E2 + b3.Mul(&z.B0, &z.B1).Double(&b3) // step 1 + b4.Square(&z.B2) // step 2 + + // step 3 + { // begin: inline b0.MulByNonResidue(&b4) + var buf, buf9 E2 + buf.Set(&b4) + buf9.Double(&buf). + Double(&buf9). + Double(&buf9). + Add(&buf9, &buf) + b0.A1.Add(&buf.A0, &buf9.A1) + { // begin: inline MulByNonResidue(&(b0).A0, &buf.A1) + (&(b0).A0).Neg(&buf.A1) + } // end: inline MulByNonResidue(&(b0).A0, &buf.A1) + b0.A0.AddAssign(&buf9.A0) + } // end: inline b0.MulByNonResidue(&b4) + b0.AddAssign(&b3) + b1.Sub(&b3, &b4) // step 4 + b2.Square(&z.B0) // step 5 + b3.Sub(&z.B0, &z.B1).AddAssign(&z.B2).Square(&b3) // steps 6 and 8 + b4.Mul(&z.B1, &z.B2).Double(&b4) // step 7 + // step 9 + { // begin: inline z.B0.MulByNonResidue(&b4) + var buf, buf9 E2 + buf.Set(&b4) + buf9.Double(&buf). + Double(&buf9). + Double(&buf9). + Add(&buf9, &buf) + z.B0.A1.Add(&buf.A0, &buf9.A1) + { // begin: inline MulByNonResidue(&(z.B0).A0, &buf.A1) + (&(z.B0).A0).Neg(&buf.A1) + } // end: inline MulByNonResidue(&(z.B0).A0, &buf.A1) + z.B0.A0.AddAssign(&buf9.A0) + } // end: inline z.B0.MulByNonResidue(&b4) + z.B0.AddAssign(&b2) + + // step 10 + z.B2.Add(&b1, &b3). + AddAssign(&b4). + SubAssign(&b2) + z.B1 = b0 + return z +} + // SquarE2 squares a E6 func (z *E6) SquarE2(x *E6) *E6 { // Karatsuba from Section 4 of https://eprint.iacr.org/2006/471.pdf diff --git a/bn256/frobenius.go b/bn256/frobenius.go new file mode 100644 index 0000000000..5804d5d44a --- /dev/null +++ b/bn256/frobenius.go @@ -0,0 +1,378 @@ +// Copyright 2020 ConsenSys AG +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by gurvy/internal/generators DO NOT EDIT + +package bn256 + +import "github.com/consensys/gurvy/bn256/fp" + +// Frobenius set z to Frobenius(x), return z +func (z *PairingResult) Frobenius(x *PairingResult) *PairingResult { + // Algorithm 28 from https://eprint.iacr.org/2010/354.pdf (beware typos!) + var t [6]E2 + + // Frobenius acts on fp2 by conjugation + t[0].Conjugate(&x.C0.B0) + t[1].Conjugate(&x.C0.B1) + t[2].Conjugate(&x.C0.B2) + t[3].Conjugate(&x.C1.B0) + t[4].Conjugate(&x.C1.B1) + t[5].Conjugate(&x.C1.B2) + + t[1].MulByNonResidue1Power2(&t[1]) + t[2].MulByNonResidue1Power4(&t[2]) + t[3].MulByNonResidue1Power1(&t[3]) + t[4].MulByNonResidue1Power3(&t[4]) + t[5].MulByNonResidue1Power5(&t[5]) + + z.C0.B0 = t[0] + z.C0.B1 = t[1] + z.C0.B2 = t[2] + z.C1.B0 = t[3] + z.C1.B1 = t[4] + z.C1.B2 = t[5] + + return z +} + +// FrobeniusSquare set z to Frobenius^2(x), and return z +func (z *PairingResult) FrobeniusSquare(x *PairingResult) *PairingResult { + // Algorithm 29 from https://eprint.iacr.org/2010/354.pdf (beware typos!) + var t [6]E2 + + t[1].MulByNonResidue2Power2(&x.C0.B1) + t[2].MulByNonResidue2Power4(&x.C0.B2) + t[3].MulByNonResidue2Power1(&x.C1.B0) + t[4].MulByNonResidue2Power3(&x.C1.B1) + t[5].MulByNonResidue2Power5(&x.C1.B2) + + z.C0.B0 = x.C0.B0 + z.C0.B1 = t[1] + z.C0.B2 = t[2] + z.C1.B0 = t[3] + z.C1.B1 = t[4] + z.C1.B2 = t[5] + + return z +} + +// FrobeniusCube set z to Frobenius^3(x), return z +func (z *PairingResult) FrobeniusCube(x *PairingResult) *PairingResult { + // Algorithm 30 from https://eprint.iacr.org/2010/354.pdf (beware typos!) + var t [6]E2 + + // Frobenius^3 acts on fp2 by conjugation + t[0].Conjugate(&x.C0.B0) + t[1].Conjugate(&x.C0.B1) + t[2].Conjugate(&x.C0.B2) + t[3].Conjugate(&x.C1.B0) + t[4].Conjugate(&x.C1.B1) + t[5].Conjugate(&x.C1.B2) + + t[1].MulByNonResidue3Power2(&t[1]) + t[2].MulByNonResidue3Power4(&t[2]) + t[3].MulByNonResidue3Power1(&t[3]) + t[4].MulByNonResidue3Power3(&t[4]) + t[5].MulByNonResidue3Power5(&t[5]) + + z.C0.B0 = t[0] + z.C0.B1 = t[1] + z.C0.B2 = t[2] + z.C1.B0 = t[3] + z.C1.B1 = t[4] + z.C1.B2 = t[5] + + return z +} + +// MulByNonResidue1Power1 set z=x*(9,1)^(1*(p^1-1)/6) and return z +func (z *E2) MulByNonResidue1Power1(x *E2) *E2 { + // (8376118865763821496583973867626364092589906065868298776909617916018768340080,16469823323077808223889137241176536799009286646108169935659301613961712198316) + b := E2{ + A0: fp.Element{ + 12653890742059813127, + 14585784200204367754, + 1278438861261381767, + 212598772761311868, + }, + A1: fp.Element{ + 11683091849979440498, + 14992204589386555739, + 15866167890766973222, + 1200023580730561873, + }, + } + z.Mul(x, &b) + return z +} + +// MulByNonResidue1Power2 set z=x*(9,1)^(2*(p^1-1)/6) and return z +func (z *E2) MulByNonResidue1Power2(x *E2) *E2 { + // (21575463638280843010398324269430826099269044274347216827212613867836435027261,10307601595873709700152284273816112264069230130616436755625194854815875713954) + b := E2{ + A0: fp.Element{ + 13075984984163199792, + 3782902503040509012, + 8791150885551868305, + 1825854335138010348, + }, + A1: fp.Element{ + 7963664994991228759, + 12257807996192067905, + 13179524609921305146, + 2767831111890561987, + }, + } + z.Mul(x, &b) + return z +} + +// MulByNonResidue1Power3 set z=x*(9,1)^(3*(p^1-1)/6) and return z +func (z *E2) MulByNonResidue1Power3(x *E2) *E2 { + // (2821565182194536844548159561693502659359617185244120367078079554186484126554,3505843767911556378687030309984248845540243509899259641013678093033130930403) + b := E2{ + A0: fp.Element{ + 16482010305593259561, + 13488546290961988299, + 3578621962720924518, + 2681173117283399901, + }, + A1: fp.Element{ + 11661927080404088775, + 553939530661941723, + 7860678177968807019, + 3208568454732775116, + }, + } + z.Mul(x, &b) + return z +} + +// MulByNonResidue1Power4 set z=x*(9,1)^(4*(p^1-1)/6) and return z +func (z *E2) MulByNonResidue1Power4(x *E2) *E2 { + // (2581911344467009335267311115468803099551665605076196740867805258568234346338,19937756971775647987995932169929341994314640652964949448313374472400716661030) + b := E2{ + A0: fp.Element{ + 8314163329781907090, + 11942187022798819835, + 11282677263046157209, + 1576150870752482284, + }, + A1: fp.Element{ + 6763840483288992073, + 7118829427391486816, + 4016233444936635065, + 2630958277570195709, + }, + } + z.Mul(x, &b) + return z +} + +// MulByNonResidue1Power5 set z=x*(9,1)^(5*(p^1-1)/6) and return z +func (z *E2) MulByNonResidue1Power5(x *E2) *E2 { + // (685108087231508774477564247770172212460312782337200605669322048753928464687,8447204650696766136447902020341177575205426561248465145919723016860428151883) + b := E2{ + A0: fp.Element{ + 14515217250696892391, + 16303087968080972555, + 3656613296917993960, + 1345095164996126785, + }, + A1: fp.Element{ + 957117326806663081, + 367382125163301975, + 15253872307375509749, + 3396254757538665050, + }, + } + z.Mul(x, &b) + return z +} + +// MulByNonResidue2Power1 set z=x*(9,1)^(1*(p^2-1)/6) and return z +func (z *E2) MulByNonResidue2Power1(x *E2) *E2 { + // 21888242871839275220042445260109153167277707414472061641714758635765020556617 + b := fp.Element{ + 14595462726357228530, + 17349508522658994025, + 1017833795229664280, + 299787779797702374, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} + +// MulByNonResidue2Power2 set z=x*(9,1)^(2*(p^2-1)/6) and return z +func (z *E2) MulByNonResidue2Power2(x *E2) *E2 { + // 21888242871839275220042445260109153167277707414472061641714758635765020556616 + b := fp.Element{ + 3697675806616062876, + 9065277094688085689, + 6918009208039626314, + 2775033306905974752, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} + +// MulByNonResidue2Power3 set z=x*(9,1)^(3*(p^2-1)/6) and return z +func (z *E2) MulByNonResidue2Power3(x *E2) *E2 { + // 21888242871839275222246405745257275088696311157297823662689037894645226208582 + b := fp.Element{ + 7548957153968385962, + 10162512645738643279, + 5900175412809962033, + 2475245527108272378, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} + +// MulByNonResidue2Power4 set z=x*(9,1)^(4*(p^2-1)/6) and return z +func (z *E2) MulByNonResidue2Power4(x *E2) *E2 { + // 2203960485148121921418603742825762020974279258880205651966 + b := fp.Element{ + 8183898218631979349, + 12014359695528440611, + 12263358156045030468, + 3187210487005268291, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} + +// MulByNonResidue2Power5 set z=x*(9,1)^(5*(p^2-1)/6) and return z +func (z *E2) MulByNonResidue2Power5(x *E2) *E2 { + // 2203960485148121921418603742825762020974279258880205651967 + b := fp.Element{ + 634941064663593387, + 1851847049789797332, + 6363182743235068435, + 711964959896995913, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} + +// MulByNonResidue3Power1 set z=x*(9,1)^(1*(p^3-1)/6) and return z +func (z *E2) MulByNonResidue3Power1(x *E2) *E2 { + // (11697423496358154304825782922584725312912383441159505038794027105778954184319,303847389135065887422783454877609941456349188919719272345083954437860409601) + b := E2{ + A0: fp.Element{ + 3914496794763385213, + 790120733010914719, + 7322192392869644725, + 581366264293887267, + }, + A1: fp.Element{ + 12817045492518885689, + 4440270538777280383, + 11178533038884588256, + 2767537931541304486, + }, + } + z.Mul(x, &b) + return z +} + +// MulByNonResidue3Power2 set z=x*(9,1)^(2*(p^3-1)/6) and return z +func (z *E2) MulByNonResidue3Power2(x *E2) *E2 { + // (3772000881919853776433695186713858239009073593817195771773381919316419345261,2236595495967245188281701248203181795121068902605861227855261137820944008926) + b := E2{ + A0: fp.Element{ + 14532872967180610477, + 12903226530429559474, + 1868623743233345524, + 2316889217940299650, + }, + A1: fp.Element{ + 12447993766991532972, + 4121872836076202828, + 7630813605053367399, + 740282956577754197, + }, + } + z.Mul(x, &b) + return z +} + +// MulByNonResidue3Power3 set z=x*(9,1)^(3*(p^3-1)/6) and return z +func (z *E2) MulByNonResidue3Power3(x *E2) *E2 { + // (19066677689644738377698246183563772429336693972053703295610958340458742082029,18382399103927718843559375435273026243156067647398564021675359801612095278180) + b := E2{ + A0: fp.Element{ + 6297350639395948318, + 15875321927225446337, + 9702569988553770230, + 805825149519570764, + }, + A1: fp.Element{ + 11117433864585119104, + 10363184613815941297, + 5420513773305887730, + 278429812070195549, + }, + } + z.Mul(x, &b) + return z +} + +// MulByNonResidue3Power4 set z=x*(9,1)^(4*(p^3-1)/6) and return z +func (z *E2) MulByNonResidue3Power4(x *E2) *E2 { + // (5324479202449903542726783395506214481928257762400643279780343368557297135718,16208900380737693084919495127334387981393726419856888799917914180988844123039) + b := E2{ + A0: fp.Element{ + 4938922280314430175, + 13823286637238282975, + 15589480384090068090, + 481952561930628184, + }, + A1: fp.Element{ + 3105754162722846417, + 11647802298615474591, + 13057042392041828081, + 1660844386505564338, + }, + } + z.Mul(x, &b) + return z +} + +// MulByNonResidue3Power5 set z=x*(9,1)^(5*(p^3-1)/6) and return z +func (z *E2) MulByNonResidue3Power5(x *E2) *E2 { + // (8941241848238582420466759817324047081148088512956452953208002715982955420483,10338197737521362862238855242243140895517409139741313354160881284257516364953) + b := E2{ + A0: fp.Element{ + 16193900971494954399, + 13995139551301264911, + 9239559758168096094, + 1571199014989505406, + }, + A1: fp.Element{ + 3254114329011132839, + 11171599147282597747, + 10965492220518093659, + 2657556514797346915, + }, + } + z.Mul(x, &b) + return z +} diff --git a/bn256/g1.go b/bn256/g1.go index 82715c036b..49943101f3 100644 --- a/bn256/g1.go +++ b/bn256/g1.go @@ -30,19 +30,21 @@ import ( "github.com/consensys/gurvy/utils/parallel" ) -// G1Jac is a point with fp.Element coordinates +type G1CoordType = fp.Element + +// G1Jac is a point with G1CoordType coordinates type G1Jac struct { - X, Y, Z fp.Element + X, Y, Z G1CoordType } // G1Affine point in affine coordinates type G1Affine struct { - X, Y fp.Element + X, Y G1CoordType } // g1JacExtended parameterized jacobian coordinates (x=X/ZZ, y=Y/ZZZ, ZZ**3=ZZZ**2) type g1JacExtended struct { - X, Y, ZZ, ZZZ fp.Element + X, Y, ZZ, ZZZ G1CoordType } // SetInfinity sets p to O @@ -86,7 +88,7 @@ func (p *g1JacExtended) mAdd(a *G1Affine) *g1JacExtended { return p } - var U2, S2, P, R, PP, PPP, Q, Q2, RR, X3, Y3 fp.Element + var U2, S2, P, R, PP, PPP, Q, Q2, RR, X3, Y3 G1CoordType // p2: a, p1: p U2.Mul(&a.X, &p.ZZ) @@ -116,7 +118,7 @@ func (p *g1JacExtended) mAdd(a *G1Affine) *g1JacExtended { // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1 func (p *g1JacExtended) double(q *G1Affine) *g1JacExtended { - var U, S, M, _M, Y3 fp.Element + var U, S, M, _M, Y3 G1CoordType U.Double(&q.Y) p.ZZ.Square(&U) @@ -195,7 +197,7 @@ func (p *G1Jac) Sub(curve *Curve, a G1Jac) *G1Jac { // WARNING super slow function (due to the division) func (p *G1Jac) ToAffineFromJac(res *G1Affine) *G1Affine { - var bufs [3]fp.Element + var bufs [3]G1CoordType if p.Z.IsZero() { res.X.SetZero() @@ -216,7 +218,7 @@ func (p *G1Jac) ToAffineFromJac(res *G1Affine) *G1Affine { // ToProjFromJac converts a point from Jacobian to projective coordinates func (p *G1Jac) ToProjFromJac() *G1Jac { // memalloc - var buf fp.Element + var buf G1CoordType buf.Square(&p.Z) p.X.Mul(&p.X, &p.Z) @@ -251,7 +253,7 @@ func (p *G1Affine) ToJacobian(Q *G1Jac) *G1Jac { } func (p *G1Affine) String(curve *Curve) string { - var x, y fp.Element + var x, y G1CoordType x.Set(&p.X) y.Set(&p.Y) return "E([" + x.String() + "," + y.String() + "])," @@ -279,7 +281,7 @@ func (p *G1Jac) Add(curve *Curve, a *G1Jac) *G1Jac { } // get some Element from our pool - var Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V fp.Element + var Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V G1CoordType // Z1Z1 = a.Z ^ 2 Z1Z1.Square(&a.Z) @@ -364,7 +366,7 @@ func (p *G1Jac) AddMixed(a *G1Affine) *G1Jac { } // get some Element from our pool - var Z1Z1, U2, S2, H, HH, I, J, r, V fp.Element + var Z1Z1, U2, S2, H, HH, I, J, r, V G1CoordType // Z1Z1 = p.Z ^ 2 Z1Z1.Square(&p.Z) @@ -422,7 +424,7 @@ func (p *G1Jac) AddMixed(a *G1Affine) *G1Jac { // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl func (p *G1Jac) Double() *G1Jac { // get some Element from our pool - var XX, YY, YYYY, ZZ, S, M, T fp.Element + var XX, YY, YYYY, ZZ, S, M, T G1CoordType // XX = a.X^2 XX.Square(&p.X) diff --git a/bn256/g2.go b/bn256/g2.go index 7dc769b54a..bf63a595b5 100644 --- a/bn256/g2.go +++ b/bn256/g2.go @@ -27,19 +27,21 @@ import ( "github.com/consensys/gurvy/utils/parallel" ) -// G2Jac is a point with E2 coordinates +type G2CoordType = E2 + +// G2Jac is a point with G2CoordType coordinates type G2Jac struct { - X, Y, Z E2 + X, Y, Z G2CoordType } // G2Affine point in affine coordinates type G2Affine struct { - X, Y E2 + X, Y G2CoordType } // g2JacExtended parameterized jacobian coordinates (x=X/ZZ, y=Y/ZZZ, ZZ**3=ZZZ**2) type g2JacExtended struct { - X, Y, ZZ, ZZZ E2 + X, Y, ZZ, ZZZ G2CoordType } // SetInfinity sets p to O @@ -83,7 +85,7 @@ func (p *g2JacExtended) mAdd(a *G2Affine) *g2JacExtended { return p } - var U2, S2, P, R, PP, PPP, Q, Q2, RR, X3, Y3 E2 + var U2, S2, P, R, PP, PPP, Q, Q2, RR, X3, Y3 G2CoordType // p2: a, p1: p U2.Mul(&a.X, &p.ZZ) @@ -113,7 +115,7 @@ func (p *g2JacExtended) mAdd(a *G2Affine) *g2JacExtended { // http://www.hyperelliptic.org/EFD/g2p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1 func (p *g2JacExtended) double(q *G2Affine) *g2JacExtended { - var U, S, M, _M, Y3 E2 + var U, S, M, _M, Y3 G2CoordType U.Double(&q.Y) p.ZZ.Square(&U) @@ -192,7 +194,7 @@ func (p *G2Jac) Sub(curve *Curve, a G2Jac) *G2Jac { // WARNING super slow function (due to the division) func (p *G2Jac) ToAffineFromJac(res *G2Affine) *G2Affine { - var bufs [3]E2 + var bufs [3]G2CoordType if p.Z.IsZero() { res.X.SetZero() @@ -213,7 +215,7 @@ func (p *G2Jac) ToAffineFromJac(res *G2Affine) *G2Affine { // ToProjFromJac converts a point from Jacobian to projective coordinates func (p *G2Jac) ToProjFromJac() *G2Jac { // memalloc - var buf E2 + var buf G2CoordType buf.Square(&p.Z) p.X.Mul(&p.X, &p.Z) @@ -248,7 +250,7 @@ func (p *G2Affine) ToJacobian(Q *G2Jac) *G2Jac { } func (p *G2Affine) String(curve *Curve) string { - var x, y E2 + var x, y G2CoordType x.Set(&p.X) y.Set(&p.Y) return "E([" + x.String() + "," + y.String() + "])," @@ -276,7 +278,7 @@ func (p *G2Jac) Add(curve *Curve, a *G2Jac) *G2Jac { } // get some Element from our pool - var Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V E2 + var Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V G2CoordType // Z1Z1 = a.Z ^ 2 Z1Z1.Square(&a.Z) @@ -361,7 +363,7 @@ func (p *G2Jac) AddMixed(a *G2Affine) *G2Jac { } // get some Element from our pool - var Z1Z1, U2, S2, H, HH, I, J, r, V E2 + var Z1Z1, U2, S2, H, HH, I, J, r, V G2CoordType // Z1Z1 = p.Z ^ 2 Z1Z1.Square(&p.Z) @@ -419,7 +421,7 @@ func (p *G2Jac) AddMixed(a *G2Affine) *G2Jac { // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl func (p *G2Jac) Double() *G2Jac { // get some Element from our pool - var XX, YY, YYYY, ZZ, S, M, T E2 + var XX, YY, YYYY, ZZ, S, M, T G2CoordType // XX = a.X^2 XX.Square(&p.X) diff --git a/bn256/pairing.go b/bn256/pairing.go index b6c28b4583..97b1763e7a 100644 --- a/bn256/pairing.go +++ b/bn256/pairing.go @@ -16,11 +16,7 @@ package bn256 -import ( - "math/bits" - - "github.com/consensys/gurvy/bn256/fp" -) +import "math/bits" // FinalExponentiation computes the final expo x**(p**6-1)(p**2+1)(p**4 - p**2 +1)/r func (curve *Curve) FinalExponentiation(z *PairingResult, _z ...*PairingResult) PairingResult { @@ -38,7 +34,6 @@ func (curve *Curve) FinalExponentiation(z *PairingResult, _z ...*PairingResult) } // FinalExponentiation sets z to the final expo x**((p**12 - 1)/r), returns z -// TODO customize this comment for the curve func (z *PairingResult) FinalExponentiation(x *PairingResult) *PairingResult { // For BN curves use Section 5 of https://eprint.iacr.org/2008/490.pdf; their x is our t @@ -167,12 +162,12 @@ func (curve *Curve) MillerLoop(P G1Affine, Q G2Affine, result *PairingResult) *P var Q1, Q2 G2Affine //Q1 = Frob(Q) - Q1.X.Conjugate(&Q.X).MulByNonResiduePower2(&Q1.X) - Q1.Y.Conjugate(&Q.Y).MulByNonResiduePower3(&Q1.Y) + Q1.X.Conjugate(&Q.X).MulByNonResidue1Power2(&Q1.X) + Q1.Y.Conjugate(&Q.Y).MulByNonResidue1Power3(&Q1.Y) // Q2 = -Frob2(Q) - Q2.X.MulByNonResiduePowerSquare2(&Q.X) - Q2.Y.MulByNonResiduePowerSquare3(&Q.Y).Neg(&Q2.Y) + Q2.X.MulByNonResidue2Power2(&Q.X) + Q2.Y.MulByNonResidue2Power3(&Q.Y).Neg(&Q2.Y) lineEvalAffine(QCur, Q1, &P, &lEval) lEval.mulAssign(result) @@ -245,9 +240,9 @@ func lineEvalAffine(Q G2Jac, R G2Affine, P *G1Affine, result *lineEvalRes) { } type lineEvalRes struct { - r0 E2 // c0.b1 - r1 E2 // c1.b1 - r2 E2 // c1.b2 + r0 G2CoordType // c0.b1 + r1 G2CoordType // c1.b1 + r2 G2CoordType // c1.b2 } func (l *lineEvalRes) mulAssign(z *PairingResult) *PairingResult { @@ -261,389 +256,15 @@ func (l *lineEvalRes) mulAssign(z *PairingResult) *PairingResult { return z } -// Frobenius set z to Frobenius(x) in E12 and return z -func (z *E12) Frobenius(x *E12) *E12 { - // Algorithm 28 from https://eprint.iacr.org/2010/354.pdf (beware typos!) - var t [6]E2 - - // Frobenius acts on fp2 by conjugation - t[0].Conjugate(&x.C0.B0) - t[1].Conjugate(&x.C0.B1) - t[2].Conjugate(&x.C0.B2) - t[3].Conjugate(&x.C1.B0) - t[4].Conjugate(&x.C1.B1) - t[5].Conjugate(&x.C1.B2) - - t[1].MulByNonResiduePower2(&t[1]) - t[2].MulByNonResiduePower4(&t[2]) - t[3].MulByNonResiduePower1(&t[3]) - t[4].MulByNonResiduePower3(&t[4]) - t[5].MulByNonResiduePower5(&t[5]) - - z.C0.B0 = t[0] - z.C0.B1 = t[1] - z.C0.B2 = t[2] - z.C1.B0 = t[3] - z.C1.B1 = t[4] - z.C1.B2 = t[5] - - return z -} - -// FrobeniusSquare set z to Frobenius^2(x) in E12 and return z -func (z *E12) FrobeniusSquare(x *E12) *E12 { - // Algorithm 29 from https://eprint.iacr.org/2010/354.pdf (beware typos!) - var t [6]E2 - - t[1].MulByNonResiduePowerSquare2(&x.C0.B1) - t[2].MulByNonResiduePowerSquare4(&x.C0.B2) - t[3].MulByNonResiduePowerSquare1(&x.C1.B0) - t[4].MulByNonResiduePowerSquare3(&x.C1.B1) - t[5].MulByNonResiduePowerSquare5(&x.C1.B2) - - z.C0.B0 = x.C0.B0 - z.C0.B1 = t[1] - z.C0.B2 = t[2] - z.C1.B0 = t[3] - z.C1.B1 = t[4] - z.C1.B2 = t[5] - - return z -} - -// FrobeniusCube set z to Frobenius^3(x) in E12 and return z -func (z *E12) FrobeniusCube(x *E12) *E12 { - // Algorithm 30 from https://eprint.iacr.org/2010/354.pdf (beware typos!) - var t [6]E2 - - // Frobenius^3 acts on fp2 by conjugation - t[0].Conjugate(&x.C0.B0) - t[1].Conjugate(&x.C0.B1) - t[2].Conjugate(&x.C0.B2) - t[3].Conjugate(&x.C1.B0) - t[4].Conjugate(&x.C1.B1) - t[5].Conjugate(&x.C1.B2) - - t[1].MulByNonResiduePowerCube2(&t[1]) - t[2].MulByNonResiduePowerCube4(&t[2]) - t[3].MulByNonResiduePowerCube1(&t[3]) - t[4].MulByNonResiduePowerCube3(&t[4]) - t[5].MulByNonResiduePowerCube5(&t[5]) - - z.C0.B0 = t[0] - z.C0.B1 = t[1] - z.C0.B2 = t[2] - z.C1.B0 = t[3] - z.C1.B1 = t[4] - z.C1.B2 = t[5] - - return z -} - -// MulByNonResiduePower1 set z=x*(9,1)^(1*(p-1)/6) and return z -func (z *E2) MulByNonResiduePower1(x *E2) *E2 { - // (9,1)^(1*(p-1)/6) - // 3850754370037169011952147076051364057158807420970682438676050522613628423219637725072182697113062777891589506424760 + u*151655185184498381465642749684540099398075398968325446656007613510403227271200139370504932015952886146304766135027 - b := E2{ - A0: fp.Element{ - 12653890742059813127, - 14585784200204367754, - 1278438861261381767, - 212598772761311868, - }, - A1: fp.Element{ - 11683091849979440498, - 14992204589386555739, - 15866167890766973222, - 1200023580730561873, - }, - } - z.Mul(x, &b) - return z -} - -// MulByNonResiduePower2 set z=x*(9,1)^(2*(p-1)/6) and return z -func (z *E2) MulByNonResiduePower2(x *E2) *E2 { - // (9,1)^(2*(p-1)/6) - // 0 + u*4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436 - b := E2{ - A0: fp.Element{ - 13075984984163199792, - 3782902503040509012, - 8791150885551868305, - 1825854335138010348, - }, - A1: fp.Element{ - 7963664994991228759, - 12257807996192067905, - 13179524609921305146, - 2767831111890561987, - }, - } - z.Mul(x, &b) - return z -} - -// MulByNonResiduePower3 set z=x*(9,1)^(3*(p-1)/6) and return z -func (z *E2) MulByNonResiduePower3(x *E2) *E2 { - // (9,1)^(3*(p-1)/6) - // 1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257 + u*1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257 - b := E2{ - A0: fp.Element{ - 16482010305593259561, - 13488546290961988299, - 3578621962720924518, - 2681173117283399901, - }, - A1: fp.Element{ - 11661927080404088775, - 553939530661941723, - 7860678177968807019, - 3208568454732775116, - }, - } - z.Mul(x, &b) - return z -} - -// MulByNonResiduePower4 set z=x*(9,1)^(4*(p-1)/6) and return z -func (z *E2) MulByNonResiduePower4(x *E2) *E2 { - // (9,1)^(4*(p-1)/6) - // 4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939437 - b := E2{ - A0: fp.Element{ - 8314163329781907090, - 11942187022798819835, - 11282677263046157209, - 1576150870752482284, - }, - A1: fp.Element{ - 6763840483288992073, - 7118829427391486816, - 4016233444936635065, - 2630958277570195709, - }, - } - z.Mul(x, &b) - return z -} - -// MulByNonResiduePower5 set z=x*(9,1)^(5*(p-1)/6) and return z -func (z *E2) MulByNonResiduePower5(x *E2) *E2 { - // (9,1)^(5*(p-1)/6) - // 877076961050607968509681729531255177986764537961432449499635504522207616027455086505066378536590128544573588734230 + u*3125332594171059424908108096204648978570118281977575435832422631601824034463382777937621250592425535493320683825557 - b := E2{ - A0: fp.Element{ - 14515217250696892391, - 16303087968080972555, - 3656613296917993960, - 1345095164996126785, - }, - A1: fp.Element{ - 957117326806663081, - 367382125163301975, - 15253872307375509749, - 3396254757538665050, - }, - } - z.Mul(x, &b) - return z -} - -// MulByNonResiduePowerSquare1 set z=x*(9,1)^(1*(p^2-1)/6) and return z -func (z *E2) MulByNonResiduePowerSquare1(x *E2) *E2 { - // (9,1)^(1*(p^2-1)/6) - // 793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620351 - b := fp.Element{ - 14595462726357228530, - 17349508522658994025, - 1017833795229664280, - 299787779797702374, - } - z.A0.Mul(&x.A0, &b) - z.A1.Mul(&x.A1, &b) - return z -} - -// MulByNonResiduePowerSquare2 set z=x*(9,1)^(2*(p^2-1)/6) and return z -func (z *E2) MulByNonResiduePowerSquare2(x *E2) *E2 { - // (9,1)^(2*(p^2-1)/6) - // 793479390729215512621379701633421447060886740281060493010456487427281649075476305620758731620350 - b := fp.Element{ - 3697675806616062876, - 9065277094688085689, - 6918009208039626314, - 2775033306905974752, - } - z.A0.Mul(&x.A0, &b) - z.A1.Mul(&x.A1, &b) - return z -} - -// MulByNonResiduePowerSquare3 set z=x*(9,1)^(3*(p^2-1)/6) and return z -func (z *E2) MulByNonResiduePowerSquare3(x *E2) *E2 { - // (9,1)^(3*(p^2-1)/6) - // 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559786 - b := fp.Element{ - 7548957153968385962, - 10162512645738643279, - 5900175412809962033, - 2475245527108272378, - } - z.A0.Mul(&x.A0, &b) - z.A1.Mul(&x.A1, &b) - return z -} - -// MulByNonResiduePowerSquare4 set z=x*(9,1)^(4*(p^2-1)/6) and return z -func (z *E2) MulByNonResiduePowerSquare4(x *E2) *E2 { - // (9,1)^(4*(p^2-1)/6) - // 4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436 - b := fp.Element{ - 8183898218631979349, - 12014359695528440611, - 12263358156045030468, - 3187210487005268291, - } - z.A0.Mul(&x.A0, &b) - z.A1.Mul(&x.A1, &b) - return z -} - -// MulByNonResiduePowerSquare5 set z=x*(9,1)^(5*(p^2-1)/6) and return z -func (z *E2) MulByNonResiduePowerSquare5(x *E2) *E2 { - // (9,1)^(5*(p^2-1)/6) - // 4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939437 - b := fp.Element{ - 634941064663593387, - 1851847049789797332, - 6363182743235068435, - 711964959896995913, - } - z.A0.Mul(&x.A0, &b) - z.A1.Mul(&x.A1, &b) - return z -} - -// MulByNonResiduePowerCube1 set z=x*(9,1)^(1*(p^3-1)/6) and return z -func (z *E2) MulByNonResiduePowerCube1(x *E2) *E2 { - // (9,1)^(1*(p^3-1)/6) - // 2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530 + u*1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257 - b := E2{ - A0: fp.Element{ - 3914496794763385213, - 790120733010914719, - 7322192392869644725, - 581366264293887267, - }, - A1: fp.Element{ - 12817045492518885689, - 4440270538777280383, - 11178533038884588256, - 2767537931541304486, - }, - } - z.Mul(x, &b) - return z -} - -// MulByNonResiduePowerCube2 set z=x*(9,1)^(2*(p^3-1)/6) and return z -func (z *E2) MulByNonResiduePowerCube2(x *E2) *E2 { - // (9,1)^(2*(p^3-1)/6) - // 0 + u*1 - b := E2{ - A0: fp.Element{ - 14532872967180610477, - 12903226530429559474, - 1868623743233345524, - 2316889217940299650, - }, - A1: fp.Element{ - 12447993766991532972, - 4121872836076202828, - 7630813605053367399, - 740282956577754197, - }, - } - z.Mul(x, &b) - return z -} - -// MulByNonResiduePowerCube3 set z=x*(9,1)^(3*(p^3-1)/6) and return z -func (z *E2) MulByNonResiduePowerCube3(x *E2) *E2 { - // (9,1)^(3*(p^3-1)/6) - // 2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530 + u*2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530 - b := E2{ - A0: fp.Element{ - 6297350639395948318, - 15875321927225446337, - 9702569988553770230, - 805825149519570764, - }, - A1: fp.Element{ - 11117433864585119104, - 10363184613815941297, - 5420513773305887730, - 278429812070195549, - }, - } - z.Mul(x, &b) - return z -} - -// MulByNonResiduePowerCube4 set z=x*(9,1)^(4*(p^3-1)/6) and return z -func (z *E2) MulByNonResiduePowerCube4(x *E2) *E2 { - // (9,1)^(4*(p^3-1)/6) - // 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559786 - b := E2{ - A0: fp.Element{ - 4938922280314430175, - 13823286637238282975, - 15589480384090068090, - 481952561930628184, - }, - A1: fp.Element{ - 3105754162722846417, - 11647802298615474591, - 13057042392041828081, - 1660844386505564338, - }, - } - z.Mul(x, &b) - return z -} - -// MulByNonResiduePowerCube5 set z=x*(9,1)^(5*(p^3-1)/6) and return z -func (z *E2) MulByNonResiduePowerCube5(x *E2) *E2 { - // (9,1)^(5*(p^3-1)/6) - // 1028732146235106349975324479215795277384839936929757896155643118032610843298655225875571310552543014690878354869257 + u*2973677408986561043442465346520108879172042883009249989176415018091420807192182638567116318576472649347015917690530 - b := E2{ - A0: fp.Element{ - 16193900971494954399, - 13995139551301264911, - 9239559758168096094, - 1571199014989505406, - }, - A1: fp.Element{ - 3254114329011132839, - 11171599147282597747, - 10965492220518093659, - 2657556514797346915, - }, - } - z.Mul(x, &b) - return z -} - const tAbsVal uint64 = 4965661367192848881 -// Expt set z to x^t in E12 and return z +// Expt set z to x^t in PairingResult and return z // TODO make a ExptAssign method that assigns the result to self; then this method can assert fail if z != x // TODO Expt is the only method that depends on tAbsVal. The rest of the tower does not depend on this value. Logically, Expt should be separated from the rest of the tower. -func (z *E12) Expt(x *E12) *E12 { +func (z *PairingResult) Expt(x *PairingResult) *PairingResult { // TODO what if x==0? // TODO make this match Element.Exp: x is a non-pointer? - var result E12 + var result PairingResult result.Set(x) l := bits.Len64(tAbsVal) - 2 diff --git a/bw6_761/bw6_761.go b/bw6_761/bw6_761.go index f74646b89b..eb7ce58790 100644 --- a/bw6_761/bw6_761.go +++ b/bw6_761/bw6_761.go @@ -21,7 +21,7 @@ const ID = gurvy.BW6_761 const sGen = 4 const bGen = sGen -type PairingResult = e6 +type PairingResult = E6 // BW6_761 returns BW6_761 curve func BW6_761() *Curve { @@ -39,8 +39,10 @@ type Curve struct { g1Infinity G1Jac // infinity (in Jacobian coords) g2Infinity G2Jac - // TODO store this number as a MAX_SIZE constant, or with build tags - loopCounter [64]int8 // NAF decomposition of t-1, t is the trace of the Frobenius restricted on the r torsion group + // Miller loop counters in NAF form + // TODO For the love of god, please clean this up + loopCounter1 [64]int8 + loopCounter2 [190]int8 // precomputed values for ScalarMulByGen tGenG1 [((1 << bGen) - 1)]G1Jac @@ -53,21 +55,27 @@ func initBW6_761() { bw6_761.B.SetUint64(4) // Setting G1Jac - bw6_761.g1Gen.X.SetString("68333130937826953018162399284085925021577172705782285525244777453303237942212457240213897533859360921141590695983") - bw6_761.g1Gen.Y.SetString("243386584320553125968203959498080829207604143167922579970841210259134422887279629198736754149500839244552761526603") + bw6_761.g1Gen.X.SetString("5492337019202608651620810666633622531924946248948182754748114963334556774714407693672822645637243083342924475378144397780999025266189779523629084326871556483802038026432771927197170911996417793635501066231650458516636932478125208") + bw6_761.g1Gen.Y.SetString("4874298780810344118673004453041997030286302865034758641338313952140849332867290574388366379298818956144982860224857872858166812124104845663394852158352478303048122861831479086904887356602146134586313962565783961814162269209043907") bw6_761.g1Gen.Z.SetString("1") // Setting G2Jac - bw6_761.g2Gen.X.SetString("129200027147742761118726589615458929865665635908074731940673005072449785691019374448547048953080140429883331266310", - "218164455698855406745723400799886985937129266327098023241324696183914328661520330195732120783615155502387891913936") - bw6_761.g2Gen.Y.SetString("178797786102020318006939402153521323286173305074858025240458924050651930669327663166574060567346617543016897467207", - "246194676937700783734853490842104812127151341609821057456393698060154678349106147660301543343243364716364400889778") - bw6_761.g2Gen.Z.SetString("1", - "0") - - // Setting the loop counter for Miller loop in NAF form - T, _ := new(big.Int).SetString("9586122913090633729", 10) - utils.NafDecomposition(T, bw6_761.loopCounter[:]) + bw6_761.g2Gen.X.SetString("5779457169892140542970811884673908634889239063901429247094594197042136765689827803062459420720318762253427359282239252479201196985966853806926626938528693270647807548111019296972244105103687281416386903420911111573334083829048020") + bw6_761.g2Gen.Y.SetString("2945005085389580383802706904000483833228424888054664780252599806365093320701303614818391222418768857269542753796449953578553937529004880983494788715529986360817835802796138196037201453469654110552028363169895102423753717534586247") + bw6_761.g2Gen.Z.SetString("1") + + // Setting the loop counters for Miller loop in NAF form + // https://eprint.iacr.org/2020/351.pdf (Algorithm 5) + // T, _ := new(big.Int).SetString("9586122913090633729", 10) + // utils.NafDecomposition(T, bw6_761.loopCounter1[:]) + // T2, _ := new(big.Int).SetString("91893752504881257691937156713741811711", 10) + // utils.NafDecomposition(T2, bw6_761.loopCounter2[:]) + + // TODO for now use the "naive" Miller loop + T, _ := new(big.Int).SetString("9586122913090633730", 10) + utils.NafDecomposition(T, bw6_761.loopCounter1[:]) + T2, _ := new(big.Int).SetString("880904806456922042166256752416502360955572640081583800319", 10) + utils.NafDecomposition(T2, bw6_761.loopCounter2[:]) // infinity point G1 bw6_761.g1Infinity.X.SetOne() diff --git a/bw6_761/e2.go b/bw6_761/e2.go index a2dc5348f9..d1fe3d441a 100644 --- a/bw6_761/e2.go +++ b/bw6_761/e2.go @@ -20,135 +20,135 @@ import ( "github.com/consensys/gurvy/bw6_761/fp" ) -// e2 is a degree-two finite field extension of fp.Element: -// A0 + A1u where u^2 == -1 is a quadratic nonresidue in fp +// E2 is a degree-two finite field extension of fp.Element: +// A0 + A1u where u^2 == -4 is a quadratic nonresidue in fp -type e2 struct { +type E2 struct { A0, A1 fp.Element } // Equal returns true if z equals x, fasle otherwise // TODO can this be deleted? Should be able to use == operator instead -func (z *e2) Equal(x *e2) bool { +func (z *E2) Equal(x *E2) bool { return z.A0.Equal(&x.A0) && z.A1.Equal(&x.A1) } -// SetString sets a e2 element from strings -func (z *e2) SetString(s1, s2 string) *e2 { +// SetString sets a E2 element from strings +func (z *E2) SetString(s1, s2 string) *E2 { z.A0.SetString(s1) z.A1.SetString(s2) return z } -func (z *e2) SetZero() *e2 { +func (z *E2) SetZero() *E2 { z.A0.SetZero() z.A1.SetZero() return z } // Clone returns a copy of self -func (z *e2) Clone() *e2 { - return &e2{ +func (z *E2) Clone() *E2 { + return &E2{ A0: z.A0, A1: z.A1, } } -// Set sets an e2 from x -func (z *e2) Set(x *e2) *e2 { +// Set sets an E2 from x +func (z *E2) Set(x *E2) *E2 { z.A0.Set(&x.A0) z.A1.Set(&x.A1) return z } // Set sets z to 1 in Montgomery form and returns z -func (z *e2) SetOne() *e2 { +func (z *E2) SetOne() *E2 { z.A0.SetOne() z.A1.SetZero() return z } // SetRandom sets a0 and a1 to random values -func (z *e2) SetRandom() *e2 { +func (z *E2) SetRandom() *E2 { z.A0.SetRandom() z.A1.SetRandom() return z } // Equal returns true if the two elements are equal, fasle otherwise -func (z *e2) IsZero() bool { +func (z *E2) IsZero() bool { return z.A0.IsZero() && z.A1.IsZero() } -// Neg negates an e2 element -func (z *e2) Neg(x *e2) *e2 { +// Neg negates an E2 element +func (z *E2) Neg(x *E2) *E2 { z.A0.Neg(&x.A0) z.A1.Neg(&x.A1) return z } // String implements Stringer interface for fancy printing -func (z *e2) String() string { +func (z *E2) String() string { return (z.A0.String() + "+" + z.A1.String() + "*u") } // ToMont converts to mont form -func (z *e2) ToMont() *e2 { +func (z *E2) ToMont() *E2 { z.A0.ToMont() z.A1.ToMont() return z } // FromMont converts from mont form -func (z *e2) FromMont() *e2 { +func (z *E2) FromMont() *E2 { z.A0.FromMont() z.A1.FromMont() return z } -// Add adds two elements of e2 -func (z *e2) Add(x, y *e2) *e2 { +// Add adds two elements of E2 +func (z *E2) Add(x, y *E2) *E2 { z.A0.Add(&x.A0, &y.A0) z.A1.Add(&x.A1, &y.A1) return z } // AddAssign adds x to z -func (z *e2) AddAssign(x *e2) *e2 { +func (z *E2) AddAssign(x *E2) *E2 { z.A0.AddAssign(&x.A0) z.A1.AddAssign(&x.A1) return z } -// Sub two elements of e2 -func (z *e2) Sub(x, y *e2) *e2 { +// Sub two elements of E2 +func (z *E2) Sub(x, y *E2) *E2 { z.A0.Sub(&x.A0, &y.A0) z.A1.Sub(&x.A1, &y.A1) return z } // SubAssign subs x from z -func (z *e2) SubAssign(x *e2) *e2 { +func (z *E2) SubAssign(x *E2) *E2 { z.A0.SubAssign(&x.A0) z.A1.SubAssign(&x.A1) return z } -// Double doubles an e2 element -func (z *e2) Double(x *e2) *e2 { +// Double doubles an E2 element +func (z *E2) Double(x *E2) *E2 { z.A0.Double(&x.A0) z.A1.Double(&x.A1) return z } -// Mul sets z to the e2-product of x,y, returns z -func (z *e2) Mul(x, y *e2) *e2 { - // (a+bu)*(c+du) == (ac+(-1)*bd) + (ad+bc)u where u^2 == -1 +// Mul sets z to the E2-product of x,y, returns z +func (z *E2) Mul(x, y *E2) *E2 { + // (a+bu)*(c+du) == (ac+(-4)*bd) + (ad+bc)u where u^2 == -4 // Karatsuba: 3 fp multiplications instead of 4 // [1]: ac // [2]: bd // [3]: (a+b)*(c+d) - // Then z.A0: [1] + (-1)*[2] + // Then z.A0: [1] + (-4)*[2] // Then z.A1: [3] - [2] - [1] var ac, bd, cplusd, aplusbcplusd fp.Element @@ -159,18 +159,19 @@ func (z *e2) Mul(x, y *e2) *e2 { aplusbcplusd.MulAssign(&cplusd) // [3]: (a+b)*(c+d) z.A1.Add(&ac, &bd) // ad+bc, [2] + [1] z.A1.Sub(&aplusbcplusd, &z.A1) // z.A1: [3] - [2] - [1] - z.A0.Sub(&ac, &bd) // z.A0: [1] - [2] + MulByNonResidue(&z.A0, &bd) + z.A0.AddAssign(&ac) // z.A0: [1] + (-4)*[2] return z } -// MulAssign sets z to the e2-product of z,x returns z -func (z *e2) MulAssign(x *e2) *e2 { - // (a+bu)*(c+du) == (ac+(-1)*bd) + (ad+bc)u where u^2 == -1 +// MulAssign sets z to the E2-product of z,x returns z +func (z *E2) MulAssign(x *E2) *E2 { + // (a+bu)*(c+du) == (ac+(-4)*bd) + (ad+bc)u where u^2 == -4 // Karatsuba: 3 fp multiplications instead of 4 // [1]: ac // [2]: bd // [3]: (a+b)*(c+d) - // Then z.A0: [1] + (-1)*[2] + // Then z.A0: [1] + (-4)*[2] // Then z.A1: [3] - [2] - [1] var ac, bd, cplusd, aplusbcplusd fp.Element @@ -181,52 +182,55 @@ func (z *e2) MulAssign(x *e2) *e2 { aplusbcplusd.MulAssign(&cplusd) // [3]: (a+b)*(c+d) z.A1.Add(&ac, &bd) // ad+bc, [2] + [1] z.A1.Sub(&aplusbcplusd, &z.A1) // z.A1: [3] - [2] - [1] - z.A0.Sub(&ac, &bd) // z.A0: [1] - [2] + MulByNonResidue(&z.A0, &bd) + z.A0.AddAssign(&ac) // z.A0: [1] + (-4)*[2] return z } -// Square sets z to the e2-product of x,x returns z -func (z *e2) Square(x *e2) *e2 { - // (a+bu)^2 == (a^2+(-1)*b^2) + (2ab)u where u^2 == -1 +// Square sets z to the E2-product of x,x returns z +func (z *E2) Square(x *E2) *E2 { + // (a+bu)^2 == (a^2+(-4)*b^2) + (2ab)u where u^2 == -4 // Complex method: 2 fp multiplications instead of 3 // [1]: ab - // [2]: (a+b)*(a+(-1)*b) - // Then z.A0: [2] - (-1+1)*[1] + // [2]: (a+b)*(a+(-4)*b) + // Then z.A0: [2] - (-4+1)*[1] // Then z.A1: 2[1] - // optimize for quadratic nonresidue -1 - var aplusb fp.Element - var result e2 + var ab, aplusb, ababetab fp.Element - aplusb.Add(&x.A0, &x.A1) // a+b - result.A0.Sub(&x.A0, &x.A1) // a-b - result.A0.MulAssign(&aplusb) // [2]: (a+b)*(a-b) - result.A1.Mul(&x.A0, &x.A1).Double(&result.A1) // [1]: ab + MulByNonResidue(&ababetab, &x.A1) - z.Set(&result) + ababetab.AddAssign(&x.A0) // a+(-4)*b + aplusb.Add(&x.A0, &x.A1) // a+b + ababetab.MulAssign(&aplusb) // [2]: (a+b)*(a+(-4)*b) + ab.Mul(&x.A0, &x.A1) // [1]: ab + z.A1.Double(&ab) // z.A1: 2*[1] + MulByNonResidue(&z.A0, &ab).AddAssign(&ab) // (-4+1)*ab + z.A0.Sub(&ababetab, &z.A0) // z.A0: [2] - (-4+1)[1] return z } // MulByNonSquare multiplies an element by (0,1) // TODO deprecate in favor of inlined MulByNonResidue in fp6 package -func (z *e2) MulByNonSquare(x *e2) *e2 { +func (z *E2) MulByNonSquare(x *E2) *E2 { a := x.A0 MulByNonResidue(&z.A0, &x.A1) z.A1 = a return z } -// Inverse sets z to the e2-inverse of x, returns z -func (z *e2) Inverse(x *e2) *e2 { +// Inverse sets z to the E2-inverse of x, returns z +func (z *E2) Inverse(x *E2) *E2 { // Algorithm 8 from https://eprint.iacr.org/2010/354.pdf - var a0, a1, t0, t1 fp.Element + var a0, a1, t0, t1, t1beta fp.Element a0 = x.A0 // = is slightly faster than Set() a1 = x.A1 // = is slightly faster than Set() - t0.Square(&a0) // step 1 - t1.Square(&a1) // step 2 - t0.Add(&t0, &t1) // step 3 + t0.Square(&a0) // step 1 + t1.Square(&a1) // step 2 + MulByNonResidue(&t1beta, &t1) + t0.SubAssign(&t1beta) // step 3 t1.Inverse(&t0) // step 4 z.A0.Mul(&a0, &t1) // step 5 z.A1.Neg(&a1).MulAssign(&t1) // step 6 @@ -234,8 +238,8 @@ func (z *e2) Inverse(x *e2) *e2 { return z } -// MulByElement multiplies an element in e2 by an element in fp -func (z *e2) MulByElement(x *e2, y *fp.Element) *e2 { +// MulByElement multiplies an element in E2 by an element in fp +func (z *E2) MulByElement(x *E2, y *fp.Element) *E2 { var yCopy fp.Element yCopy.Set(y) z.A0.Mul(&x.A0, &yCopy) @@ -243,24 +247,24 @@ func (z *e2) MulByElement(x *e2, y *fp.Element) *e2 { return z } -// Conjugate conjugates an element in e2 -func (z *e2) Conjugate(x *e2) *e2 { +// Conjugate conjugates an element in E2 +func (z *E2) Conjugate(x *E2) *E2 { z.A0.Set(&x.A0) z.A1.Neg(&x.A1) return z } -// MulByNonResidue multiplies a fp.Element by -1 +// MulByNonResidue multiplies a fp.Element by -4 // It would be nice to make this a method of fp.Element but fp.Element is outside this package func MulByNonResidue(out, in *fp.Element) *fp.Element { - (out).Neg(in) + buf := *(in) + (out).Double(&buf).Double(out).Neg(out) return out } -// MulByNonResidueInv multiplies a fp.Element by -1^{-1} +// MulByNonResidueInv multiplies a fp.Element by -4^{-1} // It would be nice to make this a method of fp.Element but fp.Element is outside this package func MulByNonResidueInv(out, in *fp.Element) *fp.Element { - // TODO this should be a no-op when out==in - (out).Set(in) + // TODO not implemented return out } diff --git a/bw6_761/e2_test.go b/bw6_761/e2_test.go new file mode 100644 index 0000000000..0c21553bcb --- /dev/null +++ b/bw6_761/e2_test.go @@ -0,0 +1,170 @@ +// Code generated by internal/tower DO NOT EDIT +package bw6_761 + +import ( + "reflect" + "testing" +) + +type E2TestPoint struct { + in [2]E2 + out [7]E2 +} + +var E2TestPoints []E2TestPoint + +// TODO this method is the same everywhere. move it someplace central and call it "compare" +func E2compare(t *testing.T, got, want interface{}) { + if !reflect.DeepEqual(got, want) { + t.Fatal("\nexpect:\t", want, "\ngot:\t", got) + } +} + +func E2check(t *testing.T, f func(*E2, *E2, *E2) *E2, m int) { + + if len(E2TestPoints) < 1 { + t.Log("no tests to run") + } + + for i := range E2TestPoints { + var receiver E2 + var out *E2 + var inCopies [len(E2TestPoints[i].in)]E2 + + for j := range inCopies { + inCopies[j].Set(&E2TestPoints[i].in[j]) + } + + // receiver, return value both set to result + out = f(&receiver, &inCopies[0], &inCopies[1]) + + E2compare(t, receiver, E2TestPoints[i].out[m]) // receiver correct + E2compare(t, *out, E2TestPoints[i].out[m]) // return value correct + for j := range inCopies { + E2compare(t, inCopies[j], E2TestPoints[i].in[j]) // inputs unchanged + } + + // receiver == one of the inputs + for j := range inCopies { + out = f(&inCopies[j], &inCopies[0], &inCopies[1]) + + E2compare(t, inCopies[j], E2TestPoints[i].out[m]) // receiver correct + E2compare(t, *out, E2TestPoints[i].out[m]) // return value correct + for k := range inCopies { + if k == j { + continue + } + E2compare(t, inCopies[k], E2TestPoints[i].in[k]) // other inputs unchanged + } + inCopies[j].Set(&E2TestPoints[i].in[j]) // reset input for next tests + } + } +} + +//--------------------// +// tests // +//--------------------// + +func TestE2Add(t *testing.T) { + E2check(t, (*E2).Add, 0) +} + +func TestE2Sub(t *testing.T) { + E2check(t, (*E2).Sub, 1) +} + +func TestE2Mul(t *testing.T) { + E2check(t, (*E2).Mul, 2) +} + +func TestE2MulByElement(t *testing.T) { + E2check(t, (*E2).MulByElementBinary, 3) +} + +func TestE2Square(t *testing.T) { + E2check(t, (*E2).SquareBinary, 4) +} + +func TestE2Inverse(t *testing.T) { + E2check(t, (*E2).InverseBinary, 5) +} + +func TestE2Conjugate(t *testing.T) { + E2check(t, (*E2).ConjugateBinary, 6) +} + +//--------------------// +// benches // +//--------------------// + +var E2BenchIn1, E2BenchIn2, E2BenchOut E2 + +func BenchmarkE2Add(b *testing.B) { + for i := 0; i < b.N; i++ { + E2BenchOut.Add(&E2BenchIn1, &E2BenchIn2) + } +} + +func BenchmarkE2Sub(b *testing.B) { + for i := 0; i < b.N; i++ { + E2BenchOut.Sub(&E2BenchIn1, &E2BenchIn2) + } +} + +func BenchmarkE2Mul(b *testing.B) { + for i := 0; i < b.N; i++ { + E2BenchOut.Mul(&E2BenchIn1, &E2BenchIn2) + } +} + +func BenchmarkE2MulByElement(b *testing.B) { + for i := 0; i < b.N; i++ { + E2BenchOut.MulByElementBinary(&E2BenchIn1, &E2BenchIn2) + } +} + +func BenchmarkE2Square(b *testing.B) { + for i := 0; i < b.N; i++ { + E2BenchOut.SquareBinary(&E2BenchIn1, &E2BenchIn2) + } +} + +func BenchmarkE2Inverse(b *testing.B) { + for i := 0; i < b.N; i++ { + E2BenchOut.InverseBinary(&E2BenchIn1, &E2BenchIn2) + } +} + +func BenchmarkE2Conjugate(b *testing.B) { + for i := 0; i < b.N; i++ { + E2BenchOut.ConjugateBinary(&E2BenchIn1, &E2BenchIn2) + } +} + +//-------------------------------------// +// unary helpers for E2 methods +//-------------------------------------// + +// SquareBinary a binary wrapper for Square +func (z *E2) SquareBinary(x, y *E2) *E2 { + return z.Square(x) +} + +// InverseBinary a binary wrapper for Inverse +func (z *E2) InverseBinary(x, y *E2) *E2 { + return z.Inverse(x) +} + +// ConjugateBinary a binary wrapper for Conjugate +func (z *E2) ConjugateBinary(x, y *E2) *E2 { + return z.Conjugate(x) +} + +//-------------------------------------// +// custom helpers for E2 methods +//-------------------------------------// + +// MulByElementBinary a binary wrapper for MulByElement +func (z *E2) MulByElementBinary(x, y *E2) *E2 { + return z.MulByElement(x, &y.A0) +} diff --git a/bw6_761/e2testpoints_test.go b/bw6_761/e2testpoints_test.go new file mode 100644 index 0000000000..117e79170a --- /dev/null +++ b/bw6_761/e2testpoints_test.go @@ -0,0 +1,112 @@ +// Code generated by internal/tower DO NOT EDIT +package bw6_761 + +func init() { + + E2TestPoints = make([]E2TestPoint, 10) + + E2TestPoints[0].in[0].SetString("0", "0") + E2TestPoints[0].in[1].SetString("0", "0") + E2TestPoints[0].out[0].SetString("0", "0") + E2TestPoints[0].out[1].SetString("0", "0") + E2TestPoints[0].out[2].SetString("0", "0") + E2TestPoints[0].out[3].SetString("0", "0") + E2TestPoints[0].out[4].SetString("0", "0") + E2TestPoints[0].out[5].SetString("0", "0") + E2TestPoints[0].out[6].SetString("0", "0") + + E2TestPoints[1].in[0].SetString("1", "0") + E2TestPoints[1].in[1].SetString("1", "0") + E2TestPoints[1].out[0].SetString("2", "0") + E2TestPoints[1].out[1].SetString("0", "0") + E2TestPoints[1].out[2].SetString("1", "0") + E2TestPoints[1].out[3].SetString("1", "0") + E2TestPoints[1].out[4].SetString("1", "0") + E2TestPoints[1].out[5].SetString("1", "0") + E2TestPoints[1].out[6].SetString("1", "0") + + E2TestPoints[2].in[0].SetString("0", "1") + E2TestPoints[2].in[1].SetString("1", "0") + E2TestPoints[2].out[0].SetString("1", "1") + E2TestPoints[2].out[1].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "1") + E2TestPoints[2].out[2].SetString("0", "1") + E2TestPoints[2].out[3].SetString("0", "1") + E2TestPoints[2].out[4].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068295", "0") + E2TestPoints[2].out[5].SetString("0", "5168587788236799404547592261706743156859751684402112582135342620157217566682618802065762387467058765730648425815339960088371319340415685819512133774343976199213703824533881637779407723567697596963924775322476834632073684839301224") + E2TestPoints[2].out[6].SetString("0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298") + + E2TestPoints[3].in[0].SetString("1", "1") + E2TestPoints[3].in[1].SetString("1", "0") + E2TestPoints[3].out[0].SetString("2", "1") + E2TestPoints[3].out[1].SetString("0", "1") + E2TestPoints[3].out[2].SetString("1", "1") + E2TestPoints[3].out[3].SetString("1", "1") + E2TestPoints[3].out[4].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068296", "2") + E2TestPoints[3].out[5].SetString("1378290076863146507879357936455131508495933782507230021902758032041924684448698347217536636657882337528172913550757322690232351824110849551869902339825060319790321019875701770074508726284719359190379940085993822568552982623813660", "5513160307452586031517431745820526033983735130028920087611032128167698737794793388870146546631529350112691654203029290760929407296443398207479609359300241279161284079502807080298034905138877436761519760343975290274211930495254639") + E2TestPoints[3].out[6].SetString("1", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298") + + E2TestPoints[4].in[0].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "0") + E2TestPoints[4].in[1].SetString("1", "0") + E2TestPoints[4].out[0].SetString("0", "0") + E2TestPoints[4].out[1].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068297", "0") + E2TestPoints[4].out[2].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "0") + E2TestPoints[4].out[3].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "0") + E2TestPoints[4].out[4].SetString("1", "0") + E2TestPoints[4].out[5].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "0") + E2TestPoints[4].out[6].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "0") + + E2TestPoints[5].in[0].SetString("0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298") + E2TestPoints[5].in[1].SetString("1", "0") + E2TestPoints[5].out[0].SetString("1", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298") + E2TestPoints[5].out[1].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298") + E2TestPoints[5].out[2].SetString("0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298") + E2TestPoints[5].out[3].SetString("0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298") + E2TestPoints[5].out[4].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068295", "0") + E2TestPoints[5].out[5].SetString("0", "1722862596078933134849197420568914385619917228134037527378447540052405855560872934021920795822352921910216141938446653362790439780138561939837377924781325399737901274844627212593135907855899198987974925107492278210691228279767075") + E2TestPoints[5].out[6].SetString("0", "1") + + E2TestPoints[6].in[0].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298") + E2TestPoints[6].in[1].SetString("1", "0") + E2TestPoints[6].out[0].SetString("0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298") + E2TestPoints[6].out[1].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068297", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298") + E2TestPoints[6].out[2].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298") + E2TestPoints[6].out[3].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298") + E2TestPoints[6].out[4].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068296", "2") + E2TestPoints[6].out[5].SetString("5513160307452586031517431745820526033983735130028920087611032128167698737794793388870146546631529350112691654203029290760929407296443398207479609359300241279161284079502807080298034905138877436761519760343975290274211930495254639", "1378290076863146507879357936455131508495933782507230021902758032041924684448698347217536636657882337528172913550757322690232351824110849551869902339825060319790321019875701770074508726284719359190379940085993822568552982623813660") + E2TestPoints[6].out[6].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "1") + + E2TestPoints[7].in[0].SetString("6425522494491572315991300805865898504143443599906677141458211804232061862991840406915511172778276913286745870821128181817904122018546949149371168292903110810731444066400496724054029931175222518192723582172466207323211441401880085", "6416003737322694212178268125126546492607601681157255988306866619114417121959935111611254541190013970335135616768030547356690662835050009937806514587416857088724648831140348909613351822310248717616923922514568389476271821145610487") + E2TestPoints[7].in[1].SetString("2088658774711260487790844378424248717100789709936011859626785314973946089954282170988258604251668795788844891546187320978669651852631657564730850926678569505083650677171229565781756388033146877635174949638537973649596321949183478", "6772253663683578844260801199408873307993319026060438930078788539855621792335282451703328220223565983059125605144607166247379925942138149128716466058708598339604234852829271478345301024909623481167138825820522997540855950579410198") + E2TestPoints[7].out[0].SetString("1622730884887100264385355502014489678764564397306538891571206958996384530702630841816086593740534021434726194613528889345412014750624358954752507520456378716863489644193217439463242687784772599875998831381035068130042850231995264", "6296807016690540517042279642259762258121251794681544808871864998760415492051725827226899578124168265753396654158851100152908829656633911307173468947000153829377278584591111537586109215796275402832163047905122274174362858605952386") + E2TestPoints[7].out[1].SetString("4336863719780311828200456427441649787042653889970665281831426489258115773037558235927252568526608117497900979274940860839234470165915291584640317366224541305647793389229267158272273543142075640557548632533928233673615119452696607", "6535200457954847907314256607993330727093951567632967167741868239468418751868144395995609504255859674916874579377209994560472496013466108568439560227833560348072019077689586281640594428824222032401684797124014504778180783685268588") + E2TestPoints[7].out[2].SetString("6012013398337115984552515975843731499325773274682351686593143829945284878265051129220193921507178418493855242102018965441171771163961066617857105237149995740527707799239937031411485755613637158187274700532317801014935348902126643", "3640620091902195547661521116810791796541479838699372110255385910555464683762442588204267268513141570059785558550443310852224027406933271412675227740620934808206024282871603824428141737779553303650564870679573146906961296548444927") + E2TestPoints[7].out[3].SetString("1466843592161907610685903466571275190405645598591239149741716811157053951797838973397636235037403843164548201681790606705993283891342428019296700659971844190741291946224740220220901456218978759099649275889019406995699076927756526", "4030209039332893714207505069713857028745197993234969589747971411442020341225164368674816204832568910636373653239202196883854263442659097167375522544369322482622055350261393177416041794930951038796890444344998369814904689447767265") + E2TestPoints[7].out[4].SetString("4952653229220446043357985046388141064842230213292556102359306746043569679006029085017243220156241675645308151510110749828014159600815241173056334037893849918908308105306032408052818835196782850551939869702437182792532268087844790", "3418199648594983389323451289638273728181451181799085604768717193167020925003995341316285077067972536624546809223769554028773397337676015864107642783255342150459074675944672856195055056625368978855525875083333171560411473005498277") + E2TestPoints[7].out[5].SetString("3669111552307599734460064980435072257623586350091580869177328782007403201242049793133854551475880055924657696694231617542620764919394150282019035062875368499964202642235153099213395956676606650281784363906394195020730547274883313", "5278757573367550407159348031246997294186286165734325773428204254511321870223038992784481442883253463898291716055355420035394496261453951965543131190912651045300796393095224883588085135936987379563064747651259463136466040491045210") + E2TestPoints[7].out[6].SetString("6425522494491572315991300805865898504143443599906677141458211804232061862991840406915511172778276913286745870821128181817904122018546949149371168292903110810731444066400496724054029931175222518192723582172466207323211441401880085", "475446646993038327218521557149111049872067231378894121206923541095206300283556624476428642099397717305728950985756066094471096285504237821542997111708444510226956268238159940759191809113348078334975777915400723366493091973457812") + + E2TestPoints[8].in[0].SetString("1554493478850369830895349504525346388528667850780445040860317310845525153144168601593767921898005858229073725270868707979853228148024579143638520111877145569836337287144974044290353948919523078307621432414273808142411809483846540", "3207330411680060796244795665281819966230190587445964995767640155240704771173451521217874801755988859757634548609498995733789450147403319645901283237218644012247647271361771885793285412835907448380415538089969980743423394284065565") + E2TestPoints[8].in[1].SetString("1532740464095164769979825729487839139176327941695294581726527339602613788201880024392864805394358376374500510077126905862756076746438610565234242563140805931730448047468327526521395102271797818849429129873663319528383626241855829", "6433006445369229057655095593791510134826788432595011178057543538708313550770678322567063037949788084739696893266874401495154272660189515397514719567461063905663479793076474212956010385012225149761131341319191084194701714879385414") + E2TestPoints[8].out[0].SetString("3087233942945534600875175234013185527704995792475739622586844650448138941346048625986632727292364234603574235347995613842609304894463189708872762675017951501566785334613301570811749051191320897157050562287937127670795435725702369", "2748886472733557314503101576797672558577310107504826064311393533739394899700638107697254656416365256856466874122586783777781963687038587284066491105554406318959521965059737248376752166424535802189647178979191952095360196044382680") + E2TestPoints[8].out[1].SetString("21753014755205060915523775037507249352339909085150459133789971242911364942288577200903116503647481854573215193741802117097151401585968578404277548736339638105889239676646517768958846647725259458192302540610488614028183241990711", "3665774350626564277986489753765967373883071067387103927223886776742014642646264934738494947095612462658802223096411207689796936607768052007736075368882881705535772577663806523209818659247279094571183897200748009391486592523748450") + E2TestPoints[8].out[2].SetString("3966163425404577066769364708614624358986267035504168205879465320763960281502275570438580726264816200859995824758792945358444406123704874060913862117895612984898216480662241464399013439073772090432852576815968401821346818712069967", "5755538474669643443379216641206549321258775931957711289152831927536704219136312507393278982065150917611257058837590961181923495881923958067020801333991662874933541581971885010834510116142157197145940539716787768586657593004727339") + E2TestPoints[8].out[3].SetString("6784993448989970858409795268456266525922952157828888146724094556218757147786511255754986510493248062150143903723490084276548381422480758330513144052195910056641708914726765069940222643939567102008827781764680762839791826518356145", "5080606796534545090069465819186397601106336184584147873008550034580715632619404494768557261361312281470362915402362687285431075483555398563835398729872700474680954030358147086021302046968117163043479648187623006440987831063730669") + E2TestPoints[8].out[4].SetString("5618456504631544074417956443343345726188849242134367637369587783132332547643669495699975929648459529098286625484986329759284844214770266055163244597043198674237029518753926838074537943640701725688087791157432933707151201772390908", "219162690063054775302219114234941608011705057780682834689216484856281300326709376255159256055423094401993436748598685088471324786839451736759106321041687764171953759798651518993896824184927365312081519395721163127976174476716879") + E2TestPoints[8].out[5].SetString("2395395390245952936217261404289159794816626936072003681545816570683381009160669432062640139688566185238489274879178311438355787506884013791558155401560058890663741957230044481336461143837134636584432363871476948775082989976020178", "1415858405047790924976552593541373863176178314716902404980819187533448469161736869016344561715852989861134366392692451191781091343400225898505029117798688957478512055237576100282099586080716423712065350965560441068635879664724340") + E2TestPoints[8].out[6].SetString("1554493478850369830895349504525346388528667850780445040860317310845525153144168601593767921898005858229073725270868707979853228148024579143638520111877145569836337287144974044290353948919523078307621432414273808142411809483846540", "3684119972635671743151994016993837576249478325090185113746150004968918651070040214869808381533422827883230019144287617717372308973150928113448228461906657586703957828016736964579258218587689347571484162339999132099341518835002734") + + E2TestPoints[9].in[0].SetString("5828685090715787262022246197330420519892365120537359578976798238063887316599791195779133736317014585736794927789676004919998493110413323600617162878830048493713128730777036772137079445977567809192462470694688860403572253456147082", "4190662364229312333526653602068311373325194060758272912230164041946721556748864468685681313837834446976330662920644193644652372608660990188416258116540272138190832938783514403748464734113086868198443933142426358310830068235442142") + E2TestPoints[9].in[1].SetString("4507736114993811280254534830304525061781281493074363331917895808531797195721889293312797634932579317099069996323395134482932435487506091105578805134789419717306105888874545544190771470528580107507086946211170564862238937797668913", "5350494694209144274510070455614023689300436599427541446486933855648386689361927030420638725240691987590324443830822357174560546717844633316165739510302465315742307088507217586939376770237140245801227294856341874312556537131688900") + E2TestPoints[9].out[0].SetString("3444970821393866002879991345359288039193977701075572801380903886386061090078188753004248187960182215195000356359284525951769169477365166946846456314494166612067629520273073465955307285082551120747649716475890312423046278134747696", "2649706674122724068639934375406677520145961747649664249203307737385484823867299763018636855789114746925790538997679937368051160205951375745232485927717435854981534927912223140315297872926630318047771527568799119780621692248062743") + E2TestPoints[9].out[1].SetString("1320948975721975981767711367025895458111083627462996247058902429532090120877901902466336101384435268637724931466280870437066057622907232495038357744040628776407022841902491227946307975448987701685375524483518295541333315658478169", "5731618054335900598413372828729945226504426373866881575257020346507958289630429174352725771886554147026870786843608449921253585011370604631600030305363108421400130949654805667181631595299543418349116338716053596841038444222821541") + E2TestPoints[9].out[2].SetString("5066328282419537662504098733746582014223139343656657962901461735765721929884505746805561620328566926601643269255892513335540745317326386096022187864331500501376659959463633138233499567033778219502257375433311490271955447989052220", "1086707975329886406268734174782886745393139790054435231457320389202918395954079870337438068350025472874089629822751734257663987114684583538998980713052757649816872578658642846388642393600089142810029785729179138379104147508631795") + E2TestPoints[9].out[3].SetString("1715584903965247748399224688856720807960633928216994116969216778965126363228408734761138863592237626447836990432366136222262649323670094305634347739741471844735130654593806051236829357387879523622164689544035710599283713461049818", "3034380589081546615921436408116570242276412487438460265658938686540493346818801353667709630383234552828663154586655508960227659197925584492328818475642222750100296858909533336820619791877177687540498989271660744443416512998435237") + E2TestPoints[9].out[4].SetString("3789634324169182881372357993405051787760290431178105373191341068349729410172425733946954388271931948735972274048633478691869957146480950524273774389287552585002277745121649635830925558419337710348412913737516482915732507076732513", "4106256498311613249179483043820740112394801546184444604747332084603573629883446390112795042491945316576481513715903036249913813330629515123222742927463257004895219496054377631492137174724853303115019870763144081977553660810990157") + E2TestPoints[9].out[5].SetString("5785953568868316062807736766288315140400360312961914466790242370608723091759995126993643007675213355188756991268630639345113565818292131024861113903282845799446009363384309833195810814814193663503183108288054947141463606537230089", "6800137574447714689772167304241471671546782244452789762524308156955198340365452908081567972195581015496993781211293307013393465053817659961302850009708333749859224952548330976335936528425053417742516038136715028248378944369666464") + E2TestPoints[9].out[6].SetString("5828685090715787262022246197330420519892365120537359578976798238063887316599791195779133736317014585736794927789676004919998493110413323600617162878830048493713128730777036772137079445977567809192462470694688860403572253456147082", "2700788020086420205870136080207346169154474851777877197283626118262901865494627267402001869451577240664533904833142419806509386511893257570933253582585029460760772160594994446624078897310509927753455767287542754531934844883626157") + + // benchmark inputs should be randomly generated, + // so use the final test point + E2BenchIn1.Set(&E2TestPoints[len(E2TestPoints)-1].in[0]) + E2BenchIn2.Set(&E2TestPoints[len(E2TestPoints)-1].in[1]) +} diff --git a/bw6_761/e6.go b/bw6_761/e6.go index 96b0aa8bab..fd1f276c58 100644 --- a/bw6_761/e6.go +++ b/bw6_761/e6.go @@ -16,31 +16,29 @@ package bw6_761 -import "github.com/consensys/gurvy/bw6_761/fp" +// E6 is a degree-three finite field extension of fp2: +// B0 + B1v + B2v^2 where v^3-0,1 is irrep in fp2 -// e6 is a degree-three finite field extension of fp2: -// B0 + B1v + B2v^2 where v^3-1,1 is irrep in fp2 - -type e6 struct { - B0, B1, B2 e2 +type E6 struct { + B0, B1, B2 E2 } // Equal returns true if z equals x, fasle otherwise // TODO can this be deleted? Should be able to use == operator instead -func (z *e6) Equal(x *e6) bool { +func (z *E6) Equal(x *E6) bool { return z.B0.Equal(&x.B0) && z.B1.Equal(&x.B1) && z.B2.Equal(&x.B2) } -// SetString sets a e6 elmt from stringf -func (z *e6) SetString(s1, s2, s3, s4, s5, s6 string) *e6 { +// SetString sets a E6 elmt from stringf +func (z *E6) SetString(s1, s2, s3, s4, s5, s6 string) *E6 { z.B0.SetString(s1, s2) z.B1.SetString(s3, s4) z.B2.SetString(s5, s6) return z } -// Set Sets a e6 elmt form another e6 elmt -func (z *e6) Set(x *e6) *e6 { +// Set Sets a E6 elmt form another E6 elmt +func (z *E6) Set(x *E6) *E6 { z.B0 = x.B0 z.B1 = x.B1 z.B2 = x.B2 @@ -48,7 +46,7 @@ func (z *e6) Set(x *e6) *e6 { } // SetOne sets z to 1 in Montgomery form and returns z -func (z *e6) SetOne() *e6 { +func (z *E6) SetOne() *E6 { z.B0.A0.SetOne() z.B0.A1.SetZero() z.B1.A0.SetZero() @@ -58,8 +56,16 @@ func (z *e6) SetOne() *e6 { return z } +// SetRandom set z to a random elmt +func (z *E6) SetRandom() *E6 { + z.B0.SetRandom() + z.B1.SetRandom() + z.B2.SetRandom() + return z +} + // ToMont converts to Mont form -func (z *e6) ToMont() *e6 { +func (z *E6) ToMont() *E6 { z.B0.ToMont() z.B1.ToMont() z.B2.ToMont() @@ -67,78 +73,79 @@ func (z *e6) ToMont() *e6 { } // FromMont converts from Mont form -func (z *e6) FromMont() *e6 { +func (z *E6) FromMont() *E6 { z.B0.FromMont() z.B1.FromMont() z.B2.FromMont() return z } -// Add adds two elements of e6 -func (z *e6) Add(x, y *e6) *e6 { +// Add adds two elements of E6 +func (z *E6) Add(x, y *E6) *E6 { z.B0.Add(&x.B0, &y.B0) z.B1.Add(&x.B1, &y.B1) z.B2.Add(&x.B2, &y.B2) return z } -// Neg negates the e6 number -func (z *e6) Neg(x *e6) *e6 { +// Neg negates the E6 number +func (z *E6) Neg(x *E6) *E6 { z.B0.Neg(&z.B0) z.B1.Neg(&z.B1) z.B2.Neg(&z.B2) return z } -// Sub two elements of e6 -func (z *e6) Sub(x, y *e6) *e6 { +// Sub two elements of E6 +func (z *E6) Sub(x, y *E6) *E6 { z.B0.Sub(&x.B0, &y.B0) z.B1.Sub(&x.B1, &y.B1) z.B2.Sub(&x.B2, &y.B2) return z } -// MulByGen Multiplies by v, root of X^3-1,1 +// MulByGen Multiplies by v, root of X^3-0,1 // TODO deprecate in favor of inlined MulByNonResidue in fp12 package -func (z *e6) MulByGen(x *e6) *e6 { - var result e6 +func (z *E6) MulByGen(x *E6) *E6 { + var result E6 result.B1 = x.B0 result.B2 = x.B1 { // begin: inline result.B0.MulByNonResidue(&x.B2) - var buf e2 - buf.Set(&x.B2) - result.B0.A1.Add(&buf.A0, &buf.A1) - { // begin: inline MulByNonResidue(&(result.B0).A0, &buf.A1) - (&(result.B0).A0).Neg(&buf.A1) - } // end: inline MulByNonResidue(&(result.B0).A0, &buf.A1) - result.B0.A0.AddAssign(&buf.A0) + buf := (&x.B2).A0 + { // begin: inline MulByNonResidue(&(result.B0).A0, &(&x.B2).A1) + buf := *(&(&x.B2).A1) + (&(result.B0).A0).Double(&buf).Double(&(result.B0).A0).Neg(&(result.B0).A0) + } // end: inline MulByNonResidue(&(result.B0).A0, &(&x.B2).A1) + (result.B0).A1 = buf } // end: inline result.B0.MulByNonResidue(&x.B2) z.Set(&result) return z } -// Double doubles an element in e6 -func (z *e6) Double(x *e6) *e6 { +// Double doubles an element in E6 +func (z *E6) Double(x *E6) *E6 { z.B0.Double(&x.B0) z.B1.Double(&x.B1) z.B2.Double(&x.B2) return z } -// String puts e6 elmt in string form -func (z *e6) String() string { +// String puts E6 elmt in string form +func (z *E6) String() string { return (z.B0.String() + "+(" + z.B1.String() + ")*v+(" + z.B2.String() + ")*v**2") } -// Mul multiplies two numbers in e6 -func (z *e6) Mul(x, y *e6) *e6 { +// Mul sets z to the E6-product of x,y, returns z +func (z *E6) Mul(x, y *E6) *E6 { + // Algorithm 13 from https://eprint.iacr.org/2010/354.pdf - var rb0, b0, b1, b2, b3, b4 e2 + var rb0, b0, b1, b2, b3, b4 E2 b0.Mul(&x.B0, &y.B0) // step 1 b1.Mul(&x.B1, &y.B1) // step 2 b2.Mul(&x.B2, &y.B2) // step 3 + // step 4 b3.Add(&x.B1, &x.B2) b4.Add(&y.B1, &y.B2) @@ -146,15 +153,15 @@ func (z *e6) Mul(x, y *e6) *e6 { SubAssign(&b1). SubAssign(&b2) { // begin: inline rb0.MulByNonResidue(&rb0) - var buf e2 - buf.Set(&rb0) - rb0.A1.Add(&buf.A0, &buf.A1) - { // begin: inline MulByNonResidue(&(rb0).A0, &buf.A1) - (&(rb0).A0).Neg(&buf.A1) - } // end: inline MulByNonResidue(&(rb0).A0, &buf.A1) - rb0.A0.AddAssign(&buf.A0) + buf := (&rb0).A0 + { // begin: inline MulByNonResidue(&(rb0).A0, &(&rb0).A1) + buf := *(&(&rb0).A1) + (&(rb0).A0).Double(&buf).Double(&(rb0).A0).Neg(&(rb0).A0) + } // end: inline MulByNonResidue(&(rb0).A0, &(&rb0).A1) + (rb0).A1 = buf } // end: inline rb0.MulByNonResidue(&rb0) rb0.AddAssign(&b0) + // step 5 b3.Add(&x.B0, &x.B1) b4.Add(&y.B0, &y.B1) @@ -162,15 +169,15 @@ func (z *e6) Mul(x, y *e6) *e6 { SubAssign(&b0). SubAssign(&b1) { // begin: inline b3.MulByNonResidue(&b2) - var buf e2 - buf.Set(&b2) - b3.A1.Add(&buf.A0, &buf.A1) - { // begin: inline MulByNonResidue(&(b3).A0, &buf.A1) - (&(b3).A0).Neg(&buf.A1) - } // end: inline MulByNonResidue(&(b3).A0, &buf.A1) - b3.A0.AddAssign(&buf.A0) + buf := (&b2).A0 + { // begin: inline MulByNonResidue(&(b3).A0, &(&b2).A1) + buf := *(&(&b2).A1) + (&(b3).A0).Double(&buf).Double(&(b3).A0).Neg(&(b3).A0) + } // end: inline MulByNonResidue(&(b3).A0, &(&b2).A1) + (b3).A1 = buf } // end: inline b3.MulByNonResidue(&b2) z.B1.AddAssign(&b3) + // step 6 b3.Add(&x.B0, &x.B2) b4.Add(&y.B0, &y.B2) @@ -182,9 +189,61 @@ func (z *e6) Mul(x, y *e6) *e6 { return z } -// MulByE2 multiplies x by an elements of e2 -func (z *e6) MulByE2(x *e6, y *e2) *e6 { - var yCopy e2 +// MulAssign sets z to the E6-product of z,x returns z +func (z *E6) MulAssign(x *E6) *E6 { + + // Algorithm 13 from https://eprint.iacr.org/2010/354.pdf + var rb0, b0, b1, b2, b3, b4 E2 + b0.Mul(&z.B0, &x.B0) // step 1 + b1.Mul(&z.B1, &x.B1) // step 2 + b2.Mul(&z.B2, &x.B2) // step 3 + + // step 4 + b3.Add(&z.B1, &z.B2) + b4.Add(&x.B1, &x.B2) + rb0.Mul(&b3, &b4). + SubAssign(&b1). + SubAssign(&b2) + { // begin: inline rb0.MulByNonResidue(&rb0) + buf := (&rb0).A0 + { // begin: inline MulByNonResidue(&(rb0).A0, &(&rb0).A1) + buf := *(&(&rb0).A1) + (&(rb0).A0).Double(&buf).Double(&(rb0).A0).Neg(&(rb0).A0) + } // end: inline MulByNonResidue(&(rb0).A0, &(&rb0).A1) + (rb0).A1 = buf + } // end: inline rb0.MulByNonResidue(&rb0) + rb0.AddAssign(&b0) + + // step 5 + b3.Add(&z.B0, &z.B1) + b4.Add(&x.B0, &x.B1) + z.B1.Mul(&b3, &b4). + SubAssign(&b0). + SubAssign(&b1) + { // begin: inline b3.MulByNonResidue(&b2) + buf := (&b2).A0 + { // begin: inline MulByNonResidue(&(b3).A0, &(&b2).A1) + buf := *(&(&b2).A1) + (&(b3).A0).Double(&buf).Double(&(b3).A0).Neg(&(b3).A0) + } // end: inline MulByNonResidue(&(b3).A0, &(&b2).A1) + (b3).A1 = buf + } // end: inline b3.MulByNonResidue(&b2) + z.B1.AddAssign(&b3) + + // step 6 + b3.Add(&z.B0, &z.B2) + b4.Add(&x.B0, &x.B2) + z.B2.Mul(&b3, &b4). + SubAssign(&b0). + SubAssign(&b2). + AddAssign(&b1) + z.B0 = rb0 + return z +} + +// MulByE2 multiplies x by an elements of E2 +func (z *E6) MulByE2(x *E6, y *E2) *E6 { + var yCopy E2 yCopy.Set(y) z.B0.Mul(&x.B0, &yCopy) z.B1.Mul(&x.B1, &yCopy) @@ -193,9 +252,9 @@ func (z *e6) MulByE2(x *e6, y *e2) *e6 { } // MulByNotv2 multiplies x by y with &y.b2=0 -func (z *e6) MulByNotv2(x, y *e6) *e6 { +func (z *E6) MulByNotv2(x, y *E6) *E6 { // Algorithm 15 from https://eprint.iacr.org/2010/354.pdf - var rb0, b0, b1, b2, b3 e2 + var rb0, b0, b1, b2, b3 E2 b0.Mul(&x.B0, &y.B0) // step 1 b1.Mul(&x.B1, &y.B1) // step 2 // step 3 @@ -203,13 +262,12 @@ func (z *e6) MulByNotv2(x, y *e6) *e6 { rb0.Mul(&b2, &y.B1). SubAssign(&b1) { // begin: inline rb0.MulByNonResidue(&rb0) - var buf e2 - buf.Set(&rb0) - rb0.A1.Add(&buf.A0, &buf.A1) - { // begin: inline MulByNonResidue(&(rb0).A0, &buf.A1) - (&(rb0).A0).Neg(&buf.A1) - } // end: inline MulByNonResidue(&(rb0).A0, &buf.A1) - rb0.A0.AddAssign(&buf.A0) + buf := (&rb0).A0 + { // begin: inline MulByNonResidue(&(rb0).A0, &(&rb0).A1) + buf := *(&(&rb0).A1) + (&(rb0).A0).Double(&buf).Double(&(rb0).A0).Neg(&(rb0).A0) + } // end: inline MulByNonResidue(&(rb0).A0, &(&rb0).A1) + (rb0).A1 = buf } // end: inline rb0.MulByNonResidue(&rb0) rb0.AddAssign(&b0) // step 4 @@ -225,22 +283,22 @@ func (z *e6) MulByNotv2(x, y *e6) *e6 { return z } -// Square squares a e6 -func (z *e6) Square(x *e6) *e6 { +// Square sets z to the E6-product of x,x, returns z +func (z *E6) Square(x *E6) *E6 { + // Algorithm 16 from https://eprint.iacr.org/2010/354.pdf - var b0, b1, b2, b3, b4 e2 + var b0, b1, b2, b3, b4 E2 b3.Mul(&x.B0, &x.B1).Double(&b3) // step 1 b4.Square(&x.B2) // step 2 // step 3 { // begin: inline b0.MulByNonResidue(&b4) - var buf e2 - buf.Set(&b4) - b0.A1.Add(&buf.A0, &buf.A1) - { // begin: inline MulByNonResidue(&(b0).A0, &buf.A1) - (&(b0).A0).Neg(&buf.A1) - } // end: inline MulByNonResidue(&(b0).A0, &buf.A1) - b0.A0.AddAssign(&buf.A0) + buf := (&b4).A0 + { // begin: inline MulByNonResidue(&(b0).A0, &(&b4).A1) + buf := *(&(&b4).A1) + (&(b0).A0).Double(&buf).Double(&(b0).A0).Neg(&(b0).A0) + } // end: inline MulByNonResidue(&(b0).A0, &(&b4).A1) + (b0).A1 = buf } // end: inline b0.MulByNonResidue(&b4) b0.AddAssign(&b3) b1.Sub(&b3, &b4) // step 4 @@ -249,13 +307,53 @@ func (z *e6) Square(x *e6) *e6 { b4.Mul(&x.B1, &x.B2).Double(&b4) // step 7 // step 9 { // begin: inline z.B0.MulByNonResidue(&b4) - var buf e2 - buf.Set(&b4) - z.B0.A1.Add(&buf.A0, &buf.A1) - { // begin: inline MulByNonResidue(&(z.B0).A0, &buf.A1) - (&(z.B0).A0).Neg(&buf.A1) - } // end: inline MulByNonResidue(&(z.B0).A0, &buf.A1) - z.B0.A0.AddAssign(&buf.A0) + buf := (&b4).A0 + { // begin: inline MulByNonResidue(&(z.B0).A0, &(&b4).A1) + buf := *(&(&b4).A1) + (&(z.B0).A0).Double(&buf).Double(&(z.B0).A0).Neg(&(z.B0).A0) + } // end: inline MulByNonResidue(&(z.B0).A0, &(&b4).A1) + (z.B0).A1 = buf + } // end: inline z.B0.MulByNonResidue(&b4) + z.B0.AddAssign(&b2) + + // step 10 + z.B2.Add(&b1, &b3). + AddAssign(&b4). + SubAssign(&b2) + z.B1 = b0 + return z +} + +// SquareAssign sets z to the E6-product of z,z returns z +func (z *E6) SquareAssign() *E6 { + + // Algorithm 16 from https://eprint.iacr.org/2010/354.pdf + var b0, b1, b2, b3, b4 E2 + b3.Mul(&z.B0, &z.B1).Double(&b3) // step 1 + b4.Square(&z.B2) // step 2 + + // step 3 + { // begin: inline b0.MulByNonResidue(&b4) + buf := (&b4).A0 + { // begin: inline MulByNonResidue(&(b0).A0, &(&b4).A1) + buf := *(&(&b4).A1) + (&(b0).A0).Double(&buf).Double(&(b0).A0).Neg(&(b0).A0) + } // end: inline MulByNonResidue(&(b0).A0, &(&b4).A1) + (b0).A1 = buf + } // end: inline b0.MulByNonResidue(&b4) + b0.AddAssign(&b3) + b1.Sub(&b3, &b4) // step 4 + b2.Square(&z.B0) // step 5 + b3.Sub(&z.B0, &z.B1).AddAssign(&z.B2).Square(&b3) // steps 6 and 8 + b4.Mul(&z.B1, &z.B2).Double(&b4) // step 7 + // step 9 + { // begin: inline z.B0.MulByNonResidue(&b4) + buf := (&b4).A0 + { // begin: inline MulByNonResidue(&(z.B0).A0, &(&b4).A1) + buf := *(&(&b4).A1) + (&(z.B0).A0).Double(&buf).Double(&(z.B0).A0).Neg(&(z.B0).A0) + } // end: inline MulByNonResidue(&(z.B0).A0, &(&b4).A1) + (z.B0).A1 = buf } // end: inline z.B0.MulByNonResidue(&b4) z.B0.AddAssign(&b2) @@ -267,10 +365,10 @@ func (z *e6) Square(x *e6) *e6 { return z } -// SquarE2 squares a e6 -func (z *e6) SquarE2(x *e6) *e6 { +// SquarE2 squares a E6 +func (z *E6) SquarE2(x *E6) *E6 { // Karatsuba from Section 4 of https://eprint.iacr.org/2006/471.pdf - var v0, v1, v2, v01, v02, v12 e2 + var v0, v1, v2, v01, v02, v12 E2 v0.Square(&x.B0) v1.Square(&x.B1) v2.Square(&x.B2) @@ -282,70 +380,66 @@ func (z *e6) SquarE2(x *e6) *e6 { v12.Square(&v12) z.B0.Sub(&v12, &v1).SubAssign(&v2) { // begin: inline z.B0.MulByNonResidue(&z.B0) - var buf e2 - buf.Set(&z.B0) - z.B0.A1.Add(&buf.A0, &buf.A1) - { // begin: inline MulByNonResidue(&(z.B0).A0, &buf.A1) - (&(z.B0).A0).Neg(&buf.A1) - } // end: inline MulByNonResidue(&(z.B0).A0, &buf.A1) - z.B0.A0.AddAssign(&buf.A0) + buf := (&z.B0).A0 + { // begin: inline MulByNonResidue(&(z.B0).A0, &(&z.B0).A1) + buf := *(&(&z.B0).A1) + (&(z.B0).A0).Double(&buf).Double(&(z.B0).A0).Neg(&(z.B0).A0) + } // end: inline MulByNonResidue(&(z.B0).A0, &(&z.B0).A1) + (z.B0).A1 = buf } // end: inline z.B0.MulByNonResidue(&z.B0) z.B0.AddAssign(&v0) { // begin: inline z.B1.MulByNonResidue(&v2) - var buf e2 - buf.Set(&v2) - z.B1.A1.Add(&buf.A0, &buf.A1) - { // begin: inline MulByNonResidue(&(z.B1).A0, &buf.A1) - (&(z.B1).A0).Neg(&buf.A1) - } // end: inline MulByNonResidue(&(z.B1).A0, &buf.A1) - z.B1.A0.AddAssign(&buf.A0) + buf := (&v2).A0 + { // begin: inline MulByNonResidue(&(z.B1).A0, &(&v2).A1) + buf := *(&(&v2).A1) + (&(z.B1).A0).Double(&buf).Double(&(z.B1).A0).Neg(&(z.B1).A0) + } // end: inline MulByNonResidue(&(z.B1).A0, &(&v2).A1) + (z.B1).A1 = buf } // end: inline z.B1.MulByNonResidue(&v2) z.B1.AddAssign(&v01).SubAssign(&v0).SubAssign(&v1) z.B2.Add(&v02, &v1).SubAssign(&v0).SubAssign(&v2) return z } -// Square3 squares a e6 -func (z *e6) Square3(x *e6) *e6 { +// Square3 squares a E6 +func (z *E6) Square3(x *E6) *E6 { // CH-SQR2 from from Section 4 of https://eprint.iacr.org/2006/471.pdf - var s0, s1, s2, s3, s4 e2 + var s0, s1, s2, s3, s4 E2 s0.Square(&x.B0) s1.Mul(&x.B0, &x.B1).Double(&s1) s2.Sub(&x.B0, &x.B1).AddAssign(&x.B2).Square(&s2) s3.Mul(&x.B1, &x.B2).Double(&s3) s4.Square(&x.B2) { // begin: inline z.B0.MulByNonResidue(&s3) - var buf e2 - buf.Set(&s3) - z.B0.A1.Add(&buf.A0, &buf.A1) - { // begin: inline MulByNonResidue(&(z.B0).A0, &buf.A1) - (&(z.B0).A0).Neg(&buf.A1) - } // end: inline MulByNonResidue(&(z.B0).A0, &buf.A1) - z.B0.A0.AddAssign(&buf.A0) + buf := (&s3).A0 + { // begin: inline MulByNonResidue(&(z.B0).A0, &(&s3).A1) + buf := *(&(&s3).A1) + (&(z.B0).A0).Double(&buf).Double(&(z.B0).A0).Neg(&(z.B0).A0) + } // end: inline MulByNonResidue(&(z.B0).A0, &(&s3).A1) + (z.B0).A1 = buf } // end: inline z.B0.MulByNonResidue(&s3) z.B0.AddAssign(&s0) { // begin: inline z.B1.MulByNonResidue(&s4) - var buf e2 - buf.Set(&s4) - z.B1.A1.Add(&buf.A0, &buf.A1) - { // begin: inline MulByNonResidue(&(z.B1).A0, &buf.A1) - (&(z.B1).A0).Neg(&buf.A1) - } // end: inline MulByNonResidue(&(z.B1).A0, &buf.A1) - z.B1.A0.AddAssign(&buf.A0) + buf := (&s4).A0 + { // begin: inline MulByNonResidue(&(z.B1).A0, &(&s4).A1) + buf := *(&(&s4).A1) + (&(z.B1).A0).Double(&buf).Double(&(z.B1).A0).Neg(&(z.B1).A0) + } // end: inline MulByNonResidue(&(z.B1).A0, &(&s4).A1) + (z.B1).A1 = buf } // end: inline z.B1.MulByNonResidue(&s4) z.B1.AddAssign(&s1) z.B2.Add(&s1, &s2).AddAssign(&s3).SubAssign(&s0).SubAssign(&s4) return z } -// Inverse an element in e6 -func (z *e6) Inverse(x *e6) *e6 { +// Inverse an element in E6 +func (z *E6) Inverse(x *E6) *E6 { // Algorithm 17 from https://eprint.iacr.org/2010/354.pdf // step 9 is wrong in the paper! // memalloc - var t [7]e2 - var c [3]e2 - var buf e2 + var t [7]E2 + var c [3]E2 + var buf E2 t[0].Square(&x.B0) // step 1 t[1].Square(&x.B1) // step 2 t[2].Square(&x.B2) // step 3 @@ -354,24 +448,22 @@ func (z *e6) Inverse(x *e6) *e6 { t[5].Mul(&x.B1, &x.B2) // step 6 // step 7 { // begin: inline c[0].MulByNonResidue(&t[5]) - var buf e2 - buf.Set(&t[5]) - c[0].A1.Add(&buf.A0, &buf.A1) - { // begin: inline MulByNonResidue(&(c[0]).A0, &buf.A1) - (&(c[0]).A0).Neg(&buf.A1) - } // end: inline MulByNonResidue(&(c[0]).A0, &buf.A1) - c[0].A0.AddAssign(&buf.A0) + buf := (&t[5]).A0 + { // begin: inline MulByNonResidue(&(c[0]).A0, &(&t[5]).A1) + buf := *(&(&t[5]).A1) + (&(c[0]).A0).Double(&buf).Double(&(c[0]).A0).Neg(&(c[0]).A0) + } // end: inline MulByNonResidue(&(c[0]).A0, &(&t[5]).A1) + (c[0]).A1 = buf } // end: inline c[0].MulByNonResidue(&t[5]) c[0].Neg(&c[0]).AddAssign(&t[0]) // step 8 { // begin: inline c[1].MulByNonResidue(&t[2]) - var buf e2 - buf.Set(&t[2]) - c[1].A1.Add(&buf.A0, &buf.A1) - { // begin: inline MulByNonResidue(&(c[1]).A0, &buf.A1) - (&(c[1]).A0).Neg(&buf.A1) - } // end: inline MulByNonResidue(&(c[1]).A0, &buf.A1) - c[1].A0.AddAssign(&buf.A0) + buf := (&t[2]).A0 + { // begin: inline MulByNonResidue(&(c[1]).A0, &(&t[2]).A1) + buf := *(&(&t[2]).A1) + (&(c[1]).A0).Double(&buf).Double(&(c[1]).A0).Neg(&(c[1]).A0) + } // end: inline MulByNonResidue(&(c[1]).A0, &(&t[2]).A1) + (c[1]).A1 = buf } // end: inline c[1].MulByNonResidue(&t[2]) c[1].SubAssign(&t[3]) c[2].Sub(&t[1], &t[4]) // step 9 is wrong in 2010/354! @@ -380,13 +472,12 @@ func (z *e6) Inverse(x *e6) *e6 { buf.Mul(&x.B1, &c[2]) t[6].AddAssign(&buf) { // begin: inline t[6].MulByNonResidue(&t[6]) - var buf e2 - buf.Set(&t[6]) - t[6].A1.Add(&buf.A0, &buf.A1) - { // begin: inline MulByNonResidue(&(t[6]).A0, &buf.A1) - (&(t[6]).A0).Neg(&buf.A1) - } // end: inline MulByNonResidue(&(t[6]).A0, &buf.A1) - t[6].A0.AddAssign(&buf.A0) + buf := (&t[6]).A0 + { // begin: inline MulByNonResidue(&(t[6]).A0, &(&t[6]).A1) + buf := *(&(&t[6]).A1) + (&(t[6]).A0).Double(&buf).Double(&(t[6]).A0).Neg(&(t[6]).A0) + } // end: inline MulByNonResidue(&(t[6]).A0, &(&t[6]).A1) + (t[6]).A1 = buf } // end: inline t[6].MulByNonResidue(&t[6]) buf.Mul(&x.B0, &c[0]) t[6].AddAssign(&buf) @@ -398,34 +489,23 @@ func (z *e6) Inverse(x *e6) *e6 { return z } -// MulByNonResidue multiplies a e2 by (1,1) -func (z *e2) MulByNonResidue(x *e2) *e2 { - var buf e2 - buf.Set(x) - z.A1.Add(&buf.A0, &buf.A1) - { // begin: inline MulByNonResidue(&(z).A0, &buf.A1) - (&(z).A0).Neg(&buf.A1) - } // end: inline MulByNonResidue(&(z).A0, &buf.A1) - z.A0.AddAssign(&buf.A0) +// MulByNonResidue multiplies a E2 by (0,1) +func (z *E2) MulByNonResidue(x *E2) *E2 { + buf := (x).A0 + { // begin: inline MulByNonResidue(&(z).A0, &(x).A1) + buf := *(&(x).A1) + (&(z).A0).Double(&buf).Double(&(z).A0).Neg(&(z).A0) + } // end: inline MulByNonResidue(&(z).A0, &(x).A1) + (z).A1 = buf return z } -// MulByNonResidueInv multiplies a e2 by (1,1)^{-1} -func (z *e2) MulByNonResidueInv(x *e2) *e2 { - // (z).A0 = ((x).A0 + (x).A1)/2 - // (z).A1 = ((x).A1 - (x).A0)/2 - buf := *(x) - (z).A0.Add(&buf.A0, &buf.A1) - (z).A1.Sub(&buf.A1, &buf.A0) - twoInv := fp.Element{ - 1730508156817200468, - 9606178027640717313, - 7150789853162776431, - 7936136305760253186, - 15245073033536294050, - 1728177566264616342, - } - (z).A0.MulAssign(&twoInv) - (z).A1.MulAssign(&twoInv) +// MulByNonResidueInv multiplies a E2 by (0,1)^{-1} +func (z *E2) MulByNonResidueInv(x *E2) *E2 { + buf := (x).A1 + { // begin: inline MulByNonResidueInv(&(z).A1, &(x).A0) + // TODO not implemented + } // end: inline MulByNonResidueInv(&(z).A1, &(x).A0) + (z).A0 = buf return z } diff --git a/bw6_761/e6_test.go b/bw6_761/e6_test.go new file mode 100644 index 0000000000..7d466004b0 --- /dev/null +++ b/bw6_761/e6_test.go @@ -0,0 +1,219 @@ +// Code generated by internal/tower DO NOT EDIT +package bw6_761 + +import ( + "reflect" + "testing" +) + +type E6TestPoint struct { + in [2]E6 + out [10]E6 +} + +var E6TestPoints []E6TestPoint + +// TODO this method is the same everywhere. move it someplace central and call it "compare" +func E6compare(t *testing.T, got, want interface{}) { + if !reflect.DeepEqual(got, want) { + t.Fatal("\nexpect:\t", want, "\ngot:\t", got) + } +} + +func E6check(t *testing.T, f func(*E6, *E6, *E6) *E6, m int) { + + if len(E6TestPoints) < 1 { + t.Log("no tests to run") + } + + for i := range E6TestPoints { + var receiver E6 + var out *E6 + var inCopies [len(E6TestPoints[i].in)]E6 + + for j := range inCopies { + inCopies[j].Set(&E6TestPoints[i].in[j]) + } + + // receiver, return value both set to result + out = f(&receiver, &inCopies[0], &inCopies[1]) + + E6compare(t, receiver, E6TestPoints[i].out[m]) // receiver correct + E6compare(t, *out, E6TestPoints[i].out[m]) // return value correct + for j := range inCopies { + E6compare(t, inCopies[j], E6TestPoints[i].in[j]) // inputs unchanged + } + + // receiver == one of the inputs + for j := range inCopies { + out = f(&inCopies[j], &inCopies[0], &inCopies[1]) + + E6compare(t, inCopies[j], E6TestPoints[i].out[m]) // receiver correct + E6compare(t, *out, E6TestPoints[i].out[m]) // return value correct + for k := range inCopies { + if k == j { + continue + } + E6compare(t, inCopies[k], E6TestPoints[i].in[k]) // other inputs unchanged + } + inCopies[j].Set(&E6TestPoints[i].in[j]) // reset input for next tests + } + } +} + +//--------------------// +// tests // +//--------------------// + +func TestE6Add(t *testing.T) { + E6check(t, (*E6).Add, 0) +} + +func TestE6Sub(t *testing.T) { + E6check(t, (*E6).Sub, 1) +} + +func TestE6Mul(t *testing.T) { + E6check(t, (*E6).Mul, 2) +} + +func TestE6Square(t *testing.T) { + E6check(t, (*E6).SquareBinary, 3) +} + +func TestE6Inverse(t *testing.T) { + E6check(t, (*E6).InverseBinary, 4) +} + +func TestE6Frobenius(t *testing.T) { + E6check(t, (*E6).FrobeniusBinary, 5) +} + +func TestE6FrobeniusSquare(t *testing.T) { + E6check(t, (*E6).FrobeniusSquareBinary, 6) +} + +func TestE6FrobeniusCube(t *testing.T) { + E6check(t, (*E6).FrobeniusCubeBinary, 7) +} + +func TestE6Expt(t *testing.T) { + E6check(t, (*E6).ExptBinary, 8) +} + +func TestE6FinalExponentiation(t *testing.T) { + E6check(t, (*E6).FinalExponentiationBinary, 9) +} + +//--------------------// +// benches // +//--------------------// + +var E6BenchIn1, E6BenchIn2, E6BenchOut E6 + +func BenchmarkE6Add(b *testing.B) { + for i := 0; i < b.N; i++ { + E6BenchOut.Add(&E6BenchIn1, &E6BenchIn2) + } +} + +func BenchmarkE6Sub(b *testing.B) { + for i := 0; i < b.N; i++ { + E6BenchOut.Sub(&E6BenchIn1, &E6BenchIn2) + } +} + +func BenchmarkE6Mul(b *testing.B) { + for i := 0; i < b.N; i++ { + E6BenchOut.Mul(&E6BenchIn1, &E6BenchIn2) + } +} + +func BenchmarkE6Square(b *testing.B) { + for i := 0; i < b.N; i++ { + E6BenchOut.SquareBinary(&E6BenchIn1, &E6BenchIn2) + } +} + +func BenchmarkE6Inverse(b *testing.B) { + for i := 0; i < b.N; i++ { + E6BenchOut.InverseBinary(&E6BenchIn1, &E6BenchIn2) + } +} + +func BenchmarkE6Frobenius(b *testing.B) { + for i := 0; i < b.N; i++ { + E6BenchOut.FrobeniusBinary(&E6BenchIn1, &E6BenchIn2) + } +} + +func BenchmarkE6FrobeniusSquare(b *testing.B) { + for i := 0; i < b.N; i++ { + E6BenchOut.FrobeniusSquareBinary(&E6BenchIn1, &E6BenchIn2) + } +} + +func BenchmarkE6FrobeniusCube(b *testing.B) { + for i := 0; i < b.N; i++ { + E6BenchOut.FrobeniusCubeBinary(&E6BenchIn1, &E6BenchIn2) + } +} + +func BenchmarkE6Expt(b *testing.B) { + for i := 0; i < b.N; i++ { + E6BenchOut.ExptBinary(&E6BenchIn1, &E6BenchIn2) + } +} + +func BenchmarkE6FinalExponentiation(b *testing.B) { + for i := 0; i < b.N; i++ { + E6BenchOut.FinalExponentiationBinary(&E6BenchIn1, &E6BenchIn2) + } +} + +//-------------------------------------// +// unary helpers for E6 methods +//-------------------------------------// + +// SquareBinary a binary wrapper for Square +func (z *E6) SquareBinary(x, y *E6) *E6 { + return z.Square(x) +} + +// InverseBinary a binary wrapper for Inverse +func (z *E6) InverseBinary(x, y *E6) *E6 { + return z.Inverse(x) +} + +// FrobeniusBinary a binary wrapper for Frobenius +func (z *E6) FrobeniusBinary(x, y *E6) *E6 { + return z.Frobenius(x) +} + +// FrobeniusSquareBinary a binary wrapper for FrobeniusSquare +func (z *E6) FrobeniusSquareBinary(x, y *E6) *E6 { + return z.FrobeniusSquare(x) +} + +// FrobeniusCubeBinary a binary wrapper for FrobeniusCube +func (z *E6) FrobeniusCubeBinary(x, y *E6) *E6 { + return z.FrobeniusCube(x) +} + +// FinalExponentiationBinary a binary wrapper for FinalExponentiation +func (z *E6) FinalExponentiationBinary(x, y *E6) *E6 { + return z.FinalExponentiation(x) +} + +//-------------------------------------// +// custom helpers for E6 methods +//-------------------------------------// + +// ExptBinary a binary wrapper for Expt +func (z *E6) ExptBinary(x, y *E6) *E6 { + z.Expt(x) + + // if tAbsVal is negative then need to undo the conjugation in order to match the test point + + return z +} diff --git a/bw6_761/e6testpoints_test.go b/bw6_761/e6testpoints_test.go new file mode 100644 index 0000000000..713c83029b --- /dev/null +++ b/bw6_761/e6testpoints_test.go @@ -0,0 +1,142 @@ +// Code generated by internal/tower DO NOT EDIT +package bw6_761 + +func init() { + + E6TestPoints = make([]E6TestPoint, 10) + + E6TestPoints[0].in[0].SetString("0", "0", "0", "0", "0", "0") + E6TestPoints[0].in[1].SetString("0", "0", "0", "0", "0", "0") + E6TestPoints[0].out[0].SetString("0", "0", "0", "0", "0", "0") + E6TestPoints[0].out[1].SetString("0", "0", "0", "0", "0", "0") + E6TestPoints[0].out[2].SetString("0", "0", "0", "0", "0", "0") + E6TestPoints[0].out[3].SetString("0", "0", "0", "0", "0", "0") + E6TestPoints[0].out[4].SetString("0", "0", "0", "0", "0", "0") + E6TestPoints[0].out[5].SetString("0", "0", "0", "0", "0", "0") + E6TestPoints[0].out[6].SetString("0", "0", "0", "0", "0", "0") + E6TestPoints[0].out[7].SetString("0", "0", "0", "0", "0", "0") + E6TestPoints[0].out[8].SetString("0", "0", "0", "0", "0", "0") + E6TestPoints[0].out[9].SetString("0", "0", "0", "0", "0", "0") + + E6TestPoints[1].in[0].SetString("1", "0", "1", "0", "1", "0") + E6TestPoints[1].in[1].SetString("1", "0", "1", "0", "1", "0") + E6TestPoints[1].out[0].SetString("2", "0", "2", "0", "2", "0") + E6TestPoints[1].out[1].SetString("0", "0", "0", "0", "0", "0") + E6TestPoints[1].out[2].SetString("1", "2", "2", "1", "3", "0") + E6TestPoints[1].out[3].SetString("1", "2", "2", "1", "3", "0") + E6TestPoints[1].out[4].SetString("1378290076863146507879357936455131508495933782507230021902758032041924684448698347217536636657882337528172913550757322690232351824110849551869902339825060319790321019875701770074508726284719359190379940085993822568552982623813660", "1378290076863146507879357936455131508495933782507230021902758032041924684448698347217536636657882337528172913550757322690232351824110849551869902339825060319790321019875701770074508726284719359190379940085993822568552982623813660", "5513160307452586031517431745820526033983735130028920087611032128167698737794793388870146546631529350112691654203029290760929407296443398207479609359300241279161284079502807080298034905138877436761519760343975290274211930495254639", "5513160307452586031517431745820526033983735130028920087611032128167698737794793388870146546631529350112691654203029290760929407296443398207479609359300241279161284079502807080298034905138877436761519760343975290274211930495254639", "0", "0") + E6TestPoints[1].out[5].SetString("1", "0", "4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775649", "0", "4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775648", "0") + E6TestPoints[1].out[6].SetString("1", "0", "4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775648", "0", "1968985824090209297278610739700577151397666382303825728450741611566800370218827257750865013421937292370006175842381275743914023380727582819905021229583192207421122272650305267822868639090213645505120388400344940985710520836292650", "0") + E6TestPoints[1].out[7].SetString("1", "0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "0", "1", "0") + E6TestPoints[1].out[8].SetString("3518224528658710461798054352125612860403225210543288443001472005345635923543242990026980758783571024547607922488101647747810584304211541283468328862950404130386905464959224164507946846276918963658239123303299662954422321897730557", "1254100823447488850243401134076191822493954568336507788808506878792894273478052231001483340071386249860963173245031372817036511106628347722484812006861086753013731621555010443227589565863202844739291843520559316432888423994270630", "5894392356633282423901546028371981970811333458760572205582167821552712019979654497663675629976018392723005349107669563432348709775567578176861207395659781764107691808300508406579088530842087408408796970769787529279934385255079332", "1244850422483782248987559714402142854262803572339787553100832493303343584781608480922083598217506298913866674725858967230836624326901380301652533083247729750109875746753989583101152144847998203021465093072869644094897933352788674", "841336007033423934730095179867645260068528996633232572552534691205484991403089105052912298341122755563203629585940391547683406816445675382158058873160455603228808871173752337934073787029583055940615629977608652536414350685736279", "3038972570481496156449318093691883565710240805689714418984709148683788658869294003448266539960682937855256424871741915462740981223791138666747710735478355846220098192647429366898544109877493994322531897650196046310617694625477601") + E6TestPoints[1].out[9].SetString("409993644243850380127482972054372034024311065359736660405652346249772415361658787609021733867598476771509612185319232928688474020129345547501412928494218299675564336495900718287852857757398815381127771651518135787076424966605755", "1309157818541559674730757149733942640631198508430134718579503589747717890076598239445203133204334670768519026995140102411523674236855936683869358338168754363293986485323030576568270264943736506512891844786651955523614122058650968", "3092759343880762581689679501495600618980053952673805678831819572879344936365462684823500745647469129541694746127125661688271106358586344532952216385500863793639736671101370604088907040140831388841391933873727853660332804873882187", "6212393674513193094809670108346419566314945394118598519534532498138432630634384371776272292600442527616669028379914219115928985791347472707937766737870317624771160682382477762844438769089461088150794119052407452050749040882759202", "6354876249486134212866668354515369532958492292704626240826484674149034343397403761005516351381243365809104953573911079160692945362689303862302989528466702622551536313319511633479971454405145037042243356322168460281592443498907227", "5977103293253114264437614936878171609611969842669908190858064050816175994545215538895367392918048097394899193541616985142333227554790277654752159893012668314367931978750854692859082309297558725431265533823303098987441449395269712") + + E6TestPoints[2].in[0].SetString("0", "1", "1", "0", "0", "1") + E6TestPoints[2].in[1].SetString("1", "0", "0", "1", "1", "0") + E6TestPoints[2].out[0].SetString("1", "1", "1", "1", "1", "1") + E6TestPoints[2].out[1].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "1", "1", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "1") + E6TestPoints[2].out[2].SetString("0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068297", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068292", "0", "0", "3") + E6TestPoints[2].out[3].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068287", "0", "0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068297", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068292", "0") + E6TestPoints[2].out[4].SetString("0", "0", "5513160307452586031517431745820526033983735130028920087611032128167698737794793388870146546631529350112691654203029290760929407296443398207479609359300241279161284079502807080298034905138877436761519760343975290274211930495254639", "0", "0", "6546877865099945912426950198161874665355685466909342604038100652199142251131317149283299024124941103258821339366097282778603671164526535371382036114169036519004024844409583407853916449852416956154304715408470657200626667463114884") + E6TestPoints[2].out[5].SetString("0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775649", "0", "0", "1968985824090209297278610739700577151397666382303825728450741611566800370218827257750865013421937292370006175842381275743914023380727582819905021229583192207421122272650305267822868639090213645505120388400344940985710520836292651") + E6TestPoints[2].out[6].SetString("0", "1", "4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775648", "0", "0", "1968985824090209297278610739700577151397666382303825728450741611566800370218827257750865013421937292370006175842381275743914023380727582819905021229583192207421122272650305267822868639090213645505120388400344940985710520836292650") + E6TestPoints[2].out[7].SetString("0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "0", "0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298") + E6TestPoints[2].out[8].SetString("0", "6746737339692871666268951118392904401003943566133502161773001219631715083017751804618602709821252300340212203548312809298875091403192298277249043131752085661482405911391426898771542707057776717388464174352805143260045478178808588", "5517162267322361400872669188573567040498231671951371416868087172689207193063637674837702830186148413728275092116414021255373578195812126864588025854540413206690878798715570107409109353878378801147075655161328722739783798731955300", "0", "0", "1086297694282053754863160041403457516457538698547649428635067612000737988755587283396446966670073090902367493081881045196828276671545730271421593582221871062906410188812003698282303396509279560784500248108843886599750664688900156") + E6TestPoints[2].out[9].SetString("1", "0", "0", "0", "0", "0") + + E6TestPoints[3].in[0].SetString("1", "1", "1", "0", "1", "1") + E6TestPoints[3].in[1].SetString("1", "0", "1", "1", "1", "0") + E6TestPoints[3].out[0].SetString("2", "1", "2", "1", "2", "1") + E6TestPoints[3].out[1].SetString("0", "1", "0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "0", "1") + E6TestPoints[3].out[2].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068292", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068293", "3", "3", "3") + E6TestPoints[3].out[3].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068288", "4", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068293", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068294", "4") + E6TestPoints[3].out[4].SetString("3659052891952608054038957884805724921917867519420467981713818775510026805593741854269231020121053237463327836738571032466807925097384726708403664300885892619672648414548996801064046096276885534462104197629568313672438746226786837", "6661442740915640574387622943835374449979073593417109175922374488620461468532944623367304457936312851696672654791813098454447825249269507260884598060250036755776405031093519128232721156081815603526498716797784156465082823025157994", "3299117266784525208032246576559480387852050416982274154337939289435384053603954387798409350675364219382722171416398738006301387359878071729889868148447501071192373498530501434356690314253487485246782047670805595676829368598911932", "4809091108953067879084791577007140384420844115015672649670897133455836574146477417871124646886547417184287401548438607450377594453808429200728232495262216835548648755973945411763158472985791496589109115790493095560849196696338362", "5616751536159497679880338902827981777934384930242839286709455980257473968855268806049553758813459360194426943246971560873953240108701411103734799471465436895553168079722764283399176325330977363121051501063814316429045848934496685", "6819463259282115970195447420626408635666505492048511344038614262994694871845534242793518849400273884024743434689352154559060451573052916763646752468637623289255550116174809777031072475018917186108835270438216569243643037593493318") + E6TestPoints[3].out[5].SetString("1", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775649", "0", "4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775648", "1968985824090209297278610739700577151397666382303825728450741611566800370218827257750865013421937292370006175842381275743914023380727582819905021229583192207421122272650305267822868639090213645505120388400344940985710520836292651") + E6TestPoints[3].out[6].SetString("1", "1", "4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775648", "0", "1968985824090209297278610739700577151397666382303825728450741611566800370218827257750865013421937292370006175842381275743914023380727582819905021229583192207421122272650305267822868639090213645505120388400344940985710520836292650", "1968985824090209297278610739700577151397666382303825728450741611566800370218827257750865013421937292370006175842381275743914023380727582819905021229583192207421122272650305267822868639090213645505120388400344940985710520836292650") + E6TestPoints[3].out[7].SetString("1", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "0", "1", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298") + E6TestPoints[3].out[8].SetString("330242444563401734904511216951857988257930814327233778812017719726022632121317052575486155602012302494501474488691727105879294345358545731102209015977800725570849279653071869468764895650720833863185361062552653216557657976737600", "1067310022372053548138246262292638524302751762906928008059115667328806548228900824973325741045116788928514286756398424059406906457682003956552663881286714093859726489576015540948028190325684431004543408428145762610426982223431309", "6467732429505686702880431915008357612129454357020679953857099692540558723334667526214617166899351713447941717453134466732498467200062209817355799611485439693074075136453403920518569611673877055022924476937664169981967896319432966", "2240455008150592117070815705276193770264226736640808484728980635342419097508857256465254135998162678504018374847577172306798303981997879979047702693335430737246599344785652392581401093787401541012364089979041436237581924174478238", "5681379510337469491325506770677672730550930745493537357657613651764689853242971618129388171730864188662337084264955586212654545870147730619873000278585340055628931966989077500683438207648419001872542394153663050307608863504480659", "368381086992242513784412154074803537858730761071768849583982100756240152884886257668890206477636880471442895502139242298910259952995026239486667555526420162354404962905316080891263847725293961570144329747487022426434264573759807") + E6TestPoints[3].out[9].SetString("4508254278978857686945563800249822284246059252366978266571097862932950963849819614427868939678811082716241623635939644811497383600242100809664437956807471864433432526332024544671180067293859192478783690138701520618001900639439053", "620182239982734440319544444106375397064026354763616844307075570737988682908557143001002902363453459085782804396413209481623481411081919105040808116605409317604098320614452608816960866821514897413855433187499109879663152515101147", "216216756587853418087563297011309857096778778465070106197205172100799183344291713127520172719437720794698173356151630672483857462713193987876838631420233110546384855040477114818558360002388802589184064632296844269629452124104649", "658057570744724911415106201896007207233144973838150675666657101942839403302646603910742032441873603499300119561545283086648025944743195039518332315747687755957781176556173939743641051772508292377498613416935454073823866995020747", "5915905172332382541222981289586750451575399925656873001324622228863040411957112382262362627639410601763169499137458763326142244982441142620230523098131683822397713716486950816326494248905320796975916383227188182862627987829088231", "2302524323839488034932979661022552842445044227545501590075187889361995521840884366798863772661066440101136052964819316705562118954346808335077945665268310961458927270930567739667439862919017692613429774668597995290768432110587192") + + E6TestPoints[4].in[0].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "0", "1", "0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "0") + E6TestPoints[4].in[1].SetString("1", "0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "0", "1", "0") + E6TestPoints[4].out[0].SetString("0", "0", "0", "0", "0", "0") + E6TestPoints[4].out[1].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068297", "0", "2", "0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068297", "0") + E6TestPoints[4].out[2].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "2", "2", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068296", "0") + E6TestPoints[4].out[3].SetString("1", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068297", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068297", "1", "3", "0") + E6TestPoints[4].out[4].SetString("5513160307452586031517431745820526033983735130028920087611032128167698737794793388870146546631529350112691654203029290760929407296443398207479609359300241279161284079502807080298034905138877436761519760343975290274211930495254639", "1378290076863146507879357936455131508495933782507230021902758032041924684448698347217536636657882337528172913550757322690232351824110849551869902339825060319790321019875701770074508726284719359190379940085993822568552982623813660", "5513160307452586031517431745820526033983735130028920087611032128167698737794793388870146546631529350112691654203029290760929407296443398207479609359300241279161284079502807080298034905138877436761519760343975290274211930495254639", "1378290076863146507879357936455131508495933782507230021902758032041924684448698347217536636657882337528172913550757322690232351824110849551869902339825060319790321019875701770074508726284719359190379940085993822568552982623813660", "0", "0") + E6TestPoints[4].out[5].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "0", "4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775649", "0", "1968985824090209297278610739700577151397666382303825728450741611566800370218827257750865013421937292370006175842381275743914023380727582819905021229583192207421122272650305267822868639090213645505120388400344940985710520836292651", "0") + E6TestPoints[4].out[6].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "0", "4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775648", "0", "4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775649", "0") + E6TestPoints[4].out[7].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "0") + E6TestPoints[4].out[8].SetString("3373225855657022077598735330150044682076443701992861666512318154863987498700248746060702424505840663093256645265684965703351174816342706475881182836174897468564699634419284685864596785146677832293660577126669449888342591221337742", "1254100823447488850243401134076191822493954568336507788808506878792894273478052231001483340071386249860963173245031372817036511106628347722484812006861086753013731621555010443227589565863202844739291843520559316432888423994270630", "5894392356633282423901546028371981970811333458760572205582167821552712019979654497663675629976018392723005349107669563432348709775567578176861207395659781764107691808300508406579088530842087408408796970769787529279934385255079332", "5646599961831950290409229967873514688216865340196362556412957666906279837461883255165599585071905388726997893027927646220325134793652867457696978615877571848841729352624519267271391486575598592930434607357099468747866979766279625", "6050114377282308604666694502408012282411139915902917536961255469004138430840402631034770884948288932077660938167846221903478352304108572377191452825964845995722796228204756512438469844394013740011284070452360460306350562433332020", "3038972570481496156449318093691883565710240805689714418984709148683788658869294003448266539960682937855256424871741915462740981223791138666747710735478355846220098192647429366898544109877493994322531897650196046310617694625477601") + E6TestPoints[4].out[9].SetString("409993644243850380127482972054372034024311065359736660405652346249772415361658787609021733867598476771509612185319232928688474020129345547501412928494218299675564336495900718287852857757398815381127771651518135787076424966605755", "5582292565774172864666032532541714901848470404106015390934286570461905532166893496642480050085077016872345540758646511039638084883698311075480153360956547235657618614055478273804273366479860289439007855643317157319150791060417331", "3798691040434969957707110180780056923499614959862344430681970587330278485878029051264182437641942558099169821626660951762890652761967903226397295313624437805311868428277138246283636591282765407110507766556241259182432108245186112", "6212393674513193094809670108346419566314945394118598519534532498138432630634384371776272292600442527616669028379914219115928985791347472707937766737870317624771160682382477762844438769089461088150794119052407452050749040882759202", "6354876249486134212866668354515369532958492292704626240826484674149034343397403761005516351381243365809104953573911079160692945362689303862302989528466702622551536313319511633479971454405145037042243356322168460281592443498907227", "914347091062618274959174745397485932867699069866241918655726109393447427698276197192315790371363590245965374212169628308828531565763970104597351806112633284583673120627654157513461322126038070520634166606666013855323463723798587") + + E6TestPoints[5].in[0].SetString("0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "1", "0", "0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298") + E6TestPoints[5].in[1].SetString("1", "0", "0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "1", "0") + E6TestPoints[5].out[0].SetString("1", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "1", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "1", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298") + E6TestPoints[5].out[1].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "1", "1", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298") + E6TestPoints[5].out[2].SetString("0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068295", "1", "0", "0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068296") + E6TestPoints[5].out[3].SetString("4", "0", "0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068293", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068292", "0") + E6TestPoints[5].out[4].SetString("0", "2", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068296", "0", "0", "5168587788236799404547592261706743156859751684402112582135342620157217566682618802065762387467058765730648425815339960088371319340415685819512133774343976199213703824533881637779407723567697596963924775322476834632073684839301223") + E6TestPoints[5].out[5].SetString("0", "1", "4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775649", "0", "0", "4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775648") + E6TestPoints[5].out[6].SetString("0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775648", "0", "0", "4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775649") + E6TestPoints[5].out[7].SetString("0", "1", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "0", "0", "1") + E6TestPoints[5].out[8].SetString("0", "2582102583837051582618679488056047624216333087577610848216291644507744556131374953155508262805686542284626644748366143526303538899277801959365648181521030595376043419122035875311754494527444698462466242090448280290758565055446897", "88824697019766060294342845264565063023867875555964087029790405408980538597476441623008619344637218870243764643801042223919442853123838121993123408019822324027091224526163937754374262968004813065814185807887834131721163710572379", "0", "0", "2675311372276464982835224096061214509936071645826171026180746163884475329302810162235056198526900650357876383129092924633981120991921600546353505246537319755089811034151171161629241425340795322386874506841888338613017586052929332") + E6TestPoints[5].out[9].SetString("1", "0", "0", "0", "0", "0") + + E6TestPoints[6].in[0].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "1", "0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298") + E6TestPoints[6].in[1].SetString("1", "0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "1", "0") + E6TestPoints[6].out[0].SetString("0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298") + E6TestPoints[6].out[1].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068297", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "2", "1", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068297", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298") + E6TestPoints[6].out[2].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068290", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068296", "2", "1", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068296", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068296") + E6TestPoints[6].out[3].SetString("5", "0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068289", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068294", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068294", "4") + E6TestPoints[6].out[4].SetString("4801624274992550108677185590899645868947928159276090148505998198268798990949436480378782867779265183085512135655165402151892489206739963240268793349932069345117905358050729993219858920089365276601865134234599417973478802281516902", "671729820853880067017015600799432323635202384976447844609647416338122138630232046477860815699689947892791853174556817917622265329440305738275945183669253224446546345426786061227648657214574416933939681991368830493699107054927235", "6791934855300342899838713296972037938978157448095194873275323876307679401705679581053926025407976139804895404320518936722625127219896424687012334634878004824959524159315281285746225311836252437887612340134951508325179860222042042", "2985465870461689186742291559108588105045343933228657087153988517058320616134364651012714736443066435079074902998030301856098957019734692170115311927418903219762428201896826938789549587620330741928620808850528135527551586910787711", "323425469300016328563748252236763711379912259433104517775015422681318066747889503859710763114665530466899781158119949367744053677137924985095825458803714515474263055205489585035534538658869163708933920958807214682151421915335335", "4080136689630975221881131797448403743561970042079164685777117639979704842050298356384043473138857461274735700763974745870001907926970745965824259634139167733675318542592330149679051103081118680635781772095721785220987168778076538") + E6TestPoints[6].out[5].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "1", "4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775649", "0", "1968985824090209297278610739700577151397666382303825728450741611566800370218827257750865013421937292370006175842381275743914023380727582819905021229583192207421122272650305267822868639090213645505120388400344940985710520836292651", "4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775648") + E6TestPoints[6].out[6].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775648", "0", "4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775649", "4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775649") + E6TestPoints[6].out[7].SetString("6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "1", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "0", "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298", "1") + E6TestPoints[6].out[8].SetString("4171022179954050731414914777308129274147291745114287008052711994906815964934725487437023790723262373651861723430791034658185443770822193748817894348916407560340846217949198569971970055555737094831053513639280957047462068861169464", "4917657824132048737225639637880293883054625702231470741041277690406785310850081403995616098882089350887935955322097073608567369838629987644462867631877353465450647209275028295287672616868668359065475137878234930804229708640135739", "2254927436100730630907604814352172991985020255147171677009289726302707209005337432704623125119518320502512307816227493598705553646637394314865414482155265427539247410654919926029951434224459689074047970210736276886203219125296103", "5212768307385084377526772493463692317790869305768171064266964575323871188796589487894694395199138041641312672250217746558051363567757595236237425241594211518918643005974643011710911316790329880974151240299250095598656158165681107", "1070452172757709957808848537647690471769640224878791697333939420864892579444261625931862862914040939430593606588337768950768919964904480848314410122870993694798474928400375094834988252596275293816801967052323639762570943313624650", "4474846701154287056064756231584618194694557657924229267545475566945545003276735827062766105036065778739623411923740378263465133828301333614832926314980734128751384270672126631725644267942951472288521293787637333343829451064958445") + E6TestPoints[6].out[9].SetString("430156402467974585180265081057775812751959796280156024273713850773549841937518021992200307416308050966476945664285030668436815020667039424285138000828143517747380692640660830852181724534702851708456546377602161285504027270228019", "1021768336404751899421691921290406416127684123619969482835960076132777590945757507364387956427641809117298200291876596345355970646794106900155810937032019279558436386768428680792807401101886255501420037501912071927223879411262066", "3494733951156623514196131614468663429004074389927811189010213115011887334713793968208827349991039192348546907813103786901804328595804618575067978519361471829220508764472392660949930376095267948871404289313742135119145684738497884", "6412900076516901744194742292894606288147432466678163712426263778922175940703739989697863894974564881170478044764336493343274182291856290209232276268560738491662470366288585988532572135498383094791126259231746484436260520035024194", "766735755449295010223866314325987118838777539707163163149191258156518699797854881545761908002696302705746309197130324786636624593961592781014808409565575417224847314775624498578382867555665861925357169480127085915249156637986566", "5374052881500508106234933850690495696980556176002229448915421933665774960210464118519175817880138024604317714575501906617854404395499562054737635249863104546991328208958365779704747396377119056558004999568833706180779502489896098") + + E6TestPoints[7].in[0].SetString("6425522494491572315991300805865898504143443599906677141458211804232061862991840406915511172778276913286745870821128181817904122018546949149371168292903110810731444066400496724054029931175222518192723582172466207323211441401880085", "6416003737322694212178268125126546492607601681157255988306866619114417121959935111611254541190013970335135616768030547356690662835050009937806514587416857088724648831140348909613351822310248717616923922514568389476271821145610487", "2088658774711260487790844378424248717100789709936011859626785314973946089954282170988258604251668795788844891546187320978669651852631657564730850926678569505083650677171229565781756388033146877635174949638537973649596321949183478", "6772253663683578844260801199408873307993319026060438930078788539855621792335282451703328220223565983059125605144607166247379925942138149128716466058708598339604234852829271478345301024909623481167138825820522997540855950579410198", "1554493478850369830895349504525346388528667850780445040860317310845525153144168601593767921898005858229073725270868707979853228148024579143638520111877145569836337287144974044290353948919523078307621432414273808142411809483846540", "3207330411680060796244795665281819966230190587445964995767640155240704771173451521217874801755988859757634548609498995733789450147403319645901283237218644012247647271361771885793285412835907448380415538089969980743423394284065565") + E6TestPoints[7].in[1].SetString("1532740464095164769979825729487839139176327941695294581726527339602613788201880024392864805394358376374500510077126905862756076746438610565234242563140805931730448047468327526521395102271797818849429129873663319528383626241855829", "6433006445369229057655095593791510134826788432595011178057543538708313550770678322567063037949788084739696893266874401495154272660189515397514719567461063905663479793076474212956010385012225149761131341319191084194701714879385414", "5828685090715787262022246197330420519892365120537359578976798238063887316599791195779133736317014585736794927789676004919998493110413323600617162878830048493713128730777036772137079445977567809192462470694688860403572253456147082", "4190662364229312333526653602068311373325194060758272912230164041946721556748864468685681313837834446976330662920644193644652372608660990188416258116540272138190832938783514403748464734113086868198443933142426358310830068235442142", "4507736114993811280254534830304525061781281493074363331917895808531797195721889293312797634932579317099069996323395134482932435487506091105578805134789419717306105888874545544190771470528580107507086946211170564862238937797668913", "5350494694209144274510070455614023689300436599427541446486933855648386689361927030420638725240691987590324443830822357174560546717844633316165739510302465315742307088507217586939376770237140245801227294856341874312556537131688900") + E6TestPoints[7].out[0].SetString("1066812574271004546574336853078080100840102629065821613670948983625052228950228695220692794883223602020381813144468474229498439644431311955255899156918615143510287014490315400202881402023423541090253011616160414008830154524667615", "5957559798376190730436574036642399084954721201216117056850619997613107250487121698090634395850390367433967942281118335400683176374685277575971722455752619395436523524838314272196818575898877071426155563403790360828208622905927602", "1025893481111315210416300893479011694513485917937221329089793392828209984310581630679709157279271693884775251582076712447506385842490733405998502106383316399845174308569757487546292202587117890875737719903257721210403662286262261", "4071465643597158638390665119201527138838844174282561732795162421592719926840655184301326350771988742394591700311464746440870539430244891557783212476123568878843462692234277031721222127599113553413683058532980243008921105695784041", "6062229593844181111149884334829871450309949343854808372778213119377322348866057894906565556830585175328143721594263842462785663635530670249217325246666565287142443176019519588481125419448103185814708378625444373004650747281515453", "1666374721573472531358076438620186113050958274337356332740783850679468038291886815550830343707269159707094424686534739457188237744693705202717511048395807729038349260490480622360118551649450898229743132516342742213215018296686166") + E6TestPoints[7].out[1].SetString("4892782030396407546011475076378059364967115658211382559731684464629448074789960382522646367383918536912245360744001275955148045272108338584136925729762304879000996018932169197532634828903424699343294452298802887794827815160024256", "6874447676269197693919962213610693900260482161098394919763113240615726993432748525131874686529637573236303291254942759312698149295414742299641306719081094782012774137442383547029885068721620363807692281625346418124335019385293372", "3151424068311205765165387863369485739688093501934802390163777237119682195597982711296808051224065897692914531510297929509832917862772581723463199746973822610322127045772701644017220573479175864394612179373818226088788981612104695", "2581591299454266510734147597340561934668124965302166017848624497908900235586417983017646906385731536082794942223962972602727553333477158940300207942168326201413401914045757074596836290796536612968694892678096639230025882343968056", "3938207748172291090037604356496478869227055270242231818456211662523351379665771044368653470254838228770868296701260186948082551781072735797409226676213027451481836497648937350472126109814539766752434186633072356122937784805245926", "4748286101786649061131514891943453819409422900554573658794496459801941504055016226884919259804708559808174672532463252010390662550112934089085055426041480295456945282233063149226452274022363998531087943663597219273631770271444964") + E6TestPoints[7].out[2].SetString("6374813773784723784341343389419495928505768283084025601441883446133432788999306490932336895806969762946047749680129540008399588970728227908865338857204474529094431871376405927248512737657506580366706683750607153960684342579936884", "771233197977228480965383448744519585068769744867512920246598619399807213509376416151358401193172159053492665473096596024613611312825124941207887878866473873797643645311965836083103680249032671845400926421140120461354953060390422", "5587676372787099554694932607721621793962781138803584929556408475876770935727724476841167446726049513836483810623153051706254956788762193848630914073605657898842154420370685307586298308312372915896109048177546724262979497171273161", "4641223455293315575102681926725285864064084191344147691748403386132392606977130115212953573852155288191390776873187167872397352464356452439118133444591870018456590436180339908328476239224662549646257129646955588131621603073059851", "3299743690967329233282638148000804360760498160533362413831836666701534857762034520299368833396053545334263892757517900279512095083385984070259156188410402570262829376883954789679342141865814042459941910007831062138636165775327167", "5799948905339827946360248023360283850436043457245082765958040873762247587498383636008282743009281294423233039412430365495487494988853843202200663013962183441943713140831152034790116190320655409735945340074529404544788143830718378") + E6TestPoints[7].out[3].SetString("2308251230813002505164232545592957308624208710129355136377908111713066471276499616879021747450173293646977365829344893623204145004612659256833998959005983106160860344222513371245574882161234637095051217205614145796120547984954867", "6525442926128129690593043984199371753346120365436093191369560487178730032554872876850470286452538153384469711592717562896097364483466239827944188938720013798251601834829639965477712594878314775180945255037895512889833049869077465", "4255925652106280328499365812472039024125057405705821924915631560255821132979773017332067635503252771738872169455856577077296484060010078529328273491007938825415995459906759136474840583063968059174323623051781836675201086778317471", "6008246304120202630344208994689271776792140006996961748366569444033638492925062936020827283385330981576993174832086338012571139908082561121164188379159766691697472985118625636558277787776211537037317832086610114678308881750212463", "6089742238483926394535043912029524348756029317564499606108702863161041188468482798828568398002183583876128638269451283761792887596107221082009380273948536310983646167624454951962334568520097243250667167412118102801150242703058510", "1801912236137169790959056914162298854977428954565668612028550448280001158744505332039708343533414320575659688151571575297594102021484304995779014408577679088155923620795566761456652528049082655802120477265755460480375736925141165") + E6TestPoints[7].out[4].SetString("5525828864032728249179333308504520425554375609014392405952993386783171982576658123014016207710416847783053752625279707883974709406237432851234282017362843453682827424031041273772818750967653269522813043870268848562971023887135265", "5941666137999509930812227708674628398992312038982744015685197995245731145052416356387334697999990115951816997084591815720167652845100009776958135727636924454323758216317042099336430677463066057426621764796899521272228353567948857", "2181435091275553366100020201399548776102709770896004903545977828816052275959226456898232570816129765479792769635854778574608113749075200192460545066125904906647208627408080290042072708860754273091326044411291711011766876054913764", "421959636784711185743253246610430242748320616621166507207074927375244693191013024563550742375613241779529887673510360631205473681198869266090571223237036387822480022062591954878298237336994073237046015245090067825997584231160434", "4651295037675685286973210685962286315428554282488296375140276673447528615959179968332602866303047344720265895220981836344732005165782084725120659280032664506057332360237885535006701014526949050670642697021526446325723744189488130", "2588275428621776724082505502361537907417882491329366888032158875500560781100994305627864429865111723355411790503124788825827907644778379915483404703905733796157638413642690870981167440715655408654431472239581333452793067519090474") + E6TestPoints[7].out[5].SetString("6425522494491572315991300805865898504143443599906677141458211804232061862991840406915511172778276913286745870821128181817904122018546949149371168292903110810731444066400496724054029931175222518192723582172466207323211441401880085", "475446646993038327218521557149111049872067231378894121206923541095206300283556624476428642099397717305728950985756066094471096285504237821542997111708444510226956268238159940759191809113348078334975777915400723366493091973457812", "3351378520359242002790517645693559956839734539116400650833390744213874315005600144322840258491097410657135551918156726662350613113773498498493444342202277687850876435926809745738418366356029995094829466609303544639627585601881792", "6323965544262035574045129441309148436446738740971590695266331451655568416790212380284698229968946491965681736358090543269553865990093149941581577307603716492267315775614097555063386137741329007178517164386061683284025786339805150", "1633077975068610969628192858328358059994425642779379678193990292195178013009874286330327037610956575510894459022341240207133644289499144945515974699781789917672775343949180077731101076433207260070970267155542847990550074405274704", "5224301940547433474562213642946616927139346419382052010646348329841238135054720956350097782977623063815644735874299226470529658134868234430959682090583298907587744176434303896926440741213127850267390613148556657988359055010173927") + E6TestPoints[7].out[6].SetString("6425522494491572315991300805865898504143443599906677141458211804232061862991840406915511172778276913286745870821128181817904122018546949149371168292903110810731444066400496724054029931175222518192723582172466207323211441401880085", "6416003737322694212178268125126546492607601681157255988306866619114417121959935111611254541190013970335135616768030547356690662835050009937806514587416857088724648831140348909613351822310248717616923922514568389476271821145610487", "1262719745647981514999673267269311239738944829180388791206605429239928225051317973334581654239428614868290660371969405683680961261141840933762593415523708182767225758755580179956661978322883117459654516970765570990031263652698314", "686681560685850660487648723833293340519280058040270593682460328908056635361488640187339916386310900256921794004875517385389726308877196448400980031938288366031659570313648667336400100196241103558143410653353544860648089318921250", "3703878930396751738873247319421953093956575418976325390459482557168920256089448848163588223780449253900896383460576665264174886683030523670195016887466366111442492468284354728351088606070866457573308000860152456709803029229947055", "2016971528867372678317417977664796960909155831936087014878708174600533363881269435132222981221634204058010187264800230736740207987464914785058398853364654895340096905072532011133155328377220401886975075058586677244935660726108362") + E6TestPoints[7].out[7].SetString("6425522494491572315991300805865898504143443599906677141458211804232061862991840406915511172778276913286745870821128181817904122018546949149371168292903110810731444066400496724054029931175222518192723582172466207323211441401880085", "475446646993038327218521557149111049872067231378894121206923541095206300283556624476428642099397717305728950985756066094471096285504237821542997111708444510226956268238159940759191809113348078334975777915400723366493091973457812", "4802791609604472051605945303851408825378879202600138249887004845235677332289209565099424579037742891852019676207599292472492107267922590194618660772446732093867954422207279284590787243390449918316724750791431139193168591169884821", "6772253663683578844260801199408873307993319026060438930078788539855621792335282451703328220223565983059125605144607166247379925942138149128716466058708598339604234852829271478345301024909623481167138825820522997540855950579410198", "1554493478850369830895349504525346388528667850780445040860317310845525153144168601593767921898005858229073725270868707979853228148024579143638520111877145569836337287144974044290353948919523078307621432414273808142411809483846540", "3684119972635671743151994016993837576249478325090185113746150004968918651070040214869808381533422827883230019144287617717372308973150928113448228461906657586703957828016736964579258218587689347571484162339999132099341518835002734") + E6TestPoints[7].out[8].SetString("2590092944503221663326332779178996600162468730661003095393813609839138982910137109487778526128563126962082291622635187275718453167629446483796637704903563920744348641589011421388773756100000094938131886346157623447158275087480593", "1055574273319342826086926798691684436478787239389325337733758000671680175003705955483831419711214251942806387853204353995896021134215264538423754354153567666412940304436089484481794762970075926619955391386112197507543674950150966", "4805927979313253252226305439077759500835336925208111158110140887402939443192438880067257505481578552701330726273239514814455866640269309901075158989057370838805948609006751427570116581090368706518198621323514429115755719530466874", "6619098785534548016140254574662199343821519069628513668338994264892104196121257915197576465821008980500772902542719323559295229624586843901758717858219306978378459145902173534924340458891690126140046835638571131201159347263470927", "1872382735723848925503666470659292585014146539662389273090733556569053776288663043161500410334465428057591663525613254515707702116353624452536404362503329887750042450164629279052753339296578433435627261594448546216353444736549433", "271289251158185784212398183885882924370871869003836758503437152967713067127582560166487809361702873975584829925093158936586146399942002406403401271270413657106098920362259433720383061603388321233867664725762527661667528925190058") + E6TestPoints[7].out[9].SetString("4696430057393205489659399851624251587750665928547391315360611739763671003375736037325425408239167766171317685706994402627379987626417991733520377503153135072917220637175645768692038115164623934658331695039093404465153351096571842", "5416029305769811848149951271872676351392250032564006147740673446975698417245040072360034970989827590592889311372323336053830835727601110394762735003179524375345046087313655854553882602830165898150589008349647503067207722631140739", "4331111269370983747017846520684992884571609690849457706668829677034731830813092299388324935703096583342764677575353523174274526931947143773554141063344849002731185779582084130623117190399662113454321425092815934656872994123984371", "765619965890773579117025577530993425073443264238130942477460973946595724236727821036691146993080743624094677382951268057180992023505017175738305540178003214004188881749628350010971137057596826668814361545851919985974813333759236", "6860045137083307132552315634168186604573782784158488285469128246075860064319193868846412123563331164960174457713335055703498723274541464369523531659461408683809436987491501952813337106333206637928584909166795502960751282758988517", "360603158955265275739770319950829654423540533409999876992929432162572522104722724126814460834034561949867525743956754045899736715758616316038772125182283327952857991888748508936240920730849994852290659812669923137351774770848339") + + E6TestPoints[8].in[0].SetString("6651664387594927919121435030879188779442261780530843208340138787953733847791657624969129769967844754278964894965474442204933935089659366985149406678763267329298246295763574693763710495197370881197175336842572263718149232452010351", "179595603522946378157780850302712986540688762779712028225643404815344989828324817883626870450960618513558242006866526591605094677775639544595026085505996823073837779489961486847172480134044159764334930225639296258590285504653768", "1244075684831597992696756877979018332700329029070743210343947608400429798442661499048569872230125601876618101949334714001039039568025340824357724619866282079277006348552357728793435133046535059870245377060535707820104677776841181", "3342545622236152204409614543674363625737099111065914357329864521559326953671990892154361677613732286942115966715806238028852099317676544544992680386586831553411458263548611025656212024290584726865791890524691566036633170921250219", "38390687917486229706577252496053862695699345909256189033654542556972076850338725891206560212596483936957302223538995009166392482003649076812314796801478402963490287296402635668819026600250079508972431363755370479860726857619432", "843199537453597610239870580111205365900330433151471558064102779728543875397852198449891498992580878761441113769995449825388518696795865662087803901213054857259497999617789925494191661441476884621294891991081768128794466156355186") + E6TestPoints[8].in[1].SetString("1372919590553518142596060426542302119932625654481012546742802107559422474679864150548831400582598426184370198747170443318586465971171482855983897755785996444869574237081997598686962456231608966336007606282965317199231364764325514", "2799314541438111957167460221049486462463650226642758372531060318733532675184873374478699881381374769051527023948561604998751282893711782727832063407738080318389057714091656555764706683516806821072456301261659745432477938553754059", "6501212313083470627788235027070691196141873263596827479867448871895247709210736803940020207672539256619890901659552681910271703117366875984048178746075532199899496264327976457995609936520479690340113940327442091057551381791727804", "780758100698045363472375816756663120293761508628053719770138511144076196019487600108299957796049712257666450523441900958752260242856897846173883099735898586502956314587623852777361236033825496446943550140876081843476074245211436", "4263906238271742585415111225469122939672571733380951152890734476049477305793678455640547065656093847300551088399440244933504539694287701733441151922451439647450106994372219223148041019196196270805081180626990929715302668105560462", "6189088740271233493351640750896225037266053181943095499690828080048534314121990829548820650572568875705783952606783339705890656682524504469530830293413931624800571284881267788566098849275777303501460383130823968192435892745428627") + E6TestPoints[8].out[0].SetString("1133133593832713522320705775145833356895218522475705645569150735303532900228030039430277987261031492822470525958858272072358641940276602081783792735423962175216215433467063442078129320005383051581283242695568468074615684097267566", "2978910144961058335325241071352199449004338989422470400756703723548877665013198192362326751832335387565085265955428131590356377571487422272427089493244077141462895493581618042611879163650850980836791231487299041691068224058407827", "853837613599336081088202222774051986362533380131420580697606320086054085409906566900906896613253170855644435855100782460148983564837969049056391666816512680224897513501825336416501438143417954258459616958008686034891146449500686", "4123303722934197567881990360431026746030860619693968077100003032703403149691478492262661635409781999199782417239248138987604359560533442391166563486322730139914414578136234878433573260324410223312735440665567647880109245166461655", "4302296926189228815121688477965176802368271079290207341924389018606449382644017181531753625868690331237508390622979239942670932176291350810253466719252918050413597281668621858816860045796446350314053611990746300195163394963179894", "140837893409098564194721648731772860686714702558416948241140699567454767276351291911028966275738066826360498622992176080117416258766122372269122495501684883108464185120548863687746879293657392170855574691936623478465445782715514") + E6TestPoints[8].out[1].SetString("5278744797041409776525374604336886659509636126049830661597336680394311373111793474420298369385246328094594696218303998886347469118487884129165508922977270884428672058681577095076748038965761914861167730559606946518917867687684837", "4271731446400566960387110311528884066556707448673103765208373246291435736886943179492610172358997537102895785812091535044015570904618104576112474376893218103636385164776813781455009428040834134643778329393948663668877260069968008", "1634313756063859904305311533183984679038124678010065839990288896714805511475416431196232847846998032897591768043568645541929095571212712599659057572916051478329115183602890121170368827949652165482031137163062729605318209104181676", "2561787521538106840937238726917700505443337602437860637559726010415250757652503292046061719817682574684449516192364337070099839074819646698818797286850932966908501948960987172878850788256759230418848340383815484193157096676038783", "2665934833961476183688255709302588465502796525064455145656710226717118193300152006338342677845914324277270781577885363526823611908270195102720674573475340354464988392302692262893321638827650604655790951166733553607322971871127269", "1545561181498096656285019511490637871113946163744526167887064859889632983519353104988754031709423690696521728916998723570659621134825608951906485306924424831410531814115030987300636443589296377071734209290226912779123486529994858") + E6TestPoints[8].out[2].SetString("4056646743720732078620033735927211467104684167523708739181554624119436914551368796353498582463117709469146584815215453890184908599388846800750523114783953262983763565912095682833108347481103512965311305187262661310297899011096082", "4612853419006508648354098979740945133552278714953081220651636502791674495671481204365258079003685404588864520195279143684039574700874739489859850387296612317205690725821393449314448973482770043324068090691975537305663175655106232", "3393101939657709461417375966250960770202777664567301340059669892291724286157885219463845555612842876855582450770650503721024892464202379014355958039411931418102086397765022200136449822850571804360140070093812771707687298448855758", "2702780164358561519526389546202215232247904457803775030133859403442927492735997077805422232726894647498327390824811838082626229231766721531377059391823202226768370577194499888201982578815203760260399809021021483977300718421396581", "6558848779444515646799918295273570025674012192091999628666175539754316493436660406197572767738572281315511979900594946927283680359336149791131729134007709694964837137630876068007930924569672320303277961320770586858878349102165432", "156674585590367926371310118249099782705297242937350103108924507197602502829838054181530427866461071059278635744004387618671807377337101196601585155840836105023506125096921028620481031107235109362391956340388255738403373975589175") + E6TestPoints[8].out[3].SetString("1040166189591085054331220778474818890632880218716827164884735215669094710714133299966749594321505989326340515697589931672625975423982594860971958467630714878898048204607693935151113267828247670491747956477956458644363800801272670", "3428698076160235422788425325537685547910173648802689508774443797264635042010665194327445762781393535107047955839172803649805882451107569589941489912437869186395540142250129786537702180955578913551070775594455725830463037634454200", "1815300904186483527040978224695858985514995820663037579607607072425146909243878256927866115285343880134949516012018263341801783530820905976192018463238479136404473130161917485152923291873749812650858069559693067935797967536182589", "6830874798128864000832654594315132667098217860295076240189709792689007295032393633358506855901426809049151016383365581197804451522268798640947888398392618807338798912831878412900473961833767277172183133335559299048241186143156905", "665566571084962511923879608295854635041426456824500376888581882544786652895821242435801933967499511003868853589084186292629237479882717830632224561911295832377554804392257569361938140699424637261446357683285696786184031429206619", "4006036855453356360897144774776682273618529586348214634135144268405230748497451936785828767203784744105774724875692224814516473110002101969250855586832818148230073219409152746310809548837915994378422106533527033070656022819033571") + E6TestPoints[8].out[4].SetString("2238456422666972467498981474107417244545571953758233117674382944138862071220638589723598950313476853353738169182898838623856874923967974224221855354020637393733334598401882141660384138521348084439938027364447400407279839967230298", "3542700518597311521555541378051040377473375193256575883464241941173925309313243775065448237770379786773297159986267040387653109924063121860906444709575193645387398546325734444657269455726770883379479690004962762297076946769328235", "3692062014102333305518469865826259726091390433755051587837318922878001584780300214220164247912812134394478574924801617032058929008311190023534205607428770875720245097231186756766430999942919774408637509670977561660127268890101283", "23599424113229359285580653124280855804098132421019445348429070876803557081802214197109801397019860965984756664558212191126101157551779753251768408079114316843643218785128121828631968632856228093692382685049691095155463039831461", "2047295861655831659454100390861409324841431340149627256618440777765999401728668961639718299610631124510698235083152691692418628083775655485552011438934147103749438711616758586160684496915422029501273612714111625117392349608557600", "2665426362806475030025357872863115178249613014128128178707509212716597430033687365899310359682165823246601829013377306626342173078518792386288727670279701149448317855330851275980585831114174194875661286925528276247328317475110746") + E6TestPoints[8].out[5].SetString("6651664387594927919121435030879188779442261780530843208340138787953733847791657624969129769967844754278964894965474442204933935089659366985149406678763267329298246295763574693763710495197370881197175336842572263718149232452010351", "6711854780792786161239008831972944555938980149756438081288146755394278432415166918204056312838451069127306325746920086859556664442778608214754485613619304775877767319888547363525371151289552636187564770204329816584174627614414531", "2649217421194319816528329666638833686143486323582317714934849445453459815405156383358287029290090644733689558032507083811537320217060889966647554792925226401458320603290593883652185237681838257853756990991835094990917691624046821", "615014832256642863708110542960689067923113866144375782814917565481044320233557761844400324916814081092819273470792687722973620633866439805775899174861702699281290195346402925990228062743803346803262580373370974402539096176892007", "2558969016750164546836672567814698152841653718641318164433455274173872761924618727150646083600057243592052256513254992214247665634575253718721571743448869610187475995119574667395952657779380029055005652556416419902180679071968126", "3860068919057956505818829237415200847776515273869122418097737990798303134057599009511168203105050637415982253577782810540305262755125200701551922437349800687319984041119607459616910944733302193699009269976569533840935535926420468") + E6TestPoints[8].out[6].SetString("6651664387594927919121435030879188779442261780530843208340138787953733847791657624969129769967844754278964894965474442204933935089659366985149406678763267329298246295763574693763710495197370881197175336842572263718149232452010351", "179595603522946378157780850302712986540688762779712028225643404815344989828324817883626870450960618513558242006866526591605094677775639544595026085505996823073837779489961486847172480134044159764334930225639296258590285504653768", "1405141736362721823831572788659815353443157294511574504590901837053030016962494884309717157059965042857071456083172369810498280649035549142289830173058944322181314254738236154858750104635303197983511613931299387170813013847205640", "2933889929822937471279064595640604848819455935325859969369008073169252148337943082088921180758865319605929327567187687699336039169011263408580932137676767346258856640483494898726103544389208722282845229531906572403592646020926073", "4294090679648081762853539861964905526942315847985575756046680343478778583468534283045830539476757960111855009016992626227747701003975344963815625158874953585800638816962531547307771947043966687387921616509797322460723507189480741", "3016869381604358895578958657303995481876184840717650860033635211069759258659746811061276704112469758654541139807787360714916744058329335039464118536136745830060486041501817534122719283291825309077714377985487765712141069770065282") + E6TestPoints[8].out[7].SetString("6651664387594927919121435030879188779442261780530843208340138787953733847791657624969129769967844754278964894965474442204933935089659366985149406678763267329298246295763574693763710495197370881197175336842572263718149232452010351", "6711854780792786161239008831972944555938980149756438081288146755394278432415166918204056312838451069127306325746920086859556664442778608214754485613619304775877767319888547363525371151289552636187564770204329816584174627614414531", "5647374699484134546700032804296639209779339883465406899169842551809193623800830237039113311059286085764246465804451899450122719552528906934991787079259019519674598750826151121579108498377061736081654323369433405022660235342227118", "3342545622236152204409614543674363625737099111065914357329864521559326953671990892154361677613732286942115966715806238028852099317676544544992680386586831553411458263548611025656212024290584726865791890524691566036633170921250219", "38390687917486229706577252496053862695699345909256189033654542556972076850338725891206560212596483936957302223538995009166392482003649076812314796801478402963490287296402635668819026600250079508972431363755370479860726857619432", "6048250846862134929156919102164452176579338479384678551449687380481079546845639537637791684296830808879423453983791163625773240423758382097261707797912246741692107099760718924878351969982119911330604808438887344713970446962713113") + E6TestPoints[8].out[8].SetString("6429555944815599137775786646165405202781609000661189305359087184949131261640451642381392149481573661093833323713164413035779125116539927376618910836907807380881122132954980642262678892736014603827893762561308985689627487894927014", "3029161700439667979018710492075341208884921526462129583869446830392045970735053530871339365080379581758158303187188403683243599820303571071625071191410301195744453888515325017036159792788543594906910031331490572844367580013927514", "3449643965492981967760598212213914485652332030925947048019578092372113069604117449542293131836856146766651316105805422568709488291633419167810649088137964898627010918821793550039895597200721517438524373200904269856680101717777955", "6687529668722141046959647110204886781917458097204602801070253322080628527937499261013211219308225838569683938639052003314827543862251678560953251958837546564770089484133022064556543076993493153187354609512294198617863079990540195", "939979112856544729675170058847340685315625251798275242444929771666237921452420621949294874376520600982442337353553823373365367154089405878509529082265323774680242043309166470781268362590547270574797693462447628589790620309600633", "5549112062114879823961974427684970730498563158852407484996803206459795481128755316632662493371911407660002720787860411113293477091943903061185847073569656585532748250135004433530209444412528084099077323139343746255444772828213614") + E6TestPoints[8].out[9].SetString("4462984634511494399772220122513818558016286115961780462190696249821668155281046972834466705865367879867305650647356552488576875441765769090417956410125493437448364964646737729435642728604351881644243159827093723085990793833656781", "6515657277587155171638619099683300649042000588403213518121076135157483556030793634504280473987726386015692845531423018493369994402894203344627022277838952974870052756725543484011049044852635991675386556084738277823821169905231385", "1489836346335365376116380521537254000856584983672757506000355431200288950602602320614765147261381818573847003526077019239237325708228478862326112852766531810181028359510285051149153901148272090952944798774221384093369199049783187", "4096237981956733271735135985488044593486725914429677380905457878313271858478016333983950662472657475645660468666256146763701435707970599587707535854424348514668276975491411077578871156094266784960313840896207535733356275408928466", "5172942457927250780342351323130910185737042065562983259433586143001416431148383664907511200412468095831024592497371517751433330417933695678788447584240447911230962704080816739580046381008349751410122621518903925780113744278938262", "1886809898911142311447750521948635483529436797233362690730108605174255249679424365399639202771399738278560073465201443202819965902142056268663557108752739634213309714070997964332249713318896904527894062785745483661374995462753552") + + E6TestPoints[9].in[0].SetString("4950061547072710631709798099215586743312531303456334409264907106904901220231612796479613609029986388702050165173704257911443879048937543912566454734737255070890758837194609748269025068343993234175023072584815858552757814692876520", "5668990529153412039685548177713337290528761861552889176646860213006681134522716234815875957810287850059412721313482938049347727102548802445106300640310700303506257240343189478662006041017291634432639089150701504847314563422943308", "2241769903901895331266503842647956785661722353437299149561525287166958372103328844849330282792832775947459976005765483073802519976217168184661639433022883481472668941316878026558229598948589415551765795756843402112757755411502689", "784215111825050636864112529266578547680694320178214165541035578000203968019440707233282813317066861987094242361729322338648242065517209453267655311404414916164955814340020677607948339377697773246256869935478973977844064374969138", "3455588989812699392208020373813315227982306143388250458998916769064351838202249084648208457081384579852260712967126021293577738150209111406254868110519433375485055213065443254114796383364619868949943779094594101407796374696280536", "5102462947757418099923349558539587126052246568628987976869768298328893871868081906375658871235131239365576268309397631500590171272195838871072561053874510223574507743800123195945640432678015333646621432007914207112362363509361063") + E6TestPoints[9].in[1].SetString("3545599771110793475858575850176183618451325316423859384643393680671252303305435467270222342051743800960960538436308100334808327091093561299489028866490853704963068372369895717821375882098909134145384175073812281397277557050865529", "6375057968691519015265713076631533158456660858178860133842693296904840402944342250425980535643213581490688233855370834194026675677925150285307135915134032292228980396444867793103148558246804153937662470464279661043174677113888839", "1111699735923865547451396168678110112153132102768419328355356296669244011213017121122379532448323847922502100971359708898880355433422444517492399617866541014841286809084312729144173009014300300130786390064280489440845582253567224", "6310324944957042879910982053984039103230396871241897981125136670582009669440122677804449290592600975461148715701831699021144346340119152064371542027599784725488349751483794785914869478380684672660284670466303975644355153326655120", "6369656161611696443494476457101608758989121204383504268932071180248083515458345268527171180502384797442823624233993450203429269555088863407430275491578529133724783671907188946387239749083669398939040558872529124034993405883537", "4887058080994859332426889890251437577520702207131301999965503969014157354371069363115278823519302333506179574056480123155578541025570460701032269991342432434718477881312778065373740983266166519041763333296400183890578581243254504") + E6TestPoints[9].out[0].SetString("1604210933867771568171584267116112819284187707344043684394510627366530101293556527662152767792318502022146135856225744795090447019476857452705971902102807176902222110185996615717857319019305572368507547228659027107270458624673750", "5152598113529198515554471572069212906505753807195599200975763349701898115223566749154173310164089743909236387415067158792212643659919704971063924856319430996783632537409548421392610967840498992418401859185012053047724327417763848", "3353469639825760878717900011326066897814854456205718477916881583836202383316345965971709815241156623869962076977125191972682875409639612702154039050889424496313955750401190755702402607962889715682552185821123891553603337665069913", "203089672466360977378304900974960108431422278883962037152382088372590215216071648950048920620256149807378390309774407908630829285082113758289685639878898042701700466445306613150274186334785649954641839971813836779434304582555959", "3461958645974311088651514850270416836741295264592633963267848840244599921717707429916735628261886964649703536591360014743781167419764200269662298386011011904618779996737350443061183623113703538348882819653466630531831368102164073", "3098070644436544892953449766515367161093279863224139867321482107133427803995659533403254511465021885230891274612091141205006953177212051812755319346091641059341380525734392410946837784520585056736485064874345278160176031633547268") + E6TestPoints[9].out[1].SetString("1404461775961917155851222249039403124861205987032475024621513426233648916926177329209391266978242587741089626737396157576635551957843982613077425868246401365927690464824714030447649186245084100029638897511003577155480257642010991", "6185382944777625563816624783357461674551769915910179152317957076311464153821865720477578605456485956209589055211898717306482810545177899919148676424301969610228881943276830535931401114194084276446876319116390956646904799428122768", "1130070167978029783815107673969846673508590250668879821206168990497714360890311723726950750344508928024957875034405774174922164542794723667169239815156342466631382132232565297414056589934289115420979405692562912671912173157935465", "1365340551183740296349920157558196986929966361472466293929689067627817720822809765516516706013877574166810094413684236768665654845952305148245624982929931789628211162234734742065622492420609896537871899899144111176253824167382317", "3449219333651087695764525897356213619223317022183866954729984697884103754686790739379681285900882195054817889342892027843374308880654022542847437835027854846351330429393536065168409143615536199551004738535721572283761381290396999", "215404866762558767496459668288149548531544361497685976904264329314736517497012543260380047715828905859396694252917508345011630246625378170040291062532077788856029862487345130571899449411848814604858098711514023221783782266106559") + E6TestPoints[9].out[2].SetString("690579668031064071410408180534897832404244537970269874005298788883458275688718836463645870336377559557869861454980257717112658294133774883397539127794418315484012226982500571532777970048445017989412947563011460466043074895590903", "6068422789193224634041308806974730201168637326861154882733632690235605753152787138964757267922184654635044787770743019934497956349794340713485464050903536615687703870264404722995451347636981264033538236920710705246159244736037591", "4978945453552898846657105664576590445774631259314376238689261995773090512857695422916763915972990323288577817934395866028726335841032495969087712010337124360292537970305698684017550329686582396466602434514125335574184835978692974", "3789315836352573972939903327785434197447317479200521260751366631800668383007893125017081746409780881062895656899982645142998586543277459597583460954093757360881434819524816433815339586161633391063964883747940228288180169603818132", "3467310988548349189451501257136313612998641429327283736009256598285858808691078654868707441930623384271738032328160531523067236402579081220202020731976414847710986491031728919196881824508578921211203801153658918217411057799852695", "6663051986792013665697510163129224380534573663925566186660996855800420787363911904840791202632661528980445316596364232264433129444078207214482595707301605264545798752846837687862907330286120146190133677825763434217842395181755143") + E6TestPoints[9].out[3].SetString("958917842137037022000650213685316697273094434126550189581863298256721908274604587146575830735450029021015826675175418060076017613430745805408044633373941064461037392600197539183484246195116848114895282433284296273317727215774338", "920744320664473217835055534374998093081203616291883478559853316818582767249821978330858578391677523764877757892311849938868330808381588204488417733779412994881070021141512551898943710603799448871570277639405366383163228591841758", "5709498038204179150227955871413163519318540520622357515159793638988403474421640764014152544168698630544204542043975241579397951287881976468562934007205318593370501035963747282493365261434095395865045103781001966431312936911103624", "3599456032517997298494443215891414871144036134728031243897647720314119889245381784199127531123546075302423317634324000461062561385073063394317329556280840629038106627712064305411944048490161118539638447209539201647722054281635303", "3384636177501348923100586559543353122644034093435107415675610287558631574977872319561932636073257104884963924962113859058548409608161558450468401230787856034886413292197589397844571018777771363099819569230294915972824542918515974", "6567641368529719853724208852090108596309587092076543882317649952089094471319245387480715905133980061000917960415678579418818341258595491316832850046465047357189858569749407532084459296593591307332628268700806626908970560169375783") + E6TestPoints[9].out[4].SetString("6037269020380227059142539123084749311158307727590196701697331829731545858402211301472651445319989521073479230229477557531115882772275040456703156221044003639145426761193355682140866528585701120820104714428100378217291690205009577", "393949339162864000993439507574321002096346251959416497659653319717510510935861253793816071479033357273430784166210747814821815649263030008797488044226039767501819837272829867318038527343446363546820846747358727843311564170101474", "2393949720989730907455941269547012724240366412236283663707367403761664768499020432599732906202433018412103342438824344372645895463680937203483486496547066429698038795811681066236316381272348890467221756705382133792488229222142019", "3798931159639185944355525644095607450692448926130453630956804042138753645800007583868754851987159444441167857147337632018253140011076051011097872139921017621337339362551838137462288615364608202893682467615089680214520388817629702", "5621863967163988157935934554557811750384634231602864557772596642136128177299399558657079281835858314352587397013763764015495290868673117462533620714871713343969483021853122337687655427532206199521243266425442117874887040858004823", "4670470945343490495032024838912906854954548024530887363903323855227517773643568414702871430106831275501090576365415675491405015845235121061582970259543885401232829021696231885878274606762781446491610843026039464842458578146418228") + E6TestPoints[9].out[5].SetString("4950061547072710631709798099215586743312531303456334409264907106904901220231612796479613609029986388702050165173704257911443879048937543912566454734737255070890758837194609748269025068343993234175023072584815858552757814692876520", "1222459855162320499711241504562320251950907050983260932866929947202942287720775501271807225479123837581451846440303675401814032018005445314243211058814601295445347859035319371710537590406305161519260611279267607995450349696124991", "2721814065681990041965807749236024618240585891369424630636738464975588946858165671382228643291367662836479425491304175960471653653095100050576591615619182709794955709674741175299782849152697089349886613506018316591642606011498277", "3884618063236651236376299455966714891472515820680884581575112183526550300482149099884447856753836688861137504442561140459100959573675321805471033386592496989791987443077331590117869132609638071133655208636151846743380494314805100", "3893447368830355022421368976548626450473959330336280035945413400315816254672401271301032455751452602357056424478300041750244720473099999573815865070964728770513903892334133571512317304458698132756774612806191923511018344071132936", "5668612907078220000180356323781712432924308107343112416259342543803584474195642966249401304349417226659794916665847274798226632112700427363007702905195688655899363885176184691148173157274074400699257748924114260002757478992520401") + E6TestPoints[9].out[6].SetString("4950061547072710631709798099215586743312531303456334409264907106904901220231612796479613609029986388702050165173704257911443879048937543912566454734737255070890758837194609748269025068343993234175023072584815858552757814692876520", "5668990529153412039685548177713337290528761861552889176646860213006681134522716234815875957810287850059412721313482938049347727102548802445106300640310700303506257240343189478662006041017291634432639089150701504847314563422943308", "480044161780094710699303906588067832578863537932125481075213177808630574754836826532898360498534886889019449485538692886669133676877931865914952182596299228322286768357863148741553250204107673798120817749174914478884850599995588", "2222617209254030666156377697042364103326458771677051362397642398682869153741901928969952513218508136792632820949496150653412557481361716500610823001128389692994661841961156582646726159436260951571987621858338292121540354429294061", "6433864409988410664164190014189373406503072351347769724083250151039078751612333116226125453745986193072411998062147163858501059617799384538628290216766441051904251093357440875117973575023875590197081008959152200766715107470723126", "566149959320801900257006765242125306872061538714124439389574245474690602327561059873742433114285987294218648356449643297636460840504588491935141851321178432324856141376061495202532724596059067052636316916200052890395115483159338") + E6TestPoints[9].out[7].SetString("4950061547072710631709798099215586743312531303456334409264907106904901220231612796479613609029986388702050165173704257911443879048937543912566454734737255070890758837194609748269025068343993234175023072584815858552757814692876520", "1222459855162320499711241504562320251950907050983260932866929947202942287720775501271807225479123837581451846440303675401814032018005445314243211058814601295445347859035319371710537590406305161519260611279267607995450349696124991", "4649680480413837208130285839627700756817946559098850959952264873042665050140162891238352900496578911693404591748021130377359239144337079574687872266102418117478936158061630823814314032475007380400133904673125710730007157707565610", "784215111825050636864112529266578547680694320178214165541035578000203968019440707233282813317066861987094242361729322338648242065517209453267655311404414916164955814340020677607948339377697773246256869935478973977844064374969138", "3455588989812699392208020373813315227982306143388250458998916769064351838202249084648208457081384579852260712967126021293577738150209111406254868110519433375485055213065443254114796383364619868949943779094594101407796374696280536", "1788987436558314439473440123736070416427422343907162132644021861880729550375409829712024312054280448275288299444388981950571587848358408888276950645250791375377097355578385654426903198745581462305278268422054905730402549609707236") + E6TestPoints[9].out[8].SetString("2908471240191208364145115134926062023624895287067064532289432652443475498226796565753187726394434134675582460485892288986449350381981930259379122000434709634834870450335690909744796443188398059943751199542259751366841706056951718", "4975800596912076102879050511883290599676471444168984258849796601936168749484071179162752987166359212598085727742287148589834333189806072363359474378600034569033895945918217519762717174866822699855408258101317930304590898072260405", "4283340414345968417940710762168946527887832813053214876361811986562124579167303863159051788092134401751406274989313728386026888524580216052518789707937356746794661127529359099714621906310482697990717509697825517828763478816532684", "2581958573287849856005000488428930976798697704703915208916077048412546489578824573817039706281553016776267049066621557987316289526659048660963131255099553802586675540924259413781201017903633913007026192735813700872975786521517288", "5061418316361079983560415611146175223772077727612664604273693195428071058314015642696999345058273877348675326146609964762787532032566038383442661148846917839995669412373842122153814778737109545770351650603418121588148954405575264", "5077498385068758391378954808478688776199054538996405308364046947531784816080777645950121753092423689813083148314612162771052968503298693497716613780946063922802663786281611333390997161060559037106723007250071931432975217701462652") + E6TestPoints[9].out[9].SetString("5546807839852495381392043976744688274171241920893911056193073519937495113348329295562025174146643396223453190535761460651765664957619936784671802416246412691136606585482119100086596233972658942339302305703277064253180780314667780", "518799378078232136225532968444818627893704188624846917242242822315785739627737087894387312593314113813772891239162208004367627822508687024326243301818917139481044313700587254807615103838601418817444751482051673093090529918350816", "3441978517473972302531816733757788286214531590338382842530866567965894677126893174834344516453996512795588175855977611324774336818027094565358853958693898970139230573587075113142655853589552360830452029383108367495677063786855758", "3550190396653232132676099096428872331658854845523238307224931519428323276363060730552242649273926876951467288663708305895274272627769597197856210273064344449798146803949801256548646697648141320873339057809846616817301864891754988", "3327283548130876947710220151167765246153183057724499538519066298257050744615600468947046391442809361901645054967849586021483559012777891918488699780843295002478313581591141295840557394894284120412235081577833575404369206461922969", "2674931618944361047023496406112858829879220240514407851259987852133447349816672975184293645084417160332720468871607383913911783898960312814821827788283883223615276701758308742340912094841829680024308678482128589901161157093786472") + + // benchmark inputs should be randomly generated, + // so use the final test point + E6BenchIn1.Set(&E6TestPoints[len(E6TestPoints)-1].in[0]) + E6BenchIn2.Set(&E6TestPoints[len(E6TestPoints)-1].in[1]) +} diff --git a/bw6_761/frobenius.go b/bw6_761/frobenius.go new file mode 100644 index 0000000000..870a06dc87 --- /dev/null +++ b/bw6_761/frobenius.go @@ -0,0 +1,176 @@ +// Copyright 2020 ConsenSys AG +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by gurvy/internal/generators DO NOT EDIT + +package bw6_761 + +import "github.com/consensys/gurvy/bw6_761/fp" + +// Frobenius set z to Frobenius(x), return z +func (z *PairingResult) Frobenius(x *PairingResult) *PairingResult { + // Adapted from https://eprint.iacr.org/2010/354.pdf (Section 3.2) + + z.B0.Conjugate(&x.B0) + z.B1.Conjugate(&x.B1) + z.B2.Conjugate(&x.B2) + + z.B1.MulByNonResidue1Power1(&z.B1) + z.B2.MulByNonResidue1Power2(&z.B2) + + return z +} + +// FrobeniusSquare set z to Frobenius^2(x), and return z +func (z *PairingResult) FrobeniusSquare(x *PairingResult) *PairingResult { + // Adapted from https://eprint.iacr.org/2010/354.pdf (Section 3.2) + + z.Set(x) + + z.B1.MulByNonResidue2Power1(&z.B1) + z.B2.MulByNonResidue2Power2(&z.B2) + + return z +} + +// FrobeniusCube set z to Frobenius^3(x), return z +func (z *PairingResult) FrobeniusCube(x *PairingResult) *PairingResult { + // Adapted from https://eprint.iacr.org/2010/354.pdf (Section 3.2) + + z.B0.Conjugate(&x.B0) + z.B1.Conjugate(&x.B1) + z.B2.Conjugate(&x.B2) + + z.B1.MulByNonResidue3Power1(&z.B1) + z.B2.MulByNonResidue3Power2(&z.B2) + + return z +} + +// MulByNonResidue1Power1 set z=x*(0,1)^(1*(p^1-1)/3) and return z +func (z *E2) MulByNonResidue1Power1(x *E2) *E2 { + // 4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775649 + b := fp.Element{ + 10159193990637832851, + 5286779382647858051, + 15149190582698529379, + 10172307932521123666, + 7672315572788794062, + 4504265454330324035, + 8586997380578354686, + 5916374020980521403, + 9559933215456904989, + 10407926721244239843, + 3712625600415690514, + 17752318063289862, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} + +// MulByNonResidue1Power2 set z=x*(0,1)^(2*(p^1-1)/3) and return z +func (z *E2) MulByNonResidue1Power2(x *E2) *E2 { + // 4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775648 + b := fp.Element{ + 9193734820520314185, + 15390913228415833887, + 5309822015742495676, + 5431732283202763350, + 17252325881282386417, + 298854800984767943, + 15252629665615712253, + 11476276919959978448, + 6617989123466214626, + 293279592164056124, + 3271178847573361778, + 76563709148138387, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} + +// MulByNonResidue2Power1 set z=x*(0,1)^(1*(p^2-1)/3) and return z +func (z *E2) MulByNonResidue2Power1(x *E2) *E2 { + // 4922464560225523242118178942575080391082002530232324381063048548642823052024664478336818169867474395270858391911405337707247735739826664939444490469542109391530482826728203582549674992333383150446779312029624171857054392282775648 + b := fp.Element{ + 9193734820520314185, + 15390913228415833887, + 5309822015742495676, + 5431732283202763350, + 17252325881282386417, + 298854800984767943, + 15252629665615712253, + 11476276919959978448, + 6617989123466214626, + 293279592164056124, + 3271178847573361778, + 76563709148138387, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} + +// MulByNonResidue2Power2 set z=x*(0,1)^(2*(p^2-1)/3) and return z +func (z *E2) MulByNonResidue2Power2(x *E2) *E2 { + // 1968985824090209297278610739700577151397666382303825728450741611566800370218827257750865013421937292370006175842381275743914023380727582819905021229583192207421122272650305267822868639090213645505120388400344940985710520836292650 + b := fp.Element{ + 7467050525960156664, + 11327349735975181567, + 4886471689715601876, + 825788856423438757, + 532349992164519008, + 5190235139112556877, + 10134108925459365126, + 2188880696701890397, + 14832254987849135908, + 2933451070611009188, + 11385631952165834796, + 64130670718986244, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} + +// MulByNonResidue3Power1 set z=x*(0,1)^(1*(p^3-1)/3) and return z +func (z *E2) MulByNonResidue3Power1(x *E2) *E2 { + // 6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068298 + b := fp.Element{ + 17481284903592032950, + 10104133845767975835, + 8607375506753517913, + 13706168424391191299, + 9580010308493592354, + 14241333420363995524, + 6665632285037357566, + 5559902898979457045, + 15504799981718861253, + 8332096944629367896, + 18005297320867222879, + 58811391084848524, + } + z.A0.Mul(&x.A0, &b) + z.A1.Mul(&x.A1, &b) + return z +} + +// MulByNonResidue3Power2 set z=x*(0,1)^(2*(p^3-1)/3) and return z +func (z *E2) MulByNonResidue3Power2(x *E2) *E2 { + // 1 + // nothing to do + return z +} diff --git a/bw6_761/g1.go b/bw6_761/g1.go index 093ae8ea06..f59d52ecf5 100644 --- a/bw6_761/g1.go +++ b/bw6_761/g1.go @@ -30,19 +30,21 @@ import ( "github.com/consensys/gurvy/utils/parallel" ) -// G1Jac is a point with fp.Element coordinates +type G1CoordType = fp.Element + +// G1Jac is a point with G1CoordType coordinates type G1Jac struct { - X, Y, Z fp.Element + X, Y, Z G1CoordType } // G1Affine point in affine coordinates type G1Affine struct { - X, Y fp.Element + X, Y G1CoordType } // g1JacExtended parameterized jacobian coordinates (x=X/ZZ, y=Y/ZZZ, ZZ**3=ZZZ**2) type g1JacExtended struct { - X, Y, ZZ, ZZZ fp.Element + X, Y, ZZ, ZZZ G1CoordType } // SetInfinity sets p to O @@ -86,7 +88,7 @@ func (p *g1JacExtended) mAdd(a *G1Affine) *g1JacExtended { return p } - var U2, S2, P, R, PP, PPP, Q, Q2, RR, X3, Y3 fp.Element + var U2, S2, P, R, PP, PPP, Q, Q2, RR, X3, Y3 G1CoordType // p2: a, p1: p U2.Mul(&a.X, &p.ZZ) @@ -116,7 +118,7 @@ func (p *g1JacExtended) mAdd(a *G1Affine) *g1JacExtended { // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1 func (p *g1JacExtended) double(q *G1Affine) *g1JacExtended { - var U, S, M, _M, Y3 fp.Element + var U, S, M, _M, Y3 G1CoordType U.Double(&q.Y) p.ZZ.Square(&U) @@ -195,7 +197,7 @@ func (p *G1Jac) Sub(curve *Curve, a G1Jac) *G1Jac { // WARNING super slow function (due to the division) func (p *G1Jac) ToAffineFromJac(res *G1Affine) *G1Affine { - var bufs [3]fp.Element + var bufs [3]G1CoordType if p.Z.IsZero() { res.X.SetZero() @@ -216,7 +218,7 @@ func (p *G1Jac) ToAffineFromJac(res *G1Affine) *G1Affine { // ToProjFromJac converts a point from Jacobian to projective coordinates func (p *G1Jac) ToProjFromJac() *G1Jac { // memalloc - var buf fp.Element + var buf G1CoordType buf.Square(&p.Z) p.X.Mul(&p.X, &p.Z) @@ -251,7 +253,7 @@ func (p *G1Affine) ToJacobian(Q *G1Jac) *G1Jac { } func (p *G1Affine) String(curve *Curve) string { - var x, y fp.Element + var x, y G1CoordType x.Set(&p.X) y.Set(&p.Y) return "E([" + x.String() + "," + y.String() + "])," @@ -279,7 +281,7 @@ func (p *G1Jac) Add(curve *Curve, a *G1Jac) *G1Jac { } // get some Element from our pool - var Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V fp.Element + var Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V G1CoordType // Z1Z1 = a.Z ^ 2 Z1Z1.Square(&a.Z) @@ -364,7 +366,7 @@ func (p *G1Jac) AddMixed(a *G1Affine) *G1Jac { } // get some Element from our pool - var Z1Z1, U2, S2, H, HH, I, J, r, V fp.Element + var Z1Z1, U2, S2, H, HH, I, J, r, V G1CoordType // Z1Z1 = p.Z ^ 2 Z1Z1.Square(&p.Z) @@ -422,7 +424,7 @@ func (p *G1Jac) AddMixed(a *G1Affine) *G1Jac { // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl func (p *G1Jac) Double() *G1Jac { // get some Element from our pool - var XX, YY, YYYY, ZZ, S, M, T fp.Element + var XX, YY, YYYY, ZZ, S, M, T G1CoordType // XX = a.X^2 XX.Square(&p.X) diff --git a/bw6_761/g2.go b/bw6_761/g2.go index a406fc78e6..af5ffc59a5 100644 --- a/bw6_761/g2.go +++ b/bw6_761/g2.go @@ -20,6 +20,9 @@ package bw6_761 import ( "runtime" + + "github.com/consensys/gurvy/bw6_761/fp" + "sync" "github.com/consensys/gurvy/bw6_761/fr" @@ -27,19 +30,21 @@ import ( "github.com/consensys/gurvy/utils/parallel" ) -// G2Jac is a point with e2 coordinates +type G2CoordType = fp.Element + +// G2Jac is a point with G2CoordType coordinates type G2Jac struct { - X, Y, Z e2 + X, Y, Z G2CoordType } // G2Affine point in affine coordinates type G2Affine struct { - X, Y e2 + X, Y G2CoordType } // g2JacExtended parameterized jacobian coordinates (x=X/ZZ, y=Y/ZZZ, ZZ**3=ZZZ**2) type g2JacExtended struct { - X, Y, ZZ, ZZZ e2 + X, Y, ZZ, ZZZ G2CoordType } // SetInfinity sets p to O @@ -83,7 +88,7 @@ func (p *g2JacExtended) mAdd(a *G2Affine) *g2JacExtended { return p } - var U2, S2, P, R, PP, PPP, Q, Q2, RR, X3, Y3 e2 + var U2, S2, P, R, PP, PPP, Q, Q2, RR, X3, Y3 G2CoordType // p2: a, p1: p U2.Mul(&a.X, &p.ZZ) @@ -113,7 +118,7 @@ func (p *g2JacExtended) mAdd(a *G2Affine) *g2JacExtended { // http://www.hyperelliptic.org/EFD/g2p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1 func (p *g2JacExtended) double(q *G2Affine) *g2JacExtended { - var U, S, M, _M, Y3 e2 + var U, S, M, _M, Y3 G2CoordType U.Double(&q.Y) p.ZZ.Square(&U) @@ -192,7 +197,7 @@ func (p *G2Jac) Sub(curve *Curve, a G2Jac) *G2Jac { // WARNING super slow function (due to the division) func (p *G2Jac) ToAffineFromJac(res *G2Affine) *G2Affine { - var bufs [3]e2 + var bufs [3]G2CoordType if p.Z.IsZero() { res.X.SetZero() @@ -213,7 +218,7 @@ func (p *G2Jac) ToAffineFromJac(res *G2Affine) *G2Affine { // ToProjFromJac converts a point from Jacobian to projective coordinates func (p *G2Jac) ToProjFromJac() *G2Jac { // memalloc - var buf e2 + var buf G2CoordType buf.Square(&p.Z) p.X.Mul(&p.X, &p.Z) @@ -248,7 +253,7 @@ func (p *G2Affine) ToJacobian(Q *G2Jac) *G2Jac { } func (p *G2Affine) String(curve *Curve) string { - var x, y e2 + var x, y G2CoordType x.Set(&p.X) y.Set(&p.Y) return "E([" + x.String() + "," + y.String() + "])," @@ -276,7 +281,7 @@ func (p *G2Jac) Add(curve *Curve, a *G2Jac) *G2Jac { } // get some Element from our pool - var Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V e2 + var Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V G2CoordType // Z1Z1 = a.Z ^ 2 Z1Z1.Square(&a.Z) @@ -361,7 +366,7 @@ func (p *G2Jac) AddMixed(a *G2Affine) *G2Jac { } // get some Element from our pool - var Z1Z1, U2, S2, H, HH, I, J, r, V e2 + var Z1Z1, U2, S2, H, HH, I, J, r, V G2CoordType // Z1Z1 = p.Z ^ 2 Z1Z1.Square(&p.Z) @@ -419,7 +424,7 @@ func (p *G2Jac) AddMixed(a *G2Affine) *G2Jac { // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl func (p *G2Jac) Double() *G2Jac { // get some Element from our pool - var XX, YY, YYYY, ZZ, S, M, T e2 + var XX, YY, YYYY, ZZ, S, M, T G2CoordType // XX = a.X^2 XX.Square(&p.X) diff --git a/bw6_761/pairing.go b/bw6_761/pairing.go index 6b33539ef0..09482f0e22 100644 --- a/bw6_761/pairing.go +++ b/bw6_761/pairing.go @@ -31,32 +31,159 @@ func (curve *Curve) FinalExponentiation(z *PairingResult, _z ...*PairingResult) return result } -// FinalExponentiation sets z to the final expo x**((p**12 - 1)/r), returns z -// TODO customize this comment for the curve +// FinalExponentiation sets z to the final expo x**((p**6 - 1)/r), returns z func (z *PairingResult) FinalExponentiation(x *PairingResult) *PairingResult { - // // easy part: x**((p**3 - 1)*(p+1)) - // var result PairingResult - // result.Set(x) - - // var t [1]PairingResult // temp memory + var result PairingResult + result.Set(x) + + // easy part exponent: (p**3 - 1)*(p+1) + { + var buf PairingResult + buf.FrobeniusCube(&result) + result.Inverse(&result) + buf.Mul(&buf, &result) + result.Frobenius(&buf). + MulAssign(&buf) + } - // t[0].FrobeniusCube(&result) // x**(p**3) - // result.Inverse(&result) // x**(-1) - // t[0].Mul(&t[0], &result) // x**(p**3-1) - // result.Frobenius(&t[0]). // x**((p**3-1)*p) - // Mul(&result, &t[0]) // x**((p**3-1)*(p+1)) + // hard part exponent: a multiple of (p**2 - p + 1)/r + // the multiple is 3*(t**3 - t**2 + 1) + // Appendix B of https://eprint.iacr.org/2020/351.pdf + // sage code: https://gitlab.inria.fr/zk-curves/bw6-761/-/blob/master/sage/pairing.py#L922 + var f [8]PairingResult // temp memory + var fp [10]PairingResult // temp memory - // // hard part (up to permutation) - // // performs the hard part of the final expo - // // Algorithm 1 of https://eprint.iacr.org/2016/130.pdf - // // The result is the same as p**4-p**2+1/r, but up to permutation (it's 3* (p**4 -p**2 +1 /r)), ok since r=1 mod 3) + f[0].Set(&result) + for i := 1; i < len(f); i++ { + f[i].Expt(&f[i-1]) + } + for i := range f { + fp[i].Frobenius(&f[i]) + } + fp[8].Expt(&fp[7]) + fp[9].Expt(&fp[8]) + + result.FrobeniusCube(&fp[5]). + MulAssign(&fp[3]). + MulAssign(&fp[6]). + SquareAssign() + + var f4fp2 PairingResult + f4fp2.Mul(&f[4], &fp[2]) + + { + var buf PairingResult + buf.Mul(&f[0], &f[1]). + MulAssign(&f[3]). + MulAssign(&f4fp2). + MulAssign(&fp[8]) + buf.FrobeniusCube(&buf) + result.MulAssign(&buf) + } + result.MulAssign(&f[5]). + MulAssign(&fp[0]). + SquareAssign() + + { + var buf PairingResult + buf.FrobeniusCube(&f[7]) + result.MulAssign(&buf) + } + result.MulAssign(&fp[9]). + SquareAssign() + + var f2fp4, f4fp2fp5 PairingResult + f2fp4.Mul(&f[2], &fp[4]) + f4fp2fp5.Mul(&f4fp2, &fp[5]) + + { + var buf PairingResult + buf.Mul(&f2fp4, &f[3]). + MulAssign(&fp[3]) + buf.FrobeniusCube(&buf) + result.MulAssign(&buf) + } + result.MulAssign(&f4fp2fp5). + MulAssign(&f[6]). + MulAssign(&fp[7]). + SquareAssign() + + { + var buf PairingResult + buf.Mul(&fp[0], &fp[9]) + buf.FrobeniusCube(&buf) + result.MulAssign(&buf) + } + result.MulAssign(&f[0]). + MulAssign(&f[7]). + MulAssign(&fp[1]). + SquareAssign() + + var fp6fp8, f5fp7 PairingResult + fp6fp8.Mul(&fp[6], &fp[8]) + f5fp7.Mul(&f[5], &fp[7]) + + { + var buf PairingResult + buf.FrobeniusCube(&fp6fp8) + result.MulAssign(&buf) + } + result.MulAssign(&f5fp7). + MulAssign(&fp[2]). + SquareAssign() + + var f3f6, f1f7 PairingResult + f3f6.Mul(&f[3], &f[6]) + f1f7.Mul(&f[1], &f[7]) + + { + var buf PairingResult + buf.Mul(&f1f7, &f[2]) + buf.FrobeniusCube(&buf) + result.MulAssign(&buf) + } + result.MulAssign(&f3f6). + MulAssign(&fp[9]). + SquareAssign() + + { + var buf PairingResult + buf.Mul(&f4fp2, &f5fp7). + MulAssign(&fp6fp8) + buf.FrobeniusCube(&buf) + result.MulAssign(&buf) + } + result.MulAssign(&f[0]). + MulAssign(&fp[0]). + MulAssign(&fp[3]). + MulAssign(&fp[5]). + SquareAssign() + + { + var buf PairingResult + buf.FrobeniusCube(&f3f6) + result.MulAssign(&buf) + } + result.MulAssign(&fp[1]). + SquareAssign() + + { + var buf PairingResult + buf.Mul(&f2fp4, &f4fp2fp5).MulAssign(&fp[9]) + buf.FrobeniusCube(&buf) + result.MulAssign(&buf) + } + result.MulAssign(&f1f7).MulAssign(&f5fp7).MulAssign(&fp[0]) - // // TODO - // z.Set(&result) + z.Set(&result) return z } // MillerLoop Miller loop +// https://eprint.iacr.org/2020/351.pdf (Algorithm 5) +// sage: https://gitlab.inria.fr/zk-curves/bw6-761/-/blob/master/sage/pairing.py#L344 +// TODO for now use the "naive" version: https://gitlab.inria.fr/zk-curves/bw6-761/-/blob/master/sage/pairing.py#L303 +// TODO for the love of god, please clean this up func (curve *Curve) MillerLoop(P G1Affine, Q G2Affine, result *PairingResult) *PairingResult { // init result @@ -78,8 +205,9 @@ func (curve *Curve) MillerLoop(P G1Affine, Q G2Affine, result *PairingResult) *P var lEval lineEvalRes - // Miller loop - for i := len(curve.loopCounter) - 2; i >= 0; i-- { + // Miller loop 1 + for i := len(curve.loopCounter1) - 2; i >= 0; i-- { + QNext.Set(&QCur) QNext.Double() QNextNeg.Neg(&QNext) @@ -90,14 +218,14 @@ func (curve *Curve) MillerLoop(P G1Affine, Q G2Affine, result *PairingResult) *P lineEvalJac(QCur, QNextNeg, &P, &lEval) lEval.mulAssign(result) - if curve.loopCounter[i] == 1 { + if curve.loopCounter1[i] == 1 { // evaluates line through 2Qcur, Q at P lineEvalAffine(QNext, Q, &P, &lEval) lEval.mulAssign(result) QNext.AddMixed(&Q) - } else if curve.loopCounter[i] == -1 { + } else if curve.loopCounter1[i] == -1 { // evaluates line through 2Qcur, -Q at P lineEvalAffine(QNext, QNeg, &P, &lEval) lEval.mulAssign(result) @@ -107,6 +235,48 @@ func (curve *Curve) MillerLoop(P G1Affine, Q G2Affine, result *PairingResult) *P QCur.Set(&QNext) } + var result1 PairingResult + result1.Set(result) // copy result of Miller loop 1 + result.SetOne() // reset result + Q.ToJacobian(&QCur) // reset QCur + + // Miller loop 2 + for i := len(curve.loopCounter2) - 2; i >= 0; i-- { + + QNext.Set(&QCur) + QNext.Double() + QNextNeg.Neg(&QNext) + + result.Square(result) + + // evaluates line though Qcur,2Qcur at P + lineEvalJac(QCur, QNextNeg, &P, &lEval) + lEval.mulAssign(result) + + if curve.loopCounter2[i] == 1 { + // evaluates line through 2Qcur, Q at P + lineEvalAffine(QNext, Q, &P, &lEval) + lEval.mulAssign(result) + + // result.MulAssign(&result1Base) + + QNext.AddMixed(&Q) + + } else if curve.loopCounter2[i] == -1 { + // evaluates line through 2Qcur, -Q at P + lineEvalAffine(QNext, QNeg, &P, &lEval) + lEval.mulAssign(result) + + // result.MulAssign(&result1Inv) + + QNext.AddMixed(&QNeg) + } + QCur.Set(&QNext) + } + + result.Frobenius(result) + result.MulAssign(&result1) + return result } @@ -114,6 +284,7 @@ func (curve *Curve) MillerLoop(P G1Affine, Q G2Affine, result *PairingResult) *P // Q, R are in jacobian coordinates // The case in which Q=R=Infinity is not handled as this doesn't happen in the SNARK pairing func lineEvalJac(Q, R G2Jac, P *G1Affine, result *lineEvalRes) { + // converts Q and R to projective coords Q.ToProjFromJac() R.ToProjFromJac() @@ -136,9 +307,9 @@ func lineEvalJac(Q, R G2Jac, P *G1Affine, result *lineEvalRes) { result.r2.Sub(&result.r2, &Q.Y) // multiply P.Z by coeffs[2] in case P is infinity - result.r1.MulByElement(&result.r1, &P.X) - result.r0.MulByElement(&result.r0, &P.Y) - //result.r2.MulByElement(&result.r2, &P.Z) + result.r1.Mul(&result.r1, &P.X) + result.r0.Mul(&result.r0, &P.Y) + //result.r2.Mul(&result.r2, &P.Z) } // Same as above but R is in affine coords @@ -164,18 +335,130 @@ func lineEvalAffine(Q G2Jac, R G2Affine, P *G1Affine, result *lineEvalRes) { result.r2.Sub(&result.r2, &Q.Y) // multiply P.Z by coeffs[2] in case P is infinity - result.r1.MulByElement(&result.r1, &P.X) - result.r0.MulByElement(&result.r0, &P.Y) - // result.r2.MulByElement(&result.r2, &P.Z) + result.r1.Mul(&result.r1, &P.X) + result.r0.Mul(&result.r0, &P.Y) + // result.r2.Mul(&result.r2, &P.Z) } type lineEvalRes struct { - r0 e2 // c0.b1 - r1 e2 // c1.b1 - r2 e2 // c1.b2 + r0 G2CoordType // c0.b1 + r1 G2CoordType // c1.b1 + r2 G2CoordType // c1.b2 } func (l *lineEvalRes) mulAssign(z *PairingResult) *PairingResult { + var a, b, c PairingResult + a.MulByVMinusThree(z, &l.r1) + b.MulByVminusTwo(z, &l.r0) + c.MulByVminusFive(z, &l.r2) + z.Add(&a, &b).Add(z, &c) + + return z +} + +const tAbsVal uint64 = 9586122913090633729 + +// Expt set z to x^t in PairingResult and return z +// TODO make a ExptAssign method that assigns the result to self; then this method can assert fail if z != x +// TODO Expt is the only method that depends on tAbsVal. The rest of the tower does not depend on this value. Logically, Expt should be separated from the rest of the tower. +func (z *PairingResult) Expt(x *PairingResult) *PairingResult { + // TODO what if x==0? + // TODO make this match Element.Exp: x is a non-pointer? + + // tAbsVal in binary: 1000010100001000110000000000000000000000000000000000000000000001 + // drop the low 46 bits (all 0 except the least significant bit): 100001010000100011 = 136227 + // Shortest addition chains can be found at https://wwwhomes.uni-bielefeld.de/achim/addition_chain.html + + var result, x33 PairingResult + + // a shortest addition chain for 136227 + result.Set(x) // 0 1 + result.Square(&result) // 1( 0) 2 + result.Square(&result) // 2( 1) 4 + result.Square(&result) // 3( 2) 8 + result.Square(&result) // 4( 3) 16 + result.Square(&result) // 5( 4) 32 + result.Mul(&result, x) // 6( 5, 0) 33 + x33.Set(&result) // save x33 for step 14 + result.Square(&result) // 7( 6) 66 + result.Square(&result) // 8( 7) 132 + result.Square(&result) // 9( 8) 264 + result.Square(&result) // 10( 9) 528 + result.Square(&result) // 11(10) 1056 + result.Square(&result) // 12(11) 2112 + result.Square(&result) // 13(12) 4224 + result.Mul(&result, &x33) // 14(13, 6) 4257 + result.Square(&result) // 15(14) 8514 + result.Square(&result) // 16(15) 17028 + result.Square(&result) // 17(16) 34056 + result.Square(&result) // 18(17) 68112 + result.Mul(&result, x) // 19(18, 0) 68113 + result.Square(&result) // 20(19) 136226 + result.Mul(&result, x) // 21(20, 0) 136227 + + // the remaining 46 bits + for i := 0; i < 46; i++ { + result.Square(&result) + } + result.Mul(&result, x) + + z.Set(&result) + return z +} + +// MulByVMinusThree set z to x*(y*v**-3) and return z (Fp6(v) where v**3=u, v**6=-4, so v**-3 = u**-1 = (-4)**-1*u) +func (z *PairingResult) MulByVMinusThree(x *PairingResult, y *G2CoordType) *PairingResult { + + var fourinv G2CoordType // (-4)**-1 + fourinv.SetString("5168587788236799404547592261706743156859751684402112582135342620157217566682618802065762387467058765730648425815339960088371319340415685819512133774343976199213703824533881637779407723567697596963924775322476834632073684839301224") + + // tmp = y*(-4)**-1 * u + var tmp E2 + tmp.A0.SetZero() + tmp.A1.Mul(y, &fourinv) + + z.MulByE2(x, &tmp) + + return z +} + +// MulByVminusTwo set z to x*(y*v**-2) and return z (Fp6(v) where v**3=u, v**6=-4, so v**-2 = (-4)**-1*u*v) +func (z *PairingResult) MulByVminusTwo(x *PairingResult, y *G2CoordType) *PairingResult { + + var fourinv G2CoordType // (-4)**-1 + fourinv.SetString("5168587788236799404547592261706743156859751684402112582135342620157217566682618802065762387467058765730648425815339960088371319340415685819512133774343976199213703824533881637779407723567697596963924775322476834632073684839301224") + + // tmp = y*(-4)**-1 * u + var tmp E2 + tmp.A0.SetZero() + tmp.A1.Mul(y, &fourinv) + + var a E2 + a.MulByElement(&x.B2, y) + z.B2.Mul(&x.B1, &tmp) + z.B1.Mul(&x.B0, &tmp) + z.B0.Set(&a) + + return z +} + +// MulByVminusFive set z to x*(y*v**-5) and return z (Fp6(v) where v**3=u, v**6=-4, so v**-5 = (-4)**-1*v) +func (z *PairingResult) MulByVminusFive(x *PairingResult, y *G2CoordType) *PairingResult { + + var fourinv G2CoordType // (-4)**-1 + fourinv.SetString("5168587788236799404547592261706743156859751684402112582135342620157217566682618802065762387467058765730648425815339960088371319340415685819512133774343976199213703824533881637779407723567697596963924775322476834632073684839301224") + + // tmp = y*(-4)**-1 * u + var tmp E2 + tmp.A0.SetZero() + tmp.A1.Mul(y, &fourinv) + + var a E2 + a.Mul(&x.B2, &tmp) + z.B2.MulByElement(&x.B1, &tmp.A1) + z.B1.MulByElement(&x.B0, &tmp.A1) + z.B0.Set(&a) + return z } diff --git a/bw6_761/pairing_test.go b/bw6_761/pairing_test.go new file mode 100644 index 0000000000..ba2b654509 --- /dev/null +++ b/bw6_761/pairing_test.go @@ -0,0 +1,149 @@ +// Code generated by internal/pairing DO NOT EDIT +package bw6_761 + +import ( + "testing" + + "github.com/consensys/gurvy/bw6_761/fr" +) + +func TestMagicPairing(t *testing.T) { + t.Skip("wip") + var r1, r2 PairingResult + + r1.SetRandom() + r2.SetRandom() + + t.Log(r1) + t.Log(r2) + + curve := BW6_761() + + res1 := curve.FinalExponentiation(&r1) + res2 := curve.FinalExponentiation(&r2) + + if res1.Equal(&res2) { + t.Fatal("TestMagicPairing failed") + } +} + +func TestComputePairing(t *testing.T) { + + curve := BW6_761() + + G := curve.g2Gen.Clone() + P := curve.g1Gen.Clone() + sG := G.Clone() + sP := P.Clone() + + var Gaff, sGaff G2Affine + var Paff, sPaff G1Affine + + // checking bilinearity + + // check 1 + scalar := fr.Element{123} + sG.ScalarMul(curve, sG, scalar) + sP.ScalarMul(curve, sP, scalar) + + var mRes1, mRes2, mRes3 PairingResult + + P.ToAffineFromJac(&Paff) + sP.ToAffineFromJac(&sPaff) + + G.ToAffineFromJac(&Gaff) + sG.ToAffineFromJac(&sGaff) + + res1 := curve.FinalExponentiation(curve.MillerLoop(Paff, sGaff, &mRes1)) + res2 := curve.FinalExponentiation(curve.MillerLoop(sPaff, Gaff, &mRes2)) + + if !res1.Equal(&res2) { + t.Fatal("pairing failed") + } + + // check 2 + s1G := G.Clone() + s2G := G.Clone() + s3G := G.Clone() + s1 := fr.Element{29372983} + s2 := fr.Element{209302420904} + var s3 fr.Element + s3.Add(&s1, &s2) + s1G.ScalarMul(curve, s1G, s1) + s2G.ScalarMul(curve, s2G, s2) + s3G.ScalarMul(curve, s3G, s3) + + var s1Gaff, s2Gaff, s3Gaff G2Affine + s1G.ToAffineFromJac(&s1Gaff) + s2G.ToAffineFromJac(&s2Gaff) + s3G.ToAffineFromJac(&s3Gaff) + + rs1 := curve.FinalExponentiation(curve.MillerLoop(Paff, s1Gaff, &mRes1)) + rs2 := curve.FinalExponentiation(curve.MillerLoop(Paff, s2Gaff, &mRes2)) + rs3 := curve.FinalExponentiation(curve.MillerLoop(Paff, s3Gaff, &mRes3)) + rs1.Mul(&rs2, &rs1) + if !rs3.Equal(&rs1) { + t.Fatal("pairing failed2") + } + +} + +//--------------------// +// benches // +//--------------------// + +func BenchmarkLineEval(b *testing.B) { + + curve := BW6_761() + + H := G2Jac{} + H.ScalarMul(curve, &curve.g2Gen, fr.Element{1213}) + + lRes := &lineEvalRes{} + var g1GenAff G1Affine + curve.g1Gen.ToAffineFromJac(&g1GenAff) + b.ResetTimer() + for i := 0; i < b.N; i++ { + lineEvalJac(curve.g2Gen, H, &g1GenAff, lRes) + } + +} + +func BenchmarkPairing(b *testing.B) { + + curve := BW6_761() + + var mRes PairingResult + + var g1GenAff G1Affine + var g2GenAff G2Affine + + curve.g1Gen.ToAffineFromJac(&g1GenAff) + curve.g2Gen.ToAffineFromJac(&g2GenAff) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + curve.FinalExponentiation(curve.MillerLoop(g1GenAff, g2GenAff, &mRes)) + } +} + +func BenchmarkFinalExponentiation(b *testing.B) { + + var a PairingResult + + curve := BW6_761() + + a.SetString( + "1382424129690940106527336948935335363935127549146605398842626667204683483408227749", + "0121296909401065273369489353353639351275491466053988426266672046834834082277499690", + "7336948129690940106527336948935335363935127549146605398842626667204683483408227749", + "6393512129690940106527336948935335363935127549146605398842626667204683483408227749", + "2581296909401065273369489353353639351275491466053988426266672046834834082277496644", + "5331296909401065273369489353353639351275491466053988426266672046834834082277495363") + + b.ResetTimer() + for i := 0; i < b.N; i++ { + curve.FinalExponentiation(&a) + } + +} diff --git a/go.mod b/go.mod index 40c7253feb..81f5fc91d4 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/consensys/gurvy go 1.14 require ( - github.com/consensys/bavard v0.1.2-0.20200424125854-c0225aa55321 + github.com/consensys/bavard v0.1.2-0.20200529165929-d36a82510300 github.com/consensys/goff v0.2.3-0.20200423152648-e4125d01b786 github.com/pkg/profile v1.4.0 github.com/spf13/cobra v1.0.0 // indirect diff --git a/go.sum b/go.sum index 56f41ec25e..6efcacee74 100644 --- a/go.sum +++ b/go.sum @@ -12,6 +12,10 @@ github.com/consensys/bavard v0.1.1 h1:sFtk3U10YO4Mt8NNCEZQhMzoQ9UMy2H5GKOx/DwNg8 github.com/consensys/bavard v0.1.1/go.mod h1:ffZkLPNQSN3E6u+zpArQSleJ/lsraMwKPCHQymPQJtM= github.com/consensys/bavard v0.1.2-0.20200424125854-c0225aa55321 h1:UxuPJ/fA9yD4x9sxZg11ozJFtGnjIDqPXXvrJJSuUTI= github.com/consensys/bavard v0.1.2-0.20200424125854-c0225aa55321/go.mod h1:ffZkLPNQSN3E6u+zpArQSleJ/lsraMwKPCHQymPQJtM= +github.com/consensys/bavard v0.1.2-0.20200529000710-aadfd92a414b h1:Y0Gjdsba4/mXKuBFnE4ZoeEw37EF37aUeNfGA+k+lnc= +github.com/consensys/bavard v0.1.2-0.20200529000710-aadfd92a414b/go.mod h1:ffZkLPNQSN3E6u+zpArQSleJ/lsraMwKPCHQymPQJtM= +github.com/consensys/bavard v0.1.2-0.20200529165929-d36a82510300 h1:P+CQRenUcTRBELnrNxcSxLotXvHDwn8PKp5XkaruUXc= +github.com/consensys/bavard v0.1.2-0.20200529165929-d36a82510300/go.mod h1:ffZkLPNQSN3E6u+zpArQSleJ/lsraMwKPCHQymPQJtM= github.com/consensys/goff v0.2.1 h1:sBdsFEetlPpXnZJR0WtZaU6X+dDCejbHqG8M21WJtk8= github.com/consensys/goff v0.2.1/go.mod h1:CsKD9nM1/fD0gqJs0vRCyQ/wocVjex+wa3mVEjC6h+s= github.com/consensys/goff v0.2.2 h1:/iNN1B1HundCfxGPiAX9AdARh2miPywe/o62mRJUjr4= diff --git a/internal/generators/curve/curve.go b/internal/generators/curve/curve.go new file mode 100644 index 0000000000..40d7bc137c --- /dev/null +++ b/internal/generators/curve/curve.go @@ -0,0 +1,74 @@ +package curve + +const ( + fpName = "fp" + frName = "fr" + fp2Name = "E2" + fp6Name = "E6" + fp12Name = "E12" + pointName = "G" +) + +// Data data used to generate the templates +type Data struct { + Fpackage string + FpModulus string + FrModulus string + Fp2NonResidue string + Fp6NonResidue string + EmbeddingDegree int + + // pairing + T string + TNeg bool + + // gpoint + PointName string // TODO this name cannot change; remove it + ThirdRootOne string + Lambda string + Size1 string + Size2 string // TODO this is a function of Size1; remove it + + // data needed in the template, initialized to constants by Init() method + FpName string + FrName string + Fp2Name string + Fp6Name string + Fp12Name string +} + +// Init initialize string constants such as z.Fp2Name, etc; return z +func (z *Data) Init() *Data { + z.FpName = fpName + z.FrName = frName + z.Fp2Name = fp2Name + z.Fp6Name = fp6Name + z.Fp12Name = fp12Name + z.PointName = pointName + return z +} + +// CTemplate is the template to generate code to initialize C to a specific curve +const CTemplate = ` +// C holds data for a specific curve +// Examples: BLS12-381, BLS12-377, BN256, BW6-761 +var C Data + +func init() { + C = Data{ + Fpackage: "{{$.Fpackage}}", + FpModulus: "{{$.FpModulus}}", + FrModulus: "{{$.FrModulus}}", + Fp2NonResidue: "{{$.Fp2NonResidue}}", + Fp6NonResidue: "{{$.Fp6NonResidue}}", + EmbeddingDegree: {{$.EmbeddingDegree}}, + T: "{{$.T}}", + TNeg: {{$.TNeg}}, + ThirdRootOne: "{{$.ThirdRootOne}}", + Lambda: "{{$.Lambda}}", + Size1: "{{$.Size1}}", + Size2: "{{$.Size2}}", + } + C.Init() +} +` diff --git a/internal/generators/curve/generated-code.go b/internal/generators/curve/generated-code.go new file mode 100644 index 0000000000..7d4f13c174 --- /dev/null +++ b/internal/generators/curve/generated-code.go @@ -0,0 +1,39 @@ +// Copyright 2020 ConsenSys AG +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by gurvy/internal/generators DO NOT EDIT + +package curve + +// C holds data for a specific curve +// Examples: BLS12-381, BLS12-377, BN256, BW6-761 +var C Data + +func init() { + C = Data{ + Fpackage: "bw6_761", + FpModulus: "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068299", + FrModulus: "258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177", + Fp2NonResidue: "-4", + Fp6NonResidue: "0,1", + EmbeddingDegree: 6, + T: "9586122913090633729", + TNeg: false, + ThirdRootOne: "1968985824090209297278610739700577151397666382303825728450741611566800370218827257750865013421937292370006175842381275743914023380727582819905021229583192207421122272650305267822868639090213645505120388400344940985710520836292650", + Lambda: "80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410945", + Size1: "65", + Size2: "316", + } + C.Init() +} diff --git a/internal/generators/gpoint/generator.go b/internal/generators/gpoint/generator.go new file mode 100644 index 0000000000..6d26b96027 --- /dev/null +++ b/internal/generators/gpoint/generator.go @@ -0,0 +1,48 @@ +package gpoint + +import ( + "path/filepath" + "strings" + + "github.com/consensys/bavard" + gpoint "github.com/consensys/gurvy/internal/generators/gpoint/templates" +) + +// Data data used to generate the templates +type Data struct { + Fpackage string + PName string + CoordType string + GroupType string + + // data useful for the "endomorphism trick" to speed up scalar multiplication + Lambda string + ThirdRootOne string + Size1 string + Size2 string +} + +// Generate generates pairing +func Generate(d Data, outputDir string) error { + + rootPath := filepath.Join(outputDir, d.Fpackage) + src := []string{ + gpoint.Base, + gpoint.Add, + gpoint.AddMixed, + gpoint.Double, + // gpoint.EndoMul, + gpoint.ScalarMul, + gpoint.WindowedMultiExp, + gpoint.MultiExp, + } + if err := bavard.Generate(filepath.Join(rootPath, strings.ToLower(d.PName)+".go"), src, d, + bavard.Package(d.Fpackage), + bavard.Apache2("ConsenSys AG", 2020), + bavard.GeneratedBy("gurvy/internal/generators"), + ); err != nil { + return err + } + + return nil +} diff --git a/internal/generators/gpoint/main/main.go b/internal/generators/gpoint/main/main.go new file mode 100644 index 0000000000..ef9ab91ea4 --- /dev/null +++ b/internal/generators/gpoint/main/main.go @@ -0,0 +1,65 @@ +package main + +import ( + "fmt" + "os" + + "github.com/consensys/gurvy/internal/generators/curve" + "github.com/consensys/gurvy/internal/generators/gpoint" +) + +func main() { + + // g1.go + { + d := gpoint.Data{ + Fpackage: curve.C.Fpackage, + PName: curve.C.PointName + "1", + CoordType: curve.C.FpName + ".Element", // TODO refer to other constants + GroupType: curve.C.FrName, + ThirdRootOne: curve.C.ThirdRootOne, + Lambda: curve.C.Lambda, + Size1: curve.C.Size1, + Size2: curve.C.Size2, + } + + // assume working directory is internal/generators + // TODO make this path more robust to changes in working directory + if err := gpoint.Generate(d, "../../"); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(-1) + } + } + + // g2.go + { + // G2: sextic twist => CoordType is a field extension of degree EmbeddingDegree / 6 + var coordType string + switch curve.C.EmbeddingDegree { + case 12: + coordType = curve.C.Fp2Name + case 6: + coordType = curve.C.FpName + ".Element" // TODO refer to other constants + default: + panic("embedding degree " + string(curve.C.EmbeddingDegree) + " not implemented") + } + + d := gpoint.Data{ + Fpackage: curve.C.Fpackage, + PName: curve.C.PointName + "2", + CoordType: coordType, + GroupType: curve.C.FrName, + // ThirdRootOne: curve.C.ThirdRootOne, + // Lambda: curve.C.Lambda, + // Size1: curve.C.Size1, + // Size2: curve.C.Size2, + } + + // assume working directory is internal/generators + // TODO make this path more robust to changes in working directory + if err := gpoint.Generate(d, "../../"); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(-1) + } + } +} diff --git a/internal/generators/template/gpoint/add.go b/internal/generators/gpoint/templates/add.go similarity index 95% rename from internal/generators/template/gpoint/add.go rename to internal/generators/gpoint/templates/add.go index 0b756c8bbb..5ce4dbb013 100644 --- a/internal/generators/template/gpoint/add.go +++ b/internal/generators/gpoint/templates/add.go @@ -19,7 +19,7 @@ func (p *{{.PName}}Jac) Add(curve *Curve, a *{{.PName}}Jac) *{{.PName}}Jac { } // get some Element from our pool - var Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V {{.CoordType}} + var Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, J, r, V {{.PName}}CoordType // Z1Z1 = a.Z ^ 2 Z1Z1.Square(&a.Z) @@ -107,7 +107,7 @@ func (p *{{.PName}}Jac) AddMixed(a *{{.PName}}Affine) *{{.PName}}Jac { } // get some Element from our pool - var Z1Z1, U2 , S2, H, HH, I, J, r, V {{.CoordType}} + var Z1Z1, U2 , S2, H, HH, I, J, r, V {{.PName}}CoordType // Z1Z1 = p.Z ^ 2 Z1Z1.Square(&p.Z) diff --git a/internal/generators/template/gpoint/base.go b/internal/generators/gpoint/templates/base.go similarity index 93% rename from internal/generators/template/gpoint/base.go rename to internal/generators/gpoint/templates/base.go index ff55e27897..28af9a1527 100644 --- a/internal/generators/template/gpoint/base.go +++ b/internal/generators/gpoint/templates/base.go @@ -13,19 +13,21 @@ import ( "sync" ) -// {{.PName}}Jac is a point with {{.CoordType}} coordinates +type {{.PName}}CoordType = {{.CoordType}} + +// {{.PName}}Jac is a point with {{.PName}}CoordType coordinates type {{.PName}}Jac struct { - X, Y, Z {{.CoordType}} + X, Y, Z {{.PName}}CoordType } // {{.PName}}Affine point in affine coordinates type {{.PName}}Affine struct { - X, Y {{.CoordType}} + X, Y {{.PName}}CoordType } // {{toLower .PName}}JacExtended parameterized jacobian coordinates (x=X/ZZ, y=Y/ZZZ, ZZ**3=ZZZ**2) type {{toLower .PName}}JacExtended struct { - X, Y, ZZ, ZZZ {{.CoordType}} + X, Y, ZZ, ZZZ {{.PName}}CoordType } // SetInfinity sets p to O @@ -69,7 +71,7 @@ func (p *{{toLower .PName}}JacExtended) mAdd(a *{{.PName}}Affine) *{{toLower .PN return p } - var U2, S2, P, R, PP, PPP, Q, Q2, RR, X3, Y3 {{.CoordType}} + var U2, S2, P, R, PP, PPP, Q, Q2, RR, X3, Y3 {{.PName}}CoordType // p2: a, p1: p U2.Mul(&a.X, &p.ZZ) @@ -99,7 +101,7 @@ func (p *{{toLower .PName}}JacExtended) mAdd(a *{{.PName}}Affine) *{{toLower .PN // http://www.hyperelliptic.org/EFD/{{toLower .PName}}p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1 func (p *{{toLower .PName}}JacExtended) double(q *{{.PName}}Affine) *{{toLower .PName}}JacExtended { - var U, S, M, _M, Y3 {{.CoordType}} + var U, S, M, _M, Y3 {{.PName}}CoordType U.Double(&q.Y) p.ZZ.Square(&U) @@ -179,7 +181,7 @@ func (p *{{.PName}}Jac) Sub(curve *Curve, a {{.PName}}Jac) *{{.PName}}Jac { // WARNING super slow function (due to the division) func (p *{{.PName}}Jac) ToAffineFromJac(res *{{.PName}}Affine) *{{.PName}}Affine { - var bufs [3]{{.CoordType}} + var bufs [3]{{.PName}}CoordType if p.Z.IsZero() { res.X.SetZero() @@ -200,7 +202,7 @@ func (p *{{.PName}}Jac) ToAffineFromJac(res *{{.PName}}Affine) *{{.PName}}Affine // ToProjFromJac converts a point from Jacobian to projective coordinates func (p *{{.PName}}Jac) ToProjFromJac() *{{.PName}}Jac { // memalloc - var buf {{.CoordType}} + var buf {{.PName}}CoordType buf.Square(&p.Z) p.X.Mul(&p.X, &p.Z) @@ -235,7 +237,7 @@ func (p *{{ .PName}}Affine) ToJacobian(Q *{{ .PName}}Jac) *{{ .PName}}Jac { } func (p *{{.PName}}Affine) String(curve *Curve) string { - var x, y {{.CoordType}} + var x, y {{.PName}}CoordType x.Set(&p.X) y.Set(&p.Y) return "E([" + x.String() + "," + y.String() + "])," diff --git a/internal/generators/template/gpoint/benchmarks.go b/internal/generators/gpoint/templates/benchmarks.go similarity index 100% rename from internal/generators/template/gpoint/benchmarks.go rename to internal/generators/gpoint/templates/benchmarks.go diff --git a/internal/generators/template/gpoint/double.go b/internal/generators/gpoint/templates/double.go similarity index 94% rename from internal/generators/template/gpoint/double.go rename to internal/generators/gpoint/templates/double.go index 2a463cd419..d7bae71393 100644 --- a/internal/generators/template/gpoint/double.go +++ b/internal/generators/gpoint/templates/double.go @@ -6,7 +6,7 @@ const Double = ` // https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2007-bl func (p *{{.PName}}Jac) Double() *{{.PName}}Jac { // get some Element from our pool - var XX, YY, YYYY, ZZ, S, M, T {{.CoordType}} + var XX, YY, YYYY, ZZ, S, M, T {{.PName}}CoordType // XX = a.X^2 XX.Square(&p.X) diff --git a/internal/generators/template/gpoint/scalarmul.go b/internal/generators/gpoint/templates/scalarmul.go similarity index 100% rename from internal/generators/template/gpoint/scalarmul.go rename to internal/generators/gpoint/templates/scalarmul.go diff --git a/internal/generators/template/gpoint/tests.go b/internal/generators/gpoint/templates/tests.go similarity index 100% rename from internal/generators/template/gpoint/tests.go rename to internal/generators/gpoint/templates/tests.go diff --git a/internal/generators/main.go b/internal/generators/main.go index 473bdd1cf7..89291bb8a9 100644 --- a/internal/generators/main.go +++ b/internal/generators/main.go @@ -3,120 +3,188 @@ package main import ( "fmt" "os" + "os/exec" - "github.com/consensys/gurvy/internal/generators/template/generator" + "github.com/consensys/bavard" + "github.com/consensys/gurvy/internal/generators/curve" + "github.com/consensys/gurvy/internal/generators/pairing" + "github.com/consensys/gurvy/internal/generators/tower" ) -//go:generate go run main.go -func main() { +// TODO move all this curve data to config file(s)? +// ------------------------------------------------------------------------------------------------- +// bls381 +var bls381 curve.Data = curve.Data{ + Fpackage: "bls381", + FpModulus: "4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787", + FrModulus: "52435875175126190479447740508185965837690552500527637822603658699938581184513", + Fp2NonResidue: "-1", + Fp6NonResidue: "1,1", + EmbeddingDegree: 12, + T: "15132376222941642752", + TNeg: true, + ThirdRootOne: "4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436", + Lambda: "228988810152649578064853576960394133503", + Size1: "128", + Size2: "128", +} - // ------------------------------------------------------------------------------------------------- - // bls381 - bls381 := generator.GenerateData{ - Fpackage: "bls381", - RootPath: "../../bls381/", - FpModulus: "4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787", - FpName: "fp", - FrModulus: "52435875175126190479447740508185965837690552500527637822603658699938581184513", - FrName: "fr", - Fp2Name: "E2", - Fp2NonResidue: "-1", - Fp6Name: "E6", - Fp6NonResidue: "1,1", - Fp12Name: "E12", - MakePairing: true, - T: "15132376222941642752", - TNeg: true, - PointName: "G", - ThirdRootOne: "4002409555221667392624310435006688643935503118305586438271171395842971157480381377015405980053539358417135540939436", - Lambda: "228988810152649578064853576960394133503", - Size1: "128", - Size2: "128", - } +// ------------------------------------------------------------------------------------------------- +// bls377 +var bls377 curve.Data = curve.Data{ + Fpackage: "bls377", + FpModulus: "258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177", + FrModulus: "8444461749428370424248824938781546531375899335154063827935233455917409239041", + Fp2NonResidue: "5", + Fp6NonResidue: "0,1", + EmbeddingDegree: 12, + T: "9586122913090633729", + TNeg: false, + ThirdRootOne: "80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410945", + Lambda: "91893752504881257701523279626832445440", + Size1: "129", + Size2: "127", +} - // ------------------------------------------------------------------------------------------------- - // bls377 - bls377 := generator.GenerateData{ - Fpackage: "bls377", - RootPath: "../../bls377/", - FpModulus: "258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177", - FpName: "fp", - FrModulus: "8444461749428370424248824938781546531375899335154063827935233455917409239041", - FrName: "fr", - Fp2Name: "E2", - Fp2NonResidue: "5", - Fp6Name: "E6", - Fp6NonResidue: "0,1", - Fp12Name: "E12", - MakePairing: true, - T: "9586122913090633729", - TNeg: false, - PointName: "G", - ThirdRootOne: "80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410945", - Lambda: "91893752504881257701523279626832445440", - Size1: "129", - Size2: "127", - } +// ------------------------------------------------------------------------------------------------- +// bn256 +var bn256 curve.Data = curve.Data{ + Fpackage: "bn256", + FpModulus: "21888242871839275222246405745257275088696311157297823662689037894645226208583", + FrModulus: "21888242871839275222246405745257275088548364400416034343698204186575808495617", + Fp2NonResidue: "-1", + Fp6NonResidue: "9,1", + EmbeddingDegree: 12, + T: "4965661367192848881", + TNeg: false, + ThirdRootOne: "2203960485148121921418603742825762020974279258880205651966", + Lambda: "4407920970296243842393367215006156084916469457145843978461", + Size1: "65", + Size2: "191", +} - // ------------------------------------------------------------------------------------------------- - // bn256 - bn256 := generator.GenerateData{ - Fpackage: "bn256", - RootPath: "../../bn256/", - FpModulus: "21888242871839275222246405745257275088696311157297823662689037894645226208583", - FpName: "fp", - FrModulus: "21888242871839275222246405745257275088548364400416034343698204186575808495617", - FrName: "fr", - Fp2Name: "E2", - Fp2NonResidue: "-1", - Fp6Name: "E6", - Fp6NonResidue: "9,1", - Fp12Name: "E12", - MakePairing: true, - T: "4965661367192848881", - TNeg: false, - PointName: "G", - ThirdRootOne: "2203960485148121921418603742825762020974279258880205651966", - Lambda: "4407920970296243842393367215006156084916469457145843978461", - Size1: "65", - Size2: "191", - } +// ------------------------------------------------------------------------------------------------- +// BW6-781 +var bw6_761 curve.Data = curve.Data{ + Fpackage: "bw6_761", + FpModulus: "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068299", + FrModulus: bls377.FpModulus, + Fp2NonResidue: "-4", + Fp6NonResidue: "0,1", + EmbeddingDegree: 6, + T: bls377.T, + TNeg: bls377.TNeg, + ThirdRootOne: "1968985824090209297278610739700577151397666382303825728450741611566800370218827257750865013421937292370006175842381275743914023380727582819905021229583192207421122272650305267822868639090213645505120388400344940985710520836292650", + Lambda: "80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410945", + Size1: "65", + Size2: "316", +} - // ------------------------------------------------------------------------------------------------- - // BW6-781 - bw6_761 := generator.GenerateData{ - Fpackage: "bw6_761", - RootPath: "../../bw6_761/", - FpModulus: "6891450384315732539396789682275657542479668912536150109513790160209623422243491736087683183289411687640864567753786613451161759120554247759349511699125301598951605099378508850372543631423596795951899700429969112842764913119068299", - FpName: "fp", - FrModulus: bls377.FpModulus, - FrName: "fr", - Fp2Name: "e2", - Fp2NonResidue: "-1", - Fp6Name: "e6", - Fp6NonResidue: "1,1", - MakePairing: true, - T: "4371281006305286848163485150587564217350348383473813272171392617577304305730246023460948554022786", // TODO this is the hard part exponent. Implement the optimized hard part from Appendix B of https://eprint.iacr.org/2020/351.pdf - TNeg: false, - PointName: "G", - ThirdRootOne: "1968985824090209297278610739700577151397666382303825728450741611566800370218827257750865013421937292370006175842381275743914023380727582819905021229583192207421122272650305267822868639090213645505120388400344940985710520836292650", - Lambda: "80949648264912719408558363140637477264845294720710499478137287262712535938301461879813459410945", - Size1: "65", - Size2: "316", - } +//go:generate go run main.go +func main() { - curve := [...]generator.GenerateData{ + curves := [...]curve.Data{ bls381, bls377, bn256, - // bw6_761, + bw6_761, } - _ = bw6_761 // TODO temporary: avoid compile error - for _, d := range curve { - if err := generator.GenerateCurve(d); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(-1) + for _, d := range curves { + + // TODO refactor calls to bavard.Generate, exec.Command + + d.Init() + + // generate curve.C + { + src := []string{ + curve.CTemplate, + } + if err := bavard.Generate("curve/generated-code.go", src, d, + bavard.Package("curve"), + bavard.Apache2("ConsenSys AG", 2020), + bavard.GeneratedBy("gurvy/internal/generators"), + ); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(-1) + } + } + + // generate primefield (uses curve.C) + { + cmd := exec.Command("go", "run", "./primefields/main/main.go") + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + // fmt.Fprintln(os.Stderr, err) + os.Exit(-1) + } + } + + // generate tower generator (uses curve.C, primefield) + { + src := []string{ + tower.TwoInvTemplate, + } + if err := bavard.Generate("tower/generated-code.go", src, d, + bavard.Package("tower"), + bavard.Apache2("ConsenSys AG", 2020), + bavard.GeneratedBy("gurvy/internal/generators"), + ); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(-1) + } + } + + // generate tower (uses curve.C) + { + cmd := exec.Command("go", "run", "./tower/main/main.go") + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + // fmt.Fprintln(os.Stderr, err) + os.Exit(-1) + } } + + // generate gpoint (uses curve.C) + { + cmd := exec.Command("go", "run", "./gpoint/main/main.go") + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + // fmt.Fprintln(os.Stderr, err) + os.Exit(-1) + } + } + + // generate pairing generator (uses curve.C, tower) + { + src := []string{ + pairing.ImportsTemplate, + } + if err := bavard.Generate("pairing/generated-code.go", src, d, + bavard.Package("pairing"), + bavard.Apache2("ConsenSys AG", 2020), + bavard.GeneratedBy("gurvy/internal/generators"), + ); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(-1) + } + } + + // generate pairing (uses curve.C) + { + cmd := exec.Command("go", "run", "./pairing/main/main.go") + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + // fmt.Fprintln(os.Stderr, err) + os.Exit(-1) + } + } + + // generate gpoint } } diff --git a/internal/generators/pairing/constants.go b/internal/generators/pairing/constants.go new file mode 100644 index 0000000000..55855c702c --- /dev/null +++ b/internal/generators/pairing/constants.go @@ -0,0 +1,145 @@ +// Copyright 2020 ConsenSys AG +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package pairing + +import ( + "math/big" + "math/bits" + "strings" +) + +type fp2Template struct { + fp2 + A0String, A1String string // base 10 +} + +// InitFrobenius set z.Frobenius to constants gamma[i][j] +// from https://eprint.iacr.org/2010/354.pdf (Section 3.2) +// gamma[i][j] = Fp6NonResidue^(j*(p^i-1)/d) +// where: +// d = EmbeddingDegree / 2 +// i = range [1,2,3] +// j = range [1,...,d-1] +func (z *Data) InitFrobenius() *Data { + + // compute d + switch z.EmbeddingDegree { + case 6, 12: + default: + panic("unsupported embedding degree") + } + d := (uint64)(z.EmbeddingDegree / 2) + + // allocate memory + z.Frobenius = make([][]fp2Template, 3) // constants for Frobenius up to exponent 3 + for i := range z.Frobenius { + z.Frobenius[i] = make([]fp2Template, d-1) + } + + // parse Fp6NonResidue + var nonResidue fp2Template + { + nonResidueStrings := strings.Split(z.Fp6NonResidue, ",") + if len(nonResidueStrings) != 2 { + panic("malformed Fp6NonResidue string") + } + nonResidue.A0.SetString(nonResidueStrings[0]) + nonResidue.A1.SetString(nonResidueStrings[1]) + } + + // compute exponent (p-1)/d + var exponent big.Int + exponent.Set(primeModulus()) + { + var i big.Int + i.SetUint64(1) + exponent.Sub(&exponent, &i) + i.SetUint64(d) + exponent.Div(&exponent, &i) + } + + // compute gamma = nonResidue^exponent + // all other constants are derived from gamma + var gamma fp2Template + gamma.exp(&nonResidue, toUint64Slice(&exponent)...) + + // compute gamma[i][j] as in https://eprint.iacr.org/2010/354.pdf (Section 3.2) + z.Frobenius[0][0].Set(&gamma.fp2) + for j := 1; j < len(z.Frobenius[0]); j++ { + z.Frobenius[0][j].Set(&z.Frobenius[0][j-1].fp2). + MulAssign(&gamma.fp2) + } + for j := range z.Frobenius[1] { + z.Frobenius[1][j].Conjugate(&z.Frobenius[0][j].fp2). + MulAssign(&z.Frobenius[0][j].fp2) + } + for j := range z.Frobenius[2] { + z.Frobenius[2][j].Set(&z.Frobenius[0][j].fp2). + MulAssign(&z.Frobenius[1][j].fp2) + } + + // compute helper data on gamma[i][j] for the template generator + for i := range z.Frobenius { + for j := range z.Frobenius[i] { + f := &z.Frobenius[i][j] + f.A0String = f.A0.String() + f.A1String = f.A1.String() + } + } + + return z +} + +// code copied from goff +func toUint64Slice(b *big.Int) (s []uint64) { + s = make([]uint64, len(b.Bits())) + for i, v := range b.Bits() { + s[i] = (uint64)(v) + } + return +} + +// exp sets z = x^exponent in fp2Template, return z +// exponent (non-montgomery form) is ordered from least significant word to most significant word +// code copied from goff +func (z *fp2Template) exp(x *fp2Template, exponent ...uint64) *fp2Template { + r := 0 + msb := 0 + for i := len(exponent) - 1; i >= 0; i-- { + if exponent[i] == 0 { + r++ + } else { + msb = (i * 64) + bits.Len64(exponent[i]) + break + } + } + exponent = exponent[:len(exponent)-r] + if len(exponent) == 0 { + z.A0.SetOne() + z.A1.SetZero() + return z + } + + z.Set(&x.fp2) + + l := msb - 2 + for i := l; i >= 0; i-- { + z.Square(&z.fp2) + if exponent[i/64]&(1<= 2 { + src := []string{ + fp2.Base, + fp2.Inline, + fp2.Mul, + } + if err := bavard.Generate(filepath.Join(rootPath, strings.ToLower(d.Fp2Name)+".go"), src, d, + bavard.Package(d.Fpackage), + bavard.Apache2("ConsenSys AG", 2020), + bavard.GeneratedBy("gurvy/internal/generators"), + ); err != nil { + return err + } + } + + // fp6 + if d.EmbeddingDegree >= 6 { + src := []string{ + fp6.Base, + fp2.Inline, + fp6.Inline, + fp6.Mul, + } + if err := bavard.Generate(filepath.Join(rootPath, strings.ToLower(d.Fp6Name)+".go"), src, d, + bavard.Package(d.Fpackage), + bavard.Apache2("ConsenSys AG", 2020), + bavard.GeneratedBy("gurvy/internal/generators"), + ); err != nil { + return err + } + } + + // fp12 + if d.EmbeddingDegree >= 12 { + src := []string{ + fp12.Base, + fp2.Inline, + fp6.Inline, + fp12.Inline, + fp12.Mul, + } + if err := bavard.Generate(filepath.Join(rootPath, strings.ToLower(d.Fp12Name)+".go"), src, d, + bavard.Package(d.Fpackage), + bavard.Apache2("ConsenSys AG", 2020), + bavard.GeneratedBy("gurvy/internal/generators"), + ); err != nil { + return err + } + } + + return nil +} + +// InitTwoInv set z.TwoInv to the inverse of 2 as an fp.Element +func (z *Data) InitTwoInv() *Data { + var twoInv fpElement + twoInv.SetUint64(2).Inverse(&twoInv) + z.TwoInv = twoInv[:] + return z +} + +const TwoInvTemplate = ` +import "github.com/consensys/gurvy/{{$.Fpackage}}/fp" + +type fpElement = fp.Element +` diff --git a/internal/generators/tower/main/main.go b/internal/generators/tower/main/main.go new file mode 100644 index 0000000000..ef3f35c577 --- /dev/null +++ b/internal/generators/tower/main/main.go @@ -0,0 +1,29 @@ +package main + +import ( + "fmt" + "os" + + "github.com/consensys/gurvy/internal/generators/curve" + "github.com/consensys/gurvy/internal/generators/tower" +) + +func main() { + + d := tower.Data{ + Fpackage: curve.C.Fpackage, + Fp2NonResidue: curve.C.Fp2NonResidue, + Fp6NonResidue: curve.C.Fp6NonResidue, + EmbeddingDegree: curve.C.EmbeddingDegree, + Fp2Name: curve.C.Fp2Name, + Fp6Name: curve.C.Fp6Name, + Fp12Name: curve.C.Fp12Name, + } + + // assume working directory is internal/generators + // TODO make this path more robust to changes in working directory + if err := tower.Generate(d, "../../"); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(-1) + } +} diff --git a/internal/generators/template/tower/fp12/base.go b/internal/generators/tower/templates/fp12/base.go similarity index 100% rename from internal/generators/template/tower/fp12/base.go rename to internal/generators/tower/templates/fp12/base.go diff --git a/internal/generators/template/tower/fp12/inline.go b/internal/generators/tower/templates/fp12/inline.go similarity index 100% rename from internal/generators/template/tower/fp12/inline.go rename to internal/generators/tower/templates/fp12/inline.go diff --git a/internal/generators/template/tower/fp12/mul.go b/internal/generators/tower/templates/fp12/mul.go similarity index 100% rename from internal/generators/template/tower/fp12/mul.go rename to internal/generators/tower/templates/fp12/mul.go diff --git a/internal/generators/template/tower/fp12/testpoints.go.backup b/internal/generators/tower/templates/fp12/testpoints.go.backup similarity index 100% rename from internal/generators/template/tower/fp12/testpoints.go.backup rename to internal/generators/tower/templates/fp12/testpoints.go.backup diff --git a/internal/generators/template/tower/fp2/base.go b/internal/generators/tower/templates/fp2/base.go similarity index 100% rename from internal/generators/template/tower/fp2/base.go rename to internal/generators/tower/templates/fp2/base.go diff --git a/internal/generators/template/tower/fp2/inline.go b/internal/generators/tower/templates/fp2/inline.go similarity index 90% rename from internal/generators/template/tower/fp2/inline.go rename to internal/generators/tower/templates/fp2/inline.go index 681c8f5d24..30d33cbab1 100644 --- a/internal/generators/template/tower/fp2/inline.go +++ b/internal/generators/tower/templates/fp2/inline.go @@ -18,8 +18,11 @@ const Inline = ` {{- else if eq $.all.Fp2NonResidue "3" }} buf := *({{$.in}}) ({{$.out}}).Double(&buf).AddAssign(&buf) + {{- else if eq $.all.Fp2NonResidue "-4" }} + buf := *({{$.in}}) + ({{$.out}}).Double(&buf).Double({{$.out}}).Neg({{$.out}}) {{- else }} - panic("not implemented yet") + // TODO not implemented {{- end }} {{- end }} @@ -52,7 +55,7 @@ const Inline = ` } ({{$.out}}).Mul(({{$.in}}), &nrinv) {{- else }} - panic("not implemented yet") + // TODO not implemented {{- end }} {{- end }} ` diff --git a/internal/generators/template/tower/fp2/mul.go b/internal/generators/tower/templates/fp2/mul.go similarity index 100% rename from internal/generators/template/tower/fp2/mul.go rename to internal/generators/tower/templates/fp2/mul.go diff --git a/internal/generators/template/tower/fp2/testpoints.go.backup b/internal/generators/tower/templates/fp2/testpoints.go.backup similarity index 100% rename from internal/generators/template/tower/fp2/testpoints.go.backup rename to internal/generators/tower/templates/fp2/testpoints.go.backup diff --git a/internal/generators/template/tower/fp6/base.go b/internal/generators/tower/templates/fp6/base.go similarity index 100% rename from internal/generators/template/tower/fp6/base.go rename to internal/generators/tower/templates/fp6/base.go diff --git a/internal/generators/template/tower/fp6/inline.go b/internal/generators/tower/templates/fp6/inline.go similarity index 94% rename from internal/generators/template/tower/fp6/inline.go rename to internal/generators/tower/templates/fp6/inline.go index d64cde233a..fe85b61e6e 100644 --- a/internal/generators/template/tower/fp6/inline.go +++ b/internal/generators/tower/templates/fp6/inline.go @@ -31,7 +31,7 @@ const Inline = ` {{- template "fpInlineMulByNonResidue" dict "all" $.all "out" (print "&(" $.out ").A0") "in" "&buf.A1" }} {{$.out}}.A0.AddAssign(&buf9.A0) {{- else}} - panic("not implemented yet") + // TODO not implemented {{- end }} {{- end }} @@ -53,12 +53,8 @@ const Inline = ` ({{$.out}}).A0.Add(&buf.A0, &buf.A1) ({{$.out}}).A1.Sub(&buf.A1, &buf.A0) twoInv := fp.Element{ - 1730508156817200468, - 9606178027640717313, - 7150789853162776431, - 7936136305760253186, - 15245073033536294050, - 1728177566264616342, + {{- range $i := .all.TwoInv}} + {{$i}},{{end}} } ({{$.out}}).A0.MulAssign(&twoInv) ({{$.out}}).A1.MulAssign(&twoInv) @@ -107,7 +103,7 @@ const Inline = ` ({{$.out}}).A0.MulAssign(&buf78inv) ({{$.out}}).A1.MulAssign(&buf78inv) {{- else}} - panic("not implemented yet") + // TODO not implemented {{- end }} {{- end }} ` diff --git a/internal/generators/template/tower/fp6/mul.go b/internal/generators/tower/templates/fp6/mul.go similarity index 73% rename from internal/generators/template/tower/fp6/mul.go rename to internal/generators/tower/templates/fp6/mul.go index 31c01bbc0e..937f2b3f70 100644 --- a/internal/generators/template/tower/fp6/mul.go +++ b/internal/generators/tower/templates/fp6/mul.go @@ -1,39 +1,53 @@ package fp6 const Mul = ` -// Mul multiplies two numbers in {{.Fp6Name}} +// Mul sets z to the {{.Fp6Name}}-product of x,y, returns z func (z *{{.Fp6Name}}) Mul(x, y *{{.Fp6Name}}) *{{.Fp6Name}} { + {{ template "mul" dict "all" . "V1" "x" "V2" "y"}} + return z +} + +// MulAssign sets z to the {{.Fp6Name}}-product of z,x returns z +func (z *{{.Fp6Name}}) MulAssign(x *{{.Fp6Name}}) *{{.Fp6Name}} { + {{ template "mul" dict "all" . "V1" "z" "V2" "x"}} + return z +} + +{{- define "mul" }} // Algorithm 13 from https://eprint.iacr.org/2010/354.pdf - var rb0, b0, b1, b2, b3, b4 {{.Fp2Name}} - b0.Mul(&x.B0, &y.B0) // step 1 - b1.Mul(&x.B1, &y.B1) // step 2 - b2.Mul(&x.B2, &y.B2) // step 3 + var rb0, b0, b1, b2, b3, b4 {{.all.Fp2Name}} + b0.Mul(&{{.V1}}.B0, &{{.V2}}.B0) // step 1 + b1.Mul(&{{.V1}}.B1, &{{.V2}}.B1) // step 2 + b2.Mul(&{{.V1}}.B2, &{{.V2}}.B2) // step 3 + // step 4 - b3.Add(&x.B1, &x.B2) - b4.Add(&y.B1, &y.B2) + b3.Add(&{{.V1}}.B1, &{{.V1}}.B2) + b4.Add(&{{.V2}}.B1, &{{.V2}}.B2) rb0.Mul(&b3, &b4). SubAssign(&b1). SubAssign(&b2) - {{- template "fp2InlineMulByNonResidue" dict "all" . "out" "rb0" "in" "&rb0" }} + {{- template "fp2InlineMulByNonResidue" dict "all" .all "out" "rb0" "in" "&rb0" }} rb0.AddAssign(&b0) + // step 5 - b3.Add(&x.B0, &x.B1) - b4.Add(&y.B0, &y.B1) + b3.Add(&{{.V1}}.B0, &{{.V1}}.B1) + b4.Add(&{{.V2}}.B0, &{{.V2}}.B1) z.B1.Mul(&b3, &b4). SubAssign(&b0). SubAssign(&b1) - {{- template "fp2InlineMulByNonResidue" dict "all" . "out" "b3" "in" "&b2" }} + {{- template "fp2InlineMulByNonResidue" dict "all" .all "out" "b3" "in" "&b2" }} z.B1.AddAssign(&b3) + // step 6 - b3.Add(&x.B0, &x.B2) - b4.Add(&y.B0, &y.B2) + b3.Add(&{{.V1}}.B0, &{{.V1}}.B2) + b4.Add(&{{.V2}}.B0, &{{.V2}}.B2) z.B2.Mul(&b3, &b4). SubAssign(&b0). SubAssign(&b2). AddAssign(&b1) z.B0 = rb0 - return z -} +{{- end }} + // MulBy{{capitalize .Fp2Name}} multiplies x by an elements of {{.Fp2Name}} func (z *{{.Fp6Name}}) MulBy{{capitalize .Fp2Name}}(x *{{.Fp6Name}}, y *{{.Fp2Name}}) *{{.Fp6Name}} { var yCopy {{.Fp2Name}} @@ -43,6 +57,7 @@ func (z *{{.Fp6Name}}) MulBy{{capitalize .Fp2Name}}(x *{{.Fp6Name}}, y *{{.Fp2Na z.B2.Mul(&x.B2, &yCopy) return z } + // MulByNotv2 multiplies x by y with &y.b2=0 func (z *{{.Fp6Name}}) MulByNotv2(x, y *{{.Fp6Name}}) *{{.Fp6Name}} { // Algorithm 15 from https://eprint.iacr.org/2010/354.pdf @@ -67,22 +82,34 @@ func (z *{{.Fp6Name}}) MulByNotv2(x, y *{{.Fp6Name}}) *{{.Fp6Name}} { z.B0 = rb0 return z } -// Square squares a {{.Fp6Name}} + +// Square sets z to the {{.Fp6Name}}-product of x,x, returns z func (z *{{.Fp6Name}}) Square(x *{{.Fp6Name}}) *{{.Fp6Name}} { + {{ template "square" dict "all" . "V" "x" }} + return z +} + +// SquareAssign sets z to the {{.Fp6Name}}-product of z,z returns z +func (z *{{.Fp6Name}}) SquareAssign() *{{.Fp6Name}} { + {{ template "square" dict "all" . "V" "z" }} + return z +} + +{{- define "square" }} // Algorithm 16 from https://eprint.iacr.org/2010/354.pdf - var b0, b1, b2, b3, b4 {{.Fp2Name}} - b3.Mul(&x.B0, &x.B1).Double(&b3) // step 1 - b4.Square(&x.B2) // step 2 + var b0, b1, b2, b3, b4 {{.all.Fp2Name}} + b3.Mul(&{{.V}}.B0, &{{.V}}.B1).Double(&b3) // step 1 + b4.Square(&{{.V}}.B2) // step 2 // step 3 - {{- template "fp2InlineMulByNonResidue" dict "all" . "out" "b0" "in" "&b4" }} + {{- template "fp2InlineMulByNonResidue" dict "all" .all "out" "b0" "in" "&b4" }} b0.AddAssign(&b3) b1.Sub(&b3, &b4) // step 4 - b2.Square(&x.B0) // step 5 - b3.Sub(&x.B0, &x.B1).AddAssign(&x.B2).Square(&b3) // steps 6 and 8 - b4.Mul(&x.B1, &x.B2).Double(&b4) // step 7 + b2.Square(&{{.V}}.B0) // step 5 + b3.Sub(&{{.V}}.B0, &{{.V}}.B1).AddAssign(&{{.V}}.B2).Square(&b3) // steps 6 and 8 + b4.Mul(&{{.V}}.B1, &{{.V}}.B2).Double(&b4) // step 7 // step 9 - {{- template "fp2InlineMulByNonResidue" dict "all" . "out" "z.B0" "in" "&b4" }} + {{- template "fp2InlineMulByNonResidue" dict "all" .all "out" "z.B0" "in" "&b4" }} z.B0.AddAssign(&b2) // step 10 @@ -90,8 +117,8 @@ func (z *{{.Fp6Name}}) Square(x *{{.Fp6Name}}) *{{.Fp6Name}} { AddAssign(&b4). SubAssign(&b2) z.B1 = b0 - return z -} +{{- end }} + // SquarE2 squares a {{.Fp6Name}} func (z *{{.Fp6Name}}) SquarE2(x *{{.Fp6Name}}) *{{.Fp6Name}} { // Karatsuba from Section 4 of https://eprint.iacr.org/2006/471.pdf diff --git a/internal/generators/template/tower/fp6/testpoints.go.backup b/internal/generators/tower/templates/fp6/testpoints.go.backup similarity index 100% rename from internal/generators/template/tower/fp6/testpoints.go.backup rename to internal/generators/tower/templates/fp6/testpoints.go.backup diff --git a/utils/utils.go b/utils/utils.go index 55c62ac2fb..19decf5a04 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -6,6 +6,7 @@ import ( // NafDecomposition gets the naf decomposition of a big number func NafDecomposition(a *big.Int, result []int8) int { + var zero, one, two, three big.Int one.SetUint64(1)