Skip to content

multi: expose local and remote spendable balance in listchannels - #10624

Open
Euler-B wants to merge 5 commits into
lightningnetwork:masterfrom
Euler-B:feature/listchannels-spendable-balance
Open

multi: expose local and remote spendable balance in listchannels#10624
Euler-B wants to merge 5 commits into
lightningnetwork:masterfrom
Euler-B:feature/listchannels-spendable-balance

Conversation

@Euler-B

@Euler-B Euler-B commented Mar 3, 2026

Copy link
Copy Markdown
Contributor

Change Description

This PR addresses the request to expose the actual "spendable" balance in the listchannels RPC.
Currently, local_balance and remote_balance only show total funds, not considering:

  • Channel reserves (ChanReserve).
  • Commitment fees (paid by the initiator).
  • The cost of adding new HTLCs.

Fixes: #4951

Steps to Test

  1. Automated Tests:
$ go test -v -run "TestChanRemoteAvailableBalance|TestApplyCommitmentFee" github.com/lightningnetwork/lnd/lnwallet
  1. Manual: Build with make install and verify local_spendable_msat in lncli listchannels.

Pull Request Checklist

Testing

  • Your PR passes all CI checks.
  • Tests covering the positive and negative (error paths) are included.
  • Bug fixes contain tests triggering the bug to prevent regressions.

Code Style and Documentation

📝 Please see our Contribution Guidelines for further guidance.

@gemini-code-assist

Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly improves the listchannels RPC by providing a more precise and actionable view of channel liquidity. By introducing new fields that account for channel reserves, commitment fees, and potential HTLC costs, users can now accurately determine the actual amount of funds available for immediate spending or forwarding, both locally and by the remote peer. This enhancement addresses a long-standing request to move beyond simple total balance reporting, offering a more realistic and useful metric for channel management.

Highlights

  • New RPC Fields for Spendable Balance: Introduced local_spendable_msat and remote_spendable_msat fields to the Channel message in the listchannels RPC response. These fields provide a more accurate representation of funds available for sending by factoring in channel reserves and commitment fees.
  • Remote Bandwidth Calculation: Implemented a new RemoteBandwidth() method within the ChannelLink interface and its concrete types to expose the remote party's available bandwidth, considering their reserves and commitment fees.
  • Refactored Balance Logic: Refactored the internal channel balance calculation logic to be more generic, allowing for accurate determination of spendable balances from both local and remote perspectives, and updated the applyCommitFee function to explicitly handle initiator status.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • htlcswitch/interfaces.go
    • Added RemoteBandwidth() method to the ChannelUpdateHandler interface.
    • Updated the comment for the existing Bandwidth() method to clarify its scope for the local party.
  • htlcswitch/link.go
    • Implemented the RemoteBandwidth() method for the channelLink type, which returns the remote party's available balance.
  • htlcswitch/mock.go
    • Added a mock implementation for the RemoteBandwidth() method to the mockChannelLink type.
    • Updated the comment for the existing Bandwidth() method.
  • lnrpc/lightning.proto
    • Added local_spendable_msat and remote_spendable_msat fields to the Channel message, including detailed descriptions of their calculation.
  • lnrpc/lightning.swagger.json
    • Updated the Swagger definition to include the newly added local_spendable_msat and remote_spendable_msat fields in the Channel object.
  • lnwallet/channel.go
    • Modified the applyCommitFee function to accept an isInitiator boolean parameter, allowing for more flexible fee application logic.
    • Introduced RemoteAvailableBalance() to calculate the remote party's spendable balance.
    • Refactored the balance calculation logic into a new generic function availableBalanceGeneric to handle both local and remote perspectives, reducing code duplication.
    • Adjusted availableCommitmentBalance to use the new generic balance calculation and correctly apply reserves and fees based on the isRemote and initiator flags.
  • lnwallet/channel_test.go
    • Added TestChanRemoteAvailableBalance to thoroughly test the accuracy of the RemoteAvailableBalance calculation.
    • Updated calls to applyCommitFee in existing tests to pass the new isInitiator parameter.
    • Modified TestChanCommitWeightDustHtlcs to pass the isRemote parameter to availableCommitmentBalance.
  • rpcserver.go
    • Updated the createRPCOpenChannel function to retrieve and populate the LocalSpendableMsat and RemoteSpendableMsat fields in the Channel RPC response using the new Bandwidth() and RemoteBandwidth() methods from the htlcSwitch link.
