Technical Documentation

The Technology
Behind SIGIL

Three cryptographic pillars — privacy, fairness, and anti-collusion — work together. Votes are encrypted, quadratically weighted, and protected by MACI research.

01

ZK Private Voting

[ How It Works ]

Votes are encrypted client-side and stored on-chain as ciphertext. The message queue is hashed with Poseidon, and the tally is verified by Groth16 proofs — without any reveal phase. Individual votes remain private.

  • check_circleOnly ciphertext is stored on-chain (and hashed into AccQueue leaves)
  • check_circleOn-chain registration and voice credit proxy enforce eligibility and voting power
  • check_circleNo reveal phase exists — individual votes are permanently sealed, even after voting ends
INPUT_DATAVOTE_OPTION_A
SECRET_NONCEx8f9...32a1
keyboard_double_arrow_down

AccQueue Leaf (On-Chain) (On-Chain)

0x4a2e8c1f9b3d7e5a6012c8b7f3d9e0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7

Credit System: Cost = Vote²

1 Vote1 credits
2 Votes4 credits
3 Votes9 credits
Visual Progression of Exponential Cost
02

Quadratic Voting

Traditional "1 token = 1 vote" can over‑weight large holders. Quadratic voting makes extra influence cost more, so conviction matters without easy domination.

How It Works:

Each voter receives voice credits. Casting more votes on the same proposal costs quadratically more: cost = votes². One vote costs 1 credit, but 10 votes costs 100 credits. This forces voters to budget their influence across proposals, naturally preventing plutocratic domination while letting conviction shine through.

03

MACI Anti-CollusionEthereum PSE Research

STEP_01

Forced Vote (Forced Vote (Coerced))

A briber forces Alice to vote "For" and watches her submit it on-chain. She complies to appear cooperative.

STEP_02

Key Change (EdDSA)

Alice secretly changes her EdDSA key. The briber cannot detect this — it looks like any other encrypted message.

STEP_03

Real Vote (Final)

Alice re-votes with her true choice using the new key. During reverse-order processing, only this vote counts.

Built on Ethereum Privacy & Scaling Explorations (PSE) research

Stronger Together

SIGIL combines ZK privacy, quadratic fairness, and MACI anti-collusion in a single system.

What SIGIL adds beyond PSE MACI

01

Quadratic Voting — D2 integration with cost = votes² credit system

02

In-Circuit Decryption — DuplexSponge runs inside the ZK circuit, reducing trust in coordinator decryption

03

No Reveal Phase — Individual votes are not published; only totals are revealed

04

ERC20 Voice Credits — Use ERC20-based voting credits via proxy

05

Automated Coordinator — GitHub Actions cron can replace a dedicated server

Technical SpecificationsConcrete numbers behind the cryptography

timerProof Generation

Varies

Groth16 proof generation time varies by circuit size, hardware, and network conditions.

local_gas_stationGas per Batch

Varies

On-chain verification cost depends on batch size and network conditions.

tagHash Function

Poseidon

t=4, rate=3 — optimized for ZK circuits.

keyKey Curve

Baby Jubjub

EdDSA-compatible elliptic curve embedded in BN254 scalar field

lockEncryption

DuplexSponge

Poseidon-based sponge cipher + ECDH key exchange for vote encryption

account_treeState Tree

Depth 4

Quinary tree — supports up to 624 voters per poll (production configuration)

memoryMessageProcessor

Varies

Constraint count depends on circuit build.

calculateTallyVotes

Varies

Constraint count depends on circuit build.

group_workTrusted Setup

pot20

Powers of Tau ceremony supporting up to 2²⁰ (1M) constraints. Groth16 phase 2 per circuit.

System Architecture

How the four core contracts work together

01

MACI

Entry point. Handles voter registration (signUp) and deploys new Poll instances.

02

Poll

Stores encrypted vote messages in an immutable AccQueue. Manages voting period.

03

MessageProcessor

Decrypts messages in reverse order. Applies key changes. Generates state transition proof.

04

Tally

Computes final vote counts. Generates Groth16 tally proof. Publishes results on-chain.

MACI → POLL → MESSAGE PROCESSOR → TALLY

Built for Developers

code

Built for
Developers

Everything you need to add private voting to a Web3 project.

package_2

TypeScript SDK

Type-safe SDK. Create polls, cast votes, and read results from the client and on-chain.

const sigil = new SigilClient({ maciAddress })
const results = await sigil.getResults(pollId)
widgets

Embeddable Widget

Mount a vanilla JS widget into any page. Handles key generation, encryption, and transaction submission.

