htlcswitch: add processRemoteUpdateFailMalformedHTLC
This commit is contained in:
1 file changed
+75
-62
+75
-62
@@ -1936,69 +1936,11 @@ func (l *channelLink) handleUpstreamMsg(ctx context.Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
case *lnwire.UpdateFailMalformedHTLC:
|
case *lnwire.UpdateFailMalformedHTLC:
|
||||||
// Convert the failure type encoded within the HTLC fail
|
err := l.processRemoteUpdateFailMalformedHTLC(msg)
|
||||||
// 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())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.failf(LinkFailureError{code: ErrInvalidUpdate},
|
l.log.Errorf("failed to process remote fail "+
|
||||||
"unable to handle upstream fail HTLC: %v", err)
|
"malformed: %v", err)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4671,3 +4613,74 @@ func (l *channelLink) processRemoteUpdateFulfillHTLC(
|
|||||||
|
|
||||||
return nil
|
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