From 767ca60008acf1c70e5a5a86ee65df6b7e9de994 Mon Sep 17 00:00:00 2001 From: Jordi Baylina Date: Sat, 18 Apr 2020 20:53:13 +0200 Subject: [PATCH] Use native big int --- cli.js | 4 +- package-lock.json | 28 +++---- package.json | 9 +- parser/jaz.jison | 166 +++++++------------------------------ parser/jaz.js | 168 +++++++------------------------------- ports/c/builder.js | 63 ++++++++------ ports/c/tester.js | 20 +++-- ports/wasm/builder.js | 69 +++++++++------- ports/wasm/tester.js | 13 ++- src/build.js | 19 ++--- src/compiler.js | 23 +++--- src/construction_phase.js | 43 +++++----- src/ctx.js | 9 +- src/gencode.js | 22 ++--- src/lcalgebra.js | 71 ++++++++-------- src/r1csfile.js | 8 +- src/utils.js | 41 +--------- test/basiccases.js | 18 ++-- 18 files changed, 276 insertions(+), 518 deletions(-) diff --git a/cli.js b/cli.js index 11be768..ab71c75 100755 --- a/cli.js +++ b/cli.js @@ -23,7 +23,7 @@ const fs = require("fs"); const path = require("path"); -const bigInt = require("big-integer"); +const Scalar = require("ffjavascript").Scalar; const compiler = require("./src/compiler"); @@ -82,7 +82,7 @@ const options = {}; options.reduceConstraints = !argv.fast; options.verbose = argv.verbose || false; options.sanityCheck = argv.sanitycheck; -options.prime = argv.prime || bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617"); +options.prime = argv.prime ? Scalar.fromString(argv.prime) : Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"); if (argv.csource) { options.cSourceWriteStream = fs.createWriteStream(cSourceName); diff --git a/package-lock.json b/package-lock.json index 26509d9..6500b25 100644 --- a/package-lock.json +++ b/package-lock.json @@ -221,11 +221,11 @@ "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" }, "circom_runtime": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/circom_runtime/-/circom_runtime-0.0.3.tgz", - "integrity": "sha512-z4ypbs9cTQn7+2FHZNTnccMj6kQCcKT2agYqCrm2kdLBJh9LDoxU1JVu5mSnVuOtgc7BclQ7r0xclG0zP2rxhw==", + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/circom_runtime/-/circom_runtime-0.0.5.tgz", + "integrity": "sha512-WEZHnRO1AJIDI2w1yX6rq4G1/MMKnExT3qirjBQR7x43i9Ww3E/wusBHTbXWLb8aYyxsBU07LGy0YXPywPGYvA==", "requires": { - "big-integer": "^1.6.48", + "ffjavascript": "0.1.0", "fnv-plus": "^1.3.1" } }, @@ -592,17 +592,17 @@ } }, "ffjavascript": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.0.5.tgz", - "integrity": "sha512-7je6PydOWLDUj3vU8JeCUgeezg4yrG/6qjlukQNuPHeeavnM4REcrN9LA2+xtqIMIPdx/wdUkPMQpixsz+CdIw==", + "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" } }, "ffwasm": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/ffwasm/-/ffwasm-0.0.6.tgz", - "integrity": "sha512-bEBKYANozdyZBCGE6XLg4s/CaJRZdFGQgbthy7EZ4OhNCIpycgklS5mlf88Bw4fXSddlU1V9iYXI4JwfGO3BhQ==", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ffwasm/-/ffwasm-0.0.7.tgz", + "integrity": "sha512-17cTLzv7HHAKqZbX8MvHxjSrR0yDdn1sh4TVsTbAvO9e6klhFicnyoVXc/sCuViV/M8g65sCmVrAmoPCZp1YkQ==", "requires": { "big-integer": "^1.6.48", "wasmbuilder": "0.0.10" @@ -1123,11 +1123,11 @@ "dev": true }, "r1csfile": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/r1csfile/-/r1csfile-0.0.3.tgz", - "integrity": "sha512-TNrodnbHw5yAMv2gj0Ezf22XS3q8zGEjdPHZLBmJauIPFxm6QmyzxlB92yZ5WNkjEtJiS7p1hvkO9/RsJXRDjw==", + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/r1csfile/-/r1csfile-0.0.4.tgz", + "integrity": "sha512-1Y/zzzEjQVTR/gPlduRaKi2K+yU+UxqtsS+obDLEEb4WAzwCkKGybRfp037CUW5OApeleS1WdGmtKv9K9FPhsA==", "requires": { - "big-integer": "^1.6.48" + "ffjavascript": "0.1.0" } }, "regexpp": { diff --git a/package.json b/package.json index 10c62a9..b272610 100644 --- a/package.json +++ b/package.json @@ -29,14 +29,13 @@ "url": "https://github.com/iden3/circom.git" }, "dependencies": { - "big-integer": "^1.6.32", "chai": "^4.2.0", - "circom_runtime": "0.0.3", + "circom_runtime": "0.0.5", "ffiasm": "0.0.2", - "ffjavascript": "0.0.5", - "ffwasm": "0.0.6", + "ffjavascript": "0.1.0", + "ffwasm": "0.0.7", "fnv-plus": "^1.3.1", - "r1csfile": "0.0.3", + "r1csfile": "0.0.4", "tmp-promise": "^2.0.2", "wasmbuilder": "0.0.10" }, diff --git a/parser/jaz.jison b/parser/jaz.jison index 34e56be..c5a70ec 100644 --- a/parser/jaz.jison +++ b/parser/jaz.jison @@ -132,10 +132,8 @@ include { return 'include'; } %{ -const bigInt = require('big-integer'); +const Scalar = require('ffjavascript').Scalar; const util = require('util'); -const __P__ = new bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617"); -const __MASK__ = new bigInt(2).pow(253).minus(1); function setLines(dst, first, last) { last = last || first; @@ -266,20 +264,12 @@ identifierList ifStatment : 'if' '(' expression ')' statment 'else' statment { - if ($3.type == "NUMBER") { - $$ = !$3.value.eq(0) ? $5 : $7; - } else { - $$ = { type: "IF", condition: $3, then: $5, else: $7 }; - } + $$ = { type: "IF", condition: $3, then: $5, else: $7 }; setLines($$, @1, @7); } | 'if' '(' expression ')' statment { - if ($3.type == "NUMBER") { - $$ = !$3.value.eq(0) ? $5 : { type: "NUMBER", value: bigInt(0) }; - } else { - $$ = { type: "IF", condition: $3, then: $5 }; - } + $$ = { type: "IF", condition: $3, then: $5 }; setLines($$, @1, @5); } ; @@ -451,11 +441,7 @@ e17 } | e17 '?' e17 ':' e17 %prec TERCOND { - if ($1.type == "NUMBER") { - $$ = !$1.value.eq(0) ? $3 : $5; - } else { - $$ = { type: "OP", op: "?", values: [$1, $3, $5] }; - } + $$ = { type: "OP", op: "?", values: [$1, $3, $5] }; setLines($$, @1, @5); } | e16 %prec EMPTY @@ -478,11 +464,7 @@ e16 e15 : e15 '||' e14 { - if (($1.type == "NUMBER") && ($3.type == "NUMBER")) { - $$ = { type: "NUMBER", value: !$1.value.eq(0) || !$3.value.eq(0) ? bigInt(1) : bigInt(0) }; - } else { - $$ = { type: "OP", op: "||", values: [$1, $3] }; - } + $$ = { type: "OP", op: "||", values: [$1, $3] }; setLines($$, @1, @3); } | e14 %prec EMPTY @@ -494,11 +476,7 @@ e15 e14 : e14 '&&' e13 { - if (($1.type == "NUMBER") && ($3.type == "NUMBER")) { - $$ = { type: "NUMBER", value: !$1.value.eq(0) && !$3.value.eq(0) ? bigInt(1) : bigInt(0) }; - } else { - $$ = { type: "OP", op: "&&", values: [$1, $3] }; - } + $$ = { type: "OP", op: "&&", values: [$1, $3] }; setLines($$, @1, @3); } | e13 %prec EMPTY @@ -510,11 +488,7 @@ e14 e13 : e13 '|' e12 { - if (($1.type == "NUMBER") && ($3.type == "NUMBER")) { - $$ = { type: "NUMBER", value: $1.value.or($3.value).and(__MASK__) }; - } else { - $$ = { type: "OP", op: "|", values: [$1, $3] }; - } + $$ = { type: "OP", op: "|", values: [$1, $3] }; setLines($$, @1, @3); } | e12 %prec EMPTY @@ -527,11 +501,7 @@ e13 e12 : e12 '^' e11 { - if (($1.type == "NUMBER") && ($3.type == "NUMBER")) { - $$ = { type: "NUMBER", value: $1.value.xor($3.value).and(__MASK__) }; - } else { - $$ = { type: "OP", op: "^", values: [$1, $3] }; - } + $$ = { type: "OP", op: "^", values: [$1, $3] }; setLines($$, @1, @3); } | e11 %prec EMPTY @@ -543,11 +513,7 @@ e12 e11 : e11 '&' e10 { - if (($1.type == "NUMBER") && ($3.type == "NUMBER")) { - $$ = { type: "NUMBER", value: $1.value.and($3.value).and(__MASK__) }; - } else { - $$ = { type: "OP", op: "&", values: [$1, $3] }; - } + $$ = { type: "OP", op: "&", values: [$1, $3] }; setLines($$, @1, @3); } | e10 %prec EMPTY @@ -562,20 +528,12 @@ e11 e10 : e10 '==' e9 { - if (($1.type == "NUMBER") && ($3.type == "NUMBER")) { - $$ = { type: "NUMBER", value: $1.value.equals($3.value) ? bigInt(1) : bigInt(0) }; - } else { - $$ = { type: "OP", op: "==", values: [$1, $3] }; - } + $$ = { type: "OP", op: "==", values: [$1, $3] }; setLines($$, @1, @3); } | e10 '!=' e9 { - if (($1.type == "NUMBER") && ($3.type == "NUMBER")) { - $$ = { type: "NUMBER", value: $1.value.eq($3.value) ? bigInt(0) : bigInt(1) }; - } else { - $$ = { type: "OP", op: "!=", values: [$1, $3] }; - } + $$ = { type: "OP", op: "!=", values: [$1, $3] }; setLines($$, @1, @3); } | e9 %prec EMPTY @@ -587,38 +545,22 @@ e10 e9 : e9 '<=' e7 { - if (($1.type == "NUMBER") && ($3.type == "NUMBER")) { - $$ = { type: "NUMBER", value: $1.value.lesserOrEquals($3.value) ? bigInt(1) : bigInt(0) }; - } else { - $$ = { type: "OP", op: "<=", values: [$1, $3] }; - } + $$ = { type: "OP", op: "<=", values: [$1, $3] }; setLines($$, @1, @3); } | e9 '>=' e7 { - if (($1.type == "NUMBER") && ($3.type == "NUMBER")) { - $$ = { type: "NUMBER", value: $1.value.greaterOrEquals($3.value) ? bigInt(1) : bigInt(0) }; - } else { - $$ = { type: "OP", op: ">=", values: [$1, $3] }; - } + $$ = { type: "OP", op: ">=", values: [$1, $3] }; setLines($$, @1, @3); } | e9 '<' e7 { - if (($1.type == "NUMBER") && ($3.type == "NUMBER")) { - $$ = { type: "NUMBER", value: $1.value.lesser($3.value) ? bigInt(1) : bigInt(0) }; - } else { - $$ = { type: "OP", op: "<", values: [$1, $3] }; - } + $$ = { type: "OP", op: "<", values: [$1, $3] }; setLines($$, @1, @3); } | e9 '>' e7 { - if (($1.type == "NUMBER") && ($3.type == "NUMBER")) { - $$ = { type: "NUMBER", value: $1.value.greater($3.value) ? bigInt(1) : bigInt(0) }; - } else { - $$ = { type: "OP", op: ">", values: [$1, $3] }; - } + $$ = { type: "OP", op: ">", values: [$1, $3] }; setLines($$, @1, @3); } | e7 %prec EMPTY @@ -630,22 +572,12 @@ e9 e7 : e7 '<<' e6 { - if (($1.type == "NUMBER") && ($3.type == "NUMBER")) { - let v = $3.value.greater(256) ? 256 : $3.value.value; - $$ = { type: "NUMBER", value: $1.value.shiftLeft(v).and(__MASK__) }; - } else { - $$ = { type: "OP", op: "<<", values: [$1, $3] }; - } + $$ = { type: "OP", op: "<<", values: [$1, $3] }; setLines($$, @1, @3); } | e7 '>>' e6 { - if (($1.type == "NUMBER") && ($3.type == "NUMBER")) { - let v = $3.value.greater(256) ? 256 : $3.value.value; - $$ = {type: "NUMBER", value: $1.value.shiftRight(v).and(__MASK__) }; - } else { - $$ = { type: "OP", op: ">>", values: [$1, $3] }; - } + $$ = { type: "OP", op: ">>", values: [$1, $3] }; setLines($$, @1, @3); } | e6 %prec EMPTY @@ -657,20 +589,12 @@ e7 e6 : e6 '+' e5 { - if (($1.type == "NUMBER") && ($3.type == "NUMBER")) { - $$ = { type: "NUMBER", value: ($1.value.plus($3.value)).mod(__P__) }; - } else { - $$ = { type: "OP", op: "+", values: [$1, $3] }; - } + $$ = { type: "OP", op: "+", values: [$1, $3] }; setLines($$, @1, @3); } | e6 '-' e5 { - if (($1.type == "NUMBER") && ($3.type == "NUMBER")) { - $$ = { type: "NUMBER", value: ($1.value.plus(__P__).minus($3.value)).mod(__P__) }; - } else { - $$ = { type: "OP", op: "-", values: [$1, $3] }; - } + $$ = { type: "OP", op: "-", values: [$1, $3] }; setLines($$, @1, @3); } | e5 %prec EMPTY @@ -683,38 +607,22 @@ e6 e5 : e5 '*' e4 { - if (($1.type == "NUMBER") && ($3.type == "NUMBER")) { - $$ = { type: "NUMBER", value: ($1.value.times($3.value)).mod(__P__) }; - } else { - $$ = { type: "OP", op: "*", values: [$1, $3] }; - } + $$ = { type: "OP", op: "*", values: [$1, $3] }; setLines($$, @1, @3); } | e5 '/' e4 { - if (($1.type == "NUMBER") && ($3.type == "NUMBER")) { - $$ = { type: "NUMBER", value: ($1.value.times($3.value.modInv(__P__))).mod(__P__) }; - } else { - $$ = { type: "OP", op: "/", values: [$1, $3] }; - } + $$ = { type: "OP", op: "/", values: [$1, $3] }; setLines($$, @1, @3); } | e5 '\\' e4 { - if (($1.type == "NUMBER") && ($3.type == "NUMBER")) { - $$ = { type: "NUMBER", value: ($1.value.divide($3.value)) }; - } else { - $$ = { type: "OP", op: "\\", values: [$1, $3] }; - } + $$ = { type: "OP", op: "\\", values: [$1, $3] }; setLines($$, @1, @3); } | e5 '%' e4 { - if (($1.type == "NUMBER") && ($3.type == "NUMBER")) { - $$ = { type: "NUMBER", value: $1.value.mod($3.value) }; - } else { - $$ = { type: "OP", op: "%", values: [$1, $3] }; - } + $$ = { type: "OP", op: "%", values: [$1, $3] }; setLines($$, @1, @3); } | e4 %prec EMPTY @@ -726,11 +634,7 @@ e5 e4 : e4 '**' e3 { - if (($1.type == "NUMBER") && ($3.type == "NUMBER")) { - $$ = { type: "NUMBER", value: $1.value.modPow($3.value, __P__) }; - } else { - $$ = { type: "OP", op: "**", values: [$1, $3] }; - } + $$ = { type: "OP", op: "**", values: [$1, $3] }; setLines($$, @1, @3); } | e3 %prec EMPTY @@ -758,29 +662,17 @@ e3 } | '-' e3 %prec UMINUS { - if ($2.type == "NUMBER") { - $$ = { type: "NUMBER", value: __P__.minus($2.value).mod(__P__) }; - } else { - $$ = { type: "OP", op: "UMINUS", values: [$2] }; - } + $$ = { type: "OP", op: "UMINUS", values: [$2] }; setLines($$, @1, @2); } | '!' e3 { - if ($2.type == "NUMBER") { - $$ = { type: "NUMBER", value: $2.value.eq(0) ? bigInt(1) : bigInt(0) }; - } else { - $$ = { type: "OP", op: "!", values: [$2] }; - } + $$ = { type: "OP", op: "!", values: [$2] }; setLines($$, @1, @2); } | '~' e3 { - if ($2.type == "NUMBER") { - $$ = { type: "NUMBER", value: $2.value.xor(__MASK__) }; - } else { - $$ = { type: "OP", op: "~", values: [$2] }; - } + $$ = { type: "OP", op: "~", values: [$2] }; setLines($$, @1, @2); } | e2 %prec EMPTY @@ -817,12 +709,12 @@ e0 } | DECNUMBER { - $$ = {type: "NUMBER", value: bigInt($1).mod(__P__) } + $$ = {type: "NUMBER", value: Scalar.fromString($1) } setLines($$, @1); } | HEXNUMBER { - $$ = {type: "NUMBER", value: bigInt($1.substr(2).toUpperCase(), 16).mod(__P__) } + $$ = {type: "NUMBER", value: Scalar.fromString($1.substr(2).toUpperCase(), 16) } setLines($$, @1); } | '(' expression ')' %prec EMPTY diff --git a/parser/jaz.js b/parser/jaz.js index 4c9db52..5d0af9e 100644 --- a/parser/jaz.js +++ b/parser/jaz.js @@ -146,21 +146,13 @@ case 20: break; case 21: - if ($$[$0-4].type == "NUMBER") { - this.$ = !$$[$0-4].value.eq(0) ? $$[$0-2] : $$[$0]; - } else { - this.$ = { type: "IF", condition: $$[$0-4], then: $$[$0-2], else: $$[$0] }; - } + this.$ = { type: "IF", condition: $$[$0-4], then: $$[$0-2], else: $$[$0] }; setLines(this.$, _$[$0-6], _$[$0]); break; case 22: - if ($$[$0-2].type == "NUMBER") { - this.$ = !$$[$0-2].value.eq(0) ? $$[$0] : { type: "NUMBER", value: bigInt(0) }; - } else { - this.$ = { type: "IF", condition: $$[$0-2], then: $$[$0] }; - } + this.$ = { type: "IF", condition: $$[$0-2], then: $$[$0] }; setLines(this.$, _$[$0-4], _$[$0]); break; @@ -321,11 +313,7 @@ case 50: break; case 51: - if ($$[$0-4].type == "NUMBER") { - this.$ = !$$[$0-4].value.eq(0) ? $$[$0-2] : $$[$0]; - } else { - this.$ = { type: "OP", op: "?", values: [$$[$0-4], $$[$0-2], $$[$0]] }; - } + this.$ = { type: "OP", op: "?", values: [$$[$0-4], $$[$0-2], $$[$0]] }; setLines(this.$, _$[$0-4], _$[$0]); break; @@ -336,71 +324,43 @@ case 52: case 53: case 54: case 56: case 58: case 60: break; case 55: - if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) { - this.$ = { type: "NUMBER", value: !$$[$0-2].value.eq(0) || !$$[$0].value.eq(0) ? bigInt(1) : bigInt(0) }; - } else { - this.$ = { type: "OP", op: "||", values: [$$[$0-2], $$[$0]] }; - } + this.$ = { type: "OP", op: "||", values: [$$[$0-2], $$[$0]] }; setLines(this.$, _$[$0-2], _$[$0]); break; case 57: - if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) { - this.$ = { type: "NUMBER", value: !$$[$0-2].value.eq(0) && !$$[$0].value.eq(0) ? bigInt(1) : bigInt(0) }; - } else { - this.$ = { type: "OP", op: "&&", values: [$$[$0-2], $$[$0]] }; - } + this.$ = { type: "OP", op: "&&", values: [$$[$0-2], $$[$0]] }; setLines(this.$, _$[$0-2], _$[$0]); break; case 59: - if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) { - this.$ = { type: "NUMBER", value: $$[$0-2].value.or($$[$0].value).and(__MASK__) }; - } else { - this.$ = { type: "OP", op: "|", values: [$$[$0-2], $$[$0]] }; - } + this.$ = { type: "OP", op: "|", values: [$$[$0-2], $$[$0]] }; setLines(this.$, _$[$0-2], _$[$0]); break; case 61: - if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) { - this.$ = { type: "NUMBER", value: $$[$0-2].value.xor($$[$0].value).and(__MASK__) }; - } else { - this.$ = { type: "OP", op: "^", values: [$$[$0-2], $$[$0]] }; - } + this.$ = { type: "OP", op: "^", values: [$$[$0-2], $$[$0]] }; setLines(this.$, _$[$0-2], _$[$0]); break; case 63: - if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) { - this.$ = { type: "NUMBER", value: $$[$0-2].value.and($$[$0].value).and(__MASK__) }; - } else { - this.$ = { type: "OP", op: "&", values: [$$[$0-2], $$[$0]] }; - } + this.$ = { type: "OP", op: "&", values: [$$[$0-2], $$[$0]] }; setLines(this.$, _$[$0-2], _$[$0]); break; case 65: - if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) { - this.$ = { type: "NUMBER", value: $$[$0-2].value.equals($$[$0].value) ? bigInt(1) : bigInt(0) }; - } else { - this.$ = { type: "OP", op: "==", values: [$$[$0-2], $$[$0]] }; - } + this.$ = { type: "OP", op: "==", values: [$$[$0-2], $$[$0]] }; setLines(this.$, _$[$0-2], _$[$0]); break; case 66: - if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) { - this.$ = { type: "NUMBER", value: $$[$0-2].value.eq($$[$0].value) ? bigInt(0) : bigInt(1) }; - } else { - this.$ = { type: "OP", op: "!=", values: [$$[$0-2], $$[$0]] }; - } + this.$ = { type: "OP", op: "!=", values: [$$[$0-2], $$[$0]] }; setLines(this.$, _$[$0-2], _$[$0]); break; @@ -411,63 +371,37 @@ case 67: case 72: break; case 68: - if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) { - this.$ = { type: "NUMBER", value: $$[$0-2].value.lesserOrEquals($$[$0].value) ? bigInt(1) : bigInt(0) }; - } else { - this.$ = { type: "OP", op: "<=", values: [$$[$0-2], $$[$0]] }; - } + this.$ = { type: "OP", op: "<=", values: [$$[$0-2], $$[$0]] }; setLines(this.$, _$[$0-2], _$[$0]); break; case 69: - if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) { - this.$ = { type: "NUMBER", value: $$[$0-2].value.greaterOrEquals($$[$0].value) ? bigInt(1) : bigInt(0) }; - } else { - this.$ = { type: "OP", op: ">=", values: [$$[$0-2], $$[$0]] }; - } + this.$ = { type: "OP", op: ">=", values: [$$[$0-2], $$[$0]] }; setLines(this.$, _$[$0-2], _$[$0]); break; case 70: - if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) { - this.$ = { type: "NUMBER", value: $$[$0-2].value.lesser($$[$0].value) ? bigInt(1) : bigInt(0) }; - } else { - this.$ = { type: "OP", op: "<", values: [$$[$0-2], $$[$0]] }; - } + this.$ = { type: "OP", op: "<", values: [$$[$0-2], $$[$0]] }; setLines(this.$, _$[$0-2], _$[$0]); break; case 71: - if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) { - this.$ = { type: "NUMBER", value: $$[$0-2].value.greater($$[$0].value) ? bigInt(1) : bigInt(0) }; - } else { - this.$ = { type: "OP", op: ">", values: [$$[$0-2], $$[$0]] }; - } + this.$ = { type: "OP", op: ">", values: [$$[$0-2], $$[$0]] }; setLines(this.$, _$[$0-2], _$[$0]); break; case 73: - if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) { - let v = $$[$0].value.greater(256) ? 256 : $$[$0].value.value; - this.$ = { type: "NUMBER", value: $$[$0-2].value.shiftLeft(v).and(__MASK__) }; - } else { - this.$ = { type: "OP", op: "<<", values: [$$[$0-2], $$[$0]] }; - } + this.$ = { type: "OP", op: "<<", values: [$$[$0-2], $$[$0]] }; setLines(this.$, _$[$0-2], _$[$0]); break; case 74: - if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) { - let v = $$[$0].value.greater(256) ? 256 : $$[$0].value.value; - this.$ = {type: "NUMBER", value: $$[$0-2].value.shiftRight(v).and(__MASK__) }; - } else { - this.$ = { type: "OP", op: ">>", values: [$$[$0-2], $$[$0]] }; - } + this.$ = { type: "OP", op: ">>", values: [$$[$0-2], $$[$0]] }; setLines(this.$, _$[$0-2], _$[$0]); break; @@ -478,71 +412,43 @@ case 75: break; case 76: - if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) { - this.$ = { type: "NUMBER", value: ($$[$0-2].value.plus($$[$0].value)).mod(__P__) }; - } else { - this.$ = { type: "OP", op: "+", values: [$$[$0-2], $$[$0]] }; - } + this.$ = { type: "OP", op: "+", values: [$$[$0-2], $$[$0]] }; setLines(this.$, _$[$0-2], _$[$0]); break; case 77: - if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) { - this.$ = { type: "NUMBER", value: ($$[$0-2].value.plus(__P__).minus($$[$0].value)).mod(__P__) }; - } else { - this.$ = { type: "OP", op: "-", values: [$$[$0-2], $$[$0]] }; - } + this.$ = { type: "OP", op: "-", values: [$$[$0-2], $$[$0]] }; setLines(this.$, _$[$0-2], _$[$0]); break; case 79: - if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) { - this.$ = { type: "NUMBER", value: ($$[$0-2].value.times($$[$0].value)).mod(__P__) }; - } else { - this.$ = { type: "OP", op: "*", values: [$$[$0-2], $$[$0]] }; - } + this.$ = { type: "OP", op: "*", values: [$$[$0-2], $$[$0]] }; setLines(this.$, _$[$0-2], _$[$0]); break; case 80: - if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) { - this.$ = { type: "NUMBER", value: ($$[$0-2].value.times($$[$0].value.modInv(__P__))).mod(__P__) }; - } else { - this.$ = { type: "OP", op: "/", values: [$$[$0-2], $$[$0]] }; - } + this.$ = { type: "OP", op: "/", values: [$$[$0-2], $$[$0]] }; setLines(this.$, _$[$0-2], _$[$0]); break; case 81: - if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) { - this.$ = { type: "NUMBER", value: ($$[$0-2].value.divide($$[$0].value)) }; - } else { - this.$ = { type: "OP", op: "\\", values: [$$[$0-2], $$[$0]] }; - } + this.$ = { type: "OP", op: "\\", values: [$$[$0-2], $$[$0]] }; setLines(this.$, _$[$0-2], _$[$0]); break; case 82: - if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) { - this.$ = { type: "NUMBER", value: $$[$0-2].value.mod($$[$0].value) }; - } else { - this.$ = { type: "OP", op: "%", values: [$$[$0-2], $$[$0]] }; - } + this.$ = { type: "OP", op: "%", values: [$$[$0-2], $$[$0]] }; setLines(this.$, _$[$0-2], _$[$0]); break; case 84: - if (($$[$0-2].type == "NUMBER") && ($$[$0].type == "NUMBER")) { - this.$ = { type: "NUMBER", value: $$[$0-2].value.modPow($$[$0].value, __P__) }; - } else { - this.$ = { type: "OP", op: "**", values: [$$[$0-2], $$[$0]] }; - } + this.$ = { type: "OP", op: "**", values: [$$[$0-2], $$[$0]] }; setLines(this.$, _$[$0-2], _$[$0]); break; @@ -566,31 +472,19 @@ case 88: break; case 89: - if ($$[$0].type == "NUMBER") { - this.$ = { type: "NUMBER", value: __P__.minus($$[$0].value).mod(__P__) }; - } else { - this.$ = { type: "OP", op: "UMINUS", values: [$$[$0]] }; - } + this.$ = { type: "OP", op: "UMINUS", values: [$$[$0]] }; setLines(this.$, _$[$0-1], _$[$0]); break; case 90: - if ($$[$0].type == "NUMBER") { - this.$ = { type: "NUMBER", value: $$[$0].value.eq(0) ? bigInt(1) : bigInt(0) }; - } else { - this.$ = { type: "OP", op: "!", values: [$$[$0]] }; - } + this.$ = { type: "OP", op: "!", values: [$$[$0]] }; setLines(this.$, _$[$0-1], _$[$0]); break; case 91: - if ($$[$0].type == "NUMBER") { - this.$ = { type: "NUMBER", value: $$[$0].value.xor(__MASK__) }; - } else { - this.$ = { type: "OP", op: "~", values: [$$[$0]] }; - } + this.$ = { type: "OP", op: "~", values: [$$[$0]] }; setLines(this.$, _$[$0-1], _$[$0]); break; @@ -613,13 +507,13 @@ case 97: case 102: case 103: break; case 98: - this.$ = {type: "NUMBER", value: bigInt($$[$0]).mod(__P__) } + this.$ = {type: "NUMBER", value: Scalar.fromString($$[$0]) } setLines(this.$, _$[$0]); break; case 99: - this.$ = {type: "NUMBER", value: bigInt($$[$0].substr(2).toUpperCase(), 16).mod(__P__) } + this.$ = {type: "NUMBER", value: Scalar.fromString($$[$0].substr(2).toUpperCase(), 16) } setLines(this.$, _$[$0]); break; @@ -866,10 +760,8 @@ parse: function parse(input) { return true; }}; -const bigInt = require('big-integer'); +const Scalar = require('ffjavascript').Scalar; const util = require('util'); -const __P__ = new bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617"); -const __MASK__ = new bigInt(2).pow(253).minus(1); function setLines(dst, first, last) { last = last || first; @@ -1365,7 +1257,7 @@ case 77: console.log("INVALID: " + yy_.yytext); return 'INVALID' break; } }, -rules: [/^(?:\s+)/,/^(?:\/\*([^*]|[\r\n]|(\*+([^*\/]|[\r\n])))*\*+\/)/,/^(?:\/\/.*)/,/^(?:var\b)/,/^(?:signal\b)/,/^(?:private\b)/,/^(?:input\b)/,/^(?:output\b)/,/^(?:linearCombination\b)/,/^(?:component\b)/,/^(?:template\b)/,/^(?:function\b)/,/^(?:if\b)/,/^(?:else\b)/,/^(?:for\b)/,/^(?:while\b)/,/^(?:compute\b)/,/^(?:do\b)/,/^(?:return\b)/,/^(?:include\b)/,/^(?:0x[0-9A-Fa-f]*)/,/^(?:[0-9]+)/,/^(?:[a-zA-Z][a-zA-Z$_0-9]*)/,/^(?:"[^"]+")/,/^(?:==>)/,/^(?:<==)/,/^(?:-->)/,/^(?:<--)/,/^(?:===)/,/^(?:>>=)/,/^(?:<<=)/,/^(?:&&)/,/^(?:\|\|)/,/^(?:==)/,/^(?:<=)/,/^(?:>=)/,/^(?:!=)/,/^(?:>>)/,/^(?:<<)/,/^(?:\*\*)/,/^(?:\+\+)/,/^(?:--)/,/^(?:\+=)/,/^(?:-=)/,/^(?:\*=)/,/^(?:\/=)/,/^(?:%=)/,/^(?:\|=)/,/^(?:&=)/,/^(?:\^=)/,/^(?:=)/,/^(?:\+)/,/^(?:-)/,/^(?:\*)/,/^(?:\/)/,/^(?:\\)/,/^(?:%)/,/^(?:\^)/,/^(?:&)/,/^(?:\|)/,/^(?:!)/,/^(?:~)/,/^(?:<)/,/^(?:>)/,/^(?:!)/,/^(?:\?)/,/^(?::)/,/^(?:\()/,/^(?:\))/,/^(?:\[)/,/^(?:\])/,/^(?:\{)/,/^(?:\})/,/^(?:;)/,/^(?:,)/,/^(?:\.)/,/^(?:$)/,/^(?:.)/], +rules: [/^(?:\s+)/,/^(?:\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+\/)/,/^(?:\/\/.*)/,/^(?:var\b)/,/^(?:signal\b)/,/^(?:private\b)/,/^(?:input\b)/,/^(?:output\b)/,/^(?:linearCombination\b)/,/^(?:component\b)/,/^(?:template\b)/,/^(?:function\b)/,/^(?:if\b)/,/^(?:else\b)/,/^(?:for\b)/,/^(?:while\b)/,/^(?:compute\b)/,/^(?:do\b)/,/^(?:return\b)/,/^(?:include\b)/,/^(?:0x[0-9A-Fa-f]*)/,/^(?:[0-9]+)/,/^(?:[a-zA-Z][a-zA-Z$_0-9]*)/,/^(?:"[^"]+")/,/^(?:==>)/,/^(?:<==)/,/^(?:-->)/,/^(?:<--)/,/^(?:===)/,/^(?:>>=)/,/^(?:<<=)/,/^(?:&&)/,/^(?:\|\|)/,/^(?:==)/,/^(?:<=)/,/^(?:>=)/,/^(?:!=)/,/^(?:>>)/,/^(?:<<)/,/^(?:\*\*)/,/^(?:\+\+)/,/^(?:--)/,/^(?:\+=)/,/^(?:-=)/,/^(?:\*=)/,/^(?:\/=)/,/^(?:%=)/,/^(?:\|=)/,/^(?:&=)/,/^(?:\^=)/,/^(?:=)/,/^(?:\+)/,/^(?:-)/,/^(?:\*)/,/^(?:\/)/,/^(?:\\)/,/^(?:%)/,/^(?:\^)/,/^(?:&)/,/^(?:\|)/,/^(?:!)/,/^(?:~)/,/^(?:<)/,/^(?:>)/,/^(?:!)/,/^(?:\?)/,/^(?::)/,/^(?:\()/,/^(?:\))/,/^(?:\[)/,/^(?:\])/,/^(?:\{)/,/^(?:\})/,/^(?:;)/,/^(?:,)/,/^(?:\.)/,/^(?:$)/,/^(?:.)/], conditions: {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77],"inclusive":true}} }); return lexer; diff --git a/ports/c/builder.js b/ports/c/builder.js index f328ec8..6ffbdce 100644 --- a/ports/c/builder.js +++ b/ports/c/builder.js @@ -1,7 +1,8 @@ const streamFromMultiArray = require("../../src/streamfromarray_txt.js"); -const bigInt = require("big-integer"); const utils = require("../../src/utils"); const assert = require("assert"); +const Scalar = require("ffjavascript").Scalar; +const F1Field = require("ffjavascript").F1Field; function ref2src(c) { if ((c[0] == "R")||(c[0] == "RI")) { @@ -340,7 +341,9 @@ class FunctionBuilderC { } class BuilderC { - constructor() { + constructor(p) { + this.F = new F1Field(p); + this.hashMaps={}; this.componentEntriesTables={}; this.sizes ={}; @@ -348,7 +351,6 @@ class BuilderC { this.functions = []; this.components = []; this.usedConstants = {}; - } setHeader(header) { @@ -369,9 +371,9 @@ class BuilderC { } addConstant(c) { - c = bigInt(c); + c = this.F.e(c); const cS = c.toString(); - if (this.usedConstants[cS]) return this.usedConstants[cS]; + if (typeof this.usedConstants[cS] != "undefined") return this.usedConstants[cS]; this.constants.push(c); this.usedConstants[cS] = this.constants.length - 1; return this.constants.length - 1; @@ -471,8 +473,6 @@ class BuilderC { _buildConstants(code) { const self = this; - const n64 = Math.floor((self.header.P.bitLength() - 1) / 64)+1; - const R = bigInt.one.shiftLeft(n64*64); code.push("// Constants"); code.push(`FrElement _constants[${self.constants.length}] = {`); @@ -482,12 +482,19 @@ class BuilderC { code.push("};"); function number2Code(n) { - if (n.lt(bigInt("80000000", 16)) ) { - return addShortMontgomeryPositive(n); - } - if (n.geq(self.header.P.minus(bigInt("80000000", 16))) ) { - return addShortMontgomeryNegative(n); + const minShort = self.F.neg(self.F.e("80000000")); + const maxShort = self.F.e("7FFFFFFF", 16); + + if ( (self.F.geq(n, minShort)) + &&(self.F.leq(n, maxShort))) + { + if (self.F.geq(n, self.F.zero)) { + return addShortMontgomeryPositive(n); + } else { + return addShortMontgomeryNegative(n); + } } + return addLongMontgomery(n); @@ -506,25 +513,31 @@ class BuilderC { } function getLongString(a) { - let r = bigInt(a); let S = ""; - let i = 0; - while (!r.isZero()) { - if (S!= "") S = S+","; - S += "0x" + r.and(bigInt("FFFFFFFFFFFFFFFF", 16)).toString(16) + "LL"; - i++; - r = r.shiftRight(64); - } - while (i0) S = S + ","; + + if ( idx >=0) { + let msb = arr[idx].toString(16); + while (msb.length<8) msb = "0" + msb; + + let lsb = arr[idx+1].toString(16); + while (lsb.length<8) lsb = "0" + lsb; + + S += "0x" + msb + lsb + "LL"; + } else { + S += "0LL"; + } } + return S; } function toMontgomery(a) { - return a.times(R).mod(self.header.P); + return self.F.mul(a, self.F.R); } } diff --git a/ports/c/tester.js b/ports/c/tester.js index b299c6d..566cf2f 100644 --- a/ports/c/tester.js +++ b/ports/c/tester.js @@ -8,12 +8,14 @@ const compiler = require("../../src/compiler"); const util = require("util"); const exec = util.promisify(require("child_process").exec); -const bigInt = require("big-integer"); +const Scalar = require("ffjavascript").Scalar; const utils = require("../../src/utils"); const loadR1cs = require("r1csfile").load; const ZqField = require("ffjavascript").ZqField; const buildZqField = require("ffiasm").buildZqField; +const {stringifyBigInts, unstringifyBigInts } = require("ffjavascript").utils; + module.exports = c_tester; @@ -31,7 +33,7 @@ async function c_tester(circomFile, _options) { options.symWriteStream = fs.createWriteStream(path.join(dir.path, baseName + ".sym")); options.r1csFileName = path.join(dir.path, baseName + ".r1cs"); - options.p = options.p || bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617"); + options.p = options.p || Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"); await compiler(circomFile, options); const source = await buildZqField(options.p, "Fr"); @@ -87,7 +89,7 @@ class CTester { async calculateWitness(input) { await fs.promises.writeFile( path.join(this.dir.path, "in.json"), - JSON.stringify(utils.stringifyBigInts(input), null, 1) + JSON.stringify(stringifyBigInts(input), null, 1) ); const r = await exec(`${path.join(this.dir.path, this.baseName)}` + ` ${path.join(this.dir.path, "in.json")}` + @@ -100,7 +102,7 @@ class CTester { path.join(this.dir.path, "out.json") ); - const res = utils.unstringifyBigInts(JSON.parse(resStr)); + const res = unstringifyBigInts(JSON.parse(resStr)); return res; } @@ -127,7 +129,7 @@ class CTester { const self = this; if (this.constraints) return; const r1cs = await loadR1cs(path.join(this.dir.path, this.baseName + ".r1cs"),true, false); - self.field = new ZqField(r1cs.prime); + self.F = new ZqField(r1cs.prime); self.nVars = r1cs.nVars; self.constraints = r1cs.constraints; } @@ -152,8 +154,8 @@ class CTester { if (typeof self.symbols[prefix] == "undefined") { assert(false, "Output variable not defined: "+ prefix); } - const ba = bigInt(actualOut[self.symbols[prefix].varIdx]).toString(); - const be = bigInt(eOut).toString(); + const ba = actualOut[self.symbols[prefix].varIdx].toString(); + const be = eOut.toString(); assert.strictEqual(ba, be, prefix); } } @@ -183,7 +185,7 @@ class CTester { } function checkConstraint(constraint) { - const F = self.field; + const F = self.F; const a = evalLC(constraint[0]); const b = evalLC(constraint[1]); const c = evalLC(constraint[2]); @@ -192,7 +194,7 @@ class CTester { } function evalLC(lc) { - const F = self.field; + const F = self.F; let v = F.zero; for (let w in lc) { v = F.add( diff --git a/ports/wasm/builder.js b/ports/wasm/builder.js index c770813..1559d9a 100644 --- a/ports/wasm/builder.js +++ b/ports/wasm/builder.js @@ -1,10 +1,11 @@ const streamFromArrayTxt = require("../../src/streamfromarray_txt"); const streamFromArrayBin = require("../../src/streamfromarray_bin"); -const bigInt = require("big-integer"); const assert = require("assert"); const ModuleBuilder = require("wasmbuilder").ModuleBuilder; const ModuleBuilderWat = require("wasmbuilder").ModuleBuilderWat; const buildRuntime = require("./build_runtime"); +const Scalar = require("ffjavascript").Scalar; +const F1Field = require("ffjavascript").F1Field; const errs = require("./errs"); @@ -689,7 +690,8 @@ class FunctionBuilderWasm { } class BuilderWasm { - constructor() { + constructor(p) { + this.F = new F1Field(p); this.hashMaps={}; this.componentEntriesTables={}; this.sizes ={}; @@ -701,8 +703,8 @@ class BuilderWasm { this.TYPE_SIGNAL = 1; this.TYPE_COMPONENT = 2; - this.addConstant(bigInt(0)); // constants[0] = 0; - this.addConstant(bigInt(1)); // constants[1] = 1; + this.addConstant(Scalar.fromString("0")); // constants[0] = 0; + this.addConstant(Scalar.fromString("1")); // constants[1] = 1; this.offsetComponentNInputSignals = 12; this.sizeofComponent = 20; @@ -710,7 +712,8 @@ class BuilderWasm { setHeader(header) { this.header=header; - this.n64 = Math.floor((this.header.P.bitLength() - 1) / 64)+1; + + this.n64 = Math.floor((Scalar.bitLength(this.header.P) - 1) / 64)+1; this.sizeFr = this.n64*8 + 8; } @@ -728,9 +731,9 @@ class BuilderWasm { } addConstant(c) { - c = bigInt(c); + c = this.F.e(c); const cS = c.toString(); - if (this.usedConstants[cS]) return this.usedConstants[cS]; + if (typeof this.usedConstants[cS] != "undefined") return this.usedConstants[cS]; this.constants.push(c); this.usedConstants[cS] = this.constants.length - 1; return this.constants.length - 1; @@ -842,7 +845,6 @@ class BuilderWasm { _buildConstants(module) { const self = this; - const R = bigInt.one.shiftLeft(this.n64*64); const bytes = []; for (let i=0; i=0) { + bytes.push(...intToBytes32(arr[idx])); + } else { + bytes.push(...intToBytes32(0)); + } } - const fBytes = [].concat(...bytes); - return fBytes; + return bytes; } function toMontgomery(a) { - return a.times(R).mod(self.header.P); + return self.F.mul(a, self.F.R); } } diff --git a/ports/wasm/tester.js b/ports/wasm/tester.js index 7f63755..d9a632a 100644 --- a/ports/wasm/tester.js +++ b/ports/wasm/tester.js @@ -6,7 +6,6 @@ var tmp = require("tmp-promise"); const path = require("path"); const compiler = require("../../src/compiler"); -const bigInt = require("big-integer"); const utils = require("../../src/utils"); const loadR1cs = require("r1csfile").load; const ZqField = require("ffjavascript").ZqField; @@ -82,7 +81,7 @@ class WasmTester { const self = this; if (this.constraints) return; const r1cs = await loadR1cs(path.join(this.dir.path, this.baseName + ".r1cs"),true, false); - self.field = new ZqField(r1cs.prime); + self.F = new ZqField(r1cs.prime); self.nVars = r1cs.nVars; self.constraints = r1cs.constraints; } @@ -107,8 +106,8 @@ class WasmTester { if (typeof self.symbols[prefix] == "undefined") { assert(false, "Output variable not defined: "+ prefix); } - const ba = bigInt(actualOut[self.symbols[prefix].varIdx]).toString(); - const be = bigInt(eOut).toString(); + const ba = actualOut[self.symbols[prefix].varIdx].toString(); + const be = eOut.toString(); assert.strictEqual(ba, be, prefix); } } @@ -138,16 +137,16 @@ class WasmTester { } function checkConstraint(constraint) { - const F = self.field; + const F = self.F; const a = evalLC(constraint[0]); const b = evalLC(constraint[1]); const c = evalLC(constraint[2]); - assert (F.sub(F.mul(a,b), c).isZero(), "Constraint doesn't match"); + assert (F.isZero(F.sub(F.mul(a,b), c)), "Constraint doesn't match"); } function evalLC(lc) { - const F = self.field; + const F = self.F; let v = F.zero; for (let w in lc) { v = F.add( diff --git a/src/build.js b/src/build.js index 3dd9bbb..c260593 100644 --- a/src/build.js +++ b/src/build.js @@ -18,7 +18,6 @@ */ const assert = require("assert"); -const bigInt = require("big-integer"); const utils = require("./utils"); const gen = require("./gencode").gen; const createRefs = require("./gencode").createRefs; @@ -35,8 +34,8 @@ function build(ctx) { ctx.definedSizes = {}; ctx.addSizes = addSizes; ctx.addConstant = addConstant; - ctx.addConstant(bigInt.zero); - ctx.addConstant(bigInt.one); + ctx.addConstant(ctx.F.zero); + ctx.addConstant(ctx.F.one); buildHeader(ctx); buildEntryTables(ctx); @@ -209,7 +208,7 @@ function buildHeader(ctx) { NInputs: ctx.components[ ctx.getComponentIdx("main") ].nInSignals, NOutputs: ctx.totals[ ctx.stOUTPUT ], NVars: ctx.totals[ctx.stONE] + ctx.totals[ctx.stOUTPUT] + ctx.totals[ctx.stPUBINPUT] + ctx.totals[ctx.stPRVINPUT] + ctx.totals[ctx.stINTERNAL], - P: ctx.field.p + P: ctx.F.p }); } @@ -391,7 +390,7 @@ function hashComponentCall(ctx, cIdx) { // TODO: At the moment generate a diferent function for each instance of the component const constParams = []; for (let p in ctx.components[cIdx].params) { - constParams.push(p + "=" + value2str(ctx.components[cIdx].params[p])); + constParams.push(p + "=" + value2str(ctx.F, ctx.components[cIdx].params[p])); } for (let n in ctx.components[cIdx].names.o) { @@ -399,7 +398,7 @@ function hashComponentCall(ctx, cIdx) { if ((entry.type == "S")&&(ctx.signals[entry.offset].o & ctx.IN)) { travelSizes(n, entry.offset, entry.sizes, (prefix, offset) => { if (utils.isDefined(ctx.signals[offset].v)) { - constParams.push(prefix + "=" + bigInt(ctx.signals[offset].value)); + constParams.push(prefix + "=" + ctx.F.e(ctx.signals[offset].v)); } }); } @@ -433,7 +432,7 @@ function hashFunctionCall(ctx, name, paramValues) { const constParams = []; for (let i=0; i0) S+=","; - S+=value2str(v[i]); + S+=value2str(F, v[i]); } S+="]"; return S; } else { - return bigInt(v).toString(); + return F.toString(F.e(v)); } } diff --git a/src/compiler.js b/src/compiler.js index 005fdd1..a8e3534 100644 --- a/src/compiler.js +++ b/src/compiler.js @@ -17,15 +17,13 @@ along with circom. If not, see . */ -const bigInt = require("big-integer"); -const __P__ = bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617"); +const Scalar = require("ffjavascript").Scalar; const sONE = 0; const build = require("./build"); const BuilderC = require("../ports/c/builder.js"); const BuilderWasm = require("../ports/wasm/builder.js"); const constructionPhase = require("./construction_phase"); const Ctx = require("./ctx"); -const ZqField = require("ffjavascript").ZqField; const utils = require("./utils"); const buildR1cs = require("./r1csfile").buildR1cs; const BigArray = require("./bigarray"); @@ -34,15 +32,14 @@ const buildSyms = require("./buildsyms"); module.exports = compile; async function compile(srcFile, options) { - options.p = options.p || __P__; + options.p = options.p || Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617"); if (!options) { options = {}; } if (typeof options.reduceConstraints === "undefined") { options.reduceConstraints = true; } - const ctx = new Ctx(); - ctx.field = new ZqField(options.p); + const ctx = new Ctx(options.p); ctx.verbose= options.verbose || false; ctx.mainComponent = options.mainComponent || "main"; ctx.newThreadTemplates = options.newThreadTemplates; @@ -85,7 +82,7 @@ async function compile(srcFile, options) { } if (options.cSourceWriteStream) { - ctx.builder = new BuilderC(); + ctx.builder = new BuilderC(options.p); build(ctx); const rdStream = ctx.builder.build(); rdStream.pipe(options.cSourceWriteStream); @@ -94,7 +91,7 @@ async function compile(srcFile, options) { } if ((options.wasmWriteStream)||(options.watWriteStream)) { - ctx.builder = new BuilderWasm(); + ctx.builder = new BuilderWasm(options.p); build(ctx); if (options.wasmWriteStream) { const rdStream = ctx.builder.build("wasm"); @@ -299,11 +296,11 @@ function reduceConstrains(ctx) { t: "LC", coefs: {} }; - const invCoef = c.c.coefs[isolatedSignal].modInv(__P__); + const invCoef = ctx.F.inv(c.c.coefs[isolatedSignal]); for (const s in c.c.coefs) { if (s != isolatedSignal) { - const v = __P__.minus(c.c.coefs[s]).times(invCoef).mod(__P__); - if (!v.isZero()) { + const v = ctx.F.mul( ctx.F.neg(c.c.coefs[s]), invCoef); + if (!ctx.F.isZero(v)) { isolatedSignalEquivalence.coefs[s] = v; } } @@ -395,9 +392,9 @@ function reduceConstrains(ctx) { function isConstant(l) { for (let k in l.coefs) { - if ((k != sONE) && (!l.coefs[k].isZero())) return false; + if ((k != sONE) && (!ctx.F.isZero(l.coefs[k]))) return false; } - if (!l.coefs[sONE] || l.coefs[sONE].isZero()) return false; + if (!l.coefs[sONE] || ctx.F.isZero(l.coefs[sONE])) return false; return true; } diff --git a/src/construction_phase.js b/src/construction_phase.js index 52e53c5..20f5778 100644 --- a/src/construction_phase.js +++ b/src/construction_phase.js @@ -49,10 +49,11 @@ const assert = require("assert"); const iterateAST = require("./iterateast"); const utils = require("./utils"); -const bigInt = require("big-integer"); - const LCAlgebra = require("./lcalgebra"); const parser = require("../parser/jaz.js").parser; +const Scalar = require("ffjavascript").Scalar; + +const {stringifyBigInts} = require("ffjavascript").utils; /* TODO: Add lines information @@ -79,7 +80,7 @@ function constructionPhase(ctx, srcFile) { assert(ctx.ast.type == "BLOCK"); - ctx.lc = new LCAlgebra(ctx.field); + ctx.lc = new LCAlgebra(ctx.F); ctx.filePath= fullFilePath; ctx.fileName= fullFileName; ctx.includedFiles = {}; @@ -218,7 +219,7 @@ function execNumber(ctx, ast) { s:[1,0], v: [{ t: "N", - v: bigInt(ast.value) + v: ctx.F.e(ast.value) }] }; } @@ -253,7 +254,7 @@ function execDeclareComponent(ctx, ast) { const size = val(ctx, sizeRef); if (size.t != "N") return ctx.throwError( ast.name.selectors[i], "expected a number"); - sizes.push( size.v.toJSNumber() ); + sizes.push( Scalar.toNumber(size.v) ); } let cIdx = ctx.addComponent(ast.name.name, sizes); @@ -277,7 +278,7 @@ function execDeclareSignal(ctx, ast) { if (ctx.error) return; if (size.s[0] != 1) return ctx.throwError(ast, "Size cannot be an array"); if (size.v[0].t != "N") return ctx.throwError(ast, "Size must be declared in construction time"); - sizes.push( size.v[0].v.toJSNumber() ); + sizes.push( Scalar.toNumber(size.v[0].v) ); } let sIdx = ctx.addSignal(ast.name.name, sizes); @@ -322,7 +323,7 @@ function execDeclareVariable(ctx, ast) { if (ctx.error) return; if (size.s[0] != 1) return ctx.throwError(ast, "Size cannot be an array"); if (size.v[0].t != "N") return ctx.throwError(ast, "Size must be declared in construction time"); - sizes.push( size.v[0].v.toJSNumber() ); + sizes.push( Scalar.toNumber(size.v[0].v) ); } const v = ctx.refs[ast.refId]; @@ -353,7 +354,7 @@ function execAssignement(ctx, ast) { if (sel.s[0] != 1) return ctx.throwError(ast, "Selector cannot be an array"); if (sel.v[0].t != "N") return {t: "NQ"}; - leftSels.push( sel.v[0].v.toJSNumber() ); + leftSels.push( Scalar.toNumber(sel.v[0].v) ); } } @@ -380,7 +381,7 @@ function execAssignement(ctx, ast) { } else if (right.t == "S") { for (let i=0; i= 0) sIdx = ctx.signals[sIdx].e; - res.coefs[sIdx] = ctx.field.one; + res.coefs[sIdx] = ctx.F.one; return res; } else { ctx.throwError(ast, "Invalid type: " + a.t); @@ -979,7 +980,7 @@ function execArray(ctx, ast) { } else if (e.t == "S") { for (let j=0; j=0) s= ctx.signals[s].e; if (utils.isDefined(ctx.signals[s].v)&&(k != sONE)) { - const v = this.field.mul(res.coefs[k], ctx.signals[s].v); + const v = this.F.mul(res.coefs[k], ctx.signals[s].v); if (!utils.isDefined(res.coefs[sONE])) { res.coefs[sONE]=v; } else { - res.coefs[sONE]= this.field.add(res.coefs[sONE], v); + res.coefs[sONE]= this.F.add(res.coefs[sONE], v); } delete res.coefs[k]; } else if (s != k) { if (!utils.isDefined(res.coefs[s])) { res.coefs[s]=res.coefs[k]; } else { - res.coefs[s]= this.field.add(res.coefs[s], res.coefs[k]); + res.coefs[s]= this.F.add(res.coefs[s], res.coefs[k]); } delete res.coefs[k]; } } for (let k in res.coefs) { - if (res.coefs[k].isZero()) delete res.coefs[k]; + if (this.F.isZero(res.coefs[k])) delete res.coefs[k]; } return res; } else if (a.t == "QEX") { diff --git a/src/r1csfile.js b/src/r1csfile.js index 51763a4..f046205 100644 --- a/src/r1csfile.js +++ b/src/r1csfile.js @@ -1,7 +1,7 @@ const fs = require("fs"); const assert = require("assert"); -const bigInt = require("big-integer"); +const Scalar = require("ffjavascript").Scalar; module.exports.buildR1cs = buildR1cs; @@ -23,10 +23,10 @@ async function buildR1cs(ctx, fileName) { await writeU64(0); // Temporally set to 0 length - const n8 = (Math.floor( (ctx.field.p.bitLength() - 1) / 64) +1)*8; + const n8 = (Math.floor( (ctx.F.bitLength - 1) / 64) +1)*8; // Field Def await writeU32(n8); // Temporally set to 0 length - await writeBigInt(ctx.field.p); + await writeBigInt(ctx.F.p); const NWires = ctx.totals[ctx.stONE] + @@ -136,7 +136,7 @@ async function buildR1cs(ctx, fileName) { async function writeBigInt(n, pos) { const b = Buffer.allocUnsafe(n8); - const dwords = bigInt(n).toArray(0x100000000).value; + const dwords = Scalar.toArray(n, 0x100000000); for (let i=0; i