mirror of
https://github.com/arnaucube/circom.git
synced 2026-02-06 18:56:40 +01:00
Almost ready for 0.5.0
This commit is contained in:
@@ -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");
|
||||
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user