func fetchChanFundingInfo(nodeChanBucket *bolt.Bucket, channel *OpenChannel) error { var b bytes.Buffer if err := writeOutpoint(&b, channel.ChanID); err != nil { return err } fundTxnKey := make([]byte, len(fundingTxnKey)+b.Len()) copy(fundTxnKey[:3], fundingTxnKey) copy(fundTxnKey[3:], b.Bytes()) infoBytes := bytes.NewReader(nodeChanBucket.Get(fundTxnKey)) // TODO(roasbeef): can remove as channel ID *is* the funding point now. channel.FundingOutpoint = &wire.OutPoint{} if err := readOutpoint(infoBytes, channel.FundingOutpoint); err != nil { return err } ourKeyBytes, err := wire.ReadVarBytes(infoBytes, 0, 34, "") if err != nil { return err } channel.OurMultiSigKey, err = btcec.ParsePubKey(ourKeyBytes, btcec.S256()) if err != nil { return err } theirKeyBytes, err := wire.ReadVarBytes(infoBytes, 0, 34, "") if err != nil { return err } channel.TheirMultiSigKey, err = btcec.ParsePubKey(theirKeyBytes, btcec.S256()) if err != nil { return err } channel.FundingWitnessScript, err = wire.ReadVarBytes(infoBytes, 0, 520, "") if err != nil { return err } scratch := make([]byte, 8) if _, err := infoBytes.Read(scratch); err != nil { return err } unixSecs := byteOrder.Uint64(scratch) channel.CreationTime = time.Unix(int64(unixSecs), 0) return nil }
func fetchChanElkremState(nodeChanBucket *bolt.Bucket, channel *OpenChannel) error { var b bytes.Buffer if err := writeOutpoint(&b, channel.ChanID); err != nil { return err } elkremKey := make([]byte, len(elkremStateKey)+b.Len()) copy(elkremKey[:3], elkremStateKey) copy(elkremKey[3:], b.Bytes()) elkremStateBytes := bytes.NewReader(nodeChanBucket.Get(elkremKey)) revKeyBytes, err := wire.ReadVarBytes(elkremStateBytes, 0, 1000, "") if err != nil { return err } channel.TheirCurrentRevocation, err = btcec.ParsePubKey(revKeyBytes, btcec.S256()) if err != nil { return err } if _, err := elkremStateBytes.Read(channel.TheirCurrentRevocationHash[:]); err != nil { return err } // TODO(roasbeef): should be rederiving on fly, or encrypting on disk. senderBytes, err := wire.ReadVarBytes(elkremStateBytes, 0, 1000, "") if err != nil { return err } elkremRoot, err := wire.NewShaHash(senderBytes) if err != nil { return err } channel.LocalElkrem = elkrem.NewElkremSender(*elkremRoot) reciverBytes, err := wire.ReadVarBytes(elkremStateBytes, 0, 1000, "") if err != nil { return err } remoteE, err := elkrem.ElkremReceiverFromBytes(reciverBytes) if err != nil { return err } channel.RemoteElkrem = remoteE return nil }
func deserializeInvoice(r io.Reader) (*Invoice, error) { var err error invoice := &Invoice{} // TODO(roasbeef): use read full everywhere invoice.Memo, err = wire.ReadVarBytes(r, 0, MaxMemoSize, "") if err != nil { return nil, err } invoice.Receipt, err = wire.ReadVarBytes(r, 0, MaxReceiptSize, "") if err != nil { return nil, err } birthBytes, err := wire.ReadVarBytes(r, 0, 300, "birth") if err != nil { return nil, err } if err := invoice.CreationDate.UnmarshalBinary(birthBytes); err != nil { return nil, err } if _, err := io.ReadFull(r, invoice.Terms.PaymentPreimage[:]); err != nil { return nil, err } var scratch [8]byte if _, err := io.ReadFull(r, scratch[:]); err != nil { return nil, err } invoice.Terms.Value = btcutil.Amount(byteOrder.Uint64(scratch[:])) var settleByte [1]byte if _, err := io.ReadFull(r, settleByte[:]); err != nil { return nil, err } if settleByte[0] == 1 { invoice.Terms.Settled = true } return invoice, nil }
func fetchChanDeliveryScripts(nodeChanBucket *bolt.Bucket, channel *OpenChannel) error { var b bytes.Buffer if err := writeOutpoint(&b, channel.ChanID); err != nil { return err } deliveryKey := make([]byte, len(deliveryScriptsKey)+b.Len()) copy(deliveryKey[:3], deliveryScriptsKey) copy(deliveryKey[3:], b.Bytes()) var err error deliveryBytes := bytes.NewReader(nodeChanBucket.Get(deliveryScriptsKey)) channel.OurDeliveryScript, err = wire.ReadVarBytes(deliveryBytes, 0, 520, "") if err != nil { return err } channel.TheirDeliveryScript, err = wire.ReadVarBytes(deliveryBytes, 0, 520, "") if err != nil { return err } return nil }
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 fetchChanCommitTxns(nodeChanBucket *bolt.Bucket, channel *OpenChannel) error { var bc bytes.Buffer var err error if err = writeOutpoint(&bc, channel.ChanID); err != nil { return err } txnsKey := make([]byte, len(commitTxnsKey)+bc.Len()) copy(txnsKey[:3], commitTxnsKey) copy(txnsKey[3:], bc.Bytes()) txnBytes := bytes.NewReader(nodeChanBucket.Get(txnsKey)) channel.OurCommitTx = wire.NewMsgTx() if err = channel.OurCommitTx.Deserialize(txnBytes); err != nil { return err } channel.OurCommitSig, err = wire.ReadVarBytes(txnBytes, 0, 80, "") if err != nil { return err } scratch := make([]byte, 4) if _, err := txnBytes.Read(scratch); err != nil { return err } channel.LocalCsvDelay = byteOrder.Uint32(scratch) if _, err := txnBytes.Read(scratch); err != nil { return err } channel.RemoteCsvDelay = byteOrder.Uint32(scratch) 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 { var err error switch e := element.(type) { case *uint8: var b [1]uint8 if _, err := r.Read(b[:]); err != nil { return err } *e = b[0] case *uint16: var b [2]byte if _, err := io.ReadFull(r, b[:]); err != nil { return err } *e = binary.BigEndian.Uint16(b[:]) case *ErrorCode: var b [2]byte if _, err := io.ReadFull(r, b[:]); err != nil { return err } *e = ErrorCode(binary.BigEndian.Uint16(b[:])) case *CreditsAmount: var b [8]byte if _, err := io.ReadFull(r, b[:]); err != nil { return err } *e = CreditsAmount(int64(binary.BigEndian.Uint64(b[:]))) case *uint32: var b [4]byte if _, err := io.ReadFull(r, b[:]); err != nil { return err } *e = binary.BigEndian.Uint32(b[:]) case *uint64: var b [8]byte if _, err := io.ReadFull(r, b[:]); err != nil { return err } *e = binary.BigEndian.Uint64(b[:]) case *HTLCKey: var b [8]byte if _, err := io.ReadFull(r, b[:]); err != nil { return err } *e = HTLCKey(int64(binary.BigEndian.Uint64(b[:]))) case *btcutil.Amount: var b [8]byte if _, err := io.ReadFull(r, b[:]); err != nil { return err } *e = btcutil.Amount(int64(binary.BigEndian.Uint64(b[:]))) case **wire.ShaHash: var b wire.ShaHash if _, err := io.ReadFull(r, b[:]); err != nil { return err } *e = &b case **btcec.PublicKey: var b [33]byte if _, err = io.ReadFull(r, b[:]); err != nil { return err } pubKey, err := btcec.ParsePubKey(b[:], btcec.S256()) if err != nil { return err } *e = pubKey case *[]uint64: var numItems uint16 if err := readElement(r, &numItems); err != nil { return err } // if numItems > 65535 { // return fmt.Errorf("Too many items in []uint64") // } // Read the number of items 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) } *e = items case *[]*btcec.Signature: var numSigs uint8 err = readElement(r, &numSigs) if err != nil { return err } if numSigs > 127 { return fmt.Errorf("Too many signatures!") } // Read that number of signatures var sigs []*btcec.Signature for i := uint8(0); i < numSigs; i++ { sig := new(btcec.Signature) err = readElement(r, &sig) if err != nil { return err } sigs = append(sigs, sig) } *e = sigs return nil case **btcec.Signature: sigBytes, err := wire.ReadVarBytes(r, 0, 73, "signature") if err != nil { return err } sig, err := btcec.ParseSignature(sigBytes, btcec.S256()) if err != nil { return err } *e = sig case *[][32]byte: // How many to read var sliceSize uint16 err = readElement(r, &sliceSize) if err != nil { return err } data := make([][32]byte, 0, sliceSize) // Append the actual for i := uint16(0); i < sliceSize; i++ { var element [32]byte err = readElement(r, &element) if err != nil { return err } data = append(data, element) } *e = data case *[32]byte: if _, err = io.ReadFull(r, e[:]); err != nil { return err } case *wire.BitcoinNet: var b [4]byte if _, err := io.ReadFull(r, b[:]); err != nil { return err } *e = wire.BitcoinNet(binary.BigEndian.Uint32(b[:])) return nil case *[]byte: bytes, err := wire.ReadVarBytes(r, 0, MaxSliceLength, "byte slice") if err != nil { return err } *e = bytes case *PkScript: pkScript, err := wire.ReadVarBytes(r, 0, 25, "pkscript") if err != nil { return err } *e = pkScript case *string: str, err := wire.ReadVarString(r, 0) if err != nil { return err } *e = str case *[]*wire.TxIn: // Read the size (1-byte number of txins) var numScripts uint8 if err := readElement(r, &numScripts); err != nil { return err } if numScripts > 127 { return fmt.Errorf("Too many txins") } // Append the actual TxIns txins := make([]*wire.TxIn, 0, numScripts) for i := uint8(0); i < numScripts; i++ { outpoint := new(wire.OutPoint) txin := wire.NewTxIn(outpoint, nil, nil) if err := readElement(r, &txin); err != nil { return err } txins = append(txins, txin) } *e = txins case **wire.TxIn: // Hash var h [32]byte if _, err = io.ReadFull(r, h[:]); err != nil { return err } hash, err := wire.NewShaHash(h[:]) if err != nil { return err } (*e).PreviousOutPoint.Hash = *hash // Index var idxBytes [4]byte _, err = io.ReadFull(r, idxBytes[:]) if err != nil { return err } (*e).PreviousOutPoint.Index = binary.BigEndian.Uint32(idxBytes[:]) return nil case **wire.OutPoint: // TODO(roasbeef): consolidate with above var h [32]byte if _, err = io.ReadFull(r, h[:]); err != nil { return err } hash, err := wire.NewShaHash(h[:]) if err != nil { return err } // Index var idxBytes [4]byte _, err = io.ReadFull(r, idxBytes[:]) if err != nil { return err } index := binary.BigEndian.Uint32(idxBytes[:]) *e = wire.NewOutPoint(hash, index) default: return fmt.Errorf("Unknown type in readElement: %T", e) } return nil }