Skip to content

Commit cd72533

Browse files
committed
tapchannel: split PaymentBandwidth logic into helpers
To make `PaymentBandwidth` more readable, we separate the main codepaths into helper functions. One is used when we're directly comparing asset units to each other, and the other one is the path that calculates an msat amount based on an RFQ quote.
1 parent 5a45773 commit cd72533

File tree

1 file changed

+65
-13
lines changed

1 file changed

+65
-13
lines changed

tapchannel/aux_traffic_shaper.go

Lines changed: 65 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -174,18 +174,40 @@ func (s *AuxTrafficShaper) PaymentBandwidth(htlcBlob,
174174
return 0, fmt.Errorf("error decoding HTLC blob: %w", err)
175175
}
176176

177-
// localBalance is the total number of local asset units.
178-
localBalance := cmsg.OutputSum(commitment.LocalOutputs())
179-
180-
// There either already is an amount set in the HTLC (which would
181-
// indicate it to be a direct-channel keysend payment that just sends
182-
// assets to the direct peer with no conversion), in which case we don't
183-
// need an RFQ ID as we can just compare the local balance and the
184-
// required HTLC amount. If there is no amount set, we need to look up
185-
// the RFQ ID in the HTLC blob and use the accepted quote to determine
186-
// the amount.
177+
// With the help of the latest HtlcView, let's calculate a more precise
178+
// local balance. This is useful in order to not forward HTLCs that may
179+
// never be settled. Other HTLCs that may also call into this method are
180+
// not yet registered to the commitment, so we need to account for them
181+
// manually.
182+
computedLocal := ComputeLocalBalance(*commitment)
183+
184+
// If the HTLC carries asset units (keysend, forwarding), then there's
185+
// no need to do any RFQ related math. We can directly compare the asset
186+
// units of the HTLC with those in our local balance.
187187
htlcAssetAmount := htlc.Amounts.Val.Sum()
188-
if htlcAssetAmount != 0 && htlcAssetAmount <= localBalance {
188+
if htlcAssetAmount != 0 {
189+
return paymentBandwidthAssetUnits(
190+
htlcAssetAmount, computedLocal, linkBandwidth, htlcAmt,
191+
)
192+
}
193+
194+
// Otherwise, we derive the available bandwidth from the HTLC's RFQ and
195+
// the asset units in our local balance.
196+
return s.paymentBandwidth(
197+
htlc, computedLocal, linkBandwidth, minHtlcAmt,
198+
)
199+
}
200+
201+
// paymentBandwidthAssetUnits includes the asset unit related checks between the
202+
// HTLC carrying the units and the asset balance of our channel. The response
203+
// will either be infinite or zero bandwidth, as we can't really map the amount
204+
// to msats without an RFQ, and it's also not needed.
205+
func paymentBandwidthAssetUnits(htlcAssetAmount, computedLocal uint64,
206+
linkBandwidth,
207+
htlcAmt lnwire.MilliSatoshi) (lnwire.MilliSatoshi, error) {
208+
209+
switch {
210+
case htlcAssetAmount <= computedLocal:
189211
// Check if the current link bandwidth can afford sending out
190212
// the htlc amount without dipping into the channel reserve. If
191213
// it goes below the reserve, we report zero bandwidth as we
@@ -204,10 +226,30 @@ func (s *AuxTrafficShaper) PaymentBandwidth(htlcBlob,
204226
// matter too much here, we just want to signal that this
205227
// channel _does_ have available bandwidth.
206228
return lnwire.NewMSatFromSatoshis(btcutil.MaxSatoshi), nil
229+
230+
case htlcAssetAmount > computedLocal:
231+
// The asset balance of the channel is simply not enough to
232+
// route the asset units, we report 0 bandwidth in order for the
233+
// HTLC to fail back.
234+
return 0, nil
235+
236+
default:
237+
// We shouldn't reach this case, we add it only for the function
238+
// to always return something and the compiler to be happy.
239+
return 0, fmt.Errorf("should not reach this, invalid htlc " +
240+
"asset amount or computed local balance")
207241
}
242+
}
243+
244+
// paymentBandwidth returns the available payment bandwidth of the channel based
245+
// on the asset rate of the RFQ quote that is included in the HTLC and the asset
246+
// units of the local balance.
247+
func (s *AuxTrafficShaper) paymentBandwidth(htlc *rfqmsg.Htlc,
248+
localBalance uint64, linkBandwidth,
249+
minHtlcAmt lnwire.MilliSatoshi) (lnwire.MilliSatoshi, error) {
208250

209-
// If the HTLC doesn't have an asset amount and RFQ ID, it's incomplete,
210-
// and we cannot determine what channel to use.
251+
// If the HTLC doesn't have an RFQ ID, it's incomplete, and we cannot
252+
// determine the bandwidth.
211253
if htlc.RfqID.ValOpt().IsNone() {
212254
log.Tracef("No RFQ ID in HTLC, cannot determine matching " +
213255
"outgoing channel")
@@ -261,6 +303,16 @@ func (s *AuxTrafficShaper) PaymentBandwidth(htlcBlob,
261303
return availableBalanceMsat, nil
262304
}
263305

306+
// ComputeLocalBalance combines the given commitment state with the HtlcView to
307+
// produce the available local balance with accuracy.
308+
func ComputeLocalBalance(commitment cmsg.Commitment) uint64 {
309+
// Let's get the current local asset balance of the channel as reported
310+
// by the latest commitment.
311+
localBalance := cmsg.OutputSum(commitment.LocalOutputs())
312+
313+
return localBalance
314+
}
315+
264316
// ProduceHtlcExtraData is a function that, based on the previous custom record
265317
// blob of an HTLC, may produce a different blob or modify the amount of bitcoin
266318
// this HTLC should carry.

0 commit comments

Comments
 (0)