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

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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") {

View File

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

View File

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