voting-circuits 0.7.0

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

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 shielded protocol. The crate requires std.

Proof flow

Orchard 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 Orchard 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 upstream zcash/orchard 0.13.1 from crates.io, allowing compatible patch releases, with the unstable-voting-circuits feature enabled to expose the governance-visibility APIs the voting circuits rely on. The previous valar-orchard fork has been retired.

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 note commitment, nullifier, 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.