diff --git a/cli.js b/cli.js index 4140623..232717f 100755 --- a/cli.js +++ b/cli.js @@ -24,6 +24,7 @@ const fs = require("fs"); const path = require("path"); const Scalar = require("ffjavascript").Scalar; +const stringifyBigInts = require("ffjavascript").utils.stringifyBigInts; const fastFile = require("fastfile"); const compiler = require("./src/compiler"); @@ -153,7 +154,7 @@ run().then(()=> { if (argv.verbose) console.log(err.stack); } if (err.ast) { - console.error(JSON.stringify(err.ast, null, 1)); + console.error(JSON.stringify(stringifyBigInts(err.ast), null, 1)); } process.exit(1); }); diff --git a/package-lock.json b/package-lock.json index e5a3c37..fd63735 100644 --- a/package-lock.json +++ b/package-lock.json @@ -203,11 +203,11 @@ "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" }, "circom_runtime": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/circom_runtime/-/circom_runtime-0.1.2.tgz", - "integrity": "sha512-qh1GsfxXLGAhLBcIQWrFHO/zu6kuXQQL1xC3+P8KRETvynTbBVSb1ul3dCiXyetm7lVNNdhb1/UoOCEZ6yu1RQ==", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/circom_runtime/-/circom_runtime-0.1.4.tgz", + "integrity": "sha512-sQWeEBD3o2jIdrKPf3VDu7DNfP+NfscYO/pxi73FE0qQW8TXTfwno8Grdl++h6OKWbzvWJdG5jQvS+WGKjpMOg==", "requires": { - "ffjavascript": "0.2.4", + "ffjavascript": "0.2.10", "fnv-plus": "^1.3.1" } }, @@ -334,9 +334,9 @@ "dev": true }, "ejs": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.3.tgz", - "integrity": "sha512-wmtrUGyfSC23GC/B1SMv2ogAUgbQEtDmTIhfqielrG5ExIM9TP4UoYdi90jLF1aTcsWCJNEO0UrgKzP0y3nTSg==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.5.tgz", + "integrity": "sha512-dldq3ZfFtgVTJMLjOe+/3sROTzALlL9E34V4/sDtUd/KlBSS0s6U1/+WPE1B4sj9CXHJpL1M6rhNJnc9Wbal9w==", "requires": { "jake": "^10.6.1" } @@ -571,9 +571,9 @@ "integrity": "sha512-0EZo2y5eW8X0oiDDRvcnufjVxlM96CQL5hvmRQtbRABWlCkH73IHwkzl0qOSdxtchaMr+0TSB7GVqaVEixRr1Q==" }, "ffiasm": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ffiasm/-/ffiasm-0.1.0.tgz", - "integrity": "sha512-fQI7b6oye7Yw3t28ku9XuhPSwwzKMeqB0pkIaGPrKl9s/ipV90o8J4Ge0s5F0UsH5Mu2wfr3hFQ2sGF+vQk5Sg==", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ffiasm/-/ffiasm-0.1.1.tgz", + "integrity": "sha512-irMMHiR9JJ7BVBrAhtliUawxVdPYSdyl81taUYJ4C1mJ0iw2ueThE/qtr0J8B83tsIY8HJvh0lg5F+6ClK4xpA==", "requires": { "big-integer": "^1.6.48", "ejs": "^3.0.1", @@ -581,13 +581,24 @@ } }, "ffjavascript": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.4.tgz", - "integrity": "sha512-XFeWcjUDFPavN+DDOxhE8p5MOhZQJc9oO1Sj4ml1pyjqNhS1ujEamcjFyK0cctdnat61i7lvpTYzdtS3RYDC8w==", + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.10.tgz", + "integrity": "sha512-GQI6gHYYG5/iD4Kt3VzezzK7fARJzP0zkc82V/+JAdjfeKBXhDSo5rpKFuK3cDcrdW0Fu2emuYNMEAuFqhEQvQ==", "requires": { "big-integer": "^1.6.48", - "wasmcurves": "0.0.4", + "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": { @@ -1163,6 +1174,16 @@ "version": "0.0.7", "resolved": "https://registry.npmjs.org/fastfile/-/fastfile-0.0.7.tgz", "integrity": "sha512-Zk7sdqsV6DsN/rhjULDfCCowPiMDsziTMFicdkrKN80yybr/6YFf9H91ELXN85dVEf6EYkVR5EHkZNc0dMqZKA==" + }, + "ffjavascript": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.4.tgz", + "integrity": "sha512-XFeWcjUDFPavN+DDOxhE8p5MOhZQJc9oO1Sj4ml1pyjqNhS1ujEamcjFyK0cctdnat61i7lvpTYzdtS3RYDC8w==", + "requires": { + "big-integer": "^1.6.48", + "wasmcurves": "0.0.4", + "worker-threads": "^1.0.0" + } } } }, diff --git a/package.json b/package.json index b81ad60..6e99dcf 100644 --- a/package.json +++ b/package.json @@ -30,10 +30,10 @@ }, "dependencies": { "chai": "^4.2.0", - "circom_runtime": "0.1.2", + "circom_runtime": "0.1.4", "fastfile": "0.0.12", - "ffiasm": "0.1.0", - "ffjavascript": "0.2.4", + "ffiasm": "0.1.1", + "ffjavascript": "0.2.10", "ffwasm": "0.0.7", "fnv-plus": "^1.3.1", "r1csfile": "0.0.14", diff --git a/ports/c/builder.js b/ports/c/builder.js index 65278fd..a1c0ac5 100644 --- a/ports/c/builder.js +++ b/ports/c/builder.js @@ -95,6 +95,10 @@ class CodeBuilderC { this.ops.push({op: "CHECKCONSTRAINT", a, b, strErr}); } + checkAssert(a, strErr) { + this.ops.push({op: "CHECKASSERT", a, strErr}); + } + log(val) { this.ops.push({op: "LOG", val}); } @@ -215,6 +219,8 @@ class CodeBuilderC { code.push(`${o.fnName}(ctx, ${o.retLabel}, ${o.params.join(",")});`); } else if (o.op == "CHECKCONSTRAINT") { code.push(`ctx->checkConstraint(__cIdx, ${ref2src(o.a)}, ${ref2src(o.b)}, "${o.strErr}");`); + } else if (o.op == "CHECKASSERT") { + code.push(`ctx->checkAssert(__cIdx, ${ref2src(o.a)}, "${o.strErr}");`); } else if (o.op == "LOG") { code.push(`ctx->log(${ref2src(o.val)});`); } diff --git a/ports/wasm/build_runtime.js b/ports/wasm/build_runtime.js index bd3bf52..442e56f 100644 --- a/ports/wasm/build_runtime.js +++ b/ports/wasm/build_runtime.js @@ -619,6 +619,35 @@ module.exports = function buildRuntime(module, builder) { )); } + function buildCheckAssert() { + const f = module.addFunction("checkAssert"); + f.addParam("cIdx", "i32"); + f.addParam("pA", "i32"); + f.addParam("pStr", "i32"); + + const c = f.getCodeBuilder(); + + f.addCode(ifSanityCheck(c, + c.if ( + c.i32_eqz( + c.call( + "Fr_isTrue", + c.getLocal("pA"), + ) + ), + c.call( + "error", + c.i32_const(errs.ASSERT_DOES_NOT_MATCH.code), + c.i32_const(errs.ASSERT_DOES_NOT_MATCH.pointer), + c.getLocal("cIdx"), + c.getLocal("pA"), + c.getLocal("pStr"), + c.i32_const(0) + ) + ) + )); + } + function buildGetNVars() { const f = module.addFunction("getNVars"); f.setReturnType("i32"); @@ -823,6 +852,7 @@ module.exports = function buildRuntime(module, builder) { buildComponentFinished(); buildCheckConstraint(); + buildCheckAssert(); buildGetNVars(); buildGetFrLen(); diff --git a/ports/wasm/builder.js b/ports/wasm/builder.js index f291b70..424504e 100644 --- a/ports/wasm/builder.js +++ b/ports/wasm/builder.js @@ -98,6 +98,9 @@ class CodeBuilderWasm { this.ops.push({op: "CHECKCONSTRAINT", a, b, strErr}); } + checkAssert(a, strErr) { + this.ops.push({op: "CHECKASSERT", a, strErr}); + } concat(cb) { this.ops.push(...cb.ops); @@ -332,6 +335,15 @@ class CodeBuilderWasm { c.i32_const(this.fnBuilder.builder.module.allocString(o.strErr)) ) ); + } else if (o.op == "CHECKASSERT") { + code.push( + c.call( + "checkAssert", + c.getLocal("cIdx"), + this.fnBuilder._deRefFr(c, o.a), + c.i32_const(this.fnBuilder.builder.module.allocString(o.strErr)) + ) + ); } else if (o.op == "LOG") { code.push( c.call( diff --git a/ports/wasm/errs.js b/ports/wasm/errs.js index 3807d41..f4f0be1 100644 --- a/ports/wasm/errs.js +++ b/ports/wasm/errs.js @@ -7,4 +7,5 @@ module.exports = { SIGNAL_ASSIGNED_TWICE: {code: 6, str: "Signal assigned twice"}, CONSTRAIN_DOES_NOT_MATCH: {code: 7, str: "Constraint doesn't match"}, MAPISINPUT_DONT_MATCH: {code: 8, str: "MapIsInput don't match"}, + ASSERT_DOES_NOT_MATCH: {code: 9, str: "Assert not satisfied"}, }; diff --git a/src/construction_phase.js b/src/construction_phase.js index 743b741..7936499 100644 --- a/src/construction_phase.js +++ b/src/construction_phase.js @@ -567,9 +567,13 @@ function execFunctionCall(ctx, ast) { return; } if (ast.name == "assert") { + ast.fileName = ctx.fileName; + ast.filePath = ctx.filePath; + const v = exec(ctx, ast.params[0]); const ev = val(ctx, v, ast); - if (ctx.F.isZero(ev)) return ctx.throwError(ast, "Assertion failed"); + if ((typeof ev.v !== "undefined")&&(ctx.F.isZero(ev.v))) return ctx.throwError(ast, "Assertion failed"); + return; } const fnc = ctx.functions[ast.name]; diff --git a/src/gencode.js b/src/gencode.js index a70237c..bd120df 100644 --- a/src/gencode.js +++ b/src/gencode.js @@ -871,6 +871,12 @@ function genFunctionCall(ctx, ast) { ctx.codeBuilder.log(toRefA_Fr1(ctx, ast.params[0], vRef)); return vRef; } + if (ast.name == "assert") { + const strErr = ast.fileName + ":" + ast.first_line + ":" + ast.first_column; + const vRef = gen(ctx, ast.params[0]); + ctx.codeBuilder.checkAssert(toRefA_Fr1(ctx, ast.params[0], vRef), strErr); + return vRef; + } const params = []; for (let i=0; i