channeldb/migration12: copy invoice deserialization
This commit is contained in:
parent
c6a01f02cd
commit
0f8048d336
234
channeldb/migration12/invoices.go
Normal file
234
channeldb/migration12/invoices.go
Normal file
@ -0,0 +1,234 @@
|
||||
package migration12
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/tlv"
|
||||
)
|
||||
|
||||
const (
|
||||
// MaxMemoSize is maximum size of the memo field within invoices stored
|
||||
// in the database.
|
||||
MaxMemoSize = 1024
|
||||
|
||||
// maxReceiptSize is the maximum size of the payment receipt stored
|
||||
// within the database along side incoming/outgoing invoices.
|
||||
maxReceiptSize = 1024
|
||||
|
||||
// MaxPaymentRequestSize is the max size of a payment request for
|
||||
// this invoice.
|
||||
// TODO(halseth): determine the max length payment request when field
|
||||
// lengths are final.
|
||||
MaxPaymentRequestSize = 4096
|
||||
|
||||
memoType tlv.Type = 0
|
||||
payReqType tlv.Type = 1
|
||||
createTimeType tlv.Type = 2
|
||||
settleTimeType tlv.Type = 3
|
||||
addIndexType tlv.Type = 4
|
||||
settleIndexType tlv.Type = 5
|
||||
preimageType tlv.Type = 6
|
||||
valueType tlv.Type = 7
|
||||
cltvDeltaType tlv.Type = 8
|
||||
expiryType tlv.Type = 9
|
||||
paymentAddrType tlv.Type = 10
|
||||
featuresType tlv.Type = 11
|
||||
invStateType tlv.Type = 12
|
||||
amtPaidType tlv.Type = 13
|
||||
)
|
||||
|
||||
var (
|
||||
// invoiceBucket is the name of the bucket within the database that
|
||||
// stores all data related to invoices no matter their final state.
|
||||
// Within the invoice bucket, each invoice is keyed by its invoice ID
|
||||
// which is a monotonically increasing uint32.
|
||||
invoiceBucket = []byte("invoices")
|
||||
|
||||
// Big endian is the preferred byte order, due to cursor scans over
|
||||
// integer keys iterating in order.
|
||||
byteOrder = binary.BigEndian
|
||||
)
|
||||
|
||||
// ContractState describes the state the invoice is in.
|
||||
type ContractState uint8
|
||||
|
||||
// ContractTerm is a companion struct to the Invoice struct. This struct houses
|
||||
// the necessary conditions required before the invoice can be considered fully
|
||||
// settled by the payee.
|
||||
type ContractTerm struct {
|
||||
// PaymentPreimage is the preimage which is to be revealed in the
|
||||
// occasion that an HTLC paying to the hash of this preimage is
|
||||
// extended.
|
||||
PaymentPreimage lntypes.Preimage
|
||||
|
||||
// Value is the expected amount of milli-satoshis to be paid to an HTLC
|
||||
// which can be satisfied by the above preimage.
|
||||
Value lnwire.MilliSatoshi
|
||||
|
||||
// State describes the state the invoice is in.
|
||||
State ContractState
|
||||
}
|
||||
|
||||
// Invoice is a payment invoice generated by a payee in order to request
|
||||
// payment for some good or service. The inclusion of invoices within Lightning
|
||||
// creates a payment work flow for merchants very similar to that of the
|
||||
// existing financial system within PayPal, etc. Invoices are added to the
|
||||
// database when a payment is requested, then can be settled manually once the
|
||||
// payment is received at the upper layer. For record keeping purposes,
|
||||
// invoices are never deleted from the database, instead a bit is toggled
|
||||
// denoting the invoice has been fully settled. Within the database, all
|
||||
// invoices must have a unique payment hash which is generated by taking the
|
||||
// sha256 of the payment preimage.
|
||||
type Invoice struct {
|
||||
// Memo is an optional memo to be stored along side an invoice. The
|
||||
// memo may contain further details pertaining to the invoice itself,
|
||||
// or any other message which fits within the size constraints.
|
||||
Memo []byte
|
||||
|
||||
// PaymentRequest is an optional field where a payment request created
|
||||
// for this invoice can be stored.
|
||||
PaymentRequest []byte
|
||||
|
||||
// FinalCltvDelta is the minimum required number of blocks before htlc
|
||||
// expiry when the invoice is accepted.
|
||||
FinalCltvDelta int32
|
||||
|
||||
// Expiry defines how long after creation this invoice should expire.
|
||||
Expiry time.Duration
|
||||
|
||||
// CreationDate is the exact time the invoice was created.
|
||||
CreationDate time.Time
|
||||
|
||||
// SettleDate is the exact time the invoice was settled.
|
||||
SettleDate time.Time
|
||||
|
||||
// Terms are the contractual payment terms of the invoice. Once all the
|
||||
// terms have been satisfied by the payer, then the invoice can be
|
||||
// considered fully fulfilled.
|
||||
//
|
||||
// TODO(roasbeef): later allow for multiple terms to fulfill the final
|
||||
// invoice: payment fragmentation, etc.
|
||||
Terms ContractTerm
|
||||
|
||||
// AddIndex is an auto-incrementing integer that acts as a
|
||||
// monotonically increasing sequence number for all invoices created.
|
||||
// Clients can then use this field as a "checkpoint" of sorts when
|
||||
// implementing a streaming RPC to notify consumers of instances where
|
||||
// an invoice has been added before they re-connected.
|
||||
//
|
||||
// NOTE: This index starts at 1.
|
||||
AddIndex uint64
|
||||
|
||||
// SettleIndex is an auto-incrementing integer that acts as a
|
||||
// monotonically increasing sequence number for all settled invoices.
|
||||
// Clients can then use this field as a "checkpoint" of sorts when
|
||||
// implementing a streaming RPC to notify consumers of instances where
|
||||
// an invoice has been settled before they re-connected.
|
||||
//
|
||||
// NOTE: This index starts at 1.
|
||||
SettleIndex uint64
|
||||
|
||||
// AmtPaid is the final amount that we ultimately accepted for pay for
|
||||
// this invoice. We specify this value independently as it's possible
|
||||
// that the invoice originally didn't specify an amount, or the sender
|
||||
// overpaid.
|
||||
AmtPaid lnwire.MilliSatoshi
|
||||
|
||||
// Htlcs records all htlcs that paid to this invoice. Some of these
|
||||
// htlcs may have been marked as canceled.
|
||||
Htlcs []byte
|
||||
}
|
||||
|
||||
// LegacyDeserializeInvoice decodes an invoice from the passed io.Reader using
|
||||
// the pre-TLV serialization.
|
||||
//
|
||||
// nolint: dupl
|
||||
func LegacyDeserializeInvoice(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 invoice, err
|
||||
}
|
||||
_, err = wire.ReadVarBytes(r, 0, maxReceiptSize, "")
|
||||
if err != nil {
|
||||
return invoice, err
|
||||
}
|
||||
|
||||
invoice.PaymentRequest, err = wire.ReadVarBytes(r, 0, MaxPaymentRequestSize, "")
|
||||
if err != nil {
|
||||
return invoice, err
|
||||
}
|
||||
|
||||
if err := binary.Read(r, byteOrder, &invoice.FinalCltvDelta); err != nil {
|
||||
return invoice, err
|
||||
}
|
||||
|
||||
var expiry int64
|
||||
if err := binary.Read(r, byteOrder, &expiry); err != nil {
|
||||
return invoice, err
|
||||
}
|
||||
invoice.Expiry = time.Duration(expiry)
|
||||
|
||||
birthBytes, err := wire.ReadVarBytes(r, 0, 300, "birth")
|
||||
if err != nil {
|
||||
return invoice, err
|
||||
}
|
||||
if err := invoice.CreationDate.UnmarshalBinary(birthBytes); err != nil {
|
||||
return invoice, err
|
||||
}
|
||||
|
||||
settledBytes, err := wire.ReadVarBytes(r, 0, 300, "settled")
|
||||
if err != nil {
|
||||
return invoice, err
|
||||
}
|
||||
if err := invoice.SettleDate.UnmarshalBinary(settledBytes); err != nil {
|
||||
return invoice, err
|
||||
}
|
||||
|
||||
if _, err := io.ReadFull(r, invoice.Terms.PaymentPreimage[:]); err != nil {
|
||||
return invoice, err
|
||||
}
|
||||
var scratch [8]byte
|
||||
if _, err := io.ReadFull(r, scratch[:]); err != nil {
|
||||
return invoice, err
|
||||
}
|
||||
invoice.Terms.Value = lnwire.MilliSatoshi(byteOrder.Uint64(scratch[:]))
|
||||
|
||||
if err := binary.Read(r, byteOrder, &invoice.Terms.State); err != nil {
|
||||
return invoice, err
|
||||
}
|
||||
|
||||
if err := binary.Read(r, byteOrder, &invoice.AddIndex); err != nil {
|
||||
return invoice, err
|
||||
}
|
||||
if err := binary.Read(r, byteOrder, &invoice.SettleIndex); err != nil {
|
||||
return invoice, err
|
||||
}
|
||||
if err := binary.Read(r, byteOrder, &invoice.AmtPaid); err != nil {
|
||||
return invoice, err
|
||||
}
|
||||
|
||||
invoice.Htlcs, err = deserializeHtlcs(r)
|
||||
if err != nil {
|
||||
return Invoice{}, err
|
||||
}
|
||||
|
||||
return invoice, nil
|
||||
}
|
||||
|
||||
// deserializeHtlcs reads a list of invoice htlcs from a reader and returns it
|
||||
// as a flattened byte slice.
|
||||
func deserializeHtlcs(r io.Reader) ([]byte, error) {
|
||||
var b bytes.Buffer
|
||||
_, err := io.Copy(&b, r)
|
||||
return b.Bytes(), err
|
||||
}
|
Loading…
Reference in New Issue
Block a user