Home/Academy/Governance/CoinShuffle
Blockchain & Cryptography

CoinShuffle: Secret Ballots on a Public Blockchain

20 min read March 28, 2026 The Marscoin Foundation Technical Deep Dive
The Martian Congressional Chamber

Here is a paradox at the heart of blockchain democracy: every transaction on a public ledger is visible to everyone, permanently. And yet democracy requires that your vote be secret — that nobody, not your employer, not your neighbor, not the proposer of the legislation, can ever know how you voted.

On Earth, this problem is solved with physical voting booths, paper ballots, and sealed envelopes. On a public blockchain where every transfer is traceable and every address is linkable, the problem seems impossible. But it is not. The Martian Republic solves it with CoinShuffle — a cryptographic mixing protocol that severs the link between a citizen's known identity and their anonymous ballot, using nothing more than public-key encryption and clever ordering.

This article covers everything: why ballot secrecy is structurally non-negotiable, how CoinShuffle works at the protocol level, how the Martian Republic implements it in production, what the security guarantees actually are, and where the system goes from here. Not the marketing version. The actual protocol, as tested and proven on March 28, 2026.

Part I: Why Ballot Secrecy Is Non-Negotiable

Ballot secrecy is not a nice-to-have feature. It is a structural requirement for democratic governance. Without it, three attack vectors become viable — and every single one has been demonstrated at scale in real-world blockchain governance.

Vote Buying: The $46 Million Proof

If votes are public, a briber can verify that the bribe was honored. This turns democracy into an auction. The Curve Wars on Ethereum proved exactly how quickly this happens: the Votium marketplace processed $46 million in openly paid bribes, with protocols paying $0.37–$0.87 per vote to direct CRV emissions toward their liquidity pools.

Votium was not a black market. It was a publicly tracked, dashboard-monitored, economically rational response to transparent voting. Anyone could visit the Votium dashboard, see the price per vote, calculate the expected return, and decide whether to sell their governance power. When votes are visible, bribery is not corruption — it is commerce.

The structural insight: Vote buying does not require malicious intent. It requires only two conditions: (1) votes are verifiable by third parties, and (2) economic incentives exist. On any blockchain with transparent governance and meaningful treasury flows, both conditions are guaranteed. The only structural defense is to remove condition (1). Make votes unverifiable. Make them secret.

Coercion in Small Communities

If votes are public, a powerful actor can punish those who vote against their interests. In a DAO of 50,000 anonymous token holders spread across the globe, this matters less. In a Mars colony of 200 people who eat together, work together, and depend on each other for survival, it matters enormously.

Consider a scenario: the colony's lead life-support engineer proposes a budget allocation that several citizens believe is wasteful. If votes are public, those citizens must weigh their honest assessment against the social cost of openly opposing the person who keeps their atmosphere breathable. Secret ballots break this dynamic entirely. You cannot retaliate against a vote you cannot see. You cannot punish a choice you cannot verify.

Strategic Voting Distortion

When citizens can see how others have voted in real time, they change their behavior. They bandwagon toward the leading option. They abstain when the outcome seems decided. They vote strategically rather than sincerely. Decades of political science research confirm this: transparent real-time tallies distort expressed preferences away from genuine preferences. Secret ballots force citizens to vote their actual convictions, producing results that more accurately reflect the community's true will.

The core principle: Participation is public. Choice is private. Permanently.

The blockchain must prove that Citizen X participated in a vote — that is auditable democracy. But it must never be possible to determine how Citizen X voted. Not now. Not in two years. Not ever. Even if their seed phrase is later compromised.

You Cannot Sell What You Cannot Prove

This is the sentence that summarizes everything. If no mechanism exists to prove how you voted — not to a briber, not to a coercer, not to an employer, not even to yourself after the vote is cast — then vote buying collapses as a strategy. Coercion becomes pointless. Social pressure loses its teeth. The voter's only rational action is to vote their genuine preference, because no other action can be rewarded or punished.

Paper ballots understood this principle centuries ago. CoinShuffle brings it to the blockchain.

Part II: How CoinShuffle Works

