Browse Source

Use native big int

master
Jordi Baylina 4 years ago
parent
commit
767ca60008
No known key found for this signature in database GPG Key ID: 7480C80C1BE43112
18 changed files with 276 additions and 518 deletions
  1. +2
    -2
      cli.js
  2. +14
    -14
      package-lock.json
  3. +4
    -5
      package.json
  4. +29
    -137
      parser/jaz.jison
  5. +30
    -138
      parser/jaz.js
  6. +38
    -25
      ports/c/builder.js
  7. +11
    -9
      ports/c/tester.js
  8. +38
    -31
      ports/wasm/builder.js
  9. +6
    -7
      ports/wasm/tester.js
  10. +9
    -10
      src/build.js
  11. +10
    -13
      src/compiler.js
  12. +22
    -21
      src/construction_phase.js
  13. +5
    -4
      src/ctx.js
  14. +11
    -11
      src/gencode.js
  15. +35
    -36
      src/lcalgebra.js
  16. +4
    -4
      src/r1csfile.js
  17. +1
    -40
      src/utils.js
  18. +7
    -11
      test/basiccases.js

+ 2
- 2
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);

+ 14
- 14
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": {

+ 4
- 5
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"
},

+ 29
- 137
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

+ 30
- 138
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;

+ 38
- 25
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 (i<n64) {
if (S!= "") S = S+",";
S += "0LL";
i++;
const arr = Scalar.toArray(a, 0x100000000);
for (let i=0; i<self.F.n64*2; i+=2) {
const idx = arr.length-2-i;
if (i>0) S = S + ",";
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);
}
}

