channeldb: add new AmtPaid field to the Invoice struct

In this commit, in order to allow the caller to specify the amount that
was ultimately accepted for an invoice, the SettleInvoice method has
gained a new parameter: amtPaid. SettleInvoice will now populate the
final amount paid in the database upon db commit.
This commit is contained in:
Olaoluwa Osuntokun 2018-04-24 20:50:56 -07:00
parent a32f2b79da
commit fc0f0d33b2
No known key found for this signature in database
GPG Key ID: 964EA263DD637C21

@ -26,6 +26,8 @@ var (
// index is used to detect duplicates, and also to provide a fast path // index is used to detect duplicates, and also to provide a fast path
// for looking up incoming HTLCs to determine if we're able to settle // for looking up incoming HTLCs to determine if we're able to settle
// them fully. // them fully.
//
// maps: payHash => invoiceIndex
invoiceIndexBucket = []byte("paymenthashes") invoiceIndexBucket = []byte("paymenthashes")
// numInvoicesKey is the name of key which houses the auto-incrementing // numInvoicesKey is the name of key which houses the auto-incrementing
@ -61,8 +63,8 @@ type ContractTerm struct {
// extended. // extended.
PaymentPreimage [32]byte PaymentPreimage [32]byte
// Value is the expected amount of milli-satoshis to be paid to an // Value is the expected amount of milli-satoshis to be paid to an HTLC
// HTLC which can be satisfied by the above preimage. // which can be satisfied by the above preimage.
Value lnwire.MilliSatoshi Value lnwire.MilliSatoshi
// Settled indicates if this particular contract term has been fully // Settled indicates if this particular contract term has been fully
@ -79,8 +81,7 @@ type ContractTerm struct {
// invoices are never deleted from the database, instead a bit is toggled // invoices are never deleted from the database, instead a bit is toggled
// denoting the invoice has been fully settled. Within the database, all // denoting the invoice has been fully settled. Within the database, all
// invoices must have a unique payment hash which is generated by taking the // invoices must have a unique payment hash which is generated by taking the
// sha256 of the payment // sha256 of the payment preimage.
// preimage.
type Invoice struct { type Invoice struct {
// Memo is an optional memo to be stored along side an invoice. The // Memo is an optional memo to be stored along side an invoice. The
// memo may contain further details pertaining to the invoice itself, // memo may contain further details pertaining to the invoice itself,
@ -103,13 +104,18 @@ type Invoice struct {
// SettleDate is the exact time the invoice was settled. // SettleDate is the exact time the invoice was settled.
SettleDate time.Time SettleDate time.Time
// Terms are the contractual payment terms of the invoice. Once // Terms are the contractual payment terms of the invoice. Once all the
// all the terms have been satisfied by the payer, then the invoice can // terms have been satisfied by the payer, then the invoice can be
// be considered fully fulfilled. // considered fully fulfilled.
// //
// TODO(roasbeef): later allow for multiple terms to fulfill the final // TODO(roasbeef): later allow for multiple terms to fulfill the final
// invoice: payment fragmentation, etc. // invoice: payment fragmentation, etc.
Terms ContractTerm Terms ContractTerm
// 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
} }
func validateInvoice(i *Invoice) error { func validateInvoice(i *Invoice) error {
@ -262,7 +268,8 @@ func (d *DB) FetchAllInvoices(pendingOnly bool) ([]*Invoice, error) {
// payment hash as fully settled. If an invoice matching the passed payment // payment hash as fully settled. If an invoice matching the passed payment
// hash doesn't existing within the database, then the action will fail with a // hash doesn't existing within the database, then the action will fail with a
// "not found" error. // "not found" error.
func (d *DB) SettleInvoice(paymentHash [32]byte) error { func (d *DB) SettleInvoice(paymentHash [32]byte, amtPaid lnwire.MilliSatoshi) error {
return d.Update(func(tx *bolt.Tx) error { return d.Update(func(tx *bolt.Tx) error {
invoices, err := tx.CreateBucketIfNotExists(invoiceBucket) invoices, err := tx.CreateBucketIfNotExists(invoiceBucket)
if err != nil { if err != nil {
@ -280,7 +287,9 @@ func (d *DB) SettleInvoice(paymentHash [32]byte) error {
return ErrInvoiceNotFound return ErrInvoiceNotFound
} }
return settleInvoice(invoices, invoiceNum) return settleInvoice(
invoices, settleIndex, invoiceNum, amtPaid,
)
}) })
} }
@ -361,6 +370,9 @@ func serializeInvoice(w io.Writer, i *Invoice) error {
return err return err
} }
if err := binary.Write(w, byteOrder, int64(i.AmtPaid)); err != nil {
return err
}
return nil return nil
} }
@ -421,12 +433,16 @@ func deserializeInvoice(r io.Reader) (*Invoice, error) {
if err := binary.Read(r, byteOrder, &invoice.Terms.Settled); err != nil { if err := binary.Read(r, byteOrder, &invoice.Terms.Settled); err != nil {
return nil, err return nil, err
if err := binary.Read(r, byteOrder, &invoice.AmtPaid); err != nil {
return invoice, err
} }
return invoice, nil return invoice, nil
} }
func settleInvoice(invoices *bolt.Bucket, invoiceNum []byte) error { func settleInvoice(invoices, settleIndex *bolt.Bucket, invoiceNum []byte,
amtPaid lnwire.MilliSatoshi) error {
invoice, err := fetchInvoice(invoiceNum, invoices) invoice, err := fetchInvoice(invoiceNum, invoices)
if err != nil { if err != nil {
return err return err
@ -438,6 +454,7 @@ func settleInvoice(invoices *bolt.Bucket, invoiceNum []byte) error {
return nil return nil
} }
invoice.AmtPaid = amtPaid
invoice.Terms.Settled = true invoice.Terms.Settled = true
invoice.SettleDate = time.Now() invoice.SettleDate = time.Now()