CoinShuffle was designed by Tim Ruffing, Pedro Moreno-Sanchez, and Aniket Kate, first published in 2014 at the Privacy Enhancing Technologies Symposium. It extends the CoinJoin concept — combining multiple transactions to obscure ownership — with a decentralized cryptographic shuffle that requires no trusted coordinator. The only cryptographic primitive it adds beyond the blockchain's native signatures is standard public-key encryption.

Let us walk through it with a concrete example: three Martian citizens — Astra, Lennart, and Valles — participating in a shuffle to acquire anonymous ballots for a proposal vote.

The Polling Station Analogy

Before we get into the cryptography, consider how a physical polling station works. You walk in. A poll worker checks your ID and confirms you are a registered voter. You receive a blank ballot — identical to every other ballot, with no identifying marks. You walk behind a curtain, mark your choice, and deposit the ballot in a sealed box. The poll worker can confirm you voted. They cannot see what you marked.

CoinShuffle is the digital equivalent of that curtain and that unmarked ballot. The "checking in" part is public (your civic address appears in the ballot funding transaction). The ballot itself is anonymous (your ballot address cannot be traced back to you). The mechanism that severs the link between the two is the shuffle.

Phase 1: Request a Ballot

01

Key Generation & Registration

Each citizen generates two things: a temporary encryption keypair (used only during the shuffle, then destroyed), and a brand-new Marscoin address that will serve as their anonymous ballot. Nobody else knows this address yet.

Astra generates: encryption key Aenc + ballot address Aballot
Lennart generates: encryption key Lenc + ballot address Lballot
Valles generates: encryption key Venc + ballot address Vballot

Each citizen connects to the ballot server via WebSocket and shares their encryption public key. The server assigns a random shuffle order: Astra (1st), Lennart (2nd), Valles (3rd).

The shuffle order matters because the protocol operates like a chain: each participant receives a growing, encrypted list, peels off one layer, shuffles, and passes it forward. The ordering is random, and every participant except the last encrypts their ballot address in layers.

Phase 2: Layered Encryption (The Nesting Dolls)

02

Wrapping the Ballot Addresses

Each citizen encrypts their ballot address in layers — like sealing a letter inside nested envelopes. The key insight: you encrypt for every participant who comes after you in the shuffle order, so that each person along the chain can remove exactly one layer.

Astra (1st) encrypts her ballot address with Lennart's key, then with Valles's key:
  Vallesenc( Lennartenc( Aballot ) ) — two layers

Lennart (2nd) encrypts his ballot address with Valles's key:
  Vallesenc( Lballot ) — one layer

Valles (3rd) does not encrypt — he is last in the chain, so by the time the list reaches him, all layers will be peeled off.
  Vballot — zero layers

Think of each ballot address as a letter sealed inside Russian nesting dolls. Astra's address has two dolls around it. Lennart's has one. Valles's has none. Each participant in the chain can only open one doll — the one locked with their own key.

Phase 3: The Shuffle (Decrypt, Randomize, Forward)

03

Pass the List, Peel a Layer, Shuffle the Order

Starting from Astra, each citizen receives the list of encrypted ballot addresses, decrypts one layer using their private key, randomly reorders the entire list, and passes it to the next person. At each step, one layer of encryption is removed and the order is randomized.

Round 1 — Astra:
Receives all encrypted addresses. Adds her own. Shuffles the order. Passes to Lennart.
Lennart now sees 3 items, each still wrapped in at least one layer — and in random order.

Round 2 — Lennart:
Decrypts his layer from each item. Adds his own address (encrypted for Valles only). Shuffles again. Passes to Valles.
Valles now sees 3 items, each wrapped in exactly one layer — in doubly-randomized order.

Round 3 — Valles:
Decrypts the final layer from each item. Adds his own address (plaintext). Shuffles one last time.

Result: Three plaintext ballot addresses in random order:
  [ m7K...2qP,  m3R...wN5,  m9A...pF8 ]

Nobody knows which address belongs to whom — not even the participants.

Why No Single Participant Can Trace the Mapping

This is the critical point. After three rounds of decryption and shuffling:

Each participant knows their own ballot address but cannot determine which of the other addresses belongs to which citizen. Even if Astra and Valles colluded, they could not determine Lennart's ballot address with certainty — because Lennart's shuffle in round 2 broke the mapping that Astra established, and Valles never had access to the pre-shuffle state.

