Skip to content

swapkit: Consolidate asset swaps on tap-sdk v0.1.1 - #1225

Open
hieblmi wants to merge 9 commits into
lightninglabs:masterfrom
hieblmi:codex/shared-asset-swapkit
Open

hieblmi wants to merge 9 commits into
lightninglabs:masterfrom
hieblmi:codex/shared-asset-swapkit

Conversation

@hieblmi

@hieblmi hieblmi commented Sep 2, 2026 •

Copy link
Copy Markdown
Collaborator

Provide shared contracts and SDK helpers for asset Loop In, asset Loop Out, and reservations. swapkit/ defines Bitcoin spending policies, signing roles, witnesses, and weights. swapkit/tapsdk/ adapts those contracts to native tap-sdk transfer construction, checks independently agreed terms, binds signing to the approved package, and handles proofs and recovery. The consuming feature owns its state machine, persistence, Lightning deadlines, and decisions about releasing signatures or preimages.

The implementation uses released tap-sdk v0.1.1 and Taproot Assets v0.8.8 on the pre-btcd-v2 dependency graph. New on-chain asset operations require a running tapd v0.8.8. The runtime gate accepts the released daemon's 0.8.8-alpha version string and rejects v0.8.6, v0.8.7, and v0.8.8 release candidates. Consuming Go modules must repeat the bounded legacy TLV decoder replacement in Loop's go.mod, because Go does not inherit dependency replacements.

All contracts have a cooperative MuSig2 path. Their unilateral refund policies are explicit:

Constructor Refund policy
NewDepositKit Sender CSV delay measured from funding confirmation
NewReservationKit Server/sender absolute CLTV height
NewSwapKit(SwapHTLCLegacyCSV) Sender CSV delay
NewSwapKit(SwapHTLCStaticLoopInV3) / SwapHTLCCLTV Sender absolute CLTV height

Both HTLC variants require the receiver's signature and the correct 32-byte preimage on success, with the existing one-block CSV. The reservation purchase flow in Loop #1229 preserves its quoted CSV delay by adapting NewDepositKit with explicit server/client key roles. NewReservationKit supplies the separate CLTV policy.

The default asset script descriptor preserves the fixed NUMS internal key and single OP_TRUE leaf through LegacyOPTrueOutput. The SDK supplied-key variant, SDKOPTrueOutput, requires explicit selection. Funded outputs retain their exact descriptors through spending and recovery.

Review the nine commits in order. Each carries unit coverage for the behavior it introduces.

  1. Share Bitcoin leaf serializers with existing swaps, preserving byte-for-byte script encodings and quote templates.
  2. Define deposit, reservation, and HTLC contracts, signing roles, witnesses, and weights.
  3. Connect the released SDK to an authenticated tapd connection and map contracts and asset descriptors to SDK requests.
  4. Enforce the tapd version floor and authenticate asset history and Bitcoin prevouts against the current chain.
  5. Check the native builder's transaction, asset allocations, and fees against independently agreed terms.
  6. Bind signing authority and final witnesses to the approved native package.
  7. Verify presigned descendants against their parents and carry them through confirmation.
  8. Recover claims, refunds, and exact output proofs from observed spends.
  9. Harden recovery against hostile peer input: bind a recovery fallback to the authenticated deposit before co-signing, verify a caller-provided asset witness before declaring it, and classify annex spends, reorgs, and stale chain responses in the observed-spend helpers.

Package usage and validation boundaries are documented in the contract README and SDK adapter README.

Rebased on Loop master 9158aed2a. Unit tests for every package this PR touches passed locally on d620bd25aca7, the swapkit and proof/policy suites also under the race detector. Lint reported no findings in the files this PR touches, and the commit-message and module tidiness checks passed. CI for this head is running.

Daemon-backed asset lifecycle tests live in Nautilus #1712. They cover the contracts, transfer and proof boundaries, and an explicitly selected SDK supplied-key OP_TRUE deposit-to-HTLC lifecycle. The server pins this head at c0f4ef6d0. The fresh-key case (claim, HTLC timeout, and deposit timeout) and the deposit HTLC timeout sweep, kit restart recovery, recovery respend, passive asset, split transfer, reorg proof, and asset HTLC cases passed locally on tapd v0.8.8 on a build containing this head's kit changes, before its last rebase onto Loop master. Companion CI runs them on the pinned head.

