multi: replace htlcResolution with an interface
This commit repalces the htlcResolution struct with an interface. This interface is implemeted by failure, settle and accept resolution structs. Only settles and fails are exported because the existing code that handles htlc resolutions uses a nil resolution to indicate that a htlc was accepted. The accept resolution is used internally to report on the resolution result of the accepted htlc, but a nil resolution is surfaced. Further refactoring of all the functions that call NotifyExitHopHtlc to handle a htlc accept case (rather than having a nil check) is required.
This commit is contained in:
11 files changed
+477
-257
No files matched your search
@@ -27,7 +27,7 @@ type InvoiceDatabase interface {
|
||||
NotifyExitHopHtlc(payHash lntypes.Hash, paidAmount lnwire.MilliSatoshi,
|
||||
expiry uint32, currentHeight int32,
|
||||
circuitKey channeldb.CircuitKey, hodlChan chan<- interface{},
|
||||
payload invoices.Payload) (*invoices.HtlcResolution, error)
|
||||
payload invoices.Payload) (invoices.HtlcResolution, error)
|
||||
|
||||
// CancelInvoice attempts to cancel the invoice corresponding to the
|
||||
// passed payment hash.
|
||||
|
||||
+41
-26
@@ -1158,7 +1158,7 @@ loop:
|
||||
for {
|
||||
// Lookup all hodl htlcs that can be failed or settled with this event.
|
||||
// The hodl htlc must be present in the map.
|
||||
circuitKey := htlcResolution.CircuitKey
|
||||
circuitKey := htlcResolution.CircuitKey()
|
||||
hodlHtlc, ok := l.hodlMap[circuitKey]
|
||||
if !ok {
|
||||
return fmt.Errorf("hodl htlc not found: %v", circuitKey)
|
||||
@@ -1193,46 +1193,61 @@ loop:
|
||||
func (l *channelLink) processHtlcResolution(resolution invoices.HtlcResolution,
|
||||
htlc hodlHtlc) error {
|
||||
|
||||
circuitKey := resolution.CircuitKey
|
||||
circuitKey := resolution.CircuitKey()
|
||||
|
||||
// Determine required action for the resolution. If the event's preimage is
|
||||
// non-nil, the htlc must be settled. Otherwise, it should be canceled.
|
||||
if resolution.Preimage != nil {
|
||||
l.log.Debugf("received settle resolution for %v", circuitKey)
|
||||
// Determine required action for the resolution based on the type of
|
||||
// resolution we have received.
|
||||
switch res := resolution.(type) {
|
||||
// Settle htlcs that returned a settle resolution using the preimage
|
||||
// in the resolution.
|
||||
case *invoices.HtlcSettleResolution:
|
||||
l.log.Debugf("received settle resolution for %v"+
|
||||
"with outcome: %v", circuitKey, res.Outcome)
|
||||
|
||||
return l.settleHTLC(
|
||||
*resolution.Preimage, htlc.pd.HtlcIndex,
|
||||
res.Preimage, htlc.pd.HtlcIndex,
|
||||
htlc.pd.SourceRef,
|
||||
)
|
||||
|
||||
// For htlc failures, we get the relevant failure message based
|
||||
// on the failure resolution and then fail the htlc.
|
||||
case *invoices.HtlcFailResolution:
|
||||
l.log.Debugf("received cancel resolution for "+
|
||||
"%v with outcome: %v", circuitKey, res.Outcome)
|
||||
|
||||
// Get the lnwire failure message based on the resolution
|
||||
// result.
|
||||
failure := getResolutionFailure(res, htlc.pd.Amount)
|
||||
|
||||
l.sendHTLCError(
|
||||
htlc.pd.HtlcIndex, failure, htlc.obfuscator,
|
||||
htlc.pd.SourceRef,
|
||||
)
|
||||
return nil
|
||||
|
||||
// Fail if we do not get a settle of fail resolution, since we
|
||||
// are only expecting to handle settles and fails.
|
||||
default:
|
||||
return fmt.Errorf("unknown htlc resolution type: %T",
|
||||
resolution)
|
||||
}
|
||||
|
||||
l.log.Debugf("received cancel resolution for %v with outcome: %v",
|
||||
circuitKey, resolution.Outcome)
|
||||
|
||||
// Get the lnwire failure message based on the resolution result.
|
||||
failure := getResolutionFailure(resolution, htlc.pd.Amount)
|
||||
|
||||
l.sendHTLCError(
|
||||
htlc.pd.HtlcIndex, failure, htlc.obfuscator,
|
||||
htlc.pd.SourceRef,
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
// getResolutionFailure returns the wire message that a htlc resolution should
|
||||
// be failed with.
|
||||
func getResolutionFailure(resolution invoices.HtlcResolution,
|
||||
func getResolutionFailure(resolution *invoices.HtlcFailResolution,
|
||||
amount lnwire.MilliSatoshi) lnwire.FailureMessage {
|
||||
|
||||
// If the resolution has been resolved as part of a MPP timeout, we need
|
||||
// to fail the htlc with lnwire.FailMppTimeout.
|
||||
// If the resolution has been resolved as part of a MPP timeout,
|
||||
// we need to fail the htlc with lnwire.FailMppTimeout.
|
||||
if resolution.Outcome == invoices.ResultMppTimeout {
|
||||
return &lnwire.FailMPPTimeout{}
|
||||
}
|
||||
|
||||
// If the htlc is not a MPP timeout, we fail it with FailIncorrectDetails
|
||||
// This covers hodl cancels (which return it to avoid leaking information
|
||||
// and other invoice failures such as underpayment or expiry too soon.
|
||||
// If the htlc is not a MPP timeout, we fail it with
|
||||
// FailIncorrectDetails. This error is sent for invoice payment
|
||||
// failures such as underpayment/ expiry too soon and hodl invoices
|
||||
// (which return FailIncorrectDetails to avoid leaking information).
|
||||
return lnwire.NewFailIncorrectDetails(
|
||||
amount, uint32(resolution.AcceptHeight),
|
||||
)
|
||||
@@ -2863,7 +2878,7 @@ func (l *channelLink) processExitHop(pd *lnwallet.PaymentDescriptor,
|
||||
}
|
||||
|
||||
// Process the received resolution.
|
||||
return l.processHtlcResolution(*event, htlc)
|
||||
return l.processHtlcResolution(event, htlc)
|
||||
}
|
||||
|
||||
// settleHTLC settles the HTLC on the channel.
|
||||
|
||||
+1
-1
@@ -816,7 +816,7 @@ func (i *mockInvoiceRegistry) SettleHodlInvoice(preimage lntypes.Preimage) error
|
||||
func (i *mockInvoiceRegistry) NotifyExitHopHtlc(rhash lntypes.Hash,
|
||||
amt lnwire.MilliSatoshi, expiry uint32, currentHeight int32,
|
||||
circuitKey channeldb.CircuitKey, hodlChan chan<- interface{},
|
||||
payload invoices.Payload) (*invoices.HtlcResolution, error) {
|
||||
payload invoices.Payload) (invoices.HtlcResolution, error) {
|
||||
|
||||
event, err := i.registry.NotifyExitHopHtlc(
|
||||
rhash, amt, expiry, currentHeight, circuitKey, hodlChan,
|
||||
|
||||
Reference in new issue
Block a user