Skip to content

valargroup/voting-circuits

Repository files navigation

voting-circuits

Governance ZKP circuits (delegation, vote proof, share reveal) for the Zcash shielded-voting protocol.

Built with halo2 on top of the upstream orchard implementation shared by Orchard and Ironwood. The crate requires std.

Proof flow

Ironwood Notes ──► Delegation (ZKP 1) ──► Vote Authority Notes (VANs)
                                              │
                                              ▼
                  Vote Proof  (ZKP 2) ──► Vote Commitments + encrypted shares
                                              │
                                              ▼
                  Share Reveal (ZKP 3) ──► Revealed shares for tally
  1. Delegation spends Ironwood V3 notes and mints VANs that carry delegated voting weight.
  2. Vote Proof spends a VAN to cast a vote, producing El Gamal-encrypted shares and a vote commitment.
  3. Share Reveal opens a single encrypted share and proves it belongs to a registered vote commitment.

Usage

This crate is the circuit-only side. Wallets typically don't call it directly; they consume the higher-level zcash_voting crate which wraps proof generation, hotkey derivation, share construction, and the HTTP wire format.

If you do want the raw gadgets for a custom prover:

use voting_circuits::vote_proof::Circuit as VoteProofCircuit;
// ... assemble public/private inputs and run halo2_proofs

Minimum supported Rust version: 1.86, as declared by the crate manifest.

Protocol domain-separation tags are registered in src/domain_tags.rs. Hash-owning modules document their own preimage layout, but new tags should be added to the registry first so the encoding rule and distinctness test stay centralized.

Package layout

src/
├── lib.rs                        # Crate root — re-exports the three circuits
├── circuit/                      # Shared gadgets used across circuits
│   ├── address_ownership.rs      #   CommitIvk + diversified-address integrity
│   ├── elgamal.rs                #   El Gamal encryption (vote proof condition 11)
│   ├── poseidon_merkle.rs        #   Poseidon-based Merkle path verification
│   ├── van_integrity.rs          #   VAN commitment hash (two-layer Poseidon)
│   └── vote_commitment.rs        #   Vote commitment hash
├── shares_hash.rs                # Shares-hash gadget (shared by ZKP 2 & 3)
│
├── delegation/                   # ZKP #1 — Delegation circuit (K=14)
│   ├── circuit.rs                #   15-condition halo2 circuit
│   ├── builder.rs                #   Multi-note bundle builder (up to 5 notes)
│   ├── prove.rs                  #   Prove / verify helpers
│   ├── imt.rs                    #   Indexed Merkle Tree (data structure)
│   ├── imt_circuit.rs            #   IMT non-membership proof gadget
│   └── README.md                 #   Detailed specification
│
├── vote_proof/                   # ZKP #2 — Vote Proof circuit (K=13)
│   ├── circuit.rs                #   12-condition halo2 circuit
│   ├── builder.rs                #   Builder producing VoteProofBundle
│   ├── prove.rs                  #   Prove / verify helpers
│   ├── authority_decrement.rs    #   Proposal-authority decrement gadget
│   └── README.md                 #   Detailed specification
│
└── share_reveal/                 # ZKP #3 — Share Reveal circuit (K=11)
    ├── circuit.rs                #   5-condition halo2 circuit
    ├── builder.rs                #   Builder
    └── prove.rs                  #   Prove / verify helpers

benches/
└── delegation.rs                 # Criterion benchmarks for delegation proving

Shared gadgets (circuit/)

Reusable halo2 gadgets that appear in more than one circuit:

Gadget Used by Purpose
address_ownership Delegation, Vote Proof CommitIvk + diversified-address binding
elgamal Vote Proof El Gamal encryption of vote shares
poseidon_merkle All three Poseidon Merkle-path membership proofs
van_integrity Delegation, Vote Proof Two-layer Poseidon hash for VAN commitments
vote_commitment Vote Proof, Share Reveal Hash of (domain, round_id, shares_hash, proposal_id, decision)

shares_hash (at crate root) computes a two-level Poseidon hash over 16 blinded share commitments and is shared by ZKP 2 and ZKP 3.

Circuit details

Circuit K Rows Conditions Spec
Delegation 14 16 384 15 ZKP #1
Vote Proof 13 8 192 12 ZKP #2
Share Reveal 11 2 048 5 ZKP #3

Dependency on orchard

This crate depends on the upstream orchard 0.15.0 release, with the circuit and unstable-voting-circuits features enabled to expose the circuit APIs used by the governance proofs. The delegation bundle builder requires Ironwood V3 notes and constructs its synthetic signed and output notes as V3.

The V3 check is a bundle-construction policy, not a note-version bit in the Halo2 statement. An Ironwood-only verifier must independently authenticate nc_root as an Ironwood note commitment tree root and must not accept an Orchard root supplied by the prover. It must authenticate nf_imt_root at the same snapshot height.

Building

cargo build

Testing

Short-running tests are the default:

cargo test

Long-running tests are explicitly ignored and can be run when circuit-level coverage is needed. Skip the row-budget and cost-breakdown diagnostics for a normal regression pass:

cargo test -- --ignored --skip row_budget --skip cost_breakdown

To inspect circuit size diagnostics, keep --nocapture so the output is printed:

cargo test row_budget -- --ignored --nocapture
cargo test cost_breakdown -- --ignored --nocapture

The long tests are slow because they synthesize Halo 2 circuits and run MockProver verification over the configured K domain (delegation uses K=14, vote_proof K=13, and share_reveal K=11). Some gadget stress tests are also long-running because they repeat many MockProver checks, for example one K=12 shares-hash test runs 16 separate prover checks. The real proof roundtrip also performs proving-key/proof generation and verification, so it is intentionally outside the default unit-test path.

Benchmarks

cargo bench   # runs delegation proving benchmarks via Criterion

Key dependencies

Crate Role
halo2_proofs Proof system (with batch verification)
halo2_gadgets Standard gadgets (Poseidon, Sinsemilla, ECC)
pasta_curves Pallas / Vesta curve arithmetic
orchard Orchard protocol primitives used by Ironwood, including note commitments, nullifiers, and CommitIvk
halo2_poseidon Poseidon hash for Merkle trees and commitments
incrementalmerkletree Incremental Merkle tree data structure
sinsemilla Sinsemilla hash (used via Orchard)

License

Dual-licensed under MIT or Apache-2.0. See LICENSE-MIT and LICENSE-APACHE.

About

No description, website, or topics provided.

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

1 star

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages