github.com/decred/dcrlnd@v0.7.6/lnwire/writer.go (about)

     1  package lnwire
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"errors"
     7  	"fmt"
     8  	"image/color"
     9  	"math"
    10  	"net"
    11  
    12  	"github.com/decred/dcrd/dcrec/secp256k1/v4"
    13  	"github.com/decred/dcrd/dcrutil/v4"
    14  	"github.com/decred/dcrd/wire"
    15  	"github.com/decred/dcrlnd/tor"
    16  )
    17  
    18  var (
    19  	// ErrNilFeatureVector is returned when the supplied feature is nil.
    20  	ErrNilFeatureVector = errors.New("cannot write nil feature vector")
    21  
    22  	// ErrPkScriptTooLong is returned when the length of the provided
    23  	// script exceeds 34.
    24  	ErrPkScriptTooLong = errors.New("'PkScript' too long")
    25  
    26  	// ErrNilTCPAddress is returned when the supplied address is nil.
    27  	ErrNilTCPAddress = errors.New("cannot write nil TCPAddr")
    28  
    29  	// ErrNilOnionAddress is returned when the supplied address is nil.
    30  	ErrNilOnionAddress = errors.New("cannot write nil onion address")
    31  
    32  	// ErrNilNetAddress is returned when a nil value is used in []net.Addr.
    33  	ErrNilNetAddress = errors.New("cannot write nil address")
    34  
    35  	// ErrNilPublicKey is returned when a nil pubkey is used.
    36  	ErrNilPublicKey = errors.New("cannot write nil pubkey")
    37  
    38  	// ErrUnknownServiceLength is returned when the onion service length is
    39  	// unknown.
    40  	ErrUnknownServiceLength = errors.New("unknown onion service length")
    41  )
    42  
    43  // ErrOutpointIndexTooBig is used when the outpoint index exceeds the max value
    44  // of uint16.
    45  func ErrOutpointIndexTooBig(index uint32) error {
    46  	return fmt.Errorf(
    47  		"index for outpoint (%v) is greater than "+
    48  			"max index of %v", index, math.MaxUint16,
    49  	)
    50  }
    51  
    52  // WriteBytes appends the given bytes to the provided buffer.
    53  //
    54  // Note: We intentionally skip the interfacer linter check here because we want
    55  // to have concrete type (bytes.Buffer) rather than interface type (io.Write)
    56  // due to performance concern.
    57  func WriteBytes(buf *bytes.Buffer, b []byte) error { // nolint: interfacer
    58  	_, err := buf.Write(b)
    59  	return err
    60  }
    61  
    62  // WriteUint8 appends the uint8 to the provided buffer.
    63  //
    64  // Note: We intentionally skip the interfacer linter check here because we want
    65  // to have concrete type (bytes.Buffer) rather than interface type (io.Write)
    66  // due to performance concern.
    67  func WriteUint8(buf *bytes.Buffer, n uint8) error { // nolint: interfacer
    68  	_, err := buf.Write([]byte{n})
    69  	return err
    70  }
    71  
    72  // WriteUint16 appends the uint16 to the provided buffer. It encodes the
    73  // integer using big endian byte order.
    74  //
    75  // Note: We intentionally skip the interfacer linter check here because we want
    76  // to have concrete type (bytes.Buffer) rather than interface type (io.Write)
    77  // due to performance concern.
    78  func WriteUint16(buf *bytes.Buffer, n uint16) error { // nolint: interfacer
    79  	var b [2]byte
    80  	binary.BigEndian.PutUint16(b[:], n)
    81  	_, err := buf.Write(b[:])
    82  	return err
    83  }
    84  
    85  // WriteUint32 appends the uint32 to the provided buffer. It encodes the
    86  // integer using big endian byte order.
    87  func WriteUint32(buf *bytes.Buffer, n uint32) error {
    88  	var b [4]byte
    89  	binary.BigEndian.PutUint32(b[:], n)
    90  	_, err := buf.Write(b[:])
    91  	return err
    92  }
    93  
    94  // WriteUint64 appends the uint64 to the provided buffer. It encodes the
    95  // integer using big endian byte order.
    96  //
    97  // Note: We intentionally skip the interfacer linter check here because we want
    98  // to have concrete type (bytes.Buffer) rather than interface type (io.Write)
    99  // due to performance concern.
   100  func WriteUint64(buf *bytes.Buffer, n uint64) error { // nolint: interfacer
   101  	var b [8]byte
   102  	binary.BigEndian.PutUint64(b[:], n)
   103  	_, err := buf.Write(b[:])
   104  	return err
   105  }
   106  
   107  // WriteSatoshi appends the Satoshi value to the provided buffer.
   108  func WriteSatoshi(buf *bytes.Buffer, amount dcrutil.Amount) error {
   109  	return WriteUint64(buf, uint64(amount))
   110  }
   111  
   112  // WriteMilliAtom appends the MilliAtom value to the provided buffer.
   113  func WriteMilliAtom(buf *bytes.Buffer, amount MilliAtom) error {
   114  	return WriteUint64(buf, uint64(amount))
   115  }
   116  
   117  // WritePublicKey appends the compressed public key to the provided buffer.
   118  func WritePublicKey(buf *bytes.Buffer, pub *secp256k1.PublicKey) error {
   119  	if pub == nil {
   120  		return ErrNilPublicKey
   121  	}
   122  
   123  	serializedPubkey := pub.SerializeCompressed()
   124  	return WriteBytes(buf, serializedPubkey)
   125  
   126  }
   127  
   128  // WriteChannelID appends the ChannelID to the provided buffer.
   129  func WriteChannelID(buf *bytes.Buffer, channelID ChannelID) error {
   130  	return WriteBytes(buf, channelID[:])
   131  }
   132  
   133  // WriteNodeAlias appends the alias to the provided buffer.
   134  func WriteNodeAlias(buf *bytes.Buffer, alias NodeAlias) error {
   135  	return WriteBytes(buf, alias[:])
   136  }
   137  
   138  // WriteShortChannelID appends the ShortChannelID to the provided buffer. It
   139  // encodes the BlockHeight and TxIndex each using 3 bytes with big endian byte
   140  // order, and encodes txPosition using 2 bytes with big endian byte order.
   141  func WriteShortChannelID(buf *bytes.Buffer, shortChanID ShortChannelID) error {
   142  	// Check that field fit in 3 bytes and write the blockHeight
   143  	if shortChanID.BlockHeight > ((1 << 24) - 1) {
   144  		return errors.New("block height should fit in 3 bytes")
   145  	}
   146  
   147  	var blockHeight [4]byte
   148  	binary.BigEndian.PutUint32(blockHeight[:], shortChanID.BlockHeight)
   149  
   150  	if _, err := buf.Write(blockHeight[1:]); err != nil {
   151  		return err
   152  	}
   153  
   154  	// Check that field fit in 3 bytes and write the txIndex
   155  	if shortChanID.TxIndex > ((1 << 24) - 1) {
   156  		return errors.New("tx index should fit in 3 bytes")
   157  	}
   158  
   159  	var txIndex [4]byte
   160  	binary.BigEndian.PutUint32(txIndex[:], shortChanID.TxIndex)
   161  	if _, err := buf.Write(txIndex[1:]); err != nil {
   162  		return err
   163  	}
   164  
   165  	// Write the TxPosition
   166  	return WriteUint16(buf, shortChanID.TxPosition)
   167  }
   168  
   169  // WriteSig appends the signature to the provided buffer.
   170  func WriteSig(buf *bytes.Buffer, sig Sig) error {
   171  	return WriteBytes(buf, sig[:])
   172  }
   173  
   174  // WriteSigs appends the slice of signatures to the provided buffer with its
   175  // length.
   176  func WriteSigs(buf *bytes.Buffer, sigs []Sig) error {
   177  	// Write the length of the sigs.
   178  	if err := WriteUint16(buf, uint16(len(sigs))); err != nil {
   179  		return err
   180  	}
   181  
   182  	for _, sig := range sigs {
   183  		if err := WriteSig(buf, sig); err != nil {
   184  			return err
   185  		}
   186  	}
   187  	return nil
   188  }
   189  
   190  // WriteFailCode appends the FailCode to the provided buffer.
   191  func WriteFailCode(buf *bytes.Buffer, e FailCode) error {
   192  	return WriteUint16(buf, uint16(e))
   193  }
   194  
   195  // WriteRawFeatureVector encodes the feature using the feature's Encode method
   196  // and appends the data to the provided buffer. An error will return if the
   197  // passed feature is nil.
   198  //
   199  // Note: We intentionally skip the interfacer linter check here because we want
   200  // to have concrete type (bytes.Buffer) rather than interface type (io.Write)
   201  // due to performance concern.
   202  func WriteRawFeatureVector(buf *bytes.Buffer, // nolint: interfacer
   203  	feature *RawFeatureVector) error {
   204  
   205  	if feature == nil {
   206  		return ErrNilFeatureVector
   207  	}
   208  
   209  	return feature.Encode(buf)
   210  }
   211  
   212  // WriteColorRGBA appends the RGBA color using three bytes.
   213  func WriteColorRGBA(buf *bytes.Buffer, e color.RGBA) error {
   214  	// Write R
   215  	if err := WriteUint8(buf, e.R); err != nil {
   216  		return err
   217  	}
   218  
   219  	// Write G
   220  	if err := WriteUint8(buf, e.G); err != nil {
   221  		return err
   222  	}
   223  
   224  	// Write B
   225  	return WriteUint8(buf, e.B)
   226  }
   227  
   228  // WriteShortChanIDEncoding appends the ShortChanIDEncoding to the provided
   229  // buffer.
   230  func WriteShortChanIDEncoding(buf *bytes.Buffer, e ShortChanIDEncoding) error {
   231  	return WriteUint8(buf, uint8(e))
   232  }
   233  
   234  // WriteFundingFlag appends the FundingFlag to the provided buffer.
   235  func WriteFundingFlag(buf *bytes.Buffer, flag FundingFlag) error {
   236  	return WriteUint8(buf, uint8(flag))
   237  }
   238  
   239  // WriteChanUpdateMsgFlags appends the update flag to the provided buffer.
   240  func WriteChanUpdateMsgFlags(buf *bytes.Buffer, f ChanUpdateMsgFlags) error {
   241  	return WriteUint8(buf, uint8(f))
   242  }
   243  
   244  // WriteChanUpdateChanFlags appends the update flag to the provided buffer.
   245  func WriteChanUpdateChanFlags(buf *bytes.Buffer, f ChanUpdateChanFlags) error {
   246  	return WriteUint8(buf, uint8(f))
   247  }
   248  
   249  // WriteDeliveryAddress appends the address to the provided buffer.
   250  func WriteDeliveryAddress(buf *bytes.Buffer, addr DeliveryAddress) error {
   251  	return writeDataWithLength(buf, addr)
   252  }
   253  
   254  // WritePingPayload appends the payload to the provided buffer.
   255  func WritePingPayload(buf *bytes.Buffer, payload PingPayload) error {
   256  	return writeDataWithLength(buf, payload)
   257  }
   258  
   259  // WritePongPayload appends the payload to the provided buffer.
   260  func WritePongPayload(buf *bytes.Buffer, payload PongPayload) error {
   261  	return writeDataWithLength(buf, payload)
   262  }
   263  
   264  // WriteErrorData appends the data to the provided buffer.
   265  func WriteErrorData(buf *bytes.Buffer, data ErrorData) error {
   266  	return writeDataWithLength(buf, data)
   267  }
   268  
   269  // WriteOpaqueReason appends the reason to the provided buffer.
   270  func WriteOpaqueReason(buf *bytes.Buffer, reason OpaqueReason) error {
   271  	return writeDataWithLength(buf, reason)
   272  }
   273  
   274  // WriteBool appends the boolean to the provided buffer.
   275  func WriteBool(buf *bytes.Buffer, b bool) error {
   276  	if b {
   277  		return WriteBytes(buf, []byte{1})
   278  	}
   279  	return WriteBytes(buf, []byte{0})
   280  }
   281  
   282  // WritePkScript appends the script to the provided buffer. Returns an error if
   283  // the provided script exceeds 34 bytes.
   284  //
   285  // Note: We intentionally skip the interfacer linter check here because we want
   286  // to have concrete type (bytes.Buffer) rather than interface type (io.Write)
   287  // due to performance concern.
   288  func WritePkScript(buf *bytes.Buffer, s PkScript) error { // nolint: interfacer
   289  	// The largest script we'll accept is a p2wsh which is exactly
   290  	// 34 bytes long.
   291  	scriptLength := len(s)
   292  	if scriptLength > 34 {
   293  		return ErrPkScriptTooLong
   294  	}
   295  
   296  	return wire.WriteVarBytes(buf, 0, s)
   297  }
   298  
   299  // WriteOutPoint appends the outpoint to the provided buffer.
   300  func WriteOutPoint(buf *bytes.Buffer, p wire.OutPoint) error {
   301  	// Before we write anything to the buffer, check the Index is sane.
   302  	if p.Index > math.MaxUint16 {
   303  		return ErrOutpointIndexTooBig(p.Index)
   304  	}
   305  
   306  	var h [32]byte
   307  	copy(h[:], p.Hash[:])
   308  	if _, err := buf.Write(h[:]); err != nil {
   309  		return err
   310  	}
   311  
   312  	// Write the index using two bytes.
   313  	return WriteUint16(buf, uint16(p.Index))
   314  }
   315  
   316  // WriteTCPAddr appends the TCP address to the provided buffer, either a IPv4
   317  // or a IPv6.
   318  func WriteTCPAddr(buf *bytes.Buffer, addr *net.TCPAddr) error {
   319  	if addr == nil {
   320  		return ErrNilTCPAddress
   321  	}
   322  
   323  	// Make a slice of bytes to hold the data of descriptor and ip. At
   324  	// most, we need 17 bytes - 1 byte for the descriptor, 16 bytes for
   325  	// IPv6.
   326  	data := make([]byte, 0, 17)
   327  
   328  	if addr.IP.To4() != nil {
   329  		data = append(data, uint8(tcp4Addr))
   330  		data = append(data, addr.IP.To4()...)
   331  	} else {
   332  		data = append(data, uint8(tcp6Addr))
   333  		data = append(data, addr.IP.To16()...)
   334  	}
   335  
   336  	if _, err := buf.Write(data); err != nil {
   337  		return err
   338  	}
   339  
   340  	return WriteUint16(buf, uint16(addr.Port))
   341  }
   342  
   343  // WriteOnionAddr appends the onion address to the provided buffer.
   344  func WriteOnionAddr(buf *bytes.Buffer, addr *tor.OnionAddr) error {
   345  	if addr == nil {
   346  		return ErrNilOnionAddress
   347  	}
   348  
   349  	var (
   350  		suffixIndex int
   351  		descriptor  []byte
   352  	)
   353  
   354  	// Decide the suffixIndex and descriptor.
   355  	switch len(addr.OnionService) {
   356  	case tor.V2Len:
   357  		descriptor = []byte{byte(v2OnionAddr)}
   358  		suffixIndex = tor.V2Len - tor.OnionSuffixLen
   359  
   360  	case tor.V3Len:
   361  		descriptor = []byte{byte(v3OnionAddr)}
   362  		suffixIndex = tor.V3Len - tor.OnionSuffixLen
   363  
   364  	default:
   365  		return ErrUnknownServiceLength
   366  	}
   367  
   368  	// Decode the address.
   369  	host, err := tor.Base32Encoding.DecodeString(
   370  		addr.OnionService[:suffixIndex],
   371  	)
   372  	if err != nil {
   373  		return err
   374  	}
   375  
   376  	// Perform the actual write when the above checks passed.
   377  	if _, err := buf.Write(descriptor); err != nil {
   378  		return err
   379  	}
   380  	if _, err := buf.Write(host); err != nil {
   381  		return err
   382  	}
   383  
   384  	return WriteUint16(buf, uint16(addr.Port))
   385  }
   386  
   387  // WriteNetAddrs appends a slice of addresses to the provided buffer with the
   388  // length info.
   389  func WriteNetAddrs(buf *bytes.Buffer, addresses []net.Addr) error {
   390  	// First, we'll encode all the addresses into an intermediate
   391  	// buffer. We need to do this in order to compute the total
   392  	// length of the addresses.
   393  	buffer := make([]byte, 0, MaxMsgBody)
   394  	addrBuf := bytes.NewBuffer(buffer)
   395  
   396  	for _, address := range addresses {
   397  		switch a := address.(type) {
   398  		case *net.TCPAddr:
   399  			if err := WriteTCPAddr(addrBuf, a); err != nil {
   400  				return err
   401  			}
   402  		case *tor.OnionAddr:
   403  			if err := WriteOnionAddr(addrBuf, a); err != nil {
   404  				return err
   405  			}
   406  		default:
   407  			return ErrNilNetAddress
   408  		}
   409  	}
   410  
   411  	// With the addresses fully encoded, we can now write out data.
   412  	return writeDataWithLength(buf, addrBuf.Bytes())
   413  }
   414  
   415  // writeDataWithLength writes the data and its length to the buffer.
   416  //
   417  // Note: We intentionally skip the interfacer linter check here because we want
   418  // to have concrete type (bytes.Buffer) rather than interface type (io.Write)
   419  // due to performance concern.
   420  func writeDataWithLength(buf *bytes.Buffer, // nolint: interfacer
   421  	data []byte) error {
   422  
   423  	var l [2]byte
   424  	binary.BigEndian.PutUint16(l[:], uint16(len(data)))
   425  	if _, err := buf.Write(l[:]); err != nil {
   426  		return err
   427  	}
   428  
   429  	_, err := buf.Write(data)
   430  	return err
   431  }