Bitcoin Governance — Schnorr Voting & P2WSH Multisig Pool

BIP-340 Schnorr vote proofs · native P2WSH 2-of-3 multisig · OP_CLTV timelocks · PSBT air-gap workflow

Not private. Bitcoin is a fully transparent ledger. The Pedersen commitment in the vote proof hides your choice from a passive observer of the JSON, but the blinding value is revealed to the tally and the on-chain footprint links each vote to a public key. This is authenticated voting, not anonymous voting. For anonymous voting you need a shielded pool (Zcash, Monero) or a Chaumian ecash layer.
Read first. Experimental prototype. Generates unsigned Bitcoin transaction templates (Bitcoin Core RPC commands) and cryptographic vote proofs. Holds no keys, connects to no network, broadcasts nothing. No external dependencies — secp256k1, BIP-340 Schnorr, bech32, and the multisig script builder are all implemented inline so this file works offline and inside strict CSP sandboxes.

1 · Voter Keypair

Each voter generates a secp256k1 keypair locally. The public key is x-only (BIP-340). The secret never leaves this page.

No key generated.

2 · Multisig Pool (P2WSH)

Enter the compressed public keys of the pool's cosigners and a threshold. The tool builds the witness script, computes the P2WSH address, and generates the funding commands. No key sharing required — this is real script-enforced multisig, not Shamir.

3 · Proposal

4 · Cast a Vote

A vote is a BIP-340 Schnorr signature over (proposalId ‖ choice ‖ nullifier), plus a Pedersen commitment to the choice. The nullifier is deterministic from the voter's public key and the proposal, so the tally can enforce one-vote-per-key without any registration step.

5 · Tally (off-chain)

Paste one vote-proof JSON per line, or a JSON array. The tally verifies each BIP-340 signature, recomputes the nullifier from the public key, rejects duplicates, and verifies the Pedersen commitment.

6 · Transaction Builder (PSBT)

Produces Bitcoin Core RPC commands for funding the pool, casting a vote (anti-spam payment), and spending via the multisig. These are templates — review against your node's documentation before running.

7 · Air-gapped PSBT Signing Workflow

Cold machine: generate the cosigner keys offline. Write the secret keys on paper. Never connect this machine to a network.
Online coordinator: collect the compressed public keys from each cosigner, build the witness script + P2WSH address in §2, and share the address with funders.
Funders: send BTC to the P2WSH address. Verify the address matches the expected witness script independently.
To spend: build an unsigned PSBT with createpsbt. Transfer the PSBT file to each cosigner over USB.
Each cosigner: run walletprocesspsbt on the cold machine to add their signature. Return the updated PSBT to the coordinator.
Coordinator: once K signatures are collected, run finalizepsbt and broadcast with sendrawtransaction.

Command reference

StepCommandWhere
Fundwalletcreatefundedpsbt '[]' '[{"<p2wsh_addr>":0.001}]' 0 '{"fee_rate":10}'Funder
Processwalletprocesspsbt "<psbt>"Funder
Finalizefinalizepsbt "<signed_psbt>"Funder
Broadcastsendrawtransaction "<final_hex>"Funder
Spend (K-of-N)walletprocesspsbt "<psbt>" on each cosignerCosigners
Reality check. Bitcoin's P2WSH multisig is script-enforced — this is strictly stronger than the Shamir workaround on chains without native multisig. But the witness script must be published to the funders before they send BTC: a P2WSH address is a hash of the script, and sending to the wrong script hash means the coins are unspendable forever. Distribute the address and the script together and have each funder independently verify sha256(script) → bech32.

8 · Local Audit Log

Everything you generate is logged locally in localStorage. Nothing leaves this browser. Export as JSON for independent verification.

Log empty.