Skip to content

Commit

Permalink
tapchannel: add chan reserve check on PaymentBandwidth method
Browse files Browse the repository at this point in the history
  • Loading branch information
GeorgeTsagk committed Sep 19, 2024
1 parent ece0f83 commit a6f5c3e
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 4 deletions.
5 changes: 3 additions & 2 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -990,7 +990,8 @@ func (s *Server) HandleTraffic(cid lnwire.ShortChannelID,
//
// NOTE: This method is part of the routing.TlvTrafficShaper interface.
func (s *Server) PaymentBandwidth(htlcBlob, commitmentBlob lfn.Option[tlv.Blob],
linkBandwidth lnwire.MilliSatoshi) (lnwire.MilliSatoshi, error) {
linkBandwidth,
htlcAmt lnwire.MilliSatoshi) (lnwire.MilliSatoshi, error) {

srvrLog.Debugf("PaymentBandwidth called, htlcBlob=%v, "+
"commitmentBlob=%v", spew.Sdump(htlcBlob),
Expand All @@ -1001,7 +1002,7 @@ func (s *Server) PaymentBandwidth(htlcBlob, commitmentBlob lfn.Option[tlv.Blob],
}

return s.cfg.AuxTrafficShaper.PaymentBandwidth(
htlcBlob, commitmentBlob, linkBandwidth,
htlcBlob, commitmentBlob, linkBandwidth, htlcAmt,
)
}

Expand Down
42 changes: 40 additions & 2 deletions tapchannel/aux_traffic_shaper.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ func (s *AuxTrafficShaper) HandleTraffic(_ lnwire.ShortChannelID,
// should be handled by the traffic shaper, the HandleTraffic method should be
// called first.
func (s *AuxTrafficShaper) PaymentBandwidth(htlcBlob,
commitmentBlob lfn.Option[tlv.Blob],
linkBandwidth lnwire.MilliSatoshi) (lnwire.MilliSatoshi, error) {
commitmentBlob lfn.Option[tlv.Blob], linkBandwidth,
htlcAmt lnwire.MilliSatoshi) (lnwire.MilliSatoshi, error) {

// If the commitment or HTLC blob is not set, we don't have any
// information about the channel and cannot determine the available
Expand All @@ -140,6 +140,28 @@ func (s *AuxTrafficShaper) PaymentBandwidth(htlcBlob,
return linkBandwidth, nil
}

// Get the minimum HTLC amount, which is just above dust.
minHtlcAmt := lnwire.NewMSatFromSatoshis(DefaultOnChainHtlcAmount)

// LND calls this hook twice. Once to see if the overall budget of the
// node is enough, and then during pathfinding to actually see if
// there's enough balance in the channel to make the payment attempt.
//
// When doing the overall balance check, we don't know what the actual
// htlcAmt is in satoshis, so a value of 0 will be passed here. Let's at
// least check if we can afford the min amount above dust. If the actual
// htlc amount ends up being greater when calling this method during
// pathfinding, we will still check it below.

// If the passed htlcAmt is below dust, then assume the dust amount. At
// this point we know we are sending assets, so we cannot anchor them to
// dust amounts. Dust HTLCs are added to the fees and aren't
// materialized in an on-chain output, so we wouldn't have anything
// to anchor the asset commitment to.
if htlcAmt < minHtlcAmt {
htlcAmt = minHtlcAmt
}

commitment, err := cmsg.DecodeCommitment(commitmentBytes)
if err != nil {
return 0, fmt.Errorf("error decoding commitment blob: %w", err)
Expand All @@ -161,6 +183,14 @@ func (s *AuxTrafficShaper) PaymentBandwidth(htlcBlob,
// the amount.
htlcAssetAmount := htlc.Amounts.Val.Sum()
if htlcAssetAmount != 0 && htlcAssetAmount <= localBalance {
// Check if the current link bandwidth can afford sending out
// the htlc amount without dipping into the channel reserve. If
// it goes below the reserve, we report zero bandwdith as we
// cannot push the htlc amount.
if linkBandwidth < htlcAmt {
return 0, nil
}

// We signal "infinite" bandwidth by returning a very high
// value (number of Satoshis ever in existence), since we might
// not have a quote available to know what the asset amount
Expand Down Expand Up @@ -190,6 +220,14 @@ func (s *AuxTrafficShaper) PaymentBandwidth(htlcBlob,

mSatPerAssetUnit := quote.BidPrice

// At this point we have acquired what we need to express the asset
// bandwidth expressed in satoshis. Before we return the result, we need
// to check if the link bandwidth can afford sending a non-dust htlc to
// the other side.
if linkBandwidth < minHtlcAmt {
return 0, nil
}

// The available balance is the local asset unit expressed in
// milli-satoshis.
return lnwire.MilliSatoshi(localBalance) * mSatPerAssetUnit, nil
Expand Down

0 comments on commit a6f5c3e

Please sign in to comment.