taprpc+tapcli: expose channel and pending asset balances#2094
Conversation
Add opt-in flags to surface two classes of hidden assets: ListBalancesRequest: include_channel (field 7), include_pending (field 8). ListUtxosRequest: include_channel (field 3). ListAssetRequest: include_channel (field 14), include_pending_transfers (field 15). ListBalancesResponse: pending_asset_balances (field 4), pending_asset_group_balances (field 5), channel_asset_balances (field 6), channel_group_balances (field 7), pending_channel_asset_balances (field 8), pending_channel_group_balances (field 9). ListAssetResponse: pending_assets (field 4) as a separate list from the paginated confirmed assets. Add AssetChannelBalance message for in-channel local/remote balance reporting. Refs lightninglabs#2093, lightninglabs#1634.
Add includeChannel parameter to QueryBalancesByAsset and QueryAssetBalancesByGroup. When set, the channel script key type is unconditionally appended via appendChannelKeyType, ensuring it takes effect even when the default BIP-86 type causes ScriptKeyTypeForDatabaseQuery to return early. Add IncludeChannel field to AssetQueryFilters and wire it through constraintsToDbFilter for ListAssets/ListUtxos. Add FetchGenesisByAssetID to AssetStore for looking up genesis info when computing pending balances for assets with zero confirmed balance.
Pass include_channel and include_pending flags through ListBalances, ListAssets, and ListUtxos to the store queries. ListBalances: pendingBalancesByAsset and pendingBalancesByGroup aggregate local outputs from unconfirmed outbound parcels, filtered by the same script key type constraints as confirmed balances. pendingBalancesByGroup extracts group keys from proof suffixes via sparse decoding and skips ungrouped assets. genesisForAsset provides genesis info lookup with DB fallback. Channel balances (open and pending-close) are fetched from lnd via fetchChannelAssetBalances and populated into the new response fields. ListAssets: pendingTransferAssets constructs Asset proto objects from unconfirmed parcel outputs by sparse-decoding proof suffixes into ChainAssets with AnchorBlockHeight=0. Content filters (amount range, group key, script key, anchor outpoint, script key type) are applied. The output's wallet-aware ScriptKey is preserved over the sparse-decoded one so script_key_is_local and script_key_type are accurate. Results go into a separate pending_assets response field to avoid inflating paginated confirmed results.
Add --include_channel to 'assets list', 'assets utxos', and 'assets balance'. Add --include_pending to 'assets balance' and 'assets list'. Update help text for list/utxos commands to clarify on-chain scope.
Summary of ChangesHello, 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 enhances the visibility of asset balances and UTXOs by introducing new opt-in flags for RPC calls. These changes allow users to see assets currently locked in Lightning channels and track unconfirmed outbound transfers directly through the standard asset listing and balance commands. The implementation ensures that these new data points are surfaced in a backward-compatible manner, improving the overall developer experience when managing assets across different states. Highlights
🧠 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. Using Gemini Code AssistThe 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
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 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. Footnotes
|
tapdb: extend TestQueryAssetBalancesCustomChannelFunding to verify that includeChannel=true returns both channel and normal assets with the correct combined balance. Add TestFetchGenesisByAssetID to validate the new DB method used by the rpcserver genesis lookup fallback. rpcserver: add unit tests for the pure/standalone helper functions introduced for balance visibility: scriptKeyTypeAllowed, appendChannelScriptKeyType, jsonToChannelBalances, and pendingBalancesByGroup (with sub-tests for aggregation, remote output skipping, ungrouped asset skipping, empty proof suffix handling, group key filtering, and script key type filtering). itest: in testAssetBalances, smoke-test ListBalances with include_pending and include_channel flags after minting. In testBasicSendUnidirectional, assert that the pending balance for the sender's change output is correct between send broadcast and block confirmation.
Document the new include_channel, include_pending, and include_pending_transfers flags across ListBalances, ListAssets, and ListUtxos, along with the corresponding CLI flags.
There was a problem hiding this comment.
Code Review
This pull request introduces the --include_channel and --include_pending flags to the asset listing and balance RPCs and CLI commands, enabling visibility into assets within Lightning channels and unconfirmed outbound transfers. The changes span the CLI, RPC server, and database layers, supported by new unit and integration tests. Feedback focuses on performance optimizations in the pending asset filtering logic and leveraging existing library methods for outpoint deserialization to improve code readability.
darioAnongba
left a comment
There was a problem hiding this comment.
I think we should pause this PR before we figure out how to improve the API request/response shapes because we are growing into an already badly shaped API:
ListBalancesResponsenow has 8 maps keyed across the 4×2 product of(state, grouping). The shape is asymmetric, not uniformly filterable, and every future state will add another two maps.- Clients can't be expected to merge/iterate 6 mutually exclusive maps that index over the same assetID / group key.
We can collapse everything into 1 iterable response for clients, something like this (generated by Opus):
enum BalanceState {
BALANCE_STATE_UNSPECIFIED = 0;
BALANCE_STATE_CONFIRMED = 1;
BALANCE_STATE_PENDING = 2; // local outputs of unconfirmed sends
BALANCE_STATE_CHANNEL_OPEN = 3;
BALANCE_STATE_CHANNEL_CLOSING = 4; // force/coop close in flight
}
enum BalanceGrouping {
BALANCE_GROUPING_UNSPECIFIED = 0;
BALANCE_GROUPING_ASSET_ID = 1;
BALANCE_GROUPING_GROUP_KEY = 2;
}
message AssetBalanceEntry {
BalanceGrouping grouping = 1; // how `key` is interpreted
bytes key = 2; // raw asset_id (32B) or group key
BalanceState state = 3;
uint64 amount = 4; // total / on-chain amount
AssetChannelBalance channel = 5; // populated only for channel states
GenesisInfo asset_genesis = 6;
}
message ListBalancesResponse {
repeated AssetBalanceEntry entries = 1;
uint64 unconfirmed_transfers = 2;
}On the request, the current oneof of two bool makes no sense. Then, with all the include_*, this API is way too ugly, just a soup of boolean flags.
We can improve with something like:
message ListBalancesRequest {
BalanceGrouping grouping = 1; // replaces oneof
bytes asset_id_filter = 2;
bytes group_key_filter = 3;
ScriptKeyTypeQuery script_key_type = 4;
bool include_leased = 5;
// Empty = CONFIRMED only (preserves current default).
repeated BalanceState include_states = 6;
uint64 min_amount = 7;
uint64 max_amount = 8;
}Since this is v0.9, we should think this through and not be afraid to break the shape IMO.
| @@ -0,0 +1,76 @@ | |||
| # Release Notes | |||
There was a problem hiding this comment.
Maybe worth considering moving to Keep a changelog https://keepachangelog.com/en/1.1.0/ for v0.9.0?
|
Going to convert this one to draft as I agree we should hold off on merging until we're more properly focused on v0.9. |
Resolves #2093, #1634. Tested e2e on a Docker regtest network.
Lightly-edited Opus-generated summary:
Each of
tapcli assets {list,balance,utxos}now accepts--include_channelto show assets locked in Lightning channels alongside regular on-chain assets. Forassets balance, this also reports in-channel balances (open and pending-close/force-close) broken down by local and remote amounts. Each oftapcli assets {balance,list}also now accepts--include_pendingto show unconfirmed outbound transfer balances and pending transfer outputs without having to manually filter ListTransfers.All this stuff is backed by new, backward-compatible, opt-in fields on the List{Balances,Assets,Utxos} RPCs.
Examples: