mineracks-ckbunker-hsm-sign/fixtures/README.md
mineracks 9d380f5013 Initial import: CKBunker HSM validation harness
WebSocket client + CLI harness + pytest suite that exercises each axis of
a CKBunker + Coldcard Mk4 policy and asserts the expected outcomes, including
the critical negative test that a large PSBT without TOTP is rejected with
a specific 'rule #1: need user(s) confirmation' reason.

Configuration via .env / YAML / CLI flags, two pre-crafted test PSBTs as
fixtures (generation guide in fixtures/README.md), dashboard counter
scraper as sanity check, design rationale in docs/.
2026-04-14 10:50:04 +10:00

103 lines
3.8 KiB
Markdown

# Test PSBTs — how to generate them
The harness needs **two pre-crafted PSBTs**:
| Fixture | Amount | Policy path expected |
|------------------|------------------|------------------------------|
| `small.psbt` | ≤ auto-approve cap (e.g. 9,000 sats if your Rule #2 cap is 10,000) | Signs without TOTP |
| `large.psbt` | > auto-approve cap, ≤ user-auth cap (e.g. 100,000 sats) | Rejected without TOTP; signs with TOTP |
Both PSBTs must:
- be **spendable by the Coldcard** bound to your CKBunker (same seed / xpub)
- spend to **an address you control** (or a burn address — they are test
inputs, you never broadcast them)
- use a real UTXO the Coldcard can see (watch-only wallet)
---
## Method 1 — Sparrow Wallet (recommended for first-time setup)
1. In Sparrow, open or create a **watch-only wallet** loaded with your
Coldcard's xpub. (The Coldcard's HSM-Mode QR or a `coldcard.txt` export
works.)
2. Send yourself a small amount on testnet **or** signet so you have a UTXO
to spend without losing real sats. (For mainnet demos, 10k sats is
~AUD $1.)
3. Build two transactions:
- `Small demo` — pay **9,000 sats** (or 90% of your Rule #2 per-txn cap)
to any receive address in the same wallet. Sparrow → Send → *Save PSBT*
→ write to `fixtures/small.psbt`.
- `Large demo` — pay **100,000 sats** (or mid-range of your Rule #1 cap)
the same way. Save as `fixtures/large.psbt`.
4. Both PSBTs should show **Coldcard as a required signer** in Sparrow.
> Do NOT broadcast these. The harness signs them, but you verify the
> signatures in Sparrow and then discard — there's no reason to spend real
> sats on a validation run.
---
## Method 2 — bitcoind (CI / automation)
If you're wiring the harness into CI against a regtest or signet
deployment, scripting PSBT generation is a one-off:
```bash
#!/usr/bin/env bash
# Requires bitcoin-cli on PATH, pointed at a node that sees your wallet.
set -euo pipefail
WALLET="ckbunker-watch"
FEE_RATE=10 # sat/vB
recipient=$(bitcoin-cli -rpcwallet=$WALLET getnewaddress)
small_raw=$(bitcoin-cli -rpcwallet=$WALLET walletcreatefundedpsbt \
'[]' "[{\"$recipient\":0.00009000}]" 0 \
"{\"fee_rate\":$FEE_RATE}" | jq -r '.psbt')
echo "$small_raw" | base64 -d > fixtures/small.psbt
large_raw=$(bitcoin-cli -rpcwallet=$WALLET walletcreatefundedpsbt \
'[]' "[{\"$recipient\":0.00100000}]" 0 \
"{\"fee_rate\":$FEE_RATE}" | jq -r '.psbt')
echo "$large_raw" | base64 -d > fixtures/large.psbt
```
---
## Method 3 — use the same PSBT file over and over
Nothing in the harness requires the PSBT to be spendable *right now* for the
reject-path test (`test_04`). The Coldcard rejects on **amount**, not on
whether the UTXO is still unspent. So:
- `small.psbt` can be reused until the UTXO is spent elsewhere.
- `large.psbt` can be reused indefinitely — every validation run that tests
Rule #1 rejection produces a rejection regardless of UTXO state.
If you run the full suite frequently, consider crafting `large.psbt`
deliberately against an **already-spent UTXO** so the success path
(`test_05`) fails at signature verification (not policy evaluation) —
this is arguably safer than running with signable funds live.
---
## File format
Either **binary** (`psbt\xff...` magic bytes) or **base64**-encoded text is
accepted by the harness — it auto-detects via magic bytes. Sparrow exports
binary by default; bitcoin-cli returns base64.
---
## What NOT to do
- Do not commit real PSBTs to git — `.gitignore` already blocks `*.psbt` in
this directory.
- Do not use a PSBT that spends a UTXO you can't afford to move. The
harness does not broadcast, but a leaked signed PSBT *can* be broadcast
by anyone.
- Do not reuse production keys for generating fixtures — prefer testnet
or signet.