β οΈ π§ This repository is currently a proof of concept. π§β οΈ
This is an attempt to create an experimental zksnark prover/verifier for gnark circuits, compatible with TinyGo, which means that it could be used on a bunch variety of targets (e.g. browsers).
It implements the same use case as this circuit, and it attempts to replace the Circom + SnarkJS stack.
- π Gnark is very fast.
- π Supports unit testing and many modern backends and curves.
- π vocdoni-node is currently writed enterily in Go, like Gnark, which will increase the maintainability of the source code.
Read about the comprehensive insights, decisions made, benchmarks and conclusions drawn in our article here https://hackmd.io/@vocdoni/B1VPA99Z3
artifacts/ -> Includes generated artifacts for the implemented and compiled circuits.
circuits/ -> Includes the available circuits definitions.
zkcensus/ -> Port to gnark of https://github.com/vocdoni/zk-franchise-proof-circuit/blob/master/circuit/census.circom
cmd/
compiler/ -> Simple command to compile available circuits.
prover/ -> Simple command to test the prover with go.
examples/ -> Example of proof generation in js using gnark into a go-wasm.
internal/
zkaddress/ -> Alternative implementation of current vocdoni zkaddress (https://github.com/vocdoni/vocdoni-node/blob/master/crypto/zk/address.go)
std/ -> Extended gnark std version with required ports.
hash/poseidon/ -> Port to gnark of https://github.com/iden3/circomlib/blob/master/circuits/poseidon.circom
smt/ -> Port to gnark of https://github.com/iden3/circomlib/blob/master/circuits/smt/smtverifier.circom
zkaddress/ -> Implementation of the zkaddress using gnark
wasm/ -> Wasm entrypoint and compiled version.
- Ports from Gnark of required Circom circuits:
ZkCensus
Vocdoni circuit port to Gnark: Gnark | Circom.ZkCensus
(Gnark version) compiler and artifacts enconder command implementation.- Some blocks found and solved 1.
- Generic Gnark prover/verifier implementation.
- Go WASM compiler as baseline. Found some incompatibilities with TinyGo2.
- Go (1.20.2)
- TinyGo (@vocdoni fork): vocdoni/tinygo
The ZkCensus circuit anonymously proves that a voter is part of a census for a given election, without revealing its identity.
The ZkCensus circuit proves the following assertions:
- The combination of the computed ZkAddress (using the given PrivateKey as seed) and the provided factoryWeight is a valid census tree leaf. This is tested computing the merkle root with the candidate leaf and the provided siblings, and comparing the result with the provided census root.
- The provided nullifier is valid. This is tested computing the nullifier with the electionID and the privateKey, and comparing the result with the provided nullifier.
- The votingWeight is equal to or less than the factoryWeight.
Term descriptions:
- ZkAddress: the address of an anonymous voter in the Vochain, it is optimised for zk-snarks and helps to reduce the number of levels of the census merkle tree. It is based on the BN254 elliptic curve and it uses the voter private key as seed. Read more here.
- Nullifier: the result of applying the Poseidon hash to the combination of the election ID and the voter private key.
+----+
PUB_votingWeight+------>+ <= +------------------+--PRI_factoryWeight
+----+ |
|
+-----------+ |
| | |
PUB_censusRoot+-------->+ |(value)<---+
| |
| SMT | +-----------+ +-----------+
| Verifier | | | | |
PRI_siblings+---------->+ |(key)<-----+ ZkAddress +<--+ pubKey +---+-+PRI_privateKey
| | | | | | |
+-----------+ +-----------+ +-----------+ |
|
+-----------+ |
+----+ | +<------------------------------+
PUB_nullifier+--------->+ == +<-----+ Poseidon |<------------+PUB_processID_0
+----+ | +<------------+PUB_processID_1
+-----------+
PUB_voteHash
Name | Private/Public | Description |
---|---|---|
votingHeight | π private |
The weight used to perform a vote. It must be equal to or lower than factoryWeight . |
factoryHeight | π’ public |
The weight assigned to the voter as Merkle Tree leaf value. |
privateKey | π private |
The voter private key. Seed of the ZkAddress. |
censusRoot | π’ public |
The Merkle Root of the current census tree. |
siblings | π private |
Siblings of the voter ZkAddress leaf in the census tree. |
nullifier | π’ public |
Parameter that combines the privateKey with the electionId to avoid proof reusability. |
electionId | π’ public |
Encoded ID of the election. |
voteHash | π’ public |
Parameter that combines the privateKey with the factoryWeight to be include it into the proof witness. |
- Compile circuit, prover and run a web example
or for Plonk
make run-tinygo-web-example-g16
make run-tinygo-web-example-plonk
See Makefile