The mathematical guarantee: As long as at least one participant in the shuffle chain is honest and applies a genuinely random permutation, the final mapping between citizens and ballot addresses is information-theoretically hidden from any coalition of the remaining participants. This holds even if the coalition includes the server that coordinates the shuffle, because the server only sees encrypted data.

Phase 4: Ballot Funding (The Joint Transaction)

04

Multi-Party Signing

The last participant in the chain constructs a single transaction that spends one UTXO from each citizen's civic wallet and sends exactly 0.1 MARS to each anonymous ballot address. All three citizens sign the transaction collaboratively. Nobody can steal funds because each citizen verifies that their ballot address is present before signing.

Inputs: 1 UTXO from Astra's civic address + 1 from Lennart's + 1 from Valles's
Outputs: 0.1 MARS to m7K...2qP + 0.1 MARS to m3R...wN5 + 0.1 MARS to m9A...pF8

Each citizen signs only their own input. The transaction is valid only when all three signatures are present.
The combined, fully-signed transaction is broadcast to the Marscoin network.

This is a CoinJoin transaction. An observer looking at the blockchain sees three civic addresses funding three anonymous addresses. They know who participated. They cannot determine who owns which ballot.

Phase 5: Cast Your Vote

05

Anonymous Vote on the Public Blockchain

Once the ballot funding transaction confirms on the blockchain, each citizen can vote. They build a new transaction from their anonymous ballot address containing an OP_RETURN with their vote, sign it with the ballot address key, and broadcast it.

m7K...2qP sends: OP_RETURN PRY_QmXa8...  → YES on Proposal #42
m3R...wN5 sends: OP_RETURN PRN_QmXa8...  → NO on Proposal #42
m9A...pF8 sends: OP_RETURN PRA_QmXa8...  → ABSTAIN on Proposal #42

Anyone can see these votes. Nobody can determine which citizen cast which vote.

The result: 3 citizens participated (auditable), 1 YES, 1 NO, 1 ABSTAIN were cast (auditable), and the mapping between citizens and votes is permanently destroyed.

Part III: The Martian Republic's Implementation

The protocol described above is the theory. What follows is how it actually runs in production — the infrastructure stack, the 11-step protocol flow, and the first successful smoke test.

The Infrastructure Stack

When a citizen clicks "Request Ballot" on a proposal page, their browser enters a pipeline that spans six components:

Ballot Infrastructure Stack
Browser ballot.blade.php — client-side crypto, WebSocket, voting UI
wss://martianrepublic.org/wss/ballot
CDN Cloudflare — TLS termination, DDoS protection
HTTPS
Proxy Apache mod_proxy_wstunnel — WebSocket reverse proxy, /wss/ballot → :3679
ws://127.0.0.1:3679
Server Ballot Server (Python + websockets) — coordinates shuffle rounds, manages rooms
clients sign PSBTs locally
API Pebas (Node.js + Express) — UTXO queries, transaction broadcast
JSON-RPC
Chain marscoind — Marscoin blockchain node

Key architectural property: The ballot server coordinates the shuffle but cannot determine the mapping. It only sees encrypted data during the shuffle rounds. It never has access to private keys. The cryptographic operations happen entirely in the citizen's browser. The server is a telephone switchboard, not a trusted authority.

The 11-Step Protocol Flow

Here is the complete protocol as implemented, step by step. Each step maps to actual code in the production system.

01

Citizen Clicks "Request Ballot"

The browser navigates to /congress/ballot/{proposalId} and generates: a random ballot seed from random_bytes(16), a ballot Marscoin address derived from that seed, an RSA ephemeral keypair for onion encryption, and identifies UTXO inputs from the citizen's civic wallet.

02

WebSocket Connection

The client opens a secure WebSocket to wss://martianrepublic.org/wss/ballot and sends its civic address plus the proposal identifier. The server registers the client in a room keyed by proposal hash and responds with JOINED_ACK.

03

Key Exchange

The client sends its RSA public key. The server stores it and maps it to the client's Marscoin civic address. When 3 or more participants have submitted keys, the shuffle can begin.

04

Shuffle Initiation

The server creates a random shuffle order and sends INITIATE_SHUFFLE to all clients with the order and peer list. Each client determines its position and encrypts its ballot address in layers — for all peers after it in the order.

05

Decryption Rounds

