lightninglabs / lightninglabs/taproot-assets

rpc: expose custom-anchor capabilities and a machine-readable API version via GetInfo

Open
#2,212 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
Go
Stars
525
Forks
150
Avg merge
2d 15h
Merged PRs (30d)
31

Description

Problem

There is no runtime way for an RPC client to discover which custom-anchor features a given tapd backend supports, nor to obtain a stable, machine-readable API/capability version. The only version signal exposed to clients is a free-form human string.

This matters specifically for lightweight/custom-anchor integrations that don't run their own tapd and instead drive a remote/hosted daemon over gRPC (e.g. building a caller-owned BTC anchor, committing assets via CommitVirtualPsbts, signing externally, then PublishAndLogTransfer). Such a caller cannot compile against the backend's Go version constants, so it can't tell whether the backend supports a given field or RPC before invoking it. The available custom-anchor RPCs — FundVirtualPsbt, AnchorVirtualPsbts, CommitVirtualPsbts, PublishAndLogTransfer (taprpc/assetwalletrpc/assetwallet.proto:15, :34, :43, :52) — and their request options have grown over time; the only signal that a feature exists is either the presence of a proto field in the client's own generated stubs (which says nothing about the server) or trial-and-error against a live daemon. A concrete example is CommitVirtualPsbtsRequest.skip_funding (taprpc/assetwalletrpc/assetwallet.proto:354-358, honored at rpcserver/rpcserver.go:3058): an older backend silently ignores it, and there is no capability the client can query to know whether zero-fee / externally-funded anchoring is actually supported.

Current behaviour

GetInfo is declared at taprpc/taprootassets.proto:133 and returns GetInfoResponse (taprpc/taprootassets.proto:1715-1743). The response carries only: version (string), lnd_version, network, lnd_identity_pubkey, node_alias, block_height, block_hash, sync_to_chain. There is no capability list and no numeric/structured API version.

The server implementation at rpcserver/rpcserver.go:527-552 populates Version from r.cfg.Version. That value is wired in tapcfg/server.go as Version: tap.Version(), and Version() (version.go:159-161) returns a human-oriented string of the form "0.8.99-alpha commit=<...>" (assembled from AppMajor/AppMinor/AppPatch/AppStatus at version.go:41-51 plus the build Commit). A client that wants feature gating has to string-parse this and hard-code a semver→feature mapping — brittle across -alpha/-rc suffixes, forks, and LiT-embedded builds where the agent name is overridden (version.go:80-91).

There is no capabilities/feature-bit surface for RPC clients today. The FeatureBit machinery that does exist (tapchannel/aux_funding_controller.go:115-121, lndservices/feature_bit_verifier.go, rfq/manager.go) is for Lightning peer/channel negotiation over the wire protocol, not for describing an tapd node's RPC capabilities to a gRPC caller.

Test coverage confirms the gap: the GetInfo itest (itest/integration_test.go:154-173) only asserts the network field round-trips and that CLI and RPC responses match — nothing about versions or capabilities.

Proposed change

Extend discovery so a remote caller can gate custom-anchor flows without version-string parsing. Either extend GetInfoResponse or add a dedicated capabilities RPC on the TaprootAssets service:

  1. Add a structured, monotonic API/capability version to GetInfoResponse (e.g. uint32 api_version and/or split uint32 version_major/minor/patch) so clients have a stable integer to compare instead of parsing version (taprpc/taprootassets.proto:1715). Populate it from the AppMajor/AppMinor/AppPatch constants (version.go:41-48) in rpcserver.GetInfo (rpcserver/rpcserver.go:542-551).
  2. Add an explicit, additive capability set — either a repeated string capabilities / repeated Feature features field on GetInfoResponse, or a new rpc GetCapabilities(...) on the TaprootAssets service (taprpc/taprootassets.proto:133 neighborhood). Enumerate the custom-anchor capabilities the backend actually honors, e.g. custom_anchor_commit_psbts, custom_anchor_publish_and_log, commit_skip_funding, commit_custom_lock_id — so callers gate on named features rather than inferring them from a version. Feature names/bits should be defined once server-side and returned as data, so old clients ignore unknown entries and new clients degrade gracefully against old servers.
  3. Add itest coverage extending testGetInfo (itest/integration_test.go:154) to assert the API version and at least one custom-anchor capability are present.

Keeping this additive (new fields / new RPC) preserves backward compatibility with existing GetInfo consumers.

Context

Filed in support of lightninglabs/tap-sdk#158, which adds an advanced custom-anchor Taproot Assets transaction builder (caller owns the BTC anchor, commits assets via CommitVirtualPsbts, signs externally, then PublishAndLogTransfer). Because GetInfo exposes no machine-readable API version or capability set, the SDK currently pins a static, version-hardcoded compatibility profile and fails closed on any backend whose version it doesn't recognize — it cannot safely probe for features like skip_funding at runtime. A capabilities/API-version surface on GetInfo (or a dedicated RPC) would let the SDK negotiate features dynamically and stop rejecting otherwise-capable remote/hosted tapd backends.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the GetInfo declaration and GetInfoResponse in taprpc/taprootassets.proto, then read rpcserver/rpcserver.go and version.go to understand current population of version data. Review testGetInfo in itest/integration_test.go and the custom-anchor RPC definitions in taprpc/assetwalletrpc.proto. Done means clients can discover a stable API version and supported custom-anchor capabilities, with integration coverage confirming them.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
api, backend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.