github.com/btcsuite/btcd@v0.24.0/wire/common.go (about) 1 // Copyright (c) 2013-2016 The btcsuite developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package wire 6 7 import ( 8 "crypto/rand" 9 "encoding/binary" 10 "fmt" 11 "io" 12 "math" 13 "time" 14 15 "github.com/btcsuite/btcd/chaincfg/chainhash" 16 ) 17 18 const ( 19 // MaxVarIntPayload is the maximum payload size for a variable length integer. 20 MaxVarIntPayload = 9 21 22 // binaryFreeListMaxItems is the number of buffers to keep in the free 23 // list to use for binary serialization and deserialization. 24 binaryFreeListMaxItems = 1024 25 ) 26 27 var ( 28 // littleEndian is a convenience variable since binary.LittleEndian is 29 // quite long. 30 littleEndian = binary.LittleEndian 31 32 // bigEndian is a convenience variable since binary.BigEndian is quite 33 // long. 34 bigEndian = binary.BigEndian 35 ) 36 37 // binaryFreeList defines a concurrent safe free list of byte slices (up to the 38 // maximum number defined by the binaryFreeListMaxItems constant) that have a 39 // cap of 8 (thus it supports up to a uint64). It is used to provide temporary 40 // buffers for serializing and deserializing primitive numbers to and from their 41 // binary encoding in order to greatly reduce the number of allocations 42 // required. 43 // 44 // For convenience, functions are provided for each of the primitive unsigned 45 // integers that automatically obtain a buffer from the free list, perform the 46 // necessary binary conversion, read from or write to the given io.Reader or 47 // io.Writer, and return the buffer to the free list. 48 type binaryFreeList chan []byte 49 50 // Borrow returns a byte slice from the free list with a length of 8. A new 51 // buffer is allocated if there are not any available on the free list. 52 func (l binaryFreeList) Borrow() []byte { 53 var buf []byte 54 select { 55 case buf = <-l: 56 default: 57 buf = make([]byte, 8) 58 } 59 return buf[:8] 60 } 61 62 // Return puts the provided byte slice back on the free list. The buffer MUST 63 // have been obtained via the Borrow function and therefore have a cap of 8. 64 func (l binaryFreeList) Return(buf []byte) { 65 select { 66 case l <- buf: 67 default: 68 // Let it go to the garbage collector. 69 } 70 } 71 72 // Uint8 reads a single byte from the provided reader using a buffer from the 73 // free list and returns it as a uint8. 74 func (l binaryFreeList) Uint8(r io.Reader) (uint8, error) { 75 buf := l.Borrow()[:1] 76 defer l.Return(buf) 77 78 if _, err := io.ReadFull(r, buf); err != nil { 79 return 0, err 80 } 81 rv := buf[0] 82 83 return rv, nil 84 } 85 86 // Uint16 reads two bytes from the provided reader using a buffer from the 87 // free list, converts it to a number using the provided byte order, and returns 88 // the resulting uint16. 89 func (l binaryFreeList) Uint16(r io.Reader, byteOrder binary.ByteOrder) (uint16, error) { 90 buf := l.Borrow()[:2] 91 defer l.Return(buf) 92 93 if _, err := io.ReadFull(r, buf); err != nil { 94 return 0, err 95 } 96 rv := byteOrder.Uint16(buf) 97 98 return rv, nil 99 } 100 101 // Uint32 reads four bytes from the provided reader using a buffer from the 102 // free list, converts it to a number using the provided byte order, and returns 103 // the resulting uint32. 104 func (l binaryFreeList) Uint32(r io.Reader, byteOrder binary.ByteOrder) (uint32, error) { 105 buf := l.Borrow()[:4] 106 defer l.Return(buf) 107 108 if _, err := io.ReadFull(r, buf); err != nil { 109 return 0, err 110 } 111 rv := byteOrder.Uint32(buf) 112 113 return rv, nil 114 } 115 116 // Uint64 reads eight bytes from the provided reader using a buffer from the 117 // free list, converts it to a number using the provided byte order, and returns 118 // the resulting uint64. 119 func (l binaryFreeList) Uint64(r io.Reader, byteOrder binary.ByteOrder) (uint64, error) { 120 buf := l.Borrow()[:8] 121 defer l.Return(buf) 122 123 if _, err := io.ReadFull(r, buf); err != nil { 124 return 0, err 125 } 126 rv := byteOrder.Uint64(buf) 127 128 return rv, nil 129 } 130 131 // PutUint8 copies the provided uint8 into a buffer from the free list and 132 // writes the resulting byte to the given writer. 133 func (l binaryFreeList) PutUint8(w io.Writer, val uint8) error { 134 buf := l.Borrow()[:1] 135 defer l.Return(buf) 136 137 buf[0] = val 138 _, err := w.Write(buf) 139 140 return err 141 } 142 143 // PutUint16 serializes the provided uint16 using the given byte order into a 144 // buffer from the free list and writes the resulting two bytes to the given 145 // writer. 146 func (l binaryFreeList) PutUint16(w io.Writer, byteOrder binary.ByteOrder, val uint16) error { 147 buf := l.Borrow()[:2] 148 defer l.Return(buf) 149 150 byteOrder.PutUint16(buf, val) 151 _, err := w.Write(buf) 152 153 return err 154 } 155 156 // PutUint32 serializes the provided uint32 using the given byte order into a 157 // buffer from the free list and writes the resulting four bytes to the given 158 // writer. 159 func (l binaryFreeList) PutUint32(w io.Writer, byteOrder binary.ByteOrder, val uint32) error { 160 buf := l.Borrow()[:4] 161 defer l.Return(buf) 162 163 byteOrder.PutUint32(buf, val) 164 _, err := w.Write(buf) 165 166 return err 167 } 168 169 // PutUint64 serializes the provided uint64 using the given byte order into a 170 // buffer from the free list and writes the resulting eight bytes to the given 171 // writer. 172 func (l binaryFreeList) PutUint64(w io.Writer, byteOrder binary.ByteOrder, val uint64) error { 173 buf := l.Borrow()[:8] 174 defer l.Return(buf) 175 176 byteOrder.PutUint64(buf, val) 177 _, err := w.Write(buf) 178 179 return err 180 } 181 182 // binarySerializer provides a free list of buffers to use for serializing and 183 // deserializing primitive integer values to and from io.Readers and io.Writers. 184 var binarySerializer binaryFreeList = make(chan []byte, binaryFreeListMaxItems) 185 186 // errNonCanonicalVarInt is the common format string used for non-canonically 187 // encoded variable length integer errors. 188 var errNonCanonicalVarInt = "non-canonical varint %x - discriminant %x must " + 189 "encode a value greater than %x" 190 191 // uint32Time represents a unix timestamp encoded with a uint32. It is used as 192 // a way to signal the readElement function how to decode a timestamp into a Go 193 // time.Time since it is otherwise ambiguous. 194 type uint32Time time.Time 195 196 // int64Time represents a unix timestamp encoded with an int64. It is used as 197 // a way to signal the readElement function how to decode a timestamp into a Go 198 // time.Time since it is otherwise ambiguous. 199 type int64Time time.Time 200 201 // readElement reads the next sequence of bytes from r using little endian 202 // depending on the concrete type of element pointed to. 203 func readElement(r io.Reader, element interface{}) error { 204 // Attempt to read the element based on the concrete type via fast 205 // type assertions first. 206 switch e := element.(type) { 207 case *int32: 208 rv, err := binarySerializer.Uint32(r, littleEndian) 209 if err != nil { 210 return err 211 } 212 *e = int32(rv) 213 return nil 214 215 case *uint32: 216 rv, err := binarySerializer.Uint32(r, littleEndian) 217 if err != nil { 218 return err 219 } 220 *e = rv 221 return nil 222 223 case *int64: 224 rv, err := binarySerializer.Uint64(r, littleEndian) 225 if err != nil { 226 return err 227 } 228 *e = int64(rv) 229 return nil 230 231 case *uint64: 232 rv, err := binarySerializer.Uint64(r, littleEndian) 233 if err != nil { 234 return err 235 } 236 *e = rv 237 return nil 238 239 case *bool: 240 rv, err := binarySerializer.Uint8(r) 241 if err != nil { 242 return err 243 } 244 if rv == 0x00 { 245 *e = false 246 } else { 247 *e = true 248 } 249 return nil 250 251 // Unix timestamp encoded as a uint32. 252 case *uint32Time: 253 rv, err := binarySerializer.Uint32(r, binary.LittleEndian) 254 if err != nil { 255 return err 256 } 257 *e = uint32Time(time.Unix(int64(rv), 0)) 258 return nil 259 260 // Unix timestamp encoded as an int64. 261 case *int64Time: 262 rv, err := binarySerializer.Uint64(r, binary.LittleEndian) 263 if err != nil { 264 return err 265 } 266 *e = int64Time(time.Unix(int64(rv), 0)) 267 return nil 268 269 // Message header checksum. 270 case *[4]byte: 271 _, err := io.ReadFull(r, e[:]) 272 if err != nil { 273 return err 274 } 275 return nil 276 277 // Message header command. 278 case *[CommandSize]uint8: 279 _, err := io.ReadFull(r, e[:]) 280 if err != nil { 281 return err 282 } 283 return nil 284 285 // IP address. 286 case *[16]byte: 287 _, err := io.ReadFull(r, e[:]) 288 if err != nil { 289 return err 290 } 291 return nil 292 293 case *chainhash.Hash: 294 _, err := io.ReadFull(r, e[:]) 295 if err != nil { 296 return err 297 } 298 return nil 299 300 case *ServiceFlag: 301 rv, err := binarySerializer.Uint64(r, littleEndian) 302 if err != nil { 303 return err 304 } 305 *e = ServiceFlag(rv) 306 return nil 307 308 case *InvType: 309 rv, err := binarySerializer.Uint32(r, littleEndian) 310 if err != nil { 311 return err 312 } 313 *e = InvType(rv) 314 return nil 315 316 case *BitcoinNet: 317 rv, err := binarySerializer.Uint32(r, littleEndian) 318 if err != nil { 319 return err 320 } 321 *e = BitcoinNet(rv) 322 return nil 323 324 case *BloomUpdateType: 325 rv, err := binarySerializer.Uint8(r) 326 if err != nil { 327 return err 328 } 329 *e = BloomUpdateType(rv) 330 return nil 331 332 case *RejectCode: 333 rv, err := binarySerializer.Uint8(r) 334 if err != nil { 335 return err 336 } 337 *e = RejectCode(rv) 338 return nil 339 } 340 341 // Fall back to the slower binary.Read if a fast path was not available 342 // above. 343 return binary.Read(r, littleEndian, element) 344 } 345 346 // readElements reads multiple items from r. It is equivalent to multiple 347 // calls to readElement. 348 func readElements(r io.Reader, elements ...interface{}) error { 349 for _, element := range elements { 350 err := readElement(r, element) 351 if err != nil { 352 return err 353 } 354 } 355 return nil 356 } 357 358 // writeElement writes the little endian representation of element to w. 359 func writeElement(w io.Writer, element interface{}) error { 360 // Attempt to write the element based on the concrete type via fast 361 // type assertions first. 362 switch e := element.(type) { 363 case int32: 364 err := binarySerializer.PutUint32(w, littleEndian, uint32(e)) 365 if err != nil { 366 return err 367 } 368 return nil 369 370 case uint32: 371 err := binarySerializer.PutUint32(w, littleEndian, e) 372 if err != nil { 373 return err 374 } 375 return nil 376 377 case int64: 378 err := binarySerializer.PutUint64(w, littleEndian, uint64(e)) 379 if err != nil { 380 return err 381 } 382 return nil 383 384 case uint64: 385 err := binarySerializer.PutUint64(w, littleEndian, e) 386 if err != nil { 387 return err 388 } 389 return nil 390 391 case bool: 392 var err error 393 if e { 394 err = binarySerializer.PutUint8(w, 0x01) 395 } else { 396 err = binarySerializer.PutUint8(w, 0x00) 397 } 398 if err != nil { 399 return err 400 } 401 return nil 402 403 // Message header checksum. 404 case [4]byte: 405 _, err := w.Write(e[:]) 406 if err != nil { 407 return err 408 } 409 return nil 410 411 // Message header command. 412 case [CommandSize]uint8: 413 _, err := w.Write(e[:]) 414 if err != nil { 415 return err 416 } 417 return nil 418 419 // IP address. 420 case [16]byte: 421 _, err := w.Write(e[:]) 422 if err != nil { 423 return err 424 } 425 return nil 426 427 case *chainhash.Hash: 428 _, err := w.Write(e[:]) 429 if err != nil { 430 return err 431 } 432 return nil 433 434 case ServiceFlag: 435 err := binarySerializer.PutUint64(w, littleEndian, uint64(e)) 436 if err != nil { 437 return err 438 } 439 return nil 440 441 case InvType: 442 err := binarySerializer.PutUint32(w, littleEndian, uint32(e)) 443 if err != nil { 444 return err 445 } 446 return nil 447 448 case BitcoinNet: 449 err := binarySerializer.PutUint32(w, littleEndian, uint32(e)) 450 if err != nil { 451 return err 452 } 453 return nil 454 455 case BloomUpdateType: 456 err := binarySerializer.PutUint8(w, uint8(e)) 457 if err != nil { 458 return err 459 } 460 return nil 461 462 case RejectCode: 463 err := binarySerializer.PutUint8(w, uint8(e)) 464 if err != nil { 465 return err 466 } 467 return nil 468 } 469 470 // Fall back to the slower binary.Write if a fast path was not available 471 // above. 472 return binary.Write(w, littleEndian, element) 473 } 474 475 // writeElements writes multiple items to w. It is equivalent to multiple 476 // calls to writeElement. 477 func writeElements(w io.Writer, elements ...interface{}) error { 478 for _, element := range elements { 479 err := writeElement(w, element) 480 if err != nil { 481 return err 482 } 483 } 484 return nil 485 } 486 487 // ReadVarInt reads a variable length integer from r and returns it as a uint64. 488 func ReadVarInt(r io.Reader, pver uint32) (uint64, error) { 489 buf := binarySerializer.Borrow() 490 defer binarySerializer.Return(buf) 491 492 n, err := ReadVarIntBuf(r, pver, buf) 493 return n, err 494 } 495 496 // ReadVarIntBuf reads a variable length integer from r using a preallocated 497 // scratch buffer and returns it as a uint64. 498 // 499 // NOTE: buf MUST at least an 8-byte slice. 500 func ReadVarIntBuf(r io.Reader, pver uint32, buf []byte) (uint64, error) { 501 if _, err := io.ReadFull(r, buf[:1]); err != nil { 502 return 0, err 503 } 504 discriminant := buf[0] 505 506 var rv uint64 507 switch discriminant { 508 case 0xff: 509 if _, err := io.ReadFull(r, buf); err != nil { 510 return 0, err 511 } 512 rv = littleEndian.Uint64(buf) 513 514 // The encoding is not canonical if the value could have been 515 // encoded using fewer bytes. 516 min := uint64(0x100000000) 517 if rv < min { 518 return 0, messageError("ReadVarInt", fmt.Sprintf( 519 errNonCanonicalVarInt, rv, discriminant, min)) 520 } 521 522 case 0xfe: 523 if _, err := io.ReadFull(r, buf[:4]); err != nil { 524 return 0, err 525 } 526 rv = uint64(littleEndian.Uint32(buf[:4])) 527 528 // The encoding is not canonical if the value could have been 529 // encoded using fewer bytes. 530 min := uint64(0x10000) 531 if rv < min { 532 return 0, messageError("ReadVarInt", fmt.Sprintf( 533 errNonCanonicalVarInt, rv, discriminant, min)) 534 } 535 536 case 0xfd: 537 if _, err := io.ReadFull(r, buf[:2]); err != nil { 538 return 0, err 539 } 540 rv = uint64(littleEndian.Uint16(buf[:2])) 541 542 // The encoding is not canonical if the value could have been 543 // encoded using fewer bytes. 544 min := uint64(0xfd) 545 if rv < min { 546 return 0, messageError("ReadVarInt", fmt.Sprintf( 547 errNonCanonicalVarInt, rv, discriminant, min)) 548 } 549 550 default: 551 rv = uint64(discriminant) 552 } 553 554 return rv, nil 555 } 556 557 // WriteVarInt serializes val to w using a variable number of bytes depending 558 // on its value. 559 func WriteVarInt(w io.Writer, pver uint32, val uint64) error { 560 buf := binarySerializer.Borrow() 561 defer binarySerializer.Return(buf) 562 563 err := WriteVarIntBuf(w, pver, val, buf) 564 return err 565 } 566 567 // WriteVarIntBuf serializes val to w using a variable number of bytes depending 568 // on its value using a preallocated scratch buffer. 569 // 570 // NOTE: buf MUST at least an 8-byte slice. 571 func WriteVarIntBuf(w io.Writer, pver uint32, val uint64, buf []byte) error { 572 switch { 573 case val < 0xfd: 574 buf[0] = uint8(val) 575 _, err := w.Write(buf[:1]) 576 return err 577 578 case val <= math.MaxUint16: 579 buf[0] = 0xfd 580 littleEndian.PutUint16(buf[1:3], uint16(val)) 581 _, err := w.Write(buf[:3]) 582 return err 583 584 case val <= math.MaxUint32: 585 buf[0] = 0xfe 586 littleEndian.PutUint32(buf[1:5], uint32(val)) 587 _, err := w.Write(buf[:5]) 588 return err 589 590 default: 591 buf[0] = 0xff 592 if _, err := w.Write(buf[:1]); err != nil { 593 return err 594 } 595 596 littleEndian.PutUint64(buf, val) 597 _, err := w.Write(buf) 598 return err 599 } 600 } 601 602 // VarIntSerializeSize returns the number of bytes it would take to serialize 603 // val as a variable length integer. 604 func VarIntSerializeSize(val uint64) int { 605 // The value is small enough to be represented by itself, so it's 606 // just 1 byte. 607 if val < 0xfd { 608 return 1 609 } 610 611 // Discriminant 1 byte plus 2 bytes for the uint16. 612 if val <= math.MaxUint16 { 613 return 3 614 } 615 616 // Discriminant 1 byte plus 4 bytes for the uint32. 617 if val <= math.MaxUint32 { 618 return 5 619 } 620 621 // Discriminant 1 byte plus 8 bytes for the uint64. 622 return 9 623 } 624 625 // ReadVarString reads a variable length string from r and returns it as a Go 626 // string. A variable length string is encoded as a variable length integer 627 // containing the length of the string followed by the bytes that represent the 628 // string itself. An error is returned if the length is greater than the 629 // maximum block payload size since it helps protect against memory exhaustion 630 // attacks and forced panics through malformed messages. 631 func ReadVarString(r io.Reader, pver uint32) (string, error) { 632 buf := binarySerializer.Borrow() 633 defer binarySerializer.Return(buf) 634 635 str, err := readVarStringBuf(r, pver, buf) 636 return str, err 637 } 638 639 // readVarStringBuf reads a variable length string from r and returns it as a Go 640 // string. A variable length string is encoded as a variable length integer 641 // containing the length of the string followed by the bytes that represent the 642 // string itself. An error is returned if the length is greater than the 643 // maximum block payload size since it helps protect against memory exhaustion 644 // attacks and forced panics through malformed messages. 645 // 646 // If b is non-nil, the provided buffer will be used for serializing small 647 // values. Otherwise a buffer will be drawn from the binarySerializer's pool 648 // and return when the method finishes. 649 // 650 // NOTE: b MUST either be nil or at least an 8-byte slice. 651 func readVarStringBuf(r io.Reader, pver uint32, buf []byte) (string, error) { 652 count, err := ReadVarIntBuf(r, pver, buf) 653 if err != nil { 654 return "", err 655 } 656 657 // Prevent variable length strings that are larger than the maximum 658 // message size. It would be possible to cause memory exhaustion and 659 // panics without a sane upper bound on this count. 660 if count > MaxMessagePayload { 661 str := fmt.Sprintf("variable length string is too long "+ 662 "[count %d, max %d]", count, MaxMessagePayload) 663 return "", messageError("ReadVarString", str) 664 } 665 666 str := make([]byte, count) 667 _, err = io.ReadFull(r, str) 668 if err != nil { 669 return "", err 670 } 671 return string(str), nil 672 } 673 674 // WriteVarString serializes str to w as a variable length integer containing 675 // the length of the string followed by the bytes that represent the string 676 // itself. 677 func WriteVarString(w io.Writer, pver uint32, str string) error { 678 buf := binarySerializer.Borrow() 679 defer binarySerializer.Return(buf) 680 681 err := writeVarStringBuf(w, pver, str, buf) 682 return err 683 } 684 685 // writeVarStringBuf serializes str to w as a variable length integer containing 686 // the length of the string followed by the bytes that represent the string 687 // itself. 688 // 689 // If b is non-nil, the provided buffer will be used for serializing small 690 // values. Otherwise a buffer will be drawn from the binarySerializer's pool 691 // and return when the method finishes. 692 // 693 // NOTE: b MUST either be nil or at least an 8-byte slice. 694 func writeVarStringBuf(w io.Writer, pver uint32, str string, buf []byte) error { 695 err := WriteVarIntBuf(w, pver, uint64(len(str)), buf) 696 if err != nil { 697 return err 698 } 699 700 _, err = w.Write([]byte(str)) 701 return err 702 } 703 704 // ReadVarBytes reads a variable length byte array. A byte array is encoded 705 // as a varInt containing the length of the array followed by the bytes 706 // themselves. An error is returned if the length is greater than the 707 // passed maxAllowed parameter which helps protect against memory exhaustion 708 // attacks and forced panics through malformed messages. The fieldName 709 // parameter is only used for the error message so it provides more context in 710 // the error. 711 func ReadVarBytes(r io.Reader, pver uint32, maxAllowed uint32, 712 fieldName string) ([]byte, error) { 713 714 buf := binarySerializer.Borrow() 715 defer binarySerializer.Return(buf) 716 717 b, err := ReadVarBytesBuf(r, pver, buf, maxAllowed, fieldName) 718 return b, err 719 } 720 721 // ReadVarBytesBuf reads a variable length byte array. A byte array is encoded 722 // as a varInt containing the length of the array followed by the bytes 723 // themselves. An error is returned if the length is greater than the 724 // passed maxAllowed parameter which helps protect against memory exhaustion 725 // attacks and forced panics through malformed messages. The fieldName 726 // parameter is only used for the error message so it provides more context in 727 // the error. If b is non-nil, the provided buffer will be used for serializing 728 // small values. Otherwise a buffer will be drawn from the binarySerializer's 729 // pool and return when the method finishes. 730 func ReadVarBytesBuf(r io.Reader, pver uint32, buf []byte, maxAllowed uint32, 731 fieldName string) ([]byte, error) { 732 733 count, err := ReadVarIntBuf(r, pver, buf) 734 if err != nil { 735 return nil, err 736 } 737 738 // Prevent byte array larger than the max message size. It would 739 // be possible to cause memory exhaustion and panics without a sane 740 // upper bound on this count. 741 if count > uint64(maxAllowed) { 742 str := fmt.Sprintf("%s is larger than the max allowed size "+ 743 "[count %d, max %d]", fieldName, count, maxAllowed) 744 return nil, messageError("ReadVarBytes", str) 745 } 746 747 bytes := make([]byte, count) 748 _, err = io.ReadFull(r, bytes) 749 if err != nil { 750 return nil, err 751 } 752 return bytes, nil 753 } 754 755 // WriteVarBytes serializes a variable length byte array to w as a varInt 756 // containing the number of bytes, followed by the bytes themselves. 757 func WriteVarBytes(w io.Writer, pver uint32, bytes []byte) error { 758 buf := binarySerializer.Borrow() 759 defer binarySerializer.Return(buf) 760 761 err := WriteVarBytesBuf(w, pver, bytes, buf) 762 return err 763 } 764 765 // WriteVarBytesBuf serializes a variable length byte array to w as a varInt 766 // containing the number of bytes, followed by the bytes themselves. If b is 767 // non-nil, the provided buffer will be used for serializing small values. 768 // Otherwise a buffer will be drawn from the binarySerializer's pool and return 769 // when the method finishes. 770 func WriteVarBytesBuf(w io.Writer, pver uint32, bytes, buf []byte) error { 771 slen := uint64(len(bytes)) 772 773 err := WriteVarIntBuf(w, pver, slen, buf) 774 if err != nil { 775 return err 776 } 777 778 _, err = w.Write(bytes) 779 return err 780 } 781 782 // randomUint64 returns a cryptographically random uint64 value. This 783 // unexported version takes a reader primarily to ensure the error paths 784 // can be properly tested by passing a fake reader in the tests. 785 func randomUint64(r io.Reader) (uint64, error) { 786 rv, err := binarySerializer.Uint64(r, bigEndian) 787 if err != nil { 788 return 0, err 789 } 790 return rv, nil 791 } 792 793 // RandomUint64 returns a cryptographically random uint64 value. 794 func RandomUint64() (uint64, error) { 795 return randomUint64(rand.Reader) 796 }