Skip to content

KIP: Multisig Wallet Conventions for Kaspa#39

Open
InKasWeRust wants to merge 2 commits intokaspanet:masterfrom
InKasWeRust:master
Open

KIP: Multisig Wallet Conventions for Kaspa#39
InKasWeRust wants to merge 2 commits intokaspanet:masterfrom
InKasWeRust:master

Conversation

@InKasWeRust
Copy link
Copy Markdown

Draft KIP proposing wallet-level conventions for Kaspa multisig,
built on top of the existing kaspa-wallet-pskt substrate. The KIP
is Informational — it proposes no consensus changes.

It covers four things:

  1. Wallet-convention defaults that PSKT deliberately leaves open:
    derivation path, cosigner pubkey ordering, redeem-script
    construction, and a two-layer descriptor format (canonical +
    compact).

  2. Three existing Kaspa consensus behaviors that currently lack
    documentation and that fail-close at broadcast time when
    wallet authors miss them:

    • P2SH input sigOpCount = N, not M
    • No Bitcoin OP_0 dummy in CHECKMULTISIG unlock scripts
    • PartialSig variant tagging ({schnorr|ecdsa})
  3. Transport framing suggestions (QR, NFC, USB) — non-normative.

  4. A non-normative appendix proposing optional PSKT size
    reductions intended to broaden the set of devices that can
    meaningfully participate in Kaspa multisig ceremonies
    (sub-$20 hardware signers with constrained cameras). These
    are candidates for upstream discussion with the
    kaspa-wallet-pskt maintainers, not unilateral KIP additions.

Reference implementation: KasSigner (air-gapped ESP32-S3 hardware
signer) + KasSee (browser WASM companion). Mainnet proof of
end-to-end operation via a 2-of-3 multisig transaction:

407d948930db9cf5ca77eb0448f0a64182643fcaded423a752a5aebfc86e8c4e

A dedicated research.kas.pa discussion thread will be opened once
initial review feedback arrives on this PR — the Comments-URI
field is left as TBD until then.

Happy to iterate on scope, wording, or structure. Flagging this
as Draft so the KIP number assignment can happen during review.

Informational KIP. Documents wallet-level conventions for Kaspa multisig built atop kaspa-wallet-pskt. Proposes no consensus changes.
Changes from the original submission:

- sigOpCount rule: corrected from `= N` to `M ≤ sigOpCount ≤ N`
  per @biryukovmaxim. M is tight under this KIP's lex-sort +
  ordered-emission conventions; N remains a safe upper bound.
  References upstream get_sig_op_count and
  op_check_multisig_schnorr_or_ecdsa in crypto/txscript/src/lib.rs.

- Redeem script arithmetic: fixed formula from `2 + N*33` to
  `3 + N*33` for M,N ≤ 16. 2-of-3 is 102 bytes, not 101.
  Verified against the reference implementation's build_script().

- QR capacity table: corrected ECC-level labeling. Now uses
  authoritative ISO/IEC 18004 ECC-L values (134/230/458 bytes
  at V6/V9/V14) with frame counts that account for the 3-byte
  framing header.

- Layer B compact descriptor: tightened from "65 bytes compressed
  pubkey with key-origin" to explicit
  "33-byte compressed pubkey || 32-byte chain_code".

- Cosigner ordering: added note that upstream multisig_redeem_script
  does not sort internally, so wallets MUST sort before calling.
  Positions the ordering rule as a KIP-introduced convention.

- Added Technical References section: concrete pointers to upstream
  PSKT integration points (Finalizer, ScriptBuilder,
  pay_to_script_hash_signature_script, PartialSigs BTreeMap ordering
  pitfall, Signature enum) and consensus validation reference.

- Measured bip32Derivations per-cosigner JSON cost (~139 bytes)
  replaces an earlier estimate in Appendix A.1.

- Acknowledgement to @biryukovmaxim for review feedback.

No normative scope changes beyond the sigOpCount rule.
@InKasWeRust
Copy link
Copy Markdown
Author

Pushed a follow-up addressing @biryukovmaxim's sigOpCount feedback
plus a source-verified audit pass over the rest of the file.
Commit message has the full change list. Short version: the rule
is now M ≤ sigOpCount ≤ N with references to get_sig_op_count and
op_check_multisig_schnorr_or_ecdsa; a couple of arithmetic and
table-labeling bugs fixed; Technical References section added with
concrete upstream integration points.

@InKasWeRust
Copy link
Copy Markdown
Author

Data point from a ceremony on mainnet today — the estimate in Appendix A.1 holds up in practice.
Ran a 2-of-3 P2SH-multisig with KasSigner v1.0.3, 1-in-2-out:
Unsigned PSKB: 2428 B
After sig 1: 2976 B (+548 B)
After sig 2: 3548 B (+572 B)
Per-partial-sig overhead: 548–572 B. Appendix A.1 estimate: ~570 B. Matches within a handful of bytes across both signers.
Final tx broadcast with sigOpCount = N (safe upper bound within the M ≤ sigOpCount ≤ N range): 594400ceb960e30faea889f85e604b9c6427045fd7372eae328f2cfe1ea0cb8f — confirmed, script ops: 3.
Thanks @biryukovmaxim for the original correction on the sigOpCount range, and @michaelsuttonil for confirming on X that exact-M becomes possible with upcoming Silverscript.

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