Almost ready for 0.5.0

This commit is contained in:
Jordi Baylina
2020-03-26 17:42:25 +01:00
parent ef899e618b
commit eb8cb0af74
62 changed files with 1249 additions and 15153 deletions

View File

@@ -1,13 +1,16 @@
const errs = require("./errs");
const buildWasmFf = require("fflib").buildWasmFf;
const buildWasmFf = require("ffwasm").buildWasmFf;
module.exports = function buildRuntime(module, builder) {
const pSanityCheck = module.alloc(4);
function buildInit() {
const f = module.addFunction("init");
f.addParam("sanityCheck", "i32");
f.addLocal("i", "i32");
const c = f.getCodeBuilder();
@@ -26,6 +29,14 @@ module.exports = function buildRuntime(module, builder) {
)
);
// Save Sanity check flag
f.addCode(
c.i32_store(
c.i32_const(pSanityCheck),
c.getLocal("sanityCheck")
)
);
f.addCode(
// i=0
c.setLocal("i", c.i32_const(0)),
@@ -66,38 +77,36 @@ module.exports = function buildRuntime(module, builder) {
))
);
if (builder.sanityCheck) {
f.addCode(
// i=0
c.setLocal("i", c.i32_const(0)),
c.block(c.loop(
// if (i==NSignals) break
c.br_if(1, c.i32_eq(c.getLocal("i"), c.i32_const(builder.header.NSignals))),
f.addCode(ifSanityCheck(c,
// i=0
c.setLocal("i", c.i32_const(0)),
c.block(c.loop(
// if (i==NSignals) break
c.br_if(1, c.i32_eq(c.getLocal("i"), c.i32_const(builder.header.NSignals))),
// signalsAssigned[i] = false
c.i32_store(
c.i32_add(
c.i32_const(builder.pSignalsAssigned),
c.i32_mul(
c.getLocal("i"),
c.i32_const(4)
)
),
c.i32_const(0)
),
// i=i+1
c.setLocal(
"i",
c.i32_add(
// signalsAssigned[i] = false
c.i32_store(
c.i32_add(
c.i32_const(builder.pSignalsAssigned),
c.i32_mul(
c.getLocal("i"),
c.i32_const(1)
c.i32_const(4)
)
),
c.br(0)
))
);
}
c.i32_const(0)
),
// i=i+1
c.setLocal(
"i",
c.i32_add(
c.getLocal("i"),
c.i32_const(1)
)
),
c.br(0)
))
));
f.addCode(
c.call(
@@ -109,14 +118,12 @@ module.exports = function buildRuntime(module, builder) {
)
)
);
if (builder.sanityCheck) {
f.addCode(
c.i32_store(
c.i32_const(builder.pSignalsAssigned),
c.i32_const(1)
)
);
}
f.addCode(ifSanityCheck(c,
c.i32_store(
c.i32_const(builder.pSignalsAssigned),
c.i32_const(1)
)
));
f.addCode(
// i=0
@@ -158,6 +165,13 @@ module.exports = function buildRuntime(module, builder) {
}
function ifSanityCheck(c, ...args) {
return c.if(
c.i32_load(c.i32_const(pSanityCheck)),
[].concat(...[...args])
);
}
function buildTriggerComponent() {
const f = module.addFunction("triggerComponent");
@@ -227,9 +241,13 @@ module.exports = function buildRuntime(module, builder) {
c.if(
c.i64_eqz(c.getLocal("h")),
c.call(
"err",
"error",
c.i32_const(errs.HASH_NOT_FOUND.code),
c.i32_const(errs.HASH_NOT_FOUND.pointer)
c.i32_const(errs.HASH_NOT_FOUND.pointer),
c.i32_const(0),
c.i32_const(0),
c.i32_const(0),
c.i32_const(0)
)
),
c.setLocal(
@@ -296,9 +314,13 @@ module.exports = function buildRuntime(module, builder) {
c.i32_const(type)
),
c.call(
"err",
"error",
c.i32_const(errs.INVALID_TYPE.code),
c.i32_const(errs.INVALID_TYPE.pointer)
c.i32_const(errs.INVALID_TYPE.pointer),
c.i32_const(0),
c.i32_const(0),
c.i32_const(0),
c.i32_const(0)
)
),
c.i32_store(
@@ -345,28 +367,30 @@ module.exports = function buildRuntime(module, builder) {
const c = f.getCodeBuilder();
if (builder.sanityCheck) {
f.addCode(
c.if(
c.i32_eqz(
c.i32_load(
c.i32_add(
c.i32_const(builder.pSignalsAssigned),
c.i32_mul(
c.getLocal("signal"),
c.i32_const(4)
)
),
)
),
c.call(
"err",
c.i32_const(errs.ACCESSING_NOT_ASSIGNED_SIGNAL.code),
c.i32_const(errs.ACCESSING_NOT_ASSIGNED_SIGNAL.pointer)
f.addCode(ifSanityCheck(c,
c.if(
c.i32_eqz(
c.i32_load(
c.i32_add(
c.i32_const(builder.pSignalsAssigned),
c.i32_mul(
c.getLocal("signal"),
c.i32_const(4)
)
),
)
),
c.call(
"error",
c.i32_const(errs.ACCESSING_NOT_ASSIGNED_SIGNAL.code),
c.i32_const(errs.ACCESSING_NOT_ASSIGNED_SIGNAL.pointer),
c.i32_const(0),
c.i32_const(0),
c.i32_const(0),
c.i32_const(0)
)
);
}
)
));
f.addCode(
c.call(
@@ -381,6 +405,11 @@ module.exports = function buildRuntime(module, builder) {
)
)
);
f.addCode(ifSanityCheck(c,
c.call("logGetSignal", c.getLocal("signal"), c.getLocal("pR") )
));
}
@@ -395,25 +424,10 @@ module.exports = function buildRuntime(module, builder) {
const c = f.getCodeBuilder();
if (builder.sanityCheck) {
f.addCode(
c.if(
c.i32_load(
c.i32_add(
c.i32_const(builder.pSignalsAssigned),
c.i32_mul(
c.getLocal("signal"),
c.i32_const(4)
)
),
),
c.call(
"err",
c.i32_const(errs.SIGNAL_ASSIGNED_TWICE.code),
c.i32_const(errs.SIGNAL_ASSIGNED_TWICE.pointer)
)
),
c.i32_store(
f.addCode(ifSanityCheck(c,
c.call("logSetSignal", c.getLocal("signal"), c.getLocal("pVal") ),
c.if(
c.i32_load(
c.i32_add(
c.i32_const(builder.pSignalsAssigned),
c.i32_mul(
@@ -421,10 +435,28 @@ module.exports = function buildRuntime(module, builder) {
c.i32_const(4)
)
),
c.i32_const(1)
),
);
}
c.call(
"error",
c.i32_const(errs.SIGNAL_ASSIGNED_TWICE.code),
c.i32_const(errs.SIGNAL_ASSIGNED_TWICE.pointer),
c.i32_const(0),
c.i32_const(0),
c.i32_const(0),
c.i32_const(0)
)
),
c.i32_store(
c.i32_add(
c.i32_const(builder.pSignalsAssigned),
c.i32_mul(
c.getLocal("signal"),
c.i32_const(4)
)
),
c.i32_const(1)
),
));
f.addCode(
c.call(
@@ -510,11 +542,13 @@ module.exports = function buildRuntime(module, builder) {
)
],
c.call(
"err2",
"error",
c.i32_const(errs.MAPISINPUT_DONT_MATCH.code),
c.i32_const(errs.MAPISINPUT_DONT_MATCH.pointer),
c.getLocal("component"),
c.getLocal("signal")
c.getLocal("signal"),
c.i32_const(0),
c.i32_const(0)
)
)
]
@@ -528,6 +562,23 @@ module.exports = function buildRuntime(module, builder) {
const c = f.getCodeBuilder();
f.addCode(ifSanityCheck(c,
c.call("logFinishComponent", c.getLocal("cIdx"))
));
f.addCode(c.ret([]));
}
function buildComponentStarted() {
const f = module.addFunction("componentStarted");
f.addParam("cIdx", "i32");
const c = f.getCodeBuilder();
f.addCode(ifSanityCheck(c,
c.call("logStartComponent", c.getLocal("cIdx"))
));
f.addCode(c.ret([]));
}
@@ -541,33 +592,31 @@ module.exports = function buildRuntime(module, builder) {
const c = f.getCodeBuilder();
if (builder.sanityCheck) {
f.addCode(
c.call(
"Fr_eq",
c.i32_const(pTmp),
c.getLocal("pA"),
c.getLocal("pB")
),
c.if (
c.i32_eqz(
c.call(
"Fr_isTrue",
c.i32_const(pTmp),
)
),
f.addCode(ifSanityCheck(c,
c.call(
"Fr_eq",
c.i32_const(pTmp),
c.getLocal("pA"),
c.getLocal("pB")
),
c.if (
c.i32_eqz(
c.call(
"err4",
c.i32_const(errs.CONSTRAIN_DOES_NOT_MATCH.code),
c.i32_const(errs.CONSTRAIN_DOES_NOT_MATCH.pointer),
c.getLocal("cIdx"),
c.getLocal("pA"),
c.getLocal("pB"),
c.getLocal("pStr"),
"Fr_isTrue",
c.i32_const(pTmp),
)
),
c.call(
"error",
c.i32_const(errs.CONSTRAIN_DOES_NOT_MATCH.code),
c.i32_const(errs.CONSTRAIN_DOES_NOT_MATCH.pointer),
c.getLocal("cIdx"),
c.getLocal("pA"),
c.getLocal("pB"),
c.getLocal("pStr"),
)
);
}
)
));
}
function buildGetNVars() {
@@ -638,9 +687,13 @@ module.exports = function buildRuntime(module, builder) {
)
),
c.call(
"err",
"error",
c.i32_const(errs.ACCESSING_NOT_ASSIGNED_SIGNAL.code),
c.i32_const(errs.ACCESSING_NOT_ASSIGNED_SIGNAL.pointer)
c.i32_const(errs.ACCESSING_NOT_ASSIGNED_SIGNAL.pointer),
c.i32_const(0),
c.i32_const(0),
c.i32_const(0),
c.i32_const(0)
)
)
);
@@ -658,35 +711,92 @@ module.exports = function buildRuntime(module, builder) {
);
}
const fErr = module.addIimportFunction("err", "runtime");
fErr.addParam("code", "i32");
fErr.addParam("pStr", "i32");
function buildGetWitnessBuffer() {
const f = module.addFunction("getWitnessBuffer");
f.setReturnType("i32");
f.addLocal("i", "i32");
f.addLocal("pSrc", "i32");
f.addLocal("pDst", "i32");
const fErr1 = module.addIimportFunction("err1", "runtime");
fErr1.addParam("code", "i32");
fErr1.addParam("pStr", "i32");
fErr1.addParam("param1", "i32");
const c = f.getCodeBuilder();
const fErr2 = module.addIimportFunction("err2", "runtime");
fErr2.addParam("code", "i32");
fErr2.addParam("pStr", "i32");
fErr2.addParam("param1", "i32");
fErr2.addParam("param2", "i32");
f.addCode(
c.setLocal("i", c.i32_const(0)),
c.block(c.loop(
// if (i==NComponents) break
c.br_if(1, c.i32_eq(c.getLocal("i"), c.i32_const(builder.header.NVars))),
const fErr3 = module.addIimportFunction("err3", "runtime");
fErr3.addParam("code", "i32");
fErr3.addParam("pStr", "i32");
fErr3.addParam("param1", "i32");
fErr3.addParam("param2", "i32");
fErr3.addParam("param3", "i32");
c.setLocal(
"pSrc",
c.i32_add(
c.i32_const(builder.pSignals),
c.i32_mul(
c.getLocal("i"),
c.i32_const(builder.sizeFr)
)
)
),
const fErr4 = module.addIimportFunction("err4", "runtime");
fErr4.addParam("code", "i32");
fErr4.addParam("pStr", "i32");
fErr4.addParam("param1", "i32");
fErr4.addParam("param2", "i32");
fErr4.addParam("param3", "i32");
fErr4.addParam("param4", "i32");
c.call(
"Fr_toLongNormal",
c.getLocal("pSrc")
),
c.setLocal(
"pDst",
c.i32_add(
c.i32_const(builder.pSignals),
c.i32_mul(
c.getLocal("i"),
c.i32_const(builder.sizeFr-8)
)
)
),
c.call(
"Fr_F1m_copy",
c.i32_add(c.getLocal("pSrc"), c.i32_const(8)),
c.getLocal("pDst")
),
// i=i+1
c.setLocal(
"i",
c.i32_add(
c.getLocal("i"),
c.i32_const(1)
)
),
c.br(0)
)),
c.i32_const(builder.pSignals)
);
}
const fError = module.addIimportFunction("error", "runtime");
fError.addParam("code", "i32");
fError.addParam("pStr", "i32");
fError.addParam("param1", "i32");
fError.addParam("param2", "i32");
fError.addParam("param3", "i32");
fError.addParam("param4", "i32");
const fLogSetSignal = module.addIimportFunction("logSetSignal", "runtime");
fLogSetSignal.addParam("signal", "i32");
fLogSetSignal.addParam("val", "i32");
const fLogGetSignal = module.addIimportFunction("logGetSignal", "runtime");
fLogGetSignal.addParam("signal", "i32");
fLogGetSignal.addParam("val", "i32");
const fLogFinishComponent = module.addIimportFunction("logFinishComponent", "runtime");
fLogFinishComponent.addParam("cIdx", "i32");
const fLogStartComponent = module.addIimportFunction("logStartComponent", "runtime");
fLogStartComponent.addParam("cIdx", "i32");
const fLog = module.addIimportFunction("log", "runtime");
fLog.addParam("code", "i32");
@@ -695,9 +805,7 @@ module.exports = function buildRuntime(module, builder) {
builder.pSignals=module.alloc(builder.header.NSignals*builder.sizeFr);
builder.pInputSignalsToTrigger=module.alloc(builder.header.NComponents*4);
if (builder.sanityCheck) {
builder.pSignalsAssigned=module.alloc(builder.header.NSignals*4);
}
builder.pSignalsAssigned=module.alloc(builder.header.NSignals*4);
buildHash2ComponentEntry();
@@ -713,6 +821,7 @@ module.exports = function buildRuntime(module, builder) {
buildGetSignal();
buildSetSignal();
buildComponentStarted();
buildComponentFinished();
buildCheckConstraint();
@@ -721,6 +830,7 @@ module.exports = function buildRuntime(module, builder) {
buildGetFrLen();
buildGetPWitness();
buildGetPRawPrime();
buildGetWitnessBuffer();
// buildFrToInt();
@@ -732,5 +842,6 @@ module.exports = function buildRuntime(module, builder) {
module.exportFunction("getPWitness");
module.exportFunction("Fr_toInt");
module.exportFunction("getPRawPrime");
module.exportFunction("getWitnessBuffer");
};

View File

@@ -528,9 +528,13 @@ class FunctionBuilderWasm {
c.getLocal("sp")
),
c.call(
"err",
"error",
c.i32_const(errs.STACK_OUT_OF_MEM.code),
c.i32_const(errs.STACK_OUT_OF_MEM.pointer)
c.i32_const(errs.STACK_OUT_OF_MEM.pointer),
c.i32_const(0),
c.i32_const(0),
c.i32_const(0),
c.i32_const(0)
)
),
@@ -550,9 +554,13 @@ class FunctionBuilderWasm {
c.getLocal("sp")
),
c.call(
"err",
"error",
c.i32_const(errs.STACK_TOO_SMALL.code),
c.i32_const(errs.STACK_TOO_SMALL.pointer)
c.i32_const(errs.STACK_TOO_SMALL.pointer),
c.i32_const(0),
c.i32_const(0),
c.i32_const(0),
c.i32_const(0)
)
),
@@ -650,7 +658,12 @@ class FunctionBuilderWasm {
const c = f.getCodeBuilder();
const code = [];
if (this.type=="COMPONENT") {
code.push(c.call("componentStarted", c.getLocal("cIdx")));
}
code.push(this._buildHeader(c));
code.push(this.body.build(c));
if (this.type=="COMPONENT") {
@@ -676,7 +689,7 @@ class FunctionBuilderWasm {
}
class BuilderWasm {
constructor(sanityCheck) {
constructor() {
this.hashMaps={};
this.componentEntriesTables={};
this.sizes ={};
@@ -684,7 +697,6 @@ class BuilderWasm {
this.usedConstants = {};
this.functions = [];
this.components = [];
this.sanityCheck = sanityCheck;
this.TYPE_SIGNAL = 1;
this.TYPE_COMPONENT = 2;

View File

@@ -5,21 +5,16 @@ const fs = require("fs");
var tmp = require("tmp-promise");
const path = require("path");
const compiler = require("../../src/compiler");
const util = require("util");
const exec = util.promisify(require("child_process").exec);
const stringifyBigInts = require("../../src/utils").stringifyBigInts;
const unstringifyBigInts = require("../../src/utils").unstringifyBigInts;
const bigInt = require("big-integer");
const utils = require("../../src/utils");
const loadR1cs = require("../../src/r1csfile").loadR1cs;
const ZqField = require("fflib").ZqField;
const loadR1cs = require("r1csfile").load;
const ZqField = require("ffjavascript").ZqField;
const WitnessCalculator = require("./witness_calculator");
const WitnessCalculatorBuilder = require("circom_runtime").WitnessCalculatorBuilder;
module.exports = wasm_tester;
async function wasm_tester(circomFile, _options) {
tmp.setGracefulCleanup();
@@ -33,7 +28,6 @@ async function wasm_tester(circomFile, _options) {
options.wasmWriteStream = fs.createWriteStream(path.join(dir.path, baseName + ".wasm"));
options.symWriteStream = fs.createWriteStream(path.join(dir.path, baseName + ".sym"));
options.r1csFileName = path.join(dir.path, baseName + ".r1cs");
options.sanityCheck = true;
const promisesArr = [];
promisesArr.push(new Promise(fulfill => options.wasmWriteStream.on("finish", fulfill)));
@@ -42,7 +36,9 @@ async function wasm_tester(circomFile, _options) {
await Promise.all(promisesArr);
const wc = await WitnessCalculator.fromFile(path.join(dir.path, baseName + ".wasm"));
const wasm = await fs.promises.readFile(path.join(dir.path, baseName + ".wasm"));
const wc = await WitnessCalculatorBuilder(wasm);
return new WasmTester(dir, baseName, wc);
}
@@ -74,10 +70,11 @@ class WasmTester {
const lines = symsStr.split("\n");
for (let i=0; i<lines.length; i++) {
const arr = lines[i].split(",");
if (arr.length!=3) continue;
this.symbols[arr[2]] = {
idx: Number(arr[0]),
idxWit: Number(arr[1])
if (arr.length!=4) continue;
this.symbols[arr[3]] = {
labelIdx: Number(arr[0]),
varIdx: Number(arr[1]),
componentIdx: Number(arr[2]),
};
}
}
@@ -87,7 +84,7 @@ class WasmTester {
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.nWires = r1cs.nWires;
self.nVars = r1cs.nVars;
self.constraints = r1cs.constraints;
}
@@ -111,7 +108,7 @@ class WasmTester {
if (typeof self.symbols[prefix] == "undefined") {
assert(false, "Output variable not defined: "+ prefix);
}
const ba = bigInt(actualOut[self.symbols[prefix].idxWit]).toString();
const ba = bigInt(actualOut[self.symbols[prefix].varIdx]).toString();
const be = bigInt(eOut).toString();
assert.strictEqual(ba, be, prefix);
}
@@ -124,8 +121,8 @@ class WasmTester {
if (!self.symbols) await self.loadSymbols();
for (let n in self.symbols) {
let v;
if (utils.isDefined(witness[self.symbols[n].idxWit])) {
v = witness[self.symbols[n].idxWit].toString();
if (utils.isDefined(witness[self.symbols[n].varIdx])) {
v = witness[self.symbols[n].varIdx].toString();
} else {
v = "undefined";
}
@@ -143,9 +140,9 @@ class WasmTester {
function checkConstraint(constraint) {
const F = self.field;
const a = evalLC(constraint.a);
const b = evalLC(constraint.b);
const c = evalLC(constraint.c);
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");
}

View File

@@ -1,209 +0,0 @@
/* globals WebAssembly */
const fs = require("fs");
const utils = require("../../src/utils");
const bigInt = require("big-integer");
module.exports.fromFile = async function(file) {
const code = await fs.promises.readFile(file);
return await module.exports.fromBuffer(code);
};
module.exports.fromBuffer = async function(code) {
const memory = new WebAssembly.Memory({initial:20000});
const wasmModule = await WebAssembly.compile(code);
let wc;
const instance = await WebAssembly.instantiate(wasmModule, {
env: {
"memory": memory
},
runtime: {
err: function(code, pstr) {
const errStr=p2str(pstr);
console.log("ERROR: ", code, errStr);
throw new Error(errStr);
},
err1: function(code, pstr, a) {
const errStr=p2str(pstr)+ " " + a;
console.log("ERROR: ", code, errStr);
throw new Error(errStr);
},
err2: function(code, pstr, a, b) {
const errStr=p2str(pstr)+ " " + a + " " + b;
console.log("ERROR: ", code, errStr);
throw new Error(errStr);
},
err3: function(code, pstr, a, b, c) {
const errStr=p2str(pstr)+ " " + a + " " + b + " " + c;
console.log("ERROR: ", code, errStr);
throw new Error(errStr);
},
err4: function(code, pstr, a,b,c,d) {
const errStr=p2str(pstr) + " " + wc.getFr(b).toString() + " != " + wc.getFr(c).toString() + " " +p2str(d);
console.log("ERROR: ", code, errStr);
throw new Error(errStr);
},
log: function(a) {
console.log(wc.getFr(a).toString());
},
}
});
wc = new WitnessCalculator(memory, instance);
return wc;
function p2str(p) {
const i8 = new Uint8Array(memory.buffer);
const bytes = [];
for (let i=0; i8[p+i]>0; i++) bytes.push(i8[p+i]);
return String.fromCharCode.apply(null, bytes);
}
};
class WitnessCalculator {
constructor(memory, instance) {
this.memory = memory;
this.i32 = new Uint32Array(memory.buffer);
this.instance = instance;
this.n32 = (this.instance.exports.getFrLen() >> 2) - 2;
const pRawPrime = this.instance.exports.getPRawPrime();
this.prime = bigInt(0);
for (let i=this.n32-1; i>=0; i--) {
this.prime = this.prime.shiftLeft(32);
this.prime = this.prime.add(bigInt(this.i32[(pRawPrime >> 2) + i]));
}
this.mask32 = bigInt("FFFFFFFF", 16);
this.NVars = this.instance.exports.getNVars();
this.n64 = Math.floor((this.prime.bitLength() - 1) / 64)+1;
this.R = bigInt.one.shiftLeft(this.n64*64);
this.RInv = this.R.modInv(this.prime);
}
async calculateWitness(input) {
const w = [];
const old0 = this.i32[0];
this.instance.exports.init();
const pSigOffset = this.allocInt();
const pFr = this.allocFr();
for (let k in input) {
const h = utils.fnvHash(k);
const hMSB = parseInt(h.slice(0,8), 16);
const hLSB = parseInt(h.slice(8,16), 16);
this.instance.exports.getSignalOffset32(pSigOffset, 0, hMSB, hLSB);
const sigOffset = this.getInt(pSigOffset);
const fArr = utils.flatArray(input[k]);
for (let i=0; i<fArr.length; i++) {
this.setFr(pFr, fArr[i]);
this.instance.exports.setSignal(0, 0, sigOffset + i, pFr);
}
}
for (let i=0; i<this.NVars; i++) {
const pWitness = this.instance.exports.getPWitness(i);
w.push(this.getFr(pWitness));
}
this.i32[0] = old0;
return w;
}
allocInt() {
const p = this.i32[0];
this.i32[0] = p+8;
return p;
}
allocFr() {
const p = this.i32[0];
this.i32[0] = p+this.n32*4 + 8;
return p;
}
getInt(p) {
return this.i32[p>>2];
}
setInt(p, v) {
this.i32[p>>2] = v;
}
getFr(p) {
const self = this;
const idx = (p>>2);
if (self.i32[idx + 1] & 0x80000000) {
let res= bigInt(0);
for (let i=self.n32-1; i>=0; i--) {
res = res.shiftLeft(32);
res = res.add(bigInt(self.i32[idx+2+i]));
}
if (self.i32[idx + 1] & 0x40000000) {
return fromMontgomery(res);
} else {
return res;
}
} else {
if (self.i32[idx] & 0x80000000) {
return self.prime.add( bigInt(self.i32[idx]).minus(bigInt(0x100000000)) );
} else {
return bigInt(self.i32[idx]);
}
}
function fromMontgomery(n) {
return n.times(self.RInv).mod(self.prime);
}
}
setFr(p, v) {
const self = this;
v = bigInt(v);
if (v.lt(bigInt("80000000", 16)) ) {
return setShortPositive(v);
}
if (v.geq(self.prime.minus(bigInt("80000000", 16))) ) {
return setShortNegative(v);
}
return setLongNormal(v);
function setShortPositive(a) {
self.i32[(p >> 2)] = parseInt(a);
self.i32[(p >> 2) + 1] = 0;
}
function setShortNegative(a) {
const b = bigInt("80000000", 16 ).add(a.minus( self.prime.minus(bigInt("80000000", 16 ))));
self.i32[(p >> 2)] = parseInt(b);
self.i32[(p >> 2) + 1] = 0;
}
function setLongNormal(a) {
self.i32[(p >> 2)] = 0;
self.i32[(p >> 2) + 1] = 0x80000000;
for (let i=0; i<self.n32; i++) {
self.i32[(p >> 2) + 2 + i] = a.shiftRight(i*32).and(self.mask32);
}
}
}
}