htlcswitch+invoices: fail mpp timeouts with FailMPPTimeout
This commit adds a getResolutionFailure function which returns an appropriate wire failure based on the outcome of a htlc resolution. It also updates the MissionControlStore test to ensure that lnd can handle failures which occur due to mpp timeout.
This commit is contained in:
parent
1d3bb5aed6
commit
e0c86f1e71
@ -1209,12 +1209,8 @@ func (l *channelLink) processHtlcResolution(resolution invoices.HtlcResolution,
|
||||
l.log.Debugf("received cancel resolution for %v with outcome: %v",
|
||||
circuitKey, resolution.Outcome)
|
||||
|
||||
// The htlc has failed so we cancel it with FailIncorrectDetails. This
|
||||
// error covers invoice failures and hodl cancels (which return it to avoid
|
||||
// leaking information).
|
||||
failure := lnwire.NewFailIncorrectDetails(
|
||||
htlc.pd.Amount, uint32(resolution.AcceptHeight),
|
||||
)
|
||||
// Get the lnwire failure message based on the resolution result.
|
||||
failure := getResolutionFailure(resolution, htlc.pd.Amount)
|
||||
|
||||
l.sendHTLCError(
|
||||
htlc.pd.HtlcIndex, failure, htlc.obfuscator,
|
||||
@ -1223,6 +1219,25 @@ func (l *channelLink) processHtlcResolution(resolution invoices.HtlcResolution,
|
||||
return nil
|
||||
}
|
||||
|
||||
// getResolutionFailure returns the wire message that a htlc resolution should
|
||||
// be failed with.
|
||||
func getResolutionFailure(resolution invoices.HtlcResolution,
|
||||
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 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.
|
||||
return lnwire.NewFailIncorrectDetails(
|
||||
amount, uint32(resolution.AcceptHeight),
|
||||
)
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
@ -16,8 +16,12 @@ import (
|
||||
|
||||
const testMaxRecords = 2
|
||||
|
||||
// TestMissionControlStore tests the recording of payment failure events
|
||||
// in mission control. It tests encoding and decoding of differing lnwire
|
||||
// failures (FailIncorrectDetails and FailMppTimeout), pruning of results
|
||||
// and idempotent writes.
|
||||
func TestMissionControlStore(t *testing.T) {
|
||||
// Set time zone explictly to keep test deterministic.
|
||||
// Set time zone explicitly to keep test deterministic.
|
||||
time.Local = time.UTC
|
||||
|
||||
file, err := ioutil.TempFile("", "*.db")
|
||||
@ -115,11 +119,12 @@ func TestMissionControlStore(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Add a newer result.
|
||||
// Add a newer result which failed due to mpp timeout.
|
||||
result3 := result1
|
||||
result3.timeReply = result1.timeReply.Add(2 * time.Hour)
|
||||
result3.timeFwd = result1.timeReply.Add(2 * time.Hour)
|
||||
result3.id = 3
|
||||
result3.failure = &lnwire.FailMPPTimeout{}
|
||||
|
||||
err = store.AddResult(&result3)
|
||||
if err != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user