Overview
identiPay uses zero-knowledge circuits built with Circom to enable privacy-preserving identity verification and anonymous payments. The circuits are compiled to Groth16 proofs, which are verified on-chain in the Sui smart contracts.All circuits use the BN254 elliptic curve and Groth16 proving system for efficient on-chain verification.
Circuit Architecture
The protocol implements three core circuits:| Circuit | Constraints | Purpose |
|---|---|---|
| identity_registration | ~700 | Creates a privacy-preserving identity commitment |
| age_check | ~1,500 | Proves minimum age without revealing birthdate |
| pool_spend | ~35,000 | Proves ownership of shielded pool note for withdrawal |
Circuit Components
Circomlib Dependencies
All circuits depend oncircomlib for cryptographic primitives:
- Poseidon: ZK-friendly hash function used for commitments and Merkle trees
- Comparators: Range checks and inequality proofs (GreaterEqThan, LessEqThan, IsZero)
- Bitify: Bit decomposition for range proofs (Num2Bits)
Field Arithmetic
All circuits operate in the BN254 scalar field:- Field size: ~254 bits
- Modulus: 21888242871839275222246405745257275088548364400416034343698204186575808495617
- Compatible with Ethereum and Sui zkSNARK verifiers
Compilation Process
Circuits are compiled using thecompile.sh script via npm scripts:
Compilation Steps
The compilation pipeline consists of four stages:Build Artifacts
After compilation, the following artifacts are generated:WebAssembly witness generator. Used client-side to compute witness from private inputs.
Final proving key. Used by the prover to generate Groth16 proofs.
Verification key in JSON format. Must be converted to Sui Move format and deployed on-chain.
Rank-1 Constraint System. Defines the circuit’s constraints.
Proof Generation
Client-Side Workflow
Proofs are generated in the user’s browser or wallet:On-Chain Verification
Proofs are verified on Sui using thezk_verifier module:
Security Considerations
Trusted Setup
Mitigations:- Use multi-party computation (MPC) for the trusted setup
- Perform public ceremony with multiple contributors
- For production, use the Perpetual Powers of Tau ceremony
Circuit Security
Best practices implemented:-
Constraint completeness: All inputs are properly constrained
- Example: Date parsing uses explicit range checks (1 ≤ month ≤ 12)
-
Underflow prevention: Comparisons use proper bit decomposition
- Example:
pool_spend.circom:129usesNum2Bits(64)to prove non-negativity
- Example:
-
Public input binding: Public inputs are constrained to prevent malleability
- Example:
age_check.circom:154-158squares public inputs to prevent optimization
- Example:
-
Nullifier uniqueness: Deterministic nullifiers prevent double-spending
- Example:
nullifier = Poseidon(commitment, ownerKey)inpool_spend.circom:115
- Example:
Performance
Proving Time
Estimated client-side proving times (browser, M1 MacBook):| Circuit | Constraints | Proving Time | Proof Size |
|---|---|---|---|
| identity_registration | ~700 | ~0.5s | 128 bytes |
| age_check | ~1,500 | ~1s | 128 bytes |
| pool_spend | ~35,000 | ~15s | 128 bytes |
Verification Cost
On-chain verification gas costs on Sui:- Base cost: ~0.001 SUI per proof verification
- Linear in number of public inputs
- Independent of constraint count (Groth16 has constant verification time)
Next Steps
Identity Registration
Create privacy-preserving identity commitments
Age Check
Prove age without revealing birthdate
Pool Spend
Anonymous withdrawals from shielded pools
