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