From 81e12d1a81a07c2e329406e879d3d1d362ed429d Mon Sep 17 00:00:00 2001 From: Thomas Dybdahl Ahle Date: Thu, 10 Sep 2026 09:12:49 +0200 Subject: [PATCH 1/2] hash_to_curve: add benchmarks for the isogeny map Benchmark{G1,G2}IsogenyPolynomials times the evaluation of the four isogeny polynomials, Benchmark{G1,G2}IsogenyPolynomialsHorner the same with Horner's rule on the coefficient tables, and Benchmark{G1,G2}Isogeny the full map including the batch inversion. Generated for every SSWU suite with an isogeny. Co-Authored-By: Claude Fable 5.1 --- ecc/bls12-377/hash_to_curve/g1_test.go | 42 ++++++++++++++++++ ecc/bls12-377/hash_to_curve/g2_test.go | 42 ++++++++++++++++++ ecc/bls12-381/hash_to_curve/g1_test.go | 42 ++++++++++++++++++ ecc/bls12-381/hash_to_curve/g2_test.go | 42 ++++++++++++++++++ ecc/bls24-315/hash_to_curve/g1_test.go | 42 ++++++++++++++++++ ecc/bls24-317/hash_to_curve/g1_test.go | 42 ++++++++++++++++++ ecc/bw6-633/hash_to_curve/g1_test.go | 42 ++++++++++++++++++ ecc/bw6-633/hash_to_curve/g2_test.go | 42 ++++++++++++++++++ ecc/bw6-761/hash_to_curve/g1_test.go | 42 ++++++++++++++++++ ecc/bw6-761/hash_to_curve/g2_test.go | 42 ++++++++++++++++++ .../hash_to_curve/template/tests/pkg.go.tmpl | 44 +++++++++++++++++++ 11 files changed, 464 insertions(+) diff --git a/ecc/bls12-377/hash_to_curve/g1_test.go b/ecc/bls12-377/hash_to_curve/g1_test.go index dbe9f590e8..0309188fb2 100644 --- a/ecc/bls12-377/hash_to_curve/g1_test.go +++ b/ecc/bls12-377/hash_to_curve/g1_test.go @@ -58,3 +58,45 @@ func TestG1SqrtRatio(t *testing.T) { properties.TestingRun(t, gopter.ConsoleReporter(false)) } + +// BenchmarkG1IsogenyPolynomials evaluates the four isogeny polynomials as +// G1Isogeny does (without the final batch inversion). +func BenchmarkG1IsogenyPolynomials(b *testing.B) { + var x, y, xn, xd, yn, yd fp.Element + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + g1IsogenyYDenominator(&yd, &x) + g1IsogenyXDenominator(&xd, &x) + g1IsogenyYNumerator(&yn, &x, &y) + g1IsogenyXNumerator(&xn, &x) + } +} + +// BenchmarkG1IsogenyPolynomialsHorner evaluates the same polynomials with +// Horner's rule on the coefficient tables, for reference. +func BenchmarkG1IsogenyPolynomialsHorner(b *testing.B) { + var x, y, xn, xd, yn, yd fp.Element + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + g1EvalPolynomial(&yd, true, g1IsogenyYDenominatorMap, &x) + g1EvalPolynomial(&xd, true, g1IsogenyXDenominatorMap, &x) + g1EvalPolynomial(&yn, false, g1IsogenyYNumeratorMap, &x) + yn.Mul(&yn, &y) + g1EvalPolynomial(&xn, false, g1IsogenyXNumeratorMap, &x) + } +} + +// BenchmarkG1Isogeny measures the full isogeny map, batch inversion included. +func BenchmarkG1Isogeny(b *testing.B) { + var x, y fp.Element + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + G1Isogeny(&x, &y) + } +} diff --git a/ecc/bls12-377/hash_to_curve/g2_test.go b/ecc/bls12-377/hash_to_curve/g2_test.go index 741b3c002c..8542357481 100644 --- a/ecc/bls12-377/hash_to_curve/g2_test.go +++ b/ecc/bls12-377/hash_to_curve/g2_test.go @@ -59,3 +59,45 @@ func TestG2SqrtRatio(t *testing.T) { properties.TestingRun(t, gopter.ConsoleReporter(false)) } + +// BenchmarkG2IsogenyPolynomials evaluates the four isogeny polynomials as +// G2Isogeny does (without the final batch inversion). +func BenchmarkG2IsogenyPolynomials(b *testing.B) { + var x, y, xn, xd, yn, yd fptower.E2 + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + g2IsogenyYDenominator(&yd, &x) + g2IsogenyXDenominator(&xd, &x) + g2IsogenyYNumerator(&yn, &x, &y) + g2IsogenyXNumerator(&xn, &x) + } +} + +// BenchmarkG2IsogenyPolynomialsHorner evaluates the same polynomials with +// Horner's rule on the coefficient tables, for reference. +func BenchmarkG2IsogenyPolynomialsHorner(b *testing.B) { + var x, y, xn, xd, yn, yd fptower.E2 + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + g2EvalPolynomial(&yd, true, g2IsogenyYDenominatorMap, &x) + g2EvalPolynomial(&xd, true, g2IsogenyXDenominatorMap, &x) + g2EvalPolynomial(&yn, false, g2IsogenyYNumeratorMap, &x) + yn.Mul(&yn, &y) + g2EvalPolynomial(&xn, false, g2IsogenyXNumeratorMap, &x) + } +} + +// BenchmarkG2Isogeny measures the full isogeny map, batch inversion included. +func BenchmarkG2Isogeny(b *testing.B) { + var x, y fptower.E2 + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + G2Isogeny(&x, &y) + } +} diff --git a/ecc/bls12-381/hash_to_curve/g1_test.go b/ecc/bls12-381/hash_to_curve/g1_test.go index 73a134675b..d50db441a5 100644 --- a/ecc/bls12-381/hash_to_curve/g1_test.go +++ b/ecc/bls12-381/hash_to_curve/g1_test.go @@ -58,3 +58,45 @@ func TestG1SqrtRatio(t *testing.T) { properties.TestingRun(t, gopter.ConsoleReporter(false)) } + +// BenchmarkG1IsogenyPolynomials evaluates the four isogeny polynomials as +// G1Isogeny does (without the final batch inversion). +func BenchmarkG1IsogenyPolynomials(b *testing.B) { + var x, y, xn, xd, yn, yd fp.Element + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + g1IsogenyYDenominator(&yd, &x) + g1IsogenyXDenominator(&xd, &x) + g1IsogenyYNumerator(&yn, &x, &y) + g1IsogenyXNumerator(&xn, &x) + } +} + +// BenchmarkG1IsogenyPolynomialsHorner evaluates the same polynomials with +// Horner's rule on the coefficient tables, for reference. +func BenchmarkG1IsogenyPolynomialsHorner(b *testing.B) { + var x, y, xn, xd, yn, yd fp.Element + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + g1EvalPolynomial(&yd, true, g1IsogenyYDenominatorMap, &x) + g1EvalPolynomial(&xd, true, g1IsogenyXDenominatorMap, &x) + g1EvalPolynomial(&yn, false, g1IsogenyYNumeratorMap, &x) + yn.Mul(&yn, &y) + g1EvalPolynomial(&xn, false, g1IsogenyXNumeratorMap, &x) + } +} + +// BenchmarkG1Isogeny measures the full isogeny map, batch inversion included. +func BenchmarkG1Isogeny(b *testing.B) { + var x, y fp.Element + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + G1Isogeny(&x, &y) + } +} diff --git a/ecc/bls12-381/hash_to_curve/g2_test.go b/ecc/bls12-381/hash_to_curve/g2_test.go index 6b4c3bb2dc..4d6db6c075 100644 --- a/ecc/bls12-381/hash_to_curve/g2_test.go +++ b/ecc/bls12-381/hash_to_curve/g2_test.go @@ -59,3 +59,45 @@ func TestG2SqrtRatio(t *testing.T) { properties.TestingRun(t, gopter.ConsoleReporter(false)) } + +// BenchmarkG2IsogenyPolynomials evaluates the four isogeny polynomials as +// G2Isogeny does (without the final batch inversion). +func BenchmarkG2IsogenyPolynomials(b *testing.B) { + var x, y, xn, xd, yn, yd fptower.E2 + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + g2IsogenyYDenominator(&yd, &x) + g2IsogenyXDenominator(&xd, &x) + g2IsogenyYNumerator(&yn, &x, &y) + g2IsogenyXNumerator(&xn, &x) + } +} + +// BenchmarkG2IsogenyPolynomialsHorner evaluates the same polynomials with +// Horner's rule on the coefficient tables, for reference. +func BenchmarkG2IsogenyPolynomialsHorner(b *testing.B) { + var x, y, xn, xd, yn, yd fptower.E2 + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + g2EvalPolynomial(&yd, true, g2IsogenyYDenominatorMap, &x) + g2EvalPolynomial(&xd, true, g2IsogenyXDenominatorMap, &x) + g2EvalPolynomial(&yn, false, g2IsogenyYNumeratorMap, &x) + yn.Mul(&yn, &y) + g2EvalPolynomial(&xn, false, g2IsogenyXNumeratorMap, &x) + } +} + +// BenchmarkG2Isogeny measures the full isogeny map, batch inversion included. +func BenchmarkG2Isogeny(b *testing.B) { + var x, y fptower.E2 + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + G2Isogeny(&x, &y) + } +} diff --git a/ecc/bls24-315/hash_to_curve/g1_test.go b/ecc/bls24-315/hash_to_curve/g1_test.go index 2f63f6d0c4..6377379813 100644 --- a/ecc/bls24-315/hash_to_curve/g1_test.go +++ b/ecc/bls24-315/hash_to_curve/g1_test.go @@ -58,3 +58,45 @@ func TestG1SqrtRatio(t *testing.T) { properties.TestingRun(t, gopter.ConsoleReporter(false)) } + +// BenchmarkG1IsogenyPolynomials evaluates the four isogeny polynomials as +// G1Isogeny does (without the final batch inversion). +func BenchmarkG1IsogenyPolynomials(b *testing.B) { + var x, y, xn, xd, yn, yd fp.Element + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + g1IsogenyYDenominator(&yd, &x) + g1IsogenyXDenominator(&xd, &x) + g1IsogenyYNumerator(&yn, &x, &y) + g1IsogenyXNumerator(&xn, &x) + } +} + +// BenchmarkG1IsogenyPolynomialsHorner evaluates the same polynomials with +// Horner's rule on the coefficient tables, for reference. +func BenchmarkG1IsogenyPolynomialsHorner(b *testing.B) { + var x, y, xn, xd, yn, yd fp.Element + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + g1EvalPolynomial(&yd, true, g1IsogenyYDenominatorMap, &x) + g1EvalPolynomial(&xd, true, g1IsogenyXDenominatorMap, &x) + g1EvalPolynomial(&yn, false, g1IsogenyYNumeratorMap, &x) + yn.Mul(&yn, &y) + g1EvalPolynomial(&xn, false, g1IsogenyXNumeratorMap, &x) + } +} + +// BenchmarkG1Isogeny measures the full isogeny map, batch inversion included. +func BenchmarkG1Isogeny(b *testing.B) { + var x, y fp.Element + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + G1Isogeny(&x, &y) + } +} diff --git a/ecc/bls24-317/hash_to_curve/g1_test.go b/ecc/bls24-317/hash_to_curve/g1_test.go index 8c47d5abad..9960adb5e8 100644 --- a/ecc/bls24-317/hash_to_curve/g1_test.go +++ b/ecc/bls24-317/hash_to_curve/g1_test.go @@ -58,3 +58,45 @@ func TestG1SqrtRatio(t *testing.T) { properties.TestingRun(t, gopter.ConsoleReporter(false)) } + +// BenchmarkG1IsogenyPolynomials evaluates the four isogeny polynomials as +// G1Isogeny does (without the final batch inversion). +func BenchmarkG1IsogenyPolynomials(b *testing.B) { + var x, y, xn, xd, yn, yd fp.Element + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + g1IsogenyYDenominator(&yd, &x) + g1IsogenyXDenominator(&xd, &x) + g1IsogenyYNumerator(&yn, &x, &y) + g1IsogenyXNumerator(&xn, &x) + } +} + +// BenchmarkG1IsogenyPolynomialsHorner evaluates the same polynomials with +// Horner's rule on the coefficient tables, for reference. +func BenchmarkG1IsogenyPolynomialsHorner(b *testing.B) { + var x, y, xn, xd, yn, yd fp.Element + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + g1EvalPolynomial(&yd, true, g1IsogenyYDenominatorMap, &x) + g1EvalPolynomial(&xd, true, g1IsogenyXDenominatorMap, &x) + g1EvalPolynomial(&yn, false, g1IsogenyYNumeratorMap, &x) + yn.Mul(&yn, &y) + g1EvalPolynomial(&xn, false, g1IsogenyXNumeratorMap, &x) + } +} + +// BenchmarkG1Isogeny measures the full isogeny map, batch inversion included. +func BenchmarkG1Isogeny(b *testing.B) { + var x, y fp.Element + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + G1Isogeny(&x, &y) + } +} diff --git a/ecc/bw6-633/hash_to_curve/g1_test.go b/ecc/bw6-633/hash_to_curve/g1_test.go index b3bc4f0842..7ea5efec5d 100644 --- a/ecc/bw6-633/hash_to_curve/g1_test.go +++ b/ecc/bw6-633/hash_to_curve/g1_test.go @@ -58,3 +58,45 @@ func TestG1SqrtRatio(t *testing.T) { properties.TestingRun(t, gopter.ConsoleReporter(false)) } + +// BenchmarkG1IsogenyPolynomials evaluates the four isogeny polynomials as +// G1Isogeny does (without the final batch inversion). +func BenchmarkG1IsogenyPolynomials(b *testing.B) { + var x, y, xn, xd, yn, yd fp.Element + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + g1IsogenyYDenominator(&yd, &x) + g1IsogenyXDenominator(&xd, &x) + g1IsogenyYNumerator(&yn, &x, &y) + g1IsogenyXNumerator(&xn, &x) + } +} + +// BenchmarkG1IsogenyPolynomialsHorner evaluates the same polynomials with +// Horner's rule on the coefficient tables, for reference. +func BenchmarkG1IsogenyPolynomialsHorner(b *testing.B) { + var x, y, xn, xd, yn, yd fp.Element + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + g1EvalPolynomial(&yd, true, g1IsogenyYDenominatorMap, &x) + g1EvalPolynomial(&xd, true, g1IsogenyXDenominatorMap, &x) + g1EvalPolynomial(&yn, false, g1IsogenyYNumeratorMap, &x) + yn.Mul(&yn, &y) + g1EvalPolynomial(&xn, false, g1IsogenyXNumeratorMap, &x) + } +} + +// BenchmarkG1Isogeny measures the full isogeny map, batch inversion included. +func BenchmarkG1Isogeny(b *testing.B) { + var x, y fp.Element + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + G1Isogeny(&x, &y) + } +} diff --git a/ecc/bw6-633/hash_to_curve/g2_test.go b/ecc/bw6-633/hash_to_curve/g2_test.go index 52bc913988..3632907354 100644 --- a/ecc/bw6-633/hash_to_curve/g2_test.go +++ b/ecc/bw6-633/hash_to_curve/g2_test.go @@ -48,3 +48,45 @@ func TestG2SqrtRatio(t *testing.T) { properties.TestingRun(t, gopter.ConsoleReporter(false)) } + +// BenchmarkG2IsogenyPolynomials evaluates the four isogeny polynomials as +// G2Isogeny does (without the final batch inversion). +func BenchmarkG2IsogenyPolynomials(b *testing.B) { + var x, y, xn, xd, yn, yd fp.Element + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + g2IsogenyYDenominator(&yd, &x) + g2IsogenyXDenominator(&xd, &x) + g2IsogenyYNumerator(&yn, &x, &y) + g2IsogenyXNumerator(&xn, &x) + } +} + +// BenchmarkG2IsogenyPolynomialsHorner evaluates the same polynomials with +// Horner's rule on the coefficient tables, for reference. +func BenchmarkG2IsogenyPolynomialsHorner(b *testing.B) { + var x, y, xn, xd, yn, yd fp.Element + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + g2EvalPolynomial(&yd, true, g2IsogenyYDenominatorMap, &x) + g2EvalPolynomial(&xd, true, g2IsogenyXDenominatorMap, &x) + g2EvalPolynomial(&yn, false, g2IsogenyYNumeratorMap, &x) + yn.Mul(&yn, &y) + g2EvalPolynomial(&xn, false, g2IsogenyXNumeratorMap, &x) + } +} + +// BenchmarkG2Isogeny measures the full isogeny map, batch inversion included. +func BenchmarkG2Isogeny(b *testing.B) { + var x, y fp.Element + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + G2Isogeny(&x, &y) + } +} diff --git a/ecc/bw6-761/hash_to_curve/g1_test.go b/ecc/bw6-761/hash_to_curve/g1_test.go index dce1dca6b3..4b272a1973 100644 --- a/ecc/bw6-761/hash_to_curve/g1_test.go +++ b/ecc/bw6-761/hash_to_curve/g1_test.go @@ -58,3 +58,45 @@ func TestG1SqrtRatio(t *testing.T) { properties.TestingRun(t, gopter.ConsoleReporter(false)) } + +// BenchmarkG1IsogenyPolynomials evaluates the four isogeny polynomials as +// G1Isogeny does (without the final batch inversion). +func BenchmarkG1IsogenyPolynomials(b *testing.B) { + var x, y, xn, xd, yn, yd fp.Element + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + g1IsogenyYDenominator(&yd, &x) + g1IsogenyXDenominator(&xd, &x) + g1IsogenyYNumerator(&yn, &x, &y) + g1IsogenyXNumerator(&xn, &x) + } +} + +// BenchmarkG1IsogenyPolynomialsHorner evaluates the same polynomials with +// Horner's rule on the coefficient tables, for reference. +func BenchmarkG1IsogenyPolynomialsHorner(b *testing.B) { + var x, y, xn, xd, yn, yd fp.Element + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + g1EvalPolynomial(&yd, true, g1IsogenyYDenominatorMap, &x) + g1EvalPolynomial(&xd, true, g1IsogenyXDenominatorMap, &x) + g1EvalPolynomial(&yn, false, g1IsogenyYNumeratorMap, &x) + yn.Mul(&yn, &y) + g1EvalPolynomial(&xn, false, g1IsogenyXNumeratorMap, &x) + } +} + +// BenchmarkG1Isogeny measures the full isogeny map, batch inversion included. +func BenchmarkG1Isogeny(b *testing.B) { + var x, y fp.Element + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + G1Isogeny(&x, &y) + } +} diff --git a/ecc/bw6-761/hash_to_curve/g2_test.go b/ecc/bw6-761/hash_to_curve/g2_test.go index b795c39929..2efa91e660 100644 --- a/ecc/bw6-761/hash_to_curve/g2_test.go +++ b/ecc/bw6-761/hash_to_curve/g2_test.go @@ -48,3 +48,45 @@ func TestG2SqrtRatio(t *testing.T) { properties.TestingRun(t, gopter.ConsoleReporter(false)) } + +// BenchmarkG2IsogenyPolynomials evaluates the four isogeny polynomials as +// G2Isogeny does (without the final batch inversion). +func BenchmarkG2IsogenyPolynomials(b *testing.B) { + var x, y, xn, xd, yn, yd fp.Element + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + g2IsogenyYDenominator(&yd, &x) + g2IsogenyXDenominator(&xd, &x) + g2IsogenyYNumerator(&yn, &x, &y) + g2IsogenyXNumerator(&xn, &x) + } +} + +// BenchmarkG2IsogenyPolynomialsHorner evaluates the same polynomials with +// Horner's rule on the coefficient tables, for reference. +func BenchmarkG2IsogenyPolynomialsHorner(b *testing.B) { + var x, y, xn, xd, yn, yd fp.Element + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + g2EvalPolynomial(&yd, true, g2IsogenyYDenominatorMap, &x) + g2EvalPolynomial(&xd, true, g2IsogenyXDenominatorMap, &x) + g2EvalPolynomial(&yn, false, g2IsogenyYNumeratorMap, &x) + yn.Mul(&yn, &y) + g2EvalPolynomial(&xn, false, g2IsogenyXNumeratorMap, &x) + } +} + +// BenchmarkG2Isogeny measures the full isogeny map, batch inversion included. +func BenchmarkG2Isogeny(b *testing.B) { + var x, y fp.Element + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + G2Isogeny(&x, &y) + } +} diff --git a/internal/generator/hash_to_curve/template/tests/pkg.go.tmpl b/internal/generator/hash_to_curve/template/tests/pkg.go.tmpl index 895964e96d..da6b2ffd74 100644 --- a/internal/generator/hash_to_curve/template/tests/pkg.go.tmpl +++ b/internal/generator/hash_to_curve/template/tests/pkg.go.tmpl @@ -94,4 +94,48 @@ func Test{{$CurveTitle}}SqrtRatio(t *testing.T) { properties.TestingRun(t, gopter.ConsoleReporter(false)) } + +{{if notNil .Isogeny}} +// Benchmark{{$CurveTitle}}IsogenyPolynomials evaluates the four isogeny polynomials as +// {{$CurveTitle}}Isogeny does (without the final batch inversion). +func Benchmark{{$CurveTitle}}IsogenyPolynomials(b *testing.B) { + var x, y, xn, xd, yn, yd {{$CoordType}} + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + {{$CurveName}}IsogenyYDenominator(&yd, &x) + {{$CurveName}}IsogenyXDenominator(&xd, &x) + {{$CurveName}}IsogenyYNumerator(&yn, &x, &y) + {{$CurveName}}IsogenyXNumerator(&xn, &x) + } +} + +// Benchmark{{$CurveTitle}}IsogenyPolynomialsHorner evaluates the same polynomials with +// Horner's rule on the coefficient tables, for reference. +func Benchmark{{$CurveTitle}}IsogenyPolynomialsHorner(b *testing.B) { + var x, y, xn, xd, yn, yd {{$CoordType}} + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + {{$CurveName}}EvalPolynomial(&yd, true, {{$CurveName}}IsogenyYDenominatorMap, &x) + {{$CurveName}}EvalPolynomial(&xd, true, {{$CurveName}}IsogenyXDenominatorMap, &x) + {{$CurveName}}EvalPolynomial(&yn, false, {{$CurveName}}IsogenyYNumeratorMap, &x) + yn.Mul(&yn, &y) + {{$CurveName}}EvalPolynomial(&xn, false, {{$CurveName}}IsogenyXNumeratorMap, &x) + } +} + +// Benchmark{{$CurveTitle}}Isogeny measures the full isogeny map, batch inversion included. +func Benchmark{{$CurveTitle}}Isogeny(b *testing.B) { + var x, y {{$CoordType}} + x.MustSetRandom() + y.MustSetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + {{$CurveTitle}}Isogeny(&x, &y) + } +} +{{- end}} {{end}} From 95923cac85daa320c925eaa4991cef26cfbdbe7d Mon Sep 17 00:00:00 2001 From: Thomas Dybdahl Ahle Date: Thu, 10 Sep 2026 09:13:37 +0200 Subject: [PATCH 2/2] hash_to_curve: evaluate isogeny polynomials with preprocessed multiplication chains A monic polynomial of degree n over a field of characteristic 0 or p > n can be evaluated with floor(n/2)+1 multiplications instead of Horner's n-1 after a one-time rational preprocessing of its coefficients (T. D. Ahle, "Fast Evaluation of Polynomials with Rational Preprocessing", https://arxiv.org/abs/2609.06022, https://thomasahle.com/fast-polynomials/). The isogeny maps of the SSWU hash-to-curve suites are fixed polynomials, so the preprocessing is done once, offline, and the generator emits straight-line code from the resulting chains. Field multiplications per isogeny map (x numerator, x denominator, y numerator, y denominator; Horner -> chains): BW6-761 G2 degrees 37/36/54/54 over Fp: 179 -> 96 BLS12-377 G2 degrees 23/22/33/33 over Fp^2: 109 -> 60 BLS12-381 G1 degrees 11/10/15/15 over Fp: 49 -> 30 BW6-633 G1 degrees 7/ 6/ 9/ 9 over Fp: 29 -> 21 (degree-6 map kept on Horner) Maps of degree <= 6 (all other curves) keep Horner's rule. - internal/generator/hash_to_curve/gen_isogeny_chains.py runs the paper's decoder (tools/polychain.py of the paper's repository) on the coefficient tables of a curve config, verifies every chain against the polynomial at 200 random points plus 0, 1, -1, and writes the chains as Go literals to internal/generator/config/__isogeny_chains.go. Non-monic numerators are divided by their leading coefficient before decoding and the result is multiplied back (one extra multiplication). - config.Isogeny gains an optional Chains field; PolyChain/LinearForm describe a chain as gates multiplying linear forms with small integer coefficients. - internal/generator/hash_to_curve/chain.go turns a chain into branch-free, division-free Go: one Mul (or Square) per gate, integer wire coefficients by Double/Add/Sub, results accumulated in locals so dst may alias x or y. - pkg_sswu.go.tmpl emits the chained {{curve}}Isogeny{X,Y}{Numerator,Denominator} when a chain exists and the generic Horner evaluator otherwise; the coefficient tables and the public IsogenyMap() accessor are unchanged. - Test{G1,G2}IsogenyChains compares every chained map with Horner on 1000 random field elements plus 0, 1, -1, and checks the aliased calls. Co-Authored-By: Claude Fable 5.1 --- ecc/bls12-377/hash_to_curve/g2.go | 807 +++++++++++++++++- ecc/bls12-377/hash_to_curve/g2_test.go | 69 ++ ecc/bls12-381/hash_to_curve/g1.go | 238 +++++- ecc/bls12-381/hash_to_curve/g1_test.go | 69 ++ ecc/bw6-633/hash_to_curve/g1.go | 140 ++- ecc/bw6-633/hash_to_curve/g1_test.go | 64 ++ ecc/bw6-761/hash_to_curve/g2.go | 731 +++++++++++++++- ecc/bw6-761/hash_to_curve/g2_test.go | 69 ++ internal/generator/config/bls12-377.go | 1 + .../config/bls12-377_g2_isogeny_chains.go | 394 +++++++++ internal/generator/config/bls12-381.go | 1 + .../config/bls12-381_g1_isogeny_chains.go | 214 +++++ internal/generator/config/bw6-633.go | 1 + .../config/bw6-633_g1_isogeny_chains.go | 125 +++ internal/generator/config/bw6-761.go | 1 + .../config/bw6-761_g2_isogeny_chains.go | 608 +++++++++++++ internal/generator/config/hash_to_curve.go | 107 ++- internal/generator/hash_to_curve/chain.go | 199 +++++ .../hash_to_curve/gen_isogeny_chains.py | 386 +++++++++ internal/generator/hash_to_curve/generate.go | 1 + .../hash_to_curve/template/pkg_sswu.go.tmpl | 64 +- .../hash_to_curve/template/tests/pkg.go.tmpl | 85 ++ 22 files changed, 4331 insertions(+), 43 deletions(-) create mode 100644 internal/generator/config/bls12-377_g2_isogeny_chains.go create mode 100644 internal/generator/config/bls12-381_g1_isogeny_chains.go create mode 100644 internal/generator/config/bw6-633_g1_isogeny_chains.go create mode 100644 internal/generator/config/bw6-761_g2_isogeny_chains.go create mode 100644 internal/generator/hash_to_curve/chain.go create mode 100644 internal/generator/hash_to_curve/gen_isogeny_chains.py diff --git a/ecc/bls12-377/hash_to_curve/g2.go b/ecc/bls12-377/hash_to_curve/g2.go index cb507e983c..56eea8d512 100644 --- a/ecc/bls12-377/hash_to_curve/g2.go +++ b/ecc/bls12-377/hash_to_curve/g2.go @@ -518,22 +518,817 @@ func G2IsogenyMap() [4][]fptower.E2 { } } +// g2IsogenyXNumerator evaluates the degree-23 XNumerator polynomial of the isogeny +// with 13 field multiplications (Horner: 23). +// +// The multiplication chain was preprocessed offline from the polynomial's +// coefficients (g2IsogenyXNumeratorMap) by internal/generator/hash_to_curve/gen_isogeny_chains.py, +// using the decoder of T. D. Ahle, "Fast Evaluation of Polynomials with Rational +// Preprocessing", https://arxiv.org/abs/2609.06022. The code is straight line: +// no branches, no divisions. func g2IsogenyXNumerator(dst *fptower.E2, x *fptower.E2) { - g2EvalPolynomial(dst, false, g2IsogenyXNumeratorMap, x) + var w [12]fptower.E2 // gate outputs + var p, r, t fptower.E2 + w[0].Add(x, &g2IsogenyXNumeratorChainConstants[0]) + w[0].Mul(&w[0], x) + w[1].Add(x, &w[0]) + w[1].Add(&w[1], &g2IsogenyXNumeratorChainConstants[1]) + r.Add(&w[0], &g2IsogenyXNumeratorChainConstants[2]) + r.Sub(&r, x) + w[1].Mul(&w[1], &r) + w[2].Add(x, &w[0]) + w[2].Add(&w[2], &g2IsogenyXNumeratorChainConstants[3]) + r.Add(&w[0], &g2IsogenyXNumeratorChainConstants[4]) + r.Sub(&r, x) + w[2].Mul(&w[2], &r) + w[3].Add(x, &g2IsogenyXNumeratorChainConstants[5]) + r.Add(&w[2], &g2IsogenyXNumeratorChainConstants[6]) + w[3].Mul(&w[3], &r) + w[4].Add(&w[0], &w[2]) + w[4].Add(&w[4], &g2IsogenyXNumeratorChainConstants[7]) + t.Double(x) + w[4].Add(&w[4], &t) + r.Add(&w[2], &g2IsogenyXNumeratorChainConstants[8]) + r.Sub(&r, &w[0]) + w[4].Mul(&w[4], &r) + w[5].Add(x, &w[0]) + w[5].Add(&w[5], &w[2]) + w[5].Add(&w[5], &g2IsogenyXNumeratorChainConstants[9]) + r.Add(x, &w[2]) + r.Add(&r, &g2IsogenyXNumeratorChainConstants[10]) + r.Sub(&r, &w[0]) + w[5].Mul(&w[5], &r) + w[6].Add(&w[0], &g2IsogenyXNumeratorChainConstants[11]) + r.Add(x, &w[4]) + r.Add(&r, &g2IsogenyXNumeratorChainConstants[12]) + w[6].Mul(&w[6], &r) + w[7].Add(&w[0], &g2IsogenyXNumeratorChainConstants[13]) + r.Add(&w[5], &g2IsogenyXNumeratorChainConstants[14]) + w[7].Mul(&w[7], &r) + w[8].Add(x, &g2IsogenyXNumeratorChainConstants[15]) + r.Add(&w[6], &g2IsogenyXNumeratorChainConstants[16]) + w[8].Mul(&w[8], &r) + w[9].Add(&w[2], &w[3]) + w[9].Add(&w[9], &w[7]) + w[9].Add(&w[9], &w[8]) + w[9].Add(&w[9], &g2IsogenyXNumeratorChainConstants[17]) + r.Add(&w[7], &w[8]) + r.Add(&r, &g2IsogenyXNumeratorChainConstants[18]) + r.Sub(&r, &w[2]) + r.Sub(&r, &w[3]) + w[9].Mul(&w[9], &r) + w[10].Add(&w[2], &w[3]) + w[10].Add(&w[10], &w[7]) + w[10].Add(&w[10], &w[8]) + w[10].Add(&w[10], &g2IsogenyXNumeratorChainConstants[19]) + r.Add(&w[7], &w[8]) + r.Add(&r, &g2IsogenyXNumeratorChainConstants[20]) + r.Sub(&r, &w[2]) + r.Sub(&r, &w[3]) + w[10].Mul(&w[10], &r) + w[11].Add(&w[1], &w[9]) + w[11].Add(&w[11], &g2IsogenyXNumeratorChainConstants[21]) + w[11].Mul(&w[11], x) + p.Add(&w[1], &w[10]) + p.Add(&p, &w[11]) + p.Add(&p, &g2IsogenyXNumeratorChainConstants[22]) + dst.Mul(&p, &g2IsogenyXNumeratorLeadingCoeff) +} + +var g2IsogenyXNumeratorChainConstants = [23]fptower.E2{ + { + A0: fp.Element{3222141002901906612, 12730377239042506897, 15091239485416259782, 2573721898648404432, 11476216881777831652, 84522106681652083}, + A1: fp.Element{2714387684714405951, 1940684564408408954, 13121612940851980629, 13831020601142483444, 15980985839883614118, 71063883012324871}, + }, + { + A0: fp.Element{1636336736601951674, 7137687199030357492, 3802415472237147371, 3879502044702885363, 17147067284964371801, 135245858876688}, + A1: fp.Element{2642628760942304869, 8369173026956522095, 14683764517721471188, 12515147771271066906, 6598877179404398254, 88688786293814750}, + }, + { + A0: fp.Element{13597925090639334659, 12163579005912204613, 9336726405807133647, 3040561050207399499, 2035045718638667978, 86584512496079663}, + A1: fp.Element{16446394872254747956, 9407237881998307536, 12369642949346229231, 9102056213461002053, 7627156092573539336, 5452481817519430}, + }, + { + A0: fp.Element{3152951200595732175, 18439448400959498898, 3200063266496385112, 7751932953177113836, 12842114621186684491, 72228916192713499}, + A1: fp.Element{9450370489958001610, 8950725229032359216, 857974832802361422, 1760338901291405786, 12661069255412904337, 11775730547970664}, + }, + { + A0: fp.Element{14820556025158074979, 6862797722170171550, 17434013825270014682, 17639848826099609789, 11551413198046412792, 114437455710669325}, + A1: fp.Element{8209150368102859299, 14583019348087371118, 11658244800514136846, 8289921851840650271, 17351363014943546543, 73718818473670901}, + }, + { + A0: fp.Element{2601959342791007226, 1292708084966662707, 2254257139009171027, 18048995664845636113, 3478854869620585086, 60862899139333652}, + A1: fp.Element{14430409366601527955, 6053563630676117039, 6011955615778909481, 17810820883071019122, 15212745191394619950, 12265868131802302}, + }, + { + A0: fp.Element{2363893467624846106, 10687051148756843001, 10846933386189216121, 9667870631051830067, 9401832202747873318, 35461520269904495}, + A1: fp.Element{1396752981329425776, 8175617734379499078, 7005197387949144732, 11751948126235500480, 1192655922140277966, 109811269637700000}, + }, + { + A0: fp.Element{11492545820084213038, 12098748843287427981, 4358125131939276257, 1473362393485697695, 10154282642241695733, 115677913988875780}, + A1: fp.Element{4320580551476421000, 5928915612233341576, 11221693840890927383, 4360546190629829605, 3243443649813181620, 66860512684078484}, + }, + { + A0: fp.Element{1056550651780565770, 16710097607327478119, 6580307909332656556, 9318110630482765943, 2680961777026842398, 61311819602264375}, + A1: fp.Element{1680502646550838621, 5621202654021445827, 867816212947713232, 7101352091110791033, 8458178086577950227, 59699193397958947}, + }, + { + A0: fp.Element{2770289305975734897, 13662383224128009951, 5667462703379068533, 14091836620518191421, 15391929330791259892, 76123829231314613}, + A1: fp.Element{13810889047913229957, 7383624074961091589, 7367214669107898635, 9352712940206466893, 17092176045516962508, 19347465227891798}, + }, + { + A0: fp.Element{17540507532213072792, 14431085268643387036, 6274450033416040284, 3191901792378933937, 10990537462357707986, 89500821119399787}, + A1: fp.Element{1177896050627007668, 12566930828924626672, 2485680081331762570, 13229471805456104363, 5660308191037898895, 47848230899683999}, + }, + { + A0: fp.Element{12215163082863183063, 12457153999079345751, 14173182858481145835, 7640451180645995303, 7358647007116562897, 63768107585135829}, + A1: fp.Element{5660570483867498160, 14692926358972844615, 4727233990367379972, 5600237122792211304, 8609859141176825066, 12351945455621644}, + }, + { + A0: fp.Element{9166656811594099915, 4021754244885439288, 15447774011772154236, 4869648379350436899, 419552589100710768, 72924852089131942}, + A1: fp.Element{9185508099017621147, 10423668293643222234, 12536100535979928158, 5361851822321620834, 10769087295631773156, 9308383972856776}, + }, + { + A0: fp.Element{16021345132676064015, 8251810192270175311, 8608860904171626393, 10741826047712872840, 5066480839046016089, 79561525194848143}, + A1: fp.Element{11580732800742961212, 11548692085955129552, 3846801445518249181, 3090738961420819544, 16740749149089108313, 118168538253901701}, + }, + { + A0: fp.Element{13688643339634881329, 8833203235744190581, 17262001301709698236, 11589235337407173099, 16148573266739368958, 73749650634588245}, + A1: fp.Element{5566595037975408187, 3838322504015267459, 15699079344171386615, 9167235202599089135, 16159835687116813439, 53619190191843146}, + }, + { + A0: fp.Element{8630771022151927502, 11162683441385315473, 13533641757112465576, 15003330259696600816, 3075864644001228637, 98987065187524533}, + A1: fp.Element{17330825913303743369, 2977491196011879630, 7779107892096910418, 1836338328303952735, 8298442232159082055, 69922571019252265}, + }, + { + A0: fp.Element{15038096042791891968, 3254706247597685503, 391487012802318128, 7931405268428249361, 6206565830664684220, 65030974439644558}, + A1: fp.Element{17535207674159655794, 17249519077694525913, 6896536821846257010, 2365774953787713521, 9657565290339944280, 9780414948167274}, + }, + { + A0: fp.Element{4149408966333697565, 5565688648941237780, 16169827920126489465, 14904325720710637861, 12703899534858798808, 108602625361235430}, + A1: fp.Element{11848758729656908566, 5161167923545170291, 3375255898824668291, 3951172399517469786, 10271809566180128574, 75961271296797125}, + }, + { + A0: fp.Element{7463232290624765832, 2883846633427044146, 5639025064782157279, 15181480670348799621, 4761790555634743741, 84887200238047529}, + A1: fp.Element{16217523589812907782, 18278084744935774734, 14404663069687801628, 8909851870640373399, 4384982536423857522, 73458346948150034}, + }, + { + A0: fp.Element{1672665943813109794, 11305682620958357146, 15378473134732990434, 14116695964957954056, 11103216462795934705, 118565079247859721}, + A1: fp.Element{8883047405753078962, 13508929174053242692, 1025631242476714162, 13700756857143519633, 17395665563799064931, 38354785811682005}, + }, + { + A0: fp.Element{2648082068878726883, 13119774297720267059, 4215062986629378590, 16953409619089257190, 11940651430194621412, 21989834108088374}, + A1: fp.Element{3382185705363568243, 11129531883218375295, 6965923139694057524, 18278082725676173000, 12035129073565037838, 94302409427036336}, + }, + { + A0: fp.Element{564329841191758699, 3559439915767180857, 18266569879958417787, 1562847279846714470, 8948435555464908729, 3761404808570587}, + A1: fp.Element{7717014337110895336, 13975526933314555090, 735375443030460622, 5720545646368614936, 4328480645143572801, 112999265400776120}, + }, + { + A0: fp.Element{2150687526181596469, 6493613407619144171, 14173830513026273596, 17365147487727336236, 3806682884545209598, 77882434163623608}, + A1: fp.Element{7251066183647754484, 8416903862640279429, 10261386168922247879, 3491456639114749441, 12322712534193273096, 101051364279039716}, + }, +} + +var g2IsogenyXNumeratorLeadingCoeff = fptower.E2{ + A0: fp.Element{3621702609341817994, 1179514540952803843, 9695126383219869545, 4861853798003230532, 15648444733987506481, 103088924877589738}, + A1: fp.Element{0}, } +// g2IsogenyXDenominator evaluates the degree-22 XDenominator polynomial of the isogeny +// with 12 field multiplications (Horner: 21). +// +// The multiplication chain was preprocessed offline from the polynomial's +// coefficients (g2IsogenyXDenominatorMap) by internal/generator/hash_to_curve/gen_isogeny_chains.py, +// using the decoder of T. D. Ahle, "Fast Evaluation of Polynomials with Rational +// Preprocessing", https://arxiv.org/abs/2609.06022. The code is straight line: +// no branches, no divisions. func g2IsogenyXDenominator(dst *fptower.E2, x *fptower.E2) { - g2EvalPolynomial(dst, true, g2IsogenyXDenominatorMap, x) + var w [12]fptower.E2 // gate outputs + var p, r, t fptower.E2 + w[0].Add(x, &g2IsogenyXDenominatorChainConstants[0]) + w[0].Mul(&w[0], x) + w[1].Add(x, &w[0]) + w[1].Add(&w[1], &g2IsogenyXDenominatorChainConstants[1]) + r.Add(&w[0], &g2IsogenyXDenominatorChainConstants[2]) + r.Sub(&r, x) + w[1].Mul(&w[1], &r) + w[2].Add(&w[0], &w[1]) + w[2].Add(&w[2], &g2IsogenyXDenominatorChainConstants[3]) + t.Double(x) + w[2].Add(&w[2], &t) + r.Add(&w[0], &w[1]) + r.Add(&r, &g2IsogenyXDenominatorChainConstants[4]) + w[2].Mul(&w[2], &r) + w[3].Add(x, &g2IsogenyXDenominatorChainConstants[5]) + r.Add(&w[0], &g2IsogenyXDenominatorChainConstants[6]) + w[3].Mul(&w[3], &r) + w[4].Add(x, &g2IsogenyXDenominatorChainConstants[7]) + r.Add(&w[0], &g2IsogenyXDenominatorChainConstants[8]) + w[4].Mul(&w[4], &r) + w[5].Add(&w[1], &w[2]) + w[5].Add(&w[5], &w[3]) + w[5].Add(&w[5], &g2IsogenyXDenominatorChainConstants[9]) + r.Add(&w[2], &g2IsogenyXDenominatorChainConstants[10]) + r.Sub(&r, &w[1]) + r.Sub(&r, &w[3]) + w[5].Mul(&w[5], &r) + w[6].Add(&w[1], &w[2]) + w[6].Add(&w[6], &g2IsogenyXDenominatorChainConstants[11]) + r.Add(&w[2], &g2IsogenyXDenominatorChainConstants[12]) + r.Sub(&r, &w[1]) + w[6].Mul(&w[6], &r) + w[7].Add(x, &g2IsogenyXDenominatorChainConstants[13]) + r.Add(&w[0], &g2IsogenyXDenominatorChainConstants[14]) + w[7].Mul(&w[7], &r) + w[8].Add(&w[1], &g2IsogenyXDenominatorChainConstants[15]) + t.Double(x) + t.Double(&t) + w[8].Sub(&w[8], &t) + t.Double(&w[0]) + t.Double(&t) + w[8].Sub(&w[8], &t) + r.Add(&w[4], &w[5]) + r.Add(&r, &g2IsogenyXDenominatorChainConstants[16]) + w[8].Mul(&w[8], &r) + w[9].Add(&w[1], &g2IsogenyXDenominatorChainConstants[17]) + t.Double(x) + t.Double(&t) + w[9].Sub(&w[9], &t) + t.Double(&w[0]) + t.Double(&t) + w[9].Sub(&w[9], &t) + r.Add(&w[6], &g2IsogenyXDenominatorChainConstants[18]) + w[9].Mul(&w[9], &r) + w[10].Add(&w[7], &w[8]) + w[10].Add(&w[10], &g2IsogenyXDenominatorChainConstants[19]) + w[10].Mul(&w[10], x) + w[11].Add(&w[9], &w[10]) + w[11].Add(&w[11], &g2IsogenyXDenominatorChainConstants[20]) + w[11].Mul(&w[11], x) + p.Add(&w[11], &g2IsogenyXDenominatorChainConstants[21]) + dst.Set(&p) +} + +var g2IsogenyXDenominatorChainConstants = [22]fptower.E2{ + { + A0: fp.Element{1154265848751688792, 11780326719097141611, 11825684401288595685, 17666152687836607893, 3797478547160688448, 63840303101030591}, + A1: fp.Element{4263328284757027879, 13272124560824390768, 14231387679750826136, 2753580376195416964, 3715824448659693737, 60828734674876385}, + }, + { + A0: fp.Element{14048413415190113936, 16656597647565408174, 12475522796035251547, 17213566288894020571, 4673513778602294603, 119316124298195768}, + A1: fp.Element{13633106231583959927, 10552866083195884502, 6300593011950444645, 18408333709741090094, 10715886761109952420, 48962444911667917}, + }, + { + A0: fp.Element{4955128446792459497, 11303873741270933715, 9846030266562445385, 15710629930456857469, 12671702023461885145, 69655501524555585}, + A1: fp.Element{1868013025751506465, 15817798586787418040, 11546857707524944151, 8767751655401791129, 4208213682069536864, 19921577709334506}, + }, + { + A0: fp.Element{3171550534383844518, 5303928859770651593, 17985794339120644541, 3302982585030485787, 15087787265339190139, 10259415279823274}, + A1: fp.Element{13294960199897990091, 7020640739236965849, 7700463032497417954, 2488310664109416692, 16983091877502910375, 53125839107506156}, + }, + { + A0: fp.Element{454763163956512871, 16419993344774455181, 6742749126837310010, 12992886552310314037, 1504609692546814373, 3597423829813745}, + A1: fp.Element{17136156982474750850, 9152371668396385580, 13844492543257676275, 15388966049834554316, 4933369038141194081, 14929272549698628}, + }, + { + A0: fp.Element{14038849858588530028, 13269494160297296218, 12647313171039202694, 15868580140727865703, 3764509345429248317, 18195302523479547}, + A1: fp.Element{15022094646206929439, 6000080154419118237, 7749057078691888553, 4175548005161794114, 8213610700034034358, 26245935330025959}, + }, + { + A0: fp.Element{12448803935547122730, 12838210961802808746, 4768865423405421217, 4437131528901387355, 14833995378647154520, 52995138701118628}, + A1: fp.Element{12578398625946435013, 1307364719294450685, 13155048605559713336, 18249510287590169627, 11448489044012346387, 17582016422066543}, + }, + { + A0: fp.Element{13028506757734465060, 2631546974117566387, 13598541794192080376, 4821278585017599131, 7079748459324874686, 92323377234432638}, + A1: fp.Element{12542094393190753865, 17108399620118004340, 5088784827262146300, 1578203535499489220, 13912433624898282378, 64485532196801810}, + }, + { + A0: fp.Element{9117312417963682558, 16051020468923139811, 1752508972464118617, 10315527610942304648, 10741306675686504497, 66722223808956378}, + A1: fp.Element{8483969599442475172, 4718867687465049423, 4899175192581539296, 12412220765127421913, 17091588062418356833, 47389923441252235}, + }, + { + A0: fp.Element{665046858536560969, 17824980368211366497, 12565259140201406671, 6273847271198957549, 8706136687204585751, 20157421148152959}, + A1: fp.Element{9713606126373825027, 11040380200698400322, 7814075665116436995, 16605267658038866460, 12039347331630752664, 7937556019297567}, + }, + { + A0: fp.Element{16436696389619712520, 14744826568209478403, 2768724951868397588, 15142425393429073649, 3188149965490022086, 110092097286411221}, + A1: fp.Element{16467421643670013313, 15318664592289706494, 6375077175989990038, 13021121166394272420, 350829546012562329, 29471883940405449}, + }, + { + A0: fp.Element{16067568142316482240, 8816819011726673708, 879159018512002503, 11814812412177626031, 18421234288666259981, 4255292091288343}, + A1: fp.Element{17230450630562644415, 2176579342348022784, 12643980990103287870, 18242566508187219349, 5476598725695350831, 104682429052915997}, + }, + { + A0: fp.Element{9073141604658502891, 16218971720211448149, 8598807940038711826, 6317686265857923155, 3448871974612762665, 78083191689242131}, + A1: fp.Element{11510063537054571045, 4052079422898989582, 4550234619672480519, 12250164396820579407, 9525635274548893178, 84987167676535278}, + }, + { + A0: fp.Element{17108006801837245774, 15842182193298358971, 16610944950283988877, 10705739055187802990, 4746190493986322084, 116291095194640898}, + A1: fp.Element{558601431382358087, 298836615496784211, 9255461897021760803, 4096514315493823971, 9952244802828786315, 68190038158770215}, + }, + { + A0: fp.Element{15614348625636635748, 10220133257470077866, 2331766583522530448, 15377468520755772318, 10585161188884657594, 118167402332042364}, + A1: fp.Element{1197643044140811071, 17853430209286613980, 1772217285448634378, 9714728073526460979, 11210770530520287611, 26439533069815365}, + }, + { + A0: fp.Element{17147435156930902668, 12963009510221622774, 5612086884011885371, 8687686386196918965, 6461824779396050436, 77927089297987421}, + A1: fp.Element{1710268757279073650, 13384092838971142740, 1224046590628978163, 15127490089133803972, 14861273234664412573, 115089354355484563}, + }, + { + A0: fp.Element{15604150773732319929, 16551515005175447501, 14139841537428878807, 5922398221424089352, 7213346299308508693, 119951727656168038}, + A1: fp.Element{8078706512211669948, 9610230372648875092, 17129128290563086518, 10419367066210135072, 685910214706788727, 39548678268375964}, + }, + { + A0: fp.Element{9757546362694547959, 17527278907480242679, 9904554276245232419, 9685792293856465760, 9452814941586356552, 108163843007287055}, + A1: fp.Element{3020635906665252554, 2354115141140949143, 12015022484815999839, 5280585901486960305, 12092647088613815214, 45467912290388179}, + }, + { + A0: fp.Element{500075052634651829, 14561573787324380932, 15271369895373109984, 10894031440252983909, 9877736359088301406, 4817132882164186}, + A1: fp.Element{11915108625765036280, 4877139757547683522, 13626343593322516420, 10994678032333493304, 8685242226956325374, 82481474687403650}, + }, + { + A0: fp.Element{3522248206037264962, 15032231745030973797, 12336748529168474985, 17003999428697790216, 14397751542775264957, 963492191812628}, + A1: fp.Element{16455924593698767787, 2676368906244536814, 17314331076140879483, 1282205652855003768, 13389656847002048639, 32951687725074127}, + }, + { + A0: fp.Element{4626232118864387010, 3232214968085237410, 6362861646375749666, 17201562190714578099, 4027071446541693126, 69145106859740927}, + A1: fp.Element{15707118783180960652, 16971567488131414919, 18299080472982864317, 6055371452599307822, 3170369998640520979, 101628767653067587}, + }, + { + A0: fp.Element{1063048776114699222, 13419136991291290443, 17670140655952814712, 17007170270485437006, 2714055472280753035, 14919040757258909}, + A1: fp.Element{16666868668043867029, 10413023948165423527, 2513282340300795191, 5135056029366772344, 18074639060500180041, 66260525510488187}, + }, } +// g2IsogenyYNumerator evaluates the degree-33 YNumerator polynomial of the isogeny +// with 18 field multiplications (Horner: 33), then multiplies by y. +// +// The multiplication chain was preprocessed offline from the polynomial's +// coefficients (g2IsogenyYNumeratorMap) by internal/generator/hash_to_curve/gen_isogeny_chains.py, +// using the decoder of T. D. Ahle, "Fast Evaluation of Polynomials with Rational +// Preprocessing", https://arxiv.org/abs/2609.06022. The code is straight line: +// no branches, no divisions. func g2IsogenyYNumerator(dst *fptower.E2, x *fptower.E2, y *fptower.E2) { - var _dst fptower.E2 - g2EvalPolynomial(&_dst, false, g2IsogenyYNumeratorMap, x) - dst.Mul(&_dst, y) + var w [17]fptower.E2 // gate outputs + var p, r fptower.E2 + w[0].Add(x, &g2IsogenyYNumeratorChainConstants[0]) + w[0].Mul(&w[0], x) + w[1].Add(x, &w[0]) + w[1].Add(&w[1], &g2IsogenyYNumeratorChainConstants[1]) + r.Add(&w[0], &g2IsogenyYNumeratorChainConstants[2]) + r.Sub(&r, x) + w[1].Mul(&w[1], &r) + w[2].Add(x, &w[0]) + w[2].Add(&w[2], &w[1]) + w[2].Add(&w[2], &g2IsogenyYNumeratorChainConstants[3]) + r.Add(&w[1], &g2IsogenyYNumeratorChainConstants[4]) + r.Sub(&r, x) + r.Sub(&r, &w[0]) + w[2].Mul(&w[2], &r) + w[3].Add(&w[0], &w[1]) + w[3].Add(&w[3], &g2IsogenyYNumeratorChainConstants[5]) + r.Add(&w[1], &g2IsogenyYNumeratorChainConstants[6]) + r.Sub(&r, &w[0]) + w[3].Mul(&w[3], &r) + w[4].Add(x, &g2IsogenyYNumeratorChainConstants[7]) + r.Add(&w[0], &g2IsogenyYNumeratorChainConstants[8]) + w[4].Mul(&w[4], &r) + w[5].Add(x, &g2IsogenyYNumeratorChainConstants[9]) + r.Add(&w[0], &g2IsogenyYNumeratorChainConstants[10]) + w[5].Mul(&w[5], &r) + w[6].Add(x, &w[1]) + w[6].Add(&w[6], &w[2]) + w[6].Add(&w[6], &w[4]) + w[6].Add(&w[6], &g2IsogenyYNumeratorChainConstants[11]) + r.Add(x, &w[2]) + r.Add(&r, &g2IsogenyYNumeratorChainConstants[12]) + r.Sub(&r, &w[1]) + r.Sub(&r, &w[4]) + w[6].Mul(&w[6], &r) + w[7].Add(&w[1], &w[3]) + w[7].Add(&w[7], &g2IsogenyYNumeratorChainConstants[13]) + r.Add(&w[3], &g2IsogenyYNumeratorChainConstants[14]) + r.Sub(&r, &w[1]) + w[7].Mul(&w[7], &r) + w[8].Add(&w[0], &g2IsogenyYNumeratorChainConstants[15]) + r.Add(&w[1], &g2IsogenyYNumeratorChainConstants[16]) + w[8].Mul(&w[8], &r) + w[9].Add(&w[0], &g2IsogenyYNumeratorChainConstants[17]) + r.Add(&w[1], &g2IsogenyYNumeratorChainConstants[18]) + w[9].Mul(&w[9], &r) + w[10].Add(x, &g2IsogenyYNumeratorChainConstants[19]) + r.Add(&w[8], &g2IsogenyYNumeratorChainConstants[20]) + w[10].Mul(&w[10], &r) + w[11].Add(&w[0], &g2IsogenyYNumeratorChainConstants[21]) + r.Add(&w[1], &g2IsogenyYNumeratorChainConstants[22]) + w[11].Mul(&w[11], &r) + w[12].Add(&w[0], &g2IsogenyYNumeratorChainConstants[23]) + r.Add(&w[1], &g2IsogenyYNumeratorChainConstants[24]) + w[12].Mul(&w[12], &r) + w[13].Add(x, &g2IsogenyYNumeratorChainConstants[25]) + r.Add(&w[11], &g2IsogenyYNumeratorChainConstants[26]) + w[13].Mul(&w[13], &r) + w[14].Add(x, &w[2]) + w[14].Add(&w[14], &w[5]) + w[14].Add(&w[14], &w[6]) + w[14].Add(&w[14], &w[9]) + w[14].Add(&w[14], &w[10]) + w[14].Add(&w[14], &g2IsogenyYNumeratorChainConstants[27]) + r.Add(&w[5], &w[6]) + r.Add(&r, &g2IsogenyYNumeratorChainConstants[28]) + r.Sub(&r, x) + r.Sub(&r, &w[2]) + r.Sub(&r, &w[9]) + r.Sub(&r, &w[10]) + w[14].Mul(&w[14], &r) + w[15].Add(x, &w[2]) + w[15].Add(&w[15], &w[7]) + w[15].Add(&w[15], &g2IsogenyYNumeratorChainConstants[29]) + r.Add(&w[7], &g2IsogenyYNumeratorChainConstants[30]) + r.Sub(&r, x) + r.Sub(&r, &w[2]) + w[15].Mul(&w[15], &r) + w[16].Add(&w[12], &w[13]) + w[16].Add(&w[16], &w[14]) + w[16].Add(&w[16], &g2IsogenyYNumeratorChainConstants[31]) + w[16].Mul(&w[16], x) + p.Add(&w[15], &w[16]) + p.Add(&p, &g2IsogenyYNumeratorChainConstants[32]) + p.Mul(&p, &g2IsogenyYNumeratorLeadingCoeff) + dst.Mul(&p, y) +} + +var g2IsogenyYNumeratorChainConstants = [33]fptower.E2{ + { + A0: fp.Element{602666794750194574, 16253837392056072658, 4509289750816526422, 17310507638103759416, 14221957585233067842, 91368629281413522}, + A1: fp.Element{8190799041436865893, 3945723741757114153, 1635516860542256527, 8017114535071492059, 15497450366780835496, 110007450566788041}, + }, + { + A0: fp.Element{12966726322049159683, 13737639606164347639, 9732578771459419751, 1642230126442628831, 787354708573519323, 27121661290097156}, + A1: fp.Element{14882091560614283360, 17745454974363136001, 440284690721205750, 893967563174319628, 18386998200542475493, 11116083348902150}, + }, + { + A0: fp.Element{17723925011826396402, 13203931493160153334, 12899882121135111663, 6836001524164610194, 13559078273858599589, 785741795671985}, + A1: fp.Element{10685994187498517824, 11378944374058951229, 1231367559612418722, 1178253936911597607, 4204692581006892041, 52828029892613315}, + }, + { + A0: fp.Element{6247131656736746815, 5741377700607387791, 13509481855780067363, 8390504760687939287, 12199093222985761458, 103594342588176245}, + A1: fp.Element{7063685458445348582, 16080742234143795053, 3940418259210832516, 9554398576500320978, 534162992944960761, 54385802710487316}, + }, + { + A0: fp.Element{3419991723655209222, 912619731541090205, 17290225450112701849, 7256180547162331066, 6225467352646579164, 88354103995916796}, + A1: fp.Element{11259931123500980807, 17116854230445594542, 3079299111151031524, 11783164740230050570, 3517690422527856586, 95452443747727186}, + }, + { + A0: fp.Element{4769007050131795821, 3243087053185887335, 17683465280032980825, 6893467554925299364, 6227778400053439267, 47200288742901577}, + A1: fp.Element{9962429919952722984, 17290868495523375415, 14804420520334721961, 6374443555802913228, 3018923690960326990, 59074364993435369}, + }, + { + A0: fp.Element{9829316298219931359, 5802198796027209681, 10199689765298528344, 12706399921068359395, 17440150156502760560, 118974542543903237}, + A1: fp.Element{7606200896728838497, 15678678975688360189, 2869587041878374896, 15976516496696047122, 8192321908512315065, 90130051157131696}, + }, + { + A0: fp.Element{7883708636152611042, 6962921053458886598, 6016413814833839076, 14027850136241001687, 16500929091393584325, 21500023846365513}, + A1: fp.Element{11749702046049860561, 671019791698589071, 11484075526404589578, 10396522889100893771, 3418946750196983732, 103786945331405676}, + }, + { + A0: fp.Element{8772136844545780147, 16162702595772307984, 15927694359875602167, 10345139539090606110, 14583463874726840243, 17407481935211121}, + A1: fp.Element{3201395345560405600, 6192123084428444120, 2072998841300135576, 5050572575246558950, 1402725367609405616, 96037030009536371}, + }, + { + A0: fp.Element{16251247514142350400, 7075393053912654258, 2791368377892800767, 14130095519724822284, 1256635826905659052, 93635152061592808}, + A1: fp.Element{14115526231506444434, 840604889424018534, 7448375671036803771, 1994713903280919180, 3760721503779028853, 7979984960558475}, + }, + { + A0: fp.Element{5457758812242166137, 9848088868160358853, 7427748759988716794, 6847589300486467389, 18022111641754705737, 39404587329537578}, + A1: fp.Element{9571363725759020144, 14892135534720695330, 1091515200174372331, 7807651048415939215, 3981665245070920013, 11533064016850169}, + }, + { + A0: fp.Element{2096097206031562285, 13147223205137989691, 6910874721728774542, 2058202209435652191, 2415375973814245350, 78154436790698801}, + A1: fp.Element{17016088328723088560, 6560736952025977318, 16363897874677140529, 12343555966356564486, 14684979866698606400, 85606358235887560}, + }, + { + A0: fp.Element{8606888525190062275, 14552525115958936928, 4341420850542608972, 10264351585334199126, 17295304144100936164, 108874482770768597}, + A1: fp.Element{15225183905812870548, 13033370998372218479, 2085261858566541786, 9970112803979710647, 15690004522244102423, 71583089528321210}, + }, + { + A0: fp.Element{10106063701711651980, 6308745503294098781, 9351984742247034562, 1034196159313894028, 7997292102100962290, 49035193913846209}, + A1: fp.Element{487771647491874349, 8416806309680733, 9299456940637249248, 3543420727561725100, 12110184223910061380, 10206583119796927}, + }, + { + A0: fp.Element{2866236074718901348, 3533421954114552063, 8692134017674383098, 7805603896318318357, 10927284685872105668, 13006427603914426}, + A1: fp.Element{8619510488267282275, 15723562106191602962, 1245436028550506073, 5750333895904339749, 17835694229772741916, 7064665400797991}, + }, + { + A0: fp.Element{14563828235190388291, 2760729076549995195, 13768888479961872631, 5882515120447670125, 4450580531195484264, 33279820602997920}, + A1: fp.Element{10956826178556827922, 668192482345536018, 11582734568615689186, 9603839181729187251, 4656146571283720838, 82692740619469605}, + }, + { + A0: fp.Element{8195070073298952786, 8372229607745801078, 11752268628355699630, 16088977792393246973, 11634046710762767996, 796551051082368}, + A1: fp.Element{3693609172735792880, 17781716822822671452, 5573628457776417444, 4901171183326755728, 12656174907056506939, 15796974966525620}, + }, + { + A0: fp.Element{9887563472096160072, 14325554421226078739, 2581615969033569927, 10071925479087116202, 10293773239339838971, 29868651103038229}, + A1: fp.Element{13277467920362985588, 16528779911123565406, 17368625120737560810, 683903549416092535, 11606108411308629751, 104599021316473826}, + }, + { + A0: fp.Element{2438024242176058612, 11687095074137797679, 12977922783832764636, 7774356947278181975, 13172260220218157062, 119018178057675452}, + A1: fp.Element{2664925751726037583, 18322513274291982396, 6414878302284477371, 12920310802691773086, 17686016969713186882, 114577323963103178}, + }, + { + A0: fp.Element{1188393250608211725, 8793463925332519393, 14677261061950408413, 6035720156488144556, 13683561262855435021, 73255929021760062}, + A1: fp.Element{3257318074745896785, 11907275726201276993, 9655290803544723758, 8228402995682269301, 14322500670977090176, 72000230431587124}, + }, + { + A0: fp.Element{2965910429724167071, 5859107059924139366, 4438634152391023857, 13922023711037083997, 17655107087531494265, 31766981517025548}, + A1: fp.Element{15605122651423203172, 9041751612534232833, 9148219693941859004, 1192498447770276214, 16800553425596525032, 11717567968300665}, + }, + { + A0: fp.Element{9988689953634863676, 156156161000032212, 4386451397615570747, 15432926100826667687, 11716252939592040777, 46819664820708884}, + A1: fp.Element{17332132392998447026, 14882480297544317964, 2540118808357405331, 8409087387911693580, 8614450095156957756, 71938116368837747}, + }, + { + A0: fp.Element{3186173863541881947, 13513775469643035251, 3399301175688133788, 6240913418963538624, 11985823891514152270, 13389838068076639}, + A1: fp.Element{12641650816911783787, 12578147504600096849, 5498278738366346671, 16432274340650274877, 4508442346057971929, 62849359433995994}, + }, + { + A0: fp.Element{14185896789436177446, 4888577488171499024, 14998614289579679571, 7828304812860674711, 6312431424607781912, 37812880673671079}, + A1: fp.Element{6819437572015009023, 7037986156103132008, 7911489002612960451, 4046782433208447910, 9912653023366641285, 30295003129786401}, + }, + { + A0: fp.Element{14039288340276673773, 940486444936268836, 17772433596336551410, 3639698359331195902, 14627840425388483700, 70228598986049441}, + A1: fp.Element{16365559541021438618, 251923185037163945, 18336682895582023661, 13358172080177218026, 6502028335198043821, 56967594264665452}, + }, + { + A0: fp.Element{8567425395415315655, 14647492331438482610, 5294683895376407365, 59546197550487721, 1970595986844101341, 40115199205345540}, + A1: fp.Element{5402305460791351078, 11086558219682608154, 1879268669096048739, 6938475617272886152, 1907448414813904506, 39507961867119496}, + }, + { + A0: fp.Element{16086252589725439775, 13797516230997337570, 18065671975165813990, 8503834875213120251, 15620294231535531086, 13651189113664575}, + A1: fp.Element{17460521789105932045, 1855078997157682943, 4525109025144816797, 9291752421755616342, 3217468809977920234, 42209385689997137}, + }, + { + A0: fp.Element{1487226229874855848, 15149937289014558691, 18207994793160321198, 11559823183158506499, 13113271328237289782, 111802762011268741}, + A1: fp.Element{7109718008943042133, 700639561936007827, 16102131404319698362, 16199929224300198625, 4478269650770476587, 113978055062745485}, + }, + { + A0: fp.Element{5055148473665256852, 4374750341387701292, 7470975655573358293, 127882245515571353, 9272997255263358535, 25685997993322696}, + A1: fp.Element{11425237194029447335, 9171004131711319079, 11536875029303363669, 6481585588914612159, 14003837882173435920, 22983578884383100}, + }, + { + A0: fp.Element{2709697359751234513, 3206950289962519695, 2642115944380422413, 14182559943922687141, 6634770938346892081, 29075856508463199}, + A1: fp.Element{13937837355417110765, 12054458098504569660, 6146227947468313333, 11972775501873420374, 6119604430982511167, 44710405005245479}, + }, + { + A0: fp.Element{6386153458881617205, 17127239257232395584, 7165629928427652601, 12852609341981187445, 2677119793592802413, 60797094224907834}, + A1: fp.Element{1717060123358844729, 3914653030823898643, 13012900368790194679, 5177754266335137665, 14771733407982383381, 19120603468816045}, + }, + { + A0: fp.Element{10408661903805199505, 10115702538880814959, 10094715726265886095, 10528926591266850780, 15093823181271636935, 21987801978767687}, + A1: fp.Element{3580726955125840477, 4078064373700445435, 9334365483223844841, 3347382076873567805, 17503404269319186649, 41684753445827262}, + }, + { + A0: fp.Element{12970963763302962935, 7256941115932928903, 14860783428018958175, 16622414158163811025, 987151010812237602, 99836025412796020}, + A1: fp.Element{7908744897091449396, 201588043562584001, 4902732936791061788, 16264375730473317433, 3671578276584443927, 31344355197917605}, + }, +} + +var g2IsogenyYNumeratorLeadingCoeff = fptower.E2{ + A0: fp.Element{18250508560718013179, 7486164413457419330, 8732750857092323232, 457033717118918321, 12167888022606617966, 20277559260742340}, + A1: fp.Element{0}, } +// g2IsogenyYDenominator evaluates the degree-33 YDenominator polynomial of the isogeny +// with 17 field multiplications (Horner: 32). +// +// The multiplication chain was preprocessed offline from the polynomial's +// coefficients (g2IsogenyYDenominatorMap) by internal/generator/hash_to_curve/gen_isogeny_chains.py, +// using the decoder of T. D. Ahle, "Fast Evaluation of Polynomials with Rational +// Preprocessing", https://arxiv.org/abs/2609.06022. The code is straight line: +// no branches, no divisions. func g2IsogenyYDenominator(dst *fptower.E2, x *fptower.E2) { - g2EvalPolynomial(dst, true, g2IsogenyYDenominatorMap, x) + var w [17]fptower.E2 // gate outputs + var p, r fptower.E2 + w[0].Add(x, &g2IsogenyYDenominatorChainConstants[0]) + w[0].Mul(&w[0], x) + w[1].Add(x, &w[0]) + w[1].Add(&w[1], &g2IsogenyYDenominatorChainConstants[1]) + r.Add(&w[0], &g2IsogenyYDenominatorChainConstants[2]) + r.Sub(&r, x) + w[1].Mul(&w[1], &r) + w[2].Add(x, &w[0]) + w[2].Add(&w[2], &w[1]) + w[2].Add(&w[2], &g2IsogenyYDenominatorChainConstants[3]) + r.Add(&w[1], &g2IsogenyYDenominatorChainConstants[4]) + r.Sub(&r, x) + r.Sub(&r, &w[0]) + w[2].Mul(&w[2], &r) + w[3].Add(&w[0], &w[1]) + w[3].Add(&w[3], &g2IsogenyYDenominatorChainConstants[5]) + r.Add(&w[1], &g2IsogenyYDenominatorChainConstants[6]) + r.Sub(&r, &w[0]) + w[3].Mul(&w[3], &r) + w[4].Add(x, &g2IsogenyYDenominatorChainConstants[7]) + r.Add(&w[0], &g2IsogenyYDenominatorChainConstants[8]) + w[4].Mul(&w[4], &r) + w[5].Add(x, &g2IsogenyYDenominatorChainConstants[9]) + r.Add(&w[0], &g2IsogenyYDenominatorChainConstants[10]) + w[5].Mul(&w[5], &r) + w[6].Add(x, &w[1]) + w[6].Add(&w[6], &w[2]) + w[6].Add(&w[6], &w[4]) + w[6].Add(&w[6], &g2IsogenyYDenominatorChainConstants[11]) + r.Add(x, &w[2]) + r.Add(&r, &g2IsogenyYDenominatorChainConstants[12]) + r.Sub(&r, &w[1]) + r.Sub(&r, &w[4]) + w[6].Mul(&w[6], &r) + w[7].Add(&w[1], &w[3]) + w[7].Add(&w[7], &g2IsogenyYDenominatorChainConstants[13]) + r.Add(&w[3], &g2IsogenyYDenominatorChainConstants[14]) + r.Sub(&r, &w[1]) + w[7].Mul(&w[7], &r) + w[8].Add(&w[0], &g2IsogenyYDenominatorChainConstants[15]) + r.Add(&w[1], &g2IsogenyYDenominatorChainConstants[16]) + w[8].Mul(&w[8], &r) + w[9].Add(&w[0], &g2IsogenyYDenominatorChainConstants[17]) + r.Add(&w[1], &g2IsogenyYDenominatorChainConstants[18]) + w[9].Mul(&w[9], &r) + w[10].Add(x, &g2IsogenyYDenominatorChainConstants[19]) + r.Add(&w[8], &g2IsogenyYDenominatorChainConstants[20]) + w[10].Mul(&w[10], &r) + w[11].Add(&w[0], &g2IsogenyYDenominatorChainConstants[21]) + r.Add(&w[1], &g2IsogenyYDenominatorChainConstants[22]) + w[11].Mul(&w[11], &r) + w[12].Add(&w[0], &g2IsogenyYDenominatorChainConstants[23]) + r.Add(&w[1], &g2IsogenyYDenominatorChainConstants[24]) + w[12].Mul(&w[12], &r) + w[13].Add(x, &g2IsogenyYDenominatorChainConstants[25]) + r.Add(&w[11], &g2IsogenyYDenominatorChainConstants[26]) + w[13].Mul(&w[13], &r) + w[14].Add(x, &w[2]) + w[14].Add(&w[14], &w[5]) + w[14].Add(&w[14], &w[6]) + w[14].Add(&w[14], &w[9]) + w[14].Add(&w[14], &w[10]) + w[14].Add(&w[14], &g2IsogenyYDenominatorChainConstants[27]) + r.Add(&w[5], &w[6]) + r.Add(&r, &g2IsogenyYDenominatorChainConstants[28]) + r.Sub(&r, x) + r.Sub(&r, &w[2]) + r.Sub(&r, &w[9]) + r.Sub(&r, &w[10]) + w[14].Mul(&w[14], &r) + w[15].Add(x, &w[2]) + w[15].Add(&w[15], &w[7]) + w[15].Add(&w[15], &g2IsogenyYDenominatorChainConstants[29]) + r.Add(&w[7], &g2IsogenyYDenominatorChainConstants[30]) + r.Sub(&r, x) + r.Sub(&r, &w[2]) + w[15].Mul(&w[15], &r) + w[16].Add(&w[12], &w[13]) + w[16].Add(&w[16], &w[14]) + w[16].Add(&w[16], &g2IsogenyYDenominatorChainConstants[31]) + w[16].Mul(&w[16], x) + p.Add(&w[15], &w[16]) + p.Add(&p, &g2IsogenyYDenominatorChainConstants[32]) + dst.Set(&p) +} + +var g2IsogenyYDenominatorChainConstants = [33]fptower.E2{ + { + A0: fp.Element{602666794750194574, 16253837392056072658, 4509289750816526422, 17310507638103759416, 14221957585233067842, 91368629281413522}, + A1: fp.Element{8190799041436865893, 3945723741757114153, 1635516860542256527, 8017114535071492059, 15497450366780835496, 110007450566788041}, + }, + { + A0: fp.Element{10201497304301458466, 13317251220681927127, 16190482369307544415, 9488269995412985369, 7510064101614312521, 91476503367704132}, + A1: fp.Element{9582647128830810090, 15899067121239528554, 5804927665201758467, 3187823495483235352, 12695727095965226941, 108735257500788181}, + }, + { + A0: fp.Element{12345530463866941092, 3735937530208056012, 9882011681376098388, 7478704829147997453, 3836818919491991052, 32532846615138066}, + A1: fp.Element{14470233575503247542, 16094170928341863182, 12790493500820045992, 13438450258239665116, 14271314974893200171, 106350395957063814}, + }, + { + A0: fp.Element{2050350781410210813, 11215347372009388900, 8727884941397539210, 4810757974806198598, 15440661958039850168, 8723679319885325}, + A1: fp.Element{6804337830747315796, 12342663687640103455, 14260868517303764353, 12761612122027465307, 8817635499040253701, 14792917524031198}, + }, + { + A0: fp.Element{8787793780038480385, 7859268283168878209, 11512194279064634640, 2369675137239501969, 17270642239072718573, 93677264254342224}, + A1: fp.Element{11556220622751408278, 14423289763268868590, 3658018454276795487, 1232173805959011755, 4327333457596578716, 66305289738683564}, + }, + { + A0: fp.Element{10422281562966337622, 17727591463476082239, 10921991931076856107, 6110659788970031400, 2391330496183649752, 2636279086669318}, + A1: fp.Element{12346934888290351926, 12659430245520773820, 5465250072383496919, 4478652941542958662, 12120332880508767235, 27931525108903603}, + }, + { + A0: fp.Element{16948373287344146603, 13283134405826436299, 8112247220615579233, 14223184333515473037, 1112855919751338687, 67467928143839809}, + A1: fp.Element{18010951943992249506, 11007064921720456814, 14062742234295162373, 8093895453007373365, 6635743374646984203, 85590905280078483}, + }, + { + A0: fp.Element{1736212745426432413, 3505147816864500283, 14557782252529064140, 7088425520138886800, 18313604068559364182, 75135137767695540}, + A1: fp.Element{2770995756375735451, 13594278807220768039, 323422727515545218, 9324605915289102846, 11536369278047909835, 89105222587582640}, + }, + { + A0: fp.Element{15772289391533644256, 2576426733974413018, 4250101369777828826, 14350563688161054474, 17655777043090859126, 11045679924013540}, + A1: fp.Element{10542711120685159218, 17034733548103135560, 14136924291520762048, 6838326285954943129, 1756169374751201395, 89386790959678242}, + }, + { + A0: fp.Element{14255096862401664310, 10455328225466386260, 16437506491112970065, 16965895414638967617, 7575253353384886625, 113165276427946916}, + A1: fp.Element{13446825314860223586, 7704738964066757974, 2917536295940727182, 16739710999382516993, 12101739319888089697, 28379992149096411}, + }, + { + A0: fp.Element{17540862387485860207, 7965127127293528198, 2964503844899021704, 2173729936985759466, 12405368133648785874, 83440818177584576}, + A1: fp.Element{5463335439909281452, 4730681955117980596, 11209632042498242140, 3668733824757523202, 16570194490133329792, 90851620230549291}, + }, + { + A0: fp.Element{14656038657398209611, 8360183312682877061, 15607493521961330048, 7342503370184009533, 6565285403113323993, 115286354925336599}, + A1: fp.Element{9869105904289632152, 471919790032987805, 17224492774063577165, 12036277310785787148, 7058099349975630306, 55454278357365892}, + }, + { + A0: fp.Element{725746171117120481, 10698271658094529964, 1506590228564063387, 6787444015423259242, 18108348320325119294, 71688712676204729}, + A1: fp.Element{15597539860187135204, 3571205501103775143, 11765394002839166985, 9995328470743334050, 1098268111390332779, 118514785157655981}, + }, + { + A0: fp.Element{18414374674054934525, 15739171074662210336, 6756700243535127883, 16154877629155672198, 6785626221123716367, 63251989537050039}, + A1: fp.Element{6502736098626820281, 5818694185261776274, 4264952962650068188, 17042541609138787357, 4310701122394148598, 62571794489136309}, + }, + { + A0: fp.Element{1151012811585504465, 16373707258950658396, 10426846139164050727, 14203621362688671433, 6775347062236730898, 27414338832542508}, + A1: fp.Element{3249150123089577207, 9929316876048275466, 10616992306620271467, 562431722657041713, 18402299534170647480, 110209778517712628}, + }, + { + A0: fp.Element{7566541055367140880, 16500637028232926932, 8854885879525474351, 15854096487746901213, 4810934849430134199, 34610949519657883}, + A1: fp.Element{11032087993468696870, 16253398246278872067, 993796275433280710, 2534343183276619199, 10094474727782747089, 79896415428695683}, + }, + { + A0: fp.Element{3670723236400489756, 16054423990089568676, 15984579850219454848, 13549464089893706539, 8658274403668640390, 69079947144071722}, + A1: fp.Element{517460813456195204, 8500284358085422696, 11984267693191815159, 6073753493537701544, 1156445351315945102, 83656664539853835}, + }, + { + A0: fp.Element{5516085163276502917, 15263095349658993457, 12824980274492789025, 11114413275040452236, 2956931534353859087, 83712576251995894}, + A1: fp.Element{8007527501421044004, 8422380325639881573, 15760415909316167683, 4858245413580550160, 17625516522825200105, 908819181629835}, + }, + { + A0: fp.Element{17104487499687201240, 7462815757086026573, 8920543810084165047, 17709160679108295794, 7120781924538440889, 20592563029628211}, + A1: fp.Element{13781163398546903245, 7242293012635837041, 1833927311600712607, 17519042757911955492, 1228161512245189495, 29653008523361642}, + }, + { + A0: fp.Element{9370367370581432319, 11057994739354357440, 8494054606978566989, 4445234022501118291, 16949034013280342737, 3242506082011479}, + A1: fp.Element{5222044693577125698, 4385316377103666813, 9622518543270948471, 1031088451194323299, 17474159998662611005, 81086378269657901}, + }, + { + A0: fp.Element{12521042749264123375, 4847419076413045717, 15595210807795655303, 13649521022623387560, 17079494032433303025, 69343540758749423}, + A1: fp.Element{7853358840072747739, 1617478376696461898, 10907268392332835637, 17281872594309154334, 12794596564178839603, 23800095971843991}, + }, + { + A0: fp.Element{3496260238312627627, 4505696728952445329, 18206587623523877993, 7161641623775962764, 7348248260690733425, 108261772984540410}, + A1: fp.Element{14783008030779619525, 15870778544452568907, 15582155560709616602, 13153525550521257090, 5451668846338054242, 92603819660756989}, + }, + { + A0: fp.Element{6366764259623671189, 10761995151366530899, 3925063661107360186, 3252816299974871817, 7915030488071377786, 20945804408656117}, + A1: fp.Element{8848160470778901666, 5058128976593075748, 2309978861419975847, 11290049523311233542, 8813543699321607152, 87103494995182198}, + }, + { + A0: fp.Element{11488027740819830497, 2640436323648261717, 16576242321916472867, 9258671998886197599, 3223687784477135793, 51902670444241898}, + A1: fp.Element{11282709310155294589, 7742608401257121397, 16548933938786998764, 6365013383131185452, 8552787184192234436, 114648668750789837}, + }, + { + A0: fp.Element{1826906442368734509, 11118929010668009538, 17093395316686474327, 14194300625955492603, 15970778735581574373, 48740197980911519}, + A1: fp.Element{4273994324056023035, 17967257322739464820, 6938961840091192148, 17602873895617507770, 15827740803061832831, 74950610526734929}, + }, + { + A0: fp.Element{10861790195324018803, 13029613078721832528, 7348781505030504733, 1773092662966489666, 9664688803425885073, 8170936546609875}, + A1: fp.Element{439259510145698401, 7999722436997160153, 9689757494314018646, 1045641213035929319, 8867670613728334794, 47983806784259530}, + }, + { + A0: fp.Element{1652263840633011189, 6359537390876497886, 4454741818063027050, 732717235323776093, 8930151551169027150, 9293012997625774}, + A1: fp.Element{17202678737205868083, 10149983401318467991, 15787830886265196836, 1835955289585538506, 4093918713038190544, 9899124212514537}, + }, + { + A0: fp.Element{18260499797868926085, 17077537036222012659, 774848108334093377, 7469043386732210630, 4052694183996032655, 72954665904028022}, + A1: fp.Element{2200391452023706565, 4087196335303304233, 14664956464618522199, 8391380170523241662, 17397070956523401492, 85943431282905219}, + }, + { + A0: fp.Element{8592251310557294077, 50789811428773205, 14244770682305110188, 8030893550872187075, 4741333803435114887, 104270875468192533}, + A1: fp.Element{16042078980903595095, 17592411866212269707, 14938460623292182830, 11350850061963594135, 12074737057017374295, 42409210082608713}, + }, + { + A0: fp.Element{4286582375415207768, 10511263536101236792, 11053493467030246764, 14965283670045619152, 15588164435867271853, 51439354688307891}, + A1: fp.Element{11419001388721964822, 4398266577937259981, 7096542335447314460, 8431420576681741075, 11908637875097059087, 106426885172741347}, + }, + { + A0: fp.Element{16263636787843970255, 121120834980387860, 11784182198995848855, 1238011329949499364, 8715063535753281784, 35730548220191828}, + A1: fp.Element{3021742560167647982, 13966200227576209426, 303353611542688769, 17862570502551019570, 7166676580155261208, 81393892230563850}, + }, + { + A0: fp.Element{292652012193275895, 12055072836975952806, 11391027978535402273, 14469250992912274955, 11897613802936937134, 85204643291029886}, + A1: fp.Element{1344549645453977566, 7724161904556238106, 6154715043408675503, 15415476428919267567, 8164292522335067779, 76114612633788841}, + }, + { + A0: fp.Element{13502383962208407269, 1317716881399816175, 7558122117323276095, 9854968054038354985, 4140050036169178561, 99375615954027157}, + A1: fp.Element{1062322864080302369, 17283461916364040084, 6929465840091385757, 17330216876465475780, 10886225167678714506, 97210713024859057}, + }, } // G2 computes the isogeny map of the curve element, given by its coordinates pX and pY. diff --git a/ecc/bls12-377/hash_to_curve/g2_test.go b/ecc/bls12-377/hash_to_curve/g2_test.go index 8542357481..1be8f9fbe5 100644 --- a/ecc/bls12-377/hash_to_curve/g2_test.go +++ b/ecc/bls12-377/hash_to_curve/g2_test.go @@ -60,6 +60,75 @@ func TestG2SqrtRatio(t *testing.T) { properties.TestingRun(t, gopter.ConsoleReporter(false)) } +// TestG2IsogenyChains checks the preprocessed multiplication chains of the +// isogeny polynomials against Horner's rule on the original coefficients. +func TestG2IsogenyChains(t *testing.T) { + t.Parallel() + + check := func(x, y *fptower.E2) { + var got, want fptower.E2 + g2IsogenyXNumerator(&got, x) + g2EvalPolynomial(&want, false, g2IsogenyXNumeratorMap, x) + if !got.Equal(&want) { + t.Fatal("x numerator: chain and Horner disagree") + } + g2IsogenyXDenominator(&got, x) + g2EvalPolynomial(&want, true, g2IsogenyXDenominatorMap, x) + if !got.Equal(&want) { + t.Fatal("x denominator: chain and Horner disagree") + } + g2IsogenyYNumerator(&got, x, y) + g2EvalPolynomial(&want, false, g2IsogenyYNumeratorMap, x) + want.Mul(&want, y) + if !got.Equal(&want) { + t.Fatal("y numerator: chain and Horner disagree") + } + g2IsogenyYDenominator(&got, x) + g2EvalPolynomial(&want, true, g2IsogenyYDenominatorMap, x) + if !got.Equal(&want) { + t.Fatal("y denominator: chain and Horner disagree") + } + } + + // 0, 1, -1 and random points + var special [3]fptower.E2 + special[1].SetOne() + special[2].Neg(&special[1]) + var y fptower.E2 + y.MustSetRandom() + for i := range special { + check(&special[i], &y) + } + n := 1000 + if testing.Short() { + n = 100 + } + for i := 0; i < n; i++ { + var x fptower.E2 + x.MustSetRandom() + y.MustSetRandom() + check(&x, &y) + } + + // aliasing as used by G2Isogeny: dst == x and dst == y + var x fptower.E2 + x.MustSetRandom() + y.MustSetRandom() + var want fptower.E2 + g2IsogenyXNumerator(&want, &x) + x2 := x + g2IsogenyXNumerator(&x2, &x2) + if !x2.Equal(&want) { + t.Fatal("x numerator: aliased evaluation differs") + } + g2IsogenyYNumerator(&want, &x, &y) + y2 := y + g2IsogenyYNumerator(&y2, &x, &y2) + if !y2.Equal(&want) { + t.Fatal("y numerator: aliased evaluation differs") + } +} + // BenchmarkG2IsogenyPolynomials evaluates the four isogeny polynomials as // G2Isogeny does (without the final batch inversion). func BenchmarkG2IsogenyPolynomials(b *testing.B) { diff --git a/ecc/bls12-381/hash_to_curve/g1.go b/ecc/bls12-381/hash_to_curve/g1.go index ad8e45009d..5b47473b4e 100644 --- a/ecc/bls12-381/hash_to_curve/g1.go +++ b/ecc/bls12-381/hash_to_curve/g1.go @@ -109,22 +109,248 @@ func G1IsogenyMap() [4][]fp.Element { } } +// g1IsogenyXNumerator evaluates the degree-11 XNumerator polynomial of the isogeny +// with 7 field multiplications (Horner: 11). +// +// The multiplication chain was preprocessed offline from the polynomial's +// coefficients (g1IsogenyXNumeratorMap) by internal/generator/hash_to_curve/gen_isogeny_chains.py, +// using the decoder of T. D. Ahle, "Fast Evaluation of Polynomials with Rational +// Preprocessing", https://arxiv.org/abs/2609.06022. The code is straight line: +// no branches, no divisions. func g1IsogenyXNumerator(dst *fp.Element, x *fp.Element) { - g1EvalPolynomial(dst, false, g1IsogenyXNumeratorMap, x) + var w [6]fp.Element // gate outputs + var p, r fp.Element + w[0].Add(x, &g1IsogenyXNumeratorChainConstants[0]) + w[0].Mul(&w[0], x) + w[1].Add(x, &w[0]) + w[1].Add(&w[1], &g1IsogenyXNumeratorChainConstants[1]) + r.Add(&w[0], &g1IsogenyXNumeratorChainConstants[2]) + r.Sub(&r, x) + w[1].Mul(&w[1], &r) + w[2].Add(x, &g1IsogenyXNumeratorChainConstants[3]) + r.Add(&w[1], &g1IsogenyXNumeratorChainConstants[4]) + w[2].Mul(&w[2], &r) + w[3].Add(&w[0], &w[1]) + w[3].Add(&w[3], &w[2]) + w[3].Add(&w[3], &g1IsogenyXNumeratorChainConstants[5]) + r.Add(&w[1], &w[2]) + r.Add(&r, &g1IsogenyXNumeratorChainConstants[6]) + r.Sub(&r, &w[0]) + w[3].Mul(&w[3], &r) + w[4].Add(&w[0], &w[1]) + w[4].Add(&w[4], &w[2]) + w[4].Add(&w[4], &g1IsogenyXNumeratorChainConstants[7]) + r.Add(&w[1], &w[2]) + r.Add(&r, &g1IsogenyXNumeratorChainConstants[8]) + r.Sub(&r, &w[0]) + w[4].Mul(&w[4], &r) + w[5].Add(&w[3], &g1IsogenyXNumeratorChainConstants[9]) + w[5].Mul(&w[5], x) + p.Add(&w[4], &w[5]) + p.Add(&p, &g1IsogenyXNumeratorChainConstants[10]) + dst.Mul(&p, &g1IsogenyXNumeratorLeadingCoeff) +} + +var g1IsogenyXNumeratorChainConstants = [11]fp.Element{ + {8992951131840873894, 3387476711969253240, 4539336759033536591, 12488624726021108657, 7230480994775629691, 327685669864996006}, + {5849978871014661991, 3299210057729334947, 10213664306841556855, 6988138907883825126, 5851573080832783677, 1505384747542192590}, + {6621723790879161923, 8725684519580169775, 4998559352523084955, 17574152691559460445, 12264031173239141248, 587383677433106806}, + {1589990106900212114, 3341874774160898667, 17238968235675567731, 2282640806487941067, 14882363664373431196, 1390393302660214142}, + {10079038892965161282, 7733559902670471093, 1241685292914441228, 18212349560582283958, 2938980714404582900, 219220052743233837}, + {650630103369754573, 942955954031092877, 11494930751603260178, 8698138106874299146, 1570379813838235149, 192769120734568164}, + {2404515647446305741, 11600466276507383248, 6332538259456936066, 9203778796711576901, 16811017751432941187, 1115524013434653827}, + {8196308499861517995, 8331244683374573117, 2489189790547868797, 18223539196963773664, 16045093755370245329, 648698279329134613}, + {1301632144555848050, 12463838453761528415, 2830686766207694270, 3838281030502845463, 16554580213400950167, 1810939862297351704}, + {12298184293847723583, 15795227307971680007, 4651728225712919295, 8839537707709685739, 16099337955735932345, 1072521649492638714}, + {2932339930693979532, 11419407500141344736, 12091845989678553817, 10834818932706466464, 18293039879892309497, 1321577289741533921}, } +var g1IsogenyXNumeratorLeadingCoeff = fp.Element{8276255265012938363, 9997870203437298645, 16819210142450232135, 5062450688048499179, 12776432501206859311, 1778476024187613533} + +// g1IsogenyXDenominator evaluates the degree-10 XDenominator polynomial of the isogeny +// with 6 field multiplications (Horner: 9). +// +// The multiplication chain was preprocessed offline from the polynomial's +// coefficients (g1IsogenyXDenominatorMap) by internal/generator/hash_to_curve/gen_isogeny_chains.py, +// using the decoder of T. D. Ahle, "Fast Evaluation of Polynomials with Rational +// Preprocessing", https://arxiv.org/abs/2609.06022. The code is straight line: +// no branches, no divisions. func g1IsogenyXDenominator(dst *fp.Element, x *fp.Element) { - g1EvalPolynomial(dst, true, g1IsogenyXDenominatorMap, x) + var w [6]fp.Element // gate outputs + var p, r fp.Element + w[0].Add(x, &g1IsogenyXDenominatorChainConstants[0]) + w[0].Mul(&w[0], x) + w[1].Add(x, &w[0]) + w[1].Add(&w[1], &g1IsogenyXDenominatorChainConstants[1]) + r.Add(&w[0], &g1IsogenyXDenominatorChainConstants[2]) + r.Sub(&r, x) + w[1].Mul(&w[1], &r) + w[2].Add(x, &w[0]) + w[2].Add(&w[2], &w[1]) + w[2].Add(&w[2], &g1IsogenyXDenominatorChainConstants[3]) + r.Add(&w[1], &g1IsogenyXDenominatorChainConstants[4]) + r.Sub(&r, x) + r.Sub(&r, &w[0]) + w[2].Mul(&w[2], &r) + w[3].Add(&w[0], &w[1]) + w[3].Add(&w[3], &g1IsogenyXDenominatorChainConstants[5]) + r.Add(&w[1], &g1IsogenyXDenominatorChainConstants[6]) + r.Sub(&r, &w[0]) + w[3].Mul(&w[3], &r) + w[4].Add(x, &w[2]) + w[4].Add(&w[4], &g1IsogenyXDenominatorChainConstants[7]) + w[4].Mul(&w[4], x) + w[5].Add(&w[3], &w[4]) + w[5].Add(&w[5], &g1IsogenyXDenominatorChainConstants[8]) + w[5].Mul(&w[5], x) + p.Add(&w[5], &g1IsogenyXDenominatorChainConstants[9]) + dst.Set(&p) +} + +var g1IsogenyXDenominatorChainConstants = [10]fp.Element{ + {7339395362885092632, 3231078578318435503, 3650564119615239380, 14326743474610619866, 6057888008318385428, 877261269812179554}, + {4173134538206962623, 3229204914066791106, 14373492604488313855, 3534389340803093834, 9428519468573984436, 852153558715099384}, + {2824247917315701850, 9262429833338027215, 6341671507896672099, 6534432122201534844, 5345435135662795437, 842173193418807282}, + {4909241937507314855, 7694924294263165239, 8769219130691586997, 10793032422595820302, 9842347481337833813, 1715422591737782675}, + {4992773620456183628, 4960124718556857406, 16635883869473222492, 9030723886105284465, 9639626004410796071, 1472936790627757079}, + {4633471081912608531, 2457456277494344524, 13154727034911391217, 2104665078954431868, 10295379395729086298, 767461104919195256}, + {14729471909635070116, 5368296582378797012, 1897086539710188546, 361103558383519886, 8896957840055463365, 1735788401392751111}, + {1592137931790919824, 11719194462760023767, 9497330277892716736, 2098900411859438058, 10363149712103394122, 365907846568320398}, + {11815793238760025457, 17791303014563980294, 12530918126900801364, 12119502670364524909, 5311671350461240609, 673825776386754884}, + {13358415881952098629, 12009257493157516192, 13928884382876484932, 12988314785833227070, 11244145530317148182, 100673949996487007}, } +// g1IsogenyYNumerator evaluates the degree-15 YNumerator polynomial of the isogeny +// with 9 field multiplications (Horner: 15), then multiplies by y. +// +// The multiplication chain was preprocessed offline from the polynomial's +// coefficients (g1IsogenyYNumeratorMap) by internal/generator/hash_to_curve/gen_isogeny_chains.py, +// using the decoder of T. D. Ahle, "Fast Evaluation of Polynomials with Rational +// Preprocessing", https://arxiv.org/abs/2609.06022. The code is straight line: +// no branches, no divisions. func g1IsogenyYNumerator(dst *fp.Element, x *fp.Element, y *fp.Element) { - var _dst fp.Element - g1EvalPolynomial(&_dst, false, g1IsogenyYNumeratorMap, x) - dst.Mul(&_dst, y) + var w [8]fp.Element // gate outputs + var p, r fp.Element + w[0].Add(x, &g1IsogenyYNumeratorChainConstants[0]) + w[0].Mul(&w[0], x) + w[1].Add(x, &w[0]) + w[1].Add(&w[1], &g1IsogenyYNumeratorChainConstants[1]) + r.Add(&w[0], &g1IsogenyYNumeratorChainConstants[2]) + r.Sub(&r, x) + w[1].Mul(&w[1], &r) + w[2].Add(&w[0], &g1IsogenyYNumeratorChainConstants[3]) + r.Add(&w[1], &g1IsogenyYNumeratorChainConstants[4]) + w[2].Mul(&w[2], &r) + w[3].Add(&w[0], &g1IsogenyYNumeratorChainConstants[5]) + r.Add(&w[1], &g1IsogenyYNumeratorChainConstants[6]) + w[3].Mul(&w[3], &r) + w[4].Add(x, &g1IsogenyYNumeratorChainConstants[7]) + r.Add(&w[2], &g1IsogenyYNumeratorChainConstants[8]) + w[4].Mul(&w[4], &r) + w[5].Add(&w[0], &w[3]) + w[5].Add(&w[5], &w[4]) + w[5].Add(&w[5], &g1IsogenyYNumeratorChainConstants[9]) + r.Add(&w[3], &w[4]) + r.Add(&r, &g1IsogenyYNumeratorChainConstants[10]) + r.Sub(&r, &w[0]) + w[5].Mul(&w[5], &r) + w[6].Add(&w[0], &w[1]) + w[6].Add(&w[6], &g1IsogenyYNumeratorChainConstants[11]) + r.Add(&w[1], &g1IsogenyYNumeratorChainConstants[12]) + r.Sub(&r, &w[0]) + w[6].Mul(&w[6], &r) + w[7].Add(&w[5], &g1IsogenyYNumeratorChainConstants[13]) + w[7].Mul(&w[7], x) + p.Add(&w[5], &w[6]) + p.Add(&p, &w[7]) + p.Add(&p, &g1IsogenyYNumeratorChainConstants[14]) + p.Mul(&p, &g1IsogenyYNumeratorLeadingCoeff) + dst.Mul(&p, y) +} + +var g1IsogenyYNumeratorChainConstants = [15]fp.Element{ + {9341539374419864187, 12661666650125547291, 15050576578818458782, 16436560605120082265, 12841803867247672760, 1697966257822301786}, + {6997187068704776211, 2047886054065902469, 7491229313099591803, 12468015617744307702, 3793870287777280947, 1737857573665420684}, + {4938565506972034573, 2864676642734395385, 11238434408777804416, 7072535503611183952, 13056009866684644877, 286612937897282981}, + {5180625823623048065, 10722223189657292576, 7248347495285899561, 10812636461575635612, 3881204420667020004, 35222930534196566}, + {8652564573598987473, 3524396078714310015, 7045869031198929516, 13471023177429493854, 815236807700183836, 323341754126334457}, + {1838335475177633654, 6980877077897340857, 2223731915321694143, 13846171241860571934, 11995721847854244786, 50070691631217393}, + {6128884934326455690, 16971720263397206527, 4990019604929463039, 14494183259125775673, 10455529814494935719, 70169560533589392}, + {3934982667839147994, 10046253461943093433, 14274289710757525477, 3484358031075370555, 9910442355738907046, 567014539515328387}, + {10646432616152236610, 888087672710863378, 12617259199898917194, 11369500421827162127, 15148939875395180206, 429842411056305823}, + {11575858602251881000, 14270999975731726268, 11181778005899840394, 10327764244215573138, 18349930057735815896, 1005727036882437081}, + {645655947397059775, 14453413599267349525, 7390250566895406544, 12301720097166065737, 11517525156216452170, 1565853868543151395}, + {2092668882148706981, 3298714587590855248, 4377134456701193110, 2930336244409030124, 7303944704450282219, 877137892996283143}, + {12186209992434181351, 5722838635091871002, 14655215173329337886, 15130269355595617562, 10042678233841425533, 1419317083964138544}, + {16660243636546444693, 6528919913781322378, 8655073692430651876, 92017086777216117, 13333407411990660470, 1518618373869877762}, + {18238852772689360389, 18194121461366999202, 3219895556372350675, 17850580149965114675, 7661345408107376805, 907232516480140134}, } +var g1IsogenyYNumeratorLeadingCoeff = fp.Element{9739780494108151959, 17207219630538774058, 553911396609642498, 6085929320386029624, 14175410874026216616, 1183751611824804793} + +// g1IsogenyYDenominator evaluates the degree-15 YDenominator polynomial of the isogeny +// with 8 field multiplications (Horner: 14). +// +// The multiplication chain was preprocessed offline from the polynomial's +// coefficients (g1IsogenyYDenominatorMap) by internal/generator/hash_to_curve/gen_isogeny_chains.py, +// using the decoder of T. D. Ahle, "Fast Evaluation of Polynomials with Rational +// Preprocessing", https://arxiv.org/abs/2609.06022. The code is straight line: +// no branches, no divisions. func g1IsogenyYDenominator(dst *fp.Element, x *fp.Element) { - g1EvalPolynomial(dst, true, g1IsogenyYDenominatorMap, x) + var w [8]fp.Element // gate outputs + var p, r fp.Element + w[0].Add(x, &g1IsogenyYDenominatorChainConstants[0]) + w[0].Mul(&w[0], x) + w[1].Add(x, &w[0]) + w[1].Add(&w[1], &g1IsogenyYDenominatorChainConstants[1]) + r.Add(&w[0], &g1IsogenyYDenominatorChainConstants[2]) + r.Sub(&r, x) + w[1].Mul(&w[1], &r) + w[2].Add(&w[0], &g1IsogenyYDenominatorChainConstants[3]) + r.Add(&w[1], &g1IsogenyYDenominatorChainConstants[4]) + w[2].Mul(&w[2], &r) + w[3].Add(&w[0], &g1IsogenyYDenominatorChainConstants[5]) + r.Add(&w[1], &g1IsogenyYDenominatorChainConstants[6]) + w[3].Mul(&w[3], &r) + w[4].Add(x, &g1IsogenyYDenominatorChainConstants[7]) + r.Add(&w[2], &g1IsogenyYDenominatorChainConstants[8]) + w[4].Mul(&w[4], &r) + w[5].Add(&w[0], &w[3]) + w[5].Add(&w[5], &w[4]) + w[5].Add(&w[5], &g1IsogenyYDenominatorChainConstants[9]) + r.Add(&w[3], &w[4]) + r.Add(&r, &g1IsogenyYDenominatorChainConstants[10]) + r.Sub(&r, &w[0]) + w[5].Mul(&w[5], &r) + w[6].Add(&w[0], &w[1]) + w[6].Add(&w[6], &g1IsogenyYDenominatorChainConstants[11]) + r.Add(&w[1], &g1IsogenyYDenominatorChainConstants[12]) + r.Sub(&r, &w[0]) + w[6].Mul(&w[6], &r) + w[7].Add(&w[5], &g1IsogenyYDenominatorChainConstants[13]) + w[7].Mul(&w[7], x) + p.Add(&w[5], &w[6]) + p.Add(&p, &w[7]) + p.Add(&p, &g1IsogenyYDenominatorChainConstants[14]) + dst.Set(&p) +} + +var g1IsogenyYDenominatorChainConstants = [15]fp.Element{ + {4351853825157900291, 3189959405956014183, 9693781038269944662, 15999343542487569112, 14262186284771958870, 330976732091920498}, + {10834359129204116260, 16811186731023720251, 1361070829148503264, 10496597033781340076, 8195281093538926709, 472586028999636043}, + {14668432752695927216, 15860557426716348904, 4989869950405347471, 18030876457067564895, 9226144332763544815, 951931119130756645}, + {4445477433815392464, 8355408609401992925, 9714636477313264944, 4334180216196067476, 15596847285811231819, 459458012477518768}, + {9175117263506407330, 7665043603563099639, 14992039796913401838, 16641849914295347300, 11601684182277509569, 1657079538992265389}, + {15929087890134406300, 10319760383178931499, 10285300532742421389, 7943410795804900993, 14876643139186439457, 1596276481878178830}, + {16340489378605803174, 11283011956259475143, 674387761048624939, 4426307692803713723, 14443219635974173744, 1557828691568519518}, + {10545921357178864108, 15594348097707723990, 15473327185274904438, 8764077371853036608, 13271831619934195741, 920385881411392518}, + {14855786627654630811, 10416493882560543519, 13850931933133536255, 15697408803640484948, 7086584489928944952, 1571814805331589983}, + {15712014058109948774, 1169959681326011752, 10564652649649904541, 5798307453948932272, 18216503191581507329, 891856449765012965}, + {3697259045068105471, 13047750717235959811, 3265390356188050980, 4711864639360334533, 15958555604686194312, 1089417612796412513}, + {15668298835808880424, 11197470773611241957, 8178531292742659665, 7362770734193596843, 1101242818956391365, 1481758300769216242}, + {660082192885946951, 11892281773336660831, 16154631808458759393, 9657867637233850719, 4055474180365982538, 406314121927326411}, + {5968546725914058265, 18384324834702704977, 2528860028235658609, 958158598599046617, 9450697084054812609, 1774547465891498542}, + {1438921833372391620, 11365291231562371378, 11126110123879639732, 17581243018772093145, 12831861873541904436, 1012439064721072293}, } // G1 computes the isogeny map of the curve element, given by its coordinates pX and pY. diff --git a/ecc/bls12-381/hash_to_curve/g1_test.go b/ecc/bls12-381/hash_to_curve/g1_test.go index d50db441a5..09769a22ae 100644 --- a/ecc/bls12-381/hash_to_curve/g1_test.go +++ b/ecc/bls12-381/hash_to_curve/g1_test.go @@ -59,6 +59,75 @@ func TestG1SqrtRatio(t *testing.T) { properties.TestingRun(t, gopter.ConsoleReporter(false)) } +// TestG1IsogenyChains checks the preprocessed multiplication chains of the +// isogeny polynomials against Horner's rule on the original coefficients. +func TestG1IsogenyChains(t *testing.T) { + t.Parallel() + + check := func(x, y *fp.Element) { + var got, want fp.Element + g1IsogenyXNumerator(&got, x) + g1EvalPolynomial(&want, false, g1IsogenyXNumeratorMap, x) + if !got.Equal(&want) { + t.Fatal("x numerator: chain and Horner disagree") + } + g1IsogenyXDenominator(&got, x) + g1EvalPolynomial(&want, true, g1IsogenyXDenominatorMap, x) + if !got.Equal(&want) { + t.Fatal("x denominator: chain and Horner disagree") + } + g1IsogenyYNumerator(&got, x, y) + g1EvalPolynomial(&want, false, g1IsogenyYNumeratorMap, x) + want.Mul(&want, y) + if !got.Equal(&want) { + t.Fatal("y numerator: chain and Horner disagree") + } + g1IsogenyYDenominator(&got, x) + g1EvalPolynomial(&want, true, g1IsogenyYDenominatorMap, x) + if !got.Equal(&want) { + t.Fatal("y denominator: chain and Horner disagree") + } + } + + // 0, 1, -1 and random points + var special [3]fp.Element + special[1].SetOne() + special[2].Neg(&special[1]) + var y fp.Element + y.MustSetRandom() + for i := range special { + check(&special[i], &y) + } + n := 1000 + if testing.Short() { + n = 100 + } + for i := 0; i < n; i++ { + var x fp.Element + x.MustSetRandom() + y.MustSetRandom() + check(&x, &y) + } + + // aliasing as used by G1Isogeny: dst == x and dst == y + var x fp.Element + x.MustSetRandom() + y.MustSetRandom() + var want fp.Element + g1IsogenyXNumerator(&want, &x) + x2 := x + g1IsogenyXNumerator(&x2, &x2) + if !x2.Equal(&want) { + t.Fatal("x numerator: aliased evaluation differs") + } + g1IsogenyYNumerator(&want, &x, &y) + y2 := y + g1IsogenyYNumerator(&y2, &x, &y2) + if !y2.Equal(&want) { + t.Fatal("y numerator: aliased evaluation differs") + } +} + // BenchmarkG1IsogenyPolynomials evaluates the four isogeny polynomials as // G1Isogeny does (without the final batch inversion). func BenchmarkG1IsogenyPolynomials(b *testing.B) { diff --git a/ecc/bw6-633/hash_to_curve/g1.go b/ecc/bw6-633/hash_to_curve/g1.go index 73f4987dbd..252b5bc42c 100644 --- a/ecc/bw6-633/hash_to_curve/g1.go +++ b/ecc/bw6-633/hash_to_curve/g1.go @@ -89,22 +89,152 @@ func G1IsogenyMap() [4][]fp.Element { } } +// g1IsogenyXNumerator evaluates the degree-7 XNumerator polynomial of the isogeny +// with 5 field multiplications (Horner: 7). +// +// The multiplication chain was preprocessed offline from the polynomial's +// coefficients (g1IsogenyXNumeratorMap) by internal/generator/hash_to_curve/gen_isogeny_chains.py, +// using the decoder of T. D. Ahle, "Fast Evaluation of Polynomials with Rational +// Preprocessing", https://arxiv.org/abs/2609.06022. The code is straight line: +// no branches, no divisions. func g1IsogenyXNumerator(dst *fp.Element, x *fp.Element) { - g1EvalPolynomial(dst, false, g1IsogenyXNumeratorMap, x) + var w [4]fp.Element // gate outputs + var p, r fp.Element + r.Add(x, &g1IsogenyXNumeratorChainConstants[0]) + w[0].Mul(x, &r) + w[1].Add(x, &w[0]) + w[1].Add(&w[1], &g1IsogenyXNumeratorChainConstants[1]) + r.Add(x, &g1IsogenyXNumeratorChainConstants[2]) + w[1].Mul(&w[1], &r) + w[2].Add(&w[1], &g1IsogenyXNumeratorChainConstants[3]) + w[2].Mul(&w[2], x) + w[3].Add(x, &w[1]) + w[3].Add(&w[3], &g1IsogenyXNumeratorChainConstants[4]) + r.Add(&w[2], &g1IsogenyXNumeratorChainConstants[5]) + w[3].Mul(&w[3], &r) + p.Add(&w[0], &w[2]) + p.Add(&p, &w[3]) + p.Add(&p, &g1IsogenyXNumeratorChainConstants[6]) + dst.Mul(&p, &g1IsogenyXNumeratorLeadingCoeff) +} + +var g1IsogenyXNumeratorChainConstants = [7]fp.Element{ + {17795057939491773484, 4690063607668157888, 18105692324502773144, 1604108702303475586, 16985927235442716662, 5155147143699977717, 10462449119864086857, 9995265235133159537, 613402561969358250, 57026063948623391}, + {8045952637501113983, 6455984557689876304, 15632462251392080645, 15945633705459381100, 8592176258907923803, 14826609726216604973, 12097402621498978931, 6799058474534004857, 12604678534794556609, 82384807706648096}, + {1364909253200871113, 15881579639214123999, 17163536323383138048, 7887298243362575438, 3670472912465113392, 11805781306583351911, 844632159965685305, 10994758396899788966, 2564299134045741418, 20931658058139245}, + {13054255490104033038, 13260896439787544960, 3853543652058571856, 8996760652246533594, 16556904948262159587, 7447551162619517080, 14739097721666160918, 17917221620657186550, 2217937318136064462, 54551827318619126}, + {4495063241761702873, 1058514130783427263, 7492873385918154823, 17261245735424327254, 8612615563135507871, 1229783241316043679, 16151526896617240895, 2107233473493303641, 4507397647992052182, 50201449282091162}, + {7998691840916010212, 3987342362036176785, 8191467580897823323, 3847850839619793855, 10974328303784297043, 4345796480065083211, 476910335202227147, 12992618282015264872, 11341917288934138476, 41619030552067644}, + {14343776272664904858, 15316006361240527662, 7607868531219299539, 12710220370627715593, 13490458704207407746, 15623356199278730352, 15264350091117869198, 17660902716535095242, 8617449707231959956, 70836900137550749}, } +var g1IsogenyXNumeratorLeadingCoeff = fp.Element{9724060856090837937, 991577158671892474, 8081435887940851138, 17002015655933157445, 16512917147008832308, 4279771572102941926, 2249177714740675361, 7317077314484777626, 9914066020430477973, 6118378914363629} + func g1IsogenyXDenominator(dst *fp.Element, x *fp.Element) { g1EvalPolynomial(dst, true, g1IsogenyXDenominatorMap, x) } +// g1IsogenyYNumerator evaluates the degree-9 YNumerator polynomial of the isogeny +// with 6 field multiplications (Horner: 9), then multiplies by y. +// +// The multiplication chain was preprocessed offline from the polynomial's +// coefficients (g1IsogenyYNumeratorMap) by internal/generator/hash_to_curve/gen_isogeny_chains.py, +// using the decoder of T. D. Ahle, "Fast Evaluation of Polynomials with Rational +// Preprocessing", https://arxiv.org/abs/2609.06022. The code is straight line: +// no branches, no divisions. func g1IsogenyYNumerator(dst *fp.Element, x *fp.Element, y *fp.Element) { - var _dst fp.Element - g1EvalPolynomial(&_dst, false, g1IsogenyYNumeratorMap, x) - dst.Mul(&_dst, y) + var w [5]fp.Element // gate outputs + var p, r fp.Element + w[0].Add(x, &g1IsogenyYNumeratorChainConstants[0]) + w[0].Mul(&w[0], x) + w[1].Add(x, &w[0]) + w[1].Add(&w[1], &g1IsogenyYNumeratorChainConstants[1]) + r.Add(&w[0], &g1IsogenyYNumeratorChainConstants[2]) + r.Sub(&r, x) + w[1].Mul(&w[1], &r) + w[2].Add(x, &w[0]) + w[2].Add(&w[2], &w[1]) + w[2].Add(&w[2], &g1IsogenyYNumeratorChainConstants[3]) + r.Add(&w[1], &g1IsogenyYNumeratorChainConstants[4]) + r.Sub(&r, x) + r.Sub(&r, &w[0]) + w[2].Mul(&w[2], &r) + w[3].Add(&w[0], &w[1]) + w[3].Add(&w[3], &g1IsogenyYNumeratorChainConstants[5]) + r.Add(&w[1], &g1IsogenyYNumeratorChainConstants[6]) + r.Sub(&r, &w[0]) + w[3].Mul(&w[3], &r) + w[4].Add(x, &w[2]) + w[4].Add(&w[4], &g1IsogenyYNumeratorChainConstants[7]) + w[4].Mul(&w[4], x) + p.Add(&w[3], &w[4]) + p.Add(&p, &g1IsogenyYNumeratorChainConstants[8]) + p.Mul(&p, &g1IsogenyYNumeratorLeadingCoeff) + dst.Mul(&p, y) } +var g1IsogenyYNumeratorChainConstants = [9]fp.Element{ + {956073432138382987, 6739453244741932649, 394971375267047345, 2013723572283565681, 2706842993316235208, 8986004168913644569, 4765538252239816549, 6203998136560182865, 15325587248165767299, 21927374493565827}, + {15285249406835733482, 6750081521070171105, 8815357268962930518, 13372636673286981002, 9852991772275223059, 9836724727988434503, 11838445730275468299, 14417385026966200909, 8640409249639115248, 30231369558417352}, + {13033222686903738272, 15045409446585490655, 13449268853060965870, 1844766025531644988, 10991223098910245280, 10558367046510669781, 10952800124273730602, 6901531103954286112, 14614353704262010100, 33788707984492860}, + {12227057337671686943, 16714302104556474377, 9191470729599018233, 3114223373832331925, 15491019502479521908, 2233830756582419937, 9888623113094608460, 4297222150762075262, 3135445299964252626, 22296023478686528}, + {18289492675621947761, 10552803483944364625, 568039562668474578, 150367334304827634, 11541638740771882575, 3556066365009686488, 7586561412728661847, 118659088003205347, 13109287116593489402, 5834310773713201}, + {5073916756560505243, 9957733281498190086, 16203605825895789556, 7841421921259093979, 849166629447316384, 16113969231805781825, 16104175962138948219, 2070956967774434961, 15354922230577453422, 23917366283531246}, + {447506285131928128, 5992449870672590418, 16953557801398367385, 7003041180933403227, 11480832947744144929, 8505227971375716041, 2795282820222653714, 1126859653820044408, 5332608447092235230, 61661272497558066}, + {11447938988046376418, 13231201925558004830, 14228694670413025794, 8585701198147104166, 15417427169369596248, 9155086897240051445, 10786163334353262350, 8915038489430403992, 5604664099447202617, 10616822892422118}, + {10823487502582422342, 16191757651498294878, 6291570879114689887, 7952179575019830933, 203272418423596496, 6769706858503850454, 10390325057885543650, 12366658724134327955, 8928887847310430819, 18390322519699520}, +} + +var g1IsogenyYNumeratorLeadingCoeff = fp.Element{12326780164586609392, 5644226856352746503, 15218547976647793114, 1423996738351226436, 17696389932683702646, 16585810622359183722, 11617060654723736714, 10287699425090206986, 6288819172487953077, 58313628540302044} + +// g1IsogenyYDenominator evaluates the degree-9 YDenominator polynomial of the isogeny +// with 5 field multiplications (Horner: 8). +// +// The multiplication chain was preprocessed offline from the polynomial's +// coefficients (g1IsogenyYDenominatorMap) by internal/generator/hash_to_curve/gen_isogeny_chains.py, +// using the decoder of T. D. Ahle, "Fast Evaluation of Polynomials with Rational +// Preprocessing", https://arxiv.org/abs/2609.06022. The code is straight line: +// no branches, no divisions. func g1IsogenyYDenominator(dst *fp.Element, x *fp.Element) { - g1EvalPolynomial(dst, true, g1IsogenyYDenominatorMap, x) + var w [5]fp.Element // gate outputs + var p, r fp.Element + w[0].Add(x, &g1IsogenyYDenominatorChainConstants[0]) + w[0].Mul(&w[0], x) + w[1].Add(x, &w[0]) + w[1].Add(&w[1], &g1IsogenyYDenominatorChainConstants[1]) + r.Add(&w[0], &g1IsogenyYDenominatorChainConstants[2]) + r.Sub(&r, x) + w[1].Mul(&w[1], &r) + w[2].Add(x, &w[0]) + w[2].Add(&w[2], &w[1]) + w[2].Add(&w[2], &g1IsogenyYDenominatorChainConstants[3]) + r.Add(&w[1], &g1IsogenyYDenominatorChainConstants[4]) + r.Sub(&r, x) + r.Sub(&r, &w[0]) + w[2].Mul(&w[2], &r) + w[3].Add(&w[0], &w[1]) + w[3].Add(&w[3], &g1IsogenyYDenominatorChainConstants[5]) + r.Add(&w[1], &g1IsogenyYDenominatorChainConstants[6]) + r.Sub(&r, &w[0]) + w[3].Mul(&w[3], &r) + w[4].Add(x, &w[2]) + w[4].Add(&w[4], &g1IsogenyYDenominatorChainConstants[7]) + w[4].Mul(&w[4], x) + p.Add(&w[3], &w[4]) + p.Add(&p, &g1IsogenyYDenominatorChainConstants[8]) + dst.Set(&p) +} + +var g1IsogenyYDenominatorChainConstants = [9]fp.Element{ + {956073432138382987, 6739453244741932649, 394971375267047345, 2013723572283565681, 2706842993316235208, 8986004168913644569, 4765538252239816549, 6203998136560182865, 15325587248165767299, 21927374493565827}, + {1418295457606371858, 17368696144712197775, 12236411670842614142, 6765535776171847098, 1383556754597404786, 11336121301189209313, 6765892652581053089, 5866147648855534349, 3133164467696956617, 34058094516696936}, + {522649552753394574, 1372960910319838727, 190688006658473422, 8769503943195172898, 15882483773468892457, 7381790717535866601, 16933597674150775553, 2481325458225267721, 6508421928076105491, 30382665599415343}, + {15916266482252776874, 12608217485240427741, 12755407579453891572, 6423112203045265908, 10508961829522844045, 8574845991603980864, 6622365784763534426, 15841349676730465698, 1831358647051271671, 58281103381974433}, + {17194157674675078029, 4803505495010405268, 2877676460321188509, 2282200305258339170, 12092177629290784665, 11001705081490959859, 2621965999951458780, 17068773018637862688, 7375425388204190600, 75954720376202151}, + {15270575552194567282, 10448985672227127104, 15308229899879658205, 15822472730125954279, 2523654967994407437, 102499087840608471, 17522894655410280492, 2094513768925804706, 5601415006496805368, 80150322455048787}, + {8320645483506465830, 9865855130496142922, 4647995534997940502, 5894146244068739437, 11926677491022013701, 2557921561559611660, 2542580033772629367, 514591411353582325, 12807246917557208279, 50583173735577927}, + {11989858795523605748, 6486363518254465684, 7614007317855782675, 9003673941388435602, 10712555808113870946, 12015705068440069976, 15705686853961276132, 7485710257515013773, 16474907105495816046, 6721118600164277}, + {10690380855825180487, 1789489936775370569, 14860239881148206278, 5767114307106263237, 13592262005505315518, 15470648969292377267, 8065627264630868222, 13575848932011500954, 10203165114724852859, 80268351198227876}, } // G1 computes the isogeny map of the curve element, given by its coordinates pX and pY. diff --git a/ecc/bw6-633/hash_to_curve/g1_test.go b/ecc/bw6-633/hash_to_curve/g1_test.go index 7ea5efec5d..4f8b212a3d 100644 --- a/ecc/bw6-633/hash_to_curve/g1_test.go +++ b/ecc/bw6-633/hash_to_curve/g1_test.go @@ -59,6 +59,70 @@ func TestG1SqrtRatio(t *testing.T) { properties.TestingRun(t, gopter.ConsoleReporter(false)) } +// TestG1IsogenyChains checks the preprocessed multiplication chains of the +// isogeny polynomials against Horner's rule on the original coefficients. +func TestG1IsogenyChains(t *testing.T) { + t.Parallel() + + check := func(x, y *fp.Element) { + var got, want fp.Element + g1IsogenyXNumerator(&got, x) + g1EvalPolynomial(&want, false, g1IsogenyXNumeratorMap, x) + if !got.Equal(&want) { + t.Fatal("x numerator: chain and Horner disagree") + } + g1IsogenyYNumerator(&got, x, y) + g1EvalPolynomial(&want, false, g1IsogenyYNumeratorMap, x) + want.Mul(&want, y) + if !got.Equal(&want) { + t.Fatal("y numerator: chain and Horner disagree") + } + g1IsogenyYDenominator(&got, x) + g1EvalPolynomial(&want, true, g1IsogenyYDenominatorMap, x) + if !got.Equal(&want) { + t.Fatal("y denominator: chain and Horner disagree") + } + } + + // 0, 1, -1 and random points + var special [3]fp.Element + special[1].SetOne() + special[2].Neg(&special[1]) + var y fp.Element + y.MustSetRandom() + for i := range special { + check(&special[i], &y) + } + n := 1000 + if testing.Short() { + n = 100 + } + for i := 0; i < n; i++ { + var x fp.Element + x.MustSetRandom() + y.MustSetRandom() + check(&x, &y) + } + + // aliasing as used by G1Isogeny: dst == x and dst == y + var x fp.Element + x.MustSetRandom() + y.MustSetRandom() + var want fp.Element + g1IsogenyXNumerator(&want, &x) + x2 := x + g1IsogenyXNumerator(&x2, &x2) + if !x2.Equal(&want) { + t.Fatal("x numerator: aliased evaluation differs") + } + g1IsogenyYNumerator(&want, &x, &y) + y2 := y + g1IsogenyYNumerator(&y2, &x, &y2) + if !y2.Equal(&want) { + t.Fatal("y numerator: aliased evaluation differs") + } +} + // BenchmarkG1IsogenyPolynomials evaluates the four isogeny polynomials as // G1Isogeny does (without the final batch inversion). func BenchmarkG1IsogenyPolynomials(b *testing.B) { diff --git a/ecc/bw6-761/hash_to_curve/g2.go b/ecc/bw6-761/hash_to_curve/g2.go index ace75e2f42..b1eb58b025 100644 --- a/ecc/bw6-761/hash_to_curve/g2.go +++ b/ecc/bw6-761/hash_to_curve/g2.go @@ -239,22 +239,741 @@ func G2IsogenyMap() [4][]fp.Element { } } +// g2IsogenyXNumerator evaluates the degree-37 XNumerator polynomial of the isogeny +// with 20 field multiplications (Horner: 37). +// +// The multiplication chain was preprocessed offline from the polynomial's +// coefficients (g2IsogenyXNumeratorMap) by internal/generator/hash_to_curve/gen_isogeny_chains.py, +// using the decoder of T. D. Ahle, "Fast Evaluation of Polynomials with Rational +// Preprocessing", https://arxiv.org/abs/2609.06022. The code is straight line: +// no branches, no divisions. func g2IsogenyXNumerator(dst *fp.Element, x *fp.Element) { - g2EvalPolynomial(dst, false, g2IsogenyXNumeratorMap, x) + var w [19]fp.Element // gate outputs + var p, r, t fp.Element + w[0].Add(x, &g2IsogenyXNumeratorChainConstants[0]) + w[0].Mul(&w[0], x) + w[1].Add(x, &w[0]) + w[1].Add(&w[1], &g2IsogenyXNumeratorChainConstants[1]) + r.Add(&w[0], &g2IsogenyXNumeratorChainConstants[2]) + r.Sub(&r, x) + w[1].Mul(&w[1], &r) + w[2].Add(&w[0], &w[1]) + w[2].Add(&w[2], &g2IsogenyXNumeratorChainConstants[3]) + t.Double(x) + w[2].Add(&w[2], &t) + r.Add(&w[0], &w[1]) + r.Add(&r, &g2IsogenyXNumeratorChainConstants[4]) + w[2].Mul(&w[2], &r) + w[3].Add(x, &g2IsogenyXNumeratorChainConstants[5]) + r.Add(&w[0], &g2IsogenyXNumeratorChainConstants[6]) + w[3].Mul(&w[3], &r) + w[4].Add(x, &g2IsogenyXNumeratorChainConstants[7]) + r.Add(&w[0], &g2IsogenyXNumeratorChainConstants[8]) + w[4].Mul(&w[4], &r) + w[5].Add(&w[1], &w[2]) + w[5].Add(&w[5], &w[3]) + w[5].Add(&w[5], &g2IsogenyXNumeratorChainConstants[9]) + r.Add(&w[2], &g2IsogenyXNumeratorChainConstants[10]) + r.Sub(&r, &w[1]) + r.Sub(&r, &w[3]) + w[5].Mul(&w[5], &r) + w[6].Add(&w[1], &w[2]) + w[6].Add(&w[6], &g2IsogenyXNumeratorChainConstants[11]) + r.Add(&w[2], &g2IsogenyXNumeratorChainConstants[12]) + r.Sub(&r, &w[1]) + w[6].Mul(&w[6], &r) + w[7].Add(&w[0], &g2IsogenyXNumeratorChainConstants[13]) + r.Add(&w[1], &g2IsogenyXNumeratorChainConstants[14]) + w[7].Mul(&w[7], &r) + w[8].Add(&w[0], &g2IsogenyXNumeratorChainConstants[15]) + r.Add(&w[1], &g2IsogenyXNumeratorChainConstants[16]) + w[8].Mul(&w[8], &r) + w[9].Add(x, &g2IsogenyXNumeratorChainConstants[17]) + r.Add(&w[7], &g2IsogenyXNumeratorChainConstants[18]) + w[9].Mul(&w[9], &r) + w[10].Add(&w[0], &g2IsogenyXNumeratorChainConstants[19]) + r.Add(&w[1], &g2IsogenyXNumeratorChainConstants[20]) + w[10].Mul(&w[10], &r) + w[11].Add(&w[0], &g2IsogenyXNumeratorChainConstants[21]) + r.Add(&w[1], &g2IsogenyXNumeratorChainConstants[22]) + w[11].Mul(&w[11], &r) + w[12].Add(x, &g2IsogenyXNumeratorChainConstants[23]) + r.Add(&w[10], &g2IsogenyXNumeratorChainConstants[24]) + w[12].Mul(&w[12], &r) + w[13].Add(&w[2], &w[4]) + w[13].Add(&w[13], &w[5]) + w[13].Add(&w[13], &w[8]) + w[13].Add(&w[13], &w[9]) + w[13].Add(&w[13], &g2IsogenyXNumeratorChainConstants[25]) + r.Add(&w[4], &w[5]) + r.Add(&r, &g2IsogenyXNumeratorChainConstants[26]) + r.Sub(&r, &w[2]) + r.Sub(&r, &w[8]) + r.Sub(&r, &w[9]) + w[13].Mul(&w[13], &r) + w[14].Add(&w[2], &w[6]) + w[14].Add(&w[14], &g2IsogenyXNumeratorChainConstants[27]) + r.Add(&w[6], &g2IsogenyXNumeratorChainConstants[28]) + r.Sub(&r, &w[2]) + w[14].Mul(&w[14], &r) + w[15].Add(x, &g2IsogenyXNumeratorChainConstants[29]) + r.Add(&w[0], &g2IsogenyXNumeratorChainConstants[30]) + w[15].Mul(&w[15], &r) + w[16].Add(&w[1], &g2IsogenyXNumeratorChainConstants[31]) + t.Double(x) + t.Double(&t) + t.Double(&t) + w[16].Sub(&w[16], &t) + t.Double(&w[0]) + t.Double(&t) + t.Double(&t) + w[16].Sub(&w[16], &t) + r.Add(&w[11], &w[12]) + r.Add(&r, &w[13]) + r.Add(&r, &g2IsogenyXNumeratorChainConstants[32]) + w[16].Mul(&w[16], &r) + w[17].Add(&w[1], &g2IsogenyXNumeratorChainConstants[33]) + t.Double(x) + t.Double(&t) + t.Double(&t) + w[17].Sub(&w[17], &t) + t.Double(&w[0]) + t.Double(&t) + t.Double(&t) + w[17].Sub(&w[17], &t) + r.Add(&w[14], &g2IsogenyXNumeratorChainConstants[34]) + w[17].Mul(&w[17], &r) + w[18].Add(&w[15], &w[16]) + w[18].Add(&w[18], &g2IsogenyXNumeratorChainConstants[35]) + w[18].Mul(&w[18], x) + p.Add(&w[17], &w[18]) + p.Add(&p, &g2IsogenyXNumeratorChainConstants[36]) + dst.Mul(&p, &g2IsogenyXNumeratorLeadingCoeff) +} + +var g2IsogenyXNumeratorChainConstants = [37]fp.Element{ + {15660156619040626664, 6765986347472863569, 17964089694103234490, 16759476759793257991, 12664394140701378796, 4072274334369135751, 6087250276926613235, 9886274326136566530, 1758014532112695361, 6095671424456890598, 5265989588483034088, 45336579717735681}, + {12282914258321061468, 18023162623693698060, 10547235272035775881, 373601955761278228, 6053075801475095836, 1263994914621750447, 5703252916111616083, 15506960990200643293, 4921240846628830437, 17216111157409722085, 16613438290466701080, 10735891046069842}, + {15610042352690884276, 16328607221126880148, 15156148388179649922, 6728490240897411007, 10183292044839989291, 7384474243387271409, 6492797978066365763, 9151751113179640694, 12439047368846336106, 8665383514443658338, 16922564564971034162, 26767348777079988}, + {6631060013052797120, 3654354214607431063, 11116496887396367729, 16648463179702607900, 11945191842880327168, 13971596790616288021, 16071959218251656725, 16971997772349022636, 824268090466931545, 5508496988174255623, 94280414901388794, 22043730154984105}, + {4900185259857964035, 11197717699705739044, 1874619036077998264, 6701808184987309536, 2622022733896220891, 4902351836400015619, 15320981393697394054, 8152317878510304522, 3294805084757435687, 15134994168655652853, 1567673158535435932, 42487972904076046}, + {1612055799004447328, 262958312008933694, 15895880659727404413, 10423054322752286198, 14430028980931053306, 4458702654647419747, 5778258188499488450, 3879521565394833024, 12551309416236374997, 11152893004905548032, 6983611417027408860, 49140186605273391}, + {5852307118726162730, 7528014097821796092, 7302977653475970490, 9665665154626492211, 3353436125043915205, 2913181839899188509, 2928896837209867647, 10293774622696584388, 1498320879323844031, 5718742510533618390, 889082807522964527, 47245993512507155}, + {7087068903201370175, 602581949786898633, 1493700076574013395, 6191457947499559071, 15087736040062908522, 9424836950338639181, 3295419285652707564, 1251164816766308859, 758655716979322910, 4027019235442324071, 5034883154337058922, 26031616778708523}, + {7186915994598444562, 11717428938325424178, 12929048726545402185, 11136803509686993642, 12075074871726841615, 7610180365777267771, 9255307002764552544, 9817659378281545438, 6007787221855615609, 17888608820549708424, 12551623257116900155, 74527466134489457}, + {362943468712935447, 6233749086811868688, 8939390684085590025, 15490386829013583896, 8433556006894782492, 12297324499685017310, 12007236913855513982, 5609795540800844449, 14660703866381319240, 14884416677718382352, 7925918405676423287, 2398049634092038}, + {16062342103349198961, 15226883611449101711, 14277106868501847999, 17606319434531102046, 15537286488573197037, 6477722201819406159, 12667452890869835535, 4207621560039652827, 15406194998265251942, 14443522369185563976, 16938982128455560896, 28592445929232284}, + {16961836503991148191, 15067365447203028521, 12355510534435633006, 16270116698090076434, 13139227365396605472, 6941346068839705044, 12580222329751256480, 13858097284170736651, 6611080155309016044, 6116571226113593342, 3411652686812506898, 74035324390421022}, + {11905324087967486239, 784767506880922902, 5054250618779258778, 13329311137793071932, 9186309488368158535, 9542241505154573299, 15320714869816548575, 151061656346467794, 16400066796889518905, 10108200532391068891, 11917209376689017105, 51992890385067316}, + {15514070612292927741, 955213832217213739, 8255443112304433917, 2989624794463381883, 15256987747291129007, 5628141899944360067, 9687164560547528566, 737559472694981816, 3572556401156409935, 10766451823195777120, 5047668303830079511, 930761044617845}, + {17909886825406371179, 3978806984777702187, 13411469840757770841, 18192397975208216926, 11789606121758034383, 13546095793483839867, 5857243192375176929, 9465477423043778129, 17953006575723965927, 4959841473763343340, 322023879092539893, 57273528262239110}, + {14040970225749899018, 11536829144286418000, 11472451372792886009, 5586668956174274645, 17661456457798141418, 4494732860399606025, 11326520723098805408, 9405053367012771310, 3470014206253235601, 17808931873440415857, 4976378659562525889, 70267856007126397}, + {7548002884555392233, 17398342451123581598, 8390445404932182519, 14641601814968488445, 11113420794033265638, 7589853595783841088, 15689723077751272006, 1010295869185115717, 8707405157749669218, 17499261798536865933, 4693820286591748371, 840074039731376}, + {14331023206146802308, 3074731574099586035, 6637864410744482121, 13840895344263742543, 770807961757117524, 8559905748634133341, 13143881079534989950, 15113084139818566867, 2190504979272369716, 16386996184004399179, 13420383325325030679, 9109854326146670}, + {16114199173278571604, 17051635769195127759, 3091987420954804459, 4787703051795412793, 15899150169693575580, 3165902764030446394, 965558480067970114, 5794565846040374134, 17180418519650032397, 6080715714433839364, 16697211759202507753, 53724256677658588}, + {12167007497222134883, 17976611555391965262, 16998941646664115153, 16277650041577273930, 18380399009399643023, 10547859702339442305, 11562537106554557991, 14739951910043968603, 1740276668892236028, 10575900914706676669, 10296531217213814409, 80811017439291605}, + {11291696860643323193, 4998443446460456248, 3241661767855813334, 9961009152320959502, 7518860765966007083, 17068143321861531647, 6782122696961975758, 13684592100088903979, 16576711471969383761, 7714099671841283926, 14382379306718520192, 20527791098939269}, + {6556013513305471559, 8328563157079746760, 18127985222733655672, 10223550914371238981, 15891972766380807768, 11716181835398465496, 3980386471941908977, 1055268910898320314, 3142459227814748706, 15110619336480745127, 4592646890959156340, 28572562065079538}, + {16443640599850945211, 16832575163129712382, 9691180987536753387, 9218960594248281051, 13990070007247811830, 9830045060391765812, 14658697120969930993, 16913073074426834012, 11786109525626593646, 9353786441396806219, 10827903510707157127, 1947859280887726}, + {9788047265451195283, 15394362794428633134, 16487199602177108431, 8185515517032565387, 18280626166559102075, 84680367122374583, 15905498929338899401, 13178711382838282928, 17080807766267893704, 14192926739848733055, 14490351237303004712, 70638295521705973}, + {478470855868339586, 15856157573454017035, 1620300516064713894, 4269272095379767, 2794500205988253378, 1445746088801020569, 1484854898575594082, 12005169520690218878, 4534613398775837571, 4094429027077516231, 7480972322296289808, 61809574654454843}, + {16060791276298938641, 5208343034853912898, 10444469908219191707, 17859078658617199372, 10211078218634493491, 9921357658717830467, 14113429393755793993, 16491061027829050727, 12167441610727830411, 1510226415033300756, 465570857251261583, 16378754375709240}, + {17091453815742117787, 14129505137323132001, 2678914098262029516, 7811849982392719033, 8735942357640748319, 14738088983580682381, 725981622341724716, 5766945126872631233, 6774511163916316774, 9532447534851688900, 5400707908610336709, 11379990424246287}, + {12187645415522023002, 2537259016288717269, 12609662451527579525, 8172833390997177746, 5032587158657169525, 2148367377958384689, 2291332333907746220, 8311489231486849317, 9877859333093402424, 13729270327324997, 21667981066331013, 63720061245783928}, + {10723053406113890876, 13344321875934495926, 7074281893829573247, 1708269490989913188, 17648512172390459408, 10893087179926289218, 1335259029882042255, 14406146453907026071, 1936597591966941853, 12905194334639681274, 14306684625445556163, 67988474182412549}, + {16472240794681230601, 2352635835384268714, 12826643234937079347, 13789071246699163540, 2654240850593655400, 6681389207672409199, 10765770862904298910, 6388543816825236685, 11739165426868489462, 3811875649724266985, 4303682039061486247, 26287299894099577}, + {14211006900825472038, 16465543533305296232, 5897082254852388093, 6520110756709429418, 7877449480758836424, 17904035865628751635, 17600968142728049594, 15461842095210130405, 1909230571102446520, 10301722076288308556, 4819113218677260142, 55352974348656512}, + {8786844007909934261, 5642893440003092511, 4183291281212769177, 9667296268728904845, 5424609826032865731, 5217325325257443958, 11825202126018622718, 1639446446685863805, 16891633224204724272, 12648521542135709344, 11617837770300273200, 74872382179005099}, + {2382882648881565408, 2112935474010569232, 10534415096668541571, 3555016208528551039, 7126636024652925935, 4218545091321151184, 1263159274734056668, 17335170738408311505, 12958492083267052560, 8909432054938888480, 7032178771932882442, 55134373394852961}, + {6342431557310200863, 4749445200442241814, 10118429605068626994, 5380015135604123085, 3482146848446674189, 547289449930237098, 8457865136413652790, 16359013433118332284, 17362522624219981140, 1626548161273728221, 6410815249428237690, 26360506931534112}, + {14386767670449864218, 12104704127608398008, 3323384919320899317, 13711225293217298748, 17998642735233855995, 5963395294796241503, 14030545868993983612, 5235986301097588305, 13880395620091054707, 9680918580840390946, 12005556641179495661, 10475811355831157}, + {4311854408584394443, 4927669195861557163, 5398135820758952101, 10603415017552785558, 995708032844235810, 4468650349404734622, 13968125383364627251, 2730723156700528470, 15945715898764678662, 17687564366533532731, 3216146425982295044, 47575704308364337}, + {5675391343527643294, 10440999401802424044, 2238103791664567782, 3201069247135638955, 15826721216812206342, 2696525248287486352, 8423365003671424511, 13719348410558573460, 2677158031148395362, 1297316169729169276, 12430209702101195309, 12000509435806366}, } +var g2IsogenyXNumeratorLeadingCoeff = fp.Element{7400649881422048662, 10325623896702355497, 3429416132468711391, 4019846222145941118, 4388535951465307810, 10138700893509897592, 14296210806827563244, 2235456450135710357, 10673962638466829444, 5656064363870144290, 14593618993797886569, 77712983218315624} + +// g2IsogenyXDenominator evaluates the degree-36 XDenominator polynomial of the isogeny +// with 19 field multiplications (Horner: 35). +// +// The multiplication chain was preprocessed offline from the polynomial's +// coefficients (g2IsogenyXDenominatorMap) by internal/generator/hash_to_curve/gen_isogeny_chains.py, +// using the decoder of T. D. Ahle, "Fast Evaluation of Polynomials with Rational +// Preprocessing", https://arxiv.org/abs/2609.06022. The code is straight line: +// no branches, no divisions. func g2IsogenyXDenominator(dst *fp.Element, x *fp.Element) { - g2EvalPolynomial(dst, true, g2IsogenyXDenominatorMap, x) + var w [19]fp.Element // gate outputs + var p, r fp.Element + w[0].Add(x, &g2IsogenyXDenominatorChainConstants[0]) + w[0].Mul(&w[0], x) + w[1].Add(x, &w[0]) + w[1].Add(&w[1], &g2IsogenyXDenominatorChainConstants[1]) + r.Add(&w[0], &g2IsogenyXDenominatorChainConstants[2]) + r.Sub(&r, x) + w[1].Mul(&w[1], &r) + w[2].Add(x, &w[0]) + w[2].Add(&w[2], &w[1]) + w[2].Add(&w[2], &g2IsogenyXDenominatorChainConstants[3]) + r.Add(&w[1], &g2IsogenyXDenominatorChainConstants[4]) + r.Sub(&r, x) + r.Sub(&r, &w[0]) + w[2].Mul(&w[2], &r) + w[3].Add(&w[0], &w[1]) + w[3].Add(&w[3], &g2IsogenyXDenominatorChainConstants[5]) + r.Add(&w[1], &g2IsogenyXDenominatorChainConstants[6]) + r.Sub(&r, &w[0]) + w[3].Mul(&w[3], &r) + w[4].Add(x, &w[0]) + w[4].Add(&w[4], &g2IsogenyXDenominatorChainConstants[7]) + r.Add(&w[0], &g2IsogenyXDenominatorChainConstants[8]) + r.Sub(&r, x) + w[4].Mul(&w[4], &r) + w[5].Add(x, &w[0]) + w[5].Add(&w[5], &w[4]) + w[5].Add(&w[5], &g2IsogenyXDenominatorChainConstants[9]) + r.Add(&w[4], &g2IsogenyXDenominatorChainConstants[10]) + r.Sub(&r, x) + r.Sub(&r, &w[0]) + w[5].Mul(&w[5], &r) + w[6].Add(&w[0], &w[4]) + w[6].Add(&w[6], &g2IsogenyXDenominatorChainConstants[11]) + r.Add(&w[4], &g2IsogenyXDenominatorChainConstants[12]) + r.Sub(&r, &w[0]) + w[6].Mul(&w[6], &r) + w[7].Add(x, &g2IsogenyXDenominatorChainConstants[13]) + r.Add(&w[0], &g2IsogenyXDenominatorChainConstants[14]) + w[7].Mul(&w[7], &r) + w[8].Add(x, &g2IsogenyXDenominatorChainConstants[15]) + r.Add(&w[0], &g2IsogenyXDenominatorChainConstants[16]) + w[8].Mul(&w[8], &r) + w[9].Add(x, &w[4]) + w[9].Add(&w[9], &w[5]) + w[9].Add(&w[9], &w[7]) + w[9].Add(&w[9], &g2IsogenyXDenominatorChainConstants[17]) + r.Add(x, &w[5]) + r.Add(&r, &g2IsogenyXDenominatorChainConstants[18]) + r.Sub(&r, &w[4]) + r.Sub(&r, &w[7]) + w[9].Mul(&w[9], &r) + w[10].Add(&w[4], &w[6]) + w[10].Add(&w[10], &g2IsogenyXDenominatorChainConstants[19]) + r.Add(&w[6], &g2IsogenyXDenominatorChainConstants[20]) + r.Sub(&r, &w[4]) + w[10].Mul(&w[10], &r) + w[11].Add(x, &g2IsogenyXDenominatorChainConstants[21]) + r.Add(&w[8], &w[9]) + r.Add(&r, &g2IsogenyXDenominatorChainConstants[22]) + w[11].Mul(&w[11], &r) + w[12].Add(&w[0], &g2IsogenyXDenominatorChainConstants[23]) + r.Add(&w[4], &g2IsogenyXDenominatorChainConstants[24]) + w[12].Mul(&w[12], &r) + w[13].Add(&w[0], &g2IsogenyXDenominatorChainConstants[25]) + r.Add(&w[4], &g2IsogenyXDenominatorChainConstants[26]) + w[13].Mul(&w[13], &r) + w[14].Add(x, &g2IsogenyXDenominatorChainConstants[27]) + r.Add(&w[12], &g2IsogenyXDenominatorChainConstants[28]) + w[14].Mul(&w[14], &r) + w[15].Add(x, &w[2]) + w[15].Add(&w[15], &w[10]) + w[15].Add(&w[15], &w[11]) + w[15].Add(&w[15], &g2IsogenyXDenominatorChainConstants[29]) + r.Add(&w[10], &w[11]) + r.Add(&r, &g2IsogenyXDenominatorChainConstants[30]) + r.Sub(&r, x) + r.Sub(&r, &w[2]) + w[15].Mul(&w[15], &r) + w[16].Add(&w[3], &w[10]) + w[16].Add(&w[16], &w[11]) + w[16].Add(&w[16], &g2IsogenyXDenominatorChainConstants[31]) + r.Add(&w[10], &w[11]) + r.Add(&r, &g2IsogenyXDenominatorChainConstants[32]) + r.Sub(&r, &w[3]) + w[16].Mul(&w[16], &r) + w[17].Add(&w[13], &w[14]) + w[17].Add(&w[17], &w[15]) + w[17].Add(&w[17], &g2IsogenyXDenominatorChainConstants[33]) + w[17].Mul(&w[17], x) + w[18].Add(&w[16], &w[17]) + w[18].Add(&w[18], &g2IsogenyXDenominatorChainConstants[34]) + w[18].Mul(&w[18], x) + p.Add(&w[18], &g2IsogenyXDenominatorChainConstants[35]) + dst.Set(&p) +} + +var g2IsogenyXDenominatorChainConstants = [36]fp.Element{ + {2462204403764110135, 5729703913239447336, 2202623194262088256, 11541476637157005385, 15263417147070268901, 8629599248545494105, 12177290009890785828, 412985217920642006, 14775123069516320754, 8577080499659834354, 3922419912073210993, 15854962891879516}, + {16762994653181605045, 9272193501161620667, 4197172967320531914, 13846258992516383824, 9297826475518271753, 2095738134470852798, 17525431879629010402, 14958768516569843423, 819791544595601118, 16532932976665132775, 2120886868936309025, 67683143375625027}, + {1601373355227045439, 2027965636663895365, 7640350441804238854, 4164919746180738652, 13672480196487310807, 11040830736315654422, 14800224911255477009, 4541256600212578989, 14802089890429754597, 9443059561092020280, 11660065881384330741, 76513276142494211}, + {4236764345498980818, 12463583539232265424, 16510635789101381781, 4445430469926074366, 10562219694995069824, 13894059678327710652, 4535921864258925271, 3621288001252170322, 13237666283381448734, 7179606092670494721, 14465852759463350525, 56534502658159065}, + {14876909301651683526, 13317438416748292283, 7033089714859577802, 6784282205708141028, 8468228452407470234, 1114099138682073739, 12467291737069439210, 14189978478940598338, 16905463429854495646, 18035089435883159378, 11832579107260936888, 49855498702307903}, + {14336509256384574343, 1245291186736622469, 4636994069244493180, 13340934997019542587, 14009325629809642063, 14767719642538145184, 14435728098774200019, 12754318327741963140, 1192842099172756412, 2208229648329767398, 11346723052429036023, 64549393515917034}, + {16892411801240732790, 2520424409424038333, 5496799840843889759, 13267901806480983010, 3662922741377957018, 9454633476412171266, 10016474655474258913, 4629284630258945537, 2093503345853471535, 4253529557831595762, 1642684684385829467, 31282727299239246}, + {15566997669511419949, 16251096474416574429, 6860786061452875044, 6457078411736173525, 3872448472849670965, 10569141600685406391, 9175400198663666167, 15300067582989813635, 5184904233731590081, 909181405297929186, 462541236951828460, 80677911393925478}, + {1128144881530893137, 12921012408238389026, 10224609126098301414, 16518641069466330102, 3709468911690814507, 13014342418207253290, 13572677855783246087, 17530156101621607476, 16624019633155485862, 2913940463632947621, 9996949709589221481, 42320860768627431}, + {11414451567443011655, 13509982314665542917, 12856464999669377605, 15522185756460427157, 2151667847030654153, 3127517211845607142, 732051182358013181, 14624044852860058201, 10722673907926607681, 12463752721210682863, 1985235618744236060, 27307051388641513}, + {17484417628990137787, 486137327933978913, 9302639747508116491, 8633441911989935689, 14724712453657231788, 14880377789773031566, 12218807534565705059, 10070208452718804219, 6818323083779352488, 4135315457784604144, 2219556842859931671, 39212366219990016}, + {12247630268399047643, 4338432912478226183, 17787147075809732925, 5766222821652678100, 12666409373278062423, 12396027949952867604, 6028545613877013420, 9312824626370660841, 3009506320405167391, 12021775674227776483, 450426863327835623, 59340891212785307}, + {3488530203593248352, 15534190513849278610, 554603189315970496, 1508479470753978073, 12463553599185220331, 404004985030319076, 2183159601851137568, 2445423871799299676, 4501825701687459065, 15709929111481416317, 1008634963738054671, 41110606473611292}, + {3566639142636367684, 10075983149078371468, 7706784683540805576, 16877253960994775892, 7618512412651152775, 16229236468019321500, 15048930362209673523, 128618350393002703, 11040975051496176350, 9196638617347112020, 9754770970731279582, 27483388523829821}, + {4940700339998245840, 16337901666157488378, 7312325352077005478, 12268443167868319350, 1991271704463705288, 3598716977795285710, 2298221872644236243, 10671508134060273227, 8353389864083274330, 15790285647642495854, 512936514825555315, 71690930359660988}, + {607915093757125189, 1243290560869525943, 16882819641985201134, 17757689447468187498, 11747303602855404529, 17916365732855957819, 9762404924895079559, 10717126894259815993, 11086527709039048156, 5352215101052929159, 18159330533798699672, 10925515417855380}, + {3259565570709920314, 561794215073899977, 1977962082941026968, 1382506541977974090, 17420024399679014523, 7816049536945669714, 5642776581273879036, 14000042345093289854, 15951149112848942306, 262466823072748043, 15890941309469583217, 76972449825427683}, + {10200716385043104016, 14803865781290656545, 8361755373520663727, 8781873817909403306, 6015205369601083994, 12770576569296162055, 18329820299081417316, 15979279741423637497, 148852915121026007, 7092804389586502314, 309207812311667038, 12656075625163906}, + {16962776493066769891, 16373276762565560213, 11335996516455056810, 917130199285779991, 12536929632598963590, 6150496737908240899, 10492176377530342822, 6319844558215828196, 14326145200346485877, 17769286765127618293, 12932130775046521707, 42687751430498036}, + {2123025031707662142, 16316062778133329898, 5770368538443252679, 15048772281729823244, 13166711108350558982, 12411135105706518931, 12774285798612131180, 8227633818640757502, 550602010513292512, 17775778612716627191, 7642263298556186006, 67152553316067885}, + {12794398832344389222, 13708790888742311873, 11177448499787983523, 14433819033038846548, 3519048682836944577, 10025373893541128044, 5015133893354521716, 17920311949507365719, 9837408315907139594, 13148866251678255002, 2618647562078240061, 78344109533000256}, + {12879848957324178938, 14044095413744665647, 17180315888800742404, 9770514935786668833, 5527046285849701263, 16863982362388947257, 18275347990066572117, 3471238998985117712, 24634138473906045, 14997960894879918776, 10520302257721843715, 12468950280329099}, + {5681455693438960468, 12504157920912072167, 18079387119686519140, 1643678709664230317, 12948545241224759302, 14144708181285228235, 16109948655130729337, 15042494404999328831, 7755305079375662169, 1528804059237060775, 15503915668587068703, 67998486379457719}, + {6336021069861630088, 17276591779149384366, 7369000348321890219, 15663325006747000960, 10029793087916526124, 15379871809221479210, 14359343532998952290, 240714517716505971, 903811695967768778, 18236465408841958062, 13463864774179716017, 73873874582515448}, + {11675055082867651905, 10496803015505538895, 11142381243660133353, 13551038590056482756, 2262430301672603658, 4286034911220731549, 8061828878575988275, 2586188171587979646, 1120629122139737461, 10641676836476589094, 17334431364773485063, 40311141829520274}, + {1527630893809263021, 12626425733750657643, 3658203258954340572, 13197572548599662596, 5815822437034612874, 17120729726844435484, 9889561725694631798, 12900272153431008933, 1925846497892583767, 4689644778405434027, 9946709983812968540, 41832187533258492}, + {14622795243111096996, 3571100694689871539, 14683678628643588279, 7320643255843363957, 482313124158697817, 3316636963170528756, 17931538193153834398, 13614423847700694234, 15290463237930559017, 4402991274889903342, 6713925584549499724, 28454858531424221}, + {4028727284223441275, 11436147836476885379, 8258876572713179592, 14252957601784422762, 1886622753634877626, 5956326879826986409, 4319525706317338907, 4855254868139539064, 646097450103989116, 7811372171569253142, 16630492211375943978, 17122284556201838}, + {12733760776829532565, 9583813772194972564, 10681225838260942833, 17029180597350526773, 13025647040309374101, 11880859445566597425, 12860984256205019522, 12967862636233314878, 15919509923068170326, 13425351579870762874, 2477456264285624817, 77813526495420062}, + {18126413567176803486, 5884415673458618456, 12329320713792006115, 17523358132661526303, 7026207256053472654, 4407953956558276833, 195842375196005502, 47645128139998277, 5832516655723004025, 11113247793555952742, 18410106860999184232, 20339689383355553}, + {17321997131091695989, 16012337655398921026, 3423113059260026741, 3595006291682741758, 9675478778114232013, 12007534794041968480, 8371881123607282645, 17718299286772666567, 1435610383561243549, 16093111749808065932, 8577736554693975514, 78595544424014363}, + {13806091986064207463, 12134333328861681485, 16850334853775999853, 14040064774425165519, 5049225656877124404, 11751495377088950964, 9171688341159262709, 15020566023394508500, 6378383758322054826, 17360374366069032408, 6316252801863649781, 565526636515486}, + {3081354102796622876, 12217432937944957483, 11371151067618400645, 15545484299940082252, 10356794957125683835, 14055306103920720438, 17343376795451085481, 11624579131337132484, 12231053519924545410, 1834926594755945080, 12912283834127808169, 38801243809945811}, + {9462523016860687124, 15062337155661078047, 14722950794722727155, 13734962862079465163, 12631951633032796064, 17032091374649279979, 7363991018290319939, 5337912147367204382, 16261536238169122770, 15195194760428318138, 4535173155480395668, 24424577280079706}, + {10064285861724894259, 7952277777271711603, 10334634603939722930, 14390080745426741535, 18395532207523847282, 11164832713577856001, 9598853241485725129, 13226446262327847184, 4669700951959291567, 11590328039300441686, 15142318181474433751, 70878838868163942}, + {4034089381130901657, 14483268041211219587, 4451441384711481103, 15289995952322762790, 2450717769600693102, 4939066300415644795, 17665818208237350352, 1445019538784972335, 7986751941135971859, 18255525212220872509, 15476577744850668494, 73322210825993170}, } +// g2IsogenyYNumerator evaluates the degree-54 YNumerator polynomial of the isogeny +// with 29 field multiplications (Horner: 54), then multiplies by y. +// +// The multiplication chain was preprocessed offline from the polynomial's +// coefficients (g2IsogenyYNumeratorMap) by internal/generator/hash_to_curve/gen_isogeny_chains.py, +// using the decoder of T. D. Ahle, "Fast Evaluation of Polynomials with Rational +// Preprocessing", https://arxiv.org/abs/2609.06022. The code is straight line: +// no branches, no divisions. func g2IsogenyYNumerator(dst *fp.Element, x *fp.Element, y *fp.Element) { - var _dst fp.Element - g2EvalPolynomial(&_dst, false, g2IsogenyYNumeratorMap, x) - dst.Mul(&_dst, y) + var w [28]fp.Element // gate outputs + var p, r, t fp.Element + w[0].Add(x, &g2IsogenyYNumeratorChainConstants[0]) + w[0].Mul(&w[0], x) + w[1].Add(x, &w[0]) + w[1].Add(&w[1], &g2IsogenyYNumeratorChainConstants[1]) + r.Add(&w[0], &g2IsogenyYNumeratorChainConstants[2]) + r.Sub(&r, x) + w[1].Mul(&w[1], &r) + w[2].Add(&w[0], &w[1]) + w[2].Add(&w[2], &g2IsogenyYNumeratorChainConstants[3]) + t.Double(x) + w[2].Add(&w[2], &t) + r.Add(&w[0], &w[1]) + r.Add(&r, &g2IsogenyYNumeratorChainConstants[4]) + w[2].Mul(&w[2], &r) + w[3].Add(x, &g2IsogenyYNumeratorChainConstants[5]) + r.Add(&w[0], &g2IsogenyYNumeratorChainConstants[6]) + w[3].Mul(&w[3], &r) + w[4].Add(x, &g2IsogenyYNumeratorChainConstants[7]) + r.Add(&w[0], &g2IsogenyYNumeratorChainConstants[8]) + w[4].Mul(&w[4], &r) + w[5].Add(&w[1], &w[2]) + w[5].Add(&w[5], &w[3]) + w[5].Add(&w[5], &g2IsogenyYNumeratorChainConstants[9]) + r.Add(&w[2], &g2IsogenyYNumeratorChainConstants[10]) + r.Sub(&r, &w[1]) + r.Sub(&r, &w[3]) + w[5].Mul(&w[5], &r) + w[6].Add(&w[1], &w[2]) + w[6].Add(&w[6], &g2IsogenyYNumeratorChainConstants[11]) + r.Add(&w[2], &g2IsogenyYNumeratorChainConstants[12]) + r.Sub(&r, &w[1]) + w[6].Mul(&w[6], &r) + w[7].Add(&w[0], &g2IsogenyYNumeratorChainConstants[13]) + r.Add(&w[1], &g2IsogenyYNumeratorChainConstants[14]) + w[7].Mul(&w[7], &r) + w[8].Add(&w[0], &g2IsogenyYNumeratorChainConstants[15]) + r.Add(&w[1], &g2IsogenyYNumeratorChainConstants[16]) + w[8].Mul(&w[8], &r) + w[9].Add(x, &g2IsogenyYNumeratorChainConstants[17]) + r.Add(&w[7], &g2IsogenyYNumeratorChainConstants[18]) + w[9].Mul(&w[9], &r) + w[10].Add(x, &g2IsogenyYNumeratorChainConstants[19]) + r.Add(&w[0], &g2IsogenyYNumeratorChainConstants[20]) + w[10].Mul(&w[10], &r) + w[11].Add(x, &g2IsogenyYNumeratorChainConstants[21]) + r.Add(&w[0], &g2IsogenyYNumeratorChainConstants[22]) + w[11].Mul(&w[11], &r) + w[12].Add(&w[1], &w[2]) + w[12].Add(&w[12], &w[4]) + w[12].Add(&w[12], &w[5]) + w[12].Add(&w[12], &w[8]) + w[12].Add(&w[12], &w[9]) + w[12].Add(&w[12], &w[10]) + w[12].Add(&w[12], &g2IsogenyYNumeratorChainConstants[23]) + r.Add(&w[2], &w[4]) + r.Add(&r, &w[5]) + r.Add(&r, &w[8]) + r.Add(&r, &w[9]) + r.Add(&r, &g2IsogenyYNumeratorChainConstants[24]) + r.Sub(&r, &w[1]) + r.Sub(&r, &w[10]) + w[12].Mul(&w[12], &r) + w[13].Add(&w[1], &w[2]) + w[13].Add(&w[13], &w[6]) + w[13].Add(&w[13], &g2IsogenyYNumeratorChainConstants[25]) + r.Add(&w[2], &w[6]) + r.Add(&r, &g2IsogenyYNumeratorChainConstants[26]) + r.Sub(&r, &w[1]) + w[13].Mul(&w[13], &r) + w[14].Add(x, &g2IsogenyYNumeratorChainConstants[27]) + r.Add(&w[0], &g2IsogenyYNumeratorChainConstants[28]) + w[14].Mul(&w[14], &r) + w[15].Add(x, &g2IsogenyYNumeratorChainConstants[29]) + r.Add(&w[0], &g2IsogenyYNumeratorChainConstants[30]) + w[15].Mul(&w[15], &r) + w[16].Add(&w[1], &g2IsogenyYNumeratorChainConstants[31]) + r.Add(&w[2], &w[14]) + r.Add(&r, &g2IsogenyYNumeratorChainConstants[32]) + w[16].Mul(&w[16], &r) + w[17].Add(&w[0], &g2IsogenyYNumeratorChainConstants[33]) + r.Add(&w[15], &w[16]) + r.Add(&r, &g2IsogenyYNumeratorChainConstants[34]) + w[17].Mul(&w[17], &r) + w[18].Add(&w[1], &g2IsogenyYNumeratorChainConstants[35]) + r.Add(&w[2], &g2IsogenyYNumeratorChainConstants[36]) + w[18].Mul(&w[18], &r) + w[19].Add(&w[0], &g2IsogenyYNumeratorChainConstants[37]) + r.Add(&w[18], &g2IsogenyYNumeratorChainConstants[38]) + w[19].Mul(&w[19], &r) + w[20].Add(x, &g2IsogenyYNumeratorChainConstants[39]) + r.Add(&w[17], &g2IsogenyYNumeratorChainConstants[40]) + w[20].Mul(&w[20], &r) + w[21].Add(&w[4], &w[5]) + w[21].Add(&w[21], &g2IsogenyYNumeratorChainConstants[41]) + t.Double(&w[2]) + w[21].Sub(&w[21], &t) + t.Double(&w[8]) + w[21].Sub(&w[21], &t) + t.Double(&w[9]) + w[21].Sub(&w[21], &t) + r.Add(&w[11], &w[12]) + r.Add(&r, &g2IsogenyYNumeratorChainConstants[42]) + w[21].Mul(&w[21], &r) + w[22].Add(&w[6], &g2IsogenyYNumeratorChainConstants[43]) + t.Double(&w[2]) + w[22].Sub(&w[22], &t) + r.Add(&w[13], &g2IsogenyYNumeratorChainConstants[44]) + w[22].Mul(&w[22], &r) + w[23].Add(x, &g2IsogenyYNumeratorChainConstants[45]) + r.Add(&w[0], &g2IsogenyYNumeratorChainConstants[46]) + w[23].Mul(&w[23], &r) + w[24].Add(&w[1], &g2IsogenyYNumeratorChainConstants[47]) + t.Double(x) + t.Add(&t, x) + t.Double(&t) + t.Double(&t) + w[24].Sub(&w[24], &t) + t.Double(&w[0]) + t.Add(&t, &w[0]) + t.Double(&t) + t.Double(&t) + w[24].Sub(&w[24], &t) + r.Add(&w[19], &w[20]) + r.Add(&r, &w[21]) + r.Add(&r, &g2IsogenyYNumeratorChainConstants[48]) + w[24].Mul(&w[24], &r) + w[25].Add(&w[1], &g2IsogenyYNumeratorChainConstants[49]) + t.Double(x) + t.Add(&t, x) + t.Double(&t) + t.Double(&t) + w[25].Sub(&w[25], &t) + t.Double(&w[0]) + t.Add(&t, &w[0]) + t.Double(&t) + t.Double(&t) + w[25].Sub(&w[25], &t) + r.Add(&w[22], &g2IsogenyYNumeratorChainConstants[50]) + w[25].Mul(&w[25], &r) + w[26].Add(&w[23], &w[24]) + w[26].Add(&w[26], &g2IsogenyYNumeratorChainConstants[51]) + w[26].Mul(&w[26], x) + w[27].Add(&w[25], &w[26]) + w[27].Add(&w[27], &g2IsogenyYNumeratorChainConstants[52]) + w[27].Mul(&w[27], x) + p.Add(&w[27], &g2IsogenyYNumeratorChainConstants[53]) + p.Mul(&p, &g2IsogenyYNumeratorLeadingCoeff) + dst.Mul(&p, y) +} + +var g2IsogenyYNumeratorChainConstants = [54]fp.Element{ + {6569078391038572744, 14065459147874217415, 7774096827988077552, 7794054389085556485, 5791875737463476097, 15534773755302905133, 2217127434723083357, 14717566962794670213, 11278607255706182500, 10027624931499419651, 13118689100523077278, 23903885975404091}, + {6799504929354399475, 5516284288680986448, 14604688401085379470, 4437221370710437197, 755022780992869398, 7269176399354844075, 4063078783513283584, 446236959794487568, 14217755080519753028, 14452187281233385148, 5038636369467061619, 62611427579077631}, + {2632450230152360848, 7358945344545079275, 15972476886423800168, 8858201920763588633, 14672016030194202147, 7986779361838190921, 6666887049556445890, 8241329673201921732, 2932703480785985293, 6226653094639363044, 3728315352486413853, 1768989977418668}, + {14660945487098307725, 15828828157342540044, 11057444735205542540, 11790379397779108370, 7307501787472742133, 1756204628053212526, 8032959068324706218, 12797784942489542543, 10104541033558694446, 6176401796480311096, 3120149170882492805, 24237297031686650}, + {16049575140033974965, 9666649928621733204, 828063343271102073, 6213734605436713513, 12925852108845134200, 15452554206885801604, 9326060362525592221, 9931949964752128781, 10242077870065578026, 14732825410383789259, 6820435446555585374, 2412101040866013}, + {14240101766627720388, 7053848804750911953, 14554128762817374240, 254813991756781879, 12233312973886554690, 6556890169719234549, 10278034152450279688, 12945863733899811853, 17350944106863676011, 13329606663338457246, 10412155404240214045, 34115304780937881}, + {11156910639213771840, 7034270101859443323, 9471943837320173152, 17130460340463062587, 7339666495678637886, 2154417811438815672, 1068791954921819826, 11653498087819985222, 13988309056671916170, 13777100958929911698, 2418398558228778948, 70721405203376824}, + {1324771359249303624, 6859991648189387557, 1803464163647762944, 14446378594320385525, 8411593652601253645, 10549152718343358199, 3154437231507115154, 14404420155563141067, 15211354199270240729, 5749517812354569051, 9819455416117361871, 14560267797425891}, + {13353346402298601650, 6839747300741310268, 12942174196106472908, 6774061680280919806, 14034472142823215063, 8009556809162198871, 6682220287001061232, 15961211166711454834, 7940691657670085568, 441886522524695260, 719290840376739413, 18521028309640808}, + {9298418760945810504, 6249781123304798267, 797251273467858555, 7994849987445252535, 3193914354186201735, 17787875975539883366, 2117317305963864564, 13808532375613873277, 14810705363191606668, 7852172444074068408, 5141067314260329064, 72332603450331773}, + {18321988925374351683, 2881455495330018741, 4377069691212262201, 7734153390618460414, 15776875648568831900, 2593352974478390730, 14804263029831108631, 6188496788272073350, 9665658682597699668, 10783778290993367595, 14032108011458186179, 37086787580526025}, + {2880631319954190297, 17149310014577729674, 1780197858495761832, 193555936606113593, 15275097111563064368, 13288393447382369555, 11701927925768583559, 9348808769381138773, 2521733367205417466, 5893299665504662393, 12976076758483275400, 14332222995081715}, + {4618933349389272128, 11728439660855120764, 283210977504136628, 2765532984377338136, 8610539885749291790, 14925895402143995169, 1598936945816629713, 2496941258941985138, 7967915030076191234, 5421410031207722431, 1557529864145418011, 68502904421821447}, + {8434410744827295041, 6759705156831753771, 1414601721607130003, 8121463082224454544, 5961333862427936219, 7885588855120593497, 592481292126757686, 2185572331765547029, 10315773231094200834, 10620170306000154845, 11067215395937811962, 1486257194431655}, + {3029780744975836201, 8910238104308459558, 9102855650453752514, 12726717943818520660, 6794805596962484451, 3169800170156811462, 1371478536804550447, 9843227684379371438, 1135419717227560985, 15388409878114272842, 9149089645273744617, 29369125116322840}, + {17932986535038167355, 10783926073340166155, 10213997282699691324, 12846508447702460572, 4195200940293449239, 3135834832987958252, 13519809078404888093, 14908481293369923565, 10078269333464243666, 11337120994774185079, 9216921946644305154, 43818851492085507}, + {10232952176749517782, 9659465140635801830, 7417225435535012580, 13987670255905822975, 13978442416022498924, 14604410349017503937, 16182433774106689816, 11641260667966642112, 5977842986563158776, 13546472518176688763, 14529950292710605892, 45537798268801954}, + {16126952974301056804, 2659305586814702599, 2507503271884736437, 11027383088331782099, 1623509623744487377, 13675874200144259793, 18353664437121725576, 11964870417226365163, 15265174169541900940, 17523354638608851084, 12387300072150557957, 55237421545887778}, + {1772734260475563195, 9819336926042890290, 2741549059267378995, 14046229895660527474, 15162780157366458323, 2128006042368596520, 13143047237278603459, 9812156099328703923, 6363973733816006275, 17477825301761702663, 2209921269647420140, 11395909280962729}, + {1831643992506604716, 1249830746210022561, 5654190697909659593, 322791453338729022, 14286359933067738198, 3710751367345168913, 4615915437299507774, 6525397535342714961, 1198679839325336823, 4375212635202503110, 17371610180333811775, 33291473025388847}, + {17914824246154866917, 10009701211779890393, 4965166706368539097, 16529052457292660783, 14534044749017359221, 15399276186670308517, 17826482586505791602, 17368698018591220297, 12035631601039795381, 2317325361453445402, 1997888039968148727, 59583506273116798}, + {16734678075253289743, 15289940836637461895, 17834868578466701458, 8141417025359893909, 15330749159616970717, 10073623169404392907, 5827078448042973433, 12997789434793751327, 16907010985799737361, 17464643684053317901, 11184171719184717434, 33248004134813674}, + {5117660451030409872, 15357279031583679827, 13456671648647770867, 10310966222698662856, 1749595525507769854, 1342132036275280740, 10776135021036513577, 4329453748964018714, 901357356656234480, 16866680235875973704, 8488678099326765952, 9053998792889125}, + {13863956388092771570, 4924712300105449686, 7211805499186081982, 3243768142668179208, 53649159520177452, 6660949128870424113, 4304848868186279236, 2488469536835306426, 11253187603735114202, 9984499009594025692, 9508597550531532648, 77708108788180568}, + {8161388337003208198, 2321564597749302904, 14035222684008009453, 15829772972624947467, 6881763268872399689, 14555884204342916581, 14350362735608114727, 3185442697068351641, 13081778176082736870, 14217999650015843241, 15229978429923425055, 23898896721054618}, + {16303185716276882997, 417660033411324118, 14534357271129639787, 15311783250364984692, 8307156977299056702, 16984739555923405906, 16315800211163197389, 17803446209196604501, 16578118294489583818, 18277585168812083379, 5512060454565367498, 447657223644268}, + {4737661623842841165, 4271599015374171002, 12223180372272561131, 16994248543088521931, 3854530771448195709, 8498694760311587234, 5086826735638470106, 15403898263005144034, 17572036828332540960, 17870965414068458651, 17392826649674290560, 3255179535643585}, + {3189668008758712247, 12294890117426034785, 830358501643893270, 2066064850244726062, 15554781154260669826, 1042012669988107820, 1785855271812243001, 11301436463611923346, 17279105456360503970, 3773340238027208247, 4202570714156225112, 44555684977544106}, + {1359406851783329700, 5751590135686453854, 5352249881815607777, 10367079493393713351, 1211269145641405937, 18383957192561590528, 8465680294440738648, 9168883325762141633, 2680267295996326819, 11402427643080729831, 17551576274755434693, 40458516826862063}, + {4439493116386453556, 18151863010329837730, 4067459192096352765, 10956747620032835083, 16171694895143715350, 17448389439227396203, 16438012123671102244, 5382351907031846162, 3420808737640813626, 2541964423203330880, 13939837418698863013, 1257906520468023}, + {12248252505910749355, 13820199696317057518, 1664642586462742805, 13784408850535503767, 13830332685409405138, 16462270299376823568, 8915662269874890969, 10708389498236138128, 5569028963870168352, 1887943970286509991, 9173837414530507589, 16683247675396848}, + {5217034841029895209, 12364222516945104256, 16317263897609388923, 13700416338319622124, 14436911548424893843, 9350577117629183818, 8934797150169665551, 9405992261651421463, 5980235970415731821, 10044707321281850767, 3987861631731999454, 51099395868283183}, + {6705605467550217541, 8412856548981333651, 13661608161740676534, 11464326669820740020, 1149442222816614390, 4279772640423225458, 1722384980769108551, 13570626096381052060, 12300573118808319897, 7831013402191375457, 10296513862486148625, 70539288637427932}, + {3025863707442267845, 17316767558067680394, 7822104683971196544, 4197858528915255902, 2090105287505359451, 2189659832823028928, 9609970429474871262, 5224804622950409604, 5490260881072719600, 12498394937641886899, 13831330996465707914, 74010074896176073}, + {3874509527318537731, 8904231809320939491, 11414879162607102892, 13709373434081889811, 4264239363140694104, 17750210968136376434, 13016166128637078412, 5254058919625486694, 11607627963011722249, 8279587879882664062, 1558271094602459087, 4339532596845461}, + {7698602406495906560, 1359339098354083204, 3295077105980385510, 98853626444859523, 2583082164114845783, 16308146534258732447, 15146047054338068064, 3937651053158686163, 13880902113254748170, 14883227990495929643, 6371289996037331967, 75061690842072956}, + {13505015515578783346, 8560909338229384784, 3095679630896031221, 3194350557721472458, 14250652602486188016, 5035457693421644647, 16930734371531429508, 14703099851338791977, 12585236066899794934, 12643299649659905491, 18008123455549059486, 54136259431234879}, + {16849132740798448992, 13125607821284603691, 16562878188112183414, 7396886896252209395, 15583703239555544877, 4279949003989810553, 10716410222711639130, 7679628481274242742, 515264682712178269, 16675514313115827441, 5663244328750696057, 47643740646234744}, + {9080065957450315142, 11028853875037812090, 463033834687229720, 15194493128258601336, 1664761897899626160, 12862354011272867640, 18232558596897501336, 12584975572396934622, 11318968611395447970, 1528263883825552494, 16800011064343359890, 42858299669526181}, + {18298837617995736872, 14260852433555042965, 12761795259122050740, 15020749030687298488, 12134532142429156622, 15263997579285932420, 13545314118195568195, 15875117921826687281, 13104483108792302935, 2140367426328403536, 17482689336213514402, 77822086424004110}, + {14690579240909062050, 4385521928153042170, 3058046370419816722, 5624077807449952616, 16799658193404172801, 2575967133988451536, 1705910876030527957, 5498092649897723437, 13562507473051540806, 4372024886788612453, 8901204408093016512, 22890749191461215}, + {9148720275099154220, 4337721960685187453, 17442684420932182428, 11408622085923215444, 5583287734027528250, 5554293219933888760, 2233120103457667069, 300517942681334665, 13686612427040510283, 1106161164378223365, 1511071618621202896, 28978984291319132}, + {16346029565970670035, 5669444738655156842, 6575625131997223858, 14834191312574853735, 16688312973546145247, 14416334012366960446, 16808102847873850124, 342915916755990100, 5131203006449095067, 3646661186370876240, 6117598012418460386, 3083119542148911}, + {1035038046220440609, 784222236317235186, 6801850885912101658, 14727112436245488210, 1670158373906309851, 17682416149381973700, 13070578321334343586, 3866253750033718494, 14642244103314573429, 8749544549557845000, 3695296143379117445, 19054756382106854}, + {15539427685609873825, 7686251820062684147, 9308269324434087388, 6899831598887384771, 6176805365918835333, 12919145982885609591, 7574000087480587541, 16710548502526419615, 8075557261571624454, 4697846271431016765, 8476563599815210148, 8419460416571244}, + {7369326412325960968, 3405484831159221512, 6999508684610790853, 5132931412817246759, 8454393153669947748, 8902693119407983421, 5558279417613173457, 15282117953084141879, 3794184671993387725, 11752277696125498158, 8147202347865580391, 48136673939296306}, + {1165431189362544288, 9512348850122205868, 16476039892118216914, 883034299042970085, 12591036869340821781, 2305771451044823975, 9441162167281330536, 9152606315904392033, 16420288368928988785, 13770073436567488430, 11778920540349821783, 76326870506673482}, + {7088997822439510981, 13389848156377090282, 5011227304903501502, 1343021295848342779, 17999433858605161235, 14681115508476113842, 8163156522655725955, 4468110561575301615, 1761709521305513565, 13322736958150584867, 8503145190395158820, 39060487781475685}, + {1016067660564623026, 13349471607923736446, 5306418189805418160, 483697058507317333, 6019976047528942686, 1241060228506582231, 1551433315781809442, 971910491877234512, 16484082634061974923, 16580646702924825172, 5812194607462747714, 25950978787445535}, + {8468436993309382003, 5289905598921737841, 10101622235413990254, 18441807878567383282, 10944002559408684217, 16072472770800854243, 14186137318895715891, 14218813273811654283, 5352886207946966023, 14317972219692043553, 3450799537564681064, 71784205685919062}, + {17059141527838770884, 6567919494445401398, 6293074987854486421, 17956700671248614077, 14079076609168229200, 14754910490999538443, 4409482963229093143, 8271532783624999685, 14029297496915091892, 2734342528659737677, 8636764454772222717, 75148049668884773}, + {12159290163927536838, 2435945209741438564, 7700367943505450406, 15813558067403221314, 10225943007026348752, 13503801999021895095, 10569870508227344947, 10566711977873553445, 9856455424877361846, 14856050889728896889, 9636403297617214411, 42828333432615562}, + {2768804981369723686, 7285022853724162819, 6185239904470234259, 5729232282797207983, 10026799492731900269, 9295619124980485245, 10093979808198553755, 1241525787326324849, 10948110736451486935, 7807469323559405558, 8051498588467713029, 25588593967610447}, + {11407448333260168194, 16692875644731784997, 7947597886331405332, 8341207537829686597, 9091596021830687573, 9011904504682357833, 15438943568173834779, 6985916616265954946, 1401284274420899148, 7307453287079285362, 10921176630918551153, 45167773672524371}, } +var g2IsogenyYNumeratorLeadingCoeff = fp.Element{7423015408621128732, 17540351087154700243, 5042698470388953525, 7223639800108209563, 17629244503623486068, 14168085454261172020, 14099638289084950690, 17978263308087521500, 18215882834796925821, 945616097071052005, 6790086883133147916, 77344178427451439} + +// g2IsogenyYDenominator evaluates the degree-54 YDenominator polynomial of the isogeny +// with 28 field multiplications (Horner: 53). +// +// The multiplication chain was preprocessed offline from the polynomial's +// coefficients (g2IsogenyYDenominatorMap) by internal/generator/hash_to_curve/gen_isogeny_chains.py, +// using the decoder of T. D. Ahle, "Fast Evaluation of Polynomials with Rational +// Preprocessing", https://arxiv.org/abs/2609.06022. The code is straight line: +// no branches, no divisions. func g2IsogenyYDenominator(dst *fp.Element, x *fp.Element) { - g2EvalPolynomial(dst, true, g2IsogenyYDenominatorMap, x) + var w [28]fp.Element // gate outputs + var p, r, t fp.Element + w[0].Add(x, &g2IsogenyYDenominatorChainConstants[0]) + w[0].Mul(&w[0], x) + w[1].Add(x, &w[0]) + w[1].Add(&w[1], &g2IsogenyYDenominatorChainConstants[1]) + r.Add(&w[0], &g2IsogenyYDenominatorChainConstants[2]) + r.Sub(&r, x) + w[1].Mul(&w[1], &r) + w[2].Add(&w[0], &w[1]) + w[2].Add(&w[2], &g2IsogenyYDenominatorChainConstants[3]) + t.Double(x) + w[2].Add(&w[2], &t) + r.Add(&w[0], &w[1]) + r.Add(&r, &g2IsogenyYDenominatorChainConstants[4]) + w[2].Mul(&w[2], &r) + w[3].Add(x, &g2IsogenyYDenominatorChainConstants[5]) + r.Add(&w[0], &g2IsogenyYDenominatorChainConstants[6]) + w[3].Mul(&w[3], &r) + w[4].Add(x, &g2IsogenyYDenominatorChainConstants[7]) + r.Add(&w[0], &g2IsogenyYDenominatorChainConstants[8]) + w[4].Mul(&w[4], &r) + w[5].Add(&w[1], &w[2]) + w[5].Add(&w[5], &w[3]) + w[5].Add(&w[5], &g2IsogenyYDenominatorChainConstants[9]) + r.Add(&w[2], &g2IsogenyYDenominatorChainConstants[10]) + r.Sub(&r, &w[1]) + r.Sub(&r, &w[3]) + w[5].Mul(&w[5], &r) + w[6].Add(&w[1], &w[2]) + w[6].Add(&w[6], &g2IsogenyYDenominatorChainConstants[11]) + r.Add(&w[2], &g2IsogenyYDenominatorChainConstants[12]) + r.Sub(&r, &w[1]) + w[6].Mul(&w[6], &r) + w[7].Add(&w[0], &g2IsogenyYDenominatorChainConstants[13]) + r.Add(&w[1], &g2IsogenyYDenominatorChainConstants[14]) + w[7].Mul(&w[7], &r) + w[8].Add(&w[0], &g2IsogenyYDenominatorChainConstants[15]) + r.Add(&w[1], &g2IsogenyYDenominatorChainConstants[16]) + w[8].Mul(&w[8], &r) + w[9].Add(x, &g2IsogenyYDenominatorChainConstants[17]) + r.Add(&w[7], &g2IsogenyYDenominatorChainConstants[18]) + w[9].Mul(&w[9], &r) + w[10].Add(x, &g2IsogenyYDenominatorChainConstants[19]) + r.Add(&w[0], &g2IsogenyYDenominatorChainConstants[20]) + w[10].Mul(&w[10], &r) + w[11].Add(x, &g2IsogenyYDenominatorChainConstants[21]) + r.Add(&w[0], &g2IsogenyYDenominatorChainConstants[22]) + w[11].Mul(&w[11], &r) + w[12].Add(&w[1], &w[2]) + w[12].Add(&w[12], &w[4]) + w[12].Add(&w[12], &w[5]) + w[12].Add(&w[12], &w[8]) + w[12].Add(&w[12], &w[9]) + w[12].Add(&w[12], &w[10]) + w[12].Add(&w[12], &g2IsogenyYDenominatorChainConstants[23]) + r.Add(&w[2], &w[4]) + r.Add(&r, &w[5]) + r.Add(&r, &w[8]) + r.Add(&r, &w[9]) + r.Add(&r, &g2IsogenyYDenominatorChainConstants[24]) + r.Sub(&r, &w[1]) + r.Sub(&r, &w[10]) + w[12].Mul(&w[12], &r) + w[13].Add(&w[1], &w[2]) + w[13].Add(&w[13], &w[6]) + w[13].Add(&w[13], &g2IsogenyYDenominatorChainConstants[25]) + r.Add(&w[2], &w[6]) + r.Add(&r, &g2IsogenyYDenominatorChainConstants[26]) + r.Sub(&r, &w[1]) + w[13].Mul(&w[13], &r) + w[14].Add(x, &g2IsogenyYDenominatorChainConstants[27]) + r.Add(&w[0], &g2IsogenyYDenominatorChainConstants[28]) + w[14].Mul(&w[14], &r) + w[15].Add(x, &g2IsogenyYDenominatorChainConstants[29]) + r.Add(&w[0], &g2IsogenyYDenominatorChainConstants[30]) + w[15].Mul(&w[15], &r) + w[16].Add(&w[1], &g2IsogenyYDenominatorChainConstants[31]) + r.Add(&w[2], &w[14]) + r.Add(&r, &g2IsogenyYDenominatorChainConstants[32]) + w[16].Mul(&w[16], &r) + w[17].Add(&w[0], &g2IsogenyYDenominatorChainConstants[33]) + r.Add(&w[15], &w[16]) + r.Add(&r, &g2IsogenyYDenominatorChainConstants[34]) + w[17].Mul(&w[17], &r) + w[18].Add(&w[1], &g2IsogenyYDenominatorChainConstants[35]) + r.Add(&w[2], &g2IsogenyYDenominatorChainConstants[36]) + w[18].Mul(&w[18], &r) + w[19].Add(&w[0], &g2IsogenyYDenominatorChainConstants[37]) + r.Add(&w[18], &g2IsogenyYDenominatorChainConstants[38]) + w[19].Mul(&w[19], &r) + w[20].Add(x, &g2IsogenyYDenominatorChainConstants[39]) + r.Add(&w[17], &g2IsogenyYDenominatorChainConstants[40]) + w[20].Mul(&w[20], &r) + w[21].Add(&w[4], &w[5]) + w[21].Add(&w[21], &g2IsogenyYDenominatorChainConstants[41]) + t.Double(&w[2]) + w[21].Sub(&w[21], &t) + t.Double(&w[8]) + w[21].Sub(&w[21], &t) + t.Double(&w[9]) + w[21].Sub(&w[21], &t) + r.Add(&w[11], &w[12]) + r.Add(&r, &g2IsogenyYDenominatorChainConstants[42]) + w[21].Mul(&w[21], &r) + w[22].Add(&w[6], &g2IsogenyYDenominatorChainConstants[43]) + t.Double(&w[2]) + w[22].Sub(&w[22], &t) + r.Add(&w[13], &g2IsogenyYDenominatorChainConstants[44]) + w[22].Mul(&w[22], &r) + w[23].Add(x, &g2IsogenyYDenominatorChainConstants[45]) + r.Add(&w[0], &g2IsogenyYDenominatorChainConstants[46]) + w[23].Mul(&w[23], &r) + w[24].Add(&w[1], &g2IsogenyYDenominatorChainConstants[47]) + t.Double(x) + t.Add(&t, x) + t.Double(&t) + t.Double(&t) + w[24].Sub(&w[24], &t) + t.Double(&w[0]) + t.Add(&t, &w[0]) + t.Double(&t) + t.Double(&t) + w[24].Sub(&w[24], &t) + r.Add(&w[19], &w[20]) + r.Add(&r, &w[21]) + r.Add(&r, &g2IsogenyYDenominatorChainConstants[48]) + w[24].Mul(&w[24], &r) + w[25].Add(&w[1], &g2IsogenyYDenominatorChainConstants[49]) + t.Double(x) + t.Add(&t, x) + t.Double(&t) + t.Double(&t) + w[25].Sub(&w[25], &t) + t.Double(&w[0]) + t.Add(&t, &w[0]) + t.Double(&t) + t.Double(&t) + w[25].Sub(&w[25], &t) + r.Add(&w[22], &g2IsogenyYDenominatorChainConstants[50]) + w[25].Mul(&w[25], &r) + w[26].Add(&w[23], &w[24]) + w[26].Add(&w[26], &g2IsogenyYDenominatorChainConstants[51]) + w[26].Mul(&w[26], x) + w[27].Add(&w[25], &w[26]) + w[27].Add(&w[27], &g2IsogenyYDenominatorChainConstants[52]) + w[27].Mul(&w[27], x) + p.Add(&w[27], &g2IsogenyYDenominatorChainConstants[53]) + dst.Set(&p) +} + +var g2IsogenyYDenominatorChainConstants = [54]fp.Element{ + {6569078391038572744, 14065459147874217415, 7774096827988077552, 7794054389085556485, 5791875737463476097, 15534773755302905133, 2217127434723083357, 14717566962794670213, 11278607255706182500, 10027624931499419651, 13118689100523077278, 23903885975404091}, + {1704643849989544096, 6253555604229534380, 550518726604274156, 10080838183509925672, 8556189996660874942, 10098914977006123863, 4541192349126311091, 3191019998711466918, 9893254832269302850, 7292872191366620277, 2064535685346196248, 70809406729011725}, + {6367685084013873735, 827888096844057317, 2576424895469922343, 7951237771413815323, 13747847067960736475, 15364133009068733647, 337549843364237395, 13343683197422409859, 11970376826992975387, 11266644619063213306, 8133302791423940673, 9342813769114162}, + {17839085940485143562, 5065801405152131616, 12748410609367743676, 16877253668202268264, 6847514097880462984, 5628199866388221564, 8305592843753178628, 5180063411173295095, 11401237437988387204, 9159819892680935928, 4435043220471704102, 61817757023258163}, + {7322334912011333931, 7532466717093114364, 6432272019508772943, 16572258488202593049, 582195112450843109, 1623196305112664468, 8859947859770573013, 1357551611256419974, 17170000563118905024, 8497179779788790986, 8662479917964004617, 50827816710209920}, + {8435884634465228898, 4506983776794704382, 7335909569163536309, 14342199263606737566, 5448023380657874948, 10555584260191338502, 3582806052318400561, 3400143141544943144, 704844512189888818, 15136936047441774077, 12478914641641811517, 78289911587479026}, + {14792144853773599886, 14218205447134481646, 9005720513897139134, 3955801890030265875, 8820324352831429228, 7387776004610349600, 16548729230593094558, 2793168827997099475, 18075713685566724547, 13839075415907945552, 16070048400050018352, 53501601657037340}, + {1106219736897713756, 3241632660551482279, 12473740984265834375, 4214239206174642878, 3633266879997307086, 15630647354516282855, 1648346938727342094, 10635942917500407138, 18380199051753573512, 16338029766430987050, 17843926740008821842, 38364826587825080}, + {7752596281828930837, 2195673423537664887, 8819136935659349284, 482753346962920023, 5000543476769358561, 433883866735266001, 5218204993095030537, 4817245127171619482, 11535257482313917717, 11565164689842641613, 2511409817694171033, 72331529045922710}, + {3998583640760070993, 13896453256480102398, 11353635741868807961, 2341353513936160871, 17455618581826345266, 18124433350041401329, 13329002194982487801, 1937805075532878869, 4112829993474183282, 6864185921906546372, 13809187167015054441, 62633384092176000}, + {12747298266038040773, 14009902882948234770, 10782743966841719779, 16587481411767579181, 5415725221199251160, 13677308099127945862, 2901692037365537111, 13443104128571267279, 15962610444172980115, 667712439249288688, 4031279762100606729, 60845946762255316}, + {5000233583457548931, 7129009110001624353, 18236798783179451944, 1721452342781568754, 9892732421550816896, 7925583000986139700, 8445006017597459077, 8853660909773922095, 9610887753261598190, 11712900455992439999, 18377968637053807750, 9785353620158892}, + {6446808822009662348, 14814937011532764894, 1367284722279510513, 12969236119652504389, 13356447840236556598, 7649939457770616621, 18411130114434127599, 12855406219607040081, 14075692986384395999, 16894173700443715148, 4389769758972073677, 76896719020888164}, + {14924654493210599164, 2111283429603602191, 17426007117202391488, 9840023474082400438, 13668362527077953512, 8178145924644653629, 10317137698314598460, 10811158385445213685, 2925959450289312356, 4852296300748747094, 2487209396538515010, 35236835717150663}, + {10096953899576588723, 1425272074953914310, 7000710865258742164, 11069791955343138684, 2888256560644024941, 14155895341371605600, 2183953452082566490, 16465916323699292930, 14116484319854684945, 13454397866034307585, 10095368599816283055, 43981423314961555}, + {691271448748885047, 12868200510432400763, 16766631785616060882, 15732060327153155216, 17734981718893646034, 11639369976374258429, 1913174451487901886, 2131535023771513819, 6885878084482365842, 5710502677992537957, 2735347382282199593, 11101899101979667}, + {2148580979607902686, 10489019003938861879, 13943527903468435212, 8322301746031610233, 6731954890306991301, 6771812611117887234, 9930013556445220795, 515427445517741668, 10798051728059948868, 1414123784672444339, 17192944912393220697, 75214849758276107}, + {16095924835249599022, 12885698717049291759, 12430969398557553090, 14933470581416848640, 14062020598976556825, 120208049192961063, 10891771660870664676, 14037477612635654429, 6295486592950610152, 58805240529921967, 14514716557260033866, 26222459769420615}, + {15066630482711615908, 2378567507474555443, 1762945311985718255, 4339940567791479035, 3077557433299207176, 17732145537477533531, 1708981947456985453, 14815454791674437253, 289775788206846935, 13096545797406260465, 15479895697064490661, 20688965545127189}, + {763844763159536895, 1533708534220045458, 18093819012545090152, 6940386438914045134, 7503980404388159350, 12873949791821051576, 12005281731265634892, 12843491938824356937, 11616919390598350693, 190197170501537570, 3553407785999718684, 57906126679191954}, + {9133230270799687523, 12555617244210952796, 1851946609918232999, 15482700086479361338, 3493668552464434891, 15062927019971402215, 3221455341079934089, 5523237176361029172, 14216296588394525387, 6382943885044141152, 5520133767560073030, 51424571968421011}, + {3516960151768072845, 747622812659542091, 9159594107290393218, 13575839866960233978, 6292009926245041964, 15494483947684543349, 17044098853291657456, 1868018679555820828, 36726977190514191, 4534264895755413897, 11859168446843320080, 47807071483742423}, + {13439846383137075710, 13605679065038141805, 92503902812285193, 10342601882828670288, 410118472347840575, 14145887197483849807, 15351629657854962338, 1999959003117693928, 12856485516116703987, 10986254851456623297, 10350456008797974228, 8841981550217908}, + {15015031671017457557, 7350425679000972260, 5644334675990205072, 18080765244107146166, 16425814098233286738, 13411034745737297637, 5613613489951773931, 71171981029434935, 8731029499610499895, 1407963326590447149, 14999506130270533383, 57424627492219956}, + {7053028082079927251, 16628415989877711998, 6602019562795184179, 8859393526733696790, 13124442583548183324, 4883622100341759581, 1080383557895558554, 16022299528400955626, 15113940343999446699, 13365028487762653231, 11025527980468574144, 54638823910600318}, + {42991360878858542, 16305301354573604265, 13970875356565536251, 1991017826022805163, 8063916872108899755, 11059115177049583625, 6053551099239730326, 11516994422681120413, 4900844267492361673, 1990947797506593960, 13373258259291447749, 6315994422480316}, + {18080506030004274932, 8319678036339025040, 6200122511398571651, 3882673497727263998, 14256358035234458988, 18074916480035724203, 643536385524570623, 7245130763098600103, 14910117517490496376, 8941427455037436943, 4083624102828047048, 51827431155857782}, + {11468877377167033621, 3242874770792196807, 9618412717873437953, 9152256288768214911, 7505189193687479912, 9011154438084333451, 8977478837094342825, 9664247138620556686, 6114417135321013040, 16525215039718772078, 4283491758720216014, 67480217032738463}, + {7930530851007637224, 1499165005549720763, 1735279805204252474, 15695738129161488814, 182133158546473215, 622120094286931165, 14440340360303381026, 3364679198672086010, 17287385724322254908, 16551504760360030197, 301347615302871950, 19290332055926756}, + {8579577109213018728, 11319994702505880159, 14436616761490520795, 16537052975879335404, 2552987800980318260, 16185261149910177237, 9499863192875107599, 15459320225154977228, 9518104838398069891, 5204943608700371331, 14958163945052001452, 75794991751386534}, + {10189665321523767189, 14093996464281610803, 17489020421242530221, 6384516440208684237, 2503843482132551016, 4853427988068340162, 6309996317086427129, 2924143635948852572, 1241725838549587846, 1215739416751519455, 9555903625998743678, 81557291374864637}, + {399430787977019319, 5939332589710845266, 2870750987442308868, 1611412373728016127, 9683021206943045207, 15868703947331031104, 10589869026359556688, 6977490861655116663, 16737167821316430594, 150214598795571480, 6188291165224645559, 37756664608874545}, + {4339345078023274661, 10238601753717969881, 762845815200590025, 18135589109233537296, 16531668442456219542, 3682468598289166979, 11840773135093502069, 3397217300187880521, 3707489986793059853, 14126836454066866496, 13338375475052808819, 13600374573124077}, + {4021961293581226177, 13949541246279199101, 6910937145121998683, 12492891468611719040, 12041975854222230239, 8824398550988697030, 7411017310580009634, 10018764695389971022, 6371826510695472316, 1456911889559420257, 7362186872696544690, 28789326637092317}, + {16930200922923218604, 4668910239331479356, 11432537429471762875, 11807476283740549196, 6490304943255246932, 13051751398294920841, 10064792484180408579, 8530393900512193769, 12460261506451578022, 6858657617875264432, 13591867655961116827, 56818916694253528}, + {7648268236653770612, 15610165381435012013, 8120558184280017444, 13585746067929446522, 6963656864837554569, 3363520649363918908, 555797329954352855, 11715766816136338146, 6906105839453283727, 2831987107318320271, 5282393292436162158, 55996970543177794}, + {10317847015863517507, 5831410163467704374, 10942181645210176817, 12107898271513361101, 12962729944912545486, 17577162630250082422, 6423092409293228575, 18154524988385222930, 9549101433331991935, 1944059731309375036, 17824139715773987050, 18114358008505674}, + {8209552774892301763, 13425752551680813621, 7217655035067893277, 5863290628512041923, 15524250284593689274, 684585592193306912, 17247110438809182948, 11847497308705343477, 17102430840150451228, 5949764578617804130, 2759616879705475258, 11277166745957274}, + {12248450623243685966, 1027195689820712831, 11889555590125601261, 9364535937496602289, 14967603768480870475, 13544636959156361120, 14772017444353695735, 8906911867717017539, 3353192867416293696, 4180669505163380087, 11644302704607108601, 69329840614404701}, + {3297410414454128203, 1549510385729581923, 1180917427298149962, 16611986107599547262, 4553450461010753029, 8917018416769519603, 723865447649856933, 7857899391336885068, 2856059849364777065, 15636187345597848833, 530480499074117670, 23805646796388000}, + {2922669359327780257, 13037045717298016995, 10171497719672773506, 7981354401240248746, 14641330650949918400, 9171969740184175376, 170461615110835543, 12328340763333684451, 8400601139849072117, 15344091777726632210, 11416360104236358666, 29868855320573658}, + {16271001338503493526, 10873434369844975239, 10978388865939168104, 3062182057911043447, 13434791868190740049, 2641442628120811765, 6363455180747968200, 13762954212272973295, 16368437550732681229, 11950558497051294484, 11996877180720238648, 68075860679093441}, + {15788680849183818884, 15437147434415214417, 13194302680441953977, 2791904965524311991, 17740774400073643087, 231611770151985249, 14563392551390521655, 8439244955506851884, 1480770463881685758, 11358281050536424805, 12443795033642195301, 51610475726921778}, + {7011026861138594303, 4825875756607429021, 785351583330170054, 1920303716071320968, 10089714413280938196, 4370891879474201358, 864538075580563034, 13789691049414485110, 6939458710056776362, 10245813678317203671, 12691317374323471384, 19944155929991767}, + {1994879068560254339, 13431320892017067903, 6976070553703802459, 352963548189121526, 13362046777657845917, 18381152767935261229, 17304836468007287090, 9628966924513173577, 16226113154532674447, 12847516833858175240, 5431526111874799237, 73599492368656524}, + {12417687841704468113, 11838681753267209599, 14438106320851959561, 8334715938262913611, 5788311909150578870, 9440900392673657652, 10177289308985266153, 11212739876269172756, 5767623796223281914, 10678259660393966744, 8291028225940717801, 5202593735226320}, + {8735751119268085036, 16918071352537648979, 18025048980049061142, 15177200146329720497, 10630137631311564059, 7827062563378509566, 13969060998828428332, 1049364009566180604, 17083393358564742, 10360320215396256981, 3113582979191315127, 78710547816615857}, + {6112006829399281045, 14301551447812209961, 14441798467559429166, 6892032635405781836, 10299814138629688554, 9212193365172618933, 5790191361421894536, 18226513306254373435, 13286358938373931488, 15134034874833685102, 13373648171414274918, 63022763114372920}, + {6230878290655816754, 15466972532647392726, 11353237737656589357, 4918258652496146788, 10329281247739033338, 17456251690960093152, 3561052294000686740, 83211315263403858, 3200569055982538202, 9536554892882376038, 16403007597703665979, 36071781156211562}, + {10036151450335710097, 9522055268545806969, 12679629403134220632, 10069325969181991548, 5790826267445273775, 10323681379321069508, 6899276624600323318, 2960580729132953227, 17866246062866594151, 12699632385114439955, 8341772210075720446, 19789795702394441}, + {14196689388520254328, 11960454144762872948, 8438914475132046191, 16601839232425465061, 8405186378539281239, 15996452565730762482, 1627640772809134055, 5389820360024450077, 5121686620604823497, 16972726780923740455, 3165024580319445119, 42221307841607512}, + {16552353519495313286, 6647864846711012713, 16941497733562332076, 13414996073470065784, 16666984497239420390, 8569739573855606596, 17234979426866398599, 15444453771037196556, 1497991832072374042, 5978870089481749768, 11456648489948665314, 56497802392045462}, + {9075975519754633, 13280355019371267828, 7963107485590722614, 7894117496558581295, 11063752020427954840, 18123626023077956700, 7644800889717054169, 5465094030791075646, 15157299628101915120, 6151474658456787881, 6136646582966217729, 42901733103666912}, + {15352945671569580611, 2193851617865193660, 18196598416328555184, 17275132829270017942, 4890939054800637279, 15081695818496033794, 5748861378547866694, 1073935720284132832, 11983257218807282771, 18156724836980600077, 2062913630182313572, 50299209337535394}, } // G2 computes the isogeny map of the curve element, given by its coordinates pX and pY. diff --git a/ecc/bw6-761/hash_to_curve/g2_test.go b/ecc/bw6-761/hash_to_curve/g2_test.go index 2efa91e660..2fa2a7a56e 100644 --- a/ecc/bw6-761/hash_to_curve/g2_test.go +++ b/ecc/bw6-761/hash_to_curve/g2_test.go @@ -49,6 +49,75 @@ func TestG2SqrtRatio(t *testing.T) { properties.TestingRun(t, gopter.ConsoleReporter(false)) } +// TestG2IsogenyChains checks the preprocessed multiplication chains of the +// isogeny polynomials against Horner's rule on the original coefficients. +func TestG2IsogenyChains(t *testing.T) { + t.Parallel() + + check := func(x, y *fp.Element) { + var got, want fp.Element + g2IsogenyXNumerator(&got, x) + g2EvalPolynomial(&want, false, g2IsogenyXNumeratorMap, x) + if !got.Equal(&want) { + t.Fatal("x numerator: chain and Horner disagree") + } + g2IsogenyXDenominator(&got, x) + g2EvalPolynomial(&want, true, g2IsogenyXDenominatorMap, x) + if !got.Equal(&want) { + t.Fatal("x denominator: chain and Horner disagree") + } + g2IsogenyYNumerator(&got, x, y) + g2EvalPolynomial(&want, false, g2IsogenyYNumeratorMap, x) + want.Mul(&want, y) + if !got.Equal(&want) { + t.Fatal("y numerator: chain and Horner disagree") + } + g2IsogenyYDenominator(&got, x) + g2EvalPolynomial(&want, true, g2IsogenyYDenominatorMap, x) + if !got.Equal(&want) { + t.Fatal("y denominator: chain and Horner disagree") + } + } + + // 0, 1, -1 and random points + var special [3]fp.Element + special[1].SetOne() + special[2].Neg(&special[1]) + var y fp.Element + y.MustSetRandom() + for i := range special { + check(&special[i], &y) + } + n := 1000 + if testing.Short() { + n = 100 + } + for i := 0; i < n; i++ { + var x fp.Element + x.MustSetRandom() + y.MustSetRandom() + check(&x, &y) + } + + // aliasing as used by G2Isogeny: dst == x and dst == y + var x fp.Element + x.MustSetRandom() + y.MustSetRandom() + var want fp.Element + g2IsogenyXNumerator(&want, &x) + x2 := x + g2IsogenyXNumerator(&x2, &x2) + if !x2.Equal(&want) { + t.Fatal("x numerator: aliased evaluation differs") + } + g2IsogenyYNumerator(&want, &x, &y) + y2 := y + g2IsogenyYNumerator(&y2, &x, &y2) + if !y2.Equal(&want) { + t.Fatal("y numerator: aliased evaluation differs") + } +} + // BenchmarkG2IsogenyPolynomials evaluates the four isogeny polynomials as // G2Isogeny does (without the final batch inversion). func BenchmarkG2IsogenyPolynomials(b *testing.B) { diff --git a/internal/generator/config/bls12-377.go b/internal/generator/config/bls12-377.go index 62bb79b071..2cee917af0 100644 --- a/internal/generator/config/bls12-377.go +++ b/internal/generator/config/bls12-377.go @@ -62,6 +62,7 @@ var BLS12_377 = Curve{ B: []string{"0x19e38372e0d4bf401d2fa5f2261e1e3fc95d51a3857fc23b1385d51ea9c973a89c22148a93dff96447700bf1c3aebac", "0x1579ddb5c1c595b7c08c3a3cef5626143c25757c6b67d0a2677b22fc0c890d8b2b1a17895d047a98c49047069f725"}, Z: []int{12, 1}, Isogeny: &Isogeny{ + Chains: &bls12377G2IsogenyChains, XMap: RationalPolynomial{ Num: [][]string{ {"0x113b0abb7ba48832ffb7aaaa7ce085078312d4bf0bf8882e8f4a0a6e24d91b535b6c81277ad9369cacc733de5cf86d9", diff --git a/internal/generator/config/bls12-377_g2_isogeny_chains.go b/internal/generator/config/bls12-377_g2_isogeny_chains.go new file mode 100644 index 0000000000..fff4ec4e0e --- /dev/null +++ b/internal/generator/config/bls12-377_g2_isogeny_chains.go @@ -0,0 +1,394 @@ +// Copyright 2020-2026 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Generated by internal/generator/hash_to_curve/gen_isogeny_chains.py from bls12-377.go (HashE2); +// do not edit by hand. Regenerate with +// python3 internal/generator/hash_to_curve/gen_isogeny_chains.py --polychain-dir /tools \ +// --config internal/generator/config/bls12-377.go --suite HashE2 --var bls12377G2IsogenyChains +// +// Multiplication chains for the isogeny polynomials, preprocessed offline with the +// decoder of "Fast Evaluation of Polynomials with Rational Preprocessing" +// (https://arxiv.org/abs/2609.06022). Each chain evaluates the polynomial with +// floor(n/2)+1 multiplications (+1 for a non-monic leading coefficient). + +package config + +var bls12377G2IsogenyChains = IsogenyChains{ + XNum: &PolyChain{ + Degree: 23, + Leading: []string{"257686488674545770403807165703608491821700153538449954828958424244540050698630649531963334687249831352703307010320", "0"}, + Constants: [][]string{ + {"149370845425811760534686783029665519258570198318330509991107894621487351112457534622091035381485685966165330961642", "93415456966895164890040074717734777292999956879384302855715231900114211298092778237021673720994821161267542752653"}, + {"226660587743740999964847632295949064585100589151071636372162622586721556828256604007390269721562239662541912528484", "71225804939397574454781075341522871279408017519663410193162107325480791099970116505343033186477432563790677873173"}, + {"82595754703512602204457896074830102307609736853240352210519457186531342661015179551815876202308195304457678322780", "178572038312825222135413924349611077983493230789758573594185045768017908476670558717465049907095874651156519215585"}, + {"116227274964867466712681167349716347088228580139095507239572914854193470111433858413940831590226977240387360857922", "218077594367671548599615463565251397215955351296403021491481610547377241516859041290275117775351738153729671393662"}, + {"93379021100777746047245167175705933479628247081400325143839851528181744150652979819334449662889133972429712730813", "201725387582885366981657339603282449176193137567630843047556450420795927665989915542169957221754296669663115049462"}, + {"16557334276117224032110413743475720570932651693565251804854640387475604030074365405083990977057955614017518082901", "213168922374705851288987814408484590716389971552723288484679798509885502014558096137870198562161795117998014851621"}, + {"34765907613244527931138590268360137119545226641384417956221488499844783554182475742764852841523019688914555345185", "53726824784555088539037605779435719562011384071354055369067147059825507062461500446796666636284060585910758976510"}, + {"78472843469459349836592268362438516632584772462782689165543940935096432261406204830002952340566759857771298000075", "181304488695808599847904787977117553376544420483158216595569803843425164421470013854645545688546128709803191734895"}, + {"84779267180202590512175797026313853767178068809888076547004859838998230475295768521607920267213083255808594213423", "231233857382419994869545069619832010735743249494065972879028842831749160889054377949477182349311695346163153231203"}, + {"90695450935611954882289698409491590155337941181257688179772695550079698715653963040269599025215213048342624693487", "10930843993997906400015430773743419799087673287517114423142420361614084966480868517496824930650162441181940637748"}, + {"88591142099377206706144502884633423187330096998628364549386867888871811891267061452741562438973709668133822290628", "213384240205342036822212559414266885413283821312984997947814807576036413195761446505572743234463713192637173115239"}, + {"193478330663768927239044430773096874126692410175231997195678105310237770639909766064283721185222078162114591473572", "134348250412456398481670791605965051633576151118474952079684317932066687949903994020335351756711756733306457478367"}, + {"12698929480902656238188072920193784522448383823178973564862356024803452993171666434991046300553156442502994171319", "74049941565031852319016742738521993296685399168691816064432151231309197638868762952926033257968006648451887541096"}, + {"220480203147521682271660550375557141855239148604135694199854850167464466575440848504175991373310433125710178016392", "93646802545981845759297512543102016144365721082137624414006943474210214406220766611929249213022208277986254434844"}, + {"140427128324050686995694142995148898983029356228167631647966436022093527016333112359613055197810388451794035091323", "67627189098715933849035990290500498305935035938957416578800150346076480863055635686170456472907000688942460276831"}, + {"215853885219592838855050905866751890031262250694330337603785033145028385609564086736406872049077293255956375549493", "34323515153753740705591356546603478481327466574320897001846118481396532590445050999573412354009989855123693663376"}, + {"205101989223225695384317328869184926347949589733408637903087484032981852453026402458209821359121213626388225258646", "48743481490822103929674148134296255230636702398785834189982383158440537624414471509794267445001552443498948914643"}, + {"162825739970624240185841252744116653076555239909837465885389756064166390195243318794526016866878114329986048378696", "93054059338774650224739685300839481598124656623929704739673971978900730573010825775236381406530673246456233518435"}, + {"79411521361766753423226438237225633723194670296914465889071302951682674213467406139009276423093651788006253760450", "93671253007886917363532184202727041626662395697037687065875767785633638725549766497439089184339896017175116987691"}, + {"114420515927071529973453120619110806820395245983954110035410128156539176445040629913293741752351231398620583267520", "67004198162023009921349703113136714843097777236102161933087429308953798683194530534547363382438273195362411628839"}, + {"199778319266770010917616086962108081594057283469624733473648194754008669201345016904462373050697822975345662976660", "179944743579294966247566869002474212857462481785231979799476808300176833043085994685769148403453083904178988072345"}, + {"38891582699380963045599797833968257103071645184390279557868130367982375431856979601367516291532558393345977662651", "138619904903178284212388707236041006892137489118139013742815585306932951219305795333385930205154844996136191035085"}, + {"231064003914046151282034250860008697270564050062578210041269487119481790530722776589604046788448934186218751729921", "194195985432130456046315900963293546643530564744753354683623376951606294290711825881948681172941564077619293375263"}, + }, + Gates: []ChainGate{ + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 0}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {1, 1}}, Const: 1}, + Right: LinearForm{Terms: [][2]int{{0, -1}, {1, 1}}, Const: 2}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {1, 1}}, Const: 3}, + Right: LinearForm{Terms: [][2]int{{0, -1}, {1, 1}}, Const: 4}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 5}, + Right: LinearForm{Terms: [][2]int{{3, 1}}, Const: 6}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 2}, {1, 1}, {3, 1}}, Const: 7}, + Right: LinearForm{Terms: [][2]int{{1, -1}, {3, 1}}, Const: 8}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {1, 1}, {3, 1}}, Const: 9}, + Right: LinearForm{Terms: [][2]int{{0, 1}, {1, -1}, {3, 1}}, Const: 10}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}}, Const: 11}, + Right: LinearForm{Terms: [][2]int{{0, 1}, {5, 1}}, Const: 12}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}}, Const: 13}, + Right: LinearForm{Terms: [][2]int{{6, 1}}, Const: 14}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 15}, + Right: LinearForm{Terms: [][2]int{{7, 1}}, Const: 16}, + }, + { + Left: LinearForm{Terms: [][2]int{{3, 1}, {4, 1}, {8, 1}, {9, 1}}, Const: 17}, + Right: LinearForm{Terms: [][2]int{{3, -1}, {4, -1}, {8, 1}, {9, 1}}, Const: 18}, + }, + { + Left: LinearForm{Terms: [][2]int{{3, 1}, {4, 1}, {8, 1}, {9, 1}}, Const: 19}, + Right: LinearForm{Terms: [][2]int{{3, -1}, {4, -1}, {8, 1}, {9, 1}}, Const: 20}, + }, + { + Left: LinearForm{Terms: [][2]int{{2, 1}, {10, 1}}, Const: 21}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + }, + Output: LinearForm{Terms: [][2]int{{2, 1}, {11, 1}, {12, 1}}, Const: 22}, + }, + XDen: &PolyChain{ + Degree: 22, + Constants: [][]string{ + {"89075852064542690701435870725058483850265243355230713295911196183804840895034022859384854535471800567580477488270", "203745930402833550635419439505012886403822855296214346472038160663081705155518117546923911447626163182068410068599"}, + {"80089261957231363110697367866915356983976547502300981750142804278769956936379245242060386818627404220892024494481", "61535886571059201740458676413515575567028788955409697415710071116526701374663777628342437017519683824139393179751"}, + {"78516493655759247796708683842677849231130916757051008998195944071969918905585328988936571243413644411999157977993", "133698943688268087340299312739282655669185691485010816059896096457169499826447404047324440223273416693644317697947"}, + {"113405194543233178292709996181886438281603578699723348292327513976787976889406294624294642882927647995584972914401", "144420644784206009038169968001968510415753494520416423145581592945994213167592995830891402055180733381683911036544"}, + {"81183540767390619732745860956682905821269672296615010924681325305018577226932573317513816609960516649678567072531", "133351044933312830207685977006944199756166261670283479461006031183455195257997556966633124778877674094128839875098"}, + {"227849193364937917220196036464368975262525600143016404579592121706842173418005221117092654221260143343236968669452", "6456980966530809514829128581343701955575564917150426331234920638178019852080418191224072449056068942321718767991"}, + {"27149589843297819995336380679454984438826489427870634291758695893894927720469157411715225102423977072139201152074", "97333325559250506649862304367552002744683953378267532093529718296882749219232024523580956925172362978225340008107"}, + {"213647157025938489888616821431106834936550607438573904685856150246386526655196638693330065185398692066051356368358", "88290884801687644184507585119512213701602279835510024683730519586815577212559273892973113459607244503561546108981"}, + {"242385095042037866681442089185266947091220754056220295316465605480108863924086301992567072962140189794815763929936", "108925498356809885102819357965422644846071332244059681764707612350555752276273813994239183803696658324189059500360"}, + {"134827942263107556949909413800782440639195697134648912768476587900062515813532175703071405658587122505948678840309", "236915941229028715832443767718515898131491102631025926605754745764114433628723052140446500009789251794176161748883"}, + {"170792677214920946743601657212925890169445203562856439506173446190995791212414047232349718244149012718781183450961", "180702313777822133227998715137128771898339111522801260106136497327153085436657236934447749292157566293300890675206"}, + {"219178538062613061685637693129062324288861252208260772140009226622371889126744879054171753699099689470465155307227", "19190614688081338197992634040624087018331438782807256129482726533860838753640762658730807213698215006515271299948"}, + {"134354070321379569826871720290701150857567388657193877012953552407692240726793628777406733588220680719830159010644", "185033354563265817179548554747843041307250477248259978233998425615117417525949228185973633700107677561293814125290"}, + {"230680223516776817188176445583834003031882209900434905137574465455681718544370189248062191769075701502214015420139", "186426063596092122524246777238894072231520801627682555891426974647453456271767556522173226880170520619409460887222"}, + {"75482737907705304433741548373095240991403694181160722187177351468605020086414224878391542399629386623588558717805", "121604324058539139603762655246150107800986636687448040531655780159709383296811563229648795914872885784162581825487"}, + {"22010831505961908782626638431692614213665395112410341025489977392913624488947673663873888049744698570349403337111", "115958223687581577818873835623560849673008905045763734988326396002394070575695286073001797919435923390041153069333"}, + {"148579660613543483902215155326845212565022894664480454409533838425392101176026086186629600120572934507832551483479", "40469314133031133546908568439575681779528276195195711633654653528051840504784628932566385675598406657999548906204"}, + {"236422017728105269899987388006201443089777078523995253005638315915515146543810271065967187203476669767432448220798", "67332454774127720974818590741233483828539087868943285544086608474270700429241047693871713399926752514911515551266"}, + {"188738079290838857043379409201572283243940444334288218969165094525293254086295226187546454149879757874958832955837", "257279550690895679866121672241306710957116840569063957679290132016599236265273106999526478254755774342184414106589"}, + {"55341112687962544229441710713899698560160336581257430719013138335953420536181385464939122150246866381119135090142", "127975929760341386627606123382547343851299673118282153654368372798411430829079278778923920403845126342120829832007"}, + {"106765024309038923367701601503930379802436767856159656983814239167196264352239228353308519621163431742126446339761", "176627488329006669243699090131006631912783738852975820078946054678047196506834813181821216557520975118250000893043"}, + {"196537929755540830130458921156910352741196129560556501635658595085779576490417628044619830744899117989899096675116", "106967816747202586221026040614608875779671819314280336591550617355334247302203894951925800601923998790402234025494"}, + }, + Gates: []ChainGate{ + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 0}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {1, 1}}, Const: 1}, + Right: LinearForm{Terms: [][2]int{{0, -1}, {1, 1}}, Const: 2}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 2}, {1, 1}, {2, 1}}, Const: 3}, + Right: LinearForm{Terms: [][2]int{{1, 1}, {2, 1}}, Const: 4}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 5}, + Right: LinearForm{Terms: [][2]int{{1, 1}}, Const: 6}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 7}, + Right: LinearForm{Terms: [][2]int{{1, 1}}, Const: 8}, + }, + { + Left: LinearForm{Terms: [][2]int{{2, 1}, {3, 1}, {4, 1}}, Const: 9}, + Right: LinearForm{Terms: [][2]int{{2, -1}, {3, 1}, {4, -1}}, Const: 10}, + }, + { + Left: LinearForm{Terms: [][2]int{{2, 1}, {3, 1}}, Const: 11}, + Right: LinearForm{Terms: [][2]int{{2, -1}, {3, 1}}, Const: 12}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 13}, + Right: LinearForm{Terms: [][2]int{{1, 1}}, Const: 14}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, -4}, {1, -4}, {2, 1}}, Const: 15}, + Right: LinearForm{Terms: [][2]int{{5, 1}, {6, 1}}, Const: 16}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, -4}, {1, -4}, {2, 1}}, Const: 17}, + Right: LinearForm{Terms: [][2]int{{7, 1}}, Const: 18}, + }, + { + Left: LinearForm{Terms: [][2]int{{8, 1}, {9, 1}}, Const: 19}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + { + Left: LinearForm{Terms: [][2]int{{10, 1}, {11, 1}}, Const: 20}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + }, + Output: LinearForm{Terms: [][2]int{{12, 1}}, Const: 21}, + }, + YNum: &PolyChain{ + Degree: 33, + Leading: []string{"191144230647045707590184821948778479495825928592047153194222027257046414968351470170933284561757547536684715232224", "0"}, + Constants: [][]string{ + {"43092294745982351593431639164915213994562179277573378005559830380641965159666142872084412355196475512662897417413", "45513070120361338339713561832571968389362575915561453263850877871608835137356522389321167403639512913191453619087"}, + {"254401076514128667627608835045914264752625794239271204940690828627194153472531178049148299388907593371239267889992", "71768037528399099276564228206927575886536262621874581114830254947437428829907954700593737410843633304850522175113"}, + {"253753957273391632602652963197388950126597405560643320836757669553256993587891959860674321659335548385194194900262", "175122579831676470036396450574764774312829913179320950140307221207066969725547792653170787242096661707067541679836"}, + {"3023964934556577431213598785049969017313370474513545548602888109096765439296221058909249194980175912830978686446", "104384158789894511973341057015977838023067938582258299400922823016004421255692050123431810117194164854671899970369"}, + {"100562913234946498846822478329566976880367709291344604951424515585729874490569500187650146734676071354889793572163", "169748883592326429795171858744343850495131832153316913695993019252728496875136512205878682379518607594739986381018"}, + {"96277448414070218054611545390680285042046790487307317459080812083856895539674055950046220640421467482637460731368", "149654306429968395394102621773012085400864508407705867740390672301435144568564601273413347614137946671767525280389"}, + {"157981181404118790754539507754315693488310667512988537320671828287797674070983161183059749589169237753193532762115", "112511810959886971641093103174704248830841076714374342684784812402736500155645778874026702733298690548179880837799"}, + {"20381026587988855356515333061721651278550222455362657835437401400966032755178588721229454970674614414533654673164", "257465422300403944975521213766496765906471455499102447985012562006895715427404738707647988556770017552537107161605"}, + {"73836943575525231851765804736954572244612581773562768833968439162874985404221727658943876070226266765285808616752", "141298877481429714628801692179411718379719062432679271300681489522326513314829314030246447217583065620806752880584"}, + {"229980068712841572782845279712090036454302348145529377277951092496700120180780709839878451418510207629404685740462", "68663172608730090830087075590950845858726892044105994550110931602028287110804266094190626803376361041904864611319"}, + {"70319945547318971696510543126637449776058413518051639658966101952910395788578377680828196771767568164981640745380", "248069934987167629813799451049850292808154780263302348853594860399842908716325357160011259104552477912408535320596"}, + {"235801198393281707448661957050685589409395986546847529438519217082790427955709487320725463582481466651949238025879", "35120969270147350492480174431423829440860953202830707234928735336345399324856441867325428428215260049417923843830"}, + {"122209635014257831928719420017383832547767757214533491550079088405931024361306667954628393826817239694628279807104", "150000882186753009422728582020909392490042696124037878154854723121580517688551061869100161720599260666300761447288"}, + {"7409224509008636129271431938492426624725761354536184057796764443427004943312851688653212846893845219021716665044", "53315439898848089624400138711252116488944019575095586153420811039604185166209993638731948467591113895037169248306"}, + {"123065628730811132055132482635658094166918105410463195478816446818253734111703129134346456999494549261180232644468", "214024458996956162522794142006725252136745032881470745843051208031229283810729731538178754988516857625244064262753"}, + {"168474415853334706644446433995102471596672839668971825463901048921981213847213341571772880659484592929682555832359", "213951115164920072304167116807010681577602155152748904598856648369058996125137000364957611942257933178868518473578"}, + {"253108474824146345952672703640747297255281347082907667005415438040978789703371902407627524070688846336396851912153", "46814282912648401861409047747590245565057870605306063896963353127729632611290735238960319119204197356741237924243"}, + {"40801915639929512995006159530212599707233838848885872626228047421364584446858618172018601387006788356699543058778", "35832350096853640580293873993259028413515989723401677054117481048546463199578632989812011984021986840173065624794"}, + {"15369842772487892283308007990810771223210498277552972526177574741806725539322178642098715035331289680231051542574", "119613714968647163851737752210958943468734006808397023376811308563889951998852547172725317765243025657058725463302"}, + {"192497741560627472322161991733234720027910533426414361514860685429783311114452220781933408483878531863746700344215", "213691166008384693444107190530674593220909311035083294837381893301529027315408034024482606612431659509408465074747"}, + {"165651415526801394720755217105951616004616882882138772922228642437002532779979661839465995364830329572598751647044", "215739450898898388602483378448745862549187563941389101449376322701717582035508935041088168161994788214350219390208"}, + {"56600152398231521497507848929899296416437507042721089979261132239424479402029808679845134355528014575989340339520", "75177203959467411872789245153768703609698100688641603163248613149200783390223375491667976909369924401062395298263"}, + {"227712937314758950563333266191085805706595461152931144986844177983797833136579633261550174527384603199447037839518", "131851108384671061583885991177089070848867719553371427708700618685955453027764185733504740779096677672098962874513"}, + {"228081226266337510597997893491940017931942347855768452079508685641868521773298197946997507106943646989704427809691", "250823629884752404113251837716071828003162993977257319514053147016158822993988230137159131737845991151903508341018"}, + {"98356501226257008124719785005415425170141144457787730824880635211255837259639210814320782161887457106241041278082", "162345683725585055208709874035290823204247247810530999449066836155964142834423792078850707104234590269682257268766"}, + {"82267958878226385860427967946349333654817362652661253088358972925574051069481046273724401049154861923615271564939", "22109110078468428787371013897421237313549310314423666164317581395230996188877127180933737665060218703581063121456"}, + {"166596338242079772568372948833677124650648219014544372649808522055894277401303159119621141337945158753264190867125", "141349932267778337633538928121642075887571543133894818591376230192464553289650787544662201709175865520433758559008"}, + {"76547044568607617942394770137419432746436808836723814060349977604532179207112852768808644183876436344538482119505", "154841706142689276199618071810060643829172826550648633654393982826864348554663000995556402696476094689349094313845"}, + {"213281600236159283081818799700602911446130141198064960150494972239085843067445987967157740520042466206719568762563", "37361074079074431366986979472121015043514918516459104668333713386509229663456407278342876990135479060967744639377"}, + {"113840842443871467645515052778592038561313331059134569835109583693221849162950431465898189397803565719815053318845", "28285183906143515568807805827148487430188517248156179871159109597467032973242862962921526588987222090769328766868"}, + {"223859018375830773596116646455262612103457614491285322112182201274348308072334472751776648635764893412234537675806", "71971039929441797295157244550711537267158974829318918880350086071496163343059339075621389749404340932871590892474"}, + {"140747669983014926195398872889038509141849499294725461042228549819938025933155597195938962339131152294870826883678", "109610652152617251386475470422279511069194614802821645823977504482438365097963638942227331823956103190207412411455"}, + {"245562322955347252464679578922709448208941924713628484337049106746115382745772048896829214018856416074095642784118", "79883473102937812212168085995928994433335947899155903380079336982267857884642917189175806269537028417710565209998"}, + }, + Gates: []ChainGate{ + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 0}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {1, 1}}, Const: 1}, + Right: LinearForm{Terms: [][2]int{{0, -1}, {1, 1}}, Const: 2}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {1, 1}, {2, 1}}, Const: 3}, + Right: LinearForm{Terms: [][2]int{{0, -1}, {1, -1}, {2, 1}}, Const: 4}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}, {2, 1}}, Const: 5}, + Right: LinearForm{Terms: [][2]int{{1, -1}, {2, 1}}, Const: 6}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 7}, + Right: LinearForm{Terms: [][2]int{{1, 1}}, Const: 8}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 9}, + Right: LinearForm{Terms: [][2]int{{1, 1}}, Const: 10}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {2, 1}, {3, 1}, {5, 1}}, Const: 11}, + Right: LinearForm{Terms: [][2]int{{0, 1}, {2, -1}, {3, 1}, {5, -1}}, Const: 12}, + }, + { + Left: LinearForm{Terms: [][2]int{{2, 1}, {4, 1}}, Const: 13}, + Right: LinearForm{Terms: [][2]int{{2, -1}, {4, 1}}, Const: 14}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}}, Const: 15}, + Right: LinearForm{Terms: [][2]int{{2, 1}}, Const: 16}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}}, Const: 17}, + Right: LinearForm{Terms: [][2]int{{2, 1}}, Const: 18}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 19}, + Right: LinearForm{Terms: [][2]int{{9, 1}}, Const: 20}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}}, Const: 21}, + Right: LinearForm{Terms: [][2]int{{2, 1}}, Const: 22}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}}, Const: 23}, + Right: LinearForm{Terms: [][2]int{{2, 1}}, Const: 24}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 25}, + Right: LinearForm{Terms: [][2]int{{12, 1}}, Const: 26}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {3, 1}, {6, 1}, {7, 1}, {10, 1}, {11, 1}}, Const: 27}, + Right: LinearForm{Terms: [][2]int{{0, -1}, {3, -1}, {6, 1}, {7, 1}, {10, -1}, {11, -1}}, Const: 28}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {3, 1}, {8, 1}}, Const: 29}, + Right: LinearForm{Terms: [][2]int{{0, -1}, {3, -1}, {8, 1}}, Const: 30}, + }, + { + Left: LinearForm{Terms: [][2]int{{13, 1}, {14, 1}, {15, 1}}, Const: 31}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + }, + Output: LinearForm{Terms: [][2]int{{16, 1}, {17, 1}}, Const: 32}, + }, + YDen: &PolyChain{ + Degree: 33, + Constants: [][]string{ + {"43092294745982351593431639164915213994562179277573378005559830380641965159666142872084412355196475512662897417413", "45513070120361338339713561832571968389362575915561453263850877871608835137356522389321167403639512913191453619087"}, + {"246513780425555610905121430090143011774082787602597790816608346623803737997707109604000187899879838377824314577583", "186643696050998969193925512258593483316425574109367722744096588230211034613648266200144156261478050740117820869526"}, + {"124465008435909072635748499487332387607833936410764294796560255076077718807263940482183079152908631945727408834000", "68447476848237511690195659831707283078816767522594973074651059088305522201576685510073621926485543892497825903422"}, + {"211825031780471517443680672909238128350323395473932179586946689520581966480345276315081488847287195321999029356307", "252803565477823773732057572265382528164553256315682770717974656993708846541157371691158674349057845871120975467739"}, + {"28079194671982946230672378922435449513259118432419966159410175893452132333031099957636229310497323450215795310798", "104678602147158332348441037219268397997774322251212267339070698589915661159478867103851392159171740344811479267322"}, + {"193257479739573705494420674674029408707584730899767019657536130121386807633696976707062128312340309067960195734237", "51761804647810213449089811131218195391819136665145845273274124856214189491338896324423662913463538931002282213526"}, + {"147014371638730122118930391382022195985767179476581723991733409498151871586684158120818122757911317220230173759607", "26903204863389158782643866474380174260821184491554457237945015978132372657238632786094767333339989200589333349731"}, + {"51494971755031106237948320520738387601855780141444210548944517863341914747449069359821076291665597097223048966971", "87321479266706978822825102633257576421517519744528846159715929343452987949009890127283992423680564510843503510456"}, + {"230914115929106686124476709239548472950379596392476159168186406841054391135810185640327383632617438019150700992523", "237386241516822067678361780205766781369171742095200521710857732974948212773669825930740120097628533937017980634326"}, + {"78611588761688249905644505767522273307041581897634273585235995578684096523507581052811762083955920234145231561875", "158504609127711014927948697775390267905805175491580825383722592436271199800370138792533197760707600472322346032529"}, + {"256638927209075263851598016708400157395918452264243276762214415461895248345908310790459830844800884636295234989207", "834143921140677684562118478684443070315922012934842906527164738874238017482658751342221716721423146273918410246"}, + {"141601856861997986000841549619257840620937124537752281700378844914036490481127698237117538105702135414709041093352", "117778679499767490887997647397479761535013542224685673803108275657753912760323866142807003667554736028496464082696"}, + {"14146880255842256586664940544628685832212676983290331427344181945589545986540701443822890731563833812998382280871", "164229203084301787950761098209878268020030174808927127866998690784649975711213651884728913782145729155808170802483"}, + {"33630815291371509174420129596457602237945700596747819056352532058089788595948002503288301423362582846879916994621", "129644741432460307887168320821894994972964988763107239041476961988857908372935461614728802683462777669300426608346"}, + {"235763182125727272419882902958948170629182162462876133636904746917708875483407720589524819210346884763844217608633", "77110533425547348733926366723410391804306982678513517551249379302305296388045588537380994688738989611129132202499"}, + {"157588106078822111496327745331327783637186186481665604949548002035042394421795015917945656363022040306017418320187", "241048436803495289471073998914932985699913399973065625361670257208819435928617112350102273853195861546501685825750"}, + {"109488921872432133252883170609807709653489700880314540226099413891132775196937445634424871606747140206322215343166", "192704618556935242627981259475057078364800647056492407854906469067747683282596959052855365367328358028366123000916"}, + {"57019398805139139345750484963251886778131277721536140532076780057582882283607054462860958716154519708303634577205", "133171629003136015975757211586057347691370642120190030426962173998251625485564005484373899578981184258372707549481"}, + {"88092386181380766193871588730234141837809749483859300710673180269843993147499435543766357319699575834013361325069", "221117011069257962721054951243148527048320233855560219527798662213386889589935933054831015483531638704725724209644"}, + {"68555952140726769774562264317415326700908612442158211179572512961391805101428401087702042927550833452823622339799", "226325463517939717348001901764858045330346018997226679656780855860124884913059197182591175472076086326750378429064"}, + {"242686920508218541715149038558367776898029547577920932614568663322406862653979010642226803351556522371179693758051", "251086486896827490316496580393157520688456172740291047300952505632709188658858694785903679319058056424702092161225"}, + {"57282349234998255587155362210577794241722641516368252203376096060460860479389915534425937105762926143263782048572", "15863546774596885009505762439019029323297109395302909141735992654322075001791117105930967985537942092497833113039"}, + {"239365805290990073687610622832315373334942681973525992273995273351485965701702568695228196620754249141792920877850", "65854597689517233187489359381492064159359791069376427018330512631430596808271673649243288016563656304319712978849"}, + {"135782621120939686102307093596063609784501697513487478364356110359134569380134108353295154376947885353690064246883", "132337945931982275568707294231729160226106258938889949390195115812485416729172088246349874652399306199894644772336"}, + {"213920931805691301057107962002782045430680047258959853262273567003593833156137172729234435853279096868786084221489", "182826954374941508638607003741969489660277354860256815065171392894287459186199475292434493134486013191429379235077"}, + {"32715139123866847557417521200235021069104459304536562911451828881318906427735869274037772431879409345615491407764", "80472393255103039414264514423672614008643656303746601585017475953222373822204879366353277492252430984737021556672"}, + {"45290142981998788095902382360186879878016989025907796646997097775039387393103408671986691628982295868878035615091", "148696983411999141956725105950081308987263086972216857903023688153100792566890681033477764154853098863268498998612"}, + {"249450373317408733603709430448853814175453239173674662034805849430992233115461893142313668119392625067768403956119", "99026270760580803685347844892774645765290035738736894596481749218854958579925367710659879327158818219197292908189"}, + {"232294149682612068393144659654728294011721517945427036658037547979773702228546976513780645057350848140576213118451", "144836640561318305631345788559979734502012606773383334373028045739486789220209705252733475710005704493416464193723"}, + {"196535180005182594460253977083195802507916520447197760721168448251444975810619754039423340589123425713700898787834", "195380508897228603218125720410264516267210297910821898308638791170763683811268323737545668350897537329068090607745"}, + {"162441973234401489490718338987016582339377578672020604100282511158494273094288252850495285991531673229320551835769", "174165067668051740796727989285671050143169310542709306647454361886633545532374109686429212503687987500711567072069"}, + {"40554773096287709957680440601145177010669513668129405560879309900811895299475946039699363506920912893088691915648", "93047475010994361577323335807977752880240926992588025884215376523048595221482312583324884582342545165692148207977"}, + {"39587469842071482526083983691732199410950995726590466844060851759581503373974682468641483429000437905384817314741", "254359694856161338918957728411480169020314596277310031246559715572450443180415657362058071705673154118144135767979"}, + }, + Gates: []ChainGate{ + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 0}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {1, 1}}, Const: 1}, + Right: LinearForm{Terms: [][2]int{{0, -1}, {1, 1}}, Const: 2}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {1, 1}, {2, 1}}, Const: 3}, + Right: LinearForm{Terms: [][2]int{{0, -1}, {1, -1}, {2, 1}}, Const: 4}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}, {2, 1}}, Const: 5}, + Right: LinearForm{Terms: [][2]int{{1, -1}, {2, 1}}, Const: 6}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 7}, + Right: LinearForm{Terms: [][2]int{{1, 1}}, Const: 8}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 9}, + Right: LinearForm{Terms: [][2]int{{1, 1}}, Const: 10}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {2, 1}, {3, 1}, {5, 1}}, Const: 11}, + Right: LinearForm{Terms: [][2]int{{0, 1}, {2, -1}, {3, 1}, {5, -1}}, Const: 12}, + }, + { + Left: LinearForm{Terms: [][2]int{{2, 1}, {4, 1}}, Const: 13}, + Right: LinearForm{Terms: [][2]int{{2, -1}, {4, 1}}, Const: 14}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}}, Const: 15}, + Right: LinearForm{Terms: [][2]int{{2, 1}}, Const: 16}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}}, Const: 17}, + Right: LinearForm{Terms: [][2]int{{2, 1}}, Const: 18}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 19}, + Right: LinearForm{Terms: [][2]int{{9, 1}}, Const: 20}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}}, Const: 21}, + Right: LinearForm{Terms: [][2]int{{2, 1}}, Const: 22}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}}, Const: 23}, + Right: LinearForm{Terms: [][2]int{{2, 1}}, Const: 24}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 25}, + Right: LinearForm{Terms: [][2]int{{12, 1}}, Const: 26}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {3, 1}, {6, 1}, {7, 1}, {10, 1}, {11, 1}}, Const: 27}, + Right: LinearForm{Terms: [][2]int{{0, -1}, {3, -1}, {6, 1}, {7, 1}, {10, -1}, {11, -1}}, Const: 28}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {3, 1}, {8, 1}}, Const: 29}, + Right: LinearForm{Terms: [][2]int{{0, -1}, {3, -1}, {8, 1}}, Const: 30}, + }, + { + Left: LinearForm{Terms: [][2]int{{13, 1}, {14, 1}, {15, 1}}, Const: 31}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + }, + Output: LinearForm{Terms: [][2]int{{16, 1}, {17, 1}}, Const: 32}, + }, +} diff --git a/internal/generator/config/bls12-381.go b/internal/generator/config/bls12-381.go index 7745ef11c4..9caf677151 100644 --- a/internal/generator/config/bls12-381.go +++ b/internal/generator/config/bls12-381.go @@ -30,6 +30,7 @@ var BLS12_381 = Curve{ B: []string{"0x12e2908d11688030018b12e8753eee3b2016c1f0f24f4070a0b9c14fcef35ef55a23215a316ceaa5d1cc48e98e172be0"}, Z: []int{11}, Isogeny: &Isogeny{ + Chains: &bls12381G1IsogenyChains, XMap: RationalPolynomial{ Num: [][]string{ {"0x11a05f2b1e833340b809101dd99815856b303e88a2d7005ff2627b56cdb4e2c85610c2d5f2e62d6eaeac1662734649b7"}, diff --git a/internal/generator/config/bls12-381_g1_isogeny_chains.go b/internal/generator/config/bls12-381_g1_isogeny_chains.go new file mode 100644 index 0000000000..2ea09509ec --- /dev/null +++ b/internal/generator/config/bls12-381_g1_isogeny_chains.go @@ -0,0 +1,214 @@ +// Copyright 2020-2026 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Generated by internal/generator/hash_to_curve/gen_isogeny_chains.py from bls12-381.go (HashE1); +// do not edit by hand. Regenerate with +// python3 internal/generator/hash_to_curve/gen_isogeny_chains.py --polychain-dir /tools \ +// --config internal/generator/config/bls12-381.go --suite HashE1 --var bls12381G1IsogenyChains +// +// Multiplication chains for the isogeny polynomials, preprocessed offline with the +// decoder of "Fast Evaluation of Polynomials with Rational Preprocessing" +// (https://arxiv.org/abs/2609.06022). Each chain evaluates the polynomial with +// floor(n/2)+1 multiplications (+1 for a non-monic leading coefficient). + +package config + +var bls12381G1IsogenyChains = IsogenyChains{ + XNum: &PolyChain{ + Degree: 11, + Leading: []string{"1058488477413994682556770863004536636444795456512795473806825292198091015005841418695586811009326456605062948114985"}, + Constants: [][]string{ + {"2621488546057070674016484327822938827334049491341799297743850250886124738430226700971713106829632851797539583580491"}, + {"3029079065131525969336530297278269206518572021099621853182211877611337633672725307145762019339170910637346785895443"}, + {"2983498228375582255971856566075697262541079097792031800275832467198281479072526327995128587008806272406748384174176"}, + {"1482035812432105458409029277991189590963977830019228431679132252458076637904833427185937169110819874871023649766382"}, + {"3238672565002568363263705962592798111608864350031284548318978020427157442393023864149212532241083928765237467988577"}, + {"2635211531504736477488611264832814830784892697469940953123465866246456487341428875137639300135703470941467096189731"}, + {"2798897900495921659510536521569808720543300862670781945815971201831546924841019038776503567148664685414229400567536"}, + {"910551153297606604212947392705566788634861053572729619927835204478296233643682909072525601087433693593802451136442"}, + {"594778220695323046414821633510984126276407725347024062968088035801496443249102899771339790826023611077938556730504"}, + {"1943074383793715170139441748673485544291949485125185546949560881883545901840393788061320455331847029656891871577901"}, + {"3015299739227131045005043482627181614033254657692441098610790483566594498492312171909346944491364075814432734265251"}, + }, + Gates: []ChainGate{ + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 0}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {1, 1}}, Const: 1}, + Right: LinearForm{Terms: [][2]int{{0, -1}, {1, 1}}, Const: 2}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 3}, + Right: LinearForm{Terms: [][2]int{{2, 1}}, Const: 4}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}, {2, 1}, {3, 1}}, Const: 5}, + Right: LinearForm{Terms: [][2]int{{1, -1}, {2, 1}, {3, 1}}, Const: 6}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}, {2, 1}, {3, 1}}, Const: 7}, + Right: LinearForm{Terms: [][2]int{{1, -1}, {2, 1}, {3, 1}}, Const: 8}, + }, + { + Left: LinearForm{Terms: [][2]int{{4, 1}}, Const: 9}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + }, + Output: LinearForm{Terms: [][2]int{{5, 1}, {6, 1}}, Const: 10}, + }, + XDen: &PolyChain{ + Degree: 10, + Constants: [][]string{ + {"1361301674662289706512104053950581544537596996381909570917387309053147232137224482343337876820534957214104272183789"}, + {"3279833617373059021619732553377905079509797061935736388649450630481586994754433428967937842653083235063586020636896"}, + {"543237025221989416844279937295353765566484203812395984260929073630827606259788203548634868621550268895277791724502"}, + {"3610346772845541386702648254701754300916372319157337923297440027193039602698052874116741825113942334711833253859593"}, + {"3688419331627259089835410910881645926379871438416805482866722572118611371785424159933230533921414530812123130126650"}, + {"1510159465629418958356650897243001073643384705801354037972963521576479691269152810333040171482177172327006162402039"}, + {"3139091381269800797493081921656391660201135750947958318950040837115026733588444975244311416987916645449191641616273"}, + {"3638306990501440313451182089042151356050128909333058533987734322842247500840177769451757723998827399387964365346432"}, + {"2691439827613222792497146528283638922667495867692785198237501298314332659878006254579783927205737954651489268935849"}, + {"1353092447850172218905095041059784486169131709710991428415161466575141675351394082965234118340787683181925558786844"}, + }, + Gates: []ChainGate{ + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 0}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {1, 1}}, Const: 1}, + Right: LinearForm{Terms: [][2]int{{0, -1}, {1, 1}}, Const: 2}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {1, 1}, {2, 1}}, Const: 3}, + Right: LinearForm{Terms: [][2]int{{0, -1}, {1, -1}, {2, 1}}, Const: 4}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}, {2, 1}}, Const: 5}, + Right: LinearForm{Terms: [][2]int{{1, -1}, {2, 1}}, Const: 6}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {3, 1}}, Const: 7}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + { + Left: LinearForm{Terms: [][2]int{{4, 1}, {5, 1}}, Const: 8}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + }, + Output: LinearForm{Terms: [][2]int{{6, 1}}, Const: 9}, + }, + YNum: &PolyChain{ + Degree: 15, + Leading: []string{"3370924952219000111210625390420697640496067348723987858345031683392215988129398381698161406651860675722373763741188"}, + Constants: [][]string{ + {"2024203459754997765994602116017146872041848955079414525017362815603600201316568531593871171825472253407484868636261"}, + {"2374260161425502056892138131965781713912335551439028682256597649727451572100048582203206773029174365000170172047438"}, + {"1956647424986716898937985283488944100422237018607927757941310750424634759802019450926808145998944103871827600359608"}, + {"2026334449153594976347412205788185034644688427732500139256703526922932004079355215191581460482219125900436321506751"}, + {"2263471536580270360099313556128226160707953340905281416147164093531844665362990773330691104040541431132540820473885"}, + {"1738469183770372720669807902711986010983968443724529050580682728269251145465726221741530958712058681285967560144879"}, + {"3522120922840222636767625535757030193073220753160441479540322922706150223265636592457049976188551036536533728434692"}, + {"3014306588748960063324743095970184213183347648831244994365146150503680655575515182801759651396457691467226051342317"}, + {"2690216825549561852942233017992724268864221916564715593443984058022753623739615758881108948117946885546845077997708"}, + {"653686967097195841091993194235543722362984390323979114581023059840836375827123678906290110656813301491128349034073"}, + {"2584647297000257360621815460084901193455031398780720194708539510574030847451650127122688381730008537320640551303621"}, + {"3879736693275939702323111586540862597777117097870272247073069985352210257883674883887285202754761061224915898916719"}, + {"3345445301485461219828312066322663137151615461321807930430342677696819270984836810400021125734592586491815829340979"}, + {"2942485676942602690298881662163994751327978999816475016684162089897982659534979056656304040762224633450282621267797"}, + {"2168224994747033307596645691804494888666333638131220877620335308620874487492312833206508359507783336855056647513829"}, + }, + Gates: []ChainGate{ + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 0}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {1, 1}}, Const: 1}, + Right: LinearForm{Terms: [][2]int{{0, -1}, {1, 1}}, Const: 2}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}}, Const: 3}, + Right: LinearForm{Terms: [][2]int{{2, 1}}, Const: 4}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}}, Const: 5}, + Right: LinearForm{Terms: [][2]int{{2, 1}}, Const: 6}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 7}, + Right: LinearForm{Terms: [][2]int{{3, 1}}, Const: 8}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}, {4, 1}, {5, 1}}, Const: 9}, + Right: LinearForm{Terms: [][2]int{{1, -1}, {4, 1}, {5, 1}}, Const: 10}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}, {2, 1}}, Const: 11}, + Right: LinearForm{Terms: [][2]int{{1, -1}, {2, 1}}, Const: 12}, + }, + { + Left: LinearForm{Terms: [][2]int{{6, 1}}, Const: 13}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + }, + Output: LinearForm{Terms: [][2]int{{6, 1}, {7, 1}, {8, 1}}, Const: 14}, + }, + YDen: &PolyChain{ + Degree: 15, + Constants: [][]string{ + {"719806776733296961845943882800876595619756248237403805665157084552723777022797743307923617080381327671886635221612"}, + {"1423142915257187695038626032825221596264974772072857592127401115839766333405376277475398651960818253168209330098646"}, + {"3885985832187236476494148485244351647442915692456811451702818404499748096042184448202695524504404864163971268141105"}, + {"2571349238818588217265393717826395807006821621588283916360470353059176559903495456464378902086997934080674499299455"}, + {"201451139590645312734191888265662943437850149832678935103556502577140240842686440698154058338011336482155587994750"}, + {"2159812921778448697544100770954124484674411587932038176549375776271479113734449874586561817199804910350790378274641"}, + {"57324134850682610198488556830452909409886499186882909859047477019103839114534572286114858300815831533455727811155"}, + {"2925087082592395082352927969883090885892742949418269267089705207532278277965989683216914686502714804636126479026477"}, + {"3186411145479701723456708346683881333796496843621875843973010359502932543058132133103115079550589086156525370654977"}, + {"2454833546762607284590424067984100440812396195385148505793263849908742632175398949600664299299866675804912295129938"}, + {"2492496632420021677692526943664269296737858823151854490582305307265698398154380004485813277170440003175278628710106"}, + {"3793582302532590910669838563999253420164936773295278165036693903336629620307997219434686805529693004167983697882936"}, + {"2327333054479273107564931870753048180789989693269684776905944305607548497570170176147887639065127727121479572800339"}, + {"1115391492419877732774133803580755702076440589386596782183234865645756467780658114159822724508834293119602705984092"}, + {"2086912889222541880360648518813739274855207118689748846022791406880358859510188427151187808770802967064830117381343"}, + }, + Gates: []ChainGate{ + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 0}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {1, 1}}, Const: 1}, + Right: LinearForm{Terms: [][2]int{{0, -1}, {1, 1}}, Const: 2}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}}, Const: 3}, + Right: LinearForm{Terms: [][2]int{{2, 1}}, Const: 4}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}}, Const: 5}, + Right: LinearForm{Terms: [][2]int{{2, 1}}, Const: 6}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 7}, + Right: LinearForm{Terms: [][2]int{{3, 1}}, Const: 8}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}, {4, 1}, {5, 1}}, Const: 9}, + Right: LinearForm{Terms: [][2]int{{1, -1}, {4, 1}, {5, 1}}, Const: 10}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}, {2, 1}}, Const: 11}, + Right: LinearForm{Terms: [][2]int{{1, -1}, {2, 1}}, Const: 12}, + }, + { + Left: LinearForm{Terms: [][2]int{{6, 1}}, Const: 13}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + }, + Output: LinearForm{Terms: [][2]int{{6, 1}, {7, 1}, {8, 1}}, Const: 14}, + }, +} diff --git a/internal/generator/config/bw6-633.go b/internal/generator/config/bw6-633.go index 9805f1caca..c4226b8c4d 100644 --- a/internal/generator/config/bw6-633.go +++ b/internal/generator/config/bw6-633.go @@ -29,6 +29,7 @@ var BW6_633 = Curve{ B: []string{"0xbb475f2945d16aae79792dd2f17748101c2558a952d4221e5a52bee6083040e779fc8d5e9c51ac35df601e0273b10c72f2b0d48da6bbc3859a3b185a7ee3060030e001265b3803227cb9d879f408d9"}, Z: []int{11}, Isogeny: &Isogeny{ + Chains: &bw6633G1IsogenyChains, XMap: RationalPolynomial{ Num: [][]string{ {"0x172ae0280920320d5154453cfc38fb78e8f3cc1f3e35c38bfe870403008707ab1c9d324595b739426a3f8e03cc03f4d2e6a3b21c833c83d2c147adc9dd927523d2b556276090b4e6217d4125c656bc"}, diff --git a/internal/generator/config/bw6-633_g1_isogeny_chains.go b/internal/generator/config/bw6-633_g1_isogeny_chains.go new file mode 100644 index 0000000000..7ad32b59d6 --- /dev/null +++ b/internal/generator/config/bw6-633_g1_isogeny_chains.go @@ -0,0 +1,125 @@ +// Copyright 2020-2026 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Generated by internal/generator/hash_to_curve/gen_isogeny_chains.py from bw6-633.go (HashE1); +// do not edit by hand. Regenerate with +// python3 internal/generator/hash_to_curve/gen_isogeny_chains.py --polychain-dir /tools \ +// --config internal/generator/config/bw6-633.go --suite HashE1 --var bw6633G1IsogenyChains +// +// Multiplication chains for the isogeny polynomials, preprocessed offline with the +// decoder of "Fast Evaluation of Polynomials with Rational Preprocessing" +// (https://arxiv.org/abs/2609.06022). Each chain evaluates the polynomial with +// floor(n/2)+1 multiplications (+1 for a non-monic leading coefficient). + +package config + +var bw6633G1IsogenyChains = IsogenyChains{ + XNum: &PolyChain{ + Degree: 7, + Leading: []string{"14220658651055190593462350431476014100423797781855070501387299076212419786906222866883269218617143819842155171189996558892871347166774020412535712555525277252132793726480796718290873865908651"}, + Constants: [][]string{ + {"6244073107289937376698167357149329315537337935124375064736357832757174759392572722933114763566694360409328211900432479439614358170476026435732554729618013040638076293689945485812288307571001"}, + {"8307258345920607994548905760930691149984251164233072114719210077751733296910955273002009303700723570515494621102993282307363303616167005403201053357340959281252002996757982534701479423326965"}, + {"14823846744554507541603245436582647218811912214056073031272612148498655272128417422578871417917784521834909889627832214899682231661101633879739414375386923459009381413210232128636865159095705"}, + {"8209004259286395587329994238923163673265742322603230046457981113131871625257272105582385721772654478546695767057785490580170562094918087682684271408335649870137635651368129623886630633399237"}, + {"7886786518056210818058442915240408366812343648433759244704575006999041420989624292898670431392285440625293296567497893202677532815547342094971977266084665121939154938330390378448827599589579"}, + {"8763729315615925354798607323398009510082820036119902545678100563245037868916625482411550938530799649301622258984628596056365672196563557787702682684632421896899711849839369324546588451875788"}, + {"16202294243455612357510465113153093644452502623764015949446576231063417919905849990523994031768024048658338232942081525027653152739876496237959777615879471759112236353295401753786971676362452"}, + }, + Gates: []ChainGate{ + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: 0}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {1, 1}}, Const: 1}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: 2}, + }, + { + Left: LinearForm{Terms: [][2]int{{2, 1}}, Const: 3}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {2, 1}}, Const: 4}, + Right: LinearForm{Terms: [][2]int{{3, 1}}, Const: 5}, + }, + }, + Output: LinearForm{Terms: [][2]int{{1, 1}, {3, 1}, {4, 1}}, Const: 6}, + }, + XDen: nil, // degree < 7: Horner + YNum: &PolyChain{ + Degree: 9, + Leading: []string{"896259999016083440764433850723278199606541877007672510591636496399942423544509844551466547391836795368203057007772892367197773981099202967176620539213777978075596243265596431825055075582478"}, + Constants: [][]string{ + {"15800939888883333688726059595298982400761937611885336072006727485941872523640742609133989636113359161683178576146198520754472442373683245236603976828753702374735593280175133210836865100000030"}, + {"3278141866623827894079617030999928783500702085834393575175521595564646886823172593102824085887882985548891167903370430028277893866205232748200254600773364849087629218380882919027979924365536"}, + {"17500427466117474731386940379742429886784709389430442059528786838204527454098932949485515599781138366210377604548761569409805282327603491187671301390829797039791468754205437161852489870870565"}, + {"737045327363519527857594279726461629627817017080708794547989455392274596113879492367127056607203630873667700379123224240872503585367107850685971867043913099217066320329041742493638612905349"}, + {"2920261564349344743640452146101316002618665738751280925608848509039918588691648149139213117089278318663156332785041967466025648030307076686740436296371572245351266351933896400977246164191940"}, + {"4256149446833554827082324951069889254157256675972839738880911369916785043740850160379319328019590983523801774744037214846633260295235498825767472290289711946411179627731759671613059718378825"}, + {"6776946972293258891203909318074192665477841083685733269349247538360594354933000842020280176714178640272236460396859933068469691919687831630521996998726608382590960533145771493064577875264637"}, + {"15336577283511810699475996719310844896972699021815958061901616722995410772831880968197668882774903285625366712817543917970662516744806786934727286953523480534741710324161979746464342745940838"}, + {"2474919183755747409181296407216307033710423921200961870692868872446326240200413382334682279577948168501077534564544339073582943311472354698999126790314890863448023874249386085177134027272815"}, + }, + Gates: []ChainGate{ + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 0}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {1, 1}}, Const: 1}, + Right: LinearForm{Terms: [][2]int{{0, -1}, {1, 1}}, Const: 2}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {1, 1}, {2, 1}}, Const: 3}, + Right: LinearForm{Terms: [][2]int{{0, -1}, {1, -1}, {2, 1}}, Const: 4}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}, {2, 1}}, Const: 5}, + Right: LinearForm{Terms: [][2]int{{1, -1}, {2, 1}}, Const: 6}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {3, 1}}, Const: 7}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + }, + Output: LinearForm{Terms: [][2]int{{4, 1}, {5, 1}}, Const: 8}, + }, + YDen: &PolyChain{ + Degree: 9, + Constants: [][]string{ + {"15800939888883333688726059595298982400761937611885336072006727485941872523640742609133989636113359161683178576146198520754472442373683245236603976828753702374735593280175133210836865100000030"}, + {"791162581589210424221236817489525242492507476958382483869149658880003164667737481498998005010135375687573438234715880289040259249927141553928536177120595147209311286272002784301035069807442"}, + {"758033992785424353295396237445008043948394914632947559692465449397770845327718072006764702792840416724827386155079712451860096614453095194345439054133466824810256689927555346379572014140890"}, + {"15223321259851598204188441401025544076714489294707839454945237584742249711590217237737658177597939133406326647006720456493010520459518049662710321624836170863296933967444881011263538706976160"}, + {"8739834532555102635484655727601701097286422181708730482460511874926922887754431916839902347506112776653359729466774066065909304399955825903905626168228138964092565467968135374424470462308740"}, + {"13297420837308853332166238553689043773668736566131670756577756228569755108929682752576897730958007684893618363789529892769679669201755031682320637397404057783566114515757461585936136855852781"}, + {"183739578019290540720384996107121413354550001231322734772645196485653059094278294840456605992465446909558421892766661599348437786883319476670411025818861823467704186175964240024724084886420"}, + {"10621795128367400847362295427481964308661937771718183589610457234849361400989355809296198514577391174616697986514817864907303373347032135672255774213097303395105051999233769512290850078445761"}, + {"7337932958312890507661605294664142330339003410880238355933454503453020259180415327054181062100224979839479724187517511964223194399224440200500150134991651065922807615165773714101783691790946"}, + }, + Gates: []ChainGate{ + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 0}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {1, 1}}, Const: 1}, + Right: LinearForm{Terms: [][2]int{{0, -1}, {1, 1}}, Const: 2}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {1, 1}, {2, 1}}, Const: 3}, + Right: LinearForm{Terms: [][2]int{{0, -1}, {1, -1}, {2, 1}}, Const: 4}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}, {2, 1}}, Const: 5}, + Right: LinearForm{Terms: [][2]int{{1, -1}, {2, 1}}, Const: 6}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {3, 1}}, Const: 7}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + }, + Output: LinearForm{Terms: [][2]int{{4, 1}, {5, 1}}, Const: 8}, + }, +} diff --git a/internal/generator/config/bw6-761.go b/internal/generator/config/bw6-761.go index aa2ec6c363..909fd1d17a 100644 --- a/internal/generator/config/bw6-761.go +++ b/internal/generator/config/bw6-761.go @@ -61,6 +61,7 @@ var BW6_761 = Curve{ B: []string{"0xe1c43bfe2767901cf467cf40adfb7afe484d0d477552a8570a117661033c8dce4d56ccf35850bb0a5c646e4433a9b0e43b8701384b604cf95ffbd668698f8bd2f2739baa20c154eb7c88974a36fb5487c4cd8a1eb00205769d93924cfb0ba0"}, Z: []int{11}, Isogeny: &Isogeny{ + Chains: &bw6761G2IsogenyChains, XMap: RationalPolynomial{ Num: [][]string{ diff --git a/internal/generator/config/bw6-761_g2_isogeny_chains.go b/internal/generator/config/bw6-761_g2_isogeny_chains.go new file mode 100644 index 0000000000..bb47d732f2 --- /dev/null +++ b/internal/generator/config/bw6-761_g2_isogeny_chains.go @@ -0,0 +1,608 @@ +// Copyright 2020-2026 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +// Generated by internal/generator/hash_to_curve/gen_isogeny_chains.py from bw6-761.go (HashE2); +// do not edit by hand. Regenerate with +// python3 internal/generator/hash_to_curve/gen_isogeny_chains.py --polychain-dir /tools \ +// --config internal/generator/config/bw6-761.go --suite HashE2 --var bw6761G2IsogenyChains +// +// Multiplication chains for the isogeny polynomials, preprocessed offline with the +// decoder of "Fast Evaluation of Polynomials with Rational Preprocessing" +// (https://arxiv.org/abs/2609.06022). Each chain evaluates the polynomial with +// floor(n/2)+1 multiplications (+1 for a non-monic leading coefficient). + +package config + +var bw6761G2IsogenyChains = IsogenyChains{ + XNum: &PolyChain{ + Degree: 37, + Leading: []string{"6755534270088906550672382581164304179698842717767358251985030237400522010701801248962506086175595679192140430917152399745404733922413294735607775529748834730309024136863373905916693610935330095082139808602643206307516810376763811"}, + Constants: [][]string{ + {"3542346150186179103360243436328306247791018542456199265095520674976410015918512480157093012411335064738542249577033633434939225929425033579288715918005406470233096403244792162337402482978007445450750912514728696672793084091760544"}, + {"6712516042785143669718663784230943122667710031603010508151454776475020327190268804872891024100079022618488191226060845017918318408865764679789310402483381095001632332614611992834649937295175765006984594952279983450417378206465334"}, + {"6045554186467686985488326551263833233927907566800860613977311227467133809171900650247787382437782814380246976194493887498873403213525240815166387163392805150090884588528129145306515350840676562933306722031531624336577200781192616"}, + {"4971670237188996959919371324266224519756475252185187502144191008331992290872641544944460757253492554554123197214151171709008769266888320212390739364986364257388225435840156108934960812516399146868491369375253903762073319309309486"}, + {"4544412127291491405117337341704526867554441890959018770156891042382279875969915840233211918916690759069083249430009850673082211501556522820778023502001089309058987446146638203150853311945614904248571235489626026626169593957361686"}, + {"2935634527643023515955073006969856627848122056500372811766966036823302478547575690689012362011322912471763461944653380846577693047441325820219619731848285966199984699161411636190407261565380256399887243746037345060553044579065902"}, + {"2207098510641959157711422705841161257497393632316329322330619070401002801376218232891724921026993753057364122329029717708642076575096803942503652534402751049022762849254408820115514306616166482713636114400222710641125478315040401"}, + {"1250531778599873482323915371751344722258765617841932948837489862075445093891173705190380267675805294686971528706809401832525729308617711767208844791292129679668743401959193803490872696049389940843464116243556090602614722454119100"}, + {"2301235190506124212372658638874056669185187068107049252520124860605339876397569180325087590376389126915778679694134812011577827489219068472313155232244820727047215961955248443864703283935828684682838449590331433904028980083983025"}, + {"2455597173803742672460589840781783817535423049098991699829988433502855562030941072215422279162957898083633979894232374555692457048156758694117518558369964679246324516769245315036562560941319706916058182464109238906224817783701687"}, + {"3794947978145554126924938404104700228730468128956439265446365447722580005832550138157158889694055018931119181152973048019276446742183280907096615612660974642142143085722614935598722499225675614448835344826577069496506967639723554"}, + {"1360036100810666528924175058688612275233216875886365386534916666072423366208911242437992671103263081903093200105614929498043926991806362343823438408559271839817652849989839305194966633854815365179038807187249249781851789765154544"}, + {"1502352835397451508226120723934931240384735883105313375163232735363122642325551725414596126941212169008013250939172938097952057026003075916918729584097402133386512260375039935492951998276301474596834263611226330812261550508749306"}, + {"3065266239918549280989588349945985041625095133683210109667828949777313532011915737058092905948431552391373397729390825734178294223589737436982181650267426947281772582241102805577684481618687245461012680479789542687848070028725686"}, + {"187909225383254355669271400812721067124647392012392613651973166162249327320005939322541876146994029984885873825614464206574755440562150136859334440269785913273016551997289345359462563776981296048657728338239614281894418264908180"}, + {"2192974931853133582218500831092986015878235496040741418776217545522241586815564099268065567699579526153218594481829062948903731181107817710911228325140856568448249898097988272902753140036078094189538956408713276897223421116603859"}, + {"5451038824468459510470239038548700198413639290265284916625626082936568942577195728527985681471319567495907039848894313335391953459234681945272335197668840773246841384614787366648377308734521159422279339150163802492274180889291404"}, + {"4611305105799262759182989788479944339832459476369931060229729709248707195000117567182323349546700303102798289783717473239330173989721775986964417010926087487884065788882332519189115581819035322956916735220244595302352098189613799"}, + {"4259096044685881939578386827986627616229560309357602263693503102829100336357424802078410635270532864546448688968407989126524936534856975476666058669555724337451850799561161383311968136175456920219096024946152806559701068627487160"}, + {"1853012828266865758975672343090491282166919911320884699472313233013880679912541010724646077335460089727587032040179036861242964619459753955995932453545204883281354210419197716530170257673510482341554408198977808098893936362911627"}, + {"2988114880076262414313920818880505081513586123848436165790646398094514505759761074913173952372702887175256543114718991252123544949739992445103635724920163006517492418798079487097624208343723487913792005407575941238309847132282622"}, + {"6671668084604902185010134327757692711722779577483087294191459836453592816011686138163260072425841502296975437414216581996786253559689979988271468287690131650231753302443022813428302854883447319103411403935383477017828993639033206"}, + {"2960442165547518729353588181815996018102242934851725499562795333468648876568805266600746590218882729863323800054460973723092238949546788543054741345811627603515665376123787461354720182769146109098011913502870700153771152401807401"}, + {"1821536457415476325506927719384926889949984811129518846241953169042731952990792264208730041268107608696882152197615485468474419809140150515345380762143686815718165701201254311335654699175175413055094458585903967730356871421845346"}, + {"1373032382884774753020621761446667543731241046503371324197283400294450404749293656853099487518084859872520777924981148883147746640971770886811041498172592760725076873377508272162763136272562976303734364483683985806055294003993410"}, + {"1810229489953795372504083174203193384438934553639284216620220194651589597693743679485554334415435822712680279948449969452490270662639568312790354803367880732749415592570405461008936561099042734067872369022966657055281828324299487"}, + {"4559430203237751418465527152222313147254675403162332643969013398016857758780825675718011703228949006347465129447681948628913902017385162354158909274912608604714495006651200240445266210438478160620189713875136489739196937326496896"}, + {"3017299673689364110799211656050349966229481649376594009692657480737619861483835538713977379854715930549405470386720979440818481032454742183903562846561692730851537378082611381250422207193874662435604107337954117786588037973006267"}, + {"2829723210237396348871122729460465820798530251299749945384750092849470956016285923583699900671478689478633833729179713870156739151889666005704061260568682145942838728926904888121247936333948437889709465374934456285379591334578059"}, + {"2088479219587584419996939027320554760420852458305474272357994932147727116529543947147760344851713811337523583402060104439357618764509353963001170478734842562919026804044363765608383654050461949263669261492698415577102067080483808"}, + {"6203884416515843467767738485431303059066070248014446453441115569431993703939155107057931054269540002726995863144483986218185960535719016715229236031150073120441329119812111915287695092781878200783939545389052515731297851900935028"}, + {"6669318432160918140720027703378382801564145991827446638471913572289835316987573104118896967510603493162197691253625353840703380434892757876365422264424490546258839936871219397189636310141352792319170482872287448436798063369980660"}, + {"329129526562069197465987980402046475398720265718320826355479362031480255921915973073612339347651481889615247893628038199512004543559537929752343039221386282031894998588823561606206538903607708974402890162200875933493154162642985"}, + {"3949389118515458113705749738127619675566700657624164163631262139276334997263641075480851126384116492073236402525394622129290266130493752722831504517756391397497215246370996141601641014363479613708773733934472656333323864294488227"}, + {"2506440585063585558345444938680743939564828369396045566332286691077373356615014350551115659506229238619283539741079677674294599656447604963939915345599923916652132588184617188851321005324819058911757119374159250829310677842558787"}, + {"3301164979098311316800357497007909549562248174873505667362662358200962234839910357977501132351800038075239947316003729789413264755283547886301368546965734341286832060561855466801240001437327551356454340958680085084884040375721156"}, + {"5972533840084876259930744543764178274885065984733445811650044559348589523272891875794996358038821342284865595032129876174246670114487333122950881488349240145291362181827126845081904936318346672634496329591583149932989573053817360"}, + }, + Gates: []ChainGate{ + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 0}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {1, 1}}, Const: 1}, + Right: LinearForm{Terms: [][2]int{{0, -1}, {1, 1}}, Const: 2}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 2}, {1, 1}, {2, 1}}, Const: 3}, + Right: LinearForm{Terms: [][2]int{{1, 1}, {2, 1}}, Const: 4}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 5}, + Right: LinearForm{Terms: [][2]int{{1, 1}}, Const: 6}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 7}, + Right: LinearForm{Terms: [][2]int{{1, 1}}, Const: 8}, + }, + { + Left: LinearForm{Terms: [][2]int{{2, 1}, {3, 1}, {4, 1}}, Const: 9}, + Right: LinearForm{Terms: [][2]int{{2, -1}, {3, 1}, {4, -1}}, Const: 10}, + }, + { + Left: LinearForm{Terms: [][2]int{{2, 1}, {3, 1}}, Const: 11}, + Right: LinearForm{Terms: [][2]int{{2, -1}, {3, 1}}, Const: 12}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}}, Const: 13}, + Right: LinearForm{Terms: [][2]int{{2, 1}}, Const: 14}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}}, Const: 15}, + Right: LinearForm{Terms: [][2]int{{2, 1}}, Const: 16}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 17}, + Right: LinearForm{Terms: [][2]int{{8, 1}}, Const: 18}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}}, Const: 19}, + Right: LinearForm{Terms: [][2]int{{2, 1}}, Const: 20}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}}, Const: 21}, + Right: LinearForm{Terms: [][2]int{{2, 1}}, Const: 22}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 23}, + Right: LinearForm{Terms: [][2]int{{11, 1}}, Const: 24}, + }, + { + Left: LinearForm{Terms: [][2]int{{3, 1}, {5, 1}, {6, 1}, {9, 1}, {10, 1}}, Const: 25}, + Right: LinearForm{Terms: [][2]int{{3, -1}, {5, 1}, {6, 1}, {9, -1}, {10, -1}}, Const: 26}, + }, + { + Left: LinearForm{Terms: [][2]int{{3, 1}, {7, 1}}, Const: 27}, + Right: LinearForm{Terms: [][2]int{{3, -1}, {7, 1}}, Const: 28}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 29}, + Right: LinearForm{Terms: [][2]int{{1, 1}}, Const: 30}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, -8}, {1, -8}, {2, 1}}, Const: 31}, + Right: LinearForm{Terms: [][2]int{{12, 1}, {13, 1}, {14, 1}}, Const: 32}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, -8}, {1, -8}, {2, 1}}, Const: 33}, + Right: LinearForm{Terms: [][2]int{{15, 1}}, Const: 34}, + }, + { + Left: LinearForm{Terms: [][2]int{{16, 1}, {17, 1}}, Const: 35}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + }, + Output: LinearForm{Terms: [][2]int{{18, 1}, {19, 1}}, Const: 36}, + }, + XDen: &PolyChain{ + Degree: 36, + Constants: [][]string{ + {"4286117714356975802825044495611510088216171100446149009742851486332074218795374096880226352243072180630674363128042759265423209050084788334830549944654808909150940749799759911130775137591165573151528829356221412135730824677337002"}, + {"211194016521612659406478449872742166718647516846042867021102924409414483344221956981985623730220861381650856149289390785899452436245294481840440421911191644590052864481247681701532321006775902724332941347098433231177570554857433"}, + {"4313307447584319740194358066866288238906341275170174998466704513128353693093891278444339062902882254252817197151002991927862842235312390743817474310939653993590643737970415768516798549563824494119215483469453872820785859011285264"}, + {"6154796401448653839994870289195745879119900622139232802738128958511637065850068308665835140387183636794439354549861415843119978630163621314450989982113282564803434657054005028350731202031727048636801730493215447766650746182774699"}, + {"6004661459059913428279804471397399159214805695023777781160836747566737841786598263290334590618583991231419474095204188984419129027929218123671452668569006040344792778424527511438409307935728201477789085975261117996109147226142369"}, + {"2933382712628769684419556864883589786037126776727297120725527907750353912510956972358403933598186759094055790680552726930165326386441570877772680721024356234472425484130678677080958126662241461186881914738224315183106444620101473"}, + {"1906904412381980015756641398937668359515471351731353783683709028351859251879028015591172949717437898769910577086986611953871344192585205914317297662499127265487841290584244626382984115109207882768989655940609495688602573183741726"}, + {"1308743546871796528218796266489254651560906864248730772879942964345954271142286571225438788618125028436765527680224392379696861588275555440009473432397773508900015041618328289836262170076173736134228292633132201769078825384412661"}, + {"5676160889083717342340324052096318111227649919169699468613680282810830771431359556489516104552047451665062468497577106833675242509097954644157286735940042376381010399110535515268528704648194740551229296086080985678393376182744050"}, + {"2626328815685155907062757106993541995809699948133807442801797804179828709605823613537330360234195795027299889099223818001418555884389423605846107417784093145087315163634664185879634256137391558276921330854996872442539220382484585"}, + {"4265571474063385346429841973465593182703607036951190574589833508456727486924964614001277007938769880013767092417784519653276551414992631299515477586534987241610464086122028801745557131685202977107018693725106279039940589444842911"}, + {"6200451395280158043047210191695931925890184543663639734141770860326317085564208645906123898022779575236116415627337585249650208626559063801861994238936851332426602500333029064358419697393764525498068772508038331266323560255475005"}, + {"6155856344890842835209875384871067740992874506539564655504740146424302754822175242665041758464333833835104757884705655130015789872014947651297408155589732886300024115866788462837153200046103773921896253315878934138144924965100595"}, + {"5616104236637239983937785987977955169222579679101822298351792271998507995844783559043120261314294078124128607545643043619707376956818579733276448006752056359699172068074303999646210482959349897409018074463448815904104352777766788"}, + {"3300151543024372868791994383603256725355996184556874131248203412508930993825995151211071166352591385129820815127972893834009012933273385665205636055763339108878300769571422708013858007794236667714293015144420051402332201584438934"}, + {"4275661004443302613262147839239401345655002387751489741172615566754418141570560935363970795196853419070324557195107380017458165612085115045754810720719856071341675369034568637186003912120874976589656813475188074688194571865094235"}, + {"5482207029282964378070257955692801352821518956623298992450154281171347971118551167008026887503865582857136096382424527015053772386617626636905637340242983648847342579509563872857590498309886188848844575283714142193860723090430049"}, + {"3864722257888037012143887890022278049876918210493928069561738786725676878792959978079128247058728002100466060708664373649163117260801736275472202303382290023198518791863537342581499083224741587009108879536790283158570401941089036"}, + {"3234925927278239863802898389091206452336641223338236894015620287602147972919240950171800425725953971883984265636452901463140010221957373600707275217279140694588863979586476823641634245990166999981072925697675516450673932689011979"}, + {"3998168237697903175831141135190310037142474312042797102368246358673342609460044115807025705040186843858020651835019018533028900894202985376546243383080214847614757810687202814397900753373300140471667367831464222157291780411682982"}, + {"1390292041281352503992907078426280608413160375102441638218819389792650575747959246599595870535949274579292481075837566996289875178994108104863964976292727890842278020707313532206744639230322784756193449348184312361226556819237473"}, + {"4483624021135538047038624644338333066869466991072751417430664344340719815147111282459709477046849825242349908922747240242229120084701243294303555403935488557841946730183559022362964877496339219796427278212756085812056072526217178"}, + {"3740240487219216910008829695602099749754698475329857413030597609831949307288064349531738440291514799677193086646539590247979571128415676667731318384382213484618496801699343511967820135509983309416131611406838776543191167411117576"}, + {"393113842666791871135368153854247986103070273927199225272058946504348138317962011912616658687400708483742788701133503041989545835277940665652389619916620022071505510024037949368325091540743729230302426405740641714192276727304182"}, + {"5007878511191093811587972787499849718238062897211205952242029334915747517824477285437250551415997727760183483643475347487971893703723264829457236158495184955672615412306011366277590849760222307478651698888360681561026793050359056"}, + {"3019458929072460534104906444921966162022805674831281235214264209802893898440131331023011004059641187489394921248761394112494524960532821787008856897178937738833750777409383493170267605993151812256096271809405117698591576523922987"}, + {"2552114958720295124743580607740581673312525147231872581815448525895439579115723830838702297134787881680656575909155617838782461939182703839816766277383154370664060512940896067765794067126205537973049843035951404482749820615291955"}, + {"6144829726759372305756325991561817559850105496300720451640564346291074421514763916531754873039457939049583479784957185362303758161733745107147368415489281066301418327029362034146899083526086245679634177430450072815999325464292492"}, + {"5659194858268404304696219145423118573867384633957482403929137208325951120447054456852460644094784708123079281805698917485302910321673288134016427113780481079185162834984486484926427978836577198552300285215034049198279171952805540"}, + {"4751455656767498989955380501238663610615092686537696996721757240074944438005339911578326532572397771763556498676695446019734028844029206226906149009535422959275533394963649064076617210770410424798211155345265360824887454282872990"}, + {"2260946613717330220332321222261086822700807839713261683727916867369009347335097451337585707632888792885126312454531343499754095525312492949276643011226068099704140046634910053746306833836854392639338655383338540332584548723670222"}, + {"1560440400424939736030567002767025808199605844293241655945994553943293044836446964283445790740137882949692553112621830343925635439262064244538421461909431928642521363863478472075645640914224070842417620233908313729990565337586643"}, + {"674515779686827745174766059487691181295853749931389770428121955643128475209451116053525714465050293204421599998527020059889318741569968588652860519670991322666801035804575651369210390600403262723190538872278537096685418601516694"}, + {"3725144130733118648721057631228067409407860075167575104365925451281513552089824342884973045189120222642115703999346549871351080296559109379675152781746002584829264585250520677044483992864709371482455866491971194283137999934608192"}, + {"3403361818558022178083584905783445885776451510606276220912052217143362944239344363157404724026936653108155476986670890090053018338770745315369445281711792290503341852240414926325274928533079678461654147842901552626671784691841705"}, + {"3120949460232568450662401433139046212077794775101614286851121724802288926476268934107743745373424007006465965038540543205301534095435514386869716555431293588827623321464037677530523579378248169865632957694024393310221271865318917"}, + }, + Gates: []ChainGate{ + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 0}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {1, 1}}, Const: 1}, + Right: LinearForm{Terms: [][2]int{{0, -1}, {1, 1}}, Const: 2}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {1, 1}, {2, 1}}, Const: 3}, + Right: LinearForm{Terms: [][2]int{{0, -1}, {1, -1}, {2, 1}}, Const: 4}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}, {2, 1}}, Const: 5}, + Right: LinearForm{Terms: [][2]int{{1, -1}, {2, 1}}, Const: 6}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {1, 1}}, Const: 7}, + Right: LinearForm{Terms: [][2]int{{0, -1}, {1, 1}}, Const: 8}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {1, 1}, {5, 1}}, Const: 9}, + Right: LinearForm{Terms: [][2]int{{0, -1}, {1, -1}, {5, 1}}, Const: 10}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}, {5, 1}}, Const: 11}, + Right: LinearForm{Terms: [][2]int{{1, -1}, {5, 1}}, Const: 12}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 13}, + Right: LinearForm{Terms: [][2]int{{1, 1}}, Const: 14}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 15}, + Right: LinearForm{Terms: [][2]int{{1, 1}}, Const: 16}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {5, 1}, {6, 1}, {8, 1}}, Const: 17}, + Right: LinearForm{Terms: [][2]int{{0, 1}, {5, -1}, {6, 1}, {8, -1}}, Const: 18}, + }, + { + Left: LinearForm{Terms: [][2]int{{5, 1}, {7, 1}}, Const: 19}, + Right: LinearForm{Terms: [][2]int{{5, -1}, {7, 1}}, Const: 20}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 21}, + Right: LinearForm{Terms: [][2]int{{9, 1}, {10, 1}}, Const: 22}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}}, Const: 23}, + Right: LinearForm{Terms: [][2]int{{5, 1}}, Const: 24}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}}, Const: 25}, + Right: LinearForm{Terms: [][2]int{{5, 1}}, Const: 26}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 27}, + Right: LinearForm{Terms: [][2]int{{13, 1}}, Const: 28}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {3, 1}, {11, 1}, {12, 1}}, Const: 29}, + Right: LinearForm{Terms: [][2]int{{0, -1}, {3, -1}, {11, 1}, {12, 1}}, Const: 30}, + }, + { + Left: LinearForm{Terms: [][2]int{{4, 1}, {11, 1}, {12, 1}}, Const: 31}, + Right: LinearForm{Terms: [][2]int{{4, -1}, {11, 1}, {12, 1}}, Const: 32}, + }, + { + Left: LinearForm{Terms: [][2]int{{14, 1}, {15, 1}, {16, 1}}, Const: 33}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + { + Left: LinearForm{Terms: [][2]int{{17, 1}, {18, 1}}, Const: 34}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + }, + Output: LinearForm{Terms: [][2]int{{19, 1}}, Const: 35}, + }, + YNum: &PolyChain{ + Degree: 54, + Leading: []string{"5397733649484578855507634964456289604571069520777825981577598776304593995500528915119395546439976295490171576433058853415619837548592763026956597381223169716241999105931395181522916629480974064371225173530858874754187415613802059"}, + Constants: [][]string{ + {"5401452828964580665261757912140617027556744176069321379593026702527908564399328201877363539480277796831010016499212349622150405168387635272175659839633093657287655232060372919635823101717676161571447026565095155524745584836595332"}, + {"3154557443154516084103348230565262668318059755972348583500205457414490933195956091903657492140273883142029780829715812662964635624834412101194714214495587666486054446154853613519021683716180267622011921047367488070475849642254399"}, + {"3795003116963145907555224873358891443013650053655137632711093151191497425915877173500172258721394581512915658649006857691754211714839909723315017531797566907482645619567217410593534820932298783198724602138089183613858761852541015"}, + {"6184651850919650018216665515185107106355085558295234739620406425953601324871396661508111720972256877723735948797901144848940145268295849803646935289603753815517356045907829486040718857421228266785586891616589330052668868377128065"}, + {"5746992213682611784191872715898198114630555056008783426882060105057859974879390936748208373995248360601700992521687446638239042550517305072692821947598357923016745971510061720372666930561541021314504259937642141114708894223901749"}, + {"6006366321556848691867575447042056745511873792147887313688716668811039704564920940712090177210907798588872532807785961998785349904586423060422160222185263123959548912485657226487520038531740528359332702995965173463916888862767342"}, + {"5374967927812668336303310904811306362413297615677780312895610814661219686127650727104780943969551077977201901932184223287929228846594520958359365858409270237329278379536767169411359776447855544374101401786894420138021437058432632"}, + {"2310895487291692959914650288195677577977187737481569759350590572092588875626709795742324677118915638472969885071971325332812687493096280437666463801002487973189984978660156033491169814144920395357892169462912448778428034400459754"}, + {"4291678276639613354646804722000039520708403360017422373435667700377127105463405415521533488801090950194357818140751731035313452301002916530789694692416971458832050162256229877817436393086317534122079444518200854182514178337658606"}, + {"6267938100035491918957519457373241751918803524004929051307733471372801367043371753587803482000815342792716131761208985171215217921420966668283951188547088725724150892081030178300464715309471639361905344447019543518167284747746622"}, + {"6031819448606193222121022784905918342663395967752858430400889850492737303488140120105133905556062869611348149684936798186042137984843984126795179449199247993129031428432916064050648308089930739412861829045581055188409012558925238"}, + {"3965526912689702734377325402831148275089821408517323498324920439325158124266373180975657128474532516577569090911853395265126815113116667128354558722034964305291139108895299069471240829934239774789316768923668753961872719265744417"}, + {"5369618576878281344083903268688956599303423760975630965973335014813004226729931668400803068442484996675460090590804027061159071500705674339086836878720068859077823786795091153755003534150812341930747507063231045487170667899540498"}, + {"4456098170025907808302598824896825413175518849009756093971873882144737135282012739881589417160900592544417304665095635491485659364377827155542964588688608125364662209001839359529544103468329997042439130700635745168012092933563069"}, + {"1023869951889821698569733225036657995490980851082346404740710499068964485295991169006168657144920484712037911299887516044937103209517387027851175893496107724455120327379805590897381624454270219500475247553704812812508345516055490"}, + {"2542036422276318154293308280834287614121775920941756827604274085878076046890768868966120725310737136653986000048729631370012062246495126808498753239319086925571060086407858081427262201466328907271416178458616004637708821855651399"}, + {"1678294497804474451568390403223390997656967081535285543259402809963616050102902898064473648085830890597753431808641967443489647349794199610960659988028717864527979192963424837311676067506703898824113538650163787669546912190848515"}, + {"1004854377563276774557706611956727166142102763165518353829558711268434225463701986320527996805867991050265081820260007297356785410392784467303967884791058816670120672287145062770401243146147127085478639008330339185834013871522895"}, + {"6799025991586217880780429335486298310731607812752188224531390328494723926861508292379851881070341765585772988427169807806615404187266538352259575287510552374548921929004205080990345593175202521574707070753059953997015242507060832"}, + {"1432504004833183605017165051171246259637014884242960421730022751085595767338385587779149432289757350810658790813782892969581096938900390477556262550204297246594556923275512278589699528870925638010521485490889969560899892795069740"}, + {"3571603939208999502434534851220891650059344370654560817794502793980270762979287594402613454886504601525182529744761245714856181473003337557556831298556416551287085817970519274198697565109341115630426915839854137354106921207382790"}, + {"1414306927190975807285348402441486330596575784053702193328880611429203544130341642815874489947078296776046607964515697915071598460821468396677881783179434419450917285789054506251238604978342330706885797771261124480680206974681860"}, + {"4652555075630776364380194929844402341313121209227834769473520311670460280932073210027660404075167337493725898900159538137336053613565234994079885196244859077604767033466900833022314411776749001082969481675122295724941016908825306"}, + {"4036267391661776134958676190481203392950801869517081740955494069851577331130113699008963545370916962616713331570500930414392775618964250516188517827613151073207492985779898022148813212767298932625284163510085466905386521928890716"}, + {"6490836534864828414551138327865117853822359862097912447630407630410687322998484952196655952843546835862132027813013405620722175097748707904558823778329201302685317402824626492093574082238104555194696422175252922869138505990330633"}, + {"384899139855704577958755552736380981497647695589160262311415474000357320307278247631626447674999526605913011481733345472804008385714642475826671005278186876311355108699210441255904316994745811861234065069458165732809447725569394"}, + {"5585381327719736032122705474071754621717931196818469965191608466495653401884461886861220733394792782086795201164339387055726577791916400798610987089053853716718498315574393616201424963397242093648918233197356400056753216402744907"}, + {"6538004757591456827255716895548373636051604378049253987735826447287641408864646659864078724371468743393234234777592004418185484835849422338125056860483182897191794605906919390328072511323569012581351612329704967108182883679801288"}, + {"5483216450447565483805846840348583370397243176030280375783394074014480909202410543096652889741473257536095913799368129643901176742496714794910784280058034565357323262384630525332455791412399564768261920025659127172073848512378120"}, + {"4394423328660490340628148426646384325369985032552080544568993919429706378284387125117316250161169116643966451678287507375233273323926431217684872033105460682152097118842071593637985950850461036055890173153009552562759279959176259"}, + {"3579804377874140460124377726531542314097157006093518484813125549914132877478104891225431182409336352908043464267898394121862404994699195406021838161000138600636127685861205088131396944581345250866347139667838882819293532149906676"}, + {"1732320436777354876548721332371809377342292008136412674975557571308358631780302008453098965198878916887557731029171983387636204123693884457369317614357812547905282952614839939108238325826843298432106328930254596795279943787691304"}, + {"6432815377259038201672928052965584258652384232453469500234148632261196273372813975062714689186164592825336609061818356985293635728759708174731082938785354354544671065937881298911956125786485726946503879296898253723793588190576580"}, + {"4954475852972944272396648653676802634022305394532411462706820672954309237098914922312956214262896436053906013952797425786945850727778682888736750118539977757664640231128755898064563279541786826721876415130321208093511318596782094"}, + {"1497345583621430840259000803081587662087753488394768574213602800681573653096577126438826946386535713717098780205339091418468754743423335585141688449498810643515052938127679563148278575718953329545661192668905966989639945222580999"}, + {"6641398889723885440091833795202368136580239430346308920425929039648831638399489751324602074782078737296947765517655531602195516787650993806195565901201215630047640017597551859820404198348794850788642690784177868382290572754491512"}, + {"5828920796852966654318166388110575797980347645253884235146610325982525540724047649742107915379385291934448591930164783464112694133577658462212371961274017019924551977075403152338769114251607605077501946413477491039191529454447758"}, + {"503283831258119659891620466346574863834883591419404839597772798673565827512216123793151332143186040151687271149575858768490252771126681078968513482768068167032426201445079487792701944146336472799715294008918530796025044046569659"}, + {"3427351962202692363363174712882415696108488635277882376836335268603325285953293005783529268616865062084993027335418491826501181655318829817291738862861203385644859825158772202416351084279363374140155860903800180963321944568975233"}, + {"6230908366773057672491763646352134125920064522353653544424203818684537424189169281081125331555441165472271024403021391642946530555858148014112885397369872221947668896943786191534579768881931732472081493618237010590659539666019980"}, + {"2522287244348261674184132210370944876124372651931049356521634592302541426941915631588399152564795849482214304894591972630490725778413031066791520945000084042124779321639155901255546177417649922338627232513719587952671078529016833"}, + {"6038571565111037804383117733520810364198119602140560601367430472649858740958604970339260439074124578753758942650810296600308181080837045149392231611584038435537046702027578272690327813903242784707829230516098573887658320908964457"}, + {"2489942943037700475633063946042861040813500917458722780258531247363971666573123303053527278803017073740636281382205893113210104173532056349155800235975612103247169093753244782457782870079851244122521599063040975295601792396767264"}, + {"6526911189088642788628842311846219550521071572586030852270874236243356156310838154015699646933873598587356353121891434446448469766974312417573938484852115934999580261018755506931342425951507803353928654559279768405819171736636708"}, + {"6377221579989233488506540784808979289971696249086696587025009475152739255122152019821718718390522731291650152060240112219972096732482839555223577718961426374230308548954640037858068574739090381391958087162828247012735299177232332"}, + {"5897780063457881467840762425199722752160518625089935473448355750592060630817177206082929346698987860713500783662757721762393793790726166047345112253278229400876426941777903052484354339350791569674561577826417997014308843032491882"}, + {"5027632199992716526143880635531966121339815563085218577056325575217226120851788753522703059653450938426914408345475068645139850080130796163990214544820054683757078303665380935314364432668667462549438684581600102223896694742064476"}, + {"5325415936904054301004082511632761165409380288852478321241185670071229565912433993433703720439069171053855573411070453775902829316308225268181934432923278912732362498998647784701874146258358449022997296518628319131647025910896465"}, + {"3155116935315148314018777285469584135609723328309301233228721951006123616832943650011635741334966816894901927726406394669645915190026077655844371998477657286586121519249469970917402050741574551562344590293425156817531040991894980"}, + {"1220672231109691577067973271126758087684327234045240584128883505605926588510110281196165153380231914353812073008504792728270355008819369483911245000046100137121025901552366940216541486925450757244375695952749368943375427692217495"}, + {"5143005511047652750146932575524494411056187425247608786339855123114818107844335992155315384129042794566728100346340702104388985777353793571550883011952794241885709465587390225615230953193747833018422746965673071394470533627043707"}, + {"487860581589246050115544061500756584200463461634202390135530688132140174689708477377947688136716537617154028552781783219975344683671543291500431620704129085777694796747841388832788392540038624568464671039014222339293792418746811"}, + {"2932303908388567283392189140209451559243672595624010495284437349133108864152030344101700521293331892697898679027238446019794866476732867107733540282141511841068164161348156484687032724020301735647644110964225695661557295964623040"}, + {"6772157075794520740143884027414871652374937501656382265887865703113777055992620585834979629308414544930302955302521997820102101627952592670837450243312916624500569253647581609284076620627013275767610208803026896850394234759729995"}, + }, + Gates: []ChainGate{ + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 0}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {1, 1}}, Const: 1}, + Right: LinearForm{Terms: [][2]int{{0, -1}, {1, 1}}, Const: 2}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 2}, {1, 1}, {2, 1}}, Const: 3}, + Right: LinearForm{Terms: [][2]int{{1, 1}, {2, 1}}, Const: 4}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 5}, + Right: LinearForm{Terms: [][2]int{{1, 1}}, Const: 6}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 7}, + Right: LinearForm{Terms: [][2]int{{1, 1}}, Const: 8}, + }, + { + Left: LinearForm{Terms: [][2]int{{2, 1}, {3, 1}, {4, 1}}, Const: 9}, + Right: LinearForm{Terms: [][2]int{{2, -1}, {3, 1}, {4, -1}}, Const: 10}, + }, + { + Left: LinearForm{Terms: [][2]int{{2, 1}, {3, 1}}, Const: 11}, + Right: LinearForm{Terms: [][2]int{{2, -1}, {3, 1}}, Const: 12}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}}, Const: 13}, + Right: LinearForm{Terms: [][2]int{{2, 1}}, Const: 14}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}}, Const: 15}, + Right: LinearForm{Terms: [][2]int{{2, 1}}, Const: 16}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 17}, + Right: LinearForm{Terms: [][2]int{{8, 1}}, Const: 18}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 19}, + Right: LinearForm{Terms: [][2]int{{1, 1}}, Const: 20}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 21}, + Right: LinearForm{Terms: [][2]int{{1, 1}}, Const: 22}, + }, + { + Left: LinearForm{Terms: [][2]int{{2, 1}, {3, 1}, {5, 1}, {6, 1}, {9, 1}, {10, 1}, {11, 1}}, Const: 23}, + Right: LinearForm{Terms: [][2]int{{2, -1}, {3, 1}, {5, 1}, {6, 1}, {9, 1}, {10, 1}, {11, -1}}, Const: 24}, + }, + { + Left: LinearForm{Terms: [][2]int{{2, 1}, {3, 1}, {7, 1}}, Const: 25}, + Right: LinearForm{Terms: [][2]int{{2, -1}, {3, 1}, {7, 1}}, Const: 26}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 27}, + Right: LinearForm{Terms: [][2]int{{1, 1}}, Const: 28}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 29}, + Right: LinearForm{Terms: [][2]int{{1, 1}}, Const: 30}, + }, + { + Left: LinearForm{Terms: [][2]int{{2, 1}}, Const: 31}, + Right: LinearForm{Terms: [][2]int{{3, 1}, {15, 1}}, Const: 32}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}}, Const: 33}, + Right: LinearForm{Terms: [][2]int{{16, 1}, {17, 1}}, Const: 34}, + }, + { + Left: LinearForm{Terms: [][2]int{{2, 1}}, Const: 35}, + Right: LinearForm{Terms: [][2]int{{3, 1}}, Const: 36}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}}, Const: 37}, + Right: LinearForm{Terms: [][2]int{{19, 1}}, Const: 38}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 39}, + Right: LinearForm{Terms: [][2]int{{18, 1}}, Const: 40}, + }, + { + Left: LinearForm{Terms: [][2]int{{3, -2}, {5, 1}, {6, 1}, {9, -2}, {10, -2}}, Const: 41}, + Right: LinearForm{Terms: [][2]int{{12, 1}, {13, 1}}, Const: 42}, + }, + { + Left: LinearForm{Terms: [][2]int{{3, -2}, {7, 1}}, Const: 43}, + Right: LinearForm{Terms: [][2]int{{14, 1}}, Const: 44}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 45}, + Right: LinearForm{Terms: [][2]int{{1, 1}}, Const: 46}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, -12}, {1, -12}, {2, 1}}, Const: 47}, + Right: LinearForm{Terms: [][2]int{{20, 1}, {21, 1}, {22, 1}}, Const: 48}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, -12}, {1, -12}, {2, 1}}, Const: 49}, + Right: LinearForm{Terms: [][2]int{{23, 1}}, Const: 50}, + }, + { + Left: LinearForm{Terms: [][2]int{{24, 1}, {25, 1}}, Const: 51}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + { + Left: LinearForm{Terms: [][2]int{{26, 1}, {27, 1}}, Const: 52}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + }, + Output: LinearForm{Terms: [][2]int{{28, 1}}, Const: 53}, + }, + YDen: &PolyChain{ + Degree: 54, + Constants: [][]string{ + {"5401452828964580665261757912140617027556744176069321379593026702527908564399328201877363539480277796831010016499212349622150405168387635272175659839633093657287655232060372919635823101717676161571447026565095155524745584836595332"}, + {"6444801952636850972269341861085664770234307524633331486470829790828121594846333106059968093496715272104173789441128526406578370431364339993985313922727657690024402604987976352757800003944587276329162375515710952754684206946995127"}, + {"709699675098685943064180129921671734340639672697230725691297211117767248717241518223719877476985147918526324008632832966002176256668662645204607486508215925531325448985711272280768012036117502599605438426728788195751378442809290"}, + {"6232558687649678534539118990636837310965441869144885421837563270913595328371343012854033823179936961981798155960307809519584421740727005858363450179517568552006809015209827783079148952198133043082303132018865908370690376627608629"}, + {"5140717187986140918148567390747084063331843083516121549040809880563422427714806833071204027265121377165940797884544632835968329521702339830658587699894918182236480927660144543578609035135539985587139532242467055648272731782085854"}, + {"1026168901005185333873566960518243400384585607076583137436830321127042274667095354734834193159546012317300965577694972792846775864085553178671497876033384624338318557769048691606150349013148506050161323755416462897377194791965447"}, + {"1341870491294024931898127742882429911979221590656353160237515306219563104686109853473988562924383664055049534904804506493058788840844478494711716223037313704704667125700060084744411674626151932517782360692563325106133156516588943"}, + {"4426905718844159116706052347075371571670981339750727277060684324543331804520830078123050597066289178818006156483745687288179890083023979550394801212956115896317592633809883006097167725667286155384828418688717116510736444392604026"}, + {"511338118764372827274246386058461991666133072534413151594626808122881118206177256606778283629757995469799752212214030641911494178505677655022338943138123304332343923348725967073529331600739051667631738149305223282000841731685224"}, + {"5977193893156306222869171401148223587062856890430709250893026193656882873527843539648194634813147337569140857150595327481603153582298979485505804790586397576592654776681300354473050032447649250969055910330536861750094287202673229"}, + {"4154651575761918558407198891988295553518206284709636949401944449745116448085948115276628812653299429748173452126172001776340383952869361745922120506642251830768933618838428842268010450400339025045324801970668920257122010612270738"}, + {"4724912712182557437654895992137275138511482533912217849740743236984032334409839409864600463348938246718562506901057513156287291592859687019984295989842672397788896659618688941218961984958822574079589571420717036413323774588854662"}, + {"4738537279459334535874696554636420857272274764868308236835713811478342529603842230546622635120999995317117312343667881472664010087850402740413863058877953313261096777395356028418162429632323730263567642803223213032976120966947813"}, + {"6271913305126306895660375031694659143869599546908206561346186966684095590788670832616176839831503516213776598382221990128324534028698297642667112178893972038351886823010327552109147368974903784834537560978782357119810561075111783"}, + {"4582486288144216644298018092964098347032350981175526072849623100444960278947478223445168129019639958909445924265481125384046210722736477049601774545098372608205890055569625298513679246656207896942428064827456298027344395529515355"}, + {"6166672924237874130943854005309194175269506151042930523628245657525043269906176617218767207740257027238504419929397402284701360641182072919943304739024061013280195089086258605314528497976780823256044233446032456057523818560681638"}, + {"6856702182360296511026764446235524364766560426890096250346205327018150991926877159025955179617568506794533344366370063867934345786061792451759581730174610589303353249899008922274971906570711465575852370290288256372683395398419832"}, + {"6208422384751831089053603188905127001539239734853978243448674535066097295352400430198174098244580295686305913381132593136555880284197289030335747933056982211899516058955204711326508713627792625785323010175274076718197740813596980"}, + {"4703018986491354164374947067623678290826052635673258587733937739705591931440073124130467616044987532457575283231197643470386356329661350983475690078343645588390362247316293689391474703903201500192084593925881328771596555522146894"}, + {"2079274920332657171110837952892334721271461952764347463294059133769316095665308542659221256981740689649408198096529961083904285901479515475651905221561824363611039622602726338721650509513053865459838436556890005849764619494085753"}, + {"3759496633387981073248015355815224728969045276009505418862982390273359950048910263844240045711442946448888552836062629796473863685689475730719586840586128477002382491148811882761948970042501641123298371449694855161720220639276200"}, + {"5093788344462710538942267863910604173627200937405367156316068691703168875621999827925681675204666980741478479748535302031314462752684772787997178102345401329030018611379975254451945035605417475471314192254247630554742325562743879"}, + {"535948666040518129771054449603407948239764040067351648828163564574217883865817009007434258294809438798390712803055652133257431138394757312835106804148621278902157057690973571781509140473747572090647942694352123748934705292095636"}, + {"5887916980246838528726681867797929986911001905292997446107047732377055495019776935687409406848082419435009395206480339214261572665592774603355143952637537636347167213267153331559621253817150406214295639956384165530600493203093483"}, + {"567148810164745130242556933699564538099402172533008259132871359133351982289538455876264554485414418380230676461162342487623218826159328342282694344024153151953111123119982445931267415621980803325469050951238115423082514852904923"}, + {"3931135022046352036375448154946876625319860253662727589691427518502077328078532882649428352701176070955278482226735424408140022620051995563419523212609739791418012477660470505093919503850782418805324651633123576359533701279491698"}, + {"857799230893463486839113541113972293404742103882060950167046606747827607711419382181109042398963468197410427057062909505405576394556255747907224952416614127818912834170720966980901879582515037983881336949915119771446555323848630"}, + {"2526759052577644991318122454894739475942709621296022970145777094127790945642615769786629541105572174061036257171738628183755567074399470257641354905470702500378097290701765376416197277890344447120409250103098107078564075121984651"}, + {"5799246074295069081301208042320132107103069462257697630116262883866081159625637612325654964230113601601033367644344531920012687626067766082174324802251589550790943541539587738111036114760459357565108155557245788939913958805219269"}, + {"4546185090452835943907221095456477269081672499472042979733287276485143654184326315053246664052171428539418339236319807728522190564657574985261627221276088030153172315514675233134247690112759050215545572302968058951148779777347313"}, + {"674359831925832290058743603281184617313495308850817677694063625839513709893082082139275962424685736139671774004321078219248721563399744757646004891127849811037101762453048334606511462370843851859092649513301784433116878113236806"}, + {"5783082006789164943917125346880597828018994310597825450528396647287691163227111234250371347566062844764321738020285842172244766734772849204462684294631693225207402557418136247987849186798796752995007680535405580914150749455705128"}, + {"394896235194503397822448309662878662079984091689210887037754574349414957027840086782568025240325850681753875918570546117937469302404377786168847775380946083062278968974145616278415024989138609789908624548367106309347277770062376"}, + {"5935373218538284502426548649177490183069144614132225277032296436630429742687602956181265774298900191622405562811437747027410342020421728671836380883480645239049121219161592385065723947660550467313808653596186217646374552459123238"}, + {"5361818154461299926468930111773689875152038426504296971672217156420391708337900102943320356441017731552079938575988547922214260179381352133697419712837789037231703883899760618697468102199068992039387651038115954397101048000715717"}, + {"6672039671072787493553168948103041327096340084755945121388826001545260145819095132147638367394206064758251132202050300208575500924595366305805308955665115161606507578654862023546153076059014939280415906515322341065341197307896285"}, + {"5264657195665551912362734932328882345689772686131009541487311905584273481004480048101739522021616114279999495762626919390023965304844369015571187389605318947978658630218770011283194011383866425012999973455777627227111961938659921"}, + {"580114249964389337461768282174417137838394103174648375253488358587669723463795411834917758186227059225099804982523938543919615109922436943223794585731427070321480497267307389857187653053098907269051985991415270229898154123191402"}, + {"2883188020938380690991482975923814023232918649113945565910262233730857985159636638174462883813917815249286644675372102588446149568104963010835010878972532136430491419687159370090979965649405916121796837277825590038243981850112181"}, + {"4636558313455689500011688199331693572443857413003936646664834517409368693722617378215903340338050456239912862691665174326085592545814888257323301491050156426581812525723514541157904587804885150282381609765356156416903164460241281"}, + {"6890742831619250983350874533879361221901834801867617255409662790325962642515717329258091492266785810161773180107935884858444953497459883496848627694094814294684188327500264865675779857062153876008282467548508893674877040725559786"}, + {"1443361879294566835107446970832265140040870355414492612845195442464924176673045071385847746189149189472238633948970427177833767897357705961563571513696716660395852094119196489612735188129205521884508702032572453147698711414009361"}, + {"2640776646754197614232142039446033842401092870905514107189646825907249208605307962960888594501785087598280137209847229105967668433383236114373033268753938020793870310650074508946430832411781952358387977265699339845355191498457801"}, + {"4629951385683425531323940212053120902053064459762750075747244018044546086841023356276533676115458281849250559100344267997401415557443235446054903629270597242265874652413974896340959398093579840941548479882166058468076172838761065"}, + {"6818644242024976580703434411556268241237918517079206302509652758745591513956061875295888483416103092605682497931919859649660529386843641239533341315790866174089201919917229921885798313727120818606669420992869015825174146876684372"}, + {"6555367643043122948840764611092263978321573346699114690068545083400771447192628055670197006503364179361274645314441681834013336949217112112112341747659789523381859598101732822560881602322592945537879833742555017554339197947109508"}, + {"42134460007869018987384930255973935704534922168302461354601544835837531025697448105741619386484132203146209304134845504056945986817746350962200514610976215175770892322113428950160824643804163401750005134730007125285718939613182"}, + {"3748707976746429464467406644632379753811576955646870870445490228698749975247962879378330872059854483074786573756413272138469933806705734672023945592456370819754929356776246497926701564786575442682372463696412375641083968888682253"}, + {"4755851653067287092224879086843360937303587986907234995757886306498188940027903813155036837900798486657075527681704270696547853516866418323538983710331555134232732229705790193418913146926486391004234299568754038238588861521036766"}, + {"1858994888578080220471656008831070323521196504626103174469635005739349626811887203387332612858005337709625247200268731579985637887313677738824392415786910542226156207953422655292587528878023706941411690024594012666400962279752050"}, + {"4905187813644156340164969274172904602488166220069166406161792474961147978361739229861683231895195399857602302925792416843815290471475588730434363721764996671835671089352900763632360629887186851306240864235933826507920301730326156"}, + {"4282433107618697961406646578749261437927714893468480014632462350534598556349564355839994249807589643997034718892572951194747579072354243375858465781423774251878141136003720410831275963011808481658977680922357025639972179990242259"}, + {"2279518369887093145766757104527124651848331864697509298112576202737410892308187191215465121000985015154709719856843216192163555010394964236105863130196934946979313860198514016590433474832637550859516189825449396600570787601520190"}, + {"4248598296291302901168995093789026529855661241999114623673189121023336682566495556944394419825873578452368066331229634465815489452673100664977987432953159247597407532622080243674058702191246004787205008355147975109967675411158998"}, + }, + Gates: []ChainGate{ + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 0}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}, {1, 1}}, Const: 1}, + Right: LinearForm{Terms: [][2]int{{0, -1}, {1, 1}}, Const: 2}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 2}, {1, 1}, {2, 1}}, Const: 3}, + Right: LinearForm{Terms: [][2]int{{1, 1}, {2, 1}}, Const: 4}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 5}, + Right: LinearForm{Terms: [][2]int{{1, 1}}, Const: 6}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 7}, + Right: LinearForm{Terms: [][2]int{{1, 1}}, Const: 8}, + }, + { + Left: LinearForm{Terms: [][2]int{{2, 1}, {3, 1}, {4, 1}}, Const: 9}, + Right: LinearForm{Terms: [][2]int{{2, -1}, {3, 1}, {4, -1}}, Const: 10}, + }, + { + Left: LinearForm{Terms: [][2]int{{2, 1}, {3, 1}}, Const: 11}, + Right: LinearForm{Terms: [][2]int{{2, -1}, {3, 1}}, Const: 12}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}}, Const: 13}, + Right: LinearForm{Terms: [][2]int{{2, 1}}, Const: 14}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}}, Const: 15}, + Right: LinearForm{Terms: [][2]int{{2, 1}}, Const: 16}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 17}, + Right: LinearForm{Terms: [][2]int{{8, 1}}, Const: 18}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 19}, + Right: LinearForm{Terms: [][2]int{{1, 1}}, Const: 20}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 21}, + Right: LinearForm{Terms: [][2]int{{1, 1}}, Const: 22}, + }, + { + Left: LinearForm{Terms: [][2]int{{2, 1}, {3, 1}, {5, 1}, {6, 1}, {9, 1}, {10, 1}, {11, 1}}, Const: 23}, + Right: LinearForm{Terms: [][2]int{{2, -1}, {3, 1}, {5, 1}, {6, 1}, {9, 1}, {10, 1}, {11, -1}}, Const: 24}, + }, + { + Left: LinearForm{Terms: [][2]int{{2, 1}, {3, 1}, {7, 1}}, Const: 25}, + Right: LinearForm{Terms: [][2]int{{2, -1}, {3, 1}, {7, 1}}, Const: 26}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 27}, + Right: LinearForm{Terms: [][2]int{{1, 1}}, Const: 28}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 29}, + Right: LinearForm{Terms: [][2]int{{1, 1}}, Const: 30}, + }, + { + Left: LinearForm{Terms: [][2]int{{2, 1}}, Const: 31}, + Right: LinearForm{Terms: [][2]int{{3, 1}, {15, 1}}, Const: 32}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}}, Const: 33}, + Right: LinearForm{Terms: [][2]int{{16, 1}, {17, 1}}, Const: 34}, + }, + { + Left: LinearForm{Terms: [][2]int{{2, 1}}, Const: 35}, + Right: LinearForm{Terms: [][2]int{{3, 1}}, Const: 36}, + }, + { + Left: LinearForm{Terms: [][2]int{{1, 1}}, Const: 37}, + Right: LinearForm{Terms: [][2]int{{19, 1}}, Const: 38}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 39}, + Right: LinearForm{Terms: [][2]int{{18, 1}}, Const: 40}, + }, + { + Left: LinearForm{Terms: [][2]int{{3, -2}, {5, 1}, {6, 1}, {9, -2}, {10, -2}}, Const: 41}, + Right: LinearForm{Terms: [][2]int{{12, 1}, {13, 1}}, Const: 42}, + }, + { + Left: LinearForm{Terms: [][2]int{{3, -2}, {7, 1}}, Const: 43}, + Right: LinearForm{Terms: [][2]int{{14, 1}}, Const: 44}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, 1}}, Const: 45}, + Right: LinearForm{Terms: [][2]int{{1, 1}}, Const: 46}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, -12}, {1, -12}, {2, 1}}, Const: 47}, + Right: LinearForm{Terms: [][2]int{{20, 1}, {21, 1}, {22, 1}}, Const: 48}, + }, + { + Left: LinearForm{Terms: [][2]int{{0, -12}, {1, -12}, {2, 1}}, Const: 49}, + Right: LinearForm{Terms: [][2]int{{23, 1}}, Const: 50}, + }, + { + Left: LinearForm{Terms: [][2]int{{24, 1}, {25, 1}}, Const: 51}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + { + Left: LinearForm{Terms: [][2]int{{26, 1}, {27, 1}}, Const: 52}, + Right: LinearForm{Terms: [][2]int{{0, 1}}, Const: -1}, + }, + }, + Output: LinearForm{Terms: [][2]int{{28, 1}}, Const: 53}, + }, +} diff --git a/internal/generator/config/hash_to_curve.go b/internal/generator/config/hash_to_curve.go index b2621507a3..56464678a2 100644 --- a/internal/generator/config/hash_to_curve.go +++ b/internal/generator/config/hash_to_curve.go @@ -1,6 +1,7 @@ package config import ( + "fmt" "math/big" field "github.com/consensys/gnark-crypto/internal/generator/field/config" @@ -18,6 +19,47 @@ type Isogeny struct { //Isogeny to original curve XMap RationalPolynomial YMap RationalPolynomial // The y map is also evaluated on x. The result is multiplied by y. + + // Chains holds optional preprocessed multiplication chains for the four maps + // (see PolyChain). Maps without a chain are evaluated with Horner's rule. + Chains *IsogenyChains +} + +// PolyChain is a straight-line multiplication chain evaluating one isogeny polynomial +// with floor(n/2)+1 multiplications (+1 when the leading coefficient is not 1) instead +// of Horner's n-1 (+1). It is produced offline from the polynomial's coefficients by +// internal/generator/hash_to_curve/gen_isogeny_chains.py, the decoder of +// +// T. D. Ahle, "Fast Evaluation of Polynomials with Rational Preprocessing", +// https://arxiv.org/abs/2609.06022 +// +// Wire 0 is the input x and the output of gate i (0-based) is wire i+1. Every gate +// multiplies two linear forms in the wires; the polynomial is the output linear form, +// times Leading when the polynomial is not monic. +type PolyChain struct { + Degree int + Leading []string // leading coefficient (one string per coordinate); nil when monic + Constants [][]string // field constants referenced by LinearForm.Const + Gates []ChainGate + Output LinearForm +} + +// ChainGate is the product of two linear forms. +type ChainGate struct { + Left, Right LinearForm +} + +// LinearForm is Σ coeff·wire + Constants[Const] (no constant when Const < 0). +// The integer coefficients are small (|coeff| ≤ 64) and are realised by doublings +// and additions in the generated code. +type LinearForm struct { + Terms [][2]int // {wire, coefficient} + Const int +} + +// IsogenyChains are the chains of the four isogeny maps; a nil entry means Horner. +type IsogenyChains struct { + XNum, XDen, YNum, YDen *PolyChain } type RationalPolynomial struct { @@ -182,7 +224,7 @@ func newIsogenousCurveInfoOptional(isogenousCurve *Isogeny) *IsogenyInfo { if isogenousCurve == nil { return nil } - return &IsogenyInfo{ + info := &IsogenyInfo{ XMap: RationalPolynomialInfo{ stringMatrixToIntMatrix(isogenousCurve.XMap.Num), stringMatrixToIntMatrix(isogenousCurve.XMap.Den), @@ -191,7 +233,65 @@ func newIsogenousCurveInfoOptional(isogenousCurve *Isogeny) *IsogenyInfo { stringMatrixToIntMatrix(isogenousCurve.YMap.Num), stringMatrixToIntMatrix(isogenousCurve.YMap.Den), }, + Chains: &IsogenyChainsInfo{}, + } + if c := isogenousCurve.Chains; c != nil { + info.Chains.XNum = newPolyChainInfo(c.XNum, len(isogenousCurve.XMap.Num)-1) + info.Chains.XDen = newPolyChainInfo(c.XDen, len(isogenousCurve.XMap.Den)) + info.Chains.YNum = newPolyChainInfo(c.YNum, len(isogenousCurve.YMap.Num)-1) + info.Chains.YDen = newPolyChainInfo(c.YDen, len(isogenousCurve.YMap.Den)) + } + return info +} + +func newPolyChainInfo(c *PolyChain, degree int) *PolyChainInfo { + if c == nil { + return nil } + if c.Degree != degree { + panic(fmt.Sprintf("isogeny chain of degree %d for a polynomial of degree %d", c.Degree, degree)) + } + info := &PolyChainInfo{ + Degree: c.Degree, + Constants: stringMatrixToIntMatrix(c.Constants), + Gates: c.Gates, + Output: c.Output, + } + if c.Leading != nil { + info.Leading = field.NewElement(c.Leading) + } + return info +} + +// PolyChainInfo is PolyChain with the constants parsed into field elements. +type PolyChainInfo struct { + Degree int + Leading field.Element // nil when monic + Constants []field.Element + Gates []ChainGate + Output LinearForm +} + +// Multiplications is the number of field multiplications of the chain. +func (c *PolyChainInfo) Multiplications() int { + if c.Leading != nil { + return len(c.Gates) + 1 + } + return len(c.Gates) +} + +// HornerMultiplications is the number of field multiplications Horner's rule uses +// for the same polynomial. +func (c *PolyChainInfo) HornerMultiplications() int { + if c.Leading != nil { + return c.Degree + } + return c.Degree - 1 +} + +// IsogenyChainsInfo mirrors IsogenyChains; a nil entry means Horner. +type IsogenyChainsInfo struct { + XNum, XDen, YNum, YDen *PolyChainInfo } // computeSarkarBlockSizes computes optimal block sizes for Sarkar's algorithm. @@ -216,8 +316,9 @@ func computeSarkarBlockSizes(e int) (int, []int) { } type IsogenyInfo struct { - XMap RationalPolynomialInfo - YMap RationalPolynomialInfo // The y map is also evaluated on x. The result is multiplied by y. + XMap RationalPolynomialInfo + YMap RationalPolynomialInfo // The y map is also evaluated on x. The result is multiplied by y. + Chains *IsogenyChainsInfo // never nil; its entries are nil for maps evaluated with Horner } type RationalPolynomialInfo struct { diff --git a/internal/generator/hash_to_curve/chain.go b/internal/generator/hash_to_curve/chain.go new file mode 100644 index 0000000000..b4dba811db --- /dev/null +++ b/internal/generator/hash_to_curve/chain.go @@ -0,0 +1,199 @@ +// Copyright 2020-2026 Consensys Software Inc. +// Licensed under the Apache License, Version 2.0. See the LICENSE file for details. + +package hash_to_curve + +import ( + "fmt" + "sort" + "strconv" + "strings" + + "github.com/consensys/gnark-crypto/internal/generator/config" +) + +// chainCode returns the body of a Go function +// +// func f(dst *T, x *T[, y *T]) +// +// that evaluates the polynomial described by the multiplication chain c at x and +// stores the result in dst (multiplied by y when mulBy == "y"). The code is straight +// line: no branches, no divisions, and every multiplication of the chain is a field +// Mul (or Square when both factors coincide). The small integer coefficients of the +// linear forms are realised with Double/Add/Sub. The result is accumulated in locals +// so dst may alias x or y, as it does in the isogeny map. +// +// constsVar names the array holding c.Constants and leadVar the leading coefficient +// (used only when the polynomial is not monic). +func chainCode(c *config.PolyChainInfo, coordType, constsVar, leadVar, mulBy string) string { + e := &chainEmitter{constsVar: constsVar} + + for i, g := range c.Gates { + out := chainVar{name: fmt.Sprintf("w[%d]", i), addr: fmt.Sprintf("&w[%d]", i)} + if sameForm(g.Left, g.Right) { + src := e.linear(g.Left, out) + e.emit("%s.Square(%s)", out.name, src) + continue + } + l := e.linear(g.Left, out) + r := e.linear(g.Right, chainVar{name: "r", addr: "&r"}) + e.emit("%s.Mul(%s, %s)", out.name, l, r) + } + + res := e.linear(c.Output, chainVar{name: "p", addr: "&p"}) + switch { + case c.Leading == nil && mulBy == "": + e.emit("dst.Set(%s)", res) + case c.Leading == nil: + e.emit("dst.Mul(%s, %s)", res, mulBy) + case mulBy == "": + e.emit("dst.Mul(%s, &%s)", res, leadVar) + default: + e.emit("p.Mul(%s, &%s)", res, leadVar) + e.emit("dst.Mul(&p, %s)", mulBy) + e.used["p"] = true + } + + var decl []string + decl = append(decl, fmt.Sprintf("var w [%d]%s // gate outputs", len(c.Gates), coordType)) + var tmps []string + for _, v := range []string{"p", "r", "t"} { + if e.used[v] { + tmps = append(tmps, v) + } + } + if len(tmps) > 0 { + decl = append(decl, fmt.Sprintf("var %s %s", strings.Join(tmps, ", "), coordType)) + } + return "\t" + strings.Join(append(decl, e.lines...), "\n\t") +} + +type chainVar struct{ name, addr string } + +type chainEmitter struct { + constsVar string + lines []string + used map[string]bool +} + +func (e *chainEmitter) emit(format string, a ...any) { + e.lines = append(e.lines, fmt.Sprintf(format, a...)) +} + +func (e *chainEmitter) use(v chainVar) { + if e.used == nil { + e.used = make(map[string]bool) + } + e.used[v.name] = true +} + +func wireRef(i int) string { + if i == 0 { + return "x" + } + return fmt.Sprintf("&w[%d]", i-1) +} + +func sameForm(a, b config.LinearForm) bool { + if a.Const != b.Const || len(a.Terms) != len(b.Terms) { + return false + } + for i := range a.Terms { + if a.Terms[i] != b.Terms[i] { + return false + } + } + return true +} + +// smallMul emits target = k * src for |k| >= 2 by double-and-add. +func (e *chainEmitter) smallMul(target chainVar, src string, k int) { + e.use(target) + neg := k < 0 + if neg { + k = -k + } + bits := strconv.FormatInt(int64(k), 2) + e.emit("%s.Double(%s)", target.name, src) + if bits[1] == '1' { + e.emit("%s.Add(%s, %s)", target.name, target.addr, src) + } + for _, b := range bits[2:] { + e.emit("%s.Double(%s)", target.name, target.addr) + if b == '1' { + e.emit("%s.Add(%s, %s)", target.name, target.addr, src) + } + } + if neg { + e.emit("%s.Neg(%s)", target.name, target.addr) + } +} + +// linear emits the evaluation of the linear form into target and returns the +// expression (a pointer) holding its value. A form that is a single wire with +// coefficient 1 is returned by reference without emitting anything. +func (e *chainEmitter) linear(lf config.LinearForm, target chainVar) string { + type term struct { + src string + k int + } + var ops []term + for _, t := range lf.Terms { + if t[1] == 0 || t[1] < -64 || t[1] > 64 { + panic(fmt.Sprintf("unsupported wire coefficient %d", t[1])) + } + ops = append(ops, term{wireRef(t[0]), t[1]}) + } + if lf.Const >= 0 { + ops = append(ops, term{fmt.Sprintf("&%s[%d]", e.constsVar, lf.Const), 1}) + } + rank := func(k int) int { + switch k { + case 1: + return 0 + case -1: + return 1 + } + return 2 + } + sort.SliceStable(ops, func(i, j int) bool { return rank(ops[i].k) < rank(ops[j].k) }) + if len(ops) == 0 { + panic("empty linear form") + } + if len(ops) == 1 && ops[0].k == 1 { + return ops[0].src + } + + e.use(target) + i := 1 + switch { + case ops[0].k == 1 && len(ops) > 1 && ops[1].k == 1: + e.emit("%s.Add(%s, %s)", target.name, ops[0].src, ops[1].src) + i = 2 + case ops[0].k == 1 && len(ops) > 1 && ops[1].k == -1: + e.emit("%s.Sub(%s, %s)", target.name, ops[0].src, ops[1].src) + i = 2 + case ops[0].k == 1: + e.emit("%s.Set(%s)", target.name, ops[0].src) + case ops[0].k == -1: + e.emit("%s.Neg(%s)", target.name, ops[0].src) + default: + e.smallMul(target, ops[0].src, ops[0].k) + } + tmp := chainVar{name: "t", addr: "&t"} + for ; i < len(ops); i++ { + switch { + case ops[i].k == 1: + e.emit("%s.Add(%s, %s)", target.name, target.addr, ops[i].src) + case ops[i].k == -1: + e.emit("%s.Sub(%s, %s)", target.name, target.addr, ops[i].src) + case ops[i].k > 0: + e.smallMul(tmp, ops[i].src, ops[i].k) + e.emit("%s.Add(%s, %s)", target.name, target.addr, tmp.addr) + default: + e.smallMul(tmp, ops[i].src, -ops[i].k) + e.emit("%s.Sub(%s, %s)", target.name, target.addr, tmp.addr) + } + } + return target.addr +} diff --git a/internal/generator/hash_to_curve/gen_isogeny_chains.py b/internal/generator/hash_to_curve/gen_isogeny_chains.py new file mode 100644 index 0000000000..2d5dfcaa3b --- /dev/null +++ b/internal/generator/hash_to_curve/gen_isogeny_chains.py @@ -0,0 +1,386 @@ +#!/usr/bin/env python3 +"""Offline preprocessing of the hash-to-curve isogeny polynomials into short +multiplication chains. + +A monic polynomial of degree n over a field of characteristic 0 or p > n can be +evaluated with floor(n/2)+1 field multiplications (instead of Horner's n-1) after a +one-time *rational preprocessing* of its coefficients: + + T. D. Ahle, "Fast Evaluation of Polynomials with Rational Preprocessing", + https://arxiv.org/abs/2609.06022, https://thomasahle.com/fast-polynomials/ + +This script reads the isogeny coefficient tables of one curve from +internal/generator/config/.go, runs the paper's decoder (tools/polychain.py +from https://github.com/thomasahle/fast-polynomials) on every map of degree > 6, +verifies each chain against the original polynomial at random points, and writes +the chain data as Go literals to internal/generator/config/_isogeny_chains.go. +The code generator (template pkg_sswu.go.tmpl) turns that data into straight-line, +branch-free Go. + +Usage: + python3 gen_isogeny_chains.py --polychain-dir /tools \ + --config internal/generator/config/bw6-761.go --suite HashE2 --var bw6761G2IsogenyChains + +Prime fields and quadratic extensions Fp[u]/(u^2 - beta) (beta = CoordExtRoot in +the curve config) are supported. Non-monic numerators are handled by dividing by +the leading coefficient before decoding and multiplying the chain's result by it +(one extra multiplication). Small integer wire coefficients in the chains +(e.g. -12 .. 2) are realised by doublings and additions, never by a field +multiplication. +""" +import argparse +import json +import os +import random +import re +import subprocess +import sys + + +def parse_args(): + ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument('--polychain-dir', required=True, help='directory containing polychain.py and poly_schedule.py') + ap.add_argument('--config', required=True, help='path to internal/generator/config/.go') + ap.add_argument('--suite', required=True, choices=['HashE1', 'HashE2']) + ap.add_argument('--var', required=True, help='Go variable name for the emitted IsogenyChains value') + ap.add_argument('--out', help='output .go file (default: /_isogeny_chains.go)') + ap.add_argument('--min-degree', type=int, default=7, help='maps of lower degree keep Horner (default 7)') + ap.add_argument('--checks', type=int, default=200, help='random evaluation points per chain (default 200)') + ap.add_argument('--seed', type=int, default=1) + return ap.parse_args() + + +args = parse_args() +sys.path.insert(0, args.polychain_dir) +import poly_schedule as ps # noqa: E402 +import polychain as pc # noqa: E402 + +random.seed(args.seed) +src = open(args.config).read() + + +# --------------------------------------------------------------------------- config parsing + +def go_int(s): + return int(s, 0) + + +P = go_int(re.search(r'FpModulus:\s*"([^"]+)"', src).group(1)) + + +def block(text, start): + """text[start:] must begin with '{'; return the brace-balanced block (inclusive).""" + assert text[start] == '{', text[start:start + 20] + depth = 0 + for i in range(start, len(text)): + if text[i] == '{': + depth += 1 + elif text[i] == '}': + depth -= 1 + if depth == 0: + return text[start:i + 1] + raise SystemExit('unbalanced braces in config') + + +def go_string_matrix(text): + """the elements of a [][]string literal, as lists of Python ints""" + inner = block(text, text.index('{'))[1:-1] + rows = [] + for m in re.finditer(r'\{([^{}]*)\}', inner): + rows.append([go_int(v) for v in re.findall(r'"([^"]+)"', m.group(1))]) + return rows + + +suite_start = src.index(args.suite + ':') +suite = block(src, src.index('{', suite_start)) + +# point definition of this suite (G1 for HashE1, G2 for HashE2) +point_name = 'g1' if args.suite == 'HashE1' else 'g2' +point_blocks = [block(src, m.start()) for m in re.finditer(r'\{\s*\n\s*CoordType:', src)] +point = next(b for b in point_blocks if re.search(r'PointName:\s*"%s"' % point_name, b)) +ext_degree = int(re.search(r'CoordExtDegree:\s*(\d+)', point).group(1)) +m = re.search(r'CoordExtRoot:\s*(-?\d+)', point) +beta = int(m.group(1)) if m else None +assert ext_degree in (1, 2), 'only Fp and Fp^2 coordinates are supported' +if ext_degree == 2: + assert beta is not None + +iso_start = suite.index('Isogeny:') +iso = block(suite, suite.index('{', iso_start)) + + +def poly_table(map_name, part): + m_start = iso.index(map_name + ':') + mp = block(iso, iso.index('{', m_start)) + p_start = mp.index(part + ':') + return go_string_matrix(mp[p_start:]) + + +# --------------------------------------------------------------------------- fields + +class Fp(ps.Field): + """GF(p) with elements represented as 1-tuples so both field degrees share code.""" + d = 1 + + def __init__(self): + super().__init__(modulus=P, use_fractions=False) + + def coerce(self, x): + if isinstance(x, tuple): + return (x[0] % P,) + return (int(x) % P,) + + def zero(self): return (0,) + def one(self): return (1,) + def add(self, a, b): a, b = self.coerce(a), self.coerce(b); return ((a[0] + b[0]) % P,) + def sub(self, a, b): a, b = self.coerce(a), self.coerce(b); return ((a[0] - b[0]) % P,) + def neg(self, a): a = self.coerce(a); return ((-a[0]) % P,) + def mul(self, a, b): a, b = self.coerce(a), self.coerce(b); return ((a[0] * b[0]) % P,) + + def inv(self, a): + a = self.coerce(a) + if a[0] == 0: + raise ZeroDivisionError + return (pow(a[0], -1, P),) + + def div(self, a, b): return self.mul(a, self.inv(b)) + def sqrt(self, a): raise NotImplementedError + def is_zero(self, a): return self.coerce(a) == (0,) + def random(self): return (random.randrange(P),) + + +class Fp2(ps.Field): + """GF(p^2) = Fp[u]/(u^2 - beta), elements as pairs (a0, a1) = a0 + a1 u.""" + d = 2 + + def __init__(self, beta): + super().__init__(modulus=P, use_fractions=False) + self.beta = beta % P + + def coerce(self, x): + if isinstance(x, tuple): + return (x[0] % P, x[1] % P) + return (int(x) % P, 0) + + def zero(self): return (0, 0) + def one(self): return (1, 0) + def add(self, a, b): a, b = self.coerce(a), self.coerce(b); return ((a[0] + b[0]) % P, (a[1] + b[1]) % P) + def sub(self, a, b): a, b = self.coerce(a), self.coerce(b); return ((a[0] - b[0]) % P, (a[1] - b[1]) % P) + def neg(self, a): a = self.coerce(a); return ((-a[0]) % P, (-a[1]) % P) + + def mul(self, a, b): + a, b = self.coerce(a), self.coerce(b) + return ((a[0] * b[0] + self.beta * a[1] * b[1]) % P, (a[0] * b[1] + a[1] * b[0]) % P) + + def inv(self, a): + a = self.coerce(a) + norm = (a[0] * a[0] - self.beta * a[1] * a[1]) % P + if norm == 0: + raise ZeroDivisionError + ni = pow(norm, -1, P) + return ((a[0] * ni) % P, (-a[1] * ni) % P) + + def div(self, a, b): return self.mul(a, self.inv(b)) + def sqrt(self, a): raise NotImplementedError + def is_zero(self, a): return self.coerce(a) == (0, 0) + def random(self): return (random.randrange(P), random.randrange(P)) + + +F = Fp() if ext_degree == 1 else Fp2(beta) + +# polychain's rational constants come back as bare ints; route them through coerce +_orig_f2f = pc._fraction_to_field +pc._fraction_to_field = lambda fr, field: field.coerce(_orig_f2f(fr, field)) + + +def elem(coords): + """config coordinate list -> field element""" + assert len(coords) == F.d, coords + return F.coerce(tuple(coords)) + + +def poly_eval(c, x): + acc = F.zero() + for cv in reversed(c): + acc = F.add(F.mul(acc, x), cv) + return acc + + +# --------------------------------------------------------------------------- chains + +TERM = re.compile(r'^(-?)(\d+)?\*?(a\d+)?$') + + +def eval_const(expr, keys): + """linear expression in the keys a_i with integer coefficients -> field element""" + s = expr.replace(' ', '').replace('-', '+-') + tot = F.zero() + for t in s.split('+'): + if not t: + continue + m = TERM.match(t) + assert m, (expr, t) + sign = -1 if m.group(1) else 1 + coef = int(m.group(2)) if m.group(2) else 1 + val = keys[int(m.group(3)[1:])] if m.group(3) else F.one() + tot = F.add(tot, F.mul(F.coerce(sign * coef), val)) + return tot + + +def build_chain(name, coeffs): + """coeffs: c_0..c_n (c_n = leading coefficient). Returns the Go literal data + (dict) or None when the degree is below the threshold.""" + n = len(coeffs) - 1 + if n < args.min_degree: + return None, n, None + lead = coeffs[n] + monic = lead == F.one() + inv = F.inv(lead) + mon = [F.mul(v, inv) for v in coeffs[:n]] + keys = pc.decode(n, mon, F) + back = [F.coerce(v) for v in pc.encode(n, keys, F)] + assert back == mon, 'decode/encode round trip failed for ' + name + r = subprocess.run([sys.executable, os.path.join(args.polychain_dir, 'polychain.py'), 'chain', str(n), '--json'], + capture_output=True, text=True) + if r.returncode: + raise SystemExit(r.stderr) + ch = json.loads(r.stdout) + assert ch['n'] == n + + wires = [w for w in ch['wires'] if w != '1'] + assert wires[0] == 'x' + widx = {w: i for i, w in enumerate(wires)} + consts, cidx = [], {} + + def const_index(val): + if F.is_zero(val): + return -1 + if val not in cidx: + cidx[val] = len(consts) + consts.append(val) + return cidx[val] + + def linform(lf): + assert '1' not in lf['terms'], lf + terms = [[widx[w], int(k)] for w, k in lf['terms'].items()] + for _, k in terms: + assert 1 <= abs(k) <= 64, 'wire coefficient %d out of the supported range' % k + return {'Terms': terms, 'Const': const_index(eval_const(lf['const'], keys))} + + gates = [] + for i, g in enumerate(ch['gates']): + assert widx[g['out']] == i + 1, 'gate outputs must be numbered in order' + gates.append({'Left': linform(g['left']), 'Right': linform(g['right'])}) + output = linform(ch['output']) + data = { + 'Degree': n, + 'Leading': None if monic else lead, + 'Constants': consts, + 'Gates': gates, + 'Output': output, + } + + # self-check: evaluate the *emitted* data structure against the polynomial + def lin(lf, w): + tot = consts[lf['Const']] if lf['Const'] >= 0 else F.zero() + for wi, k in lf['Terms']: + tot = F.add(tot, F.mul(F.coerce(k), w[wi])) + return tot + + def evaluate(x): + w = [x] + for g in gates: + w.append(F.mul(lin(g['Left'], w), lin(g['Right'], w))) + out = lin(output, w) + return out if monic else F.mul(out, lead) + + pts = [F.zero(), F.one(), F.neg(F.one())] + [F.random() for _ in range(args.checks)] + for x in pts: + assert evaluate(x) == poly_eval(coeffs, x), 'chain self-check failed for ' + name + nmul = len(gates) + (0 if monic else 1) + horner = n - 1 if monic else n + print(' %-4s degree %2d %-10s Horner %3d mults -> chain %3d mults (%d random points + 0, 1, -1 verified)' + % (name, n, '' if monic else '(non-monic)', horner, nmul, args.checks)) + return data, n, (horner, nmul) + + +x_num = [elem(c) for c in poly_table('XMap', 'Num')] +x_den = [elem(c) for c in poly_table('XMap', 'Den')] + [F.one()] # Den omits the leading 1 +y_num = [elem(c) for c in poly_table('YMap', 'Num')] +y_den = [elem(c) for c in poly_table('YMap', 'Den')] + [F.one()] + +print('%s %s over %s (p has %d bits)' % (os.path.basename(args.config), args.suite, + 'Fp' if F.d == 1 else 'Fp^2 (u^2 = %d)' % beta, P.bit_length())) +results = {} +tot_h = tot_c = 0 +for field_name, coeffs in (('XNum', x_num), ('XDen', x_den), ('YNum', y_num), ('YDen', y_den)): + data, n, counts = build_chain(field_name, coeffs) + results[field_name] = data + if counts: + tot_h += counts[0] + tot_c += counts[1] + else: + print(' %-4s degree %2d: kept Horner (degree < %d)' % (field_name, n, args.min_degree)) +if not any(results.values()): + raise SystemExit('no map of degree >= %d; nothing to emit' % args.min_degree) +print(' total multiplications on chained maps: Horner %d -> chains %d' % (tot_h, tot_c)) + + +# --------------------------------------------------------------------------- Go output + +def go_elem(v): + return '[]string{' + ', '.join('"%d"' % c for c in v) + '}' + + +def go_linform(lf, indent): + terms = ', '.join('{%d, %d}' % (w, k) for w, k in lf['Terms']) + return '%sLinearForm{Terms: [][2]int{%s}, Const: %d}' % (indent, terms, lf['Const']) + + +out = [] +out.append('// Copyright 2020-2026 Consensys Software Inc.') +out.append('// Licensed under the Apache License, Version 2.0. See the LICENSE file for details.') +out.append('') +out.append('// Generated by internal/generator/hash_to_curve/gen_isogeny_chains.py from %s (%s);' % (os.path.basename(args.config), args.suite)) +out.append('// do not edit by hand. Regenerate with') +out.append('// python3 internal/generator/hash_to_curve/gen_isogeny_chains.py --polychain-dir /tools \\') +out.append('// --config %s --suite %s --var %s' % (os.path.relpath(args.config), args.suite, args.var)) +out.append('//') +out.append('// Multiplication chains for the isogeny polynomials, preprocessed offline with the') +out.append('// decoder of "Fast Evaluation of Polynomials with Rational Preprocessing"') +out.append('// (https://arxiv.org/abs/2609.06022). Each chain evaluates the polynomial with') +out.append('// floor(n/2)+1 multiplications (+1 for a non-monic leading coefficient).') +out.append('') +out.append('package config') +out.append('') +out.append('var %s = IsogenyChains{' % args.var) +for field_name in ('XNum', 'XDen', 'YNum', 'YDen'): + data = results[field_name] + if data is None: + out.append('\t%s: nil, // degree < %d: Horner' % (field_name, args.min_degree)) + continue + out.append('\t%s: &PolyChain{' % field_name) + out.append('\t\tDegree: %d,' % data['Degree']) + if data['Leading'] is not None: + out.append('\t\tLeading: %s,' % go_elem(data['Leading'])) + out.append('\t\tConstants: [][]string{') + for c in data['Constants']: + out.append('\t\t\t%s,' % go_elem(c)) + out.append('\t\t},') + out.append('\t\tGates: []ChainGate{') + for g in data['Gates']: + out.append('\t\t\t{') + out.append('\t\t\t\tLeft: %s,' % go_linform(g['Left'], '')) + out.append('\t\t\t\tRight: %s,' % go_linform(g['Right'], '')) + out.append('\t\t\t},') + out.append('\t\t},') + out.append('\t\tOutput: %s,' % go_linform(data['Output'], '')) + out.append('\t},') +out.append('}') +out.append('') + +out_path = args.out or os.path.join(os.path.dirname(args.config), + os.path.basename(args.config)[:-3] + '_%s_isogeny_chains.go' % point_name) +open(out_path, 'w').write('\n'.join(out)) +subprocess.run(['gofmt', '-w', out_path], check=True) +print(' wrote', os.path.relpath(out_path)) diff --git a/internal/generator/hash_to_curve/generate.go b/internal/generator/hash_to_curve/generate.go index a1e84c4576..c24af995ee 100644 --- a/internal/generator/hash_to_curve/generate.go +++ b/internal/generator/hash_to_curve/generate.go @@ -48,6 +48,7 @@ func Generate(conf config.Curve, baseDir string, gen *common.Generator) error { funcs := make(txttmpl.FuncMap) funcs["asElement"] = hashConf.Field.Base.WriteElement + funcs["chainCode"] = chainCode bavardOpts := []func(*bavard.Bavard) error{bavard.Funcs(funcs)} return errors.Join( diff --git a/internal/generator/hash_to_curve/template/pkg_sswu.go.tmpl b/internal/generator/hash_to_curve/template/pkg_sswu.go.tmpl index aae92f4e08..d6ebfcddce 100644 --- a/internal/generator/hash_to_curve/template/pkg_sswu.go.tmpl +++ b/internal/generator/hash_to_curve/template/pkg_sswu.go.tmpl @@ -70,23 +70,11 @@ func {{$CurveTitle}}IsogenyMap() [4][]{{$CoordType}} { } } -func {{$CurveName}}IsogenyXNumerator(dst *{{$CoordType}}, x *{{$CoordType}}) { - {{$CurveName}}EvalPolynomial(dst, false, {{$CurveName}}IsogenyXNumeratorMap, x) -} - -func {{$CurveName}}IsogenyXDenominator(dst *{{$CoordType}}, x *{{$CoordType}}) { - {{$CurveName}}EvalPolynomial(dst, true, {{$CurveName}}IsogenyXDenominatorMap, x) -} - -func {{$CurveName}}IsogenyYNumerator(dst *{{$CoordType}}, x *{{$CoordType}}, y *{{$CoordType}}) { - var _dst {{$CoordType}} - {{$CurveName}}EvalPolynomial(&_dst, false, {{$CurveName}}IsogenyYNumeratorMap, x) - dst.Mul(&_dst, y) -} - -func {{$CurveName}}IsogenyYDenominator(dst *{{$CoordType}}, x *{{$CoordType}}) { - {{$CurveName}}EvalPolynomial(dst, true, {{$CurveName}}IsogenyYDenominatorMap, x) -} +{{- $chains := .Isogeny.Chains}} +{{- template "isogeny_poly" (dict "Chain" $chains.XNum "Name" "XNumerator" "Monic" false "MulBy" "" "CurveName" $CurveName "CoordType" $CoordType)}} +{{- template "isogeny_poly" (dict "Chain" $chains.XDen "Name" "XDenominator" "Monic" true "MulBy" "" "CurveName" $CurveName "CoordType" $CoordType)}} +{{- template "isogeny_poly" (dict "Chain" $chains.YNum "Name" "YNumerator" "Monic" false "MulBy" "y" "CurveName" $CurveName "CoordType" $CoordType)}} +{{- template "isogeny_poly" (dict "Chain" $chains.YDen "Name" "YDenominator" "Monic" true "MulBy" "" "CurveName" $CurveName "CoordType" $CoordType)}} // {{ $CurveTitle }} computes the isogeny map of the curve element, given by its coordinates pX and pY. // It mutates the coordinates pX and pY to the new coordinates of the isogeny map. @@ -497,3 +485,45 @@ func {{$CurveName}}EvalPolynomial(z *{{$CoordType}}, monic bool, coefficients [] } {{end}} + +{{/* one isogeny polynomial: a preprocessed multiplication chain when the curve config has one, Horner otherwise */}} +{{define "isogeny_poly"}} +{{- $fn := print .CurveName "Isogeny" .Name}} +{{- $args := print "dst *" .CoordType ", x *" .CoordType}} +{{- if .MulBy}}{{$args = print $args ", " .MulBy " *" .CoordType}}{{end}} +{{- if notNil .Chain}} + +// {{$fn}} evaluates the degree-{{.Chain.Degree}} {{.Name}} polynomial of the isogeny +// with {{.Chain.Multiplications}} field multiplications (Horner: {{.Chain.HornerMultiplications}}){{if .MulBy}}, then multiplies by {{.MulBy}}{{end}}. +// +// The multiplication chain was preprocessed offline from the polynomial's +// coefficients ({{$fn}}Map) by internal/generator/hash_to_curve/gen_isogeny_chains.py, +// using the decoder of T. D. Ahle, "Fast Evaluation of Polynomials with Rational +// Preprocessing", https://arxiv.org/abs/2609.06022. The code is straight line: +// no branches, no divisions. +func {{$fn}}({{$args}}) { +{{chainCode .Chain .CoordType (print $fn "ChainConstants") (print $fn "LeadingCoeff") .MulBy}} +} + +var {{$fn}}ChainConstants = [{{len .Chain.Constants}}]{{.CoordType}}{ + {{- range $c := .Chain.Constants}} + {{asElement $c}}, + {{- end}} +} +{{- if .Chain.Leading}} + +var {{$fn}}LeadingCoeff = {{.CoordType}} {{asElement .Chain.Leading}} +{{- end}} +{{- else}} + +func {{$fn}}({{$args}}) { + {{- if .MulBy}} + var _dst {{.CoordType}} + {{.CurveName}}EvalPolynomial(&_dst, {{.Monic}}, {{$fn}}Map, x) + dst.Mul(&_dst, {{.MulBy}}) + {{- else}} + {{.CurveName}}EvalPolynomial(dst, {{.Monic}}, {{$fn}}Map, x) + {{- end}} +} +{{- end}} +{{end}} diff --git a/internal/generator/hash_to_curve/template/tests/pkg.go.tmpl b/internal/generator/hash_to_curve/template/tests/pkg.go.tmpl index da6b2ffd74..6584a80047 100644 --- a/internal/generator/hash_to_curve/template/tests/pkg.go.tmpl +++ b/internal/generator/hash_to_curve/template/tests/pkg.go.tmpl @@ -96,6 +96,91 @@ func Test{{$CurveTitle}}SqrtRatio(t *testing.T) { } {{if notNil .Isogeny}} +{{- $chains := .Isogeny.Chains}} +{{- $anyChain := or (notNil $chains.XNum) (notNil $chains.XDen) (notNil $chains.YNum) (notNil $chains.YDen)}} +{{- if $anyChain}} +// Test{{$CurveTitle}}IsogenyChains checks the preprocessed multiplication chains of the +// isogeny polynomials against Horner's rule on the original coefficients. +func Test{{$CurveTitle}}IsogenyChains(t *testing.T) { + t.Parallel() + + check := func(x, y *{{$CoordType}}) { + var got, want {{$CoordType}} + {{- if notNil $chains.XNum}} + {{$CurveName}}IsogenyXNumerator(&got, x) + {{$CurveName}}EvalPolynomial(&want, false, {{$CurveName}}IsogenyXNumeratorMap, x) + if !got.Equal(&want) { + t.Fatal("x numerator: chain and Horner disagree") + } + {{- end}} + {{- if notNil $chains.XDen}} + {{$CurveName}}IsogenyXDenominator(&got, x) + {{$CurveName}}EvalPolynomial(&want, true, {{$CurveName}}IsogenyXDenominatorMap, x) + if !got.Equal(&want) { + t.Fatal("x denominator: chain and Horner disagree") + } + {{- end}} + {{- if notNil $chains.YNum}} + {{$CurveName}}IsogenyYNumerator(&got, x, y) + {{$CurveName}}EvalPolynomial(&want, false, {{$CurveName}}IsogenyYNumeratorMap, x) + want.Mul(&want, y) + if !got.Equal(&want) { + t.Fatal("y numerator: chain and Horner disagree") + } + {{- end}} + {{- if notNil $chains.YDen}} + {{$CurveName}}IsogenyYDenominator(&got, x) + {{$CurveName}}EvalPolynomial(&want, true, {{$CurveName}}IsogenyYDenominatorMap, x) + if !got.Equal(&want) { + t.Fatal("y denominator: chain and Horner disagree") + } + {{- end}} + } + + // 0, 1, -1 and random points + var special [3]{{$CoordType}} + special[1].SetOne() + special[2].Neg(&special[1]) + var y {{$CoordType}} + y.MustSetRandom() + for i := range special { + check(&special[i], &y) + } + n := 1000 + if testing.Short() { + n = 100 + } + for i := 0; i < n; i++ { + var x {{$CoordType}} + x.MustSetRandom() + y.MustSetRandom() + check(&x, &y) + } + + // aliasing as used by {{$CurveTitle}}Isogeny: dst == x and dst == y + var x {{$CoordType}} + x.MustSetRandom() + y.MustSetRandom() + var want {{$CoordType}} + {{- if notNil $chains.XNum}} + {{$CurveName}}IsogenyXNumerator(&want, &x) + x2 := x + {{$CurveName}}IsogenyXNumerator(&x2, &x2) + if !x2.Equal(&want) { + t.Fatal("x numerator: aliased evaluation differs") + } + {{- end}} + {{- if notNil $chains.YNum}} + {{$CurveName}}IsogenyYNumerator(&want, &x, &y) + y2 := y + {{$CurveName}}IsogenyYNumerator(&y2, &x, &y2) + if !y2.Equal(&want) { + t.Fatal("y numerator: aliased evaluation differs") + } + {{- end}} +} +{{- end}} + // Benchmark{{$CurveTitle}}IsogenyPolynomials evaluates the four isogeny polynomials as // {{$CurveTitle}}Isogeny does (without the final batch inversion). func Benchmark{{$CurveTitle}}IsogenyPolynomials(b *testing.B) {