Compare commits

...

62 Commits

Author SHA1 Message Date
Jordi Baylina
0d5077106a 0.5.34 2020-12-07 12:20:56 +01:00
Jordi Baylina
b68c9fa5d2 NPublic in code 2020-12-07 12:20:50 +01:00
Jordi Baylina
94cb37bd9e 0.5.33 2020-11-26 07:23:06 +01:00
Jordi Baylina
9f15dd2e29 Allows pass signal arrays to a function 2020-11-26 07:22:59 +01:00
Jordi Baylina
334697dd0c 0.5.32 2020-11-21 23:02:06 +01:00
Jordi Baylina
6c48e9ba01 FIX discard unused signals 2020-11-21 23:01:57 +01:00
Jordi Baylina
42162b10c1 0.5.31 2020-11-21 20:40:27 +01:00
Jordi Baylina
a84873161f FIX discard unused signals 2020-11-21 20:40:11 +01:00
Jordi Baylina
9bf1354bf1 0.5.30 2020-10-14 09:50:22 +02:00
Jordi Baylina
ed4c4b4de0 Merge branch 'master' of github.com:iden3/circom 2020-10-14 09:49:51 +02:00
Jordi Baylina
a1f3f714ea 0.5.29 2020-10-14 09:49:29 +02:00
Jordi Baylina
dafc9db614 fix fasfile pageSize 2020-10-14 09:49:13 +02:00
Marta Bellés
6e4a192c6a Update README.md 2020-10-05 10:12:00 +02:00
Jordi Baylina
e1286c29c7 0.5.28 2020-09-24 19:18:59 +02:00
Jordi Baylina
a002bcbc25 bls12-381 fix and fast r1cs generation 2020-09-24 19:18:49 +02:00
Jordi Baylina
f9f1d0c13e High Removed array 2020-09-19 18:36:35 +02:00
Jordi Baylina
fc01aad8b6 Reduce mem 2020-09-17 22:53:06 +02:00
Jordi Baylina
3d5aa14cdc 0.5.27 2020-09-17 17:45:44 +02:00
Jordi Baylina
5dc54bb7d2 Optimize recursive constant dependency 2020-09-17 17:42:32 +02:00
Jordi Baylina
349a39dc95 0.5.26 2020-09-17 10:38:01 +02:00
Jordi Baylina
0a2aee9932 0.5.25 2020-09-17 10:34:57 +02:00
Jordi Baylina
bad8fad3d0 Optimize optimize constraints not BigArray for small circuits 2020-09-17 10:34:49 +02:00
Jordi Baylina
0a707648fc 0.5.24 2020-09-17 01:09:31 +02:00
Jordi Baylina
263dc73906 FIX Bad optimization 2020-09-17 01:09:24 +02:00
Jordi Baylina
8e730d93a4 64 size r1cs 2020-09-04 09:10:49 +02:00
Jordi Baylina
bbe10438e0 0.5.23 2020-08-31 11:28:23 +02:00
Jordi Baylina
c2cef8d80c deps 2020-08-31 11:28:11 +02:00
Jordi Baylina
2200408986 0.5.22 2020-08-31 11:18:06 +02:00
Jordi Baylina
5f13d37fdc Better info in signal not assigned 2020-08-31 11:13:26 +02:00
Jordi Baylina
3b46b74d4a 0.5.21 2020-08-24 09:31:42 +02:00
Jordi Baylina
aa2d768465 assert working 2020-08-24 09:31:35 +02:00
Jordi Baylina
f02ceb2508 Big component entry tables 2020-08-17 12:02:24 +02:00
Jordi Baylina
d014d67032 0.5.20 2020-08-17 11:22:40 +02:00
Jordi Baylina
2e1b35a94d Fix Offset referenced by an iteger 2020-08-17 11:22:21 +02:00
Jordi Baylina
7cef1be2c3 0.5.19 2020-08-13 18:56:39 +02:00
Jordi Baylina
4b631994ca c to cpp 2020-08-13 18:56:30 +02:00
Jordi Baylina
7239abcef1 0.5.18 2020-08-12 02:26:33 +02:00
Jordi Baylina
633f755e34 Fix testers with fastfile 2020-08-12 02:26:15 +02:00
Jordi Baylina
923b19c414 Fix: Error description function not found 2020-08-12 01:36:01 +02:00
Jordi Baylina
90cc7d5072 Remove streams c and wasm gen 2020-08-07 17:10:30 +02:00
Jordi Baylina
145d5a21ad BigArray in wit2sig 2020-08-06 22:59:19 +02:00
Jordi Baylina
cbb0b229bc Big array in r1cs labels 2020-08-05 14:32:05 +02:00
Jordi Baylina
1d14e8c603 BigArray require 2020-07-30 05:06:58 +02:00
Jordi Baylina
1e2fb12631 BigArray in code 2020-07-30 05:04:15 +02:00
Jordi Baylina
0e1a1bcc23 BigArray in CBuild 2020-07-29 19:40:24 +02:00
Jordi Baylina
989987bfc2 deps 2020-07-29 09:16:43 +02:00
Jordi Baylina
5f3ef322a7 Simplify buildC 2020-07-28 12:50:23 +02:00
Jordi Baylina
3c8e61b9a4 log buildC 2020-07-27 05:00:47 +02:00
Jordi Baylina
c39423e411 0.5.17 2020-07-25 14:01:31 +02:00
Jordi Baylina
06b6c1a49e Fast write constraints 2020-07-25 13:55:17 +02:00
Jordi Baylina
6b712f3587 0.5.16 2020-07-23 15:56:47 +02:00
Jordi Baylina
26cad30222 faster write r1cs 2020-07-23 15:55:27 +02:00
Jordi Baylina
f48de61ca9 lIdx BigArray 2020-07-21 14:34:53 +02:00
Jordi Baylina
89cea4755c 0.5.15 2020-07-21 08:47:27 +02:00
Jordi Baylina
9bf6ecc4f3 Reducing constraints big array 2020-07-21 08:47:10 +02:00
Jordi Baylina
59d591c988 0.5.14 2020-07-18 14:55:09 +02:00
Jordi Baylina
9fe8be9828 optimize optimize constraints 2020-07-18 14:55:00 +02:00
Jordi Baylina
7e24d6f57d 0.5.13 2020-07-04 19:55:45 +02:00
Jordi Baylina
8655573b34 r1cs builder fix 2020-07-04 19:54:47 +02:00
Jordi Baylina
8fc6e3f1c6 0.5.12 2020-07-02 06:00:10 +02:00
Jordi Baylina
c32d303d27 deps 2020-07-02 05:59:00 +02:00
Jordi Baylina
744d3b241c deps and verbos 2020-07-02 05:33:31 +02:00
23 changed files with 1248 additions and 864 deletions

View File

