1// Copyright 2020 ConsenSys Software Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// Code generated by consensys/gnark-crypto DO NOT EDIT
16
17package bn254
18
19import (
20	"fmt"
21	"math/big"
22	"testing"
23
24	"github.com/consensys/gnark-crypto/ecc/bn254/fr"
25	"github.com/leanovate/gopter"
26	"github.com/leanovate/gopter/prop"
27)
28
29// ------------------------------------------------------------
30// examples
31
32func ExampleMillerLoop() {
33
34	// samples a random scalar r
35	var r big.Int
36	var rFr fr.Element
37	rFr.SetRandom()
38	rFr.ToBigIntRegular(&r)
39
40	// computes r*g1Gen, r*g2Gen
41	var rg1 G1Affine
42	var rg2 G2Affine
43	rg1.ScalarMultiplication(&g1GenAff, &r)
44	rg2.ScalarMultiplication(&g2GenAff, &r)
45
46	// Computes e(g1GenAff, ag2) and e(ag1, g2GenAff)
47	e1, _ := Pair([]G1Affine{g1GenAff}, []G2Affine{rg2})
48	E2, _ := Pair([]G1Affine{rg1}, []G2Affine{g2GenAff})
49
50	// checks that bilinearity property holds
51	check := e1.Equal(&E2)
52
53	fmt.Printf("%t\n", check)
54	// Output: true
55
56}
57
58// ------------------------------------------------------------
59// tests
60
61func TestPairing(t *testing.T) {
62
63	parameters := gopter.DefaultTestParameters()
64	parameters.MinSuccessfulTests = 100
65
66	properties := gopter.NewProperties(parameters)
67
68	genA := GenE12()
69	genR1 := GenFr()
70	genR2 := GenFr()
71
72	properties.Property("[BN254] Having the receiver as operand (final expo) should output the same result", prop.ForAll(
73		func(a *GT) bool {
74			var b GT
75			b.Set(a)
76			b = FinalExponentiation(a)
77			*a = FinalExponentiation(a)
78			return a.Equal(&b)
79		},
80		genA,
81	))
82
83	properties.Property("[BN254] Exponentiating FinalExpo(a) to r should output 1", prop.ForAll(
84		func(a *GT) bool {
85			var one GT
86			e := fr.Modulus()
87			one.SetOne()
88			*a = FinalExponentiation(a)
89			a.Exp(a, *e)
90			return a.Equal(&one)
91		},
92		genA,
93	))
94
95	properties.Property("[BN254] bilinearity", prop.ForAll(
96		func(a, b fr.Element) bool {
97
98			var res, resa, resb, resab, zero GT
99
100			var ag1 G1Affine
101			var bg2 G2Affine
102
103			var abigint, bbigint, ab big.Int
104
105			a.ToBigIntRegular(&abigint)
106			b.ToBigIntRegular(&bbigint)
107			ab.Mul(&abigint, &bbigint)
108
109			ag1.ScalarMultiplication(&g1GenAff, &abigint)
110			bg2.ScalarMultiplication(&g2GenAff, &bbigint)
111
112			res, _ = Pair([]G1Affine{g1GenAff}, []G2Affine{g2GenAff})
113			resa, _ = Pair([]G1Affine{ag1}, []G2Affine{g2GenAff})
114			resb, _ = Pair([]G1Affine{g1GenAff}, []G2Affine{bg2})
115
116			resab.Exp(&res, ab)
117			resa.Exp(&resa, bbigint)
118			resb.Exp(&resb, abigint)
119
120			return resab.Equal(&resa) && resab.Equal(&resb) && !res.Equal(&zero)
121
122		},
123		genR1,
124		genR2,
125	))
126
127	properties.Property("[BN254] MillerLoop of pairs should be equal to the product of MillerLoops", prop.ForAll(
128		func(a, b fr.Element) bool {
129
130			var simpleProd, factorizedProd GT
131
132			var ag1 G1Affine
133			var bg2 G2Affine
134
135			var abigint, bbigint big.Int
136
137			a.ToBigIntRegular(&abigint)
138			b.ToBigIntRegular(&bbigint)
139
140			ag1.ScalarMultiplication(&g1GenAff, &abigint)
141			bg2.ScalarMultiplication(&g2GenAff, &bbigint)
142
143			P0 := []G1Affine{g1GenAff}
144			P1 := []G1Affine{ag1}
145			Q0 := []G2Affine{g2GenAff}
146			Q1 := []G2Affine{bg2}
147
148			// FE( ML(a,b) * ML(c,d) * ML(e,f) * ML(g,h) )
149			M1, _ := MillerLoop(P0, Q0)
150			M2, _ := MillerLoop(P1, Q0)
151			M3, _ := MillerLoop(P0, Q1)
152			M4, _ := MillerLoop(P1, Q1)
153			simpleProd.Mul(&M1, &M2).Mul(&simpleProd, &M3).Mul(&simpleProd, &M4)
154			simpleProd = FinalExponentiation(&simpleProd)
155
156			tabP := []G1Affine{g1GenAff, ag1, g1GenAff, ag1}
157			tabQ := []G2Affine{g2GenAff, g2GenAff, bg2, bg2}
158
159			// FE( ML([a,c,e,g] ; [b,d,f,h]) ) -> saves 3 squares in Fqk
160			factorizedProd, _ = Pair(tabP, tabQ)
161
162			return simpleProd.Equal(&factorizedProd)
163		},
164		genR1,
165		genR2,
166	))
167
168	properties.Property("[BN254] PairingCheck", prop.ForAll(
169		func(a, b fr.Element) bool {
170
171			var g1GenAffNeg G1Affine
172			g1GenAffNeg.Neg(&g1GenAff)
173			tabP := []G1Affine{g1GenAff, g1GenAffNeg}
174			tabQ := []G2Affine{g2GenAff, g2GenAff}
175
176			res, _ := PairingCheck(tabP, tabQ)
177
178			return res
179		},
180		genR1,
181		genR2,
182	))
183	properties.TestingRun(t, gopter.ConsoleReporter(false))
184}
185
186// ------------------------------------------------------------
187// benches
188
189func BenchmarkPairing(b *testing.B) {
190
191	var g1GenAff G1Affine
192	var g2GenAff G2Affine
193
194	g1GenAff.FromJacobian(&g1Gen)
195	g2GenAff.FromJacobian(&g2Gen)
196
197	b.ResetTimer()
198	for i := 0; i < b.N; i++ {
199		Pair([]G1Affine{g1GenAff}, []G2Affine{g2GenAff})
200	}
201}
202
203func BenchmarkMillerLoop(b *testing.B) {
204
205	var g1GenAff G1Affine
206	var g2GenAff G2Affine
207
208	g1GenAff.FromJacobian(&g1Gen)
209	g2GenAff.FromJacobian(&g2Gen)
210
211	b.ResetTimer()
212	for i := 0; i < b.N; i++ {
213		MillerLoop([]G1Affine{g1GenAff}, []G2Affine{g2GenAff})
214	}
215}
216
217func BenchmarkFinalExponentiation(b *testing.B) {
218
219	var a GT
220	a.SetRandom()
221
222	b.ResetTimer()
223	for i := 0; i < b.N; i++ {
224		FinalExponentiation(&a)
225	}
226
227}
228