github.com/decred/dcrlnd@v0.7.6/watchtower/wtwire/wtwire.go (about)

     1  package wtwire
     2  
     3  import (
     4  	"encoding/binary"
     5  	"fmt"
     6  	"io"
     7  
     8  	"github.com/decred/dcrd/chaincfg/chainhash"
     9  	"github.com/decred/dcrd/dcrec/secp256k1/v4"
    10  	"github.com/decred/dcrd/wire"
    11  	"github.com/decred/dcrlnd/lnwallet/chainfee"
    12  	"github.com/decred/dcrlnd/lnwire"
    13  	"github.com/decred/dcrlnd/watchtower/blob"
    14  )
    15  
    16  // WriteElement is a one-stop shop to write the big endian representation of
    17  // any element which is to be serialized for the wire protocol. The passed
    18  // io.Writer should be backed by an appropriately sized byte slice, or be able
    19  // to dynamically expand to accommodate additional data.
    20  func WriteElement(w io.Writer, element interface{}) error {
    21  	switch e := element.(type) {
    22  	case uint8:
    23  		var b [1]byte
    24  		b[0] = e
    25  		if _, err := w.Write(b[:]); err != nil {
    26  			return err
    27  		}
    28  
    29  	case uint16:
    30  		var b [2]byte
    31  		binary.BigEndian.PutUint16(b[:], e)
    32  		if _, err := w.Write(b[:]); err != nil {
    33  			return err
    34  		}
    35  
    36  	case blob.Type:
    37  		var b [2]byte
    38  		binary.BigEndian.PutUint16(b[:], uint16(e))
    39  		if _, err := w.Write(b[:]); err != nil {
    40  			return err
    41  		}
    42  
    43  	case uint32:
    44  		var b [4]byte
    45  		binary.BigEndian.PutUint32(b[:], e)
    46  		if _, err := w.Write(b[:]); err != nil {
    47  			return err
    48  		}
    49  
    50  	case uint64:
    51  		var b [8]byte
    52  		binary.BigEndian.PutUint64(b[:], e)
    53  		if _, err := w.Write(b[:]); err != nil {
    54  			return err
    55  		}
    56  
    57  	case [16]byte:
    58  		if _, err := w.Write(e[:]); err != nil {
    59  			return err
    60  		}
    61  
    62  	case [32]byte:
    63  		if _, err := w.Write(e[:]); err != nil {
    64  			return err
    65  		}
    66  
    67  	case [33]byte:
    68  		if _, err := w.Write(e[:]); err != nil {
    69  			return err
    70  		}
    71  
    72  	case []byte:
    73  		if err := wire.WriteVarBytes(w, 0, e); err != nil {
    74  			return err
    75  		}
    76  
    77  	case chainfee.AtomPerKByte:
    78  		var b [8]byte
    79  		binary.BigEndian.PutUint64(b[:], uint64(e))
    80  		if _, err := w.Write(b[:]); err != nil {
    81  			return err
    82  		}
    83  
    84  	case ErrorCode:
    85  		var b [2]byte
    86  		binary.BigEndian.PutUint16(b[:], uint16(e))
    87  		if _, err := w.Write(b[:]); err != nil {
    88  			return err
    89  		}
    90  
    91  	case chainhash.Hash:
    92  		if _, err := w.Write(e[:]); err != nil {
    93  			return err
    94  		}
    95  
    96  	case *lnwire.RawFeatureVector:
    97  		if e == nil {
    98  			return fmt.Errorf("cannot write nil feature vector")
    99  		}
   100  
   101  		if err := e.Encode(w); err != nil {
   102  			return err
   103  		}
   104  
   105  	case *secp256k1.PublicKey:
   106  		if e == nil {
   107  			return fmt.Errorf("cannot write nil pubkey")
   108  		}
   109  
   110  		var b [33]byte
   111  		serializedPubkey := e.SerializeCompressed()
   112  		copy(b[:], serializedPubkey)
   113  		if _, err := w.Write(b[:]); err != nil {
   114  			return err
   115  		}
   116  
   117  	default:
   118  		return fmt.Errorf("unknown type in WriteElement: %T", e)
   119  	}
   120  
   121  	return nil
   122  }
   123  
   124  // WriteElements is writes each element in the elements slice to the passed
   125  // io.Writer using WriteElement.
   126  func WriteElements(w io.Writer, elements ...interface{}) error {
   127  	for _, element := range elements {
   128  		err := WriteElement(w, element)
   129  		if err != nil {
   130  			return err
   131  		}
   132  	}
   133  	return nil
   134  }
   135  
   136  // ReadElement is a one-stop utility function to deserialize any datastructure
   137  // encoded using the serialization format of lnwire.
   138  func ReadElement(r io.Reader, element interface{}) error {
   139  	switch e := element.(type) {
   140  	case *uint8:
   141  		var b [1]uint8
   142  		if _, err := r.Read(b[:]); err != nil {
   143  			return err
   144  		}
   145  		*e = b[0]
   146  
   147  	case *uint16:
   148  		var b [2]byte
   149  		if _, err := io.ReadFull(r, b[:]); err != nil {
   150  			return err
   151  		}
   152  		*e = binary.BigEndian.Uint16(b[:])
   153  
   154  	case *blob.Type:
   155  		var b [2]byte
   156  		if _, err := io.ReadFull(r, b[:]); err != nil {
   157  			return err
   158  		}
   159  		*e = blob.Type(binary.BigEndian.Uint16(b[:]))
   160  
   161  	case *uint32:
   162  		var b [4]byte
   163  		if _, err := io.ReadFull(r, b[:]); err != nil {
   164  			return err
   165  		}
   166  		*e = binary.BigEndian.Uint32(b[:])
   167  
   168  	case *uint64:
   169  		var b [8]byte
   170  		if _, err := io.ReadFull(r, b[:]); err != nil {
   171  			return err
   172  		}
   173  		*e = binary.BigEndian.Uint64(b[:])
   174  
   175  	case *[16]byte:
   176  		if _, err := io.ReadFull(r, e[:]); err != nil {
   177  			return err
   178  		}
   179  
   180  	case *[32]byte:
   181  		if _, err := io.ReadFull(r, e[:]); err != nil {
   182  			return err
   183  		}
   184  
   185  	case *[33]byte:
   186  		if _, err := io.ReadFull(r, e[:]); err != nil {
   187  			return err
   188  		}
   189  
   190  	case *[]byte:
   191  		bytes, err := wire.ReadVarBytes(r, 0, 66000, "[]byte")
   192  		if err != nil {
   193  			return err
   194  		}
   195  		*e = bytes
   196  
   197  	case *chainfee.AtomPerKByte:
   198  		var b [8]byte
   199  		if _, err := io.ReadFull(r, b[:]); err != nil {
   200  			return err
   201  		}
   202  		*e = chainfee.AtomPerKByte(binary.BigEndian.Uint64(b[:]))
   203  
   204  	case *ErrorCode:
   205  		var b [2]byte
   206  		if _, err := io.ReadFull(r, b[:]); err != nil {
   207  			return err
   208  		}
   209  		*e = ErrorCode(binary.BigEndian.Uint16(b[:]))
   210  
   211  	case *chainhash.Hash:
   212  		if _, err := io.ReadFull(r, e[:]); err != nil {
   213  			return err
   214  		}
   215  
   216  	case **lnwire.RawFeatureVector:
   217  		f := lnwire.NewRawFeatureVector()
   218  		err := f.Decode(r)
   219  		if err != nil {
   220  			return err
   221  		}
   222  
   223  		*e = f
   224  
   225  	case **secp256k1.PublicKey:
   226  		var b [secp256k1.PubKeyBytesLenCompressed]byte
   227  
   228  		if _, err := io.ReadFull(r, b[:]); err != nil {
   229  			return err
   230  		}
   231  
   232  		pubKey, err := secp256k1.ParsePubKey(b[:])
   233  		if err != nil {
   234  			return err
   235  		}
   236  		*e = pubKey
   237  
   238  	default:
   239  		return fmt.Errorf("unknown type in ReadElement: %T", e)
   240  	}
   241  
   242  	return nil
   243  }
   244  
   245  // ReadElements deserializes a variable number of elements into the passed
   246  // io.Reader, with each element being deserialized according to the ReadElement
   247  // function.
   248  func ReadElements(r io.Reader, elements ...interface{}) error {
   249  	for _, element := range elements {
   250  		err := ReadElement(r, element)
   251  		if err != nil {
   252  			return err
   253  		}
   254  	}
   255  	return nil
   256  }