mirror of
https://github.com/arnaucube/circom.git
synced 2026-02-07 11:16:42 +01:00
Compare commits
68 Commits
feature/c-
...
v0.5.30
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9bf1354bf1 | ||
|
|
ed4c4b4de0 | ||
|
|
a1f3f714ea | ||
|
|
dafc9db614 | ||
|
|
6e4a192c6a | ||
|
|
e1286c29c7 | ||
|
|
a002bcbc25 | ||
|
|
f9f1d0c13e | ||
|
|
fc01aad8b6 | ||
|
|
3d5aa14cdc | ||
|
|
5dc54bb7d2 | ||
|
|
349a39dc95 | ||
|
|
0a2aee9932 | ||
|
|
bad8fad3d0 | ||
|
|
0a707648fc | ||
|
|
263dc73906 | ||
|
|
8e730d93a4 | ||
|
|
bbe10438e0 | ||
|
|
c2cef8d80c | ||
|
|
2200408986 | ||
|
|
5f13d37fdc | ||
|
|
3b46b74d4a | ||
|
|
aa2d768465 | ||
|
|
f02ceb2508 | ||
|
|
d014d67032 | ||
|
|
2e1b35a94d | ||
|
|
7cef1be2c3 | ||
|
|
4b631994ca | ||
|
|
7239abcef1 | ||
|
|
633f755e34 | ||
|
|
923b19c414 | ||
|
|
90cc7d5072 | ||
|
|
145d5a21ad | ||
|
|
cbb0b229bc | ||
|
|
1d14e8c603 | ||
|
|
1e2fb12631 | ||
|
|
0e1a1bcc23 | ||
|
|
989987bfc2 | ||
|
|
5f3ef322a7 | ||
|
|
3c8e61b9a4 | ||
|
|
c39423e411 | ||
|
|
06b6c1a49e | ||
|
|
6b712f3587 | ||
|
|
26cad30222 | ||
|
|
f48de61ca9 | ||
|
|
89cea4755c | ||
|
|
9bf6ecc4f3 | ||
|
|
59d591c988 | ||
|
|
9fe8be9828 | ||
|
|
7e24d6f57d | ||
|
|
8655573b34 | ||
|
|
8fc6e3f1c6 | ||
|
|
c32d303d27 | ||
|
|
744d3b241c | ||
|
|
1a5f7d1a2b | ||
|
|
434e7ac498 | ||
|
|
99afb4312e | ||
|
|
67ec7c5d5b | ||
|
|
a76f3b5988 | ||
|
|
bc9d395e70 | ||
|
|
7fc457ac90 | ||
|
|
8c4980c3f9 | ||
|
|
767ca60008 | ||
|
|
f25842f67c | ||
|
|
92399017df | ||
|
|
1463685b11 | ||
|
|
a1ae6e4a44 | ||
|
|
c7c6b799ad |
@@ -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)
|
||||
|
||||
@@ -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**
|
||||
|
||||
|
||||
125
cli.js
125
cli.js
@@ -23,7 +23,9 @@
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const bigInt = require("big-integer");
|
||||
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) {
|
||||
async function run() {
|
||||
let inputFile;
|
||||
if (argv._.length == 0) {
|
||||
inputFile = "circuit.circom";
|
||||
} else if (argv._.length == 1) {
|
||||
} else if (argv._.length == 1) {
|
||||
inputFile = argv._[0];
|
||||
} else {
|
||||
} 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 || bigInt("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) {
|
||||
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) {
|
||||
}
|
||||
if (argv.sym) {
|
||||
options.symWriteStream = fs.createWriteStream(symName);
|
||||
}
|
||||
if (argv.newThreadTemplates) {
|
||||
}
|
||||
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);
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
446
package-lock.json
generated
446
package-lock.json
generated
@@ -1,35 +1,40 @@
|
||||
{
|
||||
"name": "circom",
|
||||
"version": "0.5.5",
|
||||
"version": "0.5.30",
|
||||
"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,12 +208,24 @@
|
||||
"integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII="
|
||||
},
|
||||
"circom_runtime": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/circom_runtime/-/circom_runtime-0.0.3.tgz",
|
||||
"integrity": "sha512-z4ypbs9cTQn7+2FHZNTnccMj6kQCcKT2agYqCrm2kdLBJh9LDoxU1JVu5mSnVuOtgc7BclQ7r0xclG0zP2rxhw==",
|
||||
"version": "0.1.5",
|
||||
"resolved": "https://registry.npmjs.org/circom_runtime/-/circom_runtime-0.1.5.tgz",
|
||||
"integrity": "sha512-BT3d9VCrH/rBRbThDXG731JwezKyskxyE46nACO6Tt/jaorn27LDxFDORdAAjyD0RAoBt+6FpaTp3qlYSx7Pjg==",
|
||||
"requires": {
|
||||
"ffjavascript": "0.2.10",
|
||||
"fnv-plus": "^1.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ffjavascript": {
|
||||
"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",
|
||||
"fnv-plus": "^1.3.1"
|
||||
"wasmcurves": "0.0.5",
|
||||
"worker-threads": "^1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cjson": {
|
||||
@@ -248,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": {
|
||||
@@ -264,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",
|
||||
@@ -352,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",
|
||||
@@ -364,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",
|
||||
@@ -462,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",
|
||||
@@ -481,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": {
|
||||
@@ -504,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
|
||||
}
|
||||
}
|
||||
@@ -564,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": {
|
||||
@@ -581,10 +582,15 @@
|
||||
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
|
||||
"dev": true
|
||||
},
|
||||
"fastfile": {
|
||||
"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",
|
||||
@@ -592,17 +598,30 @@
|
||||
}
|
||||
},
|
||||
"ffjavascript": {
|
||||
"version": "0.0.4",
|
||||
"resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.0.4.tgz",
|
||||
"integrity": "sha512-6eiRvy+YuGCRjH4U8KdJbRel5VBW0zeuUL1FXQ+fFxTp5xv2ClqTfCYf5ClUtq0voGpd9XJAdUCvgIxHDbAQ0Q==",
|
||||
"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": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/ffwasm/-/ffwasm-0.0.6.tgz",
|
||||
"integrity": "sha512-bEBKYANozdyZBCGE6XLg4s/CaJRZdFGQgbthy7EZ4OhNCIpycgklS5mlf88Bw4fXSddlU1V9iYXI4JwfGO3BhQ==",
|
||||
"version": "0.0.7",
|
||||
"resolved": "https://registry.npmjs.org/ffwasm/-/ffwasm-0.0.7.tgz",
|
||||
"integrity": "sha512-17cTLzv7HHAKqZbX8MvHxjSrR0yDdn1sh4TVsTbAvO9e6klhFicnyoVXc/sCuViV/M8g65sCmVrAmoPCZp1YkQ==",
|
||||
"requires": {
|
||||
"big-integer": "^1.6.48",
|
||||
"wasmbuilder": "0.0.10"
|
||||
@@ -626,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",
|
||||
@@ -658,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": {
|
||||
@@ -723,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",
|
||||
@@ -772,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",
|
||||
@@ -839,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",
|
||||
@@ -892,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",
|
||||
@@ -948,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": {
|
||||
@@ -974,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"
|
||||
@@ -1025,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"
|
||||
@@ -1054,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"
|
||||
}
|
||||
@@ -1123,11 +1179,13 @@
|
||||
"dev": true
|
||||
},
|
||||
"r1csfile": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/r1csfile/-/r1csfile-0.0.3.tgz",
|
||||
"integrity": "sha512-TNrodnbHw5yAMv2gj0Ezf22XS3q8zGEjdPHZLBmJauIPFxm6QmyzxlB92yZ5WNkjEtJiS7p1hvkO9/RsJXRDjw==",
|
||||
"version": "0.0.16",
|
||||
"resolved": "https://registry.npmjs.org/r1csfile/-/r1csfile-0.0.16.tgz",
|
||||
"integrity": "sha512-A2jRVWzGgmXeG2lVAc0H4suJmzt50it5UvBnycJgBCpMXM3tH/M6RguP7nvs6suY/yYnkN6jX6iTScSiDUF3FA==",
|
||||
"requires": {
|
||||
"big-integer": "^1.6.48"
|
||||
"@iden3/bigarray": "0.0.2",
|
||||
"fastfile": "0.0.18",
|
||||
"ffjavascript": "0.2.22"
|
||||
}
|
||||
},
|
||||
"regexpp": {
|
||||
@@ -1171,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"
|
||||
@@ -1237,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",
|
||||
@@ -1304,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"
|
||||
}
|
||||
@@ -1391,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": {
|
||||
@@ -1440,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": {
|
||||
@@ -1453,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",
|
||||
@@ -1473,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",
|
||||
@@ -1481,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": {
|
||||
@@ -1503,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",
|
||||
@@ -1517,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"
|
||||
|
||||
14
package.json
14
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "circom",
|
||||
"version": "0.5.5",
|
||||
"version": "0.5.30",
|
||||
"description": "Language to generate logic circuits",
|
||||
"main": "index.js",
|
||||
"directories": {
|
||||
@@ -29,14 +29,14 @@
|
||||
"url": "https://github.com/iden3/circom.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"big-integer": "^1.6.32",
|
||||
"chai": "^4.2.0",
|
||||
"circom_runtime": "0.0.3",
|
||||
"ffiasm": "0.0.2",
|
||||
"ffjavascript": "0.0.4",
|
||||
"ffwasm": "0.0.6",
|
||||
"circom_runtime": "0.1.5",
|
||||
"fastfile": "0.0.18",
|
||||
"ffiasm": "0.1.1",
|
||||
"ffjavascript": "0.2.22",
|
||||
"ffwasm": "0.0.7",
|
||||
"fnv-plus": "^1.3.1",
|
||||
"r1csfile": "0.0.3",
|
||||
"r1csfile": "0.0.16",
|
||||
"tmp-promise": "^2.0.2",
|
||||
"wasmbuilder": "0.0.10"
|
||||
},
|
||||
|
||||
114
parser/jaz.jison
114
parser/jaz.jison
@@ -132,10 +132,8 @@ include { return 'include'; }
|
||||
|
||||
|
||||
%{
|
||||
const bigInt = require('big-integer');
|
||||
const Scalar = require('ffjavascript').Scalar;
|
||||
const util = require('util');
|
||||
const __P__ = new bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
||||
const __MASK__ = new bigInt(2).pow(253).minus(1);
|
||||
|
||||
function setLines(dst, first, last) {
|
||||
last = last || first;
|
||||
@@ -266,20 +264,12 @@ identifierList
|
||||
ifStatment
|
||||
: 'if' '(' expression ')' statment 'else' statment
|
||||
{
|
||||
if ($3.type == "NUMBER") {
|
||||
$$ = !$3.value.eq(0) ? $5 : $7;
|
||||
} else {
|
||||
$$ = { type: "IF", condition: $3, then: $5, else: $7 };
|
||||
}
|
||||
setLines($$, @1, @7);
|
||||
}
|
||||
| 'if' '(' expression ')' statment
|
||||
{
|
||||
if ($3.type == "NUMBER") {
|
||||
$$ = !$3.value.eq(0) ? $5 : { type: "NUMBER", value: bigInt(0) };
|
||||
} else {
|
||||
$$ = { type: "IF", condition: $3, then: $5 };
|
||||
}
|
||||
setLines($$, @1, @5);
|
||||
}
|
||||
;
|
||||
@@ -451,11 +441,7 @@ e17
|
||||
}
|
||||
| e17 '?' e17 ':' e17 %prec TERCOND
|
||||
{
|
||||
if ($1.type == "NUMBER") {
|
||||
$$ = !$1.value.eq(0) ? $3 : $5;
|
||||
} else {
|
||||
$$ = { type: "OP", op: "?", values: [$1, $3, $5] };
|
||||
}
|
||||
setLines($$, @1, @5);
|
||||
}
|
||||
| e16 %prec EMPTY
|
||||
@@ -478,11 +464,7 @@ e16
|
||||
e15
|
||||
: e15 '||' e14
|
||||
{
|
||||
if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
|
||||
$$ = { type: "NUMBER", value: !$1.value.eq(0) || !$3.value.eq(0) ? bigInt(1) : bigInt(0) };
|
||||
} else {
|
||||
$$ = { type: "OP", op: "||", values: [$1, $3] };
|
||||
}
|
||||
setLines($$, @1, @3);
|
||||
}
|
||||
| e14 %prec EMPTY
|
||||
@@ -494,11 +476,7 @@ e15
|
||||
e14
|
||||
: e14 '&&' e13
|
||||
{
|
||||
if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
|
||||
$$ = { type: "NUMBER", value: !$1.value.eq(0) && !$3.value.eq(0) ? bigInt(1) : bigInt(0) };
|
||||
} else {
|
||||
$$ = { type: "OP", op: "&&", values: [$1, $3] };
|
||||
}
|
||||
setLines($$, @1, @3);
|
||||
}
|
||||
| e13 %prec EMPTY
|
||||
@@ -510,11 +488,7 @@ e14
|
||||
e13
|
||||
: e13 '|' e12
|
||||
{
|
||||
if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
|
||||
$$ = { type: "NUMBER", value: $1.value.or($3.value).and(__MASK__) };
|
||||
} else {
|
||||
$$ = { type: "OP", op: "|", values: [$1, $3] };
|
||||
}
|
||||
setLines($$, @1, @3);
|
||||
}
|
||||
| e12 %prec EMPTY
|
||||
@@ -527,11 +501,7 @@ e13
|
||||
e12
|
||||
: e12 '^' e11
|
||||
{
|
||||
if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
|
||||
$$ = { type: "NUMBER", value: $1.value.xor($3.value).and(__MASK__) };
|
||||
} else {
|
||||
$$ = { type: "OP", op: "^", values: [$1, $3] };
|
||||
}
|
||||
setLines($$, @1, @3);
|
||||
}
|
||||
| e11 %prec EMPTY
|
||||
@@ -543,11 +513,7 @@ e12
|
||||
e11
|
||||
: e11 '&' e10
|
||||
{
|
||||
if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
|
||||
$$ = { type: "NUMBER", value: $1.value.and($3.value).and(__MASK__) };
|
||||
} else {
|
||||
$$ = { type: "OP", op: "&", values: [$1, $3] };
|
||||
}
|
||||
setLines($$, @1, @3);
|
||||
}
|
||||
| e10 %prec EMPTY
|
||||
@@ -562,20 +528,12 @@ e11
|
||||
e10
|
||||
: e10 '==' e9
|
||||
{
|
||||
if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
|
||||
$$ = { type: "NUMBER", value: $1.value.equals($3.value) ? bigInt(1) : bigInt(0) };
|
||||
} else {
|
||||
$$ = { type: "OP", op: "==", values: [$1, $3] };
|
||||
}
|
||||
setLines($$, @1, @3);
|
||||
}
|
||||
| e10 '!=' e9
|
||||
{
|
||||
if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
|
||||
$$ = { type: "NUMBER", value: $1.value.eq($3.value) ? bigInt(0) : bigInt(1) };
|
||||
} else {
|
||||
$$ = { type: "OP", op: "!=", values: [$1, $3] };
|
||||
}
|
||||
setLines($$, @1, @3);
|
||||
}
|
||||
| e9 %prec EMPTY
|
||||
@@ -587,38 +545,22 @@ e10
|
||||
e9
|
||||
: e9 '<=' e7
|
||||
{
|
||||
if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
|
||||
$$ = { type: "NUMBER", value: $1.value.lesserOrEquals($3.value) ? bigInt(1) : bigInt(0) };
|
||||
} else {
|
||||
$$ = { type: "OP", op: "<=", values: [$1, $3] };
|
||||
}
|
||||
setLines($$, @1, @3);
|
||||
}
|
||||
| e9 '>=' e7
|
||||
{
|
||||
if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
|
||||
$$ = { type: "NUMBER", value: $1.value.greaterOrEquals($3.value) ? bigInt(1) : bigInt(0) };
|
||||
} else {
|
||||
$$ = { type: "OP", op: ">=", values: [$1, $3] };
|
||||
}
|
||||
setLines($$, @1, @3);
|
||||
}
|
||||
| e9 '<' e7
|
||||
{
|
||||
if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
|
||||
$$ = { type: "NUMBER", value: $1.value.lesser($3.value) ? bigInt(1) : bigInt(0) };
|
||||
} else {
|
||||
$$ = { type: "OP", op: "<", values: [$1, $3] };
|
||||
}
|
||||
setLines($$, @1, @3);
|
||||
}
|
||||
| e9 '>' e7
|
||||
{
|
||||
if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
|
||||
$$ = { type: "NUMBER", value: $1.value.greater($3.value) ? bigInt(1) : bigInt(0) };
|
||||
} else {
|
||||
$$ = { type: "OP", op: ">", values: [$1, $3] };
|
||||
}
|
||||
setLines($$, @1, @3);
|
||||
}
|
||||
| e7 %prec EMPTY
|
||||
@@ -630,22 +572,12 @@ e9
|
||||
e7
|
||||
: e7 '<<' e6
|
||||
{
|
||||
if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
|
||||
let v = $3.value.greater(256) ? 256 : $3.value.value;
|
||||
$$ = { type: "NUMBER", value: $1.value.shiftLeft(v).and(__MASK__) };
|
||||
} else {
|
||||
$$ = { type: "OP", op: "<<", values: [$1, $3] };
|
||||
}
|
||||
setLines($$, @1, @3);
|
||||
}
|
||||
| e7 '>>' e6
|
||||
{
|
||||
if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
|
||||
let v = $3.value.greater(256) ? 256 : $3.value.value;
|
||||
$$ = {type: "NUMBER", value: $1.value.shiftRight(v).and(__MASK__) };
|
||||
} else {
|
||||
$$ = { type: "OP", op: ">>", values: [$1, $3] };
|
||||
}
|
||||
setLines($$, @1, @3);
|
||||
}
|
||||
| e6 %prec EMPTY
|
||||
@@ -657,20 +589,12 @@ e7
|
||||
e6
|
||||
: e6 '+' e5
|
||||
{
|
||||
if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
|
||||
$$ = { type: "NUMBER", value: ($1.value.plus($3.value)).mod(__P__) };
|
||||
} else {
|
||||
$$ = { type: "OP", op: "+", values: [$1, $3] };
|
||||
}
|
||||
setLines($$, @1, @3);
|
||||
}
|
||||
| e6 '-' e5
|
||||
{
|
||||
if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
|
||||
$$ = { type: "NUMBER", value: ($1.value.plus(__P__).minus($3.value)).mod(__P__) };
|
||||
} else {
|
||||
$$ = { type: "OP", op: "-", values: [$1, $3] };
|
||||
}
|
||||
setLines($$, @1, @3);
|
||||
}
|
||||
| e5 %prec EMPTY
|
||||
@@ -683,38 +607,22 @@ e6
|
||||
e5
|
||||
: e5 '*' e4
|
||||
{
|
||||
if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
|
||||
$$ = { type: "NUMBER", value: ($1.value.times($3.value)).mod(__P__) };
|
||||
} else {
|
||||
$$ = { type: "OP", op: "*", values: [$1, $3] };
|
||||
}
|
||||
setLines($$, @1, @3);
|
||||
}
|
||||
| e5 '/' e4
|
||||
{
|
||||
if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
|
||||
$$ = { type: "NUMBER", value: ($1.value.times($3.value.modInv(__P__))).mod(__P__) };
|
||||
} else {
|
||||
$$ = { type: "OP", op: "/", values: [$1, $3] };
|
||||
}
|
||||
setLines($$, @1, @3);
|
||||
}
|
||||
| e5 '\\' e4
|
||||
{
|
||||
if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
|
||||
$$ = { type: "NUMBER", value: ($1.value.divide($3.value)) };
|
||||
} else {
|
||||
$$ = { type: "OP", op: "\\", values: [$1, $3] };
|
||||
}
|
||||
setLines($$, @1, @3);
|
||||
}
|
||||
| e5 '%' e4
|
||||
{
|
||||
if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
|
||||
$$ = { type: "NUMBER", value: $1.value.mod($3.value) };
|
||||
} else {
|
||||
$$ = { type: "OP", op: "%", values: [$1, $3] };
|
||||
}
|
||||
setLines($$, @1, @3);
|
||||
}
|
||||
| e4 %prec EMPTY
|
||||
@@ -726,11 +634,7 @@ e5
|
||||
e4
|
||||
: e4 '**' e3
|
||||
{
|
||||
if (($1.type == "NUMBER") && ($3.type == "NUMBER")) {
|
||||
$$ = { type: "NUMBER", value: $1.value.modPow($3.value, __P__) };
|
||||
} else {
|
||||
$$ = { type: "OP", op: "**", values: [$1, $3] };
|
||||
}
|
||||
setLines($$, @1, @3);
|
||||
}
|
||||
| e3 %prec EMPTY
|
||||
@@ -758,29 +662,17 @@ e3
|
||||
}
|
||||
| '-' e3 %prec UMINUS
|
||||
{
|
||||
if ($2.type == "NUMBER") {
|
||||
$$ = { type: "NUMBER", value: __P__.minus($2.value).mod(__P__) };
|
||||
} else {
|
||||
$$ = { type: "OP", op: "UMINUS", values: [$2] };
|
||||
}
|
||||
setLines($$, @1, @2);
|
||||
}
|
||||
| '!' e3
|
||||
{
|
||||
if ($2.type == "NUMBER") {
|
||||
$$ = { type: "NUMBER", value: $2.value.eq(0) ? bigInt(1) : bigInt(0) };
|
||||
} else {
|
||||
$$ = { type: "OP", op: "!", values: [$2] };
|
||||
}
|
||||
setLines($$, @1, @2);
|
||||
}
|
||||
| '~' e3
|
||||
{
|
||||
if ($2.type == "NUMBER") {
|
||||
$$ = { type: "NUMBER", value: $2.value.xor(__MASK__) };
|
||||
} else {
|
||||
$$ = { type: "OP", op: "~", values: [$2] };
|
||||
}
|
||||
setLines($$, @1, @2);
|
||||
}
|
||||
| e2 %prec EMPTY
|
||||
@@ -817,12 +709,12 @@ e0
|
||||
}
|
||||
| DECNUMBER
|
||||
{
|
||||
$$ = {type: "NUMBER", value: bigInt($1).mod(__P__) }
|
||||
$$ = {type: "NUMBER", value: Scalar.fromString($1) }
|
||||
setLines($$, @1);
|
||||
}
|
||||
| HEXNUMBER
|
||||
{
|
||||
$$ = {type: "NUMBER", value: bigInt($1.substr(2).toUpperCase(), 16).mod(__P__) }
|
||||
$$ = {type: "NUMBER", value: Scalar.fromString($1.substr(2).toUpperCase(), 16) }
|
||||
setLines($$, @1);
|
||||
}
|
||||
| '(' expression ')' %prec EMPTY
|
||||
|
||||
116
parser/jaz.js
116
parser/jaz.js
@@ -146,21 +146,13 @@ case 20:
|
||||
break;
|
||||
case 21:
|
||||
|
||||
if ($$[$0-4].type == "NUMBER") {
|
||||
this.$ = !$$[$0-4].value.eq(0) ? $$[$0-2] : $$[$0];
|
||||
} else {
|
||||
this.$ = { type: "IF", condition: $$[$0-4], then: $$[$0-2], else: $$[$0] };
|
||||
}
|
||||
setLines(this.$, _$[$0-6], _$[$0]);
|
||||
|
||||
break;
|
||||
case 22:
|
||||
|
||||
if ($$[$0-2].type == "NUMBER") {
|
||||
this.$ = !$$[$0-2].value.eq(0) ? $$[$0] : { type: "NUMBER", value: bigInt(0) };
|
||||
} else {
|
||||
this.$ = { type: "IF", condition: $$[$0-2], then: $$[$0] };
|
||||
}
|
||||
setLines(this.$, _$[$0-4], _$[$0]);
|
||||
|
||||
break;
|
||||
@@ -321,11 +313,7 @@ case 50:
|
||||
break;
|
||||
case 51:
|
||||
|
||||
if ($$[$0-4].type == "NUMBER") {
|
||||
this.$ = !$$[$0-4].value.eq(0) ? $$[$0-2] : $$[$0];
|
||||
} else {
|
||||
this.$ = { type: "OP", op: "?", values: [$$[$0-4], $$[$0-2], $$[$0]] };
|
||||
}
|
||||
setLines(this.$, _$[$0-4], _$[$0]);
|
||||
|
||||
break;
|
||||
@@ -336,71 +324,43 @@ case 52: case 53: case 54: case 56: case 58: case 60:
|
||||
break;
|
||||
case 55:
|
||||
|
||||
if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) {
|
||||
this.$ = { type: "NUMBER", value: !$$[$0-2].value.eq(0) || !$$[$0].value.eq(0) ? bigInt(1) : bigInt(0) };
|
||||
} else {
|
||||
this.$ = { type: "OP", op: "||", values: [$$[$0-2], $$[$0]] };
|
||||
}
|
||||
setLines(this.$, _$[$0-2], _$[$0]);
|
||||
|
||||
break;
|
||||
case 57:
|
||||
|
||||
if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) {
|
||||
this.$ = { type: "NUMBER", value: !$$[$0-2].value.eq(0) && !$$[$0].value.eq(0) ? bigInt(1) : bigInt(0) };
|
||||
} else {
|
||||
this.$ = { type: "OP", op: "&&", values: [$$[$0-2], $$[$0]] };
|
||||
}
|
||||
setLines(this.$, _$[$0-2], _$[$0]);
|
||||
|
||||
break;
|
||||
case 59:
|
||||
|
||||
if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) {
|
||||
this.$ = { type: "NUMBER", value: $$[$0-2].value.or($$[$0].value).and(__MASK__) };
|
||||
} else {
|
||||
this.$ = { type: "OP", op: "|", values: [$$[$0-2], $$[$0]] };
|
||||
}
|
||||
setLines(this.$, _$[$0-2], _$[$0]);
|
||||
|
||||
break;
|
||||
case 61:
|
||||
|
||||
if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) {
|
||||
this.$ = { type: "NUMBER", value: $$[$0-2].value.xor($$[$0].value).and(__MASK__) };
|
||||
} else {
|
||||
this.$ = { type: "OP", op: "^", values: [$$[$0-2], $$[$0]] };
|
||||
}
|
||||
setLines(this.$, _$[$0-2], _$[$0]);
|
||||
|
||||
break;
|
||||
case 63:
|
||||
|
||||
if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) {
|
||||
this.$ = { type: "NUMBER", value: $$[$0-2].value.and($$[$0].value).and(__MASK__) };
|
||||
} else {
|
||||
this.$ = { type: "OP", op: "&", values: [$$[$0-2], $$[$0]] };
|
||||
}
|
||||
setLines(this.$, _$[$0-2], _$[$0]);
|
||||
|
||||
break;
|
||||
case 65:
|
||||
|
||||
if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) {
|
||||
this.$ = { type: "NUMBER", value: $$[$0-2].value.equals($$[$0].value) ? bigInt(1) : bigInt(0) };
|
||||
} else {
|
||||
this.$ = { type: "OP", op: "==", values: [$$[$0-2], $$[$0]] };
|
||||
}
|
||||
setLines(this.$, _$[$0-2], _$[$0]);
|
||||
|
||||
break;
|
||||
case 66:
|
||||
|
||||
if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) {
|
||||
this.$ = { type: "NUMBER", value: $$[$0-2].value.eq($$[$0].value) ? bigInt(0) : bigInt(1) };
|
||||
} else {
|
||||
this.$ = { type: "OP", op: "!=", values: [$$[$0-2], $$[$0]] };
|
||||
}
|
||||
setLines(this.$, _$[$0-2], _$[$0]);
|
||||
|
||||
break;
|
||||
@@ -411,63 +371,37 @@ case 67: case 72:
|
||||
break;
|
||||
case 68:
|
||||
|
||||
if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) {
|
||||
this.$ = { type: "NUMBER", value: $$[$0-2].value.lesserOrEquals($$[$0].value) ? bigInt(1) : bigInt(0) };
|
||||
} else {
|
||||
this.$ = { type: "OP", op: "<=", values: [$$[$0-2], $$[$0]] };
|
||||
}
|
||||
setLines(this.$, _$[$0-2], _$[$0]);
|
||||
|
||||
break;
|
||||
case 69:
|
||||
|
||||
if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) {
|
||||
this.$ = { type: "NUMBER", value: $$[$0-2].value.greaterOrEquals($$[$0].value) ? bigInt(1) : bigInt(0) };
|
||||
} else {
|
||||
this.$ = { type: "OP", op: ">=", values: [$$[$0-2], $$[$0]] };
|
||||
}
|
||||
setLines(this.$, _$[$0-2], _$[$0]);
|
||||
|
||||
break;
|
||||
case 70:
|
||||
|
||||
if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) {
|
||||
this.$ = { type: "NUMBER", value: $$[$0-2].value.lesser($$[$0].value) ? bigInt(1) : bigInt(0) };
|
||||
} else {
|
||||
this.$ = { type: "OP", op: "<", values: [$$[$0-2], $$[$0]] };
|
||||
}
|
||||
setLines(this.$, _$[$0-2], _$[$0]);
|
||||
|
||||
break;
|
||||
case 71:
|
||||
|
||||
if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) {
|
||||
this.$ = { type: "NUMBER", value: $$[$0-2].value.greater($$[$0].value) ? bigInt(1) : bigInt(0) };
|
||||
} else {
|
||||
this.$ = { type: "OP", op: ">", values: [$$[$0-2], $$[$0]] };
|
||||
}
|
||||
setLines(this.$, _$[$0-2], _$[$0]);
|
||||
|
||||
break;
|
||||
case 73:
|
||||
|
||||
if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) {
|
||||
let v = $$[$0].value.greater(256) ? 256 : $$[$0].value.value;
|
||||
this.$ = { type: "NUMBER", value: $$[$0-2].value.shiftLeft(v).and(__MASK__) };
|
||||
} else {
|
||||
this.$ = { type: "OP", op: "<<", values: [$$[$0-2], $$[$0]] };
|
||||
}
|
||||
setLines(this.$, _$[$0-2], _$[$0]);
|
||||
|
||||
break;
|
||||
case 74:
|
||||
|
||||
if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) {
|
||||
let v = $$[$0].value.greater(256) ? 256 : $$[$0].value.value;
|
||||
this.$ = {type: "NUMBER", value: $$[$0-2].value.shiftRight(v).and(__MASK__) };
|
||||
} else {
|
||||
this.$ = { type: "OP", op: ">>", values: [$$[$0-2], $$[$0]] };
|
||||
}
|
||||
setLines(this.$, _$[$0-2], _$[$0]);
|
||||
|
||||
break;
|
||||
@@ -478,71 +412,43 @@ case 75:
|
||||
break;
|
||||
case 76:
|
||||
|
||||
if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) {
|
||||
this.$ = { type: "NUMBER", value: ($$[$0-2].value.plus($$[$0].value)).mod(__P__) };
|
||||
} else {
|
||||
this.$ = { type: "OP", op: "+", values: [$$[$0-2], $$[$0]] };
|
||||
}
|
||||
setLines(this.$, _$[$0-2], _$[$0]);
|
||||
|
||||
break;
|
||||
case 77:
|
||||
|
||||
if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) {
|
||||
this.$ = { type: "NUMBER", value: ($$[$0-2].value.plus(__P__).minus($$[$0].value)).mod(__P__) };
|
||||
} else {
|
||||
this.$ = { type: "OP", op: "-", values: [$$[$0-2], $$[$0]] };
|
||||
}
|
||||
setLines(this.$, _$[$0-2], _$[$0]);
|
||||
|
||||
break;
|
||||
case 79:
|
||||
|
||||
if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) {
|
||||
this.$ = { type: "NUMBER", value: ($$[$0-2].value.times($$[$0].value)).mod(__P__) };
|
||||
} else {
|
||||
this.$ = { type: "OP", op: "*", values: [$$[$0-2], $$[$0]] };
|
||||
}
|
||||
setLines(this.$, _$[$0-2], _$[$0]);
|
||||
|
||||
break;
|
||||
case 80:
|
||||
|
||||
if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) {
|
||||
this.$ = { type: "NUMBER", value: ($$[$0-2].value.times($$[$0].value.modInv(__P__))).mod(__P__) };
|
||||
} else {
|
||||
this.$ = { type: "OP", op: "/", values: [$$[$0-2], $$[$0]] };
|
||||
}
|
||||
setLines(this.$, _$[$0-2], _$[$0]);
|
||||
|
||||
break;
|
||||
case 81:
|
||||
|
||||
if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) {
|
||||
this.$ = { type: "NUMBER", value: ($$[$0-2].value.divide($$[$0].value)) };
|
||||
} else {
|
||||
this.$ = { type: "OP", op: "\\", values: [$$[$0-2], $$[$0]] };
|
||||
}
|
||||
setLines(this.$, _$[$0-2], _$[$0]);
|
||||
|
||||
break;
|
||||
case 82:
|
||||
|
||||
if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) {
|
||||
this.$ = { type: "NUMBER", value: $$[$0-2].value.mod($$[$0].value) };
|
||||
} else {
|
||||
this.$ = { type: "OP", op: "%", values: [$$[$0-2], $$[$0]] };
|
||||
}
|
||||
setLines(this.$, _$[$0-2], _$[$0]);
|
||||
|
||||
break;
|
||||
case 84:
|
||||
|
||||
if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) {
|
||||
this.$ = { type: "NUMBER", value: $$[$0-2].value.modPow($$[$0].value, __P__) };
|
||||
} else {
|
||||
this.$ = { type: "OP", op: "**", values: [$$[$0-2], $$[$0]] };
|
||||
}
|
||||
setLines(this.$, _$[$0-2], _$[$0]);
|
||||
|
||||
break;
|
||||
@@ -566,31 +472,19 @@ case 88:
|
||||
break;
|
||||
case 89:
|
||||
|
||||
if ($$[$0].type == "NUMBER") {
|
||||
this.$ = { type: "NUMBER", value: __P__.minus($$[$0].value).mod(__P__) };
|
||||
} else {
|
||||
this.$ = { type: "OP", op: "UMINUS", values: [$$[$0]] };
|
||||
}
|
||||
setLines(this.$, _$[$0-1], _$[$0]);
|
||||
|
||||
break;
|
||||
case 90:
|
||||
|
||||
if ($$[$0].type == "NUMBER") {
|
||||
this.$ = { type: "NUMBER", value: $$[$0].value.eq(0) ? bigInt(1) : bigInt(0) };
|
||||
} else {
|
||||
this.$ = { type: "OP", op: "!", values: [$$[$0]] };
|
||||
}
|
||||
setLines(this.$, _$[$0-1], _$[$0]);
|
||||
|
||||
break;
|
||||
case 91:
|
||||
|
||||
if ($$[$0].type == "NUMBER") {
|
||||
this.$ = { type: "NUMBER", value: $$[$0].value.xor(__MASK__) };
|
||||
} else {
|
||||
this.$ = { type: "OP", op: "~", values: [$$[$0]] };
|
||||
}
|
||||
setLines(this.$, _$[$0-1], _$[$0]);
|
||||
|
||||
break;
|
||||
@@ -613,13 +507,13 @@ case 97: case 102: case 103:
|
||||
break;
|
||||
case 98:
|
||||
|
||||
this.$ = {type: "NUMBER", value: bigInt($$[$0]).mod(__P__) }
|
||||
this.$ = {type: "NUMBER", value: Scalar.fromString($$[$0]) }
|
||||
setLines(this.$, _$[$0]);
|
||||
|
||||
break;
|
||||
case 99:
|
||||
|
||||
this.$ = {type: "NUMBER", value: bigInt($$[$0].substr(2).toUpperCase(), 16).mod(__P__) }
|
||||
this.$ = {type: "NUMBER", value: Scalar.fromString($$[$0].substr(2).toUpperCase(), 16) }
|
||||
setLines(this.$, _$[$0]);
|
||||
|
||||
break;
|
||||
@@ -866,10 +760,8 @@ parse: function parse(input) {
|
||||
return true;
|
||||
}};
|
||||
|
||||
const bigInt = require('big-integer');
|
||||
const Scalar = require('ffjavascript').Scalar;
|
||||
const util = require('util');
|
||||
const __P__ = new bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
||||
const __MASK__ = new bigInt(2).pow(253).minus(1);
|
||||
|
||||
function setLines(dst, first, last) {
|
||||
last = last || first;
|
||||
@@ -1365,7 +1257,7 @@ case 77: console.log("INVALID: " + yy_.yytext); return 'INVALID'
|
||||
break;
|
||||
}
|
||||
},
|
||||
rules: [/^(?:\s+)/,/^(?:\/\*([^*]|[\r\n]|(\*+([^*\/]|[\r\n])))*\*+\/)/,/^(?:\/\/.*)/,/^(?:var\b)/,/^(?:signal\b)/,/^(?:private\b)/,/^(?:input\b)/,/^(?:output\b)/,/^(?:linearCombination\b)/,/^(?:component\b)/,/^(?:template\b)/,/^(?:function\b)/,/^(?:if\b)/,/^(?:else\b)/,/^(?:for\b)/,/^(?:while\b)/,/^(?:compute\b)/,/^(?:do\b)/,/^(?:return\b)/,/^(?:include\b)/,/^(?:0x[0-9A-Fa-f]*)/,/^(?:[0-9]+)/,/^(?:[a-zA-Z][a-zA-Z$_0-9]*)/,/^(?:"[^"]+")/,/^(?:==>)/,/^(?:<==)/,/^(?:-->)/,/^(?:<--)/,/^(?:===)/,/^(?:>>=)/,/^(?:<<=)/,/^(?:&&)/,/^(?:\|\|)/,/^(?:==)/,/^(?:<=)/,/^(?:>=)/,/^(?:!=)/,/^(?:>>)/,/^(?:<<)/,/^(?:\*\*)/,/^(?:\+\+)/,/^(?:--)/,/^(?:\+=)/,/^(?:-=)/,/^(?:\*=)/,/^(?:\/=)/,/^(?:%=)/,/^(?:\|=)/,/^(?:&=)/,/^(?:\^=)/,/^(?:=)/,/^(?:\+)/,/^(?:-)/,/^(?:\*)/,/^(?:\/)/,/^(?:\\)/,/^(?:%)/,/^(?:\^)/,/^(?:&)/,/^(?:\|)/,/^(?:!)/,/^(?:~)/,/^(?:<)/,/^(?:>)/,/^(?:!)/,/^(?:\?)/,/^(?::)/,/^(?:\()/,/^(?:\))/,/^(?:\[)/,/^(?:\])/,/^(?:\{)/,/^(?:\})/,/^(?:;)/,/^(?:,)/,/^(?:\.)/,/^(?:$)/,/^(?:.)/],
|
||||
rules: [/^(?:\s+)/,/^(?:\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+\/)/,/^(?:\/\/.*)/,/^(?:var\b)/,/^(?:signal\b)/,/^(?:private\b)/,/^(?:input\b)/,/^(?:output\b)/,/^(?:linearCombination\b)/,/^(?:component\b)/,/^(?:template\b)/,/^(?:function\b)/,/^(?:if\b)/,/^(?:else\b)/,/^(?:for\b)/,/^(?:while\b)/,/^(?:compute\b)/,/^(?:do\b)/,/^(?:return\b)/,/^(?:include\b)/,/^(?:0x[0-9A-Fa-f]*)/,/^(?:[0-9]+)/,/^(?:[a-zA-Z][a-zA-Z$_0-9]*)/,/^(?:"[^"]+")/,/^(?:==>)/,/^(?:<==)/,/^(?:-->)/,/^(?:<--)/,/^(?:===)/,/^(?:>>=)/,/^(?:<<=)/,/^(?:&&)/,/^(?:\|\|)/,/^(?:==)/,/^(?:<=)/,/^(?:>=)/,/^(?:!=)/,/^(?:>>)/,/^(?:<<)/,/^(?:\*\*)/,/^(?:\+\+)/,/^(?:--)/,/^(?:\+=)/,/^(?:-=)/,/^(?:\*=)/,/^(?:\/=)/,/^(?:%=)/,/^(?:\|=)/,/^(?:&=)/,/^(?:\^=)/,/^(?:=)/,/^(?:\+)/,/^(?:-)/,/^(?:\*)/,/^(?:\/)/,/^(?:\\)/,/^(?:%)/,/^(?:\^)/,/^(?:&)/,/^(?:\|)/,/^(?:!)/,/^(?:~)/,/^(?:<)/,/^(?:>)/,/^(?:!)/,/^(?:\?)/,/^(?::)/,/^(?:\()/,/^(?:\))/,/^(?:\[)/,/^(?:\])/,/^(?:\{)/,/^(?:\})/,/^(?:;)/,/^(?:,)/,/^(?:\.)/,/^(?:$)/,/^(?:.)/],
|
||||
conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77],"inclusive":true}}
|
||||
});
|
||||
return lexer;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
const streamFromMultiArray = require("../../src/streamfromarray_txt.js");
|
||||
const bigInt = require("big-integer");
|
||||
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")) {
|
||||
@@ -94,6 +95,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});
|
||||
}
|
||||
@@ -214,6 +219,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)});`);
|
||||
}
|
||||
@@ -340,15 +347,23 @@ class FunctionBuilderC {
|
||||
}
|
||||
|
||||
class BuilderC {
|
||||
constructor() {
|
||||
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) {
|
||||
@@ -360,8 +375,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) {
|
||||
@@ -369,9 +387,9 @@ class BuilderC {
|
||||
}
|
||||
|
||||
addConstant(c) {
|
||||
c = bigInt(c);
|
||||
c = this.F.e(c);
|
||||
const cS = c.toString();
|
||||
if (this.usedConstants[cS]) return this.usedConstants[cS];
|
||||
if (typeof this.usedConstants[cS] != "undefined") return this.usedConstants[cS];
|
||||
this.constants.push(c);
|
||||
this.usedConstants[cS] = this.constants.length - 1;
|
||||
return this.constants.length - 1;
|
||||
@@ -407,8 +425,8 @@ 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}`,
|
||||
@@ -419,207 +437,291 @@ class BuilderC {
|
||||
);
|
||||
}
|
||||
|
||||
_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;
|
||||
const n64 = Math.floor((self.header.P.bitLength() - 1) / 64)+1;
|
||||
const R = bigInt.one.shiftLeft(n64*64);
|
||||
|
||||
code.push("// Constants");
|
||||
code.push(`FrElement _constants[${self.constants.length}] = {`);
|
||||
const frSize = (8 + self.F.n64*8);
|
||||
const buff = new Uint8Array(self.constants.length* frSize);
|
||||
const buffV = new DataView(buff.buffer);
|
||||
|
||||
|
||||
while (fdData.pos % 8) fdData.pos++;
|
||||
this.pConstants = fdData.pos;
|
||||
|
||||
let o = 0;
|
||||
for (let i=0; i<self.constants.length; i++) {
|
||||
code.push((i>0 ? "," : " ") + "{" + number2Code(self.constants[i]) + "}");
|
||||
Fr2Bytes(buffV, o, self.constants[i]);
|
||||
o += frSize;
|
||||
}
|
||||
code.push("};");
|
||||
|
||||
function number2Code(n) {
|
||||
if (n.lt(bigInt("80000000", 16)) ) {
|
||||
return addShortMontgomeryPositive(n);
|
||||
}
|
||||
if (n.geq(self.header.P.minus(bigInt("80000000", 16))) ) {
|
||||
return addShortMontgomeryNegative(n);
|
||||
}
|
||||
return addLongMontgomery(n);
|
||||
await fdData.write(buff);
|
||||
|
||||
|
||||
function addShortMontgomeryPositive(a) {
|
||||
return `${a.toString()}, 0x40000000, { ${getLongString(toMontgomery(a))} }`;
|
||||
function Fr2Bytes(buffV, offset, n) {
|
||||
const minShort = self.F.neg(self.F.e("80000000"));
|
||||
const maxShort = self.F.e("7FFFFFFF", 16);
|
||||
|
||||
if ( (self.F.geq(n, minShort))
|
||||
&&(self.F.leq(n, maxShort)))
|
||||
{
|
||||
if (self.F.geq(n, self.F.zero)) {
|
||||
return shortMontgomeryPositive(n);
|
||||
} else {
|
||||
return shortMontgomeryNegative(n);
|
||||
}
|
||||
}
|
||||
|
||||
return longMontgomery(n);
|
||||
|
||||
|
||||
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 = a.minus(self.header.P);
|
||||
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 r = bigInt(a);
|
||||
let S = "";
|
||||
let i = 0;
|
||||
while (!r.isZero()) {
|
||||
if (S!= "") S = S+",";
|
||||
S += "0x" + r.and(bigInt("FFFFFFFFFFFFFFFF", 16)).toString(16) + "LL";
|
||||
i++;
|
||||
r = r.shiftRight(64);
|
||||
function long(buffV, offset, a) {
|
||||
|
||||
let p = offset;
|
||||
const arr = Scalar.toArray(a, 0x100000000);
|
||||
for (let i=0; i<self.F.n64*2; i++) {
|
||||
const idx = arr.length-1-i;
|
||||
|
||||
if ( idx >=0) {
|
||||
buffV.setUint32(p, arr[idx], true);
|
||||
} else {
|
||||
buffV.setUint32(p, 0, true);
|
||||
}
|
||||
while (i<n64) {
|
||||
if (S!= "") S = S+",";
|
||||
S += "0LL";
|
||||
i++;
|
||||
p+= 4;
|
||||
}
|
||||
return S;
|
||||
}
|
||||
|
||||
function toMontgomery(a) {
|
||||
return a.times(R).mod(self.header.P);
|
||||
return self.F.mul(a, self.F.R);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_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);
|
||||
}
|
||||
|
||||
_buildWit2Sig(code) {
|
||||
code.push("// Witness to Signal Table");
|
||||
code.push(`int _wit2sig[${this.wit2sig.length}] = {`);
|
||||
let line = "";
|
||||
await fdData.write(buff);
|
||||
}
|
||||
|
||||
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 (line != "") code.push(" "+line);
|
||||
code.push("};");
|
||||
if ((this.verbose)&&(i%1000000 ==0)) console.log(`_buildWit2Sig ${i}/${this.wit2sig.length}`);
|
||||
|
||||
buffV.setUint32(4*i, this.wit2sig[i], true);
|
||||
}
|
||||
|
||||
_buildCircuitVar(code) {
|
||||
await fdData.write(buff);
|
||||
}
|
||||
|
||||
code.push(
|
||||
"// Circuit Variable",
|
||||
"Circom_Circuit _circuit = {" ,
|
||||
" NSignals,",
|
||||
" NComponents,",
|
||||
" NInputs,",
|
||||
" NOutputs,",
|
||||
" NVars,",
|
||||
" _wit2sig,",
|
||||
" _components,",
|
||||
" _mapIsInput,",
|
||||
" _constants,",
|
||||
" __P__",
|
||||
"};"
|
||||
);
|
||||
async _buildCircuitVar(fdData) {
|
||||
|
||||
const buff = new Uint8Array(72);
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
build() {
|
||||
const code=[];
|
||||
async build(fdCode, fdData) {
|
||||
const encoder = new TextEncoder("utf-8");
|
||||
fdData.pos = 72;
|
||||
while (fdData.pos % 8) fdData.pos++;
|
||||
|
||||
const code=new BigArray();
|
||||
this._buildHeader(code);
|
||||
this._buildSizes(code);
|
||||
this._buildConstants(code);
|
||||
this._buildHashMaps(code);
|
||||
this._buildComponentEntriesTables(code);
|
||||
await this._buildPrimeStr(fdData);
|
||||
await this._buildSizes(fdData);
|
||||
await this._buildConstants(fdData);
|
||||
await this._buildHashMaps(fdData);
|
||||
await this._buildComponentEntriesTables(fdData);
|
||||
this._buildFunctions(code);
|
||||
this._buildComponents(code);
|
||||
this._buildMapIsInput(code);
|
||||
this._buildWit2Sig(code);
|
||||
this._buildCircuitVar(code);
|
||||
return streamFromMultiArray(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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,11 +8,14 @@ const compiler = require("../../src/compiler");
|
||||
const util = require("util");
|
||||
const exec = util.promisify(require("child_process").exec);
|
||||
|
||||
const bigInt = require("big-integer");
|
||||
const Scalar = require("ffjavascript").Scalar;
|
||||
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;
|
||||
|
||||
module.exports = c_tester;
|
||||
|
||||
@@ -27,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 || bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
||||
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 = "";
|
||||
|
||||
@@ -57,11 +64,11 @@ async function c_tester(circomFile, _options) {
|
||||
|
||||
const cdir = path.join(path.dirname(require.resolve("circom_runtime")), "c");
|
||||
|
||||
await exec("g++" + ` ${pThread}`
|
||||
await exec("g++" + ` ${pThread}` +
|
||||
` ${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)}` +
|
||||
@@ -87,7 +94,7 @@ class CTester {
|
||||
async calculateWitness(input) {
|
||||
await fs.promises.writeFile(
|
||||
path.join(this.dir.path, "in.json"),
|
||||
JSON.stringify(utils.stringifyBigInts(input), null, 1)
|
||||
JSON.stringify(stringifyBigInts(input), null, 1)
|
||||
);
|
||||
const r = await exec(`${path.join(this.dir.path, this.baseName)}` +
|
||||
` ${path.join(this.dir.path, "in.json")}` +
|
||||
@@ -100,7 +107,7 @@ class CTester {
|
||||
path.join(this.dir.path, "out.json")
|
||||
);
|
||||
|
||||
const res = utils.unstringifyBigInts(JSON.parse(resStr));
|
||||
const res = unstringifyBigInts(JSON.parse(resStr));
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -127,7 +134,7 @@ class CTester {
|
||||
const self = this;
|
||||
if (this.constraints) return;
|
||||
const r1cs = await loadR1cs(path.join(this.dir.path, this.baseName + ".r1cs"),true, false);
|
||||
self.field = new ZqField(r1cs.prime);
|
||||
self.F = new ZqField(r1cs.prime);
|
||||
self.nVars = r1cs.nVars;
|
||||
self.constraints = r1cs.constraints;
|
||||
}
|
||||
@@ -152,8 +159,8 @@ class CTester {
|
||||
if (typeof self.symbols[prefix] == "undefined") {
|
||||
assert(false, "Output variable not defined: "+ prefix);
|
||||
}
|
||||
const ba = bigInt(actualOut[self.symbols[prefix].varIdx]).toString();
|
||||
const be = bigInt(eOut).toString();
|
||||
const ba = actualOut[self.symbols[prefix].varIdx].toString();
|
||||
const be = eOut.toString();
|
||||
assert.strictEqual(ba, be, prefix);
|
||||
}
|
||||
}
|
||||
@@ -183,7 +190,7 @@ class CTester {
|
||||
}
|
||||
|
||||
function checkConstraint(constraint) {
|
||||
const F = self.field;
|
||||
const F = self.F;
|
||||
const a = evalLC(constraint[0]);
|
||||
const b = evalLC(constraint[1]);
|
||||
const c = evalLC(constraint[2]);
|
||||
@@ -192,7 +199,7 @@ class CTester {
|
||||
}
|
||||
|
||||
function evalLC(lc) {
|
||||
const F = self.field;
|
||||
const F = self.F;
|
||||
let v = F.zero;
|
||||
for (let w in lc) {
|
||||
v = F.add(
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
)
|
||||
@@ -473,7 +473,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 +619,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");
|
||||
@@ -728,12 +757,9 @@ module.exports = function buildRuntime(module, builder) {
|
||||
|
||||
c.setLocal(
|
||||
"pSrc",
|
||||
c.i32_add(
|
||||
c.i32_const(builder.pSignals),
|
||||
c.i32_mul(
|
||||
c.call(
|
||||
"getPWitness",
|
||||
c.getLocal("i"),
|
||||
c.i32_const(builder.sizeFr)
|
||||
)
|
||||
)
|
||||
),
|
||||
|
||||
@@ -745,7 +771,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 +796,7 @@ module.exports = function buildRuntime(module, builder) {
|
||||
c.br(0)
|
||||
)),
|
||||
|
||||
c.i32_const(builder.pSignals)
|
||||
c.i32_const(builder.pOutput)
|
||||
);
|
||||
|
||||
}
|
||||
@@ -804,6 +830,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);
|
||||
|
||||
@@ -825,6 +852,7 @@ module.exports = function buildRuntime(module, builder) {
|
||||
buildComponentFinished();
|
||||
|
||||
buildCheckConstraint();
|
||||
buildCheckAssert();
|
||||
|
||||
buildGetNVars();
|
||||
buildGetFrLen();
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
const streamFromArrayTxt = require("../../src/streamfromarray_txt");
|
||||
const streamFromArrayBin = require("../../src/streamfromarray_bin");
|
||||
const bigInt = require("big-integer");
|
||||
const assert = require("assert");
|
||||
const ModuleBuilder = require("wasmbuilder").ModuleBuilder;
|
||||
const ModuleBuilderWat = require("wasmbuilder").ModuleBuilderWat;
|
||||
const buildRuntime = require("./build_runtime");
|
||||
const Scalar = require("ffjavascript").Scalar;
|
||||
const F1Field = require("ffjavascript").F1Field;
|
||||
|
||||
|
||||
const errs = require("./errs");
|
||||
@@ -99,6 +98,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);
|
||||
@@ -333,6 +335,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(
|
||||
@@ -689,7 +700,8 @@ class FunctionBuilderWasm {
|
||||
}
|
||||
|
||||
class BuilderWasm {
|
||||
constructor() {
|
||||
constructor(p) {
|
||||
this.F = new F1Field(p);
|
||||
this.hashMaps={};
|
||||
this.componentEntriesTables={};
|
||||
this.sizes ={};
|
||||
@@ -701,8 +713,8 @@ class BuilderWasm {
|
||||
this.TYPE_SIGNAL = 1;
|
||||
this.TYPE_COMPONENT = 2;
|
||||
|
||||
this.addConstant(bigInt(0)); // constants[0] = 0;
|
||||
this.addConstant(bigInt(1)); // constants[1] = 1;
|
||||
this.addConstant(Scalar.fromString("0")); // constants[0] = 0;
|
||||
this.addConstant(Scalar.fromString("1")); // constants[1] = 1;
|
||||
|
||||
this.offsetComponentNInputSignals = 12;
|
||||
this.sizeofComponent = 20;
|
||||
@@ -710,7 +722,8 @@ class BuilderWasm {
|
||||
|
||||
setHeader(header) {
|
||||
this.header=header;
|
||||
this.n64 = Math.floor((this.header.P.bitLength() - 1) / 64)+1;
|
||||
|
||||
this.n64 = Math.floor((Scalar.bitLength(this.header.P) - 1) / 64)+1;
|
||||
this.sizeFr = this.n64*8 + 8;
|
||||
}
|
||||
|
||||
@@ -728,9 +741,9 @@ class BuilderWasm {
|
||||
}
|
||||
|
||||
addConstant(c) {
|
||||
c = bigInt(c);
|
||||
c = this.F.e(c);
|
||||
const cS = c.toString();
|
||||
if (this.usedConstants[cS]) return this.usedConstants[cS];
|
||||
if (typeof this.usedConstants[cS] != "undefined") return this.usedConstants[cS];
|
||||
this.constants.push(c);
|
||||
this.usedConstants[cS] = this.constants.length - 1;
|
||||
return this.constants.length - 1;
|
||||
@@ -842,7 +855,6 @@ class BuilderWasm {
|
||||
|
||||
_buildConstants(module) {
|
||||
const self = this;
|
||||
const R = bigInt.one.shiftLeft(this.n64*64);
|
||||
|
||||
const bytes = [];
|
||||
for (let i=0; i<self.constants.length; i++) {
|
||||
@@ -852,19 +864,27 @@ class BuilderWasm {
|
||||
const fBytes = [].concat(...bytes);
|
||||
this.pConstants = module.alloc(fBytes);
|
||||
|
||||
|
||||
function Fr2Bytes(n) {
|
||||
if (n.lt(bigInt("80000000", 16)) ) {
|
||||
const minShort = self.F.neg(self.F.e("80000000"));
|
||||
const maxShort = self.F.e("7FFFFFFF", 16);
|
||||
|
||||
if ( (self.F.geq(n, minShort))
|
||||
&&(self.F.leq(n, maxShort)))
|
||||
{
|
||||
if (self.F.geq(n, self.F.zero)) {
|
||||
return shortMontgomeryPositive(n);
|
||||
}
|
||||
if (n.geq(self.header.P.minus(bigInt("80000000", 16))) ) {
|
||||
} else {
|
||||
return shortMontgomeryNegative(n);
|
||||
}
|
||||
}
|
||||
|
||||
return longMontgomery(n);
|
||||
|
||||
|
||||
function shortMontgomeryPositive(a) {
|
||||
return [
|
||||
...intToBytes32(parseInt(a)),
|
||||
...intToBytes32(Scalar.toNumber(a)),
|
||||
...intToBytes32(0x40000000),
|
||||
...long(toMontgomery(a))
|
||||
];
|
||||
@@ -872,9 +892,9 @@ class BuilderWasm {
|
||||
|
||||
|
||||
function shortMontgomeryNegative(a) {
|
||||
const b = a.minus(self.header.P);
|
||||
const b = -Scalar.toNumber(self.F.neg(a));
|
||||
return [
|
||||
...intToBytes32(parseInt(b)),
|
||||
...intToBytes32(b),
|
||||
...intToBytes32(0x40000000),
|
||||
...long(toMontgomery(a))
|
||||
];
|
||||
@@ -889,27 +909,24 @@ class BuilderWasm {
|
||||
}
|
||||
|
||||
function long(a) {
|
||||
|
||||
const bytes = [];
|
||||
let r = bigInt(a);
|
||||
let S = "";
|
||||
let i = 0;
|
||||
while (!r.isZero()) {
|
||||
S = ("0000000000000000" + r.and(bigInt("FFFFFFFFFFFFFFFF", 16)).toString(16)).substr(-16);
|
||||
bytes.push(hexToBytesR(S));
|
||||
i++;
|
||||
r = r.shiftRight(64);
|
||||
const arr = Scalar.toArray(a, 0x100000000);
|
||||
for (let i=0; i<self.F.n64*2; i++) {
|
||||
const idx = arr.length-1-i;
|
||||
|
||||
if ( idx >=0) {
|
||||
bytes.push(...intToBytes32(arr[idx]));
|
||||
} else {
|
||||
bytes.push(...intToBytes32(0));
|
||||
}
|
||||
while (i<self.n64) {
|
||||
bytes.push(hexToBytesR("0000000000000000"));
|
||||
i++;
|
||||
}
|
||||
|
||||
const fBytes = [].concat(...bytes);
|
||||
return fBytes;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function toMontgomery(a) {
|
||||
return a.times(R).mod(self.header.P);
|
||||
return self.F.mul(a, self.F.R);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -923,41 +940,41 @@ class BuilderWasm {
|
||||
}
|
||||
|
||||
_buildComponents(module) {
|
||||
const bytes = [];
|
||||
const bytes = new Array(this.components.length*5*4);
|
||||
bytes.length=0;
|
||||
for (let i=0; i<this.components.length; i++) {
|
||||
const c = this.components[i];
|
||||
|
||||
bytes.push(intToBytes32(this.hashMaps[c.hashMapName].pointer));
|
||||
bytes.push(intToBytes32(this.componentEntriesTables[c.entryTableName].pointer));
|
||||
bytes.push(intToBytes32(i));
|
||||
bytes.push(intToBytes32(c.nInSignals));
|
||||
bytes.push(intToBytes32(c.newThread ? 1 : 0));
|
||||
bytes.push(...intToBytes32(this.hashMaps[c.hashMapName].pointer));
|
||||
bytes.push(...intToBytes32(this.componentEntriesTables[c.entryTableName].pointer));
|
||||
bytes.push(...intToBytes32(i));
|
||||
bytes.push(...intToBytes32(c.nInSignals));
|
||||
bytes.push(...intToBytes32(c.newThread ? 1 : 0));
|
||||
|
||||
module.addFunctionToTable(c.functionName);
|
||||
}
|
||||
|
||||
const fBytes = [].concat(...bytes);
|
||||
this.pComponents = module.alloc(fBytes);
|
||||
this.pComponents = module.alloc(bytes);
|
||||
}
|
||||
|
||||
_buildMapIsInput(module) {
|
||||
const bytes = [];
|
||||
const bytes = new Array(this.mapIsInput.length*4);
|
||||
bytes.length=0;
|
||||
for (let i=0; i<this.mapIsInput.length; i++) {
|
||||
bytes.push(intToBytes32(this.mapIsInput[i]));
|
||||
bytes.push(...intToBytes32(this.mapIsInput[i]));
|
||||
}
|
||||
|
||||
const fBytes = [].concat(...bytes);
|
||||
this.pMapIsInput = module.alloc(fBytes);
|
||||
this.pMapIsInput = module.alloc(bytes);
|
||||
}
|
||||
|
||||
_buildWit2Sig(module) {
|
||||
const bytes = [];
|
||||
const bytes = new Array(this.wit2sig.length*4);
|
||||
bytes.length =0;
|
||||
for (let i=0; i<this.wit2sig.length; i++) {
|
||||
bytes.push(intToBytes32(this.wit2sig[i]));
|
||||
bytes.push(...intToBytes32(this.wit2sig[i]));
|
||||
}
|
||||
|
||||
const fBytes = [].concat(...bytes);
|
||||
this.pWit2sig = module.alloc(fBytes);
|
||||
this.pWit2sig = module.alloc(bytes);
|
||||
}
|
||||
|
||||
_buildCircuitVar(module) {
|
||||
@@ -983,7 +1000,8 @@ class BuilderWasm {
|
||||
}
|
||||
|
||||
|
||||
build(outType) {
|
||||
async build(fd, outType) {
|
||||
const encoder = new TextEncoder("utf-8");
|
||||
let module;
|
||||
if (outType == "wasm") {
|
||||
module=new ModuleBuilder();
|
||||
@@ -1010,12 +1028,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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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"},
|
||||
};
|
||||
|
||||
@@ -6,10 +6,10 @@ var tmp = require("tmp-promise");
|
||||
const path = require("path");
|
||||
const compiler = require("../../src/compiler");
|
||||
|
||||
const bigInt = require("big-integer");
|
||||
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;
|
||||
|
||||
@@ -25,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"));
|
||||
|
||||
@@ -82,7 +80,7 @@ class WasmTester {
|
||||
const self = this;
|
||||
if (this.constraints) return;
|
||||
const r1cs = await loadR1cs(path.join(this.dir.path, this.baseName + ".r1cs"),true, false);
|
||||
self.field = new ZqField(r1cs.prime);
|
||||
self.F = new ZqField(r1cs.prime);
|
||||
self.nVars = r1cs.nVars;
|
||||
self.constraints = r1cs.constraints;
|
||||
}
|
||||
@@ -107,8 +105,8 @@ class WasmTester {
|
||||
if (typeof self.symbols[prefix] == "undefined") {
|
||||
assert(false, "Output variable not defined: "+ prefix);
|
||||
}
|
||||
const ba = bigInt(actualOut[self.symbols[prefix].varIdx]).toString();
|
||||
const be = bigInt(eOut).toString();
|
||||
const ba = actualOut[self.symbols[prefix].varIdx].toString();
|
||||
const be = eOut.toString();
|
||||
assert.strictEqual(ba, be, prefix);
|
||||
}
|
||||
}
|
||||
@@ -138,16 +136,16 @@ class WasmTester {
|
||||
}
|
||||
|
||||
function checkConstraint(constraint) {
|
||||
const F = self.field;
|
||||
const F = self.F;
|
||||
const a = evalLC(constraint[0]);
|
||||
const b = evalLC(constraint[1]);
|
||||
const c = evalLC(constraint[2]);
|
||||
|
||||
assert (F.sub(F.mul(a,b), c).isZero(), "Constraint doesn't match");
|
||||
assert (F.isZero(F.sub(F.mul(a,b), c)), "Constraint doesn't match");
|
||||
}
|
||||
|
||||
function evalLC(lc) {
|
||||
const F = self.field;
|
||||
const F = self.F;
|
||||
let v = F.zero;
|
||||
for (let w in lc) {
|
||||
v = F.add(
|
||||
|
||||
@@ -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 {
|
||||
|
||||
61
src/build.js
61
src/build.js
@@ -18,10 +18,10 @@
|
||||
*/
|
||||
|
||||
const assert = require("assert");
|
||||
const bigInt = require("big-integer");
|
||||
const utils = require("./utils");
|
||||
const gen = require("./gencode").gen;
|
||||
const createRefs = require("./gencode").createRefs;
|
||||
const BigArray = require("./bigarray");
|
||||
|
||||
module.exports = build;
|
||||
|
||||
@@ -35,31 +35,36 @@ function build(ctx) {
|
||||
ctx.definedSizes = {};
|
||||
ctx.addSizes = addSizes;
|
||||
ctx.addConstant = addConstant;
|
||||
ctx.addConstant(bigInt.zero);
|
||||
ctx.addConstant(bigInt.one);
|
||||
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 = [];
|
||||
@@ -73,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);
|
||||
@@ -132,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]) {
|
||||
@@ -181,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)) {
|
||||
@@ -209,7 +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],
|
||||
P: ctx.field.p
|
||||
P: ctx.F.p
|
||||
});
|
||||
}
|
||||
|
||||
@@ -218,6 +205,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) );
|
||||
}
|
||||
@@ -242,8 +230,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`);
|
||||
@@ -391,7 +380,7 @@ function hashComponentCall(ctx, cIdx) {
|
||||
// TODO: At the moment generate a diferent function for each instance of the component
|
||||
const constParams = [];
|
||||
for (let p in ctx.components[cIdx].params) {
|
||||
constParams.push(p + "=" + value2str(ctx.components[cIdx].params[p]));
|
||||
constParams.push(p + "=" + value2str(ctx.F, ctx.components[cIdx].params[p]));
|
||||
}
|
||||
|
||||
for (let n in ctx.components[cIdx].names.o) {
|
||||
@@ -399,7 +388,7 @@ function hashComponentCall(ctx, cIdx) {
|
||||
if ((entry.type == "S")&&(ctx.signals[entry.offset].o & ctx.IN)) {
|
||||
travelSizes(n, entry.offset, entry.sizes, (prefix, offset) => {
|
||||
if (utils.isDefined(ctx.signals[offset].v)) {
|
||||
constParams.push(prefix + "=" + bigInt(ctx.signals[offset].value));
|
||||
constParams.push(prefix + "=" + ctx.F.e(ctx.signals[offset].v));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -433,7 +422,7 @@ function hashFunctionCall(ctx, name, paramValues) {
|
||||
const constParams = [];
|
||||
for (let i=0; i<ctx.functions[name].params.length; i++) {
|
||||
if (!paramValues[i].used) {
|
||||
constParams.push(ctx.functions[name].params[i] + utils.accSizes2Str(paramValues[i].sizes) + "=" + value2str(paramValues[i].value));
|
||||
constParams.push(ctx.functions[name].params[i] + utils.accSizes2Str(paramValues[i].sizes) + "=" + value2str(ctx.F, paramValues[i].value));
|
||||
}
|
||||
}
|
||||
let instanceDef = name;
|
||||
@@ -447,16 +436,16 @@ function hashFunctionCall(ctx, name, paramValues) {
|
||||
return {h, instanceDef};
|
||||
}
|
||||
|
||||
function value2str(v) {
|
||||
function value2str(F, v) {
|
||||
if (Array.isArray(v)) {
|
||||
let S="[";
|
||||
for (let i=0; i<v.length; i++) {
|
||||
if (i>0) S+=",";
|
||||
S+=value2str(v[i]);
|
||||
S+=value2str(F, v[i]);
|
||||
}
|
||||
S+="]";
|
||||
return S;
|
||||
} else {
|
||||
return bigInt(v).toString();
|
||||
return F.toString(F.e(v));
|
||||
}
|
||||
}
|
||||
|
||||
540
src/compiler.js
540
src/compiler.js
@@ -17,39 +17,61 @@
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const bigInt = require("big-integer");
|
||||
const __P__ = bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
||||
const Scalar = require("ffjavascript").Scalar;
|
||||
const sONE = 0;
|
||||
const build = require("./build");
|
||||
const BuilderC = require("../ports/c/builder.js");
|
||||
const BuilderWasm = require("../ports/wasm/builder.js");
|
||||
const constructionPhase = require("./construction_phase");
|
||||
const Ctx = require("./ctx");
|
||||
const ZqField = require("ffjavascript").ZqField;
|
||||
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 || __P__;
|
||||
options.prime = options.prime || Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
if (typeof options.reduceConstraints === "undefined") {
|
||||
options.reduceConstraints = true;
|
||||
}
|
||||
const ctx = new Ctx();
|
||||
ctx.field = new ZqField(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);
|
||||
@@ -60,70 +82,97 @@ async function compile(srcFile, options) {
|
||||
}
|
||||
|
||||
if (ctx.verbose) console.log("Classify Signals");
|
||||
measures.classifySignals = -performance.now();
|
||||
classifySignals(ctx);
|
||||
measures.classifySignals += performance.now();
|
||||
|
||||
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);
|
||||
|
||||
measures.generateWitnessNames = -performance.now();
|
||||
generateWitnessNames(ctx);
|
||||
measures.generateWitnessNames += performance.now();
|
||||
|
||||
if (ctx.error) {
|
||||
throw(ctx.error);
|
||||
}
|
||||
|
||||
if (options.cSourceWriteStream) {
|
||||
ctx.builder = new BuilderC();
|
||||
if (options.r1csFileName) {
|
||||
measures.generateR1cs = -performance.now();
|
||||
await buildR1cs(ctx, options.r1csFileName);
|
||||
measures.generateR1cs += performance.now();
|
||||
}
|
||||
|
||||
if (ctx.error) throw(ctx.error);
|
||||
|
||||
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);
|
||||
const rdStream = ctx.builder.build();
|
||||
rdStream.pipe(options.cSourceWriteStream);
|
||||
|
||||
// await new Promise(fulfill => options.cSourceWriteStream.on("finish", fulfill));
|
||||
await ctx.builder.build(options.cSourceFile, options.dataFile);
|
||||
measures.generateC += performance.now();
|
||||
}
|
||||
|
||||
if ((options.wasmWriteStream)||(options.watWriteStream)) {
|
||||
ctx.builder = new BuilderWasm();
|
||||
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.wasmWriteStream) {
|
||||
const rdStream = ctx.builder.build("wasm");
|
||||
rdStream.pipe(options.wasmWriteStream);
|
||||
if (options.wasmFile) {
|
||||
await ctx.builder.build(options.wasmFile, "wasm");
|
||||
}
|
||||
if (options.watWriteStream) {
|
||||
const rdStream = ctx.builder.build("wat");
|
||||
rdStream.pipe(options.watWriteStream);
|
||||
if (options.watFile) {
|
||||
await ctx.builder.build(options.watFile, "wat");
|
||||
}
|
||||
|
||||
// await new Promise(fulfill => options.wasmWriteStream.on("finish", fulfill));
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -149,6 +198,7 @@ function classifySignals(ctx) {
|
||||
|
||||
// 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 lSignal = signal;
|
||||
@@ -252,17 +302,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;
|
||||
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) {
|
||||
@@ -286,274 +387,191 @@ 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];
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
addTolIdx(removedSignals[isolatedSignal], isolatedSignal);
|
||||
ctx.constraints[possibleConstraints[i]] = null;
|
||||
nRemoved ++;
|
||||
|
||||
const isolatedSignalEquivalence = {
|
||||
t: "LC",
|
||||
coefs: {}
|
||||
};
|
||||
const invCoef = c.c.coefs[isolatedSignal].modInv(__P__);
|
||||
for (const s in c.c.coefs) {
|
||||
if (s != isolatedSignal) {
|
||||
const v = __P__.minus(c.c.coefs[s]).times(invCoef).mod(__P__);
|
||||
if (!v.isZero()) {
|
||||
isolatedSignalEquivalence.coefs[s] = v;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx.constraints[i] = null;
|
||||
|
||||
lSignal.c = ctx.stDISCARDED;
|
||||
if (nextPossibleConstraints.getKeys) {
|
||||
nextPossibleConstraints = nextPossibleConstraints.getKeys();
|
||||
} 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++;
|
||||
}
|
||||
}
|
||||
ctx.constraints.length = o;
|
||||
|
||||
function indexVariables() {
|
||||
for (let i=0; i<ctx.constraints.length; i++) linkSignalsConstraint(i);
|
||||
nextPossibleConstraints = Object.keys(nextPossibleConstraints);
|
||||
}
|
||||
|
||||
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);
|
||||
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 unindexVariables() {
|
||||
for (let s=0; s<ctx.signals.length; s++) {
|
||||
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];
|
||||
|
||||
let lSignal = ctx.signals[s];
|
||||
while (lSignal.e>=0) {
|
||||
lSignal = ctx.signals[lSignal.e];
|
||||
}
|
||||
if (lSignal.inConstraints) delete lSignal.inConstraints;
|
||||
}
|
||||
|
||||
sig2constraint[s] = null;
|
||||
lSignal.c = ctx.stDISCARDED;
|
||||
}
|
||||
|
||||
/*
|
||||
function unlinkSignal(signalName, cidx) {
|
||||
let lSignal = ctx.signals[signalName];
|
||||
while (lSignal.e>=0) {
|
||||
lSignal = ctx.signals[lSignal.e];
|
||||
}
|
||||
if ((lSignal.inConstraints)&&(lSignal.inConstraints[cidx])) {
|
||||
delete lSignal.inConstraints[cidx];
|
||||
}
|
||||
possibleConstraints = new BigArray();
|
||||
// Reverse
|
||||
for (let i=0; i<nextPossibleConstraints.length; i++) {
|
||||
possibleConstraints[i] = nextPossibleConstraints[nextPossibleConstraints.length -1 -i];
|
||||
}
|
||||
*/
|
||||
possibleConstraints = nextPossibleConstraints;
|
||||
|
||||
function linkSignal(signalName, cidx) {
|
||||
let lSignal = ctx.signals[signalName];
|
||||
while (lSignal.e>=0) {
|
||||
lSignal = ctx.signals[lSignal.e];
|
||||
totalRemoved += nRemoved;
|
||||
if (ctx.verbose) console.log(`Removed: ${totalRemoved} TotalConstraints: ${ctx.constraints.length}` );
|
||||
}
|
||||
if (!lSignal.inConstraints) lSignal.inConstraints = {};
|
||||
lSignal.inConstraints[cidx] = true;
|
||||
|
||||
|
||||
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.c == ctx.stINTERNAL)&&(!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) && (!l.coefs[k].isZero())) return false;
|
||||
if ((k != sONE) && (!ctx.F.isZero(l.coefs[k]))) return false;
|
||||
}
|
||||
if (!l.coefs[sONE] || l.coefs[sONE].isZero()) return false;
|
||||
if (!l.coefs[sONE] || ctx.F.isZero(l.coefs[sONE])) return false;
|
||||
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;
|
||||
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.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++;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
|
||||
@@ -49,10 +49,11 @@ const assert = require("assert");
|
||||
const iterateAST = require("./iterateast");
|
||||
const utils = require("./utils");
|
||||
|
||||
const bigInt = require("big-integer");
|
||||
|
||||
const LCAlgebra = require("./lcalgebra");
|
||||
const parser = require("../parser/jaz.js").parser;
|
||||
const Scalar = require("ffjavascript").Scalar;
|
||||
|
||||
const {stringifyBigInts} = require("ffjavascript").utils;
|
||||
|
||||
/* TODO: Add lines information
|
||||
|
||||
@@ -79,7 +80,7 @@ function constructionPhase(ctx, srcFile) {
|
||||
|
||||
assert(ctx.ast.type == "BLOCK");
|
||||
|
||||
ctx.lc = new LCAlgebra(ctx.field);
|
||||
ctx.lc = new LCAlgebra(ctx.F);
|
||||
ctx.filePath= fullFilePath;
|
||||
ctx.fileName= fullFileName;
|
||||
ctx.includedFiles = {};
|
||||
@@ -218,7 +219,7 @@ function execNumber(ctx, ast) {
|
||||
s:[1,0],
|
||||
v: [{
|
||||
t: "N",
|
||||
v: bigInt(ast.value)
|
||||
v: ctx.F.e(ast.value)
|
||||
}]
|
||||
};
|
||||
}
|
||||
@@ -253,7 +254,7 @@ function execDeclareComponent(ctx, ast) {
|
||||
const size = val(ctx, sizeRef);
|
||||
if (size.t != "N") return ctx.throwError( ast.name.selectors[i], "expected a number");
|
||||
|
||||
sizes.push( size.v.toJSNumber() );
|
||||
sizes.push( Scalar.toNumber(size.v) );
|
||||
}
|
||||
|
||||
let cIdx = ctx.addComponent(ast.name.name, sizes);
|
||||
@@ -277,7 +278,7 @@ function execDeclareSignal(ctx, ast) {
|
||||
if (ctx.error) return;
|
||||
if (size.s[0] != 1) return ctx.throwError(ast, "Size cannot be an array");
|
||||
if (size.v[0].t != "N") return ctx.throwError(ast, "Size must be declared in construction time");
|
||||
sizes.push( size.v[0].v.toJSNumber() );
|
||||
sizes.push( Scalar.toNumber(size.v[0].v) );
|
||||
}
|
||||
|
||||
let sIdx = ctx.addSignal(ast.name.name, sizes);
|
||||
@@ -322,7 +323,7 @@ function execDeclareVariable(ctx, ast) {
|
||||
if (ctx.error) return;
|
||||
if (size.s[0] != 1) return ctx.throwError(ast, "Size cannot be an array");
|
||||
if (size.v[0].t != "N") return ctx.throwError(ast, "Size must be declared in construction time");
|
||||
sizes.push( size.v[0].v.toJSNumber() );
|
||||
sizes.push( Scalar.toNumber(size.v[0].v) );
|
||||
}
|
||||
|
||||
const v = ctx.refs[ast.refId];
|
||||
@@ -353,7 +354,7 @@ function execAssignement(ctx, ast) {
|
||||
if (sel.s[0] != 1) return ctx.throwError(ast, "Selector cannot be an array");
|
||||
if (sel.v[0].t != "N") return {t: "NQ"};
|
||||
|
||||
leftSels.push( sel.v[0].v.toJSNumber() );
|
||||
leftSels.push( Scalar.toNumber(sel.v[0].v) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -380,7 +381,7 @@ function execAssignement(ctx, ast) {
|
||||
} else if (right.t == "S") {
|
||||
for (let i=0; i<right.s[0]; i++) {
|
||||
left.v[o+i]={t: "LC", coefs: {}};
|
||||
left.v[o+i].coefs[right.sIdx+i] = ctx.field.one;
|
||||
left.v[o+i].coefs[right.sIdx+i] = ctx.F.one;
|
||||
}
|
||||
}
|
||||
} else if ( left.t == "S") {
|
||||
@@ -561,19 +562,23 @@ function execFunctionCall(ctx, ast) {
|
||||
if (ev.v) {
|
||||
console.log(ev.v.toString());
|
||||
} else {
|
||||
console.log(JSON.stringify(ev));
|
||||
console.log(JSON.stringify(stringifyBigInts(ev)));
|
||||
}
|
||||
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 (ev.isZero()) 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++) {
|
||||
@@ -634,7 +639,7 @@ function execVariable(ctx, ast) {
|
||||
if (ctx.error) return;
|
||||
if (sel.s[0] != 1) return ctx.throwError(ast, "Variable selector cannot be an array");
|
||||
if (sel.v[0].t != "N") return NQVAL;
|
||||
sels.push(sel.v[0].v.toJSNumber());
|
||||
sels.push(Scalar.toNumber(sel.v[0].v));
|
||||
}
|
||||
|
||||
let o = 0;
|
||||
@@ -682,7 +687,7 @@ function execPin(ctx, ast) {
|
||||
|
||||
if (sel.s[0] != 1) return ctx.throwError(ast, "Component selector cannot be an array");
|
||||
if (sel.v[0].t != "N") return NQVAL;
|
||||
selsC.push(sel.v[0].v.toJSNumber());
|
||||
selsC.push(Scalar.toNumber(sel.v[0].v));
|
||||
}
|
||||
|
||||
const cIdx = ctx.getComponentIdx(ast.component.name, selsC);
|
||||
@@ -694,7 +699,10 @@ function execPin(ctx, ast) {
|
||||
if (ctx.error) return;
|
||||
if (sel.s[0] != 1) return ctx.throwError(ast, "Signal selector cannot be an array");
|
||||
if (sel.v[0].t != "N") return NQVAL;
|
||||
selsP.push(sel.v[0].v.toJSNumber());
|
||||
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);
|
||||
|
||||
@@ -741,7 +749,7 @@ function execLoop(ctx, ast) {
|
||||
return;
|
||||
}
|
||||
|
||||
while ((!v.v[0].v.isZero())&&(!ctx.returnValue)) {
|
||||
while ((! ctx.F.isZero(v.v[0].v))&&(!ctx.returnValue)) {
|
||||
exec(ctx, ast.body);
|
||||
if (ctx.error) return;
|
||||
|
||||
@@ -784,7 +792,7 @@ function execIf(ctx, ast) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!v.v[0].v.isZero()) {
|
||||
if (!ctx.F.isZero(v.v[0].v)) {
|
||||
exec(ctx, ast.then);
|
||||
} else {
|
||||
if (ast.else) {
|
||||
@@ -811,7 +819,7 @@ function execTerCon(ctx, ast) {
|
||||
return NQVAL;
|
||||
}
|
||||
|
||||
if (!v.v[0].v.isZero()) {
|
||||
if (!ctx.F.isZero(v.v[0].v)) {
|
||||
return exec(ctx, ast.values[1]);
|
||||
} else {
|
||||
return exec(ctx, ast.values[2]);
|
||||
@@ -850,7 +858,7 @@ function execOpOp(ctx, ast, op, lr) {
|
||||
if (sel.s[0] != 1) return ctx.throwError(ast, "Selector cannot be an array");
|
||||
if (sel.v[0].t != "N") return {t: "NQ"};
|
||||
|
||||
leftSels.push( sel.v[0].v.toJSNumber() );
|
||||
leftSels.push( Scalar.toNumber(sel.v[0].v) );
|
||||
}
|
||||
}
|
||||
if (!left.s) return ctx.throwError(ast, "variable. not defined yet");
|
||||
@@ -870,7 +878,7 @@ function execOpOp(ctx, ast, op, lr) {
|
||||
if (ctx.error) return;
|
||||
right = val(ctx, rightRef);
|
||||
} else {
|
||||
right = {t:"N", v: ctx.field.one};
|
||||
right = {t:"N", v: ctx.F.one};
|
||||
}
|
||||
|
||||
if (!right) return ctx.throwError(ast, "adding a no number");
|
||||
@@ -907,7 +915,7 @@ function val(ctx, a, ast) {
|
||||
};
|
||||
let sIdx = a.sIdx;
|
||||
while (ctx.signals[sIdx].e >= 0) sIdx = ctx.signals[sIdx].e;
|
||||
res.coefs[sIdx] = ctx.field.one;
|
||||
res.coefs[sIdx] = ctx.F.one;
|
||||
return res;
|
||||
} else {
|
||||
ctx.throwError(ast, "Invalid type: " + a.t);
|
||||
@@ -979,7 +987,7 @@ function execArray(ctx, ast) {
|
||||
} else if (e.t == "S") {
|
||||
for (let j=0; j<e.v.length;j++) {
|
||||
const sv = {t: "LC", coefs: {}};
|
||||
sv.coefs[e.sIdx+j] = ctx.field.one;
|
||||
sv.coefs[e.sIdx+j] = ctx.F.one;
|
||||
res.v.push(sv);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
const bigInt = require("big-integer");
|
||||
const BigArray = require("./bigarray.js");
|
||||
|
||||
const F1Field = require("ffjavascript").F1Field;
|
||||
|
||||
class TableName {
|
||||
constructor (ctx) {
|
||||
@@ -86,7 +85,9 @@ class TableName {
|
||||
|
||||
module.exports = class Ctx {
|
||||
|
||||
constructor() {
|
||||
constructor(p) {
|
||||
|
||||
this.F = new F1Field(p);
|
||||
|
||||
this.stONE = 1;
|
||||
this.stOUTPUT = 2;
|
||||
@@ -121,7 +122,7 @@ module.exports = class Ctx {
|
||||
|
||||
const oneIdx = this.addSignal("one");
|
||||
this.signals[oneIdx] = {
|
||||
v: bigInt(1),
|
||||
v: this.F.one,
|
||||
o: this.ONE,
|
||||
e: -1,
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const bigInt = require("big-integer");
|
||||
const utils = require("./utils");
|
||||
const assert = require("assert");
|
||||
const iterateAST = require("./iterateast");
|
||||
const Scalar = require("ffjavascript").Scalar;
|
||||
|
||||
module.exports.gen = gen;
|
||||
module.exports.newRef = newRef;
|
||||
@@ -300,7 +300,7 @@ function genDeclareVariable(ctx, ast) {
|
||||
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, "Variable size variables not allowed");
|
||||
sizes.push(size.value[0]);
|
||||
sizes.push(Scalar.toNumber(size.value[0]));
|
||||
}
|
||||
sizes = utils.accSizes(sizes);
|
||||
} else {
|
||||
@@ -320,7 +320,7 @@ function genDeclareVariable(ctx, ast) {
|
||||
}
|
||||
|
||||
function genNumber(ctx, ast) {
|
||||
return newRef(ctx, "BIGINT", "_num", bigInt(ast.value));
|
||||
return newRef(ctx, "BIGINT", "_num", ctx.F.e(ast.value));
|
||||
}
|
||||
|
||||
|
||||
@@ -723,7 +723,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 +871,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]);
|
||||
@@ -950,7 +964,7 @@ function genLoop(ctx, ast) {
|
||||
ctx.codeBuilder.assign(loopCond.label, ["R", cond.label], ["V", 0]);
|
||||
} else {
|
||||
if (!utils.isDefined(cond.value)) return ctx.throwError(ast, "condition value not assigned");
|
||||
if (cond.value[0].isZero()) end=true;
|
||||
if (ctx.F.isZero(cond.value[0])) end=true;
|
||||
}
|
||||
|
||||
|
||||
@@ -993,7 +1007,7 @@ function genLoop(ctx, ast) {
|
||||
} else {
|
||||
oldCodeBuilder.concat(ctx.codeBuilder);
|
||||
ctx.codeBuilder = oldCodeBuilder;
|
||||
if (cond2.value[0].isZero()) end=true;
|
||||
if (ctx.F.isZero(cond2.value[0])) end=true;
|
||||
}
|
||||
} else {
|
||||
ctx.codeBuilder.assign(loopCond.label, ["R", cond2.label], ["V", 0]);
|
||||
@@ -1042,7 +1056,7 @@ function genIf(ctx, ast) {
|
||||
|
||||
} else {
|
||||
if (!utils.isDefined(cond.value)) return ctx.throwError(ast, "condition value not assigned");
|
||||
if (!cond.value[0].isZero()) {
|
||||
if (!ctx.F.isZero(cond.value[0])) {
|
||||
gen(ctx, ast.then);
|
||||
} else {
|
||||
if (ast.else) {
|
||||
@@ -1109,9 +1123,9 @@ function genOpOp(ctx, ast, op, lr) {
|
||||
const res = ctx.refs[resRef];
|
||||
if (veval.used) {
|
||||
instantiateRef(ctx, resRef);
|
||||
ctx.codeBuilder.fieldOp(res.label, op, [["R", veval.label], ["C", ctx.addConstant(bigInt.one)]]);
|
||||
ctx.codeBuilder.fieldOp(res.label, op, [["R", veval.label], ["C", ctx.addConstant(ctx.F.one)]]);
|
||||
} else {
|
||||
res.value = [ctx.field[op](veval.value[0], bigInt(1))];
|
||||
res.value = [ctx.F[op](veval.value[0], ctx.F.one)];
|
||||
}
|
||||
genVarAssignment(ctx, ast, vRef, ast.values[0].selectors, resRef);
|
||||
if (lr == "RIGHT") {
|
||||
@@ -1157,10 +1171,10 @@ function genOp(ctx, ast, op, nOps, adjustBool) {
|
||||
} else {
|
||||
const params = [];
|
||||
for (let i=0; i<nOps; i++) {
|
||||
params.push(vals[i].value[0]);
|
||||
params.push(ctx.F.e(vals[i].value[0]));
|
||||
}
|
||||
|
||||
rRef = newRef(ctx, "BIGINT", "_tmp", adjustBool ? (ctx.field[op](...params)?bigInt.one:bigInt.zero) : ctx.field[op](...params));
|
||||
rRef = newRef(ctx, "BIGINT", "_tmp", adjustBool ? (ctx.F[op](...params)?ctx.F.one:ctx.F.zero) : ctx.F[op](...params));
|
||||
}
|
||||
return rRef;
|
||||
}
|
||||
@@ -1242,7 +1256,7 @@ function genTerCon(ctx, ast) {
|
||||
|
||||
} else {
|
||||
if (!utils.isDefined(cond.value)) return ctx.throwError(ast, "condition value not assigned");
|
||||
if (!cond.value[0].isZero()) {
|
||||
if (!ctx.F.isZero(cond.value[0])) {
|
||||
return gen(ctx, ast.values[1]);
|
||||
} else {
|
||||
return gen(ctx, ast.values[2]);
|
||||
|
||||
@@ -76,14 +76,13 @@ QEX QEX NQ NQ NQ
|
||||
NQ NQ NQ NQ NQ
|
||||
*/
|
||||
|
||||
const bigInt = require("big-integer");
|
||||
const utils = require("./utils");
|
||||
const sONE = 0;
|
||||
|
||||
class LCAlgebra {
|
||||
constructor (aField) {
|
||||
const self = this;
|
||||
this.field= aField;
|
||||
this.F= aField;
|
||||
[
|
||||
["idiv",2],
|
||||
["mod",2],
|
||||
@@ -118,18 +117,19 @@ class LCAlgebra {
|
||||
}
|
||||
return {
|
||||
t: "N",
|
||||
v: adjustBool ? ( self.field[op](...operands) ? bigInt.one: bigInt.zero) : self.field[op](...operands)
|
||||
v: adjustBool ? ( self.F[op](...operands) ? self.F.one: self.F.zero) : self.F[op](...operands)
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
_signal2lc(a) {
|
||||
const self = this;
|
||||
if (a.t == "S") {
|
||||
const lc = {
|
||||
t: "LC",
|
||||
coefs: {}
|
||||
};
|
||||
lc.coefs[a.sIdx] = bigInt(1);
|
||||
lc.coefs[a.sIdx] = self.F.one;
|
||||
return lc;
|
||||
} else {
|
||||
return a;
|
||||
@@ -200,17 +200,17 @@ class LCAlgebra {
|
||||
function add_N_N(a,b) {
|
||||
return {
|
||||
t: "N",
|
||||
v: self.field.add(a.v, b.v)
|
||||
v: self.F.add(a.v, b.v)
|
||||
};
|
||||
}
|
||||
|
||||
function add_LC_N(a,b) {
|
||||
let res = self._clone(a);
|
||||
if (b.v.isZero()) return res;
|
||||
if (self.F.isZero(b.v)) return res;
|
||||
if (!utils.isDefined(res.coefs[sONE])) {
|
||||
res.coefs[sONE]= b.v;
|
||||
} else {
|
||||
res.coefs[sONE]= self.field.add(res.coefs[sONE], b.v);
|
||||
res.coefs[sONE]= self.F.add(res.coefs[sONE], b.v);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -221,7 +221,7 @@ class LCAlgebra {
|
||||
if (!utils.isDefined(res.coefs[k])) {
|
||||
res.coefs[k]=b.coefs[k];
|
||||
} else {
|
||||
res.coefs[k]= self.field.add(res.coefs[k], b.coefs[k]);
|
||||
res.coefs[k]= self.F.add(res.coefs[k], b.coefs[k]);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
@@ -283,14 +283,14 @@ class LCAlgebra {
|
||||
function mul_N_N(a,b) {
|
||||
return {
|
||||
t: "N",
|
||||
v: self.field.mul(a.v, b.v)
|
||||
v: self.F.mul(a.v, b.v)
|
||||
};
|
||||
}
|
||||
|
||||
function mul_LC_N(a,b) {
|
||||
let res = self._clone(a);
|
||||
for (let k in res.coefs) {
|
||||
res.coefs[k] = self.field.mul(res.coefs[k], b.v);
|
||||
res.coefs[k] = self.F.mul(res.coefs[k], b.v);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -318,10 +318,10 @@ class LCAlgebra {
|
||||
const a = this._signal2lc(_a);
|
||||
let res = this._clone(a);
|
||||
if (res.t == "N") {
|
||||
res.v = this.field.neg(a.v);
|
||||
res.v = this.F.neg(a.v);
|
||||
} else if (res.t == "LC") {
|
||||
for (let k in res.coefs) {
|
||||
res.coefs[k] = this.field.neg(res.coefs[k]);
|
||||
res.coefs[k] = this.F.neg(res.coefs[k]);
|
||||
}
|
||||
} else if (res.t == "QEX") {
|
||||
res.a = this.neg(res.a);
|
||||
@@ -338,10 +338,10 @@ class LCAlgebra {
|
||||
|
||||
div(a, b) {
|
||||
if (b.t == "N") {
|
||||
if (b.v.isZero()) throw new Error("Division by zero");
|
||||
if (this.F.isZero(b.v)) throw new Error("Division by zero");
|
||||
const inv = {
|
||||
t: "N",
|
||||
v: this.field.inv(b.v)
|
||||
v: this.F.inv(b.v)
|
||||
};
|
||||
return this.mul(a, inv);
|
||||
} else {
|
||||
@@ -351,23 +351,23 @@ class LCAlgebra {
|
||||
|
||||
pow(a, b) {
|
||||
if (b.t == "N") {
|
||||
if (b.v.isZero()) {
|
||||
if (this.F.isZero(b.v)) {
|
||||
if (this.isZero(a)) {
|
||||
throw new Error("Zero to the Zero");
|
||||
}
|
||||
return {
|
||||
t: "N",
|
||||
v: this.field.one
|
||||
v: this.F.one
|
||||
};
|
||||
} else if (b.v.eq(this.field.one)) {
|
||||
} else if (this.F.eq(b.v, this.F.one)) {
|
||||
return a;
|
||||
} else if (b.v.eq(bigInt(2))) {
|
||||
} else if (this.F.eq(b.v, this.F.two)) {
|
||||
return this.mul(a,a);
|
||||
} else {
|
||||
if (a.t=="N") {
|
||||
return {
|
||||
t: "N",
|
||||
v: this.field.pow(a.v, b.v)
|
||||
v: this.F.pow(a.v, b.v)
|
||||
};
|
||||
} else {
|
||||
return {t: "NQ"};
|
||||
@@ -381,18 +381,18 @@ class LCAlgebra {
|
||||
substitute(where, signal, equivalence) {
|
||||
if (equivalence.t != "LC") throw new Error("Equivalence must be a Linear Combination");
|
||||
if (where.t == "LC") {
|
||||
if (!utils.isDefined(where.coefs[signal]) || where.coefs[signal].isZero()) return where;
|
||||
if (!utils.isDefined(where.coefs[signal]) || this.F.isZero(where.coefs[signal])) return where;
|
||||
const res=this._clone(where);
|
||||
const coef = res.coefs[signal];
|
||||
for (let k in equivalence.coefs) {
|
||||
if (k != signal) {
|
||||
const v = this.field.mul( coef, equivalence.coefs[k] );
|
||||
const v = this.F.mul( coef, equivalence.coefs[k] );
|
||||
if (!utils.isDefined(res.coefs[k])) {
|
||||
res.coefs[k]=v;
|
||||
} else {
|
||||
res.coefs[k]= this.field.add(res.coefs[k],v);
|
||||
res.coefs[k]= this.F.add(res.coefs[k],v);
|
||||
}
|
||||
if (res.coefs[k].isZero()) delete res.coefs[k];
|
||||
if (this.F.isZero(res.coefs[k])) delete res.coefs[k];
|
||||
}
|
||||
}
|
||||
delete res.coefs[signal];
|
||||
@@ -436,10 +436,10 @@ class LCAlgebra {
|
||||
|
||||
isZero(a) {
|
||||
if (a.t == "N") {
|
||||
return a.v.isZero();
|
||||
return this.F.isZero(a.v);
|
||||
} else if (a.t == "LC") {
|
||||
for (let k in a.coefs) {
|
||||
if (!a.coefs[k].isZero()) return false;
|
||||
if (!this.F.isZero(a.coefs[k])) return false;
|
||||
}
|
||||
return true;
|
||||
} else if (a.t == "QEX") {
|
||||
@@ -455,16 +455,16 @@ class LCAlgebra {
|
||||
} else if (a.t == "LC") {
|
||||
let S="";
|
||||
for (let k in a.coefs) {
|
||||
if (!a.coefs[k].isZero()) {
|
||||
if (!this.F.isZero(a.coefs[k])) {
|
||||
let c;
|
||||
if (a.coefs[k].greater(this.field.p.divide(2))) {
|
||||
if (a.coefs[k].greater(this.F.p.divide(2))) {
|
||||
S = S + "-";
|
||||
c = this.field.p.minus(a.coefs[k]);
|
||||
c = this.F.p.minus(a.coefs[k]);
|
||||
} else {
|
||||
if (S!="") S=S+" + ";
|
||||
c = a.coefs[k];
|
||||
}
|
||||
if (!c.equals(bigInt.one)) {
|
||||
if (!c.equals(this.F.one)) {
|
||||
S = S + c.toString() + "*";
|
||||
}
|
||||
let sIdx = k;
|
||||
@@ -491,11 +491,11 @@ class LCAlgebra {
|
||||
} else if (n.t == "SIGNAL") {
|
||||
return getSignalValue(ctx, n.sIdx);
|
||||
} else if (n.t == "LC") {
|
||||
let v= this.field.zero;
|
||||
let v= this.F.zero;
|
||||
for (let k in n.coefs) {
|
||||
const s = getSignalValue(ctx, k);
|
||||
if (s === null) return null;
|
||||
v = this.field.add(v, this.field.mul( n.coefs[k], s));
|
||||
v = this.F.add(v, this.F.mul( n.coefs[k], s));
|
||||
}
|
||||
return v;
|
||||
} else if (n.type == "QEX") {
|
||||
@@ -506,7 +506,7 @@ class LCAlgebra {
|
||||
const c = this.evaluate(ctx, n.c);
|
||||
if (c === null) return null;
|
||||
|
||||
return this.field.add(this.field.mul(a,b), c);
|
||||
return this.F.add(this.F.mul(a,b), c);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@@ -529,24 +529,24 @@ class LCAlgebra {
|
||||
let s = k;
|
||||
while (ctx.signals[s].e>=0) s= ctx.signals[s].e;
|
||||
if (utils.isDefined(ctx.signals[s].v)&&(k != sONE)) {
|
||||
const v = this.field.mul(res.coefs[k], ctx.signals[s].v);
|
||||
const v = this.F.mul(res.coefs[k], ctx.signals[s].v);
|
||||
if (!utils.isDefined(res.coefs[sONE])) {
|
||||
res.coefs[sONE]=v;
|
||||
} else {
|
||||
res.coefs[sONE]= this.field.add(res.coefs[sONE], v);
|
||||
res.coefs[sONE]= this.F.add(res.coefs[sONE], v);
|
||||
}
|
||||
delete res.coefs[k];
|
||||
} else if (s != k) {
|
||||
if (!utils.isDefined(res.coefs[s])) {
|
||||
res.coefs[s]=res.coefs[k];
|
||||
} else {
|
||||
res.coefs[s]= this.field.add(res.coefs[s], res.coefs[k]);
|
||||
res.coefs[s]= this.F.add(res.coefs[s], res.coefs[k]);
|
||||
}
|
||||
delete res.coefs[k];
|
||||
}
|
||||
}
|
||||
for (let k in res.coefs) {
|
||||
if (res.coefs[k].isZero()) delete res.coefs[k];
|
||||
if (this.F.isZero(res.coefs[k])) delete res.coefs[k];
|
||||
}
|
||||
return res;
|
||||
} else if (a.t == "QEX") {
|
||||
|
||||
160
src/r1csfile.js
160
src/r1csfile.js
@@ -1,32 +1,36 @@
|
||||
|
||||
const fs = require("fs");
|
||||
const fastFile = require("fastfile");
|
||||
const assert = require("assert");
|
||||
const bigInt = require("big-integer");
|
||||
const BigArray = require("./bigarray");
|
||||
|
||||
module.exports.buildR1cs = buildR1cs;
|
||||
|
||||
|
||||
async function buildR1cs(ctx, fileName) {
|
||||
|
||||
const fd = await fs.promises.open(fileName, "w");
|
||||
const fd = await fastFile.createOverride(fileName, 1<<24, 1<<22);
|
||||
|
||||
const buffBigInt = new Uint8Array(ctx.F.n8);
|
||||
|
||||
await fd.write("r1cs"); // 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.field.p.bitLength() - 1) / 64) +1)*8;
|
||||
const n8 = (Math.floor( (ctx.F.bitLength - 1) / 64) +1)*8;
|
||||
// Field Def
|
||||
await writeU32(n8); // Temporally set to 0 length
|
||||
await writeBigInt(ctx.field.p);
|
||||
await fd.writeULE32(n8); // Temporally set to 0 length
|
||||
await writeBigInt(ctx.F.p);
|
||||
|
||||
const NWires =
|
||||
ctx.totals[ctx.stONE] +
|
||||
@@ -35,39 +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 fd.datasync();
|
||||
}
|
||||
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..
|
||||
@@ -78,73 +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.sync();
|
||||
await fd.close();
|
||||
|
||||
async function writeU32(v, pos) {
|
||||
const b = Buffer.allocUnsafe(4);
|
||||
b.writeInt32LE(v);
|
||||
|
||||
await fd.write(b, 0, 4, pos);
|
||||
|
||||
if (typeof(pos) == "undefined") p += 4;
|
||||
}
|
||||
|
||||
async function writeU64(v, 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, 0, 8, pos);
|
||||
|
||||
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) {
|
||||
const b = Buffer.allocUnsafe(n8);
|
||||
|
||||
const dwords = bigInt(n).toArray(0x100000000).value;
|
||||
ctx.F.toRprLE(buffBigInt, 0, n);
|
||||
|
||||
for (let i=0; i<dwords.length; i++) {
|
||||
b.writeUInt32LE(dwords[dwords.length-1-i], i*4, 4 );
|
||||
}
|
||||
b.fill(0, dwords.length*4);
|
||||
await fd.write(buffBigInt, pos);
|
||||
|
||||
await fd.write(b, 0, fs, pos);
|
||||
|
||||
if (typeof(pos) == "undefined") p += n8;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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])];
|
||||
}
|
||||
|
||||
|
||||
50
src/utils.js
50
src/utils.js
@@ -1,5 +1,4 @@
|
||||
const fnv = require("fnv-plus");
|
||||
const bigInt = require("big-integer");
|
||||
|
||||
module.exports.ident =ident;
|
||||
|
||||
@@ -8,11 +7,10 @@ module.exports.flatArray = flatArray;
|
||||
module.exports.csArr = csArr;
|
||||
module.exports.accSizes = accSizes;
|
||||
module.exports.fnvHash = fnvHash;
|
||||
module.exports.stringifyBigInts = stringifyBigInts;
|
||||
module.exports.unstringifyBigInts = unstringifyBigInts;
|
||||
module.exports.sameSizes = sameSizes;
|
||||
module.exports.isDefined = isDefined;
|
||||
module.exports.accSizes2Str = accSizes2Str;
|
||||
module.exports.setUint64 = setUint64;
|
||||
|
||||
function ident(text) {
|
||||
if (typeof text === "string") {
|
||||
@@ -45,7 +43,7 @@ function flatArray(a) {
|
||||
fillArray(res, a[i]);
|
||||
}
|
||||
} else {
|
||||
res.push(bigInt(a));
|
||||
res.push(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,42 +72,6 @@ function fnvHash(str) {
|
||||
return fnv.hash(str, 64).hex();
|
||||
}
|
||||
|
||||
|
||||
|
||||
function stringifyBigInts(o) {
|
||||
if ((typeof(o) == "bigint") || o.eq !== undefined) {
|
||||
return o.toString(10);
|
||||
} else if (Array.isArray(o)) {
|
||||
return o.map(stringifyBigInts);
|
||||
} else if (typeof o == "object") {
|
||||
const res = {};
|
||||
for (let k in o) {
|
||||
res[k] = stringifyBigInts(o[k]);
|
||||
}
|
||||
return res;
|
||||
} else {
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function unstringifyBigInts(o) {
|
||||
if ((typeof(o) == "string") && (/^[0-9]+$/.test(o) )) {
|
||||
return bigInt(o);
|
||||
} else if (Array.isArray(o)) {
|
||||
return o.map(unstringifyBigInts);
|
||||
} else if (typeof o == "object") {
|
||||
const res = {};
|
||||
for (let k in o) {
|
||||
res[k] = unstringifyBigInts(o[k]);
|
||||
}
|
||||
return res;
|
||||
} else {
|
||||
return bigInt(o);
|
||||
}
|
||||
}
|
||||
|
||||
function sameSizes(s1, s2) {
|
||||
if (!Array.isArray(s1)) return false;
|
||||
if (!Array.isArray(s2)) return false;
|
||||
@@ -129,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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
const path = require("path");
|
||||
|
||||
const bigInt = require("big-integer");
|
||||
const Scalar = require("ffjavascript").Scalar;
|
||||
const F1Field = require("ffjavascript").F1Field;
|
||||
const c_tester = require("../index.js").c_tester;
|
||||
const wasm_tester = require("../index.js").wasm_tester;
|
||||
|
||||
const __P__ = new bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
||||
const __P__ = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
||||
|
||||
const Fr = new F1Field(__P__);
|
||||
|
||||
const basicCases = require("./basiccases.json");
|
||||
|
||||
function normalize(o) {
|
||||
if ((typeof(o) == "bigint") || o.isZero !== undefined) {
|
||||
const res = bigInt(o);
|
||||
return norm(res);
|
||||
return Fr.e(o);
|
||||
} else if (Array.isArray(o)) {
|
||||
return o.map(normalize);
|
||||
} else if (typeof o == "object") {
|
||||
@@ -21,15 +23,9 @@ function normalize(o) {
|
||||
}
|
||||
return res;
|
||||
} else {
|
||||
const res = bigInt(o);
|
||||
return norm(res);
|
||||
return Fr.e(o);
|
||||
}
|
||||
|
||||
function norm(n) {
|
||||
let res = n.mod(__P__);
|
||||
if (res.isNegative()) res = __P__.add(res);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user