ZkSnap Halo2 Circuits

This repository consists of ZK circuits written using the Halo2 proving stack. It is divided in two parts, voter and aggregator.

Overview

ZKSnap is a novel private voting protocol designed for decentralized communities and organizations. It leverages cutting-edge cryptographic techniques like zero-knowledge proofs, homomorphic encryption, and deterministic signatures to enable secure, anonymous, and cost-efficient online voting.

Key Features:

  • End-to-end voter privacy via encrypted ballots and nullifiers
  • Trustless vote tallying with zero-knowledge verifiability
  • Resistance to double-voting and coercion attacks
  • No individual vote disclosure, preventing real-time tally analysis
  • Gasless voting, eliminating monetary costs for participants

For detailed information about ZKSnap's design, cryptographic primitives, and security assumptions, please refer to the ZKSnap Whitepaper.

Getting Started

Halo 2 is written in Rust, so you need to install Rust to use this library:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Clone this repo and start off in the zksnap-circuits-halo2 directory.

git clone https://github.com/aerius-labs/zksnap-circuits-halo2.git
cd zksnap-circuits-halo2

Repository Structure

voter Package

Provides circuit for generating voter proofs. These are run by the clients (voters) in browser.

It performs the following checks:

  • Verifies if the voter is a member of the DAO.
  • Encrypts the vote using public key encryption.
  • Verifies the PLUME signature generated by the user.

aggregator Package

Provides circuits for aggregating voter proofs and updating the encrypted tally of votes. We use IVC-style recursion to continually aggregate vote proofs.

The aggregator package consists for 2 modules:

  • state_transition: Provides circuit for proving state transition (updated tally of votes & updated nullifier tree) in the aggregator.
  • wrapper: Provides IVC-style proof aggregation, where the circuit:
    • Verifies individual proofs (voter, state_transition & previous)
    • Combines the KZG accumulators from individual proofs to generate a final accumulator which acts as the constant-size proof for the previous chain of aggregations.
    • Enforces data consistency by verifying that the voter, state_transition, and previous proof instances match across incoming proofs, ensuring correct data propagation.

Tests

Tests can be run using the following command:

cargo test -- --nocapture <TEST_NAME>

Benchmarks

We use the optimal config to run benchmarks with a custom circuit degree k. We run the benchmarks in --release mode for the best performance.

The available benchmark commands are:

cargo bench --bench voter_circuit
cargo bench --bench state_transition_circuit
cargo bench --bench wrapper_circuit