github.com/consensys/gnark-crypto@v0.14.0/internal/generator/ecc/template/tests/marshal.go.tmpl (about) 1 {{ $G1TAffine := print (toUpper .G1.PointName) "Affine" }} 2 {{ $G1TJacobian := print (toUpper .G1.PointName) "Jac" }} 3 {{ $G1TJacobianExtended := print (toLower .G1.PointName) "JacExtended" }} 4 5 {{ $G2TAffine := print (toUpper .G2.PointName) "Affine" }} 6 {{ $G2TJacobian := print (toUpper .G2.PointName) "Jac" }} 7 {{ $G2TJacobianExtended := print (toLower .G2.PointName) "JacExtended" }} 8 9 import ( 10 "testing" 11 "math/rand/v2" 12 crand "crypto/rand" 13 "math/big" 14 "bytes" 15 "io" 16 "reflect" 17 18 "github.com/leanovate/gopter" 19 "github.com/leanovate/gopter/prop" 20 21 "github.com/consensys/gnark-crypto/ecc/{{.Name}}/fr" 22 "github.com/consensys/gnark-crypto/ecc/{{.Name}}/fp" 23 "github.com/consensys/gnark-crypto/ecc/{{.Name}}/internal/fptower" 24 ) 25 26 const ( 27 nbFuzzShort = 10 28 nbFuzz = 100 29 ) 30 31 func TestEncoder(t *testing.T) { 32 t.Parallel() 33 // TODO need proper fuzz testing here 34 35 var inA uint64 36 var inB fr.Element 37 var inC fp.Element 38 var inD G1Affine 39 var inE G1Affine 40 var inF G2Affine 41 var inG []G1Affine 42 var inH []G2Affine 43 var inI []fp.Element 44 var inJ []fr.Element 45 var inK fr.Vector 46 var inL [][]fr.Element 47 var inM [][]uint64 48 49 // set values of inputs 50 inA = rand.Uint64() //#nosec G404 weak rng is fine here 51 inB.SetRandom() 52 inC.SetRandom() 53 inD.ScalarMultiplication(&g1GenAff, new(big.Int).SetUint64(rand.Uint64())) //#nosec G404 weak rng is fine here 54 // inE --> infinity 55 inF.ScalarMultiplication(&g2GenAff, new(big.Int).SetUint64(rand.Uint64())) //#nosec G404 weak rng is fine here 56 inG = make([]G1Affine, 2) 57 inH = make([]G2Affine, 0) 58 inG[1] = inD 59 inI = make([]fp.Element, 3) 60 inI[2] = inD.X 61 inJ = make([]fr.Element, 0) 62 inK = make(fr.Vector, 42) 63 inK[41].SetUint64(42) 64 inL =[][]fr.Element {inJ, inK} 65 inM = [][]uint64{ {1, 2}, {4}, {} } 66 67 // encode them, compressed and raw 68 var buf, bufRaw bytes.Buffer 69 enc := NewEncoder(&buf) 70 encRaw := NewEncoder(&bufRaw, RawEncoding()) 71 toEncode := []interface{}{inA, &inB, &inC, &inD, &inE, &inF, inG, inH, inI, inJ, inK, inL, inM} 72 for _, v := range toEncode { 73 if err := enc.Encode(v); err != nil { 74 t.Fatal(err) 75 } 76 if err := encRaw.Encode(v); err != nil { 77 t.Fatal(err) 78 } 79 } 80 81 82 testDecode := func(t *testing.T, r io.Reader, n int64) { 83 dec := NewDecoder(r) 84 var outA uint64 85 var outB fr.Element 86 var outC fp.Element 87 var outD G1Affine 88 var outE G1Affine 89 outE.X.SetOne() 90 outE.Y.SetUint64(42) 91 var outF G2Affine 92 var outG []G1Affine 93 var outH []G2Affine 94 var outI []fp.Element 95 var outJ []fr.Element 96 var outK fr.Vector 97 var outL [][]fr.Element 98 var outM [][]uint64 99 100 toDecode := []interface{}{&outA, &outB, &outC, &outD, &outE, &outF, &outG, &outH, &outI, &outJ, &outK, &outL, &outM} 101 for _, v := range toDecode { 102 if err := dec.Decode(v); err != nil { 103 t.Fatal(err) 104 } 105 } 106 107 // compare values 108 if inA != outA { 109 t.Fatal("didn't encode/decode uint64 value properly") 110 } 111 112 if !inB.Equal(&outB) || !inC.Equal(&outC) { 113 t.Fatal("decode(encode(Element) failed") 114 } 115 if !inD.Equal(&outD) || !inE.Equal(&outE) { 116 t.Fatal("decode(encode(G1Affine) failed") 117 } 118 if !inF.Equal(&outF) { 119 t.Fatal("decode(encode(G2Affine) failed") 120 } 121 if (len(inG) != len(outG)) || (len(inH) != len(outH)) { 122 t.Fatal("decode(encode(slice(points))) failed") 123 } 124 for i:=0; i<len(inG);i++ { 125 if !inG[i].Equal(&outG[i]) { 126 t.Fatal("decode(encode(slice(points))) failed") 127 } 128 } 129 if (len(inI) != len(outI)) || (len(inJ) != len(outJ)) { 130 t.Fatal("decode(encode(slice(elements))) failed") 131 } 132 for i:=0; i<len(inI);i++ { 133 if !inI[i].Equal(&outI[i]) { 134 t.Fatal("decode(encode(slice(elements))) failed") 135 } 136 } 137 if !reflect.DeepEqual(inK, outK) { 138 t.Fatal("decode(encode(vector)) failed") 139 } 140 if !reflect.DeepEqual(inL, outL) { 141 t.Fatal("decode(encode(sliceĀ²(elements))) failed") 142 } 143 if !reflect.DeepEqual(inM, outM) { 144 t.Fatal("decode(encode(sliceĀ²(uint64))) failed") 145 } 146 if n != dec.BytesRead() { 147 t.Fatal("bytes read don't match bytes written") 148 } 149 } 150 151 // decode them 152 testDecode(t, &buf, enc.BytesWritten()) 153 testDecode(t, &bufRaw, encRaw.BytesWritten()) 154 155 156 } 157 158 159 160 func TestIsCompressed(t *testing.T) { 161 t.Parallel() 162 var g1Inf, g1 G1Affine 163 var g2Inf, g2 G2Affine 164 165 g1 = g1GenAff 166 g2 = g2GenAff 167 168 { 169 b := g1Inf.Bytes() 170 if !isCompressed(b[0]) { 171 t.Fatal("g1Inf.Bytes() should be compressed") 172 } 173 } 174 175 { 176 b := g1Inf.RawBytes() 177 if isCompressed(b[0]) { 178 t.Fatal("g1Inf.RawBytes() should be uncompressed") 179 } 180 } 181 182 { 183 b := g1.Bytes() 184 if !isCompressed(b[0]) { 185 t.Fatal("g1.Bytes() should be compressed") 186 } 187 } 188 189 { 190 b := g1.RawBytes() 191 if isCompressed(b[0]) { 192 t.Fatal("g1.RawBytes() should be uncompressed") 193 } 194 } 195 196 197 198 { 199 b := g2Inf.Bytes() 200 if !isCompressed(b[0]) { 201 t.Fatal("g2Inf.Bytes() should be compressed") 202 } 203 } 204 205 { 206 b := g2Inf.RawBytes() 207 if isCompressed(b[0]) { 208 t.Fatal("g2Inf.RawBytes() should be uncompressed") 209 } 210 } 211 212 { 213 b := g2.Bytes() 214 if !isCompressed(b[0]) { 215 t.Fatal("g2.Bytes() should be compressed") 216 } 217 } 218 219 { 220 b := g2.RawBytes() 221 if isCompressed(b[0]) { 222 t.Fatal("g2.RawBytes() should be uncompressed") 223 } 224 } 225 226 } 227 228 {{- $sizeOfFp := mul .Fp.NbWords 8}} 229 {{- $FpUnusedBits := .FpUnusedBits}} 230 231 {{template "marshalpoint" dict "all" . "sizeOfFp" $sizeOfFp "CoordType" .G1.CoordType "PointName" .G1.PointName "TAffine" $G1TAffine "TJacobian" $G1TJacobian "TJacobianExtended" $G1TJacobianExtended "FrNbWords" .Fr.NbWords "CRange" .G1.CRange "FpUnusedBits" $FpUnusedBits}} 232 {{template "marshalpoint" dict "all" . "sizeOfFp" $sizeOfFp "CoordType" .G2.CoordType "PointName" .G2.PointName "TAffine" $G2TAffine "TJacobian" $G2TJacobian "TJacobianExtended" $G2TJacobianExtended "FrNbWords" .Fr.NbWords "CRange" .G2.CRange "FpUnusedBits" $FpUnusedBits}} 233 234 235 {{define "marshalpoint"}} 236 237 238 239 {{if ge $.FpUnusedBits 3}} 240 func Test{{ $.TAffine }}InvalidBitMask(t *testing.T) { 241 t.Parallel() 242 var buf [SizeOf{{ $.TAffine }}Compressed]byte 243 crand.Read(buf[:]) 244 245 var p {{ $.TAffine }} 246 buf[0] = 0b111 << 5 247 if _, err := p.SetBytes(buf[:]); err != ErrInvalidEncoding { 248 t.Fatal("should error on invalid bit mask") 249 } 250 buf[0] = 0b011 << 5 251 if _, err := p.SetBytes(buf[:]); err != ErrInvalidEncoding { 252 t.Fatal("should error on invalid bit mask") 253 } 254 buf[0] = 0b001 << 5 255 if _, err := p.SetBytes(buf[:]); err != ErrInvalidEncoding { 256 t.Fatal("should error on invalid bit mask") 257 } 258 } 259 {{- end}} 260 261 262 func Test{{ $.TAffine }}Serialization(t *testing.T) { 263 t.Parallel() 264 // test round trip serialization of infinity 265 { 266 // compressed 267 { 268 var p1, p2 {{ $.TAffine }} 269 p2.X.SetRandom() 270 p2.Y.SetRandom() 271 buf := p1.Bytes() 272 n, err := p2.SetBytes(buf[:]) 273 if err != nil { 274 t.Fatal(err) 275 } 276 if n != SizeOf{{ $.TAffine }}Compressed { 277 t.Fatal("invalid number of bytes consumed in buffer") 278 } 279 if !(p2.X.IsZero() && p2.Y.IsZero()) { 280 t.Fatal("deserialization of uncompressed infinity point is not infinity") 281 } 282 } 283 284 // uncompressed 285 { 286 var p1, p2 {{ $.TAffine }} 287 p2.X.SetRandom() 288 p2.Y.SetRandom() 289 buf := p1.RawBytes() 290 n, err := p2.SetBytes(buf[:]) 291 if err != nil { 292 t.Fatal(err) 293 } 294 if n != SizeOf{{ $.TAffine }}Uncompressed { 295 t.Fatal("invalid number of bytes consumed in buffer") 296 } 297 if !(p2.X.IsZero() && p2.Y.IsZero()) { 298 t.Fatal("deserialization of uncompressed infinity point is not infinity") 299 } 300 } 301 } 302 303 parameters := gopter.DefaultTestParameters() 304 if testing.Short() { 305 parameters.MinSuccessfulTests = nbFuzzShort 306 } else { 307 parameters.MinSuccessfulTests = nbFuzz 308 } 309 310 311 312 properties := gopter.NewProperties(parameters) 313 314 315 properties.Property("[{{ toUpper $.PointName }}] Affine SetBytes(RawBytes) should stay the same", prop.ForAll( 316 func(a fp.Element) bool { 317 var start, end {{ $.TAffine }} 318 var ab big.Int 319 a.BigInt(&ab) 320 start.ScalarMultiplication(&{{ toLower .PointName }}GenAff, &ab) 321 322 buf := start.RawBytes() 323 n, err := end.SetBytes(buf[:]) 324 if err != nil { 325 return false 326 } 327 if n != SizeOf{{ $.TAffine }}Uncompressed { 328 return false 329 } 330 return start.X.Equal(&end.X) && start.Y.Equal(&end.Y) 331 }, 332 GenFp(), 333 )) 334 335 properties.Property("[{{ toUpper $.PointName }}] Affine SetBytes(Bytes()) should stay the same", prop.ForAll( 336 func(a fp.Element) bool { 337 var start, end {{ $.TAffine }} 338 var ab big.Int 339 a.BigInt(&ab) 340 start.ScalarMultiplication(&{{ toLower .PointName }}GenAff, &ab) 341 342 buf := start.Bytes() 343 n, err := end.SetBytes(buf[:]) 344 if err != nil { 345 return false 346 } 347 if n != SizeOf{{ $.TAffine }}Compressed { 348 return false 349 } 350 return start.X.Equal(&end.X) && start.Y.Equal(&end.Y) 351 }, 352 GenFp(), 353 )) 354 355 properties.TestingRun(t, gopter.ConsoleReporter(false)) 356 } 357 358 {{end}} 359 360 361 // define Gopters generators 362 363 // GenFr generates an Fr element 364 func GenFr() gopter.Gen { 365 return func(genParams *gopter.GenParameters) *gopter.GenResult { 366 var elmt fr.Element 367 368 if _, err := elmt.SetRandom(); err != nil { 369 panic(err) 370 } 371 372 return gopter.NewGenResult(elmt, gopter.NoShrinker) 373 } 374 } 375 376 // GenFp generates an Fp element 377 func GenFp() gopter.Gen { 378 return func(genParams *gopter.GenParameters) *gopter.GenResult { 379 var elmt fp.Element 380 381 if _, err := elmt.SetRandom(); err != nil { 382 panic(err) 383 } 384 385 return gopter.NewGenResult(elmt, gopter.NoShrinker) 386 } 387 } 388 389 {{/* // e3 e6 for bw6-xxx 390 // e2 e4 e12 e24 for bls24 391 // e2 e6 e12 else */}} 392 393 {{if or (eq .Name "bw6-633") (eq .Name "bw6-761") (eq .Name "bw6-756")}} 394 // GenE3 generates an E3 elmt 395 func GenE3() gopter.Gen { 396 return gopter.CombineGens( 397 GenFp(), 398 GenFp(), 399 GenFp(), 400 ).Map(func(values []interface{}) fptower.E3 { 401 return fptower.E3{A0: values[0].(fp.Element), A1: values[1].(fp.Element), A2: values[2].(fp.Element)} 402 }) 403 } 404 405 // E6 generates an E6 elmt 406 func GenE6() gopter.Gen { 407 return gopter.CombineGens( 408 GenE3(), 409 GenE3(), 410 ).Map(func(values []interface{}) fptower.E6 { 411 return fptower.E6{B0: values[0].(fptower.E3), B1: values[1].(fptower.E3)} 412 }) 413 } 414 {{ else }} 415 // GenE2 generates an fptower.E2 elmt 416 func GenE2() gopter.Gen { 417 return gopter.CombineGens( 418 GenFp(), 419 GenFp(), 420 ).Map(func(values []interface{}) fptower.E2 { 421 return fptower.E2{A0: values[0].(fp.Element), A1: values[1].(fp.Element)} 422 }) 423 } 424 425 {{if or (eq .Name "bls24-315") (eq .Name "bls24-317")}} 426 // GenE4 generates an fptower.E4 elmt 427 func GenE4() gopter.Gen { 428 return gopter.CombineGens( 429 GenE2(), 430 GenE2(), 431 ).Map(func(values []interface{}) fptower.E4 { 432 return fptower.E4{B0: values[0].(fptower.E2), B1: values[1].(fptower.E2)} 433 }) 434 } 435 436 // GenE12 generates an fptower.E12 elmt 437 func GenE12() gopter.Gen { 438 return gopter.CombineGens( 439 GenE4(), 440 GenE4(), 441 GenE4(), 442 ).Map(func(values []interface{}) fptower.E12 { 443 return fptower.E12{C0: values[0].(fptower.E4), C1: values[1].(fptower.E4), C2: values[2].(fptower.E4)} 444 }) 445 } 446 447 // GenE24 generates an fptower.E24 elmt 448 func GenE24() gopter.Gen { 449 return gopter.CombineGens( 450 GenE12(), 451 GenE12(), 452 ).Map(func(values []interface{}) fptower.E24 { 453 return fptower.E24{D0: values[0].(fptower.E12), D1: values[1].(fptower.E12)} 454 }) 455 } 456 {{ else }} 457 // GenE6 generates an fptower.E6 elmt 458 func GenE6() gopter.Gen { 459 return gopter.CombineGens( 460 GenE2(), 461 GenE2(), 462 GenE2(), 463 ).Map(func(values []interface{}) fptower.E6 { 464 return fptower.E6{B0: values[0].(fptower.E2), B1: values[1].(fptower.E2), B2: values[2].(fptower.E2)} 465 }) 466 } 467 468 // GenE12 generates an fptower.E6 elmt 469 func GenE12() gopter.Gen { 470 return gopter.CombineGens( 471 GenE6(), 472 GenE6(), 473 ).Map(func(values []interface{}) fptower.E12 { 474 return fptower.E12{C0: values[0].(fptower.E6), C1: values[1].(fptower.E6)} 475 }) 476 } 477 {{ end }} 478 {{ end }} 479 480 481 482 // GenBigInt generates a big.Int 483 func GenBigInt() gopter.Gen { 484 return func(genParams *gopter.GenParameters) *gopter.GenResult { 485 var s big.Int 486 var b [fp.Bytes]byte 487 _, err := crand.Read(b[:]) 488 if err != nil { 489 panic(err) 490 } 491 s.SetBytes(b[:]) 492 genResult := gopter.NewGenResult(s, gopter.NoShrinker) 493 return genResult 494 } 495 }