diff --git a/ecc/bls12-377/pairing_test.go b/ecc/bls12-377/pairing_test.go index 91e8b39d94..96af27ede2 100644 --- a/ecc/bls12-377/pairing_test.go +++ b/ecc/bls12-377/pairing_test.go @@ -17,6 +17,7 @@ package bls12377 import ( + "fmt" "math/big" "testing" @@ -251,7 +252,7 @@ func BenchmarkFinalExponentiation(b *testing.B) { } -func BenchmarkMultiPairing(b *testing.B) { +func BenchmarkMultiMiller(b *testing.B) { var g1GenAff G1Affine var g2GenAff G2Affine @@ -259,8 +260,46 @@ func BenchmarkMultiPairing(b *testing.B) { g1GenAff.FromJacobian(&g1Gen) g2GenAff.FromJacobian(&g2Gen) - b.ResetTimer() - for i := 0; i < b.N; i++ { - Pair([]G1Affine{g1GenAff, g1GenAff, g1GenAff}, []G2Affine{g2GenAff, g2GenAff, g2GenAff}) + n := 10 + P := make([]G1Affine, n) + Q := make([]G2Affine, n) + + for i := 2; i <= n; i++ { + for j := 0; j < i; j++ { + P[j].Set(&g1GenAff) + Q[j].Set(&g2GenAff) + } + b.Run(fmt.Sprintf("%d pairs", i), func(b *testing.B) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + MillerLoop(P, Q) + } + }) + } +} + +func BenchmarkMultiPair(b *testing.B) { + + var g1GenAff G1Affine + var g2GenAff G2Affine + + g1GenAff.FromJacobian(&g1Gen) + g2GenAff.FromJacobian(&g2Gen) + + n := 10 + P := make([]G1Affine, n) + Q := make([]G2Affine, n) + + for i := 2; i <= n; i++ { + for j := 0; j < i; j++ { + P[j].Set(&g1GenAff) + Q[j].Set(&g2GenAff) + } + b.Run(fmt.Sprintf("%d pairs", i), func(b *testing.B) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + Pair(P, Q) + } + }) } } diff --git a/ecc/bls12-381/pairing_test.go b/ecc/bls12-381/pairing_test.go index 7eddddacd8..cda5bd3f94 100644 --- a/ecc/bls12-381/pairing_test.go +++ b/ecc/bls12-381/pairing_test.go @@ -17,6 +17,7 @@ package bls12381 import ( + "fmt" "math/big" "testing" @@ -251,7 +252,7 @@ func BenchmarkFinalExponentiation(b *testing.B) { } -func BenchmarkMultiPairing(b *testing.B) { +func BenchmarkMultiMiller(b *testing.B) { var g1GenAff G1Affine var g2GenAff G2Affine @@ -259,8 +260,46 @@ func BenchmarkMultiPairing(b *testing.B) { g1GenAff.FromJacobian(&g1Gen) g2GenAff.FromJacobian(&g2Gen) - b.ResetTimer() - for i := 0; i < b.N; i++ { - Pair([]G1Affine{g1GenAff, g1GenAff, g1GenAff}, []G2Affine{g2GenAff, g2GenAff, g2GenAff}) + n := 10 + P := make([]G1Affine, n) + Q := make([]G2Affine, n) + + for i := 2; i <= n; i++ { + for j := 0; j < i; j++ { + P[j].Set(&g1GenAff) + Q[j].Set(&g2GenAff) + } + b.Run(fmt.Sprintf("%d pairs", i), func(b *testing.B) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + MillerLoop(P, Q) + } + }) + } +} + +func BenchmarkMultiPair(b *testing.B) { + + var g1GenAff G1Affine + var g2GenAff G2Affine + + g1GenAff.FromJacobian(&g1Gen) + g2GenAff.FromJacobian(&g2Gen) + + n := 10 + P := make([]G1Affine, n) + Q := make([]G2Affine, n) + + for i := 2; i <= n; i++ { + for j := 0; j < i; j++ { + P[j].Set(&g1GenAff) + Q[j].Set(&g2GenAff) + } + b.Run(fmt.Sprintf("%d pairs", i), func(b *testing.B) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + Pair(P, Q) + } + }) } } diff --git a/ecc/bls24-315/pairing_test.go b/ecc/bls24-315/pairing_test.go index 7cdc840487..e54fca70b4 100644 --- a/ecc/bls24-315/pairing_test.go +++ b/ecc/bls24-315/pairing_test.go @@ -17,6 +17,7 @@ package bls24315 import ( + "fmt" "math/big" "testing" @@ -252,7 +253,7 @@ func BenchmarkFinalExponentiation(b *testing.B) { } -func BenchmarkMultiPairing(b *testing.B) { +func BenchmarkMultiMiller(b *testing.B) { var g1GenAff G1Affine var g2GenAff G2Affine @@ -260,8 +261,46 @@ func BenchmarkMultiPairing(b *testing.B) { g1GenAff.FromJacobian(&g1Gen) g2GenAff.FromJacobian(&g2Gen) - b.ResetTimer() - for i := 0; i < b.N; i++ { - Pair([]G1Affine{g1GenAff, g1GenAff, g1GenAff}, []G2Affine{g2GenAff, g2GenAff, g2GenAff}) + n := 10 + P := make([]G1Affine, n) + Q := make([]G2Affine, n) + + for i := 2; i <= n; i++ { + for j := 0; j < i; j++ { + P[j].Set(&g1GenAff) + Q[j].Set(&g2GenAff) + } + b.Run(fmt.Sprintf("%d pairs", i), func(b *testing.B) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + MillerLoop(P, Q) + } + }) + } +} + +func BenchmarkMultiPair(b *testing.B) { + + var g1GenAff G1Affine + var g2GenAff G2Affine + + g1GenAff.FromJacobian(&g1Gen) + g2GenAff.FromJacobian(&g2Gen) + + n := 10 + P := make([]G1Affine, n) + Q := make([]G2Affine, n) + + for i := 2; i <= n; i++ { + for j := 0; j < i; j++ { + P[j].Set(&g1GenAff) + Q[j].Set(&g2GenAff) + } + b.Run(fmt.Sprintf("%d pairs", i), func(b *testing.B) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + Pair(P, Q) + } + }) } } diff --git a/ecc/bn254/internal/fptower/e12_pairing.go b/ecc/bn254/internal/fptower/e12_pairing.go index eb7e90716b..5f5d333279 100644 --- a/ecc/bn254/internal/fptower/e12_pairing.go +++ b/ecc/bn254/internal/fptower/e12_pairing.go @@ -88,3 +88,36 @@ func (z *E12) MulBy034(c0, c3, c4 *E2) *E12 { return z } + +// Mul034By034 multiplication of sparse element (c0,0,0,c3,c4,0) by sparse element (d0,0,0,d3,d4,0) +func (z *E12) Mul034by034(d0, d3, d4, c0, c3, c4 *E2) *E12 { + var tmp, x0, x3, x4, x04, x03, x34 E2 + x0.Mul(c0, d0) + x3.Mul(c3, d3) + x4.Mul(c4, d4) + tmp.Add(c0, c4) + x04.Add(d0, d4). + Mul(&x04, &tmp). + Sub(&x04, &x0). + Sub(&x04, &x4) + tmp.Add(c0, c3) + x03.Add(d0, d3). + Mul(&x03, &tmp). + Sub(&x03, &x0). + Sub(&x03, &x3) + tmp.Add(c3, c4) + x34.Add(d3, d4). + Mul(&x34, &tmp). + Sub(&x34, &x3). + Sub(&x34, &x4) + + z.C0.B0.MulByNonResidue(&x4). + Add(&z.C0.B0, &x0) + z.C0.B1.Set(&x3) + z.C0.B2.Set(&x34) + z.C1.B0.Set(&x03) + z.C1.B1.Set(&x04) + z.C1.B2.SetZero() + + return z +} diff --git a/ecc/bn254/pairing.go b/ecc/bn254/pairing.go index c73918f719..5bdb872542 100644 --- a/ecc/bn254/pairing.go +++ b/ecc/bn254/pairing.go @@ -182,6 +182,8 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { } var Q1, Q2 G2Affine + var l0 lineEvaluation + var tmp GT // cf https://eprint.iacr.org/2010/354.pdf for instance for optimal Ate Pairing for k := 0; k < n; k++ { //Q1 = Frob(Q) @@ -192,17 +194,15 @@ func MillerLoop(P []G1Affine, Q []G2Affine) (GT, error) { Q2.X.MulByNonResidue2Power2(&q[k].X) Q2.Y.MulByNonResidue2Power3(&q[k].Y).Neg(&Q2.Y) - qProj[k].AddMixedStep(&l, &Q1) - // line evaluation - l.r0.MulByElement(&l.r0, &p[k].Y) - l.r1.MulByElement(&l.r1, &p[k].X) - result.MulBy034(&l.r0, &l.r1, &l.r2) + qProj[k].AddMixedStep(&l0, &Q1) + l0.r0.MulByElement(&l0.r0, &p[k].Y) + l0.r1.MulByElement(&l0.r1, &p[k].X) qProj[k].AddMixedStep(&l, &Q2) - // line evaluation l.r0.MulByElement(&l.r0, &p[k].Y) l.r1.MulByElement(&l.r1, &p[k].X) - result.MulBy034(&l.r0, &l.r1, &l.r2) + tmp.Mul034by034(&l.r0, &l.r1, &l.r2, &l0.r0, &l0.r1, &l0.r2) + result.Mul(&result, &tmp) } return result, nil diff --git a/ecc/bn254/pairing_test.go b/ecc/bn254/pairing_test.go index e88ebd976e..8948b1872f 100644 --- a/ecc/bn254/pairing_test.go +++ b/ecc/bn254/pairing_test.go @@ -17,6 +17,7 @@ package bn254 import ( + "fmt" "math/big" "testing" @@ -251,7 +252,7 @@ func BenchmarkFinalExponentiation(b *testing.B) { } -func BenchmarkMultiPairing(b *testing.B) { +func BenchmarkMultiMiller(b *testing.B) { var g1GenAff G1Affine var g2GenAff G2Affine @@ -259,8 +260,46 @@ func BenchmarkMultiPairing(b *testing.B) { g1GenAff.FromJacobian(&g1Gen) g2GenAff.FromJacobian(&g2Gen) - b.ResetTimer() - for i := 0; i < b.N; i++ { - Pair([]G1Affine{g1GenAff, g1GenAff, g1GenAff}, []G2Affine{g2GenAff, g2GenAff, g2GenAff}) + n := 10 + P := make([]G1Affine, n) + Q := make([]G2Affine, n) + + for i := 2; i <= n; i++ { + for j := 0; j < i; j++ { + P[j].Set(&g1GenAff) + Q[j].Set(&g2GenAff) + } + b.Run(fmt.Sprintf("%d pairs", i), func(b *testing.B) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + MillerLoop(P, Q) + } + }) + } +} + +func BenchmarkMultiPair(b *testing.B) { + + var g1GenAff G1Affine + var g2GenAff G2Affine + + g1GenAff.FromJacobian(&g1Gen) + g2GenAff.FromJacobian(&g2Gen) + + n := 10 + P := make([]G1Affine, n) + Q := make([]G2Affine, n) + + for i := 2; i <= n; i++ { + for j := 0; j < i; j++ { + P[j].Set(&g1GenAff) + Q[j].Set(&g2GenAff) + } + b.Run(fmt.Sprintf("%d pairs", i), func(b *testing.B) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + Pair(P, Q) + } + }) } } diff --git a/ecc/bw6-633/pairing_test.go b/ecc/bw6-633/pairing_test.go index f3b7eb4423..bdffe61d81 100644 --- a/ecc/bw6-633/pairing_test.go +++ b/ecc/bw6-633/pairing_test.go @@ -17,6 +17,7 @@ package bw6633 import ( + "fmt" "math/big" "testing" @@ -252,7 +253,7 @@ func BenchmarkFinalExponentiation(b *testing.B) { } -func BenchmarkMultiPairing(b *testing.B) { +func BenchmarkMultiMiller(b *testing.B) { var g1GenAff G1Affine var g2GenAff G2Affine @@ -260,8 +261,46 @@ func BenchmarkMultiPairing(b *testing.B) { g1GenAff.FromJacobian(&g1Gen) g2GenAff.FromJacobian(&g2Gen) - b.ResetTimer() - for i := 0; i < b.N; i++ { - Pair([]G1Affine{g1GenAff, g1GenAff, g1GenAff}, []G2Affine{g2GenAff, g2GenAff, g2GenAff}) + n := 10 + P := make([]G1Affine, n) + Q := make([]G2Affine, n) + + for i := 2; i <= n; i++ { + for j := 0; j < i; j++ { + P[j].Set(&g1GenAff) + Q[j].Set(&g2GenAff) + } + b.Run(fmt.Sprintf("%d pairs", i), func(b *testing.B) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + MillerLoop(P, Q) + } + }) + } +} + +func BenchmarkMultiPair(b *testing.B) { + + var g1GenAff G1Affine + var g2GenAff G2Affine + + g1GenAff.FromJacobian(&g1Gen) + g2GenAff.FromJacobian(&g2Gen) + + n := 10 + P := make([]G1Affine, n) + Q := make([]G2Affine, n) + + for i := 2; i <= n; i++ { + for j := 0; j < i; j++ { + P[j].Set(&g1GenAff) + Q[j].Set(&g2GenAff) + } + b.Run(fmt.Sprintf("%d pairs", i), func(b *testing.B) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + Pair(P, Q) + } + }) } } diff --git a/ecc/bw6-761/pairing_test.go b/ecc/bw6-761/pairing_test.go index 548bd3a57c..2ec8af9ac7 100644 --- a/ecc/bw6-761/pairing_test.go +++ b/ecc/bw6-761/pairing_test.go @@ -17,6 +17,7 @@ package bw6761 import ( + "fmt" "math/big" "testing" @@ -252,7 +253,7 @@ func BenchmarkFinalExponentiation(b *testing.B) { } -func BenchmarkMultiPairing(b *testing.B) { +func BenchmarkMultiMiller(b *testing.B) { var g1GenAff G1Affine var g2GenAff G2Affine @@ -260,8 +261,46 @@ func BenchmarkMultiPairing(b *testing.B) { g1GenAff.FromJacobian(&g1Gen) g2GenAff.FromJacobian(&g2Gen) - b.ResetTimer() - for i := 0; i < b.N; i++ { - Pair([]G1Affine{g1GenAff, g1GenAff, g1GenAff}, []G2Affine{g2GenAff, g2GenAff, g2GenAff}) + n := 10 + P := make([]G1Affine, n) + Q := make([]G2Affine, n) + + for i := 2; i <= n; i++ { + for j := 0; j < i; j++ { + P[j].Set(&g1GenAff) + Q[j].Set(&g2GenAff) + } + b.Run(fmt.Sprintf("%d pairs", i), func(b *testing.B) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + MillerLoop(P, Q) + } + }) + } +} + +func BenchmarkMultiPair(b *testing.B) { + + var g1GenAff G1Affine + var g2GenAff G2Affine + + g1GenAff.FromJacobian(&g1Gen) + g2GenAff.FromJacobian(&g2Gen) + + n := 10 + P := make([]G1Affine, n) + Q := make([]G2Affine, n) + + for i := 2; i <= n; i++ { + for j := 0; j < i; j++ { + P[j].Set(&g1GenAff) + Q[j].Set(&g2GenAff) + } + b.Run(fmt.Sprintf("%d pairs", i), func(b *testing.B) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + Pair(P, Q) + } + }) } } diff --git a/internal/generator/pairing/template/tests/pairing.go.tmpl b/internal/generator/pairing/template/tests/pairing.go.tmpl index 0341088b22..09a0840a96 100644 --- a/internal/generator/pairing/template/tests/pairing.go.tmpl +++ b/internal/generator/pairing/template/tests/pairing.go.tmpl @@ -1,4 +1,5 @@ import ( + "fmt" "math/big" "testing" @@ -244,7 +245,7 @@ func BenchmarkFinalExponentiation(b *testing.B) { } -func BenchmarkMultiPairing(b *testing.B) { +func BenchmarkMultiMiller(b *testing.B) { var g1GenAff G1Affine var g2GenAff G2Affine @@ -252,8 +253,46 @@ func BenchmarkMultiPairing(b *testing.B) { g1GenAff.FromJacobian(&g1Gen) g2GenAff.FromJacobian(&g2Gen) - b.ResetTimer() - for i := 0; i < b.N; i++ { - Pair([]G1Affine{g1GenAff, g1GenAff, g1GenAff}, []G2Affine{g2GenAff, g2GenAff, g2GenAff}) + n := 10 + P := make([]G1Affine, n) + Q := make([]G2Affine, n) + + for i := 2; i <= n; i++ { + for j := 0; j < i; j++ { + P[j].Set(&g1GenAff) + Q[j].Set(&g2GenAff) + } + b.Run(fmt.Sprintf("%d pairs", i), func(b *testing.B) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + MillerLoop(P, Q) + } + }) + } +} + +func BenchmarkMultiPair(b *testing.B) { + + var g1GenAff G1Affine + var g2GenAff G2Affine + + g1GenAff.FromJacobian(&g1Gen) + g2GenAff.FromJacobian(&g2Gen) + + n := 10 + P := make([]G1Affine, n) + Q := make([]G2Affine, n) + + for i := 2; i <= n; i++ { + for j := 0; j < i; j++ { + P[j].Set(&g1GenAff) + Q[j].Set(&g2GenAff) + } + b.Run(fmt.Sprintf("%d pairs", i), func(b *testing.B) { + b.ResetTimer() + for i := 0; i < b.N; i++ { + Pair(P, Q) + } + }) } }