@@ -1,12 +1,15 @@
# Circom
Circom is a language designed to write arithmetic circuits that can be used in zero knowledge proofs.
Circom is a language designed to write arithmetic circuits that can be used in zero-knowledge proofs.
In particular, it is designed to work in [zksnarks JavaScript library](https://github.com/iden3/zksnark).
## Usage
### Circom Docs
You can read the details of circom in [the documentation webpage](https://docs.circom.io/).
### Tutorial
A good starting point [is this tutorial](https://github.com/iden3/circom/blob/master/TUTORIAL.md)

View File

@@ -8,7 +8,7 @@ This tutorial will guide you in creating your first zero-knowledge SNARK circuit
If you don't have it installed yet, you need to install `Node.js`.
The last stable version of `Node.js` (or 8.12.0) works just fine, but if you install the latest current version `Node.js` (10.12.0) you will see a significant increase in performance. This is because last versions of node includes Big Integer Libraries nativelly. The `snarkjs` library makes use of this feature if available, and this improves the performance x10 (!).
You should install at least version 10 of node. It's important to note here that the latests versions of javascript, includes big integer support and web assembly compilers that make the code run fast.
### 1.2 Install **circom** and **snarkjs**

137
cli.js
View File

@@ -24,6 +24,8 @@
const fs = require("fs");
const path = require("path");
const Scalar = require("ffjavascript").Scalar;
const stringifyBigInts = require("ffjavascript").utils.stringifyBigInts;
const fastFile = require("fastfile");
const compiler = require("./src/compiler");
@@ -60,78 +62,68 @@ const argv = require("yargs")
.argv;
let inputFile;
if (argv._.length == 0) {
inputFile = "circuit.circom";
} else if (argv._.length == 1) {
inputFile = argv._[0];
} else {
console.log("Only one circuit at a time is permited");
process.exit(1);
}
async function run() {
let inputFile;
if (argv._.length == 0) {
inputFile = "circuit.circom";
} else if (argv._.length == 1) {
inputFile = argv._[0];
} else {
console.log("Only one circuit at a time is permited");
process.exit(1);
}
const fullFileName = path.resolve(process.cwd(), inputFile);
const fileName = path.basename(fullFileName, ".circom");
const cSourceName = typeof(argv.csource) === "string" ? argv.csource : fileName + ".cpp";
const wasmName = typeof(argv.wasm) === "string" ? argv.wasm : fileName + ".wasm";
const watName = typeof(argv.wat) === "string" ? argv.wat : fileName + ".wat";
const r1csName = typeof(argv.r1cs) === "string" ? argv.r1cs : fileName + ".r1cs";
const symName = typeof(argv.sym) === "string" ? argv.sym : fileName + ".sym";
const fullFileName = path.resolve(process.cwd(), inputFile);
const fileName = path.basename(fullFileName, ".circom");
const cSourceName = typeof(argv.csource) === "string" ? argv.csource : fileName + ".cpp";
const wasmName = typeof(argv.wasm) === "string" ? argv.wasm : fileName + ".wasm";
const watName = typeof(argv.wat) === "string" ? argv.wat : fileName + ".wat";
const r1csName = typeof(argv.r1cs) === "string" ? argv.r1cs : fileName + ".r1cs";
const symName = typeof(argv.sym) === "string" ? argv.sym : fileName + ".sym";
const options = {};
options.reduceConstraints = !argv.fast;
options.verbose = argv.verbose || false;
options.sanityCheck = argv.sanitycheck;
options.prime = argv.prime ? Scalar.fromString(argv.prime) : Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617");
const options = {};
options.reduceConstraints = !argv.fast;
options.verbose = argv.verbose || false;
options.sanityCheck = argv.sanitycheck;
if (argv.csource) {
options.cSourceWriteStream = fs.createWriteStream(cSourceName);
}
if (argv.wasm) {
options.wasmWriteStream = fs.createWriteStream(wasmName);
}
if (argv.wat) {
options.watWriteStream = fs.createWriteStream(watName);
}
if (argv.r1cs) {
options.r1csFileName = r1csName;
}
if (argv.sym) {
options.symWriteStream = fs.createWriteStream(symName);
}
if (argv.newThreadTemplates) {
options.newThreadTemplates = new RegExp(argv.newThreadTemplates);
}
if (argv.csource) {
options.cSourceFile = await fastFile.createOverride(cSourceName);
const noExt = cSourceName.substr(0, cSourceName.lastIndexOf(".")) || cSourceName;
options.dataFile = await fastFile.createOverride(noExt+".dat");
}
if (argv.wasm) {
options.wasmFile = await fastFile.createOverride(wasmName);
}
if (argv.wat) {
options.watFile = await fastFile.createOverride(watName);
}
if (argv.r1cs) {
options.r1csFileName = r1csName;
}
if (argv.sym) {
options.symWriteStream = fs.createWriteStream(symName);
}
if (argv.newThreadTemplates) {
options.newThreadTemplates = new RegExp(argv.newThreadTemplates);
}
if (!argv.prime) {
options.prime = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617");
} else if (["BLS12-381", "BLS12381"]. indexOf(argv.prime.toUpperCase()) >=0) {
options.prime = Scalar.fromString("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001",16);
} else if (["BN-128", "BN128", "BN254", "BN-254"]. indexOf(argv.prime.toUpperCase()) >=0) {
options.prime = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617");
} else {
options.prime = Scalar.fromString(argv.prime);
}
compiler(fullFileName, options).then( () => {
let cSourceDone = false;
let wasmDone = false;
await compiler(fullFileName, options);
if (options.cSourceFile) await options.cSourceFile.close();
if (options.dataFile) await options.dataFile.close();
if (options.wasmFile) await options.wasmFile.close();
if (options.watFile) await options.watFile.close();
let symDone = false;
let watDone = false;
if (options.cSourceWriteStream) {
options.cSourceWriteStream.on("finish", () => {
cSourceDone = true;
finishIfDone();
});
} else {
cSourceDone = true;
}
if (options.wasmWriteStream) {
options.wasmWriteStream.on("finish", () => {
wasmDone = true;
finishIfDone();
});
} else {
wasmDone = true;
}
if (options.watWriteStream) {
options.watWriteStream.on("finish", () => {
watDone = true;
finishIfDone();
});
} else {
watDone = true;
}
if (options.symWriteStream) {
options.symWriteStream.on("finish", () => {
symDone = true;
@@ -141,12 +133,17 @@ compiler(fullFileName, options).then( () => {
symDone = true;
}
function finishIfDone() {
if ((cSourceDone)&&(symDone)&&(wasmDone)&&(watDone)) {
if (symDone) {
setTimeout(() => {
process.exit(0);
}, 300);
}
}
}
run().then(()=> {
process.exit(0);
}, (err) => {
// console.log(err);
console.log(err.stack);
@@ -157,11 +154,9 @@ compiler(fullFileName, options).then( () => {
if (argv.verbose) console.log(err.stack);
}
if (err.ast) {
console.error(JSON.stringify(err.ast, null, 1));
console.error(JSON.stringify(stringifyBigInts(err.ast), null, 1));
}
process.exit(1);
});

450
package-lock.json generated
View File

@@ -1,35 +1,40 @@
{
"name": "circom",
"version": "0.5.11",
"version": "0.5.34",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@babel/code-frame": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz",
"integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==",
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
"integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
"dev": true,
"requires": {
"@babel/highlight": "^7.8.3"
"@babel/highlight": "^7.10.4"
}
},
"@babel/helper-validator-identifier": {
"version": "7.9.0",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.0.tgz",
"integrity": "sha512-6G8bQKjOh+of4PV/ThDm/rRqlU7+IGoJuofpagU5GlEl29Vv0RGqqt86ZGRV8ZuSOY3o+8yXl5y782SMcG7SHw==",
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
"integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==",
"dev": true
},
"@babel/highlight": {
"version": "7.9.0",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz",
"integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==",
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
"integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
"dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.9.0",
"@babel/helper-validator-identifier": "^7.10.4",
"chalk": "^2.0.0",
"js-tokens": "^4.0.0"
}
},
"@iden3/bigarray": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/@iden3/bigarray/-/bigarray-0.0.2.tgz",
"integrity": "sha512-Xzdyxqm1bOFF6pdIsiHLLl3HkSLjbhqJHVyqaTxXt3RqXBEnmsUmEW47H7VOi/ak7TdkRpNkxjyK5Zbkm+y52g=="
},
"@types/color-name": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
@@ -48,9 +53,9 @@
"dev": true
},
"acorn": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz",
"integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==",
"version": "7.4.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz",
"integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==",
"dev": true
},
"acorn-jsx": {
@@ -60,9 +65,9 @@
"dev": true
},
"ajv": {
"version": "6.12.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz",
"integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==",
"version": "6.12.3",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz",
"integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==",
"dev": true,
"requires": {
"fast-deep-equal": "^3.1.1",
@@ -101,12 +106,11 @@
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg=="
},
"ansi-styles": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
"integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
"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": {
"@types/color-name": "^1.1.1",
"color-convert": "^2.0.1"
"color-convert": "^1.9.0"
}
},
"argparse": {
@@ -129,6 +133,11 @@
"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",
@@ -139,6 +148,11 @@
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz",
"integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w=="
},
"blakejs": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz",
"integrity": "sha1-ad+S75U6qIylGjLfarHFShVfx6U="
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -176,37 +190,10 @@
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
},
"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==",
"dev": true,
"requires": {
"color-convert": "^1.9.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==",
"dev": true,
"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=",
"dev": true
}
}
},
"chardet": {
@@ -221,20 +208,22 @@
"integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII="
},
"circom_runtime": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/circom_runtime/-/circom_runtime-0.0.6.tgz",
"integrity": "sha512-o0T5MuWzxnxinWG3+CygS/kZouoP+z5ZrufUwqKJy3gsVFJhkbqMpfKmcBGjhExB3uatA7cKyOiRAOLOz5+t5w==",
"version": "0.1.9",
"resolved": "https://registry.npmjs.org/circom_runtime/-/circom_runtime-0.1.9.tgz",
"integrity": "sha512-eh34quaGpeEWXthnhmC9zpoBL/5zJ0mGDbPT/plb/xVmFaKxJDcLuCr2sma5s3il8AYlEIb/nbqytojyI3TWDQ==",
"requires": {
"ffjavascript": "0.1.0",
"ffjavascript": "0.2.10",
"fnv-plus": "^1.3.1"
},
"dependencies": {
"ffjavascript": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.1.0.tgz",
"integrity": "sha512-dmKlUasSfvUcxBm8nCSKl2x7EFJsXA7OVP8XLFA03T2+6mAc3IiVLC2ambEVOcMOhyhl0vJfVZjM9f9d38D1rw==",
"version": "0.2.10",
"resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.10.tgz",
"integrity": "sha512-GQI6gHYYG5/iD4Kt3VzezzK7fARJzP0zkc82V/+JAdjfeKBXhDSo5rpKFuK3cDcrdW0Fu2emuYNMEAuFqhEQvQ==",
"requires": {
"big-integer": "^1.6.48"
"big-integer": "^1.6.48",
"wasmcurves": "0.0.5",
"worker-threads": "^1.0.0"
}
}
}
@@ -258,9 +247,9 @@
}
},
"cli-width": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
"integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz",
"integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==",
"dev": true
},
"cliui": {
@@ -274,17 +263,17 @@
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"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.4"
"color-name": "1.1.3"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
},
"colors": {
"version": "0.5.1",
@@ -362,9 +351,12 @@
"dev": true
},
"ejs": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.0.1.tgz",
"integrity": "sha512-cuIMtJwxvzumSAkqaaoGY/L6Fc/t6YvoP9/VIaK0V/CyqKLEQ8sqODmYfy/cjXEdZ9+OOL8TecbJu+1RsofGDw=="
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.5.tgz",
"integrity": "sha512-dldq3ZfFtgVTJMLjOe+/3sROTzALlL9E34V4/sDtUd/KlBSS0s6U1/+WPE1B4sj9CXHJpL1M6rhNJnc9Wbal9w==",
"requires": {
"jake": "^10.6.1"
}
},
"emoji-regex": {
"version": "8.0.0",
@@ -374,8 +366,7 @@
"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
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
},
"escodegen": {
"version": "1.3.3",
@@ -472,9 +463,9 @@
}
},
"eslint-scope": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz",
"integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==",
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.0.tgz",
"integrity": "sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==",
"dev": true,
"requires": {
"esrecurse": "^4.1.0",
@@ -491,9 +482,9 @@
}
},
"eslint-visitor-keys": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz",
"integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==",
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
"integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
"dev": true
},
"espree": {
@@ -514,18 +505,18 @@
"dev": true
},
"esquery": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.2.0.tgz",
"integrity": "sha512-weltsSqdeWIX9G2qQZz7KlTRJdkkOCTPgLYJUz1Hacf48R4YOwGPHO3+ORfWedqJKbq5WQmsgK90n+pFLIKt/Q==",
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz",
"integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==",
"dev": true,
"requires": {
"estraverse": "^5.0.0"
"estraverse": "^5.1.0"
},
"dependencies": {
"estraverse": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.0.0.tgz",
"integrity": "sha512-j3acdrMzqrxmJTNj5dbr1YbjacrYgAxVMeF0gK16E3j494mOe7xygM/ZLIguEQ0ETwAg2hlJCtHRGav+y0Ny5A==",
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
"integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
"dev": true
}
}
@@ -574,9 +565,9 @@
}
},
"fast-deep-equal": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
"integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==",
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"dev": true
},
"fast-json-stable-stringify": {
@@ -592,14 +583,14 @@
"dev": true
},
"fastfile": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/fastfile/-/fastfile-0.0.1.tgz",
"integrity": "sha512-Fk8PWafGWGEUw7oPq/dJen92ASxknCEy4ZC8n4VEvSwCp/jcReyEmVoWsRIWTf+IvAp2MzvFi54vOPeK2LQZtQ=="
"version": "0.0.18",
"resolved": "https://registry.npmjs.org/fastfile/-/fastfile-0.0.18.tgz",
"integrity": "sha512-q03PTKc+wptis4WmuFOwPNQx2p5myFUrl/dMgRlW9mymc1Egyc14JPHgiGnWK+sJ0+dBl2Vwtfh5GfSQltYOpw=="
},
"ffiasm": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/ffiasm/-/ffiasm-0.0.2.tgz",
"integrity": "sha512-o/CL7F4IodB7eRHCOQL1SrqN2DIPHrQbEwjPY7NIyeBRdnB3G0xo6b6Mj44SKiWFnvpQMb3n4N7acjD3vv4NVQ==",
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/ffiasm/-/ffiasm-0.1.1.tgz",
"integrity": "sha512-irMMHiR9JJ7BVBrAhtliUawxVdPYSdyl81taUYJ4C1mJ0iw2ueThE/qtr0J8B83tsIY8HJvh0lg5F+6ClK4xpA==",
"requires": {
"big-integer": "^1.6.48",
"ejs": "^3.0.1",
@@ -607,11 +598,24 @@
}
},
"ffjavascript": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.1.2.tgz",
"integrity": "sha512-zB1dhgBjJlvyk2VQIQzFSpUJmanYQYDR/Fo1KhZnaNW5chMFJT55qz0dx1LMKrAklBbidKzz2/C7dgibxQF94g==",
"version": "0.2.22",
"resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.22.tgz",
"integrity": "sha512-EsVqap2Txm17bKW0z/jXCX3M7rQ++nQUAJY8alWDpyhjRj90xjl6GLeVSKZQ8rOFDQ/SFFXcEB8w9X8Boxid+w==",
"requires": {
"big-integer": "^1.6.48"
"big-integer": "^1.6.48",
"wasmcurves": "0.0.12",
"worker-threads": "^1.0.0"
},
"dependencies": {
"wasmcurves": {
"version": "0.0.12",
"resolved": "https://registry.npmjs.org/wasmcurves/-/wasmcurves-0.0.12.tgz",
"integrity": "sha512-1Jl9mkatyHSNj80ILjf85SZUNuZQBCkTjJlhzqHnZQXUmIimCIWkugaVaYNjozLs1Gun4h/keZe1MBeBN0sRpg==",
"requires": {
"big-integer": "^1.6.42",
"blakejs": "^1.1.0"
}
}
}
},
"ffwasm": {
@@ -641,6 +645,14 @@
"flat-cache": "^2.0.1"
}
},
"filelist": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.1.tgz",
"integrity": "sha512-8zSK6Nu0DQIC08mUC46sWGXi+q3GGpKydAG36k+JDba6VRpkevvOWUW5a/PhShij4+vHT9M+ghgG7eM+a9JDUQ==",
"requires": {
"minimatch": "^3.0.4"
}
},
"find-up": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
@@ -673,9 +685,9 @@
}
},
"flatted": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz",
"integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==",
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz",
"integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==",
"dev": true
},
"fnv-plus": {
@@ -738,8 +750,7 @@
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
"dev": true
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
},
"iconv-lite": {
"version": "0.4.24",
@@ -787,36 +798,61 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"inquirer": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.1.0.tgz",
"integrity": "sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==",
"version": "7.3.3",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz",
"integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==",
"dev": true,
"requires": {
"ansi-escapes": "^4.2.1",
"chalk": "^3.0.0",
"chalk": "^4.1.0",
"cli-cursor": "^3.1.0",
"cli-width": "^2.0.0",
"cli-width": "^3.0.0",
"external-editor": "^3.0.3",
"figures": "^3.0.0",
"lodash": "^4.17.15",
"lodash": "^4.17.19",
"mute-stream": "0.0.8",
"run-async": "^2.4.0",
"rxjs": "^6.5.3",
"rxjs": "^6.6.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0",
"through": "^2.3.6"
},
"dependencies": {
"ansi-styles": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
"integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
"dev": true,
"requires": {
"@types/color-name": "^1.1.1",
"color-convert": "^2.0.1"
}
},
"chalk": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
"integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
"dev": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -854,18 +890,23 @@
"is-extglob": "^2.1.1"
}
},
"is-promise": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
"integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
"dev": true
},
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"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"
}
},
"jison": {
"version": "0.4.18",
"resolved": "https://registry.npmjs.org/jison/-/jison-0.4.18.tgz",
@@ -907,9 +948,9 @@
"dev": true
},
"js-yaml": {
"version": "3.13.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
"integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
"version": "3.14.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz",
"integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==",
"dev": true,
"requires": {
"argparse": "^1.0.7",
@@ -963,9 +1004,9 @@
}
},
"lodash": {
"version": "4.17.15",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
"version": "4.17.19",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
"integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
"dev": true
},
"mimic-fn": {
@@ -989,9 +1030,9 @@
"dev": true
},
"mkdirp": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz",
"integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==",
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
"dev": true,
"requires": {
"minimist": "^1.2.5"
@@ -1040,9 +1081,9 @@
}
},
"onetime": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz",
"integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==",
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
"integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
"dev": true,
"requires": {
"mimic-fn": "^2.1.0"
@@ -1069,9 +1110,9 @@
"dev": true
},
"p-limit": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz",
"integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==",
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"requires": {
"p-try": "^2.0.0"
}
@@ -1138,22 +1179,13 @@
"dev": true
},
"r1csfile": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/r1csfile/-/r1csfile-0.0.5.tgz",
"integrity": "sha512-B+BdKPb/WUTp4N/3X4d1Spgx9Ojx5tFVejGZRJxpTtzq34mC8Vi/czWfiPj85V8kud31lCfYcZ16z7+czvM0Sw==",
"version": "0.0.16",
"resolved": "https://registry.npmjs.org/r1csfile/-/r1csfile-0.0.16.tgz",
"integrity": "sha512-A2jRVWzGgmXeG2lVAc0H4suJmzt50it5UvBnycJgBCpMXM3tH/M6RguP7nvs6suY/yYnkN6jX6iTScSiDUF3FA==",
"requires": {
"fastfile": "0.0.1",
"ffjavascript": "0.1.0"
},
"dependencies": {
"ffjavascript": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.1.0.tgz",
"integrity": "sha512-dmKlUasSfvUcxBm8nCSKl2x7EFJsXA7OVP8XLFA03T2+6mAc3IiVLC2ambEVOcMOhyhl0vJfVZjM9f9d38D1rw==",
"requires": {
"big-integer": "^1.6.48"
}
}
"@iden3/bigarray": "0.0.2",
"fastfile": "0.0.18",
"ffjavascript": "0.2.22"
}
},
"regexpp": {
@@ -1197,18 +1229,15 @@
}
},
"run-async": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.0.tgz",
"integrity": "sha512-xJTbh/d7Lm7SBhc1tNvTpeCHaEzoyxPrqNlvSdMfBTYwaY++UJFyXUOxAtsRUXjlqOfj8luNaR9vjCh4KeV+pg==",
"dev": true,
"requires": {
"is-promise": "^2.1.0"
}
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
"integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==",
"dev": true
},
"rxjs": {
"version": "6.5.4",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz",
"integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==",
"version": "6.6.2",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.2.tgz",
"integrity": "sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==",
"dev": true,
"requires": {
"tslib": "^1.9.0"
@@ -1263,30 +1292,6 @@
"is-fullwidth-code-point": "^2.0.0"
},
"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==",
"dev": true,
"requires": {
"color-convert": "^1.9.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==",
"dev": true,
"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=",
"dev": true
},
"is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
@@ -1330,16 +1335,15 @@
}
},
"strip-json-comments": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz",
"integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==",
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
"dev": true
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
@@ -1417,17 +1421,17 @@
}
},
"tmp-promise": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-2.0.2.tgz",
"integrity": "sha512-zl71nFWjPKW2KXs+73gEk8RmqvtAeXPxhWDkTUoa3MSMkjq3I+9OeknjF178MQoMYsdqL730hfzvNfEkePxq9Q==",
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-2.1.1.tgz",
"integrity": "sha512-Z048AOz/w9b6lCbJUpevIJpRpUztENl8zdv1bmAKVHimfqRFl92ROkmT9rp7TVBnrEw2gtMTol/2Cp2S2kJa4Q==",
"requires": {
"tmp": "0.1.0"
}
},
"tslib": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz",
"integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==",
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
"integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==",
"dev": true
},
"type-check": {
@@ -1466,9 +1470,9 @@
}
},
"v8-compile-cache": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz",
"integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==",
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz",
"integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==",
"dev": true
},
"wasmbuilder": {
@@ -1479,6 +1483,15 @@
"big-integer": "^1.6.48"
}
},
"wasmcurves": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/wasmcurves/-/wasmcurves-0.0.5.tgz",
"integrity": "sha512-BmI4GXLjLawGg2YkvHa8zRsnWec+d1uwoxE+Iov8cqOpDL7GA5XO2pk2yuDbXHMzwIug2exnKot3baRZ86R0pA==",
"requires": {
"big-integer": "^1.6.42",
"blakejs": "^1.1.0"
}
},
"which": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
@@ -1499,6 +1512,11 @@
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
"dev": true
},
"worker-threads": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/worker-threads/-/worker-threads-1.0.0.tgz",
"integrity": "sha512-vK6Hhvph8oLxocEJIlc3YfGAZhm210uGzjZsXSu+JYLAQ/s/w4Tqgl60JrdH58hW8NSGP4m3bp8a92qPXgX05w=="
},
"wrap-ansi": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
@@ -1507,6 +1525,30 @@
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
},
"dependencies": {
"ansi-styles": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
"integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
"requires": {
"@types/color-name": "^1.1.1",
"color-convert": "^2.0.1"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
}
}
},
"wrappy": {
@@ -1529,9 +1571,9 @@
"integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w=="
},
"yargs": {
"version": "15.3.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz",
"integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==",
"version": "15.4.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
"integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
"requires": {
"cliui": "^6.0.0",
"decamelize": "^1.2.0",
@@ -1543,13 +1585,13 @@
"string-width": "^4.2.0",
"which-module": "^2.0.0",
"y18n": "^4.0.0",
"yargs-parser": "^18.1.1"
"yargs-parser": "^18.1.2"
}
},
"yargs-parser": {
"version": "18.1.2",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.2.tgz",
"integrity": "sha512-hlIPNR3IzC1YuL1c2UwwDKpXlNFBqD1Fswwh1khz5+d8Cq/8yc/Mn0i+rQXduu8hcrFKvO7Eryk+09NecTQAAQ==",
"version": "18.1.3",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
"integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
"requires": {
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"

View File

@@ -1,6 +1,6 @@
{
"name": "circom",
"version": "0.5.11",
"version": "0.5.34",
"description": "Language to generate logic circuits",
"main": "index.js",
"directories": {
@@ -30,13 +30,13 @@
},
"dependencies": {
"chai": "^4.2.0",
"circom_runtime": "0.0.6",
"fastfile": "0.0.1",
"ffiasm": "0.0.2",
"ffjavascript": "0.1.2",
"circom_runtime": "0.1.9",
"fastfile": "0.0.18",
"ffiasm": "0.1.1",
"ffjavascript": "0.2.22",
"ffwasm": "0.0.7",
"fnv-plus": "^1.3.1",
"r1csfile": "0.0.5",
"r1csfile": "0.0.16",
"tmp-promise": "^2.0.2",
"wasmbuilder": "0.0.10"
},

View File

@@ -1,8 +1,8 @@
const streamFromMultiArray = require("../../src/streamfromarray_txt.js");
const utils = require("../../src/utils");
const assert = require("assert");
const Scalar = require("ffjavascript").Scalar;
const F1Field = require("ffjavascript").F1Field;
const BigArray = require("../../src/bigarray");
function ref2src(c) {
if ((c[0] == "R")||(c[0] == "RI")) {
@@ -59,8 +59,9 @@ class CodeBuilderC {
this.ops.push({op: "SETSIGNAL", component, signal, value});
}
getSignal(dLabel, component, signal) {
this.ops.push({op: "GETSIGNAL", dLabel, component, signal});
getSignal(dLabel, component, signal, n) {
if (typeof(n) == "undefined") n=1;
this.ops.push({op: "GETSIGNAL", dLabel, component, signal, n});
}
copyN(dLabel, offset, src, n) {
@@ -95,6 +96,10 @@ class CodeBuilderC {
this.ops.push({op: "CHECKCONSTRAINT", a, b, strErr});
}
checkAssert(a, strErr) {
this.ops.push({op: "CHECKASSERT", a, strErr});
}
log(val) {
this.ops.push({op: "LOG", val});
}
@@ -177,7 +182,7 @@ class CodeBuilderC {
} else if (o.op == "SETSIGNAL") {
code.push(`ctx->setSignal(__cIdx, ${ref2src(o.component)}, ${ref2src(o.signal)}, ${ref2src(o.value)});`);
} else if (o.op == "GETSIGNAL") {
code.push(`ctx->getSignal(__cIdx, ${ref2src(o.component)}, ${ref2src(o.signal)}, ${o.dLabel});`);
code.push(`ctx->multiGetSignal(__cIdx, ${ref2src(o.component)}, ${ref2src(o.signal)}, ${o.dLabel}, ${o.n});`);
} else if (o.op == "COPYN") {
const oS = ref2src(o.offset);
const dLabel = (oS != "0") ? (o.dLabel + "+" + oS) : o.dLabel;
@@ -215,6 +220,8 @@ class CodeBuilderC {
code.push(`${o.fnName}(ctx, ${o.retLabel}, ${o.params.join(",")});`);
} else if (o.op == "CHECKCONSTRAINT") {
code.push(`ctx->checkConstraint(__cIdx, ${ref2src(o.a)}, ${ref2src(o.b)}, "${o.strErr}");`);
} else if (o.op == "CHECKASSERT") {
code.push(`ctx->checkAssert(__cIdx, ${ref2src(o.a)}, "${o.strErr}");`);
} else if (o.op == "LOG") {
code.push(`ctx->log(${ref2src(o.val)});`);
}
@@ -341,16 +348,23 @@ class FunctionBuilderC {
}
class BuilderC {
constructor(p) {
constructor(p, verbose) {
this.F = new F1Field(p);
this.hashMaps={};
this.componentEntriesTables={};
this.componentEntriesTables=new BigArray();
this.sizes ={};
this.constants = [];
this.functions = [];
this.components = [];
this.components = new BigArray();
this.usedConstants = {};
this.verbose = verbose;
this.sizePointers = {};
this.hashMapPointers = {};
this.functionIdx = {};
this.nCets = 0;
}
setHeader(header) {
@@ -362,8 +376,11 @@ class BuilderC {
this.hashMaps[name] = hm;
}
addComponentEntriesTable(name, cet) {
this.componentEntriesTables[name] = cet;
addComponentEntriesTable(name, cet, idComponent) {
this.componentEntriesTables[idComponent] = {
name: name,
cet: cet
};
}
addSizes(name, accSizes) {
@@ -409,79 +426,104 @@ class BuilderC {
_buildHeader(code) {
code.push(
"#include \"circom.h\"",
"#include \"calcwit.h\"",
"#include \"circom.hpp\"",
"#include \"calcwit.hpp\"",
`#define NSignals ${this.header.NSignals}`,
`#define NComponents ${this.header.NComponents}`,
`#define NOutputs ${this.header.NOutputs}`,
`#define NInputs ${this.header.NInputs}`,
`#define NVars ${this.header.NVars}`,
`#define NPublic ${this.header.NPublic}`,
`#define __P__ "${this.header.P.toString()}"`,
""
);
}
_buildHashMaps(code) {
async _buildHashMaps(fdData) {
code.push("// Hash Maps ");
while (fdData.pos % 8) fdData.pos++;
this.pHashMaps = fdData.pos;
const buff = new Uint8Array(256*12);
const buffV = new DataView(buff.buffer);
for (let hmName in this.hashMaps ) {
while (fdData.pos % 8) fdData.pos++;
this.hashMapPointers[hmName] = fdData.pos;
const hm = this.hashMaps[hmName];
let c = `Circom_HashEntry ${hmName}[256] = {`;
for (let i=0; i<256; i++) {
c += i>0 ? "," : "";
if (hm[i]) {
c += `{0x${hm[i][0]}LL, ${hm[i][1]}} /* ${hm[i][2]} */`;
} else {
c += "{0,0}";
}
buffV.setUint32(i*12, hm[i] ? parseInt( hm[i][0].slice(8), 16 ) : 0, true);
buffV.setUint32(i*12+4, hm[i] ? parseInt( hm[i][0].slice(0,8), 16 ) : 0, true);
buffV.setUint32(i*12+8, hm[i] ? hm[i][1] : 0, true);
}
c += "};";
code.push(c);
await fdData.write(buff);
}
}
_buildComponentEntriesTables(code) {
code.push("// Component Entry tables");
for (let cetName in this.componentEntriesTables) {
const cet = this.componentEntriesTables[cetName];
async _buildComponentEntriesTables(fdData) {
while (fdData.pos % 8) fdData.pos++;
this.pCets = fdData.pos;
for (let i=0; i< this.componentEntriesTables.length; i++) {
if ((this.verbose)&&(i%100000 ==0)) console.log(`_buildComponentEntriesTables ${i}/${this.componentEntriesTables.length}`);
const cet = this.componentEntriesTables[i].cet;
this.components[i].entryTablePointer = fdData.pos;
const buff = new Uint8Array(16*cet.length);
const buffV = new DataView(buff.buffer);
code.push(`Circom_ComponentEntry ${cetName}[${cet.length}] = {`);
for (let j=0; j<cet.length; j++) {
const ty = cet[j].type == "S" ? "_typeSignal" : "_typeComponent";
code.push(` ${j>0?",":" "}{${cet[j].offset},${cet[j].sizeName}, ${ty}}`);
utils.setUint64(buffV, 16*j+0, this.sizePointers[ cet[j].sizeName]);
buffV.setUint32(16*j+8, cet[j].offset, true);
buffV.setUint32(16*j+12, cet[j].type == "S" ? 0 : 1, true); // Size type 0-> Signal, 1->Component
this.nCets ++;
}
code.push("};");
await fdData.write(buff);
}
}
_buildSizes(code) {
code.push("// Sizes");
async _buildSizes(fdData) {
for (let sName in this.sizes) {
const accSizes = this.sizes[sName];
let c = `Circom_Size ${sName}[${accSizes.length}] = {`;
while (fdData.pos % 8) fdData.pos++;
this.sizePointers[sName] = fdData.pos;
const buff = new Uint8Array(4*accSizes.length);
const buffV = new DataView(buff.buffer);
for (let i=0; i<accSizes.length; i++) {
if (i>0) c += ",";
c += accSizes[i];
buffV.setUint32(i*4, accSizes[i], true);
}
c += "};";
code.push(c);
await fdData.write(buff);
}
}
_buildConstants(code) {
async _buildConstants(fdData) {
const self = this;
code.push("// Constants");
code.push(`FrElement _constants[${self.constants.length}] = {`);
for (let i=0; i<self.constants.length; i++) {
code.push((i>0 ? "," : " ") + "{" + number2Code(self.constants[i]) + "}");
}
code.push("};");
const frSize = (8 + self.F.n64*8);
const buff = new Uint8Array(self.constants.length* frSize);
const buffV = new DataView(buff.buffer);
function number2Code(n) {
while (fdData.pos % 8) fdData.pos++;
this.pConstants = fdData.pos;
let o = 0;
for (let i=0; i<self.constants.length; i++) {
Fr2Bytes(buffV, o, self.constants[i]);
o += frSize;
}
await fdData.write(buff);
function Fr2Bytes(buffV, offset, n) {
const minShort = self.F.neg(self.F.e("80000000"));
const maxShort = self.F.e("7FFFFFFF", 16);
@@ -489,51 +531,49 @@ class BuilderC {
&&(self.F.leq(n, maxShort)))
{
if (self.F.geq(n, self.F.zero)) {
return addShortMontgomeryPositive(n);
return shortMontgomeryPositive(n);
} else {
return addShortMontgomeryNegative(n);
return shortMontgomeryNegative(n);
}
}
return addLongMontgomery(n);
return longMontgomery(n);
function addShortMontgomeryPositive(a) {
return `${a.toString()}, 0x40000000, { ${getLongString(toMontgomery(a))} }`;
function shortMontgomeryPositive(a) {
buffV.setUint32(offset, Scalar.toNumber(a) , true );
buffV.setUint32(offset + 4, 0x40000000 , true );
long(buffV, offset + 8, toMontgomery(a));
}
function addShortMontgomeryNegative(a) {
const b = self.F.neg(a);
return `${b.toString()}, 0x40000000, { ${getLongString(toMontgomery(a))} }`;
function shortMontgomeryNegative(a) {
const b = -Scalar.toNumber(self.F.neg(a));
buffV.setUint32(offset, b , true );
buffV.setUint32(offset + 4, 0x40000000 , true );
long(buffV, offset + 8, toMontgomery(a));
}
function addLongMontgomery(a) {
return `0, 0xC0000000, { ${getLongString(toMontgomery(a))} }`;
function longMontgomery(a) {
buffV.setUint32(offset, 0 , true );
buffV.setUint32(offset + 4, 0xC0000000 , true );
long(buffV, offset + 8, toMontgomery(a));
}
function getLongString(a) {
let S = "";
function long(buffV, offset, a) {
let p = offset;
const arr = Scalar.toArray(a, 0x100000000);
for (let i=0; i<self.F.n64*2; i+=2) {
const idx = arr.length-2-i;
if (i>0) S = S + ",";
for (let i=0; i<self.F.n64*2; i++) {
const idx = arr.length-1-i;
if ( idx >=0) {
let msb = arr[idx].toString(16);
while (msb.length<8) msb = "0" + msb;
let lsb = arr[idx+1].toString(16);
while (lsb.length<8) lsb = "0" + lsb;
S += "0x" + msb + lsb + "LL";
buffV.setUint32(p, arr[idx], true);
} else {
S += "0LL";
buffV.setUint32(p, 0, true);
}
p+= 4;
}
return S;
}
function toMontgomery(a) {
@@ -541,98 +581,150 @@ class BuilderC {
}
}
}
_buildFunctions(code) {
const listedFunctions = [];
for (let i=0; i<this.functions.length; i++) {
const cfb = this.functions[i];
cfb.build(code);
if (this.functions[i].type == "COMPONENT") {
this.functionIdx[this.functions[i].name] = listedFunctions.length;
listedFunctions.push(i);
}
}
}
_buildComponents(code) {
code.push("// Components");
code.push(`Circom_Component _components[${this.components.length}] = {`);
for (let i=0; i<this.components.length; i++) {
const c = this.components[i];
code.push("// Function Table");
code.push(`Circom_ComponentFunction _functionTable[${listedFunctions.length}] = {`);
for (let i=0; i<listedFunctions.length; i++) {
const sep = i>0 ? " ," : " ";
code.push(`${sep}{${c.hashMapName}, ${c.entryTableName}, ${c.functionName}, ${c.nInSignals}, ${c.newThread}}`);
code.push(`${sep}${this.functions[listedFunctions[i]].name}`);
}
code.push("};");
}
_buildMapIsInput(code) {
code.push("// mapIsInput");
code.push(`u32 _mapIsInput[${this.mapIsInput.length}] = {`);
let line = "";
async _buildComponents(fdData) {
const buff = new Uint8Array(32);
const buffV = new DataView(buff.buffer);
while (fdData.pos % 8) fdData.pos++;
this.pComponents = fdData.pos;
for (let i=0; i<this.components.length; i++) {
if ((this.verbose)&&(i%1000000 ==0)) console.log(`_buildComponents ${i}/${this.components.length}`);
const c = this.components[i];
utils.setUint64(buffV, 0, this.hashMapPointers[c.hashMapName], true);
utils.setUint64(buffV, 8, c.entryTablePointer, true);
utils.setUint64(buffV, 16, this.functionIdx[c.functionName], true);
buffV.setUint32(24, c.nInSignals, true);
buffV.setUint32(28, c.newThread ? 1 : 0, true);
await fdData.write(buff);
}
}
async _buildMapIsInput(fdData) {
const buff = new Uint8Array(this.mapIsInput.length * 4);
const buffV = new DataView(buff.buffer);
while (fdData.pos % 8) fdData.pos++;
this.pMapIsInput = fdData.pos;
for (let i=0; i<this.mapIsInput.length; i++) {
line += i>0 ? ", " : " ";
line += toHex(this.mapIsInput[i]);
if (((i+1) % 64)==0) {
code.push(" "+line);
line = "";
}
}
if (line != "") code.push(" "+line);
code.push("};");
if ((this.verbose)&&(i%1000000 ==0)) console.log(`_buildMapIsInput ${i}/${this.mapIsInput.length}`);
function toHex(number) {
if (number < 0) number = 0xFFFFFFFF + number + 1;
let S=number.toString(16).toUpperCase();
while (S.length<8) S = "0" + S;
return "0x"+S;
buffV.setUint32(4*i, this.mapIsInput[i], true);
}
await fdData.write(buff);
}
_buildWit2Sig(code) {
code.push("// Witness to Signal Table");
code.push(`int _wit2sig[${this.wit2sig.length}] = {`);
let line = "";
async _buildWit2Sig(fdData) {
const buff = new Uint8Array(this.wit2sig.length * 4);
const buffV = new DataView(buff.buffer);
while (fdData.pos % 8) fdData.pos++;
this.pWit2Sig = fdData.pos;
for (let i=0; i<this.wit2sig.length; i++) {
line += i>0 ? "," : " ";
line += this.wit2sig[i];
if (((i+1) % 64) == 0) {
code.push(" "+line);
line = "";
if ((this.verbose)&&(i%1000000 ==0)) console.log(`_buildWit2Sig ${i}/${this.wit2sig.length}`);
buffV.setUint32(4*i, this.wit2sig[i], true);
}
await fdData.write(buff);
}
async _buildCircuitVar(fdData) {
const buff = new Uint8Array(76);
const buffV = new DataView(buff.buffer);
utils.setUint64(buffV, 0, this.pWit2Sig, true);
utils.setUint64(buffV, 8, this.pComponents, true);
utils.setUint64(buffV, 16, this.pMapIsInput, true);
utils.setUint64(buffV, 24, this.pConstants, true);
utils.setUint64(buffV, 32, this.pPriemStr, true);
utils.setUint64(buffV, 40, this.pCets, true);
buffV.setUint32(48, this.header.NSignals, true);
buffV.setUint32(52, this.header.NComponents, true);
buffV.setUint32(56, this.header.NOutputs, true);
buffV.setUint32(60, this.header.NInputs, true);
buffV.setUint32(64, this.header.NVars, true);
buffV.setUint32(68, this.nCets, true);
buffV.setUint32(72, this.header.NPublic, true);
fdData.pos = 0;
await fdData.write(buff);
}
async _buildPrimeStr(fdData) {
this.pPriemStr = fdData.pos;
const strBuff = new TextEncoder("utf-8").encode(this.header.P.toString());
await fdData.write(strBuff);
const zB = new Uint8Array(1);
zB[0] =0;
await fdData.write(zB);
}
async build(fdCode, fdData) {
const encoder = new TextEncoder("utf-8");
fdData.pos = 76;
while (fdData.pos % 8) fdData.pos++;
const code=new BigArray();
this._buildHeader(code);
await this._buildPrimeStr(fdData);
await this._buildSizes(fdData);
await this._buildConstants(fdData);
await this._buildHashMaps(fdData);
await this._buildComponentEntriesTables(fdData);
this._buildFunctions(code);
await this._buildComponents(fdData);
await this._buildMapIsInput(fdData);
await this._buildWit2Sig(fdData);
await this._buildCircuitVar(fdData);
await writeCode(code);
async function writeCode(c) {
if (c.push) {
for (let i=0; i<c.length; i++) {
await writeCode(c[i]);
}
} else if (typeof c === "string") {
await fdCode.write(encoder.encode(c + "\n"));
}
}
if (line != "") code.push(" "+line);
code.push("};");
}
_buildCircuitVar(code) {
code.push(
"// Circuit Variable",
"Circom_Circuit _circuit = {" ,
" NSignals,",
" NComponents,",
" NInputs,",
" NOutputs,",
" NVars,",
" _wit2sig,",
" _components,",
" _mapIsInput,",
" _constants,",
" __P__",
"};"
);
}
build() {
const code=[];
this._buildHeader(code);
this._buildSizes(code);
this._buildConstants(code);
this._buildHashMaps(code);
this._buildComponentEntriesTables(code);
this._buildFunctions(code);
this._buildComponents(code);
this._buildMapIsInput(code);
this._buildWit2Sig(code);
this._buildCircuitVar(code);
return streamFromMultiArray(code);
}
}

View File

@@ -13,6 +13,7 @@ const utils = require("../../src/utils");
const loadR1cs = require("r1csfile").load;
const ZqField = require("ffjavascript").ZqField;
const buildZqField = require("ffiasm").buildZqField;
const fastFile = require("fastfile");
const {stringifyBigInts, unstringifyBigInts } = require("ffjavascript").utils;
@@ -29,20 +30,24 @@ async function c_tester(circomFile, _options) {
const baseName = path.basename(circomFile, ".circom");
const options = Object.assign({}, _options);
options.cSourceWriteStream = fs.createWriteStream(path.join(dir.path, baseName + ".cpp"));
options.cSourceFile = await fastFile.createOverride(path.join(dir.path, baseName + ".cpp"));
options.dataFile = await fastFile.createOverride(path.join(dir.path, baseName + ".dat"));
options.symWriteStream = fs.createWriteStream(path.join(dir.path, baseName + ".sym"));
options.r1csFileName = path.join(dir.path, baseName + ".r1cs");
options.p = options.p || Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617");
await compiler(circomFile, options);
await options.cSourceFile.close();
await options.dataFile.close();
const source = await buildZqField(options.p, "Fr");
// console.log(dir.path);
await fs.promises.writeFile(path.join(dir.path, "fr.asm"), source.asm, "utf8");
await fs.promises.writeFile(path.join(dir.path, "fr.h"), source.h, "utf8");
await fs.promises.writeFile(path.join(dir.path, "fr.c"), source.c, "utf8");
await fs.promises.writeFile(path.join(dir.path, "fr.hpp"), source.hpp, "utf8");
await fs.promises.writeFile(path.join(dir.path, "fr.cpp"), source.cpp, "utf8");
let pThread = "";
@@ -63,7 +68,7 @@ async function c_tester(circomFile, _options) {
` ${path.join(cdir, "main.cpp")}` +
` ${path.join(cdir, "calcwit.cpp")}` +
` ${path.join(cdir, "utils.cpp")}` +
` ${path.join(dir.path, "fr.c")}` +
` ${path.join(dir.path, "fr.cpp")}` +
` ${path.join(dir.path, "fr.o")}` +
` ${path.join(dir.path, baseName + ".cpp")} ` +
` -o ${path.join(dir.path, baseName)}` +

View File

@@ -384,9 +384,9 @@ module.exports = function buildRuntime(module, builder) {
"error",
c.i32_const(errs.ACCESSING_NOT_ASSIGNED_SIGNAL.code),
c.i32_const(errs.ACCESSING_NOT_ASSIGNED_SIGNAL.pointer),
c.i32_const(0),
c.i32_const(0),
c.i32_const(0),
c.getLocal("cIdx"),
c.getLocal("component"),
c.getLocal("signal"),
c.i32_const(0)
)
)
@@ -412,6 +412,42 @@ module.exports = function buildRuntime(module, builder) {
}
function buildMultiGetSignal() {
const f = module.addFunction("multiGetSignal");
f.addParam("cIdx", "i32");
f.addParam("pR", "i32");
f.addParam("component", "i32");
f.addParam("signal", "i32");
f.addParam("n", "i32");
f.addLocal("i", "i32");
const c = f.getCodeBuilder();
f.addCode(
c.setLocal("i", c.i32_const(0)),
c.block(c.loop(
c.br_if(1, c.i32_eq(c.getLocal("i"), c.getLocal("n"))),
c.call(
"getSignal",
c.getLocal("cIdx"),
c.i32_add(
c.getLocal("pR"),
c.i32_mul(
c.getLocal("i"),
c.i32_const(builder.sizeFr)
)
),
c.getLocal("component"),
c.i32_add(
c.getLocal("signal"),
c.getLocal("i")
)
),
c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(1))),
c.br(0)
))
);
}
function buildSetSignal() {
const f = module.addFunction("setSignal");
@@ -473,7 +509,7 @@ module.exports = function buildRuntime(module, builder) {
);
f.addCode(
c.if( // If ( mapIsInput[s >> 5] & 1 << (s & 0x1f) )
c.if( // If ( mapIsInput[s >> 5] & (1 << (s & 0x1f)) )
c.i32_and(
c.i32_load(
c.i32_add(
@@ -619,6 +655,35 @@ module.exports = function buildRuntime(module, builder) {
));
}
function buildCheckAssert() {
const f = module.addFunction("checkAssert");
f.addParam("cIdx", "i32");
f.addParam("pA", "i32");
f.addParam("pStr", "i32");
const c = f.getCodeBuilder();
f.addCode(ifSanityCheck(c,
c.if (
c.i32_eqz(
c.call(
"Fr_isTrue",
c.getLocal("pA"),
)
),
c.call(
"error",
c.i32_const(errs.ASSERT_DOES_NOT_MATCH.code),
c.i32_const(errs.ASSERT_DOES_NOT_MATCH.pointer),
c.getLocal("cIdx"),
c.getLocal("pA"),
c.getLocal("pStr"),
c.i32_const(0)
)
)
));
}
function buildGetNVars() {
const f = module.addFunction("getNVars");
f.setReturnType("i32");
@@ -628,6 +693,15 @@ module.exports = function buildRuntime(module, builder) {
f.addCode(c.i32_const(builder.header.NVars));
}
function buildGetNPublic() {
const f = module.addFunction("getNPublic");
f.setReturnType("i32");
const c = f.getCodeBuilder();
f.addCode(c.i32_const(builder.header.NPublic));
}
function buildGetFrLen() {
const f = module.addFunction("getFrLen");
f.setReturnType("i32");
@@ -728,12 +802,9 @@ module.exports = function buildRuntime(module, builder) {
c.setLocal(
"pSrc",
c.i32_add(
c.i32_const(builder.pSignals),
c.i32_mul(
c.getLocal("i"),
c.i32_const(builder.sizeFr)
)
c.call(
"getPWitness",
c.getLocal("i"),
)
),
@@ -745,7 +816,7 @@ module.exports = function buildRuntime(module, builder) {
c.setLocal(
"pDst",
c.i32_add(
c.i32_const(builder.pSignals),
c.i32_const(builder.pOutput),
c.i32_mul(
c.getLocal("i"),
c.i32_const(builder.sizeFr-8)
@@ -770,7 +841,7 @@ module.exports = function buildRuntime(module, builder) {
c.br(0)
)),
c.i32_const(builder.pSignals)
c.i32_const(builder.pOutput)
);
}
@@ -804,6 +875,7 @@ module.exports = function buildRuntime(module, builder) {
buildWasmFf(module, "Fr", builder.header.P);
builder.pSignals=module.alloc(builder.header.NSignals*builder.sizeFr);
builder.pOutput=module.alloc(builder.header.NVars*(builder.sizeFr-8));
builder.pInputSignalsToTrigger=module.alloc(builder.header.NComponents*4);
builder.pSignalsAssigned=module.alloc(builder.header.NSignals*4);
@@ -820,13 +892,16 @@ module.exports = function buildRuntime(module, builder) {
buildGetSignal();
buildSetSignal();
buildMultiGetSignal();
buildComponentStarted();
buildComponentFinished();
buildCheckConstraint();
buildCheckAssert();
buildGetNVars();
buildGetNPublic();
buildGetFrLen();
buildGetPWitness();
buildGetPRawPrime();
@@ -836,9 +911,11 @@ module.exports = function buildRuntime(module, builder) {
module.exportFunction("init");
module.exportFunction("getNVars");
module.exportFunction("getNPublic");
module.exportFunction("getFrLen");
module.exportFunction("getSignalOffset32");
module.exportFunction("setSignal");
module.exportFunction("multiGetSignal");
module.exportFunction("getPWitness");
module.exportFunction("Fr_toInt");
module.exportFunction("getPRawPrime");

View File

@@ -1,5 +1,3 @@
const streamFromArrayTxt = require("../../src/streamfromarray_txt");
const streamFromArrayBin = require("../../src/streamfromarray_bin");
const assert = require("assert");
const ModuleBuilder = require("wasmbuilder").ModuleBuilder;
const ModuleBuilderWat = require("wasmbuilder").ModuleBuilderWat;
@@ -64,8 +62,9 @@ class CodeBuilderWasm {
this.ops.push({op: "SETSIGNAL", component, signal, value});
}
getSignal(dLabel, component, signal) {
this.ops.push({op: "GETSIGNAL", dLabel, component, signal});
getSignal(dLabel, component, signal, n) {
if (typeof n == "undefined") n=1;
this.ops.push({op: "GETSIGNAL", dLabel, component, signal, n});
}
copyN(dLabel, offset, src, n) {
@@ -100,6 +99,9 @@ class CodeBuilderWasm {
this.ops.push({op: "CHECKCONSTRAINT", a, b, strErr});
}
checkAssert(a, strErr) {
this.ops.push({op: "CHECKASSERT", a, strErr});
}
concat(cb) {
this.ops.push(...cb.ops);
@@ -250,11 +252,12 @@ class CodeBuilderWasm {
} else if (o.op == "GETSIGNAL") {
code.push(
c.call(
"getSignal",
"multiGetSignal",
c.getLocal("cIdx"),
this.fnBuilder._getPtr(c, o.dLabel),
this.fnBuilder._deRefInt(c, o.component),
this.fnBuilder._deRefInt(c, o.signal)
this.fnBuilder._deRefInt(c, o.signal),
c.i32_const(o.n)
)
);
} else if (o.op == "COPYN") {
@@ -334,6 +337,15 @@ class CodeBuilderWasm {
c.i32_const(this.fnBuilder.builder.module.allocString(o.strErr))
)
);
} else if (o.op == "CHECKASSERT") {
code.push(
c.call(
"checkAssert",
c.getLocal("cIdx"),
this.fnBuilder._deRefFr(c, o.a),
c.i32_const(this.fnBuilder.builder.module.allocString(o.strErr))
)
);
} else if (o.op == "LOG") {
code.push(
c.call(
@@ -769,20 +781,21 @@ class BuilderWasm {
_buildHeader(module) {
this.pCircuit = module.alloc(48);
this.pCircuit = module.alloc(52);
this.pNSignals = this.pCircuit;
this.pNComponents = this.pCircuit + 4;
this.pNInputs = this.pCircuit + 8;
this.pNOutputs = this.pCircuit + 12;
this.pNVars = this.pCircuit + 16;
this.ppWit2sig = this.pCircuit + 20;
this.ppComponents = this.pCircuit + 24;
this.ppMapIsInput = this.pCircuit + 28;
this.ppConstants = this.pCircuit + 32;
this.ppSignals = this.pCircuit + 36;
this.ppInputSignalsToTrigger = this.pCircuit + 40;
this.ppSignalsAssigned = this.pCircuit + 44;
this.pNPublic = this.pCircuit + 20;
this.ppWit2sig = this.pCircuit + 24;
this.ppComponents = this.pCircuit + 28;
this.ppMapIsInput = this.pCircuit + 32;
this.ppConstants = this.pCircuit + 36;
this.ppSignals = this.pCircuit + 40;
this.ppInputSignalsToTrigger = this.pCircuit + 44;
this.ppSignalsAssigned = this.pCircuit + 48;
}
_buildSizes(module) {
@@ -973,6 +986,7 @@ class BuilderWasm {
module.addData(this.pNInputs, intToBytes32(this.header.NInputs));
module.addData(this.pNOutputs, intToBytes32(this.header.NOutputs));
module.addData(this.pNVars, intToBytes32(this.header.NVars));
module.addData(this.pNPublic, intToBytes32(this.header.NPublic));
module.addData(this.ppWit2sig, intToBytes32(this.pWit2sig));
module.addData(this.ppComponents, intToBytes32(this.pComponents));
module.addData(this.ppMapIsInput, intToBytes32(this.pMapIsInput));
@@ -990,7 +1004,8 @@ class BuilderWasm {
}
build(outType) {
async build(fd, outType) {
const encoder = new TextEncoder("utf-8");
let module;
if (outType == "wasm") {
module=new ModuleBuilder();
@@ -1017,12 +1032,25 @@ class BuilderWasm {
module.setMemory(2000);
if (outType == "wasm") {
return streamFromArrayBin(module.build());
const bytes = module.build();
const bytesArr = new Uint8Array(bytes);
await fd.write(bytesArr);
} else if (outType == "wat") {
return streamFromArrayTxt(module.build());
const code = module.build();
await writeCode(code);
} else {
assert(false);
}
async function writeCode(c) {
if (c.push) {
for (let i=0; i<c.length; i++) {
await writeCode(c[i]);
}
} else if (typeof c === "string") {
await fd.write(encoder.encode(c + "\n"));
}
}
}
}

View File

@@ -7,4 +7,5 @@ module.exports = {
SIGNAL_ASSIGNED_TWICE: {code: 6, str: "Signal assigned twice"},
CONSTRAIN_DOES_NOT_MATCH: {code: 7, str: "Constraint doesn't match"},
MAPISINPUT_DONT_MATCH: {code: 8, str: "MapIsInput don't match"},
ASSERT_DOES_NOT_MATCH: {code: 9, str: "Assert not satisfied"},
};

View File

@@ -9,6 +9,7 @@ const compiler = require("../../src/compiler");
const utils = require("../../src/utils");
const loadR1cs = require("r1csfile").load;
const ZqField = require("ffjavascript").ZqField;
const fastFile = require("fastfile");
const WitnessCalculatorBuilder = require("circom_runtime").WitnessCalculatorBuilder;
@@ -24,16 +25,14 @@ async function wasm_tester(circomFile, _options) {
const baseName = path.basename(circomFile, ".circom");
const options = Object.assign({}, _options);
options.wasmWriteStream = fs.createWriteStream(path.join(dir.path, baseName + ".wasm"));
options.wasmFile = await fastFile.createOverride(path.join(dir.path, baseName + ".wasm"));
options.symWriteStream = fs.createWriteStream(path.join(dir.path, baseName + ".sym"));
options.r1csFileName = path.join(dir.path, baseName + ".r1cs");
const promisesArr = [];
promisesArr.push(new Promise(fulfill => options.wasmWriteStream.on("finish", fulfill)));
await compiler(circomFile, options);
await Promise.all(promisesArr);
await options.wasmFile.close();
const wasm = await fs.promises.readFile(path.join(dir.path, baseName + ".wasm"));

View File

@@ -1,4 +1,4 @@
const SUBARRAY_SIZE = 0x10000;
const SUBARRAY_SIZE = 0x40000;
const BigArrayHandler = {
get: function(obj, prop) {
@@ -19,15 +19,17 @@ const BigArrayHandler = {
class _BigArray {
constructor (initSize) {
this.length = initSize || 0;
this.arr = [];
this.arr = new Array(SUBARRAY_SIZE);
for (let i=0; i<initSize; i+=SUBARRAY_SIZE) {
this.arr[i/SUBARRAY_SIZE] = new Array(Math.min(SUBARRAY_SIZE, initSize - i));
}
return this;
}
push (element) {
this.setElement (this.length, element);
push () {
for (let i=0; i<arguments.length; i++) {
this.setElement (this.length, arguments[i]);
}
}
getElement(idx) {
idx = parseInt(idx);
@@ -39,13 +41,26 @@ class _BigArray {
idx = parseInt(idx);
const idx1 = Math.floor(idx / SUBARRAY_SIZE);
if (!this.arr[idx1]) {
this.arr[idx1] = [];
this.arr[idx1] = new Array(SUBARRAY_SIZE);
}
const idx2 = idx % SUBARRAY_SIZE;
this.arr[idx1][idx2] = value;
if (idx >= this.length) this.length = idx+1;
return true;
}
getKeys() {
const newA = new BigArray();
for (let i=0; i<this.arr.length; i++) {
if (this.arr[i]) {
for (let j=0; j<this.arr[i].length; j++) {
if (typeof this.arr[i][j] !== "undefined") {
newA.push(i*SUBARRAY_SIZE+j);
}
}
}
}
return newA;
}
}
class BigArray {

View File

@@ -21,6 +21,7 @@ const assert = require("assert");
const utils = require("./utils");
const gen = require("./gencode").gen;
const createRefs = require("./gencode").createRefs;
const BigArray = require("./bigarray");
module.exports = build;
@@ -37,28 +38,33 @@ function build(ctx) {
ctx.addConstant(ctx.F.zero);
ctx.addConstant(ctx.F.one);
if (ctx.verbose) console.log("buildHeader...");
buildHeader(ctx);
if (ctx.verbose) console.log("buildEntryTables...");
buildEntryTables(ctx);
ctx.globalNames = ctx.uniqueNames;
if (ctx.verbose) console.log("buildCode...");
buildCode(ctx);
if (ctx.verbose) console.log("buildComponentsArray...");
buildComponentsArray(ctx);
if (ctx.verbose) console.log("buildMapIsInput...");
buildMapIsInput(ctx);
if (ctx.verbose) console.log("buildWit2Sig...");
buildWit2Sig(ctx);
}
function buildEntryTables(ctx) {
const codes_hashMaps = [];
const codes_componentEntries = [];
const definedHashMaps = {};
for (let i=0; i<ctx.components.length; i++) {
if (ctx.verbose && (i%100000 ==0)) console.log(`buildEntryTables component: ${i}/${ctx.components.length}`);
const {htName, htMap} = addHashTable(i);
let code = "";
const componentEntriesTableName = ctx.getUniqueName("_entryTable" + ctx.components[i].template);
const componentEntriesTable = [];
@@ -72,34 +78,14 @@ function buildEntryTables(ctx) {
});
}
ctx.builder.addComponentEntriesTable(componentEntriesTableName, componentEntriesTable);
code += `Circom_ComponentEntry ${componentEntriesTableName}[${htMap.length}] = {\n`;
for (let j=0; j<htMap.length; j++) {
const entry = ctx.components[i].names.o[htMap[j]];
code += j>0 ? " ," : " ";
const sizeName = ctx.addSizes(entry.sizes);
const ty = entry.type == "S" ? "_typeSignal" : "_typeComponent";
code += `{${entry.offset},${sizeName}, ${ty}}\n`;
}
code += "};\n";
codes_componentEntries.push(code);
ctx.builder.addComponentEntriesTable(componentEntriesTableName, componentEntriesTable, i);
ctx.components[i].htName = htName;
ctx.components[i].etName = componentEntriesTableName;
}
return [
"// HashMaps\n" ,
codes_hashMaps , "\n" ,
"\n" ,
"// Component Entries\n" ,
codes_componentEntries , "\n" ,
"\n"
];
return;
function addHashTable(cIdx) {
const keys = Object.keys(ctx.components[cIdx].names.o);
@@ -131,6 +117,7 @@ function buildCode(ctx) {
const fnComponents = [];
for (let i=0; i<ctx.components.length; i++) {
if (ctx.verbose && (i%100000 ==0)) console.log(`buildCode component: ${i}/${ctx.components.length}`);
const {h, instanceDef} = hashComponentCall(ctx, i);
const fName = ctx.components[i].template+"_"+h;
if (!fDefined[fName]) {
@@ -180,6 +167,7 @@ function buildCode(ctx) {
function buildComponentsArray(ctx) {
for (let i=0; i< ctx.components.length; i++) {
if (ctx.verbose && (i%1000000 ==0)) console.log(`buildComponentsArray component: ${i}/${ctx.components.length}`);
let newThread;
if (ctx.newThreadTemplates) {
if (ctx.newThreadTemplates.test(ctx.components[i].template)) {
@@ -208,6 +196,7 @@ function buildHeader(ctx) {
NInputs: ctx.components[ ctx.getComponentIdx("main") ].nInSignals,
NOutputs: ctx.totals[ ctx.stOUTPUT ],
NVars: ctx.totals[ctx.stONE] + ctx.totals[ctx.stOUTPUT] + ctx.totals[ctx.stPUBINPUT] + ctx.totals[ctx.stPRVINPUT] + ctx.totals[ctx.stINTERNAL],
NPublic: ctx.totals[ctx.stOUTPUT] + ctx.totals[ctx.stPUBINPUT],
P: ctx.F.p
});
}
@@ -217,6 +206,7 @@ function buildMapIsInput(ctx) {
let map = [];
let acc = 0;
for (i=0; i<ctx.signals.length; i++) {
if (ctx.verbose && (i%1000000 ==0)) console.log(`buildMapIsInput signal: ${i}/${ctx.signals.length}`);
if (ctx.signals[i].o & ctx.IN) {
acc = acc | (1 << (i%32) );
}
@@ -241,8 +231,9 @@ function buildWit2Sig(ctx) {
ctx.totals[ctx.stPUBINPUT] +
ctx.totals[ctx.stPRVINPUT] +
ctx.totals[ctx.stINTERNAL];
const arr = Array(NVars);
const arr = new BigArray(NVars);
for (let i=0; i<ctx.signals.length; i++) {
if (ctx.verbose && (i%1000000 ==0)) console.log(`buildWit2Sig signal: ${i}/${ctx.signals.length}`);
const outIdx = ctx.signals[i].id;
if (ctx.signals[i].e>=0) continue; // If has an alias, continue..
assert(typeof outIdx != "undefined", `Signal ${i} does not have index`);

View File

@@ -28,25 +28,50 @@ const utils = require("./utils");
const buildR1cs = require("./r1csfile").buildR1cs;
const BigArray = require("./bigarray");
const buildSyms = require("./buildsyms");
const {performance} = require("perf_hooks");
module.exports = compile;
const measures = {};
function ms2String(v) {
v = Math.floor(v);
const ms = v % 1000;
v = Math.floor(v/1000);
const secs = v % 60;
v = Math.floor(v/60);
const mins = v % 60;
v = Math.floor(v/60);
const hours = v % 24;
const days = Math.floor(v/24);
let S = "";
if (days) S = S + days + "D ";
if ((S!="")||(hours)) S = S + hours.toString().padStart(2, "0") + ":";
if ((S!="")||(mins)) S = S + mins.toString().padStart(2, "0") + ":";
if ((S!="")||(secs)) S = S + secs.toString().padStart(2, "0");
S+=".";
S = S + ms.toString().padStart(3, "0");
return S;
}
async function compile(srcFile, options) {
options.p = options.p || Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617");
options.prime = options.prime || Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617");
if (!options) {
options = {};
}
if (typeof options.reduceConstraints === "undefined") {
options.reduceConstraints = true;
}
const ctx = new Ctx(options.p);
const ctx = new Ctx(options.prime);
ctx.verbose= options.verbose || false;
ctx.mainComponent = options.mainComponent || "main";
ctx.newThreadTemplates = options.newThreadTemplates;
measures.constructionPhase = -performance.now();
constructionPhase(ctx, srcFile);
measures.constructionPhase += performance.now();
if (ctx.verbose) console.log("NConstraints Before: "+ctx.constraints.length);
if (ctx.verbose) console.log("NSignals Before: "+ctx.signals.length);
if (ctx.error) {
throw(ctx.error);
@@ -56,71 +81,98 @@ async function compile(srcFile, options) {
throw new Error("A main component must be defined");
}
if (ctx.verbose) console.log("Classify Signals");
classifySignals(ctx);
if (ctx.verbose) console.log("Reduce Constants");
measures.reduceConstants = -performance.now();
reduceConstants(ctx);
measures.reduceConstants += performance.now();
if (options.reduceConstraints) {
if (ctx.verbose) console.log("Reduce Constraints");
// Repeat while reductions are performed
/*
let oldNConstrains = -1;
while (ctx.constraints.length != oldNConstrains) {
if (ctx.verbose) console.log("Reducing constraints: "+ctx.constraints.length);
oldNConstrains = ctx.constraints.length;
reduceConstrains(ctx);
}
}
*/
measures.reduceConstraints = -performance.now();
await reduceConstrains(ctx);
measures.reduceConstraints += performance.now();
}
if (ctx.verbose) console.log("NConstraints After: "+ctx.constraints.length);
if (ctx.verbose) console.log("Classify Signals");
measures.classifySignals = -performance.now();
classifySignals(ctx);
measures.classifySignals += performance.now();
measures.generateWitnessNames = -performance.now();
generateWitnessNames(ctx);
measures.generateWitnessNames += performance.now();
if (ctx.error) {
throw(ctx.error);
}
if (options.cSourceWriteStream) {
ctx.builder = new BuilderC(options.p);
build(ctx);
const rdStream = ctx.builder.build();
rdStream.pipe(options.cSourceWriteStream);
// await new Promise(fulfill => options.cSourceWriteStream.on("finish", fulfill));
if (options.r1csFileName) {
measures.generateR1cs = -performance.now();
await buildR1cs(ctx, options.r1csFileName);
measures.generateR1cs += performance.now();
}
if ((options.wasmWriteStream)||(options.watWriteStream)) {
ctx.builder = new BuilderWasm(options.p);
build(ctx);
if (options.wasmWriteStream) {
const rdStream = ctx.builder.build("wasm");
rdStream.pipe(options.wasmWriteStream);
}
if (options.watWriteStream) {
const rdStream = ctx.builder.build("wat");
rdStream.pipe(options.watWriteStream);
}
if (ctx.error) throw(ctx.error);
// await new Promise(fulfill => options.wasmWriteStream.on("finish", fulfill));
delete ctx.constraints; // Liberate memory.
if (options.cSourceFile) {
if (ctx.verbose) console.log("Generating c...");
measures.generateC = -performance.now();
ctx.builder = new BuilderC(options.prime, ctx.verbose);
build(ctx);
await ctx.builder.build(options.cSourceFile, options.dataFile);
measures.generateC += performance.now();
}
if (ctx.error) throw(ctx.error);
if ((options.wasmFile)||(options.watFile)) {
if (ctx.verbose) console.log("Generating wasm...");
measures.generateWasm = -performance.now();
ctx.builder = new BuilderWasm(options.prime);
build(ctx);
if (options.wasmFile) {
await ctx.builder.build(options.wasmFile, "wasm");
}
if (options.watFile) {
await ctx.builder.build(options.watFile, "wat");
}
measures.generateWasm += performance.now();
}
// const mainCode = gen(ctx,ast);
if (ctx.error) throw(ctx.error);
if (options.r1csFileName) {
await buildR1cs(ctx, options.r1csFileName);
}
if (options.symWriteStream) {
measures.generateSyms = -performance.now();
const rdStream = buildSyms(ctx);
rdStream.pipe(options.symWriteStream);
measures.generateSyms += performance.now();
// await new Promise(fulfill => options.symWriteStream.on("finish", fulfill));
await new Promise(fulfill => options.symWriteStream.on("finish", fulfill));
}
// const def = buildCircuitDef(ctx, mainCode);
if (ctx.verbose) {
for (let [mStr, mValue] of Object.entries(measures)) {
console.log(mStr + ": " + ms2String(mValue));
}
}
}
@@ -131,27 +183,36 @@ function classifySignals(ctx) {
function priorize(t1, t2) {
if ((t1 == ERROR) || (t2==ERROR)) return ERROR;
if (t1 == ctx.stINTERNAL) {
return t2;
} else if (t2==ctx.stINTERNAL) {
return t1;
}
if ((t1 == ctx.stONE) || (t2 == ctx.stONE)) return ctx.stONE;
if ((t1 == ctx.stOUTPUT) || (t2 == ctx.stOUTPUT)) return ctx.stOUTPUT;
if ((t1 == ctx.stPUBINPUT) || (t2 == ctx.stPUBINPUT)) return ctx.stPUBINPUT;
if ((t1 == ctx.stPRVINPUT) || (t2 == ctx.stPRVINPUT)) return ctx.stPRVINPUT;
if ((t1 == ctx.stINTERNAL) || (t2 == ctx.stINTERNAL)) return ctx.stINTERNAL;
if ((t1 == ctx.stCONSTANT) || (t2 == ctx.stCONSTANT)) return ctx.stCONSTANT;
if ((t1 == ctx.stDISCARDED) || (t2 == ctx.stDISCARDED)) return ctx.stDISCARDED;
if (t1!=t2) return ERROR;
return t1;
}
for (let i=0; i<ctx.constraints.length; i++) {
if ((ctx.verbose)&&(i%100000 == 0)) console.log(`marking as internal: ${i}/${ctx.constraints.length}`);
const c = ctx.constraints[i];
for (let s in c.a.coefs) ctx.signals[s].c = ctx.stINTERNAL;
for (let s in c.b.coefs) ctx.signals[s].c = ctx.stINTERNAL;
for (let s in c.c.coefs) ctx.signals[s].c = ctx.stINTERNAL;
}
// First classify the signals
for (let s=0; s<ctx.signals.length; s++) {
if ((ctx.verbose)&&(s%100000 == 0)) console.log(`classify signals: ${s}/${ctx.signals.length}`);
const signal = ctx.signals[s];
let tAll = ctx.stINTERNAL;
let tAll = ctx.stDISCARDED;
let lSignal = signal;
let end = false;
while (!end) {
let t = lSignal.c || ctx.stINTERNAL;
let t = lSignal.c || ctx.stDISCARDED;
if (s == 0) {
t = ctx.stONE;
} else if (lSignal.o & ctx.MAIN) {
@@ -249,17 +310,68 @@ function reduceConstants(ctx) {
ctx.constraints = newConstraints;
}
function reduceConstrains(ctx) {
indexVariables();
let possibleConstraints = ctx.constraints;
let ii=0;
while (possibleConstraints.length>0) {
let nextPossibleConstraints = new BigArray();
for (let i=0; i<possibleConstraints.length; i++) {
ii++;
if ((ctx.verbose)&&(ii%10000 == 0)) console.log("reducing constraints: ", i);
if (!ctx.constraints[i]) continue;
const c = ctx.constraints[i];
async function reduceConstrains(ctx) {
const sig2constraint = new BigArray();
let removedSignals = new BigArray();
let nRemoved;
let lIdx;
let possibleConstraints = new BigArray(ctx.constraints.length);
let nextPossibleConstraints;
for (let i=0; i<ctx.constraints.length; i++) {
if ((ctx.verbose)&&(i%100000 == 0)) console.log(`indexing constraints: ${i}/${ctx.constraints.length}`);
const insertedSig = { 0: true}; // Do not insert one.
const c = ctx.constraints[i];
for (let s in c.a.coefs) {
if (!insertedSig[s]) {
if (!sig2constraint[s]) sig2constraint[s] = {};
sig2constraint[s][i] = true;
insertedSig[s] = true;
}
}
for (let s in c.b.coefs) {
if (!insertedSig[s]) {
if (!sig2constraint[s]) sig2constraint[s] = {};
sig2constraint[s][i] = true;
insertedSig[s] = true;
}
}
for (let s in c.c.coefs) {
if (!insertedSig[s]) {
if (!sig2constraint[s]) sig2constraint[s] = {};
sig2constraint[s][i] = true;
insertedSig[s] = true;
}
}
possibleConstraints[i] = ctx.constraints.length - i -1;
}
let totalRemoved = 0;
while (possibleConstraints.length >0) {
if (possibleConstraints.length>1<<20) {
nextPossibleConstraints = new BigArray();
} else {
nextPossibleConstraints = {};
}
removedSignals = {};
nRemoved = 0;
lIdx = {};
for (let i=0;i<possibleConstraints.length;i++) {
if ((ctx.verbose)&&(i%10000 == 0)) {
await Promise.resolve();
console.log(`reducing constraints: ${i}/${possibleConstraints.length} reduced: ${nRemoved}`);
}
const c = ctx.constraints[possibleConstraints[i]];
if (!c) continue;
// Limit of number of lelements removed per step
if (nRemoved>5000000) {
nextPossibleConstraints[possibleConstraints[i]] = true;
continue;
}
// Swap a and b if b has more variables.
if (Object.keys(c.b).length > Object.keys(c.a).length) {
@@ -283,113 +395,176 @@ function reduceConstrains(ctx) {
}
if (ctx.lc.isZero(c.a) || ctx.lc.isZero(c.b)) {
const isolatedSignal = getFirstInternalSignal(ctx, c.c);
const freeC = substituteRemoved(c.c);
const isolatedSignal = getFirstInternalSignal(ctx, freeC);
if (isolatedSignal) {
removedSignals[isolatedSignal] = isolateSignal(freeC, isolatedSignal);
if (lIdx[isolatedSignal]) {
const sigs = Object.keys(lIdx[isolatedSignal]);
let lSignal = ctx.signals[isolatedSignal];
while (lSignal.e>=0) {
lSignal = ctx.signals[lSignal.e];
}
const isolatedSignalEquivalence = {
t: "LC",
coefs: {}
};
const invCoef = ctx.F.inv(c.c.coefs[isolatedSignal]);
for (const s in c.c.coefs) {
if (s != isolatedSignal) {
const v = ctx.F.mul( ctx.F.neg(c.c.coefs[s]), invCoef);
if (!ctx.F.isZero(v)) {
isolatedSignalEquivalence.coefs[s] = v;
}
for (let k=0; k<sigs.length; k++) {
const s = sigs[k];
const oldLC = removedSignals[s];
removedSignals[s] = substitute(removedSignals[s], isolatedSignal, removedSignals[isolatedSignal]);
if (oldLC !== removedSignals[s]) addTolIdx(removedSignals[s], s);
}
}
for (let j in lSignal.inConstraints) {
if ((j!=i)&&(ctx.constraints[j])) {
ctx.constraints[j] = ctx.lc.substitute(ctx.constraints[j], isolatedSignal, isolatedSignalEquivalence);
linkSignalsConstraint(j);
if (j<i) {
nextPossibleConstraints.push(j);
}
}
addTolIdx(removedSignals[isolatedSignal], isolatedSignal);
ctx.constraints[possibleConstraints[i]] = null;
nRemoved ++;
delete lIdx[isolatedSignal];
const cts = Object.keys(sig2constraint[isolatedSignal]);
for (let k=0; k<cts.length; k++) {
if (ctx.constraints[cts[k]]) nextPossibleConstraints[cts[k]] = true;
}
ctx.constraints[i] = null;
lSignal.c = ctx.stDISCARDED;
} else {
if (ctx.lc.isZero(c.c)) ctx.constraints[i] = null;
}
}
}
possibleConstraints = nextPossibleConstraints;
}
unindexVariables();
// Pack the constraints
let o = 0;
for (let i=0; i<ctx.constraints.length; i++) {
if (ctx.constraints[i]) {
if (o != i) {
ctx.constraints[o] = ctx.constraints[i];
}
o++;
if (nextPossibleConstraints.getKeys) {
nextPossibleConstraints = nextPossibleConstraints.getKeys();
} else {
nextPossibleConstraints = Object.keys(nextPossibleConstraints);
}
}
ctx.constraints.length = o;
function indexVariables() {
for (let i=0; i<ctx.constraints.length; i++) linkSignalsConstraint(i);
}
for (let i=0; i<nextPossibleConstraints.length;i++) {
if ((ctx.verbose)&&(i%10000 == 0)) {
await Promise.resolve();
console.log(`substituting constraints: ${i}/${nextPossibleConstraints.length}`);
}
const c = ctx.constraints[nextPossibleConstraints[i]];
if (c) {
const nc = {
a: substituteRemoved(c.a, nextPossibleConstraints[i]),
b: substituteRemoved(c.b, nextPossibleConstraints[i]),
c: substituteRemoved(c.c, nextPossibleConstraints[i])
};
if (ctx.lc.isZero(nc)) {
delete ctx.constraints[nextPossibleConstraints[i]];
} else {
ctx.constraints[nextPossibleConstraints[i]] = nc;
}
}
}
function linkSignalsConstraint(cidx) {
const ct = ctx.constraints[cidx];
for (let k in ct.a.coefs) linkSignal(k, cidx);
for (let k in ct.b.coefs) linkSignal(k, cidx);
for (let k in ct.c.coefs) linkSignal(k, cidx);
}
const removedSignalsList = Object.keys(removedSignals);
for (let i=0; i<removedSignalsList.length; i++) {
if ((ctx.verbose )&&(i%100000 == 0)) console.log(`removing signals: ${i}/${removedSignalsList.length}`);
const s = removedSignalsList[i];
function unindexVariables() {
for (let s=0; s<ctx.signals.length; s++) {
let lSignal = ctx.signals[s];
while (lSignal.e>=0) {
lSignal = ctx.signals[lSignal.e];
}
if (lSignal.inConstraints) delete lSignal.inConstraints;
sig2constraint[s] = null;
}
}
/*
function unlinkSignal(signalName, cidx) {
let lSignal = ctx.signals[signalName];
while (lSignal.e>=0) {
lSignal = ctx.signals[lSignal.e];
possibleConstraints = new BigArray();
// Reverse
for (let i=0; i<nextPossibleConstraints.length; i++) {
possibleConstraints[i] = nextPossibleConstraints[nextPossibleConstraints.length -1 -i];
}
if ((lSignal.inConstraints)&&(lSignal.inConstraints[cidx])) {
delete lSignal.inConstraints[cidx];
}
}
*/
possibleConstraints = nextPossibleConstraints;
function linkSignal(signalName, cidx) {
let lSignal = ctx.signals[signalName];
while (lSignal.e>=0) {
lSignal = ctx.signals[lSignal.e];
}
if (!lSignal.inConstraints) lSignal.inConstraints = {};
lSignal.inConstraints[cidx] = true;
totalRemoved += nRemoved;
if (ctx.verbose) console.log(`Removed: ${totalRemoved} TotalConstraints: ${ctx.constraints.length}` );
}
let o=0;
for (let i=0; i<ctx.constraints.length;i++) {
if ((ctx.verbose)&&(i%100000 == 0)) console.log(`reordering constraints: ${i}/${ctx.constraints.length}`);
if (ctx.constraints[i]) {
if (!ctx.lc.isZero(ctx.constraints[i])) {
ctx.constraints[o] = ctx.constraints[i];
o++;
}
}
}
ctx.constraints.length = o;
function getFirstInternalSignal(ctx, l) {
for (let k in l.coefs) {
k = Number(k);
const signal = ctx.signals[k];
if (signal.c == ctx.stINTERNAL) return k;
if ( ( ((signal.o & ctx.MAIN) == 0)
||( ((signal.o & ctx.IN) == 0)
&&((signal.o & ctx.OUT) == 0)))
&&((signal.o & ctx.ONE) ==0)
&&(!ctx.F.isZero(l.coefs[k]))
&&(!removedSignals[k])) return k;
}
return null;
}
function isolateSignal(lc, s) {
const eq = {
t: "LC",
coefs: {}
};
const invCoef = ctx.F.inv(lc.coefs[s]);
for (const k in lc.coefs) {
if (k != s) {
const v = ctx.F.mul( ctx.F.neg(lc.coefs[k]), invCoef);
if (!ctx.F.isZero(v)) {
eq.coefs[k] = v;
}
}
}
return eq;
}
function substituteRemoved(lc, idxConstraint) {
const newLc = ctx.lc._clone(lc);
for (let k in lc.coefs) {
if (removedSignals[k]) {
delete newLc.coefs[k];
for (let k2 in removedSignals[k].coefs) {
const newP = ctx.F.mul(removedSignals[k].coefs[k2], lc.coefs[k]);
if (!ctx.F.isZero(newP)) {
if (newLc.coefs[k2]) {
newLc.coefs[k2] = ctx.F.add(newLc.coefs[k2], newP);
if (ctx.F.isZero(newLc.coefs[k2])) delete newLc.coefs[k2];
} else {
newLc.coefs[k2] = newP;
}
}
if ((typeof idxConstraint != "undefined")&&(k2!=0)) {
if (!sig2constraint[k2]) sig2constraint[k2] = {};
sig2constraint[k2][idxConstraint] = true;
}
}
}
}
return newLc;
}
function substitute(lc, s, eq) {
if (!lc.coefs[s]) return lc;
const newLc = ctx.lc._clone(lc);
delete newLc.coefs[s];
for (let k2 in eq.coefs) {
const newP = ctx.F.mul(eq.coefs[k2], lc.coefs[s]);
if (!ctx.F.isZero(newP)) {
if (newLc.coefs[k2]) {
newLc.coefs[k2] = ctx.F.add(newLc.coefs[k2], newP);
if (ctx.F.isZero(newLc.coefs[k2])) delete newLc.coefs[k2];
} else {
newLc.coefs[k2] = newP;
}
}
}
return newLc;
}
function isConstant(l) {
for (let k in l.coefs) {
if ((k != sONE) && (!ctx.F.isZero(l.coefs[k]))) return false;
@@ -398,159 +573,17 @@ function reduceConstrains(ctx) {
return true;
}
}
/*
function buildCircuitDef(ctx, mainCode) {
const res = {
mainCode: mainCode
};
res.signalName2Idx = ctx.signalName2Idx;
res.components = [];
res.componentName2Idx = {};
for (let c in ctx.components) {
const idCoponent = res.components.length;
res.components.push({
name: c,
params: ctx.components[c].params,
template: ctx.components[c].template,
inputSignals: 0
});
res.componentName2Idx[c] = idCoponent;
}
res.signals = new Array(ctx.signalNames.length);
for (let i=0; i<ctx.signalNames.length; i++) {
res.signals[i] = {
names: ctx.signalNames[i],
triggerComponents: []
};
ctx.signalNames[i].map( (fullName) => {
const idComponet = res.componentName2Idx[ctx.signals[fullName].component];
if (ctx.signals[fullName].direction == "IN") {
res.signals[i].triggerComponents.push(idComponet);
res.components[idComponet].inputSignals++;
function addTolIdx(lc, newS) {
const sigs = Object.keys(lc.coefs);
for (let k=0; k<sigs.length; k++) {
const s = sigs[k];
if (s) {
if (!lIdx[s]) lIdx[s] = {};
lIdx[s][newS] = true;
}
});
}
res.constraints = buildConstraints(ctx);
res.templates = ctx.templates;
res.functions = {};
for (let f in ctx.functions) {
res.functions[f] = {
params: ctx.functionParams[f],
func: ctx.functions[f]
};
}
res.nPrvInputs = ctx.totals.prvInput;
res.nPubInputs = ctx.totals.pubInput;
res.nInputs = res.nPrvInputs + res.nPubInputs;
res.nOutputs = ctx.totals.output;
res.nVars = res.nInputs + res.nOutputs + ctx.totals.one + ctx.totals.internal;
res.nConstants = ctx.totals.constant;
res.nSignals = res.nVars + res.nConstants;
return res;
}
*/
/*
Build constraints
A constraint like this
[s1 + 2*s2 + 3*s3] * [ s2 + 5*s4] - [s0 ] = 0
[ 5*s2 + 6*s3] * [ s2 + ] - [s0 + 2* s2] = 0
[s1 + s3] * [ s2 + 5*s3] - [s4 ] = 0
is converted to
[
[{"1":"1","2":"2","3":"3"} , {"2":"1","4":"5"} , {"0":"1" }],
[{ "2":"5","3":"6"} , {"2":"1" } , {"0":"1", "2":"2"}],
[{"1":"1", "3":"1"} , {"2":"1","3":"5"} , {"4":"1" }]
]
^ ^ ^
| | |
A B C
*/
/*
function buildConstraints(ctx) {
const res = [];
function fillLC(dst, src) {
if (src.t != "LC") throw new Error("Constraint is not a LINEARCOMBINATION");
for (let s in src.coefs) {
const v = src.coefs[s].toString();
const id = ctx.signalName2Idx[s];
dst[id] = v;
}
}
for (let i=0; i<ctx.constraints.length; i++) {
const A = {};
const B = {};
const C = {};
fillLC(A, ctx.constraints[i].a);
fillLC(B, ctx.constraints[i].b);
fillLC(C, ctx.lc.negate(ctx.constraints[i].c));
res.push([A,B,C]);
}
return res;
}
*/
/*
function buildSyms(ctx, strm) {
let nSyms;
addSymbolsComponent(ctx.mainComponent + ".", ctx.getComponentIdx(ctx.mainComponent));
function addSymbolsComponent(prefix, idComponet) {
for (let n in ctx.components[idComponet].names.o) {
const entrie = ctx.components[idComponet].names.o[n];
addSymbolArray(prefix+n, entrie.type, entrie.sizes, entrie.offset);
}
}
function addSymbolArray(prefix, type, sizes, offset) {
if (sizes.length==0) {
if (type == "S") {
let s=offset;
while (ctx.signals[s].e >= 0) s = ctx.signals[s].e;
let wId = ctx.signals[s].id;
if (typeof(wId) == "undefined") wId=-1;
strm.write(`${offset},${wId},${prefix}\n`);
nSyms ++;
if ((ctx.verbose)&&(nSyms%10000 == 0)) console.log("Symbols saved: "+nSyms);
} else {
addSymbolsComponent(prefix+".", offset);
}
return 1;
} else {
let acc = 0;
for (let i=0; i<sizes[0]; i++) {
acc += addSymbolArray(`${prefix}[${i}]`, type, sizes.slice(1), offset + acc );
}
return acc;
}
}
}
*/

View File

@@ -428,10 +428,17 @@ function execAssignement(ctx, ast) {
}
// Skip if an out is assigned directly to an input.
if ((!isIn)||(!isOut)) {
sDest.e = sIdx;
} else {
if (utils.isDefined(sSrc.v)) sDest.v = sSrc.v;
if (!(isIn&&isOut)) {
if (isIn) {
sDest.e = sIdx;
} else if (isOut) {
sSrc.e = dIdx;
} else {
sDest.e = sIdx;
}
if (!isOut) {
if (utils.isDefined(sSrc.v)) sDest.v = sSrc.v;
}
}
}
}
@@ -567,14 +574,18 @@ function execFunctionCall(ctx, ast) {
return;
}
if (ast.name == "assert") {
ast.fileName = ctx.fileName;
ast.filePath = ctx.filePath;
const v = exec(ctx, ast.params[0]);
const ev = val(ctx, v, ast);
if (ctx.F.isZero(ev)) return ctx.throwError(ast, "Assertion failed");
if ((typeof ev.v !== "undefined")&&(ctx.F.isZero(ev.v))) return ctx.throwError(ast, "Assertion failed");
return;
}
const fnc = ctx.functions[ast.name];
if (!fnc) return ctx.throwError("Function not defined");
if (!fnc) return ctx.throwError(ast, "Function not defined");
const paramValues = [];
for (let i=0; i< ast.params.length; i++) {
@@ -697,6 +708,9 @@ function execPin(ctx, ast) {
if (sel.v[0].t != "N") return NQVAL;
selsP.push(Scalar.toNumber(sel.v[0].v));
}
if (!ctx.components[cIdx]) {
return ctx.throwError(ast, "Component not defined yet");
}
const sIdx = ctx.components[cIdx].names.getSignalIdx(ast.pin.name, selsP);
if (sIdx<0) return ctx.throwError(ast, "Signal not defined:" + buildFullName() );
@@ -874,7 +888,8 @@ function execOpOp(ctx, ast, op, lr) {
right = {t:"N", v: ctx.F.one};
}
if (!right) return ctx.throwError(ast, "adding a no number");
if (!right) return ctx.throwError(ast, "right operand is not initialized");
if (!resBefore) return ctx.throwError(ast, "left operand is not initialized");
const resAfter = ctx.lc[op](resBefore, right);
left.v[o] = resAfter;

View File

@@ -284,6 +284,32 @@ function genDeclareComponent(ctx, ast) {
}
function genDeclareSignal(ctx, ast) {
const v = ctx.refs[ast.refId];
let sizes;
if (ast.name.selectors.length>0) {
sizes=[];
for (let i=0; i< ast.name.selectors.length; i++) {
const sizeRef = gen(ctx, ast.name.selectors[i]);
const size = ctx.refs[sizeRef];
if (size.sizes[0] != 1) return ctx.throwError(ast, "A selector cannot be an array");
if (size.used) return ctx.throwError(ast, "Signal size variables not allowed");
sizes.push(Scalar.toNumber(size.value[0]));
}
sizes = utils.accSizes(sizes);
} else {
sizes = [1,0];
}
if ((!v.sizes)&&(sizes)) {
v.sizes = sizes;
}
if (v.sizes) {
if (!utils.sameSizes(v.sizes, sizes)) return ctx.throwError(ast, "Redefined a signal with different sized");
}
return ast.refId;
}
@@ -414,12 +440,13 @@ function genVariable(ctx, ast) {
vOffset = genGetSignalOffset(ctx, -1, ast.name);
}
const resRef = newRef(ctx, "BIGINT", "_sigValue");
const sizes = v.sizes.slice(l);
const resRef = newRef(ctx, "BIGINT", "_sigValue", null, sizes);
const res = ctx.refs[resRef];
instantiateRef(ctx, resRef);
ctx.codeBuilder.getSignal(res.label, ["CC"], toRefA_Int1(ctx, ast, vOffset));
ctx.codeBuilder.getSignal(res.label, ["CC"], toRefA_Int1(ctx, ast, vOffset), sizes[0]);
return resRef;
} else if (v.type == "BIGINT") {
const refOffset = genGetOffset(ctx, 0, v.sizes, ast.selectors );
const offset = ctx.refs[refOffset];
@@ -486,13 +513,18 @@ function genPin(ctx, ast) {
vsIdx = genGetSignalOffset(ctx, vcIdx, ast.pin.name);
}
const resRef = newRef(ctx, "BIGINT", "_sigValue");
const l = ast.selectors ? ast.selectors.length : 0;
const sizes = [1,0]; // TODO, Treat array
const resRef = newRef(ctx, "BIGINT", "_sigValue", null, sizes);
const res = ctx.refs[resRef];
instantiateRef(ctx, resRef);
ctx.codeBuilder.getSignal(
res.label,
toRefA_Int1(ctx, ast.component, vcIdx),
toRefA_Int1(ctx, ast.pin, vsIdx)
toRefA_Int1(ctx, ast.pin, vsIdx),
sizes[0]
);
return resRef;
}
@@ -723,7 +755,15 @@ function genVarAssignment(ctx, ast, lRef, sels, rRef) {
if (instantiated) {
if (offset.used) {
ctx.codeBuilder.copyN(left.label, ["R", offset.label], ["R", right.label], right.sizes[0]);
let ot;
if (offset.type == "BIGINT") {
ot = "R";
} else if (offset.type == "INT") {
ot= "RI";
} else {
assert(false);
}
ctx.codeBuilder.copyN(left.label, [ot, offset.label], ["R", right.label], right.sizes[0]);
} else {
ctx.codeBuilder.copyN(left.label, ["V", offset.value[0]], ["R", right.label], right.sizes[0]);
}
@@ -863,6 +903,12 @@ function genFunctionCall(ctx, ast) {
ctx.codeBuilder.log(toRefA_Fr1(ctx, ast.params[0], vRef));
return vRef;
}
if (ast.name == "assert") {
const strErr = ast.fileName + ":" + ast.first_line + ":" + ast.first_column;
const vRef = gen(ctx, ast.params[0]);
ctx.codeBuilder.checkAssert(toRefA_Fr1(ctx, ast.params[0], vRef), strErr);
return vRef;
}
const params = [];
for (let i=0; i<ast.params.length; i++) {
const pRef = gen(ctx, ast.params[i]);
@@ -937,7 +983,7 @@ function genLoop(ctx, ast) {
if (ctx.error) return;
const cond = ctx.refs[condRef];
if (!utils.sameSizes(cond.sizes, [1,0])) return ctx.throwError(ast.condition, "Operation cannot be done on an array");
if (!utils.sameSizes(cond.sizes, [1,0])) return ctx.throwError(ast.condition, "genLoop: Operation cannot be done on an array");
if (cond.used) {
inLoop = true;
@@ -1014,7 +1060,7 @@ function genIf(ctx, ast) {
const condRef = gen(ctx, ast.condition);
if (ctx.error) return;
const cond = ctx.refs[condRef];
if (!utils.sameSizes(cond.sizes, [1,0])) return ctx.throwError(ast.condition, "Operation cannot be done on an array");
if (!utils.sameSizes(cond.sizes, [1,0])) return ctx.throwError(ast.condition, "genIf: Operation cannot be done on an array");
if (cond.used) {
let thenCode, elseCode;
@@ -1134,7 +1180,12 @@ function genOp(ctx, ast, op, nOps, adjustBool) {
valRefs.push(ref);
vals.push(v);
if (!utils.sameSizes(v.sizes, [1,0])) return ctx.throwError(ast, "Operation cannot be done on an array");
if (!utils.sameSizes(v.sizes, [1,0])) {
console.log("xx");
console.log(i);
console.log(v);
return ctx.throwError(ast, "genOp2: Operation cannot be done on an array");
}
if ( (!v.used)
&&( (!utils.isDefined(v.value))
||(!utils.isDefined(v.value[0]))))
@@ -1170,7 +1221,7 @@ function genTerCon(ctx, ast) {
const condRef = gen(ctx, ast.values[0]);
if (ctx.error) return;
const cond = ctx.refs[condRef];
if (!utils.sameSizes(cond.sizes, [1,0])) return ctx.throwError(ast.condition, "Operation cannot be done on an array");
if (!utils.sameSizes(cond.sizes, [1,0])) return ctx.throwError(ast.condition, "genTer: Operation cannot be done on an array");
if (cond.used) {
let thenCode, elseCode;

View File

@@ -123,6 +123,7 @@ class LCAlgebra {
}
_signal2lc(a) {
const self = this;
if (a.t == "S") {
const lc = {
t: "LC",

View File

@@ -1,30 +1,35 @@
const fastFile = require("fastfile");
const assert = require("assert");
const BigArray = require("./bigarray");
module.exports.buildR1cs = buildR1cs;
async function buildR1cs(ctx, fileName) {
const fd = await fastFile.createOverride(fileName);
const fd = await fastFile.createOverride(fileName, 1<<24, 1<<22);
const buffBigInt = new Uint8Array(ctx.F.n8);
await fd.write(Buffer.from("r1cs"), 0); // Magic "r1cs"
const type = "r1cs";
const buff = new Uint8Array(4);
for (let i=0; i<4; i++) buff[i] = type.charCodeAt(i);
await fd.write(buff, 0); // Magic "r1cs"
let p = 4;
await writeU32(1); // Version
await writeU32(3); // Number of Sections
await fd.writeULE32(1); // Version
await fd.writeULE32(3); // Number of Sections
// Write the header
///////////
await writeU32(1); // Header type
const pHeaderSize = p;
await writeU64(0); // Temporally set to 0 length
await fd.writeULE32(1); // Header type
const pHeaderSize = fd.pos;
await fd.writeULE64(0); // Temporally set to 0 length
const n8 = (Math.floor( (ctx.F.bitLength - 1) / 64) +1)*8;
// Field Def
await writeU32(n8); // Temporally set to 0 length
await fd.writeULE32(n8); // Temporally set to 0 length
await writeBigInt(ctx.F.p);
const NWires =
@@ -34,38 +39,38 @@ async function buildR1cs(ctx, fileName) {
ctx.totals[ctx.stPRVINPUT] +
ctx.totals[ctx.stINTERNAL];
await writeU32(NWires);
await writeU32(ctx.totals[ctx.stOUTPUT]);
await writeU32(ctx.totals[ctx.stPUBINPUT]);
await writeU32(ctx.totals[ctx.stPRVINPUT]);
await writeU64(ctx.signals.length);
await writeU32(ctx.constraints.length);
await fd.writeULE32(NWires);
await fd.writeULE32(ctx.totals[ctx.stOUTPUT]);
await fd.writeULE32(ctx.totals[ctx.stPUBINPUT]);
await fd.writeULE32(ctx.totals[ctx.stPRVINPUT]);
await fd.writeULE64(ctx.signals.length);
await fd.writeULE32(ctx.constraints.length);
const headerSize = p - pHeaderSize - 8;
const headerSize = fd.pos - pHeaderSize - 8;
// Write constraints
///////////
await writeU32(2); // Constraints type
const pConstraintsSize = p;
await writeU64(0); // Temporally set to 0 length
await fd.writeULE32(2); // Constraints type
const pConstraintsSize = fd.pos;
await fd.writeULE64(0); // Temporally set to 0 length
for (let i=0; i<ctx.constraints.length; i++) {
if ((ctx.verbose)&&(i%10000 == 0)) {
if (ctx.verbose) console.log("writing constraint: ", i);
}
await writeConstraint(ctx.constraints[i]);
await writeConstraint(ctx.constraints[i], i);
}
const constraintsSize = p - pConstraintsSize - 8;
const constraintsSize = fd.pos - pConstraintsSize - 8;
// Write map
///////////
await writeU32(3); // wires2label type
const pMapSize = p;
await writeU64(0); // Temporally set to 0 length
await fd.writeULE32(3); // wires2label type
const pMapSize = fd.pos;
await fd.writeULE64(0); // Temporally set to 0 length
const arr = new Array(NWires);
const arr = new BigArray(NWires);
for (let i=0; i<ctx.signals.length; i++) {
const outIdx = ctx.signals[i].id;
if (ctx.signals[i].e>=0) continue; // If has an alias, continue..
@@ -76,75 +81,66 @@ async function buildR1cs(ctx, fileName) {
}
}
for (let i=0; i<arr.length; i++) {
await writeU64(arr[i]);
if ((ctx.verbose)&&(i%100000)) console.log("writing wire2label map: ", i);
await fd.writeULE64(arr[i]);
if ((ctx.verbose)&&(i%100000 == 0)) console.log(`writing wire2label map: ${i}/${arr.length}`);
}
const mapSize = p - pMapSize - 8;
const mapSize = fd.pos - pMapSize - 8;
// Write sizes
await writeU32(headerSize, pHeaderSize);
await writeU32(constraintsSize, pConstraintsSize);
await writeU32(mapSize, pMapSize);
await fd.writeULE64(headerSize, pHeaderSize);
await fd.writeULE64(constraintsSize, pConstraintsSize);
await fd.writeULE64(mapSize, pMapSize);
await fd.close();
async function writeU32(v, pos) {
let o = (typeof pos == "undefined") ? p : pos;
const b = Buffer.allocUnsafe(4);
b.writeInt32LE(v);
await fd.write(b, o);
if (typeof(pos) == "undefined") p += 4;
}
async function writeU64(v, pos) {
let o = (typeof pos == "undefined") ? p : pos;
const b = Buffer.allocUnsafe(8);
const LSB = v & 0xFFFFFFFF;
const MSB = Math.floor(v / 0x100000000);
b.writeInt32LE(LSB, 0);
b.writeInt32LE(MSB, 4);
await fd.write(b, o);
if (typeof(pos) == "undefined") p += 8;
}
async function writeConstraint(c) {
await writeLC(c.a);
await writeLC(c.b);
await writeLC(ctx.lc.neg(c.c));
}
async function writeLC(lc) {
const idxs = Object.keys(lc.coefs);
await writeU32(idxs.length);
for (let s in lc.coefs) {
let lSignal = ctx.signals[s];
function writeConstraint(c, ctIdx) {
const n8 = ctx.F.n8;
const idxA = Object.keys(c.a.coefs);
const idxB = Object.keys(c.b.coefs);
const idxC = Object.keys(c.c.coefs);
const buff = new Uint8Array((idxA.length+idxB.length+idxC.length)*(n8+4) + 12);
const buffV = new DataView(buff.buffer);
let o=0;
buffV.setUint32(o, idxA.length, true); o+=4;
for (let i=0; i<idxA.length; i++) {
const coef = idxA[i];
let lSignal = ctx.signals[coef];
while (lSignal.e >=0 ) lSignal = ctx.signals[lSignal.e];
await writeU32(lSignal.id);
await writeBigInt(lc.coefs[s]);
if (lSignal.id >= NWires) throw new Error("Signal Coef A: " + coef + " Constraint: " + ctIdx + " id: " + lSignal.id);
buffV.setUint32(o, lSignal.id, true); o+=4;
ctx.F.toRprLE(buff, o, c.a.coefs[coef]); o+=n8;
}
buffV.setUint32(o, idxB.length, true); o+=4;
for (let i=0; i<idxB.length; i++) {
const coef = idxB[i];
let lSignal = ctx.signals[coef];
while (lSignal.e >=0 ) lSignal = ctx.signals[lSignal.e];
if (lSignal.id >= NWires) throw new Error("Signal Coef B: " + coef + " Constraint: " + ctIdx + " id: " + lSignal.id);
buffV.setUint32(o, lSignal.id, true); o+=4;
ctx.F.toRprLE(buff, o, c.b.coefs[coef]); o+=n8;
}
buffV.setUint32(o, idxC.length, true); o+=4;
for (let i=0; i<idxC.length; i++) {
const coef = idxC[i];
let lSignal = ctx.signals[coef];
while (lSignal.e >=0 ) lSignal = ctx.signals[lSignal.e];
if (lSignal.id >= NWires) throw new Error("Signal Coef C: " + coef + " Constraint: " + ctIdx + " id: " + lSignal.id);
buffV.setUint32(o, lSignal.id, true); o+=4;
ctx.F.toRprLE(buff, o, ctx.F.neg(c.c.coefs[coef])); o+=n8;
}
return fd.write(buff);
}
async function writeBigInt(n, pos) {
let o = (typeof pos == "undefined") ? p : pos;
ctx.F.toRprLE(buffBigInt, 0, n);
const s = n.toString(16);
const b = Buffer.from(s.padStart(n8*2, "0"), "hex");
const buff = Buffer.allocUnsafe(b.length);
for (let i=0; i<b.length; i++) buff[i] = b[b.length-1-i];
await fd.write(buffBigInt, pos);
await fd.write(buff, o);
if (typeof(pos) == "undefined") p += n8;
}
}

View File

@@ -1,4 +1,3 @@
const Readable = require("stream").Readable;
module.exports = function streamFromArrayTxt(ma) {
@@ -22,7 +21,7 @@ module.exports = function streamFromArrayTxt(ma) {
function getFirstIdx(ma) {
if (!Array.isArray(ma)) return [];
if (typeof ma.push !== "function" ) return [];
return [0, ...getFirstIdx(ma[0])];
}

View File

@@ -10,6 +10,7 @@ module.exports.fnvHash = fnvHash;
module.exports.sameSizes = sameSizes;
module.exports.isDefined = isDefined;
module.exports.accSizes2Str = accSizes2Str;
module.exports.setUint64 = setUint64;
function ident(text) {
if (typeof text === "string") {
@@ -90,6 +91,14 @@ function accSizes2Str(sizes) {
return `[${sizes[0]/sizes[1]}]`+accSizes2Str(sizes.slice(1));
}
function setUint64(buffV, o, n) {
const sLSB = n >>> 0;
const sMSB = (n - sLSB) / 0x100000000;
buffV.setUint32(o, sLSB , true);
buffV.setUint32(o+4, sMSB , true);
}

View File

@@ -46,7 +46,7 @@ async function doTest(tester, circuit, testVectors) {
describe("basic cases", function () {
this.timeout(100000);
for (let i=0; i<basicCases.length; i++) {
for (let i=0; i< basicCases.length; i++) {
it("c/c++ " + basicCases[i].name, async () => {
await doTest(c_tester, basicCases[i].circuit, basicCases[i].tv);
});

View File

@@ -14,6 +14,17 @@
}]
]
},
{
"name": "fnarray",
"circuit": "fnarray.circom",
"tv": [
[{
"in": [1, 8, 25]
}, {
"out": [2, 16, 50]
}]
]
},
{
"name": "add",
"circuit": "add.circom",

View File

@@ -0,0 +1,21 @@
function calc(h) {
var res[3];
for (var i=0; i<3; i++) res[i] = h[i]*2;
return res;
}
template Test() {
signal input in[3];
signal output out[3];
var cout[3] = calc(in);
for (var i=0; i<3; i++) out[i] <-- cout[i];
for (var i=0; i<3; i++) out[i] === in[i]*2;
}
component main = Test();