Peer 0 receives the initial encrypted data, decrypts one layer, adds their own target, applies a Fisher-Yates shuffle to randomize the order, and forwards to peer 1. Each subsequent peer repeats: decrypt, add, shuffle, forward. The last peer decrypts the final layer — all ballot addresses are now in plaintext but randomly ordered.

06

PSBT Construction

The last peer constructs a Partially Signed Bitcoin Transaction (PSBT) with one input from each voter's civic wallet and one 0.1 MARS output to each anonymous ballot address, plus change outputs.

07

Multi-Party Signing

The server sends the PSBT to all clients. Each client signs their own input using their civic wallet key and returns the signed PSBT.

08

Combine & Broadcast

Each client receives all signed PSBTs, combines the signatures, finalizes all inputs, extracts the raw transaction, and broadcasts it to the Marscoin network via the Pebas API.

09

Ballot Registration on Blockchain

The ballot funding transaction is now on-chain. Each anonymous ballot address receives 0.1 MARS. The client polls for confirmation.

10

Vote Casting

When the ballot transaction confirms, the page transitions to show YES / NO / ABSTAIN buttons. The citizen clicks their choice. The client builds a new transaction from the anonymous ballot address with an OP_RETURN encoding the vote, signs it with the ballot key, and broadcasts it.

11

Vote Confirmed

The vote is on-chain: anonymous, auditable, immutable. The ballot key exists only in browser memory and will be destroyed when the tab closes.

The First Smoke Test: March 28, 2026

On March 28, 2026, the Martian Republic completed its first successful 3-voter CoinShuffle ballot through production infrastructure. Three test citizens — operating from the same server but through independent browser sessions — joined a shuffle room, completed the layered encryption, executed the decryption rounds, constructed and co-signed the ballot funding transaction, and broadcast it to the live Marscoin blockchain.

The ballot funding transaction confirmed on-chain. Three anonymous ballot addresses were funded with 0.1 MARS each. The test citizens then cast their votes — each from their untraceable ballot address.

Blockchain explorer showing the ballot funding transaction: three civic addresses on the left funding three anonymous ballot addresses on the right
The blockchain explorer view of the first successful CoinShuffle ballot transaction. Left side: the three civic addresses (voters' known identities). Right side: the three anonymous ballot addresses (unlinkable). The 0.1 MARS outputs fund each ballot. Anyone can verify participation; nobody can trace the mapping.

Getting here was not clean. The smoke test surfaced seven bugs that had to be fixed in real time:

# Bug Root Cause Fix
1 Handler missing argument websockets v14 removed path parameter Updated handler signature
2 WebSocket connections fail Cloudflare doesn't forward port 3678 Apache mod_proxy_wstunnel at /wss/ballot
3 Shuffle sends to wrong peer All clients = 127.0.0.1 behind proxy Match peers by Marscoin address, not IP
4 broadcastTxHash is not a function const temporal dead zone Moved function definition before first use
5 Shuffle restarts infinitely CoinShuffleServer accumulates state Clean restart between rounds
6 Client hangs after broadcast Pebas catch block never sends HTTP response Added error response to catch block
7 Tx rejected: fee exceeds maximum Electrum maxfeerate too low CLI fallback with maxfeerate=0

Every one of these bugs was a gap between theory and production. The CoinShuffle paper says nothing about WebSocket proxy configurations, Python library version changes, or Electrum fee policies. Those are the details that separate a whitepaper from a working system. As of this writing, all seven are resolved and the protocol runs end-to-end through production infrastructure.

Part IV: Security Properties

CoinShuffle's security is not a single claim. It is a set of distinct properties, each addressing a specific attack vector. Understanding them separately is essential for evaluating the system honestly.

Random Ballot Keys: The Most Important Design Decision

The Martian Republic generates ballot keys from random_bytes(16) — truly random entropy that exists only in browser memory during the voting session. This is not a limitation. It is the most critical security property in the entire system.

An alternative design would derive ballot keys deterministically from the citizen's mnemonic seed phrase — for example, at the HD path m/999999'/107'/{proposalId}'. This would be convenient: the citizen could recover their ballot key at any time by re-deriving it from their mnemonic. It would also be catastrophically insecure.

If your mnemonic leaks two years later, your entire vote history stays secret.

With random ballot keys, a compromised seed phrase reveals nothing about past votes. The ballot keys evaporated when the browser tab closed. With deterministic derivation, anyone who obtains your mnemonic — through theft, hardware failure, seed migration, or social engineering — could re-derive every ballot address you ever used, find your vote transactions on the public blockchain, and reconstruct your complete voting history retroactively.

Three specific attack vectors are eliminated by random keys:

  1. Retroactive de-anonymization. Mnemonics leak. Hardware gets recycled. Seed phrases written on paper get photographed. With deterministic derivation, any future compromise of the mnemonic exposes all past votes. With random keys, the mnemonic is irrelevant to voting history.
  2. Coercion by proof. A coercer could demand that a citizen derive their ballot key in front of them to prove their vote. With random keys, the citizen genuinely cannot comply — the key no longer exists. This is not a UX bug. It is the fundamental property that makes coercion impossible.
  3. Receipt-freeness. A vote buyer could demand cryptographic proof of how a citizen voted. With deterministic keys, the citizen could produce this proof at any time. With random keys, no such proof can ever exist. You cannot sell what you cannot prove.

What the Blockchain Reveals (and What It Cannot)

After a CoinShuffle vote, the blockchain contains two categories of information:

Public (Auditable by Anyone)

Citizen addresses X, Y, Z participated in Proposal #42. Three anonymous ballots were issued (0.1 MARS each). Three votes were cast: 2 YES, 1 NO. Total participation: 3 out of N citizens.

Private (Permanently Unknowable)

Which citizen voted which way. Which ballot address belongs to which citizen. How any specific citizen voted on any specific proposal. This information does not exist anywhere — not on the server, not on the blockchain, not in the citizen's wallet.

Comparison: How the Martian Republic Stacks Up

The following table compares the Martian Republic's CoinShuffle implementation against the most significant governance systems in the blockchain ecosystem, plus traditional paper ballots.

System Vote Privacy Coercion Resistance Post-Compromise Privacy Trusted Party
Martian Republic (CoinShuffle) Full — shuffled addresses Full — random keys, unprovable Full — keys evaporate None
Compound / Uniswap None — votes are public None N/A None
MACI (zk-SNARKs) Full — encrypted votes Partial — coordinator can decrypt Depends on implementation Coordinator required
Snapshot None — votes are public None N/A None (off-chain)
Paper Ballot Full — physical isolation Partial — can photograph Full — ballot is anonymous Poll workers

The Martian Republic's implementation achieves the strongest combination of privacy properties of any blockchain voting system currently in production. Compound, Uniswap, and Snapshot have no vote privacy at all — every vote is a public transaction. MACI achieves strong privacy but requires a trusted coordinator whose compromise would expose all votes. Paper ballots are the gold standard for physical elections but cannot provide the auditability of on-chain records.

The key differentiator is post-compromise privacy. If a MACI coordinator's key is later obtained by an adversary, all votes in every election that coordinator processed can be decrypted retroactively. If a Martian citizen's mnemonic is compromised, their voting history remains permanently secret because the ballot keys were random and transient.

The Trust Model

CoinShuffle's trust model is minimal and explicit:

The Blame Protocol

What happens if a participant deviates from the protocol? If Lennart refuses to forward the list, or Astra inserts extra addresses, or Valles decrypts incorrectly?

CoinShuffle includes a blame phase. At every step, each participant verifies that the protocol is proceeding correctly — that their own ballot address is present in the final output, that no addresses were added or removed, that decryption produced valid results. If any check fails, the honest participant broadcasts a signed complaint. The cryptographic audit trail created by the layered encryption allows identification of the misbehaving participant, who is then excluded. The shuffle restarts with only the honest participants.

A critical safety property: CoinShuffle does not attempt to protect secrecy in failed runs. If a shuffle fails and enters blame, participants may reveal decryption keys and transcripts to identify the disruptor. This is acceptable only because all ballot addresses from a failed run are discarded and never reused. Fresh addresses are generated for the restart. The security argument depends entirely on this freshness discipline.

Part V: What Comes Next

The first successful shuffle is a proof of concept. Turning it into a production-grade voting system requires solving several engineering challenges that are now at the top of the roadmap.

Scheduled Polling Windows

CoinShuffle requires all participants to be online simultaneously. The current implementation relies on citizens manually joining the ballot page at the same time. For a global community spanning multiple time zones, this is impractical.

The solution is scheduled shuffle windows: announced times when the ballot server opens rooms for specific proposals. Citizens know in advance when to show up, and the system can run multiple windows throughout the voting period to accommodate different schedules. A citizen in Singapore and a citizen in Reykjavik do not need to be in the same shuffle — they just need to each be in a shuffle.

Mobile Background Shuffle

The companion wallet app, which every citizen uses for identity verification and transactions, can participate in shuffle rounds automatically via background services. When a voting period opens, the app joins the next available shuffle without manual coordination — solving the online presence problem through push notifications and background WebSocket connections. The citizen gets notified when their ballot is ready; they vote at their convenience.

sessionStorage for Key Resilience

Currently, the ballot key exists only in JavaScript memory. If the citizen accidentally refreshes the page or navigates away before casting their vote, the key is lost and they must re-enter a new shuffle. This is a real UX problem.

The fix is sessionStorage — a browser API that preserves data across page refreshes within the same tab but automatically clears when the tab closes. The ballot key would survive accidental refreshes while still being destroyed when the voting session ends. This preserves the security property (keys are transient) while eliminating the most common failure mode.

What NOT to do: Never derive ballot keys from the citizen's mnemonic. Never store ballot keys on the server. Never transmit ballot keys over the network. Never persist ballot keys in localStorage or any medium that survives a browser session. The transience of the ballot key is the security property that makes the entire system work.

One Citizen, One Ballot Enforcement

The current protocol ensures that each shuffle participant receives exactly one ballot address. But a citizen could theoretically join multiple shuffle rounds for the same proposal. Enforcing "one citizen, one ballot" at the server level — by tracking which civic addresses have already received ballots for a given proposal — prevents double-voting while maintaining ballot secrecy. The server knows that Astra received a ballot. It does not know which ballot.

Larger Anonymity Sets

The first smoke test used 3 participants — the cryptographic minimum. The original CoinShuffle paper demonstrates feasibility with up to 50 participants, completing in approximately 40 seconds on a LAN and under 3 minutes over the internet. CoinShuffle++ (an optimized variant using DiceMix, deployed in production on the Decred blockchain) brings that down to 8 seconds for 50 participants. As the Martian Republic's citizenship grows, larger shuffle batches will dramatically strengthen the anonymity guarantee — from 1-in-3 to 1-in-50.

Mars-Local Shuffle Server

Radio signals between Mars and Earth take 4 to 24 minutes one way, depending on orbital position. A shuffle protocol that requires multiple round-trips between participants would be agonizingly slow across interplanetary distances. When the first colonists arrive on Mars, a locally hosted shuffle server with Mars-local participants will be essential. The shuffle happens at light speed within the colony; only the final ballot funding transaction needs to propagate to the broader Marscoin network.

The Foundation

On Earth, ballot secrecy was enforced by cardboard booths and human volunteers watching polling stations. On Mars, it is enforced by mathematics. The mechanism is different. The principle — that your vote belongs to you alone — is exactly the same.

CoinShuffle is not the most theoretically elegant solution. zk-SNARKs are more powerful. MACI is more flexible. But CoinShuffle runs on a standard UTXO blockchain with no smart contracts, no trusted coordinator, no exotic cryptographic infrastructure. It uses only public-key encryption — the same primitive that secures every HTTPS connection on the internet. For a civilization that may one day operate with limited computational resources, 20 light-minutes from the nearest software update, that simplicity is not a limitation. It is a survival trait.

Democracy does not work if votes can be bought. Votes can always be bought when they are public. CoinShuffle makes them private. That is not a feature. It is the foundation.

The first successful shuffle ran on March 28, 2026. Three citizens, three anonymous ballots, one transaction on the Marscoin blockchain. A small test by any measure. But it is the first time a public blockchain has been used for a secret ballot that requires no trusted third party, produces no receipt that could be used for coercion, and leaves no trace that could ever be used for retroactive de-anonymization.

The curtain is closed. The ballot is cast. The math is sound.

Continue Learning

How Mars Governs Itself: The Complete Guide Dynamic Quorum: Why Fixed Thresholds Kill DAOs The History of Blockchain Governance Back to The Academy