From 1793b1ab645345c2197dcde6809e2d0b74069cd2 Mon Sep 17 00:00:00 2001 From: George Tsagkarelis Date: Mon, 23 Jun 2025 13:01:01 +0200 Subject: [PATCH 1/3] routing+htlcswitch: ProduceHtlcExtraData uses first hop pub key --- htlcswitch/interfaces.go | 6 ++++-- routing/bandwidth_test.go | 5 +++-- routing/payment_lifecycle.go | 8 ++++++++ routing/payment_lifecycle_test.go | 6 +++++- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/htlcswitch/interfaces.go b/htlcswitch/interfaces.go index b0b67fc3404..ad7b1b097aa 100644 --- a/htlcswitch/interfaces.go +++ b/htlcswitch/interfaces.go @@ -14,6 +14,7 @@ import ( "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/record" + "github.com/lightningnetwork/lnd/routing/route" "github.com/lightningnetwork/lnd/tlv" ) @@ -495,8 +496,9 @@ type AuxHtlcModifier interface { // data blob of an HTLC, may produce a different blob or modify the // amount of bitcoin this htlc should carry. ProduceHtlcExtraData(totalAmount lnwire.MilliSatoshi, - htlcCustomRecords lnwire.CustomRecords) (lnwire.MilliSatoshi, - lnwire.CustomRecords, error) + htlcCustomRecords lnwire.CustomRecords, + peer route.Vertex) (lnwire.MilliSatoshi, lnwire.CustomRecords, + error) } // AuxTrafficShaper is an interface that allows the sender to determine if a diff --git a/routing/bandwidth_test.go b/routing/bandwidth_test.go index 4099b9608af..6ee1f1f647f 100644 --- a/routing/bandwidth_test.go +++ b/routing/bandwidth_test.go @@ -9,6 +9,7 @@ import ( "github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwire" + "github.com/lightningnetwork/lnd/routing/route" "github.com/lightningnetwork/lnd/tlv" "github.com/stretchr/testify/require" ) @@ -161,8 +162,8 @@ func (*mockTrafficShaper) PaymentBandwidth(_, _, _ fn.Option[tlv.Blob], // data blob of an HTLC, may produce a different blob or modify the // amount of bitcoin this htlc should carry. func (*mockTrafficShaper) ProduceHtlcExtraData(totalAmount lnwire.MilliSatoshi, - _ lnwire.CustomRecords) (lnwire.MilliSatoshi, lnwire.CustomRecords, - error) { + _ lnwire.CustomRecords, _ route.Vertex) (lnwire.MilliSatoshi, + lnwire.CustomRecords, error) { return totalAmount, nil, nil } diff --git a/routing/payment_lifecycle.go b/routing/payment_lifecycle.go index a64c8c87e6a..7a6443ab66a 100644 --- a/routing/payment_lifecycle.go +++ b/routing/payment_lifecycle.go @@ -724,6 +724,13 @@ func (p *paymentLifecycle) amendFirstHopData(rt *route.Route) error { // value. rt.FirstHopWireCustomRecords = p.firstHopCustomRecords + if len(rt.Hops) == 0 { + return fmt.Errorf("cannot amend first hop data, route length " + + "is zero") + } + + firstHopPK := rt.Hops[0].PubKeyBytes + // extraDataRequest is a helper struct to pass the custom records and // amount back from the traffic shaper. type extraDataRequest struct { @@ -740,6 +747,7 @@ func (p *paymentLifecycle) amendFirstHopData(rt *route.Route) error { func(ts htlcswitch.AuxTrafficShaper) fn.Result[extraDataRequest] { newAmt, newRecords, err := ts.ProduceHtlcExtraData( rt.TotalAmount, p.firstHopCustomRecords, + firstHopPK, ) if err != nil { return fn.Err[extraDataRequest](err) diff --git a/routing/payment_lifecycle_test.go b/routing/payment_lifecycle_test.go index 6d4c2fb4540..0ee751196f9 100644 --- a/routing/payment_lifecycle_test.go +++ b/routing/payment_lifecycle_test.go @@ -368,7 +368,11 @@ func TestRequestRouteSucceed(t *testing.T) { // Create a mock payment session and a dummy route. paySession := &mockPaymentSession{} - dummyRoute := &route.Route{} + dummyRoute := &route.Route{ + Hops: []*route.Hop{ + testHop, + }, + } // Mount the mocked payment session. p.paySession = paySession From 4ad84627e108e1edf9835af39ac45c235274bdbd Mon Sep 17 00:00:00 2001 From: George Tsagkarelis Date: Thu, 26 Jun 2025 12:11:56 +0200 Subject: [PATCH 2/3] htlcswitch+routing: PaymentBandwidth accepts channel peer pubkey argument --- htlcswitch/interfaces.go | 3 ++- htlcswitch/link.go | 11 ++++++++++- routing/bandwidth_test.go | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/htlcswitch/interfaces.go b/htlcswitch/interfaces.go index ad7b1b097aa..4739afff6ec 100644 --- a/htlcswitch/interfaces.go +++ b/htlcswitch/interfaces.go @@ -522,7 +522,8 @@ type AuxTrafficShaper interface { PaymentBandwidth(fundingBlob, htlcBlob, commitmentBlob fn.Option[tlv.Blob], linkBandwidth, htlcAmt lnwire.MilliSatoshi, - htlcView lnwallet.AuxHtlcView) (lnwire.MilliSatoshi, error) + htlcView lnwallet.AuxHtlcView, + peer route.Vertex) (lnwire.MilliSatoshi, error) // IsCustomHTLC returns true if the HTLC carries the set of relevant // custom records to put it under the purview of the traffic shaper, diff --git a/htlcswitch/link.go b/htlcswitch/link.go index d2bc4f4bf02..3aa47caf30c 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -31,6 +31,7 @@ import ( "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/queue" "github.com/lightningnetwork/lnd/record" + "github.com/lightningnetwork/lnd/routing/route" "github.com/lightningnetwork/lnd/ticker" "github.com/lightningnetwork/lnd/tlv" ) @@ -3503,11 +3504,19 @@ func (l *channelLink) AuxBandwidth(amount lnwire.MilliSatoshi, }) } + peerBytes := l.cfg.Peer.PubKey() + + peer, err := route.NewVertexFromBytes(peerBytes[:]) + if err != nil { + return fn.Err[OptionalBandwidth](fmt.Errorf("failed to decode "+ + "peer pub key: %v", err)) + } + // Ask for a specific bandwidth to be used for the channel. commitmentBlob := l.CommitmentCustomBlob() auxBandwidth, err := ts.PaymentBandwidth( fundingBlob, htlcBlob, commitmentBlob, l.Bandwidth(), amount, - l.channel.FetchLatestAuxHTLCView(), + l.channel.FetchLatestAuxHTLCView(), peer, ) if err != nil { return fn.Err[OptionalBandwidth](fmt.Errorf("failed to get "+ diff --git a/routing/bandwidth_test.go b/routing/bandwidth_test.go index 6ee1f1f647f..b7f6e3f13b2 100644 --- a/routing/bandwidth_test.go +++ b/routing/bandwidth_test.go @@ -153,7 +153,7 @@ func (*mockTrafficShaper) ShouldHandleTraffic(_ lnwire.ShortChannelID, // ShouldHandleTraffic method should be called first. func (*mockTrafficShaper) PaymentBandwidth(_, _, _ fn.Option[tlv.Blob], linkBandwidth, _ lnwire.MilliSatoshi, - _ lnwallet.AuxHtlcView) (lnwire.MilliSatoshi, error) { + _ lnwallet.AuxHtlcView, _ route.Vertex) (lnwire.MilliSatoshi, error) { return linkBandwidth, nil } From 9ef92d9ffd4b3cd4d73e73a440d2ad9d4c10a33a Mon Sep 17 00:00:00 2001 From: George Tsagkarelis Date: Wed, 2 Jul 2025 14:35:43 +0200 Subject: [PATCH 3/3] docs: add release note --- docs/release-notes/release-notes-0.19.2.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/release-notes-0.19.2.md b/docs/release-notes/release-notes-0.19.2.md index 440a4648847..a1fe31c1dc5 100644 --- a/docs/release-notes/release-notes-0.19.2.md +++ b/docs/release-notes/release-notes-0.19.2.md @@ -57,7 +57,10 @@ - [Improved](https://github.com/lightningnetwork/lnd/pull/9880) the connection restriction logic enforced by `accessman`. In addition, the restriction placed on outbound connections is now lifted. - +- [Enhanced](https://github.com/lightningnetwork/lnd/pull/9980) the aux traffic + shaper to now accept the first hop peer pub key as an argument. This can + affect the reported aux bandwidth and also the custom records that are + produced. ## RPC Updates ## lncli Updates