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:
6 files changed
+162
-98
No files matched your search
@@ -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
@@ -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
@@ -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 {
|
||||
|
||||
Reference in new issue
Block a user