From 716db8b7d3d6f19d659eb21e343c30d90411731b Mon Sep 17 00:00:00 2001 From: Oliver Gugger Date: Tue, 11 Feb 2025 17:16:06 +0100 Subject: [PATCH] htlcswitch+routing: return IsHandled from AuxBandwidth To make it more clear whether the external traffic shaper is handling a channel or not, we return an explicit boolean. --- htlcswitch/interfaces.go | 14 ++++++++++++-- htlcswitch/link.go | 21 ++++++++++++++------- htlcswitch/mock.go | 2 +- routing/bandwidth.go | 9 ++++++++- routing/mock_test.go | 4 +--- 5 files changed, 36 insertions(+), 14 deletions(-) diff --git a/htlcswitch/interfaces.go b/htlcswitch/interfaces.go index 1ea1318ff..a39eef6a4 100644 --- a/htlcswitch/interfaces.go +++ b/htlcswitch/interfaces.go @@ -208,8 +208,18 @@ const ( // OptionalBandwidth is a type alias for the result of a bandwidth query that // may return a bandwidth value or fn.None if the bandwidth is not available or -// not applicable. -type OptionalBandwidth = fn.Option[lnwire.MilliSatoshi] +// not applicable. IsHandled is set to false if the external traffic shaper does +// not handle the channel in question. +type OptionalBandwidth struct { + // IsHandled is true if the external traffic shaper handles the channel. + // If this is false, then the bandwidth value is not applicable. + IsHandled bool + + // Bandwidth is the available bandwidth for the channel, as determined + // by the external traffic shaper. If the external traffic shaper is not + // handling the channel, this value will be fn.None. + Bandwidth fn.Option[lnwire.MilliSatoshi] +} // ChannelLink is an interface which represents the subsystem for managing the // incoming htlc requests, applying the changes to the channel, and also diff --git a/htlcswitch/link.go b/htlcswitch/link.go index 77c8f67e3..f7b857917 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -3443,9 +3443,13 @@ func (l *channelLink) canSendHtlc(policy models.ForwardingPolicy, return NewLinkError(&lnwire.FailTemporaryNodeFailure{}) } - auxBandwidth.WhenSome(func(bandwidth lnwire.MilliSatoshi) { - availableBandwidth = bandwidth - }) + if auxBandwidth.IsHandled && auxBandwidth.Bandwidth.IsSome() { + auxBandwidth.Bandwidth.WhenSome( + func(bandwidth lnwire.MilliSatoshi) { + availableBandwidth = bandwidth + }, + ) + } // Check to see if there is enough balance in this channel. if amt > availableBandwidth { @@ -3471,8 +3475,6 @@ func (l *channelLink) AuxBandwidth(amount lnwire.MilliSatoshi, cid lnwire.ShortChannelID, htlcBlob fn.Option[tlv.Blob], ts AuxTrafficShaper) fn.Result[OptionalBandwidth] { - unknownBandwidth := fn.None[lnwire.MilliSatoshi]() - fundingBlob := l.FundingCustomBlob() shouldHandle, err := ts.ShouldHandleTraffic(cid, fundingBlob) if err != nil { @@ -3486,7 +3488,9 @@ func (l *channelLink) AuxBandwidth(amount lnwire.MilliSatoshi, // If this channel isn't handled by the aux traffic shaper, we'll return // early. if !shouldHandle { - return fn.Ok(unknownBandwidth) + return fn.Ok(OptionalBandwidth{ + IsHandled: false, + }) } // Ask for a specific bandwidth to be used for the channel. @@ -3502,7 +3506,10 @@ func (l *channelLink) AuxBandwidth(amount lnwire.MilliSatoshi, log.Debugf("ShortChannelID=%v: aux traffic shaper reported available "+ "bandwidth: %v", cid, auxBandwidth) - return fn.Ok(fn.Some(auxBandwidth)) + return fn.Ok(OptionalBandwidth{ + IsHandled: true, + Bandwidth: fn.Some(auxBandwidth), + }) } // Stats returns the statistics of channel link. diff --git a/htlcswitch/mock.go b/htlcswitch/mock.go index 5cf796657..cb814e95c 100644 --- a/htlcswitch/mock.go +++ b/htlcswitch/mock.go @@ -976,7 +976,7 @@ func (f *mockChannelLink) AuxBandwidth(lnwire.MilliSatoshi, lnwire.ShortChannelID, fn.Option[tlv.Blob], AuxTrafficShaper) fn.Result[OptionalBandwidth] { - return fn.Ok(fn.None[lnwire.MilliSatoshi]()) + return fn.Ok(OptionalBandwidth{}) } var _ ChannelLink = (*mockChannelLink)(nil) diff --git a/routing/bandwidth.go b/routing/bandwidth.go index a552628c7..5e5f1ee57 100644 --- a/routing/bandwidth.go +++ b/routing/bandwidth.go @@ -143,6 +143,13 @@ func (b *bandwidthManager) getBandwidth(cid lnwire.ShortChannelID, "auxiliary bandwidth: %w", err)) } + // If the external traffic shaper is not handling the + // channel, we'll just return the original bandwidth and + // no custom amount. + if !auxBandwidth.IsHandled { + return fn.Ok(bandwidthResult{}) + } + // We don't know the actual HTLC amount that will be // sent using the custom channel. But we'll still want // to make sure we can add another HTLC, using the @@ -152,7 +159,7 @@ func (b *bandwidthManager) getBandwidth(cid lnwire.ShortChannelID, // the max number of HTLCs on the channel. A proper // balance check is done elsewhere. return fn.Ok(bandwidthResult{ - bandwidth: auxBandwidth, + bandwidth: auxBandwidth.Bandwidth, htlcAmount: fn.Some[lnwire.MilliSatoshi](0), }) }, diff --git a/routing/mock_test.go b/routing/mock_test.go index 86fd76549..a1268d0c3 100644 --- a/routing/mock_test.go +++ b/routing/mock_test.go @@ -904,9 +904,7 @@ func (m *mockLink) AuxBandwidth(lnwire.MilliSatoshi, lnwire.ShortChannelID, fn.Option[tlv.Blob], htlcswitch.AuxTrafficShaper) fn.Result[htlcswitch.OptionalBandwidth] { - return fn.Ok[htlcswitch.OptionalBandwidth]( - fn.None[lnwire.MilliSatoshi](), - ) + return fn.Ok(htlcswitch.OptionalBandwidth{}) } // EligibleToForward returns the mock's configured eligibility.