Activity
  • No specific activity (comments, reviews, or progress updates) was provided in the context.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@litbot-9000 litbot-9000 added the severity-critical Requires expert review - security/consensus critical label Mar 3, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request successfully exposes the local and remote spendable balances in the listchannels RPC. The core of the change is a significant but well-executed refactoring in lnwallet/channel.go to create a generic balance calculation logic applicable to both local and remote parties. The new test case, TestChanRemoteAvailableBalance, is thorough and provides good coverage for the new logic. The changes to the RPC layer are consistent with the core modifications. I have a couple of minor suggestions related to code comments to improve documentation clarity and adhere to the style guide.

Note: Security Review is unavailable for this PR.

Comment thread lnwallet/channel.go Outdated
Comment thread htlcswitch/link.go Outdated
@Euler-B
Euler-B force-pushed the feature/listchannels-spendable-balance branch 4 times, most recently from 1affd68 to 6bc0965 Compare March 9, 2026 21:14
@Euler-B
Euler-B force-pushed the feature/listchannels-spendable-balance branch 2 times, most recently from e0bc98a to 34a7563 Compare March 14, 2026 15:47
@Euler-B

Euler-B commented Mar 14, 2026

Copy link
Copy Markdown
Contributor Author

Hi @ziggie1984. I've updated the PR to address the latest feedback and fixed the linting issues. This is my current approach to solve Issue #4951

@saubyk saubyk added this to lnd v0.22 Apr 10, 2026
@github-project-automation github-project-automation Bot moved this to Backlog in lnd v0.22 Apr 10, 2026
@saubyk saubyk added this to the v0.22.0 milestone Apr 10, 2026
@Euler-B
Euler-B force-pushed the feature/listchannels-spendable-balance branch from 34a7563 to 2e928b5 Compare July 6, 2026 17:12
@github-actions github-actions Bot added severity-critical Requires expert review - security/consensus critical and removed severity-critical Requires expert review - security/consensus critical labels Jul 6, 2026
@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

🔴 PR Severity: CRITICAL

File classification | 12 files | 429 lines changed (307 lines / 9 files excluding tests & auto-generated)

