Skip to content

armsves/midnightOpenVote

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

1 Commit
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ—³οΈ OpenVote - Private Voting on Midnight Network

A decentralized voting application built on Midnight Network using real Zero-Knowledge proofs for private, verifiable voting. Built with Compact smart contracts and deployed on Midnight testnet.

✨ Features

  • πŸ” True Privacy: Individual votes are private using ZK-SNARKs (not mocked!)
  • πŸ—³οΈ One Wallet, One Vote: ZK proofs ensure each wallet can only vote once per proposal
  • ⏰ Time-Limited Voting: Proposals have configurable voting periods
  • πŸ“Š Public Tallies: Vote counts are public, but individual votes remain private
  • πŸš€ Testnet Deployed: Running on real Midnight Network infrastructure
  • πŸ”„ Real-time Updates: Live vote count updates

πŸ—οΈ Architecture

Smart Contract (Compact)

  • Public State: Proposals, vote tallies, deadlines
  • Private State: Individual voting records (who voted on what)
  • ZK Circuits: Proves voter eligibility without revealing identity
  • Location: src/contract/voting.compact

Frontend (React + TypeScript)

  • Lace Wallet integration
  • ZK proof generation in browser
  • Real-time proposal updates
  • Responsive UI

πŸš€ Quick Start

Prerequisites

  1. Docker - For running the Midnight proof server
  2. Node.js 18+ and npm
  3. Lace Wallet Extension - Install from Chrome Web Store
  4. Midnight Testnet Tokens - Get from Midnight Faucet

Step 1: Clone and Install

cd OpenVote
npm install

Step 2: Start Midnight Proof Server

The proof server is required for generating ZK proofs:

docker-compose up -d

Verify it's running:

curl http://localhost:6300/health

Step 3: Configure Environment

cp .env.example .env

Edit .env and add your deployer private key from Lace wallet.

Step 4: Compile and Deploy Contract

# Compile the Compact contract
npm run build:contract

# Generate TypeScript bindings
npm run build:bindings

# Deploy to Midnight testnet
npm run deploy

Save the contract address output and add it to .env:

VITE_CONTRACT_ADDRESS=<your_contract_address_here>

Step 5: Run Frontend

npm run dev

Open http://localhost:3000 in your browser.

πŸ“– Usage Guide

Creating a Proposal

  1. Connect your Lace wallet
  2. Fill in the proposal form:
    • Title: Short, descriptive title
    • Description: What's being voted on
    • Duration: Voting period in blocks (~20 seconds per block)
  3. Click "Create Proposal"
  4. Confirm transaction in Lace wallet

Voting

  1. Find a proposal with "Open" status
  2. Click "Vote Yay" or "Vote Nay"
  3. ZK Proof Generation: Your browser generates a proof that:
    • You haven't voted on this proposal yet
    • You're eligible to vote
    • WITHOUT revealing your wallet address or vote choice
  4. Confirm the transaction
  5. Your vote is added to the public tally, but remains private!

Viewing Results

  • During Voting: Live tallies update as votes come in
  • After Deadline: Final results are displayed
  • Privacy: You can see vote counts but never individual votes

πŸ”§ Development

Project Structure

OpenVote/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ contract/
β”‚   β”‚   └── voting.compact          # Smart contract
β”‚   β”œβ”€β”€ components/
β”‚   β”‚   β”œβ”€β”€ CreateProposal.tsx      # Proposal creation form
β”‚   β”‚   β”œβ”€β”€ ProposalList.tsx        # List all proposals
β”‚   β”‚   └── ProposalCard.tsx        # Single proposal display
β”‚   β”œβ”€β”€ services/
β”‚   β”‚   └── VotingService.ts        # Contract interaction layer
β”‚   β”œβ”€β”€ App.tsx                     # Main app component
β”‚   └── main.tsx                    # Entry point
β”œβ”€β”€ docker-compose.yml              # Proof server config
β”œβ”€β”€ package.json
└── vite.config.ts

Key Technologies

  • Compact: Domain-specific language for ZK circuits
  • Midnight.js: SDK for interacting with Midnight Network
  • React + TypeScript: Modern frontend
  • Vite: Fast build tool
  • Docker: Containerized proof server

Build Commands

# Compile Compact contract
npm run build:contract

# Generate TypeScript bindings
npm run build:bindings

# Build entire project
npm run build

# Deploy to testnet
npm run deploy

# Start dev server
npm run dev

πŸ” How ZK Proofs Work

Traditional Voting Problem

  • Votes recorded on-chain are public
  • Anyone can see who voted for what
  • Vulnerable to coercion and manipulation

OpenVote's ZK Solution

  1. Private Voting Record: The contract maintains a private map of [wallet, proposalId] => hasVoted
  2. ZK Proof Generation: When voting, your browser generates a proof that:
    "I know a secret (my private key) that controls wallet X,
     AND wallet X has NOT voted on proposal Y yet,
     BUT I won't reveal which wallet or my vote"
    
  3. On-Chain Verification: The contract verifies the proof without learning:
    • Your wallet address
    • Your vote choice
    • Any identifying information
  4. Public Tally Update: Only the vote count increases

Why This Isn't Mocked

  • βœ… Real proof server (Docker container)
  • βœ… Actual ZK-SNARK circuit compilation
  • βœ… Genuine cryptographic proofs generated client-side
  • βœ… On-chain verification on Midnight testnet
  • βœ… Private state managed by Compact runtime

🌐 Network Configuration

Midnight Testnet

  • RPC: wss://rpc.testnet-02.midnight.network
  • Proof Server: http://localhost:6300 (local Docker)
  • Explorer: Midnight Explorer

Getting Testnet Tokens

  1. Install Lace wallet
  2. Create/import a wallet
  3. Visit Midnight Faucet
  4. Enter your wallet address
  5. Receive test tokens

🎯 Use Cases

DAO Governance

  • Private voting prevents whale manipulation
  • Transparent tallies ensure fair outcomes
  • Time-limited proposals create urgency

Community Polls

  • Anonymous feedback collection
  • Honest opinions without fear of backlash
  • Verifiable results

Elections

  • Private ballot casting
  • Public vote counting
  • Tamper-proof record keeping

πŸ› Troubleshooting

"Proof server not responding"

# Check if Docker is running
docker ps

# Restart proof server
docker-compose down && docker-compose up -d

# Check logs
docker-compose logs -f

"Lace wallet not found"

  • Install Lace wallet extension
  • Refresh browser after installation
  • Ensure extension is enabled

"Transaction failed"

  • Check you have testnet tokens
  • Verify contract address is set correctly
  • Ensure proof server is running

"Already voted on this proposal"

  • Each wallet can only vote once per proposal
  • This is enforced via ZK proofs
  • Try voting on a different proposal

πŸ“š Additional Resources

πŸŽ“ Educational Value

This project demonstrates:

  • Real-world ZK-SNARK implementation (not mocked!)
  • Smart contract development in Compact
  • Private state management
  • Client-side proof generation
  • Decentralized application architecture
  • Wallet integration
  • Testnet deployment

πŸ“ License

MIT License - feel free to use this for learning, hackathons, or production!

πŸ™ Acknowledgments

Built for the Midnight Network hackathon, showcasing real privacy-preserving voting without simulation or mocking.


Ready to vote privately? Get started now! πŸš€

Questions? Open an issue or check the Midnight docs.

About

Anonymous verifiable voting for Midnight

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages