Skip to content

Feature: Add SLIP-19 support for safe remote-signing of WabiSabi coinjoins#685

Draft
kravens wants to merge 2 commits into
Coldcard:masterfrom
kravens:feature/slip19-coinjoin
Draft

Feature: Add SLIP-19 support for safe remote-signing of WabiSabi coinjoins#685
kravens wants to merge 2 commits into
Coldcard:masterfrom
kravens:feature/slip19-coinjoin

Conversation

@kravens

@kravens kravens commented Jul 11, 2026

Copy link
Copy Markdown

SLIP-19 ownership proofs for coinjoin remote signing

What

Adds a USB command slp9 that returns a SLIP-19 ownership proof (BIP-322-style) for a given derivation
path + commitment, and an HSM policy field slip19_paths gating which paths may be proven while unattended.
This is the one primitive a coinjoin coordinator (e.g. Wasabi WabiSabi) needs that no existing Coldcard
command provides: a signature over SHA256(proofBody ‖ cs(spk) ‖ spk ‖ cs(commitment) ‖ commitment), which
is not a transaction sighash, so PSBT/BIP-322/message-signing cannot produce it.

Changes (3 files, ~84 lines)

  • shared/slip19.py (new) — make_ownership_proof(subpath, flags, commitment): derives the key,
    builds the proof body (magic SL\x00\x19 ‖ flags ‖ varint(count) ‖ 32-byte ownership id), computes the
    digest, ECDSA-signs (P2WPKH), and returns the fully serialized proof (proof body ‖ empty scriptSig ‖
    witness stack). Taproot (P2TR, BIP-340 keyspend over the same digest) is stubbed — the ngu primitives
    (sign_schnorr, xonly_pubkey_tweak_add, tagged-sha256) are already present.
  • shared/usb.pyslp9 command handler mirroring smsg/xpub: unpacks <III> (flags, len_subpath,
    len_commitment) + payloads, gates on hsm_active.approve_slip19(subpath) when in HSM mode, returns
    b'biny' + proof.
  • shared/hsm.pyslip19_paths policy field (mirrors msg_paths), included in policy JSON/text, and
    approve_slip19(subpath) (mirrors approve_xpub_share).

Verified (simulator)

The real slp9 command returns a proof that Wasabi's own verifier accepts — see the consumer tests
WalletWasabi.Tests/.../ColdcardProofSpikeTests.cs (OwnershipProof.VerifyOwnership passes on both the
reconstructed proof and the full wire bytes off the slp9 command).

Before upstream submission (follow-ups)

  • Implement the taproot branch (BIP86 output-key tweak + sign_schnorr).
  • Real SLIP-19 ownership id via the SLIP-21 node (currently zeros — accepted by the coordinator, which does
    not bind the id, but should be correct).
  • Decide the non-HSM UX: currently returns synchronously like xpub; upstream may want an on-device
    confirmation for interactive use (in HSM the slip19_paths whitelist is the gate).
  • testing/test_hsm.py coverage (whitelisted path signs, non-whitelisted denied) + a docs page.

kravens added 2 commits July 8, 2026 15:53
Taproot key-spend proof: BIP-86 tweak the internal key (libsecp
keypair_xonly_tweak_add handles internal even-Y + output parity), then a
BIP-340 schnorr signature over the same SLIP-19 digest. Simulator-verified
against Wasabi OwnershipProof.VerifyOwnership with an independent NBitcoin
BIP-86 derivation. Note: a full taproot coinjoin round also needs taproot
PSBT spend-signing, which is EDGE-firmware only.
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