Skip to content

multi: claim an exited asset VTXO into the tapd wallet - #1129

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

multi: claim an exited asset VTXO into the tapd wallet#1129
darioAnongba merged 6 commits into
darioAnongba/asset-tree-refresh-clientfrom
darioAnongba/asset-tree-exit-client

Conversation

@darioAnongba

@darioAnongba darioAnongba commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Client half of the asset VTXO unilateral exit, stacked on #1128. Test counterpart: lumos#774 (see the PR list on the integration epic); design: https://taproot-assets-ark.lightning.wiki/.

An unroll already materializes the pre-signed tree on chain and withholds the final sweep for asset targets, so an exited asset leaf ends as a confirmed composed output under the owner's exclusive control. This PR adds the step that turns that output into ordinary tapd balance: the claim.

The claim (tapassets.ClaimAssetVTXO, driven by waved.Server.ClaimAssetVTXO) is stateless and runs in one flow:

  • Complete the lineage. The leaf's sealed package holds its compact proof path; the caller supplies the raw block and height for every anchor transaction the exit confirmed, and tap-sdk's ConfirmProofFile assembles a full confirmed proof file from them.
  • Archive the lineage. tapd verifies a publish against its own proof archive, so the leaf's OP_TRUE script key is declared and the confirmed file imported first. The key's spec is fully recoverable from the leaf's own witness material: the control block carries the internal key and, with the leaf script, the tapscript root.
  • Spend into the wallet. One custom-anchor transition spends the composed leaf output through its exit path (the input sequence is the CSV delay) into a fresh wallet-owned anchor: script key and internal key both come from tapd, funding is caller-funded-exact out of the leaf's carrier value, and waved signs the exit path with the same sweep wallet the Bitcoin unroll uses.

The wallet script plan derives a fresh asset script key at commit time, so there is no preview fixed-point to converge on: the claim commits against a placeholder anchor script, validates the committed transaction's shape and fields, and adopts the committed output script as the thing to sign.

One adjacent fix: preflightUnrollFeasibility prices an exit in carrier sats, which refused every asset leaf as uneconomical. Asset targets are exempt, since the value that justifies the exit is the asset, not its carrier.

tap-sdk is bumped for the confirmed proof-file assembly (tap-sdk#176) and an x-only DeclareScriptKey fix.

Verified by TestRoundAssetExit in lumos: board, unroll, mature the exit delay, claim, and a plain tapd transfer out of the claimed balance.

The unroll puts the composed leaf on chain; once its CSV delay
matures, the claim completes the leaf's sealed lineage into a
confirmed proof file, spends the anchor through the exit leaf, and
commits one transition into a fresh tapd-owned anchor. Script and
internal keys both come from tapd, so the units become ordinary,
spendable wallet balance when the claim confirms.
An asset leaf's worth is the assets riding on it, so the feasibility
verdict priced in carrier sats refused every asset exit as
uneconomical.
The wallet script plan derives a fresh asset script key at commit
time, so a preview's commitment root never matches the commit and the
anchor output script is only knowable afterwards. Ship a placeholder
template and adopt the committed transaction's script instead.
Publishing verifies the transition against tapd's own proof archive,
so the leaf's confirmed lineage is imported first. The OP_TRUE script
key is declared from its own witness material: script and control
block carry the internal key and tapscript root. Declaring at claim
time is correct, since the anchor is on chain under the owner's
exclusive control and the claim spends it in the same flow.

@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: 865f091ce4

ℹ️ 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 tapassets/claim.go
Comment on lines +198 to +200
committed, err := driver.CommitClaim(
ctx, buildRequest(anchorPSBT), nil,
)

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 Persist the committed claim before continuing

If the request is canceled, waved crashes, signing fails, or publishing returns an ambiguous error after CommitClaim succeeds, the only copy of committed.packageBytes is lost even though tapd has already been mutated. A retry starts from scratch, derives new wallet keys, and commits another transition rather than resuming the exact package, which can leave a pending/leased transfer or create a conflicting double spend and strand the asset until manual reconciliation. As the onboarding workflow does, journal the commit attempt and exact transfer package/final PSBT by outpoint before signing and publishing, and serialize retries for that outpoint.

Useful? React with 👍 / 👎.

@darioAnongba
darioAnongba merged commit 1aa2174 into darioAnongba/taproot-assets-oor-runtime Aug 11, 2026
1 check passed
@darioAnongba
darioAnongba deleted the darioAnongba/asset-tree-exit-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