Merge branch 'plonk'
This commit is contained in:
commit
b4f063b928
106
.vscode/launch.json
vendored
Normal file
106
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "pwa-node",
|
||||
"request": "launch",
|
||||
"name": "plonk setup",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"program": "cli.js",
|
||||
"args": [
|
||||
"pks",
|
||||
"test/plonk_circuit/circuit.r1cs",
|
||||
"test/plonk_circuit/powersOfTau15_final.ptau",
|
||||
"test/plonk_circuit/circuit.zkey"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "pwa-node",
|
||||
"request": "launch",
|
||||
"name": "plonk prove",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"program": "cli.js",
|
||||
"args": [
|
||||
"pkp",
|
||||
"test/plonk_circuit/circuit.zkey",
|
||||
"test/plonk_circuit/witness.wtns",
|
||||
"test/plonk_circuit/proof.json",
|
||||
"test/plonk_circuit/public.json",
|
||||
"-v"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "pwa-node",
|
||||
"request": "launch",
|
||||
"name": "plonk export vk",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"program": "cli.js",
|
||||
"args": [
|
||||
"zkev",
|
||||
"test/plonk_circuit/circuit.zkey",
|
||||
"test/plonk_circuit/verification_key.json",
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "pwa-node",
|
||||
"request": "launch",
|
||||
"name": "plonk verify",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"program": "cli.js",
|
||||
"args": [
|
||||
"pkv",
|
||||
"test/plonk_circuit/verification_key.json",
|
||||
"test/plonk_circuit/public.json",
|
||||
"test/plonk_circuit/proof.json",
|
||||
"-v"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "pwa-node",
|
||||
"request": "launch",
|
||||
"name": "export solidity calldata",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"program": "cli.js",
|
||||
"args": [
|
||||
"zkesc",
|
||||
"test/plonk_circuit/public.json",
|
||||
"test/plonk_circuit/proof.json",
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "pwa-node",
|
||||
"request": "launch",
|
||||
"name": "export solidity verifier",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"program": "cli.js",
|
||||
"args": [
|
||||
"zkesv",
|
||||
"test/plonk_circuit/circuit.zkey",
|
||||
"test/plonk_circuit/verifier.sol",
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Mocha all tests",
|
||||
"program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
|
||||
"cwd": "${workspaceRoot}",
|
||||
"internalConsoleOptions": "openOnSessionStart"
|
||||
}
|
||||
]
|
||||
}
|
42
README.md
42
README.md
@ -299,11 +299,29 @@ cat circuit.r1cs.json
|
||||
|
||||
We export `r1cs` to `json` format to make it human readable.
|
||||
|
||||
### 14. Generate the reference `zkey` without phase 2 contributions
|
||||
|
||||
### 14. Setup
|
||||
|
||||
Currently, snarkjs supports 2 proving systems: groth16 and plonk.
|
||||
|
||||
Groth16 requires a trusted ceremony for each circuit. Plonk does not require it, it's enought with the powers of tau ceremony which is universal.
|
||||
|
||||
#### Plonk
|
||||
```sh
|
||||
snarkjs zkey new circuit.r1cs pot12_final.ptau circuit_0000.zkey
|
||||
snarkjs plonk setup circuit.r1cs pot12_final.ptau circuit_0000.zkey
|
||||
```
|
||||
|
||||
You can jump directly to Section 21 as plonk does not require a specific trusted ceremony.
|
||||
|
||||
### Groth16
|
||||
```sh
|
||||
snarkjs groth16 setup circuit.r1cs pot12_final.ptau circuit_0000.zkey
|
||||
```
|
||||
|
||||
This generates the reference `zkey` without phase 2 contributions
|
||||
|
||||
IMPORTANT: Do not use this zkey in production, as it's not safe. It requires at least a contribution,
|
||||
|
||||
The `zkey new` command creates an initial `zkey` file with zero contributions.
|
||||
|
||||
The `zkey` is a zero-knowledge key that includes both the proving and verification keys as well as phase 2 contributions.
|
||||
@ -403,11 +421,20 @@ The `wtns debug` command logs every time a new component starts/ends (`--trigger
|
||||
|
||||
|
||||
### 24. Create the proof
|
||||
|
||||
#### Plonk
|
||||
|
||||
```sh
|
||||
snarkjs plonk prove circuit_final.zkey witness.wtns proof.json public.json
|
||||
```
|
||||
|
||||
#### Groth16
|
||||
|
||||
```sh
|
||||
snarkjs groth16 prove circuit_final.zkey witness.wtns proof.json public.json
|
||||
```
|
||||
|
||||
We create the proof. `groth16 prove` generates the files `proof.json` and `public.json`: `proof.json` contains the actual proof, whereas `public.json` contains the values of the public inputs and output.
|
||||
We create the proof. this command generates the files `proof.json` and `public.json`: `proof.json` contains the actual proof, whereas `public.json` contains the values of the public inputs and output.
|
||||
|
||||
> Note that it's also possible to create the proof and calculate the witness in the same command by running:
|
||||
> ```sh
|
||||
@ -416,11 +443,18 @@ We create the proof. `groth16 prove` generates the files `proof.json` and `publi
|
||||
|
||||
|
||||
### 25. Verify the proof
|
||||
|
||||
#### Plonk
|
||||
```sh
|
||||
snarkjs plonk verify verification_key.json public.json proof.json
|
||||
```
|
||||
|
||||
#### Groth16
|
||||
```sh
|
||||
snarkjs groth16 verify verification_key.json public.json proof.json
|
||||
```
|
||||
|
||||
We use the `groth16 verify` command to verify the proof, passing in the `verification_key` we exported earlier.
|
||||
We use the this command to verify the proof, passing in the `verification_key` we exported earlier.
|
||||
|
||||
If all is well, you should see that `OK` has been outputted to your console. This signifies the proof is valid.
|
||||
|
||||
|
3048
build/cli.cjs
3048
build/cli.cjs
File diff suppressed because it is too large
Load Diff
2928
build/main.cjs
2928
build/main.cjs
File diff suppressed because it is too large
Load Diff
9506
build/snarkjs.js
9506
build/snarkjs.js
File diff suppressed because one or more lines are too long
11
build/snarkjs.min.js
vendored
11
build/snarkjs.min.js
vendored
File diff suppressed because one or more lines are too long
199
cli.js
199
cli.js
@ -1,20 +1,20 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of jaz (Zero Knowledge Circuit Compiler).
|
||||
This file is part of snarkJS.
|
||||
|
||||
jaz is a free software: you can redistribute it and/or modify it
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
jaz is distributed in the hope that it will be useful, but WITHOUT
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with jaz. If not, see <https://www.gnu.org/licenses/>.
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* eslint-disable no-console */
|
||||
@ -35,6 +35,7 @@ const {stringifyBigInts, unstringifyBigInts} = utils;
|
||||
|
||||
import * as zkey from "./src/zkey.js";
|
||||
import * as groth16 from "./src/groth16.js";
|
||||
import * as plonk from "./src/plonk.js";
|
||||
import * as wtns from "./src/wtns.js";
|
||||
import * as curves from "./src/curves.js";
|
||||
import path from "path";
|
||||
@ -166,13 +167,6 @@ const commands = [
|
||||
alias: ["wej"],
|
||||
action: wtnsExportJson
|
||||
},
|
||||
{
|
||||
cmd: "zkey new [circuit.r1cs] [powersoftau.ptau] [circuit_0000.zkey]",
|
||||
description: "Creates an initial pkey file with zero contributions ",
|
||||
alias: ["zkn"],
|
||||
options: "-verbose|v",
|
||||
action: zkeyNew
|
||||
},
|
||||
{
|
||||
cmd: "zkey contribute <circuit_old.zkey> <circuit_new.zkey>",
|
||||
description: "creates a zkey file with a new contribution",
|
||||
@ -242,11 +236,18 @@ const commands = [
|
||||
action: zkeyExportSolidityVerifier
|
||||
},
|
||||
{
|
||||
cmd: "zkey export soliditycalldata <public.json> <proof.json>",
|
||||
cmd: "zkey export soliditycalldata [public.json] [proof.json]",
|
||||
description: "Generates call parameters ready to be called.",
|
||||
alias: ["zkesc", "generatecall -pub|public -p|proof"],
|
||||
action: zkeyExportSolidityCalldata
|
||||
},
|
||||
{
|
||||
cmd: "groth16 setup [circuit.r1cs] [powersoftau.ptau] [circuit_0000.zkey]",
|
||||
description: "Creates an initial groth16 pkey file with zero contributions",
|
||||
alias: ["g16s", "zkn", "zkey new"],
|
||||
options: "-verbose|v",
|
||||
action: zkeyNew
|
||||
},
|
||||
{
|
||||
cmd: "groth16 prove [circuit_final.zkey] [witness.wtns] [proof.json] [public.json]",
|
||||
description: "Generates a zk Proof from witness",
|
||||
@ -267,7 +268,34 @@ const commands = [
|
||||
alias: ["g16v", "verify -vk|verificationkey -pub|public -p|proof"],
|
||||
action: groth16Verify
|
||||
},
|
||||
|
||||
{
|
||||
cmd: "plonk setup [circuit.r1cs] [powersoftau.ptau] [circuit.zkey]",
|
||||
description: "Creates an initial PLONK pkey ",
|
||||
alias: ["pks"],
|
||||
options: "-verbose|v",
|
||||
action: plonkSetup
|
||||
},
|
||||
{
|
||||
cmd: "plonk prove [circuit.zkey] [witness.wtns] [proof.json] [public.json]",
|
||||
description: "Generates a PLONK Proof from witness",
|
||||
alias: ["pkp"],
|
||||
options: "-verbose|v -protocol",
|
||||
action: plonkProve
|
||||
},
|
||||
{
|
||||
cmd: "plonk fullprove [input.json] [circuit.wasm] [circuit.zkey] [proof.json] [public.json]",
|
||||
description: "Generates a PLONK Proof from input",
|
||||
alias: ["pkf"],
|
||||
options: "-verbose|v -protocol",
|
||||
action: plonkFullProve
|
||||
},
|
||||
{
|
||||
cmd: "plonk verify [verification_key.json] [public.json] [proof.json]",
|
||||
description: "Verify a PLONK Proof",
|
||||
alias: ["pkv"],
|
||||
options: "-verbose|v",
|
||||
action: plonkVerify
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
@ -303,13 +331,6 @@ TODO COMMANDS
|
||||
*/
|
||||
|
||||
|
||||
function p256(n) {
|
||||
let nstr = n.toString(16);
|
||||
while (nstr.length < 64) nstr = "0"+nstr;
|
||||
nstr = `"0x${nstr}"`;
|
||||
return nstr;
|
||||
}
|
||||
|
||||
function changeExt(fileName, newExt) {
|
||||
let S = fileName;
|
||||
while ((S.length>0) && (S[S.length-1] != ".")) S = S.slice(0, S.length-1);
|
||||
@ -544,15 +565,12 @@ async function zkeyExportSolidityVerifier(params, options) {
|
||||
|
||||
if (options.verbose) Logger.setLogLevel("DEBUG");
|
||||
|
||||
let templateName;
|
||||
try {
|
||||
templateName = path.join( __dirname, "templates", "verifier_groth16.sol");
|
||||
await fs.promises.stat(templateName);
|
||||
} catch (err) {
|
||||
templateName = path.join( __dirname, "..", "templates", "verifier_groth16.sol");
|
||||
}
|
||||
const templates = {};
|
||||
|
||||
const verifierCode = await zkey.exportSolidityVerifier(zkeyName, templateName, logger);
|
||||
templates.groth16 = await fs.promises.readFile(path.join(__dirname, "templates", "verifier_groth16.sol.ejs"), "utf8");
|
||||
templates.plonk = await fs.promises.readFile(path.join(__dirname, "templates", "verifier_plonk.sol.ejs"), "utf8");
|
||||
|
||||
const verifierCode = await zkey.exportSolidityVerifier(zkeyName, templates, logger);
|
||||
|
||||
fs.writeFileSync(verifierName, verifierCode, "utf-8");
|
||||
|
||||
@ -582,33 +600,15 @@ async function zkeyExportSolidityCalldata(params, options) {
|
||||
const pub = unstringifyBigInts(JSON.parse(fs.readFileSync(publicName, "utf8")));
|
||||
const proof = unstringifyBigInts(JSON.parse(fs.readFileSync(proofName, "utf8")));
|
||||
|
||||
let inputs = "";
|
||||
for (let i=0; i<pub.length; i++) {
|
||||
if (inputs != "") inputs = inputs + ",";
|
||||
inputs = inputs + p256(pub[i]);
|
||||
}
|
||||
|
||||
let S;
|
||||
if ((typeof proof.protocol === "undefined") || (proof.protocol == "original")) {
|
||||
S=`[${p256(proof.pi_a[0])}, ${p256(proof.pi_a[1])}],` +
|
||||
`[${p256(proof.pi_ap[0])}, ${p256(proof.pi_ap[1])}],` +
|
||||
`[[${p256(proof.pi_b[0][1])}, ${p256(proof.pi_b[0][0])}],[${p256(proof.pi_b[1][1])}, ${p256(proof.pi_b[1][0])}]],` +
|
||||
`[${p256(proof.pi_bp[0])}, ${p256(proof.pi_bp[1])}],` +
|
||||
`[${p256(proof.pi_c[0])}, ${p256(proof.pi_c[1])}],` +
|
||||
`[${p256(proof.pi_cp[0])}, ${p256(proof.pi_cp[1])}],` +
|
||||
`[${p256(proof.pi_h[0])}, ${p256(proof.pi_h[1])}],` +
|
||||
`[${p256(proof.pi_kp[0])}, ${p256(proof.pi_kp[1])}],` +
|
||||
`[${inputs}]`;
|
||||
} else if ((proof.protocol == "groth16")||(proof.protocol == "kimleeoh")) {
|
||||
S=`[${p256(proof.pi_a[0])}, ${p256(proof.pi_a[1])}],` +
|
||||
`[[${p256(proof.pi_b[0][1])}, ${p256(proof.pi_b[0][0])}],[${p256(proof.pi_b[1][1])}, ${p256(proof.pi_b[1][0])}]],` +
|
||||
`[${p256(proof.pi_c[0])}, ${p256(proof.pi_c[1])}],` +
|
||||
`[${inputs}]`;
|
||||
let res;
|
||||
if (proof.protocol == "groth16") {
|
||||
res = await groth16.exportSolidityCallData(proof, pub);
|
||||
} else if (proof.protocol == "plonk") {
|
||||
res = await plonk.exportSolidityCallData(proof, pub);
|
||||
} else {
|
||||
throw new Error("InvalidProof");
|
||||
throw new Error("Invalid Protocol");
|
||||
}
|
||||
|
||||
console.log(S);
|
||||
console.log(res);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -986,3 +986,96 @@ async function zkeyBellmanContribute(params, options) {
|
||||
return zkey.bellmanContribute(curve, challengeName, responseName, options.entropy, logger);
|
||||
}
|
||||
|
||||
|
||||
// plonk setup <circuit.r1cs> <powersoftau.ptau> <circuit.zkey>
|
||||
async function plonkSetup(params, options) {
|
||||
let r1csName;
|
||||
let ptauName;
|
||||
let zkeyName;
|
||||
|
||||
if (params.length < 1) {
|
||||
r1csName = "circuit.r1cs";
|
||||
} else {
|
||||
r1csName = params[0];
|
||||
}
|
||||
|
||||
if (params.length < 2) {
|
||||
ptauName = "powersoftau.ptau";
|
||||
} else {
|
||||
ptauName = params[1];
|
||||
}
|
||||
|
||||
if (params.length < 3) {
|
||||
zkeyName = "circuit.zkey";
|
||||
} else {
|
||||
zkeyName = params[2];
|
||||
}
|
||||
|
||||
if (options.verbose) Logger.setLogLevel("DEBUG");
|
||||
|
||||
return plonk.setup(r1csName, ptauName, zkeyName, logger);
|
||||
}
|
||||
|
||||
|
||||
// plonk prove [circuit.zkey] [witness.wtns] [proof.json] [public.json]
|
||||
async function plonkProve(params, options) {
|
||||
|
||||
const zkeyName = params[0] || "circuit.zkey";
|
||||
const witnessName = params[1] || "witness.wtns";
|
||||
const proofName = params[2] || "proof.json";
|
||||
const publicName = params[3] || "public.json";
|
||||
|
||||
if (options.verbose) Logger.setLogLevel("DEBUG");
|
||||
|
||||
const {proof, publicSignals} = await plonk.prove(zkeyName, witnessName, logger);
|
||||
|
||||
await fs.promises.writeFile(proofName, JSON.stringify(stringifyBigInts(proof), null, 1), "utf-8");
|
||||
await fs.promises.writeFile(publicName, JSON.stringify(stringifyBigInts(publicSignals), null, 1), "utf-8");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// plonk fullprove [input.json] [circuit.wasm] [circuit.zkey] [proof.json] [public.json]
|
||||
async function plonkFullProve(params, options) {
|
||||
|
||||
const inputName = params[0] || "input.json";
|
||||
const wasmName = params[1] || "circuit.wasm";
|
||||
const zkeyName = params[2] || "circuit.zkey";
|
||||
const proofName = params[3] || "proof.json";
|
||||
const publicName = params[4] || "public.json";
|
||||
|
||||
if (options.verbose) Logger.setLogLevel("DEBUG");
|
||||
|
||||
const input = unstringifyBigInts(JSON.parse(await fs.promises.readFile(inputName, "utf8")));
|
||||
|
||||
const {proof, publicSignals} = await plonk.fullProve(input, wasmName, zkeyName, logger);
|
||||
|
||||
await fs.promises.writeFile(proofName, JSON.stringify(stringifyBigInts(proof), null, 1), "utf-8");
|
||||
await fs.promises.writeFile(publicName, JSON.stringify(stringifyBigInts(publicSignals), null, 1), "utf-8");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// plonk verify [verification_key.json] [public.json] [proof.json]
|
||||
async function plonkVerify(params, options) {
|
||||
|
||||
const verificationKeyName = params[0] || "verification_key.json";
|
||||
const publicName = params[1] || "public.json";
|
||||
const proofName = params[2] || "proof.json";
|
||||
|
||||
const verificationKey = unstringifyBigInts(JSON.parse(fs.readFileSync(verificationKeyName, "utf8")));
|
||||
const pub = unstringifyBigInts(JSON.parse(fs.readFileSync(publicName, "utf8")));
|
||||
const proof = unstringifyBigInts(JSON.parse(fs.readFileSync(proofName, "utf8")));
|
||||
|
||||
if (options.verbose) Logger.setLogLevel("DEBUG");
|
||||
|
||||
const isValid = await plonk.verify(verificationKey, pub, proof, logger);
|
||||
|
||||
if (isValid) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ export default {
|
||||
os: empty,
|
||||
crypto: empty,
|
||||
readline: empty,
|
||||
ejs: empty,
|
||||
// Stub out a "global" module that we can inject later
|
||||
global: empty,
|
||||
}),
|
||||
|
1
main.js
1
main.js
@ -5,3 +5,4 @@ export * as powersOfTau from "./src/powersoftau.js";
|
||||
export * as r1cs from "./src/r1cs.js";
|
||||
export * as wtns from "./src/wtns.js";
|
||||
export * as zKey from "./src/zkey.js";
|
||||
export * as plonk from "./src/plonk.js";
|
||||
|
351
package-lock.json
generated
351
package-lock.json
generated
@ -11,8 +11,10 @@
|
||||
"@iden3/binfileutils": "0.0.8",
|
||||
"blake2b-wasm": "https://github.com/jbaylina/blake2b-wasm.git",
|
||||
"circom_runtime": "0.1.13",
|
||||
"ejs": "^3.1.6",
|
||||
"fastfile": "0.0.19",
|
||||
"ffjavascript": "0.2.35",
|
||||
"ffjavascript": "0.2.36",
|
||||
"js-sha3": "^0.8.0",
|
||||
"logplease": "^1.2.15",
|
||||
"r1csfile": "0.0.32",
|
||||
"readline": "^1.3.0"
|
||||
@ -102,15 +104,6 @@
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@babel/highlight/node_modules/escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/highlight/node_modules/has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
@ -379,11 +372,15 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/async": {
|
||||
"version": "0.9.2",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
|
||||
"integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0="
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
||||
"dev": true
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
|
||||
},
|
||||
"node_modules/big-integer": {
|
||||
"version": "1.6.48",
|
||||
@ -417,7 +414,6 @@
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
@ -541,6 +537,16 @@
|
||||
"calcwit": "calcwit.js"
|
||||
}
|
||||
},
|
||||
"node_modules/circom_runtime/node_modules/ffjavascript": {
|
||||
"version": "0.2.35",
|
||||
"resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.35.tgz",
|
||||
"integrity": "sha512-xnC51tWbi0ah4SH+02jEfJyO+P+NiZWnxQrLDLtBYY1Dv3QM5ydxzd+gxnLEfWdT8i1bMM5pIh5P25l6fNCaVQ==",
|
||||
"dependencies": {
|
||||
"big-integer": "^1.6.48",
|
||||
"wasmcurves": "0.0.14",
|
||||
"web-worker": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cli-cursor": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
|
||||
@ -641,8 +647,7 @@
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
||||
"dev": true
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "6.0.5",
|
||||
@ -753,6 +758,20 @@
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ejs": {
|
||||
"version": "3.1.6",
|
||||
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz",
|
||||
"integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==",
|
||||
"dependencies": {
|
||||
"jake": "^10.6.1"
|
||||
},
|
||||
"bin": {
|
||||
"ejs": "bin/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
|
||||
@ -822,6 +841,14 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint": {
|
||||
"version": "6.8.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz",
|
||||
@ -957,15 +984,6 @@
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/eslint/node_modules/escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint/node_modules/has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
@ -1130,9 +1148,9 @@
|
||||
"integrity": "sha512-tz9nWR5KYb6eR2odFQ7oxqEkx8F3YQZ6NBJoJR92YEG3DqYOqyxMck8PKvTVNKx3uwvOqGnLXNScnqpdHRdHGQ=="
|
||||
},
|
||||
"node_modules/ffjavascript": {
|
||||
"version": "0.2.35",
|
||||
"resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.35.tgz",
|
||||
"integrity": "sha512-xnC51tWbi0ah4SH+02jEfJyO+P+NiZWnxQrLDLtBYY1Dv3QM5ydxzd+gxnLEfWdT8i1bMM5pIh5P25l6fNCaVQ==",
|
||||
"version": "0.2.36",
|
||||
"resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.36.tgz",
|
||||
"integrity": "sha512-OPgov0qQiV7wffycylpmEq6rm4Pu68LIMFbB1jrM5bCr1yXqgIMQ6IparbgRuFG5aj3NPmsorrGh7pQJnQlIIw==",
|
||||
"dependencies": {
|
||||
"big-integer": "^1.6.48",
|
||||
"wasmcurves": "0.0.14",
|
||||
@ -1151,15 +1169,6 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/figures/node_modules/escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/file-entry-cache": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz",
|
||||
@ -1172,6 +1181,14 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/filelist": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz",
|
||||
"integrity": "sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==",
|
||||
"dependencies": {
|
||||
"minimatch": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
@ -1656,6 +1673,79 @@
|
||||
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/jake": {
|
||||
"version": "10.8.2",
|
||||
"resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz",
|
||||
"integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==",
|
||||
"dependencies": {
|
||||
"async": "0.9.x",
|
||||
"chalk": "^2.4.2",
|
||||
"filelist": "^1.0.1",
|
||||
"minimatch": "^3.0.4"
|
||||
},
|
||||
"bin": {
|
||||
"jake": "bin/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/jake/node_modules/ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"dependencies": {
|
||||
"color-convert": "^1.9.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/jake/node_modules/chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/jake/node_modules/color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"dependencies": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/jake/node_modules/color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
|
||||
},
|
||||
"node_modules/jake/node_modules/has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/jake/node_modules/supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"dependencies": {
|
||||
"has-flag": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/jest-worker": {
|
||||
"version": "26.6.2",
|
||||
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz",
|
||||
@ -1670,6 +1760,11 @@
|
||||
"node": ">= 10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/js-sha3": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz",
|
||||
"integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q=="
|
||||
},
|
||||
"node_modules/js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
@ -1715,9 +1810,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/lodash": {
|
||||
"version": "4.17.20",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
|
||||
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/logplease": {
|
||||
@ -1753,7 +1848,6 @@
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
@ -1919,15 +2013,6 @@
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/mocha/node_modules/escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mocha/node_modules/find-up": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
|
||||
@ -2388,6 +2473,16 @@
|
||||
"ffjavascript": "0.2.35"
|
||||
}
|
||||
},
|
||||
"node_modules/r1csfile/node_modules/ffjavascript": {
|
||||
"version": "0.2.35",
|
||||
"resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.35.tgz",
|
||||
"integrity": "sha512-xnC51tWbi0ah4SH+02jEfJyO+P+NiZWnxQrLDLtBYY1Dv3QM5ydxzd+gxnLEfWdT8i1bMM5pIh5P25l6fNCaVQ==",
|
||||
"dependencies": {
|
||||
"big-integer": "^1.6.48",
|
||||
"wasmcurves": "0.0.14",
|
||||
"web-worker": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/randombytes": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||
@ -3333,12 +3428,6 @@
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
|
||||
"dev": true
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
||||
"dev": true
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
@ -3570,11 +3659,15 @@
|
||||
"integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
|
||||
"dev": true
|
||||
},
|
||||
"async": {
|
||||
"version": "0.9.2",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
|
||||
"integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0="
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
||||
"dev": true
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
|
||||
},
|
||||
"big-integer": {
|
||||
"version": "1.6.48",
|
||||
@ -3603,7 +3696,6 @@
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
@ -3701,6 +3793,18 @@
|
||||
"requires": {
|
||||
"ffjavascript": "0.2.35",
|
||||
"fnv-plus": "^1.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ffjavascript": {
|
||||
"version": "0.2.35",
|
||||
"resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.35.tgz",
|
||||
"integrity": "sha512-xnC51tWbi0ah4SH+02jEfJyO+P+NiZWnxQrLDLtBYY1Dv3QM5ydxzd+gxnLEfWdT8i1bMM5pIh5P25l6fNCaVQ==",
|
||||
"requires": {
|
||||
"big-integer": "^1.6.48",
|
||||
"wasmcurves": "0.0.14",
|
||||
"web-worker": "^1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cli-cursor": {
|
||||
@ -3787,8 +3891,7 @@
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
||||
"dev": true
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
|
||||
},
|
||||
"cross-spawn": {
|
||||
"version": "6.0.5",
|
||||
@ -3874,6 +3977,14 @@
|
||||
"esutils": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"ejs": {
|
||||
"version": "3.1.6",
|
||||
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz",
|
||||
"integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==",
|
||||
"requires": {
|
||||
"jake": "^10.6.1"
|
||||
}
|
||||
},
|
||||
"emoji-regex": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
|
||||
@ -3933,6 +4044,11 @@
|
||||
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
|
||||
"dev": true
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
|
||||
},
|
||||
"eslint": {
|
||||
"version": "6.8.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz",
|
||||
@ -4019,12 +4135,6 @@
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
|
||||
"dev": true
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
||||
"dev": true
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
@ -4180,9 +4290,9 @@
|
||||
"integrity": "sha512-tz9nWR5KYb6eR2odFQ7oxqEkx8F3YQZ6NBJoJR92YEG3DqYOqyxMck8PKvTVNKx3uwvOqGnLXNScnqpdHRdHGQ=="
|
||||
},
|
||||
"ffjavascript": {
|
||||
"version": "0.2.35",
|
||||
"resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.35.tgz",
|
||||
"integrity": "sha512-xnC51tWbi0ah4SH+02jEfJyO+P+NiZWnxQrLDLtBYY1Dv3QM5ydxzd+gxnLEfWdT8i1bMM5pIh5P25l6fNCaVQ==",
|
||||
"version": "0.2.36",
|
||||
"resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.36.tgz",
|
||||
"integrity": "sha512-OPgov0qQiV7wffycylpmEq6rm4Pu68LIMFbB1jrM5bCr1yXqgIMQ6IparbgRuFG5aj3NPmsorrGh7pQJnQlIIw==",
|
||||
"requires": {
|
||||
"big-integer": "^1.6.48",
|
||||
"wasmcurves": "0.0.14",
|
||||
@ -4196,14 +4306,6 @@
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"escape-string-regexp": "^1.0.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"file-entry-cache": {
|
||||
@ -4215,6 +4317,14 @@
|
||||
"flat-cache": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"filelist": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz",
|
||||
"integrity": "sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==",
|
||||
"requires": {
|
||||
"minimatch": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
@ -4590,6 +4700,63 @@
|
||||
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
|
||||
"dev": true
|
||||
},
|
||||
"jake": {
|
||||
"version": "10.8.2",
|
||||
"resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz",
|
||||
"integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==",
|
||||
"requires": {
|
||||
"async": "0.9.x",
|
||||
"chalk": "^2.4.2",
|
||||
"filelist": "^1.0.1",
|
||||
"minimatch": "^3.0.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"requires": {
|
||||
"color-convert": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"requires": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"jest-worker": {
|
||||
"version": "26.6.2",
|
||||
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz",
|
||||
@ -4601,6 +4768,11 @@
|
||||
"supports-color": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"js-sha3": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz",
|
||||
"integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q=="
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
@ -4640,9 +4812,9 @@
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.20",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
|
||||
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"dev": true
|
||||
},
|
||||
"logplease": {
|
||||
@ -4675,7 +4847,6 @@
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
@ -4810,12 +4981,6 @@
|
||||
"integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
|
||||
"dev": true
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
||||
"dev": true
|
||||
},
|
||||
"find-up": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
|
||||
@ -5173,6 +5338,18 @@
|
||||
"@iden3/binfileutils": "0.0.8",
|
||||
"fastfile": "0.0.19",
|
||||
"ffjavascript": "0.2.35"
|
||||
},
|
||||
"dependencies": {
|
||||
"ffjavascript": {
|
||||
"version": "0.2.35",
|
||||
"resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.35.tgz",
|
||||
"integrity": "sha512-xnC51tWbi0ah4SH+02jEfJyO+P+NiZWnxQrLDLtBYY1Dv3QM5ydxzd+gxnLEfWdT8i1bMM5pIh5P25l6fNCaVQ==",
|
||||
"requires": {
|
||||
"big-integer": "^1.6.48",
|
||||
"wasmcurves": "0.0.14",
|
||||
"web-worker": "^1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"randombytes": {
|
||||
|
@ -41,8 +41,10 @@
|
||||
"@iden3/binfileutils": "0.0.8",
|
||||
"blake2b-wasm": "https://github.com/jbaylina/blake2b-wasm.git",
|
||||
"circom_runtime": "0.1.13",
|
||||
"ejs": "^3.1.6",
|
||||
"fastfile": "0.0.19",
|
||||
"ffjavascript": "0.2.35",
|
||||
"ffjavascript": "0.2.36",
|
||||
"js-sha3": "^0.8.0",
|
||||
"logplease": "^1.2.15",
|
||||
"r1csfile": "0.0.32",
|
||||
"readline": "^1.3.0"
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const SUBARRAY_SIZE = 0x40000;
|
||||
|
||||
const BigArrayHandler = {
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
import pkg from "../package.json";
|
||||
const version = pkg.version;
|
||||
|
@ -1,3 +1,23 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export {default as fullProve} from "./groth16_fullprove.js";
|
||||
export {default as prove} from "./groth16_prove.js";
|
||||
export {default as verify} from "./groth16_verify.js";
|
||||
export {default as exportSolidityCallData} from "./groth16_exportsoliditycalldata.js";
|
||||
|
42
src/groth16_exportsoliditycalldata.js
Normal file
42
src/groth16_exportsoliditycalldata.js
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
function p256(n) {
|
||||
let nstr = n.toString(16);
|
||||
while (nstr.length < 64) nstr = "0"+nstr;
|
||||
nstr = `"0x${nstr}"`;
|
||||
return nstr;
|
||||
}
|
||||
|
||||
export default async function groth16ExportSolidityCallData(proof, pub) {
|
||||
|
||||
let inputs = "";
|
||||
for (let i=0; i<pub.length; i++) {
|
||||
if (inputs != "") inputs = inputs + ",";
|
||||
inputs = inputs + p256(pub[i]);
|
||||
}
|
||||
|
||||
let S;
|
||||
S=`[${p256(proof.pi_a[0])}, ${p256(proof.pi_a[1])}],` +
|
||||
`[[${p256(proof.pi_b[0][1])}, ${p256(proof.pi_b[0][0])}],[${p256(proof.pi_b[1][1])}, ${p256(proof.pi_b[1][0])}]],` +
|
||||
`[${p256(proof.pi_c[0])}, ${p256(proof.pi_c[1])}],` +
|
||||
`[${inputs}]`;
|
||||
|
||||
return S;
|
||||
}
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import groth16_prove from "./groth16_prove.js";
|
||||
import wtns_calculate from "./wtns_calculate.js";
|
||||
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import * as binFileUtils from "@iden3/binfileutils";
|
||||
import * as zkeyUtils from "./zkey_utils.js";
|
||||
import * as wtnsUtils from "./wtns_utils.js";
|
||||
@ -13,7 +32,11 @@ export default async function groth16Prove(zkeyFileName, witnessFileName, logger
|
||||
|
||||
const {fd: fdZKey, sections: sectionsZKey} = await binFileUtils.readBinFile(zkeyFileName, "zkey", 2, 1<<25, 1<<23);
|
||||
|
||||
const zkey = await zkeyUtils.readHeader(fdZKey, sectionsZKey, "groth16");
|
||||
const zkey = await zkeyUtils.readHeader(fdZKey, sectionsZKey);
|
||||
|
||||
if (zkey.protocol != "groth16") {
|
||||
throw new Error("zkey file is not groth16");
|
||||
}
|
||||
|
||||
if (!Scalar.eq(zkey.r, wtns.q)) {
|
||||
throw new Error("Curve of the witness does not match the curve of the proving key");
|
||||
@ -109,6 +132,7 @@ export default async function groth16Prove(zkeyFileName, witnessFileName, logger
|
||||
proof.pi_c = G1.toObject(G1.toAffine(proof.pi_c));
|
||||
|
||||
proof.protocol = "groth16";
|
||||
proof.curve = curve.name;
|
||||
|
||||
await fdZKey.close();
|
||||
await fdWtns.close();
|
||||
@ -162,7 +186,7 @@ async function buldABC1(curve, zkey, witness, coeffs, logger) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
async function buldABC(curve, zkey, witness, coeffs, logger) {
|
||||
const concurrency = curve.tm.concurrency;
|
||||
const sCoef = 4*3 + zkey.n8r;
|
||||
@ -291,7 +315,7 @@ async function buldABC(curve, zkey, witness, coeffs, logger) {
|
||||
return 4 + m*sCoef;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
async function joinABC(curve, zkey, a, b, c, logger) {
|
||||
const MAX_CHUNK_SIZE = 1 << 22;
|
||||
|
@ -74,4 +74,4 @@ export default async function groth16Verify(vk_verifier, publicSignals, proof, l
|
||||
|
||||
if (logger) logger.info("OK!");
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
@ -1,3 +1,21 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import blake2b from "blake2b-wasm";
|
||||
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import * as fastFile from "fastfile";
|
||||
|
||||
export default async function loadSymbols(symFileName) {
|
||||
|
19
src/misc.js
19
src/misc.js
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* global window */
|
||||
import Blake2b from "blake2b-wasm";
|
||||
import readline from "readline";
|
||||
|
@ -1,3 +1,21 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import * as binFileUtils from "@iden3/binfileutils";
|
||||
|
||||
|
24
src/plonk.js
Normal file
24
src/plonk.js
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export {default as setup} from "./plonk_setup.js";
|
||||
export {default as fullProve} from "./plonk_fullprove.js";
|
||||
export {default as prove} from "./plonk_prove.js";
|
||||
export {default as verify} from "./plonk_verify.js";
|
||||
export {default as exportSolidityCallData} from "./plonk_exportsoliditycalldata.js";
|
68
src/plonk_exportsoliditycalldata.js
Normal file
68
src/plonk_exportsoliditycalldata.js
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
Copyright 2021 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { getCurveFromName } from "./curves.js";
|
||||
|
||||
function i2hex(i) {
|
||||
return ("0" + i.toString(16)).slice(-2);
|
||||
}
|
||||
|
||||
function p256(n) {
|
||||
let nstr = n.toString(16);
|
||||
while (nstr.length < 64) nstr = "0"+nstr;
|
||||
nstr = `"0x${nstr}"`;
|
||||
return nstr;
|
||||
}
|
||||
|
||||
export default async function plonkExportSolidityCallData(proof, pub) {
|
||||
|
||||
const curve = await getCurveFromName(proof.curve);
|
||||
const G1 = curve.G1;
|
||||
const Fr = curve.Fr;
|
||||
|
||||
let inputs = "";
|
||||
for (let i=0; i<pub.length; i++) {
|
||||
if (inputs != "") inputs = inputs + ",";
|
||||
inputs = inputs + p256(pub[i]);
|
||||
}
|
||||
|
||||
const proofBuff = new Uint8Array(G1.F.n8*2*9 + Fr.n8*7);
|
||||
G1.toRprUncompressed(proofBuff, 0, G1.e(proof.A));
|
||||
G1.toRprUncompressed(proofBuff, G1.F.n8*2, G1.e(proof.B));
|
||||
G1.toRprUncompressed(proofBuff, G1.F.n8*4, G1.e(proof.C));
|
||||
G1.toRprUncompressed(proofBuff, G1.F.n8*6, G1.e(proof.Z));
|
||||
G1.toRprUncompressed(proofBuff, G1.F.n8*8, G1.e(proof.T1));
|
||||
G1.toRprUncompressed(proofBuff, G1.F.n8*10, G1.e(proof.T2));
|
||||
G1.toRprUncompressed(proofBuff, G1.F.n8*12, G1.e(proof.T3));
|
||||
G1.toRprUncompressed(proofBuff, G1.F.n8*14, G1.e(proof.Wxi));
|
||||
G1.toRprUncompressed(proofBuff, G1.F.n8*16, G1.e(proof.Wxiw));
|
||||
Fr.toRprBE(proofBuff, G1.F.n8*18 , Fr.e(proof.eval_a));
|
||||
Fr.toRprBE(proofBuff, G1.F.n8*18 + Fr.n8, Fr.e(proof.eval_b));
|
||||
Fr.toRprBE(proofBuff, G1.F.n8*18 + Fr.n8*2, Fr.e(proof.eval_c));
|
||||
Fr.toRprBE(proofBuff, G1.F.n8*18 + Fr.n8*3, Fr.e(proof.eval_s1));
|
||||
Fr.toRprBE(proofBuff, G1.F.n8*18 + Fr.n8*4, Fr.e(proof.eval_s2));
|
||||
Fr.toRprBE(proofBuff, G1.F.n8*18 + Fr.n8*5, Fr.e(proof.eval_zw));
|
||||
Fr.toRprBE(proofBuff, G1.F.n8*18 + Fr.n8*6, Fr.e(proof.eval_r));
|
||||
|
||||
const proofHex = Array.from(proofBuff).map(i2hex).join("");
|
||||
|
||||
const S="0x"+proofHex+",["+inputs+"]";
|
||||
|
||||
return S;
|
||||
}
|
29
src/plonk_fullprove.js
Normal file
29
src/plonk_fullprove.js
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
Copyright 2021 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import plonk_prove from "./plonk_prove.js";
|
||||
import wtns_calculate from "./wtns_calculate.js";
|
||||
|
||||
export default async function plonkFullProve(input, wasmFile, zkeyFileName, logger) {
|
||||
const wtns= {
|
||||
type: "mem"
|
||||
};
|
||||
await wtns_calculate(input, wasmFile, wtns);
|
||||
return await plonk_prove(zkeyFileName, wtns, logger);
|
||||
}
|
845
src/plonk_prove.js
Normal file
845
src/plonk_prove.js
Normal file
@ -0,0 +1,845 @@
|
||||
/*
|
||||
Copyright 2021 0kims association.
|
||||
|
||||
This file is part of snarkjs.
|
||||
|
||||
snarkjs is a free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation, either version 3 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
snarkjs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
snarkjs. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Implementation of this paper: https://eprint.iacr.org/2019/953.pdf section 8.4 */
|
||||
|
||||
import * as binFileUtils from "@iden3/binfileutils";
|
||||
import * as zkeyUtils from "./zkey_utils.js";
|
||||
import * as wtnsUtils from "./wtns_utils.js";
|
||||
import { getCurveFromQ as getCurve } from "./curves.js";
|
||||
import { Scalar, utils, BigBuffer } from "ffjavascript";
|
||||
const {stringifyBigInts} = utils;
|
||||
import jsSha3 from "js-sha3";
|
||||
const { keccak256 } = jsSha3;
|
||||
|
||||
export default async function plonk16Prove(zkeyFileName, witnessFileName, logger) {
|
||||
const {fd: fdWtns, sections: sectionsWtns} = await binFileUtils.readBinFile(witnessFileName, "wtns", 2, 1<<25, 1<<23);
|
||||
|
||||
const wtns = await wtnsUtils.readHeader(fdWtns, sectionsWtns);
|
||||
|
||||
const {fd: fdZKey, sections: sectionsZKey} = await binFileUtils.readBinFile(zkeyFileName, "zkey", 2, 1<<25, 1<<23);
|
||||
|
||||
const zkey = await zkeyUtils.readHeader(fdZKey, sectionsZKey);
|
||||
if (zkey.protocol != "plonk") {
|
||||
throw new Error("zkey file is not groth16");
|
||||
}
|
||||
|
||||
if (!Scalar.eq(zkey.r, wtns.q)) {
|
||||
throw new Error("Curve of the witness does not match the curve of the proving key");
|
||||
}
|
||||
|
||||
if (wtns.nWitness != zkey.nVars -zkey.nAdditions) {
|
||||
throw new Error(`Invalid witness length. Circuit: ${zkey.nVars}, witness: ${wtns.nWitness}, ${zkey.nAdditions}`);
|
||||
}
|
||||
|
||||
const curve = await getCurve(zkey.q);
|
||||
const Fr = curve.Fr;
|
||||
const G1 = curve.G1;
|
||||
const n8r = curve.Fr.n8;
|
||||
|
||||
if (logger) logger.debug("Reading Wtns");
|
||||
const buffWitness = await binFileUtils.readSection(fdWtns, sectionsWtns, 2);
|
||||
// First element in plonk is not used and can be any value. (But always the same).
|
||||
// We set it to zero to go faster in the exponentiations.
|
||||
buffWitness.set(Fr.zero, 0);
|
||||
const buffInternalWitness = new BigBuffer(n8r*zkey.nAdditions);
|
||||
|
||||
await calculateAdditions();
|
||||
|
||||
let A,B,C,Z;
|
||||
let A4, B4, C4, Z4;
|
||||
let pol_a,pol_b,pol_c, pol_z, pol_t, pol_r;
|
||||
let proof = {};
|
||||
|
||||
const sigmaBuff = new BigBuffer(zkey.domainSize*n8r*4*3);
|
||||
let o = sectionsZKey[12][0].p + zkey.domainSize*n8r;
|
||||
await fdZKey.readToBuffer(sigmaBuff, 0 , zkey.domainSize*n8r*4, o);
|
||||
o += zkey.domainSize*n8r*5;
|
||||
await fdZKey.readToBuffer(sigmaBuff, zkey.domainSize*n8r*4 , zkey.domainSize*n8r*4, o);
|
||||
o += zkey.domainSize*n8r*5;
|
||||
await fdZKey.readToBuffer(sigmaBuff, zkey.domainSize*n8r*8 , zkey.domainSize*n8r*4, o);
|
||||
|
||||
const pol_s1 = new BigBuffer(zkey.domainSize*n8r);
|
||||
await fdZKey.readToBuffer(pol_s1, 0 , zkey.domainSize*n8r, sectionsZKey[12][0].p);
|
||||
|
||||
const pol_s2 = new BigBuffer(zkey.domainSize*n8r);
|
||||
await fdZKey.readToBuffer(pol_s2, 0 , zkey.domainSize*n8r, sectionsZKey[12][0].p + 5*zkey.domainSize*n8r);
|
||||
|
||||
const PTau = await binFileUtils.readSection(fdZKey, sectionsZKey, 14);
|
||||
|
||||
|
||||
const ch = {};
|
||||
|
||||
await round1();
|
||||
await round2();
|
||||
await round3();
|
||||
await round4();
|
||||
await round5();
|
||||
|
||||
|
||||
///////////////////////
|
||||
// Final adjustments //
|
||||
///////////////////////
|
||||
|
||||
proof.protocol = "plonk";
|
||||
proof.curve = curve.name;
|
||||
|
||||
await fdZKey.close();
|
||||
await fdWtns.close();
|
||||
|
||||
let publicSignals = [];
|
||||
|
||||
for (let i=1; i<= zkey.nPublic; i++) {
|
||||
const pub = buffWitness.slice(i*Fr.n8, i*Fr.n8+Fr.n8);
|
||||
publicSignals.push(Scalar.fromRprLE(pub));
|
||||
}
|
||||
|
||||
proof.A = G1.toObject(proof.A);
|
||||
proof.B = G1.toObject(proof.B);
|
||||
proof.C = G1.toObject(proof.C);
|
||||
proof.Z = G1.toObject(proof.Z);
|
||||
|
||||
proof.T1 = G1.toObject(proof.T1);
|
||||
proof.T2 = G1.toObject(proof.T2);
|
||||
proof.T3 = G1.toObject(proof.T3);
|
||||
|
||||
proof.eval_a = Fr.toObject(proof.eval_a);
|
||||
proof.eval_b = Fr.toObject(proof.eval_b);
|
||||
proof.eval_c = Fr.toObject(proof.eval_c);
|
||||
proof.eval_s1 = Fr.toObject(proof.eval_s1);
|
||||
proof.eval_s2 = Fr.toObject(proof.eval_s2);
|
||||
proof.eval_zw = Fr.toObject(proof.eval_zw);
|
||||
proof.eval_t = Fr.toObject(proof.eval_t);
|
||||
proof.eval_r = Fr.toObject(proof.eval_r);
|
||||
|
||||
proof.Wxi = G1.toObject(proof.Wxi);
|
||||
proof.Wxiw = G1.toObject(proof.Wxiw);
|
||||
|
||||
delete proof.eval_t;
|
||||
|
||||
proof = stringifyBigInts(proof);
|
||||
publicSignals = stringifyBigInts(publicSignals);
|
||||
|
||||
return {proof, publicSignals};
|
||||
|
||||
async function calculateAdditions() {
|
||||
const additionsBuff = await binFileUtils.readSection(fdZKey, sectionsZKey, 3);
|
||||
|
||||
const sSum = 8+curve.Fr.n8*2;
|
||||
|
||||
for (let i=0; i<zkey.nAdditions; i++) {
|
||||
const ai= readUInt32(additionsBuff, i*sSum);
|
||||
const bi= readUInt32(additionsBuff, i*sSum+4);
|
||||
const ac= additionsBuff.slice(i*sSum+8, i*sSum+8+n8r);
|
||||
const bc= additionsBuff.slice(i*sSum+8+n8r, i*sSum+8+n8r*2);
|
||||
const aw= getWitness(ai);
|
||||
const bw= getWitness(bi);
|
||||
|
||||
const r = curve.Fr.add(
|
||||
curve.Fr.mul(ac, aw),
|
||||
curve.Fr.mul(bc, bw)
|
||||
);
|
||||
buffInternalWitness.set(r, n8r*i);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async function buildABC() {
|
||||
let A = new BigBuffer(zkey.domainSize * n8r);
|
||||
let B = new BigBuffer(zkey.domainSize * n8r);
|
||||
let C = new BigBuffer(zkey.domainSize * n8r);
|
||||
|
||||
const aMap = await binFileUtils.readSection(fdZKey, sectionsZKey, 4);
|
||||
const bMap = await binFileUtils.readSection(fdZKey, sectionsZKey, 5);
|
||||
const cMap = await binFileUtils.readSection(fdZKey, sectionsZKey, 6);
|
||||
|
||||
for (let i=0; i<zkey.nConstrains; i++) {
|
||||
const iA = readUInt32(aMap, i*4);
|
||||
A.set(getWitness(iA), i*n8r);
|
||||
const iB = readUInt32(bMap, i*4);
|
||||
B.set(getWitness(iB), i*n8r);
|
||||
const iC = readUInt32(cMap, i*4);
|
||||
C.set(getWitness(iC), i*n8r);
|
||||
}
|
||||
|
||||
A = await Fr.batchToMontgomery(A);
|
||||
B = await Fr.batchToMontgomery(B);
|
||||
C = await Fr.batchToMontgomery(C);
|
||||
|
||||
return [A,B,C];
|
||||
}
|
||||
|
||||
function readUInt32(b, o) {
|
||||
const buff = b.slice(o, o+4);
|
||||
const buffV = new DataView(buff.buffer, buff.byteOffset, buff.byteLength);
|
||||
return buffV.getUint32(0, true);
|
||||
}
|
||||
|
||||
function getWitness(idx) {
|
||||
if (idx < zkey.nVars-zkey.nAdditions) {
|
||||
return buffWitness.slice(idx*n8r, idx*n8r+n8r);
|
||||
} else if (idx < zkey.nVars) {
|
||||
return buffInternalWitness.slice((idx - (zkey.nVars-zkey.nAdditions))*n8r, (idx-(zkey.nVars-zkey.nAdditions))*n8r + n8r);
|
||||
} else {
|
||||
return curve.Fr.zero;
|
||||
}
|
||||
}
|
||||
|
||||
async function round1() {
|
||||
ch.b = [];
|
||||
for (let i=1; i<=9; i++) {
|
||||
ch.b[i] = curve.Fr.random();
|
||||
}
|
||||
|
||||
[A, B, C] = await buildABC();
|
||||
|
||||
[pol_a, A4] = await to4T(A, [ch.b[2], ch.b[1]]);
|
||||
[pol_b, B4] = await to4T(B, [ch.b[4], ch.b[3]]);
|
||||
[pol_c, C4] = await to4T(C, [ch.b[6], ch.b[5]]);
|
||||
|
||||
|
||||
proof.A = await expTau(pol_a, "multiexp A");
|
||||
proof.B = await expTau(pol_b, "multiexp B");
|
||||
proof.C = await expTau(pol_c, "multiexp C");
|
||||
}
|
||||
|
||||
async function round2() {
|
||||
|
||||
const transcript1 = new Uint8Array(G1.F.n8*2*3);
|
||||
G1.toRprUncompressed(transcript1, 0, proof.A);
|
||||
G1.toRprUncompressed(transcript1, G1.F.n8*2, proof.B);
|
||||
G1.toRprUncompressed(transcript1, G1.F.n8*4, proof.C);
|
||||
|
||||
ch.beta = hashToFr(transcript1);
|
||||
if (logger) logger.debug("beta: " + Fr.toString(ch.beta));
|
||||
|
||||
const transcript2 = new Uint8Array(n8r);
|
||||
Fr.toRprBE(transcript2, 0, ch.beta);
|
||||
ch.gamma = hashToFr(transcript2);
|
||||
if (logger) logger.debug("gamma: " + Fr.toString(ch.gamma));
|
||||
|
||||
let numArr = new BigBuffer(Fr.n8*zkey.domainSize);
|
||||
let denArr = new BigBuffer(Fr.n8*zkey.domainSize);
|
||||
|
||||
numArr.set(Fr.one, 0);
|
||||
denArr.set(Fr.one, 0);
|
||||
|
||||
let w = Fr.one;
|
||||
for (let i=0; i<zkey.domainSize; i++) {
|
||||
let n1 = A.slice(i*n8r, (i+1)*n8r);
|
||||
n1 = Fr.add( n1, Fr.mul(ch.beta, w) );
|
||||
n1 = Fr.add( n1, ch.gamma );
|
||||
|
||||
let n2 = B.slice(i*n8r, (i+1)*n8r);
|
||||
n2 = Fr.add( n2, Fr.mul(zkey.k1, Fr.mul(ch.beta, w) ));
|
||||
n2 = Fr.add( n2, ch.gamma );
|
||||
|
||||
let n3 = C.slice(i*n8r, (i+1)*n8r);
|
||||
n3 = Fr.add( n3, Fr.mul(zkey.k2, Fr.mul(ch.beta, w) ));
|
||||
n3 = Fr.add( n3, ch.gamma );
|
||||
|
||||
const num = Fr.mul(n1, Fr.mul(n2, n3));
|
||||
|
||||
let d1 = A.slice(i*n8r, (i+1)*n8r);
|
||||
d1 = Fr.add(d1, Fr.mul( sigmaBuff.slice(i*n8r*4, i*n8r*4 + n8r) , ch.beta));
|
||||
d1 = Fr.add(d1, ch.gamma);
|
||||
|
||||
let d2 = B.slice(i*n8r, (i+1)*n8r);
|
||||
d2 = Fr.add(d2, Fr.mul( sigmaBuff.slice((zkey.domainSize + i)*4*n8r, (zkey.domainSize + i)*4*n8r+n8r) , ch.beta));
|
||||
d2 = Fr.add(d2, ch.gamma);
|
||||
|
||||
let d3 = C.slice(i*n8r, (i+1)*n8r);
|
||||
d3 = Fr.add(d3, Fr.mul( sigmaBuff.slice((zkey.domainSize*2 + i)*4*n8r, (zkey.domainSize*2 + i)*4*n8r + n8r) , ch.beta));
|
||||
d3 = Fr.add(d3, ch.gamma);
|
||||
|
||||
const den = Fr.mul(d1, Fr.mul(d2, d3));
|
||||
|
||||
numArr.set(
|
||||
Fr.mul(
|
||||
numArr.slice(i*n8r,(i+1)*n8r) ,
|
||||
num
|
||||
),
|
||||
((i+1)%zkey.domainSize)*n8r
|
||||
);
|
||||
|
||||
denArr.set(
|
||||
Fr.mul(
|
||||
denArr.slice(i*n8r,(i+1)*n8r) ,
|
||||
den
|
||||
),
|
||||
((i+1)%zkey.domainSize)*n8r
|
||||
);
|
||||
|
||||
w = Fr.mul(w, Fr.w[zkey.power]);
|
||||
}
|
||||
|
||||
denArr = await Fr.batchInverse(denArr);
|
||||
|
||||
// TODO: Do it in assembly and in parallel
|
||||
for (let i=0; i<zkey.domainSize; i++) {
|
||||
numArr.set( Fr.mul( numArr.slice(i*n8r, (i+1)*n8r), denArr.slice(i*n8r, (i+1)*n8r) ) ,i*n8r);
|
||||
}
|
||||
|
||||
if (!Fr.eq(numArr.slice(0, n8r), Fr.one)) {
|
||||
throw new Error("Copy constraints does not match");
|
||||
}
|
||||
|
||||
Z = numArr;
|
||||
|
||||
[pol_z, Z4] = await to4T(Z, [ch.b[9], ch.b[8], ch.b[7]]);
|
||||
|
||||
proof.Z = await expTau( pol_z, "multiexp Z");
|
||||
}
|
||||
|
||||
async function round3() {
|
||||
|
||||
/*
|
||||
async function checkDegree(P) {
|
||||
const p = await curve.Fr.ifft(P);
|
||||
let deg = (P.byteLength/n8r)-1;
|
||||
while ((deg>0)&&(Fr.isZero(p.slice(deg*n8r, deg*n8r+n8r)))) deg--;
|
||||
return deg;
|
||||
}
|
||||
|
||||
function printPol(P) {
|
||||
const n=(P.byteLength/n8r);
|
||||
console.log("[");
|
||||
for (let i=0; i<n; i++) {
|
||||
console.log(Fr.toString(P.slice(i*n8r, i*n8r+n8r)));
|
||||
}
|
||||
console.log("]");
|
||||
}
|
||||
*/
|
||||
|
||||
const QM4 = new BigBuffer(zkey.domainSize*4*n8r);
|
||||
await fdZKey.readToBuffer(QM4, 0 , zkey.domainSize*n8r*4, sectionsZKey[7][0].p + zkey.domainSize*n8r);
|
||||
|
||||
const QL4 = new BigBuffer(zkey.domainSize*4*n8r);
|
||||
await fdZKey.readToBuffer(QL4, 0 , zkey.domainSize*n8r*4, sectionsZKey[8][0].p + zkey.domainSize*n8r);
|
||||
|
||||
const QR4 = new BigBuffer(zkey.domainSize*4*n8r);
|
||||
await fdZKey.readToBuffer(QR4, 0 , zkey.domainSize*n8r*4, sectionsZKey[9][0].p + zkey.domainSize*n8r);
|
||||
|
||||
const QO4 = new BigBuffer(zkey.domainSize*4*n8r);
|
||||
await fdZKey.readToBuffer(QO4, 0 , zkey.domainSize*n8r*4, sectionsZKey[10][0].p + zkey.domainSize*n8r);
|
||||
|
||||
const QC4 = new BigBuffer(zkey.domainSize*4*n8r);
|
||||
await fdZKey.readToBuffer(QC4, 0 , zkey.domainSize*n8r*4, sectionsZKey[11][0].p + zkey.domainSize*n8r);
|
||||
|
||||
const lPols = await binFileUtils.readSection(fdZKey, sectionsZKey, 13);
|
||||
|
||||
const transcript3 = new Uint8Array(G1.F.n8*2);
|
||||
G1.toRprUncompressed(transcript3, 0, proof.Z);
|
||||
|
||||
ch.alpha = hashToFr(transcript3);
|
||||
|
||||
if (logger) logger.debug("alpha: " + Fr.toString(ch.alpha));
|
||||
|
||||
|
||||
const Z1 = [
|
||||
Fr.zero,
|
||||
Fr.add(Fr.e(-1), Fr.w[2]),
|
||||
Fr.e(-2),
|
||||
Fr.sub(Fr.e(-1), Fr.w[2]),
|
||||
];
|
||||
|
||||
const Z2 = [
|
||||
Fr.zero,
|
||||
Fr.add(Fr.zero, Fr.mul(Fr.e(-2), Fr.w[2])),
|
||||
Fr.e(4),
|
||||
Fr.sub(Fr.zero, Fr.mul(Fr.e(-2), Fr.w[2])),
|
||||
];
|
||||
|
||||
const Z3 = [
|
||||
Fr.zero,
|
||||
Fr.add(Fr.e(2), Fr.mul(Fr.e(2), Fr.w[2])),
|
||||
Fr.e(-8),
|
||||
Fr.sub(Fr.e(2), Fr.mul(Fr.e(2), Fr.w[2])),
|
||||
];
|
||||
|
||||
const T = new BigBuffer(zkey.domainSize*4*n8r);
|
||||
const Tz = new BigBuffer(zkey.domainSize*4*n8r);
|
||||
|
||||
let w = Fr.one;
|
||||
for (let i=0; i<zkey.domainSize*4; i++) {
|
||||
const a = A4.slice(i*n8r, i*n8r+n8r);
|
||||
const b = B4.slice(i*n8r, i*n8r+n8r);
|
||||
const c = C4.slice(i*n8r, i*n8r+n8r);
|
||||
const z = Z4.slice(i*n8r, i*n8r+n8r);
|
||||
const zw = Z4.slice(((i+zkey.domainSize*4+4)%(zkey.domainSize*4)) *n8r, ((i+zkey.domainSize*4+4)%(zkey.domainSize*4)) *n8r +n8r);
|
||||
const qm = QM4.slice(i*n8r, i*n8r+n8r);
|
||||
const ql = QL4.slice(i*n8r, i*n8r+n8r);
|
||||
const qr = QR4.slice(i*n8r, i*n8r+n8r);
|
||||
const qo = QO4.slice(i*n8r, i*n8r+n8r);
|
||||
const qc = QC4.slice(i*n8r, i*n8r+n8r);
|
||||
const s1 = sigmaBuff.slice(i*n8r, i*n8r+n8r);
|
||||
const s2 = sigmaBuff.slice((i+zkey.domainSize*4)*n8r, (i+zkey.domainSize*4)*n8r+n8r);
|
||||
const s3 = sigmaBuff.slice((i+zkey.domainSize*8)*n8r, (i+zkey.domainSize*8)*n8r+n8r);
|
||||
const ap = Fr.add(ch.b[2], Fr.mul(ch.b[1], w));
|
||||
const bp = Fr.add(ch.b[4], Fr.mul(ch.b[3], w));
|
||||
const cp = Fr.add(ch.b[6], Fr.mul(ch.b[5], w));
|
||||
const w2 = Fr.square(w);
|
||||
const zp = Fr.add(Fr.add(Fr.mul(ch.b[7], w2), Fr.mul(ch.b[8], w)), ch.b[9]);
|
||||
const wW = Fr.mul(w, Fr.w[zkey.power]);
|
||||
const wW2 = Fr.square(wW);
|
||||
const zWp = Fr.add(Fr.add(Fr.mul(ch.b[7], wW2), Fr.mul(ch.b[8], wW)), ch.b[9]);
|
||||
|
||||
let pl = Fr.zero;
|
||||
for (let j=0; j<zkey.nPublic; j++) {
|
||||
pl = Fr.sub(pl, Fr.mul(
|
||||
lPols.slice( (j*5*zkey.domainSize+ zkey.domainSize+ i)*n8r, (j*5*zkey.domainSize+ zkey.domainSize + i+1)*n8r),
|
||||
A.slice(j*n8r, (j+1)*n8r)
|
||||
));
|
||||
}
|
||||
|
||||
let [e1, e1z] = mul2(a, b, ap, bp, i%4);
|
||||
e1 = Fr.mul(e1, qm);
|
||||
e1z = Fr.mul(e1z, qm);
|
||||
|
||||
e1 = Fr.add(e1, Fr.mul(a, ql));
|
||||
e1z = Fr.add(e1z, Fr.mul(ap, ql));
|
||||
|
||||
e1 = Fr.add(e1, Fr.mul(b, qr));
|
||||
e1z = Fr.add(e1z, Fr.mul(bp, qr));
|
||||
|
||||
e1 = Fr.add(e1, Fr.mul(c, qo));
|
||||
e1z = Fr.add(e1z, Fr.mul(cp, qo));
|
||||
|
||||
e1 = Fr.add(e1, pl);
|
||||
e1 = Fr.add(e1, qc);
|
||||
|
||||
const betaw = Fr.mul(ch.beta, w);
|
||||
let e2a =a;
|
||||
e2a = Fr.add(e2a, betaw);
|
||||
e2a = Fr.add(e2a, ch.gamma);
|
||||
|
||||
let e2b =b;
|
||||
e2b = Fr.add(e2b, Fr.mul(betaw, zkey.k1));
|
||||
e2b = Fr.add(e2b, ch.gamma);
|
||||
|
||||
let e2c =c;
|
||||
e2c = Fr.add(e2c, Fr.mul(betaw, zkey.k2));
|
||||
e2c = Fr.add(e2c, ch.gamma);
|
||||
|
||||
let e2d = z;
|
||||
|
||||
let [e2, e2z] = mul4(e2a, e2b, e2c, e2d, ap, bp, cp, zp, i%4);
|
||||
e2 = Fr.mul(e2, ch.alpha);
|
||||
e2z = Fr.mul(e2z, ch.alpha);
|
||||
|
||||
let e3a = a;
|
||||
e3a = Fr.add(e3a, Fr.mul(ch.beta, s1));
|
||||
e3a = Fr.add(e3a, ch.gamma);
|
||||
|
||||
let e3b = b;
|
||||
e3b = Fr.add(e3b, Fr.mul(ch.beta,s2));
|
||||
e3b = Fr.add(e3b, ch.gamma);
|
||||
|
||||
let e3c = c;
|
||||
e3c = Fr.add(e3c, Fr.mul(ch.beta,s3));
|
||||
e3c = Fr.add(e3c, ch.gamma);
|
||||
|
||||
let e3d = zw;
|
||||
let [e3, e3z] = mul4(e3a, e3b, e3c, e3d, ap, bp, cp, zWp, i%4);
|
||||
|
||||
e3 = Fr.mul(e3, ch.alpha);
|
||||
e3z = Fr.mul(e3z, ch.alpha);
|
||||
|
||||
let e4 = Fr.sub(z, Fr.one);
|
||||
e4 = Fr.mul(e4, lPols.slice( (zkey.domainSize + i)*n8r, (zkey.domainSize+i+1)*n8r));
|
||||
e4 = Fr.mul(e4, Fr.mul(ch.alpha, ch.alpha));
|
||||
|
||||
let e4z = Fr.mul(zp, lPols.slice( (zkey.domainSize + i)*n8r, (zkey.domainSize+i+1)*n8r));
|
||||
e4z = Fr.mul(e4z, Fr.mul(ch.alpha, ch.alpha));
|
||||
|
||||
let e = Fr.add(Fr.sub(Fr.add(e1, e2), e3), e4);
|
||||
let ez = Fr.add(Fr.sub(Fr.add(e1z, e2z), e3z), e4z);
|
||||
|
||||
T.set(e, i*n8r);
|
||||
Tz.set(ez, i*n8r);
|
||||
|
||||
w = Fr.mul(w, Fr.w[zkey.power+2]);
|
||||
}
|
||||
|
||||
let t = await Fr.ifft(T);
|
||||
|
||||
for (let i=0; i<zkey.domainSize; i++) {
|
||||
t.set(Fr.neg(t.slice(i*n8r, i*n8r+n8r)), i*n8r);
|
||||
}
|
||||
|
||||
for (let i=zkey.domainSize; i<zkey.domainSize*4; i++) {
|
||||
const a = Fr.sub(
|
||||
t.slice((i-zkey.domainSize)*n8r, (i-zkey.domainSize)*n8r + n8r),
|
||||
t.slice(i*n8r, i*n8r+n8r)
|
||||
);
|
||||
t.set(a, i*n8r);
|
||||
if (i > (zkey.domainSize*3 -4) ) {
|
||||
if (!Fr.isZero(a)) {
|
||||
throw new Error("T Polynomial is not divisible");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const tz = await Fr.ifft(Tz);
|
||||
for (let i=0; i<zkey.domainSize*4; i++) {
|
||||
const a = tz.slice(i*n8r, (i+1)*n8r);
|
||||
if (i > (zkey.domainSize*3 +5) ) {
|
||||
if (!Fr.isZero(a)) {
|
||||
throw new Error("Tz Polynomial is not well calculated");
|
||||
}
|
||||
} else {
|
||||
t.set(
|
||||
Fr.add(
|
||||
t.slice(i*n8r, (i+1)*n8r),
|
||||
a
|
||||
),
|
||||
i*n8r
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pol_t = t.slice(0, (zkey.domainSize*3+6)*n8r);
|
||||
|
||||
proof.T1 = await expTau( t.slice(0, zkey.domainSize*n8r) , "multiexp T1");
|
||||
proof.T2 = await expTau( t.slice(zkey.domainSize*n8r, zkey.domainSize*2*n8r) , "multiexp T2");
|
||||
proof.T3 = await expTau( t.slice(zkey.domainSize*2*n8r, (zkey.domainSize*3+6)*n8r) , "multiexp T3");
|
||||
|
||||
function mul2(a,b, ap, bp, p) {
|
||||
let r, rz;
|
||||
|
||||
|
||||
const a_b = Fr.mul(a,b);
|
||||
const a_bp = Fr.mul(a,bp);
|
||||
const ap_b = Fr.mul(ap,b);
|
||||
const ap_bp = Fr.mul(ap,bp);
|
||||
|
||||
r = a_b;
|
||||
|
||||
let a0 = Fr.add(a_bp, ap_b);
|
||||
|
||||
let a1 = ap_bp;
|
||||
|
||||
rz = a0;
|
||||
if (p) {
|
||||
rz = Fr.add(rz, Fr.mul(Z1[p], a1));
|
||||
}
|
||||
|
||||
return [r, rz];
|
||||
}
|
||||
|
||||
function mul4(a,b,c,d, ap, bp, cp, dp, p) {
|
||||
let r, rz;
|
||||
|
||||
|
||||
const a_b = Fr.mul(a,b);
|
||||
const a_bp = Fr.mul(a,bp);
|
||||
const ap_b = Fr.mul(ap,b);
|
||||
const ap_bp = Fr.mul(ap,bp);
|
||||
|
||||
const c_d = Fr.mul(c,d);
|
||||
const c_dp = Fr.mul(c,dp);
|
||||
const cp_d = Fr.mul(cp,d);
|
||||
const cp_dp = Fr.mul(cp,dp);
|
||||
|
||||
r = Fr.mul(a_b, c_d);
|
||||
|
||||
let a0 = Fr.mul(ap_b, c_d);
|
||||
a0 = Fr.add(a0, Fr.mul(a_bp, c_d));
|
||||
a0 = Fr.add(a0, Fr.mul(a_b, cp_d));
|
||||
a0 = Fr.add(a0, Fr.mul(a_b, c_dp));
|
||||
|
||||
let a1 = Fr.mul(ap_bp, c_d);
|
||||
a1 = Fr.add(a1, Fr.mul(ap_b, cp_d));
|
||||
a1 = Fr.add(a1, Fr.mul(ap_b, c_dp));
|
||||
a1 = Fr.add(a1, Fr.mul(a_bp, cp_d));
|
||||
a1 = Fr.add(a1, Fr.mul(a_bp, c_dp));
|
||||
a1 = Fr.add(a1, Fr.mul(a_b, cp_dp));
|
||||
|
||||
let a2 = Fr.mul(a_bp, cp_dp);
|
||||
a2 = Fr.add(a2, Fr.mul(ap_b, cp_dp));
|
||||
a2 = Fr.add(a2, Fr.mul(ap_bp, c_dp));
|
||||
a2 = Fr.add(a2, Fr.mul(ap_bp, cp_d));
|
||||
|
||||
let a3 = Fr.mul(ap_bp, cp_dp);
|
||||
|
||||
rz = a0;
|
||||
if (p) {
|
||||
rz = Fr.add(rz, Fr.mul(Z1[p], a1));
|
||||
rz = Fr.add(rz, Fr.mul(Z2[p], a2));
|
||||
rz = Fr.add(rz, Fr.mul(Z3[p], a3));
|
||||
}
|
||||
|
||||
return [r, rz];
|
||||
}
|
||||
}
|
||||
|
||||
async function round4() {
|
||||
const pol_qm = new BigBuffer(zkey.domainSize*n8r);
|
||||
await fdZKey.readToBuffer(pol_qm, 0 , zkey.domainSize*n8r, sectionsZKey[7][0].p);
|
||||
|
||||
const pol_ql = new BigBuffer(zkey.domainSize*n8r);
|
||||
await fdZKey.readToBuffer(pol_ql, 0 , zkey.domainSize*n8r, sectionsZKey[8][0].p);
|
||||
|
||||
const pol_qr = new BigBuffer(zkey.domainSize*n8r);
|
||||
await fdZKey.readToBuffer(pol_qr, 0 , zkey.domainSize*n8r, sectionsZKey[9][0].p);
|
||||
|
||||
const pol_qo = new BigBuffer(zkey.domainSize*n8r);
|
||||
await fdZKey.readToBuffer(pol_qo, 0 , zkey.domainSize*n8r, sectionsZKey[10][0].p);
|
||||
|
||||
const pol_qc = new BigBuffer(zkey.domainSize*n8r);
|
||||
await fdZKey.readToBuffer(pol_qc, 0 , zkey.domainSize*n8r, sectionsZKey[11][0].p);
|
||||
|
||||
const pol_s3 = new BigBuffer(zkey.domainSize*n8r);
|
||||
await fdZKey.readToBuffer(pol_s3, 0 , zkey.domainSize*n8r, sectionsZKey[12][0].p + 10*zkey.domainSize*n8r);
|
||||
|
||||
const transcript4 = new Uint8Array(G1.F.n8*2*3);
|
||||
G1.toRprUncompressed(transcript4, 0, proof.T1);
|
||||
G1.toRprUncompressed(transcript4, G1.F.n8*2, proof.T2);
|
||||
G1.toRprUncompressed(transcript4, G1.F.n8*4, proof.T3);
|
||||
ch.xi = hashToFr(transcript4);
|
||||
|
||||
if (logger) logger.debug("xi: " + Fr.toString(ch.xi));
|
||||
|
||||
proof.eval_a = evalPol(pol_a, ch.xi);
|
||||
proof.eval_b = evalPol(pol_b, ch.xi);
|
||||
proof.eval_c = evalPol(pol_c, ch.xi);
|
||||
proof.eval_s1 = evalPol(pol_s1, ch.xi);
|
||||
proof.eval_s2 = evalPol(pol_s2, ch.xi);
|
||||
proof.eval_t = evalPol(pol_t, ch.xi);
|
||||
proof.eval_zw = evalPol(pol_z, Fr.mul(ch.xi, Fr.w[zkey.power]));
|
||||
|
||||
const coef_ab = Fr.mul(proof.eval_a, proof.eval_b);
|
||||
|
||||
let e2a = proof.eval_a;
|
||||
const betaxi = Fr.mul(ch.beta, ch.xi);
|
||||
e2a = Fr.add( e2a, betaxi);
|
||||
e2a = Fr.add( e2a, ch.gamma);
|
||||
|
||||
let e2b = proof.eval_b;
|
||||
e2b = Fr.add( e2b, Fr.mul(betaxi, zkey.k1));
|
||||
e2b = Fr.add( e2b, ch.gamma);
|
||||
|
||||
let e2c = proof.eval_c;
|
||||
e2c = Fr.add( e2c, Fr.mul(betaxi, zkey.k2));
|
||||
e2c = Fr.add( e2c, ch.gamma);
|
||||
|
||||
const e2 = Fr.mul(Fr.mul(Fr.mul(e2a, e2b), e2c), ch.alpha);
|
||||
|
||||
let e3a = proof.eval_a;
|
||||
e3a = Fr.add( e3a, Fr.mul(ch.beta, proof.eval_s1));
|
||||
e3a = Fr.add( e3a, ch.gamma);
|
||||
|
||||
let e3b = proof.eval_b;
|
||||
e3b = Fr.add( e3b, Fr.mul(ch.beta, proof.eval_s2));
|
||||
e3b = Fr.add( e3b, ch.gamma);
|
||||
|
||||
let e3 = Fr.mul(e3a, e3b);
|
||||
e3 = Fr.mul(e3, ch.beta);
|
||||
e3 = Fr.mul(e3, proof.eval_zw);
|
||||
e3 = Fr.mul(e3, ch.alpha);
|
||||
|
||||
ch.xim= ch.xi;
|
||||
for (let i=0; i<zkey.power; i++) ch.xim = Fr.mul(ch.xim, ch.xim);
|
||||
const eval_l1 = Fr.div(
|
||||
Fr.sub(ch.xim, Fr.one),
|
||||
Fr.mul(Fr.sub(ch.xi, Fr.one), Fr.e(zkey.domainSize))
|
||||
);
|
||||
|
||||
const e4 = Fr.mul(eval_l1, Fr.mul(ch.alpha, ch.alpha));
|
||||
|
||||
const coefs3 = e3;
|
||||
const coefz = Fr.add(e2, e4);
|
||||
|
||||
pol_r = new BigBuffer((zkey.domainSize+3)*n8r);
|
||||
|
||||
for (let i = 0; i<zkey.domainSize+3; i++) {
|
||||
let v = Fr.mul(coefz, pol_z.slice(i*n8r,(i+1)*n8r));
|
||||
if (i<zkey.domainSize) {
|
||||
v = Fr.add(v, Fr.mul(coef_ab, pol_qm.slice(i*n8r,(i+1)*n8r)));
|
||||
v = Fr.add(v, Fr.mul(proof.eval_a, pol_ql.slice(i*n8r,(i+1)*n8r)));
|
||||
v = Fr.add(v, Fr.mul(proof.eval_b, pol_qr.slice(i*n8r,(i+1)*n8r)));
|
||||
v = Fr.add(v, Fr.mul(proof.eval_c, pol_qo.slice(i*n8r,(i+1)*n8r)));
|
||||
v = Fr.add(v, pol_qc.slice(i*n8r,(i+1)*n8r));
|
||||
v = Fr.sub(v, Fr.mul(coefs3, pol_s3.slice(i*n8r,(i+1)*n8r)));
|
||||
}
|
||||
pol_r.set(v, i*n8r);
|
||||
}
|
||||
|
||||
proof.eval_r = evalPol(pol_r, ch.xi);
|
||||
}
|
||||
|
||||
async function round5() {
|
||||
const transcript5 = new Uint8Array(n8r*7);
|
||||
Fr.toRprBE(transcript5, 0, proof.eval_a);
|
||||
Fr.toRprBE(transcript5, n8r, proof.eval_b);
|
||||
Fr.toRprBE(transcript5, n8r*2, proof.eval_c);
|
||||
Fr.toRprBE(transcript5, n8r*3, proof.eval_s1);
|
||||
Fr.toRprBE(transcript5, n8r*4, proof.eval_s2);
|
||||
Fr.toRprBE(transcript5, n8r*5, proof.eval_zw);
|
||||
Fr.toRprBE(transcript5, n8r*6, proof.eval_r);
|
||||
ch.v = [];
|
||||
ch.v[1] = hashToFr(transcript5);
|
||||
if (logger) logger.debug("v: " + Fr.toString(ch.v[1]));
|
||||
|
||||
for (let i=2; i<=6; i++ ) ch.v[i] = Fr.mul(ch.v[i-1], ch.v[1]);
|
||||
|
||||
let pol_wxi = new BigBuffer((zkey.domainSize+6)*n8r);
|
||||
|
||||
const xi2m = Fr.mul(ch.xim, ch.xim);
|
||||
|
||||
for (let i=0; i<zkey.domainSize+6; i++) {
|
||||
let w = Fr.zero;
|
||||
w = Fr.add(w, Fr.mul(xi2m, pol_t.slice( (zkey.domainSize*2+i)*n8r, (zkey.domainSize*2+i+1)*n8r )));
|
||||
|
||||
if (i<zkey.domainSize+3) {
|
||||
w = Fr.add(w, Fr.mul(ch.v[1], pol_r.slice(i*n8r, (i+1)*n8r)));
|
||||
}
|
||||
|
||||
if (i<zkey.domainSize+2) {
|
||||
w = Fr.add(w, Fr.mul(ch.v[2], pol_a.slice(i*n8r, (i+1)*n8r)));
|
||||
w = Fr.add(w, Fr.mul(ch.v[3], pol_b.slice(i*n8r, (i+1)*n8r)));
|
||||
w = Fr.add(w, Fr.mul(ch.v[4], pol_c.slice(i*n8r, (i+1)*n8r)));
|
||||
}
|
||||
|
||||
if (i<zkey.domainSize) {
|
||||
w = Fr.add(w, pol_t.slice(i*n8r, (i+1)*n8r));
|
||||
w = Fr.add(w, Fr.mul(ch.xim, pol_t.slice( (zkey.domainSize+i)*n8r, (zkey.domainSize+i+1)*n8r )));
|
||||
w = Fr.add(w, Fr.mul(ch.v[5], pol_s1.slice(i*n8r, (i+1)*n8r)));
|
||||
w = Fr.add(w, Fr.mul(ch.v[6], pol_s2.slice(i*n8r, (i+1)*n8r)));
|
||||
}
|
||||
|
||||
pol_wxi.set(w, i*n8r);
|
||||
}
|
||||
|
||||
let w0 = pol_wxi.slice(0, n8r);
|
||||
w0 = Fr.sub(w0, proof.eval_t);
|
||||
w0 = Fr.sub(w0, Fr.mul(ch.v[1], proof.eval_r));
|
||||
w0 = Fr.sub(w0, Fr.mul(ch.v[2], proof.eval_a));
|
||||
w0 = Fr.sub(w0, Fr.mul(ch.v[3], proof.eval_b));
|
||||
w0 = Fr.sub(w0, Fr.mul(ch.v[4], proof.eval_c));
|
||||
w0 = Fr.sub(w0, Fr.mul(ch.v[5], proof.eval_s1));
|
||||
w0 = Fr.sub(w0, Fr.mul(ch.v[6], proof.eval_s2));
|
||||
pol_wxi.set(w0, 0);
|
||||
|
||||
pol_wxi= divPol1(pol_wxi, ch.xi);
|
||||
|
||||
proof.Wxi = await expTau(pol_wxi, "multiexp Wxi");
|
||||
|
||||
let pol_wxiw = new BigBuffer((zkey.domainSize+3)*n8r);
|
||||
for (let i=0; i<zkey.domainSize+3; i++) {
|
||||
const w = pol_z.slice(i*n8r, (i+1)*n8r);
|
||||
pol_wxiw.set(w, i*n8r);
|
||||
}
|
||||
w0 = pol_wxiw.slice(0, n8r);
|
||||
w0 = Fr.sub(w0, proof.eval_zw);
|
||||
pol_wxiw.set(w0, 0);
|
||||
|
||||
pol_wxiw= divPol1(pol_wxiw, Fr.mul(ch.xi, Fr.w[zkey.power]));
|
||||
proof.Wxiw = await expTau(pol_wxiw, "multiexp Wxiw");
|
||||
}
|
||||
|
||||
function hashToFr(transcript) {
|
||||
const v = Scalar.fromRprBE(new Uint8Array(keccak256.arrayBuffer(transcript)));
|
||||
return Fr.e(v);
|
||||
}
|
||||
|
||||
|
||||
function evalPol(P, x) {
|
||||
const n = P.byteLength / n8r;
|
||||
if (n == 0) return Fr.zero;
|
||||
let res = P.slice((n-1)*n8r, n*n8r);
|
||||
for (let i=n-2; i>=0; i--) {
|
||||
res = Fr.add(Fr.mul(res, x), P.slice(i*n8r, (i+1)*n8r));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
function divPol1(P, d) {
|
||||
const n = P.byteLength/n8r;
|
||||
const res = new BigBuffer(n*n8r);
|
||||
res.set(Fr.zero, (n-1) *n8r);
|
||||
res.set(P.slice((n-1)*n8r, n*n8r), (n-2)*n8r);
|
||||
for (let i=n-3; i>=0; i--) {
|
||||
res.set(
|
||||
Fr.add(
|
||||
P.slice((i+1)*n8r, (i+2)*n8r),
|
||||
Fr.mul(
|
||||
d,
|
||||
res.slice((i+1)*n8r, (i+2)*n8r)
|
||||
)
|
||||
),
|
||||
i*n8r
|
||||
);
|
||||
}
|
||||
if (!Fr.eq(
|
||||
P.slice(0, n8r),
|
||||
Fr.mul(
|
||||
Fr.neg(d),
|
||||
res.slice(0, n8r)
|
||||
)
|
||||
)) {
|
||||
throw new Error("Polinomial does not divide");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
async function expTau(b, name) {
|
||||
const n = b.byteLength/n8r;
|
||||
const PTauN = PTau.slice(0, n*curve.G1.F.n8*2);
|
||||
const bm = await curve.Fr.batchFromMontgomery(b);
|
||||
let res = await curve.G1.multiExpAffine(PTauN, bm, logger, name);
|
||||
res = curve.G1.toAffine(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
async function to4T(A, pz) {
|
||||
pz = pz || [];
|
||||
let a = await Fr.ifft(A);
|
||||
const a4 = new BigBuffer(n8r*zkey.domainSize*4);
|
||||
a4.set(a, 0);
|
||||
|
||||
const a1 = new BigBuffer(n8r*(zkey.domainSize + pz.length));
|
||||
a1.set(a, 0);
|
||||
for (let i= 0; i<pz.length; i++) {
|
||||
a1.set(
|
||||
Fr.add(
|
||||
a1.slice((zkey.domainSize+i)*n8r, (zkey.domainSize+i+1)*n8r),
|
||||
pz[i]
|
||||
),
|
||||
(zkey.domainSize+i)*n8r
|
||||
);
|
||||
a1.set(
|
||||
Fr.sub(
|
||||
a1.slice(i*n8r, (i+1)*n8r),
|
||||
pz[i]
|
||||
),
|
||||
i*n8r
|
||||
);
|
||||
}
|
||||
const A4 = await Fr.fft(a4);
|
||||
return [a1, A4];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
422
src/plonk_setup.js
Normal file
422
src/plonk_setup.js
Normal file
@ -0,0 +1,422 @@
|
||||
/*
|
||||
Copyright 2021 0kims association.
|
||||
|
||||
This file is part of snarkjs.
|
||||
|
||||
snarkjs is a free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation, either version 3 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
snarkjs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
snarkjs. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Implementation of this paper: https://eprint.iacr.org/2019/953.pdf */
|
||||
|
||||
import {readR1csHeader} from "r1csfile";
|
||||
import * as utils from "./powersoftau_utils.js";
|
||||
import {
|
||||
readBinFile,
|
||||
createBinFile,
|
||||
readSection,
|
||||
writeBigInt,
|
||||
startWriteSection,
|
||||
endWriteSection,
|
||||
} from "@iden3/binfileutils";
|
||||
import { log2 } from "./misc.js";
|
||||
import { Scalar, BigBuffer } from "ffjavascript";
|
||||
import Blake2b from "blake2b-wasm";
|
||||
import BigArray from "./bigarray.js";
|
||||
|
||||
|
||||
export default async function plonkSetup(r1csName, ptauName, zkeyName, logger) {
|
||||
|
||||
await Blake2b.ready();
|
||||
|
||||
const {fd: fdPTau, sections: sectionsPTau} = await readBinFile(ptauName, "ptau", 1, 1<<22, 1<<24);
|
||||
const {curve, power} = await utils.readPTauHeader(fdPTau, sectionsPTau);
|
||||
const {fd: fdR1cs, sections: sectionsR1cs} = await readBinFile(r1csName, "r1cs", 1, 1<<22, 1<<24);
|
||||
const r1cs = await readR1csHeader(fdR1cs, sectionsR1cs, false);
|
||||
|
||||
const sG1 = curve.G1.F.n8*2;
|
||||
const G1 = curve.G1;
|
||||
const sG2 = curve.G2.F.n8*2;
|
||||
const Fr = curve.Fr;
|
||||
const n8r = curve.Fr.n8;
|
||||
|
||||
if (logger) logger.info("Reading r1cs");
|
||||
let sR1cs = await readSection(fdR1cs, sectionsR1cs, 2);
|
||||
|
||||
const plonkConstraints = new BigArray();
|
||||
const plonkAdditions = new BigArray();
|
||||
let plonkNVars = r1cs.nVars;
|
||||
|
||||
const nPublic = r1cs.nOutputs + r1cs.nPubInputs;
|
||||
|
||||
await processConstraints();
|
||||
|
||||
const fdZKey = await createBinFile(zkeyName, "zkey", 1, 14, 1<<22, 1<<24);
|
||||
|
||||
|
||||
if (r1cs.prime != curve.r) {
|
||||
if (logger) logger.error("r1cs curve does not match powers of tau ceremony curve");
|
||||
return -1;
|
||||
}
|
||||
|
||||
const cirPower = log2(plonkConstraints.length -1) +1;
|
||||
const domainSize = 2 ** cirPower;
|
||||
|
||||
if (cirPower > power) {
|
||||
if (logger) logger.error(`circuit too big for this power of tau ceremony. ${r1cs.nConstraints}*2 > 2**${power}`);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!sectionsPTau[12]) {
|
||||
if (logger) logger.error("Powers of tau is not prepared.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
const LPoints = new BigBuffer(domainSize*sG1);
|
||||
const o = sectionsPTau[12][0].p + ((2 ** (cirPower)) -1)*sG1;
|
||||
await fdPTau.readToBuffer(LPoints, 0, domainSize*sG1, o);
|
||||
|
||||
const [k1, k2] = getK1K2();
|
||||
|
||||
const vk = {};
|
||||
|
||||
|
||||
await writeAdditions(3, "Additions");
|
||||
await writeWitnessMap(4, 0, "Amap");
|
||||
await writeWitnessMap(5, 1, "Bmap");
|
||||
await writeWitnessMap(6, 2, "Cmap");
|
||||
await writeQMap(7, 3, "Qm");
|
||||
await writeQMap(8, 4, "Ql");
|
||||
await writeQMap(9, 5, "Qr");
|
||||
await writeQMap(10, 6, "Qo");
|
||||
await writeQMap(11, 7, "Qc");
|
||||
await writeSigma(12, "sigma");
|
||||
await writeLs(13, "lagrange polynomials");
|
||||
|
||||
// Write PTau points
|
||||
////////////
|
||||
|
||||
await startWriteSection(fdZKey, 14);
|
||||
const buffOut = new BigBuffer((domainSize+6)*sG1);
|
||||
await fdPTau.readToBuffer(buffOut, 0, (domainSize+6)*sG1, sectionsPTau[2][0].p);
|
||||
await fdZKey.write(buffOut);
|
||||
await endWriteSection(fdZKey);
|
||||
|
||||
|
||||
await writeHeaders();
|
||||
|
||||
await fdZKey.close();
|
||||
await fdR1cs.close();
|
||||
await fdPTau.close();
|
||||
|
||||
if (logger) logger.info("Setup Finished");
|
||||
|
||||
return ;
|
||||
|
||||
async function processConstraints() {
|
||||
|
||||
let r1csPos = 0;
|
||||
|
||||
function r1cs_readULE32() {
|
||||
const buff = sR1cs.slice(r1csPos, r1csPos+4);
|
||||
r1csPos += 4;
|
||||
const buffV = new DataView(buff.buffer);
|
||||
return buffV.getUint32(0, true);
|
||||
}
|
||||
|
||||
function r1cs_readCoef() {
|
||||
const res = Fr.fromRprLE(sR1cs.slice(r1csPos, r1csPos+curve.Fr.n8));
|
||||
r1csPos += curve.Fr.n8;
|
||||
return res;
|
||||
}
|
||||
|
||||
function r1cs_readCoefs() {
|
||||
const coefs = [];
|
||||
const res = {
|
||||
k: curve.Fr.zero
|
||||
};
|
||||
const nA = r1cs_readULE32();
|
||||
for (let i=0; i<nA; i++) {
|
||||
const s = r1cs_readULE32();
|
||||
const coefp = r1cs_readCoef();
|
||||
|
||||
if (s==0) {
|
||||
res.k = coefp;
|
||||
} else {
|
||||
coefs.push([s, coefp]);
|
||||
}
|
||||
}
|
||||
|
||||
const resCoef = reduceCoef(coefs);
|
||||
res.s = resCoef[0];
|
||||
res.coef = resCoef[1];
|
||||
return res;
|
||||
}
|
||||
|
||||
function reduceCoef(coefs) {
|
||||
if (coefs.length == 0) {
|
||||
return [0, curve.Fr.zero];
|
||||
}
|
||||
if (coefs.length == 1) {
|
||||
return coefs[0];
|
||||
}
|
||||
const arr1 = coefs.slice(0, coefs.length >> 1);
|
||||
const arr2 = coefs.slice(coefs.length >> 1);
|
||||
const coef1 = reduceCoef(arr1);
|
||||
const coef2 = reduceCoef(arr2);
|
||||
|
||||
const sl = coef1[0];
|
||||
const sr = coef2[0];
|
||||
const so = plonkNVars++;
|
||||
const qm = curve.Fr.zero;
|
||||
const ql = Fr.neg(coef1[1]);
|
||||
const qr = Fr.neg(coef2[1]);
|
||||
const qo = curve.Fr.one;
|
||||
const qc = curve.Fr.zero;
|
||||
|
||||
plonkConstraints.push([sl, sr, so, qm, ql, qr, qo, qc]);
|
||||
|
||||
plonkAdditions.push([sl, sr, coef1[1], coef2[1]]);
|
||||
|
||||
return [so, curve.Fr.one];
|
||||
}
|
||||
|
||||
for (let s = 1; s <= nPublic ; s++) {
|
||||
const sl = s;
|
||||
const sr = 0;
|
||||
const so = 0;
|
||||
const qm = curve.Fr.zero;
|
||||
const ql = curve.Fr.one;
|
||||
const qr = curve.Fr.zero;
|
||||
const qo = curve.Fr.zero;
|
||||
const qc = curve.Fr.zero;
|
||||
|
||||
plonkConstraints.push([sl, sr, so, qm, ql, qr, qo, qc]);
|
||||
}
|
||||
|
||||
for (let c=0; c<r1cs.nConstraints; c++) {
|
||||
if ((logger)&&(c%10000 == 0)) logger.debug(`processing constraints: ${c}/${r1cs.nConstraints}`);
|
||||
const A = r1cs_readCoefs();
|
||||
const B = r1cs_readCoefs();
|
||||
const C = r1cs_readCoefs();
|
||||
|
||||
const sl = A.s;
|
||||
const sr = B.s;
|
||||
const so = C.s;
|
||||
const qm = curve.Fr.mul(A.coef, B.coef);
|
||||
const ql = curve.Fr.mul(A.coef, B.k);
|
||||
const qr = curve.Fr.mul(A.k, B.coef);
|
||||
const qo = curve.Fr.neg(C.coef);
|
||||
const qc = curve.Fr.neg(C.k);
|
||||
|
||||
plonkConstraints.push([sl, sr, so, qm, ql, qr, qo, qc]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async function writeWitnessMap(sectionNum, posConstraint, name) {
|
||||
await startWriteSection(fdZKey, sectionNum);
|
||||
for (let i=0; i<plonkConstraints.length; i++) {
|
||||
await fdZKey.writeULE32(plonkConstraints[i][posConstraint]);
|
||||
if ((logger)&&(i%1000000 == 0)) logger.debug(`writing ${name}: ${i}/${plonkConstraints.length}`);
|
||||
}
|
||||
await endWriteSection(fdZKey);
|
||||
}
|
||||
|
||||
async function writeQMap(sectionNum, posConstraint, name) {
|
||||
let Q = new BigBuffer(domainSize*n8r);
|
||||
for (let i=0; i<plonkConstraints.length; i++) {
|
||||
Q.set(plonkConstraints[i][posConstraint], i*n8r);
|
||||
if ((logger)&&(i%1000000 == 0)) logger.debug(`writing ${name}: ${i}/${plonkConstraints.length}`);
|
||||
}
|
||||
await startWriteSection(fdZKey, sectionNum);
|
||||
await writeP4(Q);
|
||||
await endWriteSection(fdZKey);
|
||||
Q = await Fr.batchFromMontgomery(Q);
|
||||
vk[name]= await curve.G1.multiExpAffine(LPoints, Q, logger, "multiexp "+name);
|
||||
}
|
||||
|
||||
async function writeP4(buff) {
|
||||
const q = await Fr.ifft(buff);
|
||||
const q4 = new BigBuffer(domainSize*n8r*4);
|
||||
q4.set(q, 0);
|
||||
const Q4 = await Fr.fft(q4);
|
||||
await fdZKey.write(q);
|
||||
await fdZKey.write(Q4);
|
||||
}
|
||||
|
||||
async function writeAdditions(sectionNum, name) {
|
||||
await startWriteSection(fdZKey, sectionNum);
|
||||
const buffOut = new Uint8Array((2*4+2*n8r));
|
||||
const buffOutV = new DataView(buffOut.buffer);
|
||||
for (let i=0; i<plonkAdditions.length; i++) {
|
||||
const addition=plonkAdditions[i];
|
||||
let o=0;
|
||||
buffOutV.setUint32(o, addition[0], true); o+=4;
|
||||
buffOutV.setUint32(o, addition[1], true); o+=4;
|
||||
// The value is storen in Montgomery. stored = v*R
|
||||
// so when montgomery multiplicated by the witness it result = v*R*w/R = v*w
|
||||
buffOut.set(addition[2], o); o+= n8r;
|
||||
buffOut.set(addition[3], o); o+= n8r;
|
||||
await fdZKey.write(buffOut);
|
||||
if ((logger)&&(i%1000000 == 0)) logger.debug(`writing ${name}: ${i}/${plonkAdditions.length}`);
|
||||
}
|
||||
await endWriteSection(fdZKey);
|
||||
}
|
||||
|
||||
async function writeSigma(sectionNum, name) {
|
||||
const sigma = new BigBuffer(n8r*domainSize*3);
|
||||
const lastAparence = new BigArray(plonkNVars);
|
||||
const firstPos = new BigArray(plonkNVars);
|
||||
let w = Fr.one;
|
||||
for (let i=0; i<domainSize;i++) {
|
||||
if (i<plonkConstraints.length) {
|
||||
buildSigma(plonkConstraints[i][0], i);
|
||||
buildSigma(plonkConstraints[i][1], domainSize + i);
|
||||
buildSigma(plonkConstraints[i][2], domainSize*2 + i);
|
||||
} else {
|
||||
buildSigma(0, i);
|
||||
buildSigma(0, domainSize + i);
|
||||
buildSigma(0, domainSize*2 + i);
|
||||
}
|
||||
w = Fr.mul(w, Fr.w[cirPower]);
|
||||
if ((logger)&&(i%1000000 == 0)) logger.debug(`writing ${name} phase1: ${i}/${plonkConstraints.length}`);
|
||||
}
|
||||
for (let s=0; s<plonkNVars; s++) {
|
||||
if (typeof firstPos[s] !== "undefined") {
|
||||
sigma.set(lastAparence[s], firstPos[s]*n8r);
|
||||
} else {
|
||||
throw new Error("Variable not used");
|
||||
}
|
||||
if ((logger)&&(s%1000000 == 0)) logger.debug(`writing ${name} phase2: ${s}/${plonkNVars}`);
|
||||
}
|
||||
await startWriteSection(fdZKey, sectionNum);
|
||||
let S1 = sigma.slice(0, domainSize*n8r);
|
||||
await writeP4(S1);
|
||||
let S2 = sigma.slice(domainSize*n8r, domainSize*n8r*2);
|
||||
await writeP4(S2);
|
||||
let S3 = sigma.slice(domainSize*n8r*2, domainSize*n8r*3);
|
||||
await writeP4(S3);
|
||||
await endWriteSection(fdZKey);
|
||||
|
||||
S1 = await Fr.batchFromMontgomery(S1);
|
||||
S2 = await Fr.batchFromMontgomery(S2);
|
||||
S3 = await Fr.batchFromMontgomery(S3);
|
||||
|
||||
vk.S1= await curve.G1.multiExpAffine(LPoints, S1, logger, "multiexp S1");
|
||||
vk.S2= await curve.G1.multiExpAffine(LPoints, S2, logger, "multiexp S2");
|
||||
vk.S3= await curve.G1.multiExpAffine(LPoints, S3, logger, "multiexp S3");
|
||||
|
||||
function buildSigma(s, p) {
|
||||
if (typeof lastAparence[s] === "undefined") {
|
||||
firstPos[s] = p;
|
||||
} else {
|
||||
sigma.set(lastAparence[s], p*n8r);
|
||||
}
|
||||
let v;
|
||||
if (p<domainSize) {
|
||||
v = w;
|
||||
} else if (p<2*domainSize) {
|
||||
v = Fr.mul(w, k1);
|
||||
} else {
|
||||
v = Fr.mul(w, k2);
|
||||
}
|
||||
lastAparence[s]=v;
|
||||
}
|
||||
}
|
||||
|
||||
async function writeLs(sectionNum, name) {
|
||||
await startWriteSection(fdZKey, sectionNum);
|
||||
const l=Math.max(nPublic, 1);
|
||||
for (let i=0; i<l; i++) {
|
||||
let buff = new BigBuffer(domainSize*n8r);
|
||||
buff.set(Fr.one, i*n8r);
|
||||
await writeP4(buff);
|
||||
if (logger) logger.debug(`writing ${name} ${i}/${l}`);
|
||||
}
|
||||
await endWriteSection(fdZKey);
|
||||
}
|
||||
|
||||
async function writeHeaders() {
|
||||
|
||||
// Write the header
|
||||
///////////
|
||||
await startWriteSection(fdZKey, 1);
|
||||
await fdZKey.writeULE32(2); // Plonk
|
||||
await endWriteSection(fdZKey);
|
||||
|
||||
// Write the Plonk header section
|
||||
///////////
|
||||
|
||||
await startWriteSection(fdZKey, 2);
|
||||
const primeQ = curve.q;
|
||||
const n8q = (Math.floor( (Scalar.bitLength(primeQ) - 1) / 64) +1)*8;
|
||||
|
||||
const primeR = curve.r;
|
||||
const n8r = (Math.floor( (Scalar.bitLength(primeR) - 1) / 64) +1)*8;
|
||||
|
||||
await fdZKey.writeULE32(n8q);
|
||||
await writeBigInt(fdZKey, primeQ, n8q);
|
||||
await fdZKey.writeULE32(n8r);
|
||||
await writeBigInt(fdZKey, primeR, n8r);
|
||||
await fdZKey.writeULE32(plonkNVars); // Total number of bars
|
||||
await fdZKey.writeULE32(nPublic); // Total number of public vars (not including ONE)
|
||||
await fdZKey.writeULE32(domainSize); // domainSize
|
||||
await fdZKey.writeULE32(plonkAdditions.length); // domainSize
|
||||
await fdZKey.writeULE32(plonkConstraints.length);
|
||||
|
||||
await fdZKey.write(k1);
|
||||
await fdZKey.write(k2);
|
||||
|
||||
await fdZKey.write(G1.toAffine(vk.Qm));
|
||||
await fdZKey.write(G1.toAffine(vk.Ql));
|
||||
await fdZKey.write(G1.toAffine(vk.Qr));
|
||||
await fdZKey.write(G1.toAffine(vk.Qo));
|
||||
await fdZKey.write(G1.toAffine(vk.Qc));
|
||||
|
||||
await fdZKey.write(G1.toAffine(vk.S1));
|
||||
await fdZKey.write(G1.toAffine(vk.S2));
|
||||
await fdZKey.write(G1.toAffine(vk.S3));
|
||||
|
||||
let bX_2;
|
||||
bX_2 = await fdPTau.read(sG2, sectionsPTau[3][0].p + sG2);
|
||||
await fdZKey.write(bX_2);
|
||||
|
||||
await endWriteSection(fdZKey);
|
||||
}
|
||||
|
||||
function getK1K2() {
|
||||
let k1 = Fr.two;
|
||||
while (isIncluded(k1, [], cirPower)) Fr.add(k1, Fr.one);
|
||||
let k2 = Fr.add(k1, Fr.one);
|
||||
while (isIncluded(k2, [k1], cirPower)) Fr.add(k2, Fr.one);
|
||||
return [k1, k2];
|
||||
|
||||
|
||||
function isIncluded(k, kArr, pow) {
|
||||
const domainSize= 2**pow;
|
||||
let w = Fr.one;
|
||||
for (let i=0; i<domainSize; i++) {
|
||||
if (Fr.eq(k, w)) return true;
|
||||
for (let j=0; j<kArr.length; j++) {
|
||||
if (Fr.eq(k, Fr.mul(kArr[j], w))) return true;
|
||||
}
|
||||
w = Fr.mul(w, Fr.w[pow]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
398
src/plonk_verify.js
Normal file
398
src/plonk_verify.js
Normal file
@ -0,0 +1,398 @@
|
||||
/*
|
||||
Copyright 2021 0kims association.
|
||||
|
||||
This file is part of snarkjs.
|
||||
|
||||
snarkjs is a free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as published by the
|
||||
Free Software Foundation, either version 3 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
snarkjs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
snarkjs. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Implementation of this paper: https://eprint.iacr.org/2019/953.pdf */
|
||||
import { Scalar } from "ffjavascript";
|
||||
import * as curves from "./curves.js";
|
||||
import { utils } from "ffjavascript";
|
||||
const {unstringifyBigInts} = utils;
|
||||
import jsSha3 from "js-sha3";
|
||||
const { keccak256 } = jsSha3;
|
||||
|
||||
|
||||
export default async function plonkVerify(vk_verifier, publicSignals, proof, logger) {
|
||||
vk_verifier = unstringifyBigInts(vk_verifier);
|
||||
proof = unstringifyBigInts(proof);
|
||||
publicSignals = unstringifyBigInts(publicSignals);
|
||||
|
||||
const curve = await curves.getCurveFromName(vk_verifier.curve);
|
||||
|
||||
const Fr = curve.Fr;
|
||||
const G1 = curve.G1;
|
||||
|
||||
proof = fromObjectProof(curve,proof);
|
||||
vk_verifier = fromObjectVk(curve, vk_verifier);
|
||||
if (!isWellConstructed(curve, proof)) {
|
||||
logger.error("Proof is not well constructed");
|
||||
return false;
|
||||
}
|
||||
const challanges = calculateChallanges(curve, proof);
|
||||
if (logger) {
|
||||
logger.debug("beta: " + Fr.toString(challanges.beta, 16));
|
||||
logger.debug("gamma: " + Fr.toString(challanges.gamma, 16));
|
||||
logger.debug("alpha: " + Fr.toString(challanges.alpha, 16));
|
||||
logger.debug("xi: " + Fr.toString(challanges.xi, 16));
|
||||
logger.debug("v1: " + Fr.toString(challanges.v[1], 16));
|
||||
logger.debug("v6: " + Fr.toString(challanges.v[6], 16));
|
||||
logger.debug("u: " + Fr.toString(challanges.u, 16));
|
||||
}
|
||||
const L = calculateLagrangeEvaluations(curve, challanges, vk_verifier);
|
||||
if (logger) {
|
||||
logger.debug("Lagrange Evaluations: ");
|
||||
for (let i=1; i<L.length; i++) {
|
||||
logger.debug(`L${i}(xi)=` + Fr.toString(L[i], 16));
|
||||
}
|
||||
}
|
||||
|
||||
if (publicSignals.length != vk_verifier.nPublic) {
|
||||
logger.error("Number of public signals does not match with vk");
|
||||
return false;
|
||||
}
|
||||
|
||||
const pl = calculatePl(curve, publicSignals, L);
|
||||
if (logger) {
|
||||
logger.debug("Pl: " + Fr.toString(pl, 16));
|
||||
}
|
||||
|
||||
const t = calculateT(curve, proof, challanges, pl, L[1]);
|
||||
if (logger) {
|
||||
logger.debug("t: " + Fr.toString(t, 16));
|
||||
}
|
||||
|
||||
const D = calculateD(curve, proof, challanges, vk_verifier, L[1]);
|
||||
if (logger) {
|
||||
logger.debug("D: " + G1.toString(G1.toAffine(D), 16));
|
||||
}
|
||||
|
||||
const F = calculateF(curve, proof, challanges, vk_verifier, D);
|
||||
if (logger) {
|
||||
logger.debug("F: " + G1.toString(G1.toAffine(F), 16));
|
||||
}
|
||||
|
||||
const E = calculateE(curve, proof, challanges, vk_verifier, t);
|
||||
if (logger) {
|
||||
logger.debug("E: " + G1.toString(G1.toAffine(E), 16));
|
||||
}
|
||||
|
||||
const res = await isValidPairing(curve, proof, challanges, vk_verifier, E, F);
|
||||
|
||||
if (logger) {
|
||||
if (res) {
|
||||
logger.info("OK!");
|
||||
} else {
|
||||
logger.warn("Invalid Proof");
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
|
||||
function fromObjectProof(curve, proof) {
|
||||
const G1 = curve.G1;
|
||||
const Fr = curve.Fr;
|
||||
const res = {};
|
||||
res.A = G1.fromObject(proof.A);
|
||||
res.B = G1.fromObject(proof.B);
|
||||
res.C = G1.fromObject(proof.C);
|
||||
res.Z = G1.fromObject(proof.Z);
|
||||
res.T1 = G1.fromObject(proof.T1);
|
||||
res.T2 = G1.fromObject(proof.T2);
|
||||
res.T3 = G1.fromObject(proof.T3);
|
||||
res.eval_a = Fr.fromObject(proof.eval_a);
|
||||
res.eval_b = Fr.fromObject(proof.eval_b);
|
||||
res.eval_c = Fr.fromObject(proof.eval_c);
|
||||
res.eval_zw = Fr.fromObject(proof.eval_zw);
|
||||
res.eval_s1 = Fr.fromObject(proof.eval_s1);
|
||||
res.eval_s2 = Fr.fromObject(proof.eval_s2);
|
||||
res.eval_r = Fr.fromObject(proof.eval_r);
|
||||
res.Wxi = G1.fromObject(proof.Wxi);
|
||||
res.Wxiw = G1.fromObject(proof.Wxiw);
|
||||
return res;
|
||||
}
|
||||
|
||||
function fromObjectVk(curve, vk) {
|
||||
const G1 = curve.G1;
|
||||
const G2 = curve.G2;
|
||||
const Fr = curve.Fr;
|
||||
const res = vk;
|
||||
res.Qm = G1.fromObject(vk.Qm);
|
||||
res.Ql = G1.fromObject(vk.Ql);
|
||||
res.Qr = G1.fromObject(vk.Qr);
|
||||
res.Qo = G1.fromObject(vk.Qo);
|
||||
res.Qc = G1.fromObject(vk.Qc);
|
||||
res.S1 = G1.fromObject(vk.S1);
|
||||
res.S2 = G1.fromObject(vk.S2);
|
||||
res.S3 = G1.fromObject(vk.S3);
|
||||
res.k1 = Fr.fromObject(vk.k1);
|
||||
res.k2 = Fr.fromObject(vk.k2);
|
||||
res.X_2 = G2.fromObject(vk.X_2);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
function isWellConstructed(curve, proof) {
|
||||
const G1 = curve.G1;
|
||||
if (!G1.isValid(proof.A)) return false;
|
||||
if (!G1.isValid(proof.B)) return false;
|
||||
if (!G1.isValid(proof.C)) return false;
|
||||
if (!G1.isValid(proof.Z)) return false;
|
||||
if (!G1.isValid(proof.T1)) return false;
|
||||
if (!G1.isValid(proof.T2)) return false;
|
||||
if (!G1.isValid(proof.T3)) return false;
|
||||
if (!G1.isValid(proof.Wxi)) return false;
|
||||
if (!G1.isValid(proof.Wxiw)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function calculateChallanges(curve, proof) {
|
||||
const G1 = curve.G1;
|
||||
const Fr = curve.Fr;
|
||||
const n8r = curve.Fr.n8;
|
||||
const res = {};
|
||||
|
||||
const transcript1 = new Uint8Array(G1.F.n8*2*3);
|
||||
G1.toRprUncompressed(transcript1, 0, proof.A);
|
||||
G1.toRprUncompressed(transcript1, G1.F.n8*2, proof.B);
|
||||
G1.toRprUncompressed(transcript1, G1.F.n8*4, proof.C);
|
||||
res.beta = hashToFr(curve, transcript1);
|
||||
|
||||
const transcript2 = new Uint8Array(n8r);
|
||||
Fr.toRprBE(transcript2, 0, res.beta);
|
||||
res.gamma = hashToFr(curve, transcript2);
|
||||
|
||||
const transcript3 = new Uint8Array(G1.F.n8*2);
|
||||
G1.toRprUncompressed(transcript3, 0, proof.Z);
|
||||
res.alpha = hashToFr(curve, transcript3);
|
||||
|
||||
const transcript4 = new Uint8Array(G1.F.n8*2*3);
|
||||
G1.toRprUncompressed(transcript4, 0, proof.T1);
|
||||
G1.toRprUncompressed(transcript4, G1.F.n8*2, proof.T2);
|
||||
G1.toRprUncompressed(transcript4, G1.F.n8*4, proof.T3);
|
||||
res.xi = hashToFr(curve, transcript4);
|
||||
|
||||
const transcript5 = new Uint8Array(n8r*7);
|
||||
Fr.toRprBE(transcript5, 0, proof.eval_a);
|
||||
Fr.toRprBE(transcript5, n8r, proof.eval_b);
|
||||
Fr.toRprBE(transcript5, n8r*2, proof.eval_c);
|
||||
Fr.toRprBE(transcript5, n8r*3, proof.eval_s1);
|
||||
Fr.toRprBE(transcript5, n8r*4, proof.eval_s2);
|
||||
Fr.toRprBE(transcript5, n8r*5, proof.eval_zw);
|
||||
Fr.toRprBE(transcript5, n8r*6, proof.eval_r);
|
||||
res.v = [];
|
||||
res.v[1] = hashToFr(curve, transcript5);
|
||||
|
||||
for (let i=2; i<=6; i++ ) res.v[i] = Fr.mul(res.v[i-1], res.v[1]);
|
||||
|
||||
const transcript6 = new Uint8Array(G1.F.n8*2*2);
|
||||
G1.toRprUncompressed(transcript6, 0, proof.Wxi);
|
||||
G1.toRprUncompressed(transcript6, G1.F.n8*2, proof.Wxiw);
|
||||
res.u = hashToFr(curve, transcript6);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
function calculateLagrangeEvaluations(curve, challanges, vk) {
|
||||
const Fr = curve.Fr;
|
||||
|
||||
let xin = challanges.xi;
|
||||
let domainSize = 1;
|
||||
for (let i=0; i<vk.power; i++) {
|
||||
xin = Fr.square(xin);
|
||||
domainSize *= 2;
|
||||
}
|
||||
challanges.xin = xin;
|
||||
|
||||
challanges.zh = Fr.sub(xin, Fr.one);
|
||||
const L = [];
|
||||
|
||||
const n = Fr.e(domainSize);
|
||||
let w = Fr.one;
|
||||
for (let i=1; i<=Math.max(1, vk.nPublic); i++) {
|
||||
L[i] = Fr.div(Fr.mul(w, challanges.zh), Fr.mul(n, Fr.sub(challanges.xi, w)));
|
||||
w = Fr.mul(w, Fr.w[vk.power]);
|
||||
}
|
||||
|
||||
return L;
|
||||
}
|
||||
|
||||
function hashToFr(curve, transcript) {
|
||||
const v = Scalar.fromRprBE(new Uint8Array(keccak256.arrayBuffer(transcript)));
|
||||
return curve.Fr.e(v);
|
||||
}
|
||||
|
||||
function calculatePl(curve, publicSignals, L) {
|
||||
const Fr = curve.Fr;
|
||||
|
||||
let pl = Fr.zero;
|
||||
for (let i=0; i<publicSignals.length; i++) {
|
||||
const w = Fr.e(publicSignals[i]);
|
||||
pl = Fr.sub(pl, Fr.mul(w, L[i+1]));
|
||||
}
|
||||
return pl;
|
||||
}
|
||||
|
||||
function calculateT(curve, proof, challanges, pl, l1) {
|
||||
const Fr = curve.Fr;
|
||||
let num = proof.eval_r;
|
||||
num = Fr.add(num, pl);
|
||||
|
||||
let e1 = proof.eval_a;
|
||||
e1 = Fr.add(e1, Fr.mul(challanges.beta, proof.eval_s1));
|
||||
e1 = Fr.add(e1, challanges.gamma);
|
||||
|
||||
let e2 = proof.eval_b;
|
||||
e2 = Fr.add(e2, Fr.mul(challanges.beta, proof.eval_s2));
|
||||
e2 = Fr.add(e2, challanges.gamma);
|
||||
|
||||
let e3 = proof.eval_c;
|
||||
e3 = Fr.add(e3, challanges.gamma);
|
||||
|
||||
let e = Fr.mul(Fr.mul(e1, e2), e3);
|
||||
e = Fr.mul(e, proof.eval_zw);
|
||||
e = Fr.mul(e, challanges.alpha);
|
||||
|
||||
num = Fr.sub(num, e);
|
||||
|
||||
num = Fr.sub(num, Fr.mul(l1, Fr.square(challanges.alpha)));
|
||||
|
||||
const t = Fr.div(num, challanges.zh);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
function calculateD(curve, proof, challanges, vk, l1) {
|
||||
const G1 = curve.G1;
|
||||
const Fr = curve.Fr;
|
||||
|
||||
let s1 = Fr.mul(Fr.mul(proof.eval_a, proof.eval_b), challanges.v[1]);
|
||||
let res = G1.timesFr(vk.Qm, s1);
|
||||
|
||||
let s2 = Fr.mul(proof.eval_a, challanges.v[1]);
|
||||
res = G1.add(res, G1.timesFr(vk.Ql, s2));
|
||||
|
||||
let s3 = Fr.mul(proof.eval_b, challanges.v[1]);
|
||||
res = G1.add(res, G1.timesFr(vk.Qr, s3));
|
||||
|
||||
let s4 = Fr.mul(proof.eval_c, challanges.v[1]);
|
||||
res = G1.add(res, G1.timesFr(vk.Qo, s4));
|
||||
|
||||
res = G1.add(res, G1.timesFr(vk.Qc, challanges.v[1]));
|
||||
|
||||
const betaxi = Fr.mul(challanges.beta, challanges.xi);
|
||||
let s6a = proof.eval_a;
|
||||
s6a = Fr.add(s6a, betaxi);
|
||||
s6a = Fr.add(s6a, challanges.gamma);
|
||||
|
||||
let s6b = proof.eval_b;
|
||||
s6b = Fr.add(s6b, Fr.mul(betaxi, vk.k1));
|
||||
s6b = Fr.add(s6b, challanges.gamma);
|
||||
|
||||
let s6c = proof.eval_c;
|
||||
s6c = Fr.add(s6c, Fr.mul(betaxi, vk.k2));
|
||||
s6c = Fr.add(s6c, challanges.gamma);
|
||||
|
||||
let s6 = Fr.mul(Fr.mul(s6a, s6b), s6c);
|
||||
s6 = Fr.mul(s6, Fr.mul(challanges.alpha, challanges.v[1]));
|
||||
|
||||
let s6d = Fr.mul(Fr.mul(l1, Fr.square(challanges.alpha)), challanges.v[1]);
|
||||
s6 = Fr.add(s6, s6d);
|
||||
|
||||
s6 = Fr.add(s6, challanges.u);
|
||||
res = G1.add(res, G1.timesFr(proof.Z, s6));
|
||||
|
||||
|
||||
let s7a = proof.eval_a;
|
||||
s7a = Fr.add(s7a, Fr.mul(challanges.beta, proof.eval_s1));
|
||||
s7a = Fr.add(s7a, challanges.gamma);
|
||||
|
||||
let s7b = proof.eval_b;
|
||||
s7b = Fr.add(s7b, Fr.mul(challanges.beta, proof.eval_s2));
|
||||
s7b = Fr.add(s7b, challanges.gamma);
|
||||
|
||||
let s7 = Fr.mul(s7a, s7b);
|
||||
s7 = Fr.mul(s7, challanges.alpha);
|
||||
s7 = Fr.mul(s7, challanges.v[1]);
|
||||
s7 = Fr.mul(s7, challanges.beta);
|
||||
s7 = Fr.mul(s7, proof.eval_zw);
|
||||
res = G1.sub(res, G1.timesFr(vk.S3, s7));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
function calculateF(curve, proof, challanges, vk, D) {
|
||||
const G1 = curve.G1;
|
||||
const Fr = curve.Fr;
|
||||
|
||||
let res = proof.T1;
|
||||
|
||||
res = G1.add(res, G1.timesFr(proof.T2, challanges.xin));
|
||||
res = G1.add(res, G1.timesFr(proof.T3, Fr.square(challanges.xin)));
|
||||
res = G1.add(res, D);
|
||||
res = G1.add(res, G1.timesFr(proof.A, challanges.v[2]));
|
||||
res = G1.add(res, G1.timesFr(proof.B, challanges.v[3]));
|
||||
res = G1.add(res, G1.timesFr(proof.C, challanges.v[4]));
|
||||
res = G1.add(res, G1.timesFr(vk.S1, challanges.v[5]));
|
||||
res = G1.add(res, G1.timesFr(vk.S2, challanges.v[6]));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
function calculateE(curve, proof, challanges, vk, t) {
|
||||
const G1 = curve.G1;
|
||||
const Fr = curve.Fr;
|
||||
|
||||
let s = t;
|
||||
|
||||
s = Fr.add(s, Fr.mul(challanges.v[1], proof.eval_r));
|
||||
s = Fr.add(s, Fr.mul(challanges.v[2], proof.eval_a));
|
||||
s = Fr.add(s, Fr.mul(challanges.v[3], proof.eval_b));
|
||||
s = Fr.add(s, Fr.mul(challanges.v[4], proof.eval_c));
|
||||
s = Fr.add(s, Fr.mul(challanges.v[5], proof.eval_s1));
|
||||
s = Fr.add(s, Fr.mul(challanges.v[6], proof.eval_s2));
|
||||
s = Fr.add(s, Fr.mul(challanges.u, proof.eval_zw));
|
||||
|
||||
const res = G1.timesFr(G1.one, s);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
async function isValidPairing(curve, proof, challanges, vk, E, F) {
|
||||
const G1 = curve.G1;
|
||||
const Fr = curve.Fr;
|
||||
|
||||
let A1 = proof.Wxi;
|
||||
A1 = G1.add(A1, G1.timesFr(proof.Wxiw, challanges.u));
|
||||
|
||||
let B1 = G1.timesFr(proof.Wxi, challanges.xi);
|
||||
const s = Fr.mul(Fr.mul(challanges.u, challanges.xi), Fr.w[vk.power]);
|
||||
B1 = G1.add(B1, G1.timesFr(proof.Wxiw, s));
|
||||
B1 = G1.add(B1, F);
|
||||
B1 = G1.sub(B1, E);
|
||||
|
||||
const res = await curve.pairingEq(
|
||||
G1.neg(A1) , vk.X_2,
|
||||
B1 , curve.G2.one
|
||||
);
|
||||
|
||||
return res;
|
||||
|
||||
}
|
@ -1,3 +1,21 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export {default as newAccumulator} from "./powersoftau_new.js";
|
||||
export {default as exportChallenge} from "./powersoftau_export_challenge.js";
|
||||
|
@ -1,10 +1,27 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import Blake2b from "blake2b-wasm";
|
||||
import * as utils from "./powersoftau_utils.js";
|
||||
import * as misc from "./misc.js";
|
||||
import * as binFileUtils from "@iden3/binfileutils";
|
||||
|
||||
|
||||
|
||||
export default async function beacon(oldPtauFilename, newPTauFilename, name, beaconHashStr,numIterationsExp, logger) {
|
||||
const beaconHash = misc.hex2ByteArray(beaconHashStr);
|
||||
if ( (beaconHash.byteLength == 0)
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Format of the output
|
||||
// Hash of the last contribution 64 Bytes
|
||||
// 2^N*2-1 TauG1 Points (compressed)
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Format of the output
|
||||
// Hash of the last contribution 64 Bytes
|
||||
// 2^N*2-1 TauG1 Points (uncompressed)
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import * as binFileUtils from "@iden3/binfileutils";
|
||||
import * as utils from "./powersoftau_utils.js";
|
||||
import * as fastFile from "fastfile";
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import * as utils from "./powersoftau_utils.js";
|
||||
import * as binFileUtils from "@iden3/binfileutils";
|
||||
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import * as fastFile from "fastfile";
|
||||
import Blake2b from "blake2b-wasm";
|
||||
import * as utils from "./powersoftau_utils.js";
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
Header(1)
|
||||
n8
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import * as binFileUtils from "@iden3/binfileutils";
|
||||
import * as utils from "./powersoftau_utils.js";
|
||||
import {BigBuffer} from "ffjavascript";
|
||||
|
@ -1,3 +1,21 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import * as binFileUtils from "@iden3/binfileutils";
|
||||
import * as utils from "./powersoftau_utils.js";
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Scalar } from "ffjavascript";
|
||||
import Blake2b from "blake2b-wasm";
|
||||
import * as keyPair from "./keypair.js";
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import Blake2b from "blake2b-wasm";
|
||||
import * as utils from "./powersoftau_utils.js";
|
||||
import * as keyPair from "./keypair.js";
|
||||
|
19
src/r1cs.js
19
src/r1cs.js
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export {default as print} from "./r1cs_print.js";
|
||||
export {default as info} from "./r1cs_info.js";
|
||||
export {default as exportJson} from "./r1cs_export_json.js";
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {readR1cs} from "r1csfile";
|
||||
|
||||
export function stringifyBigInts(Fr, o) {
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Scalar } from "ffjavascript";
|
||||
import { readR1cs } from "r1csfile";
|
||||
|
||||
|
@ -1,3 +1,21 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export default function r1csPrint(r1cs, syms, logger) {
|
||||
for (let i=0; i<r1cs.constraints.length; i++) {
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export {default as genGroth16Verifier} from "./solidity_gengroth16verifier.js";
|
||||
export {default as prove} from "./groth16_prove.js";
|
||||
export {default as validate} from "./groth16_verify.js";
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const inBrowser = (typeof window !== "undefined");
|
||||
let NodeWorker;
|
||||
if (!inBrowser) {
|
||||
|
19
src/wtns.js
19
src/wtns.js
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export {default as calculate} from "./wtns_calculate.js";
|
||||
export {default as debug} from "./wtns_debug.js";
|
||||
export {default as exportJson} from "./wtns_export_json.js";
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import * as fastFile from "fastfile";
|
||||
import { WitnessCalculatorBuilder } from "circom_runtime";
|
||||
import * as wtnsUtils from "./wtns_utils.js";
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import * as fastFile from "fastfile";
|
||||
import { WitnessCalculatorBuilder } from "circom_runtime";
|
||||
import * as wtnsUtils from "./wtns_utils.js";
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {read} from "./wtns_utils.js";
|
||||
|
||||
export default async function wtnsExportJson(wtnsFileName) {
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Scalar } from "ffjavascript";
|
||||
|
||||
import * as binFileUtils from "@iden3/binfileutils";
|
||||
|
19
src/zkey.js
19
src/zkey.js
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export {default as newZKey} from "./zkey_new.js";
|
||||
export {default as exportBellman} from "./zkey_export_bellman.js";
|
||||
export {default as importBellman} from "./zkey_import_bellman.js";
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import * as binFileUtils from "@iden3/binfileutils";
|
||||
import * as zkeyUtils from "./zkey_utils.js";
|
||||
import { getCurveFromQ as getCurve } from "./curves.js";
|
||||
@ -31,7 +50,12 @@ export default async function beacon(zkeyNameOld, zkeyNameNew, name, beaconHashS
|
||||
|
||||
|
||||
const {fd: fdOld, sections: sections} = await binFileUtils.readBinFile(zkeyNameOld, "zkey", 2);
|
||||
const zkey = await zkeyUtils.readHeader(fdOld, sections, "groth16");
|
||||
const zkey = await zkeyUtils.readHeader(fdOld, sections);
|
||||
|
||||
if (zkey.protocol != "groth16") {
|
||||
throw new Error("zkey file is not groth16");
|
||||
}
|
||||
|
||||
|
||||
const curve = await getCurve(zkey.q);
|
||||
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Format of the output
|
||||
// Hash of the last contribution 64 Bytes
|
||||
// 2^N*2-1 TauG1 Points (compressed)
|
||||
|
@ -1,3 +1,21 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import * as binFileUtils from "@iden3/binfileutils";
|
||||
import * as zkeyUtils from "./zkey_utils.js";
|
||||
@ -12,7 +30,10 @@ export default async function phase2contribute(zkeyNameOld, zkeyNameNew, name, e
|
||||
await Blake2b.ready();
|
||||
|
||||
const {fd: fdOld, sections: sections} = await binFileUtils.readBinFile(zkeyNameOld, "zkey", 2);
|
||||
const zkey = await zkeyUtils.readHeader(fdOld, sections, "groth16");
|
||||
const zkey = await zkeyUtils.readHeader(fdOld, sections);
|
||||
if (zkey.protocol != "groth16") {
|
||||
throw new Error("zkey file is not groth16");
|
||||
}
|
||||
|
||||
const curve = await getCurve(zkey.q);
|
||||
|
||||
|
@ -7,7 +7,10 @@ import { getCurveFromQ as getCurve } from "./curves.js";
|
||||
export default async function phase2exportMPCParams(zkeyName, mpcparamsName, logger) {
|
||||
|
||||
const {fd: fdZKey, sections: sectionsZKey} = await binFileUtils.readBinFile(zkeyName, "zkey", 2);
|
||||
const zkey = await zkeyUtils.readHeader(fdZKey, sectionsZKey, "groth16");
|
||||
const zkey = await zkeyUtils.readHeader(fdZKey, sectionsZKey);
|
||||
if (zkey.protocol != "groth16") {
|
||||
throw new Error("zkey file is not groth16");
|
||||
}
|
||||
|
||||
const curve = await getCurve(zkey.q);
|
||||
const sG1 = curve.G1.F.n8*2;
|
||||
@ -133,4 +136,4 @@ export default async function phase2exportMPCParams(zkeyName, mpcparamsName, log
|
||||
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { readZKey as readZKey } from "./zkey_utils.js";
|
||||
|
||||
export default async function zkeyExportJson(zkeyFileName, verbose) {
|
||||
export default async function zkeyExportJson(zkeyFileName) {
|
||||
|
||||
const zKey = await readZKey(zkeyFileName, true);
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
import * as fastFile from "fastfile";
|
||||
import ejs from "ejs";
|
||||
|
||||
import exportVerificationKey from "./zkey_export_verificationkey.js";
|
||||
// Not ready yet
|
||||
@ -6,47 +7,11 @@ import exportVerificationKey from "./zkey_export_verificationkey.js";
|
||||
|
||||
|
||||
|
||||
export default async function exportSolidityVerifier(zKeyName, templateName, logger) {
|
||||
export default async function exportSolidityVerifier(zKeyName, templates, logger) {
|
||||
|
||||
const verificationKey = await exportVerificationKey(zKeyName, logger);
|
||||
|
||||
const fd = await fastFile.readExisting(templateName);
|
||||
const buff = await fd.read(fd.totalSize);
|
||||
let template = new TextDecoder("utf-8").decode(buff);
|
||||
let template = templates[verificationKey.protocol];
|
||||
|
||||
const vkalpha1_str = `${verificationKey.vk_alpha_1[0].toString()},`+
|
||||
`${verificationKey.vk_alpha_1[1].toString()}`;
|
||||
template = template.replace("<%vk_alpha1%>", vkalpha1_str);
|
||||
|
||||
const vkbeta2_str = `[${verificationKey.vk_beta_2[0][1].toString()},`+
|
||||
`${verificationKey.vk_beta_2[0][0].toString()}], `+
|
||||
`[${verificationKey.vk_beta_2[1][1].toString()},` +
|
||||
`${verificationKey.vk_beta_2[1][0].toString()}]`;
|
||||
template = template.replace("<%vk_beta2%>", vkbeta2_str);
|
||||
|
||||
const vkgamma2_str = `[${verificationKey.vk_gamma_2[0][1].toString()},`+
|
||||
`${verificationKey.vk_gamma_2[0][0].toString()}], `+
|
||||
`[${verificationKey.vk_gamma_2[1][1].toString()},` +
|
||||
`${verificationKey.vk_gamma_2[1][0].toString()}]`;
|
||||
template = template.replace("<%vk_gamma2%>", vkgamma2_str);
|
||||
|
||||
const vkdelta2_str = `[${verificationKey.vk_delta_2[0][1].toString()},`+
|
||||
`${verificationKey.vk_delta_2[0][0].toString()}], `+
|
||||
`[${verificationKey.vk_delta_2[1][1].toString()},` +
|
||||
`${verificationKey.vk_delta_2[1][0].toString()}]`;
|
||||
template = template.replace("<%vk_delta2%>", vkdelta2_str);
|
||||
|
||||
// The points
|
||||
|
||||
template = template.replace("<%vk_input_length%>", (verificationKey.IC.length-1).toString());
|
||||
template = template.replace("<%vk_ic_length%>", verificationKey.IC.length.toString());
|
||||
let vi = "";
|
||||
for (let i=0; i<verificationKey.IC.length; i++) {
|
||||
if (vi != "") vi = vi + " ";
|
||||
vi = vi + `vk.IC[${i}] = Pairing.G1Point(${verificationKey.IC[i][0].toString()},`+
|
||||
`${verificationKey.IC[i][1].toString()});\n`;
|
||||
}
|
||||
template = template.replace("<%vk_ic_pts%>", vi);
|
||||
|
||||
return template;
|
||||
return ejs.render(template , verificationKey);
|
||||
}
|
||||
|
@ -1,15 +1,49 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import * as binFileUtils from "@iden3/binfileutils";
|
||||
import * as zkeyUtils from "./zkey_utils.js";
|
||||
import { getCurveFromQ as getCurve } from "./curves.js";
|
||||
import { utils } from "ffjavascript";
|
||||
const {stringifyBigInts} = utils;
|
||||
|
||||
|
||||
export default async function zkeyExportVerificationKey(zkeyName, logger) {
|
||||
export default async function zkeyExportVerificationKey(zkeyName, /* logger */ ) {
|
||||
|
||||
const {fd, sections} = await binFileUtils.readBinFile(zkeyName, "zkey", 2);
|
||||
const zkey = await zkeyUtils.readHeader(fd, sections, "groth16");
|
||||
const zkey = await zkeyUtils.readHeader(fd, sections);
|
||||
|
||||
let res;
|
||||
if (zkey.protocol == "groth16") {
|
||||
res = await groth16Vk(zkey, fd, sections);
|
||||
} else if (zkey.protocol == "plonk") {
|
||||
res = await plonkVk(zkey);
|
||||
} else {
|
||||
throw new Error("zkey file is not groth16");
|
||||
}
|
||||
|
||||
await fd.close();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
async function groth16Vk(zkey, fd, sections) {
|
||||
const curve = await getCurve(zkey.q);
|
||||
const sG1 = curve.G1.F.n8*2;
|
||||
|
||||
@ -42,7 +76,35 @@ export default async function zkeyExportVerificationKey(zkeyName, logger) {
|
||||
|
||||
vKey = stringifyBigInts(vKey);
|
||||
|
||||
await fd.close();
|
||||
return vKey;
|
||||
}
|
||||
|
||||
|
||||
async function plonkVk(zkey) {
|
||||
const curve = await getCurve(zkey.q);
|
||||
|
||||
let vKey = {
|
||||
protocol: zkey.protocol,
|
||||
curve: curve.name,
|
||||
nPublic: zkey.nPublic,
|
||||
power: zkey.power,
|
||||
|
||||
k1: curve.Fr.toObject(zkey.k1),
|
||||
k2: curve.Fr.toObject(zkey.k2),
|
||||
|
||||
Qm: curve.G1.toObject(zkey.Qm),
|
||||
Ql: curve.G1.toObject(zkey.Ql),
|
||||
Qr: curve.G1.toObject(zkey.Qr),
|
||||
Qo: curve.G1.toObject(zkey.Qo),
|
||||
Qc: curve.G1.toObject(zkey.Qc),
|
||||
S1: curve.G1.toObject(zkey.S1),
|
||||
S2: curve.G1.toObject(zkey.S2),
|
||||
S3: curve.G1.toObject(zkey.S3),
|
||||
|
||||
X_2: curve.G2.toObject(zkey.X_2)
|
||||
};
|
||||
|
||||
vKey = stringifyBigInts(vKey);
|
||||
|
||||
return vKey;
|
||||
}
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import * as zkeyUtils from "./zkey_utils.js";
|
||||
import * as binFileUtils from "@iden3/binfileutils";
|
||||
import * as fastFile from "fastfile";
|
||||
@ -7,7 +26,10 @@ import * as misc from "./misc.js";
|
||||
export default async function phase2importMPCParams(zkeyNameOld, mpcparamsName, zkeyNameNew, name, logger) {
|
||||
|
||||
const {fd: fdZKeyOld, sections: sectionsZKeyOld} = await binFileUtils.readBinFile(zkeyNameOld, "zkey", 2);
|
||||
const zkeyHeader = await zkeyUtils.readHeader(fdZKeyOld, sectionsZKeyOld, "groth16");
|
||||
const zkeyHeader = await zkeyUtils.readHeader(fdZKeyOld, sectionsZKeyOld, false);
|
||||
if (zkeyHeader.protocol != "groth16") {
|
||||
throw new Error("zkey file is not groth16");
|
||||
}
|
||||
|
||||
const curve = await getCurve(zkeyHeader.q);
|
||||
const sG1 = curve.G1.F.n8*2;
|
||||
|
@ -1,3 +1,21 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {readR1csHeader} from "r1csfile";
|
||||
import * as utils from "./powersoftau_utils.js";
|
||||
|
@ -1,3 +1,21 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Format
|
||||
// ======
|
||||
@ -185,20 +203,30 @@ async function readG2(fd, curve, toObject) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
export async function readHeader(fd, sections, protocol, toObject) {
|
||||
if (protocol != "groth16") throw new Error("Protocol not supported: "+protocol);
|
||||
|
||||
const zkey = {};
|
||||
|
||||
export async function readHeader(fd, sections, toObject) {
|
||||
// Read Header
|
||||
/////////////////////
|
||||
await binFileUtils.startReadUniqueSection(fd, sections, 1);
|
||||
const protocolId = await fd.readULE32();
|
||||
if (protocolId != 1) throw new Error("File is not groth");
|
||||
zkey.protocol = "groth16";
|
||||
await binFileUtils.endReadSection(fd);
|
||||
|
||||
if (protocolId == 1) {
|
||||
return await readHeaderGroth16(fd, sections, toObject);
|
||||
} else if (protocolId == 2) {
|
||||
return await readHeaderPlonk(fd, sections, toObject);
|
||||
} else {
|
||||
throw new Error("Protocol not supported: ");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
async function readHeaderGroth16(fd, sections, toObject) {
|
||||
const zkey = {};
|
||||
|
||||
zkey.protocol = "groth16";
|
||||
|
||||
// Read Groth Header
|
||||
/////////////////////
|
||||
await binFileUtils.startReadUniqueSection(fd, sections, 2);
|
||||
@ -228,6 +256,51 @@ export async function readHeader(fd, sections, protocol, toObject) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
async function readHeaderPlonk(fd, sections, protocol, toObject) {
|
||||
const zkey = {};
|
||||
|
||||
zkey.protocol = "plonk";
|
||||
|
||||
// Read Plonk Header
|
||||
/////////////////////
|
||||
await binFileUtils.startReadUniqueSection(fd, sections, 2);
|
||||
const n8q = await fd.readULE32();
|
||||
zkey.n8q = n8q;
|
||||
zkey.q = await binFileUtils.readBigInt(fd, n8q);
|
||||
|
||||
const n8r = await fd.readULE32();
|
||||
zkey.n8r = n8r;
|
||||
zkey.r = await binFileUtils.readBigInt(fd, n8r);
|
||||
|
||||
let curve = await getCurve(zkey.q);
|
||||
|
||||
zkey.nVars = await fd.readULE32();
|
||||
zkey.nPublic = await fd.readULE32();
|
||||
zkey.domainSize = await fd.readULE32();
|
||||
zkey.power = log2(zkey.domainSize);
|
||||
zkey.nAdditions = await fd.readULE32();
|
||||
zkey.nConstrains = await fd.readULE32();
|
||||
zkey.k1 = await fd.read(n8r);
|
||||
zkey.k2 = await fd.read(n8r);
|
||||
|
||||
zkey.Qm = await readG1(fd, curve, toObject);
|
||||
zkey.Ql = await readG1(fd, curve, toObject);
|
||||
zkey.Qr = await readG1(fd, curve, toObject);
|
||||
zkey.Qo = await readG1(fd, curve, toObject);
|
||||
zkey.Qc = await readG1(fd, curve, toObject);
|
||||
zkey.S1 = await readG1(fd, curve, toObject);
|
||||
zkey.S2 = await readG1(fd, curve, toObject);
|
||||
zkey.S3 = await readG1(fd, curve, toObject);
|
||||
zkey.X_2 = await readG2(fd, curve, toObject);
|
||||
|
||||
await binFileUtils.endReadSection(fd);
|
||||
|
||||
return zkey;
|
||||
}
|
||||
|
||||
export async function readZKey(fileName, toObject) {
|
||||
const {fd, sections} = await binFileUtils.readBinFile(fileName, "zkey", 1);
|
||||
|
||||
@ -330,7 +403,7 @@ export async function readZKey(fileName, toObject) {
|
||||
|
||||
return zkey;
|
||||
|
||||
async function readFr2(toObject) {
|
||||
async function readFr2(/* toObject */) {
|
||||
const n = await binFileUtils.readBigInt(fd, zkey.n8r);
|
||||
return Fr.mul(n, Rri2);
|
||||
}
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import * as binFileUtils from "@iden3/binfileutils";
|
||||
import * as zkeyUtils from "./zkey_utils.js";
|
||||
import { getCurveFromQ as getCurve } from "./curves.js";
|
||||
@ -6,7 +25,6 @@ import * as misc from "./misc.js";
|
||||
import { hashToG2 as hashToG2 } from "./keypair.js";
|
||||
const sameRatio = misc.sameRatio;
|
||||
import crypto from "crypto";
|
||||
import newZKey from "./zkey_new.js";
|
||||
import {hashG1, hashPubKey} from "./zkey_utils.js";
|
||||
import { Scalar, ChaCha, BigBuffer } from "ffjavascript";
|
||||
|
||||
@ -18,11 +36,13 @@ export default async function phase2verifyFromInit(initFileName, pTauFileName, z
|
||||
await Blake2b.ready();
|
||||
|
||||
const {fd, sections} = await binFileUtils.readBinFile(zkeyFileName, "zkey", 2);
|
||||
const zkey = await zkeyUtils.readHeader(fd, sections, "groth16");
|
||||
const zkey = await zkeyUtils.readHeader(fd, sections, false);
|
||||
if (zkey.protocol != "groth16") {
|
||||
throw new Error("zkey file is not groth16");
|
||||
}
|
||||
|
||||
const curve = await getCurve(zkey.q);
|
||||
const sG1 = curve.G1.F.n8*2;
|
||||
const sG2 = curve.G2.F.n8*2;
|
||||
|
||||
const mpcParams = await zkeyUtils.readMPCParams(fd, curve, sections);
|
||||
|
||||
@ -82,7 +102,11 @@ export default async function phase2verifyFromInit(initFileName, pTauFileName, z
|
||||
|
||||
|
||||
const {fd: fdInit, sections: sectionsInit} = await binFileUtils.readBinFile(initFileName, "zkey", 2);
|
||||
const zkeyInit = await zkeyUtils.readHeader(fdInit, sectionsInit, "groth16");
|
||||
const zkeyInit = await zkeyUtils.readHeader(fdInit, sectionsInit, false);
|
||||
|
||||
if (zkeyInit.protocol != "groth16") {
|
||||
throw new Error("zkeyinit file is not groth16");
|
||||
}
|
||||
|
||||
if ( (!Scalar.eq(zkeyInit.q, zkey.q))
|
||||
||(!Scalar.eq(zkeyInit.r, zkey.r))
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
Copyright 2018 0KIMS association.
|
||||
|
||||
This file is part of snarkJS.
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import newZKey from "./zkey_new.js";
|
||||
import phase2verifyFromInit from "./zkey_verify_frominit.js";
|
||||
|
||||
|
@ -176,12 +176,36 @@ contract Verifier {
|
||||
Pairing.G1Point C;
|
||||
}
|
||||
function verifyingKey() internal pure returns (VerifyingKey memory vk) {
|
||||
vk.alfa1 = Pairing.G1Point(<%vk_alpha1%>);
|
||||
vk.beta2 = Pairing.G2Point(<%vk_beta2%>);
|
||||
vk.gamma2 = Pairing.G2Point(<%vk_gamma2%>);
|
||||
vk.delta2 = Pairing.G2Point(<%vk_delta2%>);
|
||||
vk.IC = new Pairing.G1Point[](<%vk_ic_length%>);
|
||||
<%vk_ic_pts%>
|
||||
vk.alfa1 = Pairing.G1Point(
|
||||
<%=vk_alpha_1[0]%>,
|
||||
<%=vk_alpha_1[1]%>
|
||||
);
|
||||
|
||||
vk.beta2 = Pairing.G2Point(
|
||||
[<%=vk_beta_2[0][1]%>,
|
||||
<%=vk_beta_2[0][0]%>],
|
||||
[<%=vk_beta_2[1][1]%>,
|
||||
<%=vk_beta_2[1][0]%>]
|
||||
);
|
||||
vk.gamma2 = Pairing.G2Point(
|
||||
[<%=vk_gamma_2[0][1]%>,
|
||||
<%=vk_gamma_2[0][0]%>],
|
||||
[<%=vk_gamma_2[1][1]%>,
|
||||
<%=vk_gamma_2[1][0]%>]
|
||||
);
|
||||
vk.delta2 = Pairing.G2Point(
|
||||
[<%=vk_delta_2[0][1]%>,
|
||||
<%=vk_delta_2[0][0]%>],
|
||||
[<%=vk_delta_2[1][1]%>,
|
||||
<%=vk_delta_2[1][0]%>]
|
||||
);
|
||||
vk.IC = new Pairing.G1Point[](<%=IC.length%>);
|
||||
<% for (let i=0; i<IC.length; i++) { %>
|
||||
vk.IC[<%=i%>] = Pairing.G1Point(
|
||||
<%=IC[i][0]%>,
|
||||
<%=IC[i][1]%>
|
||||
);
|
||||
<% } %>
|
||||
}
|
||||
function verify(uint[] memory input, Proof memory proof) internal view returns (uint) {
|
||||
uint256 snark_scalar_field = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
|
||||
@ -207,7 +231,7 @@ contract Verifier {
|
||||
uint[2] memory a,
|
||||
uint[2][2] memory b,
|
||||
uint[2] memory c,
|
||||
uint[<%vk_input_length%>] memory input
|
||||
uint[<%=IC.length-1%>] memory input
|
||||
) public view returns (bool r) {
|
||||
Proof memory proof;
|
||||
proof.A = Pairing.G1Point(a[0], a[1]);
|
632
templates/verifier_plonk.sol.ejs
Normal file
632
templates/verifier_plonk.sol.ejs
Normal file
@ -0,0 +1,632 @@
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
/*
|
||||
Copyright 2021 0KIMS association.
|
||||
|
||||
This file is generated with [snarkJS](https://github.com/iden3/snarkjs).
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
pragma solidity >=0.7.0 <0.9.0;
|
||||
|
||||
contract PlonkVerifier {
|
||||
|
||||
uint16 constant n = <%=2**power%>;
|
||||
uint16 constant nPublic = <%=nPublic%>;
|
||||
uint16 constant nLagrange = <%=Math.max(nPublic, 1)%>;
|
||||
|
||||
uint256 constant Qmx = <%=Qm[0]%>;
|
||||
uint256 constant Qmy = <%=Qm[1]%>;
|
||||
uint256 constant Qlx = <%=Ql[0]%>;
|
||||
uint256 constant Qly = <%=Ql[1]%>;
|
||||
uint256 constant Qrx = <%=Qr[0]%>;
|
||||
uint256 constant Qry = <%=Qr[1]%>;
|
||||
uint256 constant Qox = <%=Qo[0]%>;
|
||||
uint256 constant Qoy = <%=Qo[1]%>;
|
||||
uint256 constant Qcx = <%=Qc[0]%>;
|
||||
uint256 constant Qcy = <%=Qc[1]%>;
|
||||
uint256 constant S1x = <%=S1[0]%>;
|
||||
uint256 constant S1y = <%=S1[1]%>;
|
||||
uint256 constant S2x = <%=S2[0]%>;
|
||||
uint256 constant S2y = <%=S2[1]%>;
|
||||
uint256 constant S3x = <%=S3[0]%>;
|
||||
uint256 constant S3y = <%=S3[1]%>;
|
||||
uint256 constant k1 = 2;
|
||||
uint256 constant k2 = 3;
|
||||
uint256 constant X2x1 = <%=X_2[0][0]%>;
|
||||
uint256 constant X2x2 = <%=X_2[0][1]%>;
|
||||
uint256 constant X2y1 = <%=X_2[1][0]%>;
|
||||
uint256 constant X2y2 = <%=X_2[1][1]%>;
|
||||
|
||||
uint256 constant q = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
|
||||
uint256 constant qf = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
|
||||
uint256 constant w1 = 19540430494807482326159819597004422086093766032135589407132600596362845576832;
|
||||
|
||||
uint256 constant G1x = 1;
|
||||
uint256 constant G1y = 2;
|
||||
uint256 constant G2x1 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;
|
||||
uint256 constant G2x2 = 11559732032986387107991004021392285783925812861821192530917403151452391805634;
|
||||
uint256 constant G2y1 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
|
||||
uint256 constant G2y2 = 4082367875863433681332203403145435568316851327593401208105741076214120093531;
|
||||
uint16 constant pA = 32;
|
||||
uint16 constant pB = 96;
|
||||
uint16 constant pC = 160;
|
||||
uint16 constant pZ = 224;
|
||||
uint16 constant pT1 = 288;
|
||||
uint16 constant pT2 = 352;
|
||||
uint16 constant pT3 = 416;
|
||||
uint16 constant pWxi = 480;
|
||||
uint16 constant pWxiw = 544;
|
||||
uint16 constant pEval_a = 608;
|
||||
uint16 constant pEval_b = 640;
|
||||
uint16 constant pEval_c = 672;
|
||||
uint16 constant pEval_s1 = 704;
|
||||
uint16 constant pEval_s2 = 736;
|
||||
uint16 constant pEval_zw = 768;
|
||||
uint16 constant pEval_r = 800;
|
||||
|
||||
uint16 constant pAlpha = 0;
|
||||
uint16 constant pBeta = 32;
|
||||
uint16 constant pGamma = 64;
|
||||
uint16 constant pXi = 96;
|
||||
uint16 constant pXin = 128;
|
||||
uint16 constant pBetaXi = 160;
|
||||
uint16 constant pV1 = 192;
|
||||
uint16 constant pV2 = 224;
|
||||
uint16 constant pV3 = 256;
|
||||
uint16 constant pV4 = 288;
|
||||
uint16 constant pV5 = 320;
|
||||
uint16 constant pV6 = 352;
|
||||
uint16 constant pU = 384;
|
||||
uint16 constant pPl = 416;
|
||||
uint16 constant pEval_t = 448;
|
||||
uint16 constant pA1 = 480;
|
||||
uint16 constant pB1 = 544;
|
||||
uint16 constant pZh = 608;
|
||||
uint16 constant pZhInv = 640;
|
||||
<% for (let i=1; i<=Math.max(nPublic, 1); i++) { %>
|
||||
uint16 constant pEval_l<%=i%> = <%=640+i*32%>;
|
||||
<% } %>
|
||||
|
||||
|
||||
uint16 constant lastMem = <%=672+32*Math.max(nPublic,1)%>;
|
||||
|
||||
|
||||
function verifyProof(bytes memory proof, uint[] memory pubSignals) public view returns (bool) {
|
||||
assembly {
|
||||
/////////
|
||||
// Computes the inverse using the extended euclidean algorithm
|
||||
/////////
|
||||
function inverse(a, q) -> inv {
|
||||
let t := 0
|
||||
let newt := 1
|
||||
let r := q
|
||||
let newr := a
|
||||
let quotient
|
||||
let aux
|
||||
|
||||
for { } newr { } {
|
||||
quotient := sdiv(r, newr)
|
||||
aux := sub(t, mul(quotient, newt))
|
||||
t:= newt
|
||||
newt:= aux
|
||||
|
||||
aux := sub(r,mul(quotient, newr))
|
||||
r := newr
|
||||
newr := aux
|
||||
}
|
||||
|
||||
if gt(r, 1) { revert(0,0) }
|
||||
if slt(t, 0) { t:= add(t, q) }
|
||||
|
||||
inv := t
|
||||
}
|
||||
|
||||
///////
|
||||
// Computes the inverse of an array of values
|
||||
// See https://vitalik.ca/general/2018/07/21/starks_part_3.html in section where explain fields operations
|
||||
//////
|
||||
function inverseArray(pVals, n) {
|
||||
|
||||
let pAux := mload(0x40) // Point to the next free position
|
||||
let pIn := pVals
|
||||
let lastPIn := add(pVals, mul(n, 32)) // Read n elemnts
|
||||
let acc := mload(pIn) // Read the first element
|
||||
pIn := add(pIn, 32) // Point to the second element
|
||||
let inv
|
||||
|
||||
|
||||
for { } lt(pIn, lastPIn) {
|
||||
pAux := add(pAux, 32)
|
||||
pIn := add(pIn, 32)
|
||||
}
|
||||
{
|
||||
mstore(pAux, acc)
|
||||
acc := mulmod(acc, mload(pIn), q)
|
||||
}
|
||||
acc := inverse(acc, q)
|
||||
|
||||
// At this point pAux pint to the next free position we substract 1 to point to the last used
|
||||
pAux := sub(pAux, 32)
|
||||
// pIn points to the n+1 element, we substract to point to n
|
||||
pIn := sub(pIn, 32)
|
||||
lastPIn := pVals // We don't process the first element
|
||||
for { } gt(pIn, lastPIn) {
|
||||
pAux := sub(pAux, 32)
|
||||
pIn := sub(pIn, 32)
|
||||
}
|
||||
{
|
||||
inv := mulmod(acc, mload(pAux), q)
|
||||
acc := mulmod(acc, mload(pIn), q)
|
||||
mstore(pIn, inv)
|
||||
}
|
||||
// pIn points to first element, we just set it.
|
||||
mstore(pIn, acc)
|
||||
}
|
||||
|
||||
function checkField(v) {
|
||||
if iszero(lt(v, q)) {
|
||||
mstore(0, 0)
|
||||
return(0,0x20)
|
||||
}
|
||||
}
|
||||
|
||||
function checkInput(pProof) {
|
||||
if iszero(eq(mload(pProof), 800 )) {
|
||||
mstore(0, 0)
|
||||
return(0,0x20)
|
||||
}
|
||||
checkField(mload(add(pProof, pEval_a)))
|
||||
checkField(mload(add(pProof, pEval_b)))
|
||||
checkField(mload(add(pProof, pEval_c)))
|
||||
checkField(mload(add(pProof, pEval_s1)))
|
||||
checkField(mload(add(pProof, pEval_s2)))
|
||||
checkField(mload(add(pProof, pEval_zw)))
|
||||
checkField(mload(add(pProof, pEval_r)))
|
||||
|
||||
// Points are checked in the point operations precompiled smart contracts
|
||||
}
|
||||
|
||||
function calculateChallanges(pProof, pMem) {
|
||||
|
||||
let a
|
||||
let b
|
||||
|
||||
b := mod(keccak256(add(pProof, pA), 192), q)
|
||||
mstore( add(pMem, pBeta), b)
|
||||
mstore( add(pMem, pGamma), mod(keccak256(add(pMem, pBeta), 32), q))
|
||||
mstore( add(pMem, pAlpha), mod(keccak256(add(pProof, pZ), 64), q))
|
||||
|
||||
a := mod(keccak256(add(pProof, pT1), 192), q)
|
||||
mstore( add(pMem, pXi), a)
|
||||
mstore( add(pMem, pBetaXi), mulmod(b, a, q))
|
||||
<%for (let i=0; i<power;i++) {%>
|
||||
a:= mulmod(a, a, q)
|
||||
<%}%>
|
||||
mstore( add(pMem, pXin), a)
|
||||
a:= mod(add(sub(a, 1),q), q)
|
||||
mstore( add(pMem, pZh), a)
|
||||
mstore( add(pMem, pZhInv), a) // We will invert later together with lagrange pols
|
||||
|
||||
let v1 := mod(keccak256(add(pProof, pEval_a), 224), q)
|
||||
mstore( add(pMem, pV1), v1)
|
||||
a := mulmod(v1, v1, q)
|
||||
mstore( add(pMem, pV2), a)
|
||||
a := mulmod(a, v1, q)
|
||||
mstore( add(pMem, pV3), a)
|
||||
a := mulmod(a, v1, q)
|
||||
mstore( add(pMem, pV4), a)
|
||||
a := mulmod(a, v1, q)
|
||||
mstore( add(pMem, pV5), a)
|
||||
a := mulmod(a, v1, q)
|
||||
mstore( add(pMem, pV6), a)
|
||||
|
||||
mstore( add(pMem, pU), mod(keccak256(add(pProof, pWxi), 128), q))
|
||||
}
|
||||
|
||||
function calculateLagrange(pMem) {
|
||||
|
||||
let w := 1
|
||||
<% for (let i=1; i<=Math.max(nPublic, 1); i++) { %>
|
||||
mstore(
|
||||
add(pMem, pEval_l<%=i%>),
|
||||
mulmod(
|
||||
n,
|
||||
mod(
|
||||
add(
|
||||
sub(
|
||||
mload(add(pMem, pXi)),
|
||||
w
|
||||
),
|
||||
q
|
||||
),
|
||||
q
|
||||
),
|
||||
q
|
||||
)
|
||||
)
|
||||
<% if (i<Math.max(nPublic, 1)) { %>
|
||||
w := mulmod(w, w1, q)
|
||||
<% } %>
|
||||
<% } %>
|
||||
|
||||
inverseArray(add(pMem, pZhInv), <%=Math.max(nPublic, 1)+1%> )
|
||||
|
||||
let zh := mload(add(pMem, pZh))
|
||||
w := 1
|
||||
<% for (let i=1; i<=Math.max(nPublic, 1); i++) { %>
|
||||
<% if (i==1) { %>
|
||||
mstore(
|
||||
add(pMem, pEval_l1 ),
|
||||
mulmod(
|
||||
mload(add(pMem, pEval_l1 )),
|
||||
zh,
|
||||
q
|
||||
)
|
||||
)
|
||||
<% } else { %>
|
||||
mstore(
|
||||
add(pMem, pEval_l<%=i%>),
|
||||
mulmod(
|
||||
w,
|
||||
mulmod(
|
||||
mload(add(pMem, pEval_l<%=i%>)),
|
||||
zh,
|
||||
q
|
||||
),
|
||||
q
|
||||
)
|
||||
)
|
||||
<% } %>
|
||||
<% if (i<Math.max(nPublic, 1)) { %>
|
||||
w := mulmod(w, w1, q)
|
||||
<% } %>
|
||||
<% } %>
|
||||
|
||||
|
||||
}
|
||||
|
||||
function calculatePl(pMem, pPub) {
|
||||
let pl := 0
|
||||
|
||||
<% for (let i=0; i<nPublic; i++) { %>
|
||||
pl := mod(
|
||||
add(
|
||||
sub(
|
||||
pl,
|
||||
mulmod(
|
||||
mload(add(pMem, pEval_l<%=i+1%>)),
|
||||
mload(add(pPub, <%=32+i*32%>)),
|
||||
q
|
||||
)
|
||||
),
|
||||
q
|
||||
),
|
||||
q
|
||||
)
|
||||
<% } %>
|
||||
|
||||
mstore(add(pMem, pPl), pl)
|
||||
|
||||
|
||||
}
|
||||
|
||||
function calculateT(pProof, pMem) {
|
||||
let t
|
||||
let t1
|
||||
let t2
|
||||
t := addmod(
|
||||
mload(add(pProof, pEval_r)),
|
||||
mload(add(pMem, pPl)),
|
||||
q
|
||||
)
|
||||
|
||||
t1 := mulmod(
|
||||
mload(add(pProof, pEval_s1)),
|
||||
mload(add(pMem, pBeta)),
|
||||
q
|
||||
)
|
||||
|
||||
t1 := addmod(
|
||||
t1,
|
||||
mload(add(pProof, pEval_a)),
|
||||
q
|
||||
)
|
||||
|
||||
t1 := addmod(
|
||||
t1,
|
||||
mload(add(pMem, pGamma)),
|
||||
q
|
||||
)
|
||||
|
||||
t2 := mulmod(
|
||||
mload(add(pProof, pEval_s2)),
|
||||
mload(add(pMem, pBeta)),
|
||||
q
|
||||
)
|
||||
|
||||
t2 := addmod(
|
||||
t2,
|
||||
mload(add(pProof, pEval_b)),
|
||||
q
|
||||
)
|
||||
|
||||
t2 := addmod(
|
||||
t2,
|
||||
mload(add(pMem, pGamma)),
|
||||
q
|
||||
)
|
||||
|
||||
t1 := mulmod(t1, t2, q)
|
||||
|
||||
t2 := addmod(
|
||||
mload(add(pProof, pEval_c)),
|
||||
mload(add(pMem, pGamma)),
|
||||
q
|
||||
)
|
||||
|
||||
t1 := mulmod(t1, t2, q)
|
||||
t1 := mulmod(t1, mload(add(pProof, pEval_zw)), q)
|
||||
t1 := mulmod(t1, mload(add(pMem, pAlpha)), q)
|
||||
|
||||
t2 := mulmod(
|
||||
mload(add(pMem, pEval_l1)),
|
||||
mload(add(pMem, pAlpha)),
|
||||
q
|
||||
)
|
||||
|
||||
t2 := mulmod(
|
||||
t2,
|
||||
mload(add(pMem, pAlpha)),
|
||||
q
|
||||
)
|
||||
|
||||
t1 := addmod(t1, t2, q)
|
||||
|
||||
t := mod(sub(add(t, q), t1), q)
|
||||
t := mulmod(t, mload(add(pMem, pZhInv)), q)
|
||||
|
||||
mstore( add(pMem, pEval_t) , t)
|
||||
|
||||
}
|
||||
|
||||
function g1_set(pR, pP) {
|
||||
mstore(pR, mload(pP))
|
||||
mstore(add(pR, 32), mload(add(pP,32)))
|
||||
}
|
||||
|
||||
function g1_acc(pR, pP) {
|
||||
let mIn := mload(0x40)
|
||||
mstore(mIn, mload(pR))
|
||||
mstore(add(mIn,32), mload(add(pR, 32)))
|
||||
mstore(add(mIn,64), mload(pP))
|
||||
mstore(add(mIn,96), mload(add(pP, 32)))
|
||||
|
||||
let success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64)
|
||||
|
||||
if iszero(success) {
|
||||
mstore(0, 0)
|
||||
return(0,0x20)
|
||||
}
|
||||
}
|
||||
|
||||
function g1_mulAcc(pR, pP, s) {
|
||||
let success
|
||||
let mIn := mload(0x40)
|
||||
mstore(mIn, mload(pP))
|
||||
mstore(add(mIn,32), mload(add(pP, 32)))
|
||||
mstore(add(mIn,64), s)
|
||||
|
||||
success := staticcall(sub(gas(), 2000), 7, mIn, 96, mIn, 64)
|
||||
|
||||
if iszero(success) {
|
||||
mstore(0, 0)
|
||||
return(0,0x20)
|
||||
}
|
||||
|
||||
mstore(add(mIn,64), mload(pR))
|
||||
mstore(add(mIn,96), mload(add(pR, 32)))
|
||||
|
||||
success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64)
|
||||
|
||||
if iszero(success) {
|
||||
mstore(0, 0)
|
||||
return(0,0x20)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function g1_mulAccC(pR, x, y, s) {
|
||||
let success
|
||||
let mIn := mload(0x40)
|
||||
mstore(mIn, x)
|
||||
mstore(add(mIn,32), y)
|
||||
mstore(add(mIn,64), s)
|
||||
|
||||
success := staticcall(sub(gas(), 2000), 7, mIn, 96, mIn, 64)
|
||||
|
||||
if iszero(success) {
|
||||
mstore(0, 0)
|
||||
return(0,0x20)
|
||||
}
|
||||
|
||||
mstore(add(mIn,64), mload(pR))
|
||||
mstore(add(mIn,96), mload(add(pR, 32)))
|
||||
|
||||
success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64)
|
||||
|
||||
if iszero(success) {
|
||||
mstore(0, 0)
|
||||
return(0,0x20)
|
||||
}
|
||||
}
|
||||
|
||||
function g1_mulSetC(pR, x, y, s) {
|
||||
let success
|
||||
let mIn := mload(0x40)
|
||||
mstore(mIn, x)
|
||||
mstore(add(mIn,32), y)
|
||||
mstore(add(mIn,64), s)
|
||||
|
||||
success := staticcall(sub(gas(), 2000), 7, mIn, 96, pR, 64)
|
||||
|
||||
if iszero(success) {
|
||||
mstore(0, 0)
|
||||
return(0,0x20)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function calculateA1(pProof, pMem) {
|
||||
let p := add(pMem, pA1)
|
||||
g1_set(p, add(pProof, pWxi))
|
||||
g1_mulAcc(p, add(pProof, pWxiw), mload(add(pMem, pU)))
|
||||
}
|
||||
|
||||
|
||||
function calculateB1(pProof, pMem) {
|
||||
let s
|
||||
let s1
|
||||
let p := add(pMem, pB1)
|
||||
|
||||
// Calculate D
|
||||
s := mulmod( mload(add(pProof, pEval_a)), mload(add(pMem, pV1)), q)
|
||||
g1_mulSetC(p, Qlx, Qly, s)
|
||||
|
||||
s := mulmod( s, mload(add(pProof, pEval_b)), q)
|
||||
g1_mulAccC(p, Qmx, Qmy, s)
|
||||
|
||||
s := mulmod( mload(add(pProof, pEval_b)), mload(add(pMem, pV1)), q)
|
||||
g1_mulAccC(p, Qrx, Qry, s)
|
||||
|
||||
s := mulmod( mload(add(pProof, pEval_c)), mload(add(pMem, pV1)), q)
|
||||
g1_mulAccC(p, Qox, Qoy, s)
|
||||
|
||||
s :=mload(add(pMem, pV1))
|
||||
g1_mulAccC(p, Qcx, Qcy, s)
|
||||
|
||||
s := addmod(mload(add(pProof, pEval_a)), mload(add(pMem, pBetaXi)), q)
|
||||
s := addmod(s, mload(add(pMem, pGamma)), q)
|
||||
s1 := mulmod(k1, mload(add(pMem, pBetaXi)), q)
|
||||
s1 := addmod(s1, mload(add(pProof, pEval_b)), q)
|
||||
s1 := addmod(s1, mload(add(pMem, pGamma)), q)
|
||||
s := mulmod(s, s1, q)
|
||||
s1 := mulmod(k2, mload(add(pMem, pBetaXi)), q)
|
||||
s1 := addmod(s1, mload(add(pProof, pEval_c)), q)
|
||||
s1 := addmod(s1, mload(add(pMem, pGamma)), q)
|
||||
s := mulmod(s, s1, q)
|
||||
s := mulmod(s, mload(add(pMem, pAlpha)), q)
|
||||
s := mulmod(s, mload(add(pMem, pV1)), q)
|
||||
s1 := mulmod(mload(add(pMem, pEval_l1)), mload(add(pMem, pAlpha)), q)
|
||||
s1 := mulmod(s1, mload(add(pMem, pAlpha)), q)
|
||||
s1 := mulmod(s1, mload(add(pMem, pV1)), q)
|
||||
s := addmod(s, s1, q)
|
||||
s := addmod(s, mload(add(pMem, pU)), q)
|
||||
g1_mulAcc(p, add(pProof, pZ), s)
|
||||
|
||||
s := mulmod(mload(add(pMem, pBeta)), mload(add(pProof, pEval_s1)), q)
|
||||
s := addmod(s, mload(add(pProof, pEval_a)), q)
|
||||
s := addmod(s, mload(add(pMem, pGamma)), q)
|
||||
s1 := mulmod(mload(add(pMem, pBeta)), mload(add(pProof, pEval_s2)), q)
|
||||
s1 := addmod(s1, mload(add(pProof, pEval_b)), q)
|
||||
s1 := addmod(s1, mload(add(pMem, pGamma)), q)
|
||||
s := mulmod(s, s1, q)
|
||||
s := mulmod(s, mload(add(pMem, pAlpha)), q)
|
||||
s := mulmod(s, mload(add(pMem, pV1)), q)
|
||||
s := mulmod(s, mload(add(pMem, pBeta)), q)
|
||||
s := mulmod(s, mload(add(pProof, pEval_zw)), q)
|
||||
s := mod(sub(q, s), q)
|
||||
g1_mulAccC(p, S3x, S3y, s)
|
||||
|
||||
|
||||
// calculate F
|
||||
g1_acc(p , add(pProof, pT1))
|
||||
|
||||
s := mload(add(pMem, pXin))
|
||||
g1_mulAcc(p, add(pProof, pT2), s)
|
||||
|
||||
s := mulmod(s, s, q)
|
||||
g1_mulAcc(p, add(pProof, pT3), s)
|
||||
|
||||
g1_mulAcc(p, add(pProof, pA), mload(add(pMem, pV2)))
|
||||
g1_mulAcc(p, add(pProof, pB), mload(add(pMem, pV3)))
|
||||
g1_mulAcc(p, add(pProof, pC), mload(add(pMem, pV4)))
|
||||
g1_mulAccC(p, S1x, S1y, mload(add(pMem, pV5)))
|
||||
g1_mulAccC(p, S2x, S2y, mload(add(pMem, pV6)))
|
||||
|
||||
// calculate E
|
||||
s := mload(add(pMem, pEval_t))
|
||||
s := addmod(s, mulmod(mload(add(pProof, pEval_r)), mload(add(pMem, pV1)), q), q)
|
||||
s := addmod(s, mulmod(mload(add(pProof, pEval_a)), mload(add(pMem, pV2)), q), q)
|
||||
s := addmod(s, mulmod(mload(add(pProof, pEval_b)), mload(add(pMem, pV3)), q), q)
|
||||
s := addmod(s, mulmod(mload(add(pProof, pEval_c)), mload(add(pMem, pV4)), q), q)
|
||||
s := addmod(s, mulmod(mload(add(pProof, pEval_s1)), mload(add(pMem, pV5)), q), q)
|
||||
s := addmod(s, mulmod(mload(add(pProof, pEval_s2)), mload(add(pMem, pV6)), q), q)
|
||||
s := addmod(s, mulmod(mload(add(pProof, pEval_zw)), mload(add(pMem, pU)), q), q)
|
||||
s := mod(sub(q, s), q)
|
||||
g1_mulAccC(p, G1x, G1y, s)
|
||||
|
||||
|
||||
// Last part of B
|
||||
s := mload(add(pMem, pXi))
|
||||
g1_mulAcc(p, add(pProof, pWxi), s)
|
||||
|
||||
s := mulmod(mload(add(pMem, pU)), mload(add(pMem, pXi)), q)
|
||||
s := mulmod(s, w1, q)
|
||||
g1_mulAcc(p, add(pProof, pWxiw), s)
|
||||
|
||||
}
|
||||
|
||||
function checkPairing(pMem) -> isOk {
|
||||
let mIn := mload(0x40)
|
||||
mstore(mIn, mload(add(pMem, pA1)))
|
||||
mstore(add(mIn,32), mload(add(add(pMem, pA1), 32)))
|
||||
mstore(add(mIn,64), X2x2)
|
||||
mstore(add(mIn,96), X2x1)
|
||||
mstore(add(mIn,128), X2y2)
|
||||
mstore(add(mIn,160), X2y1)
|
||||
mstore(add(mIn,192), mload(add(pMem, pB1)))
|
||||
let s := mload(add(add(pMem, pB1), 32))
|
||||
s := mod(sub(qf, s), qf)
|
||||
mstore(add(mIn,224), s)
|
||||
mstore(add(mIn,256), G2x2)
|
||||
mstore(add(mIn,288), G2x1)
|
||||
mstore(add(mIn,320), G2y2)
|
||||
mstore(add(mIn,352), G2y1)
|
||||
|
||||
let success := staticcall(sub(gas(), 2000), 8, mIn, 384, mIn, 0x20)
|
||||
|
||||
isOk := and(success, mload(mIn))
|
||||
}
|
||||
|
||||
let pMem := mload(0x40)
|
||||
mstore(0x40, add(pMem, lastMem))
|
||||
|
||||
checkInput(proof)
|
||||
calculateChallanges(proof, pMem)
|
||||
calculateLagrange(pMem)
|
||||
calculatePl(pMem, pubSignals)
|
||||
calculateT(proof, pMem)
|
||||
calculateA1(proof, pMem)
|
||||
calculateB1(proof, pMem)
|
||||
let isValid := checkPairing(pMem)
|
||||
|
||||
mstore(0x40, sub(pMem, lastMem))
|
||||
mstore(0, isValid)
|
||||
return(0,0x20)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
@ -18,9 +18,11 @@ describe("Full process", function () {
|
||||
const zkey_1 = {type: "mem"};
|
||||
const zkey_2 = {type: "mem"};
|
||||
const zkey_final = {type: "mem"};
|
||||
const zkey_plonk = {type: "mem"};
|
||||
const bellman_1 = {type: "mem"};
|
||||
const bellman_2 = {type: "mem"};
|
||||
let vKey;
|
||||
let vKeyPlonk;
|
||||
const wtns = {type: "mem"};
|
||||
let proof;
|
||||
let publicSignals;
|
||||
@ -36,7 +38,7 @@ describe("Full process", function () {
|
||||
});
|
||||
|
||||
it ("powersoftau new", async () => {
|
||||
await snarkjs.powersOfTau.newAccumulator(curve, 10, ptau_0);
|
||||
await snarkjs.powersOfTau.newAccumulator(curve, 11, ptau_0);
|
||||
});
|
||||
|
||||
it ("powersoftau contribute ", async () => {
|
||||
@ -68,7 +70,7 @@ describe("Full process", function () {
|
||||
assert(res);
|
||||
});
|
||||
|
||||
it ("zkey new", async () => {
|
||||
it ("groth16 setup", async () => {
|
||||
await snarkjs.zKey.newZKey(path.join("test", "circuit", "circuit.r1cs"), ptau_final, zkey_0);
|
||||
});
|
||||
|
||||
@ -116,9 +118,31 @@ describe("Full process", function () {
|
||||
publicSignals = res.publicSignals;
|
||||
});
|
||||
|
||||
|
||||
it ("groth16 verify", async () => {
|
||||
const res = await snarkjs.groth16.verify(vKey, publicSignals, proof);
|
||||
assert(res == true);
|
||||
});
|
||||
|
||||
it ("plonk setup", async () => {
|
||||
await snarkjs.plonk.setup(path.join("test", "circuit", "circuit.r1cs"), ptau_final, zkey_plonk);
|
||||
});
|
||||
|
||||
it ("zkey export verificationkey", async () => {
|
||||
vKey = await snarkjs.zKey.exportVerificationKey(zkey_plonk);
|
||||
});
|
||||
|
||||
it ("plonk proof", async () => {
|
||||
const res = await snarkjs.plonk.prove(zkey_plonk, wtns);
|
||||
proof = res.proof;
|
||||
publicSignals = res.publicSignals;
|
||||
});
|
||||
|
||||
|
||||
it ("plonk verify", async () => {
|
||||
const res = await snarkjs.plonk.verify(vKey, publicSignals, proof);
|
||||
assert(res == true);
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
17
test/plonk_circuit/circuit.circom
Normal file
17
test/plonk_circuit/circuit.circom
Normal file
@ -0,0 +1,17 @@
|
||||
template TestPlonk() {
|
||||
signal input a;
|
||||
signal private input b;
|
||||
signal output c;
|
||||
|
||||
signal i1;
|
||||
signal i2;
|
||||
signal i4;
|
||||
|
||||
i1 <== a+b+3;
|
||||
|
||||
i2 <== i1*i1;
|
||||
i4 <== i2*i2;
|
||||
c <== i1*i4;
|
||||
}
|
||||
|
||||
component main = TestPlonk();
|
BIN
test/plonk_circuit/circuit.r1cs
Normal file
BIN
test/plonk_circuit/circuit.r1cs
Normal file
Binary file not shown.
6
test/plonk_circuit/circuit.sym
Normal file
6
test/plonk_circuit/circuit.sym
Normal file
@ -0,0 +1,6 @@
|
||||
1,2,0,main.a
|
||||
2,3,0,main.b
|
||||
3,1,0,main.c
|
||||
4,4,0,main.i1
|
||||
5,5,0,main.i2
|
||||
6,6,0,main.i4
|
BIN
test/plonk_circuit/circuit.wasm
Normal file
BIN
test/plonk_circuit/circuit.wasm
Normal file
Binary file not shown.
BIN
test/plonk_circuit/circuit.zkey
Normal file
BIN
test/plonk_circuit/circuit.zkey
Normal file
Binary file not shown.
1
test/plonk_circuit/input.json
Normal file
1
test/plonk_circuit/input.json
Normal file
@ -0,0 +1 @@
|
||||
{"a":1, "b":2}
|
BIN
test/plonk_circuit/powersOfTau15_final.ptau
Normal file
BIN
test/plonk_circuit/powersOfTau15_final.ptau
Normal file
Binary file not shown.
56
test/plonk_circuit/proof.json
Normal file
56
test/plonk_circuit/proof.json
Normal file
@ -0,0 +1,56 @@
|
||||
{
|
||||
"A": [
|
||||
"11939839401037308014501661426368356653724850605345253332929657172853812043781",
|
||||
"16803150087255544989431958662488492904420336924238680701501581437584428607157",
|
||||
"1"
|
||||
],
|
||||
"B": [
|
||||
"12217796857989229870486480566571024020165537615492120027996617913635583550919",
|
||||
"15953050028732489401139070996642159829273127420498389055201687358737110395633",
|
||||
"1"
|
||||
],
|
||||
"C": [
|
||||
"2906696582521990272421790638819759482269959041206664482786284127016128717160",
|
||||
"13202026981472500389768834017524824796942889042108968745956553624097139985303",
|
||||
"1"
|
||||
],
|
||||
"Z": [
|
||||
"12963117237509670288018978167117384995558675963765854814463910896579884709481",
|
||||
"4622289012016200197589549612287854254636168290945719641009001753279825228149",
|
||||
"1"
|
||||
],
|
||||
"T1": [
|
||||
"18104357506804140563327524454292715928794326274573109553633239600891197573562",
|
||||
"538095434184877169430117038240223945215803059446062355137183333593880141605",
|
||||
"1"
|
||||
],
|
||||
"T2": [
|
||||
"11026905931134233808041270707862602948406795505689051352903565023828166906250",
|
||||
"18119786770119651916429915278124137884233023858386753737488502838895847215949",
|
||||
"1"
|
||||
],
|
||||
"T3": [
|
||||
"17566889279472128646779664131922958011041076031971155851685601770551415716030",
|
||||
"9098203299195991935285362173962848018633069009185836024035896571651321000209",
|
||||
"1"
|
||||
],
|
||||
"eval_a": "18055865061248928277436374209575542340767389401367587042080949450055475826552",
|
||||
"eval_b": "21850645998014953033835315242107188012141028920551179313126430204177981301827",
|
||||
"eval_c": "5824117629917668551774989696896451058359923623432918656361263478103100196767",
|
||||
"eval_s1": "65743854351722680405937613500622654105481480423395233482389298676037124381",
|
||||
"eval_s2": "403993049457837292639608362612899661597754187086038035508895737334683813284",
|
||||
"eval_zw": "14169472644142979719809496569719127849776868311673021350864638375395829014729",
|
||||
"eval_r": "9395413794097544253619189223051084436435081924218993403215287776407899118006",
|
||||
"Wxi": [
|
||||
"3539391490802181190120434708628288229123728841695494613225112420761229267477",
|
||||
"19988904286663115119238205828592812126968004685055289879546007973679529590700",
|
||||
"1"
|
||||
],
|
||||
"Wxiw": [
|
||||
"19317464275069150558817973507256614963505445298046435829549010698677013964612",
|
||||
"16876609931905898917226763969880049506487107879332614688130170393689647229232",
|
||||
"1"
|
||||
],
|
||||
"protocol": "plonk",
|
||||
"curve": "bn128"
|
||||
}
|
4
test/plonk_circuit/public.json
Normal file
4
test/plonk_circuit/public.json
Normal file
@ -0,0 +1,4 @@
|
||||
[
|
||||
"7776",
|
||||
"1"
|
||||
]
|
62
test/plonk_circuit/verification_key.json
Normal file
62
test/plonk_circuit/verification_key.json
Normal file
@ -0,0 +1,62 @@
|
||||
{
|
||||
"protocol": "plonk",
|
||||
"curve": "bn128",
|
||||
"nPublic": 2,
|
||||
"power": 3,
|
||||
"k1": "2",
|
||||
"k2": "3",
|
||||
"Qm": [
|
||||
"4574976860925876233715815557145957880705707179788243092345689458042383890488",
|
||||
"4280641572679440220740870768701934042005081764212788702122100316880968332003",
|
||||
"1"
|
||||
],
|
||||
"Ql": [
|
||||
"965658296392348546197801330054212493203716810675203464920320569299615906620",
|
||||
"2656007013467620250344837426700774817845582578535592475523934494973414078961",
|
||||
"1"
|
||||
],
|
||||
"Qr": [
|
||||
"9466120146806803512081752933000124200435544680867502413168004293837549973279",
|
||||
"21718061423910769411439185483074527939398926867139106591112998426662463026765",
|
||||
"1"
|
||||
],
|
||||
"Qo": [
|
||||
"14232475876760437187555678371073865360567175818750566973123447255794615727867",
|
||||
"12884948380030714721172201264029036846611910042838904312559968631894569296588",
|
||||
"1"
|
||||
],
|
||||
"Qc": [
|
||||
"14611255151810715369553599153356422265550902840832241273629187752840438096443",
|
||||
"9099095607583972457036848580058361056377035074964862926640921566382822995435",
|
||||
"1"
|
||||
],
|
||||
"S1": [
|
||||
"14533465958261944855196820716374074689704505288368818447966063234824080424576",
|
||||
"12453353674569653145950160230568106433424266373528956571501497772329286407421",
|
||||
"1"
|
||||
],
|
||||
"S2": [
|
||||
"19581287390493194877650947725652399954855738146667446650367315521331119724530",
|
||||
"13292535777423157488265774466403939589622049710743071078999542362804505686482",
|
||||
"1"
|
||||
],
|
||||
"S3": [
|
||||
"7628615832235497959754170049702774596960536866278288444040861507702299255530",
|
||||
"6061093738111279431632848690609155827426019335581022466737969401920480256170",
|
||||
"1"
|
||||
],
|
||||
"X_2": [
|
||||
[
|
||||
"18029695676650738226693292988307914797657423701064905010927197838374790804409",
|
||||
"14583779054894525174450323658765874724019480979794335525732096752006891875705"
|
||||
],
|
||||
[
|
||||
"2140229616977736810657479771656733941598412651537078903776637920509952744750",
|
||||
"11474861747383700316476719153975578001603231366361248090558603872215261634898"
|
||||
],
|
||||
[
|
||||
"1",
|
||||
"0"
|
||||
]
|
||||
]
|
||||
}
|
675
test/plonk_circuit/verifier.sol
Normal file
675
test/plonk_circuit/verifier.sol
Normal file
@ -0,0 +1,675 @@
|
||||
// SPDX-License-Identifier: GPL-3.0
|
||||
/*
|
||||
Copyright 2021 0KIMS association.
|
||||
|
||||
This file is generated with [snarkJS](https://github.com/iden3/snarkjs).
|
||||
|
||||
snarkJS is a free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
pragma solidity >=0.7.0 <0.9.0;
|
||||
|
||||
contract PlonkVerifier {
|
||||
|
||||
uint16 constant n = 8;
|
||||
uint16 constant nPublic = 2;
|
||||
uint16 constant nLagrange = 2;
|
||||
|
||||
uint256 constant Qmx = 4574976860925876233715815557145957880705707179788243092345689458042383890488;
|
||||
uint256 constant Qmy = 4280641572679440220740870768701934042005081764212788702122100316880968332003;
|
||||
uint256 constant Qlx = 965658296392348546197801330054212493203716810675203464920320569299615906620;
|
||||
uint256 constant Qly = 2656007013467620250344837426700774817845582578535592475523934494973414078961;
|
||||
uint256 constant Qrx = 9466120146806803512081752933000124200435544680867502413168004293837549973279;
|
||||
uint256 constant Qry = 21718061423910769411439185483074527939398926867139106591112998426662463026765;
|
||||
uint256 constant Qox = 14232475876760437187555678371073865360567175818750566973123447255794615727867;
|
||||
uint256 constant Qoy = 12884948380030714721172201264029036846611910042838904312559968631894569296588;
|
||||
uint256 constant Qcx = 14611255151810715369553599153356422265550902840832241273629187752840438096443;
|
||||
uint256 constant Qcy = 9099095607583972457036848580058361056377035074964862926640921566382822995435;
|
||||
uint256 constant S1x = 14533465958261944855196820716374074689704505288368818447966063234824080424576;
|
||||
uint256 constant S1y = 12453353674569653145950160230568106433424266373528956571501497772329286407421;
|
||||
uint256 constant S2x = 19581287390493194877650947725652399954855738146667446650367315521331119724530;
|
||||
uint256 constant S2y = 13292535777423157488265774466403939589622049710743071078999542362804505686482;
|
||||
uint256 constant S3x = 7628615832235497959754170049702774596960536866278288444040861507702299255530;
|
||||
uint256 constant S3y = 6061093738111279431632848690609155827426019335581022466737969401920480256170;
|
||||
uint256 constant k1 = 2;
|
||||
uint256 constant k2 = 3;
|
||||
uint256 constant X2x1 = 18029695676650738226693292988307914797657423701064905010927197838374790804409;
|
||||
uint256 constant X2x2 = 14583779054894525174450323658765874724019480979794335525732096752006891875705;
|
||||
uint256 constant X2y1 = 2140229616977736810657479771656733941598412651537078903776637920509952744750;
|
||||
uint256 constant X2y2 = 11474861747383700316476719153975578001603231366361248090558603872215261634898;
|
||||
|
||||
uint256 constant q = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
|
||||
uint256 constant qf = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
|
||||
uint256 constant w1 = 19540430494807482326159819597004422086093766032135589407132600596362845576832;
|
||||
|
||||
uint256 constant G1x = 1;
|
||||
uint256 constant G1y = 2;
|
||||
uint256 constant G2x1 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;
|
||||
uint256 constant G2x2 = 11559732032986387107991004021392285783925812861821192530917403151452391805634;
|
||||
uint256 constant G2y1 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
|
||||
uint256 constant G2y2 = 4082367875863433681332203403145435568316851327593401208105741076214120093531;
|
||||
uint16 constant pA = 32;
|
||||
uint16 constant pB = 96;
|
||||
uint16 constant pC = 160;
|
||||
uint16 constant pZ = 224;
|
||||
uint16 constant pT1 = 288;
|
||||
uint16 constant pT2 = 352;
|
||||
uint16 constant pT3 = 416;
|
||||
uint16 constant pWxi = 480;
|
||||
uint16 constant pWxiw = 544;
|
||||
uint16 constant pEval_a = 608;
|
||||
uint16 constant pEval_b = 640;
|
||||
uint16 constant pEval_c = 672;
|
||||
uint16 constant pEval_s1 = 704;
|
||||
uint16 constant pEval_s2 = 736;
|
||||
uint16 constant pEval_zw = 768;
|
||||
uint16 constant pEval_r = 800;
|
||||
|
||||
uint16 constant pAlpha = 0;
|
||||
uint16 constant pBeta = 32;
|
||||
uint16 constant pGamma = 64;
|
||||
uint16 constant pXi = 96;
|
||||
uint16 constant pXin = 128;
|
||||
uint16 constant pBetaXi = 160;
|
||||
uint16 constant pV1 = 192;
|
||||
uint16 constant pV2 = 224;
|
||||
uint16 constant pV3 = 256;
|
||||
uint16 constant pV4 = 288;
|
||||
uint16 constant pV5 = 320;
|
||||
uint16 constant pV6 = 352;
|
||||
uint16 constant pU = 384;
|
||||
uint16 constant pPl = 416;
|
||||
uint16 constant pEval_t = 448;
|
||||
uint16 constant pA1 = 480;
|
||||
uint16 constant pB1 = 544;
|
||||
uint16 constant pZh = 608;
|
||||
uint16 constant pZhInv = 640;
|
||||
|
||||
uint16 constant pEval_l1 = 672;
|
||||
|
||||
uint16 constant pEval_l2 = 704;
|
||||
|
||||
|
||||
|
||||
uint16 constant lastMem = 736;
|
||||
|
||||
|
||||
function verifyProof(bytes memory proof, uint[] memory pubSignals) public view returns (bool) {
|
||||
assembly {
|
||||
/////////
|
||||
// Computes the inverse using the extended euclidean algorithm
|
||||
/////////
|
||||
function inverse(a, q) -> inv {
|
||||
let t := 0
|
||||
let newt := 1
|
||||
let r := q
|
||||
let newr := a
|
||||
let quotient
|
||||
let aux
|
||||
|
||||
for { } newr { } {
|
||||
quotient := sdiv(r, newr)
|
||||
aux := sub(t, mul(quotient, newt))
|
||||
t:= newt
|
||||
newt:= aux
|
||||
|
||||
aux := sub(r,mul(quotient, newr))
|
||||
r := newr
|
||||
newr := aux
|
||||
}
|
||||
|
||||
if gt(r, 1) { revert(0,0) }
|
||||
if slt(t, 0) { t:= add(t, q) }
|
||||
|
||||
inv := t
|
||||
}
|
||||
|
||||
///////
|
||||
// Computes the inverse of an array of values
|
||||
// See https://vitalik.ca/general/2018/07/21/starks_part_3.html in section where explain fields operations
|
||||
//////
|
||||
function inverseArray(pVals, n) {
|
||||
|
||||
let pAux := mload(0x40) // Point to the next free position
|
||||
let pIn := pVals
|
||||
let lastPIn := add(pVals, mul(n, 32)) // Read n elemnts
|
||||
let acc := mload(pIn) // Read the first element
|
||||
pIn := add(pIn, 32) // Point to the second element
|
||||
let inv
|
||||
|
||||
|
||||
for { } lt(pIn, lastPIn) {
|
||||
pAux := add(pAux, 32)
|
||||
pIn := add(pIn, 32)
|
||||
}
|
||||
{
|
||||
mstore(pAux, acc)
|
||||
acc := mulmod(acc, mload(pIn), q)
|
||||
}
|
||||
acc := inverse(acc, q)
|
||||
|
||||
// At this point pAux pint to the next free position we substract 1 to point to the last used
|
||||
pAux := sub(pAux, 32)
|
||||
// pIn points to the n+1 element, we substract to point to n
|
||||
pIn := sub(pIn, 32)
|
||||
lastPIn := pVals // We don't process the first element
|
||||
for { } gt(pIn, lastPIn) {
|
||||
pAux := sub(pAux, 32)
|
||||
pIn := sub(pIn, 32)
|
||||
}
|
||||
{
|
||||
inv := mulmod(acc, mload(pAux), q)
|
||||
acc := mulmod(acc, mload(pIn), q)
|
||||
mstore(pIn, inv)
|
||||
}
|
||||
// pIn points to first element, we just set it.
|
||||
mstore(pIn, acc)
|
||||
}
|
||||
|
||||
function checkField(v) {
|
||||
if iszero(lt(v, q)) {
|
||||
mstore(0, 0)
|
||||
return(0,0x20)
|
||||
}
|
||||
}
|
||||
|
||||
function checkInput(pProof) {
|
||||
if iszero(eq(mload(pProof), 800 )) {
|
||||
mstore(0, 0)
|
||||
return(0,0x20)
|
||||
}
|
||||
checkField(mload(add(pProof, pEval_a)))
|
||||
checkField(mload(add(pProof, pEval_b)))
|
||||
checkField(mload(add(pProof, pEval_c)))
|
||||
checkField(mload(add(pProof, pEval_s1)))
|
||||
checkField(mload(add(pProof, pEval_s2)))
|
||||
checkField(mload(add(pProof, pEval_zw)))
|
||||
checkField(mload(add(pProof, pEval_r)))
|
||||
|
||||
// Points are checked in the point operations precompiled smart contracts
|
||||
}
|
||||
|
||||
function calculateChallanges(pProof, pMem) {
|
||||
|
||||
let a
|
||||
let b
|
||||
|
||||
b := mod(keccak256(add(pProof, pA), 192), q)
|
||||
mstore( add(pMem, pBeta), b)
|
||||
mstore( add(pMem, pGamma), mod(keccak256(add(pMem, pBeta), 32), q))
|
||||
mstore( add(pMem, pAlpha), mod(keccak256(add(pProof, pZ), 64), q))
|
||||
|
||||
a := mod(keccak256(add(pProof, pT1), 192), q)
|
||||
mstore( add(pMem, pXi), a)
|
||||
mstore( add(pMem, pBetaXi), mulmod(b, a, q))
|
||||
|
||||
a:= mulmod(a, a, q)
|
||||
|
||||
a:= mulmod(a, a, q)
|
||||
|
||||
a:= mulmod(a, a, q)
|
||||
|
||||
mstore( add(pMem, pXin), a)
|
||||
a:= mod(add(sub(a, 1),q), q)
|
||||
mstore( add(pMem, pZh), a)
|
||||
mstore( add(pMem, pZhInv), a) // We will invert later together with lagrange pols
|
||||
|
||||
let v1 := mod(keccak256(add(pProof, pEval_a), 224), q)
|
||||
mstore( add(pMem, pV1), v1)
|
||||
a := mulmod(v1, v1, q)
|
||||
mstore( add(pMem, pV2), a)
|
||||
a := mulmod(a, v1, q)
|
||||
mstore( add(pMem, pV3), a)
|
||||
a := mulmod(a, v1, q)
|
||||
mstore( add(pMem, pV4), a)
|
||||
a := mulmod(a, v1, q)
|
||||
mstore( add(pMem, pV5), a)
|
||||
a := mulmod(a, v1, q)
|
||||
mstore( add(pMem, pV6), a)
|
||||
|
||||
mstore( add(pMem, pU), mod(keccak256(add(pProof, pWxi), 128), q))
|
||||
}
|
||||
|
||||
function calculateLagrange(pMem) {
|
||||
|
||||
let w := 1
|
||||
|
||||
mstore(
|
||||
add(pMem, pEval_l1),
|
||||
mulmod(
|
||||
n,
|
||||
mod(
|
||||
add(
|
||||
sub(
|
||||
mload(add(pMem, pXi)),
|
||||
w
|
||||
),
|
||||
q
|
||||
),
|
||||
q
|
||||
),
|
||||
q
|
||||
)
|
||||
)
|
||||
|
||||
w := mulmod(w, w1, q)
|
||||
|
||||
|
||||
mstore(
|
||||
add(pMem, pEval_l2),
|
||||
mulmod(
|
||||
n,
|
||||
mod(
|
||||
add(
|
||||
sub(
|
||||
mload(add(pMem, pXi)),
|
||||
w
|
||||
),
|
||||
q
|
||||
),
|
||||
q
|
||||
),
|
||||
q
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
inverseArray(add(pMem, pZhInv), 3 )
|
||||
|
||||
let zh := mload(add(pMem, pZh))
|
||||
w := 1
|
||||
|
||||
|
||||
mstore(
|
||||
add(pMem, pEval_l1 ),
|
||||
mulmod(
|
||||
mload(add(pMem, pEval_l1 )),
|
||||
zh,
|
||||
q
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
w := mulmod(w, w1, q)
|
||||
|
||||
|
||||
|
||||
mstore(
|
||||
add(pMem, pEval_l2),
|
||||
mulmod(
|
||||
w,
|
||||
mulmod(
|
||||
mload(add(pMem, pEval_l2)),
|
||||
zh,
|
||||
q
|
||||
),
|
||||
q
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
function calculatePl(pMem, pPub) {
|
||||
let pl := 0
|
||||
|
||||
|
||||
pl := mod(
|
||||
add(
|
||||
sub(
|
||||
pl,
|
||||
mulmod(
|
||||
mload(add(pMem, pEval_l1)),
|
||||
mload(add(pPub, 32)),
|
||||
q
|
||||
)
|
||||
),
|
||||
q
|
||||
),
|
||||
q
|
||||
)
|
||||
|
||||
pl := mod(
|
||||
add(
|
||||
sub(
|
||||
pl,
|
||||
mulmod(
|
||||
mload(add(pMem, pEval_l2)),
|
||||
mload(add(pPub, 64)),
|
||||
q
|
||||
)
|
||||
),
|
||||
q
|
||||
),
|
||||
q
|
||||
)
|
||||
|
||||
|
||||
mstore(add(pMem, pPl), pl)
|
||||
|
||||
|
||||
}
|
||||
|
||||
function calculateT(pProof, pMem) {
|
||||
let t
|
||||
let t1
|
||||
let t2
|
||||
t := addmod(
|
||||
mload(add(pProof, pEval_r)),
|
||||
mload(add(pMem, pPl)),
|
||||
q
|
||||
)
|
||||
|
||||
t1 := mulmod(
|
||||
mload(add(pProof, pEval_s1)),
|
||||
mload(add(pMem, pBeta)),
|
||||
q
|
||||
)
|
||||
|
||||
t1 := addmod(
|
||||
t1,
|
||||
mload(add(pProof, pEval_a)),
|
||||
q
|
||||
)
|
||||
|
||||
t1 := addmod(
|
||||
t1,
|
||||
mload(add(pMem, pGamma)),
|
||||
q
|
||||
)
|
||||
|
||||
t2 := mulmod(
|
||||
mload(add(pProof, pEval_s2)),
|
||||
mload(add(pMem, pBeta)),
|
||||
q
|
||||
)
|
||||
|
||||
t2 := addmod(
|
||||
t2,
|
||||
mload(add(pProof, pEval_b)),
|
||||
q
|
||||
)
|
||||
|
||||
t2 := addmod(
|
||||
t2,
|
||||
mload(add(pMem, pGamma)),
|
||||
q
|
||||
)
|
||||
|
||||
t1 := mulmod(t1, t2, q)
|
||||
|
||||
t2 := addmod(
|
||||
mload(add(pProof, pEval_c)),
|
||||
mload(add(pMem, pGamma)),
|
||||
q
|
||||
)
|
||||
|
||||
t1 := mulmod(t1, t2, q)
|
||||
t1 := mulmod(t1, mload(add(pProof, pEval_zw)), q)
|
||||
t1 := mulmod(t1, mload(add(pMem, pAlpha)), q)
|
||||
|
||||
t2 := mulmod(
|
||||
mload(add(pMem, pEval_l1)),
|
||||
mload(add(pMem, pAlpha)),
|
||||
q
|
||||
)
|
||||
|
||||
t2 := mulmod(
|
||||
t2,
|
||||
mload(add(pMem, pAlpha)),
|
||||
q
|
||||
)
|
||||
|
||||
t1 := addmod(t1, t2, q)
|
||||
|
||||
t := mod(sub(add(t, q), t1), q)
|
||||
t := mulmod(t, mload(add(pMem, pZhInv)), q)
|
||||
|
||||
mstore( add(pMem, pEval_t) , t)
|
||||
|
||||
}
|
||||
|
||||
function g1_set(pR, pP) {
|
||||
mstore(pR, mload(pP))
|
||||
mstore(add(pR, 32), mload(add(pP,32)))
|
||||
}
|
||||
|
||||
function g1_acc(pR, pP) {
|
||||
let mIn := mload(0x40)
|
||||
mstore(mIn, mload(pR))
|
||||
mstore(add(mIn,32), mload(add(pR, 32)))
|
||||
mstore(add(mIn,64), mload(pP))
|
||||
mstore(add(mIn,96), mload(add(pP, 32)))
|
||||
|
||||
let success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64)
|
||||
|
||||
if iszero(success) {
|
||||
mstore(0, 0)
|
||||
return(0,0x20)
|
||||
}
|
||||
}
|
||||
|
||||
function g1_mulAcc(pR, pP, s) {
|
||||
let success
|
||||
let mIn := mload(0x40)
|
||||
mstore(mIn, mload(pP))
|
||||
mstore(add(mIn,32), mload(add(pP, 32)))
|
||||
mstore(add(mIn,64), s)
|
||||
|
||||
success := staticcall(sub(gas(), 2000), 7, mIn, 96, mIn, 64)
|
||||
|
||||
if iszero(success) {
|
||||
mstore(0, 0)
|
||||
return(0,0x20)
|
||||
}
|
||||
|
||||
mstore(add(mIn,64), mload(pR))
|
||||
mstore(add(mIn,96), mload(add(pR, 32)))
|
||||
|
||||
success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64)
|
||||
|
||||
if iszero(success) {
|
||||
mstore(0, 0)
|
||||
return(0,0x20)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function g1_mulAccC(pR, x, y, s) {
|
||||
let success
|
||||
let mIn := mload(0x40)
|
||||
mstore(mIn, x)
|
||||
mstore(add(mIn,32), y)
|
||||
mstore(add(mIn,64), s)
|
||||
|
||||
success := staticcall(sub(gas(), 2000), 7, mIn, 96, mIn, 64)
|
||||
|
||||
if iszero(success) {
|
||||
mstore(0, 0)
|
||||
return(0,0x20)
|
||||
}
|
||||
|
||||
mstore(add(mIn,64), mload(pR))
|
||||
mstore(add(mIn,96), mload(add(pR, 32)))
|
||||
|
||||
success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64)
|
||||
|
||||
if iszero(success) {
|
||||
mstore(0, 0)
|
||||
return(0,0x20)
|
||||
}
|
||||
}
|
||||
|
||||
function g1_mulSetC(pR, x, y, s) {
|
||||
let success
|
||||
let mIn := mload(0x40)
|
||||
mstore(mIn, x)
|
||||
mstore(add(mIn,32), y)
|
||||
mstore(add(mIn,64), s)
|
||||
|
||||
success := staticcall(sub(gas(), 2000), 7, mIn, 96, pR, 64)
|
||||
|
||||
if iszero(success) {
|
||||
mstore(0, 0)
|
||||
return(0,0x20)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function calculateA1(pProof, pMem) {
|
||||
let p := add(pMem, pA1)
|
||||
g1_set(p, add(pProof, pWxi))
|
||||
g1_mulAcc(p, add(pProof, pWxiw), mload(add(pMem, pU)))
|
||||
}
|
||||
|
||||
|
||||
function calculateB1(pProof, pMem) {
|
||||
let s
|
||||
let s1
|
||||
let p := add(pMem, pB1)
|
||||
|
||||
// Calculate D
|
||||
s := mulmod( mload(add(pProof, pEval_a)), mload(add(pMem, pV1)), q)
|
||||
g1_mulSetC(p, Qlx, Qly, s)
|
||||
|
||||
s := mulmod( s, mload(add(pProof, pEval_b)), q)
|
||||
g1_mulAccC(p, Qmx, Qmy, s)
|
||||
|
||||
s := mulmod( mload(add(pProof, pEval_b)), mload(add(pMem, pV1)), q)
|
||||
g1_mulAccC(p, Qrx, Qry, s)
|
||||
|
||||
s := mulmod( mload(add(pProof, pEval_c)), mload(add(pMem, pV1)), q)
|
||||
g1_mulAccC(p, Qox, Qoy, s)
|
||||
|
||||
s :=mload(add(pMem, pV1))
|
||||
g1_mulAccC(p, Qcx, Qcy, s)
|
||||
|
||||
s := addmod(mload(add(pProof, pEval_a)), mload(add(pMem, pBetaXi)), q)
|
||||
s := addmod(s, mload(add(pMem, pGamma)), q)
|
||||
s1 := mulmod(k1, mload(add(pMem, pBetaXi)), q)
|
||||
s1 := addmod(s1, mload(add(pProof, pEval_b)), q)
|
||||
s1 := addmod(s1, mload(add(pMem, pGamma)), q)
|
||||
s := mulmod(s, s1, q)
|
||||
s1 := mulmod(k2, mload(add(pMem, pBetaXi)), q)
|
||||
s1 := addmod(s1, mload(add(pProof, pEval_c)), q)
|
||||
s1 := addmod(s1, mload(add(pMem, pGamma)), q)
|
||||
s := mulmod(s, s1, q)
|
||||
s := mulmod(s, mload(add(pMem, pAlpha)), q)
|
||||
s := mulmod(s, mload(add(pMem, pV1)), q)
|
||||
s1 := mulmod(mload(add(pMem, pEval_l1)), mload(add(pMem, pAlpha)), q)
|
||||
s1 := mulmod(s1, mload(add(pMem, pAlpha)), q)
|
||||
s1 := mulmod(s1, mload(add(pMem, pV1)), q)
|
||||
s := addmod(s, s1, q)
|
||||
s := addmod(s, mload(add(pMem, pU)), q)
|
||||
g1_mulAcc(p, add(pProof, pZ), s)
|
||||
|
||||
s := mulmod(mload(add(pMem, pBeta)), mload(add(pProof, pEval_s1)), q)
|
||||
s := addmod(s, mload(add(pProof, pEval_a)), q)
|
||||
s := addmod(s, mload(add(pMem, pGamma)), q)
|
||||
s1 := mulmod(mload(add(pMem, pBeta)), mload(add(pProof, pEval_s2)), q)
|
||||
s1 := addmod(s1, mload(add(pProof, pEval_b)), q)
|
||||
s1 := addmod(s1, mload(add(pMem, pGamma)), q)
|
||||
s := mulmod(s, s1, q)
|
||||
s := mulmod(s, mload(add(pMem, pAlpha)), q)
|
||||
s := mulmod(s, mload(add(pMem, pV1)), q)
|
||||
s := mulmod(s, mload(add(pMem, pBeta)), q)
|
||||
s := mulmod(s, mload(add(pProof, pEval_zw)), q)
|
||||
s := mod(sub(q, s), q)
|
||||
g1_mulAccC(p, S3x, S3y, s)
|
||||
|
||||
|
||||
// calculate F
|
||||
g1_acc(p , add(pProof, pT1))
|
||||
|
||||
s := mload(add(pMem, pXin))
|
||||
g1_mulAcc(p, add(pProof, pT2), s)
|
||||
|
||||
s := mulmod(s, s, q)
|
||||
g1_mulAcc(p, add(pProof, pT3), s)
|
||||
|
||||
g1_mulAcc(p, add(pProof, pA), mload(add(pMem, pV2)))
|
||||
g1_mulAcc(p, add(pProof, pB), mload(add(pMem, pV3)))
|
||||
g1_mulAcc(p, add(pProof, pC), mload(add(pMem, pV4)))
|
||||
g1_mulAccC(p, S1x, S1y, mload(add(pMem, pV5)))
|
||||
g1_mulAccC(p, S2x, S2y, mload(add(pMem, pV6)))
|
||||
|
||||
// calculate E
|
||||
s := mload(add(pMem, pEval_t))
|
||||
s := addmod(s, mulmod(mload(add(pProof, pEval_r)), mload(add(pMem, pV1)), q), q)
|
||||
s := addmod(s, mulmod(mload(add(pProof, pEval_a)), mload(add(pMem, pV2)), q), q)
|
||||
s := addmod(s, mulmod(mload(add(pProof, pEval_b)), mload(add(pMem, pV3)), q), q)
|
||||
s := addmod(s, mulmod(mload(add(pProof, pEval_c)), mload(add(pMem, pV4)), q), q)
|
||||
s := addmod(s, mulmod(mload(add(pProof, pEval_s1)), mload(add(pMem, pV5)), q), q)
|
||||
s := addmod(s, mulmod(mload(add(pProof, pEval_s2)), mload(add(pMem, pV6)), q), q)
|
||||
s := addmod(s, mulmod(mload(add(pProof, pEval_zw)), mload(add(pMem, pU)), q), q)
|
||||
s := mod(sub(q, s), q)
|
||||
g1_mulAccC(p, G1x, G1y, s)
|
||||
|
||||
|
||||
// Last part of B
|
||||
s := mload(add(pMem, pXi))
|
||||
g1_mulAcc(p, add(pProof, pWxi), s)
|
||||
|
||||
s := mulmod(mload(add(pMem, pU)), mload(add(pMem, pXi)), q)
|
||||
s := mulmod(s, w1, q)
|
||||
g1_mulAcc(p, add(pProof, pWxiw), s)
|
||||
|
||||
}
|
||||
|
||||
function checkPairing(pMem) -> isOk {
|
||||
let mIn := mload(0x40)
|
||||
mstore(mIn, mload(add(pMem, pA1)))
|
||||
mstore(add(mIn,32), mload(add(add(pMem, pA1), 32)))
|
||||
mstore(add(mIn,64), X2x2)
|
||||
mstore(add(mIn,96), X2x1)
|
||||
mstore(add(mIn,128), X2y2)
|
||||
mstore(add(mIn,160), X2y1)
|
||||
mstore(add(mIn,192), mload(add(pMem, pB1)))
|
||||
let s := mload(add(add(pMem, pB1), 32))
|
||||
s := mod(sub(qf, s), qf)
|
||||
mstore(add(mIn,224), s)
|
||||
mstore(add(mIn,256), G2x2)
|
||||
mstore(add(mIn,288), G2x1)
|
||||
mstore(add(mIn,320), G2y2)
|
||||
mstore(add(mIn,352), G2y1)
|
||||
|
||||
let success := staticcall(sub(gas(), 2000), 8, mIn, 384, mIn, 0x20)
|
||||
|
||||
isOk := and(success, mload(mIn))
|
||||
}
|
||||
|
||||
let pMem := mload(0x40)
|
||||
mstore(0x40, add(pMem, lastMem))
|
||||
|
||||
checkInput(proof)
|
||||
calculateChallanges(proof, pMem)
|
||||
calculateLagrange(pMem)
|
||||
calculatePl(pMem, pubSignals)
|
||||
calculateT(proof, pMem)
|
||||
calculateA1(proof, pMem)
|
||||
calculateB1(proof, pMem)
|
||||
let isValid := checkPairing(pMem)
|
||||
|
||||
mstore(0x40, sub(pMem, lastMem))
|
||||
mstore(0, isValid)
|
||||
return(0,0x20)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
BIN
test/plonk_circuit/witness.wtns
Normal file
BIN
test/plonk_circuit/witness.wtns
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user