From 6bb39798585c5e17c9ca812d984c1290865521bd Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Sat, 5 Jun 2021 12:44:30 +0200 Subject: [PATCH] ristretto255: replace backend with filippo.io/edwards25519 --- fe.go | 111 -- go.mod | 4 +- go.sum | 2 + internal/edwards25519/edwards25519.go | 328 ------ internal/edwards25519/edwards25519_test.go | 47 - internal/edwards25519/scalarmult.go | 288 ----- internal/edwards25519/scalarmult_test.go | 258 ----- internal/edwards25519/table_constants.go | 49 - internal/edwards25519/tables.go | 129 --- internal/edwards25519/tables_test.go | 125 --- internal/radix51/alias_test.go | 128 --- internal/radix51/bench_test.go | 40 - internal/radix51/fe.go | 392 ------- internal/radix51/fe_amd64.go | 13 - internal/radix51/fe_amd64.s | 348 ------ internal/radix51/fe_generic.go | 179 ---- internal/radix51/fe_noasm.go | 11 - internal/radix51/fe_test.go | 395 ------- internal/radix51/mul_bits.go | 28 - internal/radix51/mul_compat.go | 37 - internal/scalar/scalar.go | 1112 -------------------- internal/scalar/scalar_test.go | 133 --- ristretto255.go | 307 +++--- ristretto255_test.go | 108 +- scalar.go | 36 +- 25 files changed, 255 insertions(+), 4353 deletions(-) delete mode 100644 fe.go create mode 100644 go.sum delete mode 100644 internal/edwards25519/edwards25519.go delete mode 100644 internal/edwards25519/edwards25519_test.go delete mode 100644 internal/edwards25519/scalarmult.go delete mode 100644 internal/edwards25519/scalarmult_test.go delete mode 100644 internal/edwards25519/table_constants.go delete mode 100644 internal/edwards25519/tables.go delete mode 100644 internal/edwards25519/tables_test.go delete mode 100644 internal/radix51/alias_test.go delete mode 100644 internal/radix51/bench_test.go delete mode 100644 internal/radix51/fe.go delete mode 100644 internal/radix51/fe_amd64.go delete mode 100644 internal/radix51/fe_amd64.s delete mode 100644 internal/radix51/fe_generic.go delete mode 100644 internal/radix51/fe_noasm.go delete mode 100644 internal/radix51/fe_test.go delete mode 100644 internal/radix51/mul_bits.go delete mode 100644 internal/radix51/mul_compat.go delete mode 100644 internal/scalar/scalar.go delete mode 100644 internal/scalar/scalar_test.go diff --git a/fe.go b/fe.go deleted file mode 100644 index bd94255..0000000 --- a/fe.go +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Copyright 2019 George Tankersley. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package ristretto255 - -import ( - "math/big" - - "github.com/gtank/ristretto255/internal/radix51" -) - -// fePow22523 sets out to z^((p-5)/8). (p-5)/8 is 2^252-3. -func fePow22523(out, z *radix51.FieldElement) *radix51.FieldElement { - // Refactored from golang.org/x/crypto/ed25519/internal/edwards25519. - - var t0, t1, t2 radix51.FieldElement - - t0.Square(z) - for i := 1; i < 1; i++ { - t0.Square(&t0) - } - t1.Square(&t0) - for i := 1; i < 2; i++ { - t1.Square(&t1) - } - t1.Mul(z, &t1) - t0.Mul(&t0, &t1) - t0.Square(&t0) - for i := 1; i < 1; i++ { - t0.Square(&t0) - } - t0.Mul(&t1, &t0) - t1.Square(&t0) - for i := 1; i < 5; i++ { - t1.Square(&t1) - } - t0.Mul(&t1, &t0) - t1.Square(&t0) - for i := 1; i < 10; i++ { - t1.Square(&t1) - } - t1.Mul(&t1, &t0) - t2.Square(&t1) - for i := 1; i < 20; i++ { - t2.Square(&t2) - } - t1.Mul(&t2, &t1) - t1.Square(&t1) - for i := 1; i < 10; i++ { - t1.Square(&t1) - } - t0.Mul(&t1, &t0) - t1.Square(&t0) - for i := 1; i < 50; i++ { - t1.Square(&t1) - } - t1.Mul(&t1, &t0) - t2.Square(&t1) - for i := 1; i < 100; i++ { - t2.Square(&t2) - } - t1.Mul(&t2, &t1) - t1.Square(&t1) - for i := 1; i < 50; i++ { - t1.Square(&t1) - } - t0.Mul(&t1, &t0) - t0.Square(&t0) - for i := 1; i < 2; i++ { - t0.Square(&t0) - } - return out.Mul(&t0, z) -} - -// feSqrtRatio sets r to the square root of the ratio of u and v, according to -// Section 3.1.3 of draft-hdevalence-cfrg-ristretto-00. -func feSqrtRatio(r, u, v *radix51.FieldElement) (wasSquare int) { - var a, b radix51.FieldElement - - v3 := a.Mul(a.Square(v), v) // v^3 = v^2 * v - v7 := b.Mul(b.Square(v3), v) // v^7 = (v^3)^2 * v - - // r = (u * v3) * (u * v7)^((p-5)/8) - uv3 := a.Mul(u, v3) // (u * v3) - uv7 := b.Mul(u, v7) // (u * v7) - r.Mul(uv3, fePow22523(r, uv7)) - - check := a.Mul(v, a.Square(r)) // check = v * r^2 - - uNeg := b.Neg(u) - correctSignSqrt := check.Equal(u) - flippedSignSqrt := check.Equal(uNeg) - flippedSignSqrtI := check.Equal(uNeg.Mul(uNeg, sqrtM1)) - - rPrime := b.Mul(r, sqrtM1) // r_prime = SQRT_M1 * r - // r = CT_SELECT(r_prime IF flipped_sign_sqrt | flipped_sign_sqrt_i ELSE r) - r.Select(rPrime, r, flippedSignSqrt|flippedSignSqrtI) - - r.Abs(r) // Choose the nonnegative square root. - return correctSignSqrt | flippedSignSqrt -} - -func fieldElementFromDecimal(s string) *radix51.FieldElement { - n, ok := new(big.Int).SetString(s, 10) - if !ok { - panic("ristretto255: not a valid decimal: " + s) - } - return new(radix51.FieldElement).FromBig(n) -} diff --git a/go.mod b/go.mod index 30a573b..622850f 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module github.com/gtank/ristretto255 -go 1.11 +go 1.17 + +require filippo.io/edwards25519 v1.0.0-rc.1 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..6fb9eef --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU= +filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= diff --git a/internal/edwards25519/edwards25519.go b/internal/edwards25519/edwards25519.go deleted file mode 100644 index a0808bc..0000000 --- a/internal/edwards25519/edwards25519.go +++ /dev/null @@ -1,328 +0,0 @@ -// Copyright (c) 2017 George Tankersley. All rights reserved. -// Copyright (c) 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package edwards25519 implements group logic for the twisted Edwards curve -// -// -x^2 + y^2 = 1 + -(121665/121666)*x^2*y^2 -// -// This is better known as the Edwards curve equivalent to curve25519, and is -// the curve used by the Ed25519 signature scheme. -package edwards25519 - -import ( - "github.com/gtank/ristretto255/internal/radix51" -) - -// D is a constant in the curve equation. -var D = &radix51.FieldElement{929955233495203, 466365720129213, - 1662059464998953, 2033849074728123, 1442794654840575} -var d2 = new(radix51.FieldElement).Add(D, D) - -// Point types. - -// TODO: write documentation -// TODO: rename (T,X,Y,Z) to (W0,W1,W2,W3) for P2 and P3 models? -// https://doc-internal.dalek.rs/curve25519_dalek/backend/serial/curve_models/index.html - -type ProjP1xP1 struct { - X, Y, Z, T radix51.FieldElement -} - -type ProjP2 struct { - X, Y, Z radix51.FieldElement -} - -type ProjP3 struct { - X, Y, Z, T radix51.FieldElement -} - -type ProjCached struct { - YplusX, YminusX, Z, T2d radix51.FieldElement -} - -type AffineCached struct { - YplusX, YminusX, T2d radix51.FieldElement -} - -// B is the Ed25519 basepoint. -var B = ProjP3{ - X: radix51.FieldElement([5]uint64{1738742601995546, 1146398526822698, 2070867633025821, 562264141797630, 587772402128613}), - Y: radix51.FieldElement([5]uint64{1801439850948184, 1351079888211148, 450359962737049, 900719925474099, 1801439850948198}), - Z: radix51.FieldElement([5]uint64{1, 0, 0, 0, 0}), - T: radix51.FieldElement([5]uint64{1841354044333475, 16398895984059, 755974180946558, 900171276175154, 1821297809914039}), -} - -// Constructors. - -func (v *ProjP1xP1) Zero() *ProjP1xP1 { - v.X.Zero() - v.Y.One() - v.Z.One() - v.T.One() - return v -} - -func (v *ProjP2) Zero() *ProjP2 { - v.X.Zero() - v.Y.One() - v.Z.One() - return v -} - -func (v *ProjP3) Zero() *ProjP3 { - v.X.Zero() - v.Y.One() - v.Z.One() - v.T.Zero() - return v -} - -func (v *ProjCached) Zero() *ProjCached { - v.YplusX.One() - v.YminusX.One() - v.Z.One() - v.T2d.Zero() - return v -} - -func (v *AffineCached) Zero() *AffineCached { - v.YplusX.One() - v.YminusX.One() - v.T2d.Zero() - return v -} - -// Assignments. - -func (v *ProjP3) Set(u *ProjP3) *ProjP3 { - *v = *u - return v -} - -// Conversions. - -func (v *ProjP2) FromP1xP1(p *ProjP1xP1) *ProjP2 { - v.X.Mul(&p.X, &p.T) - v.Y.Mul(&p.Y, &p.Z) - v.Z.Mul(&p.Z, &p.T) - return v -} - -func (v *ProjP2) FromP3(p *ProjP3) *ProjP2 { - v.X.Set(&p.X) - v.Y.Set(&p.Y) - v.Z.Set(&p.Z) - return v -} - -func (v *ProjP3) FromP1xP1(p *ProjP1xP1) *ProjP3 { - v.X.Mul(&p.X, &p.T) - v.Y.Mul(&p.Y, &p.Z) - v.Z.Mul(&p.Z, &p.T) - v.T.Mul(&p.X, &p.Y) - return v -} - -func (v *ProjP3) FromP2(p *ProjP2) *ProjP3 { - v.X.Mul(&p.X, &p.Z) - v.Y.Mul(&p.Y, &p.Z) - v.Z.Square(&p.Z) - v.T.Mul(&p.X, &p.Y) - return v -} - -func (v *ProjCached) FromP3(p *ProjP3) *ProjCached { - v.YplusX.Add(&p.Y, &p.X) - v.YminusX.Sub(&p.Y, &p.X) - v.Z.Set(&p.Z) - v.T2d.Mul(&p.T, d2) - return v -} - -func (v *AffineCached) FromP3(p *ProjP3) *AffineCached { - v.YplusX.Add(&p.Y, &p.X) - v.YminusX.Sub(&p.Y, &p.X) - v.T2d.Mul(&p.T, d2) - - var invZ radix51.FieldElement - invZ.Invert(&p.Z) - v.YplusX.Mul(&v.YplusX, &invZ) - v.YminusX.Mul(&v.YminusX, &invZ) - v.T2d.Mul(&v.T2d, &invZ) - return v -} - -// (Re)addition and subtraction. - -func (v *ProjP3) Add(p, q *ProjP3) *ProjP3 { - result := ProjP1xP1{} - qCached := ProjCached{} - qCached.FromP3(q) - result.Add(p, &qCached) - v.FromP1xP1(&result) - return v -} - -func (v *ProjP3) Sub(p, q *ProjP3) *ProjP3 { - result := ProjP1xP1{} - qCached := ProjCached{} - qCached.FromP3(q) - result.Sub(p, &qCached) - v.FromP1xP1(&result) - return v -} - -func (v *ProjP1xP1) Add(p *ProjP3, q *ProjCached) *ProjP1xP1 { - var YplusX, YminusX, PP, MM, TT2d, ZZ2 radix51.FieldElement - - YplusX.Add(&p.Y, &p.X) - YminusX.Sub(&p.Y, &p.X) - - PP.Mul(&YplusX, &q.YplusX) - MM.Mul(&YminusX, &q.YminusX) - TT2d.Mul(&p.T, &q.T2d) - ZZ2.Mul(&p.Z, &q.Z) - - ZZ2.Add(&ZZ2, &ZZ2) - - v.X.Sub(&PP, &MM) - v.Y.Add(&PP, &MM) - v.Z.Add(&ZZ2, &TT2d) - v.T.Sub(&ZZ2, &TT2d) - return v -} - -func (v *ProjP1xP1) Sub(p *ProjP3, q *ProjCached) *ProjP1xP1 { - var YplusX, YminusX, PP, MM, TT2d, ZZ2 radix51.FieldElement - - YplusX.Add(&p.Y, &p.X) - YminusX.Sub(&p.Y, &p.X) - - PP.Mul(&YplusX, &q.YminusX) // flipped sign - MM.Mul(&YminusX, &q.YplusX) // flipped sign - TT2d.Mul(&p.T, &q.T2d) - ZZ2.Mul(&p.Z, &q.Z) - - ZZ2.Add(&ZZ2, &ZZ2) - - v.X.Sub(&PP, &MM) - v.Y.Add(&PP, &MM) - v.Z.Sub(&ZZ2, &TT2d) // flipped sign - v.T.Add(&ZZ2, &TT2d) // flipped sign - return v -} - -func (v *ProjP1xP1) AddAffine(p *ProjP3, q *AffineCached) *ProjP1xP1 { - var YplusX, YminusX, PP, MM, TT2d, Z2 radix51.FieldElement - - YplusX.Add(&p.Y, &p.X) - YminusX.Sub(&p.Y, &p.X) - - PP.Mul(&YplusX, &q.YplusX) - MM.Mul(&YminusX, &q.YminusX) - TT2d.Mul(&p.T, &q.T2d) - - Z2.Add(&p.Z, &p.Z) - - v.X.Sub(&PP, &MM) - v.Y.Add(&PP, &MM) - v.Z.Add(&Z2, &TT2d) - v.T.Sub(&Z2, &TT2d) - return v -} - -func (v *ProjP1xP1) SubAffine(p *ProjP3, q *AffineCached) *ProjP1xP1 { - var YplusX, YminusX, PP, MM, TT2d, Z2 radix51.FieldElement - - YplusX.Add(&p.Y, &p.X) - YminusX.Sub(&p.Y, &p.X) - - PP.Mul(&YplusX, &q.YminusX) // flipped sign - MM.Mul(&YminusX, &q.YplusX) // flipped sign - TT2d.Mul(&p.T, &q.T2d) - - Z2.Add(&p.Z, &p.Z) - - v.X.Sub(&PP, &MM) - v.Y.Add(&PP, &MM) - v.Z.Sub(&Z2, &TT2d) // flipped sign - v.T.Add(&Z2, &TT2d) // flipped sign - return v -} - -// Doubling. - -func (v *ProjP1xP1) Double(p *ProjP2) *ProjP1xP1 { - var XX, YY, ZZ2, XplusYsq radix51.FieldElement - - XX.Square(&p.X) - YY.Square(&p.Y) - ZZ2.Square(&p.Z) - ZZ2.Add(&ZZ2, &ZZ2) - XplusYsq.Add(&p.X, &p.Y) - XplusYsq.Square(&XplusYsq) - - v.Y.Add(&YY, &XX) - v.Z.Sub(&YY, &XX) - - v.X.Sub(&XplusYsq, &v.Y) - v.T.Sub(&ZZ2, &v.Z) - return v -} - -// Negation. - -func (v *ProjP3) Neg(p *ProjP3) *ProjP3 { - v.X.Neg(&p.X) - v.Y.Set(&p.Y) - v.Z.Set(&p.Z) - v.T.Neg(&p.T) - return v -} - -// by @ebfull -// https://github.com/dalek-cryptography/curve25519-dalek/pull/226/files -func (v *ProjP3) Equal(u *ProjP3) int { - var t1, t2, t3, t4 radix51.FieldElement - t1.Mul(&v.X, &u.Z) - t2.Mul(&u.X, &v.Z) - t3.Mul(&v.Y, &u.Z) - t4.Mul(&u.Y, &v.Z) - - return t1.Equal(&t2) & t3.Equal(&t4) -} - -// Constant-time operations - -// Select sets v to a if cond == 1 and to b if cond == 0. -func (v *ProjCached) Select(a, b *ProjCached, cond int) *ProjCached { - v.YplusX.Select(&a.YplusX, &b.YplusX, cond) - v.YminusX.Select(&a.YminusX, &b.YminusX, cond) - v.Z.Select(&a.Z, &b.Z, cond) - v.T2d.Select(&a.T2d, &b.T2d, cond) - return v -} - -// Select sets v to a if cond == 1 and to b if cond == 0. -func (v *AffineCached) Select(a, b *AffineCached, cond int) *AffineCached { - v.YplusX.Select(&a.YplusX, &b.YplusX, cond) - v.YminusX.Select(&a.YminusX, &b.YminusX, cond) - v.T2d.Select(&a.T2d, &b.T2d, cond) - return v -} - -// CondNeg negates v if cond == 1 and leaves it unchanged if cond == 0. -func (v *ProjCached) CondNeg(cond int) *ProjCached { - radix51.CondSwap(&v.YplusX, &v.YminusX, cond) - v.T2d.CondNeg(&v.T2d, cond) - return v -} - -// CondNeg negates v if cond == 1 and leaves it unchanged if cond == 0. -func (v *AffineCached) CondNeg(cond int) *AffineCached { - radix51.CondSwap(&v.YplusX, &v.YminusX, cond) - v.T2d.CondNeg(&v.T2d, cond) - return v -} diff --git a/internal/edwards25519/edwards25519_test.go b/internal/edwards25519/edwards25519_test.go deleted file mode 100644 index d8b1de6..0000000 --- a/internal/edwards25519/edwards25519_test.go +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2019 Henry de Valence. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package edwards25519 - -import ( - "testing" -) - -func TestAddSubNegOnBasePoint(t *testing.T) { - var Bneg ProjP3 - var tmpP2 ProjP2 - var tmpP1xP1 ProjP1xP1 - var tmpCached ProjCached - - Bneg.Neg(&B) - - var checkLhs, checkRhs, zero ProjP3 - zero.Zero() - - tmpCached.FromP3(&B) - tmpP1xP1.Add(&B, &tmpCached) - checkLhs.FromP1xP1(&tmpP1xP1) - tmpP2.FromP3(&B) - tmpP1xP1.Double(&tmpP2) - checkRhs.FromP1xP1(&tmpP1xP1) - if checkLhs.Equal(&checkRhs) != 1 { - t.Error("B + B != [2]B") - } - - tmpCached.FromP3(&B) - tmpP1xP1.Sub(&B, &tmpCached) - checkLhs.FromP1xP1(&tmpP1xP1) - tmpCached.FromP3(&Bneg) - tmpP1xP1.Add(&B, &tmpCached) - checkRhs.FromP1xP1(&tmpP1xP1) - if checkLhs.Equal(&checkRhs) != 1 { - t.Error("B - B != B + (-B)") - } - if zero.Equal(&checkLhs) != 1 { - t.Error("B - B != 0") - } - if zero.Equal(&checkRhs) != 1 { - t.Error("B + (-B) != 0") - } -} diff --git a/internal/edwards25519/scalarmult.go b/internal/edwards25519/scalarmult.go deleted file mode 100644 index a3c3916..0000000 --- a/internal/edwards25519/scalarmult.go +++ /dev/null @@ -1,288 +0,0 @@ -// Copyright (c) 2019 Henry de Valence. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package edwards25519 - -import ( - "github.com/gtank/ristretto255/internal/scalar" -) - -// Set v to x*B, where B is the Ed25519 basepoint, and return v. -// -// The scalar multiplication is done in constant time. -func (v *ProjP3) BasepointMul(x *scalar.Scalar) *ProjP3 { - // Write x = sum(x_i * 16^i) so x*B = sum( B*x_i*16^i ) - // as described in the Ed25519 paper - // - // Group even and odd coefficients - // x*B = x_0*16^0*B + x_2*16^2*B + ... + x_62*16^62*B - // + x_1*16^1*B + x_3*16^3*B + ... + x_63*16^63*B - // x*B = x_0*16^0*B + x_2*16^2*B + ... + x_62*16^62*B - // + 16*( x_1*16^0*B + x_3*16^2*B + ... + x_63*16^62*B) - // - // We use a lookup table for each i to get x_i*16^(2*i)*B - // and do four doublings to multiply by 16. - digits := x.SignedRadix16() - - multiple := &AffineCached{} - tmp1 := &ProjP1xP1{} - tmp2 := &ProjP2{} - - // Accumulate the odd components first - v.Zero() - for i := 1; i < 64; i += 2 { - basepointTable[i/2].SelectInto(multiple, digits[i]) - tmp1.AddAffine(v, multiple) - v.FromP1xP1(tmp1) - } - - // Multiply by 16 - tmp2.FromP3(v) // tmp2 = v in P2 coords - tmp1.Double(tmp2) // tmp1 = 2*v in P1xP1 coords - tmp2.FromP1xP1(tmp1) // tmp2 = 2*v in P2 coords - tmp1.Double(tmp2) // tmp1 = 4*v in P1xP1 coords - tmp2.FromP1xP1(tmp1) // tmp2 = 4*v in P2 coords - tmp1.Double(tmp2) // tmp1 = 8*v in P1xP1 coords - tmp2.FromP1xP1(tmp1) // tmp2 = 8*v in P2 coords - tmp1.Double(tmp2) // tmp1 = 16*v in P1xP1 coords - v.FromP1xP1(tmp1) // now v = 16*(odd components) - - // Accumulate the even components - for i := 0; i < 64; i += 2 { - basepointTable[i/2].SelectInto(multiple, digits[i]) - tmp1.AddAffine(v, multiple) - v.FromP1xP1(tmp1) - } - - return v -} - -// Set v to x*Q, and return v. v and q may alias. -// -// The scalar multiplication is done in constant time. -func (v *ProjP3) ScalarMul(x *scalar.Scalar, q *ProjP3) *ProjP3 { - var table projLookupTable - table.FromP3(q) - // v and q could alias, but once the table is built we can clobber v. - v.Zero() - - // Write x = sum(x_i * 16^i) - // so x*Q = sum( Q*x_i*16^i ) - // = Q*x_0 + 16*(Q*x_1 + 16*( ... + Q*x_63) ... ) - // <------compute inside out--------- - // - // We use the lookup table to get the x_i*Q values - // and do four doublings to compute 16*Q - digits := x.SignedRadix16() - - // Unwrap first loop iteration to save computing 16*identity - multiple := &ProjCached{} - tmp1 := &ProjP1xP1{} - tmp2 := &ProjP2{} - table.SelectInto(multiple, digits[63]) - tmp1.Add(v, multiple) // tmp1 = x_63*Q in P1xP1 coords - for i := 62; i >= 0; i-- { - tmp2.FromP1xP1(tmp1) // tmp2 = (prev) in P2 coords - tmp1.Double(tmp2) // tmp1 = 2*(prev) in P1xP1 coords - tmp2.FromP1xP1(tmp1) // tmp2 = 2*(prev) in P2 coords - tmp1.Double(tmp2) // tmp1 = 4*(prev) in P1xP1 coords - tmp2.FromP1xP1(tmp1) // tmp2 = 4*(prev) in P2 coords - tmp1.Double(tmp2) // tmp1 = 8*(prev) in P1xP1 coords - tmp2.FromP1xP1(tmp1) // tmp2 = 8*(prev) in P2 coords - tmp1.Double(tmp2) // tmp1 = 16*(prev) in P1xP1 coords - v.FromP1xP1(tmp1) // v = 16*(prev) in P3 coords - table.SelectInto(multiple, digits[i]) - tmp1.Add(v, multiple) // tmp1 = x_i*Q + 16*(prev) in P1xP1 coords - } - v.FromP1xP1(tmp1) - return v -} - -// Set v to the result of a multiscalar multiplication and return v. -// -// The multiscalar multiplication is sum(scalars[i]*points[i]). -// -// The multiscalar multiplication is performed in constant time. -func (v *ProjP3) MultiscalarMul(scalars []scalar.Scalar, points []*ProjP3) *ProjP3 { - if len(scalars) != len(points) { - panic("called MultiscalarMul with different size inputs") - } - - // Proceed as in the single-base case, but share doublings - // between each point in the multiscalar equation. - - // Build lookup tables for each point - tables := make([]projLookupTable, len(points)) - for i := range tables { - tables[i].FromP3(points[i]) - } - // Compute signed radix-16 digits for each scalar - digits := make([][64]int8, len(scalars)) - for i := range digits { - digits[i] = scalars[i].SignedRadix16() - } - - // Unwrap first loop iteration to save computing 16*identity - multiple := &ProjCached{} - tmp1 := &ProjP1xP1{} - tmp2 := &ProjP2{} - // Lookup-and-add the appropriate multiple of each input point - for j := range tables { - tables[j].SelectInto(multiple, digits[j][63]) - tmp1.Add(v, multiple) // tmp1 = v + x_(j,63)*Q in P1xP1 coords - v.FromP1xP1(tmp1) // update v - } - tmp2.FromP3(v) // set up tmp2 = v in P2 coords for next iteration - for i := 62; i >= 0; i-- { - tmp1.Double(tmp2) // tmp1 = 2*(prev) in P1xP1 coords - tmp2.FromP1xP1(tmp1) // tmp2 = 2*(prev) in P2 coords - tmp1.Double(tmp2) // tmp1 = 4*(prev) in P1xP1 coords - tmp2.FromP1xP1(tmp1) // tmp2 = 4*(prev) in P2 coords - tmp1.Double(tmp2) // tmp1 = 8*(prev) in P1xP1 coords - tmp2.FromP1xP1(tmp1) // tmp2 = 8*(prev) in P2 coords - tmp1.Double(tmp2) // tmp1 = 16*(prev) in P1xP1 coords - v.FromP1xP1(tmp1) // v = 16*(prev) in P3 coords - // Lookup-and-add the appropriate multiple of each input point - for j := range tables { - tables[j].SelectInto(multiple, digits[j][i]) - tmp1.Add(v, multiple) // tmp1 = v + x_(j,i)*Q in P1xP1 coords - v.FromP1xP1(tmp1) // update v - } - tmp2.FromP3(v) // set up tmp2 = v in P2 coords for next iteration - } - return v -} - -// Set v to a*A + b*B, where B is the Ed25519 basepoint, and return v. -// -// The scalar multiplication is done in variable time. -func (v *ProjP3) VartimeDoubleBaseMul(a *scalar.Scalar, A *ProjP3, b *scalar.Scalar) *ProjP3 { - // Similarly to the single variable-base approach, we compute - // digits and use them with a lookup table. However, because - // we are allowed to do variable-time operations, we don't - // need constant-time lookups or constant-time digit - // computations. - // - // So we use a non-adjacent form of some width w instead of - // radix 16. This is like a binary representation (one digit - // for each binary place) but we allow the digits to grow in - // magnitude up to 2^{w-1} so that the nonzero digits are as - // sparse as possible. Intuitively, this "condenses" the - // "mass" of the scalar onto sparse coefficients (meaning - // fewer additions). - - var aTable nafLookupTable5 - aTable.FromP3(A) - // Because the basepoint is fixed, we can use a wider NAF - // corresponding to a bigger table. - aNaf := a.NonAdjacentForm(5) - bNaf := b.NonAdjacentForm(8) - - // Find the first nonzero coefficient. - i := 255 - for j := i; j >= 0; j-- { - if aNaf[j] != 0 || bNaf[j] != 0 { - break - } - } - - multA := &ProjCached{} - multB := &AffineCached{} - tmp1 := &ProjP1xP1{} - tmp2 := &ProjP2{} - tmp2.Zero() - v.Zero() - - // Move from high to low bits, doubling the accumulator - // at each iteration and checking whether there is a nonzero - // coefficient to look up a multiple of. - for ; i >= 0; i-- { - tmp1.Double(tmp2) - - // Only update v if we have a nonzero coeff to add in. - if aNaf[i] > 0 { - v.FromP1xP1(tmp1) - aTable.SelectInto(multA, aNaf[i]) - tmp1.Add(v, multA) - } else if aNaf[i] < 0 { - v.FromP1xP1(tmp1) - aTable.SelectInto(multA, -aNaf[i]) - tmp1.Sub(v, multA) - } - - if bNaf[i] > 0 { - v.FromP1xP1(tmp1) - basepointNafTable.SelectInto(multB, bNaf[i]) - tmp1.AddAffine(v, multB) - } else if bNaf[i] < 0 { - v.FromP1xP1(tmp1) - basepointNafTable.SelectInto(multB, -bNaf[i]) - tmp1.SubAffine(v, multB) - } - - tmp2.FromP1xP1(tmp1) - } - - v.FromP2(tmp2) - return v -} - -// Set v to the result of a multiscalar multiplication and return v. -// -// The multiscalar multiplication is sum(scalars[i]*points[i]). -// -// The multiscalar multiplication is performed in variable time. -func (v *ProjP3) VartimeMultiscalarMul(scalars []scalar.Scalar, points []*ProjP3) *ProjP3 { - if len(scalars) != len(points) { - panic("called MultiscalarMul with different size inputs") - } - - // Generalize double-base NAF computation to arbitrary sizes. - // Here all the points are dynamic, so we only use the smaller - // tables. - - // Build lookup tables for each point - tables := make([]nafLookupTable5, len(points)) - for i := range tables { - tables[i].FromP3(points[i]) - } - // Compute a NAF for each scalar - nafs := make([][256]int8, len(scalars)) - for i := range nafs { - nafs[i] = scalars[i].NonAdjacentForm(5) - } - - multiple := &ProjCached{} - tmp1 := &ProjP1xP1{} - tmp2 := &ProjP2{} - tmp2.Zero() - v.Zero() - - // Move from high to low bits, doubling the accumulator - // at each iteration and checking whether there is a nonzero - // coefficient to look up a multiple of. - // - // Skip trying to find the first nonzero coefficent, because - // searching might be more work than a few extra doublings. - for i := 255; i >= 0; i-- { - tmp1.Double(tmp2) - - for j := range nafs { - if nafs[j][i] > 0 { - v.FromP1xP1(tmp1) - tables[j].SelectInto(multiple, nafs[j][i]) - tmp1.Add(v, multiple) - } else if nafs[j][i] < 0 { - v.FromP1xP1(tmp1) - tables[j].SelectInto(multiple, -nafs[j][i]) - tmp1.Sub(v, multiple) - } - } - - tmp2.FromP1xP1(tmp1) - } - - v.FromP2(tmp2) - return v -} diff --git a/internal/edwards25519/scalarmult_test.go b/internal/edwards25519/scalarmult_test.go deleted file mode 100644 index d435a38..0000000 --- a/internal/edwards25519/scalarmult_test.go +++ /dev/null @@ -1,258 +0,0 @@ -// Copyright 2019 Henry de Valence. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package edwards25519 - -import ( - "testing" - "testing/quick" - - "github.com/gtank/ristretto255/internal/radix51" - "github.com/gtank/ristretto255/internal/scalar" -) - -// quickCheckConfig will make each quickcheck test run (2^6 * -quickchecks) -// times. The default value of -quickchecks is 100. -var ( - quickCheckConfig = &quick.Config{MaxCountScale: 1 << 6} - - // a random scalar generated using dalek. - dalekScalar = scalar.Scalar([32]byte{219, 106, 114, 9, 174, 249, 155, 89, 69, 203, 201, 93, 92, 116, 234, 187, 78, 115, 103, 172, 182, 98, 62, 103, 187, 136, 13, 100, 248, 110, 12, 4}) - // the above, times the Ed25519 basepoint. - dalekScalarBasepoint = ProjP3{ - X: radix51.FieldElement([5]uint64{778774234987948, 1589187156384239, 1213330452914652, 186161118421127, 2186284806803213}), - Y: radix51.FieldElement([5]uint64{1241255309069369, 1115278942994853, 1016511918109334, 1303231926552315, 1801448517689873}), - Z: radix51.FieldElement([5]uint64{353337085654440, 1327844406437681, 2207296012811921, 707394926933424, 917408459573183}), - T: radix51.FieldElement([5]uint64{585487439439725, 1792815221887900, 946062846079052, 1954901232609667, 1418300670001780}), - } -) - -func TestScalarMulSmallScalars(t *testing.T) { - var z scalar.Scalar - var p, check ProjP3 - p.ScalarMul(&z, &B) - check.Zero() - if check.Equal(&p) != 1 { - t.Error("0*B != 0") - } - - z = scalar.Scalar([32]byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) - p.ScalarMul(&z, &B) - check.Set(&B) - if check.Equal(&p) != 1 { - t.Error("1*B != 1") - } -} - -func TestScalarMulVsDalek(t *testing.T) { - var p ProjP3 - p.ScalarMul(&dalekScalar, &B) - if dalekScalarBasepoint.Equal(&p) != 1 { - t.Error("Scalar mul does not match dalek") - } -} - -func TestBasepointMulVsDalek(t *testing.T) { - var p ProjP3 - p.BasepointMul(&dalekScalar) - if dalekScalarBasepoint.Equal(&p) != 1 { - t.Error("Scalar mul does not match dalek") - } -} - -func TestVartimeDoubleBaseMulVsDalek(t *testing.T) { - var p ProjP3 - var z scalar.Scalar - p.VartimeDoubleBaseMul(&dalekScalar, &B, &z) - if dalekScalarBasepoint.Equal(&p) != 1 { - t.Error("VartimeDoubleBaseMul fails with b=0") - } - p.VartimeDoubleBaseMul(&z, &B, &dalekScalar) - if dalekScalarBasepoint.Equal(&p) != 1 { - t.Error("VartimeDoubleBaseMul fails with a=0") - } -} - -func TestScalarMulDistributesOverAdd(t *testing.T) { - scalarMulDistributesOverAdd := func(x, y scalar.Scalar) bool { - // The quickcheck generation strategy chooses a random - // 32-byte array, but we require that the high bit is - // unset. FIXME: make Scalar opaque. Until then, - // mask the high bits: - x[31] &= 127 - y[31] &= 127 - var z scalar.Scalar - z.Add(&x, &y) - var p, q, r, check ProjP3 - p.ScalarMul(&x, &B) - q.ScalarMul(&y, &B) - r.ScalarMul(&z, &B) - check.Add(&p, &q) - return check.Equal(&r) == 1 - } - - if err := quick.Check(scalarMulDistributesOverAdd, quickCheckConfig); err != nil { - t.Error(err) - } -} - -func TestBasepointTableGeneration(t *testing.T) { - // The basepoint table is 32 affineLookupTables, - // corresponding to (16^2i)*B for table i. - - tmp1 := &ProjP1xP1{} - tmp2 := &ProjP2{} - tmp3 := &ProjP3{} - tmp3.Set(&B) - table := make([]affineLookupTable, 32) - for i := 0; i < 32; i++ { - // Build the table - table[i].FromP3(tmp3) - // Assert equality with the hardcoded one - if table[i] != basepointTable[i] { - t.Errorf("Basepoint table %d does not match", i) - } - - // Set p = (16^2)*p = 256*p = 2^8*p - tmp2.FromP3(tmp3) - for j := 0; j < 7; j++ { - tmp1.Double(tmp2) - tmp2.FromP1xP1(tmp1) - } - tmp1.Double(tmp2) - tmp3.FromP1xP1(tmp1) - } -} - -func TestScalarMulMatchesBasepointMul(t *testing.T) { - scalarMulMatchesBasepointMul := func(x scalar.Scalar) bool { - // FIXME opaque scalars - x[31] &= 127 - var p, q ProjP3 - p.ScalarMul(&x, &B) - q.BasepointMul(&x) - return p.Equal(&q) == 1 - } - - if err := quick.Check(scalarMulMatchesBasepointMul, quickCheckConfig); err != nil { - t.Error(err) - } -} - -func TestMultiScalarMulMatchesBasepointMul(t *testing.T) { - multiScalarMulMatchesBasepointMul := func(x, y, z scalar.Scalar) bool { - // FIXME opaque scalars - x[31] &= 127 - y[31] &= 127 - z[31] &= 127 - var p, q1, q2, q3, check ProjP3 - - p.MultiscalarMul([]scalar.Scalar{x, y, z}, []*ProjP3{&B, &B, &B}) - - q1.BasepointMul(&x) - q2.BasepointMul(&y) - q3.BasepointMul(&z) - check.Zero() - check.Add(&q1, &q2).Add(&check, &q3) - - return p.Equal(&check) == 1 - } - - if err := quick.Check(multiScalarMulMatchesBasepointMul, quickCheckConfig); err != nil { - t.Error(err) - } -} - -func TestBasepointNafTableGeneration(t *testing.T) { - var table nafLookupTable8 - table.FromP3(&B) - - if table != basepointNafTable { - t.Error("BasepointNafTable does not match") - } -} - -func TestVartimeDoubleBaseMulMatchesBasepointMul(t *testing.T) { - vartimeDoubleBaseMulMatchesBasepointMul := func(x, y scalar.Scalar) bool { - // FIXME opaque scalars - x[31] &= 127 - y[31] &= 127 - var p, q1, q2, check ProjP3 - - p.VartimeDoubleBaseMul(&x, &B, &y) - - q1.BasepointMul(&x) - q2.BasepointMul(&y) - check.Zero() - check.Add(&q1, &q2) - - return p.Equal(&check) == 1 - } - - if err := quick.Check(vartimeDoubleBaseMulMatchesBasepointMul, quickCheckConfig); err != nil { - t.Error(err) - } -} - -func TestVartimeMultiScalarMulMatchesBasepointMul(t *testing.T) { - vartimeMultiScalarMulMatchesBasepointMul := func(x, y, z scalar.Scalar) bool { - // FIXME opaque scalars - x[31] &= 127 - y[31] &= 127 - z[31] &= 127 - var p, q1, q2, q3, check ProjP3 - - p.VartimeMultiscalarMul([]scalar.Scalar{x, y, z}, []*ProjP3{&B, &B, &B}) - - q1.BasepointMul(&x) - q2.BasepointMul(&y) - q3.BasepointMul(&z) - check.Zero() - check.Add(&q1, &q2).Add(&check, &q3) - - return p.Equal(&check) == 1 - } - - if err := quick.Check(vartimeMultiScalarMulMatchesBasepointMul, quickCheckConfig); err != nil { - t.Error(err) - } -} - -// Benchmarks. - -func BenchmarkBasepointMul(t *testing.B) { - var p ProjP3 - - for i := 0; i < t.N; i++ { - p.BasepointMul(&dalekScalar) - } -} - -func BenchmarkScalarMul(t *testing.B) { - var p ProjP3 - - for i := 0; i < t.N; i++ { - p.ScalarMul(&dalekScalar, &B) - } -} - -func BenchmarkVartimeDoubleBaseMul(t *testing.B) { - var p ProjP3 - - for i := 0; i < t.N; i++ { - p.VartimeDoubleBaseMul(&dalekScalar, &B, &dalekScalar) - } -} - -func BenchmarkMultiscalarMulSize8(t *testing.B) { - var p ProjP3 - x := dalekScalar - - for i := 0; i < t.N; i++ { - p.MultiscalarMul([]scalar.Scalar{x, x, x, x, x, x, x, x}, []*ProjP3{&B, &B, &B, &B, &B, &B, &B, &B}) - } -} - -// TODO: add BenchmarkVartimeMultiscalarMulSize8 (need to have -// different scalars & points to measure cache effects). diff --git a/internal/edwards25519/table_constants.go b/internal/edwards25519/table_constants.go deleted file mode 100644 index ee9b61e..0000000 --- a/internal/edwards25519/table_constants.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2019 Henry de Valence. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package edwards25519 - -import ( - "github.com/gtank/ristretto255/internal/radix51" -) - -var ( - basepointTable = [32]affineLookupTable{ - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x493c6f58c3b85, 0xdf7181c325f7, 0xf50b0b3e4cb7, 0x5329385a44c32, 0x7cf9d3a33d4b}, YminusX: radix51.FieldElement{0x3905d740913e, 0xba2817d673a2, 0x23e2827f4e67c, 0x133d2e0c21a34, 0x44fd2f9298f81}, T2d: radix51.FieldElement{0x11205877aaa68, 0x479955893d579, 0x50d66309b67a0, 0x2d42d0dbee5ee, 0x6f117b689f0c6}}, AffineCached{YplusX: radix51.FieldElement{0x4e7fc933c71d7, 0x2cf41feb6b244, 0x7581c0a7d1a76, 0x7172d534d32f0, 0x590c063fa87d2}, YminusX: radix51.FieldElement{0x1a56042b4d5a8, 0x189cc159ed153, 0x5b8deaa3cae04, 0x2aaf04f11b5d8, 0x6bb595a669c92}, T2d: radix51.FieldElement{0x2a8b3a59b7a5f, 0x3abb359ef087f, 0x4f5a8c4db05af, 0x5b9a807d04205, 0x701af5b13ea50}}, AffineCached{YplusX: radix51.FieldElement{0x5b0a84cee9730, 0x61d10c97155e4, 0x4059cc8096a10, 0x47a608da8014f, 0x7a164e1b9a80f}, YminusX: radix51.FieldElement{0x11fe8a4fcd265, 0x7bcb8374faacc, 0x52f5af4ef4d4f, 0x5314098f98d10, 0x2ab91587555bd}, T2d: radix51.FieldElement{0x6933f0dd0d889, 0x44386bb4c4295, 0x3cb6d3162508c, 0x26368b872a2c6, 0x5a2826af12b9b}}, AffineCached{YplusX: radix51.FieldElement{0x351b98efc099f, 0x68fbfa4a7050e, 0x42a49959d971b, 0x393e51a469efd, 0x680e910321e58}, YminusX: radix51.FieldElement{0x6050a056818bf, 0x62acc1f5532bf, 0x28141ccc9fa25, 0x24d61f471e683, 0x27933f4c7445a}, T2d: radix51.FieldElement{0x3fbe9c476ff09, 0xaf6b982e4b42, 0xad1251ba78e5, 0x715aeedee7c88, 0x7f9d0cbf63553}}, AffineCached{YplusX: radix51.FieldElement{0x2bc4408a5bb33, 0x78ebdda05442, 0x2ffb112354123, 0x375ee8df5862d, 0x2945ccf146e20}, YminusX: radix51.FieldElement{0x182c3a447d6ba, 0x22964e536eff2, 0x192821f540053, 0x2f9f19e788e5c, 0x154a7e73eb1b5}, T2d: radix51.FieldElement{0x3dbf1812a8285, 0xfa17ba3f9797, 0x6f69cb49c3820, 0x34d5a0db3858d, 0x43aabe696b3bb}}, AffineCached{YplusX: radix51.FieldElement{0x4eeeb77157131, 0x1201915f10741, 0x1669cda6c9c56, 0x45ec032db346d, 0x51e57bb6a2cc3}, YminusX: radix51.FieldElement{0x6b67b7d8ca4, 0x84fa44e72933, 0x1154ee55d6f8a, 0x4425d842e7390, 0x38b64c41ae417}, T2d: radix51.FieldElement{0x4326702ea4b71, 0x6834376030b5, 0xef0512f9c380, 0xf1a9f2512584, 0x10b8e91a9f0d6}}, AffineCached{YplusX: radix51.FieldElement{0x25cd0944ea3bf, 0x75673b81a4d63, 0x150b925d1c0d4, 0x13f38d9294114, 0x461bea69283c9}, YminusX: radix51.FieldElement{0x72c9aaa3221b1, 0x267774474f74d, 0x64b0e9b28085, 0x3f04ef53b27c9, 0x1d6edd5d2e531}, T2d: radix51.FieldElement{0x36dc801b8b3a2, 0xe0a7d4935e30, 0x1deb7cecc0d7d, 0x53a94e20dd2c, 0x7a9fbb1c6a0f9}}, AffineCached{YplusX: radix51.FieldElement{0x7596604dd3e8f, 0x6fc510e058b36, 0x3670c8db2cc0d, 0x297d899ce332f, 0x915e76061bce}, YminusX: radix51.FieldElement{0x75dedf39234d9, 0x1c36ab1f3c54, 0xf08fee58f5da, 0xe19613a0d637, 0x3a9024a1320e0}, T2d: radix51.FieldElement{0x1f5d9c9a2911a, 0x7117994fafcf8, 0x2d8a8cae28dc5, 0x74ab1b2090c87, 0x26907c5c2ecc4}}}}, - - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x4dd0e632f9c1d, 0x2ced12622a5d9, 0x18de9614742da, 0x79ca96fdbb5d4, 0x6dd37d49a00ee}, YminusX: radix51.FieldElement{0x3635449aa515e, 0x3e178d0475dab, 0x50b4712a19712, 0x2dcc2860ff4ad, 0x30d76d6f03d31}, T2d: radix51.FieldElement{0x444172106e4c7, 0x1251afed2d88, 0x534fc9bed4f5a, 0x5d85a39cf5234, 0x10c697112e864}}, AffineCached{YplusX: radix51.FieldElement{0x62aa08358c805, 0x46f440848e194, 0x447b771a8f52b, 0x377ba3269d31d, 0x3bf9baf55080}, YminusX: radix51.FieldElement{0x3c4277dbe5fde, 0x5a335afd44c92, 0xc1164099753e, 0x70487006fe423, 0x25e61cabed66f}, T2d: radix51.FieldElement{0x3e128cc586604, 0x5968b2e8fc7e2, 0x49a3d5bd61cf, 0x116505b1ef6e6, 0x566d78634586e}}, AffineCached{YplusX: radix51.FieldElement{0x54285c65a2fd0, 0x55e62ccf87420, 0x46bb961b19044, 0x1153405712039, 0x14fba5f34793b}, YminusX: radix51.FieldElement{0x7a49f9cc10834, 0x2b513788a22c6, 0x5ff4b6ef2395b, 0x2ec8e5af607bf, 0x33975bca5ecc3}, T2d: radix51.FieldElement{0x746166985f7d4, 0x9939000ae79a, 0x5844c7964f97a, 0x13617e1f95b3d, 0x14829cea83fc5}}, AffineCached{YplusX: radix51.FieldElement{0x70b2f4e71ecb8, 0x728148efc643c, 0x753e03995b76, 0x5bf5fb2ab6767, 0x5fc3bc4535d7}, YminusX: radix51.FieldElement{0x37b8497dd95c2, 0x61549d6b4ffe8, 0x217a22db1d138, 0xb9cf062eb09e, 0x2fd9c71e5f758}, T2d: radix51.FieldElement{0xb3ae52afdedd, 0x19da76619e497, 0x6fa0654d2558e, 0x78219d25e41d4, 0x373767475c651}}, AffineCached{YplusX: radix51.FieldElement{0x95cb14246590, 0x2d82aa6ac68, 0x442f183bc4851, 0x6464f1c0a0644, 0x6bf5905730907}, YminusX: radix51.FieldElement{0x299fd40d1add9, 0x5f2de9a04e5f7, 0x7c0eebacc1c59, 0x4cca1b1f8290a, 0x1fbea56c3b18f}, T2d: radix51.FieldElement{0x778f1e1415b8a, 0x6f75874efc1f4, 0x28a694019027f, 0x52b37a96bdc4d, 0x2521cf67a635}}, AffineCached{YplusX: radix51.FieldElement{0x46720772f5ee4, 0x632c0f359d622, 0x2b2092ba3e252, 0x662257c112680, 0x1753d9f7cd6}, YminusX: radix51.FieldElement{0x7ee0b0a9d5294, 0x381fbeb4cca27, 0x7841f3a3e639d, 0x676ea30c3445f, 0x3fa00a7e71382}, T2d: radix51.FieldElement{0x1232d963ddb34, 0x35692e70b078d, 0x247ca14777a1f, 0x6db556be8fcd0, 0x12b5fe2fa048e}}, AffineCached{YplusX: radix51.FieldElement{0x37c26ad6f1e92, 0x46a0971227be5, 0x4722f0d2d9b4c, 0x3dc46204ee03a, 0x6f7e93c20796c}, YminusX: radix51.FieldElement{0xfbc496fce34d, 0x575be6b7dae3e, 0x4a31585cee609, 0x37e9023930ff, 0x749b76f96fb12}, T2d: radix51.FieldElement{0x2f604aea6ae05, 0x637dc939323eb, 0x3fdad9b048d47, 0xa8b0d4045af7, 0xfcec10f01e02}}, AffineCached{YplusX: radix51.FieldElement{0x2d29dc4244e45, 0x6927b1bc147be, 0x308534ac0839, 0x4853664033f41, 0x413779166feab}, YminusX: radix51.FieldElement{0x558a649fe1e44, 0x44635aeefcc89, 0x1ff434887f2ba, 0xf981220e2d44, 0x4901aa7183c51}, T2d: radix51.FieldElement{0x1b7548c1af8f0, 0x7848c53368116, 0x1b64e7383de9, 0x109fbb0587c8f, 0x41bb887b726d1}}}}, - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x34c597c6691ae, 0x7a150b6990fc4, 0x52beb9d922274, 0x70eed7164861a, 0xa871e070c6a9}, YminusX: radix51.FieldElement{0x7d44744346be, 0x282b6a564a81d, 0x4ed80f875236b, 0x6fbbe1d450c50, 0x4eb728c12fcdb}, T2d: radix51.FieldElement{0x1b5994bbc8989, 0x74b7ba84c0660, 0x75678f1cdaeb8, 0x23206b0d6f10c, 0x3ee7300f2685d}}, AffineCached{YplusX: radix51.FieldElement{0x27947841e7518, 0x32c7388dae87f, 0x414add3971be9, 0x1850832f0ef1, 0x7d47c6a2cfb89}, YminusX: radix51.FieldElement{0x255e49e7dd6b7, 0x38c2163d59eba, 0x3861f2a005845, 0x2e11e4ccbaec9, 0x1381576297912}, T2d: radix51.FieldElement{0x2d0148ef0d6e0, 0x3522a8de787fb, 0x2ee055e74f9d2, 0x64038f6310813, 0x148cf58d34c9e}}, AffineCached{YplusX: radix51.FieldElement{0x72f7d9ae4756d, 0x7711e690ffc4a, 0x582a2355b0d16, 0xdccfe885b6b4, 0x278febad4eaea}, YminusX: radix51.FieldElement{0x492f67934f027, 0x7ded0815528d4, 0x58461511a6612, 0x5ea2e50de1544, 0x3ff2fa1ebd5db}, T2d: radix51.FieldElement{0x2681f8c933966, 0x3840521931635, 0x674f14a308652, 0x3bd9c88a94890, 0x4104dd02fe9c6}}, AffineCached{YplusX: radix51.FieldElement{0x14e06db096ab8, 0x1219c89e6b024, 0x278abd486a2db, 0x240b292609520, 0x165b5a48efca}, YminusX: radix51.FieldElement{0x2bf5e1124422a, 0x673146756ae56, 0x14ad99a87e830, 0x1eaca65b080fd, 0x2c863b00afaf5}, T2d: radix51.FieldElement{0xa474a0846a76, 0x99a5ef981e32, 0x2a8ae3c4bbfe6, 0x45c34af14832c, 0x591b67d9bffec}}, AffineCached{YplusX: radix51.FieldElement{0x1b3719f18b55d, 0x754318c83d337, 0x27c17b7919797, 0x145b084089b61, 0x489b4f8670301}, YminusX: radix51.FieldElement{0x70d1c80b49bfa, 0x3d57e7d914625, 0x3c0722165e545, 0x5e5b93819e04f, 0x3de02ec7ca8f7}, T2d: radix51.FieldElement{0x2102d3aeb92ef, 0x68c22d50c3a46, 0x42ea89385894e, 0x75f9ebf55f38c, 0x49f5fbba496cb}}, AffineCached{YplusX: radix51.FieldElement{0x5628c1e9c572e, 0x598b108e822ab, 0x55d8fae29361a, 0xadc8d1a97b28, 0x6a1a6c288675}, YminusX: radix51.FieldElement{0x49a108a5bcfd4, 0x6178c8e7d6612, 0x1f03473710375, 0x73a49614a6098, 0x5604a86dcbfa6}, T2d: radix51.FieldElement{0xd1d47c1764b6, 0x1c08316a2e51, 0x2b3db45c95045, 0x1634f818d300c, 0x20989e89fe274}}, AffineCached{YplusX: radix51.FieldElement{0x4278b85eaec2e, 0xef59657be2ce, 0x72fd169588770, 0x2e9b205260b30, 0x730b9950f7059}, YminusX: radix51.FieldElement{0x777fd3a2dcc7f, 0x594a9fb124932, 0x1f8e80ca15f0, 0x714d13cec3269, 0x403ed1d0ca67}, T2d: radix51.FieldElement{0x32d35874ec552, 0x1f3048df1b929, 0x300d73b179b23, 0x6e67be5a37d0b, 0x5bd7454308303}}, AffineCached{YplusX: radix51.FieldElement{0x4932115e7792a, 0x457b9bbb930b8, 0x68f5d8b193226, 0x4164e8f1ed456, 0x5bb7db123067f}, YminusX: radix51.FieldElement{0x2d19528b24cc2, 0x4ac66b8302ff3, 0x701c8d9fdad51, 0x6c1b35c5b3727, 0x133a78007380a}, T2d: radix51.FieldElement{0x1f467c6ca62be, 0x2c4232a5dc12c, 0x7551dc013b087, 0x690c11b03bcd, 0x740dca6d58f0e}}}}, - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x28c570478433c, 0x1d8502873a463, 0x7641e7eded49c, 0x1ecedd54cf571, 0x2c03f5256c2b0}, YminusX: radix51.FieldElement{0xee0752cfce4e, 0x660dd8116fbe9, 0x55167130fffeb, 0x1c682b885955c, 0x161d25fa963ea}, T2d: radix51.FieldElement{0x718757b53a47d, 0x619e18b0f2f21, 0x5fbdfe4c1ec04, 0x5d798c81ebb92, 0x699468bdbd96b}}, AffineCached{YplusX: radix51.FieldElement{0x53de66aa91948, 0x45f81a599b1b, 0x3f7a8bd214193, 0x71d4da412331a, 0x293e1c4e6c4a2}, YminusX: radix51.FieldElement{0x72f46f4dafecf, 0x2948ffadef7a3, 0x11ecdfdf3bc04, 0x3c2e98ffeed25, 0x525219a473905}, T2d: radix51.FieldElement{0x6134b925112e1, 0x6bb942bb406ed, 0x70c445c0dde2, 0x411d822c4d7a3, 0x5b605c447f032}}, AffineCached{YplusX: radix51.FieldElement{0x1fec6f0e7f04c, 0x3cebc692c477d, 0x77986a19a95e, 0x6eaaaa1778b0f, 0x2f12fef4cc5ab}, YminusX: radix51.FieldElement{0x5805920c47c89, 0x1924771f9972c, 0x38bbddf9fc040, 0x1f7000092b281, 0x24a76dcea8aeb}, T2d: radix51.FieldElement{0x522b2dfc0c740, 0x7e8193480e148, 0x33fd9a04341b9, 0x3c863678a20bc, 0x5e607b2518a43}}, AffineCached{YplusX: radix51.FieldElement{0x4431ca596cf14, 0x15da7c801405, 0x3c9b6f8f10b5, 0x346922934017, 0x201f33139e457}, YminusX: radix51.FieldElement{0x31d8f6cdf1818, 0x1f86c4b144b16, 0x39875b8d73e9d, 0x2fbf0d9ffa7b3, 0x5067acab6ccdd}, T2d: radix51.FieldElement{0x27f6b08039d51, 0x4802f8000dfaa, 0x9692a062c525, 0x1baea91075817, 0x397cba8862460}}, AffineCached{YplusX: radix51.FieldElement{0x5c3fbc81379e7, 0x41bbc255e2f02, 0x6a3f756998650, 0x1297fd4e07c42, 0x771b4022c1e1c}, YminusX: radix51.FieldElement{0x13093f05959b2, 0x1bd352f2ec618, 0x75789b88ea86, 0x61d1117ea48b9, 0x2339d320766e6}, T2d: radix51.FieldElement{0x5d986513a2fa7, 0x63f3a99e11b0f, 0x28a0ecfd6b26d, 0x53b6835e18d8f, 0x331a189219971}}, AffineCached{YplusX: radix51.FieldElement{0x12f3a9d7572af, 0x10d00e953c4ca, 0x603df116f2f8a, 0x33dc276e0e088, 0x1ac9619ff649a}, YminusX: radix51.FieldElement{0x66f45fb4f80c6, 0x3cc38eeb9fea2, 0x107647270db1f, 0x710f1ea740dc8, 0x31167c6b83bdf}, T2d: radix51.FieldElement{0x33842524b1068, 0x77dd39d30fe45, 0x189432141a0d0, 0x88fe4eb8c225, 0x612436341f08b}}, AffineCached{YplusX: radix51.FieldElement{0x349e31a2d2638, 0x137a7fa6b16c, 0x681ae92777edc, 0x222bfc5f8dc51, 0x1522aa3178d90}, YminusX: radix51.FieldElement{0x541db874e898d, 0x62d80fb841b33, 0x3e6ef027fa97, 0x7a03c9e9633e8, 0x46ebe2309e5ef}, T2d: radix51.FieldElement{0x2f5369614938, 0x356e5ada20587, 0x11bc89f6bf902, 0x36746419c8db, 0x45fe70f505243}}, AffineCached{YplusX: radix51.FieldElement{0x24920c8951491, 0x107ec61944c5e, 0x72752e017c01f, 0x122b7dda2e97a, 0x16619f6db57a2}, YminusX: radix51.FieldElement{0x75a6960c0b8c, 0x6dde1c5e41b49, 0x42e3f516da341, 0x16a03fda8e79e, 0x428d1623a0e39}, T2d: radix51.FieldElement{0x74a4401a308fd, 0x6ed4b9558109, 0x746f1f6a08867, 0x4636f5c6f2321, 0x1d81592d60bd3}}}}, - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x5b69f7b85c5e8, 0x17a2d175650ec, 0x4cc3e6dbfc19e, 0x73e1d3873be0e, 0x3a5f6d51b0af8}, YminusX: radix51.FieldElement{0x68756a60dac5f, 0x55d757b8aec26, 0x3383df45f80bd, 0x6783f8c9f96a6, 0x20234a7789ecd}, T2d: radix51.FieldElement{0x20db67178b252, 0x73aa3da2c0eda, 0x79045c01c70d3, 0x1b37b15251059, 0x7cd682353cffe}}, AffineCached{YplusX: radix51.FieldElement{0x5cd6068acf4f3, 0x3079afc7a74cc, 0x58097650b64b4, 0x47fabac9c4e99, 0x3ef0253b2b2cd}, YminusX: radix51.FieldElement{0x1a45bd887fab6, 0x65748076dc17c, 0x5b98000aa11a8, 0x4a1ecc9080974, 0x2838c8863bdc0}, T2d: radix51.FieldElement{0x3b0cf4a465030, 0x22b8aef57a2d, 0x2ad0677e925ad, 0x4094167d7457a, 0x21dcb8a606a82}}, AffineCached{YplusX: radix51.FieldElement{0x500fabe7731ba, 0x7cc53c3113351, 0x7cf65fe080d81, 0x3c5d966011ba1, 0x5d840dbf6c6f6}, YminusX: radix51.FieldElement{0x4468c9d9fc8, 0x5da8554796b8c, 0x3b8be70950025, 0x6d5892da6a609, 0xbc3d08194a31}, T2d: radix51.FieldElement{0x6380d309fe18b, 0x4d73c2cb8ee0d, 0x6b882adbac0b6, 0x36eabdddd4cbe, 0x3a4276232ac19}}, AffineCached{YplusX: radix51.FieldElement{0xc172db447ecb, 0x3f8c505b7a77f, 0x6a857f97f3f10, 0x4fcc0567fe03a, 0x770c9e824e1a}, YminusX: radix51.FieldElement{0x2432c8a7084fa, 0x47bf73ca8a968, 0x1639176262867, 0x5e8df4f8010ce, 0x1ff177cea16de}, T2d: radix51.FieldElement{0x1d99a45b5b5fd, 0x523674f2499ec, 0xf8fa26182613, 0x58f7398048c98, 0x39f264fd41500}}, AffineCached{YplusX: radix51.FieldElement{0x34aabfe097be1, 0x43bfc03253a33, 0x29bc7fe91b7f3, 0xa761e4844a16, 0x65c621272c35f}, YminusX: radix51.FieldElement{0x53417dbe7e29c, 0x54573827394f5, 0x565eea6f650dd, 0x42050748dc749, 0x1712d73468889}, T2d: radix51.FieldElement{0x389f8ce3193dd, 0x2d424b8177ce5, 0x73fa0d3440cd, 0x139020cd49e97, 0x22f9800ab19ce}}, AffineCached{YplusX: radix51.FieldElement{0x29fdd9a6efdac, 0x7c694a9282840, 0x6f7cdeee44b3a, 0x55a3207b25cc3, 0x4171a4d38598c}, YminusX: radix51.FieldElement{0x2368a3e9ef8cb, 0x454aa08e2ac0b, 0x490923f8fa700, 0x372aa9ea4582f, 0x13f416cd64762}, T2d: radix51.FieldElement{0x758aa99c94c8c, 0x5f6001700ff44, 0x7694e488c01bd, 0xd5fde948eed6, 0x508214fa574bd}}, AffineCached{YplusX: radix51.FieldElement{0x215bb53d003d6, 0x1179e792ca8c3, 0x1a0e96ac840a2, 0x22393e2bb3ab6, 0x3a7758a4c86cb}, YminusX: radix51.FieldElement{0x269153ed6fe4b, 0x72a23aef89840, 0x52be5299699c, 0x3a5e5ef132316, 0x22f960ec6faba}, T2d: radix51.FieldElement{0x111f693ae5076, 0x3e3bfaa94ca90, 0x445799476b887, 0x24a0912464879, 0x5d9fd15f8de7f}}, AffineCached{YplusX: radix51.FieldElement{0x44d2aeed7521e, 0x50865d2c2a7e4, 0x2705b5238ea40, 0x46c70b25d3b97, 0x3bc187fa47eb9}, YminusX: radix51.FieldElement{0x408d36d63727f, 0x5faf8f6a66062, 0x2bb892da8de6b, 0x769d4f0c7e2e6, 0x332f35914f8fb}, T2d: radix51.FieldElement{0x70115ea86c20c, 0x16d88da24ada8, 0x1980622662adf, 0x501ebbc195a9d, 0x450d81ce906fb}}}}, - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x4d8961cae743f, 0x6bdc38c7dba0e, 0x7d3b4a7e1b463, 0x844bdee2adf3, 0x4cbad279663ab}, YminusX: radix51.FieldElement{0x3b6a1a6205275, 0x2e82791d06dcf, 0x23d72caa93c87, 0x5f0b7ab68aaf4, 0x2de25d4ba6345}, T2d: radix51.FieldElement{0x19024a0d71fcd, 0x15f65115f101a, 0x4e99067149708, 0x119d8d1cba5af, 0x7d7fbcefe2007}}, AffineCached{YplusX: radix51.FieldElement{0x45dc5f3c29094, 0x3455220b579af, 0x70c1631e068a, 0x26bc0630e9b21, 0x4f9cd196dcd8d}, YminusX: radix51.FieldElement{0x71e6a266b2801, 0x9aae73e2df5d, 0x40dd8b219b1a3, 0x546fb4517de0d, 0x5975435e87b75}, T2d: radix51.FieldElement{0x297d86a7b3768, 0x4835a2f4c6332, 0x70305f434160, 0x183dd014e56ae, 0x7ccdd084387a0}}, AffineCached{YplusX: radix51.FieldElement{0x484186760cc93, 0x7435665533361, 0x2f686336b801, 0x5225446f64331, 0x3593ca848190c}, YminusX: radix51.FieldElement{0x6422c6d260417, 0x212904817bb94, 0x5a319deb854f5, 0x7a9d4e060da7d, 0x428bd0ed61d0c}, T2d: radix51.FieldElement{0x3189a5e849aa7, 0x6acbb1f59b242, 0x7f6ef4753630c, 0x1f346292a2da9, 0x27398308da2d6}}, AffineCached{YplusX: radix51.FieldElement{0x10e4c0a702453, 0x4daafa37bd734, 0x49f6bdc3e8961, 0x1feffdcecdae6, 0x572c2945492c3}, YminusX: radix51.FieldElement{0x38d28435ed413, 0x4064f19992858, 0x7680fbef543cd, 0x1aadd83d58d3c, 0x269597aebe8c3}, T2d: radix51.FieldElement{0x7c745d6cd30be, 0x27c7755df78ef, 0x1776833937fa3, 0x5405116441855, 0x7f985498c05bc}}, AffineCached{YplusX: radix51.FieldElement{0x615520fbf6363, 0xb9e9bf74da6a, 0x4fe8308201169, 0x173f76127de43, 0x30f2653cd69b1}, YminusX: radix51.FieldElement{0x1ce889f0be117, 0x36f6a94510709, 0x7f248720016b4, 0x1821ed1e1cf91, 0x76c2ec470a31f}, T2d: radix51.FieldElement{0xc938aac10c85, 0x41b64ed797141, 0x1beb1c1185e6d, 0x1ed5490600f07, 0x2f1273f159647}}, AffineCached{YplusX: radix51.FieldElement{0x8bd755a70bc0, 0x49e3a885ce609, 0x16585881b5ad6, 0x3c27568d34f5e, 0x38ac1997edc5f}, YminusX: radix51.FieldElement{0x1fc7c8ae01e11, 0x2094d5573e8e7, 0x5ca3cbbf549d2, 0x4f920ecc54143, 0x5d9e572ad85b6}, T2d: radix51.FieldElement{0x6b517a751b13b, 0xcfd370b180cc, 0x5377925d1f41a, 0x34e56566008a2, 0x22dfcd9cbfe9e}}, AffineCached{YplusX: radix51.FieldElement{0x459b4103be0a1, 0x59a4b3f2d2add, 0x7d734c8bb8eeb, 0x2393cbe594a09, 0xfe9877824cde}, YminusX: radix51.FieldElement{0x3d2e0c30d0cd9, 0x3f597686671bb, 0xaa587eb63999, 0xe3c7b592c619, 0x6b2916c05448c}, T2d: radix51.FieldElement{0x334d10aba913b, 0x45cdb581cfdb, 0x5e3e0553a8f36, 0x50bb3041effb2, 0x4c303f307ff00}}, AffineCached{YplusX: radix51.FieldElement{0x403580dd94500, 0x48df77d92653f, 0x38a9fe3b349ea, 0xea89850aafe1, 0x416b151ab706a}, YminusX: radix51.FieldElement{0x23bd617b28c85, 0x6e72ee77d5a61, 0x1a972ff174dde, 0x3e2636373c60f, 0xd61b8f78b2ab}, T2d: radix51.FieldElement{0xd7efe9c136b0, 0x1ab1c89640ad5, 0x55f82aef41f97, 0x46957f317ed0d, 0x191a2af74277e}}}}, - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x62b434f460efb, 0x294c6c0fad3fc, 0x68368937b4c0f, 0x5c9f82910875b, 0x237e7dbe00545}, YminusX: radix51.FieldElement{0x6f74bc53c1431, 0x1c40e5dbbd9c2, 0x6c8fb9cae5c97, 0x4845c5ce1b7da, 0x7e2e0e450b5cc}, T2d: radix51.FieldElement{0x575ed6701b430, 0x4d3e17fa20026, 0x791fc888c4253, 0x2f1ba99078ac1, 0x71afa699b1115}}, AffineCached{YplusX: radix51.FieldElement{0x23c1c473b50d6, 0x3e7671de21d48, 0x326fa5547a1e8, 0x50e4dc25fafd9, 0x731fbc78f89}, YminusX: radix51.FieldElement{0x66f9b3953b61d, 0x555f4283cccb9, 0x7dd67fb1960e7, 0x14707a1affed4, 0x21142e9c2b1c}, T2d: radix51.FieldElement{0xc71848f81880, 0x44bd9d8233c86, 0x6e8578efe5830, 0x4045b6d7041b5, 0x4c4d6f3347e15}}, AffineCached{YplusX: radix51.FieldElement{0x4ddfc988f1970, 0x4f6173ea365e1, 0x645daf9ae4588, 0x7d43763db623b, 0x38bf9500a88f9}, YminusX: radix51.FieldElement{0x7eccfc17d1fc9, 0x4ca280782831e, 0x7b8337db1d7d6, 0x5116def3895fb, 0x193fddaaa7e47}, T2d: radix51.FieldElement{0x2c93c37e8876f, 0x3431a28c583fa, 0x49049da8bd879, 0x4b4a8407ac11c, 0x6a6fb99ebf0d4}}, AffineCached{YplusX: radix51.FieldElement{0x122b5b6e423c6, 0x21e50dff1ddd6, 0x73d76324e75c0, 0x588485495418e, 0x136fda9f42c5e}, YminusX: radix51.FieldElement{0x6c1bb560855eb, 0x71f127e13ad48, 0x5c6b304905aec, 0x3756b8e889bc7, 0x75f76914a3189}, T2d: radix51.FieldElement{0x4dfb1a305bdd1, 0x3b3ff05811f29, 0x6ed62283cd92e, 0x65d1543ec52e1, 0x22183510be8d}}, AffineCached{YplusX: radix51.FieldElement{0x2710143307a7f, 0x3d88fb48bf3ab, 0x249eb4ec18f7a, 0x136115dff295f, 0x1387c441fd404}, YminusX: radix51.FieldElement{0x766385ead2d14, 0x194f8b06095e, 0x8478f6823b62, 0x6018689d37308, 0x6a071ce17b806}, T2d: radix51.FieldElement{0x3c3d187978af8, 0x7afe1c88276ba, 0x51df281c8ad68, 0x64906bda4245d, 0x3171b26aaf1ed}}, AffineCached{YplusX: radix51.FieldElement{0x5b7d8b28a47d1, 0x2c2ee149e34c1, 0x776f5629afc53, 0x1f4ea50fc49a9, 0x6c514a6334424}, YminusX: radix51.FieldElement{0x7319097564ca8, 0x1844ebc233525, 0x21d4543fdeee1, 0x1ad27aaff1bd2, 0x221fd4873cf08}, T2d: radix51.FieldElement{0x2204f3a156341, 0x537414065a464, 0x43c0c3bedcf83, 0x5557e706ea620, 0x48daa596fb924}}, AffineCached{YplusX: radix51.FieldElement{0x61d5dc84c9793, 0x47de83040c29e, 0x189deb26507e7, 0x4d4e6fadc479a, 0x58c837fa0e8a7}, YminusX: radix51.FieldElement{0x28e665ca59cc7, 0x165c715940dd9, 0x785f3aa11c95, 0x57b98d7e38469, 0x676dd6fccad84}, T2d: radix51.FieldElement{0x1688596fc9058, 0x66f6ad403619f, 0x4d759a87772ef, 0x7856e6173bea4, 0x1c4f73f2c6a57}}, AffineCached{YplusX: radix51.FieldElement{0x6706efc7c3484, 0x6987839ec366d, 0x731f95cf7f26, 0x3ae758ebce4bc, 0x70459adb7daf6}, YminusX: radix51.FieldElement{0x24fbd305fa0bb, 0x40a98cc75a1cf, 0x78ce1220a7533, 0x6217a10e1c197, 0x795ac80d1bf64}, T2d: radix51.FieldElement{0x1db4991b42bb3, 0x469605b994372, 0x631e3715c9a58, 0x7e9cfefcf728f, 0x5fe162848ce21}}}}, - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x1852d5d7cb208, 0x60d0fbe5ce50f, 0x5a1e246e37b75, 0x51aee05ffd590, 0x2b44c043677da}, YminusX: radix51.FieldElement{0x1214fe194961a, 0xe1ae39a9e9cb, 0x543c8b526f9f7, 0x119498067e91d, 0x4789d446fc917}, T2d: radix51.FieldElement{0x487ab074eb78e, 0x1d33b5e8ce343, 0x13e419feb1b46, 0x2721f565de6a4, 0x60c52eef2bb9a}}, AffineCached{YplusX: radix51.FieldElement{0x3c5c27cae6d11, 0x36a9491956e05, 0x124bac9131da6, 0x3b6f7de202b5d, 0x70d77248d9b66}, YminusX: radix51.FieldElement{0x589bc3bfd8bf1, 0x6f93e6aa3416b, 0x4c0a3d6c1ae48, 0x55587260b586a, 0x10bc9c312ccfc}, T2d: radix51.FieldElement{0x2e84b3ec2a05b, 0x69da2f03c1551, 0x23a174661a67b, 0x209bca289f238, 0x63755bd3a976f}}, AffineCached{YplusX: radix51.FieldElement{0x7101897f1acb7, 0x3d82cb77b07b8, 0x684083d7769f5, 0x52b28472dce07, 0x2763751737c52}, YminusX: radix51.FieldElement{0x7a03e2ad10853, 0x213dcc6ad36ab, 0x1a6e240d5bdd6, 0x7c24ffcf8fedf, 0xd8cc1c48bc16}, T2d: radix51.FieldElement{0x402d36eb419a9, 0x7cef68c14a052, 0xf1255bc2d139, 0x373e7d431186a, 0x70c2dd8a7ad16}}, AffineCached{YplusX: radix51.FieldElement{0x4967db8ed7e13, 0x15aeed02f523a, 0x6149591d094bc, 0x672f204c17006, 0x32b8613816a53}, YminusX: radix51.FieldElement{0x194509f6fec0e, 0x528d8ca31acac, 0x7826d73b8b9fa, 0x24acb99e0f9b3, 0x2e0fac6363948}, T2d: radix51.FieldElement{0x7f7bee448cd64, 0x4e10f10da0f3c, 0x3936cb9ab20e9, 0x7a0fc4fea6cd0, 0x4179215c735a4}}, AffineCached{YplusX: radix51.FieldElement{0x633b9286bcd34, 0x6cab3badb9c95, 0x74e387edfbdfa, 0x14313c58a0fd9, 0x31fa85662241c}, YminusX: radix51.FieldElement{0x94e7d7dced2a, 0x68fa738e118e, 0x41b640a5fee2b, 0x6bb709df019d4, 0x700344a30cd99}, T2d: radix51.FieldElement{0x26c422e3622f4, 0xf3066a05b5f0, 0x4e2448f0480a6, 0x244cde0dbf095, 0x24bb2312a9952}}, AffineCached{YplusX: radix51.FieldElement{0xc2af5f85c6b, 0x609f4cf2883f, 0x6e86eb5a1ca13, 0x68b44a2efccd1, 0xd1d2af9ffeb5}, YminusX: radix51.FieldElement{0xed1732de67c3, 0x308c369291635, 0x33ef348f2d250, 0x4475ea1a1bb, 0xfee3e871e188}, T2d: radix51.FieldElement{0x28aa132621edf, 0x42b244caf353b, 0x66b064cc2e08a, 0x6bb20020cbdd3, 0x16acd79718531}}, AffineCached{YplusX: radix51.FieldElement{0x1c6c57887b6ad, 0x5abf21fd7592b, 0x50bd41253867a, 0x3800b71273151, 0x164ed34b18161}, YminusX: radix51.FieldElement{0x772af2d9b1d3d, 0x6d486448b4e5b, 0x2ce58dd8d18a8, 0x1849f67503c8b, 0x123e0ef6b9302}, T2d: radix51.FieldElement{0x6d94c192fe69a, 0x5475222a2690f, 0x693789d86b8b3, 0x1f5c3bdfb69dc, 0x78da0fc61073f}}, AffineCached{YplusX: radix51.FieldElement{0x780f1680c3a94, 0x2a35d3cfcd453, 0x5e5cdc7ddf8, 0x6ee888078ac24, 0x54aa4b316b38}, YminusX: radix51.FieldElement{0x15d28e52bc66a, 0x30e1e0351cb7e, 0x30a2f74b11f8c, 0x39d120cd7de03, 0x2d25deeb256b1}, T2d: radix51.FieldElement{0x468d19267cb8, 0x38cdca9b5fbf9, 0x1bbb05c2ca1e2, 0x3b015758e9533, 0x134610a6ab7da}}}}, - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x265e777d1f515, 0xf1f54c1e39a5, 0x2f01b95522646, 0x4fdd8db9dde6d, 0x654878cba97cc}, YminusX: radix51.FieldElement{0x38ec78df6b0fe, 0x13caebea36a22, 0x5ebc6e54e5f6a, 0x32804903d0eb8, 0x2102fdba2b20d}, T2d: radix51.FieldElement{0x6e405055ce6a1, 0x5024a35a532d3, 0x1f69054daf29d, 0x15d1d0d7a8bd5, 0xad725db29ecb}}, AffineCached{YplusX: radix51.FieldElement{0x7bc0c9b056f85, 0x51cfebffaffd8, 0x44abbe94df549, 0x7ecbbd7e33121, 0x4f675f5302399}, YminusX: radix51.FieldElement{0x267b1834e2457, 0x6ae19c378bb88, 0x7457b5ed9d512, 0x3280d783d05fb, 0x4aefcffb71a03}, T2d: radix51.FieldElement{0x536360415171e, 0x2313309077865, 0x251444334afbc, 0x2b0c3853756e8, 0xbccbb72a2a86}}, AffineCached{YplusX: radix51.FieldElement{0x55e4c50fe1296, 0x5fdd13efc30d, 0x1c0c6c380e5ee, 0x3e11de3fb62a8, 0x6678fd69108f3}, YminusX: radix51.FieldElement{0x6962feab1a9c8, 0x6aca28fb9a30b, 0x56db7ca1b9f98, 0x39f58497018dd, 0x4024f0ab59d6b}, T2d: radix51.FieldElement{0x6fa31636863c2, 0x10ae5a67e42b0, 0x27abbf01fda31, 0x380a7b9e64fbc, 0x2d42e2108ead4}}, AffineCached{YplusX: radix51.FieldElement{0x17b0d0f537593, 0x16263c0c9842e, 0x4ab827e4539a4, 0x6370ddb43d73a, 0x420bf3a79b423}, YminusX: radix51.FieldElement{0x5131594dfd29b, 0x3a627e98d52fe, 0x1154041855661, 0x19175d09f8384, 0x676b2608b8d2d}, T2d: radix51.FieldElement{0xba651c5b2b47, 0x5862363701027, 0xc4d6c219c6db, 0xf03dff8658de, 0x745d2ffa9c0cf}}, AffineCached{YplusX: radix51.FieldElement{0x6df5721d34e6a, 0x4f32f767a0c06, 0x1d5abeac76e20, 0x41ce9e104e1e4, 0x6e15be54c1dc}, YminusX: radix51.FieldElement{0x25a1e2bc9c8bd, 0x104c8f3b037ea, 0x405576fa96c98, 0x2e86a88e3876f, 0x1ae23ceb960cf}, T2d: radix51.FieldElement{0x25d871932994a, 0x6b9d63b560b6e, 0x2df2814c8d472, 0xfbbee20aa4ed, 0x58ded861278ec}}, AffineCached{YplusX: radix51.FieldElement{0x35ba8b6c2c9a8, 0x1dea58b3185bf, 0x4b455cd23bbbe, 0x5ec19c04883f8, 0x8ba696b531d5}, YminusX: radix51.FieldElement{0x73793f266c55c, 0xb988a9c93b02, 0x9b0ea32325db, 0x37cae71c17c5e, 0x2ff39de85485f}, T2d: radix51.FieldElement{0x53eeec3efc57a, 0x2fa9fe9022efd, 0x699c72c138154, 0x72a751ebd1ff8, 0x120633b4947cf}}, AffineCached{YplusX: radix51.FieldElement{0x531474912100a, 0x5afcdf7c0d057, 0x7a9e71b788ded, 0x5ef708f3b0c88, 0x7433be3cb393}, YminusX: radix51.FieldElement{0x4987891610042, 0x79d9d7f5d0172, 0x3c293013b9ec4, 0xc2b85f39caca, 0x35d30a99b4d59}, T2d: radix51.FieldElement{0x144c05ce997f4, 0x4960b8a347fef, 0x1da11f15d74f7, 0x54fac19c0fead, 0x2d873ede7af6d}}, AffineCached{YplusX: radix51.FieldElement{0x202e14e5df981, 0x2ea02bc3eb54c, 0x38875b2883564, 0x1298c513ae9dd, 0x543618a01600}, YminusX: radix51.FieldElement{0x2316443373409, 0x5de95503b22af, 0x699201beae2df, 0x3db5849ff737a, 0x2e773654707fa}, T2d: radix51.FieldElement{0x2bdf4974c23c1, 0x4b3b9c8d261bd, 0x26ae8b2a9bc28, 0x3068210165c51, 0x4b1443362d079}}}}, - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x454e91c529ccb, 0x24c98c6bf72cf, 0x486594c3d89a, 0x7ae13a3d7fa3c, 0x17038418eaf66}, YminusX: radix51.FieldElement{0x4b7c7b66e1f7a, 0x4bea185efd998, 0x4fabc711055f8, 0x1fb9f7836fe38, 0x582f446752da6}, T2d: radix51.FieldElement{0x17bd320324ce4, 0x51489117898c6, 0x1684d92a0410b, 0x6e4d90f78c5a7, 0xc2a1c4bcda28}}, AffineCached{YplusX: radix51.FieldElement{0x4814869bd6945, 0x7b7c391a45db8, 0x57316ac35b641, 0x641e31de9096a, 0x5a6a9b30a314d}, YminusX: radix51.FieldElement{0x5c7d06f1f0447, 0x7db70f80b3a49, 0x6cb4a3ec89a78, 0x43be8ad81397d, 0x7c558bd1c6f64}, T2d: radix51.FieldElement{0x41524d396463d, 0x1586b449e1a1d, 0x2f17e904aed8a, 0x7e1d2861d3c8e, 0x404a5ca0afba}}, AffineCached{YplusX: radix51.FieldElement{0x49e1b2a416fd1, 0x51c6a0b316c57, 0x575a59ed71bdc, 0x74c021a1fec1e, 0x39527516e7f8e}, YminusX: radix51.FieldElement{0x740070aa743d6, 0x16b64cbdd1183, 0x23f4b7b32eb43, 0x319aba58235b3, 0x46395bfdcadd9}, T2d: radix51.FieldElement{0x7db2d1a5d9a9c, 0x79a200b85422f, 0x355bfaa71dd16, 0xb77ea5f78aa, 0x76579a29e822d}}, AffineCached{YplusX: radix51.FieldElement{0x4b51352b434f2, 0x1327bd01c2667, 0x434d73b60c8a1, 0x3e0daa89443ba, 0x2c514bb2a277}, YminusX: radix51.FieldElement{0x68e7e49c02a17, 0x45795346fe8b6, 0x89306c8f3546, 0x6d89f6b2f88f6, 0x43a384dc9e05b}, T2d: radix51.FieldElement{0x3d5da8bf1b645, 0x7ded6a96a6d09, 0x6c3494fee2f4d, 0x2c989c8b6bd4, 0x1160920961548}}, AffineCached{YplusX: radix51.FieldElement{0x5616369b4dcd, 0x4ecab86ac6f47, 0x3c60085d700b2, 0x213ee10dfcea, 0x2f637d7491e6e}, YminusX: radix51.FieldElement{0x5166929dacfaa, 0x190826b31f689, 0x4f55567694a7d, 0x705f4f7b1e522, 0x351e125bc5698}, T2d: radix51.FieldElement{0x49b461af67bbe, 0x75915712c3a96, 0x69a67ef580c0d, 0x54d38ef70cffc, 0x7f182d06e7ce2}}, AffineCached{YplusX: radix51.FieldElement{0x54b728e217522, 0x69a90971b0128, 0x51a40f2a963a3, 0x10be9ac12a6bf, 0x44acc043241c5}, YminusX: radix51.FieldElement{0x48e64ab0168ec, 0x2a2bdb8a86f4f, 0x7343b6b2d6929, 0x1d804aa8ce9a3, 0x67d4ac8c343e9}, T2d: radix51.FieldElement{0x56bbb4f7a5777, 0x29230627c238f, 0x5ad1a122cd7fb, 0xdea56e50e364, 0x556d1c8312ad7}}, AffineCached{YplusX: radix51.FieldElement{0x6756b11be821, 0x462147e7bb03e, 0x26519743ebfe0, 0x782fc59682ab5, 0x97abe38cc8c7}, YminusX: radix51.FieldElement{0x740e30c8d3982, 0x7c2b47f4682fd, 0x5cd91b8c7dc1c, 0x77fa790f9e583, 0x746c6c6d1d824}, T2d: radix51.FieldElement{0x1c9877ea52da4, 0x2b37b83a86189, 0x733af49310da5, 0x25e81161c04fb, 0x577e14a34bee8}}, AffineCached{YplusX: radix51.FieldElement{0x6cebebd4dd72b, 0x340c1e442329f, 0x32347ffd1a93f, 0x14a89252cbbe0, 0x705304b8fb009}, YminusX: radix51.FieldElement{0x268ac61a73b0a, 0x206f234bebe1c, 0x5b403a7cbebe8, 0x7a160f09f4135, 0x60fa7ee96fd78}, T2d: radix51.FieldElement{0x51d354d296ec6, 0x7cbf5a63b16c7, 0x2f50bb3cf0c14, 0x1feb385cac65a, 0x21398e0ca1635}}}}, - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0xaaf9b4b75601, 0x26b91b5ae44f3, 0x6de808d7ab1c8, 0x6a769675530b0, 0x1bbfb284e98f7}, YminusX: radix51.FieldElement{0x5058a382b33f3, 0x175a91816913e, 0x4f6cdb96b8ae8, 0x17347c9da81d2, 0x5aa3ed9d95a23}, T2d: radix51.FieldElement{0x777e9c7d96561, 0x28e58f006ccac, 0x541bbbb2cac49, 0x3e63282994cec, 0x4a07e14e5e895}}, AffineCached{YplusX: radix51.FieldElement{0x358cdc477a49b, 0x3cc88fe02e481, 0x721aab7f4e36b, 0x408cc9469953, 0x50af7aed84afa}, YminusX: radix51.FieldElement{0x412cb980df999, 0x5e78dd8ee29dc, 0x171dff68c575d, 0x2015dd2f6ef49, 0x3f0bac391d313}, T2d: radix51.FieldElement{0x7de0115f65be5, 0x4242c21364dc9, 0x6b75b64a66098, 0x33c0102c085, 0x1921a316baebd}}, AffineCached{YplusX: radix51.FieldElement{0x2ad9ad9f3c18b, 0x5ec1638339aeb, 0x5703b6559a83b, 0x3fa9f4d05d612, 0x7b049deca062c}, YminusX: radix51.FieldElement{0x22f7edfb870fc, 0x569eed677b128, 0x30937dcb0a5af, 0x758039c78ea1b, 0x6458df41e273a}, T2d: radix51.FieldElement{0x3e37a35444483, 0x661fdb7d27b99, 0x317761dd621e4, 0x7323c30026189, 0x6093dccbc2950}}, AffineCached{YplusX: radix51.FieldElement{0x6eebe6084034b, 0x6cf01f70a8d7b, 0xb41a54c6670a, 0x6c84b99bb55db, 0x6e3180c98b647}, YminusX: radix51.FieldElement{0x39a8585e0706d, 0x3167ce72663fe, 0x63d14ecdb4297, 0x4be21dcf970b8, 0x57d1ea084827a}, T2d: radix51.FieldElement{0x2b6e7a128b071, 0x5b27511755dcf, 0x8584c2930565, 0x68c7bda6f4159, 0x363e999ddd97b}}, AffineCached{YplusX: radix51.FieldElement{0x48dce24baec6, 0x2b75795ec05e3, 0x3bfa4c5da6dc9, 0x1aac8659e371e, 0x231f979bc6f9b}, YminusX: radix51.FieldElement{0x43c135ee1fc4, 0x2a11c9919f2d5, 0x6334cc25dbacd, 0x295da17b400da, 0x48ee9b78693a0}, T2d: radix51.FieldElement{0x1de4bcc2af3c6, 0x61fc411a3eb86, 0x53ed19ac12ec0, 0x209dbc6b804e0, 0x79bfa9b08792}}, AffineCached{YplusX: radix51.FieldElement{0x1ed80a2d54245, 0x70efec72a5e79, 0x42151d42a822d, 0x1b5ebb6d631e8, 0x1ef4fb1594706}, YminusX: radix51.FieldElement{0x3a51da300df4, 0x467b52b561c72, 0x4d5920210e590, 0xca769e789685, 0x38c77f684817}, T2d: radix51.FieldElement{0x65ee65b167bec, 0x52da19b850a9, 0x408665656429, 0x7ab39596f9a4c, 0x575ee92a4a0bf}}, AffineCached{YplusX: radix51.FieldElement{0x6bc450aa4d801, 0x4f4a6773b0ba8, 0x6241b0b0ebc48, 0x40d9c4f1d9315, 0x200a1e7e382f5}, YminusX: radix51.FieldElement{0x80908a182fcf, 0x532913b7ba98, 0x3dccf78c385c3, 0x68002dd5eaba9, 0x43d4e7112cd3f}, T2d: radix51.FieldElement{0x5b967eaf93ac5, 0x360acca580a31, 0x1c65fd5c6f262, 0x71c7f15c2ecab, 0x50eca52651e4}}, AffineCached{YplusX: radix51.FieldElement{0x4397660e668ea, 0x7c2a75692f2f5, 0x3b29e7e6c66ef, 0x72ba658bcda9a, 0x6151c09fa131a}, YminusX: radix51.FieldElement{0x31ade453f0c9c, 0x3dfee07737868, 0x611ecf7a7d411, 0x2637e6cbd64f6, 0x4b0ee6c21c58f}, T2d: radix51.FieldElement{0x55c0dfdf05d96, 0x405569dcf475e, 0x5c5c277498bb, 0x18588d95dc389, 0x1fef24fa800f0}}}}, - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x2aff530976b86, 0xd85a48c0845a, 0x796eb963642e0, 0x60bee50c4b626, 0x28005fe6c8340}, YminusX: radix51.FieldElement{0x653fb1aa73196, 0x607faec8306fa, 0x4e85ec83e5254, 0x9f56900584fd, 0x544d49292fc86}, T2d: radix51.FieldElement{0x7ba9f34528688, 0x284a20fb42d5d, 0x3652cd9706ffe, 0x6fd7baddde6b3, 0x72e472930f316}}, AffineCached{YplusX: radix51.FieldElement{0x3f635d32a7627, 0xcbecacde00fe, 0x3411141eaa936, 0x21c1e42f3cb94, 0x1fee7f000fe06}, YminusX: radix51.FieldElement{0x5208c9781084f, 0x16468a1dc24d2, 0x7bf780ac540a8, 0x1a67eced75301, 0x5a9d2e8c2733a}, T2d: radix51.FieldElement{0x305da03dbf7e5, 0x1228699b7aeca, 0x12a23b2936bc9, 0x2a1bda56ae6e9, 0xf94051ee040}}, AffineCached{YplusX: radix51.FieldElement{0x793bb07af9753, 0x1e7b6ecd4fafd, 0x2c7b1560fb43, 0x2296734cc5fb7, 0x47b7ffd25dd40}, YminusX: radix51.FieldElement{0x56b23c3d330b2, 0x37608e360d1a6, 0x10ae0f3c8722e, 0x86d9b618b637, 0x7d79c7e8beab}, T2d: radix51.FieldElement{0x3fb9cbc08dd12, 0x75c3dd85370ff, 0x47f06fe2819ac, 0x5db06ab9215ed, 0x1c3520a35ea64}}, AffineCached{YplusX: radix51.FieldElement{0x6f40216bc059, 0x3a2579b0fd9b5, 0x71c26407eec8c, 0x72ada4ab54f0b, 0x38750c3b66d12}, YminusX: radix51.FieldElement{0x253a6bccba34a, 0x427070433701a, 0x20b8e58f9870e, 0x337c861db00cc, 0x1c3d05775d0ee}, T2d: radix51.FieldElement{0x6f1409422e51a, 0x7856bbece2d25, 0x13380a72f031c, 0x43e1080a7f3ba, 0x621e2c7d3304}}, AffineCached{YplusX: radix51.FieldElement{0x61796b0dbf0f3, 0x73c2f9c32d6f5, 0x6aa8ed1537ebe, 0x74e92c91838f4, 0x5d8e589ca1002}, YminusX: radix51.FieldElement{0x60cc8259838d, 0x38d3f35b95f3, 0x56078c243a923, 0x2de3293241bb2, 0x7d6097bd3a}, T2d: radix51.FieldElement{0x71d950842a94b, 0x46b11e5c7d817, 0x5478bbecb4f0d, 0x7c3054b0a1c5d, 0x1583d7783c1cb}}, AffineCached{YplusX: radix51.FieldElement{0x34704cc9d28c7, 0x3dee598b1f200, 0x16e1c98746d9e, 0x4050b7095afdf, 0x4958064e83c55}, YminusX: radix51.FieldElement{0x6a2ef5da27ae1, 0x28aace02e9d9d, 0x2459e965f0e8, 0x7b864d3150933, 0x252a5f2e81ed8}, T2d: radix51.FieldElement{0x94265066e80d, 0xa60f918d61a5, 0x444bf7f30fde, 0x1c40da9ed3c06, 0x79c170bd843b}}, AffineCached{YplusX: radix51.FieldElement{0x6cd50c0d5d056, 0x5b7606ae779ba, 0x70fbd226bdda1, 0x5661e53391ff9, 0x6768c0d7317b8}, YminusX: radix51.FieldElement{0x6ece464fa6fff, 0x3cc40bca460a0, 0x6e3a90afb8d0c, 0x5801abca11228, 0x6dec05e34ac9f}, T2d: radix51.FieldElement{0x625e5f155c1b3, 0x4f32f6f723296, 0x5ac980105efce, 0x17a61165eee36, 0x51445e14ddcd5}}, AffineCached{YplusX: radix51.FieldElement{0x147ab2bbea455, 0x1f240f2253126, 0xc3de9e314e89, 0x21ea5a4fca45f, 0x12e990086e4fd}, YminusX: radix51.FieldElement{0x2b4b3b144951, 0x5688977966aea, 0x18e176e399ffd, 0x2e45c5eb4938b, 0x13186f31e3929}, T2d: radix51.FieldElement{0x496b37fdfbb2e, 0x3c2439d5f3e21, 0x16e60fe7e6a4d, 0x4d7ef889b621d, 0x77b2e3f05d3e9}}}}, - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x639c12ddb0a4, 0x6180490cd7ab3, 0x3f3918297467c, 0x74568be1781ac, 0x7a195152e095}, YminusX: radix51.FieldElement{0x7a9c59c2ec4de, 0x7e9f09e79652d, 0x6a3e422f22d86, 0x2ae8e3b836c8b, 0x63b795fc7ad32}, T2d: radix51.FieldElement{0x68f02389e5fc8, 0x59f1bc877506, 0x504990e410cec, 0x9bd7d0feaee2, 0x3e8fe83d032f0}}, AffineCached{YplusX: radix51.FieldElement{0x4c8de8efd13c, 0x1c67c06e6210e, 0x183378f7f146a, 0x64352ceaed289, 0x22d60899a6258}, YminusX: radix51.FieldElement{0x315b90570a294, 0x60ce108a925f1, 0x6eff61253c909, 0x3ef0e2d70b0, 0x75ba3b797fac4}, T2d: radix51.FieldElement{0x1dbc070cdd196, 0x16d8fb1534c47, 0x500498183fa2a, 0x72f59c423de75, 0x904d07b87779}}, AffineCached{YplusX: radix51.FieldElement{0x22d6648f940b9, 0x197a5a1873e86, 0x207e4c41a54bc, 0x5360b3b4bd6d0, 0x6240aacebaf72}, YminusX: radix51.FieldElement{0x61fd4ddba919c, 0x7d8e991b55699, 0x61b31473cc76c, 0x7039631e631d6, 0x43e2143fbc1dd}, T2d: radix51.FieldElement{0x4749c5ba295a0, 0x37946fa4b5f06, 0x724c5ab5a51f1, 0x65633789dd3f3, 0x56bdaf238db40}}, AffineCached{YplusX: radix51.FieldElement{0xd36cc19d3bb2, 0x6ec4470d72262, 0x6853d7018a9ae, 0x3aa3e4dc2c8eb, 0x3aa31507e1e5}, YminusX: radix51.FieldElement{0x2b9e3f53533eb, 0x2add727a806c5, 0x56955c8ce15a3, 0x18c4f070a290e, 0x1d24a86d83741}, T2d: radix51.FieldElement{0x47648ffd4ce1f, 0x60a9591839e9d, 0x424d5f38117ab, 0x42cc46912c10e, 0x43b261dc9aeb4}}, AffineCached{YplusX: radix51.FieldElement{0x13d8b6c951364, 0x4c0017e8f632a, 0x53e559e53f9c4, 0x4b20146886eea, 0x2b4d5e242940}, YminusX: radix51.FieldElement{0x31e1988bb79bb, 0x7b82f46b3bcab, 0xf7a8ce827b41, 0x5e15816177130, 0x326055cf5b276}, T2d: radix51.FieldElement{0x155cb28d18df2, 0xc30d9ca11694, 0x2090e27ab3119, 0x208624e7a49b6, 0x27a6c809ae5d3}}, AffineCached{YplusX: radix51.FieldElement{0x4270ac43d6954, 0x2ed4cd95659a5, 0x75c0db37528f9, 0x2ccbcfd2c9234, 0x221503603d8c2}, YminusX: radix51.FieldElement{0x6ebcd1f0db188, 0x74ceb4b7d1174, 0x7d56168df4f5c, 0xbf79176fd18a, 0x2cb67174ff60a}, T2d: radix51.FieldElement{0x6cdf9390be1d0, 0x8e519c7e2b3d, 0x253c3d2a50881, 0x21b41448e333d, 0x7b1df4b73890f}}, AffineCached{YplusX: radix51.FieldElement{0x6221807f8f58c, 0x3fa92813a8be5, 0x6da98c38d5572, 0x1ed95554468f, 0x68698245d352e}, YminusX: radix51.FieldElement{0x2f2e0b3b2a224, 0xc56aa22c1c92, 0x5fdec39f1b278, 0x4c90af5c7f106, 0x61fcef2658fc5}, T2d: radix51.FieldElement{0x15d852a18187a, 0x270dbb59afb76, 0x7db120bcf92ab, 0xe7a25d714087, 0x46cf4c473daf0}}, AffineCached{YplusX: radix51.FieldElement{0x46ea7f1498140, 0x70725690a8427, 0xa73ae9f079fb, 0x2dd924461c62b, 0x1065aae50d8cc}, YminusX: radix51.FieldElement{0x525ed9ec4e5f9, 0x22d20660684c, 0x7972b70397b68, 0x7a03958d3f965, 0x29387bcd14eb5}, T2d: radix51.FieldElement{0x44525df200d57, 0x2d7f94ce94385, 0x60d00c170ecb7, 0x38b0503f3d8f0, 0x69a198e64f1ce}}}}, - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x14434dcc5caed, 0x2c7909f667c20, 0x61a839d1fb576, 0x4f23800cabb76, 0x25b2697bd267f}, YminusX: radix51.FieldElement{0x2b2e0d91a78bc, 0x3990a12ccf20c, 0x141c2e11f2622, 0xdfcefaa53320, 0x7369e6a92493a}, T2d: radix51.FieldElement{0x73ffb13986864, 0x3282bb8f713ac, 0x49ced78f297ef, 0x6697027661def, 0x1420683db54e4}}, AffineCached{YplusX: radix51.FieldElement{0x6bb6fc1cc5ad0, 0x532c8d591669d, 0x1af794da86c33, 0xe0e9d86d24d3, 0x31e83b4161d08}, YminusX: radix51.FieldElement{0xbd1e249dd197, 0xbcb1820568f, 0x2eab1718830d4, 0x396fd816997e6, 0x60b63bebf508a}, T2d: radix51.FieldElement{0xc7129e062b4f, 0x1e526415b12fd, 0x461a0fd27923d, 0x18badf670a5b7, 0x55cf1eb62d550}}, AffineCached{YplusX: radix51.FieldElement{0x6b5e37df58c52, 0x3bcf33986c60e, 0x44fb8835ceae7, 0x99dec18e71a4, 0x1a56fbaa62ba0}, YminusX: radix51.FieldElement{0x1101065c23d58, 0x5aa1290338b0f, 0x3157e9e2e7421, 0xea712017d489, 0x669a656457089}, T2d: radix51.FieldElement{0x66b505c9dc9ec, 0x774ef86e35287, 0x4d1d944c0955e, 0x52e4c39d72b20, 0x13c4836799c58}}, AffineCached{YplusX: radix51.FieldElement{0x4fb6a5d8bd080, 0x58ae34908589b, 0x3954d977baf13, 0x413ea597441dc, 0x50bdc87dc8e5b}, YminusX: radix51.FieldElement{0x25d465ab3e1b9, 0xf8fe27ec2847, 0x2d6e6dbf04f06, 0x3038cfc1b3276, 0x66f80c93a637b}, T2d: radix51.FieldElement{0x537836edfe111, 0x2be02357b2c0d, 0x6dcee58c8d4f8, 0x2d732581d6192, 0x1dd56444725fd}}, AffineCached{YplusX: radix51.FieldElement{0x7e60008bac89a, 0x23d5c387c1852, 0x79e5df1f533a8, 0x2e6f9f1c5f0cf, 0x3a3a450f63a30}, YminusX: radix51.FieldElement{0x47ff83362127d, 0x8e39af82b1f4, 0x488322ef27dab, 0x1973738a2a1a4, 0xe645912219f7}, T2d: radix51.FieldElement{0x72f31d8394627, 0x7bd294a200f1, 0x665be00e274c6, 0x43de8f1b6368b, 0x318c8d9393a9a}}, AffineCached{YplusX: radix51.FieldElement{0x69e29ab1dd398, 0x30685b3c76bac, 0x565cf37f24859, 0x57b2ac28efef9, 0x509a41c325950}, YminusX: radix51.FieldElement{0x45d032afffe19, 0x12fe49b6cde4e, 0x21663bc327cf1, 0x18a5e4c69f1dd, 0x224c7c679a1d5}, T2d: radix51.FieldElement{0x6edca6f925e9, 0x68c8363e677b8, 0x60cfa25e4fbcf, 0x1c4c17609404e, 0x5bff02328a11}}, AffineCached{YplusX: radix51.FieldElement{0x1a0dd0dc512e4, 0x10894bf5fcd10, 0x52949013f9c37, 0x1f50fba4735c7, 0x576277cdee01a}, YminusX: radix51.FieldElement{0x2137023cae00b, 0x15a3599eb26c6, 0x687221512b3c, 0x253cb3a0824e9, 0x780b8cc3fa2a4}, T2d: radix51.FieldElement{0x38abc234f305f, 0x7a280bbc103de, 0x398a836695dfe, 0x3d0af41528a1a, 0x5ff418726271b}}, AffineCached{YplusX: radix51.FieldElement{0x347e813b69540, 0x76864c21c3cbb, 0x1e049dbcd74a8, 0x5b4d60f93749c, 0x29d4db8ca0a0c}, YminusX: radix51.FieldElement{0x6080c1789db9d, 0x4be7cef1ea731, 0x2f40d769d8080, 0x35f7d4c44a603, 0x106a03dc25a96}, T2d: radix51.FieldElement{0x50aaf333353d0, 0x4b59a613cbb35, 0x223dfc0e19a76, 0x77d1e2bb2c564, 0x4ab38a51052cb}}}}, - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x7d1ef5fddc09c, 0x7beeaebb9dad9, 0x58d30ba0acfb, 0x5cd92eab5ae90, 0x3041c6bb04ed2}, YminusX: radix51.FieldElement{0x42b256768d593, 0x2e88459427b4f, 0x2b3876630701, 0x34878d405eae5, 0x29cdd1adc088a}, T2d: radix51.FieldElement{0x2f2f9d956e148, 0x6b3e6ad65c1fe, 0x5b00972b79e5d, 0x53d8d234c5daf, 0x104bbd6814049}}, AffineCached{YplusX: radix51.FieldElement{0x59a5fd67ff163, 0x3a998ead0352b, 0x83c95fa4af9a, 0x6fadbfc01266f, 0x204f2a20fb072}, YminusX: radix51.FieldElement{0xfd3168f1ed67, 0x1bb0de7784a3e, 0x34bcb78b20477, 0xa4a26e2e2182, 0x5be8cc57092a7}, T2d: radix51.FieldElement{0x43b3d30ebb079, 0x357aca5c61902, 0x5b570c5d62455, 0x30fb29e1e18c7, 0x2570fb17c2791}}, AffineCached{YplusX: radix51.FieldElement{0x6a9550bb8245a, 0x511f20a1a2325, 0x29324d7239bee, 0x3343cc37516c4, 0x241c5f91de018}, YminusX: radix51.FieldElement{0x2367f2cb61575, 0x6c39ac04d87df, 0x6d4958bd7e5bd, 0x566f4638a1532, 0x3dcb65ea53030}, T2d: radix51.FieldElement{0x172940de6caa, 0x6045b2e67451b, 0x56c07463efcb3, 0x728b6bfe6e91, 0x8420edd5fcdf}}, AffineCached{YplusX: radix51.FieldElement{0xc34e04f410ce, 0x344edc0d0a06b, 0x6e45486d84d6d, 0x44e2ecb3863f5, 0x4d654f321db8}, YminusX: radix51.FieldElement{0x720ab8362fa4a, 0x29c4347cdd9bf, 0xe798ad5f8463, 0x4fef18bcb0bfe, 0xd9a53efbc176}, T2d: radix51.FieldElement{0x5c116ddbdb5d5, 0x6d1b4bba5abcf, 0x4d28a48a5537a, 0x56b8e5b040b99, 0x4a7a4f2618991}}, AffineCached{YplusX: radix51.FieldElement{0x3b291af372a4b, 0x60e3028fe4498, 0x2267bca4f6a09, 0x719eec242b243, 0x4a96314223e0e}, YminusX: radix51.FieldElement{0x718025fb15f95, 0x68d6b8371fe94, 0x3804448f7d97c, 0x42466fe784280, 0x11b50c4cddd31}, T2d: radix51.FieldElement{0x274408a4ffd6, 0x7d382aedb34dd, 0x40acfc9ce385d, 0x628bb99a45b1e, 0x4f4bce4dce6bc}}, AffineCached{YplusX: radix51.FieldElement{0x2616ec49d0b6f, 0x1f95d8462e61c, 0x1ad3e9b9159c6, 0x79ba475a04df9, 0x3042cee561595}, YminusX: radix51.FieldElement{0x7ce5ae2242584, 0x2d25eb153d4e3, 0x3a8f3d09ba9c9, 0xf3690d04eb8e, 0x73fcdd14b71c0}, T2d: radix51.FieldElement{0x67079449bac41, 0x5b79c4621484f, 0x61069f2156b8d, 0xeb26573b10af, 0x389e740c9a9ce}}, AffineCached{YplusX: radix51.FieldElement{0x578f6570eac28, 0x644f2339c3937, 0x66e47b7956c2c, 0x34832fe1f55d0, 0x25c425e5d6263}, YminusX: radix51.FieldElement{0x4b3ae34dcb9ce, 0x47c691a15ac9f, 0x318e06e5d400c, 0x3c422d9f83eb1, 0x61545379465a6}, T2d: radix51.FieldElement{0x606a6f1d7de6e, 0x4f1c0c46107e7, 0x229b1dcfbe5d8, 0x3acc60a7b1327, 0x6539a08915484}}, AffineCached{YplusX: radix51.FieldElement{0x4dbd414bb4a19, 0x7930849f1dbb8, 0x329c5a466caf0, 0x6c824544feb9b, 0xf65320ef019b}, YminusX: radix51.FieldElement{0x21f74c3d2f773, 0x24b88d08bd3a, 0x6e678cf054151, 0x43631272e747c, 0x11c5e4aac5cd1}, T2d: radix51.FieldElement{0x6d1b1cafde0c6, 0x462c76a303a90, 0x3ca4e693cff9b, 0x3952cd45786fd, 0x4cabc7bdec330}}}}, - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x7788f3f78d289, 0x5942809b3f811, 0x5973277f8c29c, 0x10f93bc5fe67, 0x7ee498165acb2}, YminusX: radix51.FieldElement{0x69624089c0a2e, 0x75fc8e70473, 0x13e84ab1d2313, 0x2c10bedf6953b, 0x639b93f0321c8}, T2d: radix51.FieldElement{0x508e39111a1c3, 0x290120e912f7a, 0x1cbf464acae43, 0x15373e9576157, 0xedf493c85b60}}, AffineCached{YplusX: radix51.FieldElement{0x7c4d284764113, 0x7fefebf06acec, 0x39afb7a824100, 0x1b48e47e7fd65, 0x4c00c54d1dfa}, YminusX: radix51.FieldElement{0x48158599b5a68, 0x1fd75bc41d5d9, 0x2d9fc1fa95d3c, 0x7da27f20eba11, 0x403b92e3019d4}, T2d: radix51.FieldElement{0x22f818b465cf8, 0x342901dff09b8, 0x31f595dc683cd, 0x37a57745fd682, 0x355bb12ab2617}}, AffineCached{YplusX: radix51.FieldElement{0x1dac75a8c7318, 0x3b679d5423460, 0x6b8fcb7b6400e, 0x6c73783be5f9d, 0x7518eaf8e052a}, YminusX: radix51.FieldElement{0x664cc7493bbf4, 0x33d94761874e3, 0x179e1796f613, 0x1890535e2867d, 0xf9b8132182ec}, T2d: radix51.FieldElement{0x59c41b7f6c32, 0x79e8706531491, 0x6c747643cb582, 0x2e20c0ad494e4, 0x47c3871bbb175}}, AffineCached{YplusX: radix51.FieldElement{0x65d50c85066b0, 0x6167453361f7c, 0x6ba3818bb312, 0x6aff29baa7522, 0x8fea02ce8d48}, YminusX: radix51.FieldElement{0x4539771ec4f48, 0x7b9318badca28, 0x70f19afe016c5, 0x4ee7bb1608d23, 0xb89b8576469}, T2d: radix51.FieldElement{0x5dd7668deead0, 0x4096d0ba47049, 0x6275997219114, 0x29bda8a67e6ae, 0x473829a74f75d}}, AffineCached{YplusX: radix51.FieldElement{0x1533aad3902c9, 0x1dde06b11e47b, 0x784bed1930b77, 0x1c80a92b9c867, 0x6c668b4d44e4d}, YminusX: radix51.FieldElement{0x2da754679c418, 0x3164c31be105a, 0x11fac2b98ef5f, 0x35a1aaf779256, 0x2078684c4833c}, T2d: radix51.FieldElement{0xcf217a78820c, 0x65024e7d2e769, 0x23bb5efdda82a, 0x19fd4b632d3c6, 0x7411a6054f8a4}}, AffineCached{YplusX: radix51.FieldElement{0x2e53d18b175b4, 0x33e7254204af3, 0x3bcd7d5a1c4c5, 0x4c7c22af65d0f, 0x1ec9a872458c3}, YminusX: radix51.FieldElement{0x59d32b99dc86d, 0x6ac075e22a9ac, 0x30b9220113371, 0x27fd9a638966e, 0x7c136574fb813}, T2d: radix51.FieldElement{0x6a4d400a2509b, 0x41791056971c, 0x655d5866e075c, 0x2302bf3e64df8, 0x3add88a5c7cd6}}, AffineCached{YplusX: radix51.FieldElement{0x298d459393046, 0x30bfecb3d90b8, 0x3d9b8ea3df8d6, 0x3900e96511579, 0x61ba1131a406a}, YminusX: radix51.FieldElement{0x15770b635dcf2, 0x59ecd83f79571, 0x2db461c0b7fbd, 0x73a42a981345f, 0x249929fccc879}, T2d: radix51.FieldElement{0xa0f116959029, 0x5974fd7b1347a, 0x1e0cc1c08edad, 0x673bdf8ad1f13, 0x5620310cbbd8e}}, AffineCached{YplusX: radix51.FieldElement{0x6b5f477e285d6, 0x4ed91ec326cc8, 0x6d6537503a3fd, 0x626d3763988d5, 0x7ec846f3658ce}, YminusX: radix51.FieldElement{0x193434934d643, 0xd4a2445eaa51, 0x7d0708ae76fe0, 0x39847b6c3c7e1, 0x37676a2a4d9d9}, T2d: radix51.FieldElement{0x68f3f1da22ec7, 0x6ed8039a2736b, 0x2627ee04c3c75, 0x6ea90a647e7d1, 0x6daaf723399b9}}}}, - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x304bfacad8ea2, 0x502917d108b07, 0x43176ca6dd0f, 0x5d5158f2c1d84, 0x2b5449e58eb3b}, YminusX: radix51.FieldElement{0x27562eb3dbe47, 0x291d7b4170be7, 0x5d1ca67dfa8e1, 0x2a88061f298a2, 0x1304e9e71627d}, T2d: radix51.FieldElement{0x14d26adc9cfe, 0x7f1691ba16f13, 0x5e71828f06eac, 0x349ed07f0fffc, 0x4468de2d7c2dd}}, AffineCached{YplusX: radix51.FieldElement{0x2d8c6f86307ce, 0x6286ba1850973, 0x5e9dcb08444d4, 0x1a96a543362b2, 0x5da6427e63247}, YminusX: radix51.FieldElement{0x3355e9419469e, 0x1847bb8ea8a37, 0x1fe6588cf9b71, 0x6b1c9d2db6b22, 0x6cce7c6ffb44b}, T2d: radix51.FieldElement{0x4c688deac22ca, 0x6f775c3ff0352, 0x565603ee419bb, 0x6544456c61c46, 0x58f29abfe79f2}}, AffineCached{YplusX: radix51.FieldElement{0x264bf710ecdf6, 0x708c58527896b, 0x42ceae6c53394, 0x4381b21e82b6a, 0x6af93724185b4}, YminusX: radix51.FieldElement{0x6cfab8de73e68, 0x3e6efced4bd21, 0x56609500dbe, 0x71b7824ad85df, 0x577629c4a7f41}, T2d: radix51.FieldElement{0x24509c6a888, 0x2696ab12e6644, 0xcca27f4b80d8, 0xc7c1f11b119e, 0x701f25bb0caec}}, AffineCached{YplusX: radix51.FieldElement{0xf6d97cbec113, 0x4ce97fb7c93a3, 0x139835a11281b, 0x728907ada9156, 0x720a5bc050955}, YminusX: radix51.FieldElement{0xb0f8e4616ced, 0x1d3c4b50fb875, 0x2f29673dc0198, 0x5f4b0f1830ffa, 0x2e0c92bfbdc40}, T2d: radix51.FieldElement{0x709439b805a35, 0x6ec48557f8187, 0x8a4d1ba13a2c, 0x76348a0bf9ae, 0xe9b9cbb144ef}}, AffineCached{YplusX: radix51.FieldElement{0x69bd55db1beee, 0x6e14e47f731bd, 0x1a35e47270eac, 0x66f225478df8e, 0x366d44191cfd3}, YminusX: radix51.FieldElement{0x2d48ffb5720ad, 0x57b7f21a1df77, 0x5550effba0645, 0x5ec6a4098a931, 0x221104eb3f337}, T2d: radix51.FieldElement{0x41743f2bc8c14, 0x796b0ad8773c7, 0x29fee5cbb689b, 0x122665c178734, 0x4167a4e6bc593}}, AffineCached{YplusX: radix51.FieldElement{0x62665f8ce8fee, 0x29d101ac59857, 0x4d93bbba59ffc, 0x17b7897373f17, 0x34b33370cb7ed}, YminusX: radix51.FieldElement{0x39d2876f62700, 0x1cecd1d6c87, 0x7f01a11747675, 0x2350da5a18190, 0x7938bb7e22552}, T2d: radix51.FieldElement{0x591ee8681d6cc, 0x39db0b4ea79b8, 0x202220f380842, 0x2f276ba42e0ac, 0x1176fc6e2dfe6}}, AffineCached{YplusX: radix51.FieldElement{0xe28949770eb8, 0x5559e88147b72, 0x35e1e6e63ef30, 0x35b109aa7ff6f, 0x1f6a3e54f2690}, YminusX: radix51.FieldElement{0x76cd05b9c619b, 0x69654b0901695, 0x7a53710b77f27, 0x79a1ea7d28175, 0x8fc3a4c677d5}, T2d: radix51.FieldElement{0x4c199d30734ea, 0x6c622cb9acc14, 0x5660a55030216, 0x68f1199f11fb, 0x4f2fad0116b90}}, AffineCached{YplusX: radix51.FieldElement{0x4d91db73bb638, 0x55f82538112c5, 0x6d85a279815de, 0x740b7b0cd9cf9, 0x3451995f2944e}, YminusX: radix51.FieldElement{0x6b24194ae4e54, 0x2230afded8897, 0x23412617d5071, 0x3d5d30f35969b, 0x445484a4972ef}, T2d: radix51.FieldElement{0x2fcd09fea7d7c, 0x296126b9ed22a, 0x4a171012a05b2, 0x1db92c74d5523, 0x10b89ca604289}}}}, - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x141be5a45f06e, 0x5adb38becaea7, 0x3fd46db41f2bb, 0x6d488bbb5ce39, 0x17d2d1d9ef0d4}, YminusX: radix51.FieldElement{0x147499718289c, 0xa48a67e4c7ab, 0x30fbc544bafe3, 0xc701315fe58a, 0x20b878d577b75}, T2d: radix51.FieldElement{0x2af18073f3e6a, 0x33aea420d24fe, 0x298008bf4ff94, 0x3539171db961e, 0x72214f63cc65c}}, AffineCached{YplusX: radix51.FieldElement{0x5b7b9f43b29c9, 0x149ea31eea3b3, 0x4be7713581609, 0x2d87960395e98, 0x1f24ac855a154}, YminusX: radix51.FieldElement{0x37f405307a693, 0x2e5e66cf2b69c, 0x5d84266ae9c53, 0x5e4eb7de853b9, 0x5fdf48c58171c}, T2d: radix51.FieldElement{0x608328e9505aa, 0x22182841dc49a, 0x3ec96891d2307, 0x2f363fff22e03, 0xba739e2ae39}}, AffineCached{YplusX: radix51.FieldElement{0x426f5ea88bb26, 0x33092e77f75c8, 0x1a53940d819e7, 0x1132e4f818613, 0x72297de7d518d}, YminusX: radix51.FieldElement{0x698de5c8790d6, 0x268b8545beb25, 0x6d2648b96fedf, 0x47988ad1db07c, 0x3283a3e67ad7}, T2d: radix51.FieldElement{0x41dc7be0cb939, 0x1b16c66100904, 0xa24c20cbc66d, 0x4a2e9efe48681, 0x5e1296846271}}, AffineCached{YplusX: radix51.FieldElement{0x7bbc8242c4550, 0x59a06103b35b7, 0x7237e4af32033, 0x726421ab3537a, 0x78cf25d38258c}, YminusX: radix51.FieldElement{0x2eeb32d9c495a, 0x79e25772f9750, 0x6d747833bbf23, 0x6cdd816d5d749, 0x39c00c9c13698}, T2d: radix51.FieldElement{0x66b8e31489d68, 0x573857e10e2b5, 0x13be816aa1472, 0x41964d3ad4bf8, 0x6b52076b3ff}}, AffineCached{YplusX: radix51.FieldElement{0x37e16b9ce082d, 0x1882f57853eb9, 0x7d29eacd01fc5, 0x2e76a59b5e715, 0x7de2e9561a9f7}, YminusX: radix51.FieldElement{0xcfe19d95781c, 0x312cc621c453c, 0x145ace6da077c, 0x912bef9ce9b8, 0x4d57e3443bc76}, T2d: radix51.FieldElement{0xd4f4b6a55ecb, 0x7ebb0bb733bce, 0x7ba6a05200549, 0x4f6ede4e22069, 0x6b2a90af1a602}}, AffineCached{YplusX: radix51.FieldElement{0x3f3245bb2d80a, 0xe5f720f36efd, 0x3b9cccf60c06d, 0x84e323f37926, 0x465812c8276c2}, YminusX: radix51.FieldElement{0x3f4fc9ae61e97, 0x3bc07ebfa2d24, 0x3b744b55cd4a0, 0x72553b25721f3, 0x5fd8f4e9d12d3}, T2d: radix51.FieldElement{0x3beb22a1062d9, 0x6a7063b82c9a8, 0xa5a35dc197ed, 0x3c80c06a53def, 0x5b32c2b1cb16}}, AffineCached{YplusX: radix51.FieldElement{0x4a42c7ad58195, 0x5c8667e799eff, 0x2e5e74c850a1, 0x3f0db614e869a, 0x31771a4856730}, YminusX: radix51.FieldElement{0x5eccd24da8fd, 0x580bbfdf07918, 0x7e73586873c6a, 0x74ceddf77f93e, 0x3b5556a37b471}, T2d: radix51.FieldElement{0xc524e14dd482, 0x283457496c656, 0xad6bcfb6cd45, 0x375d1e8b02414, 0x4fc079d27a733}}, AffineCached{YplusX: radix51.FieldElement{0x48b440c86c50d, 0x139929cca3b86, 0xf8f2e44cdf2f, 0x68432117ba6b2, 0x241170c2bae3c}, YminusX: radix51.FieldElement{0x138b089bf2f7f, 0x4a05bfd34ea39, 0x203914c925ef5, 0x7497fffe04e3c, 0x124567cecaf98}, T2d: radix51.FieldElement{0x1ab860ac473b4, 0x5c0227c86a7ff, 0x71b12bfc24477, 0x6a573a83075, 0x3f8612966c870}}}}, - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0xfcfa36048d13, 0x66e7133bbb383, 0x64b42a8a45676, 0x4ea6e4f9a85cf, 0x26f57eee878a1}, YminusX: radix51.FieldElement{0x20cc9782a0dde, 0x65d4e3070aab3, 0x7bc8e31547736, 0x9ebfb1432d98, 0x504aa77679736}, T2d: radix51.FieldElement{0x32cd55687efb1, 0x4448f5e2f6195, 0x568919d460345, 0x34c2e0ad1a27, 0x4041943d9dba3}}, AffineCached{YplusX: radix51.FieldElement{0x17743a26caadd, 0x48c9156f9c964, 0x7ef278d1e9ad0, 0xce58ea7bd01, 0x12d931429800d}, YminusX: radix51.FieldElement{0xeeba43ebcc96, 0x384dd5395f878, 0x1df331a35d272, 0x207ecfd4af70e, 0x1420a1d976843}, T2d: radix51.FieldElement{0x67799d337594f, 0x1647548f6018, 0x57fce5578f145, 0x9220c142a71, 0x1b4f92314359a}}, AffineCached{YplusX: radix51.FieldElement{0x73030a49866b1, 0x2442be90b2679, 0x77bd3d8947dcf, 0x1fb55c1552028, 0x5ff191d56f9a2}, YminusX: radix51.FieldElement{0x4109d89150951, 0x225bd2d2d47cb, 0x57cc080e73bea, 0x6d71075721fcb, 0x239b572a7f132}, T2d: radix51.FieldElement{0x6d433ac2d9068, 0x72bf930a47033, 0x64facf4a20ead, 0x365f7a2b9402a, 0x20c526a758f3}}, AffineCached{YplusX: radix51.FieldElement{0x1ef59f042cc89, 0x3b1c24976dd26, 0x31d665cb16272, 0x28656e470c557, 0x452cfe0a5602c}, YminusX: radix51.FieldElement{0x34f89ed8dbbc, 0x73b8f948d8ef3, 0x786c1d323caab, 0x43bd4a9266e51, 0x2aacc4615313}, T2d: radix51.FieldElement{0xf7a0647877df, 0x4e1cc0f93f0d4, 0x7ec4726ef1190, 0x3bdd58bf512f8, 0x4cfb7d7b304b8}}, AffineCached{YplusX: radix51.FieldElement{0x699c29789ef12, 0x63beae321bc50, 0x325c340adbb35, 0x562e1a1e42bf6, 0x5b1d4cbc434d3}, YminusX: radix51.FieldElement{0x43d6cb89b75fe, 0x3338d5b900e56, 0x38d327d531a53, 0x1b25c61d51b9f, 0x14b4622b39075}, T2d: radix51.FieldElement{0x32615cc0a9f26, 0x57711b99cb6df, 0x5a69c14e93c38, 0x6e88980a4c599, 0x2f98f71258592}}, AffineCached{YplusX: radix51.FieldElement{0x2ae444f54a701, 0x615397afbc5c2, 0x60d7783f3f8fb, 0x2aa675fc486ba, 0x1d8062e9e7614}, YminusX: radix51.FieldElement{0x4a74cb50f9e56, 0x531d1c2640192, 0xc03d9d6c7fd2, 0x57ccd156610c1, 0x3a6ae249d806a}, T2d: radix51.FieldElement{0x2da85a9907c5a, 0x6b23721ec4caf, 0x4d2d3a4683aa2, 0x7f9c6870efdef, 0x298b8ce8aef25}}, AffineCached{YplusX: radix51.FieldElement{0x272ea0a2165de, 0x68179ef3ed06f, 0x4e2b9c0feac1e, 0x3ee290b1b63bb, 0x6ba6271803a7d}, YminusX: radix51.FieldElement{0x27953eff70cb2, 0x54f22ae0ec552, 0x29f3da92e2724, 0x242ca0c22bd18, 0x34b8a8404d5ce}, T2d: radix51.FieldElement{0x6ecb583693335, 0x3ec76bfdfb84d, 0x2c895cf56a04f, 0x6355149d54d52, 0x71d62bdd465e1}}, AffineCached{YplusX: radix51.FieldElement{0x5b5dab1f75ef5, 0x1e2d60cbeb9a5, 0x527c2175dfe57, 0x59e8a2b8ff51f, 0x1c333621262b2}, YminusX: radix51.FieldElement{0x3cc28d378df80, 0x72141f4968ca6, 0x407696bdb6d0d, 0x5d271b22ffcfb, 0x74d5f317f3172}, T2d: radix51.FieldElement{0x7e55467d9ca81, 0x6a5653186f50d, 0x6b188ece62df1, 0x4c66d36844971, 0x4aebcc4547e9d}}}}, - - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x8d9e7354b610, 0x26b750b6dc168, 0x162881e01acc9, 0x7966df31d01a5, 0x173bd9ddc9a1d}, YminusX: radix51.FieldElement{0x71b276d01c9, 0xb0d8918e025e, 0x75beea79ee2eb, 0x3c92984094db8, 0x5d88fbf95a3db}, T2d: radix51.FieldElement{0xf1efe5872df, 0x5da872318256a, 0x59ceb81635960, 0x18cf37693c764, 0x6e1cd13b19ea}}, AffineCached{YplusX: radix51.FieldElement{0x3af629e5b0353, 0x204f1a088e8e5, 0x10efc9ceea82e, 0x589863c2fa34b, 0x7f3a6a1a8d837}, YminusX: radix51.FieldElement{0xad516f166f23, 0x263f56d57c81a, 0x13422384638ca, 0x1331ff1af0a50, 0x3080603526e16}, T2d: radix51.FieldElement{0x644395d3d800b, 0x2b9203dbedefc, 0x4b18ce656a355, 0x3f3466bc182c, 0x30d0fded2e513}}, AffineCached{YplusX: radix51.FieldElement{0x4971e68b84750, 0x52ccc9779f396, 0x3e904ae8255c8, 0x4ecae46f39339, 0x4615084351c58}, YminusX: radix51.FieldElement{0x14d1af21233b3, 0x1de1989b39c0b, 0x52669dc6f6f9e, 0x43434b28c3fc7, 0xa9214202c099}, T2d: radix51.FieldElement{0x19c0aeb9a02e, 0x1a2c06995d792, 0x664cbb1571c44, 0x6ff0736fa80b2, 0x3bca0d2895ca5}}, AffineCached{YplusX: radix51.FieldElement{0x8eb69ecc01bf, 0x5b4c8912df38d, 0x5ea7f8bc2f20e, 0x120e516caafaf, 0x4ea8b4038df28}, YminusX: radix51.FieldElement{0x31bc3c5d62a4, 0x7d9fe0f4c081e, 0x43ed51467f22c, 0x1e6cc0c1ed109, 0x5631deddae8f1}, T2d: radix51.FieldElement{0x5460af1cad202, 0xb4919dd0655d, 0x7c4697d18c14c, 0x231c890bba2a4, 0x24ce0930542ca}}, AffineCached{YplusX: radix51.FieldElement{0x7a155fdf30b85, 0x1c6c6e5d487f9, 0x24be1134bdc5a, 0x1405970326f32, 0x549928a7324f4}, YminusX: radix51.FieldElement{0x90f5fd06c106, 0x6abb1021e43fd, 0x232bcfad711a0, 0x3a5c13c047f37, 0x41d4e3c28a06d}, T2d: radix51.FieldElement{0x632a763ee1a2e, 0x6fa4bffbd5e4d, 0x5fd35a6ba4792, 0x7b55e1de99de8, 0x491b66dec0dcf}}, AffineCached{YplusX: radix51.FieldElement{0x4a8ed0da64a1, 0x5ecfc45096ebe, 0x5edee93b488b2, 0x5b3c11a51bc8f, 0x4cf6b8b0b7018}, YminusX: radix51.FieldElement{0x5b13dc7ea32a7, 0x18fc2db73131e, 0x7e3651f8f57e3, 0x25656055fa965, 0x8f338d0c85ee}, T2d: radix51.FieldElement{0x3a821991a73bd, 0x3be6418f5870, 0x1ddc18eac9ef0, 0x54ce09e998dc2, 0x530d4a82eb078}}, AffineCached{YplusX: radix51.FieldElement{0x173456c9abf9e, 0x7892015100dad, 0x33ee14095fecb, 0x6ad95d67a0964, 0xdb3e7e00cbfb}, YminusX: radix51.FieldElement{0x43630e1f94825, 0x4d1956a6b4009, 0x213fe2df8b5e0, 0x5ce3a41191e6, 0x65ea753f10177}, T2d: radix51.FieldElement{0x6fc3ee2096363, 0x7ec36b96d67ac, 0x510ec6a0758b1, 0xed87df022109, 0x2a4ec1921e1a}}, AffineCached{YplusX: radix51.FieldElement{0x6162f1cf795f, 0x324ddcafe5eb9, 0x18d5e0463218, 0x7e78b9092428e, 0x36d12b5dec067}, YminusX: radix51.FieldElement{0x6259a3b24b8a2, 0x188b5f4170b9c, 0x681c0dee15deb, 0x4dfe665f37445, 0x3d143c5112780}, T2d: radix51.FieldElement{0x5279179154557, 0x39f8f0741424d, 0x45e6eb357923d, 0x42c9b5edb746f, 0x2ef517885ba82}}}}, - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x6bffb305b2f51, 0x5b112b2d712dd, 0x35774974fe4e2, 0x4af87a96e3a3, 0x57968290bb3a0}, YminusX: radix51.FieldElement{0x7974e8c58aedc, 0x7757e083488c6, 0x601c62ae7bc8b, 0x45370c2ecab74, 0x2f1b78fab143a}, T2d: radix51.FieldElement{0x2b8430a20e101, 0x1a49e1d88fee3, 0x38bbb47ce4d96, 0x1f0e7ba84d437, 0x7dc43e35dc2aa}}, AffineCached{YplusX: radix51.FieldElement{0x2a5c273e9718, 0x32bc9dfb28b4f, 0x48df4f8d5db1a, 0x54c87976c028f, 0x44fb81d82d50}, YminusX: radix51.FieldElement{0x66665887dd9c3, 0x629760a6ab0b2, 0x481e6c7243e6c, 0x97e37046fc77, 0x7ef72016758cc}, T2d: radix51.FieldElement{0x718c5a907e3d9, 0x3b9c98c6b383b, 0x6ed255eccdc, 0x6976538229a59, 0x7f79823f9c30d}}, AffineCached{YplusX: radix51.FieldElement{0x41ff068f587ba, 0x1c00a191bcd53, 0x7b56f9c209e25, 0x3781e5fccaabe, 0x64a9b0431c06d}, YminusX: radix51.FieldElement{0x4d239a3b513e8, 0x29723f51b1066, 0x642f4cf04d9c3, 0x4da095aa09b7a, 0xa4e0373d784d}, T2d: radix51.FieldElement{0x3d6a15b7d2919, 0x41aa75046a5d6, 0x691751ec2d3da, 0x23638ab6721c4, 0x71a7d0ace183}}, AffineCached{YplusX: radix51.FieldElement{0x4355220e14431, 0xe1362a283981, 0x2757cd8359654, 0x2e9cd7ab10d90, 0x7c69bcf761775}, YminusX: radix51.FieldElement{0x72daac887ba0b, 0xb7f4ac5dda60, 0x3bdda2c0498a4, 0x74e67aa180160, 0x2c3bcc7146ea7}, T2d: radix51.FieldElement{0xd7eb04e8295f, 0x4a5ea1e6fa0fe, 0x45e635c436c60, 0x28ef4a8d4d18b, 0x6f5a9a7322aca}}, AffineCached{YplusX: radix51.FieldElement{0x1d4eba3d944be, 0x100f15f3dce5, 0x61a700e367825, 0x5922292ab3d23, 0x2ab9680ee8d3}, YminusX: radix51.FieldElement{0x1000c2f41c6c5, 0x219fdf737174, 0x314727f127de7, 0x7e5277d23b81e, 0x494e21a2e147a}, T2d: radix51.FieldElement{0x48a85dde50d9a, 0x1c1f734493df4, 0x47bdb64866889, 0x59a7d048f8eec, 0x6b5d76cbea46b}}, AffineCached{YplusX: radix51.FieldElement{0x141171e782522, 0x6806d26da7c1f, 0x3f31d1bc79ab9, 0x9f20459f5168, 0x16fb869c03dd3}, YminusX: radix51.FieldElement{0x7556cec0cd994, 0x5eb9a03b7510a, 0x50ad1dd91cb71, 0x1aa5780b48a47, 0xae333f685277}, T2d: radix51.FieldElement{0x6199733b60962, 0x69b157c266511, 0x64740f893f1ca, 0x3aa408fbf684, 0x3f81e38b8f70d}}, AffineCached{YplusX: radix51.FieldElement{0x37f355f17c824, 0x7ae85334815b, 0x7e3abddd2e48f, 0x61eeabe1f45e5, 0xad3e2d34cded}, YminusX: radix51.FieldElement{0x10fcc7ed9affe, 0x4248cb0e96ff2, 0x4311c115172e2, 0x4c9d41cbf6925, 0x50510fc104f50}, T2d: radix51.FieldElement{0x40fc5336e249d, 0x3386639fb2de1, 0x7bbf871d17b78, 0x75f796b7e8004, 0x127c158bf0fa1}}, AffineCached{YplusX: radix51.FieldElement{0x28fc4ae51b974, 0x26e89bfd2dbd4, 0x4e122a07665cf, 0x7cab1203405c3, 0x4ed82479d167d}, YminusX: radix51.FieldElement{0x17c422e9879a2, 0x28a5946c8fec3, 0x53ab32e912b77, 0x7b44da09fe0a5, 0x354ef87d07ef4}, T2d: radix51.FieldElement{0x3b52260c5d975, 0x79d6836171fdc, 0x7d994f140d4bb, 0x1b6c404561854, 0x302d92d205392}}}}, - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x46fb6e4e0f177, 0x53497ad5265b7, 0x1ebdba01386fc, 0x302f0cb36a3c, 0xedc5f5eb426d}, YminusX: radix51.FieldElement{0x3c1a2bca4283d, 0x23430c7bb2f02, 0x1a3ea1bb58bc2, 0x7265763de5c61, 0x10e5d3b76f1ca}, T2d: radix51.FieldElement{0x3bfd653da8e67, 0x584953ec82a8a, 0x55e288fa7707b, 0x5395fc3931d81, 0x45b46c51361cb}}, AffineCached{YplusX: radix51.FieldElement{0x54ddd8a7fe3e4, 0x2cecc41c619d3, 0x43a6562ac4d91, 0x4efa5aca7bdd9, 0x5c1c0aef32122}, YminusX: radix51.FieldElement{0x2abf314f7fa1, 0x391d19e8a1528, 0x6a2fa13895fc7, 0x9d8eddeaa591, 0x2177bfa36dcb7}, T2d: radix51.FieldElement{0x1bbcfa79db8f, 0x3d84beb3666e1, 0x20c921d812204, 0x2dd843d3b32ce, 0x4ae619387d8ab}}, AffineCached{YplusX: radix51.FieldElement{0x17e44985bfb83, 0x54e32c626cc22, 0x96412ff38118, 0x6b241d61a246a, 0x75685abe5ba43}, YminusX: radix51.FieldElement{0x3f6aa5344a32e, 0x69683680f11bb, 0x4c3581f623aa, 0x701af5875cba5, 0x1a00d91b17bf3}, T2d: radix51.FieldElement{0x60933eb61f2b2, 0x5193fe92a4dd2, 0x3d995a550f43e, 0x3556fb93a883d, 0x135529b623b0e}}, AffineCached{YplusX: radix51.FieldElement{0x716bce22e83fe, 0x33d0130b83eb8, 0x952abad0afac, 0x309f64ed31b8a, 0x5972ea051590a}, YminusX: radix51.FieldElement{0xdbd7add1d518, 0x119f823e2231e, 0x451d66e5e7de2, 0x500c39970f838, 0x79b5b81a65ca3}, T2d: radix51.FieldElement{0x4ac20dc8f7811, 0x29589a9f501fa, 0x4d810d26a6b4a, 0x5ede00d96b259, 0x4f7e9c95905f3}}, AffineCached{YplusX: radix51.FieldElement{0x443d355299fe, 0x39b7d7d5aee39, 0x692519a2f34ec, 0x6e4404924cf78, 0x1942eec4a144a}, YminusX: radix51.FieldElement{0x74bbc5781302e, 0x73135bb81ec4c, 0x7ef671b61483c, 0x7264614ccd729, 0x31993ad92e638}, T2d: radix51.FieldElement{0x45319ae234992, 0x2219d47d24fb5, 0x4f04488b06cf6, 0x53aaa9e724a12, 0x2a0a65314ef9c}}, AffineCached{YplusX: radix51.FieldElement{0x61acd3c1c793a, 0x58b46b78779e6, 0x3369aacbe7af2, 0x509b0743074d4, 0x55dc39b6dea1}, YminusX: radix51.FieldElement{0x7937ff7f927c2, 0xc2fa14c6a5b6, 0x556bddb6dd07c, 0x6f6acc179d108, 0x4cf6e218647c2}, T2d: radix51.FieldElement{0x1227cc28d5bb6, 0x78ee9bff57623, 0x28cb2241f893a, 0x25b541e3c6772, 0x121a307710aa2}}, AffineCached{YplusX: radix51.FieldElement{0x1713ec77483c9, 0x6f70572d5facb, 0x25ef34e22ff81, 0x54d944f141188, 0x527bb94a6ced3}, YminusX: radix51.FieldElement{0x35d5e9f034a97, 0x126069785bc9b, 0x5474ec7854ff0, 0x296a302a348ca, 0x333fc76c7a40e}, T2d: radix51.FieldElement{0x5992a995b482e, 0x78dc707002ac7, 0x5936394d01741, 0x4fba4281aef17, 0x6b89069b20a7a}}, AffineCached{YplusX: radix51.FieldElement{0x2fa8cb5c7db77, 0x718e6982aa810, 0x39e95f81a1a1b, 0x5e794f3646cfb, 0x473d308a7639}, YminusX: radix51.FieldElement{0x2a0416270220d, 0x75f248b69d025, 0x1cbbc16656a27, 0x5b9ffd6e26728, 0x23bc2103aa73e}, T2d: radix51.FieldElement{0x6792603589e05, 0x248db9892595d, 0x6a53cad2d08, 0x20d0150f7ba73, 0x102f73bfde043}}}}, - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x4dae0b5511c9a, 0x5257fffe0d456, 0x54108d1eb2180, 0x96cc0f9baefa, 0x3f6bd725da4ea}, YminusX: radix51.FieldElement{0xb9ab7f5745c6, 0x5caf0f8d21d63, 0x7debea408ea2b, 0x9edb93896d16, 0x36597d25ea5c0}, T2d: radix51.FieldElement{0x58d7b106058ac, 0x3cdf8d20bee69, 0xa4cb765015e, 0x36832337c7cc9, 0x7b7ecc19da60d}}, AffineCached{YplusX: radix51.FieldElement{0x64a51a77cfa9b, 0x29cf470ca0db5, 0x4b60b6e0898d9, 0x55d04ddffe6c7, 0x3bedc661bf5c}, YminusX: radix51.FieldElement{0x2373c695c690d, 0x4c0c8520dcf18, 0x384af4b7494b9, 0x4ab4a8ea22225, 0x4235ad7601743}, T2d: radix51.FieldElement{0xcb0d078975f5, 0x292313e530c4b, 0x38dbb9124a509, 0x350d0655a11f1, 0xe7ce2b0cdf06}}, AffineCached{YplusX: radix51.FieldElement{0x6fedfd94b70f9, 0x2383f9745bfd4, 0x4beae27c4c301, 0x75aa4416a3f3f, 0x615256138aece}, YminusX: radix51.FieldElement{0x4643ac48c85a3, 0x6878c2735b892, 0x3a53523f4d877, 0x3a504ed8bee9d, 0x666e0a5d8fb46}, T2d: radix51.FieldElement{0x3f64e4870cb0d, 0x61548b16d6557, 0x7a261773596f3, 0x7724d5f275d3a, 0x7f0bc810d514d}}, AffineCached{YplusX: radix51.FieldElement{0x49dad737213a0, 0x745dee5d31075, 0x7b1a55e7fdbe2, 0x5ba988f176ea1, 0x1d3a907ddec5a}, YminusX: radix51.FieldElement{0x6ba426f4136f, 0x3cafc0606b720, 0x518f0a2359cda, 0x5fae5e46feca7, 0xd1f8dbcf8eed}, T2d: radix51.FieldElement{0x693313ed081dc, 0x5b0a366901742, 0x40c872ca4ca7e, 0x6f18094009e01, 0x11b44a31bf}}, AffineCached{YplusX: radix51.FieldElement{0x61f696a0aa75c, 0x38b0a57ad42ca, 0x1e59ab706fdc9, 0x1308d46ebfcd, 0x63d988a2d2851}, YminusX: radix51.FieldElement{0x7a06c3fc66c0c, 0x1c9bac1ba47fb, 0x23935c575038e, 0x3f0bd71c59c13, 0x3ac48d916e835}, T2d: radix51.FieldElement{0x20753afbd232e, 0x71fbb1ed06002, 0x39cae47a4af3a, 0x337c0b34d9c2, 0x33fad52b2368a}}, AffineCached{YplusX: radix51.FieldElement{0x4c8d0c422cfe8, 0x760b4275971a5, 0x3da95bc1cad3d, 0xf151ff5b7376, 0x3cc355ccb90a7}, YminusX: radix51.FieldElement{0x649c6c5e41e16, 0x60667eee6aa80, 0x4179d182be190, 0x653d9567e6979, 0x16c0f429a256d}, T2d: radix51.FieldElement{0x69443903e9131, 0x16f4ac6f9dd36, 0x2ea4912e29253, 0x2b4643e68d25d, 0x631eaf426bae7}}, AffineCached{YplusX: radix51.FieldElement{0x175b9a3700de8, 0x77c5f00aa48fb, 0x3917785ca0317, 0x5aa9b2c79399, 0x431f2c7f665f8}, YminusX: radix51.FieldElement{0x10410da66fe9f, 0x24d82dcb4d67d, 0x3e6fe0e17752d, 0x4dade1ecbb08f, 0x5599648b1ea91}, T2d: radix51.FieldElement{0x26344858f7b19, 0x5f43d4a295ac0, 0x242a75c52acd4, 0x5934480220d10, 0x7b04715f91253}}, AffineCached{YplusX: radix51.FieldElement{0x6c280c4e6bac6, 0x3ada3b361766e, 0x42fe5125c3b4f, 0x111d84d4aac22, 0x48d0acfa57cde}, YminusX: radix51.FieldElement{0x5bd28acf6ae43, 0x16fab8f56907d, 0x7acb11218d5f2, 0x41fe02023b4db, 0x59b37bf5c2f65}, T2d: radix51.FieldElement{0x726e47dabe671, 0x2ec45e746f6c1, 0x6580e53c74686, 0x5eda104673f74, 0x16234191336d3}}}}, - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x19cd61ff38640, 0x60c6c4b41ba9, 0x75cf70ca7366f, 0x118a8f16c011e, 0x4a25707a203b9}, YminusX: radix51.FieldElement{0x499def6267ff6, 0x76e858108773c, 0x693cac5ddcb29, 0x311d00a9ff4, 0x2cdfdfecd5d05}, T2d: radix51.FieldElement{0x7668a53f6ed6a, 0x303ba2e142556, 0x3880584c10909, 0x4fe20000a261d, 0x5721896d248e4}}, AffineCached{YplusX: radix51.FieldElement{0x55091a1d0da4e, 0x4f6bfc7c1050b, 0x64e4ecd2ea9be, 0x7eb1f28bbe70, 0x3c935afc4b03}, YminusX: radix51.FieldElement{0x65517fd181bae, 0x3e5772c76816d, 0x19189640898a, 0x1ed2a84de7499, 0x578edd74f63c1}, T2d: radix51.FieldElement{0x276c6492b0c3d, 0x9bfc40bf932e, 0x588e8f11f330b, 0x3d16e694dc26e, 0x3ec2ab590288c}}, AffineCached{YplusX: radix51.FieldElement{0x13a09ae32d1cb, 0x3e81eb85ab4e4, 0x7aaca43cae1f, 0x62f05d7526374, 0xe1bf66c6adba}, YminusX: radix51.FieldElement{0xd27be4d87bb9, 0x56c27235db434, 0x72e6e0ea62d37, 0x5674cd06ee839, 0x2dd5c25a200fc}, T2d: radix51.FieldElement{0x3d5e9792c887e, 0x319724dabbc55, 0x2b97c78680800, 0x7afdfdd34e6dd, 0x730548b35ae88}}, AffineCached{YplusX: radix51.FieldElement{0x3094ba1d6e334, 0x6e126a7e3300b, 0x89c0aefcfbc5, 0x2eea11f836583, 0x585a2277d8784}, YminusX: radix51.FieldElement{0x551a3cba8b8ee, 0x3b6422be2d886, 0x630e1419689bc, 0x4653b07a7a955, 0x3043443b411db}, T2d: radix51.FieldElement{0x25f8233d48962, 0x6bd8f04aff431, 0x4f907fd9a6312, 0x40fd3c737d29b, 0x7656278950ef9}}, AffineCached{YplusX: radix51.FieldElement{0x73a3ea86cf9d, 0x6e0e2abfb9c2e, 0x60e2a38ea33ee, 0x30b2429f3fe18, 0x28bbf484b613f}, YminusX: radix51.FieldElement{0x3cf59d51fc8c0, 0x7a0a0d6de4718, 0x55c3a3e6fb74b, 0x353135f884fd5, 0x3f4160a8c1b84}, T2d: radix51.FieldElement{0x12f5c6f136c7c, 0xfedba237de4c, 0x779bccebfab44, 0x3aea93f4d6909, 0x1e79cb358188f}}, AffineCached{YplusX: radix51.FieldElement{0x153d8f5e08181, 0x8533bbdb2efd, 0x1149796129431, 0x17a6e36168643, 0x478ab52d39d1f}, YminusX: radix51.FieldElement{0x436c3eef7e3f1, 0x7ffd3c21f0026, 0x3e77bf20a2da9, 0x418bffc8472de, 0x65d7951b3a3b3}, T2d: radix51.FieldElement{0x6a4d39252d159, 0x790e35900ecd4, 0x30725bf977786, 0x10a5c1635a053, 0x16d87a411a212}}, AffineCached{YplusX: radix51.FieldElement{0x4d5e2d54e0583, 0x2e5d7b33f5f74, 0x3a5de3f887ebf, 0x6ef24bd6139b7, 0x1f990b577a5a6}, YminusX: radix51.FieldElement{0x57e5a42066215, 0x1a18b44983677, 0x3e652de1e6f8f, 0x6532be02ed8eb, 0x28f87c8165f38}, T2d: radix51.FieldElement{0x44ead1be8f7d6, 0x5759d4f31f466, 0x378149f47943, 0x69f3be32b4f29, 0x45882fe1534d6}}, AffineCached{YplusX: radix51.FieldElement{0x49929943c6fe4, 0x4347072545b15, 0x3226bced7e7c5, 0x3a134ced89df, 0x7dcf843ce405f}, YminusX: radix51.FieldElement{0x1345d757983d6, 0x222f54234cccd, 0x1784a3d8adbb4, 0x36ebeee8c2bcc, 0x688fe5b8f626f}, T2d: radix51.FieldElement{0xd6484a4732c0, 0x7b94ac6532d92, 0x5771b8754850f, 0x48dd9df1461c8, 0x6739687e73271}}}}, - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x5cc9dc80c1ac0, 0x683671486d4cd, 0x76f5f1a5e8173, 0x6d5d3f5f9df4a, 0x7da0b8f68d7e7}, YminusX: radix51.FieldElement{0x2014385675a6, 0x6155fb53d1def, 0x37ea32e89927c, 0x59a668f5a82e, 0x46115aba1d4dc}, T2d: radix51.FieldElement{0x71953c3b5da76, 0x6642233d37a81, 0x2c9658076b1bd, 0x5a581e63010ff, 0x5a5f887e83674}}, AffineCached{YplusX: radix51.FieldElement{0x628d3a0a643b9, 0x1cd8640c93d2, 0xb7b0cad70f2c, 0x3864da98144be, 0x43e37ae2d5d1c}, YminusX: radix51.FieldElement{0x301cf70a13d11, 0x2a6a1ba1891ec, 0x2f291fb3f3ae0, 0x21a7b814bea52, 0x3669b656e44d1}, T2d: radix51.FieldElement{0x63f06eda6e133, 0x233342758070f, 0x98e0459cc075, 0x4df5ead6c7c1b, 0x6a21e6cd4fd5e}}, AffineCached{YplusX: radix51.FieldElement{0x129126699b2e3, 0xee11a2603de8, 0x60ac2f5c74c21, 0x59b192a196808, 0x45371b07001e8}, YminusX: radix51.FieldElement{0x6170a3046e65f, 0x5401a46a49e38, 0x20add5561c4a8, 0x7abb4edde9e46, 0x586bf9f1a195f}, T2d: radix51.FieldElement{0x3088d5ef8790b, 0x38c2126fcb4db, 0x685bae149e3c3, 0xbcd601a4e930, 0xeafb03790e52}}, AffineCached{YplusX: radix51.FieldElement{0x805e0f75ae1d, 0x464cc59860a28, 0x248e5b7b00bef, 0x5d99675ef8f75, 0x44ae3344c5435}, YminusX: radix51.FieldElement{0x555c13748042f, 0x4d041754232c0, 0x521b430866907, 0x3308e40fb9c39, 0x309acc675a02c}, T2d: radix51.FieldElement{0x289b9bba543ee, 0x3ab592e28539e, 0x64d82abcdd83a, 0x3c78ec172e327, 0x62d5221b7f946}}, AffineCached{YplusX: radix51.FieldElement{0x5d4263af77a3c, 0x23fdd2289aeb0, 0x7dc64f77eb9ec, 0x1bd28338402c, 0x14f29a5383922}, YminusX: radix51.FieldElement{0x4299c18d0936d, 0x5914183418a49, 0x52a18c721aed5, 0x2b151ba82976d, 0x5c0efde4bc754}, T2d: radix51.FieldElement{0x17edc25b2d7f5, 0x37336a6081bee, 0x7b5318887e5c3, 0x49f6d491a5be1, 0x5e72365c7bee0}}, AffineCached{YplusX: radix51.FieldElement{0x339062f08b33e, 0x4bbf3e657cfb2, 0x67af7f56e5967, 0x4dbd67f9ed68f, 0x70b20555cb734}, YminusX: radix51.FieldElement{0x3fc074571217f, 0x3a0d29b2b6aeb, 0x6478ccdde59d, 0x55e4d051bddfa, 0x77f1104c47b4e}, T2d: radix51.FieldElement{0x113c555112c4c, 0x7535103f9b7ca, 0x140ed1d9a2108, 0x2522333bc2af, 0xe34398f4a064}}, AffineCached{YplusX: radix51.FieldElement{0x30b093e4b1928, 0x1ce7e7ec80312, 0x4e575bdf78f84, 0x61f7a190bed39, 0x6f8aded6ca379}, YminusX: radix51.FieldElement{0x522d93ecebde8, 0x24f045e0f6cf, 0x16db63426cfa1, 0x1b93a1fd30fd8, 0x5e5405368a362}, T2d: radix51.FieldElement{0x123dfdb7b29a, 0x4344356523c68, 0x79a527921ee5f, 0x74bfccb3e817e, 0x780de72ec8d3d}}, AffineCached{YplusX: radix51.FieldElement{0x7eaf300f42772, 0x5455188354ce3, 0x4dcca4a3dcbac, 0x3d314d0bfebcb, 0x1defc6ad32b58}, YminusX: radix51.FieldElement{0x28545089ae7bc, 0x1e38fe9a0c15c, 0x12046e0e2377b, 0x6721c560aa885, 0xeb28bf671928}, T2d: radix51.FieldElement{0x3be1aef5195a7, 0x6f22f62bdb5eb, 0x39768b8523049, 0x43394c8fbfdbd, 0x467d201bf8dd2}}}}, - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x6f4bd567ae7a9, 0x65ac89317b783, 0x7d3b20fd8932, 0xf208326916, 0x2ef9c5a5ba384}, YminusX: radix51.FieldElement{0x6919a74ef4fad, 0x59ed4611452bf, 0x691ec04ea09ef, 0x3cbcb2700e984, 0x71c43c4f5ba3c}, T2d: radix51.FieldElement{0x56df6fa9e74cd, 0x79c95e4cf56df, 0x7be643bc609e2, 0x149c12ad9e878, 0x5a758ca390c5f}}, AffineCached{YplusX: radix51.FieldElement{0x918b1d61dc94, 0xd350260cd19c, 0x7a2ab4e37b4d9, 0x21fea735414d7, 0xa738027f639d}, YminusX: radix51.FieldElement{0x72710d9462495, 0x25aafaa007456, 0x2d21f28eaa31b, 0x17671ea005fd0, 0x2dbae244b3eb7}, T2d: radix51.FieldElement{0x74a2f57ffe1cc, 0x1bc3073087301, 0x7ec57f4019c34, 0x34e082e1fa524, 0x2698ca635126a}}, AffineCached{YplusX: radix51.FieldElement{0x5702f5e3dd90e, 0x31c9a4a70c5c7, 0x136a5aa78fc24, 0x1992f3b9f7b01, 0x3c004b0c4afa3}, YminusX: radix51.FieldElement{0x5318832b0ba78, 0x6f24b9ff17cec, 0xa47f30e060c7, 0x58384540dc8d0, 0x1fb43dcc49cae}, T2d: radix51.FieldElement{0x146ac06f4b82b, 0x4b500d89e7355, 0x3351e1c728a12, 0x10b9f69932fe3, 0x6b43fd01cd1fd}}, AffineCached{YplusX: radix51.FieldElement{0x742583e760ef3, 0x73dc1573216b8, 0x4ae48fdd7714a, 0x4f85f8a13e103, 0x73420b2d6ff0d}, YminusX: radix51.FieldElement{0x75d4b4697c544, 0x11be1fff7f8f4, 0x119e16857f7e1, 0x38a14345cf5d5, 0x5a68d7105b52f}, T2d: radix51.FieldElement{0x4f6cb9e851e06, 0x278c4471895e5, 0x7efcdce3d64e4, 0x64f6d455c4b4c, 0x3db5632fea34b}}, AffineCached{YplusX: radix51.FieldElement{0x190b1829825d5, 0xe7d3513225c9, 0x1c12be3b7abae, 0x58777781e9ca6, 0x59197ea495df2}, YminusX: radix51.FieldElement{0x6ee2bf75dd9d8, 0x6c72ceb34be8d, 0x679c9cc345ec7, 0x7898df96898a4, 0x4321adf49d75}, T2d: radix51.FieldElement{0x16019e4e55aae, 0x74fc5f25d209c, 0x4566a939ded0d, 0x66063e716e0b7, 0x45eafdc1f4d70}}, AffineCached{YplusX: radix51.FieldElement{0x64624cfccb1ed, 0x257ab8072b6c1, 0x120725676f0a, 0x4a018d04e8eee, 0x3f73ceea5d56d}, YminusX: radix51.FieldElement{0x401858045d72b, 0x459e5e0ca2d30, 0x488b719308bea, 0x56f4a0d1b32b5, 0x5a5eebc80362d}, T2d: radix51.FieldElement{0x7bfd10a4e8dc6, 0x7c899366736f4, 0x55ebbeaf95c01, 0x46db060903f8a, 0x2605889126621}}, AffineCached{YplusX: radix51.FieldElement{0x18e3cc676e542, 0x26079d995a990, 0x4a7c217908b2, 0x1dc7603e6655a, 0xdedfa10b2444}, YminusX: radix51.FieldElement{0x704a68360ff04, 0x3cecc3cde8b3e, 0x21cd5470f64ff, 0x6abc18d953989, 0x54ad0c2e4e615}, T2d: radix51.FieldElement{0x367d5b82b522a, 0xd3f4b83d7dc7, 0x3067f4cdbc58d, 0x20452da697937, 0x62ecb2baa77a9}}, AffineCached{YplusX: radix51.FieldElement{0x72836afb62874, 0xaf3c2094b240, 0xc285297f357a, 0x7cc2d5680d6e3, 0x61913d5075663}, YminusX: radix51.FieldElement{0x5795261152b3d, 0x7a1dbbafa3cbd, 0x5ad31c52588d5, 0x45f3a4164685c, 0x2e59f919a966d}, T2d: radix51.FieldElement{0x62d361a3231da, 0x65284004e01b8, 0x656533be91d60, 0x6ae016c00a89f, 0x3ddbc2a131c05}}}}, - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x257a22796bb14, 0x6f360fb443e75, 0x680e47220eaea, 0x2fcf2a5f10c18, 0x5ee7fb38d8320}, YminusX: radix51.FieldElement{0x40ff9ce5ec54b, 0x57185e261b35b, 0x3e254540e70a9, 0x1b5814003e3f8, 0x78968314ac04b}, T2d: radix51.FieldElement{0x5fdcb41446a8e, 0x5286926ff2a71, 0xf231e296b3f6, 0x684a357c84693, 0x61d0633c9bca0}}, AffineCached{YplusX: radix51.FieldElement{0x328bcf8fc73df, 0x3b4de06ff95b4, 0x30aa427ba11a5, 0x5ee31bfda6d9c, 0x5b23ac2df8067}, YminusX: radix51.FieldElement{0x44935ffdb2566, 0x12f016d176c6e, 0x4fbb00f16f5ae, 0x3fab78d99402a, 0x6e965fd847aed}, T2d: radix51.FieldElement{0x2b953ee80527b, 0x55f5bcdb1b35a, 0x43a0b3fa23c66, 0x76e07388b820a, 0x79b9bbb9dd95d}}, AffineCached{YplusX: radix51.FieldElement{0x17dae8e9f7374, 0x719f76102da33, 0x5117c2a80ca8b, 0x41a66b65d0936, 0x1ba811460accb}, YminusX: radix51.FieldElement{0x355406a3126c2, 0x50d1918727d76, 0x6e5ea0b498e0e, 0xa3b6063214f2, 0x5065f158c9fd2}, T2d: radix51.FieldElement{0x169fb0c429954, 0x59aedd9ecee10, 0x39916eb851802, 0x57917555cc538, 0x3981f39e58a4f}}, AffineCached{YplusX: radix51.FieldElement{0x5dfa56de66fde, 0x58809075908, 0x6d3d8cb854a94, 0x5b2f4e970b1e3, 0x30f4452edcbc1}, YminusX: radix51.FieldElement{0x38a7559230a93, 0x52c1cde8ba31f, 0x2a4f2d4745a3d, 0x7e9d42d4a28a, 0x38dc083705acd}, T2d: radix51.FieldElement{0x52782c5759740, 0x53f3397d990ad, 0x3a939c7e84d15, 0x234c4227e39e0, 0x632d9a1a593f2}}, AffineCached{YplusX: radix51.FieldElement{0x1fd11ed0c84a7, 0x21b3ed2757e1, 0x73e1de58fc1c6, 0x5d110c84616ab, 0x3a5a7df28af64}, YminusX: radix51.FieldElement{0x36b15b807cba6, 0x3f78a9e1afed7, 0xa59c2c608f1f, 0x52bdd8ecb81b7, 0xb24f48847ed4}, T2d: radix51.FieldElement{0x2d4be511beac7, 0x6bda4d99e5b9b, 0x17e6996914e01, 0x7b1f0ce7fcf80, 0x34fcf74475481}}, AffineCached{YplusX: radix51.FieldElement{0x31dab78cfaa98, 0x4e3216e5e54b7, 0x249823973b689, 0x2584984e48885, 0x119a3042fb37}, YminusX: radix51.FieldElement{0x7e04c789767ca, 0x1671b28cfb832, 0x7e57ea2e1c537, 0x1fbaaef444141, 0x3d3bdc164dfa6}, T2d: radix51.FieldElement{0x2d89ce8c2177d, 0x6cd12ba182cf4, 0x20a8ac19a7697, 0x539fab2cc72d9, 0x56c088f1ede20}}, AffineCached{YplusX: radix51.FieldElement{0x35fac24f38f02, 0x7d75c6197ab03, 0x33e4bc2a42fa7, 0x1c7cd10b48145, 0x38b7ea483590}, YminusX: radix51.FieldElement{0x53d1110a86e17, 0x6416eb65f466d, 0x41ca6235fce20, 0x5c3fc8a99bb12, 0x9674c6b99108}, T2d: radix51.FieldElement{0x6f82199316ff8, 0x5d54f1a9f3e9, 0x3bcc5d0bd274a, 0x5b284b8d2d5ad, 0x6e5e31025969e}}, AffineCached{YplusX: radix51.FieldElement{0x4fb0e63066222, 0x130f59747e660, 0x41868fecd41a, 0x3105e8c923bc6, 0x3058ad43d1838}, YminusX: radix51.FieldElement{0x462f587e593fb, 0x3d94ba7ce362d, 0x330f9b52667b7, 0x5d45a48e0f00a, 0x8f5114789a8d}, T2d: radix51.FieldElement{0x40ffde57663d0, 0x71445d4c20647, 0x2653e68170f7c, 0x64cdee3c55ed6, 0x26549fa4efe3d}}}}, - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x68549af3f666e, 0x9e2941d4bb68, 0x2e8311f5dff3c, 0x6429ef91ffbd2, 0x3a10dfe132ce3}, YminusX: radix51.FieldElement{0x55a461e6bf9d6, 0x78eeef4b02e83, 0x1d34f648c16cf, 0x7fea2aba5132, 0x1926e1dc6401e}, T2d: radix51.FieldElement{0x74e8aea17cea0, 0xc743f83fbc0f, 0x7cb03c4bf5455, 0x68a8ba9917e98, 0x1fa1d01d861e5}}, AffineCached{YplusX: radix51.FieldElement{0x4ac00d1df94ab, 0x3ba2101bd271b, 0x7578988b9c4af, 0xf2bf89f49f7e, 0x73fced18ee9a0}, YminusX: radix51.FieldElement{0x55947d599832, 0x346fe2aa41990, 0x164c8079195b, 0x799ccfb7bba27, 0x773563bc6a75c}, T2d: radix51.FieldElement{0x1e90863139cb3, 0x4f8b407d9a0d6, 0x58e24ca924f69, 0x7a246bbe76456, 0x1f426b701b864}}, AffineCached{YplusX: radix51.FieldElement{0x635c891a12552, 0x26aebd38ede2f, 0x66dc8faddae05, 0x21c7d41a03786, 0xb76bb1b3fa7e}, YminusX: radix51.FieldElement{0x1264c41911c01, 0x702f44584bdf9, 0x43c511fc68ede, 0x482c3aed35f9, 0x4e1af5271d31b}, T2d: radix51.FieldElement{0xc1f97f92939b, 0x17a88956dc117, 0x6ee005ef99dc7, 0x4aa9172b231cc, 0x7b6dd61eb772a}}, AffineCached{YplusX: radix51.FieldElement{0xabf9ab01d2c7, 0x3880287630ae6, 0x32eca045beddb, 0x57f43365f32d0, 0x53fa9b659bff6}, YminusX: radix51.FieldElement{0x5c1e850f33d92, 0x1ec119ab9f6f5, 0x7f16f6de663e9, 0x7a7d6cb16dec6, 0x703e9bceaf1d2}, T2d: radix51.FieldElement{0x4c8e994885455, 0x4ccb5da9cad82, 0x3596bc610e975, 0x7a80c0ddb9f5e, 0x398d93e5c4c61}}, AffineCached{YplusX: radix51.FieldElement{0x77c60d2e7e3f2, 0x4061051763870, 0x67bc4e0ecd2aa, 0x2bb941f1373b9, 0x699c9c9002c30}, YminusX: radix51.FieldElement{0x3d16733e248f3, 0xe2b7e14be389, 0x42c0ddaf6784a, 0x589ea1fc67850, 0x53b09b5ddf191}, T2d: radix51.FieldElement{0x6a7235946f1cc, 0x6b99cbb2fbe60, 0x6d3a5d6485c62, 0x4839466e923c0, 0x51caf30c6fcdd}}, AffineCached{YplusX: radix51.FieldElement{0x2f99a18ac54c7, 0x398a39661ee6f, 0x384331e40cde3, 0x4cd15c4de19a6, 0x12ae29c189f8e}, YminusX: radix51.FieldElement{0x3a7427674e00a, 0x6142f4f7e74c1, 0x4cc93318c3a15, 0x6d51bac2b1ee7, 0x5504aa292383f}, T2d: radix51.FieldElement{0x6c0cb1f0d01cf, 0x187469ef5d533, 0x27138883747bf, 0x2f52ae53a90e8, 0x5fd14fe958eba}}, AffineCached{YplusX: radix51.FieldElement{0x2fe5ebf93cb8e, 0x226da8acbe788, 0x10883a2fb7ea1, 0x94707842cf44, 0x7dd73f960725d}, YminusX: radix51.FieldElement{0x42ddf2845ab2c, 0x6214ffd3276bb, 0xb8d181a5246, 0x268a6d579eb20, 0x93ff26e58647}, T2d: radix51.FieldElement{0x524fe68059829, 0x65b75e47cb621, 0x15eb0a5d5cc19, 0x5209b3929d5a, 0x2f59bcbc86b47}}, AffineCached{YplusX: radix51.FieldElement{0x1d560b691c301, 0x7f5bafce3ce08, 0x4cd561614806c, 0x4588b6170b188, 0x2aa55e3d01082}, YminusX: radix51.FieldElement{0x47d429917135f, 0x3eacfa07af070, 0x1deab46b46e44, 0x7a53f3ba46cdf, 0x5458b42e2e51a}, T2d: radix51.FieldElement{0x192e60c07444f, 0x5ae8843a21daa, 0x6d721910b1538, 0x3321a95a6417e, 0x13e9004a8a768}}}}, - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x600c9193b877f, 0x21c1b8a0d7765, 0x379927fb38ea2, 0x70d7679dbe01b, 0x5f46040898de9}, YminusX: radix51.FieldElement{0x58845832fcedb, 0x135cd7f0c6e73, 0x53ffbdfe8e35b, 0x22f195e06e55b, 0x73937e8814bce}, T2d: radix51.FieldElement{0x37116297bf48d, 0x45a9e0d069720, 0x25af71aa744ec, 0x41af0cb8aaba3, 0x2cf8a4e891d5e}}, AffineCached{YplusX: radix51.FieldElement{0x5487e17d06ba2, 0x3872a032d6596, 0x65e28c09348e0, 0x27b6bb2ce40c2, 0x7a6f7f2891d6a}, YminusX: radix51.FieldElement{0x3fd8707110f67, 0x26f8716a92db2, 0x1cdaa1b753027, 0x504be58b52661, 0x2049bd6e58252}, T2d: radix51.FieldElement{0x1fd8d6a9aef49, 0x7cb67b7216fa1, 0x67aff53c3b982, 0x20ea610da9628, 0x6011aadfc5459}}, AffineCached{YplusX: radix51.FieldElement{0x6d0c802cbf890, 0x141bfed554c7b, 0x6dbb667ef4263, 0x58f3126857edc, 0x69ce18b779340}, YminusX: radix51.FieldElement{0x7926dcf95f83c, 0x42e25120e2bec, 0x63de96df1fa15, 0x4f06b50f3f9cc, 0x6fc5cc1b0b62f}, T2d: radix51.FieldElement{0x75528b29879cb, 0x79a8fd2125a3d, 0x27c8d4b746ab8, 0xf8893f02210c, 0x15596b3ae5710}}, AffineCached{YplusX: radix51.FieldElement{0x731167e5124ca, 0x17b38e8bbe13f, 0x3d55b942f9056, 0x9c1495be913f, 0x3aa4e241afb6d}, YminusX: radix51.FieldElement{0x739d23f9179a2, 0x632fadbb9e8c4, 0x7c8522bfe0c48, 0x6ed0983ef5aa9, 0xd2237687b5f4}, T2d: radix51.FieldElement{0x138bf2a3305f5, 0x1f45d24d86598, 0x5274bad2160fe, 0x1b6041d58d12a, 0x32fcaa6e4687a}}, AffineCached{YplusX: radix51.FieldElement{0x7a4732787ccdf, 0x11e427c7f0640, 0x3659385f8c64, 0x5f4ead9766bfb, 0x746f6336c2600}, YminusX: radix51.FieldElement{0x56e8dc57d9af5, 0x5b3be17be4f78, 0x3bf928cf82f4b, 0x52e55600a6f11, 0x4627e9cefebd6}, T2d: radix51.FieldElement{0x2f345ab6c971c, 0x653286e63e7e9, 0x51061b78a23ad, 0x14999acb54501, 0x7b4917007ed66}}, AffineCached{YplusX: radix51.FieldElement{0x41b28dd53a2dd, 0x37be85f87ea86, 0x74be3d2a85e41, 0x1be87fac96ca6, 0x1d03620fe08cd}, YminusX: radix51.FieldElement{0x5fb5cab84b064, 0x2513e778285b0, 0x457383125e043, 0x6bda3b56e223d, 0x122ba376f844f}, T2d: radix51.FieldElement{0x232cda2b4e554, 0x422ba30ff840, 0x751e7667b43f5, 0x6261755da5f3e, 0x2c70bf52b68e}}, AffineCached{YplusX: radix51.FieldElement{0x532bf458d72e1, 0x40f96e796b59c, 0x22ef79d6f9da3, 0x501ab67beca77, 0x6b0697e3feb43}, YminusX: radix51.FieldElement{0x7ec4b5d0b2fbb, 0x200e910595450, 0x742057105715e, 0x2f07022530f60, 0x26334f0a409ef}, T2d: radix51.FieldElement{0xf04adf62a3c0, 0x5e0edb48bb6d9, 0x7c34aa4fbc003, 0x7d74e4e5cac24, 0x1cc37f43441b2}}, AffineCached{YplusX: radix51.FieldElement{0x656f1c9ceaeb9, 0x7031cacad5aec, 0x1308cd0716c57, 0x41c1373941942, 0x3a346f772f196}, YminusX: radix51.FieldElement{0x7565a5cc7324f, 0x1ca0d5244a11, 0x116b067418713, 0xa57d8c55edae, 0x6c6809c103803}, T2d: radix51.FieldElement{0x55112e2da6ac8, 0x6363d0a3dba5a, 0x319c98ba6f40c, 0x2e84b03a36ec7, 0x5911b9f6ef7c}}}}, - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x1acf3512eeaef, 0x2639839692a69, 0x669a234830507, 0x68b920c0603d4, 0x555ef9d1c64b2}, YminusX: radix51.FieldElement{0x39983f5df0ebb, 0x1ea2589959826, 0x6ce638703cdd6, 0x6311678898505, 0x6b3cecf9aa270}, T2d: radix51.FieldElement{0x770ba3b73bd08, 0x11475f7e186d4, 0x251bc9892bbc, 0x24eab9bffcc5a, 0x675f4de133817}}, AffineCached{YplusX: radix51.FieldElement{0x7f6d93bdab31d, 0x1f3aca5bfd425, 0x2fa521c1c9760, 0x62180ce27f9cd, 0x60f450b882cd3}, YminusX: radix51.FieldElement{0x452036b1782fc, 0x2d95b07681c5, 0x5901cf99205b2, 0x290686e5eecb4, 0x13d99df70164c}, T2d: radix51.FieldElement{0x35ec321e5c0ca, 0x13ae337f44029, 0x4008e813f2da7, 0x640272f8e0c3a, 0x1c06de9e55eda}}, AffineCached{YplusX: radix51.FieldElement{0x52b40ff6d69aa, 0x31b8809377ffa, 0x536625cd14c2c, 0x516af252e17d1, 0x78096f8e7d32b}, YminusX: radix51.FieldElement{0x77ad6a33ec4e2, 0x717c5dc11d321, 0x4a114559823e4, 0x306ce50a1e2b1, 0x4cf38a1fec2db}, T2d: radix51.FieldElement{0x2aa650dfa5ce7, 0x54916a8f19415, 0xdc96fe71278, 0x55f2784e63eb8, 0x373cad3a26091}}, AffineCached{YplusX: radix51.FieldElement{0x6a8fb89ddbbad, 0x78c35d5d97e37, 0x66e3674ef2cb2, 0x34347ac53dd8f, 0x21547eda5112a}, YminusX: radix51.FieldElement{0x4634d82c9f57c, 0x4249268a6d652, 0x6336d687f2ff7, 0x4fe4f4e26d9a0, 0x40f3d945441}, T2d: radix51.FieldElement{0x5e939fd5986d3, 0x12a2147019bdf, 0x4c466e7d09cb2, 0x6fa5b95d203dd, 0x63550a334a254}}, AffineCached{YplusX: radix51.FieldElement{0x2584572547b49, 0x75c58811c1377, 0x4d3c637cc171b, 0x33d30747d34e3, 0x39a92bafaa7d7}, YminusX: radix51.FieldElement{0x7d6edb569cf37, 0x60194a5dc2ca0, 0x5af59745e10a6, 0x7a8f53e004875, 0x3eea62c7daf78}, T2d: radix51.FieldElement{0x4c713e693274e, 0x6ed1b7a6eb3a4, 0x62ace697d8e15, 0x266b8292ab075, 0x68436a0665c9c}}, AffineCached{YplusX: radix51.FieldElement{0x6d317e820107c, 0x90815d2ca3ca, 0x3ff1eb1499a1, 0x23960f050e319, 0x5373669c91611}, YminusX: radix51.FieldElement{0x235e8202f3f27, 0x44c9f2eb61780, 0x630905b1d7003, 0x4fcc8d274ead1, 0x17b6e7f68ab78}, T2d: radix51.FieldElement{0x14ab9a0e5257, 0x9939567f8ba5, 0x4b47b2a423c82, 0x688d7e57ac42d, 0x1cb4b5a678f87}}, AffineCached{YplusX: radix51.FieldElement{0x4aa62a2a007e7, 0x61e0e38f62d6e, 0x2f888fcc4782, 0x7562b83f21c00, 0x2dc0fd2d82ef6}, YminusX: radix51.FieldElement{0x4c06b394afc6c, 0x4931b4bf636cc, 0x72b60d0322378, 0x25127c6818b25, 0x330bca78de743}, T2d: radix51.FieldElement{0x6ff841119744e, 0x2c560e8e49305, 0x7254fefe5a57a, 0x67ae2c560a7df, 0x3c31be1b369f1}}, AffineCached{YplusX: radix51.FieldElement{0xbc93f9cb4272, 0x3f8f9db73182d, 0x2b235eabae1c4, 0x2ddbf8729551a, 0x41cec1097e7d5}, YminusX: radix51.FieldElement{0x4864d08948aee, 0x5d237438df61e, 0x2b285601f7067, 0x25dbcbae6d753, 0x330b61134262d}, T2d: radix51.FieldElement{0x619d7a26d808a, 0x3c3b3c2adbef2, 0x6877c9eec7f52, 0x3beb9ebe1b66d, 0x26b44cd91f287}}}}, - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x7f29362730383, 0x7fd7951459c36, 0x7504c512d49e7, 0x87ed7e3bc55f, 0x7deb10149c726}, YminusX: radix51.FieldElement{0x48478f387475, 0x69397d9678a3e, 0x67c8156c976f3, 0x2eb4d5589226c, 0x2c709e6c1c10a}, T2d: radix51.FieldElement{0x2af6a8766ee7a, 0x8aaa79a1d96c, 0x42f92d59b2fb0, 0x1752c40009c07, 0x8e68e9ff62ce}}, AffineCached{YplusX: radix51.FieldElement{0x509d50ab8f2f9, 0x1b8ab247be5e5, 0x5d9b2e6b2e486, 0x4faa5479a1339, 0x4cb13bd738f71}, YminusX: radix51.FieldElement{0x5500a4bc130ad, 0x127a17a938695, 0x2a26fa34e36d, 0x584d12e1ecc28, 0x2f1f3f87eeba3}, T2d: radix51.FieldElement{0x48c75e515b64a, 0x75b6952071ef0, 0x5d46d42965406, 0x7746106989f9f, 0x19a1e353c0ae2}}, AffineCached{YplusX: radix51.FieldElement{0x172cdd596bdbd, 0x731ddf881684, 0x10426d64f8115, 0x71a4fd8a9a3da, 0x736bd3990266a}, YminusX: radix51.FieldElement{0x47560bafa05c3, 0x418dcabcc2fa3, 0x35991cecf8682, 0x24371a94b8c60, 0x41546b11c20c3}, T2d: radix51.FieldElement{0x32d509334b3b4, 0x16c102cae70aa, 0x1720dd51bf445, 0x5ae662faf9821, 0x412295a2b87fa}}, AffineCached{YplusX: radix51.FieldElement{0x55261e293eac6, 0x6426759b65cc, 0x40265ae116a48, 0x6c02304bae5bc, 0x760bb8d195ad}, YminusX: radix51.FieldElement{0x19b88f57ed6e9, 0x4cdbf1904a339, 0x42b49cd4e4f2c, 0x71a2e771909d9, 0x14e153ebb52d2}, T2d: radix51.FieldElement{0x61a17cde6818a, 0x53dad34108827, 0x32b32c55c55b6, 0x2f9165f9347a3, 0x6b34be9bc33ac}}, AffineCached{YplusX: radix51.FieldElement{0x469656571f2d3, 0xaa61ce6f423f, 0x3f940d71b27a1, 0x185f19d73d16a, 0x1b9c7b62e6dd}, YminusX: radix51.FieldElement{0x72f643a78c0b2, 0x3de45c04f9e7b, 0x706d68d30fa5c, 0x696f63e8e2f24, 0x2012c18f0922d}, T2d: radix51.FieldElement{0x355e55ac89d29, 0x3e8b414ec7101, 0x39db07c520c90, 0x6f41e9b77efe1, 0x8af5b784e4ba}}, AffineCached{YplusX: radix51.FieldElement{0x314d289cc2c4b, 0x23450e2f1bc4e, 0xcd93392f92f4, 0x1370c6a946b7d, 0x6423c1d5afd98}, YminusX: radix51.FieldElement{0x499dc881f2533, 0x34ef26476c506, 0x4d107d2741497, 0x346c4bd6efdb3, 0x32b79d71163a1}, T2d: radix51.FieldElement{0x5f8d9edfcb36a, 0x1e6e8dcbf3990, 0x7974f348af30a, 0x6e6724ef19c7c, 0x480a5efbc13e2}}, AffineCached{YplusX: radix51.FieldElement{0x14ce442ce221f, 0x18980a72516cc, 0x72f80db86677, 0x703331fda526e, 0x24b31d47691c8}, YminusX: radix51.FieldElement{0x1e70b01622071, 0x1f163b5f8a16a, 0x56aaf341ad417, 0x7989635d830f7, 0x47aa27600cb7b}, T2d: radix51.FieldElement{0x41eedc015f8c3, 0x7cf8d27ef854a, 0x289e3584693f9, 0x4a7857b309a7, 0x545b585d14dda}}, AffineCached{YplusX: radix51.FieldElement{0x4e4d0e3b321e1, 0x7451fe3d2ac40, 0x666f678eea98d, 0x38858667fead, 0x4d22dc3e64c8d}, YminusX: radix51.FieldElement{0x7275ea0d43a0f, 0x681137dd7ccf7, 0x1e79cbab79a38, 0x22a214489a66a, 0xf62f9c332ba5}, T2d: radix51.FieldElement{0x46589d63b5f39, 0x7eaf979ec3f96, 0x4ebe81572b9a8, 0x21b7f5d61694a, 0x1c0fa01a36371}}}}, - affineLookupTable{points: [8]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x2b0e8c936a50, 0x6b83b58b6cd21, 0x37ed8d3e72680, 0xa037db9f2a62, 0x4005419b1d2bc}, YminusX: radix51.FieldElement{0x604b622943dff, 0x1c899f6741a58, 0x60219e2f232fb, 0x35fae92a7f9cb, 0xfa3614f3b1ca}, T2d: radix51.FieldElement{0x3febdb9be82f0, 0x5e74895921400, 0x553ea38822706, 0x5a17c24cfc88c, 0x1fba218aef40a}}, AffineCached{YplusX: radix51.FieldElement{0x657043e7b0194, 0x5c11b55efe9e7, 0x7737bc6a074fb, 0xeae41ce355cc, 0x6c535d13ff776}, YminusX: radix51.FieldElement{0x49448fac8f53e, 0x34f74c6e8356a, 0xad780607dba2, 0x7213a7eb63eb6, 0x392e3acaa8c86}, T2d: radix51.FieldElement{0x534e93e8a35af, 0x8b10fd02c997, 0x26ac2acb81e05, 0x9d8c98ce3b79, 0x25e17fe4d50ac}}, AffineCached{YplusX: radix51.FieldElement{0x77ff576f121a7, 0x4e5f9b0fc722b, 0x46f949b0d28c8, 0x4cde65d17ef26, 0x6bba828f89698}, YminusX: radix51.FieldElement{0x9bd71e04f676, 0x25ac841f2a145, 0x1a47eac823871, 0x1a8a8c36c581a, 0x255751442a9fb}, T2d: radix51.FieldElement{0x1bc6690fe3901, 0x314132f5abc5a, 0x611835132d528, 0x5f24b8eb48a57, 0x559d504f7f6b7}}, AffineCached{YplusX: radix51.FieldElement{0x91e7f6d266fd, 0x36060ef037389, 0x18788ec1d1286, 0x287441c478eb0, 0x123ea6a3354bd}, YminusX: radix51.FieldElement{0x38378b3eb54d5, 0x4d4aaa78f94ee, 0x4a002e875a74d, 0x10b851367b17c, 0x1ab12d5807e3}, T2d: radix51.FieldElement{0x5189041e32d96, 0x5b062b090231, 0xc91766e7b78f, 0xaa0f55a138ec, 0x4a3961e2c918a}}, AffineCached{YplusX: radix51.FieldElement{0x7d644f3233f1e, 0x1c69f9e02c064, 0x36ae5e5266898, 0x8fc1dad38b79, 0x68aceead9bd41}, YminusX: radix51.FieldElement{0x43be0f8e6bba0, 0x68fdffc614e3b, 0x4e91dab5b3be0, 0x3b1d4c9212ff0, 0x2cd6bce3fb1db}, T2d: radix51.FieldElement{0x4c90ef3d7c210, 0x496f5a0818716, 0x79cf88cc239b8, 0x2cb9c306cf8db, 0x595760d5b508f}}, AffineCached{YplusX: radix51.FieldElement{0x2cbebfd022790, 0xb8822aec1105, 0x4d1cfd226bccc, 0x515b2fa4971be, 0x2cb2c5df54515}, YminusX: radix51.FieldElement{0x1bfe104aa6397, 0x11494ff996c25, 0x64251623e5800, 0xd49fc5e044be, 0x709fa43edcb29}, T2d: radix51.FieldElement{0x25d8c63fd2aca, 0x4c5cd29dffd61, 0x32ec0eb48af05, 0x18f9391f9b77c, 0x70f029ecf0c81}}, AffineCached{YplusX: radix51.FieldElement{0x2afaa5e10b0b9, 0x61de08355254d, 0xeb587de3c28d, 0x4f0bb9f7dbbd5, 0x44eca5a2a74bd}, YminusX: radix51.FieldElement{0x307b32eed3e33, 0x6748ab03ce8c2, 0x57c0d9ab810bc, 0x42c64a224e98c, 0xb7d5d8a6c314}, T2d: radix51.FieldElement{0x448327b95d543, 0x146681e3a4ba, 0x38714adc34e0c, 0x4f26f0e298e30, 0x272224512c7de}}, AffineCached{YplusX: radix51.FieldElement{0x3bb8a42a975fc, 0x6f2d5b46b17ef, 0x7b6a9223170e5, 0x53713fe3b7e6, 0x19735fd7f6bc2}, YminusX: radix51.FieldElement{0x492af49c5342e, 0x2365cdf5a0357, 0x32138a7ffbb60, 0x2a1f7d14646fe, 0x11b5df18a44cc}, T2d: radix51.FieldElement{0x390d042c84266, 0x1efe32a8fdc75, 0x6925ee7ae1238, 0x4af9281d0e832, 0xfef911191df8}}}}, - } - basepointNafTable = nafLookupTable8{points: [64]AffineCached{AffineCached{YplusX: radix51.FieldElement{0x493c6f58c3b85, 0xdf7181c325f7, 0xf50b0b3e4cb7, 0x5329385a44c32, 0x7cf9d3a33d4b}, YminusX: radix51.FieldElement{0x3905d740913e, 0xba2817d673a2, 0x23e2827f4e67c, 0x133d2e0c21a34, 0x44fd2f9298f81}, T2d: radix51.FieldElement{0x11205877aaa68, 0x479955893d579, 0x50d66309b67a0, 0x2d42d0dbee5ee, 0x6f117b689f0c6}}, AffineCached{YplusX: radix51.FieldElement{0x5b0a84cee9730, 0x61d10c97155e4, 0x4059cc8096a10, 0x47a608da8014f, 0x7a164e1b9a80f}, YminusX: radix51.FieldElement{0x11fe8a4fcd265, 0x7bcb8374faacc, 0x52f5af4ef4d4f, 0x5314098f98d10, 0x2ab91587555bd}, T2d: radix51.FieldElement{0x6933f0dd0d889, 0x44386bb4c4295, 0x3cb6d3162508c, 0x26368b872a2c6, 0x5a2826af12b9b}}, AffineCached{YplusX: radix51.FieldElement{0x2bc4408a5bb33, 0x78ebdda05442, 0x2ffb112354123, 0x375ee8df5862d, 0x2945ccf146e20}, YminusX: radix51.FieldElement{0x182c3a447d6ba, 0x22964e536eff2, 0x192821f540053, 0x2f9f19e788e5c, 0x154a7e73eb1b5}, T2d: radix51.FieldElement{0x3dbf1812a8285, 0xfa17ba3f9797, 0x6f69cb49c3820, 0x34d5a0db3858d, 0x43aabe696b3bb}}, AffineCached{YplusX: radix51.FieldElement{0x25cd0944ea3bf, 0x75673b81a4d63, 0x150b925d1c0d4, 0x13f38d9294114, 0x461bea69283c9}, YminusX: radix51.FieldElement{0x72c9aaa3221b1, 0x267774474f74d, 0x64b0e9b28085, 0x3f04ef53b27c9, 0x1d6edd5d2e531}, T2d: radix51.FieldElement{0x36dc801b8b3a2, 0xe0a7d4935e30, 0x1deb7cecc0d7d, 0x53a94e20dd2c, 0x7a9fbb1c6a0f9}}, AffineCached{YplusX: radix51.FieldElement{0x6678aa6a8632f, 0x5ea3788d8b365, 0x21bd6d6994279, 0x7ace75919e4e3, 0x34b9ed338add7}, YminusX: radix51.FieldElement{0x6217e039d8064, 0x6dea408337e6d, 0x57ac112628206, 0x647cb65e30473, 0x49c05a51fadc9}, T2d: radix51.FieldElement{0x4e8bf9045af1b, 0x514e33a45e0d6, 0x7533c5b8bfe0f, 0x583557b7e14c9, 0x73c172021b008}}, AffineCached{YplusX: radix51.FieldElement{0x700848a802ade, 0x1e04605c4e5f7, 0x5c0d01b9767fb, 0x7d7889f42388b, 0x4275aae2546d8}, YminusX: radix51.FieldElement{0x75b0249864348, 0x52ee11070262b, 0x237ae54fb5acd, 0x3bfd1d03aaab5, 0x18ab598029d5c}, T2d: radix51.FieldElement{0x32cc5fd6089e9, 0x426505c949b05, 0x46a18880c7ad2, 0x4a4221888ccda, 0x3dc65522b53df}}, AffineCached{YplusX: radix51.FieldElement{0xc222a2007f6d, 0x356b79bdb77ee, 0x41ee81efe12ce, 0x120a9bd07097d, 0x234fd7eec346f}, YminusX: radix51.FieldElement{0x7013b327fbf93, 0x1336eeded6a0d, 0x2b565a2bbf3af, 0x253ce89591955, 0x267882d17602}, T2d: radix51.FieldElement{0xa119732ea378, 0x63bf1ba8e2a6c, 0x69f94cc90df9a, 0x431d1779bfc48, 0x497ba6fdaa097}}, AffineCached{YplusX: radix51.FieldElement{0x6cc0313cfeaa0, 0x1a313848da499, 0x7cb534219230a, 0x39596dedefd60, 0x61e22917f12de}, YminusX: radix51.FieldElement{0x3cd86468ccf0b, 0x48553221ac081, 0x6c9464b4e0a6e, 0x75fba84180403, 0x43b5cd4218d05}, T2d: radix51.FieldElement{0x2762f9bd0b516, 0x1c6e7fbddcbb3, 0x75909c3ace2bd, 0x42101972d3ec9, 0x511d61210ae4d}}, AffineCached{YplusX: radix51.FieldElement{0x676ef950e9d81, 0x1b81ae089f258, 0x63c4922951883, 0x2f1d54d9b3237, 0x6d325924ddb85}, YminusX: radix51.FieldElement{0x386484420de87, 0x2d6b25db68102, 0x650b4962873c0, 0x4081cfd271394, 0x71a7fe6fe2482}, T2d: radix51.FieldElement{0x182b8a5c8c854, 0x73fcbe5406d8e, 0x5de3430cff451, 0x554b967ac8c41, 0x4746c4b6559ee}}, AffineCached{YplusX: radix51.FieldElement{0x77b3c6dc69a2b, 0x4edf13ec2fa6e, 0x4e85ad77beac8, 0x7dba2b28e7bda, 0x5c9a51de34fe9}, YminusX: radix51.FieldElement{0x546c864741147, 0x3a1df99092690, 0x1ca8cc9f4d6bb, 0x36b7fc9cd3b03, 0x219663497db5e}, T2d: radix51.FieldElement{0xf1cf79f10e67, 0x43ccb0a2b7ea2, 0x5089dfff776a, 0x1dd84e1d38b88, 0x4804503c60822}}, AffineCached{YplusX: radix51.FieldElement{0x49ed02ca37fc7, 0x474c2b5957884, 0x5b8388e816683, 0x4b6c454b76be4, 0x553398a516506}, YminusX: radix51.FieldElement{0x21d23a36d175, 0x4fd3373c6476d, 0x20e291eeed02a, 0x62f2ecf2e7210, 0x771e098858de4}, T2d: radix51.FieldElement{0x2f5d278451edf, 0x730b133997342, 0x6965420eb6975, 0x308a3bfa516cf, 0x5a5ed1d68ff5a}}, AffineCached{YplusX: radix51.FieldElement{0x5122afe150e83, 0x4afc966bb0232, 0x1c478833c8268, 0x17839c3fc148f, 0x44acb897d8bf9}, YminusX: radix51.FieldElement{0x5e0c558527359, 0x3395b73afd75c, 0x72afa4e4b970, 0x62214329e0f6d, 0x19b60135fefd}, T2d: radix51.FieldElement{0x68145e134b83, 0x1e4860982c3cc, 0x68fb5f13d799, 0x7c9283744547e, 0x150c49fde6ad2}}, AffineCached{YplusX: radix51.FieldElement{0x3f29509471138, 0x729eeb4ca31cf, 0x69c22b575bfbc, 0x4910857bce212, 0x6b2b5a075bb99}, YminusX: radix51.FieldElement{0x1863c9cdca868, 0x3770e295a1709, 0xd85a3720fd13, 0x5e0ff1f71ab06, 0x78a6d7791e05f}, T2d: radix51.FieldElement{0x7704b47a0b976, 0x2ae82e91aab17, 0x50bd6429806cd, 0x68055158fd8ea, 0x725c7ffc4ad55}}, AffineCached{YplusX: radix51.FieldElement{0x26715d1cf99b2, 0x2205441a69c88, 0x448427dcd4b54, 0x1d191e88abdc5, 0x794cc9277cb1f}, YminusX: radix51.FieldElement{0x2bf71cd098c0, 0x49dabcc6cd230, 0x40a6533f905b2, 0x573efac2eb8a4, 0x4cd54625f855f}, T2d: radix51.FieldElement{0x6c426c2ac5053, 0x5a65ece4b095e, 0xc44086f26bb6, 0x7429568197885, 0x7008357b6fcc8}}, AffineCached{YplusX: radix51.FieldElement{0x672738773f01, 0x752bf799f6171, 0x6b4a6dae33323, 0x7b54696ead1dc, 0x6ef7e9851ad0}, YminusX: radix51.FieldElement{0x39fbb82584a34, 0x47a568f257a03, 0x14d88091ead91, 0x2145b18b1ce24, 0x13a92a3669d6d}, T2d: radix51.FieldElement{0x3771cc0577de5, 0x3ca06bb8b9952, 0xb81c5d50390, 0x43512340780ec, 0x3c296ddf8a2af}}, AffineCached{YplusX: radix51.FieldElement{0x515f9d914a713, 0x73191ff2255d5, 0x54f5cc2a4bdef, 0x3dd57fc118bcf, 0x7a99d393490c7}, YminusX: radix51.FieldElement{0x34d2ebb1f2541, 0xe815b723ff9d, 0x286b416e25443, 0xbdfe38d1bee8, 0xa892c7007477}, T2d: radix51.FieldElement{0x2ed2436bda3e8, 0x2afd00f291ea, 0xbe7381dea321, 0x3e952d4b2b193, 0x286762d28302f}}, AffineCached{YplusX: radix51.FieldElement{0x36093ce35b25, 0x3b64d7552e9cf, 0x71ee0fe0b8460, 0x69d0660c969e5, 0x32f1da046a9d9}, YminusX: radix51.FieldElement{0x58e2bce2ef5bd, 0x68ce8f78c6f8a, 0x6ee26e39261b2, 0x33d0aa50bcf9d, 0x7686f2a3d6f17}, T2d: radix51.FieldElement{0x512a66d597c6a, 0x609a70a57551, 0x26c08a3c464c, 0x4531fc8ee39e1, 0x561305f8a9ad2}}, AffineCached{YplusX: radix51.FieldElement{0x4978dec92aed1, 0x69adae7ca201, 0x11ee923290f55, 0x69641898d916c, 0xaaec53e35d4}, YminusX: radix51.FieldElement{0x2cc28e7b0c0d5, 0x77b60eb8a6ce4, 0x4042985c277a6, 0x636657b46d3eb, 0x30a1aef2c57c}, T2d: radix51.FieldElement{0x1f773003ad2aa, 0x5642cc10f76, 0x3b48f82cfca6, 0x2403c10ee4329, 0x20be9c1c24065}}, AffineCached{YplusX: radix51.FieldElement{0x387d8249673a6, 0x5bea8dc927c2a, 0x5bd8ed5650ef0, 0xef0e3fcd40e1, 0x750ab3361f0ac}, YminusX: radix51.FieldElement{0xe44ae2025e60, 0x5f97b9727041c, 0x5683472c0ecec, 0x188882eb1ce7c, 0x69764c545067e}, T2d: radix51.FieldElement{0x23283a2f81037, 0x477aff97e23d1, 0xb8958dbcbb68, 0x205b97e8add6, 0x54f96b3fb7075}}, AffineCached{YplusX: radix51.FieldElement{0x5f20429669279, 0x8fafae4941f5, 0x15d83c4eb7688, 0x1cf379eca4146, 0x3d7fe9c52bb75}, YminusX: radix51.FieldElement{0x5afc616b11ecd, 0x39f4aec8f22ef, 0x3b39e1625d92e, 0x5f85bd4508873, 0x78e6839fbe85d}, T2d: radix51.FieldElement{0x32df737b8856b, 0x608342f14e06, 0x3967889d74175, 0x1211907fba550, 0x70f268f350088}}, AffineCached{YplusX: radix51.FieldElement{0x64583b1805f47, 0x22c1baf832cd0, 0x132c01bd4d717, 0x4ecf4c3a75b8f, 0x7c0d345cfad88}, YminusX: radix51.FieldElement{0x4112070dcf355, 0x7dcff9c22e464, 0x54ada60e03325, 0x25cd98eef769a, 0x404e56c039b8c}, T2d: radix51.FieldElement{0x71f4b8c78338a, 0x62cfc16bc2b23, 0x17cf51280d9aa, 0x3bbae5e20a95a, 0x20d754762aaec}}, AffineCached{YplusX: radix51.FieldElement{0x7c36fc73bb758, 0x4a6c797734bd1, 0xef248ab3950e, 0x63154c9a53ec8, 0x2b8f1e46f3cee}, YminusX: radix51.FieldElement{0x4feb135b9f543, 0x63bd192ad93ae, 0x44e2ea612cdf7, 0x670f4991583ab, 0x38b8ada8790b4}, T2d: radix51.FieldElement{0x4a9cdf51f95d, 0x5d963fbd596b8, 0x22d9b68ace54a, 0x4a98e8836c599, 0x49aeb32ceba1}}, AffineCached{YplusX: radix51.FieldElement{0x7d0b75fc7931, 0x16f4ce4ba754a, 0x5ace4c03fbe49, 0x27e0ec12a159c, 0x795ee17530f67}, YminusX: radix51.FieldElement{0x67d3c63dcfe7e, 0x112f0adc81aee, 0x53df04c827165, 0x2fe5b33b430f0, 0x51c665e0c8d62}, T2d: radix51.FieldElement{0x25b0a52ecbd81, 0x5dc0695fce4a9, 0x3b928c575047d, 0x23bf3512686e5, 0x6cd19bf49dc54}}, AffineCached{YplusX: radix51.FieldElement{0x6612165afc386, 0x1171aa36203ff, 0x2642ea820a8aa, 0x1f3bb7b313f10, 0x5e01b3a7429e4}, YminusX: radix51.FieldElement{0x7619052179ca3, 0xc16593f0afd0, 0x265c4795c7428, 0x31c40515d5442, 0x7520f3db40b2e}, T2d: radix51.FieldElement{0x50be3d39357a1, 0x3ab33d294a7b6, 0x4c479ba59edb3, 0x4c30d184d326f, 0x71092c9ccef3c}}, AffineCached{YplusX: radix51.FieldElement{0x3d8ac74051dcf, 0x10ab6f543d0ad, 0x5d0f3ac0fda90, 0x5ef1d2573e5e4, 0x4173a5bb7137a}, YminusX: radix51.FieldElement{0x523f0364918c, 0x687f56d638a7b, 0x20796928ad013, 0x5d38405a54f33, 0xea15b03d0257}, T2d: radix51.FieldElement{0x56e31f0f9218a, 0x5635f88e102f8, 0x2cbc5d969a5b8, 0x533fbc98b347a, 0x5fc565614a4e3}}, AffineCached{YplusX: radix51.FieldElement{0x2e1e67790988e, 0x1e38b9ae44912, 0x648fbb4075654, 0x28df1d840cd72, 0x3214c7409d466}, YminusX: radix51.FieldElement{0x6570dc46d7ae5, 0x18a9f1b91e26d, 0x436b6183f42ab, 0x550acaa4f8198, 0x62711c414c454}, T2d: radix51.FieldElement{0x1827406651770, 0x4d144f286c265, 0x17488f0ee9281, 0x19e6cdb5c760c, 0x5bea94073ecb8}}, AffineCached{YplusX: radix51.FieldElement{0xce63f343d2f8, 0x1e0a87d1e368e, 0x45edbc019eea, 0x6979aed28d0d1, 0x4ad0785944f1b}, YminusX: radix51.FieldElement{0x5bf0912c89be4, 0x62fadcaf38c83, 0x25ec196b3ce2c, 0x77655ff4f017b, 0x3aacd5c148f61}, T2d: radix51.FieldElement{0x63b34c3318301, 0xe0e62d04d0b1, 0x676a233726701, 0x29e9a042d9769, 0x3aff0cb1d9028}}, AffineCached{YplusX: radix51.FieldElement{0x6430bf4c53505, 0x264c3e4507244, 0x74c9f19a39270, 0x73f84f799bc47, 0x2ccf9f732bd99}, YminusX: radix51.FieldElement{0x5c7eb3a20405e, 0x5fdb5aad930f8, 0x4a757e63b8c47, 0x28e9492972456, 0x110e7e86f4cd2}, T2d: radix51.FieldElement{0xd89ed603f5e4, 0x51e1604018af8, 0xb8eedc4a2218, 0x51ba98b9384d0, 0x5c557e0b9693}}, AffineCached{YplusX: radix51.FieldElement{0x6bbb089c20eb0, 0x6df41fb0b9eee, 0x51087ed87e16f, 0x102db5c9fa731, 0x289fef0841861}, YminusX: radix51.FieldElement{0x1ce311fc97e6f, 0x6023f3fb5db1f, 0x7b49775e8fc98, 0x3ad70adbf5045, 0x6e154c178fe98}, T2d: radix51.FieldElement{0x16336fed69abf, 0x4f066b929f9ec, 0x4e9ff9e6c5b93, 0x18c89bc4bb2ba, 0x6afbf642a95ca}}, AffineCached{YplusX: radix51.FieldElement{0x55070f913a8cc, 0x765619eac2bbc, 0x3ab5225f47459, 0x76ced14ab5b48, 0x12c093cedb801}, YminusX: radix51.FieldElement{0xde0c62f5d2c1, 0x49601cf734fb5, 0x6b5c38263f0f6, 0x4623ef5b56d06, 0xdb4b851b9503}, T2d: radix51.FieldElement{0x47f9308b8190f, 0x414235c621f82, 0x31f5ff41a5a76, 0x6736773aab96d, 0x33aa8799c6635}}, AffineCached{YplusX: radix51.FieldElement{0xf588fc156cb1, 0x363414da4f069, 0x7296ad9b68aea, 0x4d3711316ae43, 0x212cd0c1c8d58}, YminusX: radix51.FieldElement{0x7f51ebd085cf2, 0x12cfa67e3f5e1, 0x1800cf1e3d46a, 0x54337615ff0a8, 0x233c6f29e8e21}, T2d: radix51.FieldElement{0x4d5107f18c781, 0x64a4fd3a51a5e, 0x4f4cd0448bb37, 0x671d38543151e, 0x1db7778911914}}, AffineCached{YplusX: radix51.FieldElement{0x14769dd701ab6, 0x28339f1b4b667, 0x4ab214b8ae37b, 0x25f0aefa0b0fe, 0x7ae2ca8a017d2}, YminusX: radix51.FieldElement{0x352397c6bc26f, 0x18a7aa0227bbe, 0x5e68cc1ea5f8b, 0x6fe3e3a7a1d5f, 0x31ad97ad26e2a}, T2d: radix51.FieldElement{0x17ed0920b962, 0x187e33b53b6fd, 0x55829907a1463, 0x641f248e0a792, 0x1ed1fc53a6622}}, AffineCached{YplusX: radix51.FieldElement{0x642a61c092d2d, 0x31937e711d17f, 0x4dc4bedcd4122, 0x2569f0c8b3ddf, 0x503d664a57aa2}, YminusX: radix51.FieldElement{0x1e98e4d89f26e, 0x510ae16fcfe97, 0x2171172ce0b7c, 0x55191edbf3682, 0x5b12b36f28bc0}, T2d: radix51.FieldElement{0x3395b90a91537, 0x6f9e6fcbe5943, 0x23a2feae6ea0f, 0x4718c95011f06, 0x36906685e9a1f}}, AffineCached{YplusX: radix51.FieldElement{0x4be3c4fd8781d, 0x242716afc8a89, 0x16cf4e4bf3c77, 0x1d2f593f7325f, 0x355dccf04805c}, YminusX: radix51.FieldElement{0x10dd8b8699e48, 0x7463aeb8f8d63, 0x760856e91c033, 0xcf2b008ee055, 0x5b1112708474b}, T2d: radix51.FieldElement{0x5984dcb3c75db, 0x4eafecacff977, 0x16606587ed97b, 0x7b2d89c5ac45b, 0x584587b225ae4}}, AffineCached{YplusX: radix51.FieldElement{0x5c10f66a67ed6, 0x5997232f8890a, 0x2c8862e13ad85, 0x62a45a7ffe9c0, 0x5e27ba4b982a}, YminusX: radix51.FieldElement{0x3a363f12f57a6, 0x36677857dc672, 0x6016edd50d745, 0x777eda40c0454, 0x3d8918fb87d11}, T2d: radix51.FieldElement{0x6a67d1e5a864d, 0x61bc54210c7e0, 0x5a0ab3f96bab6, 0x2ed35b0884775, 0x7f8f3424d64a5}}, AffineCached{YplusX: radix51.FieldElement{0x24807b24886af, 0x3d8885fbc4f63, 0x115953e5523b4, 0x132d7a918d23d, 0x7e755cba0310f}, YminusX: radix51.FieldElement{0x6293624794ed1, 0xed1e1ed161da, 0x8ef30fb86fc3, 0x362557eff0b67, 0xcaa7059c3235}, T2d: radix51.FieldElement{0x44f52761a3023, 0x104d2decd135f, 0x791656699386a, 0x11871237a067e, 0x4536c2aee70b3}}, AffineCached{YplusX: radix51.FieldElement{0x3eff321ccb9c3, 0x68ca42af7119c, 0x58c5a2e68e2fd, 0x3d9ee302ff687, 0x6a15d0f5ca449}, YminusX: radix51.FieldElement{0x1a302599db7fa, 0x6fe05f844dc03, 0x1c40635bad39c, 0x238ff0dfc297f, 0x7bbdf8041ba47}, T2d: radix51.FieldElement{0x5e1f109bfa8d5, 0x73c44389e11c1, 0x25e21637093ab, 0x5bd7d979ccd1b, 0x55c206d4035cd}}, AffineCached{YplusX: radix51.FieldElement{0x7faad90de7625, 0x3c286391c6144, 0x529672e089f46, 0x61287ccedae10, 0x5cd6b3922ee71}, YminusX: radix51.FieldElement{0x38159b8443d37, 0x55ad9ec9f2e2a, 0x47a7bf00acf6d, 0x75c2cce0a6006, 0x278fc8bcd74e9}, T2d: radix51.FieldElement{0x4a994d633ebc7, 0x5cf46f4f7de07, 0x33450af844449, 0x21429fa184f70, 0x468615291ab88}}, AffineCached{YplusX: radix51.FieldElement{0x3851d54ceb6f, 0x559bfad6ce588, 0x389e4afb488a7, 0x242fa5690a98c, 0x5523e2f353889}, YminusX: radix51.FieldElement{0x1099c54a5efd2, 0x41e0af3f2ee34, 0x753ef3fd7141a, 0x6e9ee0c59c789, 0x636db66a5894e}, T2d: radix51.FieldElement{0x2536e7bd0d4de, 0x56cb47e3c535f, 0x72130d43d8496, 0x7cc447ad13e59, 0x5288cf65559b0}}, AffineCached{YplusX: radix51.FieldElement{0x2b629f0d9881c, 0x27caae1ce21f2, 0x12eebeff2c7ec, 0xe92ff727c4a4, 0x12c70c85f4524}, YminusX: radix51.FieldElement{0x5c8c50a97289b, 0x75d502547f652, 0x5da24a563faae, 0x30a36eb796307, 0x63f01b555a964}, T2d: radix51.FieldElement{0x5bda5e538767f, 0xfa612c198d48, 0x354cd4580a64c, 0x4aa9e49cfb4ea, 0x437165416ab62}}, AffineCached{YplusX: radix51.FieldElement{0x5b1fbddfdad86, 0x75c96cef1bc3a, 0x603747eb606fe, 0xdbb5bc0c8ccc, 0x46fe985f1b972}, YminusX: radix51.FieldElement{0xa2836e64b9a, 0x21e92a74e2c26, 0x7cd91d540da93, 0x11e423291a7a3, 0x3ea46dc72c2dd}, T2d: radix51.FieldElement{0x5018588e2dfa7, 0x3fa0ebdd53fe, 0x271d3959ce7d0, 0x4a735072f4bec, 0x88b0ca7df432}}, AffineCached{YplusX: radix51.FieldElement{0x70e54fefe6cc0, 0x2751ca3b2820c, 0x4d68f7c3aee75, 0x449fd4f8711fa, 0x3c755700af5ee}, YminusX: radix51.FieldElement{0x445337c54aa9d, 0x7cfc86df9a4c8, 0x4466d61db423a, 0x1bcf6c7d0eb4a, 0x7d5b0546110e1}, T2d: radix51.FieldElement{0x73a96d7c70596, 0x7615f603e6f13, 0x87035eabe3f9, 0x556b20b23346a, 0x1ae5c564b3a77}}, AffineCached{YplusX: radix51.FieldElement{0x1ad4c0302594b, 0x28f8d4b709b41, 0x2178a904fef9b, 0x331a28073e004, 0x201a641198d92}, YminusX: radix51.FieldElement{0xe6863e708d5b, 0x9914b654bfb1, 0x1d176412796b7, 0x3c307983e740f, 0x5d9cf1e818af1}, T2d: radix51.FieldElement{0x21d3be2a1592b, 0x54c571883eb7b, 0x109312caf6eaa, 0x5932abca49e6e, 0x3aa0a0c361fe0}}, AffineCached{YplusX: radix51.FieldElement{0x45fe508dff693, 0x56cc1f071b283, 0x1de95131f404a, 0x1a0239374eeae, 0x3e6190f708b20}, YminusX: radix51.FieldElement{0x46e21e149ef2e, 0x4a00ce2d20cf, 0x1e2ccc2338304, 0x94d8553aae4f, 0x6ee309f230d1a}, T2d: radix51.FieldElement{0xae32ac67b877, 0x1ea8fd8412729, 0x3a126b5e8888a, 0x3a5b0ba127bd8, 0x64cde98364f1d}}, AffineCached{YplusX: radix51.FieldElement{0x6b982b66c4ffa, 0x218c3e0b9085f, 0x654ec3ee2d06c, 0x396913cabc3, 0x19767cc144203}, YminusX: radix51.FieldElement{0x7d6e4071f6450, 0x1f7c3ea3ee4e1, 0xa53ecdf4e3da, 0x418c2797ed200, 0x2c41a80e5b453}, T2d: radix51.FieldElement{0x60fe08e9dc54b, 0x6b2f1c309a0b7, 0x3293b11cbbbbc, 0x1f4578658a7ed, 0x393bc7b77c81c}}, AffineCached{YplusX: radix51.FieldElement{0x367a868cd8c15, 0x74719add93627, 0x4174ad15a144f, 0x34b3df65cfb24, 0x6ebb5599ac3d3}, YminusX: radix51.FieldElement{0x38645b73f4755, 0x1b10773615d37, 0x70305ea7d72d4, 0x731fbdc8a9de2, 0x7c0cebbd0ca4e}, T2d: radix51.FieldElement{0x4c5da306059bd, 0x4acefccbf4853, 0x6b25a6c99b7af, 0x6461833026867, 0x7cead1176a994}}, AffineCached{YplusX: radix51.FieldElement{0x31e08c64de622, 0x7af71922a0c43, 0x6c048211cacec, 0x56e6e9b5b0e13, 0x7b816374fe4d0}, YminusX: radix51.FieldElement{0x64cdb68564783, 0x3acd825866df, 0x4bb8f4c4cca1d, 0x2a8bfe5c9f091, 0x32e73d7c414d7}, T2d: radix51.FieldElement{0x71bc104113fcc, 0x1f1194e6b0a52, 0x17e905170f1f4, 0xb1c793ce3aeb, 0x6f56ae3ce96f0}}, AffineCached{YplusX: radix51.FieldElement{0x2a3e186f6b4b9, 0x41e64af26a8ef, 0x134dafe05997e, 0x74a2b9edc733, 0x2bcbc96fc92ab}, YminusX: radix51.FieldElement{0x96ed8c1e9273, 0x68c2dacbaba7, 0x3cbdc9b7e4dad, 0x68bcdc69bd16a, 0x6ff27a9feafb3}, T2d: radix51.FieldElement{0x1f73e611f6329, 0xd51039c82d81, 0x1b8b0d7c0cec5, 0x466a870023ad2, 0x72b5a5b6de284}}, AffineCached{YplusX: radix51.FieldElement{0x12c4628a337c3, 0x46c67f460e78e, 0x490e5de68725e, 0x68435d2018c42, 0x3485a7aa6fde7}, YminusX: radix51.FieldElement{0x69774ed68e720, 0x3297de2957e26, 0x6450077e37426, 0xb3fe28b59cae, 0x61aa1160d97b7}, T2d: radix51.FieldElement{0x48a7b7f55128e, 0x6bab0c5b2e4a6, 0x3822130dd2f2d, 0xa159b9f678b4, 0x2c6ce0503ee8d}}, AffineCached{YplusX: radix51.FieldElement{0x717e676469b1a, 0x43c043c63d129, 0x44a290cd033b3, 0x1d3877054dc01, 0xf8c2b5378339}, YminusX: radix51.FieldElement{0x2dfb19c632889, 0x38525489e51b0, 0x3da48697a5b33, 0x3d4f27772b64d, 0xe77ad1d92649}, T2d: radix51.FieldElement{0x2301df2db5c75, 0x21501a33bc5e3, 0x276b53f750382, 0x6fabc7001775c, 0x4cc1e54c7258d}}, AffineCached{YplusX: radix51.FieldElement{0x3e1d86b3ae19c, 0x28f3017a71713, 0xd04fe40c7a9e, 0x73bc322e1cfff, 0x7294f2237a32d}, YminusX: radix51.FieldElement{0x4c0667543638e, 0x70c89c91f7e7f, 0x2a6ed9bd0987d, 0x1727ae4d753a0, 0x62ef3fdce7514}, T2d: radix51.FieldElement{0x8017f77d3efd, 0x3c70d3e486dcb, 0x409977a7b4776, 0x1525ed4e71ba7, 0x1928c87d15666}}, AffineCached{YplusX: radix51.FieldElement{0x47d566087229, 0x156b2eb18c947, 0x738a46cb6a68b, 0x54a2baad4303a, 0x4ae0ec1d4499f}, YminusX: radix51.FieldElement{0x4955ab57e2130, 0x7b2c89ebea361, 0x2f4b265bfadfe, 0x31821023a7684, 0x77db41774458f}, T2d: radix51.FieldElement{0x6cb9ba2be7da7, 0x3019c0fbab07a, 0x742ff1219ac76, 0x387575fd24bc9, 0x17f1b3461da31}}, AffineCached{YplusX: radix51.FieldElement{0x16b3d036c2886, 0x1dc7c9cf34134, 0x105ec02eb1d75, 0x126d5e3ac73ca, 0x78a82c43f443d}, YminusX: radix51.FieldElement{0x4199b3403ce52, 0x34f6ce21cb1c9, 0x5da9cd4b28d84, 0x31368bb16bda2, 0x3d9b99a13ada9}, T2d: radix51.FieldElement{0x38112702675c4, 0x5688d28e9c0ad, 0x712b1ffbf44e7, 0x1c8229cd3ad7b, 0xb49208bd81bb}}, AffineCached{YplusX: radix51.FieldElement{0x550fb0a0d0782, 0x62dd31ddac07f, 0x4026023ab23b5, 0x22460b1c9cc37, 0x3e40a64da2d51}, YminusX: radix51.FieldElement{0x2dcb32d287241, 0x6b892b09826b7, 0x5a36039ecf45d, 0x290c3d6097e79, 0x157ee7b2e1f28}, T2d: radix51.FieldElement{0x5a52e9dca709f, 0x378e7ff97b2fe, 0x4b8fe54948b42, 0x75a0fadd77b78, 0x5a277115c55fb}}, AffineCached{YplusX: radix51.FieldElement{0xd921e5854c55, 0x70dfbc6364f68, 0x48b9b89cf1ec, 0x6b9f1b1b72827, 0xf4e191892dd3}, YminusX: radix51.FieldElement{0x23015328300cc, 0x7fab0f4f85562, 0x1b6e3c321fb1d, 0x777279c16beac, 0x4689b02ab17df}, T2d: radix51.FieldElement{0x51c12ec4132ed, 0x31b2456b7b877, 0x5c21e5387d181, 0x313c37a49ca2f, 0x3b2432ebc9edd}}, AffineCached{YplusX: radix51.FieldElement{0x899781c7d8ef, 0x10de7318502e0, 0xdb18be90ad68, 0x60da1115b11c, 0x361fd1330328d}, YminusX: radix51.FieldElement{0x6ccc2b78c2e59, 0x706382f92b777, 0x70258f43764dc, 0x5dcc6ff9a04f6, 0x6c55c1f2ab2db}, T2d: radix51.FieldElement{0x30c8165159986, 0x22ef8a1e89a45, 0x3e81112e25ce4, 0x24358acb40b6a, 0x3cd845a927b2c}}, AffineCached{YplusX: radix51.FieldElement{0x506d72c1951df, 0x4bd1f05fea25e, 0x6e39d7efa8cd, 0x156aab5585124, 0x45f998ac7247f}, YminusX: radix51.FieldElement{0x715addf6fd3b0, 0x7cf1aebd6e3a2, 0x391b7101c8a9, 0x56887ab35ab69, 0x36121e8a0da91}, T2d: radix51.FieldElement{0x30728c55d3ecd, 0x188cd2a66f481, 0x151333b5b850d, 0x18dffa3616ab9, 0x23b086cf066d5}}, AffineCached{YplusX: radix51.FieldElement{0x66080b4bdd58f, 0x130c6974631ac, 0x4b2f0e6f5f290, 0x30aa27f229a80, 0x16c5fa19014f1}, YminusX: radix51.FieldElement{0x35118ea05195e, 0x46f82d20b86d, 0x34a3ccac75145, 0x53a7519c28496, 0x1ebb5388c6e8}, T2d: radix51.FieldElement{0x5416ee772f53b, 0xb9739d12a1e8, 0x2581c43263fe3, 0x2857fe94e1ab, 0x4864ef1818473}}, AffineCached{YplusX: radix51.FieldElement{0x5a83a0bd0b830, 0x37723868519a1, 0x54fbd2193bae, 0x12873379f4d82, 0x26c03aed7f6bc}, YminusX: radix51.FieldElement{0x7c33297639ab3, 0x5640d1a71df02, 0x588f03cd11f1e, 0x7b62e6025c41d, 0x2a7adc0c34dba}, T2d: radix51.FieldElement{0x67a2f581c7dce, 0x40905352db2c3, 0x62690f0ea7a25, 0x3aa486ca53ddc, 0x78b5169959e1d}}, AffineCached{YplusX: radix51.FieldElement{0x4c85a5769cc40, 0x74ae9ba657f2b, 0x61aa0db9bfa54, 0xda0ee5c50b2a, 0x457ec0224bcd2}, YminusX: radix51.FieldElement{0x18254df5d180d, 0xff9d3a8ca21f, 0x239c47dd41854, 0x38493ab951aa4, 0x2314bc90371e}, T2d: radix51.FieldElement{0xaefe8f26908a, 0x3bf6aa75a6f3d, 0x2133be85aeecc, 0x524ddc5bc9b75, 0x79572c534fcf0}}, AffineCached{YplusX: radix51.FieldElement{0x34300e0749597, 0x4720c80988687, 0x22326917cdc98, 0x50e0a49fb55cb, 0x7890c0b6e7f19}, YminusX: radix51.FieldElement{0x5b23ca35b2d6f, 0x7572598372473, 0x65ba812ec2836, 0x79f82199bc406, 0x70ddf8d98b60e}, T2d: radix51.FieldElement{0x140b7fdd75dc4, 0x30b5f02d37e92, 0x2d212168ecc0e, 0x5515ac7118f6, 0x45769691e89a7}}, AffineCached{YplusX: radix51.FieldElement{0x63ddc5ba643ad, 0x33d37236d6721, 0x19e76422173fb, 0x63c45d73a082b, 0x2ec0f706b05c7}, YminusX: radix51.FieldElement{0x3e305345b2ddb, 0x6bd805d736a9c, 0x55785f51ea730, 0x6c10111aef7ee, 0x10b74232f01c1}, T2d: radix51.FieldElement{0x21694608f59d8, 0x3f7c7a18f9f87, 0x13851c22537b8, 0x353c8285b3715, 0x5d6fa9d25a3f4}}, AffineCached{YplusX: radix51.FieldElement{0x45afeb2a3a6dd, 0xf3be01ccb585, 0x27e72b699b3b4, 0x38e032665fb0c, 0x574fa41887c9e}, YminusX: radix51.FieldElement{0x74185e46e6cbb, 0x25e447ca48db, 0x5f49918a9a730, 0x4bd3cbffafbfa, 0x645e704f775f6}, T2d: radix51.FieldElement{0x529dade891efa, 0x5a245dcfb1925, 0x53854443ce9cf, 0x499791aacc114, 0x7420e574dcaab}}, AffineCached{YplusX: radix51.FieldElement{0x66e3f94234b1c, 0x4d36843821f07, 0x711529721ed87, 0x3aa2a599d849, 0x2ba60fa9c3cdc}, YminusX: radix51.FieldElement{0x6a138a034513c, 0x5e8df3a73beec, 0x51b92983f9880, 0x1e994571c80c6, 0x44ef4632b581b}, T2d: radix51.FieldElement{0x6491c21d364c9, 0x58ca44944b47a, 0x1c725d1768ee, 0x1e7ab7a88ece0, 0x7054899c44b5f}}}} -) diff --git a/internal/edwards25519/tables.go b/internal/edwards25519/tables.go deleted file mode 100644 index a1f470d..0000000 --- a/internal/edwards25519/tables.go +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (c) 2019 Henry de Valence. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package edwards25519 - -import ( - "crypto/subtle" -) - -// A dynamic lookup table for variable-base, constant-time scalar muls. -type projLookupTable struct { - points [8]ProjCached -} - -// A precomputed lookup table for fixed-base, constant-time scalar muls. -type affineLookupTable struct { - points [8]AffineCached -} - -// A dynamic lookup table for variable-base, variable-time scalar muls. -type nafLookupTable5 struct { - points [8]ProjCached -} - -// A precomputed lookup table for fixed-base, variable-time scalar muls. -type nafLookupTable8 struct { - points [64]AffineCached -} - -// Constructors. - -// Builds a lookup table at runtime. Fast. -func (v *projLookupTable) FromP3(q *ProjP3) { - // Goal: v.points[i] = (i+1)*Q, i.e., Q, 2Q, ..., 8Q - // This allows lookup of -8Q, ..., -Q, 0, Q, ..., 8Q - v.points[0].FromP3(q) - tmpP3 := ProjP3{} - tmpP1xP1 := ProjP1xP1{} - for i := 0; i < 7; i++ { - // Compute (i+1)*Q as Q + i*Q and convert to a ProjCached - // This is needlessly complicated because the API has explicit - // recievers instead of creating stack objects and relying on RVO - v.points[i+1].FromP3(tmpP3.FromP1xP1(tmpP1xP1.Add(q, &v.points[i]))) - } -} - -// This is not optimised for speed; affine tables should be precomputed. -func (v *affineLookupTable) FromP3(q *ProjP3) { - // Goal: v.points[i] = (i+1)*Q, i.e., Q, 2Q, ..., 8Q - // This allows lookup of -8Q, ..., -Q, 0, Q, ..., 8Q - v.points[0].FromP3(q) - tmpP3 := ProjP3{} - tmpP1xP1 := ProjP1xP1{} - for i := 0; i < 7; i++ { - // Compute (i+1)*Q as Q + i*Q and convert to AffineCached - v.points[i+1].FromP3(tmpP3.FromP1xP1(tmpP1xP1.AddAffine(q, &v.points[i]))) - } -} - -// Builds a lookup table at runtime. Fast. -func (v *nafLookupTable5) FromP3(q *ProjP3) { - // Goal: v.points[i] = (2*i+1)*Q, i.e., Q, 3Q, 5Q, ..., 15Q - // This allows lookup of -15Q, ..., -3Q, -Q, 0, Q, 3Q, ..., 15Q - v.points[0].FromP3(q) - q2 := ProjP3{} - q2.Add(q, q) - tmpP3 := ProjP3{} - tmpP1xP1 := ProjP1xP1{} - for i := 0; i < 7; i++ { - v.points[i+1].FromP3(tmpP3.FromP1xP1(tmpP1xP1.Add(&q2, &v.points[i]))) - } -} - -// This is not optimised for speed; affine tables should be precomputed. -func (v *nafLookupTable8) FromP3(q *ProjP3) { - v.points[0].FromP3(q) - q2 := ProjP3{} - q2.Add(q, q) - tmpP3 := ProjP3{} - tmpP1xP1 := ProjP1xP1{} - for i := 0; i < 63; i++ { - v.points[i+1].FromP3(tmpP3.FromP1xP1(tmpP1xP1.AddAffine(&q2, &v.points[i]))) - } -} - -// Selectors. - -// Set dest to x*Q, where -8 <= x <= 8, in constant time. -func (v *projLookupTable) SelectInto(dest *ProjCached, x int8) { - // Compute xabs = |x| - xmask := x >> 7 - xabs := uint8((x + xmask) ^ xmask) - - dest.Zero() - for j := 1; j <= 8; j++ { - // Set dest = j*Q if |x| = j - cond := subtle.ConstantTimeByteEq(xabs, uint8(j)) - dest.Select(&v.points[j-1], dest, cond) - } - // Now dest = |x|*Q, conditionally negate to get x*Q - dest.CondNeg(int(xmask & 1)) -} - -// Set dest to x*Q, where -8 <= x <= 8, in constant time. -func (v *affineLookupTable) SelectInto(dest *AffineCached, x int8) { - // Compute xabs = |x| - xmask := x >> 7 - xabs := uint8((x + xmask) ^ xmask) - - dest.Zero() - for j := 1; j <= 8; j++ { - // Set dest = j*Q if |x| = j - cond := subtle.ConstantTimeByteEq(xabs, uint8(j)) - dest.Select(&v.points[j-1], dest, cond) - } - // Now dest = |x|*Q, conditionally negate to get x*Q - dest.CondNeg(int(xmask & 1)) -} - -// Given odd x with 0 < x < 2^4, return x*Q (in variable time). -func (v *nafLookupTable5) SelectInto(dest *ProjCached, x int8) { - *dest = v.points[x/2] -} - -// Given odd x with 0 < x < 2^7, return x*Q (in variable time). -func (v *nafLookupTable8) SelectInto(dest *AffineCached, x int8) { - *dest = v.points[x/2] -} diff --git a/internal/edwards25519/tables_test.go b/internal/edwards25519/tables_test.go deleted file mode 100644 index 99a5508..0000000 --- a/internal/edwards25519/tables_test.go +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright 2019 Henry de Valence. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package edwards25519 - -import ( - "testing" -) - -func TestProjLookupTable(t *testing.T) { - var table projLookupTable - table.FromP3(&B) - - var tmp1, tmp2, tmp3 ProjCached - table.SelectInto(&tmp1, 6) - table.SelectInto(&tmp2, -2) - table.SelectInto(&tmp3, -4) - // Expect T1 + T2 + T3 = identity - - var accP1xP1 ProjP1xP1 - var accP3, check ProjP3 - accP3.Zero() - check.Zero() - - accP1xP1.Add(&accP3, &tmp1) - accP3.FromP1xP1(&accP1xP1) - accP1xP1.Add(&accP3, &tmp2) - accP3.FromP1xP1(&accP1xP1) - accP1xP1.Add(&accP3, &tmp3) - accP3.FromP1xP1(&accP1xP1) - - if accP3.Equal(&check) != 1 { - t.Errorf("Sanity check on ProjLookupTable.SelectInto failed! %x %x %x", tmp1, tmp2, tmp3) - } -} - -func TestAffineLookupTable(t *testing.T) { - var table affineLookupTable - table.FromP3(&B) - - var tmp1, tmp2, tmp3 AffineCached - table.SelectInto(&tmp1, 3) - table.SelectInto(&tmp2, -7) - table.SelectInto(&tmp3, 4) - // Expect T1 + T2 + T3 = identity - - var accP1xP1 ProjP1xP1 - var accP3, check ProjP3 - accP3.Zero() - check.Zero() - - accP1xP1.AddAffine(&accP3, &tmp1) - accP3.FromP1xP1(&accP1xP1) - accP1xP1.AddAffine(&accP3, &tmp2) - accP3.FromP1xP1(&accP1xP1) - accP1xP1.AddAffine(&accP3, &tmp3) - accP3.FromP1xP1(&accP1xP1) - - if accP3.Equal(&check) != 1 { - t.Errorf("Sanity check on ProjLookupTable.SelectInto failed! %x %x %x", tmp1, tmp2, tmp3) - } -} - -func TestNafLookupTable5(t *testing.T) { - var table nafLookupTable5 - table.FromP3(&B) - - var tmp1, tmp2, tmp3, tmp4 ProjCached - table.SelectInto(&tmp1, 9) - table.SelectInto(&tmp2, 11) - table.SelectInto(&tmp3, 7) - table.SelectInto(&tmp4, 13) - // Expect T1 + T2 = T3 + T4 - - var accP1xP1 ProjP1xP1 - var lhs, rhs ProjP3 - lhs.Zero() - rhs.Zero() - - accP1xP1.Add(&lhs, &tmp1) - lhs.FromP1xP1(&accP1xP1) - accP1xP1.Add(&lhs, &tmp2) - lhs.FromP1xP1(&accP1xP1) - - accP1xP1.Add(&rhs, &tmp3) - rhs.FromP1xP1(&accP1xP1) - accP1xP1.Add(&rhs, &tmp4) - rhs.FromP1xP1(&accP1xP1) - - if lhs.Equal(&rhs) != 1 { - t.Errorf("Sanity check on nafLookupTable5 failed") - } -} - -func TestNafLookupTable8(t *testing.T) { - var table nafLookupTable8 - table.FromP3(&B) - - var tmp1, tmp2, tmp3, tmp4 AffineCached - table.SelectInto(&tmp1, 49) - table.SelectInto(&tmp2, 11) - table.SelectInto(&tmp3, 35) - table.SelectInto(&tmp4, 25) - // Expect T1 + T2 = T3 + T4 - - var accP1xP1 ProjP1xP1 - var lhs, rhs ProjP3 - lhs.Zero() - rhs.Zero() - - accP1xP1.AddAffine(&lhs, &tmp1) - lhs.FromP1xP1(&accP1xP1) - accP1xP1.AddAffine(&lhs, &tmp2) - lhs.FromP1xP1(&accP1xP1) - - accP1xP1.AddAffine(&rhs, &tmp3) - rhs.FromP1xP1(&accP1xP1) - accP1xP1.AddAffine(&rhs, &tmp4) - rhs.FromP1xP1(&accP1xP1) - - if lhs.Equal(&rhs) != 1 { - t.Errorf("Sanity check on nafLookupTable8 failed") - } -} diff --git a/internal/radix51/alias_test.go b/internal/radix51/alias_test.go deleted file mode 100644 index 907089e..0000000 --- a/internal/radix51/alias_test.go +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright (c) 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package radix51 - -import ( - "testing" - "testing/quick" -) - -func checkAliasingOneArg(f func(v, x *FieldElement) *FieldElement) func(v, x FieldElement) bool { - return func(v, x FieldElement) bool { - x1, v1 := x, x - - // Calculate a reference f(x) without aliasing. - if out := f(&v, &x); out != &v && isInBounds(out) { - return false - } - - // Test aliasing the argument and the receiver. - if out := f(&v1, &v1); out != &v1 || v1 != v { - return false - } - - // Ensure the arguments was not modified. - return x == x1 - } -} - -func checkAliasingTwoArgs(f func(v, x, y *FieldElement) *FieldElement) func(v, x, y FieldElement) bool { - return func(v, x, y FieldElement) bool { - x1, y1, v1 := x, y, FieldElement{} - - // Calculate a reference f(x, y) without aliasing. - if out := f(&v, &x, &y); out != &v && isInBounds(out) { - return false - } - - // Test aliasing the first argument and the receiver. - v1 = x - if out := f(&v1, &v1, &y); out != &v1 || v1 != v { - return false - } - // Test aliasing the second argument and the receiver. - v1 = y - if out := f(&v1, &x, &v1); out != &v1 || v1 != v { - return false - } - - // Calculate a reference f(x, x) without aliasing. - if out := f(&v, &x, &x); out != &v { - return false - } - - // Test aliasing the first argument and the receiver. - v1 = x - if out := f(&v1, &v1, &x); out != &v1 || v1 != v { - return false - } - // Test aliasing the second argument and the receiver. - v1 = x - if out := f(&v1, &x, &v1); out != &v1 || v1 != v { - return false - } - // Test aliasing both arguments and the receiver. - v1 = x - if out := f(&v1, &v1, &v1); out != &v1 || v1 != v { - return false - } - - // Ensure the arguments were not modified. - return x == x1 && y == y1 - } -} - -func TestAliasing(t *testing.T) { - type target struct { - name string - oneArgF func(v, x *FieldElement) *FieldElement - twoArgsF func(v, x, y *FieldElement) *FieldElement - } - for _, tt := range []target{ - {name: "Abs", oneArgF: (*FieldElement).Abs}, - {name: "Invert", oneArgF: (*FieldElement).Invert}, - {name: "Neg", oneArgF: (*FieldElement).Neg}, - {name: "Set", oneArgF: (*FieldElement).Set}, - {name: "Square", oneArgF: (*FieldElement).Square}, - { - name: "CondNeg0", - oneArgF: func(v, x *FieldElement) *FieldElement { - return (*FieldElement).CondNeg(v, x, 0) - }, - }, - { - name: "CondNeg1", - oneArgF: func(v, x *FieldElement) *FieldElement { - return (*FieldElement).CondNeg(v, x, 1) - }, - }, - {name: "Mul", twoArgsF: (*FieldElement).Mul}, - {name: "Add", twoArgsF: (*FieldElement).Add}, - {name: "Sub", twoArgsF: (*FieldElement).Sub}, - { - name: "Select0", - twoArgsF: func(v, x, y *FieldElement) *FieldElement { - return (*FieldElement).Select(v, x, y, 0) - }, - }, - { - name: "Select1", - twoArgsF: func(v, x, y *FieldElement) *FieldElement { - return (*FieldElement).Select(v, x, y, 1) - }, - }, - } { - var err error - switch { - case tt.oneArgF != nil: - err = quick.Check(checkAliasingOneArg(tt.oneArgF), &quick.Config{MaxCountScale: 1 << 8}) - case tt.twoArgsF != nil: - err = quick.Check(checkAliasingTwoArgs(tt.twoArgsF), &quick.Config{MaxCountScale: 1 << 8}) - } - if err != nil { - t.Errorf("%v: %v", tt.name, err) - } - } -} diff --git a/internal/radix51/bench_test.go b/internal/radix51/bench_test.go deleted file mode 100644 index f5c05fc..0000000 --- a/internal/radix51/bench_test.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package radix51_test - -import ( - "testing" - - "github.com/gtank/ristretto255/internal/radix51" -) - -func BenchmarkAdd(b *testing.B) { - var x, y radix51.FieldElement - x.One() - y.Add(radix51.One, radix51.One) - b.ResetTimer() - for i := 0; i < b.N; i++ { - x.Add(&x, &y) - } -} - -func BenchmarkMul(b *testing.B) { - var x, y radix51.FieldElement - x.One() - y.Add(radix51.One, radix51.One) - b.ResetTimer() - for i := 0; i < b.N; i++ { - x.Mul(&x, &y) - } -} - -func BenchmarkMul32(b *testing.B) { - var x radix51.FieldElement - x.One() - b.ResetTimer() - for i := 0; i < b.N; i++ { - x.Mul32(&x, 0xaa42aa42) - } -} diff --git a/internal/radix51/fe.go b/internal/radix51/fe.go deleted file mode 100644 index 090fca6..0000000 --- a/internal/radix51/fe.go +++ /dev/null @@ -1,392 +0,0 @@ -// Copyright (c) 2017 George Tankersley. All rights reserved. -// Copyright (c) 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package radix51 implements GF(2^255-19) field arithmetic in radix 2^51 -// representation. This code is a port of the public domain amd64-51-30k version -// of ed25519 from SUPERCOP. -// -// The interface works similarly to math/big.Int, and all arguments and -// receivers are allowed to alias. -package radix51 - -import ( - "crypto/subtle" - "encoding/binary" - "math/big" - "math/bits" -) - -// FieldElement represents an element of the field GF(2^255-19). An element t -// represents the integer t[0] + t[1]*2^51 + t[2]*2^102 + t[3]*2^153 + -// t[4]*2^204. -// -// Between operations, all limbs are expected to be lower than 2^51, except the -// first one, which can be up to 2^255 + 2^13 * 19 due to carry propagation. -// -// The zero value is a valid zero element. -type FieldElement [5]uint64 - -const maskLow51Bits uint64 = (1 << 51) - 1 - -var ( - Zero = &FieldElement{0, 0, 0, 0, 0} - One = &FieldElement{1, 0, 0, 0, 0} - Two = &FieldElement{2, 0, 0, 0, 0} - MinusOne = new(FieldElement).Neg(One) -) - -// Zero sets v = 0 and returns v. -func (v *FieldElement) Zero() *FieldElement { - *v = *Zero - return v -} - -// One sets v = 1 and returns v. -func (v *FieldElement) One() *FieldElement { - *v = *One - return v -} - -// carryPropagate brings the limbs below 52, 51, 51, 51, 51 bits. It is split in -// two because of the inliner heuristics. The two functions MUST be called one -// after the other. -func (v *FieldElement) carryPropagate1() *FieldElement { - v[1] += v[0] >> 51 - v[0] &= maskLow51Bits - v[2] += v[1] >> 51 - v[1] &= maskLow51Bits - v[3] += v[2] >> 51 - v[2] &= maskLow51Bits - return v -} -func (v *FieldElement) carryPropagate2() *FieldElement { - v[4] += v[3] >> 51 - v[3] &= maskLow51Bits - v[0] += (v[4] >> 51) * 19 - v[4] &= maskLow51Bits - return v -} - -// reduce reduces v modulo 2^255 - 19 and returns it. -func (v *FieldElement) reduce() *FieldElement { - v.carryPropagate1().carryPropagate2() - - // After the light reduction we now have a field element representation - // v < 2^255 + 2^13 * 19, but need v < 2^255 - 19. - - // If v >= 2^255 - 19, then v + 19 >= 2^255, which would overflow 2^255 - 1, - // generating a carry. That is, c will be 0 if v < 2^255 - 19, and 1 otherwise. - c := (v[0] + 19) >> 51 - c = (v[1] + c) >> 51 - c = (v[2] + c) >> 51 - c = (v[3] + c) >> 51 - c = (v[4] + c) >> 51 - - // If v < 2^255 - 19 and c = 0, this will be a no-op. Otherwise, it's - // effectively applying the reduction identity to the carry. - v[0] += 19 * c - - v[1] += v[0] >> 51 - v[0] = v[0] & maskLow51Bits - v[2] += v[1] >> 51 - v[1] = v[1] & maskLow51Bits - v[3] += v[2] >> 51 - v[2] = v[2] & maskLow51Bits - v[4] += v[3] >> 51 - v[3] = v[3] & maskLow51Bits - // no additional carry - v[4] = v[4] & maskLow51Bits - - return v -} - -// Add sets v = a + b and returns v. -func (v *FieldElement) Add(a, b *FieldElement) *FieldElement { - v[0] = a[0] + b[0] - v[1] = a[1] + b[1] - v[2] = a[2] + b[2] - v[3] = a[3] + b[3] - v[4] = a[4] + b[4] - return v.carryPropagate1().carryPropagate2() -} - -// Sub sets v = a - b and returns v. -func (v *FieldElement) Sub(a, b *FieldElement) *FieldElement { - // We first add 2 * p, to guarantee the subtraction won't underflow, and - // then subtract b (which can be up to 2^255 + 2^13 * 19). - v[0] = (a[0] + 0xFFFFFFFFFFFDA) - b[0] - v[1] = (a[1] + 0xFFFFFFFFFFFFE) - b[1] - v[2] = (a[2] + 0xFFFFFFFFFFFFE) - b[2] - v[3] = (a[3] + 0xFFFFFFFFFFFFE) - b[3] - v[4] = (a[4] + 0xFFFFFFFFFFFFE) - b[4] - return v.carryPropagate1().carryPropagate2() -} - -// Neg sets v = -a and returns v. -func (v *FieldElement) Neg(a *FieldElement) *FieldElement { - return v.Sub(Zero, a) -} - -// Invert sets v = 1/z mod p and returns v. -func (v *FieldElement) Invert(z *FieldElement) *FieldElement { - // Inversion is implemented as exponentiation with exponent p − 2. It uses the - // same sequence of 255 squarings and 11 multiplications as [Curve25519]. - var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t FieldElement - - z2.Square(z) // 2 - t.Square(&z2) // 4 - t.Square(&t) // 8 - z9.Mul(&t, z) // 9 - z11.Mul(&z9, &z2) // 11 - t.Square(&z11) // 22 - z2_5_0.Mul(&t, &z9) // 2^5 - 2^0 = 31 - - t.Square(&z2_5_0) // 2^6 - 2^1 - for i := 0; i < 4; i++ { - t.Square(&t) // 2^10 - 2^5 - } - z2_10_0.Mul(&t, &z2_5_0) // 2^10 - 2^0 - - t.Square(&z2_10_0) // 2^11 - 2^1 - for i := 0; i < 9; i++ { - t.Square(&t) // 2^20 - 2^10 - } - z2_20_0.Mul(&t, &z2_10_0) // 2^20 - 2^0 - - t.Square(&z2_20_0) // 2^21 - 2^1 - for i := 0; i < 19; i++ { - t.Square(&t) // 2^40 - 2^20 - } - t.Mul(&t, &z2_20_0) // 2^40 - 2^0 - - t.Square(&t) // 2^41 - 2^1 - for i := 0; i < 9; i++ { - t.Square(&t) // 2^50 - 2^10 - } - z2_50_0.Mul(&t, &z2_10_0) // 2^50 - 2^0 - - t.Square(&z2_50_0) // 2^51 - 2^1 - for i := 0; i < 49; i++ { - t.Square(&t) // 2^100 - 2^50 - } - z2_100_0.Mul(&t, &z2_50_0) // 2^100 - 2^0 - - t.Square(&z2_100_0) // 2^101 - 2^1 - for i := 0; i < 99; i++ { - t.Square(&t) // 2^200 - 2^100 - } - t.Mul(&t, &z2_100_0) // 2^200 - 2^0 - - t.Square(&t) // 2^201 - 2^1 - for i := 0; i < 49; i++ { - t.Square(&t) // 2^250 - 2^50 - } - t.Mul(&t, &z2_50_0) // 2^250 - 2^0 - - t.Square(&t) // 2^251 - 2^1 - t.Square(&t) // 2^252 - 2^2 - t.Square(&t) // 2^253 - 2^3 - t.Square(&t) // 2^254 - 2^4 - t.Square(&t) // 2^255 - 2^5 - - return v.Mul(&t, &z11) // 2^255 - 21 -} - -// Set sets v = a and returns v. -func (v *FieldElement) Set(a *FieldElement) *FieldElement { - *v = *a - return v -} - -// FromBytes sets v to x, which must be a 32 bytes little-endian encoding. -// -// Consistently with RFC 7748, the most significant bit (the high bit of the -// last byte) is ignored, and non-canonical values (2^255-19 through 2^255-1) -// are accepted. -func (v *FieldElement) FromBytes(x []byte) *FieldElement { - if len(x) != 32 { - panic("ed25519: invalid field element input size") - } - - // Provide headroom for the slight binary.LittleEndian.Uint64 overread. (We - // read 64 bits at an offset of 200, but then take only 4+51 into account.) - var buf [33]byte - copy(buf[:], x) - - for i := range v { - bitsOffset := i * 51 - v[i] = binary.LittleEndian.Uint64(buf[bitsOffset/8:]) - v[i] >>= uint(bitsOffset % 8) - v[i] &= maskLow51Bits - } - - return v -} - -// Bytes appends a 32 bytes little-endian encoding of v to b. -func (v *FieldElement) Bytes(b []byte) []byte { - t := *v - t.reduce() - - res, out := sliceForAppend(b, 32) - for i := range out { - out[i] = 0 - } - - var buf [8]byte - for i := range t { - bitsOffset := i * 51 - binary.LittleEndian.PutUint64(buf[:], t[i]<= len(out) { - break - } - out[off] |= b - } - } - - return res -} - -// sliceForAppend extends the input slice by n bytes. head is the full extended -// slice, while tail is the appended part. If the original slice has sufficient -// capacity no allocation is performed. -func sliceForAppend(in []byte, n int) (head, tail []byte) { - if total := len(in) + n; cap(in) >= total { - head = in[:total] - } else { - head = make([]byte, total) - copy(head, in) - } - tail = head[len(in):] - return -} - -// FromBig sets v = n and returns v. The bit length of n must not exceed 256. -func (v *FieldElement) FromBig(n *big.Int) *FieldElement { - if n.BitLen() > 32*8 { - panic("ed25519: invalid field element input size") - } - - buf := make([]byte, 0, 32) - for _, word := range n.Bits() { - for i := 0; i < bits.UintSize; i += 8 { - if len(buf) >= cap(buf) { - break - } - buf = append(buf, byte(word)) - word >>= 8 - } - } - - return v.FromBytes(buf[:32]) -} - -// ToBig returns v as a big.Int. -func (v *FieldElement) ToBig() *big.Int { - buf := v.Bytes(nil) - - words := make([]big.Word, 32*8/bits.UintSize) - for n := range words { - for i := 0; i < bits.UintSize; i += 8 { - if len(buf) == 0 { - break - } - words[n] |= big.Word(buf[0]) << big.Word(i) - buf = buf[1:] - } - } - - return new(big.Int).SetBits(words) -} - -// Equal returns 1 if v and u are equal, and 0 otherwise. -func (v *FieldElement) Equal(u *FieldElement) int { - var sa, sv [32]byte - u.Bytes(sa[:0]) - v.Bytes(sv[:0]) - return subtle.ConstantTimeCompare(sa[:], sv[:]) -} - -const mask64Bits uint64 = (1 << 64) - 1 - -// Select sets v to a if cond == 1, and to b if cond == 0. -func (v *FieldElement) Select(a, b *FieldElement, cond int) *FieldElement { - m := uint64(cond) * mask64Bits - v[0] = (m & a[0]) | (^m & b[0]) - v[1] = (m & a[1]) | (^m & b[1]) - v[2] = (m & a[2]) | (^m & b[2]) - v[3] = (m & a[3]) | (^m & b[3]) - v[4] = (m & a[4]) | (^m & b[4]) - return v -} - -// CondSwap swaps a and b if cond == 1 or leaves them unchanged if cond == 0. -func CondSwap(a, b *FieldElement, cond int) { - m := uint64(cond) * mask64Bits - t := m & (a[0] ^ b[0]) - a[0] ^= t - b[0] ^= t - t = m & (a[1] ^ b[1]) - a[1] ^= t - b[1] ^= t - t = m & (a[2] ^ b[2]) - a[2] ^= t - b[2] ^= t - t = m & (a[3] ^ b[3]) - a[3] ^= t - b[3] ^= t - t = m & (a[4] ^ b[4]) - a[4] ^= t - b[4] ^= t -} - -// CondNeg sets v to -u if cond == 1, and to u if cond == 0. -func (v *FieldElement) CondNeg(u *FieldElement, cond int) *FieldElement { - tmp := new(FieldElement).Neg(u) - return v.Select(tmp, u, cond) -} - -// IsNegative returns 1 if v is negative, and 0 otherwise. -func (v *FieldElement) IsNegative() int { - var b [32]byte - v.Bytes(b[:0]) - return int(b[0] & 1) -} - -// Abs sets v to |u| and returns v. -func (v *FieldElement) Abs(u *FieldElement) *FieldElement { - return v.CondNeg(u, u.IsNegative()) -} - -// Mul sets v = x * y and returns v. -func (v *FieldElement) Mul(x, y *FieldElement) *FieldElement { - feMul(v, x, y) - return v -} - -// Square sets v = x * x and returns v. -func (v *FieldElement) Square(x *FieldElement) *FieldElement { - feSquare(v, x) - return v -} - -// Mul32 sets v = x * y and returns v. -func (v *FieldElement) Mul32(x *FieldElement, y uint32) *FieldElement { - x0lo, x0hi := mul51(x[0], y) - x1lo, x1hi := mul51(x[1], y) - x2lo, x2hi := mul51(x[2], y) - x3lo, x3hi := mul51(x[3], y) - x4lo, x4hi := mul51(x[4], y) - v[0] = x0lo + 19*x4hi // carried over per the reduction identity - v[1] = x1lo + x0hi - v[2] = x2lo + x1hi - v[3] = x3lo + x2hi - v[4] = x4lo + x3hi - // The hi portions are going to be only 32 bits, plus any previous excess, - // so we can skip the carry propagation. - return v -} diff --git a/internal/radix51/fe_amd64.go b/internal/radix51/fe_amd64.go deleted file mode 100644 index 8327caa..0000000 --- a/internal/radix51/fe_amd64.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) 2017 George Tankersley. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build amd64,!purego - -package radix51 - -//go:noescape -func feMul(out, a, b *FieldElement) - -//go:noescape -func feSquare(out, x *FieldElement) diff --git a/internal/radix51/fe_amd64.s b/internal/radix51/fe_amd64.s deleted file mode 100644 index dfc95e6..0000000 --- a/internal/radix51/fe_amd64.s +++ /dev/null @@ -1,348 +0,0 @@ -// Copyright (c) 2017 George Tankersley. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build amd64,!purego - -// func feMul(out, a, b *FieldElement) -TEXT ·feMul(SB),$0-24 - // Based on assembly generated by PeachPy. Equivalent to the Go in - // feMulGeneric, which was originally based on the amd64-51-30k - // assembly in SUPERCOP. - - MOVQ out+0(FP), DI - MOVQ a+8(FP), BX - MOVQ b+16(FP), CX - - // Calculate r0 - MOVQ 0(BX), AX // rax <-- x0 - MULQ 0(CX) // rdx, rax <-- x0*y0 - MOVQ AX, SI // r00 = rax - MOVQ DX, BP // r01 = rdx - - MOVQ 8(BX), DX // rdx <-- x1 - IMUL3Q $19, DX, AX // rax <-- x1*19 - MULQ 32(CX) // rdx, rax <-- x1_19*y4 - ADDQ AX, SI // r00 += rax - ADCQ DX, BP // r01 += rdx - - MOVQ 16(BX), DX // rdx <-- x2 - IMUL3Q $19, DX, AX // rax <-- x2*19 - MULQ 24(CX) // rdx, rax <-- x2_19*y3 - ADDQ AX, SI // r00 += rax - ADCQ DX, BP // r01 += rdx - - MOVQ 24(BX), DX // rdx <-- x3 - IMUL3Q $19, DX, AX // rax <-- x3*19 - MULQ 16(CX) // rdx, rax <-- x3_19 * y2 - ADDQ AX, SI // r00 += rax - ADCQ DX, BP // r01 += rdx - - MOVQ 32(BX), DX // rdx <-- x4 - IMUL3Q $19, DX, AX // rax <-- x4*19 - MULQ 8(CX) // rdx rax <-- x4_19*y1 - ADDQ AX, SI // r00 += rax - ADCQ DX, BP // r01 += rdx - - // Calculate r1 - MOVQ 0(BX), AX - MULQ 8(CX) - MOVQ AX, R8 // r10 - MOVQ DX, R9 // r11 - - MOVQ 8(BX), AX - MULQ 0(CX) - ADDQ AX, R8 - ADCQ DX, R9 - - MOVQ 16(BX), DX - IMUL3Q $19, DX, AX - MULQ 32(CX) - ADDQ AX, R8 - ADCQ DX, R9 - - MOVQ 24(BX), DX - IMUL3Q $19, DX, AX - MULQ 24(CX) - ADDQ AX, R8 - ADCQ DX, R9 - - MOVQ 32(BX), DX - IMUL3Q $19, DX, AX - MULQ 16(CX) - ADDQ AX, R8 - ADCQ DX, R9 - - // Calculate r2 - MOVQ 0(BX), AX - MULQ 16(CX) - MOVQ AX, R10 // r20 - MOVQ DX, R11 // r21 - - MOVQ 8(BX), AX - MULQ 8(CX) - ADDQ AX, R10 - ADCQ DX, R11 - - MOVQ 16(BX), AX - MULQ 0(CX) - ADDQ AX, R10 - ADCQ DX, R11 - - MOVQ 24(BX), DX - IMUL3Q $19, DX, AX - MULQ 32(CX) - ADDQ AX, R10 - ADCQ DX, R11 - - MOVQ 32(BX), DX - IMUL3Q $19, DX, AX - MULQ 24(CX) - ADDQ AX, R10 - ADCQ DX, R11 - - // Calculate r3 - MOVQ 0(BX), AX - MULQ 24(CX) - MOVQ AX, R12 // r30 - MOVQ DX, R13 // r31 - - MOVQ 8(BX), AX - MULQ 16(CX) - ADDQ AX, R12 - ADCQ DX, R13 - - MOVQ 16(BX), AX - MULQ 8(CX) - ADDQ AX, R12 - ADCQ DX, R13 - - MOVQ 24(BX), AX - MULQ 0(CX) - ADDQ AX, R12 - ADCQ DX, R13 - - MOVQ 32(BX), DX - IMUL3Q $19, DX, AX - MULQ 32(CX) - ADDQ AX, R12 - ADCQ DX, R13 - - // Calculate r4 - MOVQ 0(BX), AX - MULQ 32(CX) - MOVQ AX, R14 // r40 - MOVQ DX, R15 // r41 - - MOVQ 8(BX), AX - MULQ 24(CX) - ADDQ AX, R14 - ADCQ DX, R15 - - MOVQ 16(BX), AX - MULQ 16(CX) - ADDQ AX, R14 - ADCQ DX, R15 - - MOVQ 24(BX), AX - MULQ 8(CX) - ADDQ AX, R14 - ADCQ DX, R15 - - MOVQ 32(BX), AX - MULQ 0(CX) - ADDQ AX, R14 - ADCQ DX, R15 - - - MOVQ $2251799813685247, AX // (1<<51) - 1 - SHLQ $13, SI, BP // r01 = shld with r00 - ANDQ AX, SI // r00 &= mask51 - SHLQ $13, R8, R9 // r11 = shld with r10 - ANDQ AX, R8 // r10 &= mask51 - ADDQ BP, R8 // r10 += r01 - SHLQ $13, R10, R11 // r21 = shld with r20 - ANDQ AX, R10 // r20 &= mask51 - ADDQ R9, R10 // r20 += r11 - SHLQ $13, R12, R13 // r31 = shld with r30 - ANDQ AX, R12 // r30 &= mask51 - ADDQ R11, R12 // r30 += r21 - SHLQ $13, R14, R15 // r41 = shld with r40 - ANDQ AX, R14 // r40 &= mask51 - ADDQ R13, R14 // r40 += r31 - IMUL3Q $19, R15, R15 // r41 = r41*19 - ADDQ R15, SI // r00 += r41 - - MOVQ SI, DX // rdx <-- r00 - SHRQ $51, DX // rdx <-- r00 >> 51 - ADDQ DX, R8 // r10 += r00 >> 51 - MOVQ R8, DX // rdx <-- r10 - SHRQ $51, DX // rdx <-- r10 >> 51 - ANDQ AX, SI // r00 &= mask51 - ADDQ DX, R10 // r20 += r10 >> 51 - MOVQ R10, DX // rdx <-- r20 - SHRQ $51, DX // rdx <-- r20 >> 51 - ANDQ AX, R8 // r10 &= mask51 - ADDQ DX, R12 // r30 += r20 >> 51 - MOVQ R12, DX // rdx <-- r30 - SHRQ $51, DX // rdx <-- r30 >> 51 - ANDQ AX, R10 // r20 &= mask51 - ADDQ DX, R14 // r40 += r30 >> 51 - MOVQ R14, DX // rdx <-- r40 - SHRQ $51, DX // rdx <-- r40 >> 51 - ANDQ AX, R12 // r30 &= mask51 - IMUL3Q $19, DX, DX // rdx <-- (r40 >> 51) * 19 - ADDQ DX, SI // r00 += (r40 >> 51) *19 - ANDQ AX, R14 // r40 &= mask51 - - MOVQ SI, 0(DI) - MOVQ R8, 8(DI) - MOVQ R10, 16(DI) - MOVQ R12, 24(DI) - MOVQ R14, 32(DI) - RET - -// func feSquare(out, x *FieldElement) -TEXT ·feSquare(SB),4,$0-16 - MOVQ out+0(FP), DI - MOVQ x+8(FP), SI - - // r0 = x0*x0 + x1*38*x4 + x2*38*x3 - MOVQ 0(SI), AX - MULQ 0(SI) - MOVQ AX, CX // r00 - MOVQ DX, R8 // r01 - - MOVQ 8(SI), DX - IMUL3Q $38, DX, AX - MULQ 32(SI) - ADDQ AX, CX - ADCQ DX, R8 - - MOVQ 16(SI), DX - IMUL3Q $38, DX, AX - MULQ 24(SI) - ADDQ AX, CX - ADCQ DX, R8 - - // r1 = x0*2*x1 + x2*38*x4 + x3*19*x3 - MOVQ 0(SI), AX - SHLQ $1, AX - MULQ 8(SI) - MOVQ AX, R9 // r10 - MOVQ DX, R10 // r11 - - MOVQ 16(SI), DX - IMUL3Q $38, DX, AX - MULQ 32(SI) - ADDQ AX, R9 - ADCQ DX, R10 - - MOVQ 24(SI), DX - IMUL3Q $19, DX, AX - MULQ 24(SI) - ADDQ AX, R9 - ADCQ DX, R10 - - // r2 = x0*2*x2 + x1*x1 + x3*38*x4 - MOVQ 0(SI), AX - SHLQ $1, AX - MULQ 16(SI) - MOVQ AX, R11 // r20 - MOVQ DX, R12 // r21 - - MOVQ 8(SI), AX - MULQ 8(SI) - ADDQ AX, R11 - ADCQ DX, R12 - - MOVQ 24(SI), DX - IMUL3Q $38, DX, AX - MULQ 32(SI) - ADDQ AX, R11 - ADCQ DX, R12 - - // r3 = x0*2*x3 + x1*2*x2 + x4*19*x4 - MOVQ 0(SI), AX - SHLQ $1, AX - MULQ 24(SI) - MOVQ AX, R13 // r30 - MOVQ DX, R14 // r31 - - MOVQ 8(SI), AX - SHLQ $1, AX - MULQ 16(SI) - ADDQ AX, R13 - ADCQ DX, R14 - - MOVQ 32(SI), DX - IMUL3Q $19, DX, AX - MULQ 32(SI) - ADDQ AX, R13 - ADCQ DX, R14 - - // r4 = x0*2*x4 + x1*2*x3 + x2*x2 - MOVQ 0(SI), AX - SHLQ $1, AX - MULQ 32(SI) - MOVQ AX, R15 // r40 - MOVQ DX, BX // r41 - - MOVQ 8(SI), AX - SHLQ $1, AX - MULQ 24(SI) - ADDQ AX, R15 - ADCQ DX, BX - - MOVQ 16(SI), AX - MULQ 16(SI) - ADDQ AX, R15 - ADCQ DX, BX - - // Reduce - MOVQ $2251799813685247, AX // (1<<51) - 1 - SHLQ $13, CX, R8 // r01 = shld with r00 - ANDQ AX, CX // r00 &= mask51 - SHLQ $13, R9, R10 // r11 = shld with r10 - ANDQ AX, R9 // r10 &= mask51 - ADDQ R8, R9 // r10 += r01 - SHLQ $13, R11, R12 // r21 = shld with r20 - ANDQ AX, R11 // r20 &= mask51 - ADDQ R10, R11 // r20 += r11 - SHLQ $13, R13, R14 // r31 = shld with r30 - ANDQ AX, R13 // r30 &= mask51 - ADDQ R12, R13 // r30 += r21 - SHLQ $13, R15, BX // r41 = shld with r40 - ANDQ AX, R15 // r40 &= mask51 - ADDQ R14, R15 // r40 += r31 - IMUL3Q $19, BX, DX // r41 = r41*19 - ADDQ DX, CX // r00 += r41 - - MOVQ CX, DX // rdx <-- r00 - SHRQ $51, DX // rdx <-- r00 >> 51 - ADDQ DX, R9 // r10 += r00 >> 51 - MOVQ R9, DX // rdx <-- r10 - SHRQ $51, DX // rdx <-- r10 >> 51 - ANDQ AX, CX // r00 &= mask51 - ADDQ DX, R11 // r20 += r10 >> 51 - MOVQ R11, DX // rdx <-- r20 - SHRQ $51, DX // rdx <-- r20 >> 51 - ANDQ AX, R9 // r10 &= mask51 - ADDQ DX, R13 // r30 += r20 >> 51 - MOVQ R13, DX // rdx <-- r30 - SHRQ $51, DX // rdx <-- r30 >> 51 - ANDQ AX, R11 // r20 &= mask51 - ADDQ DX, R15 // r40 += r30 >> 51 - MOVQ R15, DX // rdx <-- r40 - SHRQ $51, DX // rdx <-- r40 >> 51 - ANDQ AX, R13 // r30 &= mask51 - IMUL3Q $19, DX, DX // rdx <-- (r40 >> 51) * 19 - ADDQ DX, CX // r00 += (r40 >> 51) *19 - ANDQ AX, R15 // r40 &= mask51 - - MOVQ CX, 0(DI) - MOVQ R9, 8(DI) - MOVQ R11, 16(DI) - MOVQ R13, 24(DI) - MOVQ R15, 32(DI) - RET diff --git a/internal/radix51/fe_generic.go b/internal/radix51/fe_generic.go deleted file mode 100644 index 601d9e7..0000000 --- a/internal/radix51/fe_generic.go +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright (c) 2017 George Tankersley. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package radix51 - -func feMulGeneric(v, x, y *FieldElement) { - x0 := x[0] - x1 := x[1] - x2 := x[2] - x3 := x[3] - x4 := x[4] - - y0 := y[0] - y1 := y[1] - y2 := y[2] - y3 := y[3] - y4 := y[4] - - // Reduction can be carried out simultaneously to multiplication. For - // example, we do not compute a coefficient r_5 . Whenever the result of a - // mul instruction belongs to r_5 , for example in the multiplication of - // x_3*y_2 , we multiply one of the inputs by 19 and add the result to r_0. - - x1_19 := x1 * 19 - x2_19 := x2 * 19 - x3_19 := x3 * 19 - x4_19 := x4 * 19 - - // calculate r0 = x0*y0 + 19*(x1*y4 + x2*y3 + x3*y2 + x4*y1) - r00, r01 := madd64(0, 0, x0, y0) - r00, r01 = madd64(r00, r01, x1_19, y4) - r00, r01 = madd64(r00, r01, x2_19, y3) - r00, r01 = madd64(r00, r01, x3_19, y2) - r00, r01 = madd64(r00, r01, x4_19, y1) - - // calculate r1 = x0*y1 + x1*y0 + 19*(x2*y4 + x3*y3 + x4*y2) - r10, r11 := madd64(0, 0, x0, y1) - r10, r11 = madd64(r10, r11, x1, y0) - r10, r11 = madd64(r10, r11, x2_19, y4) - r10, r11 = madd64(r10, r11, x3_19, y3) - r10, r11 = madd64(r10, r11, x4_19, y2) - - // calculate r2 = x0*y2 + x1*y1 + x2*y0 + 19*(x3*y4 + x4*y3) - r20, r21 := madd64(0, 0, x0, y2) - r20, r21 = madd64(r20, r21, x1, y1) - r20, r21 = madd64(r20, r21, x2, y0) - r20, r21 = madd64(r20, r21, x3_19, y4) - r20, r21 = madd64(r20, r21, x4_19, y3) - - // calculate r3 = x0*y3 + x1*y2 + x2*y1 + x3*y0 + 19*x4*y4 - r30, r31 := madd64(0, 0, x0, y3) - r30, r31 = madd64(r30, r31, x1, y2) - r30, r31 = madd64(r30, r31, x2, y1) - r30, r31 = madd64(r30, r31, x3, y0) - r30, r31 = madd64(r30, r31, x4_19, y4) - - // calculate r4 = x0*y4 + x1*y3 + x2*y2 + x3*y1 + x4*y0 - r40, r41 := madd64(0, 0, x0, y4) - r40, r41 = madd64(r40, r41, x1, y3) - r40, r41 = madd64(r40, r41, x2, y2) - r40, r41 = madd64(r40, r41, x3, y1) - r40, r41 = madd64(r40, r41, x4, y0) - - // After the multiplication we need to reduce (carry) the 5 coefficients to - // obtain a result with coefficients that are at most slightly larger than - // 2^51 . Denote the two registers holding coefficient r_0 as r_00 and r_01 - // with r_0 = 2^64*r_01 + r_00 . Similarly denote the two registers holding - // coefficient r_1 as r_10 and r_11 . We first shift r_01 left by 13, while - // shifting in the most significant bits of r_00 (shld instruction) and - // then compute the logical and of r_00 with 2^51 − 1. We do the same with - // r_10 and r_11 and add r_01 into r_10 after the logical and with 2^51 − - // 1. We proceed this way for coefficients r_2,...,r_4; register r_41 is - // multiplied by 19 before adding it to r_00 . - - r01 = (r01 << 13) | (r00 >> 51) - r00 &= maskLow51Bits - - r11 = (r11 << 13) | (r10 >> 51) - r10 &= maskLow51Bits - r10 += r01 - - r21 = (r21 << 13) | (r20 >> 51) - r20 &= maskLow51Bits - r20 += r11 - - r31 = (r31 << 13) | (r30 >> 51) - r30 &= maskLow51Bits - r30 += r21 - - r41 = (r41 << 13) | (r40 >> 51) - r40 &= maskLow51Bits - r40 += r31 - - r41 *= 19 - r00 += r41 - - // Now all 5 coefficients fit into 64-bit registers but are still too large - // to be used as input to another multiplication. We therefore carry from - // r_0 to r_1 , from r_1 to r_2 , from r_2 to r_3 , from r_3 to r_4 , and - // finally from r_4 to r_0 . Each of these carries is done as one copy, one - // right shift by 51, one logical and with 2^51 − 1, and one addition. - *v = FieldElement{r00, r10, r20, r30, r40} - v.carryPropagate1().carryPropagate2() -} - -func feSquareGeneric(v, x *FieldElement) { - // Squaring needs only 15 mul instructions. Some inputs are multiplied by 2; - // this is combined with multiplication by 19 where possible. The coefficient - // reduction after squaring is the same as for multiplication. - - x0 := x[0] - x1 := x[1] - x2 := x[2] - x3 := x[3] - x4 := x[4] - - x0_2 := x0 << 1 - x1_2 := x1 << 1 - - x1_38 := x1 * 38 - x2_38 := x2 * 38 - x3_38 := x3 * 38 - - x3_19 := x3 * 19 - x4_19 := x4 * 19 - - // r0 = x0*x0 + x1*38*x4 + x2*38*x3 - r00, r01 := madd64(0, 0, x0, x0) - r00, r01 = madd64(r00, r01, x1_38, x4) - r00, r01 = madd64(r00, r01, x2_38, x3) - - // r1 = x0*2*x1 + x2*38*x4 + x3*19*x3 - r10, r11 := madd64(0, 0, x0_2, x1) - r10, r11 = madd64(r10, r11, x2_38, x4) - r10, r11 = madd64(r10, r11, x3_19, x3) - - // r2 = x0*2*x2 + x1*x1 + x3*38*x4 - r20, r21 := madd64(0, 0, x0_2, x2) - r20, r21 = madd64(r20, r21, x1, x1) - r20, r21 = madd64(r20, r21, x3_38, x4) - - // r3 = x0*2*x3 + x1*2*x2 + x4*19*x4 - r30, r31 := madd64(0, 0, x0_2, x3) - r30, r31 = madd64(r30, r31, x1_2, x2) - r30, r31 = madd64(r30, r31, x4_19, x4) - - // r4 = x0*2*x4 + x1*2*x3 + x2*x2 - r40, r41 := madd64(0, 0, x0_2, x4) - r40, r41 = madd64(r40, r41, x1_2, x3) - r40, r41 = madd64(r40, r41, x2, x2) - - // Same reduction - - r01 = (r01 << 13) | (r00 >> 51) - r00 &= maskLow51Bits - - r11 = (r11 << 13) | (r10 >> 51) - r10 &= maskLow51Bits - r10 += r01 - - r21 = (r21 << 13) | (r20 >> 51) - r20 &= maskLow51Bits - r20 += r11 - - r31 = (r31 << 13) | (r30 >> 51) - r30 &= maskLow51Bits - r30 += r21 - - r41 = (r41 << 13) | (r40 >> 51) - r40 &= maskLow51Bits - r40 += r31 - - r41 *= 19 - r00 += r41 - - *v = FieldElement{r00, r10, r20, r30, r40} - v.carryPropagate1().carryPropagate2() -} diff --git a/internal/radix51/fe_noasm.go b/internal/radix51/fe_noasm.go deleted file mode 100644 index 39cfa36..0000000 --- a/internal/radix51/fe_noasm.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !amd64 purego - -package radix51 - -func feMul(v, x, y *FieldElement) { feMulGeneric(v, x, y) } - -func feSquare(v, x *FieldElement) { feSquareGeneric(v, x) } diff --git a/internal/radix51/fe_test.go b/internal/radix51/fe_test.go deleted file mode 100644 index 5dbdedf..0000000 --- a/internal/radix51/fe_test.go +++ /dev/null @@ -1,395 +0,0 @@ -// Copyright (c) 2017 George Tankersley. All rights reserved. -// Copyright (c) 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package radix51 - -import ( - "bytes" - "crypto/rand" - "io" - "math/big" - "math/bits" - mathrand "math/rand" - "reflect" - "testing" - "testing/quick" -) - -// quickCheckConfig will make each quickcheck test run (1024 * -quickchecks) -// times. The default value of -quickchecks is 100. -var quickCheckConfig = &quick.Config{MaxCountScale: 1 << 10} - -func generateFieldElement(rand *mathrand.Rand) FieldElement { - // Generation strategy: generate random limb values of [52, 51, 51, 51, 51] - // bits, like the ones returned by lightReduce. - const maskLow52Bits = (1 << 52) - 1 - return FieldElement{ - rand.Uint64() & maskLow52Bits, - rand.Uint64() & maskLow51Bits, - rand.Uint64() & maskLow51Bits, - rand.Uint64() & maskLow51Bits, - rand.Uint64() & maskLow51Bits, - } -} - -// weirdLimbs can be combined to generate a range of edge-case field elements. -// 0 and -1 are intentionally more weighted, as they combine well. -var ( - weirdLimbs51 = []uint64{ - 0, 0, 0, 0, - 1, - 19 - 1, - 19, - 0x2aaaaaaaaaaaa, - 0x5555555555555, - (1 << 51) - 20, - (1 << 51) - 19, - (1 << 51) - 1, (1 << 51) - 1, - (1 << 51) - 1, (1 << 51) - 1, - } - weirdLimbs52 = []uint64{ - 0, 0, 0, 0, 0, 0, - 1, - 19 - 1, - 19, - 0x2aaaaaaaaaaaa, - 0x5555555555555, - (1 << 51) - 20, - (1 << 51) - 19, - (1 << 51) - 1, (1 << 51) - 1, - (1 << 51) - 1, (1 << 51) - 1, - (1 << 51) - 1, (1 << 51) - 1, - 1 << 51, - (1 << 51) + 1, - (1 << 52) - 19, - (1 << 52) - 1, - } -) - -func generateWeirdFieldElement(rand *mathrand.Rand) FieldElement { - return FieldElement{ - weirdLimbs52[rand.Intn(len(weirdLimbs52))], - weirdLimbs51[rand.Intn(len(weirdLimbs51))], - weirdLimbs51[rand.Intn(len(weirdLimbs51))], - weirdLimbs51[rand.Intn(len(weirdLimbs51))], - weirdLimbs51[rand.Intn(len(weirdLimbs51))], - } -} - -func (x FieldElement) Generate(rand *mathrand.Rand, size int) reflect.Value { - if rand.Intn(2) == 0 { - return reflect.ValueOf(generateWeirdFieldElement(rand)) - } - return reflect.ValueOf(generateFieldElement(rand)) -} - -// isInBounds returns whether the element is within the expected bit size bounds -// after a light reduction. -func isInBounds(x *FieldElement) bool { - return bits.Len64(x[0]) <= 52 && - bits.Len64(x[1]) <= 51 && - bits.Len64(x[2]) <= 51 && - bits.Len64(x[3]) <= 51 && - bits.Len64(x[4]) <= 51 -} - -func TestMulDistributesOverAdd(t *testing.T) { - mulDistributesOverAdd := func(x, y, z FieldElement) bool { - // Compute t1 = (x+y)*z - t1 := new(FieldElement) - t1.Add(&x, &y) - t1.Mul(t1, &z) - - // Compute t2 = x*z + y*z - t2 := new(FieldElement) - t3 := new(FieldElement) - t2.Mul(&x, &z) - t3.Mul(&y, &z) - t2.Add(t2, t3) - - return t1.Equal(t2) == 1 && isInBounds(t1) && isInBounds(t2) - } - - if err := quick.Check(mulDistributesOverAdd, quickCheckConfig); err != nil { - t.Error(err) - } -} - -func TestMul64to128(t *testing.T) { - a := uint64(5) - b := uint64(5) - r0, r1 := madd64(0, 0, a, b) - if r0 != 0x19 || r1 != 0 { - t.Errorf("lo-range wide mult failed, got %d + %d*(2**64)", r0, r1) - } - - a = uint64(18014398509481983) // 2^54 - 1 - b = uint64(18014398509481983) // 2^54 - 1 - r0, r1 = madd64(0, 0, a, b) - if r0 != 0xff80000000000001 || r1 != 0xfffffffffff { - t.Errorf("hi-range wide mult failed, got %d + %d*(2**64)", r0, r1) - } - - a = uint64(1125899906842661) - b = uint64(2097155) - r0, r1 = madd64(0, 0, a, b) - r0, r1 = madd64(r0, r1, a, b) - r0, r1 = madd64(r0, r1, a, b) - r0, r1 = madd64(r0, r1, a, b) - r0, r1 = madd64(r0, r1, a, b) - if r0 != 16888498990613035 || r1 != 640 { - t.Errorf("wrong answer: %d + %d*(2**64)", r0, r1) - } -} - -var r0, r1 uint64 - -func BenchmarkWideMultCall(t *testing.B) { - a := uint64(18014398509481983) - b := uint64(18014398509481983) - - for i := 0; i < t.N; i++ { - r0, r1 = madd64(r0, r1, a, b) - } -} - -func TestFromBytesRoundTrip(t *testing.T) { - f1 := func(in, out [32]byte, fe FieldElement) bool { - fe.FromBytes(in[:]) - fe.Bytes(out[:0]) - - // Mask the most significant bit as it's ignored by FromBytes. (Now - // instead of earlier so we check the masking in FromBytes is working.) - in[len(in)-1] &= (1 << 7) - 1 - - // TODO: values in the range [2^255-19, 2^255-1] will still fail the - // comparison as they will have been reduced in the round-trip, but the - // current quickcheck generation strategy will never hit them, which is - // not good. We should have a weird generator that aims for edge cases, - // and we'll know it works when this test breaks. - - return bytes.Equal(in[:], out[:]) && isInBounds(&fe) - } - if err := quick.Check(f1, nil); err != nil { - t.Errorf("failed bytes->FE->bytes round-trip: %v", err) - } - - f2 := func(fe, r FieldElement, out [32]byte) bool { - fe.Bytes(out[:0]) - r.FromBytes(out[:]) - - // Intentionally not using Equal not to go through Bytes again. - // Calling reduce because both Generate and FromBytes can produce - // non-canonical representations. - fe.reduce() - r.reduce() - return fe == r - } - if err := quick.Check(f2, nil); err != nil { - t.Errorf("failed FE->bytes->FE round-trip: %v", err) - } - - // Check some fixed vectors from dalek - type feRTTest struct { - fe FieldElement - b []byte - } - var tests = []feRTTest{ - { - fe: FieldElement([5]uint64{358744748052810, 1691584618240980, 977650209285361, 1429865912637724, 560044844278676}), - b: []byte{74, 209, 69, 197, 70, 70, 161, 222, 56, 226, 229, 19, 112, 60, 25, 92, 187, 74, 222, 56, 50, 153, 51, 233, 40, 74, 57, 6, 160, 185, 213, 31}, - }, - { - fe: FieldElement([5]uint64{84926274344903, 473620666599931, 365590438845504, 1028470286882429, 2146499180330972}), - b: []byte{199, 23, 106, 112, 61, 77, 216, 79, 186, 60, 11, 118, 13, 16, 103, 15, 42, 32, 83, 250, 44, 57, 204, 198, 78, 199, 253, 119, 146, 172, 3, 122}, - }, - } - - for _, tt := range tests { - if !bytes.Equal(tt.fe.Bytes(nil), tt.b) || new(FieldElement).FromBytes(tt.b).Equal(&tt.fe) != 1 { - t.Errorf("Failed fixed roundtrip: %v", tt) - } - } -} - -func swapEndianness(buf []byte) []byte { - for i := 0; i < len(buf)/2; i++ { - buf[i], buf[len(buf)-i-1] = buf[len(buf)-i-1], buf[i] - } - return buf -} - -func TestBytesBigEquivalence(t *testing.T) { - f1 := func(in, out [32]byte, fe, fe1 FieldElement) bool { - fe.FromBytes(in[:]) - - in[len(in)-1] &= (1 << 7) - 1 // mask the most significant bit - b := new(big.Int).SetBytes(swapEndianness(in[:])) - fe1.FromBig(b) - - if fe != fe1 { - return false - } - - fe.Bytes(out[:0]) - buf := make([]byte, 32) // pad with zeroes - copy(buf, swapEndianness(fe1.ToBig().Bytes())) - - return bytes.Equal(out[:], buf) && isInBounds(&fe) && isInBounds(&fe1) - } - if err := quick.Check(f1, nil); err != nil { - t.Error(err) - } -} - -func TestFromBytesRoundTripEdgeCases(t *testing.T) { - // TODO: values close to 0, close to 2^255-19, between 2^255-19 and 2^255-1, - // and between 2^255 and 2^256-1. Test both the documented FromBytes - // behavior, and that Bytes reduces them. -} - -// Tests self-consistency between FeMul and FeSquare. -func TestSanity(t *testing.T) { - var x FieldElement - var x2, x2sq FieldElement - // var x2Go, x2sqGo FieldElement - - x = [5]uint64{1, 1, 1, 1, 1} - x2.Mul(&x, &x) - // FeMulGo(&x2Go, &x, &x) - x2sq.Square(&x) - // FeSquareGo(&x2sqGo, &x) - - // if !vartimeEqual(x2, x2Go) || !vartimeEqual(x2sq, x2sqGo) || !vartimeEqual(x2, x2sq) { - // t.Fatalf("all ones failed\nmul.s: %d\nmul.g: %d\nsqr.s: %d\nsqr.g: %d\n", x2, x2Go, x2sq, x2sqGo) - // } - - if x2 != x2sq { - t.Fatalf("all ones failed\nmul: %x\nsqr: %x\n", x2, x2sq) - } - - var bytes [32]byte - - _, err := io.ReadFull(rand.Reader, bytes[:]) - if err != nil { - t.Fatal(err) - } - x.FromBytes(bytes[:]) - - x2.Mul(&x, &x) - // FeMulGo(&x2Go, &x, &x) - x2sq.Square(&x) - // FeSquareGo(&x2sqGo, &x) - - // if !vartimeEqual(x2, x2Go) || !vartimeEqual(x2sq, x2sqGo) || !vartimeEqual(x2, x2sq) { - // t.Fatalf("random field element failed\nfe: %x\n\nmul.s: %x\nmul.g: %x\nsqr.s: %x\nsqr.g: %x\n", x, x2, x2Go, x2sq, x2sqGo) - // } - - if x2 != x2sq { - t.Fatalf("all ones failed\nmul: %x\nsqr: %x\n", x2, x2sq) - } -} - -func TestEqual(t *testing.T) { - var x FieldElement = [5]uint64{1, 1, 1, 1, 1} - var y FieldElement = [5]uint64{5, 4, 3, 2, 1} - - eq := x.Equal(&x) - if eq != 1 { - t.Errorf("wrong about equality") - } - - eq = x.Equal(&y) - if eq != 0 { - t.Errorf("wrong about inequality") - } -} - -func TestInvert(t *testing.T) { - var x FieldElement = [5]uint64{1, 1, 1, 1, 1} - var one FieldElement = [5]uint64{1, 0, 0, 0, 0} - var xinv, r FieldElement - - xinv.Invert(&x) - r.Mul(&x, &xinv) - r.reduce() - - if one != r { - t.Errorf("inversion identity failed, got: %x", r) - } - - var bytes [32]byte - - _, err := io.ReadFull(rand.Reader, bytes[:]) - if err != nil { - t.Fatal(err) - } - x.FromBytes(bytes[:]) - - xinv.Invert(&x) - r.Mul(&x, &xinv) - r.reduce() - - if one != r { - t.Errorf("random inversion identity failed, got: %x for field element %x", r, x) - } -} - -func TestSelectSwap(t *testing.T) { - a := FieldElement([5]uint64{358744748052810, 1691584618240980, 977650209285361, 1429865912637724, 560044844278676}) - b := FieldElement([5]uint64{84926274344903, 473620666599931, 365590438845504, 1028470286882429, 2146499180330972}) - - var c, d FieldElement - - c.Select(&a, &b, 1) - d.Select(&a, &b, 0) - - if c.Equal(&a) != 1 || d.Equal(&b) != 1 { - t.Errorf("Select failed") - } - - CondSwap(&c, &d, 0) - - if c.Equal(&a) != 1 || d.Equal(&b) != 1 { - t.Errorf("Swap failed") - } - - CondSwap(&c, &d, 1) - - if c.Equal(&b) != 1 || d.Equal(&a) != 1 { - t.Errorf("Swap failed") - } -} - -func TestMul32(t *testing.T) { - isAlmostInBounds := func(x *FieldElement) bool { - return bits.Len64(x[0]) <= 52 && - bits.Len64(x[1]) <= 52 && - bits.Len64(x[2]) <= 52 && - bits.Len64(x[3]) <= 52 && - bits.Len64(x[4]) <= 52 - } - - mul32EquivalentToMul := func(x FieldElement, y uint32) bool { - t1 := new(FieldElement) - for i := 0; i < 100; i++ { - t1.Mul32(&x, y) - } - - ty := new(FieldElement) - ty[0] = uint64(y) - - t2 := new(FieldElement) - for i := 0; i < 100; i++ { - t2.Mul(&x, ty) - } - - return t1.Equal(t2) == 1 && isAlmostInBounds(t1) && isInBounds(t2) - } - - if err := quick.Check(mul32EquivalentToMul, quickCheckConfig); err != nil { - t.Error(err) - } -} diff --git a/internal/radix51/mul_bits.go b/internal/radix51/mul_bits.go deleted file mode 100644 index 89b867c..0000000 --- a/internal/radix51/mul_bits.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2019 George Tankersley. All rights reserved. -// Copyright (c) 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build go1.13 - -package radix51 - -import "math/bits" - -// madd64 returns ol + oh * 2⁶⁴ = lo + hi * 2⁶⁴ + a * b. That is, it multiplies -// a and b, and adds the result to the split uint128 [lo,hi]. -func madd64(lo, hi, a, b uint64) (ol uint64, oh uint64) { - oh, ol = bits.Mul64(a, b) - var c uint64 - ol, c = bits.Add64(ol, lo, 0) - oh, _ = bits.Add64(oh, hi, c) - return -} - -// mul51 returns lo + hi * 2⁵¹ = a * b. -func mul51(a uint64, b uint32) (lo uint64, hi uint64) { - mh, ml := bits.Mul64(a, uint64(b)) - lo = ml & maskLow51Bits - hi = (mh << 13) | (ml >> 51) - return -} diff --git a/internal/radix51/mul_compat.go b/internal/radix51/mul_compat.go deleted file mode 100644 index 4b9ac35..0000000 --- a/internal/radix51/mul_compat.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2017 George Tankersley. All rights reserved. -// Copyright (c) 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !go1.13 - -package radix51 - -import "unsafe" - -// madd64 returns ol + oh * 2⁶⁴ = lo + hi * 2⁶⁴ + a * b. That is, it multiplies -// a and b, and adds the result to the split uint128 [lo,hi]. -func madd64(lo, hi, a, b uint64) (ol uint64, oh uint64) { - t1 := (a>>32)*(b&0xFFFFFFFF) + ((a & 0xFFFFFFFF) * (b & 0xFFFFFFFF) >> 32) - t2 := (a&0xFFFFFFFF)*(b>>32) + (t1 & 0xFFFFFFFF) - ol = (a * b) + lo - cmp := ol < lo - oh = hi + (a>>32)*(b>>32) + t1>>32 + t2>>32 + uint64(*(*byte)(unsafe.Pointer(&cmp))) - return -} - -const mask32 = 1<<32 - 1 - -// mul51 returns lo + hi * 2⁵¹ = a * b. -func mul51(a uint64, b uint32) (lo uint64, hi uint64) { - w0 := (a & mask32) * uint64(b) - t := (a>>32)*uint64(b) + w0>>32 - w1 := t & mask32 - w2 := t >> 32 - mh := w2 + w1>>32 - ml := a * uint64(b) - - lo = ml & maskLow51Bits - hi = (mh << 13) | (ml >> 51) - return -} diff --git a/internal/scalar/scalar.go b/internal/scalar/scalar.go deleted file mode 100644 index 5b25577..0000000 --- a/internal/scalar/scalar.go +++ /dev/null @@ -1,1112 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Copyright 2019 Henry de Valence. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package scalar implements the ristretto255 scalar group. -package scalar - -import ( - "crypto/subtle" - "encoding/binary" - "errors" -) - -// A Scalar is an integer modulo -// l = 2^252 + 27742317777372353535851937790883648493, -// here represented as an opaque little-endian byte string. -type Scalar [32]byte - -var ( - scZero = Scalar([32]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) - - scOne = Scalar([32]byte{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) - - // sage: l = GF(2**252 + 27742317777372353535851937790883648493) - // sage: l(-1).lift().digits(256) - scMinusOne = Scalar([32]byte{236, 211, 245, 92, 26, 99, 18, 88, 214, 156, 247, 162, 222, 249, 222, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16}) -) - -// Add sets s = x + y mod l and returns s. -func (s *Scalar) Add(x, y *Scalar) *Scalar { - // s = 1 * x + y mod l - scMulAdd(s, &scOne, x, y) - return s -} - -// Sub sets s = x - y mod l and returns s. -func (s *Scalar) Sub(x, y *Scalar) *Scalar { - // s = -1 * y + x - scMulAdd(s, &scMinusOne, y, x) - return s -} - -// Neg sets s = -x mod l and returns s. -func (s *Scalar) Neg(x *Scalar) *Scalar { - scMulAdd(s, &scMinusOne, x, &scZero) - return s -} - -// Mul sets s = x * y mod l and returns s. -func (s *Scalar) Mul(x, y *Scalar) *Scalar { - scMulAdd(s, x, y, &scZero) - return s -} - -// FromUniformBytes sets s to an uniformly distributed value given 64 uniformly -// distributed random bytes. -func (s *Scalar) FromUniformBytes(x []byte) *Scalar { - if len(x) != 64 { - panic("scalar: invalid uniform input length") - } - var wideBytes [64]byte - copy(wideBytes[:], x[:]) - scReduce(s, &wideBytes) - return s -} - -// FromCanonicalBytes sets s = x, where x is a 32 bytes little-endian encoding -// of s. If x is not a canonical encoding of s, FromCanonicalBytes returns an -// error and the receiver is unchanged. -func (s *Scalar) FromCanonicalBytes(x []byte) error { - if len(x) != 32 { - panic("scalar: invalid scalar length") - } - if !scMinimal(x) { - return errors.New("invalid scalar encoding") - } - copy(s[:], x) - return nil -} - -// reduce reduces s mod l returns it. -func (s *Scalar) reduce() *Scalar { - var wideBytes [64]byte - copy(wideBytes[:], s[:]) - scReduce(s, &wideBytes) - return s -} - -// Bytes appends a 32 bytes little-endian encoding of s to b. -func (s *Scalar) Bytes(b []byte) []byte { - t := *s - t.reduce() - - res, out := sliceForAppend(b, 32) - copy(out, t[:]) - - return res -} - -// Equal returns 1 if s and t are equal, and 0 otherwise. -func (s *Scalar) Equal(t *Scalar) int { - var ss, st [32]byte - t.Bytes(st[:0]) - s.Bytes(ss[:0]) - return subtle.ConstantTimeCompare(ss[:], st[:]) -} - -// sliceForAppend extends the input slice by n bytes. head is the full extended -// slice, while tail is the appended part. If the original slice has sufficient -// capacity no allocation is performed. -func sliceForAppend(in []byte, n int) (head, tail []byte) { - if total := len(in) + n; cap(in) >= total { - head = in[:total] - } else { - head = make([]byte, total) - copy(head, in) - } - tail = head[len(in):] - return -} - -func load3(in []byte) int64 { - r := int64(in[0]) - r |= int64(in[1]) << 8 - r |= int64(in[2]) << 16 - return r -} - -func load4(in []byte) int64 { - r := int64(in[0]) - r |= int64(in[1]) << 8 - r |= int64(in[2]) << 16 - r |= int64(in[3]) << 24 - return r -} - -// Input: -// a[0]+256*a[1]+...+256^31*a[31] = a -// b[0]+256*b[1]+...+256^31*b[31] = b -// c[0]+256*c[1]+...+256^31*c[31] = c -// -// Output: -// s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l -// where l = 2^252 + 27742317777372353535851937790883648493. -func scMulAdd(s, a, b, c *Scalar) { - a0 := 2097151 & load3(a[:]) - a1 := 2097151 & (load4(a[2:]) >> 5) - a2 := 2097151 & (load3(a[5:]) >> 2) - a3 := 2097151 & (load4(a[7:]) >> 7) - a4 := 2097151 & (load4(a[10:]) >> 4) - a5 := 2097151 & (load3(a[13:]) >> 1) - a6 := 2097151 & (load4(a[15:]) >> 6) - a7 := 2097151 & (load3(a[18:]) >> 3) - a8 := 2097151 & load3(a[21:]) - a9 := 2097151 & (load4(a[23:]) >> 5) - a10 := 2097151 & (load3(a[26:]) >> 2) - a11 := (load4(a[28:]) >> 7) - b0 := 2097151 & load3(b[:]) - b1 := 2097151 & (load4(b[2:]) >> 5) - b2 := 2097151 & (load3(b[5:]) >> 2) - b3 := 2097151 & (load4(b[7:]) >> 7) - b4 := 2097151 & (load4(b[10:]) >> 4) - b5 := 2097151 & (load3(b[13:]) >> 1) - b6 := 2097151 & (load4(b[15:]) >> 6) - b7 := 2097151 & (load3(b[18:]) >> 3) - b8 := 2097151 & load3(b[21:]) - b9 := 2097151 & (load4(b[23:]) >> 5) - b10 := 2097151 & (load3(b[26:]) >> 2) - b11 := (load4(b[28:]) >> 7) - c0 := 2097151 & load3(c[:]) - c1 := 2097151 & (load4(c[2:]) >> 5) - c2 := 2097151 & (load3(c[5:]) >> 2) - c3 := 2097151 & (load4(c[7:]) >> 7) - c4 := 2097151 & (load4(c[10:]) >> 4) - c5 := 2097151 & (load3(c[13:]) >> 1) - c6 := 2097151 & (load4(c[15:]) >> 6) - c7 := 2097151 & (load3(c[18:]) >> 3) - c8 := 2097151 & load3(c[21:]) - c9 := 2097151 & (load4(c[23:]) >> 5) - c10 := 2097151 & (load3(c[26:]) >> 2) - c11 := (load4(c[28:]) >> 7) - var carry [23]int64 - - s0 := c0 + a0*b0 - s1 := c1 + a0*b1 + a1*b0 - s2 := c2 + a0*b2 + a1*b1 + a2*b0 - s3 := c3 + a0*b3 + a1*b2 + a2*b1 + a3*b0 - s4 := c4 + a0*b4 + a1*b3 + a2*b2 + a3*b1 + a4*b0 - s5 := c5 + a0*b5 + a1*b4 + a2*b3 + a3*b2 + a4*b1 + a5*b0 - s6 := c6 + a0*b6 + a1*b5 + a2*b4 + a3*b3 + a4*b2 + a5*b1 + a6*b0 - s7 := c7 + a0*b7 + a1*b6 + a2*b5 + a3*b4 + a4*b3 + a5*b2 + a6*b1 + a7*b0 - s8 := c8 + a0*b8 + a1*b7 + a2*b6 + a3*b5 + a4*b4 + a5*b3 + a6*b2 + a7*b1 + a8*b0 - s9 := c9 + a0*b9 + a1*b8 + a2*b7 + a3*b6 + a4*b5 + a5*b4 + a6*b3 + a7*b2 + a8*b1 + a9*b0 - s10 := c10 + a0*b10 + a1*b9 + a2*b8 + a3*b7 + a4*b6 + a5*b5 + a6*b4 + a7*b3 + a8*b2 + a9*b1 + a10*b0 - s11 := c11 + a0*b11 + a1*b10 + a2*b9 + a3*b8 + a4*b7 + a5*b6 + a6*b5 + a7*b4 + a8*b3 + a9*b2 + a10*b1 + a11*b0 - s12 := a1*b11 + a2*b10 + a3*b9 + a4*b8 + a5*b7 + a6*b6 + a7*b5 + a8*b4 + a9*b3 + a10*b2 + a11*b1 - s13 := a2*b11 + a3*b10 + a4*b9 + a5*b8 + a6*b7 + a7*b6 + a8*b5 + a9*b4 + a10*b3 + a11*b2 - s14 := a3*b11 + a4*b10 + a5*b9 + a6*b8 + a7*b7 + a8*b6 + a9*b5 + a10*b4 + a11*b3 - s15 := a4*b11 + a5*b10 + a6*b9 + a7*b8 + a8*b7 + a9*b6 + a10*b5 + a11*b4 - s16 := a5*b11 + a6*b10 + a7*b9 + a8*b8 + a9*b7 + a10*b6 + a11*b5 - s17 := a6*b11 + a7*b10 + a8*b9 + a9*b8 + a10*b7 + a11*b6 - s18 := a7*b11 + a8*b10 + a9*b9 + a10*b8 + a11*b7 - s19 := a8*b11 + a9*b10 + a10*b9 + a11*b8 - s20 := a9*b11 + a10*b10 + a11*b9 - s21 := a10*b11 + a11*b10 - s22 := a11 * b11 - s23 := int64(0) - - carry[0] = (s0 + (1 << 20)) >> 21 - s1 += carry[0] - s0 -= carry[0] << 21 - carry[2] = (s2 + (1 << 20)) >> 21 - s3 += carry[2] - s2 -= carry[2] << 21 - carry[4] = (s4 + (1 << 20)) >> 21 - s5 += carry[4] - s4 -= carry[4] << 21 - carry[6] = (s6 + (1 << 20)) >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[8] = (s8 + (1 << 20)) >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[10] = (s10 + (1 << 20)) >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - carry[12] = (s12 + (1 << 20)) >> 21 - s13 += carry[12] - s12 -= carry[12] << 21 - carry[14] = (s14 + (1 << 20)) >> 21 - s15 += carry[14] - s14 -= carry[14] << 21 - carry[16] = (s16 + (1 << 20)) >> 21 - s17 += carry[16] - s16 -= carry[16] << 21 - carry[18] = (s18 + (1 << 20)) >> 21 - s19 += carry[18] - s18 -= carry[18] << 21 - carry[20] = (s20 + (1 << 20)) >> 21 - s21 += carry[20] - s20 -= carry[20] << 21 - carry[22] = (s22 + (1 << 20)) >> 21 - s23 += carry[22] - s22 -= carry[22] << 21 - - carry[1] = (s1 + (1 << 20)) >> 21 - s2 += carry[1] - s1 -= carry[1] << 21 - carry[3] = (s3 + (1 << 20)) >> 21 - s4 += carry[3] - s3 -= carry[3] << 21 - carry[5] = (s5 + (1 << 20)) >> 21 - s6 += carry[5] - s5 -= carry[5] << 21 - carry[7] = (s7 + (1 << 20)) >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[9] = (s9 + (1 << 20)) >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[11] = (s11 + (1 << 20)) >> 21 - s12 += carry[11] - s11 -= carry[11] << 21 - carry[13] = (s13 + (1 << 20)) >> 21 - s14 += carry[13] - s13 -= carry[13] << 21 - carry[15] = (s15 + (1 << 20)) >> 21 - s16 += carry[15] - s15 -= carry[15] << 21 - carry[17] = (s17 + (1 << 20)) >> 21 - s18 += carry[17] - s17 -= carry[17] << 21 - carry[19] = (s19 + (1 << 20)) >> 21 - s20 += carry[19] - s19 -= carry[19] << 21 - carry[21] = (s21 + (1 << 20)) >> 21 - s22 += carry[21] - s21 -= carry[21] << 21 - - s11 += s23 * 666643 - s12 += s23 * 470296 - s13 += s23 * 654183 - s14 -= s23 * 997805 - s15 += s23 * 136657 - s16 -= s23 * 683901 - s23 = 0 - - s10 += s22 * 666643 - s11 += s22 * 470296 - s12 += s22 * 654183 - s13 -= s22 * 997805 - s14 += s22 * 136657 - s15 -= s22 * 683901 - s22 = 0 - - s9 += s21 * 666643 - s10 += s21 * 470296 - s11 += s21 * 654183 - s12 -= s21 * 997805 - s13 += s21 * 136657 - s14 -= s21 * 683901 - s21 = 0 - - s8 += s20 * 666643 - s9 += s20 * 470296 - s10 += s20 * 654183 - s11 -= s20 * 997805 - s12 += s20 * 136657 - s13 -= s20 * 683901 - s20 = 0 - - s7 += s19 * 666643 - s8 += s19 * 470296 - s9 += s19 * 654183 - s10 -= s19 * 997805 - s11 += s19 * 136657 - s12 -= s19 * 683901 - s19 = 0 - - s6 += s18 * 666643 - s7 += s18 * 470296 - s8 += s18 * 654183 - s9 -= s18 * 997805 - s10 += s18 * 136657 - s11 -= s18 * 683901 - s18 = 0 - - carry[6] = (s6 + (1 << 20)) >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[8] = (s8 + (1 << 20)) >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[10] = (s10 + (1 << 20)) >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - carry[12] = (s12 + (1 << 20)) >> 21 - s13 += carry[12] - s12 -= carry[12] << 21 - carry[14] = (s14 + (1 << 20)) >> 21 - s15 += carry[14] - s14 -= carry[14] << 21 - carry[16] = (s16 + (1 << 20)) >> 21 - s17 += carry[16] - s16 -= carry[16] << 21 - - carry[7] = (s7 + (1 << 20)) >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[9] = (s9 + (1 << 20)) >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[11] = (s11 + (1 << 20)) >> 21 - s12 += carry[11] - s11 -= carry[11] << 21 - carry[13] = (s13 + (1 << 20)) >> 21 - s14 += carry[13] - s13 -= carry[13] << 21 - carry[15] = (s15 + (1 << 20)) >> 21 - s16 += carry[15] - s15 -= carry[15] << 21 - - s5 += s17 * 666643 - s6 += s17 * 470296 - s7 += s17 * 654183 - s8 -= s17 * 997805 - s9 += s17 * 136657 - s10 -= s17 * 683901 - s17 = 0 - - s4 += s16 * 666643 - s5 += s16 * 470296 - s6 += s16 * 654183 - s7 -= s16 * 997805 - s8 += s16 * 136657 - s9 -= s16 * 683901 - s16 = 0 - - s3 += s15 * 666643 - s4 += s15 * 470296 - s5 += s15 * 654183 - s6 -= s15 * 997805 - s7 += s15 * 136657 - s8 -= s15 * 683901 - s15 = 0 - - s2 += s14 * 666643 - s3 += s14 * 470296 - s4 += s14 * 654183 - s5 -= s14 * 997805 - s6 += s14 * 136657 - s7 -= s14 * 683901 - s14 = 0 - - s1 += s13 * 666643 - s2 += s13 * 470296 - s3 += s13 * 654183 - s4 -= s13 * 997805 - s5 += s13 * 136657 - s6 -= s13 * 683901 - s13 = 0 - - s0 += s12 * 666643 - s1 += s12 * 470296 - s2 += s12 * 654183 - s3 -= s12 * 997805 - s4 += s12 * 136657 - s5 -= s12 * 683901 - s12 = 0 - - carry[0] = (s0 + (1 << 20)) >> 21 - s1 += carry[0] - s0 -= carry[0] << 21 - carry[2] = (s2 + (1 << 20)) >> 21 - s3 += carry[2] - s2 -= carry[2] << 21 - carry[4] = (s4 + (1 << 20)) >> 21 - s5 += carry[4] - s4 -= carry[4] << 21 - carry[6] = (s6 + (1 << 20)) >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[8] = (s8 + (1 << 20)) >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[10] = (s10 + (1 << 20)) >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - - carry[1] = (s1 + (1 << 20)) >> 21 - s2 += carry[1] - s1 -= carry[1] << 21 - carry[3] = (s3 + (1 << 20)) >> 21 - s4 += carry[3] - s3 -= carry[3] << 21 - carry[5] = (s5 + (1 << 20)) >> 21 - s6 += carry[5] - s5 -= carry[5] << 21 - carry[7] = (s7 + (1 << 20)) >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[9] = (s9 + (1 << 20)) >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[11] = (s11 + (1 << 20)) >> 21 - s12 += carry[11] - s11 -= carry[11] << 21 - - s0 += s12 * 666643 - s1 += s12 * 470296 - s2 += s12 * 654183 - s3 -= s12 * 997805 - s4 += s12 * 136657 - s5 -= s12 * 683901 - s12 = 0 - - carry[0] = s0 >> 21 - s1 += carry[0] - s0 -= carry[0] << 21 - carry[1] = s1 >> 21 - s2 += carry[1] - s1 -= carry[1] << 21 - carry[2] = s2 >> 21 - s3 += carry[2] - s2 -= carry[2] << 21 - carry[3] = s3 >> 21 - s4 += carry[3] - s3 -= carry[3] << 21 - carry[4] = s4 >> 21 - s5 += carry[4] - s4 -= carry[4] << 21 - carry[5] = s5 >> 21 - s6 += carry[5] - s5 -= carry[5] << 21 - carry[6] = s6 >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[7] = s7 >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[8] = s8 >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[9] = s9 >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[10] = s10 >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - carry[11] = s11 >> 21 - s12 += carry[11] - s11 -= carry[11] << 21 - - s0 += s12 * 666643 - s1 += s12 * 470296 - s2 += s12 * 654183 - s3 -= s12 * 997805 - s4 += s12 * 136657 - s5 -= s12 * 683901 - s12 = 0 - - carry[0] = s0 >> 21 - s1 += carry[0] - s0 -= carry[0] << 21 - carry[1] = s1 >> 21 - s2 += carry[1] - s1 -= carry[1] << 21 - carry[2] = s2 >> 21 - s3 += carry[2] - s2 -= carry[2] << 21 - carry[3] = s3 >> 21 - s4 += carry[3] - s3 -= carry[3] << 21 - carry[4] = s4 >> 21 - s5 += carry[4] - s4 -= carry[4] << 21 - carry[5] = s5 >> 21 - s6 += carry[5] - s5 -= carry[5] << 21 - carry[6] = s6 >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[7] = s7 >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[8] = s8 >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[9] = s9 >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[10] = s10 >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - - s[0] = byte(s0 >> 0) - s[1] = byte(s0 >> 8) - s[2] = byte((s0 >> 16) | (s1 << 5)) - s[3] = byte(s1 >> 3) - s[4] = byte(s1 >> 11) - s[5] = byte((s1 >> 19) | (s2 << 2)) - s[6] = byte(s2 >> 6) - s[7] = byte((s2 >> 14) | (s3 << 7)) - s[8] = byte(s3 >> 1) - s[9] = byte(s3 >> 9) - s[10] = byte((s3 >> 17) | (s4 << 4)) - s[11] = byte(s4 >> 4) - s[12] = byte(s4 >> 12) - s[13] = byte((s4 >> 20) | (s5 << 1)) - s[14] = byte(s5 >> 7) - s[15] = byte((s5 >> 15) | (s6 << 6)) - s[16] = byte(s6 >> 2) - s[17] = byte(s6 >> 10) - s[18] = byte((s6 >> 18) | (s7 << 3)) - s[19] = byte(s7 >> 5) - s[20] = byte(s7 >> 13) - s[21] = byte(s8 >> 0) - s[22] = byte(s8 >> 8) - s[23] = byte((s8 >> 16) | (s9 << 5)) - s[24] = byte(s9 >> 3) - s[25] = byte(s9 >> 11) - s[26] = byte((s9 >> 19) | (s10 << 2)) - s[27] = byte(s10 >> 6) - s[28] = byte((s10 >> 14) | (s11 << 7)) - s[29] = byte(s11 >> 1) - s[30] = byte(s11 >> 9) - s[31] = byte(s11 >> 17) -} - -// Input: -// s[0]+256*s[1]+...+256^63*s[63] = s -// -// Output: -// s[0]+256*s[1]+...+256^31*s[31] = s mod l -// where l = 2^252 + 27742317777372353535851937790883648493. -func scReduce(out *Scalar, s *[64]byte) { - s0 := 2097151 & load3(s[:]) - s1 := 2097151 & (load4(s[2:]) >> 5) - s2 := 2097151 & (load3(s[5:]) >> 2) - s3 := 2097151 & (load4(s[7:]) >> 7) - s4 := 2097151 & (load4(s[10:]) >> 4) - s5 := 2097151 & (load3(s[13:]) >> 1) - s6 := 2097151 & (load4(s[15:]) >> 6) - s7 := 2097151 & (load3(s[18:]) >> 3) - s8 := 2097151 & load3(s[21:]) - s9 := 2097151 & (load4(s[23:]) >> 5) - s10 := 2097151 & (load3(s[26:]) >> 2) - s11 := 2097151 & (load4(s[28:]) >> 7) - s12 := 2097151 & (load4(s[31:]) >> 4) - s13 := 2097151 & (load3(s[34:]) >> 1) - s14 := 2097151 & (load4(s[36:]) >> 6) - s15 := 2097151 & (load3(s[39:]) >> 3) - s16 := 2097151 & load3(s[42:]) - s17 := 2097151 & (load4(s[44:]) >> 5) - s18 := 2097151 & (load3(s[47:]) >> 2) - s19 := 2097151 & (load4(s[49:]) >> 7) - s20 := 2097151 & (load4(s[52:]) >> 4) - s21 := 2097151 & (load3(s[55:]) >> 1) - s22 := 2097151 & (load4(s[57:]) >> 6) - s23 := (load4(s[60:]) >> 3) - - s11 += s23 * 666643 - s12 += s23 * 470296 - s13 += s23 * 654183 - s14 -= s23 * 997805 - s15 += s23 * 136657 - s16 -= s23 * 683901 - s23 = 0 - - s10 += s22 * 666643 - s11 += s22 * 470296 - s12 += s22 * 654183 - s13 -= s22 * 997805 - s14 += s22 * 136657 - s15 -= s22 * 683901 - s22 = 0 - - s9 += s21 * 666643 - s10 += s21 * 470296 - s11 += s21 * 654183 - s12 -= s21 * 997805 - s13 += s21 * 136657 - s14 -= s21 * 683901 - s21 = 0 - - s8 += s20 * 666643 - s9 += s20 * 470296 - s10 += s20 * 654183 - s11 -= s20 * 997805 - s12 += s20 * 136657 - s13 -= s20 * 683901 - s20 = 0 - - s7 += s19 * 666643 - s8 += s19 * 470296 - s9 += s19 * 654183 - s10 -= s19 * 997805 - s11 += s19 * 136657 - s12 -= s19 * 683901 - s19 = 0 - - s6 += s18 * 666643 - s7 += s18 * 470296 - s8 += s18 * 654183 - s9 -= s18 * 997805 - s10 += s18 * 136657 - s11 -= s18 * 683901 - s18 = 0 - - var carry [17]int64 - - carry[6] = (s6 + (1 << 20)) >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[8] = (s8 + (1 << 20)) >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[10] = (s10 + (1 << 20)) >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - carry[12] = (s12 + (1 << 20)) >> 21 - s13 += carry[12] - s12 -= carry[12] << 21 - carry[14] = (s14 + (1 << 20)) >> 21 - s15 += carry[14] - s14 -= carry[14] << 21 - carry[16] = (s16 + (1 << 20)) >> 21 - s17 += carry[16] - s16 -= carry[16] << 21 - - carry[7] = (s7 + (1 << 20)) >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[9] = (s9 + (1 << 20)) >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[11] = (s11 + (1 << 20)) >> 21 - s12 += carry[11] - s11 -= carry[11] << 21 - carry[13] = (s13 + (1 << 20)) >> 21 - s14 += carry[13] - s13 -= carry[13] << 21 - carry[15] = (s15 + (1 << 20)) >> 21 - s16 += carry[15] - s15 -= carry[15] << 21 - - s5 += s17 * 666643 - s6 += s17 * 470296 - s7 += s17 * 654183 - s8 -= s17 * 997805 - s9 += s17 * 136657 - s10 -= s17 * 683901 - s17 = 0 - - s4 += s16 * 666643 - s5 += s16 * 470296 - s6 += s16 * 654183 - s7 -= s16 * 997805 - s8 += s16 * 136657 - s9 -= s16 * 683901 - s16 = 0 - - s3 += s15 * 666643 - s4 += s15 * 470296 - s5 += s15 * 654183 - s6 -= s15 * 997805 - s7 += s15 * 136657 - s8 -= s15 * 683901 - s15 = 0 - - s2 += s14 * 666643 - s3 += s14 * 470296 - s4 += s14 * 654183 - s5 -= s14 * 997805 - s6 += s14 * 136657 - s7 -= s14 * 683901 - s14 = 0 - - s1 += s13 * 666643 - s2 += s13 * 470296 - s3 += s13 * 654183 - s4 -= s13 * 997805 - s5 += s13 * 136657 - s6 -= s13 * 683901 - s13 = 0 - - s0 += s12 * 666643 - s1 += s12 * 470296 - s2 += s12 * 654183 - s3 -= s12 * 997805 - s4 += s12 * 136657 - s5 -= s12 * 683901 - s12 = 0 - - carry[0] = (s0 + (1 << 20)) >> 21 - s1 += carry[0] - s0 -= carry[0] << 21 - carry[2] = (s2 + (1 << 20)) >> 21 - s3 += carry[2] - s2 -= carry[2] << 21 - carry[4] = (s4 + (1 << 20)) >> 21 - s5 += carry[4] - s4 -= carry[4] << 21 - carry[6] = (s6 + (1 << 20)) >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[8] = (s8 + (1 << 20)) >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[10] = (s10 + (1 << 20)) >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - - carry[1] = (s1 + (1 << 20)) >> 21 - s2 += carry[1] - s1 -= carry[1] << 21 - carry[3] = (s3 + (1 << 20)) >> 21 - s4 += carry[3] - s3 -= carry[3] << 21 - carry[5] = (s5 + (1 << 20)) >> 21 - s6 += carry[5] - s5 -= carry[5] << 21 - carry[7] = (s7 + (1 << 20)) >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[9] = (s9 + (1 << 20)) >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[11] = (s11 + (1 << 20)) >> 21 - s12 += carry[11] - s11 -= carry[11] << 21 - - s0 += s12 * 666643 - s1 += s12 * 470296 - s2 += s12 * 654183 - s3 -= s12 * 997805 - s4 += s12 * 136657 - s5 -= s12 * 683901 - s12 = 0 - - carry[0] = s0 >> 21 - s1 += carry[0] - s0 -= carry[0] << 21 - carry[1] = s1 >> 21 - s2 += carry[1] - s1 -= carry[1] << 21 - carry[2] = s2 >> 21 - s3 += carry[2] - s2 -= carry[2] << 21 - carry[3] = s3 >> 21 - s4 += carry[3] - s3 -= carry[3] << 21 - carry[4] = s4 >> 21 - s5 += carry[4] - s4 -= carry[4] << 21 - carry[5] = s5 >> 21 - s6 += carry[5] - s5 -= carry[5] << 21 - carry[6] = s6 >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[7] = s7 >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[8] = s8 >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[9] = s9 >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[10] = s10 >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - carry[11] = s11 >> 21 - s12 += carry[11] - s11 -= carry[11] << 21 - - s0 += s12 * 666643 - s1 += s12 * 470296 - s2 += s12 * 654183 - s3 -= s12 * 997805 - s4 += s12 * 136657 - s5 -= s12 * 683901 - s12 = 0 - - carry[0] = s0 >> 21 - s1 += carry[0] - s0 -= carry[0] << 21 - carry[1] = s1 >> 21 - s2 += carry[1] - s1 -= carry[1] << 21 - carry[2] = s2 >> 21 - s3 += carry[2] - s2 -= carry[2] << 21 - carry[3] = s3 >> 21 - s4 += carry[3] - s3 -= carry[3] << 21 - carry[4] = s4 >> 21 - s5 += carry[4] - s4 -= carry[4] << 21 - carry[5] = s5 >> 21 - s6 += carry[5] - s5 -= carry[5] << 21 - carry[6] = s6 >> 21 - s7 += carry[6] - s6 -= carry[6] << 21 - carry[7] = s7 >> 21 - s8 += carry[7] - s7 -= carry[7] << 21 - carry[8] = s8 >> 21 - s9 += carry[8] - s8 -= carry[8] << 21 - carry[9] = s9 >> 21 - s10 += carry[9] - s9 -= carry[9] << 21 - carry[10] = s10 >> 21 - s11 += carry[10] - s10 -= carry[10] << 21 - - out[0] = byte(s0 >> 0) - out[1] = byte(s0 >> 8) - out[2] = byte((s0 >> 16) | (s1 << 5)) - out[3] = byte(s1 >> 3) - out[4] = byte(s1 >> 11) - out[5] = byte((s1 >> 19) | (s2 << 2)) - out[6] = byte(s2 >> 6) - out[7] = byte((s2 >> 14) | (s3 << 7)) - out[8] = byte(s3 >> 1) - out[9] = byte(s3 >> 9) - out[10] = byte((s3 >> 17) | (s4 << 4)) - out[11] = byte(s4 >> 4) - out[12] = byte(s4 >> 12) - out[13] = byte((s4 >> 20) | (s5 << 1)) - out[14] = byte(s5 >> 7) - out[15] = byte((s5 >> 15) | (s6 << 6)) - out[16] = byte(s6 >> 2) - out[17] = byte(s6 >> 10) - out[18] = byte((s6 >> 18) | (s7 << 3)) - out[19] = byte(s7 >> 5) - out[20] = byte(s7 >> 13) - out[21] = byte(s8 >> 0) - out[22] = byte(s8 >> 8) - out[23] = byte((s8 >> 16) | (s9 << 5)) - out[24] = byte(s9 >> 3) - out[25] = byte(s9 >> 11) - out[26] = byte((s9 >> 19) | (s10 << 2)) - out[27] = byte(s10 >> 6) - out[28] = byte((s10 >> 14) | (s11 << 7)) - out[29] = byte(s11 >> 1) - out[30] = byte(s11 >> 9) - out[31] = byte(s11 >> 17) -} - -// order is the order of Curve25519 in little-endian form. -var order = [4]uint64{0x5812631a5cf5d3ed, 0x14def9dea2f79cd6, 0, 0x1000000000000000} - -// scMinimal returns true if the given scalar is less than the order of the -// curve. -func scMinimal(sc []byte) bool { - for i := 3; ; i-- { - v := binary.LittleEndian.Uint64(sc[i*8:]) - if v > order[i] { - return false - } else if v < order[i] { - break - } else if i == 0 { - return false - } - } - - return true -} - -// NonAdjacentForm computes a width-w non-adjacent form for this scalar. -func (s *Scalar) NonAdjacentForm(w uint) [256]int8 { - // This implementation is adapted from the one - // in curve25519-dalek and is documented there: - // https://github.com/dalek-cryptography/curve25519-dalek/blob/f630041af28e9a405255f98a8a93adca18e4315b/src/scalar.rs#L800-L871 - if s[31] > 127 { - panic("scalar has high bit set illegally") - } - if w < 2 { - panic("w must be at least 2 by the definition of NAF") - } else if w > 8 { - panic("NAF digits must fit in int8") - } - - var naf [256]int8 - var digits [5]uint64 - - for i := 0; i < 4; i++ { - digits[i] = binary.LittleEndian.Uint64(s[i*8:]) - } - - width := uint64(1 << w) - windowMask := uint64(width - 1) - - pos := uint(0) - carry := uint64(0) - for pos < 256 { - indexU64 := pos / 64 - indexBit := pos % 64 - var bitBuf uint64 - if indexBit < 64-w { - // This window's bits are contained in a single u64 - bitBuf = digits[indexU64] >> indexBit - } else { - // Combine the current 64 bits with bits from the next 64 - bitBuf = (digits[indexU64] >> indexBit) | (digits[1+indexU64] << (64 - indexBit)) - } - - // Add carry into the current window - window := carry + (bitBuf & windowMask) - - if window&1 == 0 { - // If the window value is even, preserve the carry and continue. - // Why is the carry preserved? - // If carry == 0 and window & 1 == 0, - // then the next carry should be 0 - // If carry == 1 and window & 1 == 0, - // then bit_buf & 1 == 1 so the next carry should be 1 - pos += 1 - continue - } - - if window < width/2 { - carry = 0 - naf[pos] = int8(window) - } else { - carry = 1 - naf[pos] = int8(window) - int8(width) - } - - pos += w - } - return naf -} - -func (s *Scalar) SignedRadix16() [64]int8 { - if s[31] > 127 { - panic("scalar has high bit set illegally") - } - - var digits [64]int8 - - // Compute unsigned radix-16 digits: - for i := 0; i < 32; i++ { - digits[2*i] = int8(s[i] & 15) - digits[2*i+1] = int8((s[i] >> 4) & 15) - } - - // Recenter coefficients: - for i := 0; i < 63; i++ { - carry := (digits[i] + 8) >> 4 - digits[i] -= carry << 4 - digits[i+1] += carry - } - - return digits -} - -// Given k > 0, set s = s**(2*i). -func (s *Scalar) pow2k(k int) { - for i := 0; i < k; i++ { - s.Mul(s, s) - } -} - -// Inv sets s to the inverse of a nonzero scalar v and returns s. -func (s *Scalar) Inv(t *Scalar) *Scalar { - // Uses a hardcoded sliding window of width 4. - var table [8]Scalar - var tt Scalar - tt.Mul(t, t) - table[0] = *t - for i := 0; i < 7; i++ { - table[i+1].Mul(&table[i], &tt) - } - // Now table = [t**1, t**3, t**7, t**11, t**13, t**15] - // so t**k = t[k/2] for odd k - - // To compute the sliding window digits, use the following Sage script: - - // sage: import itertools - // sage: def sliding_window(w,k): - // ....: digits = [] - // ....: while k > 0: - // ....: if k % 2 == 1: - // ....: kmod = k % (2**w) - // ....: digits.append(kmod) - // ....: k = k - kmod - // ....: else: - // ....: digits.append(0) - // ....: k = k // 2 - // ....: return digits - - // Now we can compute s roughly as follows: - - // sage: s = 1 - // sage: for coeff in reversed(sliding_window(4,l-2)): - // ....: s = s*s - // ....: if coeff > 0 : - // ....: s = s*t**coeff - - // This works on one bit at a time, with many runs of zeros. - // The digits can be collapsed into [(count, coeff)] as follows: - - // sage: [(len(list(group)),d) for d,group in itertools.groupby(sliding_window(4,l-2))] - - // Entries of the form (k, 0) turn into pow2k(k) - // Entries of the form (1, coeff) turn into a squaring and then a table lookup. - // We can fold the squaring into the previous pow2k(k) as pow2k(k+1). - - *s = table[1/2] - s.pow2k(127 + 1) - s.Mul(s, &table[1/2]) - s.pow2k(4 + 1) - s.Mul(s, &table[9/2]) - s.pow2k(3 + 1) - s.Mul(s, &table[11/2]) - s.pow2k(3 + 1) - s.Mul(s, &table[13/2]) - s.pow2k(3 + 1) - s.Mul(s, &table[15/2]) - s.pow2k(4 + 1) - s.Mul(s, &table[7/2]) - s.pow2k(4 + 1) - s.Mul(s, &table[15/2]) - s.pow2k(3 + 1) - s.Mul(s, &table[5/2]) - s.pow2k(3 + 1) - s.Mul(s, &table[1/2]) - s.pow2k(4 + 1) - s.Mul(s, &table[15/2]) - s.pow2k(4 + 1) - s.Mul(s, &table[15/2]) - s.pow2k(4 + 1) - s.Mul(s, &table[7/2]) - s.pow2k(3 + 1) - s.Mul(s, &table[3/2]) - s.pow2k(4 + 1) - s.Mul(s, &table[11/2]) - s.pow2k(5 + 1) - s.Mul(s, &table[11/2]) - s.pow2k(9 + 1) - s.Mul(s, &table[9/2]) - s.pow2k(3 + 1) - s.Mul(s, &table[3/2]) - s.pow2k(4 + 1) - s.Mul(s, &table[3/2]) - s.pow2k(4 + 1) - s.Mul(s, &table[3/2]) - s.pow2k(4 + 1) - s.Mul(s, &table[9/2]) - s.pow2k(3 + 1) - s.Mul(s, &table[7/2]) - s.pow2k(3 + 1) - s.Mul(s, &table[3/2]) - s.pow2k(3 + 1) - s.Mul(s, &table[13/2]) - s.pow2k(3 + 1) - s.Mul(s, &table[7/2]) - s.pow2k(4 + 1) - s.Mul(s, &table[9/2]) - s.pow2k(3 + 1) - s.Mul(s, &table[15/2]) - s.pow2k(4 + 1) - s.Mul(s, &table[11/2]) - - return s -} diff --git a/internal/scalar/scalar_test.go b/internal/scalar/scalar_test.go deleted file mode 100644 index df3648b..0000000 --- a/internal/scalar/scalar_test.go +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright 2019 Henry de Valence. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package scalar - -import ( - "bytes" - "math/big" - "testing" - "testing/quick" -) - -// quickCheckConfig will make each quickcheck test run (1024 * -quickchecks) -// times. The default value of -quickchecks is 100. -var quickCheckConfig = &quick.Config{MaxCountScale: 1 << 10} - -func TestFromBytesRoundTrip(t *testing.T) { - f1 := func(in, out [32]byte, sc Scalar) bool { - in[len(in)-1] &= (1 << 4) - 1 // Mask out top 4 bits for 252-bit numbers - if err := sc.FromCanonicalBytes(in[:]); err != nil { - return false - } - sc.Bytes(out[:0]) - return bytes.Equal(in[:], out[:]) && scMinimal(sc[:]) - } - if err := quick.Check(f1, nil); err != nil { - t.Errorf("failed bytes->scalar->bytes round-trip: %v", err) - } - - f2 := func(sc1, sc2 Scalar, out [32]byte) bool { - sc1.Bytes(out[:0]) - if err := sc2.FromCanonicalBytes(out[:]); err != nil { - return false - } - - sc1.reduce() - sc2.reduce() - return sc1 == sc2 - } - if err := quick.Check(f2, nil); err != nil { - t.Errorf("failed scalar->bytes->scalar round-trip: %v", err) - } -} - -func TestFromUniformBytes(t *testing.T) { - mod, _ := new(big.Int).SetString("27742317777372353535851937790883648493", 10) - mod.Add(mod, new(big.Int).Lsh(big.NewInt(1), 252)) - f := func(in [64]byte, sc Scalar) bool { - sc.FromUniformBytes(in[:]) - if !scMinimal(sc[:]) { - return false - } - b := sc.Bytes(nil) - byteSwap(b) // convert to big endian for SetBytes - scBig := new(big.Int).SetBytes(b) - byteSwap(in[:]) // convert to big endian for SetBytes - inBig := new(big.Int).SetBytes(in[:]) - return inBig.Mod(inBig, mod).Cmp(scBig) == 0 - } - if err := quick.Check(f, nil); err != nil { - t.Error(err) - } -} - -func byteSwap(b []byte) { - for i := range b[:len(b)/2] { - b[i], b[len(b)-i-1] = b[len(b)-i-1], b[i] - } -} - -func TestMulDistributesOverAdd(t *testing.T) { - mulDistributesOverAdd := func(x, y, z Scalar) bool { - // Compute t1 = (x+y)*z - var t1 Scalar - t1.Add(&x, &y) - t1.Mul(&t1, &z) - - // Compute t2 = x*z + y*z - var t2 Scalar - var t3 Scalar - t2.Mul(&x, &z) - t3.Mul(&y, &z) - t2.Add(&t2, &t3) - - return t1.Equal(&t2) == 1 && scMinimal(t1[:]) && scMinimal(t2[:]) - } - - if err := quick.Check(mulDistributesOverAdd, quickCheckConfig); err != nil { - t.Error(err) - } -} - -func TestNonAdjacentForm(t *testing.T) { - s := Scalar([32]byte{ - 0x1a, 0x0e, 0x97, 0x8a, 0x90, 0xf6, 0x62, 0x2d, - 0x37, 0x47, 0x02, 0x3f, 0x8a, 0xd8, 0x26, 0x4d, - 0xa7, 0x58, 0xaa, 0x1b, 0x88, 0xe0, 0x40, 0xd1, - 0x58, 0x9e, 0x7b, 0x7f, 0x23, 0x76, 0xef, 0x09, - }) - expectedNaf := [256]int8{ - 0, 13, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, -9, 0, 0, 0, 0, -11, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1, - 0, 0, 0, 0, 9, 0, 0, 0, 0, -5, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 11, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, - -9, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 9, 0, - 0, 0, 0, -15, 0, 0, 0, 0, -7, 0, 0, 0, 0, -9, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, -3, 0, - 0, 0, 0, -11, 0, 0, 0, 0, -7, 0, 0, 0, 0, -13, 0, 0, 0, 0, 11, 0, 0, 0, 0, -9, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, -15, 0, 0, 0, 0, 1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 13, 0, 0, 0, - 0, 0, 0, 11, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, -9, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 7, - 0, 0, 0, 0, 0, -15, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 15, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, - } - - sNaf := s.NonAdjacentForm(5) - - for i := 0; i < 256; i++ { - if expectedNaf[i] != sNaf[i] { - t.Errorf("Wrong digit at position %d, got %d, expected %d", i, sNaf[i], expectedNaf[i]) - } - } -} - -func TestInvert(t *testing.T) { - invertWorks := func(x Scalar) bool { - var xInv, check Scalar - xInv.Inv(&x) - check.Mul(&x, &xInv) - - return check.Equal(&scOne) == 1 - } - - if err := quick.Check(invertWorks, quickCheckConfig); err != nil { - t.Error(err) - } -} diff --git a/ristretto255.go b/ristretto255.go index 03ad57c..e88474b 100644 --- a/ristretto255.go +++ b/ristretto255.go @@ -17,28 +17,61 @@ import ( "encoding/base64" "errors" - "github.com/gtank/ristretto255/internal/edwards25519" - "github.com/gtank/ristretto255/internal/radix51" - "github.com/gtank/ristretto255/internal/scalar" + "filippo.io/edwards25519" + "filippo.io/edwards25519/field" ) -// Constants from draft-hdevalence-cfrg-ristretto-01, Section 3.1. +// Constants from draft-hdevalence-cfrg-ristretto-01, Section 3.1. See +// TestConstants for their decimal values. var ( - sqrtM1 = fieldElementFromDecimal( - "19681161376707505956807079304988542015446066515923890162744021073123829784752") - sqrtADMinusOne = fieldElementFromDecimal( - "25063068953384623474111414158702152701244531502492656460079210482610430750235") - invSqrtAMinusD = fieldElementFromDecimal( - "54469307008909316920995813868745141605393597292927456921205312896311721017578") - oneMinusDSQ = fieldElementFromDecimal( - "1159843021668779879193775521855586647937357759715417654439879720876111806838") - dMinusOneSQ = fieldElementFromDecimal( - "40440834346308536858101042469323190826248399146238708352240133220865137265952") + d, _ = new(field.Element).SetBytes([]byte{ + 0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75, + 0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00, + 0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c, + 0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52, + }) + sqrtM1, _ = new(field.Element).SetBytes([]byte{ + 0xb0, 0xa0, 0x0e, 0x4a, 0x27, 0x1b, 0xee, 0xc4, + 0x78, 0xe4, 0x2f, 0xad, 0x06, 0x18, 0x43, 0x2f, + 0xa7, 0xd7, 0xfb, 0x3d, 0x99, 0x00, 0x4d, 0x2b, + 0x0b, 0xdf, 0xc1, 0x4f, 0x80, 0x24, 0x83, 0x2b, + }) + sqrtADMinusOne, _ = new(field.Element).SetBytes([]byte{ + 0x1b, 0x2e, 0x7b, 0x49, 0xa0, 0xf6, 0x97, 0x7e, + 0xbd, 0x54, 0x78, 0x1b, 0x0c, 0x8e, 0x9d, 0xaf, + 0xfd, 0xd1, 0xf5, 0x31, 0xc9, 0xfc, 0x3c, 0x0f, + 0xac, 0x48, 0x83, 0x2b, 0xbf, 0x31, 0x69, 0x37, + }) + invSqrtAMinusD, _ = new(field.Element).SetBytes([]byte{ + 0xea, 0x40, 0x5d, 0x80, 0xaa, 0xfd, 0xc8, 0x99, + 0xbe, 0x72, 0x41, 0x5a, 0x17, 0x16, 0x2f, 0x9d, + 0x40, 0xd8, 0x01, 0xfe, 0x91, 0x7b, 0xc2, 0x16, + 0xa2, 0xfc, 0xaf, 0xcf, 0x05, 0x89, 0x6c, 0x78, + }) + oneMinusDSQ, _ = new(field.Element).SetBytes([]byte{ + 0x76, 0xc1, 0x5f, 0x94, 0xc1, 0x09, 0x7c, 0xe2, + 0x0f, 0x35, 0x5e, 0xcd, 0x38, 0xa1, 0x81, 0x2c, + 0xe4, 0xdf, 0x70, 0xbe, 0xdd, 0xab, 0x94, 0x99, + 0xd7, 0xe0, 0xb3, 0xb2, 0xa8, 0x72, 0x90, 0x02, + }) + dMinusOneSQ, _ = new(field.Element).SetBytes([]byte{ + 0x20, 0x4d, 0xed, 0x44, 0xaa, 0x5a, 0xad, 0x31, + 0x99, 0x19, 0x1e, 0xb0, 0x2c, 0x4a, 0x9e, 0xd2, + 0xeb, 0x4e, 0x9b, 0x52, 0x2f, 0xd3, 0xdc, 0x4c, + 0x41, 0x22, 0x6c, 0xf6, 0x7a, 0xb3, 0x68, 0x59, + }) +) + +var ( + zero = new(field.Element) + one = new(field.Element).One() + two = new(field.Element).Add(one, one) + minusOne = new(field.Element).Subtract(zero, one) ) // Element is an element of the ristretto255 prime-order group. type Element struct { - r edwards25519.ProjP3 + r edwards25519.Point } // NewElement returns a new Element set to the identity value. @@ -51,14 +84,14 @@ func NewElement() *Element { // NewIdentityElement returns a new Element set to the identity value. func NewIdentityElement() *Element { e := &Element{} - e.r.Zero() + e.r.Set(edwards25519.NewIdentityPoint()) return e } // NewGeneratorElement returns a new Element set to the canonical generator. func NewGeneratorElement() *Element { e := &Element{} - e.r.Set(&edwards25519.B) + e.r.Set(edwards25519.NewGeneratorPoint()) return e } @@ -72,14 +105,17 @@ func (e *Element) Set(x *Element) *Element { // // Note that Elements must not be compared in any other way. func (e *Element) Equal(ee *Element) int { - var f0, f1 radix51.FieldElement + X1, Y1, _, _ := e.r.ExtendedCoordinates() + X2, Y2, _, _ := ee.r.ExtendedCoordinates() - f0.Mul(&e.r.X, &ee.r.Y) // x1 * y2 - f1.Mul(&e.r.Y, &ee.r.X) // y1 * x2 + var f0, f1 field.Element + + f0.Multiply(X1, Y2) // x1 * y2 + f1.Multiply(Y1, X2) // y1 * x2 out := f0.Equal(&f1) - f0.Mul(&e.r.Y, &ee.r.Y) // y1 * y2 - f1.Mul(&e.r.X, &ee.r.X) // x1 * x2 + f0.Multiply(Y1, Y2) // y1 * y2 + f1.Multiply(X1, X2) // x1 * x2 out = out | f0.Equal(&f1) return out @@ -106,13 +142,13 @@ func (e *Element) SetUniformBytes(b []byte) (*Element, error) { return nil, errors.New("ristretto255: SetUniformBytes input is not 64 bytes long") } - f := &radix51.FieldElement{} + f := &field.Element{} - f.FromBytes(b[:32]) + f.SetBytes(b[:32]) point1 := &Element{} mapToPoint(&point1.r, f) - f.FromBytes(b[32:]) + f.SetBytes(b[32:]) point2 := &Element{} mapToPoint(&point2.r, f) @@ -120,32 +156,32 @@ func (e *Element) SetUniformBytes(b []byte) (*Element, error) { } // mapToPoint implements MAP from Section 3.2.4 of draft-hdevalence-cfrg-ristretto-00. -func mapToPoint(out *edwards25519.ProjP3, t *radix51.FieldElement) { +func mapToPoint(out *edwards25519.Point, t *field.Element) { // r = SQRT_M1 * t^2 - r := &radix51.FieldElement{} - r.Mul(sqrtM1, r.Square(t)) + r := &field.Element{} + r.Multiply(sqrtM1, r.Square(t)) // u = (r + 1) * ONE_MINUS_D_SQ - u := &radix51.FieldElement{} - u.Mul(u.Add(r, radix51.One), oneMinusDSQ) + u := &field.Element{} + u.Multiply(u.Add(r, one), oneMinusDSQ) // c = -1 - c := &radix51.FieldElement{} - c.Set(radix51.MinusOne) + c := &field.Element{} + c.Set(minusOne) // v = (c - r*D) * (r + D) - rPlusD := &radix51.FieldElement{} - rPlusD.Add(r, edwards25519.D) - v := &radix51.FieldElement{} - v.Mul(v.Sub(c, v.Mul(r, edwards25519.D)), rPlusD) + rPlusD := &field.Element{} + rPlusD.Add(r, d) + v := &field.Element{} + v.Multiply(v.Subtract(c, v.Multiply(r, d)), rPlusD) // (was_square, s) = SQRT_RATIO_M1(u, v) - s := &radix51.FieldElement{} - wasSquare := feSqrtRatio(s, u, v) + s := &field.Element{} + _, wasSquare := s.SqrtRatio(u, v) // s_prime = -CT_ABS(s*t) - sPrime := &radix51.FieldElement{} - sPrime.Neg(sPrime.Abs(sPrime.Mul(s, t))) + sPrime := &field.Element{} + sPrime.Negate(sPrime.Absolute(sPrime.Multiply(s, t))) // s = CT_SELECT(s IF was_square ELSE s_prime) s.Select(s, sPrime, wasSquare) @@ -153,31 +189,35 @@ func mapToPoint(out *edwards25519.ProjP3, t *radix51.FieldElement) { c.Select(c, r, wasSquare) // N = c * (r - 1) * D_MINUS_ONE_SQ - v - N := &radix51.FieldElement{} - N.Mul(c, N.Sub(r, radix51.One)) - N.Sub(N.Mul(N, dMinusOneSQ), v) + N := &field.Element{} + N.Multiply(c, N.Subtract(r, one)) + N.Subtract(N.Multiply(N, dMinusOneSQ), v) - s2 := &radix51.FieldElement{} + s2 := &field.Element{} s2.Square(s) // w0 = 2 * s * v - w0 := &radix51.FieldElement{} - w0.Add(w0, w0.Mul(s, v)) + w0 := &field.Element{} + w0.Add(w0, w0.Multiply(s, v)) // w1 = N * SQRT_AD_MINUS_ONE - w1 := &radix51.FieldElement{} - w1.Mul(N, sqrtADMinusOne) + w1 := &field.Element{} + w1.Multiply(N, sqrtADMinusOne) // w2 = 1 - s^2 - w2 := &radix51.FieldElement{} - w2.Sub(radix51.One, s2) + w2 := &field.Element{} + w2.Subtract(one, s2) // w3 = 1 + s^2 - w3 := &radix51.FieldElement{} - w3.Add(radix51.One, s2) + w3 := &field.Element{} + w3.Add(one, s2) // return (w0*w3, w2*w1, w1*w3, w0*w2) - out.X.Mul(w0, w3) - out.Y.Mul(w2, w1) - out.Z.Mul(w1, w3) - out.T.Mul(w0, w2) + var X, Y, Z, T field.Element + X.Multiply(w0, w3) + Y.Multiply(w2, w1) + Z.Multiply(w1, w3) + T.Multiply(w0, w2) + if _, err := out.SetExtendedCoordinates(&X, &Y, &Z, &T); err != nil { + panic("ristretto255: internal error: MAP generated invalid coordinates") + } } // Encode appends the 32 bytes canonical encoding of e to b @@ -185,75 +225,95 @@ func mapToPoint(out *edwards25519.ProjP3, t *radix51.FieldElement) { // // Deprecated: use Bytes. This API will be removed before v1.0.0. func (e *Element) Encode(b []byte) []byte { - return e.bytes(b) + ret, out := sliceForAppend(b, 32) + e.bytes(out) + return ret +} + +// sliceForAppend takes a slice and a requested number of bytes. It returns a +// slice with the contents of the given slice followed by that many bytes and a +// second slice that aliases into it and contains only the extra bytes. If the +// original slice has sufficient capacity then no allocation is performed. +func sliceForAppend(in []byte, n int) (head, tail []byte) { + if total := len(in) + n; cap(in) >= total { + head = in[:total] + } else { + head = make([]byte, total) + copy(head, in) + } + tail = head[len(in):] + return } // Bytes returns the 32 bytes canonical encoding of e. func (e *Element) Bytes() []byte { // Bytes is outlined to let the allocation happen on the stack of the caller. - b := make([]byte, 0, 32) + b := make([]byte, 32) return e.bytes(b) } func (e *Element) bytes(b []byte) []byte { - tmp := &radix51.FieldElement{} + X, Y, Z, T := e.r.ExtendedCoordinates() + tmp := &field.Element{} // u1 = (z0 + y0) * (z0 - y0) - u1 := &radix51.FieldElement{} - u1.Add(&e.r.Z, &e.r.Y).Mul(u1, tmp.Sub(&e.r.Z, &e.r.Y)) + u1 := &field.Element{} + u1.Add(Z, Y).Multiply(u1, tmp.Subtract(Z, Y)) // u2 = x0 * y0 - u2 := &radix51.FieldElement{} - u2.Mul(&e.r.X, &e.r.Y) + u2 := &field.Element{} + u2.Multiply(X, Y) // Ignore was_square since this is always square // (_, invsqrt) = SQRT_RATIO_M1(1, u1 * u2^2) - invSqrt := &radix51.FieldElement{} - feSqrtRatio(invSqrt, radix51.One, tmp.Square(u2).Mul(tmp, u1)) + invSqrt := &field.Element{} + invSqrt.SqrtRatio(one, tmp.Square(u2).Multiply(tmp, u1)) // den1 = invsqrt * u1 // den2 = invsqrt * u2 - den1, den2 := &radix51.FieldElement{}, &radix51.FieldElement{} - den1.Mul(invSqrt, u1) - den2.Mul(invSqrt, u2) + den1, den2 := &field.Element{}, &field.Element{} + den1.Multiply(invSqrt, u1) + den2.Multiply(invSqrt, u2) // z_inv = den1 * den2 * t0 - zInv := &radix51.FieldElement{} - zInv.Mul(den1, den2).Mul(zInv, &e.r.T) + zInv := &field.Element{} + zInv.Multiply(den1, den2).Multiply(zInv, T) // ix0 = x0 * SQRT_M1 // iy0 = y0 * SQRT_M1 - ix0, iy0 := &radix51.FieldElement{}, &radix51.FieldElement{} - ix0.Mul(&e.r.X, sqrtM1) - iy0.Mul(&e.r.Y, sqrtM1) + ix0, iy0 := &field.Element{}, &field.Element{} + ix0.Multiply(X, sqrtM1) + iy0.Multiply(Y, sqrtM1) // enchanted_denominator = den1 * INVSQRT_A_MINUS_D - enchantedDenominator := &radix51.FieldElement{} - enchantedDenominator.Mul(den1, invSqrtAMinusD) + enchantedDenominator := &field.Element{} + enchantedDenominator.Multiply(den1, invSqrtAMinusD) // rotate = IS_NEGATIVE(t0 * z_inv) - rotate := tmp.Mul(&e.r.T, zInv).IsNegative() + rotate := tmp.Multiply(T, zInv).IsNegative() // x = CT_SELECT(iy0 IF rotate ELSE x0) // y = CT_SELECT(ix0 IF rotate ELSE y0) - x, y := &radix51.FieldElement{}, &radix51.FieldElement{} - x.Select(iy0, &e.r.X, rotate) - y.Select(ix0, &e.r.Y, rotate) + x, y := &field.Element{}, &field.Element{} + x.Select(iy0, X, rotate) + y.Select(ix0, Y, rotate) // z = z0 - z := &e.r.Z + z := Z // den_inv = CT_SELECT(enchanted_denominator IF rotate ELSE den2) - denInv := &radix51.FieldElement{} + denInv := &field.Element{} denInv.Select(enchantedDenominator, den2, rotate) // y = CT_NEG(y, IS_NEGATIVE(x * z_inv)) - y.CondNeg(y, tmp.Mul(x, zInv).IsNegative()) + isNegative := tmp.Multiply(x, zInv).IsNegative() + y.Select(tmp.Negate(y), y, isNegative) // s = CT_ABS(den_inv * (z - y)) - s := tmp.Sub(z, y).Mul(tmp, denInv).Abs(tmp) + s := tmp.Subtract(z, y).Multiply(tmp, denInv).Absolute(tmp) // Return the canonical little-endian encoding of s. - return s.Bytes(b) + copy(b, s.Bytes()) + return b } -var errInvalidEncoding = errors.New("invalid Ristretto encoding") +var errInvalidEncoding = errors.New("ristretto255: invalid element encoding") // Decode sets e to the decoded value of in. If in is not a 32 byte canonical // encoding, Decode returns an error, and the receiver is unchanged. @@ -273,12 +333,11 @@ func (e *Element) SetCanonicalBytes(in []byte) (*Element, error) { } // First, interpret the string as an integer s in little-endian representation. - s := &radix51.FieldElement{} - s.FromBytes(in) + s := &field.Element{} + s.SetBytes(in) // If the resulting value is >= p, decoding fails. - var buf [32]byte - if !bytes.Equal(s.Bytes(buf[:0]), in) { + if !bytes.Equal(s.Bytes(), in) { return nil, errInvalidEncoding } @@ -288,63 +347,65 @@ func (e *Element) SetCanonicalBytes(in []byte) (*Element, error) { } // ss = s^2 - sSqr := &radix51.FieldElement{} + sSqr := &field.Element{} sSqr.Square(s) // u1 = 1 - ss - u1 := &radix51.FieldElement{} - u1.Sub(radix51.One, sSqr) + u1 := &field.Element{} + u1.Subtract(one, sSqr) // u2 = 1 + ss - u2 := &radix51.FieldElement{} - u2.Add(radix51.One, sSqr) + u2 := &field.Element{} + u2.Add(one, sSqr) // u2_sqr = u2^2 - u2Sqr := &radix51.FieldElement{} + u2Sqr := &field.Element{} u2Sqr.Square(u2) // v = -(D * u1^2) - u2_sqr - v := &radix51.FieldElement{} - v.Square(u1).Mul(v, edwards25519.D).Neg(v).Sub(v, u2Sqr) + v := &field.Element{} + v.Square(u1).Multiply(v, d).Negate(v).Subtract(v, u2Sqr) // (was_square, invsqrt) = SQRT_RATIO_M1(1, v * u2_sqr) - invSqrt, tmp := &radix51.FieldElement{}, &radix51.FieldElement{} - wasSquare := feSqrtRatio(invSqrt, radix51.One, tmp.Mul(v, u2Sqr)) + invSqrt, tmp := &field.Element{}, &field.Element{} + _, wasSquare := invSqrt.SqrtRatio(one, tmp.Multiply(v, u2Sqr)) // den_x = invsqrt * u2 // den_y = invsqrt * den_x * v - denX, denY := &radix51.FieldElement{}, &radix51.FieldElement{} - denX.Mul(invSqrt, u2) - denY.Mul(invSqrt, denX).Mul(denY, v) + denX, denY := &field.Element{}, &field.Element{} + denX.Multiply(invSqrt, u2) + denY.Multiply(invSqrt, denX).Multiply(denY, v) // x = CT_ABS(2 * s * den_x) // y = u1 * den_y // t = x * y - var out edwards25519.ProjP3 - out.X.Mul(radix51.Two, s).Mul(&out.X, denX).Abs(&out.X) - out.Y.Mul(u1, denY) - out.Z.One() - out.T.Mul(&out.X, &out.Y) + var X, Y, Z, T field.Element + X.Multiply(two, s).Multiply(&X, denX).Absolute(&X) + Y.Multiply(u1, denY) + Z.One() + T.Multiply(&X, &Y) // If was_square is FALSE, or IS_NEGATIVE(t) returns TRUE, or y = 0, decoding fails. - if wasSquare == 0 || out.T.IsNegative() == 1 || out.Y.Equal(radix51.Zero) == 1 { + if wasSquare == 0 || T.IsNegative() == 1 || Y.Equal(zero) == 1 { return nil, errInvalidEncoding } // Otherwise, return the internal representation in extended coordinates (x, y, 1, t). - e.r.Set(&out) + if _, err := e.r.SetExtendedCoordinates(&X, &Y, &Z, &T); err != nil { + panic("ristretto255: internal error: DECODE generated invalid coordinates") + } return e, nil } // ScalarBaseMult sets e = s * B, where B is the canonical generator, and returns e. func (e *Element) ScalarBaseMult(s *Scalar) *Element { - e.r.BasepointMul(&s.s) + e.r.ScalarBaseMult(&s.s) return e } // ScalarMult sets e = s * p, and returns e. func (e *Element) ScalarMult(s *Scalar, p *Element) *Element { - e.r.ScalarMul(&s.s, &p.r) + e.r.ScalarMult(&s.s, &p.r) return e } @@ -355,13 +416,13 @@ func (e *Element) MultiScalarMult(s []*Scalar, p []*Element) *Element { if len(p) != len(s) { panic("ristretto255: MultiScalarMult invoked with mismatched slice lengths") } - points := make([]*edwards25519.ProjP3, len(p)) - scalars := make([]scalar.Scalar, len(s)) + points := make([]*edwards25519.Point, len(p)) + scalars := make([]*edwards25519.Scalar, len(s)) for i := range s { points[i] = &p[i].r - scalars[i] = s[i].s + scalars[i] = &s[i].s } - e.r.MultiscalarMul(scalars, points) + e.r.MultiScalarMult(scalars, points) return e } @@ -370,15 +431,15 @@ func (e *Element) MultiScalarMult(s []*Scalar, p []*Element) *Element { // Execution time depends on the inputs. func (e *Element) VarTimeMultiScalarMult(s []*Scalar, p []*Element) *Element { if len(p) != len(s) { - panic("ristretto255: MultiScalarMult invoked with mismatched slice lengths") + panic("ristretto255: VarTimeMultiScalarMult invoked with mismatched slice lengths") } - points := make([]*edwards25519.ProjP3, len(p)) - scalars := make([]scalar.Scalar, len(s)) + points := make([]*edwards25519.Point, len(p)) + scalars := make([]*edwards25519.Scalar, len(s)) for i := range s { points[i] = &p[i].r - scalars[i] = s[i].s + scalars[i] = &s[i].s } - e.r.VartimeMultiscalarMul(scalars, points) + e.r.VarTimeMultiScalarMult(scalars, points) return e } @@ -387,7 +448,7 @@ func (e *Element) VarTimeMultiScalarMult(s []*Scalar, p []*Element) *Element { // // Execution time depends on the inputs. func (e *Element) VarTimeDoubleScalarBaseMult(a *Scalar, A *Element, b *Scalar) *Element { - e.r.VartimeDoubleBaseMul(&a.s, &A.r, &b.s) + e.r.VarTimeDoubleScalarBaseMult(&a.s, &A.r, &b.s) return e } @@ -399,13 +460,13 @@ func (e *Element) Add(p, q *Element) *Element { // Subtract sets e = p - q, and returns e. func (e *Element) Subtract(p, q *Element) *Element { - e.r.Sub(&p.r, &q.r) + e.r.Subtract(&p.r, &q.r) return e } // Negate sets e = -p, and returns e. func (e *Element) Negate(p *Element) *Element { - e.r.Neg(&p.r) + e.r.Negate(&p.r) return e } diff --git a/ristretto255_test.go b/ristretto255_test.go index 18a6834..c6a9f53 100644 --- a/ristretto255_test.go +++ b/ristretto255_test.go @@ -5,68 +5,12 @@ import ( "crypto/sha512" "encoding/hex" "encoding/json" + "math/big" "testing" - "github.com/gtank/ristretto255/internal/radix51" + "filippo.io/edwards25519/field" ) -func assertFeEqual(value, expect *radix51.FieldElement) { - if value.Equal(expect) == 1 { - return - } else { - panic("failed equality assertion") - } -} - -type sqrtRatioTest struct { - u, v *radix51.FieldElement - sqrt *radix51.FieldElement - choice int - negative int -} - -func TestSqrtRatioM1(t *testing.T) { - // These tests can be found in curve25519-dalek's 'field.rs' - var ( - zero, one = radix51.Zero, radix51.One - - // Two is nonsquare in our field, 4 is square - two = new(radix51.FieldElement).Add(one, one) - four = new(radix51.FieldElement).Add(two, two) - - // 2*i - twoTimesSqrtM1 = new(radix51.FieldElement).Mul(two, sqrtM1) - - sqrt2i = fieldElementFromDecimal( - "38214883241950591754978413199355411911188925816896391856984770930832735035196") - - invSqrt4 = fieldElementFromDecimal( - "28948022309329048855892746252171976963317496166410141009864396001978282409974") - ) - - // Check the construction of those magic numbers. - assertFeEqual(new(radix51.FieldElement).Mul(sqrt2i, sqrt2i), twoTimesSqrtM1) - assertFeEqual(new(radix51.FieldElement).Mul(new(radix51.FieldElement).Square(invSqrt4), four), one) - - var tests = []sqrtRatioTest{ - {u: zero, v: zero, sqrt: zero, choice: 1, negative: 0}, - {u: zero, v: one, sqrt: zero, choice: 1, negative: 0}, - {u: one, v: zero, sqrt: zero, choice: 0, negative: 0}, - {u: two, v: one, sqrt: sqrt2i, choice: 0, negative: 0}, - {u: four, v: one, sqrt: two, choice: 1, negative: 0}, - {u: one, v: four, sqrt: invSqrt4, choice: 1, negative: 0}, - } - - for idx, tt := range tests { - sqrt := new(radix51.FieldElement) - choice := feSqrtRatio(sqrt, tt.u, tt.v) - if choice != tt.choice || sqrt.Equal(tt.sqrt) != 1 || sqrt.IsNegative() != tt.negative { - t.Errorf("Failed test %d", idx) - t.Logf("Got {u: %v, v: %v, sqrt: %v, choice: %d, neg: %d}", tt.u, tt.v, sqrt, choice, sqrt.IsNegative()) - } - } -} - // The encoding of the canonical generator. var compressedRistrettoBasepoint, _ = hex.DecodeString("e2f2ae0a6abc4e71a884a961c500515f58e30b6aa582dd8db6a65945e08d2d76") @@ -274,7 +218,7 @@ func TestMarshalScalar(t *testing.T) { x := new(Scalar) // generate an arbitrary scalar xbytes := sha512.Sum512([]byte("Hello World")) - x.FromUniformBytes(xbytes[:]) + x.SetUniformBytes(xbytes[:]) text, err := json.Marshal(x) if err != nil { t.Fatalf("Could not marshal json: %v", err) @@ -336,10 +280,10 @@ func TestScalarSet(t *testing.T) { scOne := make([]byte, 32) scOne[0] = 0x01 - sc1, sc2 := NewScalar(), NewScalar().Zero() + sc1, sc2 := NewScalar(), NewScalar() // sc1 <- 1 - sc1.Decode(scOne) + sc1.SetCanonicalBytes(scOne) // 1 != 0 if sc1.Equal(sc2) == 1 { @@ -362,3 +306,45 @@ func TestScalarSet(t *testing.T) { t.Error("shouldn't have changed") } } + +func TestConstants(t *testing.T) { + // From draft-hdevalence-cfrg-ristretto-01, Section 3.1. + t.Run("d", func(t *testing.T) { + testConstant(t, d, + "37095705934669439343138083508754565189542113879843219016388785533085940283555") + }) + t.Run("sqrtM1", func(t *testing.T) { + testConstant(t, sqrtM1, + "19681161376707505956807079304988542015446066515923890162744021073123829784752") + }) + t.Run("sqrtADMinusOne", func(t *testing.T) { + testConstant(t, sqrtADMinusOne, + "25063068953384623474111414158702152701244531502492656460079210482610430750235") + }) + t.Run("invSqrtAMinusD", func(t *testing.T) { + testConstant(t, invSqrtAMinusD, + "54469307008909316920995813868745141605393597292927456921205312896311721017578") + }) + t.Run("oneMinusDSQ", func(t *testing.T) { + testConstant(t, oneMinusDSQ, + "1159843021668779879193775521855586647937357759715417654439879720876111806838") + }) + t.Run("dMinusOneSQ", func(t *testing.T) { + testConstant(t, dMinusOneSQ, + "40440834346308536858101042469323190826248399146238708352240133220865137265952") + }) +} + +func testConstant(t *testing.T, f *field.Element, decimal string) { + b, ok := new(big.Int).SetString(decimal, 10) + if !ok { + t.Fatal("invalid decimal") + } + buf := b.FillBytes(make([]byte, 32)) + for i := 0; i < len(buf)/2; i++ { + buf[i], buf[len(buf)-i-1] = buf[len(buf)-i-1], buf[i] + } + if !bytes.Equal(f.Bytes(), buf) { + t.Errorf("expected %x", buf) + } +} diff --git a/scalar.go b/scalar.go index 63a810d..da7981c 100644 --- a/scalar.go +++ b/scalar.go @@ -8,20 +8,22 @@ import ( "encoding/base64" "errors" - "github.com/gtank/ristretto255/internal/scalar" + "filippo.io/edwards25519" ) // A Scalar is an element of the ristretto255 scalar field, as specified in // draft-hdevalence-cfrg-ristretto-01, Section 3.4. That is, an integer modulo // // l = 2^252 + 27742317777372353535851937790883648493 +// +// The zero value is a valid zero element. type Scalar struct { - s scalar.Scalar + s edwards25519.Scalar } // NewScalar returns a Scalar set to the value 0. func NewScalar() *Scalar { - return (&Scalar{}).Zero() + return &Scalar{} } // Set sets the value of s to x and returns s. @@ -38,19 +40,19 @@ func (s *Scalar) Add(x, y *Scalar) *Scalar { // Subtract sets s = x - y mod l and returns s. func (s *Scalar) Subtract(x, y *Scalar) *Scalar { - s.s.Sub(&x.s, &y.s) + s.s.Subtract(&x.s, &y.s) return s } // Negate sets s = -x mod l and returns s. func (s *Scalar) Negate(x *Scalar) *Scalar { - s.s.Neg(&x.s) + s.s.Negate(&x.s) return s } // Multiply sets s = x * y mod l and returns s. func (s *Scalar) Multiply(x, y *Scalar) *Scalar { - s.s.Mul(&x.s, &y.s) + s.s.Multiply(&x.s, &y.s) return s } @@ -58,7 +60,7 @@ func (s *Scalar) Multiply(x, y *Scalar) *Scalar { // // If x is 0, the result is undefined. func (s *Scalar) Invert(x *Scalar) *Scalar { - s.s.Inv(&x.s) + s.s.Invert(&x.s) return s } @@ -74,12 +76,12 @@ func (s *Scalar) FromUniformBytes(x []byte) *Scalar { } // SetUniformBytes sets s to an uniformly distributed value given 64 uniformly -// distributed random bytes. +// distributed random bytes. If x is not of the right length, SetUniformBytes +// returns nil and an error, and the receiver is unchanged. func (s *Scalar) SetUniformBytes(x []byte) (*Scalar, error) { - if len(x) != 64 { + if _, err := s.s.SetUniformBytes(x); err != nil { return nil, errors.New("ristretto255: SetUniformBytes input is not 64 bytes long") } - s.s.FromUniformBytes(x) return s, nil } @@ -97,8 +99,8 @@ func (s *Scalar) Decode(x []byte) error { // s. If x is not a canonical encoding of s, SetCanonicalBytes returns nil and // an error and the receiver is unchanged. func (s *Scalar) SetCanonicalBytes(x []byte) (*Scalar, error) { - if err := s.s.FromCanonicalBytes(x); err != nil { - return nil, err + if _, err := s.s.SetCanonicalBytes(x); err != nil { + return nil, errors.New("ristretto255: " + err.Error()) } return s, nil } @@ -107,14 +109,14 @@ func (s *Scalar) SetCanonicalBytes(x []byte) (*Scalar, error) { // // Deprecated: use Bytes. This API will be removed before v1.0.0. func (s *Scalar) Encode(b []byte) []byte { - return s.s.Bytes(b) + ret, out := sliceForAppend(b, 32) + copy(out, s.s.Bytes()) + return ret } // Bytes returns the 32 bytes little-endian encoding of s. func (s *Scalar) Bytes() []byte { - // Bytes is small, so the allocation happens on the stack of the caller. - b := make([]byte, 0, 32) - return s.s.Bytes(b) + return s.s.Bytes() } // Equal returns 1 if v and u are equal, and 0 otherwise. @@ -124,7 +126,7 @@ func (s *Scalar) Equal(u *Scalar) int { // Zero sets s = 0 and returns s. func (s *Scalar) Zero() *Scalar { - s.s = scalar.Scalar{} + s.s = edwards25519.Scalar{} return s }