Skip to content

Commit 26feffc

Browse files
committed
server+tapchannel: always handle traffic for asset HTLCs
This fixes the first part of the issue: We didn't tell lnd that we wanted to handle traffic for non-asset channels. But that's wrong, because then lnd will pick non-asset channels for HTLCs in some situations. So we explicitly need to tell lnd there is no bandwidth in non-asset channels if an asset HTLC should be forwarded (or sent).
1 parent 30bc48f commit 26feffc

File tree

1 file changed

+38
-41
lines changed

1 file changed

+38
-41
lines changed

tapchannel/aux_traffic_shaper.go

Lines changed: 38 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -81,27 +81,30 @@ func (s *AuxTrafficShaper) Stop() error {
8181
// it is handled by the traffic shaper, then the normal bandwidth calculation
8282
// can be skipped and the bandwidth returned by PaymentBandwidth should be used
8383
// instead.
84-
func (s *AuxTrafficShaper) ShouldHandleTraffic(_ lnwire.ShortChannelID,
85-
fundingBlob, _ lfn.Option[tlv.Blob]) (bool, error) {
86-
87-
// If there is no auxiliary blob in the channel, it's not a custom
88-
// channel, and we don't need to handle it.
89-
if fundingBlob.IsNone() {
90-
log.Tracef("No aux funding blob set, not handling traffic")
84+
func (s *AuxTrafficShaper) ShouldHandleTraffic(cid lnwire.ShortChannelID,
85+
_, htlcBlob lfn.Option[tlv.Blob]) (bool, error) {
86+
87+
// The rule here is simple: If the HTLC is an asset HTLC, we _need_ to
88+
// handle the bandwidth. Because of non-strict forwarding in lnd, it
89+
// could otherwise be the case that we forward an asset HTLC on a
90+
// non-asset channel, which would be a problem.
91+
htlcBytes := htlcBlob.UnwrapOr(nil)
92+
if len(htlcBytes) == 0 {
93+
log.Tracef("Empty HTLC blob, not handling traffic for %v", cid)
9194
return false, nil
9295
}
9396

94-
// If we can successfully decode the channel blob as a channel capacity
95-
// information, we know that this is a custom channel.
96-
err := lfn.MapOptionZ(fundingBlob, func(blob tlv.Blob) error {
97-
_, err := cmsg.DecodeOpenChannel(blob)
98-
return err
99-
})
100-
if err != nil {
101-
return false, err
97+
// If there are no asset HTLC custom records, we don't need to do
98+
// anything as this is a regular payment.
99+
if !rfqmsg.HasAssetHTLCEntries(htlcBytes) {
100+
log.Tracef("No asset HTLC custom records, not handling "+
101+
"traffic for %v", cid)
102+
return false, nil
102103
}
103104

104-
// No error, so this is a custom channel, we'll want to decide.
105+
// If this _is_ an asset HTLC, we definitely want to handle the
106+
// bandwidth for this channel, so we can deny forwarding asset HTLCs
107+
// over non-asset channels.
105108
return true, nil
106109
}
107110

@@ -110,38 +113,32 @@ func (s *AuxTrafficShaper) ShouldHandleTraffic(_ lnwire.ShortChannelID,
110113
// is no bandwidth available. To find out if a channel is a custom channel that
111114
// should be handled by the traffic shaper, the HandleTraffic method should be
112115
// called first.
113-
func (s *AuxTrafficShaper) PaymentBandwidth(_, htlcBlob,
116+
func (s *AuxTrafficShaper) PaymentBandwidth(fundingBlob, htlcBlob,
114117
commitmentBlob lfn.Option[tlv.Blob], linkBandwidth,
115118
htlcAmt lnwire.MilliSatoshi,
116119
htlcView lnwallet.AuxHtlcView) (lnwire.MilliSatoshi, error) {
117120

118-
// If the commitment or HTLC blob is not set, we don't have any
119-
// information about the channel and cannot determine the available
120-
// bandwidth from a taproot asset perspective. We return the link
121-
// bandwidth as a fallback.
122-
if commitmentBlob.IsNone() || htlcBlob.IsNone() {
123-
log.Tracef("No commitment or HTLC blob set, returning link "+
124-
"bandwidth %v", linkBandwidth)
125-
return linkBandwidth, nil
126-
}
127-
128-
commitmentBytes := commitmentBlob.UnsafeFromSome()
129-
htlcBytes := htlcBlob.UnsafeFromSome()
130-
131-
// Sometimes the blob is set but actually empty, in which case we also
132-
// don't have any information about the channel.
133-
if len(commitmentBytes) == 0 || len(htlcBytes) == 0 {
134-
log.Tracef("Empty commitment or HTLC blob, returning link "+
135-
"bandwidth %v", linkBandwidth)
121+
fundingBlobBytes := fundingBlob.UnwrapOr(nil)
122+
htlcBytes := htlcBlob.UnwrapOr(nil)
123+
commitmentBytes := commitmentBlob.UnwrapOr(nil)
124+
125+
// If the HTLC is not an asset HTLC, we can just return the normal link
126+
// bandwidth, as we don't need to do any special math. We shouldn't even
127+
// get here in the first place, since the ShouldHandleTraffic function
128+
// should return false in this case.
129+
if len(htlcBytes) == 0 || !rfqmsg.HasAssetHTLCEntries(htlcBytes) {
130+
log.Tracef("Empty HTLC blob or no asset HTLC custom records, "+
131+
"returning link bandwidth %v", linkBandwidth)
136132
return linkBandwidth, nil
137133
}
138134

139-
// If there are no asset HTLC custom records, we don't need to do
140-
// anything as this is a regular payment.
141-
if !rfqmsg.HasAssetHTLCEntries(htlcBytes) {
142-
log.Tracef("No asset HTLC custom records, returning link "+
143-
"bandwidth %v", linkBandwidth)
144-
return linkBandwidth, nil
135+
// If this is an asset HTLC but the channel is not an asset channel, we
136+
// MUST deny forwarding the HTLC.
137+
if len(commitmentBytes) == 0 || len(fundingBlobBytes) == 0 {
138+
log.Tracef("Empty commitment or funding blob, cannot forward" +
139+
"asset HTLC over non-asset channel, returning 0 " +
140+
"bandwidth")
141+
return 0, nil
145142
}
146143

147144
commitment, err := cmsg.DecodeCommitment(commitmentBytes)

0 commit comments

Comments
 (0)