github.com/consensys/gnark-crypto@v0.14.0/ecc/bn254/marshal.go (about) 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 17 package bn254 18 19 import ( 20 "encoding/binary" 21 "errors" 22 "io" 23 "reflect" 24 "sync/atomic" 25 26 "github.com/consensys/gnark-crypto/ecc/bn254/fp" 27 "github.com/consensys/gnark-crypto/ecc/bn254/fr" 28 "github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower" 29 "github.com/consensys/gnark-crypto/internal/parallel" 30 ) 31 32 // To encode G1Affine and G2Affine points, we mask the most significant bits with these bits to specify without ambiguity 33 // metadata needed for point (de)compression 34 // we have less than 3 bits available on the msw, so we can't follow BLS12-381 style encoding. 35 // the difference is the case where a point is infinity and uncompressed is not flagged 36 const ( 37 mMask byte = 0b11 << 6 38 mUncompressed byte = 0b00 << 6 39 mCompressedSmallest byte = 0b10 << 6 40 mCompressedLargest byte = 0b11 << 6 41 mCompressedInfinity byte = 0b01 << 6 42 ) 43 44 // SizeOfGT represents the size in bytes that a GT element need in binary form 45 const SizeOfGT = fptower.SizeOfGT 46 47 var ( 48 ErrInvalidInfinityEncoding = errors.New("invalid infinity point encoding") 49 ErrInvalidEncoding = errors.New("invalid point encoding") 50 ) 51 52 // Encoder writes bn254 object values to an output stream 53 type Encoder struct { 54 w io.Writer 55 n int64 // written bytes 56 raw bool // raw vs compressed encoding 57 } 58 59 // Decoder reads bn254 object values from an inbound stream 60 type Decoder struct { 61 r io.Reader 62 n int64 // read bytes 63 subGroupCheck bool // default to true 64 } 65 66 // NewDecoder returns a binary decoder supporting curve bn254 objects in both 67 // compressed and uncompressed (raw) forms 68 func NewDecoder(r io.Reader, options ...func(*Decoder)) *Decoder { 69 d := &Decoder{r: r, subGroupCheck: true} 70 71 for _, o := range options { 72 o(d) 73 } 74 75 return d 76 } 77 78 // Decode reads the binary encoding of v from the stream 79 // type must be *uint64, *fr.Element, *fp.Element, *G1Affine, *G2Affine, *[]G1Affine or *[]G2Affine 80 func (dec *Decoder) Decode(v interface{}) (err error) { 81 rv := reflect.ValueOf(v) 82 if v == nil || rv.Kind() != reflect.Ptr || rv.IsNil() || !rv.Elem().CanSet() { 83 return errors.New("bn254 decoder: unsupported type, need pointer") 84 } 85 86 // implementation note: code is a bit verbose (abusing code generation), but minimize allocations on the heap 87 // in particular, careful attention must be given to usage of Bytes() method on Elements and Points 88 // that return an array (not a slice) of bytes. Using this is beneficial to minimize memory allocations 89 // in very large (de)serialization upstream in gnark. 90 // (but detrimental to code readability here) 91 92 var read64 int64 93 if vf, ok := v.(io.ReaderFrom); ok { 94 read64, err = vf.ReadFrom(dec.r) 95 dec.n += read64 96 return 97 } 98 99 var buf [SizeOfG2AffineUncompressed]byte 100 var read int 101 var sliceLen uint32 102 103 switch t := v.(type) { 104 case *[][]uint64: 105 if sliceLen, err = dec.readUint32(); err != nil { 106 return 107 } 108 *t = make([][]uint64, sliceLen) 109 110 for i := range *t { 111 if sliceLen, err = dec.readUint32(); err != nil { 112 return 113 } 114 (*t)[i] = make([]uint64, sliceLen) 115 for j := range (*t)[i] { 116 if (*t)[i][j], err = dec.readUint64(); err != nil { 117 return 118 } 119 } 120 } 121 return 122 case *[]uint64: 123 if sliceLen, err = dec.readUint32(); err != nil { 124 return 125 } 126 *t = make([]uint64, sliceLen) 127 for i := range *t { 128 if (*t)[i], err = dec.readUint64(); err != nil { 129 return 130 } 131 } 132 return 133 case *fr.Element: 134 read, err = io.ReadFull(dec.r, buf[:fr.Bytes]) 135 dec.n += int64(read) 136 if err != nil { 137 return 138 } 139 err = t.SetBytesCanonical(buf[:fr.Bytes]) 140 return 141 case *fp.Element: 142 read, err = io.ReadFull(dec.r, buf[:fp.Bytes]) 143 dec.n += int64(read) 144 if err != nil { 145 return 146 } 147 err = t.SetBytesCanonical(buf[:fp.Bytes]) 148 return 149 case *[]fr.Element: 150 read64, err = (*fr.Vector)(t).ReadFrom(dec.r) 151 dec.n += read64 152 return 153 case *[]fp.Element: 154 read64, err = (*fp.Vector)(t).ReadFrom(dec.r) 155 dec.n += read64 156 return 157 case *[][]fr.Element: 158 if sliceLen, err = dec.readUint32(); err != nil { 159 return 160 } 161 if len(*t) != int(sliceLen) { 162 *t = make([][]fr.Element, sliceLen) 163 } 164 for i := range *t { 165 read64, err = (*fr.Vector)(&(*t)[i]).ReadFrom(dec.r) 166 dec.n += read64 167 } 168 return 169 case *G1Affine: 170 // we start by reading compressed point size, if metadata tells us it is uncompressed, we read more. 171 read, err = io.ReadFull(dec.r, buf[:SizeOfG1AffineCompressed]) 172 dec.n += int64(read) 173 if err != nil { 174 return 175 } 176 nbBytes := SizeOfG1AffineCompressed 177 178 // most significant byte contains metadata 179 if !isCompressed(buf[0]) { 180 nbBytes = SizeOfG1AffineUncompressed 181 // we read more. 182 read, err = io.ReadFull(dec.r, buf[SizeOfG1AffineCompressed:SizeOfG1AffineUncompressed]) 183 dec.n += int64(read) 184 if err != nil { 185 return 186 } 187 } 188 _, err = t.setBytes(buf[:nbBytes], dec.subGroupCheck) 189 return 190 case *G2Affine: 191 // we start by reading compressed point size, if metadata tells us it is uncompressed, we read more. 192 read, err = io.ReadFull(dec.r, buf[:SizeOfG2AffineCompressed]) 193 dec.n += int64(read) 194 if err != nil { 195 return 196 } 197 nbBytes := SizeOfG2AffineCompressed 198 199 // most significant byte contains metadata 200 if !isCompressed(buf[0]) { 201 nbBytes = SizeOfG2AffineUncompressed 202 // we read more. 203 read, err = io.ReadFull(dec.r, buf[SizeOfG2AffineCompressed:SizeOfG2AffineUncompressed]) 204 dec.n += int64(read) 205 if err != nil { 206 return 207 } 208 } 209 _, err = t.setBytes(buf[:nbBytes], dec.subGroupCheck) 210 return 211 case *[]G1Affine: 212 sliceLen, err = dec.readUint32() 213 if err != nil { 214 return 215 } 216 if len(*t) != int(sliceLen) || *t == nil { 217 *t = make([]G1Affine, sliceLen) 218 } 219 compressed := make([]bool, sliceLen) 220 for i := 0; i < len(*t); i++ { 221 222 // we start by reading compressed point size, if metadata tells us it is uncompressed, we read more. 223 read, err = io.ReadFull(dec.r, buf[:SizeOfG1AffineCompressed]) 224 dec.n += int64(read) 225 if err != nil { 226 return 227 } 228 nbBytes := SizeOfG1AffineCompressed 229 230 // most significant byte contains metadata 231 if !isCompressed(buf[0]) { 232 nbBytes = SizeOfG1AffineUncompressed 233 // we read more. 234 read, err = io.ReadFull(dec.r, buf[SizeOfG1AffineCompressed:SizeOfG1AffineUncompressed]) 235 dec.n += int64(read) 236 if err != nil { 237 return 238 } 239 _, err = (*t)[i].setBytes(buf[:nbBytes], false) 240 if err != nil { 241 return 242 } 243 } else { 244 var r bool 245 if r, err = (*t)[i].unsafeSetCompressedBytes(buf[:nbBytes]); err != nil { 246 return 247 } 248 compressed[i] = !r 249 } 250 } 251 var nbErrs uint64 252 parallel.Execute(len(compressed), func(start, end int) { 253 for i := start; i < end; i++ { 254 if compressed[i] { 255 if err := (*t)[i].unsafeComputeY(dec.subGroupCheck); err != nil { 256 atomic.AddUint64(&nbErrs, 1) 257 } 258 } else if dec.subGroupCheck { 259 if !(*t)[i].IsInSubGroup() { 260 atomic.AddUint64(&nbErrs, 1) 261 } 262 } 263 } 264 }) 265 if nbErrs != 0 { 266 return errors.New("point decompression failed") 267 } 268 269 return nil 270 case *[]G2Affine: 271 sliceLen, err = dec.readUint32() 272 if err != nil { 273 return 274 } 275 if len(*t) != int(sliceLen) { 276 *t = make([]G2Affine, sliceLen) 277 } 278 compressed := make([]bool, sliceLen) 279 for i := 0; i < len(*t); i++ { 280 281 // we start by reading compressed point size, if metadata tells us it is uncompressed, we read more. 282 read, err = io.ReadFull(dec.r, buf[:SizeOfG2AffineCompressed]) 283 dec.n += int64(read) 284 if err != nil { 285 return 286 } 287 nbBytes := SizeOfG2AffineCompressed 288 289 // most significant byte contains metadata 290 if !isCompressed(buf[0]) { 291 nbBytes = SizeOfG2AffineUncompressed 292 // we read more. 293 read, err = io.ReadFull(dec.r, buf[SizeOfG2AffineCompressed:SizeOfG2AffineUncompressed]) 294 dec.n += int64(read) 295 if err != nil { 296 return 297 } 298 _, err = (*t)[i].setBytes(buf[:nbBytes], false) 299 if err != nil { 300 return 301 } 302 } else { 303 var r bool 304 if r, err = (*t)[i].unsafeSetCompressedBytes(buf[:nbBytes]); err != nil { 305 return 306 } 307 compressed[i] = !r 308 } 309 } 310 var nbErrs uint64 311 parallel.Execute(len(compressed), func(start, end int) { 312 for i := start; i < end; i++ { 313 if compressed[i] { 314 if err := (*t)[i].unsafeComputeY(dec.subGroupCheck); err != nil { 315 atomic.AddUint64(&nbErrs, 1) 316 } 317 } else if dec.subGroupCheck { 318 if !(*t)[i].IsInSubGroup() { 319 atomic.AddUint64(&nbErrs, 1) 320 } 321 } 322 } 323 }) 324 if nbErrs != 0 { 325 return errors.New("point decompression failed") 326 } 327 328 return nil 329 default: 330 n := binary.Size(t) 331 if n == -1 { 332 return errors.New("bn254 encoder: unsupported type") 333 } 334 err = binary.Read(dec.r, binary.BigEndian, t) 335 if err == nil { 336 dec.n += int64(n) 337 } 338 return 339 } 340 } 341 342 // BytesRead return total bytes read from reader 343 func (dec *Decoder) BytesRead() int64 { 344 return dec.n 345 } 346 347 func (dec *Decoder) readUint32() (r uint32, err error) { 348 var read int 349 var buf [4]byte 350 read, err = io.ReadFull(dec.r, buf[:4]) 351 dec.n += int64(read) 352 if err != nil { 353 return 354 } 355 r = binary.BigEndian.Uint32(buf[:4]) 356 return 357 } 358 359 func (dec *Decoder) readUint64() (r uint64, err error) { 360 var read int 361 var buf [8]byte 362 read, err = io.ReadFull(dec.r, buf[:]) 363 dec.n += int64(read) 364 if err != nil { 365 return 366 } 367 r = binary.BigEndian.Uint64(buf[:]) 368 return 369 } 370 371 func isCompressed(msb byte) bool { 372 mData := msb & mMask 373 return !(mData == mUncompressed) 374 } 375 376 // NewEncoder returns a binary encoder supporting curve bn254 objects 377 func NewEncoder(w io.Writer, options ...func(*Encoder)) *Encoder { 378 // default settings 379 enc := &Encoder{ 380 w: w, 381 n: 0, 382 raw: false, 383 } 384 385 // handle options 386 for _, option := range options { 387 option(enc) 388 } 389 390 return enc 391 } 392 393 // Encode writes the binary encoding of v to the stream 394 // type must be uint64, *fr.Element, *fp.Element, *G1Affine, *G2Affine, []G1Affine or []G2Affine 395 func (enc *Encoder) Encode(v interface{}) (err error) { 396 if enc.raw { 397 return enc.encodeRaw(v) 398 } 399 return enc.encode(v) 400 } 401 402 // BytesWritten return total bytes written on writer 403 func (enc *Encoder) BytesWritten() int64 { 404 return enc.n 405 } 406 407 // RawEncoding returns an option to use in NewEncoder(...) which sets raw encoding mode to true 408 // points will not be compressed using this option 409 func RawEncoding() func(*Encoder) { 410 return func(enc *Encoder) { 411 enc.raw = true 412 } 413 } 414 415 // NoSubgroupChecks returns an option to use in NewDecoder(...) which disable subgroup checks on the points 416 // the decoder will read. Use with caution, as crafted points from an untrusted source can lead to crypto-attacks. 417 func NoSubgroupChecks() func(*Decoder) { 418 return func(dec *Decoder) { 419 dec.subGroupCheck = false 420 } 421 } 422 423 // isZeroed checks that the provided bytes are at 0 424 func isZeroed(firstByte byte, buf []byte) bool { 425 if firstByte != 0 { 426 return false 427 } 428 for _, b := range buf { 429 if b != 0 { 430 return false 431 } 432 } 433 return true 434 } 435 436 func (enc *Encoder) encode(v interface{}) (err error) { 437 rv := reflect.ValueOf(v) 438 if v == nil || (rv.Kind() == reflect.Ptr && rv.IsNil()) { 439 return errors.New("<no value> encoder: can't encode <nil>") 440 } 441 442 // implementation note: code is a bit verbose (abusing code generation), but minimize allocations on the heap 443 444 var written64 int64 445 if vw, ok := v.(io.WriterTo); ok { 446 written64, err = vw.WriteTo(enc.w) 447 enc.n += written64 448 return 449 } 450 451 var written int 452 453 switch t := v.(type) { 454 case []uint64: 455 return enc.writeUint64Slice(t) 456 case [][]uint64: 457 return enc.writeUint64SliceSlice(t) 458 case *fr.Element: 459 buf := t.Bytes() 460 written, err = enc.w.Write(buf[:]) 461 enc.n += int64(written) 462 return 463 case *fp.Element: 464 buf := t.Bytes() 465 written, err = enc.w.Write(buf[:]) 466 enc.n += int64(written) 467 return 468 case *G1Affine: 469 buf := t.Bytes() 470 written, err = enc.w.Write(buf[:]) 471 enc.n += int64(written) 472 return 473 case *G2Affine: 474 buf := t.Bytes() 475 written, err = enc.w.Write(buf[:]) 476 enc.n += int64(written) 477 return 478 case fr.Vector: 479 written64, err = t.WriteTo(enc.w) 480 enc.n += written64 481 return 482 case fp.Vector: 483 written64, err = t.WriteTo(enc.w) 484 enc.n += written64 485 return 486 case []fr.Element: 487 written64, err = (*fr.Vector)(&t).WriteTo(enc.w) 488 enc.n += written64 489 return 490 case []fp.Element: 491 written64, err = (*fp.Vector)(&t).WriteTo(enc.w) 492 enc.n += written64 493 return 494 case [][]fr.Element: 495 // write slice length 496 if err = binary.Write(enc.w, binary.BigEndian, uint32(len(t))); err != nil { 497 return 498 } 499 enc.n += 4 500 for i := range t { 501 written64, err = (*fr.Vector)(&t[i]).WriteTo(enc.w) 502 enc.n += written64 503 } 504 return 505 case []G1Affine: 506 // write slice length 507 err = binary.Write(enc.w, binary.BigEndian, uint32(len(t))) 508 if err != nil { 509 return 510 } 511 enc.n += 4 512 513 var buf [SizeOfG1AffineCompressed]byte 514 515 for i := 0; i < len(t); i++ { 516 buf = t[i].Bytes() 517 written, err = enc.w.Write(buf[:]) 518 enc.n += int64(written) 519 if err != nil { 520 return 521 } 522 } 523 return nil 524 case []G2Affine: 525 // write slice length 526 err = binary.Write(enc.w, binary.BigEndian, uint32(len(t))) 527 if err != nil { 528 return 529 } 530 enc.n += 4 531 532 var buf [SizeOfG2AffineCompressed]byte 533 534 for i := 0; i < len(t); i++ { 535 buf = t[i].Bytes() 536 written, err = enc.w.Write(buf[:]) 537 enc.n += int64(written) 538 if err != nil { 539 return 540 } 541 } 542 return nil 543 default: 544 n := binary.Size(t) 545 if n == -1 { 546 return errors.New("<no value> encoder: unsupported type") 547 } 548 err = binary.Write(enc.w, binary.BigEndian, t) 549 enc.n += int64(n) 550 return 551 } 552 } 553 554 func (enc *Encoder) encodeRaw(v interface{}) (err error) { 555 rv := reflect.ValueOf(v) 556 if v == nil || (rv.Kind() == reflect.Ptr && rv.IsNil()) { 557 return errors.New("<no value> encoder: can't encode <nil>") 558 } 559 560 // implementation note: code is a bit verbose (abusing code generation), but minimize allocations on the heap 561 562 var written64 int64 563 if vw, ok := v.(io.WriterTo); ok { 564 written64, err = vw.WriteTo(enc.w) 565 enc.n += written64 566 return 567 } 568 569 var written int 570 571 switch t := v.(type) { 572 case []uint64: 573 return enc.writeUint64Slice(t) 574 case [][]uint64: 575 return enc.writeUint64SliceSlice(t) 576 case *fr.Element: 577 buf := t.Bytes() 578 written, err = enc.w.Write(buf[:]) 579 enc.n += int64(written) 580 return 581 case *fp.Element: 582 buf := t.Bytes() 583 written, err = enc.w.Write(buf[:]) 584 enc.n += int64(written) 585 return 586 case *G1Affine: 587 buf := t.RawBytes() 588 written, err = enc.w.Write(buf[:]) 589 enc.n += int64(written) 590 return 591 case *G2Affine: 592 buf := t.RawBytes() 593 written, err = enc.w.Write(buf[:]) 594 enc.n += int64(written) 595 return 596 case fr.Vector: 597 written64, err = t.WriteTo(enc.w) 598 enc.n += written64 599 return 600 case fp.Vector: 601 written64, err = t.WriteTo(enc.w) 602 enc.n += written64 603 return 604 case []fr.Element: 605 written64, err = (*fr.Vector)(&t).WriteTo(enc.w) 606 enc.n += written64 607 return 608 case []fp.Element: 609 written64, err = (*fp.Vector)(&t).WriteTo(enc.w) 610 enc.n += written64 611 return 612 case [][]fr.Element: 613 // write slice length 614 if err = binary.Write(enc.w, binary.BigEndian, uint32(len(t))); err != nil { 615 return 616 } 617 enc.n += 4 618 for i := range t { 619 written64, err = (*fr.Vector)(&t[i]).WriteTo(enc.w) 620 enc.n += written64 621 } 622 return 623 case []G1Affine: 624 // write slice length 625 err = binary.Write(enc.w, binary.BigEndian, uint32(len(t))) 626 if err != nil { 627 return 628 } 629 enc.n += 4 630 631 var buf [SizeOfG1AffineUncompressed]byte 632 633 for i := 0; i < len(t); i++ { 634 buf = t[i].RawBytes() 635 written, err = enc.w.Write(buf[:]) 636 enc.n += int64(written) 637 if err != nil { 638 return 639 } 640 } 641 return nil 642 case []G2Affine: 643 // write slice length 644 err = binary.Write(enc.w, binary.BigEndian, uint32(len(t))) 645 if err != nil { 646 return 647 } 648 enc.n += 4 649 650 var buf [SizeOfG2AffineUncompressed]byte 651 652 for i := 0; i < len(t); i++ { 653 buf = t[i].RawBytes() 654 written, err = enc.w.Write(buf[:]) 655 enc.n += int64(written) 656 if err != nil { 657 return 658 } 659 } 660 return nil 661 default: 662 n := binary.Size(t) 663 if n == -1 { 664 return errors.New("<no value> encoder: unsupported type") 665 } 666 err = binary.Write(enc.w, binary.BigEndian, t) 667 enc.n += int64(n) 668 return 669 } 670 } 671 672 func (enc *Encoder) writeUint64Slice(t []uint64) (err error) { 673 if err = enc.writeUint32(uint32(len(t))); err != nil { 674 return 675 } 676 for i := range t { 677 if err = enc.writeUint64(t[i]); err != nil { 678 return 679 } 680 } 681 return nil 682 } 683 684 func (enc *Encoder) writeUint64SliceSlice(t [][]uint64) (err error) { 685 if err = enc.writeUint32(uint32(len(t))); err != nil { 686 return 687 } 688 for i := range t { 689 if err = enc.writeUint32(uint32(len(t[i]))); err != nil { 690 return 691 } 692 for j := range t[i] { 693 if err = enc.writeUint64(t[i][j]); err != nil { 694 return 695 } 696 } 697 } 698 return nil 699 } 700 701 func (enc *Encoder) writeUint64(a uint64) error { 702 var buff [64 / 8]byte 703 binary.BigEndian.PutUint64(buff[:], a) 704 written, err := enc.w.Write(buff[:]) 705 enc.n += int64(written) 706 return err 707 } 708 709 func (enc *Encoder) writeUint32(a uint32) error { 710 var buff [32 / 8]byte 711 binary.BigEndian.PutUint32(buff[:], a) 712 written, err := enc.w.Write(buff[:]) 713 enc.n += int64(written) 714 return err 715 } 716 717 // SizeOfG1AffineCompressed represents the size in bytes that a G1Affine need in binary form, compressed 718 const SizeOfG1AffineCompressed = 32 719 720 // SizeOfG1AffineUncompressed represents the size in bytes that a G1Affine need in binary form, uncompressed 721 const SizeOfG1AffineUncompressed = SizeOfG1AffineCompressed * 2 722 723 // Marshal converts p to a byte slice (without point compression) 724 func (p *G1Affine) Marshal() []byte { 725 b := p.RawBytes() 726 return b[:] 727 } 728 729 // Unmarshal is an alias to SetBytes() 730 func (p *G1Affine) Unmarshal(buf []byte) error { 731 _, err := p.SetBytes(buf) 732 return err 733 } 734 735 // Bytes returns binary representation of p 736 // will store X coordinate in regular form and a parity bit 737 // as we have less than 3 bits available in our coordinate, we can't follow BLS12-381 style encoding (ZCash/IETF) 738 // 739 // we use the 2 most significant bits instead 740 // 741 // 00 -> uncompressed 742 // 10 -> compressed, use smallest lexicographically square root of Y^2 743 // 11 -> compressed, use largest lexicographically square root of Y^2 744 // 01 -> compressed infinity point 745 // the "uncompressed infinity point" will just have 00 (uncompressed) followed by zeroes (infinity = 0,0 in affine coordinates) 746 func (p *G1Affine) Bytes() (res [SizeOfG1AffineCompressed]byte) { 747 748 // check if p is infinity point 749 if p.X.IsZero() && p.Y.IsZero() { 750 res[0] = mCompressedInfinity 751 return 752 } 753 754 msbMask := mCompressedSmallest 755 // compressed, we need to know if Y is lexicographically bigger than -Y 756 // if p.Y ">" -p.Y 757 if p.Y.LexicographicallyLargest() { 758 msbMask = mCompressedLargest 759 } 760 761 // we store X and mask the most significant word with our metadata mask 762 fp.BigEndian.PutElement((*[fp.Bytes]byte)(res[0:0+fp.Bytes]), p.X) 763 764 res[0] |= msbMask 765 766 return 767 } 768 769 // RawBytes returns binary representation of p (stores X and Y coordinate) 770 // see Bytes() for a compressed representation 771 func (p *G1Affine) RawBytes() (res [SizeOfG1AffineUncompressed]byte) { 772 773 // check if p is infinity point 774 if p.X.IsZero() && p.Y.IsZero() { 775 776 res[0] = mUncompressed 777 778 return 779 } 780 781 // not compressed 782 // we store the Y coordinate 783 fp.BigEndian.PutElement((*[fp.Bytes]byte)(res[32:32+fp.Bytes]), p.Y) 784 785 // we store X and mask the most significant word with our metadata mask 786 fp.BigEndian.PutElement((*[fp.Bytes]byte)(res[0:0+fp.Bytes]), p.X) 787 788 res[0] |= mUncompressed 789 790 return 791 } 792 793 // SetBytes sets p from binary representation in buf and returns number of consumed bytes 794 // 795 // bytes in buf must match either RawBytes() or Bytes() output 796 // 797 // if buf is too short io.ErrShortBuffer is returned 798 // 799 // if buf contains compressed representation (output from Bytes()) and we're unable to compute 800 // the Y coordinate (i.e the square root doesn't exist) this function returns an error 801 // 802 // this check if the resulting point is on the curve and in the correct subgroup 803 func (p *G1Affine) SetBytes(buf []byte) (int, error) { 804 return p.setBytes(buf, true) 805 } 806 807 func (p *G1Affine) setBytes(buf []byte, subGroupCheck bool) (int, error) { 808 if len(buf) < SizeOfG1AffineCompressed { 809 return 0, io.ErrShortBuffer 810 } 811 812 // most significant byte 813 mData := buf[0] & mMask 814 815 // check buffer size 816 if mData == mUncompressed { 817 if len(buf) < SizeOfG1AffineUncompressed { 818 return 0, io.ErrShortBuffer 819 } 820 } 821 822 // infinity encoded, we still check that the buffer is full of zeroes. 823 if mData == mCompressedInfinity { 824 if !isZeroed(buf[0] & ^mMask, buf[1:SizeOfG1AffineCompressed]) { 825 return 0, ErrInvalidInfinityEncoding 826 } 827 p.X.SetZero() 828 p.Y.SetZero() 829 return SizeOfG1AffineCompressed, nil 830 } 831 832 // uncompressed point 833 if mData == mUncompressed { 834 // read X and Y coordinates 835 if err := p.X.SetBytesCanonical(buf[:fp.Bytes]); err != nil { 836 return 0, err 837 } 838 if err := p.Y.SetBytesCanonical(buf[fp.Bytes : fp.Bytes*2]); err != nil { 839 return 0, err 840 } 841 842 // subgroup check 843 if subGroupCheck && !p.IsInSubGroup() { 844 return 0, errors.New("invalid point: subgroup check failed") 845 } 846 847 return SizeOfG1AffineUncompressed, nil 848 } 849 850 // we have a compressed coordinate 851 // we need to 852 // 1. copy the buffer (to keep this method thread safe) 853 // 2. we need to solve the curve equation to compute Y 854 855 var bufX [fp.Bytes]byte 856 copy(bufX[:fp.Bytes], buf[:fp.Bytes]) 857 bufX[0] &= ^mMask 858 859 // read X coordinate 860 if err := p.X.SetBytesCanonical(bufX[:fp.Bytes]); err != nil { 861 return 0, err 862 } 863 864 var YSquared, Y fp.Element 865 866 YSquared.Square(&p.X).Mul(&YSquared, &p.X) 867 YSquared.Add(&YSquared, &bCurveCoeff) 868 if Y.Sqrt(&YSquared) == nil { 869 return 0, errors.New("invalid compressed coordinate: square root doesn't exist") 870 } 871 872 if Y.LexicographicallyLargest() { 873 // Y ">" -Y 874 if mData == mCompressedSmallest { 875 Y.Neg(&Y) 876 } 877 } else { 878 // Y "<=" -Y 879 if mData == mCompressedLargest { 880 Y.Neg(&Y) 881 } 882 } 883 884 p.Y = Y 885 886 // subgroup check 887 if subGroupCheck && !p.IsInSubGroup() { 888 return 0, errors.New("invalid point: subgroup check failed") 889 } 890 891 return SizeOfG1AffineCompressed, nil 892 } 893 894 // unsafeComputeY called by Decoder when processing slices of compressed point in parallel (step 2) 895 // it computes the Y coordinate from the already set X coordinate and is compute intensive 896 func (p *G1Affine) unsafeComputeY(subGroupCheck bool) error { 897 // stored in unsafeSetCompressedBytes 898 899 mData := byte(p.Y[0]) 900 901 // we have a compressed coordinate, we need to solve the curve equation to compute Y 902 var YSquared, Y fp.Element 903 904 YSquared.Square(&p.X).Mul(&YSquared, &p.X) 905 YSquared.Add(&YSquared, &bCurveCoeff) 906 if Y.Sqrt(&YSquared) == nil { 907 return errors.New("invalid compressed coordinate: square root doesn't exist") 908 } 909 910 if Y.LexicographicallyLargest() { 911 // Y ">" -Y 912 if mData == mCompressedSmallest { 913 Y.Neg(&Y) 914 } 915 } else { 916 // Y "<=" -Y 917 if mData == mCompressedLargest { 918 Y.Neg(&Y) 919 } 920 } 921 922 p.Y = Y 923 924 // subgroup check 925 if subGroupCheck && !p.IsInSubGroup() { 926 return errors.New("invalid point: subgroup check failed") 927 } 928 929 return nil 930 } 931 932 // unsafeSetCompressedBytes is called by Decoder when processing slices of compressed point in parallel (step 1) 933 // assumes buf[:8] mask is set to compressed 934 // returns true if point is infinity and need no further processing 935 // it sets X coordinate and uses Y for scratch space to store decompression metadata 936 func (p *G1Affine) unsafeSetCompressedBytes(buf []byte) (isInfinity bool, err error) { 937 938 // read the most significant byte 939 mData := buf[0] & mMask 940 941 if mData == mCompressedInfinity { 942 isInfinity = true 943 if !isZeroed(buf[0] & ^mMask, buf[1:SizeOfG1AffineCompressed]) { 944 return isInfinity, ErrInvalidInfinityEncoding 945 } 946 p.X.SetZero() 947 p.Y.SetZero() 948 return isInfinity, nil 949 } 950 951 // we need to copy the input buffer (to keep this method thread safe) 952 var bufX [fp.Bytes]byte 953 copy(bufX[:fp.Bytes], buf[:fp.Bytes]) 954 bufX[0] &= ^mMask 955 956 // read X coordinate 957 if err := p.X.SetBytesCanonical(bufX[:fp.Bytes]); err != nil { 958 return false, err 959 } 960 // store mData in p.Y[0] 961 p.Y[0] = uint64(mData) 962 963 // recomputing Y will be done asynchronously 964 return isInfinity, nil 965 } 966 967 // SizeOfG2AffineCompressed represents the size in bytes that a G2Affine need in binary form, compressed 968 const SizeOfG2AffineCompressed = 32 * 2 969 970 // SizeOfG2AffineUncompressed represents the size in bytes that a G2Affine need in binary form, uncompressed 971 const SizeOfG2AffineUncompressed = SizeOfG2AffineCompressed * 2 972 973 // Marshal converts p to a byte slice (without point compression) 974 func (p *G2Affine) Marshal() []byte { 975 b := p.RawBytes() 976 return b[:] 977 } 978 979 // Unmarshal is an alias to SetBytes() 980 func (p *G2Affine) Unmarshal(buf []byte) error { 981 _, err := p.SetBytes(buf) 982 return err 983 } 984 985 // Bytes returns binary representation of p 986 // will store X coordinate in regular form and a parity bit 987 // as we have less than 3 bits available in our coordinate, we can't follow BLS12-381 style encoding (ZCash/IETF) 988 // 989 // we use the 2 most significant bits instead 990 // 991 // 00 -> uncompressed 992 // 10 -> compressed, use smallest lexicographically square root of Y^2 993 // 11 -> compressed, use largest lexicographically square root of Y^2 994 // 01 -> compressed infinity point 995 // the "uncompressed infinity point" will just have 00 (uncompressed) followed by zeroes (infinity = 0,0 in affine coordinates) 996 func (p *G2Affine) Bytes() (res [SizeOfG2AffineCompressed]byte) { 997 998 // check if p is infinity point 999 if p.X.IsZero() && p.Y.IsZero() { 1000 res[0] = mCompressedInfinity 1001 return 1002 } 1003 1004 msbMask := mCompressedSmallest 1005 // compressed, we need to know if Y is lexicographically bigger than -Y 1006 // if p.Y ">" -p.Y 1007 if p.Y.LexicographicallyLargest() { 1008 msbMask = mCompressedLargest 1009 } 1010 1011 // we store X and mask the most significant word with our metadata mask 1012 // p.X.A1 | p.X.A0 1013 fp.BigEndian.PutElement((*[fp.Bytes]byte)(res[32:32+fp.Bytes]), p.X.A0) 1014 fp.BigEndian.PutElement((*[fp.Bytes]byte)(res[0:0+fp.Bytes]), p.X.A1) 1015 1016 res[0] |= msbMask 1017 1018 return 1019 } 1020 1021 // RawBytes returns binary representation of p (stores X and Y coordinate) 1022 // see Bytes() for a compressed representation 1023 func (p *G2Affine) RawBytes() (res [SizeOfG2AffineUncompressed]byte) { 1024 1025 // check if p is infinity point 1026 if p.X.IsZero() && p.Y.IsZero() { 1027 1028 res[0] = mUncompressed 1029 1030 return 1031 } 1032 1033 // not compressed 1034 // we store the Y coordinate 1035 // p.Y.A1 | p.Y.A0 1036 fp.BigEndian.PutElement((*[fp.Bytes]byte)(res[96:96+fp.Bytes]), p.Y.A0) 1037 fp.BigEndian.PutElement((*[fp.Bytes]byte)(res[64:64+fp.Bytes]), p.Y.A1) 1038 1039 // we store X and mask the most significant word with our metadata mask 1040 // p.X.A1 | p.X.A0 1041 fp.BigEndian.PutElement((*[fp.Bytes]byte)(res[0:0+fp.Bytes]), p.X.A1) 1042 fp.BigEndian.PutElement((*[fp.Bytes]byte)(res[32:32+fp.Bytes]), p.X.A0) 1043 1044 res[0] |= mUncompressed 1045 1046 return 1047 } 1048 1049 // SetBytes sets p from binary representation in buf and returns number of consumed bytes 1050 // 1051 // bytes in buf must match either RawBytes() or Bytes() output 1052 // 1053 // if buf is too short io.ErrShortBuffer is returned 1054 // 1055 // if buf contains compressed representation (output from Bytes()) and we're unable to compute 1056 // the Y coordinate (i.e the square root doesn't exist) this function returns an error 1057 // 1058 // this check if the resulting point is on the curve and in the correct subgroup 1059 func (p *G2Affine) SetBytes(buf []byte) (int, error) { 1060 return p.setBytes(buf, true) 1061 } 1062 1063 func (p *G2Affine) setBytes(buf []byte, subGroupCheck bool) (int, error) { 1064 if len(buf) < SizeOfG2AffineCompressed { 1065 return 0, io.ErrShortBuffer 1066 } 1067 1068 // most significant byte 1069 mData := buf[0] & mMask 1070 1071 // check buffer size 1072 if mData == mUncompressed { 1073 if len(buf) < SizeOfG2AffineUncompressed { 1074 return 0, io.ErrShortBuffer 1075 } 1076 } 1077 1078 // infinity encoded, we still check that the buffer is full of zeroes. 1079 if mData == mCompressedInfinity { 1080 if !isZeroed(buf[0] & ^mMask, buf[1:SizeOfG2AffineCompressed]) { 1081 return 0, ErrInvalidInfinityEncoding 1082 } 1083 p.X.SetZero() 1084 p.Y.SetZero() 1085 return SizeOfG2AffineCompressed, nil 1086 } 1087 1088 // uncompressed point 1089 if mData == mUncompressed { 1090 // read X and Y coordinates 1091 // p.X.A1 | p.X.A0 1092 if err := p.X.A1.SetBytesCanonical(buf[:fp.Bytes]); err != nil { 1093 return 0, err 1094 } 1095 if err := p.X.A0.SetBytesCanonical(buf[fp.Bytes : fp.Bytes*2]); err != nil { 1096 return 0, err 1097 } 1098 // p.Y.A1 | p.Y.A0 1099 if err := p.Y.A1.SetBytesCanonical(buf[fp.Bytes*2 : fp.Bytes*3]); err != nil { 1100 return 0, err 1101 } 1102 if err := p.Y.A0.SetBytesCanonical(buf[fp.Bytes*3 : fp.Bytes*4]); err != nil { 1103 return 0, err 1104 } 1105 1106 // subgroup check 1107 if subGroupCheck && !p.IsInSubGroup() { 1108 return 0, errors.New("invalid point: subgroup check failed") 1109 } 1110 1111 return SizeOfG2AffineUncompressed, nil 1112 } 1113 1114 // we have a compressed coordinate 1115 // we need to 1116 // 1. copy the buffer (to keep this method thread safe) 1117 // 2. we need to solve the curve equation to compute Y 1118 1119 var bufX [fp.Bytes]byte 1120 copy(bufX[:fp.Bytes], buf[:fp.Bytes]) 1121 bufX[0] &= ^mMask 1122 1123 // read X coordinate 1124 // p.X.A1 | p.X.A0 1125 if err := p.X.A1.SetBytesCanonical(bufX[:fp.Bytes]); err != nil { 1126 return 0, err 1127 } 1128 if err := p.X.A0.SetBytesCanonical(buf[fp.Bytes : fp.Bytes*2]); err != nil { 1129 return 0, err 1130 } 1131 1132 var YSquared, Y fptower.E2 1133 1134 YSquared.Square(&p.X).Mul(&YSquared, &p.X) 1135 YSquared.Add(&YSquared, &bTwistCurveCoeff) 1136 if YSquared.Legendre() == -1 { 1137 return 0, errors.New("invalid compressed coordinate: square root doesn't exist") 1138 } 1139 Y.Sqrt(&YSquared) 1140 1141 if Y.LexicographicallyLargest() { 1142 // Y ">" -Y 1143 if mData == mCompressedSmallest { 1144 Y.Neg(&Y) 1145 } 1146 } else { 1147 // Y "<=" -Y 1148 if mData == mCompressedLargest { 1149 Y.Neg(&Y) 1150 } 1151 } 1152 1153 p.Y = Y 1154 1155 // subgroup check 1156 if subGroupCheck && !p.IsInSubGroup() { 1157 return 0, errors.New("invalid point: subgroup check failed") 1158 } 1159 1160 return SizeOfG2AffineCompressed, nil 1161 } 1162 1163 // unsafeComputeY called by Decoder when processing slices of compressed point in parallel (step 2) 1164 // it computes the Y coordinate from the already set X coordinate and is compute intensive 1165 func (p *G2Affine) unsafeComputeY(subGroupCheck bool) error { 1166 // stored in unsafeSetCompressedBytes 1167 1168 mData := byte(p.Y.A0[0]) 1169 1170 // we have a compressed coordinate, we need to solve the curve equation to compute Y 1171 var YSquared, Y fptower.E2 1172 1173 YSquared.Square(&p.X).Mul(&YSquared, &p.X) 1174 YSquared.Add(&YSquared, &bTwistCurveCoeff) 1175 if YSquared.Legendre() == -1 { 1176 return errors.New("invalid compressed coordinate: square root doesn't exist") 1177 } 1178 Y.Sqrt(&YSquared) 1179 1180 if Y.LexicographicallyLargest() { 1181 // Y ">" -Y 1182 if mData == mCompressedSmallest { 1183 Y.Neg(&Y) 1184 } 1185 } else { 1186 // Y "<=" -Y 1187 if mData == mCompressedLargest { 1188 Y.Neg(&Y) 1189 } 1190 } 1191 1192 p.Y = Y 1193 1194 // subgroup check 1195 if subGroupCheck && !p.IsInSubGroup() { 1196 return errors.New("invalid point: subgroup check failed") 1197 } 1198 1199 return nil 1200 } 1201 1202 // unsafeSetCompressedBytes is called by Decoder when processing slices of compressed point in parallel (step 1) 1203 // assumes buf[:8] mask is set to compressed 1204 // returns true if point is infinity and need no further processing 1205 // it sets X coordinate and uses Y for scratch space to store decompression metadata 1206 func (p *G2Affine) unsafeSetCompressedBytes(buf []byte) (isInfinity bool, err error) { 1207 1208 // read the most significant byte 1209 mData := buf[0] & mMask 1210 1211 if mData == mCompressedInfinity { 1212 isInfinity = true 1213 if !isZeroed(buf[0] & ^mMask, buf[1:SizeOfG2AffineCompressed]) { 1214 return isInfinity, ErrInvalidInfinityEncoding 1215 } 1216 p.X.SetZero() 1217 p.Y.SetZero() 1218 return isInfinity, nil 1219 } 1220 1221 // we need to copy the input buffer (to keep this method thread safe) 1222 var bufX [fp.Bytes]byte 1223 copy(bufX[:fp.Bytes], buf[:fp.Bytes]) 1224 bufX[0] &= ^mMask 1225 1226 // read X coordinate 1227 // p.X.A1 | p.X.A0 1228 if err := p.X.A1.SetBytesCanonical(bufX[:fp.Bytes]); err != nil { 1229 return false, err 1230 } 1231 if err := p.X.A0.SetBytesCanonical(buf[fp.Bytes : fp.Bytes*2]); err != nil { 1232 return false, err 1233 } 1234 1235 // store mData in p.Y.A0[0] 1236 p.Y.A0[0] = uint64(mData) 1237 1238 // recomputing Y will be done asynchronously 1239 return isInfinity, nil 1240 }