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  }