@@ -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,38 @@ 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 .BalanceAboveReserve (party ) {
3029
+ d := int64 (entry .Amount )
3030
+ balanceDeltas .ModifyForParty (
3031
+ party .CounterParty (),
3032
+ func (acc int64 ) int64 {
3033
+ return acc + d
3034
+ },
3035
+ )
3036
+ } else {
3037
+ d := int64 (entry .Amount )
3038
+ balanceDeltas .ModifyForParty (
3039
+ party ,
3040
+ func (acc int64 ) int64 {
3041
+ return acc + d
3042
+ },
3043
+ )
3044
+ }
3045
+
2990
3046
// If an incoming HTLC is being settled, then
2991
3047
// this means that the preimage has been
2992
3048
// received by the settling party Therefore, we
@@ -3024,7 +3080,7 @@ func (lc *LightningChannel) evaluateHTLCView(view *HtlcView,
3024
3080
liveAdds := fn .Filter (
3025
3081
view .Updates .GetForParty (party ),
3026
3082
func (pd * paymentDescriptor ) bool {
3027
- isAdd := pd .EntryType == Add
3083
+ isAdd := pd .isAdd ()
3028
3084
shouldSkip := skip .GetForParty (party ).
3029
3085
Contains (pd .HtlcIndex )
3030
3086
@@ -3063,7 +3119,7 @@ func (lc *LightningChannel) evaluateHTLCView(view *HtlcView,
3063
3119
// corresponding to whoseCommitmentChain.
3064
3120
isUncommitted := func (update * paymentDescriptor ) bool {
3065
3121
switch update .EntryType {
3066
- case Add :
3122
+ case Add , NoopAdd :
3067
3123
return update .addCommitHeights .GetForParty (
3068
3124
whoseCommitChain ,
3069
3125
) == 0
@@ -3827,7 +3883,7 @@ func (lc *LightningChannel) validateCommitmentSanity(theirLogCounter,
3827
3883
// Go through all updates, checking that they don't violate the
3828
3884
// channel constraints.
3829
3885
for _ , entry := range updates {
3830
- if entry .EntryType == Add {
3886
+ if entry .isAdd () {
3831
3887
// An HTLC is being added, this will add to the
3832
3888
// number and amount in flight.
3833
3889
amtInFlight += entry .Amount
@@ -4483,6 +4539,14 @@ func (lc *LightningChannel) ProcessChanSyncMsg(ctx context.Context,
4483
4539
// Next, we'll need to send over any updates we sent as part of
4484
4540
// this new proposed commitment state.
4485
4541
for _ , logUpdate := range commitDiff .LogUpdates {
4542
+ //nolint:ll
4543
+ if htlc , ok := logUpdate .UpdateMsg .(* lnwire.UpdateAddHTLC ); ok {
4544
+ delete (htlc .CustomRecords , uint64 (NoopHtlcType .TypeVal ()))
4545
+
4546
+ if len (htlc .CustomRecords ) == 0 {
4547
+ htlc .CustomRecords = nil
4548
+ }
4549
+ }
4486
4550
commitUpdates = append (
4487
4551
commitUpdates , logUpdate .UpdateMsg ,
4488
4552
)
@@ -5706,7 +5770,7 @@ func (lc *LightningChannel) ReceiveRevocation(revMsg *lnwire.RevokeAndAck) (
5706
5770
// don't re-forward any already processed HTLC's after a
5707
5771
// restart.
5708
5772
switch {
5709
- case pd .EntryType == Add && committedAdd && shouldFwdAdd :
5773
+ case pd .isAdd () && committedAdd && shouldFwdAdd :
5710
5774
// Construct a reference specifying the location that
5711
5775
// this forwarded Add will be written in the forwarding
5712
5776
// package constructed at this remote height.
@@ -5725,7 +5789,7 @@ func (lc *LightningChannel) ReceiveRevocation(revMsg *lnwire.RevokeAndAck) (
5725
5789
addUpdatesToForward , pd .toLogUpdate (),
5726
5790
)
5727
5791
5728
- case pd .EntryType != Add && committedRmv && shouldFwdRmv :
5792
+ case ! pd .isAdd () && committedRmv && shouldFwdRmv :
5729
5793
// Construct a reference specifying the location that
5730
5794
// this forwarded Settle/Fail will be written in the
5731
5795
// forwarding package constructed at this remote height.
@@ -5964,7 +6028,7 @@ func (lc *LightningChannel) GetDustSum(whoseCommit lntypes.ChannelParty,
5964
6028
// Grab all of our HTLCs and evaluate against the dust limit.
5965
6029
for e := lc .updateLogs .Local .Front (); e != nil ; e = e .Next () {
5966
6030
pd := e .Value
5967
- if pd .EntryType != Add {
6031
+ if ! pd .isAdd () {
5968
6032
continue
5969
6033
}
5970
6034
@@ -5983,7 +6047,7 @@ func (lc *LightningChannel) GetDustSum(whoseCommit lntypes.ChannelParty,
5983
6047
// Grab all of their HTLCs and evaluate against the dust limit.
5984
6048
for e := lc .updateLogs .Remote .Front (); e != nil ; e = e .Next () {
5985
6049
pd := e .Value
5986
- if pd .EntryType != Add {
6050
+ if ! pd .isAdd () {
5987
6051
continue
5988
6052
}
5989
6053
@@ -6056,9 +6120,16 @@ func (lc *LightningChannel) MayAddOutgoingHtlc(amt lnwire.MilliSatoshi) error {
6056
6120
func (lc * LightningChannel ) htlcAddDescriptor (htlc * lnwire.UpdateAddHTLC ,
6057
6121
openKey * models.CircuitKey ) * paymentDescriptor {
6058
6122
6123
+ entryType := Add
6124
+ customRecords := htlc .CustomRecords .Copy ()
6125
+ noopTLV := uint64 (NoopHtlcType .TypeVal ())
6126
+ if _ , ok := customRecords [noopTLV ]; ok {
6127
+ entryType = NoopAdd
6128
+ }
6129
+
6059
6130
return & paymentDescriptor {
6060
6131
ChanID : htlc .ChanID ,
6061
- EntryType : Add ,
6132
+ EntryType : entryType ,
6062
6133
RHash : PaymentHash (htlc .PaymentHash ),
6063
6134
Timeout : htlc .Expiry ,
6064
6135
Amount : htlc .Amount ,
@@ -6067,7 +6138,7 @@ func (lc *LightningChannel) htlcAddDescriptor(htlc *lnwire.UpdateAddHTLC,
6067
6138
OnionBlob : htlc .OnionBlob ,
6068
6139
OpenCircuitKey : openKey ,
6069
6140
BlindingPoint : htlc .BlindingPoint ,
6070
- CustomRecords : htlc . CustomRecords . Copy () ,
6141
+ CustomRecords : customRecords ,
6071
6142
}
6072
6143
}
6073
6144
@@ -6120,17 +6191,24 @@ func (lc *LightningChannel) ReceiveHTLC(htlc *lnwire.UpdateAddHTLC) (uint64,
6120
6191
lc .updateLogs .Remote .htlcCounter )
6121
6192
}
6122
6193
6194
+ entryType := Add
6195
+ customRecords := htlc .CustomRecords .Copy ()
6196
+ noopTLV := uint64 (NoopHtlcType .TypeVal ())
6197
+ if _ , ok := customRecords [noopTLV ]; ok {
6198
+ entryType = NoopAdd
6199
+ }
6200
+
6123
6201
pd := & paymentDescriptor {
6124
6202
ChanID : htlc .ChanID ,
6125
- EntryType : Add ,
6203
+ EntryType : entryType ,
6126
6204
RHash : PaymentHash (htlc .PaymentHash ),
6127
6205
Timeout : htlc .Expiry ,
6128
6206
Amount : htlc .Amount ,
6129
6207
LogIndex : lc .updateLogs .Remote .logIndex ,
6130
6208
HtlcIndex : lc .updateLogs .Remote .htlcCounter ,
6131
6209
OnionBlob : htlc .OnionBlob ,
6132
6210
BlindingPoint : htlc .BlindingPoint ,
6133
- CustomRecords : htlc . CustomRecords . Copy () ,
6211
+ CustomRecords : customRecords ,
6134
6212
}
6135
6213
6136
6214
localACKedIndex := lc .commitChains .Remote .tail ().messageIndices .Local
@@ -9819,7 +9897,7 @@ func (lc *LightningChannel) unsignedLocalUpdates(remoteMessageIndex,
9819
9897
9820
9898
// We don't save add updates as they are restored from the
9821
9899
// remote commitment in restoreStateLogs.
9822
- if pd .EntryType == Add {
9900
+ if pd .isAdd () {
9823
9901
continue
9824
9902
}
9825
9903
0 commit comments