htlcswitch: add processRemoteUpdateFailHTLC
This commit is contained in:
1 file changed
+43
-33
+43
-33
@@ -1945,40 +1945,9 @@ func (l *channelLink) handleUpstreamMsg(ctx context.Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
case *lnwire.UpdateFailHTLC:
|
case *lnwire.UpdateFailHTLC:
|
||||||
// Verify that the failure reason is at least 256 bytes plus
|
err := l.processRemoteUpdateFailHTLC(msg)
|
||||||
// overhead.
|
|
||||||
const minimumFailReasonLength = lnwire.FailureMessageLength +
|
|
||||||
2 + 2 + 32
|
|
||||||
|
|
||||||
if len(msg.Reason) < minimumFailReasonLength {
|
|
||||||
// We've received a reason with a non-compliant length.
|
|
||||||
// Older nodes happily relay back these failures that
|
|
||||||
// may originate from a node further downstream.
|
|
||||||
// Therefore we can't just fail the channel.
|
|
||||||
//
|
|
||||||
// We want to be compliant ourselves, so we also can't
|
|
||||||
// pass back the reason unmodified. And we must make
|
|
||||||
// sure that we don't hit the magic length check of 260
|
|
||||||
// bytes in processRemoteSettleFails either.
|
|
||||||
//
|
|
||||||
// Because the reason is unreadable for the payer
|
|
||||||
// anyway, we just replace it by a compliant-length
|
|
||||||
// series of random bytes.
|
|
||||||
msg.Reason = make([]byte, minimumFailReasonLength)
|
|
||||||
_, err := crand.Read(msg.Reason[:])
|
|
||||||
if err != nil {
|
|
||||||
l.log.Errorf("Random generation error: %v", err)
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add fail to the update log.
|
|
||||||
idx := msg.ID
|
|
||||||
err := l.channel.ReceiveFailHTLC(idx, msg.Reason[:])
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.failf(LinkFailureError{code: ErrInvalidUpdate},
|
l.log.Errorf("failed to process remote fail: %v", err)
|
||||||
"unable to handle upstream fail HTLC: %v", err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4684,3 +4653,44 @@ func (l *channelLink) processRemoteUpdateFailMalformedHTLC(
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// processRemoteUpdateFailHTLC takes an `UpdateFailHTLC` msg sent from the
|
||||||
|
// remote and processes it.
|
||||||
|
func (l *channelLink) processRemoteUpdateFailHTLC(
|
||||||
|
msg *lnwire.UpdateFailHTLC) error {
|
||||||
|
|
||||||
|
// Verify that the failure reason is at least 256 bytes plus overhead.
|
||||||
|
const minimumFailReasonLength = lnwire.FailureMessageLength + 2 + 2 + 32
|
||||||
|
|
||||||
|
if len(msg.Reason) < minimumFailReasonLength {
|
||||||
|
// We've received a reason with a non-compliant length. Older
|
||||||
|
// nodes happily relay back these failures that may originate
|
||||||
|
// from a node further downstream. Therefore we can't just fail
|
||||||
|
// the channel.
|
||||||
|
//
|
||||||
|
// We want to be compliant ourselves, so we also can't pass back
|
||||||
|
// the reason unmodified. And we must make sure that we don't
|
||||||
|
// hit the magic length check of 260 bytes in
|
||||||
|
// processRemoteSettleFails either.
|
||||||
|
//
|
||||||
|
// Because the reason is unreadable for the payer anyway, we
|
||||||
|
// just replace it by a compliant-length series of random bytes.
|
||||||
|
msg.Reason = make([]byte, minimumFailReasonLength)
|
||||||
|
_, err := crand.Read(msg.Reason[:])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("random generation error: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add fail to the update log.
|
||||||
|
idx := msg.ID
|
||||||
|
err := l.channel.ReceiveFailHTLC(idx, msg.Reason[:])
|
||||||
|
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