Repository: lightningnetwork/lnd
Pull request #9605 (2025-03-17 14:20:44)

cmd: fix error parsed from status
A user was having trouble debugging its node, which was running in an `lnd` without the `walletrpc` enabled. The user then tried to build the `lncli` with the RPC enabled, but the `lnd` node could not be built since it was running remotely. Then the command failed with the following weird msg,
```
./lncli wallet pendingsweeps
[lncli] Wallet is encrypted. Please unlock using 'lncli unlock', or set password using 'lncli create' if this is the first time starting lnd.
```

This message is confusing as it doesn't show the RPC isn't built. This is now changed to,
```
./lncli-debug wallet pendingsweeps
[lncli] rpc error: code = Unimplemented desc = unknown service walletrpc.WalletKit
```

In addition, this error msg is also fixed,
```
./lncli unlock       
Input wallet password: 
[lncli] rpc error: code = Unknown desc = wallet already unlocked, WalletUnlocker service is no longer available
```
is now changed to,
```
./lncli-debug unlock              
Input wallet password: 
[lncli] Wallet is already unlocked
```

coderabbitai[bot]: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- This is an auto-generated comment: skip review by coderabbit.ai -->

> [!IMPORTANT]
> ## Review skipped
> 
> Auto reviews are limited to specific labels.
> 
> <details>
> <summary>:label: Labels to auto review (1)</summary>
> 
> * llm-review
> 
> </details>
> 
> Please check the settings in the CodeRabbit UI or the `.coderabbit.yaml` file in this repository. To trigger a single review, invoke the `@coderabbitai review` command.
> 
> You can disable this status message by setting the `reviews.review_status` to `false` in the CodeRabbit configuration file.

<!-- end of auto-generated comment: skip review by coderabbit.ai -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=lightningnetwork/lnd&utm_content=9605):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->

Patch:
diff --git a/cmd/commands/cmd_macaroon.go b/cmd/commands/cmd_macaroon.go
index 7e94e496d..d7d6d5f9d 100644
--- a/cmd/commands/cmd_macaroon.go
+++ b/cmd/commands/cmd_macaroon.go
@@ -30,10 +30,6 @@ var (
 		Name:  "ip_address",
 		Usage: "the IP address the macaroon will be bound to",
 	}
-	macIPRangeFlag = cli.StringFlag{
-		Name:  "ip_range",
-		Usage: "the IP range the macaroon will be bound to",
-	}
 	macCustomCaveatNameFlag = cli.StringFlag{
 		Name:  "custom_caveat_name",
 		Usage: "the name of the custom caveat to add",
@@ -561,19 +557,6 @@ func applyMacaroonConstraints(ctx *cli.Context,
 		)
 	}
 
