Tester Guide (Pre-Alpha)

Formerly "Swap Key", the internal codename; protocol lineage v3.16 unchanged. This page mirrors docs/TESTER-GUIDE.md from the release package — the package copy travels with the exact build you run.

Welcome, and thank you for testing. This guide takes you from nothing to a completed swap, covers the local UI and the second-device watchtower, and tells you exactly how to report what breaks.

1. ⚠ Limitations banner — read this first, it is not optional

  • TESTNET/REGTEST ONLY — NO REAL FUNDS. Mainnet has no config variant by construction; that stays true until the external cryptographer review. Treat every coin this wallet touches as expendable test money.
  • ~HALF of swap attempts refuse and close through REFUNDS — by design. The role↔CSV pre-commitment fix is deferred to the cryptographer review; the interim convention makes convention-mismatched attempts refuse at the CSV-binding guard, and your funds come back automatically at the refund timelock (roughly 24–36 hours on testnet). A refunded swap is the safety system WORKING. Retry, don't panic.
  • Plaintext TCP peer transport — loopback/LAN/VPN interop only; assume anyone on the path can watch the (non-secret) negotiation. Tor/Noise is post-pre-alpha.
  • Software key custody — a BIP39/BIP32 encrypted file, not a hardware enclave. Your passphrase and 24-word mnemonic are the whole defense.
  • serve has NO auth — loopback only, and any local process can drive your wallet while it runs. Don't run it on a shared machine.
  • Claim-delay privacy holds are real: after a swap settles you may see holding the SL claim until height N for many blocks. That is the privacy posture working — leave the wallet running.
  • Onboarding delays are real: each newly onboarded coin becomes swappable only after its OWN randomized decorrelation delay, drawn per coin. status annotates each unit with its maturity time and height gate; a swap attempted early refuses cleanly and leaves the coin untouched, so retrying is free. (The current signed manifest sets the testing-period delay; the production-scale 24–72 h value returns after the testing round.)
  • testnet4 REORGS are routine. If a reorg detected: … HOLDING … line appears mid-swap, the wallet is deliberately pausing until the orphaned confirmation settles. A reorg can only ever DELAY an exit, never fire one early. Leave it running.

2. Install

Option A — the release package (switchbitcoin-prealpha-<version>-<git>-<platform>/): verify SHA256SUMS, put the folder somewhere convenient, and use the two binaries directly: switchbitcoin-cli (the wallet) and switchbitcoin-manifest (operator tooling — testers normally never need it). README-FIRST.txt points back here.

Option B — build from source (windows-gnu is the verified host): Rust toolchain + a MinGW gcc (Windows), then scripts/build-release.sh — it runs the full test gates, refuses to package a binary with a test trust root, and drops the package under dist/. Linux/macOS: same script, best-effort (untested hosts).

Check what you have — every bug report starts with this line:

switchbitcoin-cli version

It prints the build (crate version + git hash), the pre-alpha banner, and the pinned manifest trust root. Cross-check that root against the key published on the homepage. If you EVER see an UNSHIPPABLE BUILD banner, stop and report it — that binary trusts a public test key.

3. A Bitcoin node

You need your own Bitcoin Core 28 or newer (P2A/TRUC support), synced on testnet4 — or regtest for a purely local rehearsal: two wallets (two data dirs, two configs) on one machine against bitcoind -regtest, same quickstart flow with --network regtest, and you mine your own blocks.

bitcoind -testnet4 -server=1

There is deliberately no hosted RPC option: pointing your wallet at someone else's node hands them your addresses, your timing, and the power to lie to you about confirmations. Pre-alpha testing assumes your own node. Windows note: no -daemon on Windows builds — give bitcoind its own terminal. Cookie auth (the default) is the easiest hookup: point rpc_cookie_file at <bitcoind datadir>/testnet4/.cookie.

4. Quickstart (zero → first swap)

Run switchbitcoin-cli quickstart — it prints the numbered walkthrough (init → address → faucet → onboard → swap ticket) and every wallet command tells you the next one. Highlights and traps:

5. Connectivity (NAT & reachability)

A swap needs a live TCP link between the two wallets. On one machine (loopback) or one LAN this just works. Across the internet the maker (swap --make) runs a listener the taker must reach, and home routers block inbound connections by default.

6. The local UI (optional)

switchbitcoin-cli serve

then open SwitchBitcoin-Wallet.html (shipped in the package) in a browser. It talks to http://127.0.0.1:3316 — loopback only, no auth (limitation banner applies). Onboarding, tickets, and live swap state all work from the page; everything the UI does is also in the CLI.

When a backend is connected the page shows a live status strip: the permanent pre-alpha banner with build version, manifest version + id (with a LOUD warning on the fingerprintable v0 baseline), refund reality explained rather than shown as a bare "failed", claim holds rendered as privacy holds until a named block, alarms shown prominently, and the active/max swap count. The page renders /status verbatim — it never invents state. If a surface looks wrong, switchbitcoin-cli status / manifest show say the same thing.