🔴 Critical (6 files)
  • htlcswitch/interfaces.go - htlcswitch/* (HTLC forwarding/payment routing state machine interfaces)
  • htlcswitch/link.go - htlcswitch/* (HTLC forwarding link logic)
  • htlcswitch/mock.go - htlcswitch/* (package file; does not match mock exclusion patterns mock_*.go/*_mock.go)
  • lnwallet/channel.go - lnwallet/* (channel state, commitment transactions)
  • peer/test_utils.go - peer/* (encrypted peer connection support code; filename doesn't match *_test.go exclusion pattern)
  • rpcserver.go - explicitly listed core server coordination file
🟠 High (3 files)
  • lnrpc/lightning.pb.go - lnrpc/* generated gRPC bindings (excluded from line/file counts as auto-generated)
  • lnrpc/lightning.proto - lnrpc/* RPC/API definition
  • lnrpc/lightning.swagger.json - lnrpc/* swagger API spec
🟢 Low (3 files)
  • docs/release-notes/release-notes-0.20.1.md - release notes
  • lnwallet/channel_test.go - test-only change
  • peer/brontide_test.go - test-only change

Analysis

The highest-severity files touched are in htlcswitch/* (HTLC forwarding state machine), lnwallet/* (channel/commitment transaction logic), peer/* (encrypted peer connection support), and rpcserver.go (core server coordination) — all of which fall under the CRITICAL tier per policy. That alone sets the PR's baseline severity to CRITICAL.

For reference, this PR also touches multiple distinct critical packages (htlcswitch, lnwallet, peer, plus rpcserver.go), which would normally trigger a one-level severity bump — but since CRITICAL is already the highest tier, this has no further effect. File count (9) and line changes (307, excluding tests/generated code) are both well under the size-based bump thresholds (20 files / 500 lines), so those thresholds are not a factor here.

Given the changes to lnwallet/channel.go (commitment transaction / channel state logic) and htlcswitch/link.go (HTLC forwarding), this PR warrants expert review of channel state correctness and payment routing safety.


To override, add a severity-override-{critical,high,medium,low} label.

@saubyk

saubyk commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

/gateway review

@lightninglabs-gateway

lightninglabs-gateway Bot commented Jul 7, 2026

Copy link
Copy Markdown

✅ Review posted: #10624 (review)

6 finding(s); 6 inline, 0 in body.

🔁 Need a re-review after pushing changes? Reply with /gateway re-review.
Maintainers can also /gateway dismiss <id> to silence specific findings, or anyone can /gateway explain <id> for elaboration.

@lightninglabs-gateway lightninglabs-gateway Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR exposes local/remote spendable balance in listchannels by adding RemoteAvailableBalance()/RemoteBandwidth() and refactoring lnwallet/channel.go's balance computation into a party-generic form. The intent and the reserve/dust/initiator mapping are sound, and the RPC/proto plumbing is consistent.

The refactor, however, silently changes the HTLC view used by the pre-existing AvailableBalance() path — it now folds in un-ACKed remote updates rather than only remote-ACKed ones. Because that value drives Bandwidth() on a high-reach HTLC-forwarding path, this is the primary concern and needs to be confirmed intentional or reverted. A secondary correctness/usability gap is that the new RPC fields silently report 0 for any channel without an active link, with no signal to the consumer.

Findings: 🔴 0 Blocker · 🟠 2 Major · 🟡 4 Minor · 🔵 0 Nit

Comment thread lnwallet/channel.go Outdated
Comment thread rpcserver.go
Comment thread docs/release-notes/release-notes-0.20.1.md Outdated
Comment thread htlcswitch/interfaces.go
Comment thread lnrpc/lightning.proto Outdated
Comment thread lnwallet/channel_test.go
@lightninglabs-gateway

Copy link
Copy Markdown

🤖 gateway audit metadata for this PR — auto-generated, please don't edit.

@Euler-B
Euler-B force-pushed the feature/listchannels-spendable-balance branch 6 times, most recently from 6185e0b to 1410c20 Compare July 9, 2026 15:16
@litbot-9000

Copy link
Copy Markdown
Collaborator

@Euler-B, remember to re-request review from reviewers when ready

This commit refactors availableCommitmentBalance and applyCommitFee to
be party-agnostic, allowing the calculation of the available balance
from the perspective of either the local or remote party. We also
introduce RemoteAvailableBalance to expose this new functionality.

A new test TestChanRemoteAvailableBalance has been added to verify
the accuracy of these calculations across various states.
This commit adds a new RemoteBandwidth method to the ChannelLink
interface and implements it in channelLink by calling the new
RemoteAvailableBalance method in lnwallet.

The mockChannelLink and peer test mocks have also been updated to
satisfy the interface.
This commit adds local_spendable_msat and remote_spendable_msat to the
Channel message in lightning.proto. This allows clients to see the
actual amount of funds that can be sent or received in a channel,
accounting for reserves and fees.
This commit updates the ListChannels RPC to populate the new
local_spendable_msat and remote_spendable_msat fields by querying the
active channel link from the htlcSwitch.
@Euler-B
Euler-B force-pushed the feature/listchannels-spendable-balance branch from 1410c20 to cbb522a Compare August 12, 2026 00:04
@litbot-9000

Copy link
Copy Markdown
Collaborator

@Euler-B, remember to re-request review from reviewers when ready

2 similar comments
@litbot-9000

Copy link
Copy Markdown
Collaborator

@Euler-B, remember to re-request review from reviewers when ready

@litbot-9000

Copy link
Copy Markdown
Collaborator

@Euler-B, remember to re-request review from reviewers when ready

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gateway-active severity-critical Requires expert review - security/consensus critical

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

rpc: expose potential HTLC addition cost to channels list for spendable balance calculation

3 participants