/* 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); } 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()); } } }