Skip to content

Commit f74efa3

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 dd9279c commit f74efa3

File tree

1 file changed

+64
-13
lines changed

1 file changed

+64
-13
lines changed

tapchannel/aux_traffic_shaper.go

Lines changed: 64 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.paymentBandwidthRfqMath(
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,29 @@ 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, nil
207240
}
241+
}
208242

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.
243+
// paymentBandwidthRfqMath returns the available payment bandwidth of the
244+
// channel based on the asset rate of the RFQ quote that is included in the
245+
// HTLC and the asset units of the local balance.
246+
func (s *AuxTrafficShaper) paymentBandwidthRfqMath(htlc *rfqmsg.Htlc,
247+
localBalance uint64, linkBandwidth,
248+
minHtlcAmt lnwire.MilliSatoshi) (lnwire.MilliSatoshi, error) {
249+
250+
// If the HTLC doesn't have an RFQ ID, it's incomplete, and we cannot
251+
// determine the bandwidth.
211252
if htlc.RfqID.ValOpt().IsNone() {
212253
log.Tracef("No RFQ ID in HTLC, cannot determine matching " +
213254
"outgoing channel")
@@ -261,6 +302,16 @@ func (s *AuxTrafficShaper) PaymentBandwidth(htlcBlob,
261302
return availableBalanceMsat, nil
262303
}
263304

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

0 commit comments

Comments
 (0)