-
Notifications
You must be signed in to change notification settings - Fork 366
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: add BN254 pairing using field emulation * refactor: make methods private * feat: add equality assertion for GT elements * docs: add package documentation and example * refactor: algebra into native (2-chain) and emulated * fix: remove pairing_bn254 * fix: use sw_emulated instead of weierstrass * fix: update path to algebra/native * fix: update path to algebra/native * fix: update path to algebra/native/twistededwards * docs: add documentation to std/algebra packages * style(std/fields_*): separate Fpk ops specific to choice of pairing * style: apply suggested edits --------- Co-authored-by: Ivo Kubjas <ivo.kubjas@consensys.net>
- Loading branch information
Showing
79 changed files
with
1,443 additions
and
1,412 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// Package algebra implements: | ||
// - base finite field 𝔽p arithmetic, | ||
// - extension finite fields arithmetic (𝔽p², 𝔽p⁴, 𝔽p⁶, 𝔽p¹², 𝔽p²⁴), | ||
// - short Weierstrass curve arithmetic over G1 (E/𝔽p) and G2 (Eₜ/𝔽p² or Eₜ/𝔽p⁴) | ||
// - twisted Edwards curve arithmetic | ||
// | ||
// These arithmetic operations are implemented | ||
// - using native field via the 2-chains BLS12-377/BW6-761 and BLS24-315/BW-633 | ||
// (`native/`) or associated twisted Edwards (e.g. Jubjub/BLS12-381) and | ||
// - using nonnative field via field emulation (`emulated/`). This allows to | ||
// use any curve over any (SNARK) field (e.g. secp256k1 curve arithmetic over | ||
// BN254 SNARK field or BN254 pairing over BN254 SNARK field). The drawback | ||
// of this approach is the extreme cost of the operations. | ||
package algebra |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
// Package fields_bn254 implements the fields arithmetic of the Fp12 tower | ||
// used to compute the pairing over the BN254 curve. | ||
// | ||
// 𝔽p²[u] = 𝔽p/u²+1 | ||
// 𝔽p⁶[v] = 𝔽p²/v³-9-u | ||
// 𝔽p¹²[w] = 𝔽p⁶/w²-v | ||
package fields_bn254 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,226 @@ | ||
package fields_bn254 | ||
|
||
type E12 struct { | ||
C0, C1 E6 | ||
} | ||
|
||
type Ext12 struct { | ||
*Ext6 | ||
} | ||
|
||
func NewExt12(baseField *curveF) *Ext12 { | ||
return &Ext12{Ext6: NewExt6(baseField)} | ||
} | ||
func (e Ext12) Conjugate(x *E12) *E12 { | ||
z1 := e.Ext6.Neg(&x.C1) // z.C1.Neg(&z.C1) | ||
return &E12{ // return z | ||
C0: x.C0, | ||
C1: *z1, | ||
} | ||
} | ||
|
||
func (e Ext12) Inverse(x *E12) *E12 { | ||
// var t0, t1, tmp E6 | ||
t0 := e.Ext6.Square(&x.C0) // t0.Square(&x.C0) | ||
t1 := e.Ext6.Square(&x.C1) // t1.Square(&x.C1) | ||
tmp := e.Ext6.MulByNonResidue(t1) // tmp.MulByNonResidue(&t1) | ||
t0 = e.Ext6.Sub(t0, tmp) // t0.Sub(&t0, &tmp) | ||
t1 = e.Ext6.Inverse(t0) // t1.Inverse(&t0) | ||
z0 := e.Ext6.Mul(&x.C0, t1) // z.C0.Mul(&x.C0, &t1) | ||
z1 := e.Ext6.Mul(&x.C1, t1) // z.C1.Mul(&x.C1, &t1). | ||
z1 = e.Ext6.Neg(z1) // Neg(&z.C1) | ||
return &E12{ // return z | ||
C0: *z0, | ||
C1: *z1, | ||
} | ||
} | ||
|
||
func (e Ext12) Mul(x, y *E12) *E12 { | ||
// var a, b, c E6 | ||
a := e.Ext6.Add(&x.C0, &x.C1) // a.Add(&x.C0, &x.C1) | ||
b := e.Ext6.Add(&y.C0, &y.C1) // b.Add(&y.C0, &y.C1) | ||
a = e.Ext6.Mul(a, b) // a.Mul(&a, &b) | ||
b = e.Ext6.Mul(&x.C0, &y.C0) // b.Mul(&x.C0, &y.C0) | ||
c := e.Ext6.Mul(&x.C1, &y.C1) // c.Mul(&x.C1, &y.C1) | ||
z1 := e.Ext6.Sub(a, b) // z.C1.Sub(&a, &b). | ||
z1 = e.Ext6.Sub(z1, c) // Sub(&z.C1, &c) | ||
z0 := e.Ext6.MulByNonResidue(c) // z.C0.MulByNonResidue(&c). | ||
z0 = e.Ext6.Add(z0, b) // Add(&z.C0, &b) | ||
return &E12{ // return z | ||
C0: *z0, | ||
C1: *z1, | ||
} | ||
} | ||
|
||
func (e Ext12) CyclotomicSquare(x *E12) *E12 { | ||
// var t [9]E2 | ||
t0 := e.Ext2.Square(&x.C1.B1) // t[0].Square(&x.C1.B1) | ||
t1 := e.Ext2.Square(&x.C0.B0) // t[1].Square(&x.C0.B0) | ||
t6 := e.Ext2.Add(&x.C1.B1, &x.C0.B0) // t[6].Add(&x.C1.B1, &x.C0.B0). | ||
t6 = e.Ext2.Square(t6) // Square(&t[6]). | ||
t6 = e.Ext2.Sub(t6, t0) // Sub(&t[6], &t[0]). | ||
t6 = e.Ext2.Sub(t6, t1) // Sub(&t[6], &t[1]) | ||
t2 := e.Ext2.Square(&x.C0.B2) // t[2].Square(&x.C0.B2) | ||
t3 := e.Ext2.Square(&x.C1.B0) // t[3].Square(&x.C1.B0) | ||
t7 := e.Ext2.Add(&x.C0.B2, &x.C1.B0) // t[7].Add(&x.C0.B2, &x.C1.B0). | ||
t7 = e.Ext2.Square(t7) // Square(&t[7]). | ||
t7 = e.Ext2.Sub(t7, t2) // Sub(&t[7], &t[2]). | ||
t7 = e.Ext2.Sub(t7, t3) // Sub(&t[7], &t[3]) | ||
t4 := e.Ext2.Square(&x.C1.B2) // t[4].Square(&x.C1.B2) | ||
t5 := e.Ext2.Square(&x.C0.B1) // t[5].Square(&x.C0.B1) | ||
t8 := e.Ext2.Add(&x.C1.B2, &x.C0.B1) // t[8].Add(&x.C1.B2, &x.C0.B1). | ||
t8 = e.Ext2.Square(t8) // Square(&t[8]). | ||
t8 = e.Ext2.Sub(t8, t4) // Sub(&t[8], &t[4]). | ||
t8 = e.Ext2.Sub(t8, t5) // Sub(&t[8], &t[5]). | ||
t8 = e.Ext2.MulByNonResidue(t8) // MulByNonResidue(&t[8]) | ||
t0 = e.Ext2.MulByNonResidue(t0) // t[0].MulByNonResidue(&t[0]). | ||
t0 = e.Ext2.Add(t0, t1) // Add(&t[0], &t[1]) | ||
t2 = e.Ext2.MulByNonResidue(t2) // t[2].MulByNonResidue(&t[2]). | ||
t2 = e.Ext2.Add(t2, t3) // Add(&t[2], &t[3]) | ||
t4 = e.Ext2.MulByNonResidue(t4) // t[4].MulByNonResidue(&t[4]). | ||
t4 = e.Ext2.Add(t4, t5) // Add(&t[4], &t[5]) | ||
z00 := e.Ext2.Sub(t0, &x.C0.B0) // z.C0.B0.Sub(&t[0], &x.C0.B0). | ||
z00 = e.Ext2.Double(z00) // Double(&z.C0.B0). | ||
z00 = e.Ext2.Add(z00, t0) // Add(&z.C0.B0, &t[0]) | ||
z01 := e.Ext2.Sub(t2, &x.C0.B1) // z.C0.B1.Sub(&t[2], &x.C0.B1). | ||
z01 = e.Ext2.Double(z01) // Double(&z.C0.B1). | ||
z01 = e.Ext2.Add(z01, t2) // Add(&z.C0.B1, &t[2]) | ||
z02 := e.Ext2.Sub(t4, &x.C0.B2) // z.C0.B2.Sub(&t[4], &x.C0.B2). | ||
z02 = e.Ext2.Double(z02) // Double(&z.C0.B2). | ||
z02 = e.Ext2.Add(z02, t4) // Add(&z.C0.B2, &t[4]) | ||
z10 := e.Ext2.Add(t8, &x.C1.B0) // z.C1.B0.Add(&t[8], &x.C1.B0). | ||
z10 = e.Ext2.Double(z10) // Double(&z.C1.B0). | ||
z10 = e.Ext2.Add(z10, t8) // Add(&z.C1.B0, &t[8]) | ||
z11 := e.Ext2.Add(t6, &x.C1.B1) // z.C1.B1.Add(&t[6], &x.C1.B1). | ||
z11 = e.Ext2.Double(z11) // Double(&z.C1.B1). | ||
z11 = e.Ext2.Add(z11, t6) // Add(&z.C1.B1, &t[6]) | ||
z12 := e.Ext2.Add(t7, &x.C1.B2) // z.C1.B2.Add(&t[7], &x.C1.B2). | ||
z12 = e.Ext2.Double(z12) // Double(&z.C1.B2). | ||
z12 = e.Ext2.Add(z12, t7) // Add(&z.C1.B2, &t[7]) | ||
return &E12{ // return z | ||
C0: E6{ | ||
B0: *z00, | ||
B1: *z01, | ||
B2: *z02, | ||
}, | ||
C1: E6{ | ||
B0: *z10, | ||
B1: *z11, | ||
B2: *z12, | ||
}, | ||
} | ||
} | ||
|
||
func (e Ext12) NCycloSquare(z *E12, n int) *E12 { | ||
for i := 0; i < n; i++ { | ||
z = e.CyclotomicSquare(z) | ||
} | ||
return z | ||
} | ||
|
||
func (e Ext12) Frobenius(x *E12) *E12 { | ||
// var t [6]E2 | ||
t0 := e.Ext2.Conjugate(&x.C0.B0) // t[0].Conjugate(&x.C0.B0) | ||
t1 := e.Ext2.Conjugate(&x.C0.B1) // t[1].Conjugate(&x.C0.B1) | ||
t2 := e.Ext2.Conjugate(&x.C0.B2) // t[2].Conjugate(&x.C0.B2) | ||
t3 := e.Ext2.Conjugate(&x.C1.B0) // t[3].Conjugate(&x.C1.B0) | ||
t4 := e.Ext2.Conjugate(&x.C1.B1) // t[4].Conjugate(&x.C1.B1) | ||
t5 := e.Ext2.Conjugate(&x.C1.B2) // t[5].Conjugate(&x.C1.B2) | ||
t1 = e.Ext2.MulByNonResidue1Power2(t1) // t[1].MulByNonResidue1Power2(&t[1]) | ||
t2 = e.Ext2.MulByNonResidue1Power4(t2) // t[2].MulByNonResidue1Power4(&t[2]) | ||
t3 = e.Ext2.MulByNonResidue1Power1(t3) // t[3].MulByNonResidue1Power1(&t[3]) | ||
t4 = e.Ext2.MulByNonResidue1Power3(t4) // t[4].MulByNonResidue1Power3(&t[4]) | ||
t5 = e.Ext2.MulByNonResidue1Power5(t5) // t[5].MulByNonResidue1Power5(&t[5]) | ||
return &E12{ // return z | ||
C0: E6{ | ||
B0: *t0, // z.C0.B0 = t[0] | ||
B1: *t1, // z.C0.B1 = t[1] | ||
B2: *t2, // z.C0.B2 = t[2] | ||
}, | ||
C1: E6{ | ||
B0: *t3, // z.C1.B0 = t[3] | ||
B1: *t4, // z.C1.B1 = t[4] | ||
B2: *t5, // z.C1.B2 = t[5] | ||
}, | ||
} | ||
} | ||
|
||
func (e Ext12) FrobeniusSquare(x *E12) *E12 { | ||
z00 := &x.C0.B0 // z.C0.B0 = x.C0.B0 | ||
z01 := e.Ext2.MulByNonResidue2Power2(&x.C0.B1) // z.C0.B1.MulByNonResidue2Power2(&x.C0.B1) | ||
z02 := e.Ext2.MulByNonResidue2Power4(&x.C0.B2) // z.C0.B2.MulByNonResidue2Power4(&x.C0.B2) | ||
z10 := e.Ext2.MulByNonResidue2Power1(&x.C1.B0) // z.C1.B0.MulByNonResidue2Power1(&x.C1.B0) | ||
z11 := e.Ext2.MulByNonResidue2Power3(&x.C1.B1) // z.C1.B1.MulByNonResidue2Power3(&x.C1.B1) | ||
z12 := e.Ext2.MulByNonResidue2Power5(&x.C1.B2) // z.C1.B2.MulByNonResidue2Power5(&x.C1.B2) | ||
return &E12{ // return z | ||
C0: E6{B0: *z00, B1: *z01, B2: *z02}, | ||
C1: E6{B0: *z10, B1: *z11, B2: *z12}, | ||
} | ||
} | ||
|
||
func (e Ext12) FrobeniusCube(x *E12) *E12 { | ||
// var t [6]E2 | ||
t0 := e.Ext2.Conjugate(&x.C0.B0) // t[0].Conjugate(&x.C0.B0) | ||
t1 := e.Ext2.Conjugate(&x.C0.B1) // t[1].Conjugate(&x.C0.B1) | ||
t2 := e.Ext2.Conjugate(&x.C0.B2) // t[2].Conjugate(&x.C0.B2) | ||
t3 := e.Ext2.Conjugate(&x.C1.B0) // t[3].Conjugate(&x.C1.B0) | ||
t4 := e.Ext2.Conjugate(&x.C1.B1) // t[4].Conjugate(&x.C1.B1) | ||
t5 := e.Ext2.Conjugate(&x.C1.B2) // t[5].Conjugate(&x.C1.B2) | ||
t1 = e.Ext2.MulByNonResidue3Power2(t1) // t[1].MulByNonResidue3Power2(&t[1]) | ||
t2 = e.Ext2.MulByNonResidue3Power4(t2) // t[2].MulByNonResidue3Power4(&t[2]) | ||
t3 = e.Ext2.MulByNonResidue3Power1(t3) // t[3].MulByNonResidue3Power1(&t[3]) | ||
t4 = e.Ext2.MulByNonResidue3Power3(t4) // t[4].MulByNonResidue3Power3(&t[4]) | ||
t5 = e.Ext2.MulByNonResidue3Power5(t5) // t[5].MulByNonResidue3Power5(&t[5]) | ||
return &E12{ // return z | ||
C0: E6{ | ||
B0: *t0, // z.C0.B0 = t[0] | ||
B1: *t1, // z.C0.B1 = t[1] | ||
B2: *t2, // z.C0.B2 = t[2] | ||
}, | ||
C1: E6{ | ||
B0: *t3, // z.C1.B0 = t[3] | ||
B1: *t4, // z.C1.B1 = t[4] | ||
B2: *t5, // z.C1.B2 = t[5] | ||
}, | ||
} | ||
} | ||
|
||
func (e Ext12) One() *E12 { | ||
z000 := e.fp.One() | ||
zero := e.fp.Zero() | ||
return &E12{ | ||
C0: E6{ | ||
B0: E2{A0: *z000, A1: *zero}, | ||
B1: E2{A0: *zero, A1: *zero}, | ||
B2: E2{A0: *zero, A1: *zero}, | ||
}, | ||
C1: E6{ | ||
B0: E2{A0: *zero, A1: *zero}, | ||
B1: E2{A0: *zero, A1: *zero}, | ||
B2: E2{A0: *zero, A1: *zero}, | ||
}, | ||
} | ||
} | ||
|
||
func (e Ext12) Square(x *E12) *E12 { | ||
// var c0, c2, c3 E6 | ||
c0 := e.Ext6.Sub(&x.C0, &x.C1) // c0.Sub(&x.C0, &x.C1) | ||
c3 := e.Ext6.MulByNonResidue(&x.C1) // c3.MulByNonResidue(&x.C1). | ||
c3 = e.Ext6.Neg(c3) // Neg(&c3). | ||
c3 = e.Ext6.Add(&x.C0, c3) // Add(&x.C0, &c3) | ||
c2 := e.Ext6.Mul(&x.C0, &x.C1) // c2.Mul(&x.C0, &x.C1) | ||
c0 = e.Ext6.Mul(c0, c3) // c0.Mul(&c0, &c3). | ||
c0 = e.Ext6.Add(c0, c2) // Add(&c0, &c2) | ||
z1 := e.Ext6.double(c2) // z.C1.Double(&c2) | ||
c2 = e.Ext6.MulByNonResidue(c2) // c2.MulByNonResidue(&c2) | ||
z0 := e.Ext6.Add(c0, c2) // z.C0.Add(&c0, &c2) | ||
return &E12{ // return z | ||
C0: *z0, | ||
C1: *z1, | ||
} | ||
} | ||
|
||
func (e Ext12) AssertIsEqual(x, y *E12) { | ||
e.Ext6.AssertIsEqual(&x.C0, &y.C0) | ||
e.Ext6.AssertIsEqual(&x.C1, &y.C1) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package fields_bn254 | ||
|
||
func (e Ext12) Expt(x *E12) *E12 { | ||
// var result, t0, t1, t2, t3, t4, t5, t6 E12 | ||
t3 := e.CyclotomicSquare(x) // t3.CyclotomicSquare(x) | ||
t5 := e.CyclotomicSquare(t3) // t5.CyclotomicSquare(&t3) | ||
result := e.CyclotomicSquare(t5) // result.CyclotomicSquare(&t5) | ||
t0 := e.CyclotomicSquare(result) // t0.CyclotomicSquare(&result) | ||
t2 := e.Mul(x, t0) // t2.Mul(x, &t0) | ||
t0 = e.Mul(t3, t2) // t0.Mul(&t3, &t2) | ||
t1 := e.Mul(x, t0) // t1.Mul(x, &t0) | ||
t4 := e.Mul(result, t2) // t4.Mul(&result, &t2) | ||
t6 := e.CyclotomicSquare(t2) // t6.CyclotomicSquare(&t2) | ||
t1 = e.Mul(t0, t1) // t1.Mul(&t0, &t1) | ||
t0 = e.Mul(t3, t1) // t0.Mul(&t3, &t1) | ||
t6 = e.NCycloSquare(t6, 6) // t6.NCycloSquare(6) | ||
t5 = e.Mul(t5, t6) // t5.Mul(&t5, &t6) | ||
t5 = e.Mul(t4, t5) // t5.Mul(&t4, &t5) | ||
t5 = e.NCycloSquare(t5, 7) // t5.NCycloSquare(7) | ||
t4 = e.Mul(t4, t5) // t4.Mul(&t4, &t5) | ||
t4 = e.NCycloSquare(t4, 8) // t4.NCycloSquare(8) | ||
t4 = e.Mul(t0, t4) // t4.Mul(&t0, &t4) | ||
t3 = e.Mul(t3, t4) // t3.Mul(&t3, &t4) | ||
t3 = e.NCycloSquare(t3, 6) // t3.NCycloSquare(6) | ||
t2 = e.Mul(t2, t3) // t2.Mul(&t2, &t3) | ||
t2 = e.NCycloSquare(t2, 8) // t2.NCycloSquare(8) | ||
t2 = e.Mul(t0, t2) // t2.Mul(&t0, &t2) | ||
t2 = e.NCycloSquare(t2, 6) // t2.NCycloSquare(6) | ||
t2 = e.Mul(t0, t2) // t2.Mul(&t0, &t2) | ||
t2 = e.NCycloSquare(t2, 10) // t2.NCycloSquare(10) | ||
t1 = e.Mul(t1, t2) // t1.Mul(&t1, &t2) | ||
t1 = e.NCycloSquare(t1, 6) // t1.NCycloSquare(6) | ||
t0 = e.Mul(t0, t1) // t0.Mul(&t0, &t1) | ||
z := e.Mul(result, t0) // z.Mul(&result, &t0) | ||
return z // return z | ||
} | ||
|
||
func (e Ext12) MulBy034(z *E12, c0, c3, c4 *E2) *E12 { | ||
// var a, b, d E6 | ||
a := e.Ext6.MulByE2(&z.C0, c0) // a.MulByE2(&z.C0, c0) | ||
// b.Set(&z.C1) | ||
b := e.Ext6.MulBy01(&z.C1, c3, c4) // b.MulBy01(c3, c4) | ||
c0 = e.Ext2.Add(c0, c3) // c0.Add(c0, c3) | ||
d := e.Ext6.Add(&z.C0, &z.C1) // d.Add(&z.C0, &z.C1) | ||
d = e.Ext6.MulBy01(d, c0, c4) // d.MulBy01(c0, c4) | ||
z1 := e.Add(a, b) // z.C1.Add(&a, &b). | ||
z1 = e.Neg(z1) // Neg(&z.C1). | ||
z1 = e.Add(z1, d) // Add(&z.C1, &d) | ||
z0 := e.MulByNonResidue(b) // z.C0.MulByNonResidue(&b). | ||
z0 = e.Add(z0, a) // Add(&z.C0, &a) | ||
return &E12{ // return z | ||
C0: *z0, | ||
C1: *z1, | ||
} | ||
} | ||
|
||
func (e Ext12) MulBy034by034(d0, d3, d4, c0, c3, c4 *E2) *E12 { | ||
// var tmp, x0, x3, x4, x04, x03, x34 E2 | ||
x0 := e.Ext2.Mul(c0, d0) // x0.Mul(c0, d0) | ||
x3 := e.Ext2.Mul(c3, d3) // x3.Mul(c3, d3) | ||
x4 := e.Ext2.Mul(c4, d4) // x4.Mul(c4, d4) | ||
tmp := e.Ext2.Add(c0, c4) // tmp.Add(c0, c4) | ||
x04 := e.Ext2.Add(d0, d4) // x04.Add(d0, d4). | ||
x04 = e.Ext2.Mul(x04, tmp) // Mul(&x04, &tmp). | ||
x04 = e.Ext2.Sub(x04, x0) // Sub(&x04, &x0). | ||
x04 = e.Ext2.Sub(x04, x4) // Sub(&x04, &x4) | ||
tmp = e.Ext2.Add(c0, c3) // tmp.Add(c0, c3) | ||
x03 := e.Ext2.Add(d0, d3) // x03.Add(d0, d3). | ||
x03 = e.Ext2.Mul(x03, tmp) // Mul(&x03, &tmp). | ||
x03 = e.Ext2.Sub(x03, x0) // Sub(&x03, &x0). | ||
x03 = e.Ext2.Sub(x03, x3) // Sub(&x03, &x3) | ||
tmp = e.Ext2.Add(c3, c4) // tmp.Add(c3, c4) | ||
x34 := e.Ext2.Add(d3, d4) // x34.Add(d3, d4). | ||
x34 = e.Ext2.Mul(x34, tmp) // Mul(&x34, &tmp). | ||
x34 = e.Ext2.Sub(x34, x3) // Sub(&x34, &x3). | ||
x34 = e.Ext2.Sub(x34, x4) // Sub(&x34, &x4) | ||
z00 := e.Ext2.MulByNonResidue(x4) // z.C0.B0.MulByNonResidue(&x4). | ||
z00 = e.Ext2.Add(z00, x0) // Add(&z.C0.B0, &x0) | ||
z01 := x3 // z.C0.B1.Set(&x3) | ||
z02 := x34 // z.C0.B2.Set(&x34) | ||
z10 := x03 // z.C1.B0.Set(&x03) | ||
z11 := x04 // z.C1.B1.Set(&x04) | ||
z12 := e.Ext2.Zero() // z.C1.B2.SetZero() | ||
return &E12{ // return z | ||
C0: E6{ | ||
B0: *z00, | ||
B1: *z01, | ||
B2: *z02, | ||
}, | ||
C1: E6{ | ||
B0: *z10, | ||
B1: *z11, | ||
B2: *z12, | ||
}, | ||
} | ||
} |
Oops, something went wrong.