lnwire: update/document [read/write]Element funcs
This commit is contained in:
1 file changed
+113
-247
+113
-247
@@ -62,252 +62,197 @@ func (c CreditsAmount) ToSatoshi() int64 {
|
|||||||
return int64(c / 1000)
|
return int64(c / 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Writes the big endian representation of element
|
// writeElement is a one-stop shop to write the big endian representation of
|
||||||
// Unified function to call when writing different types
|
// any element which is to be serialized for the wire protocol. The passed
|
||||||
// Pre-allocate a byte-array of the correct size for cargo-cult security
|
// io.Writer should be backed by an appropriatly sized byte slice, or be able
|
||||||
// More copies but whatever...
|
// 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?
|
||||||
func writeElement(w io.Writer, element interface{}) error {
|
func writeElement(w io.Writer, element interface{}) error {
|
||||||
var err error
|
|
||||||
switch e := element.(type) {
|
switch e := element.(type) {
|
||||||
case uint8:
|
case uint8:
|
||||||
var b [1]byte
|
var b [1]byte
|
||||||
b[0] = byte(e)
|
b[0] = byte(e)
|
||||||
_, err = w.Write(b[:])
|
if _, err := w.Write(b[:]); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
case uint16:
|
case uint16:
|
||||||
var b [2]byte
|
var b [2]byte
|
||||||
binary.BigEndian.PutUint16(b[:], uint16(e))
|
binary.BigEndian.PutUint16(b[:], uint16(e))
|
||||||
_, err = w.Write(b[:])
|
if _, err := w.Write(b[:]); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
case CreditsAmount:
|
case CreditsAmount:
|
||||||
err = binary.Write(w, binary.BigEndian, int64(e))
|
if err := binary.Write(w, binary.BigEndian, int64(e)); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
case uint32:
|
case uint32:
|
||||||
var b [4]byte
|
var b [4]byte
|
||||||
binary.BigEndian.PutUint32(b[:], uint32(e))
|
binary.BigEndian.PutUint32(b[:], uint32(e))
|
||||||
_, err = w.Write(b[:])
|
if _, err := w.Write(b[:]); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
case uint64:
|
case uint64:
|
||||||
var b [8]byte
|
var b [8]byte
|
||||||
binary.BigEndian.PutUint64(b[:], uint64(e))
|
binary.BigEndian.PutUint64(b[:], uint64(e))
|
||||||
_, err = w.Write(b[:])
|
if _, err := w.Write(b[:]); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
case HTLCKey:
|
case HTLCKey:
|
||||||
err = binary.Write(w, binary.BigEndian, int64(e))
|
if err := binary.Write(w, binary.BigEndian, int64(e)); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
case btcutil.Amount:
|
case btcutil.Amount:
|
||||||
err = binary.Write(w, binary.BigEndian, int64(e))
|
if err := binary.Write(w, binary.BigEndian, int64(e)); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
case *btcec.PublicKey:
|
case *btcec.PublicKey:
|
||||||
var b [33]byte
|
var b [33]byte
|
||||||
serializedPubkey := e.SerializeCompressed()
|
serializedPubkey := e.SerializeCompressed()
|
||||||
if len(serializedPubkey) != 33 {
|
|
||||||
return fmt.Errorf("Wrong size pubkey")
|
|
||||||
}
|
|
||||||
copy(b[:], serializedPubkey)
|
copy(b[:], serializedPubkey)
|
||||||
_, err = w.Write(b[:])
|
// TODO(roasbeef): use WriteVarBytes here?
|
||||||
if err != nil {
|
if _, err := w.Write(b[:]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
case []uint64:
|
case []uint64:
|
||||||
|
// Enforce a max number of elements in a uint64 slice.
|
||||||
numItems := len(e)
|
numItems := len(e)
|
||||||
if numItems > 65535 {
|
if numItems > 65535 {
|
||||||
return fmt.Errorf("Too many []uint64s")
|
return fmt.Errorf("Too many []uint64s")
|
||||||
}
|
}
|
||||||
// Write the size
|
|
||||||
err = writeElement(w, uint16(numItems))
|
// First write out the the number of elements in the slice as a
|
||||||
if err != nil {
|
// length prefix.
|
||||||
|
if err := writeElement(w, uint16(numItems)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Write the data
|
|
||||||
|
// After the prefix detailing the number of elements, write out
|
||||||
|
// each uint64 in series.
|
||||||
for i := 0; i < numItems; i++ {
|
for i := 0; i < numItems; i++ {
|
||||||
err = writeElement(w, e[i])
|
if err := writeElement(w, e[i]); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
case []*btcec.Signature:
|
case []*btcec.Signature:
|
||||||
|
// Enforce a sane number for the maximum number of signatures.
|
||||||
numSigs := len(e)
|
numSigs := len(e)
|
||||||
if numSigs > 127 {
|
if numSigs > 127 {
|
||||||
return fmt.Errorf("Too many signatures!")
|
return fmt.Errorf("Too many signatures!")
|
||||||
}
|
}
|
||||||
// Write the size
|
|
||||||
err = writeElement(w, uint8(numSigs))
|
// First write out the the number of elements in the slice as a
|
||||||
if err != nil {
|
// length prefix.
|
||||||
|
if err := writeElement(w, uint8(numSigs)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Write the data
|
|
||||||
|
// After the prefix detailing the number of elements, write out
|
||||||
|
// each signature in series.
|
||||||
for i := 0; i < numSigs; i++ {
|
for i := 0; i < numSigs; i++ {
|
||||||
err = writeElement(w, e[i])
|
if err := writeElement(w, e[i]); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
case *btcec.Signature:
|
case *btcec.Signature:
|
||||||
sig := e.Serialize()
|
sig := e.Serialize()
|
||||||
sigLength := len(sig)
|
if len(sig) > 73 {
|
||||||
if sigLength > 73 {
|
|
||||||
return fmt.Errorf("Signature too long!")
|
return fmt.Errorf("Signature too long!")
|
||||||
}
|
}
|
||||||
// Write the size
|
|
||||||
err = writeElement(w, uint8(sigLength))
|
if err := wire.WriteVarBytes(w, 0, sig); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Write the data
|
|
||||||
_, err = w.Write(sig)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
case *wire.ShaHash:
|
case *wire.ShaHash:
|
||||||
_, err = w.Write(e[:])
|
if _, err := w.Write(e[:]); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
case [][20]byte:
|
||||||
case []*[20]byte:
|
// First write out the number of elements in the slice.
|
||||||
// Get size of slice and dump in slice
|
|
||||||
sliceSize := len(e)
|
sliceSize := len(e)
|
||||||
err = writeElement(w, uint16(sliceSize))
|
if err := writeElement(w, uint16(sliceSize)); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Write in each sequentially
|
|
||||||
|
// Then write each out sequentially.
|
||||||
for _, element := range e {
|
for _, element := range e {
|
||||||
err = writeElement(w, &element)
|
if err := writeElement(w, &element); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
case **[20]byte:
|
|
||||||
_, err = w.Write((*e)[:])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
case [20]byte:
|
case [20]byte:
|
||||||
_, err = w.Write(e[:])
|
// TODO(roasbeef): should be factor out to caller logic...
|
||||||
if err != nil {
|
if _, err := w.Write(e[:]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
case wire.BitcoinNet:
|
case wire.BitcoinNet:
|
||||||
var b [4]byte
|
var b [4]byte
|
||||||
binary.BigEndian.PutUint32(b[:], uint32(e))
|
binary.BigEndian.PutUint32(b[:], uint32(e))
|
||||||
_, err := w.Write(b[:])
|
if _, err := w.Write(b[:]); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
case []byte:
|
case []byte:
|
||||||
|
// Enforce the maxmium length of all slices used in the wire
|
||||||
|
// protocol.
|
||||||
sliceLength := len(e)
|
sliceLength := len(e)
|
||||||
if sliceLength > MAX_SLICE_LENGTH {
|
if sliceLength > MaxSliceLength {
|
||||||
return fmt.Errorf("Slice length too long!")
|
return fmt.Errorf("Slice length too long!")
|
||||||
}
|
}
|
||||||
// Write the size
|
|
||||||
err = writeElement(w, uint16(sliceLength))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Write the data
|
|
||||||
_, err = w.Write(e)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
case PkScript:
|
case PkScript:
|
||||||
|
// Make sure it's P2PKH or P2SH size or less.
|
||||||
scriptLength := len(e)
|
scriptLength := len(e)
|
||||||
// Make sure it's P2PKH or P2SH size or less
|
|
||||||
if scriptLength > 25 {
|
if scriptLength > 25 {
|
||||||
return fmt.Errorf("PkScript too long!")
|
return fmt.Errorf("PkScript too long!")
|
||||||
}
|
}
|
||||||
// Write the size (1-byte)
|
|
||||||
err = writeElement(w, uint8(scriptLength))
|
if err := wire.WriteVarBytes(w, 0, e); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Write the data
|
|
||||||
_, err = w.Write(e)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
case string:
|
case string:
|
||||||
strlen := len(e)
|
strlen := len(e)
|
||||||
if strlen > 65535 {
|
if strlen > MaxSliceLength {
|
||||||
return fmt.Errorf("String too long!")
|
return fmt.Errorf("String too long!")
|
||||||
}
|
}
|
||||||
// Write the size (2-bytes)
|
|
||||||
err = writeElement(w, uint16(strlen))
|
if err := wire.WriteVarString(w, 0, e); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Write the data
|
|
||||||
_, err = w.Write([]byte(e))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case []*wire.TxIn:
|
case []*wire.TxIn:
|
||||||
// Append the unsigned(!!!) txins
|
|
||||||
// Write the size (1-byte)
|
// Write the size (1-byte)
|
||||||
if len(e) > 127 {
|
if len(e) > 127 {
|
||||||
return fmt.Errorf("Too many txins")
|
return fmt.Errorf("Too many txins")
|
||||||
}
|
}
|
||||||
err = writeElement(w, uint8(len(e)))
|
|
||||||
if err != nil {
|
// Write out the number of txins.
|
||||||
|
if err := writeElement(w, uint8(len(e))); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append the actual TxIns (Size: NumOfTxins * 36)
|
// Append the actual TxIns (Size: NumOfTxins * 36)
|
||||||
// Do not include the sequence number to eliminate funny business
|
// During serialization we leave out the sequence number to
|
||||||
|
// eliminate any funny business.
|
||||||
for _, in := range e {
|
for _, in := range e {
|
||||||
err = writeElement(w, in)
|
if err := writeElement(w, in); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
case *wire.TxIn:
|
case *wire.TxIn:
|
||||||
// Hash
|
// First write out the previous txid.
|
||||||
var h [32]byte
|
var h [32]byte
|
||||||
copy(h[:], e.PreviousOutPoint.Hash.Bytes())
|
copy(h[:], e.PreviousOutPoint.Hash[:])
|
||||||
_, err = w.Write(h[:])
|
if _, err := w.Write(h[:]); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Index
|
|
||||||
|
// Then the exact index of the previous out point.
|
||||||
var idx [4]byte
|
var idx [4]byte
|
||||||
binary.BigEndian.PutUint32(idx[:], e.PreviousOutPoint.Index)
|
binary.BigEndian.PutUint32(idx[:], e.PreviousOutPoint.Index)
|
||||||
_, err = w.Write(idx[:])
|
if _, err := w.Write(idx[:]); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
// TODO(roasbeef): *MsgTx
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("Unknown type in writeElement: %T", e)
|
return fmt.Errorf("Unknown type in writeElement: %T", e)
|
||||||
}
|
}
|
||||||
@@ -315,6 +260,8 @@ func writeElement(w io.Writer, element interface{}) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// writeElements is writes each element in the elements slice to the passed
|
||||||
|
// io.Writer using writeElement.
|
||||||
func writeElements(w io.Writer, elements ...interface{}) error {
|
func writeElements(w io.Writer, elements ...interface{}) error {
|
||||||
for _, element := range elements {
|
for _, element := range elements {
|
||||||
err := writeElement(w, element)
|
err := writeElement(w, element)
|
||||||
@@ -325,89 +272,73 @@ func writeElements(w io.Writer, elements ...interface{}) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// readElement is a one-stop utility function to deserialize any datastructure
|
||||||
|
// encoded using the serialization format of lnwire.
|
||||||
func readElement(r io.Reader, element interface{}) error {
|
func readElement(r io.Reader, element interface{}) error {
|
||||||
var err error
|
var err error
|
||||||
switch e := element.(type) {
|
switch e := element.(type) {
|
||||||
case *uint8:
|
case *uint8:
|
||||||
var b [1]uint8
|
var b [1]uint8
|
||||||
_, err = r.Read(b[:])
|
if _, err := r.Read(b[:]); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*e = b[0]
|
*e = b[0]
|
||||||
return nil
|
|
||||||
case *uint16:
|
case *uint16:
|
||||||
var b [2]byte
|
var b [2]byte
|
||||||
_, err = io.ReadFull(r, b[:])
|
if _, err := io.ReadFull(r, b[:]); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*e = binary.BigEndian.Uint16(b[:])
|
*e = binary.BigEndian.Uint16(b[:])
|
||||||
return nil
|
|
||||||
case *CreditsAmount:
|
case *CreditsAmount:
|
||||||
var b [8]byte
|
var b [8]byte
|
||||||
_, err = io.ReadFull(r, b[:])
|
if _, err := io.ReadFull(r, b[:]); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*e = CreditsAmount(int64(binary.BigEndian.Uint64(b[:])))
|
*e = CreditsAmount(int64(binary.BigEndian.Uint64(b[:])))
|
||||||
return nil
|
|
||||||
case *uint32:
|
case *uint32:
|
||||||
var b [4]byte
|
var b [4]byte
|
||||||
_, err = io.ReadFull(r, b[:])
|
if _, err := io.ReadFull(r, b[:]); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*e = binary.BigEndian.Uint32(b[:])
|
*e = binary.BigEndian.Uint32(b[:])
|
||||||
return nil
|
|
||||||
case *uint64:
|
case *uint64:
|
||||||
var b [8]byte
|
var b [8]byte
|
||||||
_, err = io.ReadFull(r, b[:])
|
if _, err := io.ReadFull(r, b[:]); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*e = binary.BigEndian.Uint64(b[:])
|
*e = binary.BigEndian.Uint64(b[:])
|
||||||
return nil
|
|
||||||
case *HTLCKey:
|
case *HTLCKey:
|
||||||
var b [8]byte
|
var b [8]byte
|
||||||
_, err = io.ReadFull(r, b[:])
|
if _, err := io.ReadFull(r, b[:]); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*e = HTLCKey(int64(binary.BigEndian.Uint64(b[:])))
|
*e = HTLCKey(int64(binary.BigEndian.Uint64(b[:])))
|
||||||
return nil
|
|
||||||
case *btcutil.Amount:
|
case *btcutil.Amount:
|
||||||
var b [8]byte
|
var b [8]byte
|
||||||
_, err = io.ReadFull(r, b[:])
|
if _, err := io.ReadFull(r, b[:]); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*e = btcutil.Amount(int64(binary.BigEndian.Uint64(b[:])))
|
*e = btcutil.Amount(int64(binary.BigEndian.Uint64(b[:])))
|
||||||
return nil
|
|
||||||
case **wire.ShaHash:
|
case **wire.ShaHash:
|
||||||
var b wire.ShaHash
|
var b wire.ShaHash
|
||||||
_, err = io.ReadFull(r, b[:])
|
if _, err := io.ReadFull(r, b[:]); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*e = &b
|
*e = &b
|
||||||
return nil
|
|
||||||
case **btcec.PublicKey:
|
case **btcec.PublicKey:
|
||||||
var b [33]byte
|
var b [33]byte
|
||||||
_, err = io.ReadFull(r, b[:])
|
if _, err = io.ReadFull(r, b[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
pubKey, err := btcec.ParsePubKey(b[:], btcec.S256())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
x, err := btcec.ParsePubKey(b[:], btcec.S256())
|
*e = pubKey
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*e = x
|
|
||||||
return nil
|
|
||||||
case *[]uint64:
|
case *[]uint64:
|
||||||
var numItems uint16
|
var numItems uint16
|
||||||
err = readElement(r, &numItems)
|
if err := readElement(r, &numItems); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// if numItems > 65535 {
|
// if numItems > 65535 {
|
||||||
@@ -425,7 +356,6 @@ func readElement(r io.Reader, element interface{}) error {
|
|||||||
items = append(items, item)
|
items = append(items, item)
|
||||||
}
|
}
|
||||||
*e = items
|
*e = items
|
||||||
return nil
|
|
||||||
case *[]*btcec.Signature:
|
case *[]*btcec.Signature:
|
||||||
var numSigs uint8
|
var numSigs uint8
|
||||||
err = readElement(r, &numSigs)
|
err = readElement(r, &numSigs)
|
||||||
@@ -449,39 +379,25 @@ func readElement(r io.Reader, element interface{}) error {
|
|||||||
*e = sigs
|
*e = sigs
|
||||||
return nil
|
return nil
|
||||||
case **btcec.Signature:
|
case **btcec.Signature:
|
||||||
var sigLength uint8
|
sigBytes, err := wire.ReadVarBytes(r, 0, 73, "signature")
|
||||||
err = readElement(r, &sigLength)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if sigLength > 73 {
|
sig, err := btcec.ParseSignature(sigBytes, btcec.S256())
|
||||||
return fmt.Errorf("Signature too long!")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the sig length
|
|
||||||
l := io.LimitReader(r, int64(sigLength))
|
|
||||||
sig, err := ioutil.ReadAll(l)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(sig) != int(sigLength) {
|
*e = sig
|
||||||
return fmt.Errorf("EOF: Signature length mismatch.")
|
case *[][20]byte:
|
||||||
}
|
|
||||||
btcecSig, err := btcec.ParseSignature(sig, btcec.S256())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*e = btcecSig
|
|
||||||
return nil
|
|
||||||
case *[]*[20]byte:
|
|
||||||
// How many to read
|
// How many to read
|
||||||
var sliceSize uint16
|
var sliceSize uint16
|
||||||
err = readElement(r, &sliceSize)
|
err = readElement(r, &sliceSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var data []*[20]byte
|
|
||||||
|
data := make([][20]byte, 0, sliceSize)
|
||||||
// Append the actual
|
// Append the actual
|
||||||
for i := uint16(0); i < sliceSize; i++ {
|
for i := uint16(0); i < sliceSize; i++ {
|
||||||
var element [20]byte
|
var element [20]byte
|
||||||
@@ -489,93 +405,42 @@ func readElement(r io.Reader, element interface{}) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
data = append(data, &element)
|
data = append(data, element)
|
||||||
}
|
}
|
||||||
*e = data
|
*e = data
|
||||||
return nil
|
|
||||||
case *[20]byte:
|
case *[20]byte:
|
||||||
_, err = io.ReadFull(r, e[:])
|
if _, err = io.ReadFull(r, e[:]); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
case *wire.BitcoinNet:
|
case *wire.BitcoinNet:
|
||||||
var b [4]byte
|
var b [4]byte
|
||||||
_, err := io.ReadFull(r, b[:])
|
if _, err := io.ReadFull(r, b[:]); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*e = wire.BitcoinNet(binary.BigEndian.Uint32(b[:]))
|
*e = wire.BitcoinNet(binary.BigEndian.Uint32(b[:]))
|
||||||
return nil
|
return nil
|
||||||
case *[]byte:
|
case *[]byte:
|
||||||
// Get the blob length first
|
bytes, err := wire.ReadVarBytes(r, 0, MaxSliceLength, "byte slice")
|
||||||
var blobLength uint16
|
|
||||||
err = readElement(r, &blobLength)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
*e = bytes
|
||||||
// Shouldn't need to do this, since it's uint16, but we
|
|
||||||
// might have a different value for MAX_SLICE_LENGTH...
|
|
||||||
if int(blobLength) > MAX_SLICE_LENGTH {
|
|
||||||
return fmt.Errorf("Slice length too long!")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the slice length
|
|
||||||
l := io.LimitReader(r, int64(blobLength))
|
|
||||||
*e, err = ioutil.ReadAll(l)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if len(*e) != int(blobLength) {
|
|
||||||
return fmt.Errorf("EOF: Slice length mismatch.")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
case *PkScript:
|
case *PkScript:
|
||||||
// Get the script length first
|
pkScript, err := wire.ReadVarBytes(r, 0, 25, "pkscript")
|
||||||
var scriptLength uint8
|
|
||||||
err = readElement(r, &scriptLength)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
*e = pkScript
|
||||||
if scriptLength > 25 {
|
|
||||||
return fmt.Errorf("PkScript too long!")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the script length
|
|
||||||
l := io.LimitReader(r, int64(scriptLength))
|
|
||||||
*e, err = ioutil.ReadAll(l)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if len(*e) != int(scriptLength) {
|
|
||||||
return fmt.Errorf("EOF: Signature length mismatch.")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
case *string:
|
case *string:
|
||||||
// Get the string length first
|
str, err := wire.ReadVarString(r, 0)
|
||||||
var strlen uint16
|
|
||||||
err = readElement(r, &strlen)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Read the string for the length
|
*e = str
|
||||||
l := io.LimitReader(r, int64(strlen))
|
|
||||||
b, err := ioutil.ReadAll(l)
|
|
||||||
if len(b) != int(strlen) {
|
|
||||||
return fmt.Errorf("EOF: String length mismatch.")
|
|
||||||
}
|
|
||||||
*e = string(b)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
case *[]*wire.TxIn:
|
case *[]*wire.TxIn:
|
||||||
// Read the size (1-byte number of txins)
|
// Read the size (1-byte number of txins)
|
||||||
var numScripts uint8
|
var numScripts uint8
|
||||||
err = readElement(r, &numScripts)
|
if err := readElement(r, &numScripts); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if numScripts > 127 {
|
if numScripts > 127 {
|
||||||
@@ -583,23 +448,20 @@ func readElement(r io.Reader, element interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Append the actual TxIns
|
// Append the actual TxIns
|
||||||
var txins []*wire.TxIn
|
txins := make([]*wire.TxIn, 0, numScripts)
|
||||||
for i := uint8(0); i < numScripts; i++ {
|
for i := uint8(0); i < numScripts; i++ {
|
||||||
outpoint := new(wire.OutPoint)
|
outpoint := new(wire.OutPoint)
|
||||||
txin := wire.NewTxIn(outpoint, nil, nil)
|
txin := wire.NewTxIn(outpoint, nil, nil)
|
||||||
err = readElement(r, &txin)
|
if err := readElement(r, &txin); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
txins = append(txins, txin)
|
txins = append(txins, txin)
|
||||||
}
|
}
|
||||||
*e = txins
|
*e = txins
|
||||||
return nil
|
|
||||||
case **wire.TxIn:
|
case **wire.TxIn:
|
||||||
// Hash
|
// Hash
|
||||||
var h [32]byte
|
var h [32]byte
|
||||||
_, err = io.ReadFull(r, h[:])
|
if _, err = io.ReadFull(r, h[:]); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
hash, err := wire.NewShaHash(h[:])
|
hash, err := wire.NewShaHash(h[:])
|
||||||
@@ -607,6 +469,7 @@ func readElement(r io.Reader, element interface{}) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
(*e).PreviousOutPoint.Hash = *hash
|
(*e).PreviousOutPoint.Hash = *hash
|
||||||
|
|
||||||
// Index
|
// Index
|
||||||
var idxBytes [4]byte
|
var idxBytes [4]byte
|
||||||
_, err = io.ReadFull(r, idxBytes[:])
|
_, err = io.ReadFull(r, idxBytes[:])
|
||||||
@@ -622,6 +485,9 @@ func readElement(r io.Reader, element interface{}) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// readElements deserializes a variable number of elements into the passed
|
||||||
|
// io.Reader, with each element being deserialized according to the readElement
|
||||||
|
// function.
|
||||||
func readElements(r io.Reader, elements ...interface{}) error {
|
func readElements(r io.Reader, elements ...interface{}) error {
|
||||||
for _, element := range elements {
|
for _, element := range elements {
|
||||||
err := readElement(r, element)
|
err := readElement(r, element)
|
||||||
|
|||||||
Reference in new issue
Block a user