+ 11
- 9
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(

+ 38
- 31
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<self.constants.length; i++) {
@ -852,19 +854,27 @@ class BuilderWasm {
const fBytes = [].concat(...bytes);
this.pConstants = module.alloc(fBytes);
function Fr2Bytes(n) {
if (n.lt(bigInt("80000000", 16)) ) {
return shortMontgomeryPositive(n);
}
if (n.geq(self.header.P.minus(bigInt("80000000", 16))) ) {
return shortMontgomeryNegative(n);
const minShort = self.F.neg(self.F.e("80000000"));
const maxShort = self.F.e("7FFFFFFF", 16);
if ( (self.F.geq(n, minShort))
&&(self.F.leq(n, maxShort)))
{
if (self.F.geq(n, self.F.zero)) {
return shortMontgomeryPositive(n);
} else {
return shortMontgomeryNegative(n);
}
}
return longMontgomery(n);
function shortMontgomeryPositive(a) {
return [
...intToBytes32(parseInt(a)),
...intToBytes32(Scalar.toNumber(a)),
...intToBytes32(0x40000000),
...long(toMontgomery(a))
];
@ -872,9 +882,9 @@ class BuilderWasm {
function shortMontgomeryNegative(a) {
const b = a.minus(self.header.P);
const b = -Scalar.toNumber(self.F.neg(a));
return [
...intToBytes32(parseInt(b)),
...intToBytes32(b),
...intToBytes32(0x40000000),
...long(toMontgomery(a))
];
@ -889,27 +899,24 @@ class BuilderWasm {
}
function long(a) {
const bytes = [];
let r = bigInt(a);
let S = "";
let i = 0;
while (!r.isZero()) {
S = ("0000000000000000" + r.and(bigInt("FFFFFFFFFFFFFFFF", 16)).toString(16)).substr(-16);
bytes.push(hexToBytesR(S));
i++;
r = r.shiftRight(64);
}
while (i<self.n64) {
bytes.push(hexToBytesR("0000000000000000"));
i++;
const arr = Scalar.toArray(a, 0x100000000);
for (let i=0; i<self.F.n64*2; i++) {
const idx = arr.length-1-i;
if ( idx >=0) {
bytes.push(...intToBytes32(arr[idx]));
} else {
bytes.push(...intToBytes32(0));
}
}
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);
}
}

+ 6
- 7
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(

+ 9
- 10
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; i<ctx.functions[name].params.length; i++) {
if (!paramValues[i].used) {
constParams.push(ctx.functions[name].params[i] + utils.accSizes2Str(paramValues[i].sizes) + "=" + value2str(paramValues[i].value));
constParams.push(ctx.functions[name].params[i] + utils.accSizes2Str(paramValues[i].sizes) + "=" + value2str(ctx.F, paramValues[i].value));
}
}
let instanceDef = name;
@ -447,16 +446,16 @@ function hashFunctionCall(ctx, name, paramValues) {
return {h, instanceDef};
}
function value2str(v) {
function value2str(F, v) {
if (Array.isArray(v)) {
let S="[";
for (let i=0; i<v.length; i++) {
if (i>0) S+=",";
S+=value2str(v[i]);
S+=value2str(F, v[i]);
}
S+="]";
return S;
} else {
return bigInt(v).toString();
return F.toString(F.e(v));
}
}

+ 10
- 13
src/compiler.js

@ -17,15 +17,13 @@
along with circom. If not, see <https://www.gnu.org/licenses/>.
*/
const bigInt = require("big-integer");
const __P__ = bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
const Scalar = require("ffjavascript").Scalar;
const sONE = 0;
const build = require("./build");
const BuilderC = require("../ports/c/builder.js");
const BuilderWasm = require("../ports/wasm/builder.js");
const constructionPhase = require("./construction_phase");
const Ctx = require("./ctx");
const ZqField = require("ffjavascript").ZqField;
const utils = require("./utils");
const buildR1cs = require("./r1csfile").buildR1cs;
const BigArray = require("./bigarray");
@ -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;
}

+ 22
- 21
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<right.s[0]; i++) {
left.v[o+i]={t: "LC", coefs: {}};
left.v[o+i].coefs[right.sIdx+i] = ctx.field.one;
left.v[o+i].coefs[right.sIdx+i] = ctx.F.one;
}
}
} else if ( left.t == "S") {
@ -561,14 +562,14 @@ function execFunctionCall(ctx, ast) {
if (ev.v) {
console.log(ev.v.toString());
} else {
console.log(JSON.stringify(ev));
console.log(JSON.stringify(stringifyBigInts(ev)));
}
return;
}
if (ast.name == "assert") {
const v = exec(ctx, ast.params[0]);
const ev = val(ctx, v, ast);
if (ev.isZero()) return ctx.throwError(ast, "Assertion failed");
if (ctx.F.isZero(ev)) return ctx.throwError(ast, "Assertion failed");
}
const fnc = ctx.functions[ast.name];
@ -634,7 +635,7 @@ function execVariable(ctx, ast) {
if (ctx.error) return;
if (sel.s[0] != 1) return ctx.throwError(ast, "Variable selector cannot be an array");
if (sel.v[0].t != "N") return NQVAL;
sels.push(sel.v[0].v.toJSNumber());
sels.push(Scalar.toNumber(sel.v[0].v));
}
let o = 0;
@ -682,7 +683,7 @@ function execPin(ctx, ast) {
if (sel.s[0] != 1) return ctx.throwError(ast, "Component selector cannot be an array");
if (sel.v[0].t != "N") return NQVAL;
selsC.push(sel.v[0].v.toJSNumber());
selsC.push(Scalar.toNumber(sel.v[0].v));
}
const cIdx = ctx.getComponentIdx(ast.component.name, selsC);
@ -694,7 +695,7 @@ function execPin(ctx, ast) {
if (ctx.error) return;
if (sel.s[0] != 1) return ctx.throwError(ast, "Signal selector cannot be an array");
if (sel.v[0].t != "N") return NQVAL;
selsP.push(sel.v[0].v.toJSNumber());
selsP.push(Scalar.toNumber(sel.v[0].v));
}
const sIdx = ctx.components[cIdx].names.getSignalIdx(ast.pin.name, selsP);
@ -741,7 +742,7 @@ function execLoop(ctx, ast) {
return;
}
while ((!v.v[0].v.isZero())&&(!ctx.returnValue)) {
while ((! ctx.F.isZero(v.v[0].v))&&(!ctx.returnValue)) {
exec(ctx, ast.body);
if (ctx.error) return;
@ -784,7 +785,7 @@ function execIf(ctx, ast) {
return;
}
if (!v.v[0].v.isZero()) {
if (!ctx.F.isZero(v.v[0].v)) {
exec(ctx, ast.then);
} else {
if (ast.else) {
@ -811,7 +812,7 @@ function execTerCon(ctx, ast) {
return NQVAL;
}
if (!v.v[0].v.isZero()) {
if (!ctx.F.isZero(v.v[0].v)) {
return exec(ctx, ast.values[1]);
} else {
return exec(ctx, ast.values[2]);
@ -850,7 +851,7 @@ function execOpOp(ctx, ast, op, lr) {
if (sel.s[0] != 1) return ctx.throwError(ast, "Selector cannot be an array");
if (sel.v[0].t != "N") return {t: "NQ"};
leftSels.push( sel.v[0].v.toJSNumber() );
leftSels.push( Scalar.toNumber(sel.v[0].v) );
}
}
if (!left.s) return ctx.throwError(ast, "variable. not defined yet");
@ -870,7 +871,7 @@ function execOpOp(ctx, ast, op, lr) {
if (ctx.error) return;
right = val(ctx, rightRef);
} else {
right = {t:"N", v: ctx.field.one};
right = {t:"N", v: ctx.F.one};
}
if (!right) return ctx.throwError(ast, "adding a no number");
@ -907,7 +908,7 @@ function val(ctx, a, ast) {
};
let sIdx = a.sIdx;
while (ctx.signals[sIdx].e >= 0) sIdx = ctx.signals[sIdx].e;
res.coefs[sIdx] = ctx.field.one;
res.coefs[sIdx] = ctx.F.one;
return res;
} else {
ctx.throwError(ast, "Invalid type: " + a.t);
@ -979,7 +980,7 @@ function execArray(ctx, ast) {
} else if (e.t == "S") {
for (let j=0; j<e.v.length;j++) {
const sv = {t: "LC", coefs: {}};
sv.coefs[e.sIdx+j] = ctx.field.one;
sv.coefs[e.sIdx+j] = ctx.F.one;
res.v.push(sv);
}
} else {

+ 5
- 4
src/ctx.js

@ -1,6 +1,5 @@
const bigInt = require("big-integer");
const BigArray = require("./bigarray.js");
const F1Field = require("ffjavascript").F1Field;
class TableName {
constructor (ctx) {
@ -86,7 +85,9 @@ class TableName {
module.exports = class Ctx {
constructor() {
constructor(p) {
this.F = new F1Field(p);
this.stONE = 1;
this.stOUTPUT = 2;
@ -121,7 +122,7 @@ module.exports = class Ctx {
const oneIdx = this.addSignal("one");
this.signals[oneIdx] = {
v: bigInt(1),
v: this.F.one,
o: this.ONE,
e: -1,
};

+ 11
- 11
src/gencode.js

@ -1,7 +1,7 @@
const bigInt = require("big-integer");
const utils = require("./utils");
const assert = require("assert");
const iterateAST = require("./iterateast");
const Scalar = require("ffjavascript").Scalar;
module.exports.gen = gen;
module.exports.newRef = newRef;
@ -300,7 +300,7 @@ function genDeclareVariable(ctx, ast) {
const size = ctx.refs[sizeRef];
if (size.sizes[0] != 1) return ctx.throwError(ast, "A selector cannot be an array");
if (size.used) return ctx.throwError(ast, "Variable size variables not allowed");
sizes.push(size.value[0]);
sizes.push(Scalar.toNumber(size.value[0]));
}
sizes = utils.accSizes(sizes);
} else {
@ -320,7 +320,7 @@ function genDeclareVariable(ctx, ast) {
}
function genNumber(ctx, ast) {
return newRef(ctx, "BIGINT", "_num", bigInt(ast.value));
return newRef(ctx, "BIGINT", "_num", ctx.F.e(ast.value));
}
@ -950,7 +950,7 @@ function genLoop(ctx, ast) {
ctx.codeBuilder.assign(loopCond.label, ["R", cond.label], ["V", 0]);
} else {
if (!utils.isDefined(cond.value)) return ctx.throwError(ast, "condition value not assigned");
if (cond.value[0].isZero()) end=true;
if (ctx.F.isZero(cond.value[0])) end=true;
}
@ -993,7 +993,7 @@ function genLoop(ctx, ast) {
} else {
oldCodeBuilder.concat(ctx.codeBuilder);
ctx.codeBuilder = oldCodeBuilder;
if (cond2.value[0].isZero()) end=true;
if (ctx.F.isZero(cond2.value[0])) end=true;
}
} else {
ctx.codeBuilder.assign(loopCond.label, ["R", cond2.label], ["V", 0]);
@ -1042,7 +1042,7 @@ function genIf(ctx, ast) {
} else {
if (!utils.isDefined(cond.value)) return ctx.throwError(ast, "condition value not assigned");
if (!cond.value[0].isZero()) {
if (!ctx.F.isZero(cond.value[0])) {
gen(ctx, ast.then);
} else {
if (ast.else) {
@ -1109,9 +1109,9 @@ function genOpOp(ctx, ast, op, lr) {
const res = ctx.refs[resRef];
if (veval.used) {
instantiateRef(ctx, resRef);
ctx.codeBuilder.fieldOp(res.label, op, [["R", veval.label], ["C", ctx.addConstant(bigInt.one)]]);
ctx.codeBuilder.fieldOp(res.label, op, [["R", veval.label], ["C", ctx.addConstant(ctx.F.one)]]);
} else {
res.value = [ctx.field[op](veval.value[0], bigInt(1))];
res.value = [ctx.F[op](veval.value[0], ctx.F.one)];
}
genVarAssignment(ctx, ast, vRef, ast.values[0].selectors, resRef);
if (lr == "RIGHT") {
@ -1157,10 +1157,10 @@ function genOp(ctx, ast, op, nOps, adjustBool) {
} else {
const params = [];
for (let i=0; i<nOps; i++) {
params.push(vals[i].value[0]);
params.push(ctx.F.e(vals[i].value[0]));
}
rRef = newRef(ctx, "BIGINT", "_tmp", adjustBool ? (ctx.field[op](...params)?bigInt.one:bigInt.zero) : ctx.field[op](...params));
rRef = newRef(ctx, "BIGINT", "_tmp", adjustBool ? (ctx.F[op](...params)?ctx.F.one:ctx.F.zero) : ctx.F[op](...params));
}
return rRef;
}
@ -1242,7 +1242,7 @@ function genTerCon(ctx, ast) {
} else {
if (!utils.isDefined(cond.value)) return ctx.throwError(ast, "condition value not assigned");
if (!cond.value[0].isZero()) {
if (!ctx.F.isZero(cond.value[0])) {
return gen(ctx, ast.values[1]);
} else {
return gen(ctx, ast.values[2]);

+ 35
- 36
src/lcalgebra.js

@ -76,14 +76,13 @@ QEX QEX NQ NQ NQ
NQ NQ NQ NQ NQ
*/
const bigInt = require("big-integer");
const utils = require("./utils");
const sONE = 0;
class LCAlgebra {
constructor (aField) {
const self = this;
this.field= aField;
this.F= aField;
[
["idiv",2],
["mod",2],
@ -118,7 +117,7 @@ class LCAlgebra {
}
return {
t: "N",
v: adjustBool ? ( self.field[op](...operands) ? bigInt.one: bigInt.zero) : self.field[op](...operands)
v: adjustBool ? ( self.F[op](...operands) ? self.F.one: self.F.zero) : self.F[op](...operands)
};
};
}
@ -129,7 +128,7 @@ class LCAlgebra {
t: "LC",
coefs: {}
};
lc.coefs[a.sIdx] = bigInt(1);
lc.coefs[a.sIdx] = self.F.one;
return lc;
} else {
return a;
@ -200,17 +199,17 @@ class LCAlgebra {
function add_N_N(a,b) {
return {
t: "N",
v: self.field.add(a.v, b.v)
v: self.F.add(a.v, b.v)
};
}
function add_LC_N(a,b) {
let res = self._clone(a);
if (b.v.isZero()) return res;
if (self.F.isZero(b.v)) return res;
if (!utils.isDefined(res.coefs[sONE])) {
res.coefs[sONE]= b.v;
} else {
res.coefs[sONE]= self.field.add(res.coefs[sONE], b.v);
res.coefs[sONE]= self.F.add(res.coefs[sONE], b.v);
}
return res;
}
@ -221,7 +220,7 @@ class LCAlgebra {
if (!utils.isDefined(res.coefs[k])) {
res.coefs[k]=b.coefs[k];
} else {
res.coefs[k]= self.field.add(res.coefs[k], b.coefs[k]);
res.coefs[k]= self.F.add(res.coefs[k], b.coefs[k]);
}
}
return res;
@ -283,14 +282,14 @@ class LCAlgebra {
function mul_N_N(a,b) {
return {
t: "N",
v: self.field.mul(a.v, b.v)
v: self.F.mul(a.v, b.v)
};
}
function mul_LC_N(a,b) {
let res = self._clone(a);
for (let k in res.coefs) {
res.coefs[k] = self.field.mul(res.coefs[k], b.v);
res.coefs[k] = self.F.mul(res.coefs[k], b.v);
}
return res;
}
@ -318,10 +317,10 @@ class LCAlgebra {
const a = this._signal2lc(_a);
let res = this._clone(a);
if (res.t == "N") {
res.v = this.field.neg(a.v);
res.v = this.F.neg(a.v);
} else if (res.t == "LC") {
for (let k in res.coefs) {
res.coefs[k] = this.field.neg(res.coefs[k]);
res.coefs[k] = this.F.neg(res.coefs[k]);
}
} else if (res.t == "QEX") {
res.a = this.neg(res.a);
@ -338,10 +337,10 @@ class LCAlgebra {
div(a, b) {
if (b.t == "N") {
if (b.v.isZero()) throw new Error("Division by zero");
if (this.F.isZero(b.v)) throw new Error("Division by zero");
const inv = {
t: "N",
v: this.field.inv(b.v)
v: this.F.inv(b.v)
};
return this.mul(a, inv);
} else {
@ -351,23 +350,23 @@ class LCAlgebra {
pow(a, b) {
if (b.t == "N") {
if (b.v.isZero()) {
if (this.F.isZero(b.v)) {
if (this.isZero(a)) {
throw new Error("Zero to the Zero");
}
return {
t: "N",
v: this.field.one
v: this.F.one
};
} else if (b.v.eq(this.field.one)) {
} else if (this.F.eq(b.v, this.F.one)) {
return a;
} else if (b.v.eq(bigInt(2))) {
} else if (this.F.eq(b.v, this.F.two)) {
return this.mul(a,a);
} else {
if (a.t=="N") {
return {
t: "N",
v: this.field.pow(a.v, b.v)
v: this.F.pow(a.v, b.v)
};
} else {
return {t: "NQ"};
@ -381,18 +380,18 @@ class LCAlgebra {
substitute(where, signal, equivalence) {
if (equivalence.t != "LC") throw new Error("Equivalence must be a Linear Combination");
if (where.t == "LC") {
if (!utils.isDefined(where.coefs[signal]) || where.coefs[signal].isZero()) return where;
if (!utils.isDefined(where.coefs[signal]) || this.F.isZero(where.coefs[signal])) return where;
const res=this._clone(where);
const coef = res.coefs[signal];
for (let k in equivalence.coefs) {
if (k != signal) {
const v = this.field.mul( coef, equivalence.coefs[k] );
const v = this.F.mul( coef, equivalence.coefs[k] );
if (!utils.isDefined(res.coefs[k])) {
res.coefs[k]=v;
} else {
res.coefs[k]= this.field.add(res.coefs[k],v);
res.coefs[k]= this.F.add(res.coefs[k],v);
}
if (res.coefs[k].isZero()) delete res.coefs[k];
if (this.F.isZero(res.coefs[k])) delete res.coefs[k];
}
}
delete res.coefs[signal];
@ -436,10 +435,10 @@ class LCAlgebra {
isZero(a) {
if (a.t == "N") {
return a.v.isZero();
return this.F.isZero(a.v);
} else if (a.t == "LC") {
for (let k in a.coefs) {
if (!a.coefs[k].isZero()) return false;
if (!this.F.isZero(a.coefs[k])) return false;
}
return true;
} else if (a.t == "QEX") {
@ -455,16 +454,16 @@ class LCAlgebra {
} else if (a.t == "LC") {
let S="";
for (let k in a.coefs) {
if (!a.coefs[k].isZero()) {
if (!this.F.isZero(a.coefs[k])) {
let c;
if (a.coefs[k].greater(this.field.p.divide(2))) {
if (a.coefs[k].greater(this.F.p.divide(2))) {
S = S + "-";
c = this.field.p.minus(a.coefs[k]);
c = this.F.p.minus(a.coefs[k]);
} else {
if (S!="") S=S+" + ";
c = a.coefs[k];
}
if (!c.equals(bigInt.one)) {
if (!c.equals(this.F.one)) {
S = S + c.toString() + "*";
}
let sIdx = k;
@ -491,11 +490,11 @@ class LCAlgebra {
} else if (n.t == "SIGNAL") {
return getSignalValue(ctx, n.sIdx);
} else if (n.t == "LC") {
let v= this.field.zero;
let v= this.F.zero;
for (let k in n.coefs) {
const s = getSignalValue(ctx, k);
if (s === null) return null;
v = this.field.add(v, this.field.mul( n.coefs[k], s));
v = this.F.add(v, this.F.mul( n.coefs[k], s));
}
return v;
} else if (n.type == "QEX") {
@ -506,7 +505,7 @@ class LCAlgebra {
const c = this.evaluate(ctx, n.c);
if (c === null) return null;
return this.field.add(this.field.mul(a,b), c);
return this.F.add(this.F.mul(a,b), c);
} else {
return null;
}
@ -529,24 +528,24 @@ class LCAlgebra {
let s = k;
while (ctx.signals[s].e>=0) s= ctx.signals[s].e;
if (utils.isDefined(ctx.signals[s].v)&&(k != sONE)) {
const v = this.field.mul(res.coefs[k], ctx.signals[s].v);
const v = this.F.mul(res.coefs[k], ctx.signals[s].v);
if (!utils.isDefined(res.coefs[sONE])) {
res.coefs[sONE]=v;
} else {
res.coefs[sONE]= this.field.add(res.coefs[sONE], v);
res.coefs[sONE]= this.F.add(res.coefs[sONE], v);
}
delete res.coefs[k];
} else if (s != k) {
if (!utils.isDefined(res.coefs[s])) {
res.coefs[s]=res.coefs[k];
} else {
res.coefs[s]= this.field.add(res.coefs[s], res.coefs[k]);
res.coefs[s]= this.F.add(res.coefs[s], res.coefs[k]);
}
delete res.coefs[k];
}
}
for (let k in res.coefs) {
if (res.coefs[k].isZero()) delete res.coefs[k];
if (this.F.isZero(res.coefs[k])) delete res.coefs[k];
}
return res;
} else if (a.t == "QEX") {

+ 4
- 4
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<dwords.length; i++) {
b.writeUInt32LE(dwords[dwords.length-1-i], i*4, 4 );

+ 1
- 40
src/utils.js

@ -1,5 +1,4 @@
const fnv = require("fnv-plus");
const bigInt = require("big-integer");
module.exports.ident =ident;
@ -8,8 +7,6 @@ module.exports.flatArray = flatArray;
module.exports.csArr = csArr;
module.exports.accSizes = accSizes;
module.exports.fnvHash = fnvHash;
module.exports.stringifyBigInts = stringifyBigInts;
module.exports.unstringifyBigInts = unstringifyBigInts;
module.exports.sameSizes = sameSizes;
module.exports.isDefined = isDefined;
module.exports.accSizes2Str = accSizes2Str;
@ -45,7 +42,7 @@ function flatArray(a) {
fillArray(res, a[i]);
}
} else {
res.push(bigInt(a));
res.push(a);
}
}
}
@ -74,42 +71,6 @@ function fnvHash(str) {
return fnv.hash(str, 64).hex();
}
function stringifyBigInts(o) {
if ((typeof(o) == "bigint") || o.eq !== undefined) {
return o.toString(10);
} else if (Array.isArray(o)) {
return o.map(stringifyBigInts);
} else if (typeof o == "object") {
const res = {};
for (let k in o) {
res[k] = stringifyBigInts(o[k]);
}
return res;
} else {
return o;
}
}
function unstringifyBigInts(o) {
if ((typeof(o) == "string") && (/^[0-9]+$/.test(o) )) {
return bigInt(o);
} else if (Array.isArray(o)) {
return o.map(unstringifyBigInts);
} else if (typeof o == "object") {
const res = {};
for (let k in o) {
res[k] = unstringifyBigInts(o[k]);
}
return res;
} else {
return bigInt(o);
}
}
function sameSizes(s1, s2) {
if (!Array.isArray(s1)) return false;
if (!Array.isArray(s2)) return false;

+ 7
- 11
test/basiccases.js

@ -1,17 +1,19 @@
const path = require("path");
const bigInt = require("big-integer");
const Scalar = require("ffjavascript").Scalar;
const F1Field = require("ffjavascript").F1Field;
const c_tester = require("../index.js").c_tester;
const wasm_tester = require("../index.js").wasm_tester;
const __P__ = new bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
const __P__ = Scalar.fromString("21888242871839275222246405745257275088548364400416034343698204186575808495617");
const Fr = new F1Field(__P__);
const basicCases = require("./basiccases.json");
function normalize(o) {
if ((typeof(o) == "bigint") || o.isZero !== undefined) {
const res = bigInt(o);
return norm(res);
return Fr.e(o);
} else if (Array.isArray(o)) {
return o.map(normalize);
} else if (typeof o == "object") {
@ -21,15 +23,9 @@ function normalize(o) {
}
return res;
} else {
const res = bigInt(o);
return norm(res);
return Fr.e(o);
}
function norm(n) {
let res = n.mod(__P__);
if (res.isNegative()) res = __P__.add(res);
return res;
}
}

Loading…
Cancel
Save