htlcswitch: add processRemoteUpdateFailMalformedHTLC

This commit is contained in:
yyforyongyu
2025-06-30 21:36:40 +08:00
parent f9df5a9f51
commit e883a51a63

View File

@@ -1936,69 +1936,11 @@ func (l *channelLink) handleUpstreamMsg(ctx context.Context,
}
case *lnwire.UpdateFailMalformedHTLC:
// Convert the failure type encoded within the HTLC fail
// message to the proper generic lnwire error code.
var failure lnwire.FailureMessage
switch msg.FailureCode {
case lnwire.CodeInvalidOnionVersion:
failure = &lnwire.FailInvalidOnionVersion{
OnionSHA256: msg.ShaOnionBlob,
}
case lnwire.CodeInvalidOnionHmac:
failure = &lnwire.FailInvalidOnionHmac{
OnionSHA256: msg.ShaOnionBlob,
}
case lnwire.CodeInvalidOnionKey:
failure = &lnwire.FailInvalidOnionKey{
OnionSHA256: msg.ShaOnionBlob,
}
// Handle malformed errors that are part of a blinded route.
// This case is slightly different, because we expect every
// relaying node in the blinded portion of the route to send
// malformed errors. If we're also a relaying node, we're
// likely going to switch this error out anyway for our own
// malformed error, but we handle the case here for
// completeness.
case lnwire.CodeInvalidBlinding:
failure = &lnwire.FailInvalidBlinding{
OnionSHA256: msg.ShaOnionBlob,
}
default:
l.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
// form.
var b bytes.Buffer
if err := lnwire.EncodeFailure(&b, failure, 0); err != nil {
l.log.Errorf("unable to encode malformed error: %v", err)
return
}
// If remote side have been unable to parse the onion blob we
// have sent to it, than we should transform the malformed HTLC
// message to the usual HTLC fail message.
err := l.channel.ReceiveFailHTLC(msg.ID, b.Bytes())
err := l.processRemoteUpdateFailMalformedHTLC(msg)
if err != nil {
l.failf(LinkFailureError{code: ErrInvalidUpdate},
"unable to handle upstream fail HTLC: %v", err)
l.log.Errorf("failed to process remote fail "+
"malformed: %v", err)
return
}
@@ -4671,3 +4613,74 @@ func (l *channelLink) processRemoteUpdateFulfillHTLC(
return nil
}
// processRemoteUpdateFailMalformedHTLC takes an `UpdateFailMalformedHTLC` msg
// sent from the remote and processes it.
func (l *channelLink) processRemoteUpdateFailMalformedHTLC(
msg *lnwire.UpdateFailMalformedHTLC) error {
// Convert the failure type encoded within the HTLC fail message to the
// proper generic lnwire error code.
var failure lnwire.FailureMessage
switch msg.FailureCode {
case lnwire.CodeInvalidOnionVersion:
failure = &lnwire.FailInvalidOnionVersion{
OnionSHA256: msg.ShaOnionBlob,
}
case lnwire.CodeInvalidOnionHmac:
failure = &lnwire.FailInvalidOnionHmac{
OnionSHA256: msg.ShaOnionBlob,
}
case lnwire.CodeInvalidOnionKey:
failure = &lnwire.FailInvalidOnionKey{
OnionSHA256: msg.ShaOnionBlob,
}
// Handle malformed errors that are part of a blinded route. This case
// is slightly different, because we expect every relaying node in the
// blinded portion of the route to send malformed errors. If we're also
// a relaying node, we're likely going to switch this error out anyway
// for our own malformed error, but we handle the case here for
// completeness.
case lnwire.CodeInvalidBlinding:
failure = &lnwire.FailInvalidBlinding{
OnionSHA256: msg.ShaOnionBlob,
}
default:
l.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 form.
var b bytes.Buffer
if err := lnwire.EncodeFailure(&b, failure, 0); err != nil {
return fmt.Errorf("unable to encode malformed error: %w", err)
}
// If remote side have been unable to parse the onion blob we have sent
// to it, than we should transform the malformed HTLC message to the
// usual HTLC fail message.
err := l.channel.ReceiveFailHTLC(msg.ID, b.Bytes())
if err != nil {
l.failf(LinkFailureError{code: ErrInvalidUpdate},
"unable to handle upstream fail HTLC: %v", err)
return err
}
return nil
}