A zk-SNARK implementation, use circom and snarkjs
Welcome to submit any issues or prs, also welcome DM me via twitter
Create random numbers and circuits, get pk and vk through trusted setup
- Install dependencies
yarn global add circom
yarn global add snarkjs
- Secure Multi-party Computation
Here is the output tool of zcash in ceremonypowersoftau
snarkjs powersoftau new bn128 12 pot12_0000.ptau -v
snarkjs powersoftau contribute pot12_0000.ptau pot12_0001.ptau --name="First contribution" -v
snarkjs powersoftau contribute pot12_0001.ptau pot12_0002.ptau --name="Second contribution" -v -e="some random text"
snarkjs powersoftau export challenge pot12_0002.ptau challenge_0003
snarkjs powersoftau challenge contribute bn128 challenge_0003 response_0003 -e="some random text"
snarkjs powersoftau import response pot12_0002.ptau response_0003 pot12_0003.ptau -n="Third contribution name"
Verify the ptau file so far
snarkjs powersoftau verify pot12_0003.ptau
More info about the powers of tau ceremony and MPC
- Apply a random beacon,get final ptau file
snarkjs powersoftau beacon pot12_0003.ptau pot12_beacon.ptau 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f 10 -n="Final Beacon"
snarkjs powersoftau prepare phase2 pot12_beacon.ptau pot12_final.ptau -v
Verify this ptau file
snarkjs powersoftau verify pot12_final.ptau
- Create circuit
Using circom to write circuit,the circomlib also encapsulates the basic circuit
cat <<EOT > circuit.circom
template Multiplier(n) {
signal input a;
signal input b;
signal output c;
signal int[n];
int[0] <== a*a + b;
for (var i=1; i<n; i++) {
int[i] <== int[i-1]*int[i-1] + b;
}
c <== int[n-1];
}
component main = Multiplier(1000);
EOT
More circom specification refer official documentation
- Compile circuit
circom circuit.circom --r1cs --wasm --sym
View circuit information
snarkjs r1cs info circuit.r1cs
snarkjs r1cs print circuit.r1cs circuit.sym
- trusted setup Export r1cs.json and create witness
snarkjs r1cs export json circuit.r1cs circuit.r1cs.json
cat <<EOT > input.json
{"a": 3, "b": 11}
EOT
circuit_js$ node generate_witness.js circuit.wasm ../input.json ../witness.wtns
// or
snarkjs wtns calculate circuit.wasm input.json witness.wtns
You can use the proof system of plonk or groth16,and there will be Halo2 developed by Aztec and Zcash in the future
snarkjs plonk setup circuit.r1cs pot12_final.ptau circuit_final.zkey
snarkjs groth16 setup circuit.r1cs pot12_final.ptau circuit_0000.zkey
- Get pk and export the vk
snarkjs zkey export verificationkey circuit_final.zkey verification_key.json
Import pk、witness(s,private input)and x(public input),export proof
snarkjs plonk prove circuit_final.zkey witness.wtns proof.json public.json
Import proof、x(public input)and verification key,then verifiers can verify the result of proof
// plonk
snarkjs plonk verify verification_key.json public.json proof.json
// groth16
snarkjs groth16 verify verification_key.json public.json proof.json
Export solidity file,contracts can be deployed via Remix,you can call contract after deploy verifier.sol
snarkjs zkey export solidityverifier circuit_final.zkey verifier.sol
You can also use soliditycalldata to simulate the verification call, return the verifyProof field and put it in the environment where the remix contract is deployed
snarkjs zkey export soliditycalldata public.json proof.json
[1] : Create your first zero-knowledge snark circuit using circom and snarkjs
[2] : Explaining SNARKs Part I: Homomorphic Hidings
[3] : What are zk-SNARKs?
[4] : Why and How zk-SNARK Works 1: Introduction & the Medium of a Proof
[5] : Why and How zk-SNARK Works: Definitive Explanation
[6] : Zk-SNARKs: Under the Hood -- vitalik