mirror of
https://github.com/arnaucube/circom.git
synced 2026-02-07 03:06:42 +01:00
Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
144
cli.js
144
cli.js
@@ -24,6 +24,8 @@
|
|||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const Scalar = require("ffjavascript").Scalar;
|
const Scalar = require("ffjavascript").Scalar;
|
||||||
|
const stringifyBigInts = require("ffjavascript").utils.stringifyBigInts;
|
||||||
|
const fastFile = require("fastfile");
|
||||||
|
|
||||||
const compiler = require("./src/compiler");
|
const compiler = require("./src/compiler");
|
||||||
|
|
||||||
@@ -60,87 +62,68 @@ const argv = require("yargs")
|
|||||||
.argv;
|
.argv;
|
||||||
|
|
||||||
|
|
||||||
let inputFile;
|
async function run() {
|
||||||
if (argv._.length == 0) {
|
let inputFile;
|
||||||
inputFile = "circuit.circom";
|
if (argv._.length == 0) {
|
||||||
} else if (argv._.length == 1) {
|
inputFile = "circuit.circom";
|
||||||
inputFile = argv._[0];
|
} else if (argv._.length == 1) {
|
||||||
} else {
|
inputFile = argv._[0];
|
||||||
console.log("Only one circuit at a time is permited");
|
} else {
|
||||||
process.exit(1);
|
console.log("Only one circuit at a time is permited");
|
||||||
}
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
const fullFileName = path.resolve(process.cwd(), inputFile);
|
const fullFileName = path.resolve(process.cwd(), inputFile);
|
||||||
const fileName = path.basename(fullFileName, ".circom");
|
const fileName = path.basename(fullFileName, ".circom");
|
||||||
const cSourceName = typeof(argv.csource) === "string" ? argv.csource : fileName + ".cpp";
|
const cSourceName = typeof(argv.csource) === "string" ? argv.csource : fileName + ".cpp";
|
||||||
const wasmName = typeof(argv.wasm) === "string" ? argv.wasm : fileName + ".wasm";
|
const wasmName = typeof(argv.wasm) === "string" ? argv.wasm : fileName + ".wasm";
|
||||||
const watName = typeof(argv.wat) === "string" ? argv.wat : fileName + ".wat";
|
const watName = typeof(argv.wat) === "string" ? argv.wat : fileName + ".wat";
|
||||||
const r1csName = typeof(argv.r1cs) === "string" ? argv.r1cs : fileName + ".r1cs";
|
const r1csName = typeof(argv.r1cs) === "string" ? argv.r1cs : fileName + ".r1cs";
|
||||||
const symName = typeof(argv.sym) === "string" ? argv.sym : fileName + ".sym";
|
const symName = typeof(argv.sym) === "string" ? argv.sym : fileName + ".sym";
|
||||||
|
|
||||||
const options = {};
|
const options = {};
|
||||||
options.reduceConstraints = !argv.fast;
|
options.reduceConstraints = !argv.fast;
|
||||||
options.verbose = argv.verbose || false;
|
options.verbose = argv.verbose || false;
|
||||||
options.sanityCheck = argv.sanitycheck;
|
options.sanityCheck = argv.sanitycheck;
|
||||||
|
|
||||||
if (argv.csource) {
|
if (argv.csource) {
|
||||||
options.cSourceWriteStream = fs.createWriteStream(cSourceName);
|
options.cSourceFile = await fastFile.createOverride(cSourceName);
|
||||||
}
|
const noExt = cSourceName.substr(0, cSourceName.lastIndexOf(".")) || cSourceName;
|
||||||
if (argv.wasm) {
|
options.dataFile = await fastFile.createOverride(noExt+".dat");
|
||||||
options.wasmWriteStream = fs.createWriteStream(wasmName);
|
}
|
||||||
}
|
if (argv.wasm) {
|
||||||
if (argv.wat) {
|
options.wasmFile = await fastFile.createOverride(wasmName);
|
||||||
options.watWriteStream = fs.createWriteStream(watName);
|
}
|
||||||
}
|
if (argv.wat) {
|
||||||
if (argv.r1cs) {
|
options.watFile = await fastFile.createOverride(watName);
|
||||||
options.r1csFileName = r1csName;
|
}
|
||||||
}
|
if (argv.r1cs) {
|
||||||
if (argv.sym) {
|
options.r1csFileName = r1csName;
|
||||||
options.symWriteStream = fs.createWriteStream(symName);
|
}
|
||||||
}
|
if (argv.sym) {
|
||||||
if (argv.newThreadTemplates) {
|
options.symWriteStream = fs.createWriteStream(symName);
|
||||||
options.newThreadTemplates = new RegExp(argv.newThreadTemplates);
|
}
|
||||||
}
|
if (argv.newThreadTemplates) {
|
||||||
if (!argv.prime) {
|
options.newThreadTemplates = new RegExp(argv.newThreadTemplates);
|
||||||
options.prime = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
}
|
||||||
} else if (["BLS12-381", "BLS12381"]. indexOf(argv.prime.toUpperCase()) >=0) {
|
if (!argv.prime) {
|
||||||
options.prime = Scalar.fromString("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001",16);
|
options.prime = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
||||||
} else if (["BN-128", "BN128", "BN254", "BN-254"]. indexOf(argv.prime.toUpperCase()) >=0) {
|
} else if (["BLS12-381", "BLS12381"]. indexOf(argv.prime.toUpperCase()) >=0) {
|
||||||
options.prime = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
options.prime = Scalar.fromString("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001",16);
|
||||||
} else {
|
} else if (["BN-128", "BN128", "BN254", "BN-254"]. indexOf(argv.prime.toUpperCase()) >=0) {
|
||||||
options.prime = Scalar.fromString(argv.prime);
|
options.prime = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
||||||
}
|
} else {
|
||||||
|
options.prime = Scalar.fromString(argv.prime);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
compiler(fullFileName, options).then( () => {
|
await compiler(fullFileName, options);
|
||||||
let cSourceDone = false;
|
|
||||||
let wasmDone = false;
|
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 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) {
|
if (options.symWriteStream) {
|
||||||
options.symWriteStream.on("finish", () => {
|
options.symWriteStream.on("finish", () => {
|
||||||
symDone = true;
|
symDone = true;
|
||||||
@@ -150,12 +133,17 @@ compiler(fullFileName, options).then( () => {
|
|||||||
symDone = true;
|
symDone = true;
|
||||||
}
|
}
|
||||||
function finishIfDone() {
|
function finishIfDone() {
|
||||||
if ((cSourceDone)&&(symDone)&&(wasmDone)&&(watDone)) {
|
if (symDone) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}, 300);
|
}, 300);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
run().then(()=> {
|
||||||
|
process.exit(0);
|
||||||
}, (err) => {
|
}, (err) => {
|
||||||
// console.log(err);
|
// console.log(err);
|
||||||
console.log(err.stack);
|
console.log(err.stack);
|
||||||
@@ -166,11 +154,9 @@ compiler(fullFileName, options).then( () => {
|
|||||||
if (argv.verbose) console.log(err.stack);
|
if (argv.verbose) console.log(err.stack);
|
||||||
}
|
}
|
||||||
if (err.ast) {
|
if (err.ast) {
|
||||||
console.error(JSON.stringify(err.ast, null, 1));
|
console.error(JSON.stringify(stringifyBigInts(err.ast), null, 1));
|
||||||
}
|
}
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
180
package-lock.json
generated
180
package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "circom",
|
"name": "circom",
|
||||||
"version": "0.5.12",
|
"version": "0.5.23",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -48,9 +48,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"acorn": {
|
"acorn": {
|
||||||
"version": "7.3.1",
|
"version": "7.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz",
|
||||||
"integrity": "sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA==",
|
"integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"acorn-jsx": {
|
"acorn-jsx": {
|
||||||
@@ -60,9 +60,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"ajv": {
|
"ajv": {
|
||||||
"version": "6.12.2",
|
"version": "6.12.3",
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz",
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz",
|
||||||
"integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==",
|
"integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"fast-deep-equal": "^3.1.1",
|
"fast-deep-equal": "^3.1.1",
|
||||||
@@ -143,6 +143,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz",
|
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz",
|
||||||
"integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w=="
|
"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": {
|
"brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||||
@@ -198,22 +203,12 @@
|
|||||||
"integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII="
|
"integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII="
|
||||||
},
|
},
|
||||||
"circom_runtime": {
|
"circom_runtime": {
|
||||||
"version": "0.0.6",
|
"version": "0.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/circom_runtime/-/circom_runtime-0.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/circom_runtime/-/circom_runtime-0.1.5.tgz",
|
||||||
"integrity": "sha512-o0T5MuWzxnxinWG3+CygS/kZouoP+z5ZrufUwqKJy3gsVFJhkbqMpfKmcBGjhExB3uatA7cKyOiRAOLOz5+t5w==",
|
"integrity": "sha512-BT3d9VCrH/rBRbThDXG731JwezKyskxyE46nACO6Tt/jaorn27LDxFDORdAAjyD0RAoBt+6FpaTp3qlYSx7Pjg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"ffjavascript": "0.1.0",
|
"ffjavascript": "0.2.10",
|
||||||
"fnv-plus": "^1.3.1"
|
"fnv-plus": "^1.3.1"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"ffjavascript": {
|
|
||||||
"version": "0.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.1.0.tgz",
|
|
||||||
"integrity": "sha512-dmKlUasSfvUcxBm8nCSKl2x7EFJsXA7OVP8XLFA03T2+6mAc3IiVLC2ambEVOcMOhyhl0vJfVZjM9f9d38D1rw==",
|
|
||||||
"requires": {
|
|
||||||
"big-integer": "^1.6.48"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"cjson": {
|
"cjson": {
|
||||||
@@ -235,9 +230,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"cli-width": {
|
"cli-width": {
|
||||||
"version": "2.2.1",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz",
|
||||||
"integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==",
|
"integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"cliui": {
|
"cliui": {
|
||||||
@@ -339,9 +334,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"ejs": {
|
"ejs": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.5.tgz",
|
||||||
"integrity": "sha512-wmtrUGyfSC23GC/B1SMv2ogAUgbQEtDmTIhfqielrG5ExIM9TP4UoYdi90jLF1aTcsWCJNEO0UrgKzP0y3nTSg==",
|
"integrity": "sha512-dldq3ZfFtgVTJMLjOe+/3sROTzALlL9E34V4/sDtUd/KlBSS0s6U1/+WPE1B4sj9CXHJpL1M6rhNJnc9Wbal9w==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"jake": "^10.6.1"
|
"jake": "^10.6.1"
|
||||||
}
|
}
|
||||||
@@ -502,9 +497,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"estraverse": {
|
"estraverse": {
|
||||||
"version": "5.1.0",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz",
|
||||||
"integrity": "sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw==",
|
"integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -571,14 +566,14 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"fastfile": {
|
"fastfile": {
|
||||||
"version": "0.0.2",
|
"version": "0.0.12",
|
||||||
"resolved": "https://registry.npmjs.org/fastfile/-/fastfile-0.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/fastfile/-/fastfile-0.0.12.tgz",
|
||||||
"integrity": "sha512-rS9vpAM4DS+xacKSH0MVCqr/Y5SiIAiunJTYSuq1H9nfRpkP37ewgnjH3FztziKBUQB2xPYS/WxEEjHl+pA5Fg=="
|
"integrity": "sha512-0EZo2y5eW8X0oiDDRvcnufjVxlM96CQL5hvmRQtbRABWlCkH73IHwkzl0qOSdxtchaMr+0TSB7GVqaVEixRr1Q=="
|
||||||
},
|
},
|
||||||
"ffiasm": {
|
"ffiasm": {
|
||||||
"version": "0.0.2",
|
"version": "0.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/ffiasm/-/ffiasm-0.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/ffiasm/-/ffiasm-0.1.1.tgz",
|
||||||
"integrity": "sha512-o/CL7F4IodB7eRHCOQL1SrqN2DIPHrQbEwjPY7NIyeBRdnB3G0xo6b6Mj44SKiWFnvpQMb3n4N7acjD3vv4NVQ==",
|
"integrity": "sha512-irMMHiR9JJ7BVBrAhtliUawxVdPYSdyl81taUYJ4C1mJ0iw2ueThE/qtr0J8B83tsIY8HJvh0lg5F+6ClK4xpA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"big-integer": "^1.6.48",
|
"big-integer": "^1.6.48",
|
||||||
"ejs": "^3.0.1",
|
"ejs": "^3.0.1",
|
||||||
@@ -586,11 +581,24 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ffjavascript": {
|
"ffjavascript": {
|
||||||
"version": "0.1.2",
|
"version": "0.2.10",
|
||||||
"resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.10.tgz",
|
||||||
"integrity": "sha512-zB1dhgBjJlvyk2VQIQzFSpUJmanYQYDR/Fo1KhZnaNW5chMFJT55qz0dx1LMKrAklBbidKzz2/C7dgibxQF94g==",
|
"integrity": "sha512-GQI6gHYYG5/iD4Kt3VzezzK7fARJzP0zkc82V/+JAdjfeKBXhDSo5rpKFuK3cDcrdW0Fu2emuYNMEAuFqhEQvQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"big-integer": "^1.6.48"
|
"big-integer": "^1.6.48",
|
||||||
|
"wasmcurves": "0.0.5",
|
||||||
|
"worker-threads": "^1.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ffwasm": {
|
"ffwasm": {
|
||||||
@@ -773,21 +781,21 @@
|
|||||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||||
},
|
},
|
||||||
"inquirer": {
|
"inquirer": {
|
||||||
"version": "7.2.0",
|
"version": "7.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz",
|
||||||
"integrity": "sha512-E0c4rPwr9ByePfNlTIB8z51kK1s2n6jrHuJeEHENl/sbq2G/S1auvibgEwNR4uSyiU+PiYHqSwsgGiXjG8p5ZQ==",
|
"integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ansi-escapes": "^4.2.1",
|
"ansi-escapes": "^4.2.1",
|
||||||
"chalk": "^3.0.0",
|
"chalk": "^4.1.0",
|
||||||
"cli-cursor": "^3.1.0",
|
"cli-cursor": "^3.1.0",
|
||||||
"cli-width": "^2.0.0",
|
"cli-width": "^3.0.0",
|
||||||
"external-editor": "^3.0.3",
|
"external-editor": "^3.0.3",
|
||||||
"figures": "^3.0.0",
|
"figures": "^3.0.0",
|
||||||
"lodash": "^4.17.15",
|
"lodash": "^4.17.19",
|
||||||
"mute-stream": "0.0.8",
|
"mute-stream": "0.0.8",
|
||||||
"run-async": "^2.4.0",
|
"run-async": "^2.4.0",
|
||||||
"rxjs": "^6.5.3",
|
"rxjs": "^6.6.0",
|
||||||
"string-width": "^4.1.0",
|
"string-width": "^4.1.0",
|
||||||
"strip-ansi": "^6.0.0",
|
"strip-ansi": "^6.0.0",
|
||||||
"through": "^2.3.6"
|
"through": "^2.3.6"
|
||||||
@@ -804,9 +812,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"chalk": {
|
"chalk": {
|
||||||
"version": "3.0.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
|
||||||
"integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
|
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ansi-styles": "^4.1.0",
|
"ansi-styles": "^4.1.0",
|
||||||
@@ -979,9 +987,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lodash": {
|
"lodash": {
|
||||||
"version": "4.17.15",
|
"version": "4.17.19",
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
|
||||||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
|
"integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"mimic-fn": {
|
"mimic-fn": {
|
||||||
@@ -1056,9 +1064,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"onetime": {
|
"onetime": {
|
||||||
"version": "5.1.0",
|
"version": "5.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
|
||||||
"integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==",
|
"integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"mimic-fn": "^2.1.0"
|
"mimic-fn": "^2.1.0"
|
||||||
@@ -1154,25 +1162,27 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"r1csfile": {
|
"r1csfile": {
|
||||||
"version": "0.0.5",
|
"version": "0.0.14",
|
||||||
"resolved": "https://registry.npmjs.org/r1csfile/-/r1csfile-0.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/r1csfile/-/r1csfile-0.0.14.tgz",
|
||||||
"integrity": "sha512-B+BdKPb/WUTp4N/3X4d1Spgx9Ojx5tFVejGZRJxpTtzq34mC8Vi/czWfiPj85V8kud31lCfYcZ16z7+czvM0Sw==",
|
"integrity": "sha512-7m4eWpnbjkwGGUaRmIAJc4w+HvaeBPJXUKHIqLkHeD9Yyjem6/EHmlgDVl+4hWNWGZqdhXuMqWSH9+O6QOXBdw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"fastfile": "0.0.1",
|
"fastfile": "0.0.7",
|
||||||
"ffjavascript": "0.1.0"
|
"ffjavascript": "0.2.4"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fastfile": {
|
"fastfile": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/fastfile/-/fastfile-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/fastfile/-/fastfile-0.0.7.tgz",
|
||||||
"integrity": "sha512-Fk8PWafGWGEUw7oPq/dJen92ASxknCEy4ZC8n4VEvSwCp/jcReyEmVoWsRIWTf+IvAp2MzvFi54vOPeK2LQZtQ=="
|
"integrity": "sha512-Zk7sdqsV6DsN/rhjULDfCCowPiMDsziTMFicdkrKN80yybr/6YFf9H91ELXN85dVEf6EYkVR5EHkZNc0dMqZKA=="
|
||||||
},
|
},
|
||||||
"ffjavascript": {
|
"ffjavascript": {
|
||||||
"version": "0.1.0",
|
"version": "0.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.4.tgz",
|
||||||
"integrity": "sha512-dmKlUasSfvUcxBm8nCSKl2x7EFJsXA7OVP8XLFA03T2+6mAc3IiVLC2ambEVOcMOhyhl0vJfVZjM9f9d38D1rw==",
|
"integrity": "sha512-XFeWcjUDFPavN+DDOxhE8p5MOhZQJc9oO1Sj4ml1pyjqNhS1ujEamcjFyK0cctdnat61i7lvpTYzdtS3RYDC8w==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"big-integer": "^1.6.48"
|
"big-integer": "^1.6.48",
|
||||||
|
"wasmcurves": "0.0.4",
|
||||||
|
"worker-threads": "^1.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1224,9 +1234,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"rxjs": {
|
"rxjs": {
|
||||||
"version": "6.6.0",
|
"version": "6.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.2.tgz",
|
||||||
"integrity": "sha512-3HMA8z/Oz61DUHe+SdOiQyzIf4tOx5oQHmMir7IZEu6TMqCLHT4LRcmNaUS0NwOz8VLvmmBduMsoaUvMaIiqzg==",
|
"integrity": "sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"tslib": "^1.9.0"
|
"tslib": "^1.9.0"
|
||||||
@@ -1324,9 +1334,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip-json-comments": {
|
"strip-json-comments": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
|
||||||
"integrity": "sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w==",
|
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"supports-color": {
|
"supports-color": {
|
||||||
@@ -1472,6 +1482,15 @@
|
|||||||
"big-integer": "^1.6.48"
|
"big-integer": "^1.6.48"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"wasmcurves": {
|
||||||
|
"version": "0.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/wasmcurves/-/wasmcurves-0.0.4.tgz",
|
||||||
|
"integrity": "sha512-c/Tob+F/7jJhep1b2qtj54r4nkGaRifNbQ1OJx8cBBFH1RlHbWIbISHWONClOxiVwy/JZOpbN4SgvSX/4lF80A==",
|
||||||
|
"requires": {
|
||||||
|
"big-integer": "^1.6.42",
|
||||||
|
"blakejs": "^1.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"which": {
|
"which": {
|
||||||
"version": "1.3.1",
|
"version": "1.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
|
||||||
@@ -1492,6 +1511,11 @@
|
|||||||
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
|
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
|
||||||
"dev": true
|
"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": {
|
"wrap-ansi": {
|
||||||
"version": "6.2.0",
|
"version": "6.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
|
||||||
@@ -1546,9 +1570,9 @@
|
|||||||
"integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w=="
|
"integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w=="
|
||||||
},
|
},
|
||||||
"yargs": {
|
"yargs": {
|
||||||
"version": "15.3.1",
|
"version": "15.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
|
||||||
"integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==",
|
"integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"cliui": "^6.0.0",
|
"cliui": "^6.0.0",
|
||||||
"decamelize": "^1.2.0",
|
"decamelize": "^1.2.0",
|
||||||
@@ -1560,7 +1584,7 @@
|
|||||||
"string-width": "^4.2.0",
|
"string-width": "^4.2.0",
|
||||||
"which-module": "^2.0.0",
|
"which-module": "^2.0.0",
|
||||||
"y18n": "^4.0.0",
|
"y18n": "^4.0.0",
|
||||||
"yargs-parser": "^18.1.1"
|
"yargs-parser": "^18.1.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"yargs-parser": {
|
"yargs-parser": {
|
||||||
|
|||||||
12
package.json
12
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "circom",
|
"name": "circom",
|
||||||
"version": "0.5.12",
|
"version": "0.5.23",
|
||||||
"description": "Language to generate logic circuits",
|
"description": "Language to generate logic circuits",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"directories": {
|
"directories": {
|
||||||
@@ -30,13 +30,13 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chai": "^4.2.0",
|
"chai": "^4.2.0",
|
||||||
"circom_runtime": "0.0.6",
|
"circom_runtime": "0.1.5",
|
||||||
"fastfile": "0.0.2",
|
"fastfile": "0.0.12",
|
||||||
"ffiasm": "0.0.2",
|
"ffiasm": "0.1.1",
|
||||||
"ffjavascript": "0.1.2",
|
"ffjavascript": "0.2.10",
|
||||||
"ffwasm": "0.0.7",
|
"ffwasm": "0.0.7",
|
||||||
"fnv-plus": "^1.3.1",
|
"fnv-plus": "^1.3.1",
|
||||||
"r1csfile": "0.0.5",
|
"r1csfile": "0.0.14",
|
||||||
"tmp-promise": "^2.0.2",
|
"tmp-promise": "^2.0.2",
|
||||||
"wasmbuilder": "0.0.10"
|
"wasmbuilder": "0.0.10"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
const streamFromMultiArray = require("../../src/streamfromarray_txt.js");
|
|
||||||
const utils = require("../../src/utils");
|
const utils = require("../../src/utils");
|
||||||
const assert = require("assert");
|
const assert = require("assert");
|
||||||
const Scalar = require("ffjavascript").Scalar;
|
const Scalar = require("ffjavascript").Scalar;
|
||||||
const F1Field = require("ffjavascript").F1Field;
|
const F1Field = require("ffjavascript").F1Field;
|
||||||
|
const BigArray = require("../../src/bigarray");
|
||||||
|
|
||||||
function ref2src(c) {
|
function ref2src(c) {
|
||||||
if ((c[0] == "R")||(c[0] == "RI")) {
|
if ((c[0] == "R")||(c[0] == "RI")) {
|
||||||
@@ -95,6 +95,10 @@ class CodeBuilderC {
|
|||||||
this.ops.push({op: "CHECKCONSTRAINT", a, b, strErr});
|
this.ops.push({op: "CHECKCONSTRAINT", a, b, strErr});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkAssert(a, strErr) {
|
||||||
|
this.ops.push({op: "CHECKASSERT", a, strErr});
|
||||||
|
}
|
||||||
|
|
||||||
log(val) {
|
log(val) {
|
||||||
this.ops.push({op: "LOG", val});
|
this.ops.push({op: "LOG", val});
|
||||||
}
|
}
|
||||||
@@ -215,6 +219,8 @@ class CodeBuilderC {
|
|||||||
code.push(`${o.fnName}(ctx, ${o.retLabel}, ${o.params.join(",")});`);
|
code.push(`${o.fnName}(ctx, ${o.retLabel}, ${o.params.join(",")});`);
|
||||||
} else if (o.op == "CHECKCONSTRAINT") {
|
} else if (o.op == "CHECKCONSTRAINT") {
|
||||||
code.push(`ctx->checkConstraint(__cIdx, ${ref2src(o.a)}, ${ref2src(o.b)}, "${o.strErr}");`);
|
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") {
|
} else if (o.op == "LOG") {
|
||||||
code.push(`ctx->log(${ref2src(o.val)});`);
|
code.push(`ctx->log(${ref2src(o.val)});`);
|
||||||
}
|
}
|
||||||
@@ -341,16 +347,23 @@ class FunctionBuilderC {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class BuilderC {
|
class BuilderC {
|
||||||
constructor(p) {
|
constructor(p, verbose) {
|
||||||
this.F = new F1Field(p);
|
this.F = new F1Field(p);
|
||||||
|
|
||||||
this.hashMaps={};
|
this.hashMaps={};
|
||||||
this.componentEntriesTables={};
|
this.componentEntriesTables=new BigArray();
|
||||||
this.sizes ={};
|
this.sizes ={};
|
||||||
this.constants = [];
|
this.constants = [];
|
||||||
this.functions = [];
|
this.functions = [];
|
||||||
this.components = [];
|
this.components = new BigArray();
|
||||||
this.usedConstants = {};
|
this.usedConstants = {};
|
||||||
|
this.verbose = verbose;
|
||||||
|
|
||||||
|
|
||||||
|
this.sizePointers = {};
|
||||||
|
this.hashMapPointers = {};
|
||||||
|
this.functionIdx = {};
|
||||||
|
this.nCets = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
setHeader(header) {
|
setHeader(header) {
|
||||||
@@ -362,8 +375,11 @@ class BuilderC {
|
|||||||
this.hashMaps[name] = hm;
|
this.hashMaps[name] = hm;
|
||||||
}
|
}
|
||||||
|
|
||||||
addComponentEntriesTable(name, cet) {
|
addComponentEntriesTable(name, cet, idComponent) {
|
||||||
this.componentEntriesTables[name] = cet;
|
this.componentEntriesTables[idComponent] = {
|
||||||
|
name: name,
|
||||||
|
cet: cet
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
addSizes(name, accSizes) {
|
addSizes(name, accSizes) {
|
||||||
@@ -409,8 +425,8 @@ class BuilderC {
|
|||||||
|
|
||||||
_buildHeader(code) {
|
_buildHeader(code) {
|
||||||
code.push(
|
code.push(
|
||||||
"#include \"circom.h\"",
|
"#include \"circom.hpp\"",
|
||||||
"#include \"calcwit.h\"",
|
"#include \"calcwit.hpp\"",
|
||||||
`#define NSignals ${this.header.NSignals}`,
|
`#define NSignals ${this.header.NSignals}`,
|
||||||
`#define NComponents ${this.header.NComponents}`,
|
`#define NComponents ${this.header.NComponents}`,
|
||||||
`#define NOutputs ${this.header.NOutputs}`,
|
`#define NOutputs ${this.header.NOutputs}`,
|
||||||
@@ -421,67 +437,91 @@ 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 ) {
|
for (let hmName in this.hashMaps ) {
|
||||||
|
|
||||||
|
while (fdData.pos % 8) fdData.pos++;
|
||||||
|
this.hashMapPointers[hmName] = fdData.pos;
|
||||||
const hm = this.hashMaps[hmName];
|
const hm = this.hashMaps[hmName];
|
||||||
|
|
||||||
let c = `Circom_HashEntry ${hmName}[256] = {`;
|
|
||||||
for (let i=0; i<256; i++) {
|
for (let i=0; i<256; i++) {
|
||||||
c += i>0 ? "," : "";
|
buffV.setUint32(i*12, hm[i] ? parseInt( hm[i][0].slice(8), 16 ) : 0, true);
|
||||||
if (hm[i]) {
|
buffV.setUint32(i*12+4, hm[i] ? parseInt( hm[i][0].slice(0,8), 16 ) : 0, true);
|
||||||
c += `{0x${hm[i][0]}LL, ${hm[i][1]}} /* ${hm[i][2]} */`;
|
buffV.setUint32(i*12+8, hm[i] ? hm[i][1] : 0, true);
|
||||||
} else {
|
|
||||||
c += "{0,0}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
c += "};";
|
|
||||||
code.push(c);
|
await fdData.write(buff);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_buildComponentEntriesTables(code) {
|
async _buildComponentEntriesTables(fdData) {
|
||||||
code.push("// Component Entry tables");
|
|
||||||
for (let cetName in this.componentEntriesTables) {
|
while (fdData.pos % 8) fdData.pos++;
|
||||||
const cet = this.componentEntriesTables[cetName];
|
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++) {
|
for (let j=0; j<cet.length; j++) {
|
||||||
const ty = cet[j].type == "S" ? "_typeSignal" : "_typeComponent";
|
utils.setUint64(buffV, 16*j+0, this.sizePointers[ cet[j].sizeName]);
|
||||||
code.push(` ${j>0?",":" "}{${cet[j].offset},${cet[j].sizeName}, ${ty}}`);
|
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) {
|
async _buildSizes(fdData) {
|
||||||
code.push("// Sizes");
|
|
||||||
for (let sName in this.sizes) {
|
for (let sName in this.sizes) {
|
||||||
const accSizes = this.sizes[sName];
|
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++) {
|
for (let i=0; i<accSizes.length; i++) {
|
||||||
if (i>0) c += ",";
|
buffV.setUint32(i*4, accSizes[i], true);
|
||||||
c += accSizes[i];
|
|
||||||
}
|
}
|
||||||
c += "};";
|
await fdData.write(buff);
|
||||||
code.push(c);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_buildConstants(code) {
|
|
||||||
|
async _buildConstants(fdData) {
|
||||||
const self = this;
|
const self = this;
|
||||||
|
|
||||||
code.push("// Constants");
|
const frSize = (8 + self.F.n64*8);
|
||||||
code.push(`FrElement _constants[${self.constants.length}] = {`);
|
const buff = new Uint8Array(self.constants.length* frSize);
|
||||||
for (let i=0; i<self.constants.length; i++) {
|
const buffV = new DataView(buff.buffer);
|
||||||
code.push((i>0 ? "," : " ") + "{" + number2Code(self.constants[i]) + "}");
|
|
||||||
}
|
|
||||||
code.push("};");
|
|
||||||
|
|
||||||
function number2Code(n) {
|
|
||||||
|
while (fdData.pos % 8) fdData.pos++;
|
||||||
|
this.pConstants = fdData.pos;
|
||||||
|
|
||||||
|
let o = 0;
|
||||||
|
for (let i=0; i<self.constants.length; i++) {
|
||||||
|
Fr2Bytes(buffV, o, self.constants[i]);
|
||||||
|
o += frSize;
|
||||||
|
}
|
||||||
|
await fdData.write(buff);
|
||||||
|
|
||||||
|
|
||||||
|
function Fr2Bytes(buffV, offset, n) {
|
||||||
const minShort = self.F.neg(self.F.e("80000000"));
|
const minShort = self.F.neg(self.F.e("80000000"));
|
||||||
const maxShort = self.F.e("7FFFFFFF", 16);
|
const maxShort = self.F.e("7FFFFFFF", 16);
|
||||||
|
|
||||||
@@ -489,51 +529,49 @@ class BuilderC {
|
|||||||
&&(self.F.leq(n, maxShort)))
|
&&(self.F.leq(n, maxShort)))
|
||||||
{
|
{
|
||||||
if (self.F.geq(n, self.F.zero)) {
|
if (self.F.geq(n, self.F.zero)) {
|
||||||
return addShortMontgomeryPositive(n);
|
return shortMontgomeryPositive(n);
|
||||||
} else {
|
} else {
|
||||||
return addShortMontgomeryNegative(n);
|
return shortMontgomeryNegative(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return addLongMontgomery(n);
|
return longMontgomery(n);
|
||||||
|
|
||||||
|
|
||||||
function addShortMontgomeryPositive(a) {
|
function shortMontgomeryPositive(a) {
|
||||||
return `${a.toString()}, 0x40000000, { ${getLongString(toMontgomery(a))} }`;
|
buffV.setUint32(offset, Scalar.toNumber(a) , true );
|
||||||
|
buffV.setUint32(offset + 4, 0x40000000 , true );
|
||||||
|
long(buffV, offset + 8, toMontgomery(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function addShortMontgomeryNegative(a) {
|
function shortMontgomeryNegative(a) {
|
||||||
const b = -Scalar.toNumber(self.F.neg(a));
|
const b = -Scalar.toNumber(self.F.neg(a));
|
||||||
return `${b.toString()}, 0x40000000, { ${getLongString(toMontgomery(a))} }`;
|
buffV.setUint32(offset, b , true );
|
||||||
|
buffV.setUint32(offset + 4, 0x40000000 , true );
|
||||||
|
long(buffV, offset + 8, toMontgomery(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
function addLongMontgomery(a) {
|
function longMontgomery(a) {
|
||||||
return `0, 0xC0000000, { ${getLongString(toMontgomery(a))} }`;
|
buffV.setUint32(offset, 0 , true );
|
||||||
|
buffV.setUint32(offset + 4, 0xC0000000 , true );
|
||||||
|
long(buffV, offset + 8, toMontgomery(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
function getLongString(a) {
|
function long(buffV, offset, a) {
|
||||||
let S = "";
|
|
||||||
|
let p = offset;
|
||||||
const arr = Scalar.toArray(a, 0x100000000);
|
const arr = Scalar.toArray(a, 0x100000000);
|
||||||
for (let i=0; i<self.F.n64*2; i+=2) {
|
for (let i=0; i<self.F.n64*2; i++) {
|
||||||
const idx = arr.length-2-i;
|
const idx = arr.length-1-i;
|
||||||
|
|
||||||
if (i>0) S = S + ",";
|
|
||||||
|
|
||||||
if ( idx >=0) {
|
if ( idx >=0) {
|
||||||
let msb = arr[idx].toString(16);
|
buffV.setUint32(p, arr[idx], true);
|
||||||
while (msb.length<8) msb = "0" + msb;
|
|
||||||
|
|
||||||
let lsb = arr[idx+1].toString(16);
|
|
||||||
while (lsb.length<8) lsb = "0" + lsb;
|
|
||||||
|
|
||||||
S += "0x" + msb + lsb + "LL";
|
|
||||||
} else {
|
} else {
|
||||||
S += "0LL";
|
buffV.setUint32(p, 0, true);
|
||||||
}
|
}
|
||||||
|
p+= 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
return S;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function toMontgomery(a) {
|
function toMontgomery(a) {
|
||||||
@@ -541,98 +579,143 @@ class BuilderC {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_buildFunctions(code) {
|
_buildFunctions(code) {
|
||||||
|
const listedFunctions = [];
|
||||||
for (let i=0; i<this.functions.length; i++) {
|
for (let i=0; i<this.functions.length; i++) {
|
||||||
const cfb = this.functions[i];
|
const cfb = this.functions[i];
|
||||||
cfb.build(code);
|
cfb.build(code);
|
||||||
|
if (this.functions[i].type == "COMPONENT") {
|
||||||
|
this.functionIdx[this.functions[i].name] = listedFunctions.length;
|
||||||
|
listedFunctions.push(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
_buildComponents(code) {
|
code.push("// Function Table");
|
||||||
code.push("// Components");
|
code.push(`Circom_ComponentFunction _functionTable[${listedFunctions.length}] = {`);
|
||||||
code.push(`Circom_Component _components[${this.components.length}] = {`);
|
for (let i=0; i<listedFunctions.length; i++) {
|
||||||
for (let i=0; i<this.components.length; i++) {
|
|
||||||
const c = this.components[i];
|
|
||||||
const sep = i>0 ? " ," : " ";
|
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("};");
|
code.push("};");
|
||||||
}
|
}
|
||||||
|
|
||||||
_buildMapIsInput(code) {
|
|
||||||
code.push("// mapIsInput");
|
async _buildComponents(fdData) {
|
||||||
code.push(`u32 _mapIsInput[${this.mapIsInput.length}] = {`);
|
|
||||||
let line = "";
|
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++) {
|
for (let i=0; i<this.mapIsInput.length; i++) {
|
||||||
line += i>0 ? ", " : " ";
|
if ((this.verbose)&&(i%1000000 ==0)) console.log(`_buildMapIsInput ${i}/${this.mapIsInput.length}`);
|
||||||
line += toHex(this.mapIsInput[i]);
|
|
||||||
if (((i+1) % 64)==0) {
|
|
||||||
code.push(" "+line);
|
|
||||||
line = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (line != "") code.push(" "+line);
|
|
||||||
code.push("};");
|
|
||||||
|
|
||||||
function toHex(number) {
|
buffV.setUint32(4*i, this.mapIsInput[i], true);
|
||||||
if (number < 0) number = 0xFFFFFFFF + number + 1;
|
|
||||||
let S=number.toString(16).toUpperCase();
|
|
||||||
while (S.length<8) S = "0" + S;
|
|
||||||
return "0x"+S;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await fdData.write(buff);
|
||||||
}
|
}
|
||||||
|
|
||||||
_buildWit2Sig(code) {
|
async _buildWit2Sig(fdData) {
|
||||||
code.push("// Witness to Signal Table");
|
|
||||||
code.push(`int _wit2sig[${this.wit2sig.length}] = {`);
|
const buff = new Uint8Array(this.wit2sig.length * 4);
|
||||||
let line = "";
|
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++) {
|
for (let i=0; i<this.wit2sig.length; i++) {
|
||||||
line += i>0 ? "," : " ";
|
if ((this.verbose)&&(i%1000000 ==0)) console.log(`_buildWit2Sig ${i}/${this.wit2sig.length}`);
|
||||||
line += this.wit2sig[i];
|
|
||||||
if (((i+1) % 64) == 0) {
|
buffV.setUint32(4*i, this.wit2sig[i], true);
|
||||||
code.push(" "+line);
|
}
|
||||||
line = "";
|
|
||||||
|
await fdData.write(buff);
|
||||||
|
}
|
||||||
|
|
||||||
|
async _buildCircuitVar(fdData) {
|
||||||
|
|
||||||
|
const pP = fdData.pos;
|
||||||
|
|
||||||
|
const strBuff = new TextEncoder("utf-8").encode(this.header.P.toString());
|
||||||
|
await fdData.write(strBuff);
|
||||||
|
|
||||||
|
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, pP, 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 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);
|
||||||
|
await this._buildSizes(fdData);
|
||||||
|
await this._buildConstants(fdData);
|
||||||
|
await this._buildHashMaps(fdData);
|
||||||
|
await this._buildComponentEntriesTables(fdData);
|
||||||
|
this._buildFunctions(code);
|
||||||
|
await this._buildComponents(fdData);
|
||||||
|
await this._buildMapIsInput(fdData);
|
||||||
|
await this._buildWit2Sig(fdData);
|
||||||
|
await this._buildCircuitVar(fdData);
|
||||||
|
await writeCode(code);
|
||||||
|
|
||||||
|
async function writeCode(c) {
|
||||||
|
if (c.push) {
|
||||||
|
for (let i=0; i<c.length; i++) {
|
||||||
|
await writeCode(c[i]);
|
||||||
|
}
|
||||||
|
} else if (typeof c === "string") {
|
||||||
|
await fdCode.write(encoder.encode(c + "\n"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (line != "") code.push(" "+line);
|
|
||||||
code.push("};");
|
|
||||||
}
|
|
||||||
|
|
||||||
_buildCircuitVar(code) {
|
|
||||||
|
|
||||||
code.push(
|
|
||||||
"// Circuit Variable",
|
|
||||||
"Circom_Circuit _circuit = {" ,
|
|
||||||
" NSignals,",
|
|
||||||
" NComponents,",
|
|
||||||
" NInputs,",
|
|
||||||
" NOutputs,",
|
|
||||||
" NVars,",
|
|
||||||
" _wit2sig,",
|
|
||||||
" _components,",
|
|
||||||
" _mapIsInput,",
|
|
||||||
" _constants,",
|
|
||||||
" __P__",
|
|
||||||
"};"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
build() {
|
|
||||||
const code=[];
|
|
||||||
this._buildHeader(code);
|
|
||||||
this._buildSizes(code);
|
|
||||||
this._buildConstants(code);
|
|
||||||
this._buildHashMaps(code);
|
|
||||||
this._buildComponentEntriesTables(code);
|
|
||||||
this._buildFunctions(code);
|
|
||||||
this._buildComponents(code);
|
|
||||||
this._buildMapIsInput(code);
|
|
||||||
this._buildWit2Sig(code);
|
|
||||||
this._buildCircuitVar(code);
|
|
||||||
return streamFromMultiArray(code);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ const utils = require("../../src/utils");
|
|||||||
const loadR1cs = require("r1csfile").load;
|
const loadR1cs = require("r1csfile").load;
|
||||||
const ZqField = require("ffjavascript").ZqField;
|
const ZqField = require("ffjavascript").ZqField;
|
||||||
const buildZqField = require("ffiasm").buildZqField;
|
const buildZqField = require("ffiasm").buildZqField;
|
||||||
|
const fastFile = require("fastfile");
|
||||||
|
|
||||||
const {stringifyBigInts, unstringifyBigInts } = require("ffjavascript").utils;
|
const {stringifyBigInts, unstringifyBigInts } = require("ffjavascript").utils;
|
||||||
|
|
||||||
@@ -29,20 +30,24 @@ async function c_tester(circomFile, _options) {
|
|||||||
const baseName = path.basename(circomFile, ".circom");
|
const baseName = path.basename(circomFile, ".circom");
|
||||||
const options = Object.assign({}, _options);
|
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.symWriteStream = fs.createWriteStream(path.join(dir.path, baseName + ".sym"));
|
||||||
options.r1csFileName = path.join(dir.path, baseName + ".r1cs");
|
options.r1csFileName = path.join(dir.path, baseName + ".r1cs");
|
||||||
|
|
||||||
options.p = options.p || Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
options.p = options.p || Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
||||||
await compiler(circomFile, options);
|
await compiler(circomFile, options);
|
||||||
|
|
||||||
|
await options.cSourceFile.close();
|
||||||
|
await options.dataFile.close();
|
||||||
|
|
||||||
const source = await buildZqField(options.p, "Fr");
|
const source = await buildZqField(options.p, "Fr");
|
||||||
|
|
||||||
// console.log(dir.path);
|
// 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.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.hpp"), source.hpp, "utf8");
|
||||||
await fs.promises.writeFile(path.join(dir.path, "fr.c"), source.c, "utf8");
|
await fs.promises.writeFile(path.join(dir.path, "fr.cpp"), source.cpp, "utf8");
|
||||||
|
|
||||||
let pThread = "";
|
let pThread = "";
|
||||||
|
|
||||||
@@ -63,7 +68,7 @@ async function c_tester(circomFile, _options) {
|
|||||||
` ${path.join(cdir, "main.cpp")}` +
|
` ${path.join(cdir, "main.cpp")}` +
|
||||||
` ${path.join(cdir, "calcwit.cpp")}` +
|
` ${path.join(cdir, "calcwit.cpp")}` +
|
||||||
` ${path.join(cdir, "utils.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, "fr.o")}` +
|
||||||
` ${path.join(dir.path, baseName + ".cpp")} ` +
|
` ${path.join(dir.path, baseName + ".cpp")} ` +
|
||||||
` -o ${path.join(dir.path, baseName)}` +
|
` -o ${path.join(dir.path, baseName)}` +
|
||||||
|
|||||||
@@ -384,9 +384,9 @@ module.exports = function buildRuntime(module, builder) {
|
|||||||
"error",
|
"error",
|
||||||
c.i32_const(errs.ACCESSING_NOT_ASSIGNED_SIGNAL.code),
|
c.i32_const(errs.ACCESSING_NOT_ASSIGNED_SIGNAL.code),
|
||||||
c.i32_const(errs.ACCESSING_NOT_ASSIGNED_SIGNAL.pointer),
|
c.i32_const(errs.ACCESSING_NOT_ASSIGNED_SIGNAL.pointer),
|
||||||
c.i32_const(0),
|
c.getLocal("cIdx"),
|
||||||
c.i32_const(0),
|
c.getLocal("component"),
|
||||||
c.i32_const(0),
|
c.getLocal("signal"),
|
||||||
c.i32_const(0)
|
c.i32_const(0)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -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() {
|
function buildGetNVars() {
|
||||||
const f = module.addFunction("getNVars");
|
const f = module.addFunction("getNVars");
|
||||||
f.setReturnType("i32");
|
f.setReturnType("i32");
|
||||||
@@ -823,6 +852,7 @@ module.exports = function buildRuntime(module, builder) {
|
|||||||
buildComponentFinished();
|
buildComponentFinished();
|
||||||
|
|
||||||
buildCheckConstraint();
|
buildCheckConstraint();
|
||||||
|
buildCheckAssert();
|
||||||
|
|
||||||
buildGetNVars();
|
buildGetNVars();
|
||||||
buildGetFrLen();
|
buildGetFrLen();
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
const streamFromArrayTxt = require("../../src/streamfromarray_txt");
|
|
||||||
const streamFromArrayBin = require("../../src/streamfromarray_bin");
|
|
||||||
const assert = require("assert");
|
const assert = require("assert");
|
||||||
const ModuleBuilder = require("wasmbuilder").ModuleBuilder;
|
const ModuleBuilder = require("wasmbuilder").ModuleBuilder;
|
||||||
const ModuleBuilderWat = require("wasmbuilder").ModuleBuilderWat;
|
const ModuleBuilderWat = require("wasmbuilder").ModuleBuilderWat;
|
||||||
@@ -100,6 +98,9 @@ class CodeBuilderWasm {
|
|||||||
this.ops.push({op: "CHECKCONSTRAINT", a, b, strErr});
|
this.ops.push({op: "CHECKCONSTRAINT", a, b, strErr});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkAssert(a, strErr) {
|
||||||
|
this.ops.push({op: "CHECKASSERT", a, strErr});
|
||||||
|
}
|
||||||
|
|
||||||
concat(cb) {
|
concat(cb) {
|
||||||
this.ops.push(...cb.ops);
|
this.ops.push(...cb.ops);
|
||||||
@@ -334,6 +335,15 @@ class CodeBuilderWasm {
|
|||||||
c.i32_const(this.fnBuilder.builder.module.allocString(o.strErr))
|
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") {
|
} else if (o.op == "LOG") {
|
||||||
code.push(
|
code.push(
|
||||||
c.call(
|
c.call(
|
||||||
@@ -990,7 +1000,8 @@ class BuilderWasm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
build(outType) {
|
async build(fd, outType) {
|
||||||
|
const encoder = new TextEncoder("utf-8");
|
||||||
let module;
|
let module;
|
||||||
if (outType == "wasm") {
|
if (outType == "wasm") {
|
||||||
module=new ModuleBuilder();
|
module=new ModuleBuilder();
|
||||||
@@ -1017,12 +1028,25 @@ class BuilderWasm {
|
|||||||
|
|
||||||
module.setMemory(2000);
|
module.setMemory(2000);
|
||||||
if (outType == "wasm") {
|
if (outType == "wasm") {
|
||||||
return streamFromArrayBin(module.build());
|
const bytes = module.build();
|
||||||
|
const bytesArr = new Uint8Array(bytes);
|
||||||
|
await fd.write(bytesArr);
|
||||||
} else if (outType == "wat") {
|
} else if (outType == "wat") {
|
||||||
return streamFromArrayTxt(module.build());
|
const code = module.build();
|
||||||
|
await writeCode(code);
|
||||||
} else {
|
} else {
|
||||||
assert(false);
|
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"},
|
SIGNAL_ASSIGNED_TWICE: {code: 6, str: "Signal assigned twice"},
|
||||||
CONSTRAIN_DOES_NOT_MATCH: {code: 7, str: "Constraint doesn't match"},
|
CONSTRAIN_DOES_NOT_MATCH: {code: 7, str: "Constraint doesn't match"},
|
||||||
MAPISINPUT_DONT_MATCH: {code: 8, str: "MapIsInput don't match"},
|
MAPISINPUT_DONT_MATCH: {code: 8, str: "MapIsInput don't match"},
|
||||||
|
ASSERT_DOES_NOT_MATCH: {code: 9, str: "Assert not satisfied"},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ const compiler = require("../../src/compiler");
|
|||||||
const utils = require("../../src/utils");
|
const utils = require("../../src/utils");
|
||||||
const loadR1cs = require("r1csfile").load;
|
const loadR1cs = require("r1csfile").load;
|
||||||
const ZqField = require("ffjavascript").ZqField;
|
const ZqField = require("ffjavascript").ZqField;
|
||||||
|
const fastFile = require("fastfile");
|
||||||
|
|
||||||
const WitnessCalculatorBuilder = require("circom_runtime").WitnessCalculatorBuilder;
|
const WitnessCalculatorBuilder = require("circom_runtime").WitnessCalculatorBuilder;
|
||||||
|
|
||||||
@@ -24,16 +25,14 @@ async function wasm_tester(circomFile, _options) {
|
|||||||
const baseName = path.basename(circomFile, ".circom");
|
const baseName = path.basename(circomFile, ".circom");
|
||||||
const options = Object.assign({}, _options);
|
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.symWriteStream = fs.createWriteStream(path.join(dir.path, baseName + ".sym"));
|
||||||
options.r1csFileName = path.join(dir.path, baseName + ".r1cs");
|
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 compiler(circomFile, options);
|
||||||
|
|
||||||
await Promise.all(promisesArr);
|
await options.wasmFile.close();
|
||||||
|
|
||||||
const wasm = await fs.promises.readFile(path.join(dir.path, baseName + ".wasm"));
|
const wasm = await fs.promises.readFile(path.join(dir.path, baseName + ".wasm"));
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const SUBARRAY_SIZE = 0x10000;
|
const SUBARRAY_SIZE = 0x40000;
|
||||||
|
|
||||||
const BigArrayHandler = {
|
const BigArrayHandler = {
|
||||||
get: function(obj, prop) {
|
get: function(obj, prop) {
|
||||||
@@ -19,15 +19,17 @@ const BigArrayHandler = {
|
|||||||
class _BigArray {
|
class _BigArray {
|
||||||
constructor (initSize) {
|
constructor (initSize) {
|
||||||
this.length = initSize || 0;
|
this.length = initSize || 0;
|
||||||
this.arr = [];
|
this.arr = new Array(SUBARRAY_SIZE);
|
||||||
|
|
||||||
for (let i=0; i<initSize; i+=SUBARRAY_SIZE) {
|
for (let i=0; i<initSize; i+=SUBARRAY_SIZE) {
|
||||||
this.arr[i/SUBARRAY_SIZE] = new Array(Math.min(SUBARRAY_SIZE, initSize - i));
|
this.arr[i/SUBARRAY_SIZE] = new Array(Math.min(SUBARRAY_SIZE, initSize - i));
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
push (element) {
|
push () {
|
||||||
this.setElement (this.length, element);
|
for (let i=0; i<arguments.length; i++) {
|
||||||
|
this.setElement (this.length, arguments[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
getElement(idx) {
|
getElement(idx) {
|
||||||
idx = parseInt(idx);
|
idx = parseInt(idx);
|
||||||
@@ -39,13 +41,26 @@ class _BigArray {
|
|||||||
idx = parseInt(idx);
|
idx = parseInt(idx);
|
||||||
const idx1 = Math.floor(idx / SUBARRAY_SIZE);
|
const idx1 = Math.floor(idx / SUBARRAY_SIZE);
|
||||||
if (!this.arr[idx1]) {
|
if (!this.arr[idx1]) {
|
||||||
this.arr[idx1] = [];
|
this.arr[idx1] = new Array(SUBARRAY_SIZE);
|
||||||
}
|
}
|
||||||
const idx2 = idx % SUBARRAY_SIZE;
|
const idx2 = idx % SUBARRAY_SIZE;
|
||||||
this.arr[idx1][idx2] = value;
|
this.arr[idx1][idx2] = value;
|
||||||
if (idx >= this.length) this.length = idx+1;
|
if (idx >= this.length) this.length = idx+1;
|
||||||
return true;
|
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 {
|
class BigArray {
|
||||||
|
|||||||
42
src/build.js
42
src/build.js
@@ -21,6 +21,7 @@ const assert = require("assert");
|
|||||||
const utils = require("./utils");
|
const utils = require("./utils");
|
||||||
const gen = require("./gencode").gen;
|
const gen = require("./gencode").gen;
|
||||||
const createRefs = require("./gencode").createRefs;
|
const createRefs = require("./gencode").createRefs;
|
||||||
|
const BigArray = require("./bigarray");
|
||||||
|
|
||||||
module.exports = build;
|
module.exports = build;
|
||||||
|
|
||||||
@@ -37,28 +38,33 @@ function build(ctx) {
|
|||||||
ctx.addConstant(ctx.F.zero);
|
ctx.addConstant(ctx.F.zero);
|
||||||
ctx.addConstant(ctx.F.one);
|
ctx.addConstant(ctx.F.one);
|
||||||
|
|
||||||
|
if (ctx.verbose) console.log("buildHeader...");
|
||||||
buildHeader(ctx);
|
buildHeader(ctx);
|
||||||
|
if (ctx.verbose) console.log("buildEntryTables...");
|
||||||
buildEntryTables(ctx);
|
buildEntryTables(ctx);
|
||||||
ctx.globalNames = ctx.uniqueNames;
|
ctx.globalNames = ctx.uniqueNames;
|
||||||
|
|
||||||
|
if (ctx.verbose) console.log("buildCode...");
|
||||||
buildCode(ctx);
|
buildCode(ctx);
|
||||||
|
|
||||||
|
if (ctx.verbose) console.log("buildComponentsArray...");
|
||||||
buildComponentsArray(ctx);
|
buildComponentsArray(ctx);
|
||||||
|
|
||||||
|
if (ctx.verbose) console.log("buildMapIsInput...");
|
||||||
buildMapIsInput(ctx);
|
buildMapIsInput(ctx);
|
||||||
|
|
||||||
|
if (ctx.verbose) console.log("buildWit2Sig...");
|
||||||
buildWit2Sig(ctx);
|
buildWit2Sig(ctx);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildEntryTables(ctx) {
|
function buildEntryTables(ctx) {
|
||||||
|
|
||||||
const codes_hashMaps = [];
|
|
||||||
const codes_componentEntries = [];
|
|
||||||
const definedHashMaps = {};
|
const definedHashMaps = {};
|
||||||
for (let i=0; i<ctx.components.length; i++) {
|
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);
|
const {htName, htMap} = addHashTable(i);
|
||||||
|
|
||||||
let code = "";
|
|
||||||
const componentEntriesTableName = ctx.getUniqueName("_entryTable" + ctx.components[i].template);
|
const componentEntriesTableName = ctx.getUniqueName("_entryTable" + ctx.components[i].template);
|
||||||
|
|
||||||
const componentEntriesTable = [];
|
const componentEntriesTable = [];
|
||||||
@@ -72,34 +78,14 @@ function buildEntryTables(ctx) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.builder.addComponentEntriesTable(componentEntriesTableName, componentEntriesTable);
|
ctx.builder.addComponentEntriesTable(componentEntriesTableName, componentEntriesTable, i);
|
||||||
|
|
||||||
|
|
||||||
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.components[i].htName = htName;
|
ctx.components[i].htName = htName;
|
||||||
ctx.components[i].etName = componentEntriesTableName;
|
ctx.components[i].etName = componentEntriesTableName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return [
|
return;
|
||||||
"// HashMaps\n" ,
|
|
||||||
codes_hashMaps , "\n" ,
|
|
||||||
"\n" ,
|
|
||||||
"// Component Entries\n" ,
|
|
||||||
codes_componentEntries , "\n" ,
|
|
||||||
"\n"
|
|
||||||
];
|
|
||||||
|
|
||||||
function addHashTable(cIdx) {
|
function addHashTable(cIdx) {
|
||||||
const keys = Object.keys(ctx.components[cIdx].names.o);
|
const keys = Object.keys(ctx.components[cIdx].names.o);
|
||||||
@@ -131,6 +117,7 @@ function buildCode(ctx) {
|
|||||||
|
|
||||||
const fnComponents = [];
|
const fnComponents = [];
|
||||||
for (let i=0; i<ctx.components.length; i++) {
|
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 {h, instanceDef} = hashComponentCall(ctx, i);
|
||||||
const fName = ctx.components[i].template+"_"+h;
|
const fName = ctx.components[i].template+"_"+h;
|
||||||
if (!fDefined[fName]) {
|
if (!fDefined[fName]) {
|
||||||
@@ -180,6 +167,7 @@ function buildCode(ctx) {
|
|||||||
|
|
||||||
function buildComponentsArray(ctx) {
|
function buildComponentsArray(ctx) {
|
||||||
for (let i=0; i< ctx.components.length; i++) {
|
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;
|
let newThread;
|
||||||
if (ctx.newThreadTemplates) {
|
if (ctx.newThreadTemplates) {
|
||||||
if (ctx.newThreadTemplates.test(ctx.components[i].template)) {
|
if (ctx.newThreadTemplates.test(ctx.components[i].template)) {
|
||||||
@@ -217,6 +205,7 @@ function buildMapIsInput(ctx) {
|
|||||||
let map = [];
|
let map = [];
|
||||||
let acc = 0;
|
let acc = 0;
|
||||||
for (i=0; i<ctx.signals.length; i++) {
|
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) {
|
if (ctx.signals[i].o & ctx.IN) {
|
||||||
acc = acc | (1 << (i%32) );
|
acc = acc | (1 << (i%32) );
|
||||||
}
|
}
|
||||||
@@ -241,8 +230,9 @@ function buildWit2Sig(ctx) {
|
|||||||
ctx.totals[ctx.stPUBINPUT] +
|
ctx.totals[ctx.stPUBINPUT] +
|
||||||
ctx.totals[ctx.stPRVINPUT] +
|
ctx.totals[ctx.stPRVINPUT] +
|
||||||
ctx.totals[ctx.stINTERNAL];
|
ctx.totals[ctx.stINTERNAL];
|
||||||
const arr = Array(NVars);
|
const arr = new BigArray(NVars);
|
||||||
for (let i=0; i<ctx.signals.length; i++) {
|
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;
|
const outIdx = ctx.signals[i].id;
|
||||||
if (ctx.signals[i].e>=0) continue; // If has an alias, continue..
|
if (ctx.signals[i].e>=0) continue; // If has an alias, continue..
|
||||||
assert(typeof outIdx != "undefined", `Signal ${i} does not have index`);
|
assert(typeof outIdx != "undefined", `Signal ${i} does not have index`);
|
||||||
|
|||||||
329
src/compiler.js
329
src/compiler.js
@@ -28,8 +28,30 @@ const utils = require("./utils");
|
|||||||
const buildR1cs = require("./r1csfile").buildR1cs;
|
const buildR1cs = require("./r1csfile").buildR1cs;
|
||||||
const BigArray = require("./bigarray");
|
const BigArray = require("./bigarray");
|
||||||
const buildSyms = require("./buildsyms");
|
const buildSyms = require("./buildsyms");
|
||||||
|
const {performance} = require("perf_hooks");
|
||||||
|
|
||||||
module.exports = compile;
|
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) {
|
async function compile(srcFile, options) {
|
||||||
options.prime = options.prime || Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
options.prime = options.prime || Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
||||||
@@ -44,9 +66,12 @@ async function compile(srcFile, options) {
|
|||||||
ctx.mainComponent = options.mainComponent || "main";
|
ctx.mainComponent = options.mainComponent || "main";
|
||||||
ctx.newThreadTemplates = options.newThreadTemplates;
|
ctx.newThreadTemplates = options.newThreadTemplates;
|
||||||
|
|
||||||
|
measures.constructionPhase = -performance.now();
|
||||||
constructionPhase(ctx, srcFile);
|
constructionPhase(ctx, srcFile);
|
||||||
|
measures.constructionPhase += performance.now();
|
||||||
|
|
||||||
if (ctx.verbose) console.log("NConstraints Before: "+ctx.constraints.length);
|
if (ctx.verbose) console.log("NConstraints Before: "+ctx.constraints.length);
|
||||||
|
if (ctx.verbose) console.log("NSignals Before: "+ctx.signals.length);
|
||||||
|
|
||||||
if (ctx.error) {
|
if (ctx.error) {
|
||||||
throw(ctx.error);
|
throw(ctx.error);
|
||||||
@@ -57,72 +82,97 @@ async function compile(srcFile, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ctx.verbose) console.log("Classify Signals");
|
if (ctx.verbose) console.log("Classify Signals");
|
||||||
|
measures.classifySignals = -performance.now();
|
||||||
classifySignals(ctx);
|
classifySignals(ctx);
|
||||||
|
measures.classifySignals += performance.now();
|
||||||
|
|
||||||
if (ctx.verbose) console.log("Reduce Constants");
|
if (ctx.verbose) console.log("Reduce Constants");
|
||||||
|
measures.reduceConstants = -performance.now();
|
||||||
reduceConstants(ctx);
|
reduceConstants(ctx);
|
||||||
|
measures.reduceConstants += performance.now();
|
||||||
|
|
||||||
if (options.reduceConstraints) {
|
if (options.reduceConstraints) {
|
||||||
|
|
||||||
if (ctx.verbose) console.log("Reduce Constraints");
|
if (ctx.verbose) console.log("Reduce Constraints");
|
||||||
// Repeat while reductions are performed
|
// Repeat while reductions are performed
|
||||||
|
/*
|
||||||
let oldNConstrains = -1;
|
let oldNConstrains = -1;
|
||||||
while (ctx.constraints.length != oldNConstrains) {
|
while (ctx.constraints.length != oldNConstrains) {
|
||||||
if (ctx.verbose) console.log("Reducing constraints: "+ctx.constraints.length);
|
if (ctx.verbose) console.log("Reducing constraints: "+ctx.constraints.length);
|
||||||
oldNConstrains = ctx.constraints.length;
|
oldNConstrains = ctx.constraints.length;
|
||||||
reduceConstrains(ctx);
|
reduceConstrains(ctx);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
measures.reduceConstraints = -performance.now();
|
||||||
|
await reduceConstrains(ctx);
|
||||||
|
measures.reduceConstraints += performance.now();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx.verbose) console.log("NConstraints After: "+ctx.constraints.length);
|
if (ctx.verbose) console.log("NConstraints After: "+ctx.constraints.length);
|
||||||
|
|
||||||
|
measures.generateWitnessNames = -performance.now();
|
||||||
generateWitnessNames(ctx);
|
generateWitnessNames(ctx);
|
||||||
|
measures.generateWitnessNames += performance.now();
|
||||||
|
|
||||||
if (ctx.error) {
|
if (ctx.error) {
|
||||||
throw(ctx.error);
|
throw(ctx.error);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.cSourceWriteStream) {
|
if (options.r1csFileName) {
|
||||||
if (ctx.verbose) console.log("Generating c...");
|
measures.generateR1cs = -performance.now();
|
||||||
ctx.builder = new BuilderC(options.prime);
|
await buildR1cs(ctx, options.r1csFileName);
|
||||||
build(ctx);
|
measures.generateR1cs += performance.now();
|
||||||
const rdStream = ctx.builder.build();
|
|
||||||
rdStream.pipe(options.cSourceWriteStream);
|
|
||||||
|
|
||||||
// await new Promise(fulfill => options.cSourceWriteStream.on("finish", fulfill));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((options.wasmWriteStream)||(options.watWriteStream)) {
|
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);
|
||||||
|
await ctx.builder.build(options.cSourceFile, options.dataFile);
|
||||||
|
measures.generateC += performance.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx.error) throw(ctx.error);
|
||||||
|
|
||||||
|
if ((options.wasmFile)||(options.watFile)) {
|
||||||
if (ctx.verbose) console.log("Generating wasm...");
|
if (ctx.verbose) console.log("Generating wasm...");
|
||||||
|
measures.generateWasm = -performance.now();
|
||||||
ctx.builder = new BuilderWasm(options.prime);
|
ctx.builder = new BuilderWasm(options.prime);
|
||||||
build(ctx);
|
build(ctx);
|
||||||
if (options.wasmWriteStream) {
|
if (options.wasmFile) {
|
||||||
const rdStream = ctx.builder.build("wasm");
|
await ctx.builder.build(options.wasmFile, "wasm");
|
||||||
rdStream.pipe(options.wasmWriteStream);
|
|
||||||
}
|
}
|
||||||
if (options.watWriteStream) {
|
if (options.watFile) {
|
||||||
const rdStream = ctx.builder.build("wat");
|
await ctx.builder.build(options.watFile, "wat");
|
||||||
rdStream.pipe(options.watWriteStream);
|
|
||||||
}
|
}
|
||||||
|
measures.generateWasm += performance.now();
|
||||||
// await new Promise(fulfill => options.wasmWriteStream.on("finish", fulfill));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// const mainCode = gen(ctx,ast);
|
// const mainCode = gen(ctx,ast);
|
||||||
if (ctx.error) throw(ctx.error);
|
if (ctx.error) throw(ctx.error);
|
||||||
|
|
||||||
if (options.r1csFileName) {
|
|
||||||
await buildR1cs(ctx, options.r1csFileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.symWriteStream) {
|
if (options.symWriteStream) {
|
||||||
|
measures.generateSyms = -performance.now();
|
||||||
const rdStream = buildSyms(ctx);
|
const rdStream = buildSyms(ctx);
|
||||||
rdStream.pipe(options.symWriteStream);
|
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);
|
// const def = buildCircuitDef(ctx, mainCode);
|
||||||
|
|
||||||
|
if (ctx.verbose) {
|
||||||
|
for (let [mStr, mValue] of Object.entries(measures)) {
|
||||||
|
console.log(mStr + ": " + ms2String(mValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -148,6 +198,7 @@ function classifySignals(ctx) {
|
|||||||
|
|
||||||
// First classify the signals
|
// First classify the signals
|
||||||
for (let s=0; s<ctx.signals.length; s++) {
|
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];
|
const signal = ctx.signals[s];
|
||||||
let tAll = ctx.stINTERNAL;
|
let tAll = ctx.stINTERNAL;
|
||||||
let lSignal = signal;
|
let lSignal = signal;
|
||||||
@@ -251,7 +302,239 @@ function reduceConstants(ctx) {
|
|||||||
ctx.constraints = newConstraints;
|
ctx.constraints = newConstraints;
|
||||||
}
|
}
|
||||||
|
|
||||||
function reduceConstrains(ctx) {
|
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].push(i);
|
||||||
|
insertedSig[s] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let s in c.b.coefs) {
|
||||||
|
if (!insertedSig[s]) {
|
||||||
|
if (!sig2constraint[s]) sig2constraint[s] = [];
|
||||||
|
sig2constraint[s].push(i);
|
||||||
|
insertedSig[s] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let s in c.c.coefs) {
|
||||||
|
if (!insertedSig[s]) {
|
||||||
|
if (!sig2constraint[s]) sig2constraint[s] = [];
|
||||||
|
sig2constraint[s].push(i);
|
||||||
|
insertedSig[s] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
possibleConstraints[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (possibleConstraints.length >0) {
|
||||||
|
nextPossibleConstraints = new BigArray();
|
||||||
|
removedSignals = new BigArray();
|
||||||
|
nRemoved = 0;
|
||||||
|
lIdx = new BigArray();
|
||||||
|
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;
|
||||||
|
|
||||||
|
// Swap a and b if b has more variables.
|
||||||
|
if (Object.keys(c.b).length > Object.keys(c.a).length) {
|
||||||
|
const aux = c.a;
|
||||||
|
c.a=c.b;
|
||||||
|
c.b=aux;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mov to C if possible.
|
||||||
|
if (isConstant(c.a)) {
|
||||||
|
const ct = {t: "N", v: c.a.coefs[sONE]};
|
||||||
|
c.c = ctx.lc.add(ctx.lc.mul(c.b, ct), c.c);
|
||||||
|
c.a = { t: "LC", coefs: {} };
|
||||||
|
c.b = { t: "LC", coefs: {} };
|
||||||
|
}
|
||||||
|
if (isConstant(c.b)) {
|
||||||
|
const ct = {t: "N", v: c.b.coefs[sONE]};
|
||||||
|
c.c = ctx.lc.add(ctx.lc.mul(c.a, ct), c.c);
|
||||||
|
c.a = { t: "LC", coefs: {} };
|
||||||
|
c.b = { t: "LC", coefs: {} };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx.lc.isZero(c.a) || ctx.lc.isZero(c.b)) {
|
||||||
|
const freeC = substituteRemoved(c.c);
|
||||||
|
const isolatedSignal = getFirstInternalSignal(ctx, freeC);
|
||||||
|
if (isolatedSignal) {
|
||||||
|
// console.log(isolatedSignal);
|
||||||
|
// console.log(freeC);
|
||||||
|
removedSignals[isolatedSignal] = isolateSignal(freeC, isolatedSignal);
|
||||||
|
if (lIdx[isolatedSignal]) {
|
||||||
|
lIdx[isolatedSignal].forEach( (s) => {
|
||||||
|
removedSignals[s] = substitute(removedSignals[s], isolatedSignal, removedSignals[isolatedSignal]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
addTolIdx(removedSignals[isolatedSignal], isolatedSignal);
|
||||||
|
ctx.constraints[possibleConstraints[i]] = null;
|
||||||
|
nRemoved ++;
|
||||||
|
|
||||||
|
sig2constraint[isolatedSignal].forEach( (s) => {
|
||||||
|
nextPossibleConstraints[s] = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nextPossibleConstraints = nextPossibleConstraints.getKeys();
|
||||||
|
|
||||||
|
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),
|
||||||
|
b: substituteRemoved(c.b),
|
||||||
|
c: substituteRemoved(c.c)
|
||||||
|
};
|
||||||
|
if (ctx.lc.isZero(nc)) {
|
||||||
|
delete ctx.constraints[nextPossibleConstraints[i]];
|
||||||
|
} else {
|
||||||
|
ctx.constraints[nextPossibleConstraints[i]] = nc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const removedSignalsList = removedSignals.getKeys;
|
||||||
|
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
|
||||||
|
lSignal.c = ctx.stDISCARDED;
|
||||||
|
}
|
||||||
|
|
||||||
|
possibleConstraints = nextPossibleConstraints;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)&&(!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) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newLc;
|
||||||
|
}
|
||||||
|
|
||||||
|
function substitute(lc, s, eq) {
|
||||||
|
if (!lc.coefs[s]) return lc;
|
||||||
|
const newLc = ctx.lc._clone(lc);
|
||||||
|
delete newLc.coefs[s];
|
||||||
|
for (let k2 in eq.coefs) {
|
||||||
|
const newP = ctx.F.mul(eq.coefs[k2], lc.coefs[s]);
|
||||||
|
if (!ctx.F.isZero(newP)) {
|
||||||
|
if (newLc.coefs[k2]) {
|
||||||
|
newLc.coefs[k2] = ctx.F.add(newLc.coefs[k2], newP);
|
||||||
|
if (ctx.F.isZero(newLc.coefs[k2])) delete newLc.coefs[k2];
|
||||||
|
} else {
|
||||||
|
newLc.coefs[k2] = newP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newLc;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isConstant(l) {
|
||||||
|
for (let k in l.coefs) {
|
||||||
|
if ((k != sONE) && (!ctx.F.isZero(l.coefs[k]))) return false;
|
||||||
|
}
|
||||||
|
if (!l.coefs[sONE] || ctx.F.isZero(l.coefs[sONE])) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addTolIdx(lc, newS) {
|
||||||
|
for (let s in lc.coefs) {
|
||||||
|
if (!lIdx[s]) lIdx[s] = [];
|
||||||
|
lIdx[s].push(newS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function reduceConstrains_old(ctx) {
|
||||||
indexVariables();
|
indexVariables();
|
||||||
let possibleConstraints = ctx.constraints;
|
let possibleConstraints = ctx.constraints;
|
||||||
let ii=0;
|
let ii=0;
|
||||||
|
|||||||
@@ -567,14 +567,18 @@ function execFunctionCall(ctx, ast) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ast.name == "assert") {
|
if (ast.name == "assert") {
|
||||||
|
ast.fileName = ctx.fileName;
|
||||||
|
ast.filePath = ctx.filePath;
|
||||||
|
|
||||||
const v = exec(ctx, ast.params[0]);
|
const v = exec(ctx, ast.params[0]);
|
||||||
const ev = val(ctx, v, ast);
|
const ev = val(ctx, v, ast);
|
||||||
if (ctx.F.isZero(ev)) return ctx.throwError(ast, "Assertion failed");
|
if ((typeof ev.v !== "undefined")&&(ctx.F.isZero(ev.v))) return ctx.throwError(ast, "Assertion failed");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fnc = ctx.functions[ast.name];
|
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 = [];
|
const paramValues = [];
|
||||||
for (let i=0; i< ast.params.length; i++) {
|
for (let i=0; i< ast.params.length; i++) {
|
||||||
|
|||||||
@@ -723,7 +723,15 @@ function genVarAssignment(ctx, ast, lRef, sels, rRef) {
|
|||||||
|
|
||||||
if (instantiated) {
|
if (instantiated) {
|
||||||
if (offset.used) {
|
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 {
|
} else {
|
||||||
ctx.codeBuilder.copyN(left.label, ["V", offset.value[0]], ["R", right.label], right.sizes[0]);
|
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));
|
ctx.codeBuilder.log(toRefA_Fr1(ctx, ast.params[0], vRef));
|
||||||
return 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 = [];
|
const params = [];
|
||||||
for (let i=0; i<ast.params.length; i++) {
|
for (let i=0; i<ast.params.length; i++) {
|
||||||
const pRef = gen(ctx, ast.params[i]);
|
const pRef = gen(ctx, ast.params[i]);
|
||||||
|
|||||||
@@ -123,6 +123,7 @@ class LCAlgebra {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_signal2lc(a) {
|
_signal2lc(a) {
|
||||||
|
const self = this;
|
||||||
if (a.t == "S") {
|
if (a.t == "S") {
|
||||||
const lc = {
|
const lc = {
|
||||||
t: "LC",
|
t: "LC",
|
||||||
|
|||||||
149
src/r1csfile.js
149
src/r1csfile.js
@@ -1,30 +1,36 @@
|
|||||||
|
|
||||||
const fastFile = require("fastfile");
|
const fastFile = require("fastfile");
|
||||||
const assert = require("assert");
|
const assert = require("assert");
|
||||||
|
const BigArray = require("./bigarray");
|
||||||
|
|
||||||
module.exports.buildR1cs = buildR1cs;
|
module.exports.buildR1cs = buildR1cs;
|
||||||
|
|
||||||
|
|
||||||
async function buildR1cs(ctx, fileName) {
|
async function buildR1cs(ctx, fileName) {
|
||||||
|
|
||||||
const fd = await fastFile.createOverride(fileName);
|
const fd = await fastFile.createOverride(fileName);
|
||||||
|
|
||||||
|
|
||||||
await fd.write(Buffer.from("r1cs"), 0); // Magic "r1cs"
|
const buffBigInt = new Uint8Array(ctx.F.n8);
|
||||||
|
|
||||||
let p = 4;
|
const type = "r1cs";
|
||||||
await writeU32(1); // Version
|
const buff = new Uint8Array(4);
|
||||||
await writeU32(3); // Number of Sections
|
for (let i=0; i<4; i++) buff[i] = type.charCodeAt(i);
|
||||||
|
await fd.write(buff, 0); // Magic "r1cs"
|
||||||
|
|
||||||
|
await fd.writeULE32(1); // Version
|
||||||
|
await fd.writeULE32(3); // Number of Sections
|
||||||
|
|
||||||
// Write the header
|
// Write the header
|
||||||
///////////
|
///////////
|
||||||
await writeU32(1); // Header type
|
await fd.writeULE32(1); // Header type
|
||||||
const pHeaderSize = p;
|
const pHeaderSize = fd.pos;
|
||||||
await writeU64(0); // Temporally set to 0 length
|
await fd.writeULE64(0); // Temporally set to 0 length
|
||||||
|
|
||||||
|
|
||||||
const n8 = (Math.floor( (ctx.F.bitLength - 1) / 64) +1)*8;
|
const n8 = (Math.floor( (ctx.F.bitLength - 1) / 64) +1)*8;
|
||||||
// Field Def
|
// Field Def
|
||||||
await writeU32(n8); // Temporally set to 0 length
|
await fd.writeULE32(n8); // Temporally set to 0 length
|
||||||
await writeBigInt(ctx.F.p);
|
await writeBigInt(ctx.F.p);
|
||||||
|
|
||||||
const NWires =
|
const NWires =
|
||||||
@@ -34,20 +40,20 @@ async function buildR1cs(ctx, fileName) {
|
|||||||
ctx.totals[ctx.stPRVINPUT] +
|
ctx.totals[ctx.stPRVINPUT] +
|
||||||
ctx.totals[ctx.stINTERNAL];
|
ctx.totals[ctx.stINTERNAL];
|
||||||
|
|
||||||
await writeU32(NWires);
|
await fd.writeULE32(NWires);
|
||||||
await writeU32(ctx.totals[ctx.stOUTPUT]);
|
await fd.writeULE32(ctx.totals[ctx.stOUTPUT]);
|
||||||
await writeU32(ctx.totals[ctx.stPUBINPUT]);
|
await fd.writeULE32(ctx.totals[ctx.stPUBINPUT]);
|
||||||
await writeU32(ctx.totals[ctx.stPRVINPUT]);
|
await fd.writeULE32(ctx.totals[ctx.stPRVINPUT]);
|
||||||
await writeU64(ctx.signals.length);
|
await fd.writeULE64(ctx.signals.length);
|
||||||
await writeU32(ctx.constraints.length);
|
await fd.writeULE32(ctx.constraints.length);
|
||||||
|
|
||||||
const headerSize = p - pHeaderSize - 8;
|
const headerSize = fd.pos - pHeaderSize - 8;
|
||||||
|
|
||||||
// Write constraints
|
// Write constraints
|
||||||
///////////
|
///////////
|
||||||
await writeU32(2); // Constraints type
|
await fd.writeULE32(2); // Constraints type
|
||||||
const pConstraintsSize = p;
|
const pConstraintsSize = fd.pos;
|
||||||
await writeU64(0); // Temporally set to 0 length
|
await fd.writeULE64(0); // Temporally set to 0 length
|
||||||
|
|
||||||
for (let i=0; i<ctx.constraints.length; i++) {
|
for (let i=0; i<ctx.constraints.length; i++) {
|
||||||
if ((ctx.verbose)&&(i%10000 == 0)) {
|
if ((ctx.verbose)&&(i%10000 == 0)) {
|
||||||
@@ -56,16 +62,16 @@ async function buildR1cs(ctx, fileName) {
|
|||||||
await writeConstraint(ctx.constraints[i]);
|
await writeConstraint(ctx.constraints[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const constraintsSize = p - pConstraintsSize - 8;
|
const constraintsSize = fd.pos - pConstraintsSize - 8;
|
||||||
|
|
||||||
// Write map
|
// Write map
|
||||||
///////////
|
///////////
|
||||||
await writeU32(3); // wires2label type
|
await fd.writeULE32(3); // wires2label type
|
||||||
const pMapSize = p;
|
const pMapSize = fd.pos;
|
||||||
await writeU64(0); // Temporally set to 0 length
|
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++) {
|
for (let i=0; i<ctx.signals.length; i++) {
|
||||||
const outIdx = ctx.signals[i].id;
|
const outIdx = ctx.signals[i].id;
|
||||||
if (ctx.signals[i].e>=0) continue; // If has an alias, continue..
|
if (ctx.signals[i].e>=0) continue; // If has an alias, continue..
|
||||||
@@ -76,75 +82,64 @@ async function buildR1cs(ctx, fileName) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (let i=0; i<arr.length; i++) {
|
for (let i=0; i<arr.length; i++) {
|
||||||
await writeU64(arr[i]);
|
await fd.writeULE64(arr[i]);
|
||||||
if ((ctx.verbose)&&(i%100000)) console.log("writing wire2label map: ", 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
|
// Write sizes
|
||||||
await writeU32(headerSize, pHeaderSize);
|
await fd.writeULE32(headerSize, pHeaderSize);
|
||||||
await writeU32(constraintsSize, pConstraintsSize);
|
await fd.writeULE32(constraintsSize, pConstraintsSize);
|
||||||
await writeU32(mapSize, pMapSize);
|
await fd.writeULE32(mapSize, pMapSize);
|
||||||
|
|
||||||
await fd.close();
|
await fd.close();
|
||||||
|
|
||||||
async function writeU32(v, pos) {
|
function writeConstraint(c) {
|
||||||
let o = (typeof pos == "undefined") ? p : pos;
|
const n8 = ctx.F.n8;
|
||||||
|
const idxA = Object.keys(c.a.coefs);
|
||||||
const b = Buffer.allocUnsafe(4);
|
const idxB = Object.keys(c.b.coefs);
|
||||||
b.writeInt32LE(v);
|
const idxC = Object.keys(c.c.coefs);
|
||||||
|
const buff = new Uint8Array((idxA.length+idxB.length+idxC.length)*(n8+4) + 12);
|
||||||
await fd.write(b, o);
|
const buffV = new DataView(buff.buffer);
|
||||||
|
let o=0;
|
||||||
if (typeof(pos) == "undefined") p += 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function writeU64(v, pos) {
|
|
||||||
let o = (typeof pos == "undefined") ? p : pos;
|
|
||||||
|
|
||||||
const b = Buffer.allocUnsafe(8);
|
|
||||||
|
|
||||||
const LSB = v & 0xFFFFFFFF;
|
|
||||||
const MSB = Math.floor(v / 0x100000000);
|
|
||||||
b.writeInt32LE(LSB, 0);
|
|
||||||
b.writeInt32LE(MSB, 4);
|
|
||||||
|
|
||||||
await fd.write(b, o);
|
|
||||||
|
|
||||||
if (typeof(pos) == "undefined") p += 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function writeConstraint(c) {
|
|
||||||
await writeLC(c.a);
|
|
||||||
await writeLC(c.b);
|
|
||||||
await writeLC(ctx.lc.neg(c.c));
|
|
||||||
}
|
|
||||||
|
|
||||||
async function writeLC(lc) {
|
|
||||||
const idxs = Object.keys(lc.coefs);
|
|
||||||
await writeU32(idxs.length);
|
|
||||||
for (let s in lc.coefs) {
|
|
||||||
let lSignal = ctx.signals[s];
|
|
||||||
|
|
||||||
|
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];
|
while (lSignal.e >=0 ) lSignal = ctx.signals[lSignal.e];
|
||||||
|
buffV.setUint32(o, lSignal.id, true); o+=4;
|
||||||
await writeU32(lSignal.id);
|
ctx.F.toRprLE(buff, o, c.a.coefs[coef]); o+=n8;
|
||||||
await writeBigInt(lc.coefs[s]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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];
|
||||||
|
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];
|
||||||
|
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) {
|
async function writeBigInt(n, pos) {
|
||||||
|
|
||||||
let o = (typeof pos == "undefined") ? p : pos;
|
ctx.F.toRprLE(buffBigInt, 0, n);
|
||||||
|
|
||||||
const s = n.toString(16);
|
await fd.write(buffBigInt, pos);
|
||||||
const b = Buffer.from(s.padStart(n8*2, "0"), "hex");
|
|
||||||
const buff = Buffer.allocUnsafe(b.length);
|
|
||||||
for (let i=0; i<b.length; i++) buff[i] = b[b.length-1-i];
|
|
||||||
|
|
||||||
await fd.write(buff, o);
|
|
||||||
|
|
||||||
if (typeof(pos) == "undefined") p += n8;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
const Readable = require("stream").Readable;
|
const Readable = require("stream").Readable;
|
||||||
|
|
||||||
module.exports = function streamFromArrayTxt(ma) {
|
module.exports = function streamFromArrayTxt(ma) {
|
||||||
@@ -22,7 +21,7 @@ module.exports = function streamFromArrayTxt(ma) {
|
|||||||
|
|
||||||
|
|
||||||
function getFirstIdx(ma) {
|
function getFirstIdx(ma) {
|
||||||
if (!Array.isArray(ma)) return [];
|
if (typeof ma.push !== "function" ) return [];
|
||||||
return [0, ...getFirstIdx(ma[0])];
|
return [0, ...getFirstIdx(ma[0])];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ module.exports.fnvHash = fnvHash;
|
|||||||
module.exports.sameSizes = sameSizes;
|
module.exports.sameSizes = sameSizes;
|
||||||
module.exports.isDefined = isDefined;
|
module.exports.isDefined = isDefined;
|
||||||
module.exports.accSizes2Str = accSizes2Str;
|
module.exports.accSizes2Str = accSizes2Str;
|
||||||
|
module.exports.setUint64 = setUint64;
|
||||||
|
|
||||||
function ident(text) {
|
function ident(text) {
|
||||||
if (typeof text === "string") {
|
if (typeof text === "string") {
|
||||||
@@ -90,6 +91,14 @@ function accSizes2Str(sizes) {
|
|||||||
return `[${sizes[0]/sizes[1]}]`+accSizes2Str(sizes.slice(1));
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user