From 53c88f4095cbcfcd7663b6067e31bfdf141b4a57 Mon Sep 17 00:00:00 2001 From: Youssef El Housni Date: Mon, 3 Jun 2024 21:07:58 +0200 Subject: [PATCH 1/4] perf(bw6-761): eliminate finalexp --- .../emulated/fields_bw6761/e6_pairing.go | 202 ++++++++++++++++++ std/algebra/emulated/fields_bw6761/hints.go | 39 ++++ std/algebra/emulated/sw_bw6761/pairing.go | 5 +- 3 files changed, 243 insertions(+), 3 deletions(-) diff --git a/std/algebra/emulated/fields_bw6761/e6_pairing.go b/std/algebra/emulated/fields_bw6761/e6_pairing.go index 12cbf4ab41..488782a2cf 100644 --- a/std/algebra/emulated/fields_bw6761/e6_pairing.go +++ b/std/algebra/emulated/fields_bw6761/e6_pairing.go @@ -321,3 +321,205 @@ func (e *Ext6) MulBy02345(z *E6, x [5]*baseEl) *E6 { A5: *z12, } } + +// FinalExponentiationCheck checks that a Miller function output x lies in the +// same equivalence class as the reduced pairing. This replaces the final +// exponentiation step in-circuit. +// The method is adapted from Section 4 of [On Proving Pairings] paper by A. Novakovic and L. Eagen. +// +// [On Proving Pairings]: https://eprint.iacr.org/2024/640.pdf +func (e Ext6) FinalExponentiationCheck(x *E6) *E6 { + res, err := e.fp.NewHint(finalExpHint, 6, &x.A0, &x.A1, &x.A2, &x.A3, &x.A4, &x.A5) + if err != nil { + // err is non-nil only for invalid number of inputs + panic(err) + } + + residueWitness := E6{ + A0: *res[0], + A1: *res[1], + A2: *res[2], + A3: *res[3], + A4: *res[4], + A5: *res[5], + } + + // Check that x == residueWitness^λ + // where λ = u^3-u^2+1 - (u+1)p, with u the BW6-761 seed + // and residueWitness from the hint. + + // exponentiation by U1=u^3-u^2+1 + t0 := e.ExpByU1(&residueWitness) + // exponentiation by U2=u+1 + t1 := e.ExpByU2(&residueWitness) + + t1 = e.Frobenius(t1) + t0 = e.DivUnchecked(t0, t1) + + e.AssertIsEqual(t0, x) + + return nil +} + +func (e Ext6) nSquare(z *E6, n int) *E6 { + for i := 0; i < n; i++ { + z = e.Square(z) + } + return z +} + +// ExpByU2 set z to z^(x₀+1) in E12 and return z +// x₀+1 = 9586122913090633730 +func (e Ext6) ExpByU2(z *E6) *E6 { + z = e.Reduce(z) + result := e.Copy(z) + t := e.nSquare(result, 1) + result = e.nSquare(t, 4) + result = e.Mul(result, z) + z33 := e.Copy(result) + result = e.nSquare(result, 7) + result = e.Mul(result, z33) + result = e.nSquare(result, 4) + result = e.Mul(result, z) + result = e.nSquare(result, 1) + result = e.Mul(result, z) + result = e.nSquare(result, 46) + result = e.Mul(result, t) + + return result +} + +// ExpByU1 set z to z^(x₀^3-x₀^2+1) in E12 and return z +// x₀^3-x₀^2+1 = 880904806456922042166256752416502360965158762994674434049 +func (e Ext6) ExpByU1(x *E6) *E6 { + // t5.Square(&x) + t5 := e.Square(x) + // z.Mul(&x, &t5) + z := e.Mul(x, t5) + // t0.Square(&z) + t0 := e.Square(z) + // t6.Mul(&x, &t0) + t6 := e.Mul(x, t0) + // t8.Mul(&x, &t6) + t8 := e.Mul(x, t6) + // t7.Mul(&t5, &t8) + t7 := e.Mul(t5, t8) + // t9.Mul(&t0, &t8) + t9 := e.Mul(t0, t8) + // t3.Mul(&z, &t9) + t3 := e.Mul(z, t9) + // t2.Mul(&x, &t3) + t2 := e.Mul(x, t3) + // t1.Mul(&t6, &t2) + t1 := e.Mul(t6, t2) + // t0.Mul(&t8, &t1) + t0 = e.Mul(t8, t1) + // t4.Square(&t0) + t4 := e.Square(t0) + // t4.Mul(&z, &t4) + t4 = e.Mul(z, t4) + // t8.Mul(&t8, &t4) + t8 = e.Mul(t8, t4) + // t2.Mul(&t2, &t8) + t2 = e.Mul(t2, t8) + // t9.Mul(&t9, &t2) + t9 = e.Mul(t9, t2) + // t5.Mul(&t5, &t9) + t5 = e.Mul(t5, t9) + // t10.Mul(&t0, &t9) + t10 := e.Mul(t0, t9) + // for s := 0; s < 6; s++ { + // t10.Square(t10t10) + // } + t10 = e.nSquare(t10, 6) + // t9.Mul(&t9, &t10) + t9 = e.Mul(t9, t10) + // for s := 0; s < 10; s++ { + // t9.Square(t9t9) + // } + t9 = e.nSquare(t9, 10) + // t8.Mul(&t8, &t9) + t8 = e.Mul(t8, t9) + // for s := 0; s < 10; s++ { + // t8.Square(t8t8) + // } + t8 = e.nSquare(t8, 10) + // t8.Mul(&t5, &t8) + t8 = e.Mul(t5, t8) + // t7.Mul(&t7, &t8) + t7 = e.Mul(t7, t8) + // for s := 0; s < 4; s++ { + // t7.Square(t7t7) + // } + t7 = e.nSquare(t7, 4) + // t6.Mul(&t6, &t7) + t6 = e.Mul(t6, t7) + // for s := 0; s < 11; s++ { + // t6.Square(t6t6) + // } + t6 = e.nSquare(t6, 11) + // t5.Mul(&t5, &t6) + t5 = e.Mul(t5, t6) + // for s := 0; s < 3; s++ { + // t5.Square(t5t5) + // } + t5 = e.nSquare(t5, 3) + // t5.Mul(&z, &t5) + t5 = e.Mul(z, t5) + // for s := 0; s < 17; s++ { + // t5.Square(t5t5) + // } + t5 = e.nSquare(t5, 17) + // t4.Mul(&t4, &t5) + t4 = e.Mul(t4, t5) + // for s := 0; s < 7; s++ { + // t4.Square(t4t4) + // } + t4 = e.nSquare(t4, 7) + // t3.Mul(&t3, &t4) + t3 = e.Mul(t3, t4) + // for s := 0; s < 11; s++ { + // t3.Square(t3t3) + // } + t3 = e.nSquare(t3, 11) + // t2.Mul(&t2, &t3) + t2 = e.Mul(t2, t3) + // for s := 0; s < 7; s++ { + // t2.Square(t2t2) + // } + t2 = e.nSquare(t2, 7) + // t1.Mul(&t1, &t2) + t1 = e.Mul(t1, t2) + // for s := 0; s < 3; s++ { + // t1.Square(t1t1) + // } + t1 = e.nSquare(t1, 3) + // t1.Mul(&x, &t1) + t1 = e.Mul(x, t1) + // for s := 0; s < 35; s++ { + // t1.Square(t1t1) + // } + t1 = e.nSquare(t1, 35) + // t1.Mul(&t0, &t1) + t1 = e.Mul(t0, t1) + // for s := 0; s < 7; s++ { + // t1.Square(t1t1) + // } + t1 = e.nSquare(t1, 7) + // t0.Mul(&t0, &t1) + t0 = e.Mul(t0, t1) + // for s := 0; s < 5; s++ { + // t0.Square(t0t0) + // } + t0 = e.nSquare(t0, 5) + // z.Mul(&z, &t0) + z = e.Mul(z, t0) + // for s := 0; s < 46; s++ { + // z.Square(zz) + // } + z = e.nSquare(z, 46) + // z.Mul(&x, &z) + z = e.Mul(x, z) + + return z +} diff --git a/std/algebra/emulated/fields_bw6761/hints.go b/std/algebra/emulated/fields_bw6761/hints.go index 994daa0d18..255cc9b2ff 100644 --- a/std/algebra/emulated/fields_bw6761/hints.go +++ b/std/algebra/emulated/fields_bw6761/hints.go @@ -19,6 +19,7 @@ func GetHints() []solver.Hint { divE6Hint, inverseE6Hint, divE6By362880Hint, + finalExpHint, } } @@ -106,3 +107,41 @@ func divE6By362880Hint(nativeMod *big.Int, nativeInputs, nativeOutputs []*big.In return nil }) } + +func finalExpHint(nativeMod *big.Int, nativeInputs, nativeOutputs []*big.Int) error { + // This adapted from section 4.3.2 of https://eprint.iacr.org/2024/640.pdf + return emulated.UnwrapHint(nativeInputs, nativeOutputs, + func(mod *big.Int, inputs, outputs []*big.Int) error { + var millerLoop, residueWitness bw6761.E6 + var rInv, mInv big.Int + + millerLoop.B0.A0.SetBigInt(inputs[0]) + millerLoop.B0.A1.SetBigInt(inputs[2]) + millerLoop.B0.A2.SetBigInt(inputs[4]) + millerLoop.B1.A0.SetBigInt(inputs[1]) + millerLoop.B1.A1.SetBigInt(inputs[3]) + millerLoop.B1.A2.SetBigInt(inputs[5]) + + // 1. compute r-th root: + // Exponentiate to rInv where + // rInv = 1/r mod (p^6-1)/r + rInv.SetString("279142441805511726233822077180198394933430419224185936052953462287387912118470357993263103168031788043160461358474005435622327506926362567154401645657309519073154383052970657693950208844465818979551693587858245321454505472049236704031061301292776853925224359757586505231126091244204292668007110271845616234279927419974150119801003450133674289144711275201991607282264849765236206295842916353255855388186086438329721887082685697023028663652777877691341551982676874308309620809049793085180324511691754953492619183755890255644855765188965000691813063771086522132765764526955251054211157804606693386854395171192876178005945476647006847460976477055233044799299417913662363985523123796056692751028712679181978298499780752966303529102009307348414562366180130429432094237007700663759126264893082917308542509779442201840676518234962495304673134599305371982876385622279935346701152286347948653741121231188575146952014672242471261647823749129902237689180055673361938161119768341970519416039779128617354778773830515364777252518313057683396662835013368967463878342754251509207391537635831891662211848811733884861792121210263430418966889668537646457064092991696527814120385172941004264289812969796992647021735186941896252860419364971543301451924917610828019341224722038007513", 10) + residueWitness.Exp(millerLoop, &rInv) + + // 2. compute m-th root: + // where m = (x+1 + x(x^2-x^1-1)q) / r + // Exponentiate to mInv where + // mInv = 1/m mod p^6-1/r + mInv.SetString("420096572758781926988571022578549119077996267041217186563532964653013626327499627643558150289556860284699838191238508062761264485377946319676011525555582097381055209304464769241709045835179375847000286979304653199040198646948595850434830718773056593021324330541604029824826938177546414778934883707126835848724258610612114712835130017082970786784508470382396148858570586085402148355642863720286568566937773459407961735112550507047306343380386401338522186960986251395049985320677251315016812720092326581314645206610216409714397970562842517827716362494341171265008409446148022671451843025093584702610246849007545665518399731546205544005105929880663530772806759681913801835273987094997504640832304570158760940364827187477825525048007459079382410480491250884588399683894539404567701993526561088158396861020181640181843560309670937868772703282755078557149854363818903590441797744966016708880143332350534049482338696654635346189790575286999280892407997722996866724226514621504774811766428733682155766330614074143245300182851212177081558245259537898592443393875891588079021560334726750431309338787970594548465289737362624558256642461612913108676326999205533110217714096123782036214164015261929502119392490941988919030563789520985909704716341786823561745842985678563", 10) + residueWitness.Exp(residueWitness, &mInv) + + residueWitness.B0.A0.BigInt(outputs[0]) + residueWitness.B0.A1.BigInt(outputs[2]) + residueWitness.B0.A2.BigInt(outputs[4]) + residueWitness.B1.A0.BigInt(outputs[1]) + residueWitness.B1.A1.BigInt(outputs[3]) + residueWitness.B1.A2.BigInt(outputs[5]) + + return nil + }) +} diff --git a/std/algebra/emulated/sw_bw6761/pairing.go b/std/algebra/emulated/sw_bw6761/pairing.go index b6fb462139..3f56f73889 100644 --- a/std/algebra/emulated/sw_bw6761/pairing.go +++ b/std/algebra/emulated/sw_bw6761/pairing.go @@ -141,13 +141,12 @@ func (pr Pairing) Pair(P []*G1Affine, Q []*G2Affine) (*GTEl, error) { // // This function doesn't check that the inputs are in the correct subgroups. func (pr Pairing) PairingCheck(P []*G1Affine, Q []*G2Affine) error { - f, err := pr.Pair(P, Q) + f, err := pr.MillerLoop(P, Q) if err != nil { return err } - one := pr.One() - pr.AssertIsEqual(f, one) + pr.FinalExponentiationCheck(f) return nil } From 78e54688a2ee4dc6bb6f2c637bc6366f0b5a4e79 Mon Sep 17 00:00:00 2001 From: Youssef El Housni Date: Mon, 3 Jun 2024 23:11:23 +0200 Subject: [PATCH 2/4] refactor: clean code --- .../emulated/fields_bw6761/e6_pairing.go | 79 ------------------- 1 file changed, 79 deletions(-) diff --git a/std/algebra/emulated/fields_bw6761/e6_pairing.go b/std/algebra/emulated/fields_bw6761/e6_pairing.go index 488782a2cf..d3db8054be 100644 --- a/std/algebra/emulated/fields_bw6761/e6_pairing.go +++ b/std/algebra/emulated/fields_bw6761/e6_pairing.go @@ -392,133 +392,54 @@ func (e Ext6) ExpByU2(z *E6) *E6 { // ExpByU1 set z to z^(x₀^3-x₀^2+1) in E12 and return z // x₀^3-x₀^2+1 = 880904806456922042166256752416502360965158762994674434049 func (e Ext6) ExpByU1(x *E6) *E6 { - // t5.Square(&x) t5 := e.Square(x) - // z.Mul(&x, &t5) z := e.Mul(x, t5) - // t0.Square(&z) t0 := e.Square(z) - // t6.Mul(&x, &t0) t6 := e.Mul(x, t0) - // t8.Mul(&x, &t6) t8 := e.Mul(x, t6) - // t7.Mul(&t5, &t8) t7 := e.Mul(t5, t8) - // t9.Mul(&t0, &t8) t9 := e.Mul(t0, t8) - // t3.Mul(&z, &t9) t3 := e.Mul(z, t9) - // t2.Mul(&x, &t3) t2 := e.Mul(x, t3) - // t1.Mul(&t6, &t2) t1 := e.Mul(t6, t2) - // t0.Mul(&t8, &t1) t0 = e.Mul(t8, t1) - // t4.Square(&t0) t4 := e.Square(t0) - // t4.Mul(&z, &t4) t4 = e.Mul(z, t4) - // t8.Mul(&t8, &t4) t8 = e.Mul(t8, t4) - // t2.Mul(&t2, &t8) t2 = e.Mul(t2, t8) - // t9.Mul(&t9, &t2) t9 = e.Mul(t9, t2) - // t5.Mul(&t5, &t9) t5 = e.Mul(t5, t9) - // t10.Mul(&t0, &t9) t10 := e.Mul(t0, t9) - // for s := 0; s < 6; s++ { - // t10.Square(t10t10) - // } t10 = e.nSquare(t10, 6) - // t9.Mul(&t9, &t10) t9 = e.Mul(t9, t10) - // for s := 0; s < 10; s++ { - // t9.Square(t9t9) - // } t9 = e.nSquare(t9, 10) - // t8.Mul(&t8, &t9) t8 = e.Mul(t8, t9) - // for s := 0; s < 10; s++ { - // t8.Square(t8t8) - // } t8 = e.nSquare(t8, 10) - // t8.Mul(&t5, &t8) t8 = e.Mul(t5, t8) - // t7.Mul(&t7, &t8) t7 = e.Mul(t7, t8) - // for s := 0; s < 4; s++ { - // t7.Square(t7t7) - // } t7 = e.nSquare(t7, 4) - // t6.Mul(&t6, &t7) t6 = e.Mul(t6, t7) - // for s := 0; s < 11; s++ { - // t6.Square(t6t6) - // } t6 = e.nSquare(t6, 11) - // t5.Mul(&t5, &t6) t5 = e.Mul(t5, t6) - // for s := 0; s < 3; s++ { - // t5.Square(t5t5) - // } t5 = e.nSquare(t5, 3) - // t5.Mul(&z, &t5) t5 = e.Mul(z, t5) - // for s := 0; s < 17; s++ { - // t5.Square(t5t5) - // } t5 = e.nSquare(t5, 17) - // t4.Mul(&t4, &t5) t4 = e.Mul(t4, t5) - // for s := 0; s < 7; s++ { - // t4.Square(t4t4) - // } t4 = e.nSquare(t4, 7) - // t3.Mul(&t3, &t4) t3 = e.Mul(t3, t4) - // for s := 0; s < 11; s++ { - // t3.Square(t3t3) - // } t3 = e.nSquare(t3, 11) - // t2.Mul(&t2, &t3) t2 = e.Mul(t2, t3) - // for s := 0; s < 7; s++ { - // t2.Square(t2t2) - // } t2 = e.nSquare(t2, 7) - // t1.Mul(&t1, &t2) t1 = e.Mul(t1, t2) - // for s := 0; s < 3; s++ { - // t1.Square(t1t1) - // } t1 = e.nSquare(t1, 3) - // t1.Mul(&x, &t1) t1 = e.Mul(x, t1) - // for s := 0; s < 35; s++ { - // t1.Square(t1t1) - // } t1 = e.nSquare(t1, 35) - // t1.Mul(&t0, &t1) t1 = e.Mul(t0, t1) - // for s := 0; s < 7; s++ { - // t1.Square(t1t1) - // } t1 = e.nSquare(t1, 7) - // t0.Mul(&t0, &t1) t0 = e.Mul(t0, t1) - // for s := 0; s < 5; s++ { - // t0.Square(t0t0) - // } t0 = e.nSquare(t0, 5) - // z.Mul(&z, &t0) z = e.Mul(z, t0) - // for s := 0; s < 46; s++ { - // z.Square(zz) - // } z = e.nSquare(z, 46) - // z.Mul(&x, &z) z = e.Mul(x, z) return z From 2d162ddce41de597b2df9cbe5d08a27ba693adda Mon Sep 17 00:00:00 2001 From: Youssef El Housni Date: Wed, 5 Jun 2024 16:17:56 +0200 Subject: [PATCH 3/4] perf(bw6-761): push ML to cyclo-group before FE elimination --- .../emulated/fields_bw6761/e6_pairing.go | 42 +++++++++---------- std/algebra/emulated/sw_bw6761/pairing.go | 10 +++++ 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/std/algebra/emulated/fields_bw6761/e6_pairing.go b/std/algebra/emulated/fields_bw6761/e6_pairing.go index d3db8054be..d5215106e9 100644 --- a/std/algebra/emulated/fields_bw6761/e6_pairing.go +++ b/std/algebra/emulated/fields_bw6761/e6_pairing.go @@ -373,17 +373,17 @@ func (e Ext6) nSquare(z *E6, n int) *E6 { func (e Ext6) ExpByU2(z *E6) *E6 { z = e.Reduce(z) result := e.Copy(z) - t := e.nSquare(result, 1) - result = e.nSquare(t, 4) + t := e.nSquareKarabina12345(result, 1) + result = e.nSquareKarabina12345(t, 4) result = e.Mul(result, z) z33 := e.Copy(result) - result = e.nSquare(result, 7) + result = e.nSquareKarabina12345(result, 7) result = e.Mul(result, z33) - result = e.nSquare(result, 4) + result = e.nSquareKarabina12345(result, 4) result = e.Mul(result, z) - result = e.nSquare(result, 1) + result = e.nSquareKarabina12345(result, 1) result = e.Mul(result, z) - result = e.nSquare(result, 46) + result = e.nSquareKarabina12345(result, 46) result = e.Mul(result, t) return result @@ -410,36 +410,36 @@ func (e Ext6) ExpByU1(x *E6) *E6 { t9 = e.Mul(t9, t2) t5 = e.Mul(t5, t9) t10 := e.Mul(t0, t9) - t10 = e.nSquare(t10, 6) + t10 = e.nSquareKarabina12345(t10, 6) t9 = e.Mul(t9, t10) - t9 = e.nSquare(t9, 10) + t9 = e.nSquareKarabina12345(t9, 10) t8 = e.Mul(t8, t9) - t8 = e.nSquare(t8, 10) + t8 = e.nSquareKarabina12345(t8, 10) t8 = e.Mul(t5, t8) t7 = e.Mul(t7, t8) - t7 = e.nSquare(t7, 4) + t7 = e.nSquareKarabina12345(t7, 4) t6 = e.Mul(t6, t7) - t6 = e.nSquare(t6, 11) + t6 = e.nSquareKarabina12345(t6, 11) t5 = e.Mul(t5, t6) - t5 = e.nSquare(t5, 3) + t5 = e.nSquareKarabina12345(t5, 3) t5 = e.Mul(z, t5) - t5 = e.nSquare(t5, 17) + t5 = e.nSquareKarabina12345(t5, 17) t4 = e.Mul(t4, t5) - t4 = e.nSquare(t4, 7) + t4 = e.nSquareKarabina12345(t4, 7) t3 = e.Mul(t3, t4) - t3 = e.nSquare(t3, 11) + t3 = e.nSquareKarabina12345(t3, 11) t2 = e.Mul(t2, t3) - t2 = e.nSquare(t2, 7) + t2 = e.nSquareKarabina12345(t2, 7) t1 = e.Mul(t1, t2) - t1 = e.nSquare(t1, 3) + t1 = e.nSquareKarabina12345(t1, 3) t1 = e.Mul(x, t1) - t1 = e.nSquare(t1, 35) + t1 = e.nSquareKarabina12345(t1, 35) t1 = e.Mul(t0, t1) - t1 = e.nSquare(t1, 7) + t1 = e.nSquareKarabina12345(t1, 7) t0 = e.Mul(t0, t1) - t0 = e.nSquare(t0, 5) + t0 = e.nSquareKarabina12345(t0, 5) z = e.Mul(z, t0) - z = e.nSquare(z, 46) + z = e.nSquareKarabina12345(z, 46) z = e.Mul(x, z) return z diff --git a/std/algebra/emulated/sw_bw6761/pairing.go b/std/algebra/emulated/sw_bw6761/pairing.go index 3f56f73889..88485288cb 100644 --- a/std/algebra/emulated/sw_bw6761/pairing.go +++ b/std/algebra/emulated/sw_bw6761/pairing.go @@ -146,6 +146,16 @@ func (pr Pairing) PairingCheck(P []*G1Affine, Q []*G2Affine) error { return err } + // We perform the easy part of the final exp to push f to the cyclotomic + // subgroup so that FinalExponentiationCheck is carried with optimized + // cyclotomic squaring (e.g. Karabina12345). + // + // f = f^(p³-1)(p+1) + buf := pr.Conjugate(f) + buf = pr.DivUnchecked(buf, f) + f = pr.Frobenius(buf) + f = pr.Mul(f, buf) + pr.FinalExponentiationCheck(f) return nil From 48cf0a0a6b49aea890aabc01623c9f554c77749e Mon Sep 17 00:00:00 2001 From: Youssef El Housni Date: Fri, 14 Jun 2024 17:09:17 +0100 Subject: [PATCH 4/4] perf(bw6-761): use Karabina even for 1 square --- std/algebra/emulated/fields_bw6761/e6_pairing.go | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/std/algebra/emulated/fields_bw6761/e6_pairing.go b/std/algebra/emulated/fields_bw6761/e6_pairing.go index d5215106e9..8361ed8146 100644 --- a/std/algebra/emulated/fields_bw6761/e6_pairing.go +++ b/std/algebra/emulated/fields_bw6761/e6_pairing.go @@ -361,13 +361,6 @@ func (e Ext6) FinalExponentiationCheck(x *E6) *E6 { return nil } -func (e Ext6) nSquare(z *E6, n int) *E6 { - for i := 0; i < n; i++ { - z = e.Square(z) - } - return z -} - // ExpByU2 set z to z^(x₀+1) in E12 and return z // x₀+1 = 9586122913090633730 func (e Ext6) ExpByU2(z *E6) *E6 { @@ -392,9 +385,9 @@ func (e Ext6) ExpByU2(z *E6) *E6 { // ExpByU1 set z to z^(x₀^3-x₀^2+1) in E12 and return z // x₀^3-x₀^2+1 = 880904806456922042166256752416502360965158762994674434049 func (e Ext6) ExpByU1(x *E6) *E6 { - t5 := e.Square(x) + t5 := e.nSquareKarabina12345(x, 1) z := e.Mul(x, t5) - t0 := e.Square(z) + t0 := e.nSquareKarabina12345(z, 1) t6 := e.Mul(x, t0) t8 := e.Mul(x, t6) t7 := e.Mul(t5, t8) @@ -403,7 +396,7 @@ func (e Ext6) ExpByU1(x *E6) *E6 { t2 := e.Mul(x, t3) t1 := e.Mul(t6, t2) t0 = e.Mul(t8, t1) - t4 := e.Square(t0) + t4 := e.nSquareKarabina12345(t0, 1) t4 = e.Mul(z, t4) t8 = e.Mul(t8, t4) t2 = e.Mul(t2, t8)