/*
Copyright 2018 0kims association.
This file is part of zksnark JavaScript library.
zksnark JavaScript library is a free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your option)
any later version.
zksnark JavaScript library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
zksnark JavaScript library. If not, see .
*/
const bigInt = require("./bigint");
module.exports = calculateWitness;
function calculateWitness(circuit, inputSignals, log) {
log = log || (() => {});
const ctx = new RTCtx(circuit, log);
function iterateSelector(values, sels, cb) {
if (!Array.isArray(values)) {
return cb(sels, values);
}
for (let i=0; i " + ctx.witness[i].toString());
}
// return ctx.witness.slice(0, circuit.nVars);
return ctx.witness;
}
class RTCtx {
constructor(circuit, log) {
this.log = log || function() {};
this.scopes = [];
this.circuit = circuit;
this.witness = new Array(circuit.nSignals);
this.notInitSignals = {};
for (let c in this.circuit.components) {
this.notInitSignals[c] = this.circuit.components[c].inputSignals;
}
}
_sels2str(sels) {
let res = "";
for (let i=0; i {
if (this.notInitSignals[c] == 0) this.triggerComponent(c);
});
return value;
}
setVar(name, sels, value) {
function setVarArray(a, sels2, value) {
if (sels2.length == 1) {
a[sels2[0]] = value;
} else {
if (typeof(a[sels2[0]]) == "undefined") a[sels2[0]] = [];
setVarArray(a[sels2[0]], sels2.slice(1), value);
}
}
const scope = this.scopes[this.scopes.length-1];
if (sels.length == 0) {
scope[name] = value;
} else {
if (typeof(scope[name]) == "undefined") scope[name] = [];
setVarArray(scope[name], sels, value);
}
return value;
}
getVar(name, sels) {
function select(a, sels2) {
return (sels2.length == 0) ? a : select(a[sels2[0]], sels2.slice(1));
}
for (let i=this.scopes.length-1; i>=0; i--) {
if (typeof(this.scopes[i][name]) != "undefined") return select(this.scopes[i][name], sels);
}
throw new Error("Variable not defined: " + name);
}
getSignal(name, sels) {
let fullName = name=="one" ? "one" : this.currentComponent + "." + name;
fullName += this._sels2str(sels);
return this.getSignalFullName(fullName);
}
getPin(componentName, componentSels, signalName, signalSels) {
let fullName = componentName=="one" ? "one" : this.currentComponent + "." + componentName;
fullName += this._sels2str(componentSels) +
"."+
signalName+
this._sels2str(signalSels);
return this.getSignalFullName(fullName);
}
getSignalFullName(fullName) {
const sId = this.circuit.getSignalIdx(fullName);
if (typeof(this.witness[sId]) == "undefined") {
throw new Error("Signal not initialized: "+fullName);
}
this.log("get --->" + fullName + " = " + this.witness[sId].toString() );
return this.witness[sId];
}
assert(a,b) {
const ba = bigInt(a);
const bb = bigInt(b);
if (!ba.equals(bb)) {
throw new Error("Constraint doesn't match: " + ba.toString() + " != " + bb.toString());
}
}
}