-	if ctx.IsSet(macIPRangeFlag.Name) {
-		_, net, err := net.ParseCIDR(ctx.String(macIPRangeFlag.Name))
-		if err != nil {
-			return nil, fmt.Errorf("unable to parse ip_range "+
-				"%s: %w", ctx.String("ip_range"), err)
-		}
-
-		macConstraints = append(
-			macConstraints,
-			macaroons.IPLockConstraint(net.String()),
-		)
-	}
-
 	if ctx.IsSet(macCustomCaveatNameFlag.Name) {
 		customCaveatName := ctx.String(macCustomCaveatNameFlag.Name)
 		if containsWhiteSpace(customCaveatName) {
diff --git a/cmd/commands/commands.go b/cmd/commands/commands.go
index f41925392..7969cd20a 100644
--- a/cmd/commands/commands.go
+++ b/cmd/commands/commands.go
@@ -251,41 +251,47 @@ func printModifiedProtoJSON(resp proto.Message) {
 // to command actions.
 func actionDecorator(f func(*cli.Context) error) func(*cli.Context) error {
 	return func(c *cli.Context) error {
-		if err := f(c); err != nil {
-			s, ok := status.FromError(err)
-
-			// If it's a command for the UnlockerService (like
-			// 'create' or 'unlock') but the wallet is already
-			// unlocked, then these methods aren't recognized any
-			// more because this service is shut down after
-			// successful unlock. That's why the code
-			// 'Unimplemented' means something different for these
-			// two commands.
-			if s.Code() == codes.Unimplemented &&
-				(c.Command.Name == "create" ||
-					c.Command.Name == "unlock" ||
-					c.Command.Name == "changepassword" ||
-					c.Command.Name == "createwatchonly") {
-
-				return fmt.Errorf("Wallet is already unlocked")
-			}
+		err := f(c)
 
-			// lnd might be active, but not possible to contact
-			// using RPC if the wallet is encrypted. If we get
-			// error code Unimplemented, it means that lnd is
-			// running, but the RPC server is not active yet (only
-			// WalletUnlocker server active) and most likely this
-			// is because of an encrypted wallet.
-			if ok && s.Code() == codes.Unimplemented {
-				return fmt.Errorf("Wallet is encrypted. " +
-					"Please unlock using 'lncli unlock', " +
-					"or set password using 'lncli create'" +
-					" if this is the first time starting " +
-					"lnd.")
-			}
+		// Exit early if there's no error.
+		if err == nil {
+			return nil
+		}
+
+		// Try to parse the Status representatio from this error.
+		s, ok := status.FromError(err)
+
+		// If this cannot be represented by a Status, exit early.
+		if !ok {
 			return err
 		}
-		return nil
+
+		// If it's a command for the UnlockerService (like 'create' or
+		// 'unlock') but the wallet is already unlocked, then these
+		// methods aren't recognized any more because this service is
+		// shut down after successful unlock.
+		if s.Code() == codes.Unknown &&
+			(c.Command.Name == "create" ||
+				c.Command.Name == "unlock" ||
+				c.Command.Name == "changepassword" ||
+				c.Command.Name == "createwatchonly") {
+
+			return errors.New("wallet is already unlocked")
+		}
+
+		// lnd might be active, but not possible to contact using RPC if
+		// the wallet is encrypted. If we get error code Unknown, it
+		// means that lnd is running, but the RPC server is not active
+		// yet (only WalletUnlocker server active) and most likely this
+		// is because of an encrypted wallet.
+		if s.Code() == codes.Unknown {
+			return errors.New("wallet is encrypted - please " +
+				"unlock using 'lncli unlock', or set " +
+				"password using 'lncli create' if this is " +
+				"the first time starting lnd")
+		}
+
+		return s.Err()
 	}
 }
 
diff --git a/config_builder.go b/config_builder.go
index bb9c1b320..43c9e4a68 100644
--- a/config_builder.go
+++ b/config_builder.go
@@ -472,7 +472,7 @@ func (d *DefaultWalletImpl) BuildWalletConfig(ctx context.Context,
 		}
 		macaroonService, err = macaroons.NewService(
 			rootKeyStore, "lnd", walletInitParams.StatelessInit,
-			macaroons.IPLockChecker, macaroons.IPRangeLockChecker,
+			macaroons.IPLockChecker,
 			macaroons.CustomChecker(interceptorChain),
 		)
 		if err != nil {
diff --git a/docs/release-notes/release-notes-0.19.0.md b/docs/release-notes/release-notes-0.19.0.md
index 2b1b1f6e7..42a1a8e23 100644
--- a/docs/release-notes/release-notes-0.19.0.md
+++ b/docs/release-notes/release-notes-0.19.0.md
@@ -85,9 +85,6 @@
 * [Fixed a bug](https://github.com/lightningnetwork/lnd/pull/9595) where the
   initial graph sync query may be failed due to inconsistent state.
 
-* [The aux bandwidth calculation was fixed for non-asset
-  channels](https://github.com/lightningnetwork/lnd/pull/9502).
-
 # New Features
 
 * [Support](https://github.com/lightningnetwork/lnd/pull/8390) for 
@@ -166,10 +163,6 @@
   on the channel. LND will disable the channel for new HTLCs and kick off the
   cooperative close flow automatically when the channel has no HTLCs left.
 
-* [A new macaroon constraint](https://github.com/lightningnetwork/lnd/pull/9546)
-  to allow for restriction of access based on an IP range. Prior to this only
-  specific IPs could be allowed or denied.
-
 # Improvements
 ## Functional Updates
 
@@ -236,6 +229,12 @@
 
 ## lncli Updates
 
+* [Fixed](https://github.com/lightningnetwork/lnd/pull/9605) a case where
+  inaccurate error message is displayed. Previously, when the `lnd` is built
+  without with a given RPC service yet the `cli` does, running a command to
+  access the RPC server would give an error saying the wallet is encrypted. This
+  is now fixed to show specifically which RPC server is missing.
+
 ## Code Health
 
 * [Add retry logic](https://github.com/lightningnetwork/lnd/pull/8381) for
diff --git a/htlcswitch/interfaces.go b/htlcswitch/interfaces.go
index a39eef6a4..1ea1318ff 100644
--- a/htlcswitch/interfaces.go
+++ b/htlcswitch/interfaces.go
@@ -208,18 +208,8 @@ 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. 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]
-}
+// not applicable.
+type OptionalBandwidth = 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 3918d8cc6..e8e20973e 100644
--- a/htlcswitch/link.go
+++ b/htlcswitch/link.go
@@ -3443,13 +3443,9 @@ func (l *channelLink) canSendHtlc(policy models.ForwardingPolicy,
 		return NewLinkError(&lnwire.FailTemporaryNodeFailure{})
 	}
 
-	if auxBandwidth.IsHandled && auxBandwidth.Bandwidth.IsSome() {
-		auxBandwidth.Bandwidth.WhenSome(
-			func(bandwidth lnwire.MilliSatoshi) {
-				availableBandwidth = bandwidth
-			},
-		)
-	}
+	auxBandwidth.WhenSome(func(bandwidth lnwire.MilliSatoshi) {
+		availableBandwidth = bandwidth
+	})
 
 	// Check to see if there is enough balance in this channel.
 	if amt > availableBandwidth {
@@ -3475,6 +3471,8 @@ 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 {
@@ -3488,9 +3486,7 @@ 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(OptionalBandwidth{
-			IsHandled: false,
-		})
+		return fn.Ok(unknownBandwidth)
 	}
 
 	// Ask for a specific bandwidth to be used for the channel.
@@ -3506,10 +3502,7 @@ func (l *channelLink) AuxBandwidth(amount lnwire.MilliSatoshi,
 	log.Debugf("ShortChannelID=%v: aux traffic shaper reported available "+
 		"bandwidth: %v", cid, auxBandwidth)
 
-	return fn.Ok(OptionalBandwidth{
-		IsHandled: true,
-		Bandwidth: fn.Some(auxBandwidth),
-	})
+	return fn.Ok(fn.Some(auxBandwidth))
 }
 
 // Stats returns the statistics of channel link.
diff --git a/htlcswitch/mock.go b/htlcswitch/mock.go
index cb814e95c..5cf796657 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(OptionalBandwidth{})
+	return fn.Ok(fn.None[lnwire.MilliSatoshi]())
 }
 
 var _ ChannelLink = (*mockChannelLink)(nil)
diff --git a/macaroons/constraints.go b/macaroons/constraints.go
index 231fd1a46..642f8edcf 100644
--- a/macaroons/constraints.go
+++ b/macaroons/constraints.go
@@ -3,7 +3,6 @@ package macaroons
 import (
 	"bytes"
 	"context"
-	"errors"
 	"fmt"
 	"net"
 	"strings"
@@ -22,10 +21,6 @@ const (
 	// in the serialized macaroon. We choose a single space as the delimiter
 	// between the because that is also used by the macaroon bakery library.
 	CondLndCustom = "lnd-custom"
-
-	// CondIPRange is the caveat condition name that is used for tying an IP
-	// range to a macaroon.
-	CondIPRange = "iprange"
 )
 
 // CustomCaveatAcceptor is an interface that contains a single method for
@@ -85,9 +80,9 @@ func TimeoutConstraint(seconds int64) func(*macaroon.Macaroon) error {
 	}
 }
 
-// IPLockConstraint locks a macaroon to a specific IP address. If ipAddr is an
-// empty string, this constraint does nothing to accommodate  default value's
-// desired behavior.
+// IPLockConstraint locks macaroon to a specific IP address.
+// If address is an empty string, this constraint does nothing to
+// accommodate default value's desired behavior.
 func IPLockConstraint(ipAddr string) func(*macaroon.Macaroon) error {
 	return func(mac *macaroon.Macaroon) error {
 		if ipAddr != "" {
@@ -98,32 +93,8 @@ func IPLockConstraint(ipAddr string) func(*macaroon.Macaroon) error {
 			}
 			caveat := checkers.Condition("ipaddr",
 				macaroonIPAddr.String())
-
-			return mac.AddFirstPartyCaveat([]byte(caveat))
-		}
-
-		return nil
-	}
-}
-
-// IPRangeLockConstraint locks a macaroon to a specific IP address range. If
-// ipRange is an empty string, this constraint does nothing to accommodate
-// default value's desired behavior.
-func IPRangeLockConstraint(ipRange string) func(*macaroon.Macaroon) error {
-	return func(mac *macaroon.Macaroon) error {
-		if ipRange != "" {
-			_, parsedNet, err := net.ParseCIDR(ipRange)
-			if err != nil {
-				return fmt.Errorf("incorrect macaroon IP "+
-					"range: %w", err)
-			}
-			caveat := checkers.Condition(
-				CondIPRange, parsedNet.String(),
-			)
-
 			return mac.AddFirstPartyCaveat([]byte(caveat))
 		}
-
 		return nil
 	}
 }
@@ -151,39 +122,6 @@ func IPLockChecker() (string, checkers.Func) {
 	}
 }
 
-// IPRangeLockChecker accepts client IP range from the validation context and
-// compares it with the IP range locked in the macaroon. It is of the `Checker`
-// type.
-func IPRangeLockChecker() (string, checkers.Func) {
-	return CondIPRange, func(ctx context.Context, cond, arg string) error {
-		// Get peer info and extract IP range from it for macaroon
-		// check.
-		pr, ok := peer.FromContext(ctx)
-		if !ok {
-			return errors.New("unable to get peer info from " +
-				"context")
-		}
-		peerAddr, _, err := net.SplitHostPort(pr.Addr.String())
-		if err != nil {
-			return fmt.Errorf("unable to parse peer address: %w",
-				err)
-		}
-
-		_, ipNet, err := net.ParseCIDR(arg)
-		if err != nil {
-			return fmt.Errorf("unable to parse macaroon IP "+
-				"range: %w", err)
-		}
-
-		if !ipNet.Contains(net.ParseIP(peerAddr)) {
-			return errors.New("macaroon locked to different " +
-				"IP range")
-		}
-
-		return nil
-	}
-}
-
 // CustomConstraint returns a function that adds a custom caveat condition to
 // a macaroon.
 func CustomConstraint(name, condition string) func(*macaroon.Macaroon) error {
diff --git a/routing/bandwidth.go b/routing/bandwidth.go
index e9cfb5968..833782616 100644
--- a/routing/bandwidth.go
+++ b/routing/bandwidth.go
@@ -143,13 +143,6 @@ 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
@@ -159,7 +152,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,
+				bandwidth:  auxBandwidth,
 				htlcAmount: fn.Some[lnwire.MilliSatoshi](0),
 			})
 		},


Test patch:
diff --git a/itest/lnd_macaroons_test.go b/itest/lnd_macaroons_test.go
index 936140508..b896d455a 100644
--- a/itest/lnd_macaroons_test.go
+++ b/itest/lnd_macaroons_test.go
@@ -37,8 +37,9 @@ func testMacaroonAuthentication(ht *lntest.HarnessTest) {
 		name string
 		run  func(ctxt context.Context, t *testing.T)
 	}{{
-		// Make sure we get an error if we use no macaroons but try to
-		// connect to a node that has macaroon authentication enabled.
+		// First test: Make sure we get an error if we use no macaroons
+		// but try to connect to a node that has macaroon authentication
+		// enabled.
 		name: "no macaroon",
 		run: func(ctxt context.Context, t *testing.T) {
 			conn, err := testNode.ConnectRPCWithMacaroon(nil)
@@ -50,7 +51,8 @@ func testMacaroonAuthentication(ht *lntest.HarnessTest) {
 			require.Contains(t, err.Error(), "expected 1 macaroon")
 		},
 	}, {
-		// Ensure that an invalid macaroon also triggers an error.
+		// Second test: Ensure that an invalid macaroon also triggers an
+		// error.
 		name: "invalid macaroon",
 		run: func(ctxt context.Context, t *testing.T) {
 			invalidMac, _ := macaroon.New(
@@ -66,7 +68,8 @@ func testMacaroonAuthentication(ht *lntest.HarnessTest) {
 			require.Contains(t, err.Error(), "invalid ID")
 		},
 	}, {
-		// Try to access a write method with read-only macaroon.
+		// Third test: Try to access a write method with read-only
+		// macaroon.
 		name: "read only macaroon",
 		run: func(ctxt context.Context, t *testing.T) {
 			readonlyMac, err := testNode.ReadMacaroon(
@@ -82,8 +85,8 @@ func testMacaroonAuthentication(ht *lntest.HarnessTest) {
 			require.Contains(t, err.Error(), "permission denied")
 		},
 	}, {
-		// Check first-party caveat with timeout that expired 30 seconds
-		// ago.
+		// Fourth test: Check first-party caveat with timeout that
+		// expired 30 seconds ago.
 		name: "expired macaroon",
 		run: func(ctxt context.Context, t *testing.T) {
 			readonlyMac, err := testNode.ReadMacaroon(
@@ -103,7 +106,7 @@ func testMacaroonAuthentication(ht *lntest.HarnessTest) {
 			require.Contains(t, err.Error(), "macaroon has expired")
 		},
 	}, {
-		// Check first-party caveat with invalid IP address.
+		// Fifth test: Check first-party caveat with invalid IP address.
 		name: "invalid IP macaroon",
 		run: func(ctxt context.Context, t *testing.T) {
 			readonlyMac, err := testNode.ReadMacaroon(
@@ -125,7 +128,7 @@ func testMacaroonAuthentication(ht *lntest.HarnessTest) {
 			require.Contains(t, err.Error(), "different IP address")
 		},
 	}, {
-		// Make sure that if we do everything correct and
+		// Sixth test: Make sure that if we do everything correct and
 		// send the admin macaroon with first-party caveats that we can
 		// satisfy, we get a correct answer.
 		name: "correct macaroon",
@@ -146,51 +149,8 @@ func testMacaroonAuthentication(ht *lntest.HarnessTest) {
 			assert.Contains(t, res.Address, "bcrt1")
 		},
 	}, {
-		// Check first-party caveat with invalid IP range.
-		name: "invalid IP range macaroon",
-		run: func(ctxt context.Context, t *testing.T) {
-			readonlyMac, err := testNode.ReadMacaroon(
-				testNode.Cfg.ReadMacPath, defaultTimeout,
-			)
-			require.NoError(t, err)
-			invalidIPRangeMac, err := macaroons.AddConstraints(
-				readonlyMac, macaroons.IPRangeLockConstraint(
-					"1.1.1.1/32",
-				),
-			)
-			require.NoError(t, err)
-			cleanup, client := macaroonClient(
-				t, testNode, invalidIPRangeMac,
-			)
-			defer cleanup()
-			_, err = client.GetInfo(ctxt, infoReq)
-			require.Error(t, err)
-			require.Contains(t, err.Error(), "different IP range")
-		},
-	}, {
-		// Make sure that if we do everything correct and send the admin
-		// macaroon with first-party caveats that we can satisfy, we get
-		// a correct answer.
-		name: "correct macaroon",
-		run: func(ctxt context.Context, t *testing.T) {
-			adminMac, err := testNode.ReadMacaroon(
-				testNode.Cfg.AdminMacPath, defaultTimeout,
-			)
-			require.NoError(t, err)
-			adminMac, err = macaroons.AddConstraints(
-				adminMac, macaroons.TimeoutConstraint(30),
-				macaroons.IPRangeLockConstraint("127.0.0.0/8"),
-			)
-			require.NoError(t, err)
-			cleanup, client := macaroonClient(t, testNode, adminMac)
-			defer cleanup()
-			res, err := client.NewAddress(ctxt, newAddrReq)
-			require.NoError(t, err, "get new address")
-			assert.Contains(t, res.Address, "bcrt1")
-		},
-	}, {
-		// Bake a macaroon that can only access exactly two RPCs and
-		// make sure it works as expected.
+		// Seventh test: Bake a macaroon that can only access exactly
+		// two RPCs and make sure it works as expected.
 		name: "custom URI permissions",
 		run: func(ctxt context.Context, t *testing.T) {
 			entity := macaroons.PermissionEntityCustomURI
@@ -239,9 +199,9 @@ func testMacaroonAuthentication(ht *lntest.HarnessTest) {
 			require.Contains(t, err.Error(), "permission denied")
 		},
 	}, {
-		// Check that with the CheckMacaroonPermissions RPC, we can
-		// check that a macaroon follows (or doesn't) permissions and
-		// constraints.
+		// Eighth test: check that with the CheckMacaroonPermissions
+		// RPC, we can check that a macaroon follows (or doesn't)
+		// permissions and constraints.
 		name: "unknown permissions",
 		run: func(ctxt context.Context, t *testing.T) {
 			// A test macaroon created with permissions from pool,
diff --git a/routing/mock_test.go b/routing/mock_test.go
index a1268d0c3..86fd76549 100644
--- a/routing/mock_test.go
+++ b/routing/mock_test.go
@@ -904,7 +904,9 @@ func (m *mockLink) AuxBandwidth(lnwire.MilliSatoshi, lnwire.ShortChannelID,
 	fn.Option[tlv.Blob],
 	htlcswitch.AuxTrafficShaper) fn.Result[htlcswitch.OptionalBandwidth] {
 
-	return fn.Ok(htlcswitch.OptionalBandwidth{})
+	return fn.Ok[htlcswitch.OptionalBandwidth](
+		fn.None[lnwire.MilliSatoshi](),
+	)
 }
 
 // EligibleToForward returns the mock's configured eligibility.