Skip to content

Commit bf5288e

Browse files
committed
htlcswitch+lnwallet: persist UpdateFailHTLC extra data
When propagating a failure backwards along a route we want to persist the received ExtraData of the downstream link so that any handling can occur on our node before returning the updated ExtraData to our upstream link.
1 parent 662566c commit bf5288e

File tree

6 files changed

+118
-86
lines changed

6 files changed

+118
-86
lines changed

htlcswitch/link.go

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3560,7 +3560,7 @@ func (l *channelLink) sendHTLCError(add lnwire.UpdateAddHTLC,
35603560
return
35613561
}
35623562

3563-
err = l.channel.FailHTLC(add.ID, reason, &sourceRef, nil, nil)
3563+
err = l.channel.FailHTLC(add.ID, reason, nil, &sourceRef, nil, nil)
35643564
if err != nil {
35653565
l.log.Errorf("unable cancel htlc: %v", err)
35663566
return
@@ -3569,7 +3569,7 @@ func (l *channelLink) sendHTLCError(add lnwire.UpdateAddHTLC,
35693569
// Send the appropriate failure message depending on whether we're
35703570
// in a blinded route or not.
35713571
if err := l.sendIncomingHTLCFailureMsg(
3572-
add.ID, e, reason,
3572+
add.ID, e, reason, nil,
35733573
); err != nil {
35743574
l.log.Errorf("unable to send HTLC failure: %v", err)
35753575
return
@@ -3613,8 +3613,8 @@ func (l *channelLink) sendHTLCError(add lnwire.UpdateAddHTLC,
36133613
// used if we are the introduction node and need to present an error as if
36143614
// we're the failing party.
36153615
func (l *channelLink) sendIncomingHTLCFailureMsg(htlcIndex uint64,
3616-
e hop.ErrorEncrypter,
3617-
originalFailure lnwire.OpaqueReason) error {
3616+
e hop.ErrorEncrypter, originalFailure lnwire.OpaqueReason,
3617+
extraData lnwire.ExtraOpaqueData) error {
36183618

36193619
var msg lnwire.Message
36203620
switch {
@@ -3627,9 +3627,10 @@ func (l *channelLink) sendIncomingHTLCFailureMsg(htlcIndex uint64,
36273627
// code.
36283628
case e == nil:
36293629
msg = &lnwire.UpdateFailHTLC{
3630-
ChanID: l.ChanID(),
3631-
ID: htlcIndex,
3632-
Reason: originalFailure,
3630+
ChanID: l.ChanID(),
3631+
ID: htlcIndex,
3632+
Reason: originalFailure,
3633+
ExtraData: extraData,
36333634
}
36343635

36353636
l.log.Errorf("Unexpected blinded failure when "+
@@ -3640,9 +3641,10 @@ func (l *channelLink) sendIncomingHTLCFailureMsg(htlcIndex uint64,
36403641
// transformation on the error message and can just send the original.
36413642
case !e.Type().IsBlinded():
36423643
msg = &lnwire.UpdateFailHTLC{
3643-
ChanID: l.ChanID(),
3644-
ID: htlcIndex,
3645-
Reason: originalFailure,
3644+
ChanID: l.ChanID(),
3645+
ID: htlcIndex,
3646+
Reason: originalFailure,
3647+
ExtraData: extraData,
36463648
}
36473649

36483650
// When we're the introduction node, we need to convert the error to
@@ -4177,7 +4179,7 @@ func (l *channelLink) processRemoteUpdateFailMalformedHTLC(
41774179
// If remote side have been unable to parse the onion blob we have sent
41784180
// to it, than we should transform the malformed HTLC message to the
41794181
// usual HTLC fail message.
4180-
err := l.channel.ReceiveFailHTLC(msg.ID, b.Bytes())
4182+
err := l.channel.ReceiveFailHTLC(msg.ID, b.Bytes(), msg.ExtraData)
41814183
if err != nil {
41824184
l.failf(LinkFailureError{code: ErrInvalidUpdate},
41834185
"unable to handle upstream fail HTLC: %v", err)
@@ -4218,7 +4220,7 @@ func (l *channelLink) processRemoteUpdateFailHTLC(
42184220

42194221
// Add fail to the update log.
42204222
idx := msg.ID
4221-
err := l.channel.ReceiveFailHTLC(idx, msg.Reason[:])
4223+
err := l.channel.ReceiveFailHTLC(idx, msg.Reason[:], msg.ExtraData)
42224224
if err != nil {
42234225
l.failf(LinkFailureError{code: ErrInvalidUpdate},
42244226
"unable to handle upstream fail HTLC: %v", err)
@@ -4658,8 +4660,8 @@ func (l *channelLink) processLocalUpdateFailHTLC(ctx context.Context,
46584660
// remove then HTLC from our local state machine.
46594661
inKey := pkt.inKey()
46604662
err := l.channel.FailHTLC(
4661-
pkt.incomingHTLCID, htlc.Reason, pkt.sourceRef, pkt.destRef,
4662-
&inKey,
4663+
pkt.incomingHTLCID, htlc.Reason, htlc.ExtraData, pkt.sourceRef,
4664+
pkt.destRef, &inKey,
46634665
)
46644666
if err != nil {
46654667
l.log.Errorf("unable to cancel incoming HTLC for "+
@@ -4695,7 +4697,9 @@ func (l *channelLink) processLocalUpdateFailHTLC(ctx context.Context,
46954697
// HTLC. If the incoming blinding point is non-nil, we know that we are
46964698
// a relaying node in a blinded path. Otherwise, we're either an
46974699
// introduction node or not part of a blinded path at all.
4698-
err = l.sendIncomingHTLCFailureMsg(htlc.ID, pkt.obfuscator, htlc.Reason)
4700+
err = l.sendIncomingHTLCFailureMsg(
4701+
htlc.ID, pkt.obfuscator, htlc.Reason, htlc.ExtraData,
4702+
)
46994703
if err != nil {
47004704
l.log.Errorf("unable to send HTLC failure: %v", err)
47014705

htlcswitch/link_isolated_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ func (l *linkTestContext) receiveFailAliceToBob() {
254254
l.t.Fatalf("expected UpdateFailHTLC, got %T", msg)
255255
}
256256

257-
err := l.bobChannel.ReceiveFailHTLC(failMsg.ID, failMsg.Reason)
257+
err := l.bobChannel.ReceiveFailHTLC(failMsg.ID, failMsg.Reason, nil)
258258
if err != nil {
259259
l.t.Fatalf("unable to apply received fail htlc: %v", err)
260260
}

htlcswitch/link_test.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2678,7 +2678,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) {
26782678
reason := make([]byte, 292)
26792679
copy(reason, []byte("nop"))
26802680

2681-
err = harness.bobChannel.FailHTLC(bobIndex, reason, nil, nil, nil)
2681+
err = harness.bobChannel.FailHTLC(bobIndex, reason, nil, nil, nil, nil)
26822682
require.NoError(t, err, "unable to fail htlc")
26832683
failMsg := &lnwire.UpdateFailHTLC{
26842684
ID: 1,
@@ -2925,7 +2925,9 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) {
29252925
if !ok {
29262926
t.Fatalf("expected UpdateFailHTLC, got %T", msg)
29272927
}
2928-
err = harness.bobChannel.ReceiveFailHTLC(failMsg.ID, []byte("fail"))
2928+
err = harness.bobChannel.ReceiveFailHTLC(
2929+
failMsg.ID, []byte("fail"), nil,
2930+
)
29292931
require.NoError(t, err, "failed receiving fail htlc")
29302932

29312933
// After failing an HTLC, the link will automatically trigger
@@ -7310,7 +7312,7 @@ func TestChannelLinkShortFailureRelay(t *testing.T) {
73107312
// Return a short htlc failure from Bob to Alice and lock in.
73117313
shortReason := make([]byte, 260)
73127314

7313-
err = harness.bobChannel.FailHTLC(0, shortReason, nil, nil, nil)
7315+
err = harness.bobChannel.FailHTLC(0, shortReason, nil, nil, nil, nil)
73147316
require.NoError(t, err)
73157317

73167318
harness.aliceLink.HandleChannelUpdate(&lnwire.UpdateFailHTLC{

lnwallet/channel.go

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,13 +1161,14 @@ func (lc *LightningChannel) logUpdateToPayDesc(logUpdate *channeldb.LogUpdate,
11611161
ogHTLC := remoteUpdateLog.lookupHtlc(wireMsg.ID)
11621162

11631163
pd = &paymentDescriptor{
1164-
ChanID: wireMsg.ChanID,
1165-
Amount: ogHTLC.Amount,
1166-
RHash: ogHTLC.RHash,
1167-
ParentIndex: ogHTLC.HtlcIndex,
1168-
LogIndex: logUpdate.LogIndex,
1169-
EntryType: Fail,
1170-
FailReason: wireMsg.Reason[:],
1164+
ChanID: wireMsg.ChanID,
1165+
Amount: ogHTLC.Amount,
1166+
RHash: ogHTLC.RHash,
1167+
ParentIndex: ogHTLC.HtlcIndex,
1168+
LogIndex: logUpdate.LogIndex,
1169+
EntryType: Fail,
1170+
FailReason: wireMsg.Reason[:],
1171+
FailExtraData: wireMsg.ExtraData,
11711172
removeCommitHeights: lntypes.Dual[uint64]{
11721173
Remote: commitHeight,
11731174
},
@@ -1261,13 +1262,14 @@ func (lc *LightningChannel) localLogUpdateToPayDesc(logUpdate *channeldb.LogUpda
12611262
ogHTLC := remoteUpdateLog.lookupHtlc(wireMsg.ID)
12621263

12631264
return &paymentDescriptor{
1264-
ChanID: wireMsg.ChanID,
1265-
Amount: ogHTLC.Amount,
1266-
RHash: ogHTLC.RHash,
1267-
ParentIndex: ogHTLC.HtlcIndex,
1268-
LogIndex: logUpdate.LogIndex,
1269-
EntryType: Fail,
1270-
FailReason: wireMsg.Reason[:],
1265+
ChanID: wireMsg.ChanID,
1266+
Amount: ogHTLC.Amount,
1267+
RHash: ogHTLC.RHash,
1268+
ParentIndex: ogHTLC.HtlcIndex,
1269+
LogIndex: logUpdate.LogIndex,
1270+
EntryType: Fail,
1271+
FailReason: wireMsg.Reason[:],
1272+
FailExtraData: wireMsg.ExtraData,
12711273
removeCommitHeights: lntypes.Dual[uint64]{
12721274
Remote: commitHeight,
12731275
},
@@ -1380,13 +1382,14 @@ func (lc *LightningChannel) remoteLogUpdateToPayDesc(logUpdate *channeldb.LogUpd
13801382
ogHTLC := localUpdateLog.lookupHtlc(wireMsg.ID)
13811383

13821384
return &paymentDescriptor{
1383-
ChanID: wireMsg.ChanID,
1384-
Amount: ogHTLC.Amount,
1385-
RHash: ogHTLC.RHash,
1386-
ParentIndex: ogHTLC.HtlcIndex,
1387-
LogIndex: logUpdate.LogIndex,
1388-
EntryType: Fail,
1389-
FailReason: wireMsg.Reason[:],
1385+
ChanID: wireMsg.ChanID,
1386+
Amount: ogHTLC.Amount,
1387+
RHash: ogHTLC.RHash,
1388+
ParentIndex: ogHTLC.HtlcIndex,
1389+
LogIndex: logUpdate.LogIndex,
1390+
EntryType: Fail,
1391+
FailReason: wireMsg.Reason[:],
1392+
FailExtraData: wireMsg.ExtraData,
13901393
removeCommitHeights: lntypes.Dual[uint64]{
13911394
Local: commitHeight,
13921395
},
@@ -6432,7 +6435,8 @@ func (lc *LightningChannel) ReceiveHTLCSettle(preimage [32]byte, htlcIndex uint6
64326435
// NOTE: It is okay for sourceRef, destRef, and closeKey to be nil when unit
64336436
// testing the wallet.
64346437
func (lc *LightningChannel) FailHTLC(htlcIndex uint64, reason []byte,
6435-
sourceRef *channeldb.AddRef, destRef *channeldb.SettleFailRef,
6438+
extraData lnwire.ExtraOpaqueData, sourceRef *channeldb.AddRef,
6439+
destRef *channeldb.SettleFailRef,
64366440
closeKey *models.CircuitKey) error {
64376441

64386442
lc.Lock()
@@ -6460,6 +6464,7 @@ func (lc *LightningChannel) FailHTLC(htlcIndex uint64, reason []byte,
64606464
SourceRef: sourceRef,
64616465
DestRef: destRef,
64626466
ClosedCircuitKey: closeKey,
6467+
FailExtraData: extraData,
64636468
}
64646469

64656470
lc.updateLogs.Local.appendUpdate(pd)
@@ -6527,7 +6532,7 @@ func (lc *LightningChannel) MalformedFailHTLC(htlcIndex uint64,
65276532
// commitment update. This method should be called in response to the upstream
65286533
// party cancelling an outgoing HTLC.
65296534
func (lc *LightningChannel) ReceiveFailHTLC(htlcIndex uint64, reason []byte,
6530-
) error {
6535+
extraData lnwire.ExtraOpaqueData) error {
65316536

65326537
lc.Lock()
65336538
defer lc.Unlock()
@@ -6544,13 +6549,14 @@ func (lc *LightningChannel) ReceiveFailHTLC(htlcIndex uint64, reason []byte,
65446549
}
65456550

65466551
pd := &paymentDescriptor{
6547-
ChanID: lc.ChannelID(),
6548-
Amount: htlc.Amount,
6549-
RHash: htlc.RHash,
6550-
ParentIndex: htlc.HtlcIndex,
6551-
LogIndex: lc.updateLogs.Remote.logIndex,
6552-
EntryType: Fail,
6553-
FailReason: reason,
6552+
ChanID: lc.ChannelID(),
6553+
Amount: htlc.Amount,
6554+
RHash: htlc.RHash,
6555+
ParentIndex: htlc.HtlcIndex,
6556+
LogIndex: lc.updateLogs.Remote.logIndex,
6557+
EntryType: Fail,
6558+
FailReason: reason,
6559+
FailExtraData: extraData,
65546560
}
65556561

65566562
lc.updateLogs.Remote.appendUpdate(pd)

0 commit comments

Comments
 (0)