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