Skip to content

Esimuda/veilvote

Repository files navigation

Veil Vote — Privacy-Preserving DAO Voting (Hackathon Readme)

One-liner: Veil Vote is a minimal, audit-friendly commit–reveal voting system built on Solana using Anchor, designed to give DAOs privacy-preserving voting primitives that are easy to run and extend.


Problem statement

Traditional on-chain DAO voting exposes voter choices as soon as votes are cast or tallied. That creates risks:

  • Voter coercion and vote-buying when choices can be immediately verified.
  • Information cascades and herding because early tallies influence later voters.
  • Privacy loss for members who prefer anonymity.

There is a clear need for simple voting primitives that keep vote choices confidential until an intended reveal phase.


Solution overview

Veil Vote implements a commit–reveal scheme on Solana (Anchor):

  • Commit phase: Voters submit a cryptographic commitment (SHA-256 hash of choice || secret). The on-chain program stores only the hash and the voter's commitment record.
  • Reveal phase: After the voting deadline, voters publish their cleartext choice and secret. The program verifies the hash and tallies votes.

This approach guarantees that votes are:

  • Hidden during the commit phase (no plaintext vote on-chain).
  • Binding (voters cannot change their vote without breaking the hash match).

Veil Vote is intentionally minimal so it can be inspected and audited within a hackathon timeframe while remaining a solid foundation for later enhancements.


How commit–reveal preserves privacy

  • Commitment: Voter computes commit = SHA256(choice || secret) locally and sends commit on-chain. The secret never leaves the voter's client until reveal time (and can be stored client-side securely).
  • Hiding: Because SHA-256 is one-way, the commitment does not reveal choice or secret.
  • Binding: On reveal, the program recomputes SHA256(choice || secret) and compares it to the stored commit. A mismatch fails the reveal.

Security properties:

  • Confidentiality (during commit): The choice cannot be recovered from the hash alone.
  • Integrity: A revealed choice is verifiably the same choice that produced the commitment.
  • Non-repudiation: The commitment ties a signer to a single revealed vote (double-vote protected by PDAs).

Limitations are provided below; these are deliberate trade-offs for hackathon speed and auditability.


Architecture (ASCII diagram)

Client (browser) ├─ generate secret (32 bytes) ├─ compute commit = SHA256(choice || secret) ├─ store secret locally (localStorage by default) └─ submit commit to Solana program

Solana Program (Anchor) ├─ create_proposal (proposal metadata + deadline) ├─ commit_vote (store commit hash, voter PDA) └─ reveal_vote (verify SHA256(choice||secret) == commit, tally)

On-chain storage:

  • Proposal account (metadata, deadline, tallies)
  • VoteCommitment account (voter pubkey, commit hash, revealed flag)

Data flow summary: Client (choice + secret) -> hash -> commit -> on-chain After deadline: Client -> reveal (choice + secret) -> program verifies + tally


How to run locally (quick)

Prerequisites:

  • Node.js and npm
  • Rust + Anchor (for building the program)
  • Solana CLI configured for localnet or devnet
  • A Solana wallet (Phantom recommended for browser testing)

Steps (dev flow):

  1. Build the Solana program
cd c:\Users\pc\Desktop\Veilvote
anchor build
  1. (Optional) Run tests
anchor test
  1. Start local validator or use devnet

Local validator (optional):

solana-test-validator
# in a new terminal, then deploy to localnet
anchor deploy --provider.cluster localnet
  1. Start the frontend
cd app
npm install
npm run dev
# open http://localhost:3000 in your browser
  1. Workflow
  • Use the UI to Create Proposal (admin key or test key)
  • Connect wallet and Commit Vote (the UI will generate a secret and compute a hash)
  • After the deadline, Reveal Vote with the secret (or use the stored secret in browser)

Notes:

  • The frontend utilities live in app/src/utils — see vote.ts for commit hashing and localStorage helpers.
  • To interact programmatically, consult INTEGRATION_GUIDE.md for Anchor/TypeScript examples.

Limitations (honest, judge-friendly)

  • Secrets are stored in browser localStorage by default (convenient for demos). For production, secrets must be stored encrypted or managed off-chain via secure backends or hardware wallets.
  • This system does not provide voter anonymity beyond the fact that votes are not stored in plaintext on-chain; voters are still identifiable by their signer pubkey when committing and revealing.
  • Tallying is public after reveal — if you need fully private tallies, you'll need more advanced cryptography.
  • No anti-coercion cryptographic countermeasures (e.g., receipt-freeness) — these are out of scope for this basic design.
  • The implementation uses SHA-256 commitments rather than more advanced primitives like Pedersen commitments or ZK proofs; this was a deliberate simplicity choice.

Roadmap to zero-knowledge proofs (how to get stronger privacy)

  1. Replace simple SHA-256 commitments with Pedersen commitments where hiding and homomorphic tallying are needed.

  2. Add ZK-SNARK or ZK-STARK based revealless verification: voters submit a ZK proof that they voted one of allowed options without revealing which one.

  3. Private tallying via homomorphic aggregation or secure multi-party computation:

    • Homomorphic commitments + aggregation on-chain and a ZK proof of correct decryption of the final tally.
  4. Integrate an identity-preserving privacy layer (e.g., anonymous credentials) to decouple voter identity from the ballot while preventing double-voting.

  5. Audit and optimize gas/compute on Solana (ZK-friendly circuits, batching proofs).

This repository is intentionally structured so the commit–reveal core can be replaced or extended with ZK primitives as a next step.


Why this is hackathon-ready

  • Minimal, auditable smart contract surface — easy to review in a short time.
  • Clear separation of client-side secrets and on-chain state.
  • Straightforward UI and developer workflow so judges can test the full flow in minutes.
  • A direct path to more advanced privacy features (ZK) without rearchitecting the whole stack.

If you'd like, I can now:

  • Add a short demo script that walks through Create → Commit → Reveal using a test key.
  • Add a quick encrypted-secret storage example (browser-based) for stronger demo security.

Files to inspect next: programs/veil_vote/src/lib.rs, app/src/utils/vote.ts, APP_SETUP.md, PRIVACY_ANALYSIS.md.

Thank you — ready to help wire the demo or add the ZK prototype next.

Veil Vote - Private Voting Program for Solana

A complete Anchor-based Solana program implementing a private, commit-reveal voting system.

Features

  • Create Proposals: Initialize voting proposals with title, description, and deadline
  • Commit Votes Privately: Voters submit a hash of their vote without revealing the choice
  • Reveal Votes: After voting deadline, votes are revealed and validated against commitments
  • Vote Tallying: Automatic counting of Yes (1) and No (0) votes
  • Security: Hash-based commitment scheme prevents vote manipulation

Program Structure

veil_vote/
├── Anchor.toml              # Anchor configuration
├── Cargo.toml               # Workspace Cargo.toml
├── programs/
│   └── veil_vote/
│       ├── Cargo.toml       # Program dependencies
│       └── src/
│           └── lib.rs       # Main program logic
└── tests/                   # Test directory

Account Types

Proposal

Stores proposal metadata and vote tallies:

  • proposal_id: Unique identifier
  • title: Proposal title (max 100 chars)
  • description: Proposal description (max 500 chars)
  • authority: Creator's/authority's public key
  • voting_deadline: Unix timestamp when voting ends
  • total_votes: Total votes cast and revealed
  • vote_count_yes: Number of Yes votes
  • vote_count_no: Number of No votes
  • created_at: Creation timestamp

VoteCommitment

Records each voter's commitment:

  • proposal_id: Associated proposal
  • voter: Voter's public key
  • vote_hash: Keccak256 hash of (voter || vote_choice || secret)
  • committed_at: Commitment timestamp
  • revealed: Whether vote has been revealed
  • vote_choice: Vote choice (0=No, 1=Yes, only valid after reveal)

Instructions

1. Create Proposal

fn create_proposal(
    proposal_id: u64,
    title: String,
    description: String,
    voting_deadline: i64,
)

Creates a new proposal. Only the creator can initialize it.

2. Commit Vote

fn commit_vote(vote_hash: [u8; 32])

Voter submits a hash commitment of their vote. Must be done before deadline.

3. Reveal Vote

fn reveal_vote(vote_choice: u8, secret: [u8; 32])

Voter reveals their vote after deadline. Hash is validated against commitment.

Vote Hash Calculation

The vote hash is computed as:

hash = Keccak256(voter_pubkey || vote_choice || secret)

Where:

  • voter_pubkey: 32 bytes
  • vote_choice: 1 byte (0 or 1)
  • secret: 32 bytes

Building

anchor build

Testing

anchor test

Deployment

Update the program ID in declare_id!() and Anchor.toml before deployment.

anchor deploy

Error Codes

  • InvalidDeadline: Voting deadline must be in the future
  • InvalidTitle: Title length must be 1-100 characters
  • InvalidDescription: Description length must be 1-500 characters
  • VotingEnded: Cannot commit votes after deadline
  • AlreadyVoted: Voter has already committed
  • InvalidVoteChoice: Vote must be 0 (No) or 1 (Yes)
  • VoteAlreadyRevealed: Vote has been revealed
  • Unauthorized: Access denied
  • InvalidReveal: Reveal hash doesn't match commitment
  • VoteRevealTooEarly: Cannot reveal before voting deadline ends

Security Considerations

  1. Commitment Scheme: Uses cryptographic hash to hide votes until reveal
  2. Vote Validation: Reveals are validated against original commitments
  3. Deadline Enforcement: Voting and reveal phases are time-locked
  4. Signature Verification: All instructions require signer authorization
  5. No Vote Selling: Secret is kept off-chain to prevent vote coercion

Future Enhancements

  • Add vote delegation
  • Implement vote weight (token-weighted voting)
  • Add proposal voting for approval
  • Implement timelocks for proposals
  • Add vote encryption for additional privacy

About

A privacy focused DAO voting infra onn Solana

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors