From f423e800b7ec7b037921b8ad4794a6842a0b578b Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Fri, 22 Sep 2023 15:11:01 -0300 Subject: [PATCH 1/7] ecc: avoid inverses in Jac equality check Signed-off-by: Ignacio Hagopian --- internal/generator/ecc/template/point.go.tmpl | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/internal/generator/ecc/template/point.go.tmpl b/internal/generator/ecc/template/point.go.tmpl index d4e0fe760..f247b8b41 100644 --- a/internal/generator/ecc/template/point.go.tmpl +++ b/internal/generator/ecc/template/point.go.tmpl @@ -211,13 +211,21 @@ func (p *{{ $TJacobian }}) Equal(a *{{ $TJacobian }}) bool { if p.Z.IsZero() && a.Z.IsZero() { return true } - _p := {{ $TAffine }}{} - _p.FromJacobian(p) - _a := {{ $TAffine }}{} - _a.FromJacobian(a) + var pZSquare, aZSquare {{.CoordType}} + pZSquare.Square(&p.Z) + aZSquare.Square(&a.Z) + + var lhs, rhs {{.CoordType}} + lhs.Mul(&p.X, &aZSquare) + rhs.Mul(&a.X, &pZSquare) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &a.Z) + rhs.Mul(&a.Y, &pZSquare).Mul(&rhs, &p.Z) - return _p.X.Equal(&_a.X) && _p.Y.Equal(&_a.Y) + return lhs.Equal(&rhs) } // Neg computes -G From 168f69f152e88f07545af169bef8c7dd7341f72e Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Fri, 22 Sep 2023 15:11:54 -0300 Subject: [PATCH 2/7] ecc: add bench for Jac equality check Signed-off-by: Ignacio Hagopian --- .../ecc/template/tests/point.go.tmpl | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/internal/generator/ecc/template/tests/point.go.tmpl b/internal/generator/ecc/template/tests/point.go.tmpl index 932221628..ccb1384a0 100644 --- a/internal/generator/ecc/template/tests/point.go.tmpl +++ b/internal/generator/ecc/template/tests/point.go.tmpl @@ -584,6 +584,51 @@ func Benchmark{{ $TJacobian }}IsInSubGroup(b *testing.B) { } +func Benchmark{{ $TJacobian }}Equal(b *testing.B) { + var scalar {{ .CoordType}} + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("failed to set scalar: %s", err) + } + + var a {{ $TJacobian }} + a.ScalarMultiplication(&{{.PointName}}Gen, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + var scalarSquared {{ .CoordType}} + scalarSquared.Square(&scalar) + + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalarSquared) + aZScaled.Y.Mul(&aZScaled.Y, &scalarSquared).Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 {{ $TJacobian }} + aPlus1.AddAssign(&{{.PointName}}Gen) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkBatchAdd{{ $TAffine }}(b *testing.B) { var P, R p{{$TAffine}}C{{$c}} From ea76da5fc2c75675e2a72cbf136690d2a0269ce9 Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Fri, 22 Sep 2023 15:12:14 -0300 Subject: [PATCH 3/7] edwards: avoid inverses in Projective equality check Signed-off-by: Ignacio Hagopian --- internal/generator/edwards/template/point.go.tmpl | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/internal/generator/edwards/template/point.go.tmpl b/internal/generator/edwards/template/point.go.tmpl index 4851916fe..4c3de021d 100644 --- a/internal/generator/edwards/template/point.go.tmpl +++ b/internal/generator/edwards/template/point.go.tmpl @@ -281,10 +281,17 @@ func (p *PointProj) Equal(p1 *PointProj) bool { if p.Z.IsZero() || p1.Z.IsZero() { return false } - var pAffine, p1Affine PointAffine - pAffine.FromProj(p) - p1Affine.FromProj(p1) - return pAffine.Equal(&p1Affine) + + var lhs, rhs fr.Element + lhs.Mul(&p.X, &p1.Z) + rhs.Mul(&p1.X, &p.Z) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &p1.Z) + rhs.Mul(&p1.Y, &p.Z) + + return lhs.Equal(&rhs) } // IsZero returns true if p=0 false otherwise From 01ea57bef796a621412ede7e6e145ca100e97904 Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Fri, 22 Sep 2023 15:12:24 -0300 Subject: [PATCH 4/7] edwards: add bench for Projective equality check Signed-off-by: Ignacio Hagopian --- .../edwards/template/tests/point.go.tmpl | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/internal/generator/edwards/template/tests/point.go.tmpl b/internal/generator/edwards/template/tests/point.go.tmpl index 960ff0ca5..4f2d16708 100644 --- a/internal/generator/edwards/template/tests/point.go.tmpl +++ b/internal/generator/edwards/template/tests/point.go.tmpl @@ -732,6 +732,52 @@ func GenBigInt() gopter.Gen { // ------------------------------------------------------------ // benches +func BenchmarkProjEqual(b *testing.B) { + params := GetEdwardsCurve() + + var scalar fr.Element + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("error generating random scalar: %v", err) + } + + var baseProj PointProj + baseProj.FromAffine(¶ms.Base) + var a PointProj + a.ScalarMultiplication(&baseProj, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalar) + aZScaled.Y.Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 PointProj + aPlus1.Add(&aPlus1, &baseProj) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkScalarMulExtended(b *testing.B) { params := GetEdwardsCurve() var a PointExtended From acd785ca326a50918d7c0085def16b77226c66ff Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Fri, 22 Sep 2023 15:12:34 -0300 Subject: [PATCH 5/7] go generate Signed-off-by: Ignacio Hagopian --- ecc/bls12-377/g1.go | 18 ++++++--- ecc/bls12-377/g1_test.go | 45 +++++++++++++++++++++ ecc/bls12-377/g2.go | 18 ++++++--- ecc/bls12-377/g2_test.go | 45 +++++++++++++++++++++ ecc/bls12-377/twistededwards/point.go | 15 +++++-- ecc/bls12-377/twistededwards/point_test.go | 46 ++++++++++++++++++++++ ecc/bls12-378/g1.go | 18 ++++++--- ecc/bls12-378/g1_test.go | 45 +++++++++++++++++++++ ecc/bls12-378/g2.go | 18 ++++++--- ecc/bls12-378/g2_test.go | 45 +++++++++++++++++++++ ecc/bls12-378/twistededwards/point.go | 15 +++++-- ecc/bls12-378/twistededwards/point_test.go | 46 ++++++++++++++++++++++ ecc/bls12-381/bandersnatch/point.go | 15 +++++-- ecc/bls12-381/bandersnatch/point_test.go | 46 ++++++++++++++++++++++ ecc/bls12-381/g1.go | 18 ++++++--- ecc/bls12-381/g1_test.go | 45 +++++++++++++++++++++ ecc/bls12-381/g2.go | 18 ++++++--- ecc/bls12-381/g2_test.go | 45 +++++++++++++++++++++ ecc/bls12-381/twistededwards/point.go | 15 +++++-- ecc/bls12-381/twistededwards/point_test.go | 46 ++++++++++++++++++++++ ecc/bls24-315/g1.go | 18 ++++++--- ecc/bls24-315/g1_test.go | 45 +++++++++++++++++++++ ecc/bls24-315/g2.go | 18 ++++++--- ecc/bls24-315/g2_test.go | 45 +++++++++++++++++++++ ecc/bls24-315/twistededwards/point.go | 15 +++++-- ecc/bls24-315/twistededwards/point_test.go | 46 ++++++++++++++++++++++ ecc/bls24-317/g1.go | 18 ++++++--- ecc/bls24-317/g1_test.go | 45 +++++++++++++++++++++ ecc/bls24-317/g2.go | 18 ++++++--- ecc/bls24-317/g2_test.go | 45 +++++++++++++++++++++ ecc/bls24-317/twistededwards/point.go | 15 +++++-- ecc/bls24-317/twistededwards/point_test.go | 46 ++++++++++++++++++++++ ecc/bn254/g1.go | 18 ++++++--- ecc/bn254/g1_test.go | 45 +++++++++++++++++++++ ecc/bn254/g2.go | 18 ++++++--- ecc/bn254/g2_test.go | 45 +++++++++++++++++++++ ecc/bn254/twistededwards/point.go | 15 +++++-- ecc/bn254/twistededwards/point_test.go | 46 ++++++++++++++++++++++ ecc/bw6-633/g1.go | 18 ++++++--- ecc/bw6-633/g1_test.go | 45 +++++++++++++++++++++ ecc/bw6-633/g2.go | 18 ++++++--- ecc/bw6-633/g2_test.go | 45 +++++++++++++++++++++ ecc/bw6-633/twistededwards/point.go | 15 +++++-- ecc/bw6-633/twistededwards/point_test.go | 46 ++++++++++++++++++++++ ecc/bw6-756/g1.go | 18 ++++++--- ecc/bw6-756/g1_test.go | 45 +++++++++++++++++++++ ecc/bw6-756/g2.go | 18 ++++++--- ecc/bw6-756/g2_test.go | 45 +++++++++++++++++++++ ecc/bw6-756/twistededwards/point.go | 15 +++++-- ecc/bw6-756/twistededwards/point_test.go | 46 ++++++++++++++++++++++ ecc/bw6-761/g1.go | 18 ++++++--- ecc/bw6-761/g1_test.go | 45 +++++++++++++++++++++ ecc/bw6-761/g2.go | 18 ++++++--- ecc/bw6-761/g2_test.go | 45 +++++++++++++++++++++ ecc/bw6-761/twistededwards/point.go | 15 +++++-- ecc/bw6-761/twistededwards/point_test.go | 46 ++++++++++++++++++++++ ecc/secp256k1/g1.go | 18 ++++++--- ecc/secp256k1/g1_test.go | 45 +++++++++++++++++++++ 58 files changed, 1672 insertions(+), 135 deletions(-) diff --git a/ecc/bls12-377/g1.go b/ecc/bls12-377/g1.go index 17ea4160f..3d24e0f14 100644 --- a/ecc/bls12-377/g1.go +++ b/ecc/bls12-377/g1.go @@ -188,13 +188,21 @@ func (p *G1Jac) Equal(a *G1Jac) bool { if p.Z.IsZero() && a.Z.IsZero() { return true } - _p := G1Affine{} - _p.FromJacobian(p) - _a := G1Affine{} - _a.FromJacobian(a) + var pZSquare, aZSquare fp.Element + pZSquare.Square(&p.Z) + aZSquare.Square(&a.Z) + + var lhs, rhs fp.Element + lhs.Mul(&p.X, &aZSquare) + rhs.Mul(&a.X, &pZSquare) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &a.Z) + rhs.Mul(&a.Y, &pZSquare).Mul(&rhs, &p.Z) - return _p.X.Equal(&_a.X) && _p.Y.Equal(&_a.Y) + return lhs.Equal(&rhs) } // Neg computes -G diff --git a/ecc/bls12-377/g1_test.go b/ecc/bls12-377/g1_test.go index e455a648d..fa77d44d5 100644 --- a/ecc/bls12-377/g1_test.go +++ b/ecc/bls12-377/g1_test.go @@ -516,6 +516,51 @@ func BenchmarkG1JacIsInSubGroup(b *testing.B) { } +func BenchmarkG1JacEqual(b *testing.B) { + var scalar fp.Element + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("failed to set scalar: %s", err) + } + + var a G1Jac + a.ScalarMultiplication(&g1Gen, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + var scalarSquared fp.Element + scalarSquared.Square(&scalar) + + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalarSquared) + aZScaled.Y.Mul(&aZScaled.Y, &scalarSquared).Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 G1Jac + aPlus1.AddAssign(&g1Gen) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkBatchAddG1Affine(b *testing.B) { var P, R pG1AffineC16 diff --git a/ecc/bls12-377/g2.go b/ecc/bls12-377/g2.go index 0f06e46fa..13ed328d3 100644 --- a/ecc/bls12-377/g2.go +++ b/ecc/bls12-377/g2.go @@ -177,13 +177,21 @@ func (p *G2Jac) Equal(a *G2Jac) bool { if p.Z.IsZero() && a.Z.IsZero() { return true } - _p := G2Affine{} - _p.FromJacobian(p) - _a := G2Affine{} - _a.FromJacobian(a) + var pZSquare, aZSquare fptower.E2 + pZSquare.Square(&p.Z) + aZSquare.Square(&a.Z) + + var lhs, rhs fptower.E2 + lhs.Mul(&p.X, &aZSquare) + rhs.Mul(&a.X, &pZSquare) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &a.Z) + rhs.Mul(&a.Y, &pZSquare).Mul(&rhs, &p.Z) - return _p.X.Equal(&_a.X) && _p.Y.Equal(&_a.Y) + return lhs.Equal(&rhs) } // Neg computes -G diff --git a/ecc/bls12-377/g2_test.go b/ecc/bls12-377/g2_test.go index 529dcc76a..e5425aa87 100644 --- a/ecc/bls12-377/g2_test.go +++ b/ecc/bls12-377/g2_test.go @@ -505,6 +505,51 @@ func BenchmarkG2JacIsInSubGroup(b *testing.B) { } +func BenchmarkG2JacEqual(b *testing.B) { + var scalar fptower.E2 + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("failed to set scalar: %s", err) + } + + var a G2Jac + a.ScalarMultiplication(&g2Gen, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + var scalarSquared fptower.E2 + scalarSquared.Square(&scalar) + + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalarSquared) + aZScaled.Y.Mul(&aZScaled.Y, &scalarSquared).Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 G2Jac + aPlus1.AddAssign(&g2Gen) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkBatchAddG2Affine(b *testing.B) { var P, R pG2AffineC16 diff --git a/ecc/bls12-377/twistededwards/point.go b/ecc/bls12-377/twistededwards/point.go index 59a75fafc..39177ad98 100644 --- a/ecc/bls12-377/twistededwards/point.go +++ b/ecc/bls12-377/twistededwards/point.go @@ -297,10 +297,17 @@ func (p *PointProj) Equal(p1 *PointProj) bool { if p.Z.IsZero() || p1.Z.IsZero() { return false } - var pAffine, p1Affine PointAffine - pAffine.FromProj(p) - p1Affine.FromProj(p1) - return pAffine.Equal(&p1Affine) + + var lhs, rhs fr.Element + lhs.Mul(&p.X, &p1.Z) + rhs.Mul(&p1.X, &p.Z) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &p1.Z) + rhs.Mul(&p1.Y, &p.Z) + + return lhs.Equal(&rhs) } // IsZero returns true if p=0 false otherwise diff --git a/ecc/bls12-377/twistededwards/point_test.go b/ecc/bls12-377/twistededwards/point_test.go index 33770efbe..4d0631d1a 100644 --- a/ecc/bls12-377/twistededwards/point_test.go +++ b/ecc/bls12-377/twistededwards/point_test.go @@ -748,6 +748,52 @@ func GenBigInt() gopter.Gen { // ------------------------------------------------------------ // benches +func BenchmarkProjEqual(b *testing.B) { + params := GetEdwardsCurve() + + var scalar fr.Element + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("error generating random scalar: %v", err) + } + + var baseProj PointProj + baseProj.FromAffine(¶ms.Base) + var a PointProj + a.ScalarMultiplication(&baseProj, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalar) + aZScaled.Y.Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 PointProj + aPlus1.Add(&aPlus1, &baseProj) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkScalarMulExtended(b *testing.B) { params := GetEdwardsCurve() var a PointExtended diff --git a/ecc/bls12-378/g1.go b/ecc/bls12-378/g1.go index a1e14cf60..5ba2824b1 100644 --- a/ecc/bls12-378/g1.go +++ b/ecc/bls12-378/g1.go @@ -188,13 +188,21 @@ func (p *G1Jac) Equal(a *G1Jac) bool { if p.Z.IsZero() && a.Z.IsZero() { return true } - _p := G1Affine{} - _p.FromJacobian(p) - _a := G1Affine{} - _a.FromJacobian(a) + var pZSquare, aZSquare fp.Element + pZSquare.Square(&p.Z) + aZSquare.Square(&a.Z) + + var lhs, rhs fp.Element + lhs.Mul(&p.X, &aZSquare) + rhs.Mul(&a.X, &pZSquare) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &a.Z) + rhs.Mul(&a.Y, &pZSquare).Mul(&rhs, &p.Z) - return _p.X.Equal(&_a.X) && _p.Y.Equal(&_a.Y) + return lhs.Equal(&rhs) } // Neg computes -G diff --git a/ecc/bls12-378/g1_test.go b/ecc/bls12-378/g1_test.go index 672b3f9fa..473fa6206 100644 --- a/ecc/bls12-378/g1_test.go +++ b/ecc/bls12-378/g1_test.go @@ -516,6 +516,51 @@ func BenchmarkG1JacIsInSubGroup(b *testing.B) { } +func BenchmarkG1JacEqual(b *testing.B) { + var scalar fp.Element + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("failed to set scalar: %s", err) + } + + var a G1Jac + a.ScalarMultiplication(&g1Gen, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + var scalarSquared fp.Element + scalarSquared.Square(&scalar) + + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalarSquared) + aZScaled.Y.Mul(&aZScaled.Y, &scalarSquared).Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 G1Jac + aPlus1.AddAssign(&g1Gen) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkBatchAddG1Affine(b *testing.B) { var P, R pG1AffineC16 diff --git a/ecc/bls12-378/g2.go b/ecc/bls12-378/g2.go index ba6437496..dcde1e472 100644 --- a/ecc/bls12-378/g2.go +++ b/ecc/bls12-378/g2.go @@ -177,13 +177,21 @@ func (p *G2Jac) Equal(a *G2Jac) bool { if p.Z.IsZero() && a.Z.IsZero() { return true } - _p := G2Affine{} - _p.FromJacobian(p) - _a := G2Affine{} - _a.FromJacobian(a) + var pZSquare, aZSquare fptower.E2 + pZSquare.Square(&p.Z) + aZSquare.Square(&a.Z) + + var lhs, rhs fptower.E2 + lhs.Mul(&p.X, &aZSquare) + rhs.Mul(&a.X, &pZSquare) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &a.Z) + rhs.Mul(&a.Y, &pZSquare).Mul(&rhs, &p.Z) - return _p.X.Equal(&_a.X) && _p.Y.Equal(&_a.Y) + return lhs.Equal(&rhs) } // Neg computes -G diff --git a/ecc/bls12-378/g2_test.go b/ecc/bls12-378/g2_test.go index 2d360a2d8..65ac23a1a 100644 --- a/ecc/bls12-378/g2_test.go +++ b/ecc/bls12-378/g2_test.go @@ -505,6 +505,51 @@ func BenchmarkG2JacIsInSubGroup(b *testing.B) { } +func BenchmarkG2JacEqual(b *testing.B) { + var scalar fptower.E2 + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("failed to set scalar: %s", err) + } + + var a G2Jac + a.ScalarMultiplication(&g2Gen, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + var scalarSquared fptower.E2 + scalarSquared.Square(&scalar) + + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalarSquared) + aZScaled.Y.Mul(&aZScaled.Y, &scalarSquared).Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 G2Jac + aPlus1.AddAssign(&g2Gen) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkBatchAddG2Affine(b *testing.B) { var P, R pG2AffineC16 diff --git a/ecc/bls12-378/twistededwards/point.go b/ecc/bls12-378/twistededwards/point.go index 4cd7c6d43..7587c02d5 100644 --- a/ecc/bls12-378/twistededwards/point.go +++ b/ecc/bls12-378/twistededwards/point.go @@ -297,10 +297,17 @@ func (p *PointProj) Equal(p1 *PointProj) bool { if p.Z.IsZero() || p1.Z.IsZero() { return false } - var pAffine, p1Affine PointAffine - pAffine.FromProj(p) - p1Affine.FromProj(p1) - return pAffine.Equal(&p1Affine) + + var lhs, rhs fr.Element + lhs.Mul(&p.X, &p1.Z) + rhs.Mul(&p1.X, &p.Z) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &p1.Z) + rhs.Mul(&p1.Y, &p.Z) + + return lhs.Equal(&rhs) } // IsZero returns true if p=0 false otherwise diff --git a/ecc/bls12-378/twistededwards/point_test.go b/ecc/bls12-378/twistededwards/point_test.go index 152d4b8bf..b53451742 100644 --- a/ecc/bls12-378/twistededwards/point_test.go +++ b/ecc/bls12-378/twistededwards/point_test.go @@ -748,6 +748,52 @@ func GenBigInt() gopter.Gen { // ------------------------------------------------------------ // benches +func BenchmarkProjEqual(b *testing.B) { + params := GetEdwardsCurve() + + var scalar fr.Element + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("error generating random scalar: %v", err) + } + + var baseProj PointProj + baseProj.FromAffine(¶ms.Base) + var a PointProj + a.ScalarMultiplication(&baseProj, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalar) + aZScaled.Y.Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 PointProj + aPlus1.Add(&aPlus1, &baseProj) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkScalarMulExtended(b *testing.B) { params := GetEdwardsCurve() var a PointExtended diff --git a/ecc/bls12-381/bandersnatch/point.go b/ecc/bls12-381/bandersnatch/point.go index 1046d9cae..8cddf0ee5 100644 --- a/ecc/bls12-381/bandersnatch/point.go +++ b/ecc/bls12-381/bandersnatch/point.go @@ -296,10 +296,17 @@ func (p *PointProj) Equal(p1 *PointProj) bool { if p.Z.IsZero() || p1.Z.IsZero() { return false } - var pAffine, p1Affine PointAffine - pAffine.FromProj(p) - p1Affine.FromProj(p1) - return pAffine.Equal(&p1Affine) + + var lhs, rhs fr.Element + lhs.Mul(&p.X, &p1.Z) + rhs.Mul(&p1.X, &p.Z) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &p1.Z) + rhs.Mul(&p1.Y, &p.Z) + + return lhs.Equal(&rhs) } // IsZero returns true if p=0 false otherwise diff --git a/ecc/bls12-381/bandersnatch/point_test.go b/ecc/bls12-381/bandersnatch/point_test.go index ccc05c079..996461af6 100644 --- a/ecc/bls12-381/bandersnatch/point_test.go +++ b/ecc/bls12-381/bandersnatch/point_test.go @@ -748,6 +748,52 @@ func GenBigInt() gopter.Gen { // ------------------------------------------------------------ // benches +func BenchmarkProjEqual(b *testing.B) { + params := GetEdwardsCurve() + + var scalar fr.Element + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("error generating random scalar: %v", err) + } + + var baseProj PointProj + baseProj.FromAffine(¶ms.Base) + var a PointProj + a.ScalarMultiplication(&baseProj, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalar) + aZScaled.Y.Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 PointProj + aPlus1.Add(&aPlus1, &baseProj) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkScalarMulExtended(b *testing.B) { params := GetEdwardsCurve() var a PointExtended diff --git a/ecc/bls12-381/g1.go b/ecc/bls12-381/g1.go index 8eb803c3b..02798747c 100644 --- a/ecc/bls12-381/g1.go +++ b/ecc/bls12-381/g1.go @@ -188,13 +188,21 @@ func (p *G1Jac) Equal(a *G1Jac) bool { if p.Z.IsZero() && a.Z.IsZero() { return true } - _p := G1Affine{} - _p.FromJacobian(p) - _a := G1Affine{} - _a.FromJacobian(a) + var pZSquare, aZSquare fp.Element + pZSquare.Square(&p.Z) + aZSquare.Square(&a.Z) + + var lhs, rhs fp.Element + lhs.Mul(&p.X, &aZSquare) + rhs.Mul(&a.X, &pZSquare) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &a.Z) + rhs.Mul(&a.Y, &pZSquare).Mul(&rhs, &p.Z) - return _p.X.Equal(&_a.X) && _p.Y.Equal(&_a.Y) + return lhs.Equal(&rhs) } // Neg computes -G diff --git a/ecc/bls12-381/g1_test.go b/ecc/bls12-381/g1_test.go index 586d9d683..9f226fd4a 100644 --- a/ecc/bls12-381/g1_test.go +++ b/ecc/bls12-381/g1_test.go @@ -516,6 +516,51 @@ func BenchmarkG1JacIsInSubGroup(b *testing.B) { } +func BenchmarkG1JacEqual(b *testing.B) { + var scalar fp.Element + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("failed to set scalar: %s", err) + } + + var a G1Jac + a.ScalarMultiplication(&g1Gen, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + var scalarSquared fp.Element + scalarSquared.Square(&scalar) + + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalarSquared) + aZScaled.Y.Mul(&aZScaled.Y, &scalarSquared).Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 G1Jac + aPlus1.AddAssign(&g1Gen) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkBatchAddG1Affine(b *testing.B) { var P, R pG1AffineC16 diff --git a/ecc/bls12-381/g2.go b/ecc/bls12-381/g2.go index 798337382..e58b642dc 100644 --- a/ecc/bls12-381/g2.go +++ b/ecc/bls12-381/g2.go @@ -177,13 +177,21 @@ func (p *G2Jac) Equal(a *G2Jac) bool { if p.Z.IsZero() && a.Z.IsZero() { return true } - _p := G2Affine{} - _p.FromJacobian(p) - _a := G2Affine{} - _a.FromJacobian(a) + var pZSquare, aZSquare fptower.E2 + pZSquare.Square(&p.Z) + aZSquare.Square(&a.Z) + + var lhs, rhs fptower.E2 + lhs.Mul(&p.X, &aZSquare) + rhs.Mul(&a.X, &pZSquare) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &a.Z) + rhs.Mul(&a.Y, &pZSquare).Mul(&rhs, &p.Z) - return _p.X.Equal(&_a.X) && _p.Y.Equal(&_a.Y) + return lhs.Equal(&rhs) } // Neg computes -G diff --git a/ecc/bls12-381/g2_test.go b/ecc/bls12-381/g2_test.go index 4905c7b91..34dfa1ece 100644 --- a/ecc/bls12-381/g2_test.go +++ b/ecc/bls12-381/g2_test.go @@ -505,6 +505,51 @@ func BenchmarkG2JacIsInSubGroup(b *testing.B) { } +func BenchmarkG2JacEqual(b *testing.B) { + var scalar fptower.E2 + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("failed to set scalar: %s", err) + } + + var a G2Jac + a.ScalarMultiplication(&g2Gen, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + var scalarSquared fptower.E2 + scalarSquared.Square(&scalar) + + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalarSquared) + aZScaled.Y.Mul(&aZScaled.Y, &scalarSquared).Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 G2Jac + aPlus1.AddAssign(&g2Gen) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkBatchAddG2Affine(b *testing.B) { var P, R pG2AffineC16 diff --git a/ecc/bls12-381/twistededwards/point.go b/ecc/bls12-381/twistededwards/point.go index 38b952f5a..54de81197 100644 --- a/ecc/bls12-381/twistededwards/point.go +++ b/ecc/bls12-381/twistededwards/point.go @@ -297,10 +297,17 @@ func (p *PointProj) Equal(p1 *PointProj) bool { if p.Z.IsZero() || p1.Z.IsZero() { return false } - var pAffine, p1Affine PointAffine - pAffine.FromProj(p) - p1Affine.FromProj(p1) - return pAffine.Equal(&p1Affine) + + var lhs, rhs fr.Element + lhs.Mul(&p.X, &p1.Z) + rhs.Mul(&p1.X, &p.Z) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &p1.Z) + rhs.Mul(&p1.Y, &p.Z) + + return lhs.Equal(&rhs) } // IsZero returns true if p=0 false otherwise diff --git a/ecc/bls12-381/twistededwards/point_test.go b/ecc/bls12-381/twistededwards/point_test.go index e41a23421..fe3e16a6b 100644 --- a/ecc/bls12-381/twistededwards/point_test.go +++ b/ecc/bls12-381/twistededwards/point_test.go @@ -748,6 +748,52 @@ func GenBigInt() gopter.Gen { // ------------------------------------------------------------ // benches +func BenchmarkProjEqual(b *testing.B) { + params := GetEdwardsCurve() + + var scalar fr.Element + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("error generating random scalar: %v", err) + } + + var baseProj PointProj + baseProj.FromAffine(¶ms.Base) + var a PointProj + a.ScalarMultiplication(&baseProj, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalar) + aZScaled.Y.Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 PointProj + aPlus1.Add(&aPlus1, &baseProj) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkScalarMulExtended(b *testing.B) { params := GetEdwardsCurve() var a PointExtended diff --git a/ecc/bls24-315/g1.go b/ecc/bls24-315/g1.go index 26f0c28fe..350e0a528 100644 --- a/ecc/bls24-315/g1.go +++ b/ecc/bls24-315/g1.go @@ -188,13 +188,21 @@ func (p *G1Jac) Equal(a *G1Jac) bool { if p.Z.IsZero() && a.Z.IsZero() { return true } - _p := G1Affine{} - _p.FromJacobian(p) - _a := G1Affine{} - _a.FromJacobian(a) + var pZSquare, aZSquare fp.Element + pZSquare.Square(&p.Z) + aZSquare.Square(&a.Z) + + var lhs, rhs fp.Element + lhs.Mul(&p.X, &aZSquare) + rhs.Mul(&a.X, &pZSquare) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &a.Z) + rhs.Mul(&a.Y, &pZSquare).Mul(&rhs, &p.Z) - return _p.X.Equal(&_a.X) && _p.Y.Equal(&_a.Y) + return lhs.Equal(&rhs) } // Neg computes -G diff --git a/ecc/bls24-315/g1_test.go b/ecc/bls24-315/g1_test.go index 7251a9e2e..eb0e8693c 100644 --- a/ecc/bls24-315/g1_test.go +++ b/ecc/bls24-315/g1_test.go @@ -516,6 +516,51 @@ func BenchmarkG1JacIsInSubGroup(b *testing.B) { } +func BenchmarkG1JacEqual(b *testing.B) { + var scalar fp.Element + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("failed to set scalar: %s", err) + } + + var a G1Jac + a.ScalarMultiplication(&g1Gen, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + var scalarSquared fp.Element + scalarSquared.Square(&scalar) + + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalarSquared) + aZScaled.Y.Mul(&aZScaled.Y, &scalarSquared).Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 G1Jac + aPlus1.AddAssign(&g1Gen) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkBatchAddG1Affine(b *testing.B) { var P, R pG1AffineC16 diff --git a/ecc/bls24-315/g2.go b/ecc/bls24-315/g2.go index 4b6062206..13ce0a4e9 100644 --- a/ecc/bls24-315/g2.go +++ b/ecc/bls24-315/g2.go @@ -177,13 +177,21 @@ func (p *G2Jac) Equal(a *G2Jac) bool { if p.Z.IsZero() && a.Z.IsZero() { return true } - _p := G2Affine{} - _p.FromJacobian(p) - _a := G2Affine{} - _a.FromJacobian(a) + var pZSquare, aZSquare fptower.E4 + pZSquare.Square(&p.Z) + aZSquare.Square(&a.Z) + + var lhs, rhs fptower.E4 + lhs.Mul(&p.X, &aZSquare) + rhs.Mul(&a.X, &pZSquare) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &a.Z) + rhs.Mul(&a.Y, &pZSquare).Mul(&rhs, &p.Z) - return _p.X.Equal(&_a.X) && _p.Y.Equal(&_a.Y) + return lhs.Equal(&rhs) } // Neg computes -G diff --git a/ecc/bls24-315/g2_test.go b/ecc/bls24-315/g2_test.go index 6a98aa51e..6ad91794f 100644 --- a/ecc/bls24-315/g2_test.go +++ b/ecc/bls24-315/g2_test.go @@ -505,6 +505,51 @@ func BenchmarkG2JacIsInSubGroup(b *testing.B) { } +func BenchmarkG2JacEqual(b *testing.B) { + var scalar fptower.E4 + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("failed to set scalar: %s", err) + } + + var a G2Jac + a.ScalarMultiplication(&g2Gen, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + var scalarSquared fptower.E4 + scalarSquared.Square(&scalar) + + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalarSquared) + aZScaled.Y.Mul(&aZScaled.Y, &scalarSquared).Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 G2Jac + aPlus1.AddAssign(&g2Gen) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkBatchAddG2Affine(b *testing.B) { var P, R pG2AffineC16 diff --git a/ecc/bls24-315/twistededwards/point.go b/ecc/bls24-315/twistededwards/point.go index 44de4d67f..0a58cb485 100644 --- a/ecc/bls24-315/twistededwards/point.go +++ b/ecc/bls24-315/twistededwards/point.go @@ -297,10 +297,17 @@ func (p *PointProj) Equal(p1 *PointProj) bool { if p.Z.IsZero() || p1.Z.IsZero() { return false } - var pAffine, p1Affine PointAffine - pAffine.FromProj(p) - p1Affine.FromProj(p1) - return pAffine.Equal(&p1Affine) + + var lhs, rhs fr.Element + lhs.Mul(&p.X, &p1.Z) + rhs.Mul(&p1.X, &p.Z) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &p1.Z) + rhs.Mul(&p1.Y, &p.Z) + + return lhs.Equal(&rhs) } // IsZero returns true if p=0 false otherwise diff --git a/ecc/bls24-315/twistededwards/point_test.go b/ecc/bls24-315/twistededwards/point_test.go index c684004f4..12f4b6316 100644 --- a/ecc/bls24-315/twistededwards/point_test.go +++ b/ecc/bls24-315/twistededwards/point_test.go @@ -748,6 +748,52 @@ func GenBigInt() gopter.Gen { // ------------------------------------------------------------ // benches +func BenchmarkProjEqual(b *testing.B) { + params := GetEdwardsCurve() + + var scalar fr.Element + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("error generating random scalar: %v", err) + } + + var baseProj PointProj + baseProj.FromAffine(¶ms.Base) + var a PointProj + a.ScalarMultiplication(&baseProj, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalar) + aZScaled.Y.Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 PointProj + aPlus1.Add(&aPlus1, &baseProj) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkScalarMulExtended(b *testing.B) { params := GetEdwardsCurve() var a PointExtended diff --git a/ecc/bls24-317/g1.go b/ecc/bls24-317/g1.go index c6dd46698..50b479a5e 100644 --- a/ecc/bls24-317/g1.go +++ b/ecc/bls24-317/g1.go @@ -188,13 +188,21 @@ func (p *G1Jac) Equal(a *G1Jac) bool { if p.Z.IsZero() && a.Z.IsZero() { return true } - _p := G1Affine{} - _p.FromJacobian(p) - _a := G1Affine{} - _a.FromJacobian(a) + var pZSquare, aZSquare fp.Element + pZSquare.Square(&p.Z) + aZSquare.Square(&a.Z) + + var lhs, rhs fp.Element + lhs.Mul(&p.X, &aZSquare) + rhs.Mul(&a.X, &pZSquare) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &a.Z) + rhs.Mul(&a.Y, &pZSquare).Mul(&rhs, &p.Z) - return _p.X.Equal(&_a.X) && _p.Y.Equal(&_a.Y) + return lhs.Equal(&rhs) } // Neg computes -G diff --git a/ecc/bls24-317/g1_test.go b/ecc/bls24-317/g1_test.go index 8f62e1fb8..371e3e47a 100644 --- a/ecc/bls24-317/g1_test.go +++ b/ecc/bls24-317/g1_test.go @@ -516,6 +516,51 @@ func BenchmarkG1JacIsInSubGroup(b *testing.B) { } +func BenchmarkG1JacEqual(b *testing.B) { + var scalar fp.Element + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("failed to set scalar: %s", err) + } + + var a G1Jac + a.ScalarMultiplication(&g1Gen, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + var scalarSquared fp.Element + scalarSquared.Square(&scalar) + + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalarSquared) + aZScaled.Y.Mul(&aZScaled.Y, &scalarSquared).Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 G1Jac + aPlus1.AddAssign(&g1Gen) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkBatchAddG1Affine(b *testing.B) { var P, R pG1AffineC16 diff --git a/ecc/bls24-317/g2.go b/ecc/bls24-317/g2.go index 728ec59b1..6a11e348f 100644 --- a/ecc/bls24-317/g2.go +++ b/ecc/bls24-317/g2.go @@ -177,13 +177,21 @@ func (p *G2Jac) Equal(a *G2Jac) bool { if p.Z.IsZero() && a.Z.IsZero() { return true } - _p := G2Affine{} - _p.FromJacobian(p) - _a := G2Affine{} - _a.FromJacobian(a) + var pZSquare, aZSquare fptower.E4 + pZSquare.Square(&p.Z) + aZSquare.Square(&a.Z) + + var lhs, rhs fptower.E4 + lhs.Mul(&p.X, &aZSquare) + rhs.Mul(&a.X, &pZSquare) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &a.Z) + rhs.Mul(&a.Y, &pZSquare).Mul(&rhs, &p.Z) - return _p.X.Equal(&_a.X) && _p.Y.Equal(&_a.Y) + return lhs.Equal(&rhs) } // Neg computes -G diff --git a/ecc/bls24-317/g2_test.go b/ecc/bls24-317/g2_test.go index 94026ccfc..23d6e154c 100644 --- a/ecc/bls24-317/g2_test.go +++ b/ecc/bls24-317/g2_test.go @@ -505,6 +505,51 @@ func BenchmarkG2JacIsInSubGroup(b *testing.B) { } +func BenchmarkG2JacEqual(b *testing.B) { + var scalar fptower.E4 + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("failed to set scalar: %s", err) + } + + var a G2Jac + a.ScalarMultiplication(&g2Gen, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + var scalarSquared fptower.E4 + scalarSquared.Square(&scalar) + + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalarSquared) + aZScaled.Y.Mul(&aZScaled.Y, &scalarSquared).Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 G2Jac + aPlus1.AddAssign(&g2Gen) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkBatchAddG2Affine(b *testing.B) { var P, R pG2AffineC16 diff --git a/ecc/bls24-317/twistededwards/point.go b/ecc/bls24-317/twistededwards/point.go index 406e55e77..54d073a71 100644 --- a/ecc/bls24-317/twistededwards/point.go +++ b/ecc/bls24-317/twistededwards/point.go @@ -297,10 +297,17 @@ func (p *PointProj) Equal(p1 *PointProj) bool { if p.Z.IsZero() || p1.Z.IsZero() { return false } - var pAffine, p1Affine PointAffine - pAffine.FromProj(p) - p1Affine.FromProj(p1) - return pAffine.Equal(&p1Affine) + + var lhs, rhs fr.Element + lhs.Mul(&p.X, &p1.Z) + rhs.Mul(&p1.X, &p.Z) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &p1.Z) + rhs.Mul(&p1.Y, &p.Z) + + return lhs.Equal(&rhs) } // IsZero returns true if p=0 false otherwise diff --git a/ecc/bls24-317/twistededwards/point_test.go b/ecc/bls24-317/twistededwards/point_test.go index beb1fb883..331a1d5ae 100644 --- a/ecc/bls24-317/twistededwards/point_test.go +++ b/ecc/bls24-317/twistededwards/point_test.go @@ -748,6 +748,52 @@ func GenBigInt() gopter.Gen { // ------------------------------------------------------------ // benches +func BenchmarkProjEqual(b *testing.B) { + params := GetEdwardsCurve() + + var scalar fr.Element + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("error generating random scalar: %v", err) + } + + var baseProj PointProj + baseProj.FromAffine(¶ms.Base) + var a PointProj + a.ScalarMultiplication(&baseProj, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalar) + aZScaled.Y.Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 PointProj + aPlus1.Add(&aPlus1, &baseProj) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkScalarMulExtended(b *testing.B) { params := GetEdwardsCurve() var a PointExtended diff --git a/ecc/bn254/g1.go b/ecc/bn254/g1.go index c03823d25..2733f5b11 100644 --- a/ecc/bn254/g1.go +++ b/ecc/bn254/g1.go @@ -188,13 +188,21 @@ func (p *G1Jac) Equal(a *G1Jac) bool { if p.Z.IsZero() && a.Z.IsZero() { return true } - _p := G1Affine{} - _p.FromJacobian(p) - _a := G1Affine{} - _a.FromJacobian(a) + var pZSquare, aZSquare fp.Element + pZSquare.Square(&p.Z) + aZSquare.Square(&a.Z) + + var lhs, rhs fp.Element + lhs.Mul(&p.X, &aZSquare) + rhs.Mul(&a.X, &pZSquare) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &a.Z) + rhs.Mul(&a.Y, &pZSquare).Mul(&rhs, &p.Z) - return _p.X.Equal(&_a.X) && _p.Y.Equal(&_a.Y) + return lhs.Equal(&rhs) } // Neg computes -G diff --git a/ecc/bn254/g1_test.go b/ecc/bn254/g1_test.go index b7a17b61d..75b918755 100644 --- a/ecc/bn254/g1_test.go +++ b/ecc/bn254/g1_test.go @@ -477,6 +477,51 @@ func BenchmarkG1JacIsInSubGroup(b *testing.B) { } +func BenchmarkG1JacEqual(b *testing.B) { + var scalar fp.Element + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("failed to set scalar: %s", err) + } + + var a G1Jac + a.ScalarMultiplication(&g1Gen, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + var scalarSquared fp.Element + scalarSquared.Square(&scalar) + + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalarSquared) + aZScaled.Y.Mul(&aZScaled.Y, &scalarSquared).Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 G1Jac + aPlus1.AddAssign(&g1Gen) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkBatchAddG1Affine(b *testing.B) { var P, R pG1AffineC16 diff --git a/ecc/bn254/g2.go b/ecc/bn254/g2.go index bb57fe175..70b1de2fe 100644 --- a/ecc/bn254/g2.go +++ b/ecc/bn254/g2.go @@ -177,13 +177,21 @@ func (p *G2Jac) Equal(a *G2Jac) bool { if p.Z.IsZero() && a.Z.IsZero() { return true } - _p := G2Affine{} - _p.FromJacobian(p) - _a := G2Affine{} - _a.FromJacobian(a) + var pZSquare, aZSquare fptower.E2 + pZSquare.Square(&p.Z) + aZSquare.Square(&a.Z) + + var lhs, rhs fptower.E2 + lhs.Mul(&p.X, &aZSquare) + rhs.Mul(&a.X, &pZSquare) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &a.Z) + rhs.Mul(&a.Y, &pZSquare).Mul(&rhs, &p.Z) - return _p.X.Equal(&_a.X) && _p.Y.Equal(&_a.Y) + return lhs.Equal(&rhs) } // Neg computes -G diff --git a/ecc/bn254/g2_test.go b/ecc/bn254/g2_test.go index 0690bf900..c4567c018 100644 --- a/ecc/bn254/g2_test.go +++ b/ecc/bn254/g2_test.go @@ -504,6 +504,51 @@ func BenchmarkG2JacIsInSubGroup(b *testing.B) { } +func BenchmarkG2JacEqual(b *testing.B) { + var scalar fptower.E2 + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("failed to set scalar: %s", err) + } + + var a G2Jac + a.ScalarMultiplication(&g2Gen, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + var scalarSquared fptower.E2 + scalarSquared.Square(&scalar) + + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalarSquared) + aZScaled.Y.Mul(&aZScaled.Y, &scalarSquared).Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 G2Jac + aPlus1.AddAssign(&g2Gen) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkBatchAddG2Affine(b *testing.B) { var P, R pG2AffineC16 diff --git a/ecc/bn254/twistededwards/point.go b/ecc/bn254/twistededwards/point.go index 83f589356..add15937c 100644 --- a/ecc/bn254/twistededwards/point.go +++ b/ecc/bn254/twistededwards/point.go @@ -297,10 +297,17 @@ func (p *PointProj) Equal(p1 *PointProj) bool { if p.Z.IsZero() || p1.Z.IsZero() { return false } - var pAffine, p1Affine PointAffine - pAffine.FromProj(p) - p1Affine.FromProj(p1) - return pAffine.Equal(&p1Affine) + + var lhs, rhs fr.Element + lhs.Mul(&p.X, &p1.Z) + rhs.Mul(&p1.X, &p.Z) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &p1.Z) + rhs.Mul(&p1.Y, &p.Z) + + return lhs.Equal(&rhs) } // IsZero returns true if p=0 false otherwise diff --git a/ecc/bn254/twistededwards/point_test.go b/ecc/bn254/twistededwards/point_test.go index 43df981bd..0c58a80a7 100644 --- a/ecc/bn254/twistededwards/point_test.go +++ b/ecc/bn254/twistededwards/point_test.go @@ -748,6 +748,52 @@ func GenBigInt() gopter.Gen { // ------------------------------------------------------------ // benches +func BenchmarkProjEqual(b *testing.B) { + params := GetEdwardsCurve() + + var scalar fr.Element + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("error generating random scalar: %v", err) + } + + var baseProj PointProj + baseProj.FromAffine(¶ms.Base) + var a PointProj + a.ScalarMultiplication(&baseProj, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalar) + aZScaled.Y.Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 PointProj + aPlus1.Add(&aPlus1, &baseProj) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkScalarMulExtended(b *testing.B) { params := GetEdwardsCurve() var a PointExtended diff --git a/ecc/bw6-633/g1.go b/ecc/bw6-633/g1.go index 5bb8d1f9e..da7b4d91b 100644 --- a/ecc/bw6-633/g1.go +++ b/ecc/bw6-633/g1.go @@ -193,13 +193,21 @@ func (p *G1Jac) Equal(a *G1Jac) bool { if p.Z.IsZero() && a.Z.IsZero() { return true } - _p := G1Affine{} - _p.FromJacobian(p) - _a := G1Affine{} - _a.FromJacobian(a) + var pZSquare, aZSquare fp.Element + pZSquare.Square(&p.Z) + aZSquare.Square(&a.Z) + + var lhs, rhs fp.Element + lhs.Mul(&p.X, &aZSquare) + rhs.Mul(&a.X, &pZSquare) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &a.Z) + rhs.Mul(&a.Y, &pZSquare).Mul(&rhs, &p.Z) - return _p.X.Equal(&_a.X) && _p.Y.Equal(&_a.Y) + return lhs.Equal(&rhs) } // Neg computes -G diff --git a/ecc/bw6-633/g1_test.go b/ecc/bw6-633/g1_test.go index 7bdf11483..4d5fa5c93 100644 --- a/ecc/bw6-633/g1_test.go +++ b/ecc/bw6-633/g1_test.go @@ -516,6 +516,51 @@ func BenchmarkG1JacIsInSubGroup(b *testing.B) { } +func BenchmarkG1JacEqual(b *testing.B) { + var scalar fp.Element + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("failed to set scalar: %s", err) + } + + var a G1Jac + a.ScalarMultiplication(&g1Gen, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + var scalarSquared fp.Element + scalarSquared.Square(&scalar) + + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalarSquared) + aZScaled.Y.Mul(&aZScaled.Y, &scalarSquared).Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 G1Jac + aPlus1.AddAssign(&g1Gen) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkBatchAddG1Affine(b *testing.B) { var P, R pG1AffineC16 diff --git a/ecc/bw6-633/g2.go b/ecc/bw6-633/g2.go index cce9c360c..5651e3117 100644 --- a/ecc/bw6-633/g2.go +++ b/ecc/bw6-633/g2.go @@ -172,13 +172,21 @@ func (p *G2Jac) Equal(a *G2Jac) bool { if p.Z.IsZero() && a.Z.IsZero() { return true } - _p := G2Affine{} - _p.FromJacobian(p) - _a := G2Affine{} - _a.FromJacobian(a) + var pZSquare, aZSquare fp.Element + pZSquare.Square(&p.Z) + aZSquare.Square(&a.Z) + + var lhs, rhs fp.Element + lhs.Mul(&p.X, &aZSquare) + rhs.Mul(&a.X, &pZSquare) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &a.Z) + rhs.Mul(&a.Y, &pZSquare).Mul(&rhs, &p.Z) - return _p.X.Equal(&_a.X) && _p.Y.Equal(&_a.Y) + return lhs.Equal(&rhs) } // Neg computes -G diff --git a/ecc/bw6-633/g2_test.go b/ecc/bw6-633/g2_test.go index 5b5b9a59a..c50010d06 100644 --- a/ecc/bw6-633/g2_test.go +++ b/ecc/bw6-633/g2_test.go @@ -486,6 +486,51 @@ func BenchmarkG2JacIsInSubGroup(b *testing.B) { } +func BenchmarkG2JacEqual(b *testing.B) { + var scalar fp.Element + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("failed to set scalar: %s", err) + } + + var a G2Jac + a.ScalarMultiplication(&g2Gen, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + var scalarSquared fp.Element + scalarSquared.Square(&scalar) + + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalarSquared) + aZScaled.Y.Mul(&aZScaled.Y, &scalarSquared).Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 G2Jac + aPlus1.AddAssign(&g2Gen) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkBatchAddG2Affine(b *testing.B) { var P, R pG2AffineC16 diff --git a/ecc/bw6-633/twistededwards/point.go b/ecc/bw6-633/twistededwards/point.go index d50a4081d..5c7d7c66d 100644 --- a/ecc/bw6-633/twistededwards/point.go +++ b/ecc/bw6-633/twistededwards/point.go @@ -297,10 +297,17 @@ func (p *PointProj) Equal(p1 *PointProj) bool { if p.Z.IsZero() || p1.Z.IsZero() { return false } - var pAffine, p1Affine PointAffine - pAffine.FromProj(p) - p1Affine.FromProj(p1) - return pAffine.Equal(&p1Affine) + + var lhs, rhs fr.Element + lhs.Mul(&p.X, &p1.Z) + rhs.Mul(&p1.X, &p.Z) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &p1.Z) + rhs.Mul(&p1.Y, &p.Z) + + return lhs.Equal(&rhs) } // IsZero returns true if p=0 false otherwise diff --git a/ecc/bw6-633/twistededwards/point_test.go b/ecc/bw6-633/twistededwards/point_test.go index f50541d1e..e8814e0f5 100644 --- a/ecc/bw6-633/twistededwards/point_test.go +++ b/ecc/bw6-633/twistededwards/point_test.go @@ -748,6 +748,52 @@ func GenBigInt() gopter.Gen { // ------------------------------------------------------------ // benches +func BenchmarkProjEqual(b *testing.B) { + params := GetEdwardsCurve() + + var scalar fr.Element + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("error generating random scalar: %v", err) + } + + var baseProj PointProj + baseProj.FromAffine(¶ms.Base) + var a PointProj + a.ScalarMultiplication(&baseProj, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalar) + aZScaled.Y.Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 PointProj + aPlus1.Add(&aPlus1, &baseProj) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkScalarMulExtended(b *testing.B) { params := GetEdwardsCurve() var a PointExtended diff --git a/ecc/bw6-756/g1.go b/ecc/bw6-756/g1.go index 5cad95ab9..d9274a772 100644 --- a/ecc/bw6-756/g1.go +++ b/ecc/bw6-756/g1.go @@ -193,13 +193,21 @@ func (p *G1Jac) Equal(a *G1Jac) bool { if p.Z.IsZero() && a.Z.IsZero() { return true } - _p := G1Affine{} - _p.FromJacobian(p) - _a := G1Affine{} - _a.FromJacobian(a) + var pZSquare, aZSquare fp.Element + pZSquare.Square(&p.Z) + aZSquare.Square(&a.Z) + + var lhs, rhs fp.Element + lhs.Mul(&p.X, &aZSquare) + rhs.Mul(&a.X, &pZSquare) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &a.Z) + rhs.Mul(&a.Y, &pZSquare).Mul(&rhs, &p.Z) - return _p.X.Equal(&_a.X) && _p.Y.Equal(&_a.Y) + return lhs.Equal(&rhs) } // Neg computes -G diff --git a/ecc/bw6-756/g1_test.go b/ecc/bw6-756/g1_test.go index b8e6964a8..da3edfaf1 100644 --- a/ecc/bw6-756/g1_test.go +++ b/ecc/bw6-756/g1_test.go @@ -516,6 +516,51 @@ func BenchmarkG1JacIsInSubGroup(b *testing.B) { } +func BenchmarkG1JacEqual(b *testing.B) { + var scalar fp.Element + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("failed to set scalar: %s", err) + } + + var a G1Jac + a.ScalarMultiplication(&g1Gen, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + var scalarSquared fp.Element + scalarSquared.Square(&scalar) + + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalarSquared) + aZScaled.Y.Mul(&aZScaled.Y, &scalarSquared).Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 G1Jac + aPlus1.AddAssign(&g1Gen) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkBatchAddG1Affine(b *testing.B) { var P, R pG1AffineC16 diff --git a/ecc/bw6-756/g2.go b/ecc/bw6-756/g2.go index 40be72f49..db9911793 100644 --- a/ecc/bw6-756/g2.go +++ b/ecc/bw6-756/g2.go @@ -172,13 +172,21 @@ func (p *G2Jac) Equal(a *G2Jac) bool { if p.Z.IsZero() && a.Z.IsZero() { return true } - _p := G2Affine{} - _p.FromJacobian(p) - _a := G2Affine{} - _a.FromJacobian(a) + var pZSquare, aZSquare fp.Element + pZSquare.Square(&p.Z) + aZSquare.Square(&a.Z) + + var lhs, rhs fp.Element + lhs.Mul(&p.X, &aZSquare) + rhs.Mul(&a.X, &pZSquare) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &a.Z) + rhs.Mul(&a.Y, &pZSquare).Mul(&rhs, &p.Z) - return _p.X.Equal(&_a.X) && _p.Y.Equal(&_a.Y) + return lhs.Equal(&rhs) } // Neg computes -G diff --git a/ecc/bw6-756/g2_test.go b/ecc/bw6-756/g2_test.go index 0c5699b79..fe33bc2e2 100644 --- a/ecc/bw6-756/g2_test.go +++ b/ecc/bw6-756/g2_test.go @@ -486,6 +486,51 @@ func BenchmarkG2JacIsInSubGroup(b *testing.B) { } +func BenchmarkG2JacEqual(b *testing.B) { + var scalar fp.Element + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("failed to set scalar: %s", err) + } + + var a G2Jac + a.ScalarMultiplication(&g2Gen, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + var scalarSquared fp.Element + scalarSquared.Square(&scalar) + + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalarSquared) + aZScaled.Y.Mul(&aZScaled.Y, &scalarSquared).Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 G2Jac + aPlus1.AddAssign(&g2Gen) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkBatchAddG2Affine(b *testing.B) { var P, R pG2AffineC16 diff --git a/ecc/bw6-756/twistededwards/point.go b/ecc/bw6-756/twistededwards/point.go index e46bac929..f3c33b2dc 100644 --- a/ecc/bw6-756/twistededwards/point.go +++ b/ecc/bw6-756/twistededwards/point.go @@ -297,10 +297,17 @@ func (p *PointProj) Equal(p1 *PointProj) bool { if p.Z.IsZero() || p1.Z.IsZero() { return false } - var pAffine, p1Affine PointAffine - pAffine.FromProj(p) - p1Affine.FromProj(p1) - return pAffine.Equal(&p1Affine) + + var lhs, rhs fr.Element + lhs.Mul(&p.X, &p1.Z) + rhs.Mul(&p1.X, &p.Z) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &p1.Z) + rhs.Mul(&p1.Y, &p.Z) + + return lhs.Equal(&rhs) } // IsZero returns true if p=0 false otherwise diff --git a/ecc/bw6-756/twistededwards/point_test.go b/ecc/bw6-756/twistededwards/point_test.go index 13648781f..c6d5d8503 100644 --- a/ecc/bw6-756/twistededwards/point_test.go +++ b/ecc/bw6-756/twistededwards/point_test.go @@ -748,6 +748,52 @@ func GenBigInt() gopter.Gen { // ------------------------------------------------------------ // benches +func BenchmarkProjEqual(b *testing.B) { + params := GetEdwardsCurve() + + var scalar fr.Element + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("error generating random scalar: %v", err) + } + + var baseProj PointProj + baseProj.FromAffine(¶ms.Base) + var a PointProj + a.ScalarMultiplication(&baseProj, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalar) + aZScaled.Y.Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 PointProj + aPlus1.Add(&aPlus1, &baseProj) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkScalarMulExtended(b *testing.B) { params := GetEdwardsCurve() var a PointExtended diff --git a/ecc/bw6-761/g1.go b/ecc/bw6-761/g1.go index 3f00288a0..54ad6519c 100644 --- a/ecc/bw6-761/g1.go +++ b/ecc/bw6-761/g1.go @@ -193,13 +193,21 @@ func (p *G1Jac) Equal(a *G1Jac) bool { if p.Z.IsZero() && a.Z.IsZero() { return true } - _p := G1Affine{} - _p.FromJacobian(p) - _a := G1Affine{} - _a.FromJacobian(a) + var pZSquare, aZSquare fp.Element + pZSquare.Square(&p.Z) + aZSquare.Square(&a.Z) + + var lhs, rhs fp.Element + lhs.Mul(&p.X, &aZSquare) + rhs.Mul(&a.X, &pZSquare) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &a.Z) + rhs.Mul(&a.Y, &pZSquare).Mul(&rhs, &p.Z) - return _p.X.Equal(&_a.X) && _p.Y.Equal(&_a.Y) + return lhs.Equal(&rhs) } // Neg computes -G diff --git a/ecc/bw6-761/g1_test.go b/ecc/bw6-761/g1_test.go index 6f342aa51..0637db0c4 100644 --- a/ecc/bw6-761/g1_test.go +++ b/ecc/bw6-761/g1_test.go @@ -516,6 +516,51 @@ func BenchmarkG1JacIsInSubGroup(b *testing.B) { } +func BenchmarkG1JacEqual(b *testing.B) { + var scalar fp.Element + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("failed to set scalar: %s", err) + } + + var a G1Jac + a.ScalarMultiplication(&g1Gen, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + var scalarSquared fp.Element + scalarSquared.Square(&scalar) + + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalarSquared) + aZScaled.Y.Mul(&aZScaled.Y, &scalarSquared).Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 G1Jac + aPlus1.AddAssign(&g1Gen) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkBatchAddG1Affine(b *testing.B) { var P, R pG1AffineC16 diff --git a/ecc/bw6-761/g2.go b/ecc/bw6-761/g2.go index 9f6ccbf13..c454e7ca2 100644 --- a/ecc/bw6-761/g2.go +++ b/ecc/bw6-761/g2.go @@ -172,13 +172,21 @@ func (p *G2Jac) Equal(a *G2Jac) bool { if p.Z.IsZero() && a.Z.IsZero() { return true } - _p := G2Affine{} - _p.FromJacobian(p) - _a := G2Affine{} - _a.FromJacobian(a) + var pZSquare, aZSquare fp.Element + pZSquare.Square(&p.Z) + aZSquare.Square(&a.Z) + + var lhs, rhs fp.Element + lhs.Mul(&p.X, &aZSquare) + rhs.Mul(&a.X, &pZSquare) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &a.Z) + rhs.Mul(&a.Y, &pZSquare).Mul(&rhs, &p.Z) - return _p.X.Equal(&_a.X) && _p.Y.Equal(&_a.Y) + return lhs.Equal(&rhs) } // Neg computes -G diff --git a/ecc/bw6-761/g2_test.go b/ecc/bw6-761/g2_test.go index 55f053a3d..634a91e1e 100644 --- a/ecc/bw6-761/g2_test.go +++ b/ecc/bw6-761/g2_test.go @@ -486,6 +486,51 @@ func BenchmarkG2JacIsInSubGroup(b *testing.B) { } +func BenchmarkG2JacEqual(b *testing.B) { + var scalar fp.Element + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("failed to set scalar: %s", err) + } + + var a G2Jac + a.ScalarMultiplication(&g2Gen, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + var scalarSquared fp.Element + scalarSquared.Square(&scalar) + + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalarSquared) + aZScaled.Y.Mul(&aZScaled.Y, &scalarSquared).Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 G2Jac + aPlus1.AddAssign(&g2Gen) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkBatchAddG2Affine(b *testing.B) { var P, R pG2AffineC16 diff --git a/ecc/bw6-761/twistededwards/point.go b/ecc/bw6-761/twistededwards/point.go index 1943561d4..d1fee121c 100644 --- a/ecc/bw6-761/twistededwards/point.go +++ b/ecc/bw6-761/twistededwards/point.go @@ -297,10 +297,17 @@ func (p *PointProj) Equal(p1 *PointProj) bool { if p.Z.IsZero() || p1.Z.IsZero() { return false } - var pAffine, p1Affine PointAffine - pAffine.FromProj(p) - p1Affine.FromProj(p1) - return pAffine.Equal(&p1Affine) + + var lhs, rhs fr.Element + lhs.Mul(&p.X, &p1.Z) + rhs.Mul(&p1.X, &p.Z) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &p1.Z) + rhs.Mul(&p1.Y, &p.Z) + + return lhs.Equal(&rhs) } // IsZero returns true if p=0 false otherwise diff --git a/ecc/bw6-761/twistededwards/point_test.go b/ecc/bw6-761/twistededwards/point_test.go index 80be8ff2d..33668686b 100644 --- a/ecc/bw6-761/twistededwards/point_test.go +++ b/ecc/bw6-761/twistededwards/point_test.go @@ -748,6 +748,52 @@ func GenBigInt() gopter.Gen { // ------------------------------------------------------------ // benches +func BenchmarkProjEqual(b *testing.B) { + params := GetEdwardsCurve() + + var scalar fr.Element + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("error generating random scalar: %v", err) + } + + var baseProj PointProj + baseProj.FromAffine(¶ms.Base) + var a PointProj + a.ScalarMultiplication(&baseProj, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalar) + aZScaled.Y.Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 PointProj + aPlus1.Add(&aPlus1, &baseProj) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkScalarMulExtended(b *testing.B) { params := GetEdwardsCurve() var a PointExtended diff --git a/ecc/secp256k1/g1.go b/ecc/secp256k1/g1.go index 862e9c6ac..31b93f4d4 100644 --- a/ecc/secp256k1/g1.go +++ b/ecc/secp256k1/g1.go @@ -188,13 +188,21 @@ func (p *G1Jac) Equal(a *G1Jac) bool { if p.Z.IsZero() && a.Z.IsZero() { return true } - _p := G1Affine{} - _p.FromJacobian(p) - _a := G1Affine{} - _a.FromJacobian(a) + var pZSquare, aZSquare fp.Element + pZSquare.Square(&p.Z) + aZSquare.Square(&a.Z) + + var lhs, rhs fp.Element + lhs.Mul(&p.X, &aZSquare) + rhs.Mul(&a.X, &pZSquare) + if !lhs.Equal(&rhs) { + return false + } + lhs.Mul(&p.Y, &aZSquare).Mul(&lhs, &a.Z) + rhs.Mul(&a.Y, &pZSquare).Mul(&rhs, &p.Z) - return _p.X.Equal(&_a.X) && _p.Y.Equal(&_a.Y) + return lhs.Equal(&rhs) } // Neg computes -G diff --git a/ecc/secp256k1/g1_test.go b/ecc/secp256k1/g1_test.go index 252e46aef..fe2bae69d 100644 --- a/ecc/secp256k1/g1_test.go +++ b/ecc/secp256k1/g1_test.go @@ -477,6 +477,51 @@ func BenchmarkG1JacIsInSubGroup(b *testing.B) { } +func BenchmarkG1JacEqual(b *testing.B) { + var scalar fp.Element + if _, err := scalar.SetRandom(); err != nil { + b.Fatalf("failed to set scalar: %s", err) + } + + var a G1Jac + a.ScalarMultiplication(&g1Gen, big.NewInt(42)) + + b.Run("equal", func(b *testing.B) { + var scalarSquared fp.Element + scalarSquared.Square(&scalar) + + aZScaled := a + aZScaled.X.Mul(&aZScaled.X, &scalarSquared) + aZScaled.Y.Mul(&aZScaled.Y, &scalarSquared).Mul(&aZScaled.Y, &scalar) + aZScaled.Z.Mul(&aZScaled.Z, &scalar) + + // Check the setup. + if !a.Equal(&aZScaled) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aZScaled) + } + }) + + b.Run("not equal", func(b *testing.B) { + var aPlus1 G1Jac + aPlus1.AddAssign(&g1Gen) + + // Check the setup. + if a.Equal(&aPlus1) { + b.Fatalf("invalid test setup") + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + a.Equal(&aPlus1) + } + }) +} + func BenchmarkBatchAddG1Affine(b *testing.B) { var P, R pG1AffineC15 From a7ef62f8bdd85b393f868cf372721438351011e2 Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Fri, 22 Sep 2023 15:49:09 -0300 Subject: [PATCH 6/7] fix bench detail & go generate Signed-off-by: Ignacio Hagopian --- ecc/bls12-377/twistededwards/point_test.go | 2 +- ecc/bls12-378/twistededwards/point_test.go | 2 +- ecc/bls12-381/bandersnatch/point_test.go | 2 +- ecc/bls12-381/twistededwards/point_test.go | 2 +- ecc/bls24-315/twistededwards/point_test.go | 2 +- ecc/bls24-317/twistededwards/point_test.go | 2 +- ecc/bn254/twistededwards/point_test.go | 2 +- ecc/bw6-633/twistededwards/point_test.go | 2 +- ecc/bw6-756/twistededwards/point_test.go | 2 +- ecc/bw6-761/twistededwards/point_test.go | 2 +- internal/generator/edwards/template/tests/point.go.tmpl | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/ecc/bls12-377/twistededwards/point_test.go b/ecc/bls12-377/twistededwards/point_test.go index 4d0631d1a..8c013f0d9 100644 --- a/ecc/bls12-377/twistededwards/point_test.go +++ b/ecc/bls12-377/twistededwards/point_test.go @@ -780,7 +780,7 @@ func BenchmarkProjEqual(b *testing.B) { b.Run("not equal", func(b *testing.B) { var aPlus1 PointProj - aPlus1.Add(&aPlus1, &baseProj) + aPlus1.Add(&a, &baseProj) // Check the setup. if a.Equal(&aPlus1) { diff --git a/ecc/bls12-378/twistededwards/point_test.go b/ecc/bls12-378/twistededwards/point_test.go index b53451742..8d6f7ba79 100644 --- a/ecc/bls12-378/twistededwards/point_test.go +++ b/ecc/bls12-378/twistededwards/point_test.go @@ -780,7 +780,7 @@ func BenchmarkProjEqual(b *testing.B) { b.Run("not equal", func(b *testing.B) { var aPlus1 PointProj - aPlus1.Add(&aPlus1, &baseProj) + aPlus1.Add(&a, &baseProj) // Check the setup. if a.Equal(&aPlus1) { diff --git a/ecc/bls12-381/bandersnatch/point_test.go b/ecc/bls12-381/bandersnatch/point_test.go index 996461af6..f5df6db26 100644 --- a/ecc/bls12-381/bandersnatch/point_test.go +++ b/ecc/bls12-381/bandersnatch/point_test.go @@ -780,7 +780,7 @@ func BenchmarkProjEqual(b *testing.B) { b.Run("not equal", func(b *testing.B) { var aPlus1 PointProj - aPlus1.Add(&aPlus1, &baseProj) + aPlus1.Add(&a, &baseProj) // Check the setup. if a.Equal(&aPlus1) { diff --git a/ecc/bls12-381/twistededwards/point_test.go b/ecc/bls12-381/twistededwards/point_test.go index fe3e16a6b..adb988a04 100644 --- a/ecc/bls12-381/twistededwards/point_test.go +++ b/ecc/bls12-381/twistededwards/point_test.go @@ -780,7 +780,7 @@ func BenchmarkProjEqual(b *testing.B) { b.Run("not equal", func(b *testing.B) { var aPlus1 PointProj - aPlus1.Add(&aPlus1, &baseProj) + aPlus1.Add(&a, &baseProj) // Check the setup. if a.Equal(&aPlus1) { diff --git a/ecc/bls24-315/twistededwards/point_test.go b/ecc/bls24-315/twistededwards/point_test.go index 12f4b6316..e7bec5f9d 100644 --- a/ecc/bls24-315/twistededwards/point_test.go +++ b/ecc/bls24-315/twistededwards/point_test.go @@ -780,7 +780,7 @@ func BenchmarkProjEqual(b *testing.B) { b.Run("not equal", func(b *testing.B) { var aPlus1 PointProj - aPlus1.Add(&aPlus1, &baseProj) + aPlus1.Add(&a, &baseProj) // Check the setup. if a.Equal(&aPlus1) { diff --git a/ecc/bls24-317/twistededwards/point_test.go b/ecc/bls24-317/twistededwards/point_test.go index 331a1d5ae..1cdad6e19 100644 --- a/ecc/bls24-317/twistededwards/point_test.go +++ b/ecc/bls24-317/twistededwards/point_test.go @@ -780,7 +780,7 @@ func BenchmarkProjEqual(b *testing.B) { b.Run("not equal", func(b *testing.B) { var aPlus1 PointProj - aPlus1.Add(&aPlus1, &baseProj) + aPlus1.Add(&a, &baseProj) // Check the setup. if a.Equal(&aPlus1) { diff --git a/ecc/bn254/twistededwards/point_test.go b/ecc/bn254/twistededwards/point_test.go index 0c58a80a7..8e5617d08 100644 --- a/ecc/bn254/twistededwards/point_test.go +++ b/ecc/bn254/twistededwards/point_test.go @@ -780,7 +780,7 @@ func BenchmarkProjEqual(b *testing.B) { b.Run("not equal", func(b *testing.B) { var aPlus1 PointProj - aPlus1.Add(&aPlus1, &baseProj) + aPlus1.Add(&a, &baseProj) // Check the setup. if a.Equal(&aPlus1) { diff --git a/ecc/bw6-633/twistededwards/point_test.go b/ecc/bw6-633/twistededwards/point_test.go index e8814e0f5..aedf31246 100644 --- a/ecc/bw6-633/twistededwards/point_test.go +++ b/ecc/bw6-633/twistededwards/point_test.go @@ -780,7 +780,7 @@ func BenchmarkProjEqual(b *testing.B) { b.Run("not equal", func(b *testing.B) { var aPlus1 PointProj - aPlus1.Add(&aPlus1, &baseProj) + aPlus1.Add(&a, &baseProj) // Check the setup. if a.Equal(&aPlus1) { diff --git a/ecc/bw6-756/twistededwards/point_test.go b/ecc/bw6-756/twistededwards/point_test.go index c6d5d8503..234ac9c4b 100644 --- a/ecc/bw6-756/twistededwards/point_test.go +++ b/ecc/bw6-756/twistededwards/point_test.go @@ -780,7 +780,7 @@ func BenchmarkProjEqual(b *testing.B) { b.Run("not equal", func(b *testing.B) { var aPlus1 PointProj - aPlus1.Add(&aPlus1, &baseProj) + aPlus1.Add(&a, &baseProj) // Check the setup. if a.Equal(&aPlus1) { diff --git a/ecc/bw6-761/twistededwards/point_test.go b/ecc/bw6-761/twistededwards/point_test.go index 33668686b..5a1f98fd9 100644 --- a/ecc/bw6-761/twistededwards/point_test.go +++ b/ecc/bw6-761/twistededwards/point_test.go @@ -780,7 +780,7 @@ func BenchmarkProjEqual(b *testing.B) { b.Run("not equal", func(b *testing.B) { var aPlus1 PointProj - aPlus1.Add(&aPlus1, &baseProj) + aPlus1.Add(&a, &baseProj) // Check the setup. if a.Equal(&aPlus1) { diff --git a/internal/generator/edwards/template/tests/point.go.tmpl b/internal/generator/edwards/template/tests/point.go.tmpl index 4f2d16708..fe758266f 100644 --- a/internal/generator/edwards/template/tests/point.go.tmpl +++ b/internal/generator/edwards/template/tests/point.go.tmpl @@ -764,7 +764,7 @@ func BenchmarkProjEqual(b *testing.B) { b.Run("not equal", func(b *testing.B) { var aPlus1 PointProj - aPlus1.Add(&aPlus1, &baseProj) + aPlus1.Add(&a, &baseProj) // Check the setup. if a.Equal(&aPlus1) { From 255461e78d73633c79e7135d8c8749491a4c2b94 Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Sun, 24 Sep 2023 08:52:53 -0300 Subject: [PATCH 7/7] ecc: fix neutral elements cases Signed-off-by: Ignacio Hagopian --- ecc/bls12-377/g1.go | 11 ++++++++--- ecc/bls12-377/g2.go | 11 ++++++++--- ecc/bls12-377/twistededwards/point.go | 8 +++++++- ecc/bls12-378/g1.go | 11 ++++++++--- ecc/bls12-378/g2.go | 11 ++++++++--- ecc/bls12-378/twistededwards/point.go | 8 +++++++- ecc/bls12-381/bandersnatch/point.go | 8 +++++++- ecc/bls12-381/g1.go | 11 ++++++++--- ecc/bls12-381/g2.go | 11 ++++++++--- ecc/bls12-381/twistededwards/point.go | 8 +++++++- ecc/bls24-315/g1.go | 11 ++++++++--- ecc/bls24-315/g2.go | 11 ++++++++--- ecc/bls24-315/twistededwards/point.go | 8 +++++++- ecc/bls24-317/g1.go | 11 ++++++++--- ecc/bls24-317/g2.go | 11 ++++++++--- ecc/bls24-317/twistededwards/point.go | 8 +++++++- ecc/bn254/g1.go | 11 ++++++++--- ecc/bn254/g2.go | 11 ++++++++--- ecc/bn254/twistededwards/point.go | 8 +++++++- ecc/bw6-633/g1.go | 11 ++++++++--- ecc/bw6-633/g2.go | 11 ++++++++--- ecc/bw6-633/twistededwards/point.go | 8 +++++++- ecc/bw6-756/g1.go | 11 ++++++++--- ecc/bw6-756/g2.go | 11 ++++++++--- ecc/bw6-756/twistededwards/point.go | 8 +++++++- ecc/bw6-761/g1.go | 11 ++++++++--- ecc/bw6-761/g2.go | 11 ++++++++--- ecc/bw6-761/twistededwards/point.go | 8 +++++++- ecc/secp256k1/g1.go | 11 ++++++++--- internal/generator/ecc/template/point.go.tmpl | 11 ++++++++--- internal/generator/edwards/template/point.go.tmpl | 8 +++++++- 31 files changed, 237 insertions(+), 71 deletions(-) diff --git a/ecc/bls12-377/g1.go b/ecc/bls12-377/g1.go index 3d24e0f14..43410258d 100644 --- a/ecc/bls12-377/g1.go +++ b/ecc/bls12-377/g1.go @@ -184,9 +184,14 @@ func (p *G1Jac) Set(a *G1Jac) *G1Jac { // Equal tests if two points (in Jacobian coordinates) are equal func (p *G1Jac) Equal(a *G1Jac) bool { - - if p.Z.IsZero() && a.Z.IsZero() { - return true + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return a.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if a.Z.IsZero() { + return false } var pZSquare, aZSquare fp.Element diff --git a/ecc/bls12-377/g2.go b/ecc/bls12-377/g2.go index 13ed328d3..8e0039799 100644 --- a/ecc/bls12-377/g2.go +++ b/ecc/bls12-377/g2.go @@ -173,9 +173,14 @@ func (p *G2Jac) Set(a *G2Jac) *G2Jac { // Equal tests if two points (in Jacobian coordinates) are equal func (p *G2Jac) Equal(a *G2Jac) bool { - - if p.Z.IsZero() && a.Z.IsZero() { - return true + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return a.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if a.Z.IsZero() { + return false } var pZSquare, aZSquare fptower.E2 diff --git a/ecc/bls12-377/twistededwards/point.go b/ecc/bls12-377/twistededwards/point.go index 39177ad98..9359b12ff 100644 --- a/ecc/bls12-377/twistededwards/point.go +++ b/ecc/bls12-377/twistededwards/point.go @@ -294,7 +294,13 @@ func (p *PointProj) setInfinity() *PointProj { // Equal returns true if p=p1 false otherwise // If one point is on the affine chart Z=0 it returns false func (p *PointProj) Equal(p1 *PointProj) bool { - if p.Z.IsZero() || p1.Z.IsZero() { + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return p1.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if p1.Z.IsZero() { return false } diff --git a/ecc/bls12-378/g1.go b/ecc/bls12-378/g1.go index 5ba2824b1..03f555f7c 100644 --- a/ecc/bls12-378/g1.go +++ b/ecc/bls12-378/g1.go @@ -184,9 +184,14 @@ func (p *G1Jac) Set(a *G1Jac) *G1Jac { // Equal tests if two points (in Jacobian coordinates) are equal func (p *G1Jac) Equal(a *G1Jac) bool { - - if p.Z.IsZero() && a.Z.IsZero() { - return true + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return a.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if a.Z.IsZero() { + return false } var pZSquare, aZSquare fp.Element diff --git a/ecc/bls12-378/g2.go b/ecc/bls12-378/g2.go index dcde1e472..c0bf26edc 100644 --- a/ecc/bls12-378/g2.go +++ b/ecc/bls12-378/g2.go @@ -173,9 +173,14 @@ func (p *G2Jac) Set(a *G2Jac) *G2Jac { // Equal tests if two points (in Jacobian coordinates) are equal func (p *G2Jac) Equal(a *G2Jac) bool { - - if p.Z.IsZero() && a.Z.IsZero() { - return true + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return a.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if a.Z.IsZero() { + return false } var pZSquare, aZSquare fptower.E2 diff --git a/ecc/bls12-378/twistededwards/point.go b/ecc/bls12-378/twistededwards/point.go index 7587c02d5..c66be4aca 100644 --- a/ecc/bls12-378/twistededwards/point.go +++ b/ecc/bls12-378/twistededwards/point.go @@ -294,7 +294,13 @@ func (p *PointProj) setInfinity() *PointProj { // Equal returns true if p=p1 false otherwise // If one point is on the affine chart Z=0 it returns false func (p *PointProj) Equal(p1 *PointProj) bool { - if p.Z.IsZero() || p1.Z.IsZero() { + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return p1.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if p1.Z.IsZero() { return false } diff --git a/ecc/bls12-381/bandersnatch/point.go b/ecc/bls12-381/bandersnatch/point.go index 8cddf0ee5..68b06bc91 100644 --- a/ecc/bls12-381/bandersnatch/point.go +++ b/ecc/bls12-381/bandersnatch/point.go @@ -293,7 +293,13 @@ func (p *PointProj) setInfinity() *PointProj { // Equal returns true if p=p1 false otherwise // If one point is on the affine chart Z=0 it returns false func (p *PointProj) Equal(p1 *PointProj) bool { - if p.Z.IsZero() || p1.Z.IsZero() { + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return p1.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if p1.Z.IsZero() { return false } diff --git a/ecc/bls12-381/g1.go b/ecc/bls12-381/g1.go index 02798747c..5ba2d93d8 100644 --- a/ecc/bls12-381/g1.go +++ b/ecc/bls12-381/g1.go @@ -184,9 +184,14 @@ func (p *G1Jac) Set(a *G1Jac) *G1Jac { // Equal tests if two points (in Jacobian coordinates) are equal func (p *G1Jac) Equal(a *G1Jac) bool { - - if p.Z.IsZero() && a.Z.IsZero() { - return true + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return a.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if a.Z.IsZero() { + return false } var pZSquare, aZSquare fp.Element diff --git a/ecc/bls12-381/g2.go b/ecc/bls12-381/g2.go index e58b642dc..d40cf1a6f 100644 --- a/ecc/bls12-381/g2.go +++ b/ecc/bls12-381/g2.go @@ -173,9 +173,14 @@ func (p *G2Jac) Set(a *G2Jac) *G2Jac { // Equal tests if two points (in Jacobian coordinates) are equal func (p *G2Jac) Equal(a *G2Jac) bool { - - if p.Z.IsZero() && a.Z.IsZero() { - return true + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return a.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if a.Z.IsZero() { + return false } var pZSquare, aZSquare fptower.E2 diff --git a/ecc/bls12-381/twistededwards/point.go b/ecc/bls12-381/twistededwards/point.go index 54de81197..fc68f84c4 100644 --- a/ecc/bls12-381/twistededwards/point.go +++ b/ecc/bls12-381/twistededwards/point.go @@ -294,7 +294,13 @@ func (p *PointProj) setInfinity() *PointProj { // Equal returns true if p=p1 false otherwise // If one point is on the affine chart Z=0 it returns false func (p *PointProj) Equal(p1 *PointProj) bool { - if p.Z.IsZero() || p1.Z.IsZero() { + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return p1.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if p1.Z.IsZero() { return false } diff --git a/ecc/bls24-315/g1.go b/ecc/bls24-315/g1.go index 350e0a528..903fbad19 100644 --- a/ecc/bls24-315/g1.go +++ b/ecc/bls24-315/g1.go @@ -184,9 +184,14 @@ func (p *G1Jac) Set(a *G1Jac) *G1Jac { // Equal tests if two points (in Jacobian coordinates) are equal func (p *G1Jac) Equal(a *G1Jac) bool { - - if p.Z.IsZero() && a.Z.IsZero() { - return true + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return a.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if a.Z.IsZero() { + return false } var pZSquare, aZSquare fp.Element diff --git a/ecc/bls24-315/g2.go b/ecc/bls24-315/g2.go index 13ce0a4e9..541a06ef2 100644 --- a/ecc/bls24-315/g2.go +++ b/ecc/bls24-315/g2.go @@ -173,9 +173,14 @@ func (p *G2Jac) Set(a *G2Jac) *G2Jac { // Equal tests if two points (in Jacobian coordinates) are equal func (p *G2Jac) Equal(a *G2Jac) bool { - - if p.Z.IsZero() && a.Z.IsZero() { - return true + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return a.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if a.Z.IsZero() { + return false } var pZSquare, aZSquare fptower.E4 diff --git a/ecc/bls24-315/twistededwards/point.go b/ecc/bls24-315/twistededwards/point.go index 0a58cb485..31ed71a52 100644 --- a/ecc/bls24-315/twistededwards/point.go +++ b/ecc/bls24-315/twistededwards/point.go @@ -294,7 +294,13 @@ func (p *PointProj) setInfinity() *PointProj { // Equal returns true if p=p1 false otherwise // If one point is on the affine chart Z=0 it returns false func (p *PointProj) Equal(p1 *PointProj) bool { - if p.Z.IsZero() || p1.Z.IsZero() { + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return p1.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if p1.Z.IsZero() { return false } diff --git a/ecc/bls24-317/g1.go b/ecc/bls24-317/g1.go index 50b479a5e..76a8ccabe 100644 --- a/ecc/bls24-317/g1.go +++ b/ecc/bls24-317/g1.go @@ -184,9 +184,14 @@ func (p *G1Jac) Set(a *G1Jac) *G1Jac { // Equal tests if two points (in Jacobian coordinates) are equal func (p *G1Jac) Equal(a *G1Jac) bool { - - if p.Z.IsZero() && a.Z.IsZero() { - return true + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return a.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if a.Z.IsZero() { + return false } var pZSquare, aZSquare fp.Element diff --git a/ecc/bls24-317/g2.go b/ecc/bls24-317/g2.go index 6a11e348f..7fde5e070 100644 --- a/ecc/bls24-317/g2.go +++ b/ecc/bls24-317/g2.go @@ -173,9 +173,14 @@ func (p *G2Jac) Set(a *G2Jac) *G2Jac { // Equal tests if two points (in Jacobian coordinates) are equal func (p *G2Jac) Equal(a *G2Jac) bool { - - if p.Z.IsZero() && a.Z.IsZero() { - return true + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return a.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if a.Z.IsZero() { + return false } var pZSquare, aZSquare fptower.E4 diff --git a/ecc/bls24-317/twistededwards/point.go b/ecc/bls24-317/twistededwards/point.go index 54d073a71..906c6f741 100644 --- a/ecc/bls24-317/twistededwards/point.go +++ b/ecc/bls24-317/twistededwards/point.go @@ -294,7 +294,13 @@ func (p *PointProj) setInfinity() *PointProj { // Equal returns true if p=p1 false otherwise // If one point is on the affine chart Z=0 it returns false func (p *PointProj) Equal(p1 *PointProj) bool { - if p.Z.IsZero() || p1.Z.IsZero() { + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return p1.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if p1.Z.IsZero() { return false } diff --git a/ecc/bn254/g1.go b/ecc/bn254/g1.go index 2733f5b11..eff9e13cc 100644 --- a/ecc/bn254/g1.go +++ b/ecc/bn254/g1.go @@ -184,9 +184,14 @@ func (p *G1Jac) Set(a *G1Jac) *G1Jac { // Equal tests if two points (in Jacobian coordinates) are equal func (p *G1Jac) Equal(a *G1Jac) bool { - - if p.Z.IsZero() && a.Z.IsZero() { - return true + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return a.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if a.Z.IsZero() { + return false } var pZSquare, aZSquare fp.Element diff --git a/ecc/bn254/g2.go b/ecc/bn254/g2.go index 70b1de2fe..f9de9cf7c 100644 --- a/ecc/bn254/g2.go +++ b/ecc/bn254/g2.go @@ -173,9 +173,14 @@ func (p *G2Jac) Set(a *G2Jac) *G2Jac { // Equal tests if two points (in Jacobian coordinates) are equal func (p *G2Jac) Equal(a *G2Jac) bool { - - if p.Z.IsZero() && a.Z.IsZero() { - return true + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return a.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if a.Z.IsZero() { + return false } var pZSquare, aZSquare fptower.E2 diff --git a/ecc/bn254/twistededwards/point.go b/ecc/bn254/twistededwards/point.go index add15937c..084c0db9b 100644 --- a/ecc/bn254/twistededwards/point.go +++ b/ecc/bn254/twistededwards/point.go @@ -294,7 +294,13 @@ func (p *PointProj) setInfinity() *PointProj { // Equal returns true if p=p1 false otherwise // If one point is on the affine chart Z=0 it returns false func (p *PointProj) Equal(p1 *PointProj) bool { - if p.Z.IsZero() || p1.Z.IsZero() { + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return p1.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if p1.Z.IsZero() { return false } diff --git a/ecc/bw6-633/g1.go b/ecc/bw6-633/g1.go index da7b4d91b..e9d45e8a3 100644 --- a/ecc/bw6-633/g1.go +++ b/ecc/bw6-633/g1.go @@ -189,9 +189,14 @@ func (p *G1Jac) Set(a *G1Jac) *G1Jac { // Equal tests if two points (in Jacobian coordinates) are equal func (p *G1Jac) Equal(a *G1Jac) bool { - - if p.Z.IsZero() && a.Z.IsZero() { - return true + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return a.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if a.Z.IsZero() { + return false } var pZSquare, aZSquare fp.Element diff --git a/ecc/bw6-633/g2.go b/ecc/bw6-633/g2.go index 5651e3117..585496295 100644 --- a/ecc/bw6-633/g2.go +++ b/ecc/bw6-633/g2.go @@ -168,9 +168,14 @@ func (p *G2Jac) Set(a *G2Jac) *G2Jac { // Equal tests if two points (in Jacobian coordinates) are equal func (p *G2Jac) Equal(a *G2Jac) bool { - - if p.Z.IsZero() && a.Z.IsZero() { - return true + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return a.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if a.Z.IsZero() { + return false } var pZSquare, aZSquare fp.Element diff --git a/ecc/bw6-633/twistededwards/point.go b/ecc/bw6-633/twistededwards/point.go index 5c7d7c66d..6dd41d0f6 100644 --- a/ecc/bw6-633/twistededwards/point.go +++ b/ecc/bw6-633/twistededwards/point.go @@ -294,7 +294,13 @@ func (p *PointProj) setInfinity() *PointProj { // Equal returns true if p=p1 false otherwise // If one point is on the affine chart Z=0 it returns false func (p *PointProj) Equal(p1 *PointProj) bool { - if p.Z.IsZero() || p1.Z.IsZero() { + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return p1.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if p1.Z.IsZero() { return false } diff --git a/ecc/bw6-756/g1.go b/ecc/bw6-756/g1.go index d9274a772..b31c1e464 100644 --- a/ecc/bw6-756/g1.go +++ b/ecc/bw6-756/g1.go @@ -189,9 +189,14 @@ func (p *G1Jac) Set(a *G1Jac) *G1Jac { // Equal tests if two points (in Jacobian coordinates) are equal func (p *G1Jac) Equal(a *G1Jac) bool { - - if p.Z.IsZero() && a.Z.IsZero() { - return true + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return a.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if a.Z.IsZero() { + return false } var pZSquare, aZSquare fp.Element diff --git a/ecc/bw6-756/g2.go b/ecc/bw6-756/g2.go index db9911793..1826664a6 100644 --- a/ecc/bw6-756/g2.go +++ b/ecc/bw6-756/g2.go @@ -168,9 +168,14 @@ func (p *G2Jac) Set(a *G2Jac) *G2Jac { // Equal tests if two points (in Jacobian coordinates) are equal func (p *G2Jac) Equal(a *G2Jac) bool { - - if p.Z.IsZero() && a.Z.IsZero() { - return true + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return a.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if a.Z.IsZero() { + return false } var pZSquare, aZSquare fp.Element diff --git a/ecc/bw6-756/twistededwards/point.go b/ecc/bw6-756/twistededwards/point.go index f3c33b2dc..799ff121c 100644 --- a/ecc/bw6-756/twistededwards/point.go +++ b/ecc/bw6-756/twistededwards/point.go @@ -294,7 +294,13 @@ func (p *PointProj) setInfinity() *PointProj { // Equal returns true if p=p1 false otherwise // If one point is on the affine chart Z=0 it returns false func (p *PointProj) Equal(p1 *PointProj) bool { - if p.Z.IsZero() || p1.Z.IsZero() { + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return p1.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if p1.Z.IsZero() { return false } diff --git a/ecc/bw6-761/g1.go b/ecc/bw6-761/g1.go index 54ad6519c..ffa552d0b 100644 --- a/ecc/bw6-761/g1.go +++ b/ecc/bw6-761/g1.go @@ -189,9 +189,14 @@ func (p *G1Jac) Set(a *G1Jac) *G1Jac { // Equal tests if two points (in Jacobian coordinates) are equal func (p *G1Jac) Equal(a *G1Jac) bool { - - if p.Z.IsZero() && a.Z.IsZero() { - return true + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return a.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if a.Z.IsZero() { + return false } var pZSquare, aZSquare fp.Element diff --git a/ecc/bw6-761/g2.go b/ecc/bw6-761/g2.go index c454e7ca2..2d52afa5d 100644 --- a/ecc/bw6-761/g2.go +++ b/ecc/bw6-761/g2.go @@ -168,9 +168,14 @@ func (p *G2Jac) Set(a *G2Jac) *G2Jac { // Equal tests if two points (in Jacobian coordinates) are equal func (p *G2Jac) Equal(a *G2Jac) bool { - - if p.Z.IsZero() && a.Z.IsZero() { - return true + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return a.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if a.Z.IsZero() { + return false } var pZSquare, aZSquare fp.Element diff --git a/ecc/bw6-761/twistededwards/point.go b/ecc/bw6-761/twistededwards/point.go index d1fee121c..9a76c4904 100644 --- a/ecc/bw6-761/twistededwards/point.go +++ b/ecc/bw6-761/twistededwards/point.go @@ -294,7 +294,13 @@ func (p *PointProj) setInfinity() *PointProj { // Equal returns true if p=p1 false otherwise // If one point is on the affine chart Z=0 it returns false func (p *PointProj) Equal(p1 *PointProj) bool { - if p.Z.IsZero() || p1.Z.IsZero() { + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return p1.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if p1.Z.IsZero() { return false } diff --git a/ecc/secp256k1/g1.go b/ecc/secp256k1/g1.go index 31b93f4d4..cc5ce27b4 100644 --- a/ecc/secp256k1/g1.go +++ b/ecc/secp256k1/g1.go @@ -184,9 +184,14 @@ func (p *G1Jac) Set(a *G1Jac) *G1Jac { // Equal tests if two points (in Jacobian coordinates) are equal func (p *G1Jac) Equal(a *G1Jac) bool { - - if p.Z.IsZero() && a.Z.IsZero() { - return true + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return a.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if a.Z.IsZero() { + return false } var pZSquare, aZSquare fp.Element diff --git a/internal/generator/ecc/template/point.go.tmpl b/internal/generator/ecc/template/point.go.tmpl index f247b8b41..5ae345f67 100644 --- a/internal/generator/ecc/template/point.go.tmpl +++ b/internal/generator/ecc/template/point.go.tmpl @@ -207,9 +207,14 @@ func (p *{{ $TJacobian }}) Set(a *{{ $TJacobian }}) *{{ $TJacobian }} { // Equal tests if two points (in Jacobian coordinates) are equal func (p *{{ $TJacobian }}) Equal(a *{{ $TJacobian }}) bool { - - if p.Z.IsZero() && a.Z.IsZero() { - return true + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return a.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if a.Z.IsZero() { + return false } var pZSquare, aZSquare {{.CoordType}} diff --git a/internal/generator/edwards/template/point.go.tmpl b/internal/generator/edwards/template/point.go.tmpl index 4c3de021d..a842e9c33 100644 --- a/internal/generator/edwards/template/point.go.tmpl +++ b/internal/generator/edwards/template/point.go.tmpl @@ -278,7 +278,13 @@ func (p *PointProj) setInfinity() *PointProj { // Equal returns true if p=p1 false otherwise // If one point is on the affine chart Z=0 it returns false func (p *PointProj) Equal(p1 *PointProj) bool { - if p.Z.IsZero() || p1.Z.IsZero() { + // If one point is infinity, the other must also be infinity. + if p.Z.IsZero() { + return p1.Z.IsZero() + } + // If the other point is infinity, return false since we can't + // the following checks would be incorrect. + if p1.Z.IsZero() { return false }