From 416bc8c68c6231ed3df304ae9a1731861a295b15 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Wed, 21 Aug 2019 15:24:21 +0200 Subject: [PATCH] channeldb+invoices: move hold invoice settle logic into registry This commit is a continuation of the centralization of invoice state transition logic in the invoice registry. --- channeldb/invoice_test.go | 5 +- channeldb/invoices.go | 92 +++++-------------------------------- invoices/invoiceregistry.go | 24 +++++++++- 3 files changed, 37 insertions(+), 84 deletions(-) diff --git a/channeldb/invoice_test.go b/channeldb/invoice_test.go index 7ea19afd..0e5afd1e 100644 --- a/channeldb/invoice_test.go +++ b/channeldb/invoice_test.go @@ -692,8 +692,9 @@ func getUpdateInvoice(amt lnwire.MilliSatoshi) InvoiceUpdateCallback { } update := &InvoiceUpdateDesc{ - State: ContractSettled, - AmtPaid: amt, + Preimage: invoice.Terms.PaymentPreimage, + State: ContractSettled, + AmtPaid: amt, } return update, nil diff --git a/channeldb/invoices.go b/channeldb/invoices.go index 195d82ff..de480f36 100644 --- a/channeldb/invoices.go +++ b/channeldb/invoices.go @@ -284,6 +284,9 @@ type InvoiceUpdateDesc struct { // AmtPaid is the updated amount that has been paid to this invoice. AmtPaid lnwire.MilliSatoshi + + // Preimage must be set to the preimage when state is settled. + Preimage lntypes.Preimage } // InvoiceUpdateCallback is a callback used in the db transaction to update the @@ -740,47 +743,8 @@ func (d *DB) UpdateInvoice(paymentHash lntypes.Hash, } updatedInvoice, err = updateInvoice( - invoices, settleIndex, invoiceNum, callback, - ) - - return err - }) - - return updatedInvoice, err -} - -// SettleHoldInvoice sets the preimage of a hodl invoice and marks the invoice -// as settled. -func (d *DB) SettleHoldInvoice(preimage lntypes.Preimage) (*Invoice, error) { - var updatedInvoice *Invoice - hash := preimage.Hash() - err := d.Update(func(tx *bbolt.Tx) error { - invoices, err := tx.CreateBucketIfNotExists(invoiceBucket) - if err != nil { - return err - } - invoiceIndex, err := invoices.CreateBucketIfNotExists( - invoiceIndexBucket, - ) - if err != nil { - return err - } - settleIndex, err := invoices.CreateBucketIfNotExists( - settleIndexBucket, - ) - if err != nil { - return err - } - - // Check the invoice index to see if an invoice paying to this - // hash exists within the DB. - invoiceNum := invoiceIndex.Get(hash[:]) - if invoiceNum == nil { - return ErrInvoiceNotFound - } - - updatedInvoice, err = settleHoldInvoice( - invoices, settleIndex, invoiceNum, preimage, + paymentHash, invoices, settleIndex, invoiceNum, + callback, ) return err @@ -1243,8 +1207,8 @@ func copyInvoice(src *Invoice) *Invoice { // updateInvoice fetches the invoice, obtains the update descriptor from the // callback and applies the updates in a single db transaction. -func updateInvoice(invoices, settleIndex *bbolt.Bucket, invoiceNum []byte, - callback InvoiceUpdateCallback) (*Invoice, error) { +func updateInvoice(hash lntypes.Hash, invoices, settleIndex *bbolt.Bucket, + invoiceNum []byte, callback InvoiceUpdateCallback) (*Invoice, error) { invoice, err := fetchInvoice(invoiceNum, invoices) if err != nil { @@ -1272,6 +1236,11 @@ func updateInvoice(invoices, settleIndex *bbolt.Bucket, invoiceNum []byte, if preUpdateState != invoice.Terms.State && invoice.Terms.State == ContractSettled { + if update.Preimage.Hash() != hash { + return nil, fmt.Errorf("preimage does not match") + } + invoice.Terms.PaymentPreimage = update.Preimage + err := setSettleFields(settleIndex, invoiceNum, &invoice) if err != nil { return nil, err @@ -1314,43 +1283,6 @@ func setSettleFields(settleIndex *bbolt.Bucket, invoiceNum []byte, return nil } -func settleHoldInvoice(invoices, settleIndex *bbolt.Bucket, - invoiceNum []byte, preimage lntypes.Preimage) (*Invoice, - error) { - - invoice, err := fetchInvoice(invoiceNum, invoices) - if err != nil { - return nil, err - } - - switch invoice.Terms.State { - case ContractOpen: - return &invoice, ErrInvoiceStillOpen - case ContractCanceled: - return &invoice, ErrInvoiceAlreadyCanceled - case ContractSettled: - return &invoice, ErrInvoiceAlreadySettled - } - - invoice.Terms.PaymentPreimage = preimage - - err = setSettleFields(settleIndex, invoiceNum, &invoice) - if err != nil { - return nil, err - } - - var buf bytes.Buffer - if err := serializeInvoice(&buf, &invoice); err != nil { - return nil, err - } - - if err := invoices.Put(invoiceNum[:], buf.Bytes()); err != nil { - return nil, err - } - - return &invoice, nil -} - func cancelInvoice(invoices *bbolt.Bucket, invoiceNum []byte) ( *Invoice, error) { diff --git a/invoices/invoiceregistry.go b/invoices/invoiceregistry.go index d2729d15..1681bae5 100644 --- a/invoices/invoiceregistry.go +++ b/invoices/invoiceregistry.go @@ -456,6 +456,7 @@ func (i *InvoiceRegistry) updateInvoice(invoice *channeldb.Invoice, if holdInvoice { update.State = channeldb.ContractAccepted } else { + update.Preimage = invoice.Terms.PaymentPreimage update.State = channeldb.ContractSettled } return &update, nil @@ -587,13 +588,32 @@ func (i *InvoiceRegistry) SettleHodlInvoice(preimage lntypes.Preimage) error { i.Lock() defer i.Unlock() - invoice, err := i.cdb.SettleHoldInvoice(preimage) + updateInvoice := func(invoice *channeldb.Invoice) ( + *channeldb.InvoiceUpdateDesc, error) { + + switch invoice.Terms.State { + case channeldb.ContractOpen: + return nil, channeldb.ErrInvoiceStillOpen + case channeldb.ContractCanceled: + return nil, channeldb.ErrInvoiceAlreadyCanceled + case channeldb.ContractSettled: + return nil, channeldb.ErrInvoiceAlreadySettled + } + + return &channeldb.InvoiceUpdateDesc{ + AmtPaid: invoice.AmtPaid, + State: channeldb.ContractSettled, + Preimage: preimage, + }, nil + } + + hash := preimage.Hash() + invoice, err := i.cdb.UpdateInvoice(hash, updateInvoice) if err != nil { log.Errorf("SettleHodlInvoice with preimage %v: %v", preimage, err) return err } - hash := preimage.Hash() log.Debugf("Invoice(%v): settled with preimage %v", hash, invoice.Terms.PaymentPreimage)