lnw+ba+utxon+cdb: reverts OutPoint and TxOut encoding

This commit is contained in:
Conner Fromknecht 2017-07-25 20:39:59 -07:00 committed by Olaoluwa Osuntokun
parent 8698085e35
commit 6ffe33f01a
8 changed files with 148 additions and 148 deletions

@ -15,7 +15,6 @@ import (
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/htlcswitch"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/roasbeef/btcd/chaincfg/chainhash"
"github.com/roasbeef/btcd/txscript"
"github.com/roasbeef/btcd/wire"
@ -676,7 +675,6 @@ type retributionInfo struct {
// the channel's contract by the counterparty. This function returns a *fully*
// signed transaction with the witness for each input fully in place.
func (b *breachArbiter) createJusticeTx(r *retributionInfo) (*wire.MsgTx, error) {
// First, we obtain a new public key script from the wallet which we'll
// sweep the funds to.
// TODO(roasbeef): possibly create many outputs to minimize change in
@ -854,7 +852,7 @@ func (rs *retributionStore) Add(ret *retributionInfo) error {
}
var outBuf bytes.Buffer
if err := lnwire.WriteOutPoint(&outBuf, &ret.chanPoint); err != nil {
if err := writeOutpoint(&outBuf, &ret.chanPoint); err != nil {
return err
}
@ -885,7 +883,7 @@ func (rs *retributionStore) Remove(key *wire.OutPoint) error {
}
var outBuf bytes.Buffer
if err := lnwire.WriteOutPoint(&outBuf, key); err != nil {
if err := writeOutpoint(&outBuf, key); err != nil {
return err
}
@ -926,7 +924,7 @@ func (ret *retributionInfo) Encode(w io.Writer) error {
return err
}
if err := lnwire.WriteOutPoint(w, &ret.chanPoint); err != nil {
if err := writeOutpoint(w, &ret.chanPoint); err != nil {
return err
}
@ -965,7 +963,7 @@ func (ret *retributionInfo) Decode(r io.Reader) error {
}
ret.commitHash = *hash
if err := lnwire.ReadOutPoint(r, &ret.chanPoint); err != nil {
if err := readOutpoint(r, &ret.chanPoint); err != nil {
return err
}
@ -1005,7 +1003,7 @@ func (bo *breachedOutput) Encode(w io.Writer) error {
return err
}
if err := lnwire.WriteOutPoint(w, &bo.outpoint); err != nil {
if err := writeOutpoint(w, &bo.outpoint); err != nil {
return err
}
@ -1039,7 +1037,7 @@ func (bo *breachedOutput) Decode(r io.Reader) error {
}
bo.amt = btcutil.Amount(binary.BigEndian.Uint64(scratch[:8]))
if err := lnwire.ReadOutPoint(r, &bo.outpoint); err != nil {
if err := readOutpoint(r, &bo.outpoint); err != nil {
return err
}

@ -380,7 +380,7 @@ func (c *OpenChannel) fullSync(tx *bolt.Tx) error {
return err
}
var b bytes.Buffer
if err := writeOutpoint(&b, c.ChanID); err != nil {
if err := writeOutpoint(&b, &c.FundingOutpoint); err != nil {
return err
}
if chanIndexBucket.Get(b.Bytes()) == nil {
@ -871,7 +871,7 @@ func (c *OpenChannel) CloseChannel(summary *ChannelCloseSummary) error {
}
var b bytes.Buffer
if err := writeOutpoint(&b, c.ChanID); err != nil {
if err := writeOutpoint(&b, &c.FundingOutpoint); err != nil {
return err
}
@ -1245,7 +1245,7 @@ func putChanCapacity(openChanBucket *bolt.Bucket, channel *OpenChannel) error {
scratch3 := make([]byte, 8)
var b bytes.Buffer
if err := writeOutpoint(&b, channel.ChanID); err != nil {
if err := writeOutpoint(&b, &channel.FundingOutpoint); err != nil {
return err
}
@ -1290,7 +1290,7 @@ func deleteChanCapacity(openChanBucket *bolt.Bucket, chanID []byte) error {
func fetchChanCapacity(openChanBucket *bolt.Bucket, channel *OpenChannel) error {
// A byte slice re-used to compute each key prefix below.
var b bytes.Buffer
if err := writeOutpoint(&b, channel.ChanID); err != nil {
if err := writeOutpoint(&b, &channel.FundingOutpoint); err != nil {
return err
}
@ -1317,7 +1317,7 @@ func putChanFeePerKw(openChanBucket *bolt.Bucket, channel *OpenChannel) error {
byteOrder.PutUint64(scratch, uint64(channel.FeePerKw))
var b bytes.Buffer
if err := writeOutpoint(&b, channel.ChanID); err != nil {
if err := writeOutpoint(&b, &channel.FundingOutpoint); err != nil {
return err
}
@ -1337,7 +1337,7 @@ func deleteChanMinFeePerKw(openChanBucket *bolt.Bucket, chanID []byte) error {
func fetchChanMinFeePerKw(openChanBucket *bolt.Bucket, channel *OpenChannel) error {
var b bytes.Buffer
if err := writeOutpoint(&b, channel.ChanID); err != nil {
if err := writeOutpoint(&b, &channel.FundingOutpoint); err != nil {
return err
}
@ -1356,7 +1356,7 @@ func putChanNumUpdates(openChanBucket *bolt.Bucket, channel *OpenChannel) error
byteOrder.PutUint64(scratch, channel.NumUpdates)
var b bytes.Buffer
if err := writeOutpoint(&b, channel.ChanID); err != nil {
if err := writeOutpoint(&b, &channel.FundingOutpoint); err != nil {
return err
}
@ -1376,7 +1376,7 @@ func deleteChanNumUpdates(openChanBucket *bolt.Bucket, chanID []byte) error {
func fetchChanNumUpdates(openChanBucket *bolt.Bucket, channel *OpenChannel) error {
var b bytes.Buffer
if err := writeOutpoint(&b, channel.ChanID); err != nil {
if err := writeOutpoint(&b, &channel.FundingOutpoint); err != nil {
return err
}
@ -1395,7 +1395,7 @@ func putChanAmountsTransferred(openChanBucket *bolt.Bucket, channel *OpenChannel
scratch2 := make([]byte, 8)
var b bytes.Buffer
if err := writeOutpoint(&b, channel.ChanID); err != nil {
if err := writeOutpoint(&b, &channel.FundingOutpoint); err != nil {
return err
}
@ -1428,7 +1428,7 @@ func deleteChanAmountsTransferred(openChanBucket *bolt.Bucket, chanID []byte) er
func fetchChanAmountsTransferred(openChanBucket *bolt.Bucket, channel *OpenChannel) error {
var b bytes.Buffer
if err := writeOutpoint(&b, channel.ChanID); err != nil {
if err := writeOutpoint(&b, &channel.FundingOutpoint); err != nil {
return err
}
@ -1450,7 +1450,7 @@ func putChanIsPending(openChanBucket *bolt.Bucket, channel *OpenChannel) error {
scratch := make([]byte, 2)
var b bytes.Buffer
if err := writeOutpoint(&b, channel.ChanID); err != nil {
if err := writeOutpoint(&b, &channel.FundingOutpoint); err != nil {
return err
}
@ -1476,7 +1476,7 @@ func deleteChanIsPending(openChanBucket *bolt.Bucket, chanID []byte) error {
func fetchChanIsPending(openChanBucket *bolt.Bucket, channel *OpenChannel) error {
var b bytes.Buffer
if err := writeOutpoint(&b, channel.ChanID); err != nil {
if err := writeOutpoint(&b, &channel.FundingOutpoint); err != nil {
return err
}
@ -1541,7 +1541,7 @@ func deleteChanConfInfo(openChanBucket *bolt.Bucket, chanID []byte) error {
func putChannelIDs(nodeChanBucket *bolt.Bucket, channel *OpenChannel) error {
// TODO(roasbeef): just pass in chanID everywhere for puts
var b bytes.Buffer
if err := writeOutpoint(&b, channel.ChanID); err != nil {
if err := writeOutpoint(&b, &channel.FundingOutpoint); err != nil {
return err
}
@ -1568,7 +1568,7 @@ func fetchChannelIDs(nodeChanBucket *bolt.Bucket, channel *OpenChannel) error {
b bytes.Buffer
)
if err = writeOutpoint(&b, channel.ChanID); err != nil {
if err = writeOutpoint(&b, &channel.FundingOutpoint); err != nil {
return err
}
@ -1658,7 +1658,7 @@ func deleteChanCommitTxns(nodeChanBucket *bolt.Bucket, chanID []byte) error {
func fetchChanCommitTxns(nodeChanBucket *bolt.Bucket, channel *OpenChannel) error {
var bc bytes.Buffer
var err error
if err = writeOutpoint(&bc, channel.ChanID); err != nil {
if err = writeOutpoint(&bc, &channel.FundingOutpoint); err != nil {
return err
}
txnsKey := make([]byte, len(commitTxnsKey)+bc.Len())
@ -1745,7 +1745,7 @@ func putChanConfigs(nodeChanBucket *bolt.Bucket, channel *OpenChannel) error {
func fetchChanConfigs(nodeChanBucket *bolt.Bucket, channel *OpenChannel) error {
var bc bytes.Buffer
if err := writeOutpoint(&bc, channel.ChanID); err != nil {
if err := writeOutpoint(&bc, &channel.FundingOutpoint); err != nil {
return err
}
configKey := make([]byte, len(chanConfigPrefix)+len(bc.Bytes()))
@ -1885,7 +1885,7 @@ func deleteChanFundingInfo(nodeChanBucket *bolt.Bucket, chanID []byte) error {
func fetchChanFundingInfo(nodeChanBucket *bolt.Bucket, channel *OpenChannel) error {
var b bytes.Buffer
if err := writeOutpoint(&b, channel.ChanID); err != nil {
if err := writeOutpoint(&b, &channel.FundingOutpoint); err != nil {
return err
}
fundTxnKey := make([]byte, len(fundingTxnKey)+b.Len())
@ -1971,7 +1971,7 @@ func deleteChanRevocationState(nodeChanBucket *bolt.Bucket, chanID []byte) error
func fetchChanRevocationState(nodeChanBucket *bolt.Bucket, channel *OpenChannel) error {
var b bytes.Buffer
if err := writeOutpoint(&b, channel.ChanID); err != nil {
if err := writeOutpoint(&b, &channel.FundingOutpoint); err != nil {
return err
}
preimageKey := make([]byte, len(revocationStateKey)+b.Len())

@ -269,7 +269,7 @@ func (d *DB) fetchNodeChannels(openChanBucket,
outBytes := bytes.NewReader(k)
chanID := &wire.OutPoint{}
if err := lnwire.ReadOutPoint(outBytes, chanID); err != nil {
if err := readOutpoint(outBytes, chanID); err != nil {
return err
}
@ -373,7 +373,7 @@ func (d *DB) MarkChannelAsOpen(outpoint *wire.OutPoint,
// Generate the database key, which will consist of the
// IsPending prefix followed by the channel's outpoint.
var b bytes.Buffer
if err := lnwire.WriteOutPoint(&b, outpoint); err != nil {
if err := writeOutpoint(&b, outpoint); err != nil {
return err
}
keyPrefix := make([]byte, 3+b.Len())
@ -455,7 +455,7 @@ func (d *DB) FetchClosedChannels(pendingOnly bool) ([]*ChannelCloseSummary, erro
func (d *DB) MarkChanFullyClosed(chanPoint *wire.OutPoint) error {
return d.Update(func(tx *bolt.Tx) error {
var b bytes.Buffer
if err := lnwire.WriteOutPoint(&b, chanPoint); err != nil {
if err := writeOutpoint(&b, chanPoint); err != nil {
return err
}

@ -456,7 +456,7 @@ func (c *ChannelGraph) AddChannelEdge(edge *ChannelEdgeInfo) error {
// Finally we add it to the channel index which maps channel
// points (outpoints) to the shorter channel ID's.
var b bytes.Buffer
if err := lnwire.WriteOutPoint(&b, &edge.ChannelPoint); err != nil {
if err := writeOutpoint(&b, &edge.ChannelPoint); err != nil {
return err
}
return chanIndex.Put(b.Bytes(), chanKey[:])
@ -600,7 +600,7 @@ func (c *ChannelGraph) PruneGraph(spentOutputs []*wire.OutPoint,
// if NOT if filter
var opBytes bytes.Buffer
if err := lnwire.WriteOutPoint(&opBytes, chanPoint); err != nil {
if err := writeOutpoint(&opBytes, chanPoint); err != nil {
return nil
}
@ -724,7 +724,7 @@ func (c *ChannelGraph) ChannelID(chanPoint *wire.OutPoint) (uint64, error) {
var chanID uint64
var b bytes.Buffer
if err := lnwire.WriteOutPoint(&b, chanPoint); err != nil {
if err := writeOutpoint(&b, chanPoint); err != nil {
return 0, nil
}
@ -756,7 +756,7 @@ func (c *ChannelGraph) ChannelID(chanPoint *wire.OutPoint) (uint64, error) {
func delChannelByEdge(edges *bolt.Bucket, edgeIndex *bolt.Bucket,
chanIndex *bolt.Bucket, chanPoint *wire.OutPoint) error {
var b bytes.Buffer
if err := lnwire.WriteOutPoint(&b, chanPoint); err != nil {
if err := writeOutpoint(&b, chanPoint); err != nil {
return err
}
@ -1271,7 +1271,7 @@ func (c *ChannelGraph) FetchChannelEdgesByOutpoint(op *wire.OutPoint) (*ChannelE
return err
}
var b bytes.Buffer
if err := lnwire.WriteOutPoint(&b, op); err != nil {
if err := writeOutpoint(&b, op); err != nil {
return err
}
chanID := chanIndex.Get(b.Bytes())
@ -1692,7 +1692,7 @@ func putChanEdgeInfo(edgeIndex *bolt.Bucket, edgeInfo *ChannelEdgeInfo, chanID [
return err
}
if err := lnwire.WriteOutPoint(&b, &edgeInfo.ChannelPoint); err != nil {
if err := writeOutpoint(&b, &edgeInfo.ChannelPoint); err != nil {
return err
}
if err := binary.Write(&b, byteOrder, uint64(edgeInfo.Capacity)); err != nil {
@ -1794,7 +1794,7 @@ func deserializeChanEdgeInfo(r io.Reader) (*ChannelEdgeInfo, error) {
}
edgeInfo.ChannelPoint = wire.OutPoint{}
if err := lnwire.ReadOutPoint(r, &edgeInfo.ChannelPoint); err != nil {
if err := readOutpoint(r, &edgeInfo.ChannelPoint); err != nil {
return nil, err
}
if err := binary.Read(r, byteOrder, &edgeInfo.Capacity); err != nil {

@ -4,11 +4,13 @@ import (
"encoding/binary"
"fmt"
"io"
"math"
"net"
"github.com/go-errors/errors"
"github.com/roasbeef/btcd/btcec"
"github.com/roasbeef/btcd/chaincfg/chainhash"
"github.com/roasbeef/btcd/wire"
"github.com/roasbeef/btcutil"
)
@ -187,7 +189,21 @@ func writeElement(w io.Writer, element interface{}) error {
}
case wire.OutPoint:
if err := WriteOutPoint(w, &e); err != nil {
var h [32]byte
copy(h[:], e.Hash[:])
if _, err := w.Write(h[:]); err != nil {
return err
}
if e.Index > math.MaxUint16 {
return fmt.Errorf("index for outpoint (%v) is "+
"greater than max index of %v", e.Index,
math.MaxUint16)
}
var idx [2]byte
binary.BigEndian.PutUint16(idx[:], uint16(e.Index))
if _, err := w.Write(idx[:]); err != nil {
return err
}
@ -463,10 +479,30 @@ func readElement(r io.Reader, element interface{}) error {
}
*e = pkScript
case *wire.OutPoint:
if err := ReadOutPoint(r, e); err != nil {
var h [32]byte
if _, err = io.ReadFull(r, h[:]); err != nil {
return err
}
hash, err := chainhash.NewHash(h[:])
if err != nil {
return err
}
var idxBytes [2]byte
_, err = io.ReadFull(r, idxBytes[:])
if err != nil {
return err
}
index := binary.BigEndian.Uint16(idxBytes[:])
*e = wire.OutPoint{
Hash: *hash,
Index: uint32(index),
}
case *FailCode:
if err := readElement(r, (*uint16)(e)); err != nil {
return err
}
case *ChannelID:
if _, err := io.ReadFull(r, e[:]); err != nil {
return err

@ -1,59 +0,0 @@
package lnwire
import (
"encoding/binary"
"fmt"
"io"
"math"
"github.com/roasbeef/btcd/chaincfg/chainhash"
"github.com/roasbeef/btcd/wire"
)
// WriteOutPoint serializes a wire.OutPoint struct into the passed io.Writer
// stream.
func WriteOutPoint(w io.Writer, o *wire.OutPoint) error {
if _, err := w.Write(o.Hash[:chainhash.HashSize]); err != nil {
return err
}
if o.Index > math.MaxUint16 {
return fmt.Errorf("index for outpoint (%v) is "+
"greater than max index of %v", o.Index, math.MaxUint16)
}
var idx [2]byte
binary.BigEndian.PutUint16(idx[:], uint16(o.Index))
if _, err := w.Write(idx[:]); err != nil {
return err
}
return nil
}
// ReadOutPoint deserializes a wire.OutPoint struct from the passed io.Reader
// stream.
func ReadOutPoint(r io.Reader, o *wire.OutPoint) error {
var h [chainhash.HashSize]byte
if _, err := io.ReadFull(r, h[:]); err != nil {
return err
}
hash, err := chainhash.NewHash(h[:])
if err != nil {
return err
}
var idxBytes [2]byte
_, err = io.ReadFull(r, idxBytes[:])
if err != nil {
return err
}
index := binary.BigEndian.Uint16(idxBytes[:])
*o = wire.OutPoint{
Hash: *hash,
Index: uint32(index),
}
return nil
}

@ -1,40 +0,0 @@
package lnwire
import (
"bytes"
"reflect"
"testing"
"github.com/roasbeef/btcd/chaincfg/chainhash"
"github.com/roasbeef/btcd/wire"
)
func TestOutpointSerialization(t *testing.T) {
outpoint := wire.OutPoint{
Hash: [chainhash.HashSize]byte{
0x51, 0xb6, 0x37, 0xd8, 0xfc, 0xd2, 0xc6, 0xda,
0x48, 0x59, 0xe6, 0x96, 0x31, 0x13, 0xa1, 0x17,
0x2d, 0xe7, 0x93, 0xe4, 0xb7, 0x25, 0xb8, 0x4d,
0x1f, 0xb, 0x4c, 0xf9, 0x9e, 0xc5, 0x8c, 0xe9,
},
Index: 9,
}
var buf bytes.Buffer
if err := WriteOutPoint(&buf, &outpoint); err != nil {
t.Fatalf("unable to serialize outpoint: %v", err)
}
var deserializedOutpoint wire.OutPoint
if err := ReadOutPoint(&buf, &deserializedOutpoint); err != nil {
t.Fatalf("unable to deserialize outpoint: %v", err)
}
if !reflect.DeepEqual(outpoint, deserializedOutpoint) {
t.Fatalf("original and deserialized outpoints are different:\n"+
"original : %+v\n"+
"deserialized : %+v\n",
outpoint, deserializedOutpoint)
}
}

@ -14,7 +14,6 @@ import (
"github.com/lightningnetwork/lnd/chainntnfs"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/roasbeef/btcd/txscript"
"github.com/roasbeef/btcd/wire"
"github.com/roasbeef/btcutil"
@ -441,7 +440,7 @@ func (u *utxoNursery) NurseryReport(chanPoint *wire.OutPoint) (*contractMaturity
}
var b bytes.Buffer
if err := lnwire.WriteOutPoint(&b, chanPoint); err != nil {
if err := writeOutpoint(&b, chanPoint); err != nil {
return err
}
chanPointBytes := b.Bytes()
@ -547,7 +546,7 @@ func (k *kidOutput) enterPreschool(db *channeldb.DB) error {
// Once we have the buckets we can insert the raw bytes of the
// immature outpoint into the preschool bucket.
var outpointBytes bytes.Buffer
if err := lnwire.WriteOutPoint(&outpointBytes, &k.outPoint); err != nil {
if err := writeOutpoint(&outpointBytes, &k.outPoint); err != nil {
return err
}
var kidBytes bytes.Buffer
@ -563,7 +562,7 @@ func (k *kidOutput) enterPreschool(db *channeldb.DB) error {
// track all the immature outpoints for a particular channel's
// chanPoint.
var b bytes.Buffer
err = lnwire.WriteOutPoint(&b, &k.originChanPoint)
err = writeOutpoint(&b, &k.originChanPoint)
if err != nil {
return err
}
@ -604,7 +603,7 @@ func (k *kidOutput) waitForPromotion(db *channeldb.DB, confChan *chainntnfs.Conf
// array form prior to database insertion.
err := db.Update(func(tx *bolt.Tx) error {
var originPoint bytes.Buffer
if err := lnwire.WriteOutPoint(&originPoint, &k.originChanPoint); err != nil {
if err := writeOutpoint(&originPoint, &k.originChanPoint); err != nil {
return err
}
@ -621,7 +620,7 @@ func (k *kidOutput) waitForPromotion(db *channeldb.DB, confChan *chainntnfs.Conf
// along in the maturity pipeline we first delete the entry
// from the preschool bucket, as well as the secondary index.
var outpointBytes bytes.Buffer
if err := lnwire.WriteOutPoint(&outpointBytes, &k.outPoint); err != nil {
if err := writeOutpoint(&outpointBytes, &k.outPoint); err != nil {
return err
}
if err := psclBucket.Delete(outpointBytes.Bytes()); err != nil {
@ -916,7 +915,7 @@ func deleteGraduatedOutputs(db *channeldb.DB, deleteHeight uint32) error {
}
for _, sweptOutput := range sweptOutputs {
var chanPoint bytes.Buffer
err := lnwire.WriteOutPoint(&chanPoint, &sweptOutput.originChanPoint)
err := writeOutpoint(&chanPoint, &sweptOutput.originChanPoint)
if err != nil {
return err
}
@ -990,10 +989,10 @@ func serializeKidOutput(w io.Writer, kid *kidOutput) error {
return err
}
if err := lnwire.WriteOutPoint(w, &kid.outPoint); err != nil {
if err := writeOutpoint(w, &kid.outPoint); err != nil {
return err
}
if err := lnwire.WriteOutPoint(w, &kid.originChanPoint); err != nil {
if err := writeOutpoint(w, &kid.originChanPoint); err != nil {
return err
}
@ -1047,12 +1046,12 @@ func deserializeKidOutput(r io.Reader) (*kidOutput, error) {
}
kid.amt = btcutil.Amount(byteOrder.Uint64(scratch[:]))
err := lnwire.ReadOutPoint(io.LimitReader(r, 40), &kid.outPoint)
err := readOutpoint(io.LimitReader(r, 40), &kid.outPoint)
if err != nil {
return nil, err
}
err = lnwire.ReadOutPoint(io.LimitReader(r, 40), &kid.originChanPoint)
err = readOutpoint(io.LimitReader(r, 40), &kid.originChanPoint)
if err != nil {
return nil, err
}
@ -1109,3 +1108,69 @@ func deserializeKidOutput(r io.Reader) (*kidOutput, error) {
return kid, nil
}
// TODO(bvu): copied from channeldb, remove repetition
func writeOutpoint(w io.Writer, o *wire.OutPoint) error {
// TODO(roasbeef): make all scratch buffers on the stack
scratch := make([]byte, 4)
// TODO(roasbeef): write raw 32 bytes instead of wasting the extra
// byte.
if err := wire.WriteVarBytes(w, 0, o.Hash[:]); err != nil {
return err
}
byteOrder.PutUint32(scratch, o.Index)
_, err := w.Write(scratch)
return err
}
// TODO(bvu): copied from channeldb, remove repetition
func readOutpoint(r io.Reader, o *wire.OutPoint) error {
scratch := make([]byte, 4)
txid, err := wire.ReadVarBytes(r, 0, 32, "prevout")
if err != nil {
return err
}
copy(o.Hash[:], txid)
if _, err := r.Read(scratch); err != nil {
return err
}
o.Index = byteOrder.Uint32(scratch)
return nil
}
func writeTxOut(w io.Writer, txo *wire.TxOut) error {
scratch := make([]byte, 8)
byteOrder.PutUint64(scratch, uint64(txo.Value))
if _, err := w.Write(scratch); err != nil {
return err
}
if err := wire.WriteVarBytes(w, 0, txo.PkScript); err != nil {
return err
}
return nil
}
func readTxOut(r io.Reader, txo *wire.TxOut) error {
scratch := make([]byte, 8)
if _, err := r.Read(scratch); err != nil {
return err
}
txo.Value = int64(byteOrder.Uint64(scratch))
pkScript, err := wire.ReadVarBytes(r, 0, 80, "pkScript")
if err != nil {
return err
}
txo.PkScript = pkScript
return nil
}