Use native big int

This commit is contained in:
Jordi Baylina
2020-04-18 20:53:13 +02:00
parent f25842f67c
commit 767ca60008
18 changed files with 276 additions and 518 deletions

View File

@@ -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);
}
}

View File

@@ -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(