htlcswitch: always assume an onion error for malformed htlc failures

Previously a temporary channel failure was returning for unexpected
malformed htlc failures. This is not what we want to communicate to the
sender, because the sender may apply a penalty to us only.

Returning the temporary channel failure is especially problematic if we
ourselves are the sender and the malformed htlc failure comes from our
direct peer. When interpretating the failure, we aren't able to
distinguish anymore between our channel not having enough balance and
our peer sending an unexpected failure back.
This commit is contained in:
Joost Jager 2019-08-16 19:46:51 +02:00
parent e135cf7326
commit 67e40d4433
No known key found for this signature in database
GPG Key ID: A61B9D4C393C59C7
3 changed files with 18 additions and 5 deletions

@ -1637,8 +1637,21 @@ func (l *channelLink) handleUpstreamMsg(msg lnwire.Message) {
OnionSHA256: msg.ShaOnionBlob,
}
default:
log.Errorf("Unknown failure code: %v", msg.FailureCode)
failure = &lnwire.FailTemporaryChannelFailure{}
log.Warnf("Unexpected failure code received in "+
"UpdateFailMailformedHTLC: %v", msg.FailureCode)
// We don't just pass back the error we received from
// our successor. Otherwise we might report a failure
// that penalizes us more than needed. If the onion that
// we forwarded was correct, the node should have been
// able to send back its own failure. The node did not
// send back its own failure, so we assume there was a
// problem with the onion and report that back. We reuse
// the invalid onion key failure because there is no
// specific error for this case.
failure = &lnwire.FailInvalidOnionKey{
OnionSHA256: msg.ShaOnionBlob,
}
}
// With the error parsed, we'll convert the into it's opaque

@ -2097,8 +2097,8 @@ func TestUpdateFailMalformedHTLCErrorConversion(t *testing.T) {
fwdingErr := err.(*ForwardingError)
failureMsg := fwdingErr.FailureMessage
if _, ok := failureMsg.(*lnwire.FailTemporaryChannelFailure); !ok {
t.Fatalf("expected temp chan failure instead got: %v",
if _, ok := failureMsg.(*lnwire.FailInvalidOnionKey); !ok {
t.Fatalf("expected onion failure instead got: %v",
fwdingErr.FailureMessage)
}
}

@ -3570,7 +3570,7 @@ func testSphinxReplayPersistence(net *lntest.NetworkHarness, t *harnessTest) {
// Construct the response we expect after sending a duplicate packet
// that fails due to sphinx replay detection.
replayErr := "TemporaryChannelFailure"
replayErr := "InvalidOnionKey"
if !strings.Contains(resp.PaymentError, replayErr) {
t.Fatalf("received payment error: %v, expected %v",
resp.PaymentError, replayErr)