7. Signed parameter manifests

Settlement parameters arrive on a signed, versioned manifest — never from your config file. Two commands matter to a tester:

8. Backup, restore, and the second-device watchtower

This is the best fund-safety demo you can run:

  1. switchbitcoin-cli backup wallet.skbak (on your main device; refuses while the wallet is running).
  2. Move the bundle to a second device (or second directory + own config), switchbitcoin-cli restore --from wallet.skbak.
  3. switchbitcoin-cli watch on the second device.
  4. Start a swap on the primary and kill the process mid-swap.
  5. Watch the tower fire your pre-armed refund at CSV maturity — funds come back with the primary dead.

What a watchtower can and cannot do: it can only ever broadcast your own pre-armed refund (single-signed at negotiate time, pays your own key) and a CPFP fee-bump of that refund — it holds no session key, never signs completions, never negotiates. It cannot steal and cannot grief; two devices firing the same refund is idempotent (same bytes, same txid).

9. Troubleshooting (keyed to the real strings)

You seeIt means / do this
swept escrow carries the wrong refund CSV (extract-and-race guard); refund The ~50% role/CSV convention mismatch (banner item 2). The swap closes through refunds. Retry a fresh swap.
swap routed to the refund exit: … then refund path resolved Normal refund closure. Funds return at CSV maturity; leave the wallet running (or recover later).
holding the SL claim until height N Privacy hold, not a hang. Keep running; on regtest, keep mining.
reorg detected: … HOLDING … A testnet4 reorg orphaned a confirmation your live swap depends on. The wallet holds until it re-confirms — the safety system working. Keep running; report only if it never clears.
another process holds this swap store (single-instance) Two processes on one data dir (often serve + swap, or watch on the primary dir). One wallet process per dir.
wallet onboarding is incomplete — run switchbitcoin-cli init first init never finished (mnemonic retype/Phase-0). Re-run init.
keystore: wrong passphrase or corrupted file Wrong passphrase (retype) — or real file damage: restore keystore.bin from backup / init --restore from the mnemonic.
this command needs a node: add a [node] section to switchbitcoin.toml Fill [node] in the config (section 3).
deposit not found or not confirmed — wait for a confirmation The faucet tx hasn't confirmed, or the <txid:vout> is wrong (vout is the output INDEX paying your address).
coins become leasable after their decorrelation delay … / timelock/deadline invariant violated: … onboarding delay The onboarding privacy delay. NOT a bug and nothing is stuck (no lease, no broadcast) — status shows each unit's maturity; wait and re-run swap.
handshake: peer runs different signed params (manifest mismatch) You and your partner are on different manifest versions. Both run manifest show, ingest the current manifest, retry.
manifest REFUSED: … signature does not verify The file isn't signed by the pinned operator root (corrupt download, wrong file, or the retired-key v1). Re-fetch the round's manifest.
ALARM (manifest open): ProvisionalFallback/RollbackDetected… The stored manifest was tampered/rolled back and quarantined; the wallet fell back to the compiled baseline. Re-ingest the current manifest and REPORT IT.
no taker reached … before the accept timeout / could not reach the peer at … Reachability (NAT/firewall) — section 5. Nothing was locked; fix the address and retry.
chain reconcile failed — fix the node/data dir before swapping The node is unreachable/out of sync. Fix [node]/bitcoind first; refusing to swap in that state is deliberate.
FEE WEATHER WARNING: live N sat/vB exceeds baked … NOT a hang and NOT an error — the swap proceeds; if a Setup or settlement then stalls, the reserve-CPFP backstop fee-bumps it automatically.
ALARM — RefundStalledBelowFeeFloor: … Congestion + no usable reserve for the fee bump. The refund still fires; only confirmation waits. If it names the watchtower device, onboard a deposit there.
standing down (completion-supersedes) The counterparty's completion confirmed, so the refund is moot. Correct behavior.
ALARM: … quarantine / unreadable swap record A sealed record failed authentication. ALWAYS report this one with diag output.
error: unknown flag … Typo protection — flags are strict on purpose. switchbitcoin-cli help.

The package copy of the guide carries the complete table, including watchtower- and fee-bump-specific lines.

10. Reporting bugs

  1. Run switchbitcoin-cli diag and copy the WHOLE block. It is redacted by construction — no seed, mnemonic, passphrase, or RPC secrets — and names the exact build.
  2. Fill in docs/BUG-REPORT-TEMPLATE.md from the package (what you did, what you expected, what happened, diag output, your Bitcoin Core version, the failing command's full stderr).
  3. Send it through the channel you were onboarded with (pre-alpha testers are hand-picked; there is no public tracker yet).

Wallet output never contains secrets by construction — but if you paste anything else (configs, terminal scrollback from init), CHECK IT: the mnemonic is displayed once during init, and that's on you to keep out of reports.