Skip to content

multi: refresh asset VTXOs through the round (client) - #1128

Merged
darioAnongba merged 3 commits into
darioAnongba/asset-tree-m5-clientfrom
darioAnongba/asset-tree-refresh-client
Aug 11, 2026
Merged

multi: refresh asset VTXOs through the round (client)#1128
darioAnongba merged 3 commits into
darioAnongba/asset-tree-m5-clientfrom
darioAnongba/asset-tree-refresh-client

Conversation

@darioAnongba

@darioAnongba darioAnongba commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Client half of the asset leaf refresh, stacked on #1108. Operator counterpart: lumos#773 (see the PR list on the integration epic); design: https://taproot-assets-ark.lightning.wiki/.

A refresh forfeits an asset leaf and asks the same units back as a fixed-amount asset VTXO request, so the next round reissues them through its asset transition. Three changes make that work end to end:

  • Refresh intents carry asset identity. The wallet descriptor and the waved adapter expose the leaf's asset reference and amount, and handleRefreshVTXOs stamps them onto the new VTXO request with FixedAmount set: the seal quote can never shrink an asset carrier, and the request never acts as the change slot. The RPC preview accepts explicitly named asset targets; the catch-all --all selection still skips them, so a bulk Bitcoin refresh cannot pull an asset leaf along silently.
  • The join-auth proof composes. The proof-of-funds input for a forfeited VTXO derived the default timeout path, whose witness program is the bare policy output. An asset leaf pays to the policy branched with its asset root, so the proof now builds the composed control block the same way boarding disclosures already do.
  • Round-store loads rehydrate asset identity. The round store's ClientVTXO loader dropped the Taproot Asset columns, which made a forfeited asset leaf look like plain sats to the join-auth builder.

Forfeit signing needed no changes: the VTXO actor already resolves its spend path through EffectiveStandardSpendInfo, which extends the control block with the asset root.

Verified by TestRoundAssetRefresh in lumos: board, refresh with inventory-funded reissue, and an out-of-round spend from the refreshed leaf.

Refreshing an asset-bearing VTXO forfeits the leaf and asks the same
units back as a fixed-amount asset VTXO request, so the round reissues
them through its asset transition. The wallet descriptor and the RPC
preview learn the asset identity; the blanket refresh rejection is
lifted for explicitly named targets while the catch-all selection
still skips them.
The proof-of-funds input for a forfeited VTXO derived the default
timeout path, whose witness program is the bare policy output. An
asset leaf pays to the policy branched with its asset root, so the
proof needs the composed control block, the same way boarding
disclosures already build theirs.
The round store's ClientVTXO loader dropped the Taproot Asset columns,
so a forfeited asset leaf looked like plain sats to the join-auth
builder and its proof spent the wrong witness program.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4efe00666f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread wallet/wallet.go
Comment on lines +1735 to +1738
if vtxo.TaprootAssetRef != "" {
request.AssetRef = vtxo.TaprootAssetRef
request.AssetAmount = vtxo.TaprootAssetAmount
request.FixedAmount = true

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Add a change leg for asset-only refresh batches

When the selected batch contains only asset VTXOs, every replacement is marked FixedAmount and none can become the fee-bearing change output. A single asset refresh therefore has input sats exactly equal to its fixed output and is rejected whenever the quoted operator fee is positive; two or more asset replacements are rejected even with a zero fee because designateChangeMarker skips every fixed output, leaving the multi-output intent with no IsChange marker. Add an ordinary Bitcoin change/funding leg or reject these unsupported selections before reserving them.

AGENTS.md reference: wallet/AGENTS.md:L40-L42

Useful? React with 👍 / 👎.

Comment thread wallet/interfaces.go
Comment on lines +64 to +67
// TaprootAssetRef is the canonical reference of the Taproot Asset
// this VTXO carries, empty for a Bitcoin-only VTXO. A refresh must
// reissue the same asset through the round's asset transition.
TaprootAssetRef string

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve the asset-root discriminator in wallet descriptors

For upgraded wallets containing the explicitly supported historical root-only asset rows, TaprootAssetRef is empty even though TaprootAssetRoot is non-nil. This descriptor therefore misclassifies such a VTXO as Bitcoin-only, and handleRefreshVTXOs emits a replacement request without AssetRef, AssetAmount, or FixedAmount; the refresh consequently cannot reissue the asset and may submit a destructive transition to an operator lacking conservation checks. Carry the root into this adapter and reject or recover metadata for root-only assets rather than using an empty reference as the Bitcoin discriminator.

Useful? React with 👍 / 👎.

@darioAnongba
darioAnongba merged commit 1aa2174 into darioAnongba/taproot-assets-oor-runtime Aug 11, 2026
3 checks passed
@darioAnongba
darioAnongba deleted the darioAnongba/asset-tree-refresh-client branch August 11, 2026 16:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant