htlcswitch: abtract invoice from link

This commit detaches signaling the invoice registry that an htlc was
locked in from the actually settling of the htlc.

It is a preparation for hodl invoices.
This commit is contained in:
Joost Jager committed 2019-03-15 10:09:15 +01:00
1 parent aeb35d9898
commit 1f41a2abce
6 files changed
+162 -98

No files matched your search

+7 -3
View File
@@ -3,6 +3,7 @@ package htlcswitch
import (
"github.com/btcsuite/btcd/wire"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/invoices"
"github.com/lightningnetwork/lnd/lnpeer"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwire"
@@ -17,9 +18,12 @@ type InvoiceDatabase interface {
// extended to us gives us enough time to settle as we prescribe.
LookupInvoice(lntypes.Hash) (channeldb.Invoice, uint32, error)
// SettleInvoice attempts to mark an invoice corresponding to the
// passed payment hash as fully settled.
SettleInvoice(payHash lntypes.Hash, paidAmount lnwire.MilliSatoshi) error
// NotifyExitHopHtlc attempts to mark an invoice as settled. If the
// invoice is a debug invoice, then this method is a noop as debug
// invoices are never fully settled. The return value describes how the
// htlc should be resolved.
NotifyExitHopHtlc(rhash lntypes.Hash, amt lnwire.MilliSatoshi) (
*invoices.HodlEvent, error)
// CancelInvoice attempts to cancel the invoice corresponding to the
// passed payment hash.
+64 -21
View File
@@ -16,6 +16,7 @@ import (
"github.com/lightningnetwork/lnd/contractcourt"
"github.com/lightningnetwork/lnd/htlcswitch/hodl"
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/invoices"
"github.com/lightningnetwork/lnd/lnpeer"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwallet"
@@ -348,6 +349,12 @@ type channelLink struct {
quit chan struct{}
}
// hodlHtlc contains htlc data that is required for resolution.
type hodlHtlc struct {
pd *lnwallet.PaymentDescriptor
obfuscator ErrorEncrypter
}
// NewChannelLink creates a new instance of a ChannelLink given a configuration
// and active channel that will be used to verify/apply updates to.
func NewChannelLink(cfg ChannelLinkConfig,
@@ -1064,6 +1071,50 @@ out:
}
}
// processHodlEvent applies a received hodl event to the provided htlc. When
// this function returns without an error, the commit tx should be updated.
func (l *channelLink) processHodlEvent(hodlEvent invoices.HodlEvent,
htlcs ...hodlHtlc) error {
hash := hodlEvent.Hash
if hodlEvent.Preimage == nil {
l.debugf("Received hodl cancel event for %v", hash)
} else {
l.debugf("Received hodl settle event for %v", hash)
}
// Determine required action for the resolution.
var hodlAction func(htlc hodlHtlc) error
if hodlEvent.Preimage != nil {
hodlAction = func(htlc hodlHtlc) error {
return l.settleHTLC(
*hodlEvent.Preimage, htlc.pd.HtlcIndex,
htlc.pd.SourceRef,
)
}
} else {
hodlAction = func(htlc hodlHtlc) error {
failure := lnwire.NewFailUnknownPaymentHash(
htlc.pd.Amount,
)
l.sendHTLCError(
htlc.pd.HtlcIndex, failure, htlc.obfuscator,
htlc.pd.SourceRef,
)
return nil
}
}
// Apply action for all htlcs matching this hash.
for _, htlc := range htlcs {
if err := hodlAction(htlc); err != nil {
return err
}
}
return nil
}
// randomFeeUpdateTimeout returns a random timeout between the bounds defined
// within the link's configuration that will be used to determine when the link
// should propose an update to its commitment fee rate.
@@ -2674,30 +2725,22 @@ func (l *channelLink) processExitHop(pd *lnwallet.PaymentDescriptor,
return true, nil
}
// Notify the invoiceRegistry of the invoices we just settled (with the
// amount accepted at settle time) with this latest commitment update.
//
// If we crash right after this, this code will be re-executed after
// restart and the HTLC fulfill message will be sent out then.
err = l.cfg.Registry.SettleInvoice(invoiceHash, pd.Amount)
// Reject htlcs for canceled invoices.
if err == channeldb.ErrInvoiceAlreadyCanceled {
l.errorf("Rejecting htlc due to canceled invoice")
failure := lnwire.NewFailUnknownPaymentHash(pd.Amount)
l.sendHTLCError(pd.HtlcIndex, failure, obfuscator, pd.SourceRef)
return true, nil
}
// Handle unexpected errors.
// Notify the invoiceRegistry of the exit hop htlc. If we crash right
// after this, this code will be re-executed after restart. We will
// receive back a resolution event.
event, err := l.cfg.Registry.NotifyExitHopHtlc(
invoiceHash, pd.Amount,
)
if err != nil {
return false, fmt.Errorf("unable to settle invoice: %v", err)
return false, err
}
preimage := invoice.Terms.PaymentPreimage
err = l.settleHTLC(preimage, pd.HtlcIndex, pd.SourceRef)
// Process the received resolution.
htlc := hodlHtlc{
pd: pd,
obfuscator: obfuscator,
}
err = l.processHodlEvent(*event, htlc)
if err != nil {
return false, err
}
+5 -5
View File
@@ -759,18 +759,18 @@ func (i *mockInvoiceRegistry) LookupInvoice(rHash lntypes.Hash) (channeldb.Invoi
return i.registry.LookupInvoice(rHash)
}
func (i *mockInvoiceRegistry) SettleInvoice(rhash lntypes.Hash,
amt lnwire.MilliSatoshi) error {
func (i *mockInvoiceRegistry) NotifyExitHopHtlc(rhash lntypes.Hash,
amt lnwire.MilliSatoshi) (*invoices.HodlEvent, error) {
err := i.registry.SettleInvoice(rhash, amt)
event, err := i.registry.NotifyExitHopHtlc(rhash, amt)
if err != nil {
return err
return event, err
}
if i.settleChan != nil {
i.settleChan <- rhash
}
return nil
return event, err
}
func (i *mockInvoiceRegistry) CancelInvoice(payHash lntypes.Hash) error {