@@ -551,6 +551,20 @@ func (lc *LightningChannel) diskHtlcToPayDesc(feeRate chainfee.SatPerKWeight,
551
551
remoteOutputIndex = htlc .OutputIndex
552
552
}
553
553
554
+ customRecords := htlc .CustomRecords .Copy ()
555
+ entryType := Add
556
+
557
+ // If the noop HTLC TLV is set then change this HTLC's type to noop.
558
+ noopTLV := uint64 (NoopHtlcType .TypeVal ())
559
+ if _ , ok := customRecords [noopTLV ]; ok {
560
+ entryType = NoopAdd
561
+ }
562
+
563
+ // The NoopAdd HTLC is an internal construct, and isn't meant to show up
564
+ // on the wire. So we'll remove the special element from the set of
565
+ // custom records.
566
+ delete (customRecords , noopTLV )
567
+
554
568
// With the scripts reconstructed (depending on if this is our commit
555
569
// vs theirs or a pending commit for the remote party), we can now
556
570
// re-create the original payment descriptor.
@@ -559,7 +573,7 @@ func (lc *LightningChannel) diskHtlcToPayDesc(feeRate chainfee.SatPerKWeight,
559
573
RHash : htlc .RHash ,
560
574
Timeout : htlc .RefundTimeout ,
561
575
Amount : htlc .Amt ,
562
- EntryType : Add ,
576
+ EntryType : entryType ,
563
577
HtlcIndex : htlc .HtlcIndex ,
564
578
LogIndex : htlc .LogIndex ,
565
579
OnionBlob : htlc .OnionBlob ,
@@ -570,7 +584,7 @@ func (lc *LightningChannel) diskHtlcToPayDesc(feeRate chainfee.SatPerKWeight,
570
584
theirPkScript : theirP2WSH ,
571
585
theirWitnessScript : theirWitnessScript ,
572
586
BlindingPoint : htlc .BlindingPoint ,
573
- CustomRecords : htlc . CustomRecords . Copy () ,
587
+ CustomRecords : customRecords ,
574
588
}, nil
575
589
}
576
590
@@ -1100,6 +1114,11 @@ func (lc *LightningChannel) logUpdateToPayDesc(logUpdate *channeldb.LogUpdate,
1100
1114
},
1101
1115
}
1102
1116
1117
+ noopTLV := uint64 (NoopHtlcType .TypeVal ())
1118
+ if _ , ok := pd .CustomRecords [noopTLV ]; ok {
1119
+ pd .EntryType = NoopAdd
1120
+ }
1121
+
1103
1122
isDustRemote := HtlcIsDust (
1104
1123
lc .channelState .ChanType , false , lntypes .Remote ,
1105
1124
feeRate , wireMsg .Amount .ToSatoshis (), remoteDustLimit ,
@@ -1336,6 +1355,11 @@ func (lc *LightningChannel) remoteLogUpdateToPayDesc(logUpdate *channeldb.LogUpd
1336
1355
},
1337
1356
}
1338
1357
1358
+ noopTLV := uint64 (NoopHtlcType .TypeVal ())
1359
+ if _ , ok := pd .CustomRecords [noopTLV ]; ok {
1360
+ pd .EntryType = NoopAdd
1361
+ }
1362
+
1339
1363
// We don't need to generate an htlc script yet. This will be
1340
1364
// done once we sign our remote commitment.
1341
1365
@@ -1736,7 +1760,7 @@ func (lc *LightningChannel) restorePendingRemoteUpdates(
1736
1760
// but this Add restoration was a no-op as every single one of
1737
1761
// these Adds was already restored since they're all incoming
1738
1762
// htlcs on the local commitment.
1739
- if payDesc .EntryType == Add {
1763
+ if payDesc .isAdd () {
1740
1764
continue
1741
1765
}
1742
1766
@@ -1881,7 +1905,7 @@ func (lc *LightningChannel) restorePendingLocalUpdates(
1881
1905
}
1882
1906
1883
1907
switch payDesc .EntryType {
1884
- case Add :
1908
+ case Add , NoopAdd :
1885
1909
// The HtlcIndex of the added HTLC _must_ be equal to
1886
1910
// the log's htlcCounter at this point. If it is not we
1887
1911
// panic to catch this.
@@ -2987,6 +3011,41 @@ func (lc *LightningChannel) evaluateHTLCView(view *HtlcView,
2987
3011
)
2988
3012
if rmvHeight == 0 {
2989
3013
switch {
3014
+ // If this a noop add, then when we settle the
3015
+ // HTLC, we actually credit the sender with the
3016
+ // amount again, thus making it a noop.
3017
+ case entry .EntryType == Settle &&
3018
+ addEntry .EntryType == NoopAdd :
3019
+ channel := lc .channelState
3020
+
3021
+ // If the receiver has existing balance
3022
+ // above dust then we go ahead with
3023
+ // crediting the amount back to the
3024
+ // sender. Otherwise we give the amount
3025
+ // to the receiver. We do this because
3026
+ // the receiver needs some above-dust
3027
+ // balance to anchor the AuxBlob.
3028
+ if channel .BalanceAboveDustForParty (
3029
+ party ,
3030
+ ) {
3031
+
3032
+ d := int64 (entry .Amount )
3033
+ balanceDeltas .ModifyForParty (
3034
+ party .CounterParty (),
3035
+ func (acc int64 ) int64 {
3036
+ return acc + d
3037
+ },
3038
+ )
3039
+ } else {
3040
+ d := int64 (entry .Amount )
3041
+ balanceDeltas .ModifyForParty (
3042
+ party ,
3043
+ func (acc int64 ) int64 {
3044
+ return acc + d
3045
+ },
3046
+ )
3047
+ }
3048
+
2990
3049
// If an incoming HTLC is being settled, then
2991
3050
// this means that the preimage has been
2992
3051
// received by the settling party Therefore, we
@@ -3024,7 +3083,7 @@ func (lc *LightningChannel) evaluateHTLCView(view *HtlcView,
3024
3083
liveAdds := fn .Filter (
3025
3084
view .Updates .GetForParty (party ),
3026
3085
func (pd * paymentDescriptor ) bool {
3027
- isAdd := pd .EntryType == Add
3086
+ isAdd := pd .isAdd ()
3028
3087
shouldSkip := skip .GetForParty (party ).
3029
3088
Contains (pd .HtlcIndex )
3030
3089
@@ -3063,7 +3122,7 @@ func (lc *LightningChannel) evaluateHTLCView(view *HtlcView,
3063
3122
// corresponding to whoseCommitmentChain.
3064
3123
isUncommitted := func (update * paymentDescriptor ) bool {
3065
3124
switch update .EntryType {
3066
- case Add :
3125
+ case Add , NoopAdd :
3067
3126
return update .addCommitHeights .GetForParty (
3068
3127
whoseCommitChain ,
3069
3128
) == 0
@@ -3827,7 +3886,7 @@ func (lc *LightningChannel) validateCommitmentSanity(theirLogCounter,
3827
3886
// Go through all updates, checking that they don't violate the
3828
3887
// channel constraints.
3829
3888
for _ , entry := range updates {
3830
- if entry .EntryType == Add {
3889
+ if entry .isAdd () {
3831
3890
// An HTLC is being added, this will add to the
3832
3891
// number and amount in flight.
3833
3892
amtInFlight += entry .Amount
@@ -4483,6 +4542,14 @@ func (lc *LightningChannel) ProcessChanSyncMsg(ctx context.Context,
4483
4542
// Next, we'll need to send over any updates we sent as part of
4484
4543
// this new proposed commitment state.
4485
4544
for _ , logUpdate := range commitDiff .LogUpdates {
4545
+ //nolint:ll
4546
+ if htlc , ok := logUpdate .UpdateMsg .(* lnwire.UpdateAddHTLC ); ok {
4547
+ delete (htlc .CustomRecords , uint64 (NoopHtlcType .TypeVal ()))
4548
+
4549
+ if len (htlc .CustomRecords ) == 0 {
4550
+ htlc .CustomRecords = nil
4551
+ }
4552
+ }
4486
4553
commitUpdates = append (
4487
4554
commitUpdates , logUpdate .UpdateMsg ,
4488
4555
)
@@ -5706,7 +5773,7 @@ func (lc *LightningChannel) ReceiveRevocation(revMsg *lnwire.RevokeAndAck) (
5706
5773
// don't re-forward any already processed HTLC's after a
5707
5774
// restart.
5708
5775
switch {
5709
- case pd .EntryType == Add && committedAdd && shouldFwdAdd :
5776
+ case pd .isAdd () && committedAdd && shouldFwdAdd :
5710
5777
// Construct a reference specifying the location that
5711
5778
// this forwarded Add will be written in the forwarding
5712
5779
// package constructed at this remote height.
@@ -5725,7 +5792,7 @@ func (lc *LightningChannel) ReceiveRevocation(revMsg *lnwire.RevokeAndAck) (
5725
5792
addUpdatesToForward , pd .toLogUpdate (),
5726
5793
)
5727
5794
5728
- case pd .EntryType != Add && committedRmv && shouldFwdRmv :
5795
+ case ! pd .isAdd () && committedRmv && shouldFwdRmv :
5729
5796
// Construct a reference specifying the location that
5730
5797
// this forwarded Settle/Fail will be written in the
5731
5798
// forwarding package constructed at this remote height.
@@ -5964,7 +6031,7 @@ func (lc *LightningChannel) GetDustSum(whoseCommit lntypes.ChannelParty,
5964
6031
// Grab all of our HTLCs and evaluate against the dust limit.
5965
6032
for e := lc .updateLogs .Local .Front (); e != nil ; e = e .Next () {
5966
6033
pd := e .Value
5967
- if pd .EntryType != Add {
6034
+ if ! pd .isAdd () {
5968
6035
continue
5969
6036
}
5970
6037
@@ -5983,7 +6050,7 @@ func (lc *LightningChannel) GetDustSum(whoseCommit lntypes.ChannelParty,
5983
6050
// Grab all of their HTLCs and evaluate against the dust limit.
5984
6051
for e := lc .updateLogs .Remote .Front (); e != nil ; e = e .Next () {
5985
6052
pd := e .Value
5986
- if pd .EntryType != Add {
6053
+ if ! pd .isAdd () {
5987
6054
continue
5988
6055
}
5989
6056
@@ -6056,9 +6123,16 @@ func (lc *LightningChannel) MayAddOutgoingHtlc(amt lnwire.MilliSatoshi) error {
6056
6123
func (lc * LightningChannel ) htlcAddDescriptor (htlc * lnwire.UpdateAddHTLC ,
6057
6124
openKey * models.CircuitKey ) * paymentDescriptor {
6058
6125
6126
+ entryType := Add
6127
+ customRecords := htlc .CustomRecords .Copy ()
6128
+ noopTLV := uint64 (NoopHtlcType .TypeVal ())
6129
+ if _ , ok := customRecords [noopTLV ]; ok {
6130
+ entryType = NoopAdd
6131
+ }
6132
+
6059
6133
return & paymentDescriptor {
6060
6134
ChanID : htlc .ChanID ,
6061
- EntryType : Add ,
6135
+ EntryType : entryType ,
6062
6136
RHash : PaymentHash (htlc .PaymentHash ),
6063
6137
Timeout : htlc .Expiry ,
6064
6138
Amount : htlc .Amount ,
@@ -6067,7 +6141,7 @@ func (lc *LightningChannel) htlcAddDescriptor(htlc *lnwire.UpdateAddHTLC,
6067
6141
OnionBlob : htlc .OnionBlob ,
6068
6142
OpenCircuitKey : openKey ,
6069
6143
BlindingPoint : htlc .BlindingPoint ,
6070
- CustomRecords : htlc . CustomRecords . Copy () ,
6144
+ CustomRecords : customRecords ,
6071
6145
}
6072
6146
}
6073
6147
@@ -6120,17 +6194,24 @@ func (lc *LightningChannel) ReceiveHTLC(htlc *lnwire.UpdateAddHTLC) (uint64,
6120
6194
lc .updateLogs .Remote .htlcCounter )
6121
6195
}
6122
6196
6197
+ entryType := Add
6198
+ customRecords := htlc .CustomRecords .Copy ()
6199
+ noopTLV := uint64 (NoopHtlcType .TypeVal ())
6200
+ if _ , ok := customRecords [noopTLV ]; ok {
6201
+ entryType = NoopAdd
6202
+ }
6203
+
6123
6204
pd := & paymentDescriptor {
6124
6205
ChanID : htlc .ChanID ,
6125
- EntryType : Add ,
6206
+ EntryType : entryType ,
6126
6207
RHash : PaymentHash (htlc .PaymentHash ),
6127
6208
Timeout : htlc .Expiry ,
6128
6209
Amount : htlc .Amount ,
6129
6210
LogIndex : lc .updateLogs .Remote .logIndex ,
6130
6211
HtlcIndex : lc .updateLogs .Remote .htlcCounter ,
6131
6212
OnionBlob : htlc .OnionBlob ,
6132
6213
BlindingPoint : htlc .BlindingPoint ,
6133
- CustomRecords : htlc . CustomRecords . Copy () ,
6214
+ CustomRecords : customRecords ,
6134
6215
}
6135
6216
6136
6217
localACKedIndex := lc .commitChains .Remote .tail ().messageIndices .Local
@@ -9819,7 +9900,7 @@ func (lc *LightningChannel) unsignedLocalUpdates(remoteMessageIndex,
9819
9900
9820
9901
// We don't save add updates as they are restored from the
9821
9902
// remote commitment in restoreStateLogs.
9822
- if pd .EntryType == Add {
9903
+ if pd .isAdd () {
9823
9904
continue
9824
9905
}
9825
9906
0 commit comments