Skip to content

Commit 4368718

Browse files
committed
htlcswitch: convert blinded failures for blinded payments
1 parent de9c9c0 commit 4368718

File tree

2 files changed

+117
-7
lines changed

2 files changed

+117
-7
lines changed

htlcswitch/hop/error_encryptor.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ const (
3939
EncrypterTypeRelaying = 4
4040
)
4141

42+
// IsBlinded returns a boolean indicating whether the error encrypter belongs
43+
// to a blinded route.
44+
func (e EncrypterType) IsBlinded() bool {
45+
return e == EncrypterTypeIntroduction || e == EncrypterTypeRelaying
46+
}
47+
4248
// ErrorEncrypterExtracter defines a function signature that extracts an
4349
// ErrorEncrypter from an sphinx OnionPacket.
4450
type ErrorEncrypterExtracter func(*btcec.PublicKey) (ErrorEncrypter,

htlcswitch/link.go

Lines changed: 111 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1793,8 +1793,20 @@ func (l *channelLink) handleDownstreamPkt(pkt *htlcPacket) {
17931793
htlc.ID = pkt.incomingHTLCID
17941794

17951795
// We send the HTLC message to the peer which initially created
1796-
// the HTLC.
1797-
l.cfg.Peer.SendMessage(false, htlc)
1796+
// the HTLC. If the incoming blinding point is non-nil, we
1797+
// know that we are a relaying node in a blinded path.
1798+
// Otherwise, we're either an introduction node or not part of
1799+
// a blinded path at all.
1800+
if err := l.sendIncomingHTLCFailureMsg(
1801+
htlc.ID,
1802+
pkt.obfuscator,
1803+
htlc.Reason,
1804+
); err != nil {
1805+
l.log.Errorf("unable to send HTLC failure: %v",
1806+
err)
1807+
1808+
return
1809+
}
17981810

17991811
// If the packet does not have a link failure set, it failed
18001812
// further down the route so we notify a forwarding failure.
@@ -3720,11 +3732,14 @@ func (l *channelLink) sendHTLCError(pd *lnwallet.PaymentDescriptor,
37203732
return
37213733
}
37223734

3723-
l.cfg.Peer.SendMessage(false, &lnwire.UpdateFailHTLC{
3724-
ChanID: l.ChanID(),
3725-
ID: pd.HtlcIndex,
3726-
Reason: reason,
3727-
})
3735+
// Send the appropriate failure message depending on whether we're
3736+
// in a blinded route or not.
3737+
if err := l.sendIncomingHTLCFailureMsg(
3738+
pd.HtlcIndex, e, reason,
3739+
); err != nil {
3740+
l.log.Errorf("unable to send HTLC failure: %v", err)
3741+
return
3742+
}
37283743

37293744
// Notify a link failure on our incoming link. Outgoing htlc information
37303745
// is not available at this point, because we have not decrypted the
@@ -3753,6 +3768,95 @@ func (l *channelLink) sendHTLCError(pd *lnwallet.PaymentDescriptor,
37533768
)
37543769
}
37553770

3771+
// sendPeerHTLCFailure handles sending a HTLC failure message back to the
3772+
// peer from which the HTLC was received. This function is primarily used to
3773+
// handle the special requirements of route blinding, specifically:
3774+
// - Forwarding nodes must switch out any errors with MalformedFailHTLC
3775+
// - Introduction nodes should return regular HTLC failure messages.
3776+
//
3777+
// It accepts the original opaque failure, which will be used in the case
3778+
// that we're not part of a blinded route and an error encrypter that'll be
3779+
// used if we are the introduction node and need to present an error as if
3780+
// we're the failing party.
3781+
//
3782+
// Note: this function does not yet handle special error cases for receiving
3783+
// nodes in blinded paths, as LND does not support blinded receives.
3784+
func (l *channelLink) sendIncomingHTLCFailureMsg(htlcIndex uint64,
3785+
e hop.ErrorEncrypter,
3786+
originalFailure lnwire.OpaqueReason) error {
3787+
3788+
var msg lnwire.Message
3789+
switch {
3790+
// Our circuit's error encrypter will be nil if this was a locally
3791+
// initiated payment. We can only hit a blinded error for a locally
3792+
// initiated payment if we allow ourselves to be picked as the
3793+
// introduction node for our own payments and in that case we
3794+
// shouldn't reach this code. To prevent the HTLC getting stuck,
3795+
// we fail it back and log an error.
3796+
// code.
3797+
case e == nil:
3798+
msg = &lnwire.UpdateFailHTLC{
3799+
ChanID: l.ChanID(),
3800+
ID: htlcIndex,
3801+
Reason: originalFailure,
3802+
}
3803+
3804+
l.log.Errorf("Unexpected blinded failure when "+
3805+
"we are the sending node, incoming htlc: %v(%v)",
3806+
l.ShortChanID(), htlcIndex)
3807+
3808+
// For cleartext hops (ie, non-blinded/normal) we don't need any
3809+
// transformation on the error message and can just send the original.
3810+
case !e.Type().IsBlinded():
3811+
msg = &lnwire.UpdateFailHTLC{
3812+
ChanID: l.ChanID(),
3813+
ID: htlcIndex,
3814+
Reason: originalFailure,
3815+
}
3816+
3817+
// When we're the introduction node, we need to convert the error to
3818+
// a UpdateFailHTLC.
3819+
case e.Type() == hop.EncrypterTypeIntroduction:
3820+
l.log.Debugf("Introduction blinded node switching out failure "+
3821+
"error: %v", htlcIndex)
3822+
3823+
// The specification does not require that we set the onion
3824+
// blob.
3825+
failureMsg := lnwire.NewInvalidBlinding(nil)
3826+
reason, err := e.EncryptFirstHop(failureMsg)
3827+
if err != nil {
3828+
return err
3829+
}
3830+
3831+
msg = &lnwire.UpdateFailHTLC{
3832+
ChanID: l.ChanID(),
3833+
ID: htlcIndex,
3834+
Reason: reason,
3835+
}
3836+
3837+
// If we are a relaying node, we need to switch out any error that
3838+
// we've received to a malformed HTLC error.
3839+
case e.Type() == hop.EncrypterTypeRelaying:
3840+
l.log.Debugf("Relaying blinded node switching out malformed "+
3841+
"error: %v", htlcIndex)
3842+
3843+
msg = &lnwire.UpdateFailMalformedHTLC{
3844+
ChanID: l.ChanID(),
3845+
ID: htlcIndex,
3846+
FailureCode: lnwire.CodeInvalidBlinding,
3847+
}
3848+
3849+
default:
3850+
return fmt.Errorf("unexpected encrypter: %d", e)
3851+
}
3852+
3853+
if err := l.cfg.Peer.SendMessage(false, msg); err != nil {
3854+
l.log.Warnf("Send update fail failed: %v", err)
3855+
}
3856+
3857+
return nil
3858+
}
3859+
37563860
// sendMalformedHTLCError helper function which sends the malformed HTLC update
37573861
// to the payment sender.
37583862
func (l *channelLink) sendMalformedHTLCError(htlcIndex uint64,

0 commit comments

Comments
 (0)