snarkjs/README.md

415 lines
12 KiB
Markdown
Raw Normal View History

2018-10-21 19:41:44 +02:00
# snarkjs: JavaScript implementation of zkSNARKs.
2018-08-09 08:16:34 +02:00
2020-07-13 07:21:03 +02:00
This is a JavaScript and Pure Web Assembly implementation of zkSNARK schemes. It uses the Groth16 Protocol (3 point only and 3 pairings)
2018-08-09 08:16:34 +02:00
2020-07-13 18:33:50 +02:00
This library includes all the tools required to perform trusted setup multi-party ceremonies: including the universal "powers of tau" ceremony, and the second phase circuit specific ceremonies.
2018-08-09 08:16:34 +02:00
2020-07-13 18:33:50 +02:00
The formats used in this library for the multi-party computation are compatible with the ones used in [Semaphore's Perpetual Powers of Tau](https://github.com/weijiekoh/perpetualpowersoftau) and [other implementations](https://github.com/kobigurk/phase2-bn254).
2018-08-09 08:16:34 +02:00
2020-07-13 18:33:50 +02:00
This library uses the compiled circuits generated by the [circom](https://github.com/iden3/circom) compiler.
2019-04-12 14:20:43 +02:00
2020-07-13 18:33:50 +02:00
The library works in `node.js` as well as directly in the browser.
2019-04-12 14:20:43 +02:00
2020-07-13 18:33:50 +02:00
It's an [ES module](https://hacks.mozilla.org/2018/03/es-modules-a-cartoon-deep-dive/), so it can be directly imported into bigger projects using [Rollup](https://rollupjs.org/guide/en/) or [Webpack](https://webpack.js.org/).
2019-04-12 14:20:43 +02:00
2020-07-13 18:33:50 +02:00
The low-level cryptography is performed directly in wasm, and uses worker threads to parallelize the computations. The result is a high performance library with benchmarks comparable to host implementations.
2018-08-09 08:16:34 +02:00
2020-07-13 18:33:50 +02:00
## Preliminaries
### Install node v14
First off, make sure you have a recent version of `Node.js` installed. While any version after `v12` should work fine, we recommend you install `v14` or later.
If youre not sure which version of Node you have installed, you can run:
```sh
node -v
```
To download the latest version of Node, see [here](https://nodejs.org/en/download/).
2020-07-13 07:21:03 +02:00
### Install snarkjs and circom
2020-07-13 18:33:50 +02:00
To install `circom` and `snarkjs`, run:
2018-09-14 14:27:36 +02:00
```sh
2020-07-13 08:10:55 +02:00
npm install -g circom@latest
npm install -g snarkjs@latest
2018-08-09 08:16:34 +02:00
```
2020-07-13 18:33:50 +02:00
If you're seeing an error, try prefixing both commands with `sudo`.
### Understand the Help command
To see a list of all `snarkjs` commands, as well as descriptions about their inputs and outputs, run:
2018-10-21 19:41:44 +02:00
```sh
snarkjs --help
```
2020-07-13 07:21:03 +02:00
The help for specific command:
2018-10-21 19:41:44 +02:00
2020-07-13 07:21:03 +02:00
Example
```sh
snarkjs groth16 prove --help
```
2018-08-09 08:16:34 +02:00
2020-07-13 18:33:50 +02:00
Most of the commands have a short alias.
2018-08-09 08:16:34 +02:00
2020-07-13 18:33:50 +02:00
For example, the previous command can also be invoked as:
2020-07-13 07:21:03 +02:00
```sh
snarkjs g16p --help
2018-08-09 08:16:34 +02:00
```
2020-07-13 18:33:50 +02:00
### Debugging tip
If you a feel a command is taking longer than it should, re-run it with a `-v` or `--verbose` option to see more details about how it's progressing and where it's getting blocked. For example:
```sh
snarkjs g16p -v
```
## Guide
2020-07-13 18:33:50 +02:00
### 0. Create and move into a new directory
2020-07-13 08:10:55 +02:00
```sh
mkdir snarkjs_example
cd snarkjs_example
```
### 1. Start a new powers of tau ceremony
2020-07-13 07:21:03 +02:00
```sh
snarkjs powersoftau new bn128 12 pot12_0000.ptau -v
2018-08-09 08:16:34 +02:00
```
2020-07-13 18:33:50 +02:00
The first parameter after `new` refers to the type of curve you wish to use. At the moment, we support both `bn128` and `bls12-381`.
2018-08-09 08:16:34 +02:00
The second parameter, in this case `12`, is the power of two of the maximum number of contraints that the ceremony can accept: in this case, the number of constraints is `2 ^ 12 = 4096`. The maximum value supported here is `28`, which means you can use `snarkjs` to securely generate zk-snark parameters for circuits with up to `2 ^ 28` (≈268 million) constraints.
2018-08-09 08:16:34 +02:00
> Note that the creator of the ceremony is also the first contributor.
2018-08-09 08:16:34 +02:00
2020-07-13 18:33:50 +02:00
### 2. Contribute to the ceremony
2020-07-13 07:21:03 +02:00
```sh
snarkjs powersoftau contribute pot12_0000.ptau pot12_0001.ptau --name="First contribution" -v
2020-07-13 07:21:03 +02:00
```
2018-08-09 08:16:34 +02:00
You'll be prompted to enter a random text as an extra source of entropy.
`contribute` takes as input the transcript of the protocol so far, in this case `pot12_0000.ptau`, and outputs a new transcript, in this case `pot12_0001.ptau`, which includes the computation carried out by the new contributor.
`name` can be anything you want, and is just included for reference (it will be printed when you verify the file (step 4).
2018-08-09 08:16:34 +02:00
2020-07-13 18:33:50 +02:00
### 3. Provide a second contribution
2020-07-13 07:21:03 +02:00
```sh
snarkjs powersoftau contribute pot12_0001.ptau pot12_0002.ptau --name="Second contribution" -v -e="some random text"
2020-07-13 07:21:03 +02:00
```
By allowing you to write the random text as part of the command, the `-e` parameter allows `contribute` to be non-interactive.
### 4. Provide a third contribution using third party software
```sh
snarkjs powersoftau export challange pot12_0002.ptau challange_0003
snarkjs powersoftau challange contribute bn128 challange_0003 response_0003
snarkjs powersoftau import response pot12_0002.ptau response_0003 pot12_0003.ptau -n="Third contribution name"
```
2018-08-09 08:16:34 +02:00
The commands above use [this software](https://github.com/kobigurk/phase2-bn254) to help generate a challenge, response, and a new `ptau` file.
2018-08-09 08:16:34 +02:00
### 5. Verify the protocol so far
2020-07-13 07:21:03 +02:00
```sh
snarkjs powersoftau verify pot12_0003.ptau
2020-07-13 07:21:03 +02:00
```
The `verify` command verifies a `ptau` (powers of tau) file. Which means it checks all the contributions to the multi-party computation (MPC) up to that point. It also prints the hashes of all the intermediary results to the console.
2018-08-09 08:16:34 +02:00
If everything checks out, you should see the following at the top of the output:
2018-08-09 08:16:34 +02:00
2020-07-13 07:21:03 +02:00
```sh
[INFO] snarkJS: Powers Of tau file OK!
2018-08-09 08:16:34 +02:00
```
In sum, whenever a new zk-snark project needs to perform a trusted setup, you can just pick the latest `ptau` file, and run the `verify` command to verify the entire chain of challenges and responses so far.
2018-08-09 08:16:34 +02:00
### 6. Apply a random beacon
2020-07-13 07:21:03 +02:00
```sh
snarkjs powersoftau beacon pot12_0003.ptau pot12_beacon.ptau 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f 10 -n="Final Beacon"
2018-08-09 08:16:34 +02:00
```
The next step is to apply a random beacon to it (we need to apply a random beacon in order to finalise phase 1 of the trusted setup).
> A random beacon is a source of public randomness that is not available before a fixed time. The beacon itself can be a delayed hash function (e.g. 2^40 iterations of SHA256) evaluated on some high entropy and publicly available data. Possible sources of data include: the closing value of the stock market on a certain date in the future, the output of a selected set of national lotteries, or the value of a block at a particular height in one or more blockchains. E.g. the hash of the 11 millionth Ethereum block (which as of this writing is some 3 months in the future). See [here](https://eprint.iacr.org/2017/1050.pdf) for more on the importance of a random beacon.
### 7. Prepare phase 2
2020-07-13 07:21:03 +02:00
```sh
2020-07-13 08:10:55 +02:00
snarkjs powersoftau prepare phase2 pot12_beacon.ptau pot12_final.ptau -v
2020-07-13 07:21:03 +02:00
```
2018-08-09 08:16:34 +02:00
We're now ready to prepare phase 2 of the setup (the circuit-specific phase).
### 8. Verify the final protocol transcript
2020-07-13 07:21:03 +02:00
```sh
snarkjs powersoftau verify pot12_final.ptau
```
2020-07-13 07:21:03 +02:00
### Create a circuit
```sh
cat <<EOT > circuit.circom
template Multiplier(n) {
signal private input a;
signal private 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];
2018-08-09 08:16:34 +02:00
}
2020-07-13 07:21:03 +02:00
component main = Multiplier(1000);
EOT
2018-08-09 08:16:34 +02:00
```
2020-07-13 07:21:03 +02:00
This is an example circom fille that allows to test the system with different number of contraints.
In this case 1000, but it can be changed to any nomber of constraints.
### compile the circuit
```sh
circom circuit.circom -r -w -s -v
```
-r to generate the .r1cs file
-w to generate the .wasm file that computes the witness from an input.
-s to generate the .sym file that contains the human readable names of all signals. (Important to debug the circuit)
-v Verbose. To see the progress of the compilation.
### info of a circuit
```sh
snarkjs r1cs info circuit.r1cs
```
### Print the constraints
```sh
snarkjs r1cs print circuit.r1cs
```
### export r1cs to json
```sh
snarkjs r1cs export json circuit.r1cs circuit.r1cs.json
2020-07-13 08:37:21 +02:00
cat circuit.r1cs.json
2020-07-13 07:21:03 +02:00
```
### Generate the reference zKey without contributions from the circuit.
```sh
snarkjs zkey new circuit.r1cs pot12_final.ptau circuit_0000.zkey
```
circuit_0000.zkey does not include any contribution yet, so it cannot be used in a final circuit.
### Contribute in the phase2 ceremony
```sh
snarkjs zkey contribute circuit_0000.zkey circuit_0001.zkey --name="1st Contributor Name" -v
```
### Do a second phase2 contribution
```sh
snarkjs zkey contribute circuit_0001.zkey circuit_0002.zkey --name="Second contribution Name" -v -e="Another random entropy"
```
### Verify the zkey file
```sh
snarkjs zkey verify circuit.r1cs pot12_final.ptau circuit_0002.zkey
```
### Contribute using third party software.
```sh
snarkjs zkey export bellman circuit_0002.zkey challange_phase2_0003
snarkjs zkey bellman contribute bn128 challange_phase2_0003 response_phase2_0003
snarkjs zkey import bellman circuit_0002.zkey response_phase2_0003 circuit_0003.zkey -n="Third contribution name"
```
### Add a beacon
```sh
snarkjs zkey beacon circuit_0003.zkey circuit_final.zkey 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f 10 -n="Final Beacon phase2"
```
### Verify the final file
```sh
snarkjs zkey verify circuit.r1cs pot12_final.ptau circuit_final.zkey
```
### Export the verification key
```sh
snarkjs zkey export verificationkey circuit_final.zkey verification_key.json
```
### Calculat witess
```sh
cat <<EOT > input.json
{"a": 3, "b": 11}
EOT
snarkjs wtns calculate circuit.wasm input.json witness.wtns
```
### Debug witness calculation
In general, when you are developing a new circuit you will want to check for some errors in the witness calculation process.
You can do it by doing
```sh
snarkjs wtns debug circuit.wasm input.json witness.wtns circuit.sym --trigger --get --set
```
This will log every time a new component is started/ended ( --trigger ) when a signal is set (--set) and when it's get (--get)
### Proof calculation
```sh
snarkjs groth16 prove circuit_final.zkey witness.wtns proof.json public.json
```
It is possible also to do the calculate witness and the prove calculation in the same command:
```sh
snarkjs groth16 fullprove input.json circuit.wasm circuit_final.zkey proof.json public.json
```
### Verify
```sh
snarkjs groth16 verify verification_key.json public.json proof.json
```
### Export Solidity Verifier
```sh
snarkjs zkey export solidityverifier circuit_final.zkey verifier.sol
```
You can deploy th "Verifier" smartcontract using remix for example.
In order to simulate a verification call, you can do:
```sh
2020-07-13 09:05:25 +02:00
snarkjs zkey export soliditycalldata public.json proof.json
2020-07-13 07:21:03 +02:00
```
And cut and paste the resolt directlly in the "verifyProof" field in the deployed smart contract.
This call will return true if the proof and the public data is valid.
## Use in node
```sh
2020-07-13 09:05:25 +02:00
npm init
2020-07-13 07:21:03 +02:00
npm install snarkjs
```
2018-08-09 08:16:34 +02:00
2018-09-14 14:27:36 +02:00
```js
2020-07-13 07:21:03 +02:00
const snarkjs = require("snarkjs");
const fs = require("fs");
async function run() {
const { proof, publicSignals } = await snarkjs.groth16.fullProve({a: 10, b: 21}, "circuit.wasm", "circuit_final.zkey");
console.log("Proof: ");
console.log(JSON.stringify(proof, null, 1));
const vKey = JSON.parse(fs.readFileSync("verification_key.json"));
const res = await snarkjs.groth16.verify(vKey, publicSignals, proof);
if (res === true) {
console.log("Verification OK");
} else {
console.log("Invalid proof");
}
2018-08-09 08:16:34 +02:00
}
2020-07-13 07:21:03 +02:00
run().then(() => {
process.exit(0);
});
2018-08-09 08:16:34 +02:00
```
2018-10-21 19:41:44 +02:00
2020-07-13 07:21:03 +02:00
## Use in the web
load snarkjs.min.js and start using it normally.
2020-07-13 09:05:25 +02:00
```
cp node_modules/snarkjs/build/snarkjs.min.js .
```
2020-07-13 07:21:03 +02:00
```html
<!doctype html>
<html>
<head>
<title>Snarkjs client example</title>
</head>
<body>
<h1>Snarkjs client example</h1>
<button id="bGenProof"> Create proof </button>
<!-- JS-generated output will be added here. -->
<pre class="proof"> Proof: <code id="proof"></code></pre>
<pre class="proof"> Result: <code id="result"></code></pre>
<script src="snarkjs.min.js"> </script>
<!-- This is the bundle generated by rollup.js -->
<script>
const proofCompnent = document.getElementById('proof');
const resultComponent = document.getElementById('result');
const bGenProof = document.getElementById("bGenProof");
bGenProof.addEventListener("click", calculateProof);
async function calculateProof() {
const { proof, publicSignals } =
await snarkjs.groth16.fullProve( { a: 3, b: 11}, "circuit.wasm", "circuit_final.zkey");
proofCompnent.innerHTML = JSON.stringify(proof, null, 1);
const vkey = await fetch("verification_key.json").then( function(res) {
return res.json();
});
const res = await snarkjs.groth16.verify(vkey, publicSignals, proof);
resultComponent.innerHTML = res;
}
</script>
</body>
</html>
```
2018-10-21 19:41:44 +02:00
## License
snarkjs is part of the iden3 project copyright 2018 0KIMS association and published with GPL-3 license. Please check the COPYING file for more details.