mountSigilWidget({ target: '#vote', pollId: 0 })
terminal

Crypto Primitives

Use low-level crypto utilities for flexibility: command packing, message encryption, and key derivation.

import { packCommand, buildEncryptedVoteMessage } from "sigil-sdk"
const msg = await buildEncryptedVoteMessage(params)

Built for Token Communities

arrow_rightTreasury Governance — Allocate funds without whale manipulation
arrow_rightProtocol Upgrades — Vote on parameter changes privately
arrow_rightGrant Allocation — Fair quadratic funding decisions
arrow_rightCommunity Decisions — NFT, DeFi, and social DAO voting

Security & Trust

verified

Open Source — audit and fork freely

verified

PSE MACI Protocol — Built on Ethereum Foundation Privacy & Scaling Explorations research

verified

On-chain Groth16 — Every tally verified by smart contract, not a server

verified

Zero Knowledge — Coordinator tallies votes but individual choices are never published

Protocol Stack

POSEIDON HASH | EDDSA KEYS
GROTH16 PROOFS | BABY JUBJUB
DUPLEXSPONGE CIPHER | ECDH

Tallying Pipeline

When voting ends, the coordinator automatically begins tallying. Each step requires blockchain transactions, and total time depends on network conditions.

01
Varies

Data Merge

Voter list and encrypted messages are merged into Merkle trees. Requires multiple blockchain transactions.

02
Varies

Message Processing

The coordinator decrypts all messages in reverse order, applies key changes, and identifies valid votes. A ZK proof is generated and submitted on-chain for each batch.

03
Varies

Tally Proof

Valid votes are tallied and a Groth16 proof is generated. This proof mathematically guarantees the tally is correct.

04
Varies

Publish Results

Aggregate results (total For/Against) are published on-chain. Individual votes are never revealed — only the final totals.

Total time: varies by network

info

Proof generation and confirmations vary by circuit size, hardware, and chain conditions. L2 networks often reduce latency compared to L1.

Infrastructure & Operations

cloud_done

SIGIL minimizes backend infrastructure. Most work happens in the browser and on-chain. The coordinator can run on GitHub Actions or your own server.

01
cloud_off

Minimal Backend

The frontend is a Next.js app deployable on Vercel/Netlify. Crypto runs in the browser; data lives on-chain. No app backend, only a coordinator job.

02
token

ERC20 Voice Credits

ERC20-based voting credits are supported via proxy (1 token = 1 credit, floor division). Configure the token address at deployment.

03
speed

L2 / Multi-Chain Deployment

All contracts are standard Solidity 0.8.24 with no chain-specific dependencies. Deploy on any EVM-compatible chain. On L2 networks (Base, Arbitrum, Polygon), costs and latency are typically lower than L1, depending on network conditions.

04
groups

Token-Gated Proposals

When proposal gates are configured, token holders can create proposals directly. Owners can reconfigure or clear gates.

05
smart_toy

GitHub Actions Coordinator

The coordinator can run as a GitHub Actions cron job (every 5 minutes). It merges queues, generates Groth16 proofs, and publishes results on-chain.

06
dns

Custom Server Option

For faster processing, run the coordinator on your own server (npx tsx src/run.ts). It checks every ~10 seconds instead of 5 minutes. Requires a funded wallet and the coordinator key.

07
handshake

Delegation Registry

Delegation is supported. Full voting-power delegation requires DelegatingVoiceCreditProxy and depends on deployment config.

08
schedule

Timelocked Execution

Optional on-chain execution when the executor is configured and execution is registered.

On-Chain Deployments

Contracts are deployed on Ethereum Sepolia. Links are provided per contract.

MACI Registry

0x12DaA8f679e7C798645750F91106b38b38C6341B

View on Etherscanopen_in_new

AccQueue (State)

0xA0Af58848a15DFeC67486591f225464323D84622

View on Etherscanopen_in_new

TON Token (Voice Credits)

0xa30fe40285B8f5c0457DbC3B7C8A280373c40044

View on Etherscanopen_in_new

Security GuaranteesSeven cryptographic properties guaranteed by the MACI protocol

Collusion Resistant

Only Coordinator decrypts; bribers cannot verify compliance

Receipt-Free

Key Change invalidates any "proof" shown to a briber

Vote Privacy

No reveal phase — individual votes are permanently encrypted

Uncensorable

Immutable AccQueue — omitting a vote causes proof failure

Unforgeable

EdDSA signature required with voter's current key

Non-Repudiable

New votes override, never delete — all messages are permanent

Correct Execution

Groth16 on-chain verification proves tally correctness