Eligibility proofs
A vote is only valid if the prover is in the current eligible set for that election.
Not for profit · Open source (AGPL-3.0-or-later)
ZK Voting is a self-hostable voting and polling system. Zero-knowledge proofs let anyone check that only eligible people voted, each at most once, and that the published tally matches the accepted ballots. Nobody's choice is published.
# run your own node
cp .env.example .env
docker compose up -d --build
curl -fsS http://127.0.0.1:3000/health
Democratic processes still ask voters, candidates and courts to trust a small set of operators: who is on the roll, who was turned away, whether a ballot was counted, and whether the result matches the ballots. ZK Voting makes those claims checkable.
It has two tightly coupled parts: a Node application where voters, election officials and observers do their work, and Solidity smart contracts that register voters, open ballots, accept votes with zero-knowledge proofs and enforce disqualification on Ethereum.
Zero-knowledge proofs let the chain check facts about a voter without putting the ballot in the clear.
A person registers for a jurisdiction. Their Merkle leaf is an identity commitment, never their wallet address.
Officials commit the eligible set and the disqualification set for the election. Disqualifications are public, coded, on-chain state changes.
The ballot carries a proof that the voter is eligible and not disqualified. A one-time nullifier means a second ballot is rejected.
Public dashboards publish vote proofs once an hour, after the hour closes, so a person leaving a polling place can't be matched to a live tick.
After the poll closes, anyone can check that the published totals match the accepted ballots.
A vote is only valid if the prover is in the current eligible set for that election.
Officials can bar a registered person for coded, jurisdiction-defined reasons, and the circuits reject their vote.
Each nullifier is accepted once. Voters can change their mind privately on the form before they submit.
The selected option is never a plaintext field anyone can read from a transaction.
Yes/no, single choice, multiple choice, ranked choice (IRV), measures and articles.
Passkeys, Ethereum wallet, email, smart card or civic ID, with email MFA and a vote PIN at ballot submit.
A block explorer and results pages let observers follow registrations, disqualifications and the tally.
An offline auditor reconstructs an election from published artifacts without the node's private database.
WCAG 2.2 AA checks on the voter and admin pages, plus a documented bot API with OpenAPI and llms.txt.
A jurisdiction runs its own node with Docker Compose, Coolify, Dokploy or CapRover, optionally private behind a Tailscale sidecar. Every node serves its self-hosting guides at /docs.
Cheap, high-volume civic activity lands on the ZK Voting L2, a purpose-built civic sequencer and prover that settles to Ethereum. Final tallies can be mirrored on Ethereum mainnet.
Under active development. Unit tests use a mock verifier, the first proving path is in progress and the trusted-setup ceremony is not done yet. Don't use it for a binding election today.
See it running on the demo →ZK Voting is licensed AGPL-3.0-or-later. Nobody is meant to make money from it; voter data is not a product.