Cryptonean/Quiet-Quorum

★ 0Forks 0JavaScriptGitHub ↗Compare

README

Quiet Quorum

Private ballots. Public certainty. Quiet Quorum provides anonymous, credential-gated DAO voting with publicly verifiable results on Midnight Preview.

Eligible members prove membership without revealing their identity, cast Yes / No / Abstain, and consume a proposal-specific nullifier that prevents double voting. Observers can verify proposal rules, aggregate tallies, and quorum outcomes without learning who voted or how any individual voted.

CI

Current status (Level 4 MVP)

This repository implements the Level 4 Core MVP:

  • Compact contract with membership + nullifier + Yes/No/Abstain + finalize/quorum
  • Browser dApp with Lace/1AM connect, deploy/join, admin flows, and private vote proving
  • Privacy model documented below and in the UI Privacy panel
  • CI workflow that typechecks, tests, and builds on every push
  • Workspace layout: contract/, frontend/, docs/, .github/

Still owned by the operator before submission packaging:

  • Demo video link

Repository layout

private-dao-voting-midnight/
├── contract/
│   ├── src/dao-voting.compact
│   ├── managed/{keys,zkir,contract}
│   └── test/
├── frontend/
│   ├── src/{browser-circuit,components,hooks,voting,wallet,providers}
│   └── public/{keys,zkir}
├── docs/
├── .github/workflows/ci.yml
└── README.md

Development

Requirements:

  • Node.js 22+
  • pnpm 10
  • Compact CLI (pragma language_version >= 0.23) for regenerating ZK artifacts
cp .env.example .env
pnpm install
pnpm test
pnpm typecheck
pnpm dev

App: http://localhost:5176

Regenerate Compact bindings and ZK assets after circuit changes:

pnpm build:zk

Production frontend build:

pnpm build

Demo walkthrough

  1. Connect Lace or 1AM on Midnight Preview.
  2. Deploy voting contract (admin).
  3. Register demo voter root.
  4. Create and open proposal.
  5. Select a demo voter credential and cast Yes / No / Abstain.
  6. Confirm the public tally updates.
  7. Attempt a second vote with the same credential → rejected (NULLIFIER_SPENT).
  8. Optionally close and finalize to publish Passed / Failed / QuorumFail.

Privacy model

Public ledger state

  • Contract address and administrator commitment
  • Accepted voter Merkle root
  • Proposal identifiers, content digests, open/close slots, quorum config
  • Aggregate Yes / No / Abstain counters
  • Proposal-specific spent nullifiers
  • Final status: Passed, Failed, QuorumFail, or Cancelled

Private witnesses

  • Voter secret and leaf salt
  • Merkle authentication path and leaf index bits
  • Ballot choice before it is applied to a public counter branch

What is disclosed, and to whom

Data Audience Notes
Tallies, nullifiers, proposal rules Everyone Required for public auditability
Which counter moved / when Everyone Inherent to live public counters
Voter identity ↔ ballot mapping Nobody Not present in public state
Merkle path / voter secret Prover only Never logged or submitted in cleartext

Wallet and network metadata remain outside the ZK privacy boundary.

Environment

VITE_NETWORK_ID=preview
# Leave unset for 1AM/ProofStation proving:
# VITE_PROOF_SERVER_URL=
# Local Docker proving with Lace:
# VITE_PROOF_SERVER_URL=http://localhost:6300
# VITE_ZK_CONFIG_BASE_URL=
# VITE_DEFAULT_CONTRACT=

Deployment artifacts

Artifact Value
Preview contract address 40ef8f3376c5f077867770a40101a75b3f71084cfffd18514538a993ad828d8d
CI .github/workflows/ci.yml
Product X profile @QuietQuorum
Demo video https://drive.google.com/file/d/15hAAR9ZoMevzH8thn772YUoG6Y_1F6jK/view?usp=sharing

Success narrative

A DAO member proves they are on the approved voter list without revealing who they are, casts a private Yes/No/Abstain, and is blocked from voting twice by a proposal-specific nullifier. Anyone can verify the public tally and quorum outcome on Midnight Preview.

Contributors

Cryptonean

Issues