@hieblmi hieblmi added the no-changelog Skip the release notes CI check label Sep 2, 2026
@hieblmi
hieblmi force-pushed the codex/shared-asset-swapkit branch 4 times, most recently from c206f0d to 2814bf6 Compare September 3, 2026 05:54
@hieblmi hieblmi added asset loop out Taproot Asset Loop Out work and removed no-changelog Skip the release notes CI check labels Sep 3, 2026
@hieblmi hieblmi changed the title assets: Add shared asset HTLC kit assets: Add shared asset tooling Sep 3, 2026
@hieblmi hieblmi added the no-changelog Skip the release notes CI check label Sep 3, 2026
@hieblmi
hieblmi force-pushed the codex/shared-asset-swapkit branch 2 times, most recently from 4283082 to 50595de Compare September 3, 2026 08:12
@hieblmi hieblmi self-assigned this Sep 3, 2026
@hieblmi
hieblmi marked this pull request as ready for review September 3, 2026 12:22
@hieblmi

hieblmi commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator Author

/gateway review

@lightninglabs-gateway

Copy link
Copy Markdown

👀 gateway review starting…

@starius starius left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Style — ~18 unexported funcs and ~14 test helpers have no godoc, against the convention. Non-test: canonicalAddressParams, cloneAddressParams (both copies), validateScripts, genBtcControlBlock, validateAsset (both), findUniqueInput (both), validateSweep (both), validateSequence, verifyTapscriptSignature (both), timeoutPathSibling, encodedTimeoutPathSibling, newHtlcSwapKit, validateProof.

Comment thread assets/tapkit.go Resolved
Comment thread assets/tapkit.go Resolved
Comment thread assets/deposit/kit.go Resolved
Comment thread assets/deposit/kit.go Resolved
Comment thread assets/deposit/kit.go Resolved
Comment thread assets/deposit/kit.go Resolved
Comment thread assets/htlc/swapkit.go Resolved
@hieblmi

hieblmi commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator Author

Follow-up commit 818876e also adds documentation to the unexported production and test helpers listed in the general review. Local verification passed: go test ./..., go test -race ./assets/..., go vet ./..., golangci-lint (0 issues), plus a Nautilus #1712 itest-package compile with integration tags.

@hieblmi
hieblmi requested a review from starius September 8, 2026 13:05
@hieblmi
hieblmi force-pushed the codex/shared-asset-swapkit branch from 818876e to 81e876c Compare September 8, 2026 14:33
Comment thread assets/deposit/kit.go Resolved
Comment thread assets/htlc/swapkit.go Resolved
Comment thread assets/deposit/kit.go Resolved
Comment thread assets/deposit/kit.go Resolved
Comment thread assets/htlc/swapkit.go Resolved
Comment thread assets/deposit/kit.go Resolved
Comment thread assets/htlc/swapkit.go Resolved
Comment thread assets/deposit/kit.go Resolved
Comment thread assets/deposit/kit.go Resolved
Comment thread assets/htlc/swapkit.go Resolved
Comment thread assets/htlc/script.go Resolved
@litbot-9000

Copy link
Copy Markdown
Collaborator

@bhandras: review reminder
@sputn1ck: review reminder
@hieblmi, remember to re-request review from reviewers when ready

@hieblmi
hieblmi force-pushed the codex/shared-asset-swapkit branch from 81e876c to dcd5af1 Compare September 17, 2026 08:44
@litbot-9000

Copy link
Copy Markdown
Collaborator

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

@hieblmi
hieblmi force-pushed the codex/shared-asset-swapkit branch from f7565a9 to 4a124f3 Compare November 2, 2026 16:05
@hieblmi hieblmi changed the title assets: Consolidate shared swap contracts on tap-sdk swapkit: Consolidate asset swaps on the local Taproot Assets SDK Nov 2, 2026
@hieblmi
hieblmi force-pushed the codex/shared-asset-swapkit branch from 4a124f3 to a6b6846 Compare November 2, 2026 20:49
@hieblmi hieblmi changed the title swapkit: Consolidate asset swaps on the local Taproot Assets SDK swapkit: Consolidate asset swaps on tap-sdk v0.1.1 Nov 2, 2026
@hieblmi
hieblmi force-pushed the codex/shared-asset-swapkit branch 2 times, most recently from 8347df9 to 941c126 Compare November 3, 2026 13:08
@litbot-9000

