diff --git a/ecc/bls377/g1_test.go b/ecc/bls377/g1_test.go index 67df8c69a5..d7506429de 100644 --- a/ecc/bls377/g1_test.go +++ b/ecc/bls377/g1_test.go @@ -105,27 +105,26 @@ func TestG1JacScalarMul(t *testing.T) { func TestG1JacMultiExp(t *testing.T) { curve := BLS377() - // var points []G1Jac + var points []G1Jac var scalars []fr.Element var got G1Jac // // Test 1: testPointsG1multiExp // - // TODO why is this commented? - // numPoints, wants := testPointsG1MultiExpResults() + numPoints, wants := testPointsG1MultiExpResults() - // for i := range numPoints { - // if numPoints[i] > 10000 { - // continue - // } - // points, scalars = testPointsG1MultiExp(numPoints[i]) + for i := range numPoints { + if numPoints[i] > 10000 { + continue + } + points, scalars = testPointsG1MultiExp(numPoints[i]) - // got.multiExp(curve, points, scalars) - // if !got.Equal(&wants[i]) { - // t.Error("multiExp G1Jac fail for points:", numPoints[i]) - // } - // } + got.multiExp(curve, points, scalars) + if !got.Equal(&wants[i]) { + t.Error("multiExp G1Jac fail for points:", numPoints[i]) + } + } // // Test 2: testPointsG1() @@ -133,9 +132,9 @@ func TestG1JacMultiExp(t *testing.T) { p := testPointsG1() // scalars - s1 := fr.Element{23872983, 238203802, 9827897384, 2372} - s2 := fr.Element{128923, 2878236, 398478, 187970707} - s3 := fr.Element{9038947, 3947970, 29080823, 282739} + s1 := fr.Element{23872983, 238203802, 9827897384, 2372} // 14889285316340551032002176131108485811963550694615991316137431 + s2 := fr.Element{128923, 2878236, 398478, 187970707} // 1179911251111561301561648964820473185772012989930899737079831459739 + s3 := fr.Element{9038947, 3947970, 29080823, 282739} // 1774781467561494742381858548177178844765555009630735687022668899 scalars = []fr.Element{ s1, @@ -347,19 +346,15 @@ func testPointsG1MultiExp(n int) (points []G1Jac, scalars []fr.Element) { // To ensure a diverse selection of scalars that use all words of an fr.Element, // each scalar should be a power of a large generator of fr. - // 22 is a small generator of fr for bls377. - // 2^{31}-1 is prime, so 22^{2^31}-1} is a large generator of fr for bls377 - // generator in Montgomery form var scalarGenMont fr.Element scalarGenMont.SetString("7716837800905789770901243404444209691916730933998574719964609384059111546487") - scalars[0].Set(&scalarGenMont).FromMont() var curScalarMont fr.Element // Montgomery form curScalarMont.Set(&scalarGenMont) for i := 1; i < len(scalars); i++ { - curScalarMont.MulAssign(&scalarGenMont) - scalars[i].Set(&curScalarMont).FromMont() // scalars[i] = scalars[0]^i + curScalarMont.MulAssign(&scalarGenMont) // scalars[i] = scalars[0]^i + scalars[i].Set(&curScalarMont).FromMont() } return points, scalars diff --git a/ecc/bls377/g2_test.go b/ecc/bls377/g2_test.go index 7a1fcdb8df..a13e6e2794 100644 --- a/ecc/bls377/g2_test.go +++ b/ecc/bls377/g2_test.go @@ -8,8 +8,241 @@ import ( "github.com/consensys/gnark/ecc/bls377/fr" ) -func TestG2NotReallyHere(t *testing.T) { - t.Skip("testPointsG2() not available?") +func TestG2JacToAffineFromJac(t *testing.T) { + + p := testPointsG2() + + _p := G2Affine{} + p[0].ToAffineFromJac(&_p) + if !_p.X.Equal(&p[1].X) || !_p.Y.Equal(&p[1].Y) { + t.Fatal("ToAffineFromJac failed") + } + +} + +func TestG2Conv(t *testing.T) { + p := testPointsG2() + + for i := 0; i < len(p); i++ { + var pJac G2Jac + var pAff G2Affine + p[i].ToAffineFromJac(&pAff) + pAff.ToJacobian(&pJac) + if !pJac.Equal(&p[i]) { + t.Fatal("jacobian to affine to jacobian fails") + } + } +} + +func TestG2JacAdd(t *testing.T) { + + curve := BLS377() + p := testPointsG2() + + // p3 = p1 + p2 + p1 := p[1].Clone() + _p2 := G2Affine{} + p[2].ToAffineFromJac(&_p2) + p[1].AddMixed(&_p2) + p[2].Add(curve, p1) + + if !p[3].Equal(&p[1]) { + t.Fatal("Add failed") + } + + // test commutativity + if !p[3].Equal(&p[2]) { + t.Fatal("Add failed") + } +} + +func TestG2JacSub(t *testing.T) { + + curve := BLS377() + p := testPointsG2() + + // p4 = p1 - p2 + p[1].Sub(curve, p[2]) + + if !p[4].Equal(&p[1]) { + t.Fatal("Sub failed") + } +} + +func TestG2JacDouble(t *testing.T) { + + curve := BLS377() + p := testPointsG2() + + // p5 = 2 * p1 + p[1].Double() + if !p[5].Equal(&p[1]) { + t.Fatal("Double failed") + } + + G := curve.g2Infinity.Clone() + R := curve.g2Infinity.Clone() + G.Double() + + if !G.Equal(R) { + t.Fatal("Double failed (infinity case)") + } +} + +func TestG2JacScalarMul(t *testing.T) { + + curve := BLS377() + p := testPointsG2() + + // p6 = [p1]32394 (scalar mul) + scalar := fr.Element{32394} + p[1].ScalarMul(curve, &p[1], scalar) + + if !p[1].Equal(&p[6]) { + t.Error("ScalarMul failed") + } +} + +func TestG2JacMultiExp(t *testing.T) { + curve := BLS377() + var points []G2Jac + var scalars []fr.Element + var got G2Jac + + // + // Test 1: testPointsG2multiExp + // + numPoints, wants := testPointsG2MultiExpResults() + + for i := range numPoints { + if numPoints[i] > 10000 { + continue + } + points, scalars = testPointsG2MultiExp(numPoints[i]) + + got.multiExp(curve, points, scalars) + if !got.Equal(&wants[i]) { + t.Error("multiExp G2Jac fail for points:", numPoints[i]) + } + } + + // + // Test 2: testPointsG2() + // + p := testPointsG2() + + // scalars + s1 := fr.Element{23872983, 238203802, 9827897384, 2372} // 14889285316340551032002176131108485811963550694615991316137431 + s2 := fr.Element{128923, 2878236, 398478, 187970707} // 1179911251111561301561648964820473185772012989930899737079831459739 + s3 := fr.Element{9038947, 3947970, 29080823, 282739} // 1774781467561494742381858548177178844765555009630735687022668899 + + scalars = []fr.Element{ + s1, + s2, + s3, + } + + got.multiExp(curve, p[17:20], scalars) + if !got.Equal(&p[20]) { + t.Error("multiExp G2Jac failed") + } + + // + // Test 3: edge cases + // + + // one input point p[1] + scalars[0] = fr.Element{32394, 0, 0, 0} // single-word scalar + got.multiExp(curve, p[1:2], scalars[:1]) + if !got.Equal(&p[6]) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + + scalars[0] = fr.Element{2, 0, 0, 0} // scalar = 2 + got.multiExp(curve, p[1:2], scalars[:1]) + if !got.Equal(&p[5]) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{1, 0, 0, 0} // scalar = 1 + got.multiExp(curve, p[1:2], scalars[:1]) + if !got.Equal(&p[1]) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{0, 0, 0, 0} // scalar = 0 + got.multiExp(curve, p[1:2], scalars[:1]) + if !got.Equal(&curve.g2Infinity) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)} // scalar == (4-word maxuint) + got.multiExp(curve, p[1:2], scalars[:1]) + if !got.Equal(&p[21]) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + + // one input point curve.g2Infinity + infinity := []G2Jac{curve.g2Infinity} + + scalars[0] = fr.Element{32394, 0, 0, 0} // single-word scalar + got.multiExp(curve, infinity, scalars[:1]) + if !got.Equal(&curve.g2Infinity) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{2, 0, 0, 0} // scalar = 2 + got.multiExp(curve, infinity, scalars[:1]) + if !got.Equal(&curve.g2Infinity) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{1, 0, 0, 0} // scalar = 1 + got.multiExp(curve, infinity, scalars[:1]) + if !got.Equal(&curve.g2Infinity) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{0, 0, 0, 0} // scalar = 0 + got.multiExp(curve, infinity, scalars[:1]) + if !got.Equal(&curve.g2Infinity) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)} // scalar == (4-word maxuint) + got.multiExp(curve, infinity, scalars[:1]) + if !got.Equal(&curve.g2Infinity) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + + // two input points: p[1], curve.g2Infinity + twoPoints := []G2Jac{p[1], curve.g2Infinity} + + scalars[0] = fr.Element{32394, 0, 0, 0} // single-word scalar + scalars[1] = fr.Element{2, 0, 0, 0} // scalar = 2 + got.multiExp(curve, twoPoints, scalars[:2]) + if !got.Equal(&p[6]) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{2, 0, 0, 0} // scalar = 2 + scalars[1] = fr.Element{1, 0, 0, 0} // scalar = 1 + got.multiExp(curve, twoPoints, scalars[:2]) + if !got.Equal(&p[5]) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{1, 0, 0, 0} // scalar = 1 + scalars[1] = fr.Element{0, 0, 0, 0} // scalar = 0 + got.multiExp(curve, twoPoints, scalars[:2]) + if !got.Equal(&p[1]) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{0, 0, 0, 0} // scalar = 0 + scalars[1] = fr.Element{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)} // scalar == (4-word maxuint) + got.multiExp(curve, twoPoints, scalars[:2]) + if !got.Equal(&curve.g2Infinity) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)} // scalar == (4-word maxuint) + scalars[1] = fr.Element{32394, 0, 0, 0} // single-word scalar + got.multiExp(curve, twoPoints, scalars[:2]) + if !got.Equal(&p[21]) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + + // TODO: Jacobian points with nontrivial Z coord? } func TestMultiExpG2(t *testing.T) { @@ -113,19 +346,15 @@ func testPointsG2MultiExp(n int) (points []G2Jac, scalars []fr.Element) { // To ensure a diverse selection of scalars that use all words of an fr.Element, // each scalar should be a power of a large generator of fr. - // 22 is a small generator of fr for bls377. - // 2^{31}-1 is prime, so 22^{2^31}-1} is a large generator of fr for bls377 - // generator in Montgomery form var scalarGenMont fr.Element scalarGenMont.SetString("7716837800905789770901243404444209691916730933998574719964609384059111546487") - scalars[0].Set(&scalarGenMont).FromMont() var curScalarMont fr.Element // Montgomery form curScalarMont.Set(&scalarGenMont) for i := 1; i < len(scalars); i++ { - curScalarMont.MulAssign(&scalarGenMont) - scalars[i].Set(&curScalarMont).FromMont() // scalars[i] = scalars[0]^i + curScalarMont.MulAssign(&scalarGenMont) // scalars[i] = scalars[0]^i + scalars[i].Set(&curScalarMont).FromMont() } return points, scalars @@ -137,6 +366,62 @@ func testPointsG2MultiExp(n int) (points []G2Jac, scalars []fr.Element) { var benchResG2 G2Jac +func BenchmarkG2ScalarMul(b *testing.B) { + + curve := BLS377() + p := testPointsG2() + + var scalar fr.Element + scalar.SetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + p[1].ScalarMul(curve, &p[1], scalar) + b.StopTimer() + scalar.SetRandom() + b.StartTimer() + } + +} + +func BenchmarkG2Add(b *testing.B) { + + curve := BLS377() + p := testPointsG2() + + b.ResetTimer() + for i := 0; i < b.N; i++ { + benchResG2 = p[1] + benchResG2.Add(curve, &p[2]) + } + +} + +func BenchmarkG2AddMixed(b *testing.B) { + + p := testPointsG2() + _p2 := G2Affine{} + p[2].ToAffineFromJac(&_p2) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + benchResG2 = p[1] + benchResG2.AddMixed(&_p2) + } + +} + +func BenchmarkG2Double(b *testing.B) { + + p := testPointsG2() + + b.ResetTimer() + for i := 0; i < b.N; i++ { + benchResG2 = p[1] + benchResG2.Double() + } + +} + func BenchmarkG2WindowedMultiExp(b *testing.B) { curve := BLS377() diff --git a/ecc/bls381/g1_test.go b/ecc/bls381/g1_test.go index e345fed4b7..7c9862a7d3 100644 --- a/ecc/bls381/g1_test.go +++ b/ecc/bls381/g1_test.go @@ -105,27 +105,26 @@ func TestG1JacScalarMul(t *testing.T) { func TestG1JacMultiExp(t *testing.T) { curve := BLS381() - // var points []G1Jac + var points []G1Jac var scalars []fr.Element var got G1Jac // // Test 1: testPointsG1multiExp // - // TODO why is this commented? - // numPoints, wants := testPointsG1MultiExpResults() + numPoints, wants := testPointsG1MultiExpResults() - // for i := range numPoints { - // if numPoints[i] > 10000 { - // continue - // } - // points, scalars = testPointsG1MultiExp(numPoints[i]) + for i := range numPoints { + if numPoints[i] > 10000 { + continue + } + points, scalars = testPointsG1MultiExp(numPoints[i]) - // got.multiExp(curve, points, scalars) - // if !got.Equal(&wants[i]) { - // t.Error("multiExp G1Jac fail for points:", numPoints[i]) - // } - // } + got.multiExp(curve, points, scalars) + if !got.Equal(&wants[i]) { + t.Error("multiExp G1Jac fail for points:", numPoints[i]) + } + } // // Test 2: testPointsG1() @@ -133,9 +132,9 @@ func TestG1JacMultiExp(t *testing.T) { p := testPointsG1() // scalars - s1 := fr.Element{23872983, 238203802, 9827897384, 2372} - s2 := fr.Element{128923, 2878236, 398478, 187970707} - s3 := fr.Element{9038947, 3947970, 29080823, 282739} + s1 := fr.Element{23872983, 238203802, 9827897384, 2372} // 14889285316340551032002176131108485811963550694615991316137431 + s2 := fr.Element{128923, 2878236, 398478, 187970707} // 1179911251111561301561648964820473185772012989930899737079831459739 + s3 := fr.Element{9038947, 3947970, 29080823, 282739} // 1774781467561494742381858548177178844765555009630735687022668899 scalars = []fr.Element{ s1, @@ -347,19 +346,15 @@ func testPointsG1MultiExp(n int) (points []G1Jac, scalars []fr.Element) { // To ensure a diverse selection of scalars that use all words of an fr.Element, // each scalar should be a power of a large generator of fr. - // 22 is a small generator of fr for bls377. - // 2^{31}-1 is prime, so 22^{2^31}-1} is a large generator of fr for bls377 - // generator in Montgomery form var scalarGenMont fr.Element - scalarGenMont.SetString("7716837800905789770901243404444209691916730933998574719964609384059111546487") - + scalarGenMont.SetString("42033899646658082535995012643440421268349534540760060111646640675404812871419") scalars[0].Set(&scalarGenMont).FromMont() var curScalarMont fr.Element // Montgomery form curScalarMont.Set(&scalarGenMont) for i := 1; i < len(scalars); i++ { - curScalarMont.MulAssign(&scalarGenMont) - scalars[i].Set(&curScalarMont).FromMont() // scalars[i] = scalars[0]^i + curScalarMont.MulAssign(&scalarGenMont) // scalars[i] = scalars[0]^i + scalars[i].Set(&curScalarMont).FromMont() } return points, scalars diff --git a/ecc/bls381/g2_test.go b/ecc/bls381/g2_test.go index 33de6ab8de..777d465fc2 100644 --- a/ecc/bls381/g2_test.go +++ b/ecc/bls381/g2_test.go @@ -8,8 +8,241 @@ import ( "github.com/consensys/gnark/ecc/bls381/fr" ) -func TestG2NotReallyHere(t *testing.T) { - t.Skip("testPointsG2() not available?") +func TestG2JacToAffineFromJac(t *testing.T) { + + p := testPointsG2() + + _p := G2Affine{} + p[0].ToAffineFromJac(&_p) + if !_p.X.Equal(&p[1].X) || !_p.Y.Equal(&p[1].Y) { + t.Fatal("ToAffineFromJac failed") + } + +} + +func TestG2Conv(t *testing.T) { + p := testPointsG2() + + for i := 0; i < len(p); i++ { + var pJac G2Jac + var pAff G2Affine + p[i].ToAffineFromJac(&pAff) + pAff.ToJacobian(&pJac) + if !pJac.Equal(&p[i]) { + t.Fatal("jacobian to affine to jacobian fails") + } + } +} + +func TestG2JacAdd(t *testing.T) { + + curve := BLS381() + p := testPointsG2() + + // p3 = p1 + p2 + p1 := p[1].Clone() + _p2 := G2Affine{} + p[2].ToAffineFromJac(&_p2) + p[1].AddMixed(&_p2) + p[2].Add(curve, p1) + + if !p[3].Equal(&p[1]) { + t.Fatal("Add failed") + } + + // test commutativity + if !p[3].Equal(&p[2]) { + t.Fatal("Add failed") + } +} + +func TestG2JacSub(t *testing.T) { + + curve := BLS381() + p := testPointsG2() + + // p4 = p1 - p2 + p[1].Sub(curve, p[2]) + + if !p[4].Equal(&p[1]) { + t.Fatal("Sub failed") + } +} + +func TestG2JacDouble(t *testing.T) { + + curve := BLS381() + p := testPointsG2() + + // p5 = 2 * p1 + p[1].Double() + if !p[5].Equal(&p[1]) { + t.Fatal("Double failed") + } + + G := curve.g2Infinity.Clone() + R := curve.g2Infinity.Clone() + G.Double() + + if !G.Equal(R) { + t.Fatal("Double failed (infinity case)") + } +} + +func TestG2JacScalarMul(t *testing.T) { + + curve := BLS381() + p := testPointsG2() + + // p6 = [p1]32394 (scalar mul) + scalar := fr.Element{32394} + p[1].ScalarMul(curve, &p[1], scalar) + + if !p[1].Equal(&p[6]) { + t.Error("ScalarMul failed") + } +} + +func TestG2JacMultiExp(t *testing.T) { + curve := BLS381() + var points []G2Jac + var scalars []fr.Element + var got G2Jac + + // + // Test 1: testPointsG2multiExp + // + numPoints, wants := testPointsG2MultiExpResults() + + for i := range numPoints { + if numPoints[i] > 10000 { + continue + } + points, scalars = testPointsG2MultiExp(numPoints[i]) + + got.multiExp(curve, points, scalars) + if !got.Equal(&wants[i]) { + t.Error("multiExp G2Jac fail for points:", numPoints[i]) + } + } + + // + // Test 2: testPointsG2() + // + p := testPointsG2() + + // scalars + s1 := fr.Element{23872983, 238203802, 9827897384, 2372} // 14889285316340551032002176131108485811963550694615991316137431 + s2 := fr.Element{128923, 2878236, 398478, 187970707} // 1179911251111561301561648964820473185772012989930899737079831459739 + s3 := fr.Element{9038947, 3947970, 29080823, 282739} // 1774781467561494742381858548177178844765555009630735687022668899 + + scalars = []fr.Element{ + s1, + s2, + s3, + } + + got.multiExp(curve, p[17:20], scalars) + if !got.Equal(&p[20]) { + t.Error("multiExp G2Jac failed") + } + + // + // Test 3: edge cases + // + + // one input point p[1] + scalars[0] = fr.Element{32394, 0, 0, 0} // single-word scalar + got.multiExp(curve, p[1:2], scalars[:1]) + if !got.Equal(&p[6]) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + + scalars[0] = fr.Element{2, 0, 0, 0} // scalar = 2 + got.multiExp(curve, p[1:2], scalars[:1]) + if !got.Equal(&p[5]) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{1, 0, 0, 0} // scalar = 1 + got.multiExp(curve, p[1:2], scalars[:1]) + if !got.Equal(&p[1]) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{0, 0, 0, 0} // scalar = 0 + got.multiExp(curve, p[1:2], scalars[:1]) + if !got.Equal(&curve.g2Infinity) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)} // scalar == (4-word maxuint) + got.multiExp(curve, p[1:2], scalars[:1]) + if !got.Equal(&p[21]) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + + // one input point curve.g2Infinity + infinity := []G2Jac{curve.g2Infinity} + + scalars[0] = fr.Element{32394, 0, 0, 0} // single-word scalar + got.multiExp(curve, infinity, scalars[:1]) + if !got.Equal(&curve.g2Infinity) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{2, 0, 0, 0} // scalar = 2 + got.multiExp(curve, infinity, scalars[:1]) + if !got.Equal(&curve.g2Infinity) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{1, 0, 0, 0} // scalar = 1 + got.multiExp(curve, infinity, scalars[:1]) + if !got.Equal(&curve.g2Infinity) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{0, 0, 0, 0} // scalar = 0 + got.multiExp(curve, infinity, scalars[:1]) + if !got.Equal(&curve.g2Infinity) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)} // scalar == (4-word maxuint) + got.multiExp(curve, infinity, scalars[:1]) + if !got.Equal(&curve.g2Infinity) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + + // two input points: p[1], curve.g2Infinity + twoPoints := []G2Jac{p[1], curve.g2Infinity} + + scalars[0] = fr.Element{32394, 0, 0, 0} // single-word scalar + scalars[1] = fr.Element{2, 0, 0, 0} // scalar = 2 + got.multiExp(curve, twoPoints, scalars[:2]) + if !got.Equal(&p[6]) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{2, 0, 0, 0} // scalar = 2 + scalars[1] = fr.Element{1, 0, 0, 0} // scalar = 1 + got.multiExp(curve, twoPoints, scalars[:2]) + if !got.Equal(&p[5]) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{1, 0, 0, 0} // scalar = 1 + scalars[1] = fr.Element{0, 0, 0, 0} // scalar = 0 + got.multiExp(curve, twoPoints, scalars[:2]) + if !got.Equal(&p[1]) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{0, 0, 0, 0} // scalar = 0 + scalars[1] = fr.Element{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)} // scalar == (4-word maxuint) + got.multiExp(curve, twoPoints, scalars[:2]) + if !got.Equal(&curve.g2Infinity) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)} // scalar == (4-word maxuint) + scalars[1] = fr.Element{32394, 0, 0, 0} // single-word scalar + got.multiExp(curve, twoPoints, scalars[:2]) + if !got.Equal(&p[21]) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + + // TODO: Jacobian points with nontrivial Z coord? } func TestMultiExpG2(t *testing.T) { @@ -113,19 +346,15 @@ func testPointsG2MultiExp(n int) (points []G2Jac, scalars []fr.Element) { // To ensure a diverse selection of scalars that use all words of an fr.Element, // each scalar should be a power of a large generator of fr. - // 22 is a small generator of fr for bls377. - // 2^{31}-1 is prime, so 22^{2^31}-1} is a large generator of fr for bls377 - // generator in Montgomery form var scalarGenMont fr.Element - scalarGenMont.SetString("7716837800905789770901243404444209691916730933998574719964609384059111546487") - + scalarGenMont.SetString("42033899646658082535995012643440421268349534540760060111646640675404812871419") scalars[0].Set(&scalarGenMont).FromMont() var curScalarMont fr.Element // Montgomery form curScalarMont.Set(&scalarGenMont) for i := 1; i < len(scalars); i++ { - curScalarMont.MulAssign(&scalarGenMont) - scalars[i].Set(&curScalarMont).FromMont() // scalars[i] = scalars[0]^i + curScalarMont.MulAssign(&scalarGenMont) // scalars[i] = scalars[0]^i + scalars[i].Set(&curScalarMont).FromMont() } return points, scalars @@ -137,6 +366,62 @@ func testPointsG2MultiExp(n int) (points []G2Jac, scalars []fr.Element) { var benchResG2 G2Jac +func BenchmarkG2ScalarMul(b *testing.B) { + + curve := BLS381() + p := testPointsG2() + + var scalar fr.Element + scalar.SetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + p[1].ScalarMul(curve, &p[1], scalar) + b.StopTimer() + scalar.SetRandom() + b.StartTimer() + } + +} + +func BenchmarkG2Add(b *testing.B) { + + curve := BLS381() + p := testPointsG2() + + b.ResetTimer() + for i := 0; i < b.N; i++ { + benchResG2 = p[1] + benchResG2.Add(curve, &p[2]) + } + +} + +func BenchmarkG2AddMixed(b *testing.B) { + + p := testPointsG2() + _p2 := G2Affine{} + p[2].ToAffineFromJac(&_p2) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + benchResG2 = p[1] + benchResG2.AddMixed(&_p2) + } + +} + +func BenchmarkG2Double(b *testing.B) { + + p := testPointsG2() + + b.ResetTimer() + for i := 0; i < b.N; i++ { + benchResG2 = p[1] + benchResG2.Double() + } + +} + func BenchmarkG2WindowedMultiExp(b *testing.B) { curve := BLS381() diff --git a/ecc/bls381/testpoints_test.go b/ecc/bls381/testpoints_test.go index f1bf13fbff..a0018ae37a 100644 --- a/ecc/bls381/testpoints_test.go +++ b/ecc/bls381/testpoints_test.go @@ -149,5 +149,139 @@ func testPointsG2() []G2Jac { "1", "0") + // p[7] to p[16] not replicated from bls377 + + // p17, p18, 19 * multiExp s1, s2, s3 = p20 + // s1 := [4]uint64{23872983, 238203802, 9827897384, 2372} + // s2 := [4]uint64{128923, 2878236, 398478, 187970707} + // s3 := [4]uint64{9038947, 3947970, 29080823, 282739} + p[17].X.SetString( + "2202586612900994873063608552841973917436690599769271351619758785779549040922297408971872949745387444534381685191191", + "3464776149541825301602496274039842806938444644899411525347342674758277617954130969607745175930233761413583223644182") + p[17].Y.SetString( + "507426788540992755676907019092555296361180575897063872461245419726679987620568924388374760274845235898119538081619", + "3691885784341839275587505587751732069423717818048149148072924556673370797769298089292481194066529224981666380678024") + p[17].Z.SetString( + "1", + "0") + + p[18].X.SetString( + "2755933130101908962709786556737093741356293514040913750947518614142366457564507460693406402662114000824917918204705", + "3389937467249190203473940661807417991739348463603284924068815586042297827971806542963081393795040217333009710785286") + p[18].Y.SetString( + "715188382044380789549292371514692343202085269668949063202459756137923176367594659257534275389325852962125763348005", + "507529072093281807048934908207023087905587479009036705146959338329271035317213316249865622576465338615278124998730") + p[18].Z.SetString( + "1", + "0") + + p[19].X.SetString( + "2009638089140076443804417159590254694154060033899241601761094660925956841848674079695857855434136260467032911899935", + "3287140504760183715903129913367996792793209583122547900517542365929720306105887550202981732139558499070590424934757") + p[19].Y.SetString( + "699686293084588933897711839832926149809430649920959708760119529593696515224910449991081462094697986726628407964072", + "1863419544743841284837633939534350991741562571162789312166261686839585147155103444863480292261673970876360505794250") + p[19].Z.SetString( + "1", + "0") + + // p20 == res of multi exp + p[20].X.SetString( + "84529039374666718277529700946262418737172638462598583376813745906761085133933616610464713836999970246740835498124", + "200788104950560778986481389818843697550292411565834125694594224528648354986559524649660524742379207895349368042801") + p[20].Y.SetString( + "1198622988276120327657471540224092304474598960375185430941756130765837204246790977379976326351639122526524374956807", + "2293005577597025110092666752964021782402844612125091970146124038789992153640537203837709198912206199326741287945771") + p[20].Z.SetString( + "1", + "0") + + // p21 == (4-word maxuint)*p1 + p[21].X.SetString( + "1226003647875516422282934775512085514143566766842114591042686375996582274001361707970589616597986014664003776987242", + "3245586245768149809337716635590889405115525957977411403876917607016670800879063600981654304393718006814005020211411") + p[21].Y.SetString( + "3679164383760787456650091727622997807797410699239459771765975075010303507725746646626614950133386665671884609926180", + "422880483224654014725925354054823171264923607444001980764353345379792196609154566011444360276228231588947993617755") + p[21].Z.SetString( + "1", + "0") + return p[:] } + +func testPointsG1MultiExpResults() (numPoints []int, results []G1Jac) { + + // numPoints = []int{3, 10, 100, 1000, 10000, 40000, 100000} + numPoints = []int{3, 10, 100, 1000, 10000} + results = make([]G1Jac, len(numPoints)) + + // results[i] is the correct result of a call to MultiExp() with points, scalars obtained from testPointsG1MultiExp(numPoints[i]) + results[0].X.SetString("1063668066206625393886898675997136214519953936093872959699938669245133689229546210233201454713897568141649096059308") + results[0].Y.SetString("3728670671166849093711364979467466074553186302210399493199938182187213090744918640000186701736929258655568313052903") + results[0].Z.SetString("1") + + results[1].X.SetString("284444052298236836388689630108831180912940788279073520254045272904443704081674588280028548005868979748929051041579") + results[1].Y.SetString("843601811327511620566905929790133509921660019145394752670956999738901615454236294001383413244525345930806565029129") + results[1].Z.SetString("1") + + results[2].X.SetString("91165781391259207903108016760058594160349920951432176972803268365212065293197282668190228876621475752302813448449") + results[2].Y.SetString("2446275390591568525236111901899004014345400155077298625839271762654303634586249005893446826364526048915596910346983") + results[2].Z.SetString("1") + + results[3].X.SetString("938224670186625310542570182651690777277803845252857755644145658816265062443214627106355868532761513188921327812873") + results[3].Y.SetString("3392623173618832298639155082927383636897941885150668189269416898164534770216187204547547652476448731144060021113156") + results[3].Z.SetString("1") + + results[4].X.SetString("75329938957966753928355270083376891464301958841562844596878147519056439445770609127149425991713848252478235124012") + results[4].Y.SetString("3139579621803091316970578735415038976252909469250676909467422456705947580617567925663074825186869748256014846158903") + results[4].Z.SetString("1") + + // results[5].X.SetString("174726425602612409871117349550442447793392830539428091034317231404863071348963900550105936476769273104441605387471") + // results[5].Y.SetString("78667243717276722997367850074282147024960711878205676784883024627806097669419139243867546374951219178316064697147") + // results[5].Z.SetString("1") + + // results[6].X.SetString("138671866875049014460325223627448433792468765135069488284141862889475194960245595363099811289409216974304797784683") + // results[6].Y.SetString("181164511376313563167278130122243418652082373082573007445455589404606795890548834473895883485588067757132508312576") + // results[6].Z.SetString("1") + + return numPoints, results +} + +func testPointsG2MultiExpResults() (numPoints []int, results []G2Jac) { + + // numPoints = []int{3, 10, 100, 1000, 10000, 40000, 100000} + numPoints = []int{3, 10, 100, 1000, 10000} + results = make([]G2Jac, len(numPoints)) + + // results[i] is the correct result of a call to MultiExp() with points, scalars obtained from testPointsG1MultiExp(numPoints[i]) + results[0].X.SetString("2596940579533731777456758084512876982460616783564451603441163549410329535860250548558023782513784206872055019283053", "3121647695118252935422799417096029466378050162208393342451785281738777557575274326326704229766525387057913584200933") + results[0].Y.SetString("3220487432194437157830604673386728027313260291427773637707915060199079879321600401317875750798325628734098677555635", "1053141739159111372905482239084662956734573628209948201240248312447967757804798727043155850274673237897545377955303") + results[0].Z.SetString("1", "0") + + results[1].X.SetString("2051082072965948978760493076682262498193009485656548582760358487669072113188138707820101130627851820255228861294231", "1927662243715221603780671965507813009304744487742752405640292249565383689318799519072462774802883474639409725301872") + results[1].Y.SetString("3996548275835622483004408294477349301101844363095689541864171242805054126687881971594794090395506191170440804280893", "3986626825041131871509201886901429271763318143573979643243559966023155529029255778937462689568079056390153816329491") + results[1].Z.SetString("1", "0") + + results[2].X.SetString("2250171021255861868586029487840199495875436202361187537523654507707406227912057209503127341255305872764284724019755", "1919855706574790408369722950923866090481641818233628500890991492733492387525497729745017865543347054374991222156238") + results[2].Y.SetString("305768928596197415528087082464614516405931978104797851095998972639223828616256884865917793600369161754953080579461", "2801741067835790372499927654858730896044545796776815791503409937639790676039228713369459482079841946758605856351160") + results[2].Z.SetString("1", "0") + + results[3].X.SetString("3568003272251257010091075548760262619086593984826342088801838323984743277354720913926370748654905141396306049466298", "126725153604270953162844848049690968046481359929272814346181106914674675713040469808097195947963538843946681887946") + results[3].Y.SetString("2074160998254058296031497324375121245752338813895238201500273300742330457308350633287173150545968499651147177447157", "267810771878668212014080014580442108305304166358659045989333623004284348574808010767307265685282049524515903708940") + results[3].Z.SetString("1", "0") + + results[4].X.SetString("3263848000351048585697979022205461817787053941895406719470350712435086752969502658918465402626221251111579793760697", "1044967064007802175246713933555223514018209768839491573115395743890333686857917989769735921536094217180818121145229") + results[4].Y.SetString("3166117077335756221007288061936791717037282545266096611106725004521113492072777827931355825497185226986112700523730", "368500512569199316549789951676133774771913030542685495176280618016237847444007718847908629432641700917812994076185") + results[4].Z.SetString("1", "0") + + // results[5].X.SetString("201807775096989966680767386931709910109379987129950282337816764673393112014814630555568113030518691051087881679000", "110030068071180046294243738844362032878145181870079171976251969030556962132577022410169004282737772794226662913103") + // results[5].Y.SetString("56844626940924884826885517611993278692743014349326655935956149147898701499013033691800787951228822587399193027994", "242276761124031297290914712351169949160095935055733945943210598350408812424612707018929301956794274916286562370826") + // results[5].Z.SetString("1", "0") + + // results[6].X.SetString("33514021694280699508968035027077166613025356836264586532410525622610950855527033829392500778367194475694813270427", "215157238962893988211570897268792861887454317579185078199804937830755862734494408568360944443760891144549210691374") + // results[6].Y.SetString("134836144050657451785051205208586077741559724544344739454701286920723433111216706834743856501190637179999982011926", "56936738555332765978668695896266799297487692241196801589915736548731583606115317075635100125794623933574467744418") + // results[6].Z.SetString("1", "0") + + return numPoints, results +} diff --git a/ecc/bn256/g1_test.go b/ecc/bn256/g1_test.go index b48f18c2d1..a62c1ec8ec 100644 --- a/ecc/bn256/g1_test.go +++ b/ecc/bn256/g1_test.go @@ -105,27 +105,26 @@ func TestG1JacScalarMul(t *testing.T) { func TestG1JacMultiExp(t *testing.T) { curve := BN256() - // var points []G1Jac + var points []G1Jac var scalars []fr.Element var got G1Jac // // Test 1: testPointsG1multiExp // - // TODO why is this commented? - // numPoints, wants := testPointsG1MultiExpResults() + numPoints, wants := testPointsG1MultiExpResults() - // for i := range numPoints { - // if numPoints[i] > 10000 { - // continue - // } - // points, scalars = testPointsG1MultiExp(numPoints[i]) + for i := range numPoints { + if numPoints[i] > 10000 { + continue + } + points, scalars = testPointsG1MultiExp(numPoints[i]) - // got.multiExp(curve, points, scalars) - // if !got.Equal(&wants[i]) { - // t.Error("multiExp G1Jac fail for points:", numPoints[i]) - // } - // } + got.multiExp(curve, points, scalars) + if !got.Equal(&wants[i]) { + t.Error("multiExp G1Jac fail for points:", numPoints[i]) + } + } // // Test 2: testPointsG1() @@ -133,9 +132,9 @@ func TestG1JacMultiExp(t *testing.T) { p := testPointsG1() // scalars - s1 := fr.Element{23872983, 238203802, 9827897384, 2372} - s2 := fr.Element{128923, 2878236, 398478, 187970707} - s3 := fr.Element{9038947, 3947970, 29080823, 282739} + s1 := fr.Element{23872983, 238203802, 9827897384, 2372} // 14889285316340551032002176131108485811963550694615991316137431 + s2 := fr.Element{128923, 2878236, 398478, 187970707} // 1179911251111561301561648964820473185772012989930899737079831459739 + s3 := fr.Element{9038947, 3947970, 29080823, 282739} // 1774781467561494742381858548177178844765555009630735687022668899 scalars = []fr.Element{ s1, @@ -347,19 +346,15 @@ func testPointsG1MultiExp(n int) (points []G1Jac, scalars []fr.Element) { // To ensure a diverse selection of scalars that use all words of an fr.Element, // each scalar should be a power of a large generator of fr. - // 22 is a small generator of fr for bls377. - // 2^{31}-1 is prime, so 22^{2^31}-1} is a large generator of fr for bls377 - // generator in Montgomery form var scalarGenMont fr.Element - scalarGenMont.SetString("7716837800905789770901243404444209691916730933998574719964609384059111546487") - + scalarGenMont.SetString("18147194858733678592031140175294542593979808267792252765512745512101703194607") scalars[0].Set(&scalarGenMont).FromMont() var curScalarMont fr.Element // Montgomery form curScalarMont.Set(&scalarGenMont) for i := 1; i < len(scalars); i++ { - curScalarMont.MulAssign(&scalarGenMont) - scalars[i].Set(&curScalarMont).FromMont() // scalars[i] = scalars[0]^i + curScalarMont.MulAssign(&scalarGenMont) // scalars[i] = scalars[0]^i + scalars[i].Set(&curScalarMont).FromMont() } return points, scalars diff --git a/ecc/bn256/g2_test.go b/ecc/bn256/g2_test.go index 521871c085..3648c2deb7 100644 --- a/ecc/bn256/g2_test.go +++ b/ecc/bn256/g2_test.go @@ -8,8 +8,241 @@ import ( "github.com/consensys/gnark/ecc/bn256/fr" ) -func TestG2NotReallyHere(t *testing.T) { - t.Skip("testPointsG2() not available?") +func TestG2JacToAffineFromJac(t *testing.T) { + + p := testPointsG2() + + _p := G2Affine{} + p[0].ToAffineFromJac(&_p) + if !_p.X.Equal(&p[1].X) || !_p.Y.Equal(&p[1].Y) { + t.Fatal("ToAffineFromJac failed") + } + +} + +func TestG2Conv(t *testing.T) { + p := testPointsG2() + + for i := 0; i < len(p); i++ { + var pJac G2Jac + var pAff G2Affine + p[i].ToAffineFromJac(&pAff) + pAff.ToJacobian(&pJac) + if !pJac.Equal(&p[i]) { + t.Fatal("jacobian to affine to jacobian fails") + } + } +} + +func TestG2JacAdd(t *testing.T) { + + curve := BN256() + p := testPointsG2() + + // p3 = p1 + p2 + p1 := p[1].Clone() + _p2 := G2Affine{} + p[2].ToAffineFromJac(&_p2) + p[1].AddMixed(&_p2) + p[2].Add(curve, p1) + + if !p[3].Equal(&p[1]) { + t.Fatal("Add failed") + } + + // test commutativity + if !p[3].Equal(&p[2]) { + t.Fatal("Add failed") + } +} + +func TestG2JacSub(t *testing.T) { + + curve := BN256() + p := testPointsG2() + + // p4 = p1 - p2 + p[1].Sub(curve, p[2]) + + if !p[4].Equal(&p[1]) { + t.Fatal("Sub failed") + } +} + +func TestG2JacDouble(t *testing.T) { + + curve := BN256() + p := testPointsG2() + + // p5 = 2 * p1 + p[1].Double() + if !p[5].Equal(&p[1]) { + t.Fatal("Double failed") + } + + G := curve.g2Infinity.Clone() + R := curve.g2Infinity.Clone() + G.Double() + + if !G.Equal(R) { + t.Fatal("Double failed (infinity case)") + } +} + +func TestG2JacScalarMul(t *testing.T) { + + curve := BN256() + p := testPointsG2() + + // p6 = [p1]32394 (scalar mul) + scalar := fr.Element{32394} + p[1].ScalarMul(curve, &p[1], scalar) + + if !p[1].Equal(&p[6]) { + t.Error("ScalarMul failed") + } +} + +func TestG2JacMultiExp(t *testing.T) { + curve := BN256() + var points []G2Jac + var scalars []fr.Element + var got G2Jac + + // + // Test 1: testPointsG2multiExp + // + numPoints, wants := testPointsG2MultiExpResults() + + for i := range numPoints { + if numPoints[i] > 10000 { + continue + } + points, scalars = testPointsG2MultiExp(numPoints[i]) + + got.multiExp(curve, points, scalars) + if !got.Equal(&wants[i]) { + t.Error("multiExp G2Jac fail for points:", numPoints[i]) + } + } + + // + // Test 2: testPointsG2() + // + p := testPointsG2() + + // scalars + s1 := fr.Element{23872983, 238203802, 9827897384, 2372} // 14889285316340551032002176131108485811963550694615991316137431 + s2 := fr.Element{128923, 2878236, 398478, 187970707} // 1179911251111561301561648964820473185772012989930899737079831459739 + s3 := fr.Element{9038947, 3947970, 29080823, 282739} // 1774781467561494742381858548177178844765555009630735687022668899 + + scalars = []fr.Element{ + s1, + s2, + s3, + } + + got.multiExp(curve, p[17:20], scalars) + if !got.Equal(&p[20]) { + t.Error("multiExp G2Jac failed") + } + + // + // Test 3: edge cases + // + + // one input point p[1] + scalars[0] = fr.Element{32394, 0, 0, 0} // single-word scalar + got.multiExp(curve, p[1:2], scalars[:1]) + if !got.Equal(&p[6]) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + + scalars[0] = fr.Element{2, 0, 0, 0} // scalar = 2 + got.multiExp(curve, p[1:2], scalars[:1]) + if !got.Equal(&p[5]) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{1, 0, 0, 0} // scalar = 1 + got.multiExp(curve, p[1:2], scalars[:1]) + if !got.Equal(&p[1]) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{0, 0, 0, 0} // scalar = 0 + got.multiExp(curve, p[1:2], scalars[:1]) + if !got.Equal(&curve.g2Infinity) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)} // scalar == (4-word maxuint) + got.multiExp(curve, p[1:2], scalars[:1]) + if !got.Equal(&p[21]) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + + // one input point curve.g2Infinity + infinity := []G2Jac{curve.g2Infinity} + + scalars[0] = fr.Element{32394, 0, 0, 0} // single-word scalar + got.multiExp(curve, infinity, scalars[:1]) + if !got.Equal(&curve.g2Infinity) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{2, 0, 0, 0} // scalar = 2 + got.multiExp(curve, infinity, scalars[:1]) + if !got.Equal(&curve.g2Infinity) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{1, 0, 0, 0} // scalar = 1 + got.multiExp(curve, infinity, scalars[:1]) + if !got.Equal(&curve.g2Infinity) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{0, 0, 0, 0} // scalar = 0 + got.multiExp(curve, infinity, scalars[:1]) + if !got.Equal(&curve.g2Infinity) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)} // scalar == (4-word maxuint) + got.multiExp(curve, infinity, scalars[:1]) + if !got.Equal(&curve.g2Infinity) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + + // two input points: p[1], curve.g2Infinity + twoPoints := []G2Jac{p[1], curve.g2Infinity} + + scalars[0] = fr.Element{32394, 0, 0, 0} // single-word scalar + scalars[1] = fr.Element{2, 0, 0, 0} // scalar = 2 + got.multiExp(curve, twoPoints, scalars[:2]) + if !got.Equal(&p[6]) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{2, 0, 0, 0} // scalar = 2 + scalars[1] = fr.Element{1, 0, 0, 0} // scalar = 1 + got.multiExp(curve, twoPoints, scalars[:2]) + if !got.Equal(&p[5]) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{1, 0, 0, 0} // scalar = 1 + scalars[1] = fr.Element{0, 0, 0, 0} // scalar = 0 + got.multiExp(curve, twoPoints, scalars[:2]) + if !got.Equal(&p[1]) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{0, 0, 0, 0} // scalar = 0 + scalars[1] = fr.Element{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)} // scalar == (4-word maxuint) + got.multiExp(curve, twoPoints, scalars[:2]) + if !got.Equal(&curve.g2Infinity) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + scalars[0] = fr.Element{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)} // scalar == (4-word maxuint) + scalars[1] = fr.Element{32394, 0, 0, 0} // single-word scalar + got.multiExp(curve, twoPoints, scalars[:2]) + if !got.Equal(&p[21]) { + t.Error("multiExp G2Jac failed, scalar:", scalars[0]) + } + + // TODO: Jacobian points with nontrivial Z coord? } func TestMultiExpG2(t *testing.T) { @@ -113,19 +346,15 @@ func testPointsG2MultiExp(n int) (points []G2Jac, scalars []fr.Element) { // To ensure a diverse selection of scalars that use all words of an fr.Element, // each scalar should be a power of a large generator of fr. - // 22 is a small generator of fr for bls377. - // 2^{31}-1 is prime, so 22^{2^31}-1} is a large generator of fr for bls377 - // generator in Montgomery form var scalarGenMont fr.Element - scalarGenMont.SetString("7716837800905789770901243404444209691916730933998574719964609384059111546487") - + scalarGenMont.SetString("18147194858733678592031140175294542593979808267792252765512745512101703194607") scalars[0].Set(&scalarGenMont).FromMont() var curScalarMont fr.Element // Montgomery form curScalarMont.Set(&scalarGenMont) for i := 1; i < len(scalars); i++ { - curScalarMont.MulAssign(&scalarGenMont) - scalars[i].Set(&curScalarMont).FromMont() // scalars[i] = scalars[0]^i + curScalarMont.MulAssign(&scalarGenMont) // scalars[i] = scalars[0]^i + scalars[i].Set(&curScalarMont).FromMont() } return points, scalars @@ -137,6 +366,62 @@ func testPointsG2MultiExp(n int) (points []G2Jac, scalars []fr.Element) { var benchResG2 G2Jac +func BenchmarkG2ScalarMul(b *testing.B) { + + curve := BN256() + p := testPointsG2() + + var scalar fr.Element + scalar.SetRandom() + b.ResetTimer() + for i := 0; i < b.N; i++ { + p[1].ScalarMul(curve, &p[1], scalar) + b.StopTimer() + scalar.SetRandom() + b.StartTimer() + } + +} + +func BenchmarkG2Add(b *testing.B) { + + curve := BN256() + p := testPointsG2() + + b.ResetTimer() + for i := 0; i < b.N; i++ { + benchResG2 = p[1] + benchResG2.Add(curve, &p[2]) + } + +} + +func BenchmarkG2AddMixed(b *testing.B) { + + p := testPointsG2() + _p2 := G2Affine{} + p[2].ToAffineFromJac(&_p2) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + benchResG2 = p[1] + benchResG2.AddMixed(&_p2) + } + +} + +func BenchmarkG2Double(b *testing.B) { + + p := testPointsG2() + + b.ResetTimer() + for i := 0; i < b.N; i++ { + benchResG2 = p[1] + benchResG2.Double() + } + +} + func BenchmarkG2WindowedMultiExp(b *testing.B) { curve := BN256() diff --git a/ecc/bn256/testpoints_test.go b/ecc/bn256/testpoints_test.go index b347e3b734..003385c902 100644 --- a/ecc/bn256/testpoints_test.go +++ b/ecc/bn256/testpoints_test.go @@ -4,7 +4,6 @@ func testPointsG1() []G1Jac { var p [22]G1Jac // p0 - // TODO don't know how to generate points in Jacobian form in sage p[0].X.SetString("16136477863895212049116837538159456976053980364000089191811312707815806892427") p[0].Y.SetString("4310293206130354412480322090271321698513108961683717502632485513758245842731") p[0].Z.SetString("1234") @@ -70,85 +69,219 @@ func testPointsG1() []G1Jac { return p[:] } -// func testPointsG2() []G2Jac { - -// var p [22]G2Jac - -// // p0 -// p[0].X.SetString( -// "2004970593981567740370369434353185716177956995681873131806513578915171518042974867779686738194168556722043467439973", -// "130296815349073351363233179092671862558862576036785156614277722952675134780387423861649705291813398926563594457471") -// p[0].Y.SetString( -// "3369164521789284642999273622633545831809622716593431525634112388870994473970980352836941579236492973396990323872004", -// "1513535608590884453838490831502094356439707185352678339702344091973726148020269065969272043729759094443100178505394") -// p[0].Z.SetString( -// "4", -// "5") - -// // p1 = p0.ToAffineFromJac -// p[1].X.SetString( -// "3530486458255518483646657753300465068233361547001606344843397309332648122759199161038835588610138188998735896249365", -// "556359626370552735366469208656132171537953714011244503981293113570685962099899069626710494303020175970496332053819") -// p[1].Y.SetString( -// "688206249007371037300932698574694060421430775835917018620054976409346176157603328155654383245339911153033552044328", -// "159347828284068266532164708674697800959559338289778389611370325567206642394897182319932651433026161219393286360146") -// p[1].Z.SetString( -// "1", -// "0") - -// // p2 -// p[2].X.SetString( -// "197413270562807690745656892442795252389967589761886091356130693428843994549103474407990204434784430379880520506244", -// "2966075435814405027288619687471854377740680678626013143798209545087260963188657609741075513234516032013681364796552") -// p[2].Y.SetString( -// "2147601649225450814936088801320441937023172243578255854811214584520776577932800128320192525549821917751472838738061", -// "341918327827836780738320776077912197453555729459780664879765279914792098943423412544527938211197886285793026781150") -// p[2].Z.SetString( -// "1", -// "0") - -// // p3 = p1 + p2 -// p[3].X.SetString( -// "1237053023188090217416331093931490387538239908576013126186652051303057354770718797724346067258878379356294772424598", -// "89027191981628286663121839960122619575658354038856765080163991156649604671230564997966839333055129246114658951260") -// p[3].Y.SetString( -// "2408237036380763312629162352108023995112090550462461649682551345684445385346941042669141258298839309106546349839675", -// "168858193311407630557037812473265030312950243680383653854192555532696630731492117702567964122283584498909346837915") -// p[3].Z.SetString( -// "1", -// "0") - -// // p4 = p1 - p2 -// p[4].X.SetString( -// "2808227530904945854514239082616775638950945975668518623228206527451582114737689628483058689902839046970715398346940", -// "2092923305300078907398884324285952111074442511080067446455483697972997333674476537493287111344909940716772530911824") -// p[4].Y.SetString( -// "9029170194298821312406015223423031712875462840471533167314997970084704720279248482719254821825277050842703978963", -// "1791528790377798316835005915999796866680140927420012663122980378694709081540761137828414038843654827432461031049980") -// p[4].Z.SetString( -// "1", -// "0") - -// // p5 = 2 * p1 -// p[5].X.SetString( -// "3630316824791380774225593152558365502064856753475309411502269130729689479204492718861472887099289921648171470386045", -// "3308431947200670016156312747022703395534013548589857669127747813912952972353052651859427627507243154371458537118354") -// p[5].Y.SetString("2241144403084318756929829373385307633720396011831626665277133645700492971686858781396857856283291921163666824908637", -// "1779226401414592123686108370119990686867136392371717495028159487826154349395920535560335272072186878968501138903591") -// p[5].Z.SetString( -// "1", -// "0") - -// // p6 = [p1]32394 (scalar mul) -// p[6].X.SetString( -// "2959926218980789340685315297176523062770280227251831416616582630833820527728724524275383620970768393444521817013684", -// "1415873966012981853017046488708460583169124961917426224289346004415869228910183058143842933009876946349420773870661") -// p[6].Y.SetString( -// "111261742887494713538668775238298274865185947357398396022404291690169138934298381772988232727438601108079100711153", -// "1730016633762742417476569654040523075813392630204052190533170579166957859372406074194863335322197611607906287556326") -// p[6].Z.SetString( -// "1", -// "0") - -// return p[:] -// } +func testPointsG2() []G2Jac { + + var p [22]G2Jac + + // p0 + p[0].X.SetString( + "4295563638500786782562963921232374813036557810495924581926808279272960428403", + "20977085216808592083342070517943147456450208828675775160411834193549098728773") + p[0].Y.SetString( + "7195742981034666332293377284887193189475668460604120107733908587369501685142", + "4507890142277109789182876409717501963673566088418605592669633257980200221329") + p[0].Z.SetString( + "4", + "5") + + // p1 = p0.ToAffineFromJac + p[1].X.SetString( + "21387829499166991439154279460029636119801876889632880718297279566941547053111", + "2741234276868653584412455034302568783762372659624442005776105153582157075344") + p[1].Y.SetString( + "17336653084963236202906880963508617370681486526772544590154653923697387100352", + "8707084505271241013609523947582819156486382703230158869759248651064216080275") + p[1].Z.SetString( + "1", + "0") + + // p2 + p[2].X.SetString( + "11506439749177368052947928630536758329808063398830617846794148000224637753146", + "14791918325418497703371055041272272025221888631511120661766263175637653198851") + p[2].Y.SetString( + "10191457944050009344740987438037235040130352882256368265051633619951296239157", + "13261069725461908577834580451944689961963884282683160677158169046841105073946") + p[2].Z.SetString( + "1", + "0") + + // p3 = p1 + p2 + p[3].X.SetString( + "17521250374706321200455118782485091239656441888563049833651823860373848152220", + "20306929681196427434080926292344051943185841002051785079399704219072510130455") + p[3].Y.SetString( + "1175230638610719718942789338918950355539207516516531988101380669408791523461", + "15629689716347290414575487807245635888817139965107937678396560757579542643842") + p[3].Z.SetString( + "1", + "0") + + // p4 = p1 - p2 + p[4].X.SetString( + "16646958125318885474119398946320407516015482751022906749995931667412462869035", + "3979250317133682244387190247613728464032807963121149039767856511773333702564") + p[4].Y.SetString( + "11418227128794009249331777002337315743744979940751734539813234734692005147785", + "10603450518475646195174296956743056621401212933063784362005192388098594584899") + p[4].Z.SetString( + "1", + "0") + + // p5 = 2 * p1 + p[5].X.SetString( + "5085451634826807655626759668932704593491693236811826377942879653889090073049", + "4991973513180050454833046201112245473015734832486642010051753360563312734056") + p[5].Y.SetString("5895517549418633969651468090145401251289416716871872376582568639053531760558", + "14056756068619140853880989887863076968884520609043416067288213847281641388771") + p[5].Z.SetString( + "1", + "0") + + // p6 = [p1]32394 (scalar mul) + p[6].X.SetString( + "13617885012148396053642778724119601755128151941089641093879946080723533552385", + "19062077248354334522033848410070266052003600057390107360812250621931426446838") + p[6].Y.SetString( + "2873041414167462272072084997952603485490628440269764977378778099934979597754", + "18900397334006643067990111059064421657448927728690307894304857802649868328287") + p[6].Z.SetString( + "1", + "0") + + // p[7] to p[16] not replicated from bls377 + + // p17, p18, 19 * multiExp s1, s2, s3 = p20 + // s1 := [4]uint64{23872983, 238203802, 9827897384, 2372} + // s2 := [4]uint64{128923, 2878236, 398478, 187970707} + // s3 := [4]uint64{9038947, 3947970, 29080823, 282739} + p[17].X.SetString( + "6280675843406923423316577600694888964906884321223372185103519887130090681586", + "8821942975381774136714919814137866692593095695696579066184029147639380756053") + p[17].Y.SetString( + "21489578689446628847970496562663898952159199396354792262009753994345722371137", + "12047855003950897118227177488944366071399100026873185768816438152506000440310") + p[17].Z.SetString( + "1", + "0") + + p[18].X.SetString( + "18266812961165398549109340760236448719896058417781697590625535383067895697932", + "16683922768892478180629924100966398567151929928306131494048052550782299250946") + p[18].Y.SetString( + "11791443923461319423786343526502961253682992961425824797867216643811420044924", + "14998158673246010817593312050844027929887481968470709334757728911713710697704") + p[18].Z.SetString( + "1", + "0") + + p[19].X.SetString( + "21797933274118352007115220575798226586484731209922884549121696782667950145379", + "21383956343663430919785656200947328515609176972789864030966076987379471942163") + p[19].Y.SetString( + "1140783183542840884659090975032382234564626261784168184867723083088536708172", + "5100014377801226636905268226734489236804662610935379352274814439572272315171") + p[19].Z.SetString( + "1", + "0") + + // p20 == res of multi exp + p[20].X.SetString( + "12282266978735816148546013491102423669144880803788931202287771058183967994366", + "5616834333011604201884399636592175069996776392856335991211512004025520046290") + p[20].Y.SetString( + "30609250202525430259708479663717288178564698613768989993668270210247489639", + "9322483171062908304513694365813752998874360082623919344536978945259902528193") + p[20].Z.SetString( + "1", + "0") + + // p21 == (4-word maxuint)*p1 + p[21].X.SetString( + "14395003398603548562761429015090433265863932002299407527254596723612849782759", + "5720634663221903819765119717594189965145433905346515625885800457099494825451") + p[21].Y.SetString( + "9360100162291804786377167894540736531588090470400632366225052479696467660278", + "15142355968451824193638947718908774056025313920775979380118561380284965762558") + p[21].Z.SetString( + "1", + "0") + + return p[:] +} + +func testPointsG1MultiExpResults() (numPoints []int, results []G1Jac) { + + // numPoints = []int{3, 10, 100, 1000, 10000, 40000, 100000} + numPoints = []int{3, 10, 100, 1000, 10000} + results = make([]G1Jac, len(numPoints)) + + // results[i] is the correct result of a call to MultiExp() with points, scalars obtained from testPointsG1MultiExp(numPoints[i]) + results[0].X.SetString("21823068321801324264246932177565542007558933997910700825630665687278407072755") + results[0].Y.SetString("16363490754264238285158153641602398262936592272245759447416429802071216556398") + results[0].Z.SetString("1") + + results[1].X.SetString("13815345236147268646421076867730742869957813854411453959377257350757210271364") + results[1].Y.SetString("17682266209456948512040738671875089228616964163743186073941786345441281452536") + results[1].Z.SetString("1") + + results[2].X.SetString("3288974316043067651372453043431675392510574138108409176384584315895377745646") + results[2].Y.SetString("3238875461451030501940937494636334577607188587872244018526219126218967297852") + results[2].Z.SetString("1") + + results[3].X.SetString("3246358504018312280490136845807124125588025188566651933500100317911192805668") + results[3].Y.SetString("21382468183726643863380489724459807507925550816522642135958492994154820495151") + results[3].Z.SetString("1") + + results[4].X.SetString("7986938277825977167717629829088835068193140040586187858716846674113015653253") + results[4].Y.SetString("8528498341058869644414978903704909806405107236392482536715709223267487086501") + results[4].Z.SetString("1") + + // results[5].X.SetString("174726425602612409871117349550442447793392830539428091034317231404863071348963900550105936476769273104441605387471") + // results[5].Y.SetString("78667243717276722997367850074282147024960711878205676784883024627806097669419139243867546374951219178316064697147") + // results[5].Z.SetString("1") + + // results[6].X.SetString("138671866875049014460325223627448433792468765135069488284141862889475194960245595363099811289409216974304797784683") + // results[6].Y.SetString("181164511376313563167278130122243418652082373082573007445455589404606795890548834473895883485588067757132508312576") + // results[6].Z.SetString("1") + + return numPoints, results +} + +func testPointsG2MultiExpResults() (numPoints []int, results []G2Jac) { + + // numPoints = []int{3, 10, 100, 1000, 10000, 40000, 100000} + numPoints = []int{3, 10, 100, 1000, 10000} + results = make([]G2Jac, len(numPoints)) + + // results[i] is the correct result of a call to MultiExp() with points, scalars obtained from testPointsG1MultiExp(numPoints[i]) + results[0].X.SetString("9744533565299549798811882408400864810917743451440547817726300253373739157614", "2479387564119333310025127498830864681644333631072106936513831370958753531637") + results[0].Y.SetString("6286044029317501759709115603001076408275087437030553245083306533739207946030", "15926185610847029765710142354332817883563703393603345064375006008177007265288") + results[0].Z.SetString("1", "0") + + results[1].X.SetString("16443733177630792654750398116472655777377437265700537410309313050108656182753", "12032003544017166656290055180464392381450852692332913046975887044908077941043") + results[1].Y.SetString("13319626638999726283897002362202261086859428043507635324645636166188602982340", "12220033323617473327344460736800944055957642633914934192630721740534013995312") + results[1].Z.SetString("1", "0") + + results[2].X.SetString("16414050765579347072931326787263094989531433567846869327307424702589123000311", "9275888744814559947125544514127011001174197442679469172557315359924120081348") + results[2].Y.SetString("3605907440182038344700816770018632232794150395010414724676465274304427012143", "9618157707639426906247811447063943037878760866083486416385767675061155561122") + results[2].Z.SetString("1", "0") + + results[3].X.SetString("3319141713357252056396189859078463073123163214795270806282688716743503744214", "17265633798585747628167412971759347990636339789703676764076917541414536663843") + results[3].Y.SetString("4584764017725683921195605422567097987176366014448830578926359936478145427580", "13715834265552892533704722230516871665670449304086243155110400650671944956974") + results[3].Z.SetString("1", "0") + + results[4].X.SetString("16619899412987329916593471127820677878496274980167423702178814519248896008124", "11881005026711950444999168859047426267651773752136329581098085905757433098834") + results[4].Y.SetString("20746951231970086264538435937942269921387258757093926818416964546052070249531", "8734107452357857264844498135371019542973101504295572412973779004020713163761") + results[4].Z.SetString("1", "0") + + // results[5].X.SetString("201807775096989966680767386931709910109379987129950282337816764673393112014814630555568113030518691051087881679000", "110030068071180046294243738844362032878145181870079171976251969030556962132577022410169004282737772794226662913103") + // results[5].Y.SetString("56844626940924884826885517611993278692743014349326655935956149147898701499013033691800787951228822587399193027994", "242276761124031297290914712351169949160095935055733945943210598350408812424612707018929301956794274916286562370826") + // results[5].Z.SetString("1", "0") + + // results[6].X.SetString("33514021694280699508968035027077166613025356836264586532410525622610950855527033829392500778367194475694813270427", "215157238962893988211570897268792861887454317579185078199804937830755862734494408568360944443760891144549210691374") + // results[6].Y.SetString("134836144050657451785051205208586077741559724544344739454701286920723433111216706834743856501190637179999982011926", "56936738555332765978668695896266799297487692241196801589915736548731583606115317075635100125794623933574467744418") + // results[6].Z.SetString("1", "0") + + return numPoints, results +} diff --git a/ecc/internal/generator.go b/ecc/internal/generator.go index 8ce5bbc82d..2ced38651f 100644 --- a/ecc/internal/generator.go +++ b/ecc/internal/generator.go @@ -129,25 +129,25 @@ func main() { }) // test points - // if fMakeTestPoints { + if fMakeTestPoints { - // testInputs := fp2.GenerateTestInputs(fFp) - // var err error - // fp2TemplateData.TestPoints, err = tower.GenerateTestOutputs(testInputs, "../internal/tower/fp2/testpoints.sage", fFp, fFp2) - // if err != nil { - // fmt.Fprintln(os.Stderr, "error:", err) - // os.Exit(-1) - // } - // if !sanityCheck(fp2TemplateData.TestPoints, fp2.Degree) { - // fmt.Fprintln(os.Stderr, "idiot!", err) - // os.Exit(-1) - // } + testInputs := fp2.GenerateTestInputs(fFp) + var err error + fp2TemplateData.TestPoints, err = tower.GenerateTestOutputs(testInputs, "../internal/tower/fp2/testpoints.sage", fFp, fFp2) + if err != nil { + fmt.Fprintln(os.Stderr, "error:", err) + os.Exit(-1) + } + if !sanityCheck(fp2TemplateData.TestPoints, fp2.Degree) { + fmt.Fprintln(os.Stderr, "idiot!", err) + os.Exit(-1) + } - // fp2Data = append(fp2Data, codegenData{ - // path: filepath.Join(fOutputDir, strings.ToLower(fp2TemplateData.Name)+"testpoints_test.go"), - // sources: fp2.CodeTestPoints, - // }) - // } + fp2Data = append(fp2Data, codegenData{ + path: filepath.Join(fOutputDir, strings.ToLower(fp2TemplateData.Name)+"testpoints_test.go"), + sources: fp2.CodeTestPoints, + }) + } if err := generateCode(fp2Data, fp2TemplateData); err != nil { fmt.Fprintln(os.Stderr, "error:", err) @@ -193,25 +193,25 @@ func main() { }) // test points - // if fMakeTestPoints { + if fMakeTestPoints { - // testInputs := fp6.GenerateTestInputs(fFp) - // var err error - // fp6TemplateData.TestPoints, err = tower.GenerateTestOutputs(testInputs, "../internal/tower/fp6/testpoints.sage", fFp, fFp2, fFp6Split[0], fFp6Split[1]) - // if err != nil { - // fmt.Fprintln(os.Stderr, "error:", err) - // os.Exit(-1) - // } - // if !sanityCheck(fp6TemplateData.TestPoints, fp6.Degree) { - // fmt.Fprintln(os.Stderr, "idiot!", err) - // os.Exit(-1) - // } + testInputs := fp6.GenerateTestInputs(fFp) + var err error + fp6TemplateData.TestPoints, err = tower.GenerateTestOutputs(testInputs, "../internal/tower/fp6/testpoints.sage", fFp, fFp2, fFp6Split[0], fFp6Split[1]) + if err != nil { + fmt.Fprintln(os.Stderr, "error:", err) + os.Exit(-1) + } + if !sanityCheck(fp6TemplateData.TestPoints, fp6.Degree) { + fmt.Fprintln(os.Stderr, "idiot!", err) + os.Exit(-1) + } - // fp6Data = append(fp6Data, codegenData{ - // path: filepath.Join(fOutputDir, strings.ToLower(fp6TemplateData.Name)+"testpoints_test.go"), - // sources: fp6.CodeTestPoints, - // }) - // } + fp6Data = append(fp6Data, codegenData{ + path: filepath.Join(fOutputDir, strings.ToLower(fp6TemplateData.Name)+"testpoints_test.go"), + sources: fp6.CodeTestPoints, + }) + } if err := generateCode(fp6Data, fp6TemplateData); err != nil { fmt.Fprintln(os.Stderr, "error:", err) @@ -316,10 +316,12 @@ func main() { PackageName string Name string CType string + Fr string }{ PackageName: fPackageName, Name: strings.ToUpper(g.structName), CType: g.coordType, + Fr: fFr, } var gpointData []codegenData diff --git a/ecc/internal/gpoint/benchmarks.go b/ecc/internal/gpoint/benchmarks.go index a0d4ee21bd..398c5edbde 100644 --- a/ecc/internal/gpoint/benchmarks.go +++ b/ecc/internal/gpoint/benchmarks.go @@ -8,7 +8,6 @@ const benchmarks = ` var benchRes{{.Name}} {{.Name}}Jac -{{- if ne .Name "G2"}} func Benchmark{{.Name}}ScalarMul(b *testing.B) { curve := {{toUpper .PackageName}}() @@ -65,7 +64,6 @@ func Benchmark{{.Name}}Double(b *testing.B) { } } -{{- end }} func Benchmark{{.Name}}WindowedMultiExp(b *testing.B) { curve := {{toUpper .PackageName}}() diff --git a/ecc/internal/gpoint/tests.go b/ecc/internal/gpoint/tests.go index a94f7e65be..102e9ae252 100644 --- a/ecc/internal/gpoint/tests.go +++ b/ecc/internal/gpoint/tests.go @@ -11,12 +11,6 @@ import ( "github.com/consensys/gnark/ecc/{{.PackageName}}/fr" ) -{{- if eq .Name "G2"}} -func Test{{.Name}}NotReallyHere(t *testing.T) { - t.Skip("testPoints{{.Name}}() not available?") -} -{{- else}} - func Test{{.Name}}JacToAffineFromJac(t *testing.T) { p := testPoints{{.Name}}() @@ -117,27 +111,26 @@ func Test{{.Name}}JacScalarMul(t *testing.T) { func Test{{.Name}}JacMultiExp(t *testing.T) { curve := {{toUpper .PackageName}}() - // var points []{{.Name}}Jac + var points []{{.Name}}Jac var scalars []fr.Element var got {{.Name}}Jac // // Test 1: testPoints{{.Name}}multiExp // - // TODO why is this commented? - // numPoints, wants := testPoints{{.Name}}MultiExpResults() + numPoints, wants := testPoints{{.Name}}MultiExpResults() - // for i := range numPoints { - // if numPoints[i] > 10000 { - // continue - // } - // points, scalars = testPoints{{.Name}}MultiExp(numPoints[i]) + for i := range numPoints { + if numPoints[i] > 10000 { + continue + } + points, scalars = testPoints{{.Name}}MultiExp(numPoints[i]) - // got.multiExp(curve, points, scalars) - // if !got.Equal(&wants[i]) { - // t.Error("multiExp {{.Name}}Jac fail for points:", numPoints[i]) - // } - // } + got.multiExp(curve, points, scalars) + if !got.Equal(&wants[i]) { + t.Error("multiExp {{.Name}}Jac fail for points:", numPoints[i]) + } + } // // Test 2: testPoints{{.Name}}() @@ -145,9 +138,9 @@ func Test{{.Name}}JacMultiExp(t *testing.T) { p := testPoints{{.Name}}() // scalars - s1 := fr.Element{23872983, 238203802, 9827897384, 2372} - s2 := fr.Element{128923, 2878236, 398478, 187970707} - s3 := fr.Element{9038947, 3947970, 29080823, 282739} + s1 := fr.Element{23872983, 238203802, 9827897384, 2372} // 14889285316340551032002176131108485811963550694615991316137431 + s2 := fr.Element{128923, 2878236, 398478, 187970707} // 1179911251111561301561648964820473185772012989930899737079831459739 + s3 := fr.Element{9038947, 3947970, 29080823, 282739} // 1774781467561494742381858548177178844765555009630735687022668899 scalars = []fr.Element{ s1, @@ -258,8 +251,6 @@ func Test{{.Name}}JacMultiExp(t *testing.T) { // TODO: Jacobian points with nontrivial Z coord? } -{{- end}} - func TestMultiExp{{ .Name}}(t *testing.T) { curve := {{toUpper .PackageName}}() @@ -341,7 +332,6 @@ func TestMultiExp{{.Name}}LotOfPoints(t *testing.T) { } - func testPoints{{.Name}}MultiExp(n int) (points []{{.Name}}Jac, scalars []fr.Element) { curve := {{toUpper .PackageName}}() @@ -362,19 +352,25 @@ func testPoints{{.Name}}MultiExp(n int) (points []{{.Name}}Jac, scalars []fr.Ele // To ensure a diverse selection of scalars that use all words of an fr.Element, // each scalar should be a power of a large generator of fr. - // 22 is a small generator of fr for bls377. - // 2^{31}-1 is prime, so 22^{2^31}-1} is a large generator of fr for bls377 - // generator in Montgomery form var scalarGenMont fr.Element - scalarGenMont.SetString("7716837800905789770901243404444209691916730933998574719964609384059111546487") - + scalarGenMont.SetString(" + {{- if eq .Fr "8444461749428370424248824938781546531375899335154063827935233455917409239041" -}} + 7716837800905789770901243404444209691916730933998574719964609384059111546487 + {{- else if eq .Fr "52435875175126190479447740508185965837690552500527637822603658699938581184513" -}} + 42033899646658082535995012643440421268349534540760060111646640675404812871419 + {{- else if eq .Fr "21888242871839275222246405745257275088548364400416034343698204186575808495617" -}} + 18147194858733678592031140175294542593979808267792252765512745512101703194607 + {{- else -}} + not implemented + {{- end -}} + ") scalars[0].Set(&scalarGenMont).FromMont() var curScalarMont fr.Element // Montgomery form curScalarMont.Set(&scalarGenMont) for i := 1; i < len(scalars); i++ { - curScalarMont.MulAssign(&scalarGenMont) - scalars[i].Set(&curScalarMont).FromMont() // scalars[i] = scalars[0]^i + curScalarMont.MulAssign(&scalarGenMont) // scalars[i] = scalars[0]^i + scalars[i].Set(&curScalarMont).FromMont() } return points, scalars diff --git a/ecc/internal/testPointsMultiExp.sage b/ecc/internal/testPointsMultiExp-bls377.sage old mode 100644 new mode 100755 similarity index 97% rename from ecc/internal/testPointsMultiExp.sage rename to ecc/internal/testPointsMultiExp-bls377.sage index 4d3bdad82e..5c3f60e79f --- a/ecc/internal/testPointsMultiExp.sage +++ b/ecc/internal/testPointsMultiExp-bls377.sage @@ -1,7 +1,12 @@ +#!/usr/bin/env sage + +import sys +from sage.all import * + # Compute the result of a multi-exponentiation in the G1, G2 torsion groups of bls377 # set numPoints as desired -numPoints=1 +numPoints=100 # bls377 fp modulus p=258664426012969094010652733694893533536393512754914660539884262666720468348340822774968888139573360124440321458177 diff --git a/ecc/internal/testPointsMultiExp-bls381.sage b/ecc/internal/testPointsMultiExp-bls381.sage new file mode 100755 index 0000000000..e476e02acd --- /dev/null +++ b/ecc/internal/testPointsMultiExp-bls381.sage @@ -0,0 +1,68 @@ +#!/usr/bin/env sage + +import sys +from sage.all import * + +# Compute the result of a multi-exponentiation in the G1, G2 torsion groups of bls381 + +# set numPoints as desired +numPoints=10000 + +# bls381 fp modulus +p=4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787 + +# bls381 fr modulus +r=52435875175126190479447740508185965837690552500527637822603658699938581184513 + +# large multiplicative generator of fr +exp=42033899646658082535995012643440421268349534540760060111646640675404812871419 + +# +# G1 +# +Fp=GF(p) +E=EllipticCurve(Fp, [0,4]) + +# generator of torsion group G1 with order r +G1=E(2407661716269791519325591009883849385849641130669941829988413640673772478386903154468379397813974815295049686961384,821462058248938975967615814494474302717441302457255475448080663619194518120412959273482223614332657512049995916067) + +R1=G1-G1 # initialize point at infinity +nextpoint=R1 +nextscalar=1 +for i in range(numPoints): + nextpoint = nextpoint + G1 + nextscalar = nextscalar * exp % r + R1 = R1 + nextscalar * nextpoint +print "G1:", numPoints, R1 + +# +# G2 +# +Fp2. = GF(p^2, modulus=x^2+1) +Etwist = EllipticCurve(Fp2, [0, 4*(u+1)]) + +# generator of torsion group G2 with order r +G2 = Etwist([3914881020997020027725320596272602335133880006033342744016315347583472833929664105802124952724390025419912690116411+277275454976865553761595788585036366131740173742845697399904006633521909118147462773311856983264184840438626176168*u, 253800087101532902362860387055050889666401414686580130872654083467859828854605749525591159464755920666929166876282+1710145663789443622734372402738721070158916073226464929008132596760920130516982819361355832232719175024697380252309*u]) + +R2=G2-G2 # initialize point at infinity +nextpoint=R2 +nextscalar=1 +for i in range(numPoints): + nextpoint = nextpoint + G2 + nextscalar = nextscalar * exp % r + R2 = R2 + nextscalar * nextpoint +print "G2:", numPoints, R2 + +# +# G1 edge cases +# +# P1 = E(1033606393457524462202509281301391801774795384185741853644472965267802293960888374171626887455592584665037630738774, 3621796482720998302222855382742072090172959453363519638042647136675190127709381413539787942875187889828554162336553) +# s = 115792089237316195423570985008687907853269984665640564039457584007913129639935 +# print "maxuint*P1:", s*P1 + +# +# G2 edge cases +# +# P2 = Etwist(3530486458255518483646657753300465068233361547001606344843397309332648122759199161038835588610138188998735896249365 + 556359626370552735366469208656132171537953714011244503981293113570685962099899069626710494303020175970496332053819*u, 688206249007371037300932698574694060421430775835917018620054976409346176157603328155654383245339911153033552044328 + 159347828284068266532164708674697800959559338289778389611370325567206642394897182319932651433026161219393286360146*u) +# s = 115792089237316195423570985008687907853269984665640564039457584007913129639935 +# print "maxuint*P2:", s*P2 diff --git a/ecc/internal/testPointsMultiExp-bn256.sage b/ecc/internal/testPointsMultiExp-bn256.sage new file mode 100755 index 0000000000..98c27659a5 --- /dev/null +++ b/ecc/internal/testPointsMultiExp-bn256.sage @@ -0,0 +1,54 @@ +#!/usr/bin/env sage + +import sys +from sage.all import * + +# Compute the result of a multi-exponentiation in the G1, G2 torsion groups of bn256 + +# set numPoints as desired +numPoints=10000 + +# bn256 fp modulus +p=21888242871839275222246405745257275088696311157297823662689037894645226208583 + +# bn256 fr modulus +r=21888242871839275222246405745257275088548364400416034343698204186575808495617 + +# large multiplicative generator of fr +exp=18147194858733678592031140175294542593979808267792252765512745512101703194607 + +# +# G1 +# +Fp=GF(p) +E=EllipticCurve(Fp, [0,3]) + +# generator of torsion group G1 with order r +G1=E(20567171726433170376993012834626974355708098753738075953327671604980729474588,14259118686601658563517637559143782061303537174604067025175876803301021346267) + +R1=G1-G1 # initialize point at infinity +nextpoint=R1 +nextscalar=1 +for i in range(numPoints): + nextpoint = nextpoint + G1 + nextscalar = nextscalar * exp % r + R1 = R1 + nextscalar * nextpoint +print "G1:", numPoints, R1 + +# +# G2 +# +Fp2. = GF(p^2, modulus=x^2+1) +Etwist = EllipticCurve(Fp2, [0, 3*(u+9)^-1]) + +# generator of torsion group G2 with order r +G2 = Etwist([14433365730775072582213482468844163390964025019096075555058505630999708262443+3683446723006852480794963570030936618743148392137679437247363531986401769417*u, 21253271987667943455369004300257637004831224612428754877033343975009216128128+12495620673937637012904672587588023149812491484245871073230980321212840773339*u]) + +R2=G2-G2 # initialize point at infinity +nextpoint=R2 +nextscalar=1 +for i in range(numPoints): + nextpoint = nextpoint + G2 + nextscalar = nextscalar * exp % r + R2 = R2 + nextscalar * nextpoint +print "G2:", numPoints, R2 diff --git a/ecc/internal/tower/fp12/testpoints.sage b/ecc/internal/tower/fp12/testpoints.sage index 6eb609d665..e255907b66 100755 --- a/ecc/internal/tower/fp12/testpoints.sage +++ b/ecc/internal/tower/fp12/testpoints.sage @@ -24,7 +24,9 @@ r=sage_eval(sys.argv[3]) # print "r:", r # final exponent: (p^12-1)/r -exponent = (p^12 - 1)/r +# for BLS381, BLS377 need to multiply by 3, but not BN256. +# TODO: handle multiplication by 3 (or not) in this script +exponent = 3*(p^12 - 1)/r # print "exponent:", exponent # fp2 field