Skip to content

feat: add CovVHTLC covenant claim script and covclaim watcher daemon#396

Open
Kukks wants to merge 4 commits intoarkade-script-finalfrom
feat/cov-vhtlc
Open

feat: add CovVHTLC covenant claim script and covclaim watcher daemon#396
Kukks wants to merge 4 commits intoarkade-script-finalfrom
feat/cov-vhtlc

Conversation

@Kukks
Copy link
Copy Markdown
Contributor

@Kukks Kukks commented Apr 1, 2026

Summary

  • CovVHTLC: New VHTLC variant with a 7th covenant claim tapscript leaf. Anyone with the hash preimage can claim the VTXO — no user signature required. The Arkade introspector validates output constraints (destination address + amount) via INSPECTOUTPUTSCRIPTPUBKEY + INSPECTOUTPUTVALUE before co-signing.
  • Covenant preimage condition: Uses SIZE 32 EQUALVERIFY before HASH160 check, matching Boltz's Liquid covenant claim design.
  • covclaim daemon: Standalone Node.js service that watches for on-chain covenant VTXOs via esplora and automatically builds + broadcasts claim transactions through the introspector. Includes REST API for registering covenants.
  • 24 unit tests covering construction, leaf accessors, covenant script structure, address generation, and validation.

Architecture

The covenant claim leaf uses ConditionMultisig with empty pubkeys — ArkadeVtxoScript.processScripts appends the tweaked introspector key, resulting in a 1-of-1 multisig where only the introspector signs after validating the arkade script constraints.

Multi-input spending is safe by design (same approach as Boltz on Liquid): the covenant pins output 0 to a specific address + amount, so additional inputs cannot redirect covenant funds.

Test plan

  • All 24 CovVHTLC unit tests pass (npx vitest run test/cov-vhtlc.test.ts)
  • Verify first 6 leaves produce identical scripts to standard VHTLC (covered by test)
  • e2e test with introspector for covenant claim path
  • covclaim daemon integration test against regtest

Kukks added 4 commits March 5, 2026 12:43
arkd v0.9.0-rc.4 adds Extension TLV support (pkg/ark-lib/extension),
required for the IntrospectorPacket OP_RETURN format.

introspector v0.0.1-rc.1 includes the OP_RETURN-based IntrospectorPacket
encoding (PR #9) and OP_MERKLEPATHVERIFY (PR #11).
…commitment tx modification

- Pass Extension output to buildForfeitTx as additionalOutputs so the
  IntrospectorPacket is part of the transaction from construction,
  preventing txid mismatch with the introspector's expected value.

- Remove addIntrospectorPacketToTx for boarding commitment txs. The
  introspector already knows arkade scripts from the intent proof
  submission, so modifying the server-built commitment tx (which
  changes its txid) is unnecessary.

- Add optional additionalOutputs parameter to buildForfeitTx and
  buildForfeitTxWithOutput for Extension OP_RETURN support.
arkd reconstructs forfeit txs with exactly 2 outputs (forfeit + anchor)
and compares txids. Adding an Extension output changes the txid, causing
INVALID_FORFEIT_TXS errors. The introspector already has arkade script
info from the intent proof, so forfeits don't need Extension outputs.

Also reverts the additionalOutputs parameter from buildForfeitTx since
it's no longer needed.
CovVHTLC extends VHTLC with a 7th tapscript leaf that enables covenant-enforced
claims. Anyone with the preimage can claim the VTXO — no user signature required.
The Arkade introspector validates output constraints (destination address + amount)
via introspection opcodes before co-signing.

Includes:
- CovVHTLC script class with 7 leaves (6 standard VHTLC + 1 covenant claim)
- Covenant preimage condition with SIZE 32 check (matching Boltz Liquid design)
- Arkade script using INSPECTOUTPUTSCRIPTPUBKEY + INSPECTOUTPUTVALUE
- 24 unit tests covering construction, leaf accessors, script structure, validation
- covclaim: standalone Node.js daemon that watches for on-chain covenant VTXOs
  and automatically builds + broadcasts claim transactions via the introspector
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 1, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (1)
  • next-version

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 34488d11-04d7-4f62-98fe-0451057ad207

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/cov-vhtlc

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@arkanaai arkanaai bot left a comment

Choose a reason for hiding this comment

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

CovVHTLC + covclaim Daemon Review

TL;DR: Well-structured covenant claim extension. The script design is sound — SIZE 32 gate + HASH160 + introspector co-sign mirrors the proven Boltz Liquid pattern. A few security/robustness items worth addressing before this goes live.


Architecture ✅

The 7th leaf design is clean: ConditionMultisig with empty pubkeys + ArkadeVtxoScript.processScripts appending the tweaked introspector key = 1-of-1 multisig where the introspector validates output constraints before signing. Multi-input safety holds because the covenant pins output 0 to a fixed address + amount.

The batch.ts cleanup (removing addIntrospectorPacketToTx from commitment + forfeit txs) is correct — the introspector gets arkade scripts from intent proofs, so modifying those txs was both unnecessary and dangerous (changed txids).

Security Observations

1. Preimage over unauthenticated HTTP (covclaim/src/server.ts)
The REST API accepts preimages with zero auth. Anyone who can reach port 1234 can register arbitrary covenants. For regtest this is fine, but the README should explicitly warn that production deployments must be behind TLS + auth (or localhost-only). The preimage is the money — leaking it means anyone can front-run the claim.

2. Claiming unconfirmed UTXOs (covclaim/src/watcher.ts:53)

const utxo = utxos.find((u) => u.status.confirmed) ?? utxos[0];

Claiming an unconfirmed UTXO is risky — if the funding tx gets reorged or RBF'd, the claim tx becomes invalid and the daemon marks the covenant "claimed" with a stale txid. Consider requiring at least 1 confirmation, or adding a re-check after broadcast.

3. No UTXO value validation (covclaim/src/claimer.ts)
If inputAmount < expectedAmount + fee, the tx construction will produce an invalid transaction (or negative change). Add an explicit check before building the tx:

if (inputAmount < expectedAmount + fee) {
    throw new Error(`UTXO value ${inputAmount} insufficient for claim ${expectedAmount} + fee ${fee}`);
}

4. Vsize underestimate (covclaim/src/claimer.ts:17)
ESTIMATED_VSIZE = 200 may be tight for deep taproot trees. A CovVHTLC with 7 leaves has a Merkle path depth of ~3, plus the witness includes sig (64b) + preimage (32b) + leaf script + control block. Worth measuring against a real regtest tx and adding margin, or computing dynamically.

Code Quality

5. Duplicated networkFromConfig — identical function in both covclaim/src/claimer.ts and covclaim/src/derive.ts. Extract to a shared util.

6. In-memory store (covclaim/src/store.ts) — daemon restart loses all registered covenants. Acceptable for alpha/regtest but worth a TODO comment or a simple JSON-file persistence option.

7. Test coverage is solid — 24 tests covering construction, leaf identity with VHTLC, arkade script introspection opcodes, validation edge cases, and address determinism. The test verifying first 6 leaves match VHTLC is particularly valuable for catching drift.

Cross-Repo Impact

  • Bumps introspector to v0.0.1-rc.1 and arkd branch to v0.9.0-rc.4 in docker-compose + Dockerfiles — ensure these tags exist and are stable before merging.
  • The CovVHTLC export from src/index.ts is a public API addition — consumers of @arkade-os/sdk will see this in the next release.
  • Related: ArkLabsHQ/introspector must support the IntrospectorPacket format and INSPECTOUTPUTSCRIPTPUBKEY / INSPECTOUTPUTVALUE opcodes (PRs #9 and #11 per commit message).

Minor

  • covclaim/package.json pins @arkade-os/sdk as file:.. — works for monorepo dev but will need adjustment for standalone deployment or CI.
  • The express import in server.ts uses default import (import express from "express") — works with esModuleInterop: true but worth noting for strict ESM consumers.

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