Copy link
Copy Markdown
Collaborator

@starius: review reminder

@hieblmi
hieblmi force-pushed the codex/shared-asset-swapkit branch from 941c126 to 0ad07d7 Compare November 4, 2026 13:41
@hieblmi
hieblmi requested a review from bhandras November 5, 2026 13:18
@hieblmi
hieblmi force-pushed the codex/shared-asset-swapkit branch 5 times, most recently from dc2961f to 34cd8d2 Compare November 10, 2026 12:38
@litbot-9000

Copy link
Copy Markdown
Collaborator

@starius: review reminder
@bhandras: review reminder

@hieblmi
hieblmi force-pushed the codex/shared-asset-swapkit branch 2 times, most recently from 9dc4039 to 7d29edd Compare November 11, 2026 13:36
Route existing HTLC, static address and reservation scripts through
the same leaf serializers. Pin the quote templates so moving the
serialization cannot change signed numbers or zero-hash fee estimates.
Define the key roles, cooperative and unilateral paths, witnesses and
weight estimates for both directions. Exercise the legacy vectors and
execute the spend conditions against the Bitcoin script engine.
Build the adapter against released pre-btcd-v2 modules and retain the
bounded legacy TLV decoder. Map contracts into SDK plans and reuse the
authenticated wallet connection.

Define the shared runtime version floor and operation-scoped checks.
Warn about older backends during daemon initialization while leaving
ordinary payments and offline witness construction available.
Authenticate proof history, asset commitments, group issuances and
Bitcoin inputs before granting on-chain authority. Apply the shared
tapd floor at proof boundaries while keeping offline construction
available.

Distinguish invalid funding candidates from exact outputs waiting on
confirmations or a chain backend. Preserve retryable results when no
candidate is ready.
Prepare confirmed inputs for native Build and check its allocations,
Bitcoin template, change policy and fee before granting authority.
Verify wallet-funded fees again after native Commit.
Check signing policy and the saved package before using LND, and
accept peer witnesses only for the approved transaction. Preserve
durable recovery while ephemeral signing sessions remain caller-owned.

Separate contract-input signing from finalization so wallet-funded
callers can sign fee inputs before sealing the final anchor transaction.
Bind native compact paths to approved signed parents. After parents
confirm, replace proof metadata with authenticated histories without
altering the transaction or final witnesses.
Recover contract spends through native SDK packages and exact output
proofs. Preserve the original contract descriptors, asset quantities
and confirmation evidence across claims and refunds.

Make publication retries consult exact archived proofs and the tapd
transfer log before logging again. Report pending confirmations without
creating duplicate transfer records or repeating their anchor fees.
Bind a recovery fallback package to the authenticated deposit before
it is co-signed. The MuSig2 sighash covers the committed PSBT's own
previous output, so a peer that changed only the signed input value
or script obtained a valid signature that spent nothing real. Compare
that prevout with the deposit output, reject a committed asset that
carries its own lock time, and require normal broadcast.

Verify a caller-provided asset witness commits to its input script
key before declaring it to tapd, so a peer cannot bind a wallet
script key to an unrelated internal key.

Recognize a BIP-341 annex when matching the agreed leaf, reject an
annex spend from reconstruction rather than mis-slicing its witness,
report a reorg observed during outcome verification as retryable, and
guard the observed-spend discovery helpers against a chain that
returns a block without the watched spend.
@hieblmi
hieblmi force-pushed the codex/shared-asset-swapkit branch from 7d29edd to d620bd2 Compare November 12, 2026 16:17
@GustavoStingelin
GustavoStingelin self-requested a review November 13, 2026 13:23

@GustavoStingelin GustavoStingelin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Found no issues.

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

Labels

asset loop out Taproot Asset Loop Out work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants