QUORUM
( QRM ) · Protocol Documentation

Confidential governance,
documented end to end.

QUORUM is confidential governance infrastructure for Solana organizations. Private inputs, public proof. This guide explains how each module works, what runs in your browser, what runs on the server, and what is settled on chain.

Introduction

Overview

QUORUM lets a DAO vote, propose, and manage a treasury without leaking the information that makes governance manipulable. Ballots are encrypted in your browser, eligibility is proven with zero knowledge, the running tally stays hidden until close, and the final result is verifiable by anyone. Proposals stay sealed until execution, so there is no front running window. Treasury records stay confidential, with solvency proven by range proof and selective disclosure to auditors.

The protocol is organized into modules, each backed by real cryptography rather than a placeholder:

ModuleWhat it provides
VotingSealed ballots, ZK eligibility, threshold tally, verifiable correctness.
ProposalsHidden until execution, commit reveal, on pass or timelock.
TreasuryConfidential balances, ZK solvency proofs, auditor disclosure.
MembersEligibility snapshot and private delegation of voting weight.
StakingReal Token 2022 QRM staking that settles on chain on devnet.
ProofsA public surface where anyone verifies the protocol was honest.
How it fits together

Architecture

The frontend is a TanStack Start React application. The governance API is a set of typed server functions, not a separate service, each validated with zod. Persistent state lives in Supabase Postgres. Cryptographic settlement happens on Solana devnet through a single consolidated program.

Browser (React, client side crypto + in browser ZK proving)
   |  Sign In With Solana, sealed ballot, proof generation
   v
Server functions (createServerFn, zod validated, session JWT)
   |
   +--> Supabase Postgres   commitments, nullifiers, proofs, encrypted records
   +--> Solana devnet        program "quorum_anchor": eligibility root, tally hash,
                             on chain Groth16 verifier, QRM Token 2022 staking

A deliberate design choice keeps cost near zero: the chain stores roots and hashes, never per ballot accounts. All ballots and commitments live in Postgres, and a single Merkle root per vote plus the final result hash are anchored on chain.

Source
Server functions live in src/fn. Client crypto lives in src/lib/crypto. Solana helpers live in src/lib/solana. The on chain program is under onchain/.
Sign In With Solana

Wallet Authentication

Authentication proves wallet ownership without a password. The client requests a nonce, the wallet signs a canonical message, and the server verifies the signature with tweetnacl and issues a session cookie. QUORUM never asks for a seed phrase and never takes custody.

// client
const { nonce, message } = await requestNonce({ data: { wallet } });
const signature = await wallet.signMessage(message);
await verifySignature({ data: { wallet, nonce, signature } });
// server sets an HttpOnly session cookie; getMe() restores the session

Nonces are single use and expire, which prevents replay. Ballots are never linked to the session: the session gates spam, but the stored ballot is anonymous by construction.

Module I

Sealed Ballot Voting

A voter proves eligibility with a zero knowledge proof, encrypts the choice in the browser, and submits a sealed ballot. No one, including QUORUM, can read the choice until the tally runs. The running count of ballots is public, the choices are not.

1. Encrypt the choice. The vote is one hot encoded over the option set and encrypted with exponential ElGamal over Ristretto255. Because the scheme is additively homomorphic, encrypted ballots can be summed and only the totals decrypted.

2. Prove eligibility. The browser generates a Groth16 proof of membership in the eligibility Merkle tree plus a unique nullifier, without revealing identity or balance. The nullifier prevents double voting.

3. Tally with a threshold key. Decryption uses a 3 of 5 threshold key produced by a Pedersen DKG, so no single party holds the secret. The server sums the ciphertexts and recovers only the per option totals.

4. Prove the tally is honest. Each partial decryption carries a Chaum Pedersen DLEQ proof. Anyone can verify that the announced totals are the honest decryption of the sealed ballots, with no trust in the server.

Receipt free
The protocol re randomizes ciphertexts so a voter cannot prove to a briber what they submitted. The participation receipt proves that you voted, never how you voted.
Server functionPurpose
castBallotVerify the ZK proof against the live root, store the nullifier and ciphertext.
runTallySum ciphertexts, threshold decrypt, write totals plus a DLEQ transcript.
verifyTallyRe verify the DLEQ transcript so totals are provably correct.
Module II

Hidden Proposals

Proposals are submitted encrypted. Only their existence, author eligibility, and voting rules are public. The content is revealed at execution or after a timelock, which removes the front running window entirely.

The body is encrypted in the browser with AES GCM and bound by a SHA 256 commitment. Only the ciphertext and the commitment reach the server. The author keeps the plaintext and reveals later, at which point the server checks the plaintext against the commitment.

const { encPayload, commitHash } = await sealProposal(text); // client side
await submitProposal({ data: { encPayload, commitHash, reveal: "on_pass" } });
// later, only the author can reveal:
await revealProposal({ data: { proposalId, plaintext } }); // commit is verified

Reveal policy is either on_pass, released once the vote passes, or timelock, released after a set window. The server rejects a reveal whose plaintext does not match the commitment.

Module III

Confidential Treasury

Treasury holdings stay confidential while remaining accountable. Solvency is proven with a zero knowledge range proof, and individual records can be disclosed to a chosen auditor without exposing the rest of the treasury.

Solvency proofs. The operator enters the real reserve balance and a public threshold. The browser generates a Groth16 range proof that reserves are at least the threshold, and only the proof and a commitment leave. The balance stays hidden. The proof is also verified on chain by the program.

Selective disclosure. A single record is encrypted to one auditor public key with ECIES over Ristretto255. Only the holder of that auditor secret can read it.

Server functionPurpose
recordSolvencyProofStore a ZK range proof of reserves, optionally verified on chain.
issueDisclosureEncrypt one record to an auditor public key (ECIES).
addAuditor, revokeAuditorManage the auditor keys authorized for disclosure.
Module IV

Members and Delegation

Eligibility is committed as a zero knowledge Merkle snapshot. Members can vote, or privately delegate their voting weight to another eligible member, without exposing balances or linking identities. Delegated weight is aggregated privately at tally time.

await setDelegation({ data: { delegate } });   // delegate must be an eligible member
await clearDelegation();                        // vote your own weight again

The server enforces two rules: you cannot delegate to yourself, and the target must already be an eligible member. Nullifiers continue to prevent double voting across delegation.

Network

QRM Staking

QRM is a Token 2022 mint on devnet. Staking is a real on chain transfer from your wallet to the protocol vault, confirmed by the server before the ledger is credited. Tally nodes stake QRM to run the confidential counting network and earn per vote fees. Misbehavior, such as leaking a ballot, censoring, or a false tally, is slashed.

await qrmFaucet();                              // devnet drip of QRM
const sig = await wallet.signAndSendTransaction(stakeTx); // Token 2022 transfer to the vault
await confirmStake({ data: { signature: sig } });         // server confirms on devnet, credits
await unstakeQrm({ data: { amount } });                   // vault returns QRM, debits the ledger
Browser note
The Solana SDK expects the global Buffer, which browsers do not provide by default. QUORUM polyfills it before the SDK runs, so the wallet transfer builds correctly.
Public trust surface

Proofs and Verification

The Proofs surface publishes every closed vote, tally attestation, treasury solvency proof, and tally node record with one click verification. Verification requires no wallet and no trust in QUORUM, which is the point: an outsider can confirm the protocol was honest.

Two levels of verification exist. A record level check confirms a verified proof exists for a reference. A cryptographic check re runs the DLEQ math on the tally transcript itself.

Settlement

On Chain Anchoring

A single Anchor program, quorum_anchor, is deployed to Solana devnet. It anchors the eligibility root and the tally result hash, and it embeds a real BN254 Groth16 verifier built on the alt_bn128 syscalls, which verifies solvency proofs on chain. The footprint is intentionally tiny: roots and hashes, never per ballot accounts, so rent stays minimal and vote accounts are closable.

Anchored itemMeaning
eligibility_rootThe Merkle root of the eligibility snapshot for a vote.
tally hashA commitment to the final result and the correctness transcript.
solvency proofA treasury range proof verified on chain by the program.
For integrators

Developer SDK

The @quorum/sdk package exposes the same client side primitives QUORUM uses in production, so anything you seal is compatible with the live tally. Everything runs client side: no server, no secret keys, no trust. You seal with public inputs, and you verify with only the published transcript.

npm add @quorum/sdk

import { sealBallot, verifyTally } from "@quorum/sdk";

// Seal a vote client side. Your choice never leaves the browser in the clear.
const ballot = await sealBallot(tallyPubkey, "yes", ["yes", "no", "abstain"]);

// Verify any published tally trustlessly. No server, no keys.
const { verified, totals } = verifyTally(transcript);
ExportPurpose
sealBallotEncrypt a one hot vote to the tally key, returns ciphertext and commitment.
verifyTallyTrustlessly verify announced totals with DLEQ proofs.
sealProposal, verifyProposalRevealCommit a hidden proposal and check a later reveal.
generateAuditorKey, encryptToAuditor, decryptAsAuditorECIES selective disclosure.

The current release covers sealing and verification. Driving a deployment, such as creating votes or submitting ballots, uses authenticated server functions and is paired with your own transport.

Guarantees

Security Model

QUORUM is designed to fail closed. Each guarantee is enforced by cryptography, not by policy.

PropertyHow it holds
Ballot privacyChoices are encrypted client side to a threshold key; no single party can decrypt.
Receipt freenessCiphertexts are re randomized, so a voter cannot prove a choice to a briber.
No double votingA unique nullifier per voter per vote, enforced in the database and at tally.
Tally correctnessChaum Pedersen DLEQ proofs make the totals verifiable by anyone.
No live tallyThe running result is hidden until close, which defeats whale following.
Solvency without exposureA range proof proves reserves meet a threshold while the balance stays hidden.
Fails closedAn invalid proof is rejected; no valid proof means no execution.
Status
QUORUM runs on Solana devnet. A mainnet promotion is gated behind third party audits. Review audits before relying on the protocol with real value.
Open the Dashboard