2015-12-23 11:08:34 +03:00
|
|
|
package lnwire
|
|
|
|
|
|
|
|
import (
|
2015-12-30 16:38:57 +03:00
|
|
|
"bytes"
|
2015-12-23 11:08:34 +03:00
|
|
|
"encoding/binary"
|
|
|
|
"fmt"
|
2016-05-23 23:50:36 +03:00
|
|
|
"io"
|
|
|
|
|
2016-12-25 01:55:31 +03:00
|
|
|
"net"
|
|
|
|
|
2016-12-07 18:46:22 +03:00
|
|
|
"github.com/go-errors/errors"
|
2016-05-15 17:17:44 +03:00
|
|
|
"github.com/roasbeef/btcd/btcec"
|
2017-01-06 00:56:27 +03:00
|
|
|
"github.com/roasbeef/btcd/chaincfg/chainhash"
|
2016-05-23 23:50:36 +03:00
|
|
|
"github.com/roasbeef/btcd/txscript"
|
2016-05-15 17:17:44 +03:00
|
|
|
"github.com/roasbeef/btcd/wire"
|
|
|
|
"github.com/roasbeef/btcutil"
|
2015-12-23 11:08:34 +03:00
|
|
|
)
|
|
|
|
|
2016-05-23 23:50:36 +03:00
|
|
|
// MaxSliceLength is the maximum allowed lenth for any opaque byte slices in
|
|
|
|
// the wire protocol.
|
|
|
|
const MaxSliceLength = 65535
|
2016-01-05 19:19:22 +03:00
|
|
|
|
2016-05-23 23:50:36 +03:00
|
|
|
// PkScript is simple type definition which represents a raw serialized public
|
|
|
|
// key script.
|
2015-12-23 11:08:34 +03:00
|
|
|
type PkScript []byte
|
|
|
|
|
2016-05-23 23:50:36 +03:00
|
|
|
// CreditsAmount are the native currency unit used within the Lightning Network.
|
|
|
|
// Credits are denominated in sub-satoshi amounts, so micro-satoshis (1/1000).
|
|
|
|
// This value is purposefully signed in order to allow the expression of negative
|
|
|
|
// fees.
|
2016-02-18 15:29:08 +03:00
|
|
|
//
|
2016-01-17 04:14:35 +03:00
|
|
|
// "In any science-fiction movie, anywhere in the galaxy, currency is referred
|
|
|
|
// to as 'credits.'"
|
|
|
|
// --Sam Humphries. Ebert, Roger (1999). Ebert's bigger little movie
|
|
|
|
// glossary. Andrews McMeel. p. 172.
|
2016-02-18 15:29:08 +03:00
|
|
|
//
|
2016-05-23 23:50:36 +03:00
|
|
|
// https://en.wikipedia.org/wiki/List_of_fictional_currencies
|
|
|
|
// https://en.wikipedia.org/wiki/Fictional_currency#Trends_in_the_use_of_fictional_currencies
|
|
|
|
// http://tvtropes.org/pmwiki/pmwiki.php/Main/WeWillSpendCreditsInTheFuture
|
2016-01-17 04:14:35 +03:00
|
|
|
// US Display format: 1 BTC = 100,000,000'000 XCB
|
|
|
|
// Or in BTC = 1.00000000'000
|
2016-05-23 23:50:36 +03:00
|
|
|
// Credits (XCB, accountants should use XCB :^)
|
|
|
|
type CreditsAmount int64
|
2015-12-27 05:20:25 +03:00
|
|
|
|
2016-05-23 23:50:36 +03:00
|
|
|
// ToSatoshi converts an amount in Credits to the coresponding amount
|
|
|
|
// expressed in Satoshis.
|
|
|
|
//
|
|
|
|
// NOTE: This function rounds down by default (floor).
|
2016-02-29 11:45:38 +03:00
|
|
|
func (c CreditsAmount) ToSatoshi() int64 {
|
|
|
|
return int64(c / 1000)
|
|
|
|
}
|
|
|
|
|
2016-05-23 23:51:21 +03:00
|
|
|
// writeElement is a one-stop shop to write the big endian representation of
|
|
|
|
// any element which is to be serialized for the wire protocol. The passed
|
|
|
|
// io.Writer should be backed by an appropriatly sized byte slice, or be able
|
|
|
|
// to dynamically expand to accomdate additional data.
|
|
|
|
//
|
|
|
|
// TODO(roasbeef): this should eventually draw from a buffer pool for
|
|
|
|
// serialization.
|
|
|
|
// TODO(roasbeef): switch to var-ints for all?
|
2015-12-31 10:34:40 +03:00
|
|
|
func writeElement(w io.Writer, element interface{}) error {
|
2015-12-23 11:08:34 +03:00
|
|
|
switch e := element.(type) {
|
|
|
|
case uint8:
|
|
|
|
var b [1]byte
|
|
|
|
b[0] = byte(e)
|
2016-05-23 23:51:21 +03:00
|
|
|
if _, err := w.Write(b[:]); err != nil {
|
2015-12-23 11:08:34 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-01-05 19:19:22 +03:00
|
|
|
case uint16:
|
|
|
|
var b [2]byte
|
|
|
|
binary.BigEndian.PutUint16(b[:], uint16(e))
|
2016-05-23 23:51:21 +03:00
|
|
|
if _, err := w.Write(b[:]); err != nil {
|
2016-01-05 19:19:22 +03:00
|
|
|
return err
|
|
|
|
}
|
2017-02-16 15:25:36 +03:00
|
|
|
case FailCode:
|
2017-01-06 08:43:25 +03:00
|
|
|
var b [2]byte
|
|
|
|
binary.BigEndian.PutUint16(b[:], uint16(e))
|
|
|
|
if _, err := w.Write(b[:]); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-10-23 23:39:54 +03:00
|
|
|
case ErrorCode:
|
|
|
|
var b [2]byte
|
|
|
|
binary.BigEndian.PutUint16(b[:], uint16(e))
|
|
|
|
if _, err := w.Write(b[:]); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-02-16 15:25:36 +03:00
|
|
|
case btcutil.Amount:
|
|
|
|
var b [8]byte
|
|
|
|
binary.BigEndian.PutUint64(b[:], uint64(e))
|
|
|
|
if _, err := w.Write(b[:]); err != nil {
|
2016-01-05 19:19:22 +03:00
|
|
|
return err
|
|
|
|
}
|
2015-12-23 11:08:34 +03:00
|
|
|
case uint32:
|
|
|
|
var b [4]byte
|
|
|
|
binary.BigEndian.PutUint32(b[:], uint32(e))
|
2016-05-23 23:51:21 +03:00
|
|
|
if _, err := w.Write(b[:]); err != nil {
|
2015-12-23 11:08:34 +03:00
|
|
|
return err
|
|
|
|
}
|
2015-12-30 16:38:57 +03:00
|
|
|
case uint64:
|
|
|
|
var b [8]byte
|
|
|
|
binary.BigEndian.PutUint64(b[:], uint64(e))
|
2016-05-23 23:51:21 +03:00
|
|
|
if _, err := w.Write(b[:]); err != nil {
|
2015-12-30 16:38:57 +03:00
|
|
|
return err
|
|
|
|
}
|
2015-12-23 11:08:34 +03:00
|
|
|
case *btcec.PublicKey:
|
|
|
|
var b [33]byte
|
|
|
|
serializedPubkey := e.SerializeCompressed()
|
|
|
|
copy(b[:], serializedPubkey)
|
2016-05-23 23:51:21 +03:00
|
|
|
// TODO(roasbeef): use WriteVarBytes here?
|
|
|
|
if _, err := w.Write(b[:]); err != nil {
|
2015-12-23 11:08:34 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-01-15 04:02:23 +03:00
|
|
|
case []uint64:
|
2016-05-23 23:51:21 +03:00
|
|
|
// Enforce a max number of elements in a uint64 slice.
|
2016-01-15 04:02:23 +03:00
|
|
|
numItems := len(e)
|
|
|
|
if numItems > 65535 {
|
|
|
|
return fmt.Errorf("Too many []uint64s")
|
|
|
|
}
|
2016-05-23 23:51:21 +03:00
|
|
|
|
|
|
|
// First write out the the number of elements in the slice as a
|
|
|
|
// length prefix.
|
|
|
|
if err := writeElement(w, uint16(numItems)); err != nil {
|
2016-01-15 04:02:23 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-05-23 23:51:21 +03:00
|
|
|
|
|
|
|
// After the prefix detailing the number of elements, write out
|
|
|
|
// each uint64 in series.
|
2016-01-15 04:02:23 +03:00
|
|
|
for i := 0; i < numItems; i++ {
|
2016-05-23 23:51:21 +03:00
|
|
|
if err := writeElement(w, e[i]); err != nil {
|
2016-01-15 04:02:23 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
2015-12-31 11:25:00 +03:00
|
|
|
case []*btcec.Signature:
|
2016-05-23 23:51:21 +03:00
|
|
|
// Enforce a sane number for the maximum number of signatures.
|
2015-12-31 11:25:00 +03:00
|
|
|
numSigs := len(e)
|
2015-12-30 16:38:57 +03:00
|
|
|
if numSigs > 127 {
|
|
|
|
return fmt.Errorf("Too many signatures!")
|
|
|
|
}
|
2016-05-23 23:51:21 +03:00
|
|
|
|
|
|
|
// First write out the the number of elements in the slice as a
|
|
|
|
// length prefix.
|
|
|
|
if err := writeElement(w, uint8(numSigs)); err != nil {
|
2015-12-30 16:38:57 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-05-23 23:51:21 +03:00
|
|
|
|
|
|
|
// After the prefix detailing the number of elements, write out
|
|
|
|
// each signature in series.
|
2015-12-30 16:38:57 +03:00
|
|
|
for i := 0; i < numSigs; i++ {
|
2016-05-23 23:51:21 +03:00
|
|
|
if err := writeElement(w, e[i]); err != nil {
|
2015-12-30 16:38:57 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case *btcec.Signature:
|
2016-12-08 23:56:37 +03:00
|
|
|
var b [64]byte
|
|
|
|
err := serializeSigToWire(&b, e)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
2015-12-30 16:38:57 +03:00
|
|
|
}
|
2016-12-08 23:56:37 +03:00
|
|
|
// Write buffer
|
|
|
|
if _, err = w.Write(b[:]); err != nil {
|
2015-12-30 16:38:57 +03:00
|
|
|
return err
|
|
|
|
}
|
2017-01-06 00:56:27 +03:00
|
|
|
case *chainhash.Hash:
|
2016-05-23 23:51:21 +03:00
|
|
|
if _, err := w.Write(e[:]); err != nil {
|
2015-12-30 16:38:57 +03:00
|
|
|
return err
|
|
|
|
}
|
2015-12-28 14:24:16 +03:00
|
|
|
case wire.BitcoinNet:
|
|
|
|
var b [4]byte
|
|
|
|
binary.BigEndian.PutUint32(b[:], uint32(e))
|
2016-05-23 23:51:21 +03:00
|
|
|
if _, err := w.Write(b[:]); err != nil {
|
2015-12-28 14:24:16 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-01-05 19:19:22 +03:00
|
|
|
case []byte:
|
2017-02-16 15:25:36 +03:00
|
|
|
if _, err := w.Write(e[:]); err != nil {
|
2016-05-31 01:42:53 +03:00
|
|
|
return err
|
|
|
|
}
|
2015-12-23 11:08:34 +03:00
|
|
|
case PkScript:
|
2016-05-23 23:51:21 +03:00
|
|
|
// Make sure it's P2PKH or P2SH size or less.
|
2015-12-23 11:08:34 +03:00
|
|
|
scriptLength := len(e)
|
|
|
|
if scriptLength > 25 {
|
|
|
|
return fmt.Errorf("PkScript too long!")
|
|
|
|
}
|
2016-05-23 23:51:21 +03:00
|
|
|
|
|
|
|
if err := wire.WriteVarBytes(w, 0, e); err != nil {
|
2015-12-23 11:08:34 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-01-05 19:53:42 +03:00
|
|
|
case string:
|
|
|
|
strlen := len(e)
|
2016-05-23 23:51:21 +03:00
|
|
|
if strlen > MaxSliceLength {
|
2016-01-05 19:53:42 +03:00
|
|
|
return fmt.Errorf("String too long!")
|
|
|
|
}
|
2016-05-23 23:51:21 +03:00
|
|
|
|
|
|
|
if err := wire.WriteVarString(w, 0, e); err != nil {
|
2016-01-05 19:53:42 +03:00
|
|
|
return err
|
|
|
|
}
|
2015-12-23 11:08:34 +03:00
|
|
|
case []*wire.TxIn:
|
2016-01-17 04:14:35 +03:00
|
|
|
// Write the size (1-byte)
|
2015-12-23 11:08:34 +03:00
|
|
|
if len(e) > 127 {
|
|
|
|
return fmt.Errorf("Too many txins")
|
|
|
|
}
|
2016-05-23 23:51:21 +03:00
|
|
|
|
|
|
|
// Write out the number of txins.
|
|
|
|
if err := writeElement(w, uint8(len(e))); err != nil {
|
2015-12-23 11:08:34 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-05-23 23:51:21 +03:00
|
|
|
|
2016-01-17 04:14:35 +03:00
|
|
|
// Append the actual TxIns (Size: NumOfTxins * 36)
|
2016-05-23 23:51:21 +03:00
|
|
|
// During serialization we leave out the sequence number to
|
|
|
|
// eliminate any funny business.
|
2015-12-23 11:08:34 +03:00
|
|
|
for _, in := range e {
|
2016-05-23 23:51:21 +03:00
|
|
|
if err := writeElement(w, in); err != nil {
|
2015-12-23 11:08:34 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
2015-12-31 11:25:00 +03:00
|
|
|
case *wire.TxIn:
|
2016-05-23 23:51:21 +03:00
|
|
|
// First write out the previous txid.
|
2015-12-31 11:25:00 +03:00
|
|
|
var h [32]byte
|
2016-05-23 23:51:21 +03:00
|
|
|
copy(h[:], e.PreviousOutPoint.Hash[:])
|
|
|
|
if _, err := w.Write(h[:]); err != nil {
|
2015-12-31 11:25:00 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-05-23 23:51:21 +03:00
|
|
|
|
|
|
|
// Then the exact index of the previous out point.
|
2015-12-31 11:25:00 +03:00
|
|
|
var idx [4]byte
|
|
|
|
binary.BigEndian.PutUint32(idx[:], e.PreviousOutPoint.Index)
|
2016-05-23 23:51:21 +03:00
|
|
|
if _, err := w.Write(idx[:]); err != nil {
|
2015-12-31 11:25:00 +03:00
|
|
|
return err
|
|
|
|
}
|
2017-02-16 15:31:19 +03:00
|
|
|
case *FeatureVector:
|
|
|
|
if err := e.Encode(w); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-02-16 15:34:44 +03:00
|
|
|
|
|
|
|
case wire.OutPoint:
|
2016-05-31 01:42:53 +03:00
|
|
|
// TODO(roasbeef): consolidate with above
|
|
|
|
// First write out the previous txid.
|
|
|
|
var h [32]byte
|
|
|
|
copy(h[:], e.Hash[:])
|
|
|
|
if _, err := w.Write(h[:]); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Then the exact index of this output.
|
|
|
|
var idx [4]byte
|
|
|
|
binary.BigEndian.PutUint32(idx[:], e.Index)
|
|
|
|
if _, err := w.Write(idx[:]); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-05-23 23:51:21 +03:00
|
|
|
// TODO(roasbeef): *MsgTx
|
2016-10-05 23:47:02 +03:00
|
|
|
case int64, float64:
|
|
|
|
err := binary.Write(w, binary.BigEndian, e)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-12-22 23:17:24 +03:00
|
|
|
case ChannelID:
|
2016-12-07 18:46:22 +03:00
|
|
|
// Check that field fit in 3 bytes and write the blockHeight
|
|
|
|
if e.BlockHeight > ((1 << 24) - 1) {
|
|
|
|
return errors.New("block height should fit in 3 bytes")
|
|
|
|
}
|
|
|
|
|
|
|
|
var blockHeight [4]byte
|
|
|
|
binary.BigEndian.PutUint32(blockHeight[:], e.BlockHeight)
|
|
|
|
|
|
|
|
if _, err := w.Write(blockHeight[1:]); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check that field fit in 3 bytes and write the txIndex
|
|
|
|
if e.TxIndex > ((1 << 24) - 1) {
|
|
|
|
return errors.New("tx index should fit in 3 bytes")
|
|
|
|
}
|
|
|
|
|
|
|
|
var txIndex [4]byte
|
|
|
|
binary.BigEndian.PutUint32(txIndex[:], e.TxIndex)
|
|
|
|
if _, err := w.Write(txIndex[1:]); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write the txPosition
|
|
|
|
var txPosition [2]byte
|
|
|
|
binary.BigEndian.PutUint16(txPosition[:], e.TxPosition)
|
|
|
|
if _, err := w.Write(txPosition[:]); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
case *net.TCPAddr:
|
|
|
|
var ip [16]byte
|
|
|
|
copy(ip[:], e.IP.To16())
|
|
|
|
if _, err := w.Write(ip[:]); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
var port [4]byte
|
|
|
|
binary.BigEndian.PutUint32(port[:], uint32(e.Port))
|
|
|
|
if _, err := w.Write(port[:]); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
case RGB:
|
|
|
|
err := writeElements(w,
|
|
|
|
e.red,
|
|
|
|
e.green,
|
|
|
|
e.blue,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
case Alias:
|
2017-02-16 15:25:36 +03:00
|
|
|
if err := writeElements(w, e.data[:]); err != nil {
|
2016-12-07 18:46:22 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2015-12-23 11:08:34 +03:00
|
|
|
default:
|
|
|
|
return fmt.Errorf("Unknown type in writeElement: %T", e)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-05-23 23:51:21 +03:00
|
|
|
// writeElements is writes each element in the elements slice to the passed
|
|
|
|
// io.Writer using writeElement.
|
2015-12-31 10:34:40 +03:00
|
|
|
func writeElements(w io.Writer, elements ...interface{}) error {
|
2015-12-28 14:24:16 +03:00
|
|
|
for _, element := range elements {
|
2015-12-31 10:34:40 +03:00
|
|
|
err := writeElement(w, element)
|
2015-12-28 14:24:16 +03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-05-23 23:51:21 +03:00
|
|
|
// readElement is a one-stop utility function to deserialize any datastructure
|
|
|
|
// encoded using the serialization format of lnwire.
|
2015-12-31 10:34:40 +03:00
|
|
|
func readElement(r io.Reader, element interface{}) error {
|
2015-12-23 11:08:34 +03:00
|
|
|
var err error
|
|
|
|
switch e := element.(type) {
|
2015-12-27 05:20:25 +03:00
|
|
|
case *uint8:
|
2015-12-27 10:52:20 +03:00
|
|
|
var b [1]uint8
|
2016-05-23 23:51:21 +03:00
|
|
|
if _, err := r.Read(b[:]); err != nil {
|
2015-12-27 05:20:25 +03:00
|
|
|
return err
|
|
|
|
}
|
2015-12-27 10:52:20 +03:00
|
|
|
*e = b[0]
|
2017-02-16 15:25:36 +03:00
|
|
|
case *FailCode:
|
2017-01-06 08:43:25 +03:00
|
|
|
var b [2]byte
|
|
|
|
if _, err := io.ReadFull(r, b[:]); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-02-16 15:25:36 +03:00
|
|
|
*e = FailCode(binary.BigEndian.Uint16(b[:]))
|
2016-01-05 19:19:22 +03:00
|
|
|
case *uint16:
|
|
|
|
var b [2]byte
|
2016-05-23 23:51:21 +03:00
|
|
|
if _, err := io.ReadFull(r, b[:]); err != nil {
|
2016-01-05 19:19:22 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
*e = binary.BigEndian.Uint16(b[:])
|
2016-10-23 23:39:54 +03:00
|
|
|
case *ErrorCode:
|
|
|
|
var b [2]byte
|
|
|
|
if _, err := io.ReadFull(r, b[:]); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
*e = ErrorCode(binary.BigEndian.Uint16(b[:]))
|
2015-12-23 11:08:34 +03:00
|
|
|
case *uint32:
|
|
|
|
var b [4]byte
|
2016-05-23 23:51:21 +03:00
|
|
|
if _, err := io.ReadFull(r, b[:]); err != nil {
|
2015-12-23 11:08:34 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
*e = binary.BigEndian.Uint32(b[:])
|
2015-12-30 16:38:57 +03:00
|
|
|
case *uint64:
|
|
|
|
var b [8]byte
|
2016-05-23 23:51:21 +03:00
|
|
|
if _, err := io.ReadFull(r, b[:]); err != nil {
|
2015-12-30 16:38:57 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
*e = binary.BigEndian.Uint64(b[:])
|
2015-12-27 05:20:25 +03:00
|
|
|
case *btcutil.Amount:
|
|
|
|
var b [8]byte
|
2016-05-23 23:51:21 +03:00
|
|
|
if _, err := io.ReadFull(r, b[:]); err != nil {
|
2015-12-27 05:20:25 +03:00
|
|
|
return err
|
|
|
|
}
|
2015-12-27 10:52:20 +03:00
|
|
|
*e = btcutil.Amount(int64(binary.BigEndian.Uint64(b[:])))
|
2017-01-06 00:56:27 +03:00
|
|
|
case **chainhash.Hash:
|
|
|
|
var b chainhash.Hash
|
2016-05-23 23:51:21 +03:00
|
|
|
if _, err := io.ReadFull(r, b[:]); err != nil {
|
2015-12-30 16:38:57 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
*e = &b
|
2015-12-27 10:52:20 +03:00
|
|
|
case **btcec.PublicKey:
|
2016-12-07 18:46:22 +03:00
|
|
|
var b [btcec.PubKeyBytesLenCompressed]byte
|
2016-05-23 23:51:21 +03:00
|
|
|
if _, err = io.ReadFull(r, b[:]); err != nil {
|
2015-12-27 05:20:25 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-05-23 23:51:21 +03:00
|
|
|
|
|
|
|
pubKey, err := btcec.ParsePubKey(b[:], btcec.S256())
|
2015-12-30 16:38:57 +03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-05-23 23:51:21 +03:00
|
|
|
*e = pubKey
|
2017-02-16 15:31:19 +03:00
|
|
|
case **FeatureVector:
|
|
|
|
f, err := NewFeatureVectorFromReader(r)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
*e = f
|
|
|
|
|
2016-01-15 04:02:23 +03:00
|
|
|
case *[]uint64:
|
|
|
|
var numItems uint16
|
2016-05-23 23:51:21 +03:00
|
|
|
if err := readElement(r, &numItems); err != nil {
|
2016-01-15 04:02:23 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-01-17 04:14:35 +03:00
|
|
|
// if numItems > 65535 {
|
|
|
|
// return fmt.Errorf("Too many items in []uint64")
|
|
|
|
// }
|
2016-01-15 04:02:23 +03:00
|
|
|
|
2016-01-17 04:14:35 +03:00
|
|
|
// Read the number of items
|
2016-01-15 04:02:23 +03:00
|
|
|
var items []uint64
|
|
|
|
for i := uint16(0); i < numItems; i++ {
|
|
|
|
var item uint64
|
|
|
|
err = readElement(r, &item)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
items = append(items, item)
|
|
|
|
}
|
2016-02-29 11:45:38 +03:00
|
|
|
*e = items
|
2015-12-31 11:25:00 +03:00
|
|
|
case *[]*btcec.Signature:
|
2015-12-30 16:38:57 +03:00
|
|
|
var numSigs uint8
|
2015-12-31 10:34:40 +03:00
|
|
|
err = readElement(r, &numSigs)
|
2015-12-27 05:20:25 +03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2015-12-30 16:38:57 +03:00
|
|
|
if numSigs > 127 {
|
|
|
|
return fmt.Errorf("Too many signatures!")
|
|
|
|
}
|
|
|
|
|
2016-01-17 04:14:35 +03:00
|
|
|
// Read that number of signatures
|
2015-12-31 11:25:00 +03:00
|
|
|
var sigs []*btcec.Signature
|
2015-12-30 16:38:57 +03:00
|
|
|
for i := uint8(0); i < numSigs; i++ {
|
|
|
|
sig := new(btcec.Signature)
|
2015-12-31 10:34:40 +03:00
|
|
|
err = readElement(r, &sig)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2015-12-31 11:25:00 +03:00
|
|
|
sigs = append(sigs, sig)
|
2015-12-30 16:38:57 +03:00
|
|
|
}
|
2016-02-29 11:45:38 +03:00
|
|
|
*e = sigs
|
2015-12-30 16:38:57 +03:00
|
|
|
return nil
|
|
|
|
case **btcec.Signature:
|
2016-12-08 23:56:37 +03:00
|
|
|
var b [64]byte
|
|
|
|
if _, err := io.ReadFull(r, b[:]); err != nil {
|
2015-12-30 16:38:57 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-12-08 23:56:37 +03:00
|
|
|
err = deserializeSigFromWire(e, b)
|
2015-12-30 16:38:57 +03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2015-12-28 14:24:16 +03:00
|
|
|
case *wire.BitcoinNet:
|
|
|
|
var b [4]byte
|
2016-05-23 23:51:21 +03:00
|
|
|
if _, err := io.ReadFull(r, b[:]); err != nil {
|
2015-12-28 14:24:16 +03:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
*e = wire.BitcoinNet(binary.BigEndian.Uint32(b[:]))
|
|
|
|
return nil
|
2017-02-16 15:25:36 +03:00
|
|
|
case []byte:
|
|
|
|
if _, err := io.ReadFull(r, e); err != nil {
|
2016-01-05 19:19:22 +03:00
|
|
|
return err
|
|
|
|
}
|
2015-12-27 05:20:25 +03:00
|
|
|
case *PkScript:
|
2016-05-23 23:51:21 +03:00
|
|
|
pkScript, err := wire.ReadVarBytes(r, 0, 25, "pkscript")
|
2015-12-27 05:20:25 +03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-05-23 23:51:21 +03:00
|
|
|
*e = pkScript
|
2016-01-05 19:53:42 +03:00
|
|
|
case *string:
|
2016-05-23 23:51:21 +03:00
|
|
|
str, err := wire.ReadVarString(r, 0)
|
2016-01-05 19:53:42 +03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-05-23 23:51:21 +03:00
|
|
|
*e = str
|
2015-12-27 10:52:20 +03:00
|
|
|
case *[]*wire.TxIn:
|
2016-01-17 04:14:35 +03:00
|
|
|
// Read the size (1-byte number of txins)
|
2015-12-30 16:38:57 +03:00
|
|
|
var numScripts uint8
|
2016-05-23 23:51:21 +03:00
|
|
|
if err := readElement(r, &numScripts); err != nil {
|
2015-12-27 05:20:25 +03:00
|
|
|
return err
|
|
|
|
}
|
2015-12-30 16:38:57 +03:00
|
|
|
if numScripts > 127 {
|
2015-12-27 05:20:25 +03:00
|
|
|
return fmt.Errorf("Too many txins")
|
|
|
|
}
|
|
|
|
|
2016-01-17 04:14:35 +03:00
|
|
|
// Append the actual TxIns
|
2016-05-23 23:51:21 +03:00
|
|
|
txins := make([]*wire.TxIn, 0, numScripts)
|
2015-12-30 16:38:57 +03:00
|
|
|
for i := uint8(0); i < numScripts; i++ {
|
2015-12-31 11:25:00 +03:00
|
|
|
outpoint := new(wire.OutPoint)
|
2016-02-16 09:13:17 +03:00
|
|
|
txin := wire.NewTxIn(outpoint, nil, nil)
|
2016-05-23 23:51:21 +03:00
|
|
|
if err := readElement(r, &txin); err != nil {
|
2015-12-27 05:20:25 +03:00
|
|
|
return err
|
|
|
|
}
|
2015-12-31 11:25:00 +03:00
|
|
|
txins = append(txins, txin)
|
2015-12-27 05:20:25 +03:00
|
|
|
}
|
2016-02-29 11:45:38 +03:00
|
|
|
*e = txins
|
2015-12-31 11:25:00 +03:00
|
|
|
case **wire.TxIn:
|
2016-01-17 04:14:35 +03:00
|
|
|
// Hash
|
2015-12-31 11:25:00 +03:00
|
|
|
var h [32]byte
|
2016-05-23 23:51:21 +03:00
|
|
|
if _, err = io.ReadFull(r, h[:]); err != nil {
|
2015-12-31 11:25:00 +03:00
|
|
|
return err
|
|
|
|
}
|
2017-01-06 00:56:27 +03:00
|
|
|
hash, err := chainhash.NewHash(h[:])
|
2015-12-31 11:25:00 +03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2015-12-31 11:41:55 +03:00
|
|
|
(*e).PreviousOutPoint.Hash = *hash
|
2016-05-23 23:51:21 +03:00
|
|
|
|
2016-01-17 04:14:35 +03:00
|
|
|
// Index
|
2015-12-31 11:25:00 +03:00
|
|
|
var idxBytes [4]byte
|
|
|
|
_, err = io.ReadFull(r, idxBytes[:])
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
(*e).PreviousOutPoint.Index = binary.BigEndian.Uint32(idxBytes[:])
|
|
|
|
return nil
|
2017-02-16 15:34:44 +03:00
|
|
|
case *wire.OutPoint:
|
2016-05-31 01:42:53 +03:00
|
|
|
// TODO(roasbeef): consolidate with above
|
|
|
|
var h [32]byte
|
|
|
|
if _, err = io.ReadFull(r, h[:]); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-01-06 00:56:27 +03:00
|
|
|
hash, err := chainhash.NewHash(h[:])
|
2016-05-31 01:42:53 +03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
// Index
|
|
|
|
var idxBytes [4]byte
|
|
|
|
_, err = io.ReadFull(r, idxBytes[:])
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-06-21 07:55:07 +03:00
|
|
|
index := binary.BigEndian.Uint32(idxBytes[:])
|
|
|
|
|
2017-02-16 15:34:44 +03:00
|
|
|
*e = wire.OutPoint{Hash: *hash, Index: index}
|
2016-10-05 23:47:02 +03:00
|
|
|
case *int64, *float64:
|
|
|
|
err := binary.Read(r, binary.BigEndian, e)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-12-22 23:17:24 +03:00
|
|
|
case *ChannelID:
|
2016-12-07 18:46:22 +03:00
|
|
|
var blockHeight [4]byte
|
|
|
|
if _, err = io.ReadFull(r, blockHeight[1:]); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
var txIndex [4]byte
|
|
|
|
if _, err = io.ReadFull(r, txIndex[1:]); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
var txPosition [2]byte
|
|
|
|
if _, err = io.ReadFull(r, txPosition[:]); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-12-22 23:17:24 +03:00
|
|
|
*e = ChannelID{
|
2016-12-07 18:46:22 +03:00
|
|
|
BlockHeight: binary.BigEndian.Uint32(blockHeight[:]),
|
|
|
|
TxIndex: binary.BigEndian.Uint32(txIndex[:]),
|
|
|
|
TxPosition: binary.BigEndian.Uint16(txPosition[:]),
|
|
|
|
}
|
|
|
|
|
|
|
|
case **net.TCPAddr:
|
|
|
|
var ip [16]byte
|
|
|
|
if _, err = io.ReadFull(r, ip[:]); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
var port [4]byte
|
|
|
|
if _, err = io.ReadFull(r, port[:]); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
*e = &net.TCPAddr{
|
|
|
|
IP: (net.IP)(ip[:]),
|
|
|
|
Port: int(binary.BigEndian.Uint32(port[:])),
|
|
|
|
}
|
|
|
|
case *RGB:
|
|
|
|
err := readElements(r,
|
|
|
|
&e.red,
|
|
|
|
&e.green,
|
|
|
|
&e.blue,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
case *Alias:
|
|
|
|
var a [32]byte
|
2017-02-16 15:25:36 +03:00
|
|
|
if err := readElements(r, a[:]); err != nil {
|
2016-12-07 18:46:22 +03:00
|
|
|
return err
|
|
|
|
}
|
2016-10-05 23:47:02 +03:00
|
|
|
|
2016-12-25 01:55:31 +03:00
|
|
|
*e, err = newAlias(a[:])
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2015-12-27 05:20:25 +03:00
|
|
|
default:
|
|
|
|
return fmt.Errorf("Unknown type in readElement: %T", e)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-05-23 23:51:21 +03:00
|
|
|
// readElements deserializes a variable number of elements into the passed
|
|
|
|
// io.Reader, with each element being deserialized according to the readElement
|
|
|
|
// function.
|
2015-12-31 10:34:40 +03:00
|
|
|
func readElements(r io.Reader, elements ...interface{}) error {
|
2015-12-28 14:24:16 +03:00
|
|
|
for _, element := range elements {
|
2015-12-31 10:34:40 +03:00
|
|
|
err := readElement(r, element)
|
2015-12-28 14:24:16 +03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2015-12-23 11:08:34 +03:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2015-12-30 16:38:57 +03:00
|
|
|
|
2016-05-23 23:48:13 +03:00
|
|
|
// validatePkScript determines if the passed pkScript is a valid pkScript within
|
|
|
|
// lnwire. The only pkScript templates that lnwire currently allows are:
|
|
|
|
// P2SH, P2WSH, P2PKH, and P2WKH.
|
|
|
|
func isValidPkScript(pkScript PkScript) bool {
|
|
|
|
// A nil pkScript is obviously invalid.
|
|
|
|
if pkScript == nil {
|
|
|
|
return false
|
2015-12-31 10:34:40 +03:00
|
|
|
}
|
2016-05-23 23:48:13 +03:00
|
|
|
|
|
|
|
switch len(pkScript) {
|
|
|
|
case 25:
|
|
|
|
// A valid p2pkh script must be exactly 25 bytes. It must begin
|
|
|
|
// with the define prefix, and end with the define suffix.
|
|
|
|
p2pkhPrefix := []byte{txscript.OP_DUP, txscript.OP_HASH160}
|
|
|
|
p2pkhSuffix := []byte{txscript.OP_EQUALVERIFY, txscript.OP_CHECKSIG,
|
|
|
|
txscript.OP_DATA_20}
|
|
|
|
if !bytes.Equal(pkScript[0:3], p2pkhPrefix) ||
|
|
|
|
!bytes.Equal(pkScript[23:25], p2pkhSuffix) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
case 22:
|
|
|
|
// P2WKH
|
|
|
|
// A valid P2WKH script must be exactly 22 bytes, with the first
|
|
|
|
// two op codes being an OP_0 marking a version zero witness
|
|
|
|
// program, and the second byte being a 20 byte push data.
|
|
|
|
if pkScript[0] != txscript.OP_0 ||
|
|
|
|
pkScript[1] != txscript.OP_DATA_20 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
case 23:
|
|
|
|
// A valid P2SH script must begin with OP_HASH160 PUSHDATA(20),
|
|
|
|
// contain 20 bytes, then end with an OP_EQUAL.
|
|
|
|
p2shPrefix := []byte{txscript.OP_HASH160, txscript.OP_DATA_20}
|
|
|
|
p2shSuffix := []byte{txscript.OP_EQUAL}
|
|
|
|
if !bytes.Equal(pkScript[0:2], p2shPrefix) ||
|
|
|
|
!bytes.Equal(pkScript[22:23], p2shSuffix) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
case 34:
|
|
|
|
// A P2WSH script must be exactly 34 bytes, with the first two
|
|
|
|
// op codes being an OP_0 marking a version zero witness program,
|
|
|
|
// and the second byte being a 32 byte push data.
|
|
|
|
if pkScript[0] != txscript.OP_0 ||
|
|
|
|
pkScript[1] != txscript.OP_DATA_32 {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return false
|
2015-12-30 16:38:57 +03:00
|
|
|
}
|
|
|
|
|
2016-05-23 23:48:13 +03:00
|
|
|
return true
|
2015-12-30 16:38:57 +03:00
|
|
|
}
|