mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-08-28 14:40:51 +02:00
htlcswitch: add processRemoteUpdateFailMalformedHTLC
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
Reference in New Issue
Block a user