Skip to content

Commit 7a59c6e

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 d099239 commit 7a59c6e

File tree

3 files changed

+64
-45
lines changed

3 files changed

+64
-45
lines changed

htlcswitch/link.go

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1909,6 +1909,7 @@ func (l *channelLink) handleDownstreamPkt(ctx context.Context,
19091909
err := l.channel.FailHTLC(
19101910
pkt.incomingHTLCID,
19111911
htlc.Reason,
1912+
htlc.ExtraData,
19121913
pkt.sourceRef,
19131914
pkt.destRef,
19141915
&inKey,
@@ -1954,6 +1955,7 @@ func (l *channelLink) handleDownstreamPkt(ctx context.Context,
19541955
htlc.ID,
19551956
pkt.obfuscator,
19561957
htlc.Reason,
1958+
htlc.ExtraData,
19571959
); err != nil {
19581960
l.log.Errorf("unable to send HTLC failure: %v",
19591961
err)
@@ -2263,7 +2265,9 @@ func (l *channelLink) handleUpstreamMsg(ctx context.Context,
22632265
// If remote side have been unable to parse the onion blob we
22642266
// have sent to it, than we should transform the malformed HTLC
22652267
// message to the usual HTLC fail message.
2266-
err := l.channel.ReceiveFailHTLC(msg.ID, b.Bytes())
2268+
err := l.channel.ReceiveFailHTLC(
2269+
msg.ID, b.Bytes(), msg.ExtraData,
2270+
)
22672271
if err != nil {
22682272
l.failf(LinkFailureError{code: ErrInvalidUpdate},
22692273
"unable to handle upstream fail HTLC: %v", err)
@@ -2301,7 +2305,9 @@ func (l *channelLink) handleUpstreamMsg(ctx context.Context,
23012305

23022306
// Add fail to the update log.
23032307
idx := msg.ID
2304-
err := l.channel.ReceiveFailHTLC(idx, msg.Reason[:])
2308+
err := l.channel.ReceiveFailHTLC(
2309+
idx, msg.Reason[:], msg.ExtraData,
2310+
)
23052311
if err != nil {
23062312
l.failf(LinkFailureError{code: ErrInvalidUpdate},
23072313
"unable to handle upstream fail HTLC: %v", err)
@@ -4395,7 +4401,7 @@ func (l *channelLink) sendHTLCError(add lnwire.UpdateAddHTLC,
43954401
return
43964402
}
43974403

4398-
err = l.channel.FailHTLC(add.ID, reason, &sourceRef, nil, nil)
4404+
err = l.channel.FailHTLC(add.ID, reason, nil, &sourceRef, nil, nil)
43994405
if err != nil {
44004406
l.log.Errorf("unable cancel htlc: %v", err)
44014407
return
@@ -4404,7 +4410,7 @@ func (l *channelLink) sendHTLCError(add lnwire.UpdateAddHTLC,
44044410
// Send the appropriate failure message depending on whether we're
44054411
// in a blinded route or not.
44064412
if err := l.sendIncomingHTLCFailureMsg(
4407-
add.ID, e, reason,
4413+
add.ID, e, reason, nil,
44084414
); err != nil {
44094415
l.log.Errorf("unable to send HTLC failure: %v", err)
44104416
return
@@ -4448,8 +4454,8 @@ func (l *channelLink) sendHTLCError(add lnwire.UpdateAddHTLC,
44484454
// used if we are the introduction node and need to present an error as if
44494455
// we're the failing party.
44504456
func (l *channelLink) sendIncomingHTLCFailureMsg(htlcIndex uint64,
4451-
e hop.ErrorEncrypter,
4452-
originalFailure lnwire.OpaqueReason) error {
4457+
e hop.ErrorEncrypter, originalFailure lnwire.OpaqueReason,
4458+
extraData lnwire.ExtraOpaqueData) error {
44534459

44544460
var msg lnwire.Message
44554461
switch {
@@ -4462,9 +4468,10 @@ func (l *channelLink) sendIncomingHTLCFailureMsg(htlcIndex uint64,
44624468
// code.
44634469
case e == nil:
44644470
msg = &lnwire.UpdateFailHTLC{
4465-
ChanID: l.ChanID(),
4466-
ID: htlcIndex,
4467-
Reason: originalFailure,
4471+
ChanID: l.ChanID(),
4472+
ID: htlcIndex,
4473+
Reason: originalFailure,
4474+
ExtraData: extraData,
44684475
}
44694476

44704477
l.log.Errorf("Unexpected blinded failure when "+
@@ -4475,9 +4482,10 @@ func (l *channelLink) sendIncomingHTLCFailureMsg(htlcIndex uint64,
44754482
// transformation on the error message and can just send the original.
44764483
case !e.Type().IsBlinded():
44774484
msg = &lnwire.UpdateFailHTLC{
4478-
ChanID: l.ChanID(),
4479-
ID: htlcIndex,
4480-
Reason: originalFailure,
4485+
ChanID: l.ChanID(),
4486+
ID: htlcIndex,
4487+
Reason: originalFailure,
4488+
ExtraData: extraData,
44814489
}
44824490

44834491
// When we're the introduction node, we need to convert the error to

lnwallet/channel.go

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

11541154
pd = &paymentDescriptor{
1155-
ChanID: wireMsg.ChanID,
1156-
Amount: ogHTLC.Amount,
1157-
RHash: ogHTLC.RHash,
1158-
ParentIndex: ogHTLC.HtlcIndex,
1159-
LogIndex: logUpdate.LogIndex,
1160-
EntryType: Fail,
1161-
FailReason: wireMsg.Reason[:],
1155+
ChanID: wireMsg.ChanID,
1156+
Amount: ogHTLC.Amount,
1157+
RHash: ogHTLC.RHash,
1158+
ParentIndex: ogHTLC.HtlcIndex,
1159+
LogIndex: logUpdate.LogIndex,
1160+
EntryType: Fail,
1161+
FailReason: wireMsg.Reason[:],
1162+
FailExtraData: wireMsg.ExtraData,
11621163
removeCommitHeights: lntypes.Dual[uint64]{
11631164
Remote: commitHeight,
11641165
},
@@ -1252,13 +1253,14 @@ func (lc *LightningChannel) localLogUpdateToPayDesc(logUpdate *channeldb.LogUpda
12521253
ogHTLC := remoteUpdateLog.lookupHtlc(wireMsg.ID)
12531254

12541255
return &paymentDescriptor{
1255-
ChanID: wireMsg.ChanID,
1256-
Amount: ogHTLC.Amount,
1257-
RHash: ogHTLC.RHash,
1258-
ParentIndex: ogHTLC.HtlcIndex,
1259-
LogIndex: logUpdate.LogIndex,
1260-
EntryType: Fail,
1261-
FailReason: wireMsg.Reason[:],
1256+
ChanID: wireMsg.ChanID,
1257+
Amount: ogHTLC.Amount,
1258+
RHash: ogHTLC.RHash,
1259+
ParentIndex: ogHTLC.HtlcIndex,
1260+
LogIndex: logUpdate.LogIndex,
1261+
EntryType: Fail,
1262+
FailReason: wireMsg.Reason[:],
1263+
FailExtraData: wireMsg.ExtraData,
12621264
removeCommitHeights: lntypes.Dual[uint64]{
12631265
Remote: commitHeight,
12641266
},
@@ -1367,13 +1369,14 @@ func (lc *LightningChannel) remoteLogUpdateToPayDesc(logUpdate *channeldb.LogUpd
13671369
ogHTLC := localUpdateLog.lookupHtlc(wireMsg.ID)
13681370

13691371
return &paymentDescriptor{
1370-
ChanID: wireMsg.ChanID,
1371-
Amount: ogHTLC.Amount,
1372-
RHash: ogHTLC.RHash,
1373-
ParentIndex: ogHTLC.HtlcIndex,
1374-
LogIndex: logUpdate.LogIndex,
1375-
EntryType: Fail,
1376-
FailReason: wireMsg.Reason[:],
1372+
ChanID: wireMsg.ChanID,
1373+
Amount: ogHTLC.Amount,
1374+
RHash: ogHTLC.RHash,
1375+
ParentIndex: ogHTLC.HtlcIndex,
1376+
LogIndex: logUpdate.LogIndex,
1377+
EntryType: Fail,
1378+
FailReason: wireMsg.Reason[:],
1379+
FailExtraData: wireMsg.ExtraData,
13771380
removeCommitHeights: lntypes.Dual[uint64]{
13781381
Local: commitHeight,
13791382
},
@@ -6298,7 +6301,8 @@ func (lc *LightningChannel) ReceiveHTLCSettle(preimage [32]byte, htlcIndex uint6
62986301
// NOTE: It is okay for sourceRef, destRef, and closeKey to be nil when unit
62996302
// testing the wallet.
63006303
func (lc *LightningChannel) FailHTLC(htlcIndex uint64, reason []byte,
6301-
sourceRef *channeldb.AddRef, destRef *channeldb.SettleFailRef,
6304+
extraData lnwire.ExtraOpaqueData, sourceRef *channeldb.AddRef,
6305+
destRef *channeldb.SettleFailRef,
63026306
closeKey *models.CircuitKey) error {
63036307

63046308
lc.Lock()
@@ -6326,6 +6330,7 @@ func (lc *LightningChannel) FailHTLC(htlcIndex uint64, reason []byte,
63266330
SourceRef: sourceRef,
63276331
DestRef: destRef,
63286332
ClosedCircuitKey: closeKey,
6333+
FailExtraData: extraData,
63296334
}
63306335

63316336
lc.updateLogs.Local.appendUpdate(pd)
@@ -6393,7 +6398,7 @@ func (lc *LightningChannel) MalformedFailHTLC(htlcIndex uint64,
63936398
// commitment update. This method should be called in response to the upstream
63946399
// party cancelling an outgoing HTLC.
63956400
func (lc *LightningChannel) ReceiveFailHTLC(htlcIndex uint64, reason []byte,
6396-
) error {
6401+
extraData lnwire.ExtraOpaqueData) error {
63976402

63986403
lc.Lock()
63996404
defer lc.Unlock()
@@ -6410,13 +6415,14 @@ func (lc *LightningChannel) ReceiveFailHTLC(htlcIndex uint64, reason []byte,
64106415
}
64116416

64126417
pd := &paymentDescriptor{
6413-
ChanID: lc.ChannelID(),
6414-
Amount: htlc.Amount,
6415-
RHash: htlc.RHash,
6416-
ParentIndex: htlc.HtlcIndex,
6417-
LogIndex: lc.updateLogs.Remote.logIndex,
6418-
EntryType: Fail,
6419-
FailReason: reason,
6418+
ChanID: lc.ChannelID(),
6419+
Amount: htlc.Amount,
6420+
RHash: htlc.RHash,
6421+
ParentIndex: htlc.HtlcIndex,
6422+
LogIndex: lc.updateLogs.Remote.logIndex,
6423+
EntryType: Fail,
6424+
FailReason: reason,
6425+
FailExtraData: extraData,
64206426
}
64216427

64226428
lc.updateLogs.Remote.appendUpdate(pd)

lnwallet/payment_descriptor.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,10 @@ type paymentDescriptor struct {
229229
// CustomRecords also stores the set of optional custom records that
230230
// may have been attached to a sent HTLC.
231231
CustomRecords lnwire.CustomRecords
232+
233+
// FailExtraData stores any extra opaque data that may have been present
234+
// when receiving an UpdateFailHTLC message.
235+
FailExtraData lnwire.ExtraOpaqueData
232236
}
233237

234238
// toLogUpdate recovers the underlying LogUpdate from the paymentDescriptor.
@@ -257,9 +261,10 @@ func (pd *paymentDescriptor) toLogUpdate() channeldb.LogUpdate {
257261
}
258262
case Fail:
259263
msg = &lnwire.UpdateFailHTLC{
260-
ChanID: pd.ChanID,
261-
ID: pd.ParentIndex,
262-
Reason: pd.FailReason,
264+
ChanID: pd.ChanID,
265+
ID: pd.ParentIndex,
266+
Reason: pd.FailReason,
267+
ExtraData: pd.FailExtraData,
263268
}
264269
case MalformedFail:
265270
msg = &lnwire.UpdateFailMalformedHTLC{

0 commit comments

Comments
 (0)