@ -1,4 +1,4 @@ |
|||
exports.Circuit = require "./src/circuit.js"; |
|||
exports.setup = require "./src/setup.js"; |
|||
exports.genProof = require "./src/prover.js"; |
|||
exports.isValid = require "./src/verifier.js"; |
|||
exports.Circuit = require("./src/circuit.js"); |
|||
exports.setup = require("./src/setup.js"); |
|||
exports.genProof = require("./src/prover.js"); |
|||
exports.isValid = require("./src/verifier.js"); |
@ -0,0 +1,209 @@ |
|||
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<values.length; i++) { |
|||
sels.push(i); |
|||
iterateSelector(values[i], sels, cb); |
|||
sels.pop(i); |
|||
} |
|||
} |
|||
|
|||
ctx.setSignal("one", [], bigInt(1)); |
|||
|
|||
for (let c in ctx.notInitSignals) { |
|||
if (ctx.notInitSignals[c] == 0) ctx.triggerComponent(c); |
|||
} |
|||
|
|||
for (let s in inputSignals) { |
|||
ctx.currentComponent = "main"; |
|||
iterateSelector(inputSignals[s], [], function(selector, value) { |
|||
ctx.setSignal(s, selector, bigInt(value)); |
|||
}); |
|||
} |
|||
|
|||
for (let i=0; i<circuit.nInputs; i++) { |
|||
const idx = circuit.inputIdx(i); |
|||
if (typeof(ctx.witness[idx]) == "undefined") { |
|||
throw new Error("Input Signal not assigned: " + circuit.signalNames(i)); |
|||
} |
|||
} |
|||
|
|||
|
|||
for (let i=0; i<ctx.witness.length; i++) { |
|||
if (typeof(ctx.witness[i]) == "undefined") { |
|||
throw new Error("Signal not assigned: " + circuit.signalNames(i)); |
|||
} |
|||
log(circuit.signalNames(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<sels.length; i++) { |
|||
res += `[${sels[i]}]`; |
|||
} |
|||
return res; |
|||
} |
|||
|
|||
setPin(componentName, componentSels, signalName, signalSels, value) { |
|||
let fullName = componentName=="one" ? "one" : this.currentComponent + "." + componentName; |
|||
fullName += this._sels2str(componentSels) + |
|||
"."+ |
|||
signalName+ |
|||
this._sels2str(signalSels); |
|||
this.setSignalFullName(fullName, value); |
|||
} |
|||
|
|||
setSignal(name, sels, value) { |
|||
let fullName = this.currentComponent ? this.currentComponent + "." + name : name; |
|||
fullName += this._sels2str(sels); |
|||
this.setSignalFullName(fullName, value); |
|||
} |
|||
|
|||
triggerComponent(c) { |
|||
this.log("Component Treiggered: " + c); |
|||
|
|||
// Set notInitSignals to -1 to not initialize again
|
|||
this.notInitSignals[c] --; |
|||
const oldComponent = this.currentComponent; |
|||
this.currentComponent = this.circuit.components[c].name; |
|||
const template = this.circuit.components[c].template; |
|||
|
|||
const newScope = {}; |
|||
for (let p in this.circuit.components[c].params) { |
|||
newScope[p] = this.circuit.components[c].params[p]; |
|||
} |
|||
|
|||
const oldScope = this.scopes; |
|||
this.scopes = [ this.scopes[0], newScope ]; |
|||
|
|||
// TODO set params.
|
|||
|
|||
this.circuit.templates[template](this); |
|||
this.scopes = oldScope; |
|||
this.currentComponent = oldComponent; |
|||
} |
|||
|
|||
callFunction(functionName, params) { |
|||
|
|||
const newScope = {}; |
|||
for (let p=0; p<this.circuit.functions[functionName].params.length; p++) { |
|||
const paramName = this.circuit.functions[functionName].params[p]; |
|||
newScope[paramName] = params[p]; |
|||
} |
|||
|
|||
const oldScope = this.scopes; |
|||
this.scopes = [ this.scopes[0], newScope ]; |
|||
|
|||
// TODO set params.
|
|||
|
|||
const res = this.circuit.functions[functionName].func(this); |
|||
this.scopes = oldScope; |
|||
|
|||
return res; |
|||
} |
|||
|
|||
setSignalFullName(fullName, value) { |
|||
this.log("set " + fullName + " <-- " + value.toString()); |
|||
const sId = this.circuit.getSignalIdx(fullName); |
|||
let firstInit =false; |
|||
if (typeof(this.witness[sId]) == "undefined") { |
|||
firstInit = true; |
|||
} |
|||
this.witness[sId] = value; |
|||
const callComponents = []; |
|||
for (let i=0; i<this.circuit.signals[sId].triggerComponents.length; i++) { |
|||
var idCmp = this.circuit.signals[sId].triggerComponents[i]; |
|||
if (firstInit) this.notInitSignals[idCmp] --; |
|||
callComponents.push(idCmp); |
|||
} |
|||
callComponents.map( (c) => { |
|||
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("Constrain doesn't match: " + ba.toString() + " != " + bb.toString()); |
|||
} |
|||
} |
|||
} |
@ -1,6 +1,106 @@ |
|||
const bigInt = require("./bigint.js"); |
|||
|
|||
const __P__ = bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617"); |
|||
const __MASK__ = bigInt("28948022309329048855892746252171976963317496166410141009864396001978282409983"); // 0x3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
|
|||
const calculateWitness = require("./calculateWitness.js"); |
|||
|
|||
module.exports = class Circuit { |
|||
constructor(circuitDef) { |
|||
this.nPubInputs = circuitDef.nPubInputs; |
|||
this.nPrvInputs = circuitDef.nPrvInputs; |
|||
this.nInputs = circuitDef.nInputs; |
|||
this.nOutputs = circuitDef.nOutputs; |
|||
this.nVars = circuitDef.nVars; |
|||
this.nSignals = circuitDef.nSignals; |
|||
this.nConstants = circuitDef.nConstants; |
|||
|
|||
this.nConstrains = circuitDef.constrains.length; |
|||
|
|||
this.signalName2Idx = circuitDef.signalName2Idx; |
|||
this.components = circuitDef.components; |
|||
this.componentName2Idx = circuitDef.componentName2Idx; |
|||
this.signals = circuitDef.signals; |
|||
this.constrains = circuitDef.constrains; |
|||
|
|||
this.templates = {}; |
|||
for (let t in circuitDef.templates) { |
|||
this.templates[t] = eval(" const __f= " +circuitDef.templates[t] + "\n__f"); |
|||
} |
|||
|
|||
this.functions = {}; |
|||
for (let f in circuitDef.functions) { |
|||
this.functions[f] = { |
|||
params: circuitDef.functions[f].params, |
|||
func: eval(" const __f= " +circuitDef.functions[f].func + "\n__f;") |
|||
}; |
|||
} |
|||
} |
|||
|
|||
calculateWitness(input) { |
|||
return calculateWitness(this, input); |
|||
} |
|||
|
|||
getSignalIdx(name) { |
|||
if (typeof(this.signalName2Idx[name]) != "undefined") return this.signalName2Idx[name]; |
|||
if (!isNaN(name)) return Number(name); |
|||
throw new Error("Invalid signal identifier: ", name); |
|||
} |
|||
|
|||
// returns the index of the i'th output
|
|||
outputIdx(i) { |
|||
if (i>=this.nOutputs) throw new Error("Accessing an invalid output: "+i); |
|||
return i+1; |
|||
} |
|||
|
|||
// returns the index of the i'th input
|
|||
inputIdx(i) { |
|||
if (i>=this.nInputs) throw new Error("Accessing an invalid input: "+i); |
|||
return this.nOutputs + 1 + i; |
|||
} |
|||
|
|||
// returns the index of the i'th public input
|
|||
pubInputIdx(i) { |
|||
if (i>=this.nPubInputs) throw new Error("Accessing an invalid pubInput: "+i); |
|||
return this.inputIdx(i); |
|||
} |
|||
|
|||
// returns the index of the i'th private input
|
|||
prvInputIdx(i) { |
|||
if (i>=this.nPrvInputs) throw new Error("Accessing an invalid prvInput: "+i); |
|||
return this.inputIdx(this.nPubInputs + i); |
|||
} |
|||
|
|||
// returns the index of the i'th variable
|
|||
varIdx(i) { |
|||
if (i>=this.nVars) throw new Error("Accessing an invalid variable: "+i); |
|||
return i; |
|||
} |
|||
|
|||
// returns the index of the i'th constant
|
|||
constantIdx(i) { |
|||
if (i>=this.nConstants) throw new Error("Accessing an invalid constant: "+i); |
|||
return this.nVars + i; |
|||
} |
|||
|
|||
// returns the index of the i'th signal
|
|||
signalIdx(i) { |
|||
if (i>=this.nSignls) throw new Error("Accessing an invalid signal: "+i); |
|||
return i; |
|||
} |
|||
|
|||
signalNames(i) { |
|||
return this.signals[ this.getSignalIdx(i) ].names.join(", "); |
|||
} |
|||
|
|||
a(constrain, signalIdx) { |
|||
return bigInt(this.constrains[constrain][0][signalIdx] || 0 ); |
|||
} |
|||
|
|||
b(constrain, signalIdx) { |
|||
return bigInt(this.constrains[constrain][1][signalIdx] || 0); |
|||
} |
|||
|
|||
c(constrain, signalIdx) { |
|||
return bigInt(this.constrains[constrain][2][signalIdx] || 0); |
|||
} |
|||
}; |
@ -0,0 +1,108 @@ |
|||
const fUtils = require("./futils.js"); |
|||
|
|||
class RatZqField { |
|||
constructor(F) { |
|||
this.F = F; |
|||
this.zero = [F.zero, F.one]; |
|||
this.one = [F.one, F.one]; |
|||
this.two = [F.two, F.one]; |
|||
this.twoinv = [F.one, F.two]; |
|||
this.q = F.q; |
|||
} |
|||
|
|||
add(a,b) { |
|||
return [ |
|||
this.F.add( |
|||
this.F.mul(a[0], b[1]), |
|||
this.F.mul(a[1], b[0])), |
|||
this.F.mul(a[1], b[1])]; |
|||
} |
|||
|
|||
double(a) { |
|||
return [this.F.add(a[0], a[0]), a[1]]; |
|||
} |
|||
|
|||
sub(a,b) { |
|||
return [ |
|||
this.F.sub( |
|||
this.F.mul(a[0], b[1]), |
|||
this.F.mul(a[1], b[0])), |
|||
this.F.mul(a[1], b[1])]; |
|||
} |
|||
|
|||
neg(a) { |
|||
return [this.F.neg(a[0]), a[1]]; |
|||
} |
|||
|
|||
mul(a,b) { |
|||
return [ |
|||
this.F.mul(a[0], b[0]), |
|||
this.F.mul(a[1], b[1]), |
|||
]; |
|||
} |
|||
|
|||
copy(a) { |
|||
return [a[0], a[1]]; |
|||
} |
|||
|
|||
div(a, b) { |
|||
return [ |
|||
this.F.mul(a[0], b[1]), |
|||
this.F.mul(a[1], b[0]), |
|||
]; |
|||
} |
|||
|
|||
inverse(a) { |
|||
return [a[1], a[0]]; |
|||
} |
|||
|
|||
square(a) { |
|||
return [ |
|||
this.F.square(a[0]), |
|||
this.F.square(a[1]) |
|||
]; |
|||
} |
|||
|
|||
mulScalar(base, e) { |
|||
return [this.F.mulScalar(base[0], e) , base[1]]; |
|||
} |
|||
|
|||
exp(base, e) { |
|||
return fUtils.exp(this, base, e); |
|||
} |
|||
|
|||
equals(a, b) { |
|||
return this.F.equals( |
|||
this.F.mul(a[0], b[1]), |
|||
this.F.mul(a[1], b[0]) |
|||
); |
|||
} |
|||
|
|||
isZero(a) { |
|||
return this.F.isZero(a[0]); |
|||
} |
|||
|
|||
affine(a) { |
|||
return [this.F.div(a[0], a[1]), this.F.one]; |
|||
} |
|||
|
|||
toString(a) { |
|||
const ca = this.affine(a); |
|||
return `"0x${ca[0].toString(16)}"`; |
|||
} |
|||
|
|||
random() { |
|||
return [this.F.random(), this.F.one]; |
|||
} |
|||
|
|||
fromF(a) { |
|||
return [a, this.F.one]; |
|||
} |
|||
|
|||
toF(a) { |
|||
return this.affine(a)[0]; |
|||
} |
|||
} |
|||
|
|||
|
|||
module.exports = RatZqField; |
@ -1,52 +1,52 @@ |
|||
const G1Curve = require("./g1curve"); |
|||
const G2Curve = require("./g2curve"); |
|||
const GT = require("./gt"); |
|||
const BN128 = require("./BN128.js"); |
|||
|
|||
const G1 = new G1Curve(); |
|||
const G2 = new G2Curve(); |
|||
const Gt = new GT(); |
|||
const bn128 = new BN128(); |
|||
const G1 = bn128.G1; |
|||
const G2 = bn128.G2; |
|||
|
|||
const pairing = require("./pairing"); |
|||
const pairing = bn128.pairing; |
|||
|
|||
module.exports = function isValid(vk_verifier, proof, publicSignals) { |
|||
|
|||
let full_pi_a = vk_verifier.A[0]; |
|||
for (let s= 0; s< vk_verifier.nPublic; s++) { |
|||
full_pi_a = G1.add( full_pi_a, G1.mulEscalar( vk_verifier.A[s], publicSignals[s])); |
|||
full_pi_a = G1.add( full_pi_a, G1.mulScalar( vk_verifier.A[s+1], publicSignals[s])); |
|||
} |
|||
|
|||
let full_pi_a = G1.add(proof.pi_a, vk_verifier.A[vk_verifier.nPublic]); |
|||
full_pi_a = G1.add( full_pi_a, proof.pi_a); |
|||
|
|||
if (! Gt.equal( |
|||
pairing( proof.pi_a , vk_verifier.vk_a ), |
|||
pairing( proof.pi_ap , G2.g ))) |
|||
if (! bn128.F12.equals( |
|||
bn128.pairing( proof.pi_a , vk_verifier.vk_a ), |
|||
bn128.pairing( proof.pi_ap , G2.g ))) |
|||
return false; |
|||
|
|||
if (! Gt.equal( |
|||
pairing( vk_verifier.vk_b, proof.pi_b ), |
|||
pairing( proof.pi_ap , G2.g ))) |
|||
if (! bn128.F12.equals( |
|||
bn128.pairing( vk_verifier.vk_b, proof.pi_b ), |
|||
bn128.pairing( proof.pi_bp , G2.g ))) |
|||
return false; |
|||
|
|||
if (! Gt.equal( |
|||
pairing( proof.pi_c , vk_verifier.vk_c ), |
|||
pairing( proof.pi_cp , G2.g ))) |
|||
if (! bn128.F12.equals( |
|||
bn128.pairing( proof.pi_c , vk_verifier.vk_c ), |
|||
bn128.pairing( proof.pi_cp , G2.g ))) |
|||
return false; |
|||
|
|||
if (! Gt.equal( |
|||
pairing( full_pi_a , proof.pi_b ), |
|||
Gt.mul( |
|||
pairing( proof.pi_h , vk_verifier.vk_z ), |
|||
pairing( proof.pi_b , G2.g ), |
|||
), |
|||
pairing( proof.pi_kp , vk_verifier.vk_g ))) |
|||
if (! bn128.F12.equals( |
|||
bn128.pairing( full_pi_a , proof.pi_b ), |
|||
bn128.F12.mul( |
|||
bn128.pairing( proof.pi_h , vk_verifier.vk_z ), |
|||
bn128.pairing( proof.pi_c , G2.g ), |
|||
))) |
|||
return false; |
|||
|
|||
if (! Gt.equal( |
|||
Gt.mul( |
|||
pairing( G1.add(full_pi_a, proof.pi_c) , vk_verifier.vk_gb_2 ), |
|||
pairing( vk_verifier.vk_gb_1 , proof.pi_b ), |
|||
if (! bn128.F12.equals( |
|||
bn128.F12.mul( |
|||
bn128.pairing( G1.add(full_pi_a, proof.pi_c) , vk_verifier.vk_gb_2 ), |
|||
bn128.pairing( vk_verifier.vk_gb_1 , proof.pi_b ), |
|||
), |
|||
pairing( proof.pi_kp , vk_verifier.vk_g ))) |
|||
bn128.pairing( proof.pi_kp , vk_verifier.vk_g ))) |
|||
return false; |
|||
|
|||
|
|||
|
|||
return true; |
|||
}; |
@ -0,0 +1,20 @@ |
|||
const chai = require("chai"); |
|||
const fs = require("fs"); |
|||
|
|||
const Circuit = require("../src/circuit.js"); |
|||
const BN128 = require("../src/BN128.js"); |
|||
const F1Field = require("../src/zqfield.js"); |
|||
|
|||
const assert = chai.assert; |
|||
|
|||
|
|||
describe("Calculate witness", () => { |
|||
it("Should calculate the witness of a sum circuit", () => { |
|||
|
|||
const cirDef = JSON.parse(fs.readFileSync("../jaz/sum.json", "utf8")); |
|||
const cir = new Circuit(cirDef); |
|||
const witness = cir.calculateWitness({"a": "33", "b": "34"}); |
|||
|
|||
assert.equal(witness[cir.getSignalIdx("main.out")].toString(), "67"); |
|||
}); |
|||
}); |
@ -0,0 +1,70 @@ |
|||
const chai = require("chai"); |
|||
|
|||
const bigInt = require("../src/bigint.js"); |
|||
const ZqField = require("../src/zqfield.js"); |
|||
const RatZqField = require("../src/ratzqfield.js"); |
|||
|
|||
const q = bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617"); |
|||
const Z = new ZqField(q); |
|||
const R = new RatZqField(Z); |
|||
|
|||
const assert = chai.assert; |
|||
|
|||
function r(a,b) { |
|||
return [bigInt(a), bigInt(b)]; |
|||
} |
|||
|
|||
|
|||
describe("Rational zq Field", () => { |
|||
it("Should compare correctly", () => { |
|||
assert( R.equals(r(3,5), r(6,10))); |
|||
assert(!R.equals(r(3,5), r(6,11))); |
|||
}); |
|||
it("Should add correctly", () => { |
|||
const a = r(7,4); |
|||
const b = r(5,12); |
|||
|
|||
assert(R.equals( R.add(a,b), r(13, 6))); |
|||
}); |
|||
it("Should substract", () => { |
|||
const a = r(7,4); |
|||
const b = r(5,12); |
|||
|
|||
assert(R.equals( R.sub(a,b), r(4, 3))); |
|||
}); |
|||
it("Should multiply", () => { |
|||
const a = r(7,4); |
|||
const b = r(5,12); |
|||
|
|||
assert(R.equals( R.mul(a,b), r(35, 48))); |
|||
}); |
|||
it("Should div", () => { |
|||
const a = r(7,4); |
|||
const b = r(5,12); |
|||
|
|||
assert(R.equals( R.div(a,b), r(7*12, 5*4))); |
|||
}); |
|||
it("Should square", () => { |
|||
const a = r(7,4); |
|||
|
|||
assert(R.equals( R.square(a), r(49, 16))); |
|||
}); |
|||
it("Should affine", () => { |
|||
const a = r(12,4); |
|||
const aa = R.affine(a); |
|||
assert(Z.equals( aa[0], bigInt(3))); |
|||
assert(Z.equals( aa[1], Z.one)); |
|||
}); |
|||
it("Should convert from Z to R", () => { |
|||
const vz = bigInt(34); |
|||
const vr = R.fromF(vz); |
|||
|
|||
assert(R.equals( vr, r(34,1))); |
|||
}); |
|||
it("Should convert from R to Z", () => { |
|||
const vr = r(32, 2); |
|||
const vz = R.toF(vr); |
|||
|
|||
assert(Z.equals( vz, bigInt(16))); |
|||
}); |
|||
}); |
@ -0,0 +1,67 @@ |
|||
const chai = require("chai"); |
|||
const fs = require("fs"); |
|||
const bigInt = require("../src/bigint.js"); |
|||
|
|||
const Circuit = require("../src/circuit.js"); |
|||
const zkSnark = require("../index.js"); |
|||
|
|||
const assert = chai.assert; |
|||
|
|||
|
|||
function stringifyBigInts(o) { |
|||
if ((typeof(o) == "bigint") || (o instanceof bigInt)) { |
|||
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 o; |
|||
} |
|||
} |
|||
|
|||
describe("zkSnark", () => { |
|||
it("Load a circuit, create trusted setup, create a proof and validate", () => { |
|||
|
|||
const cirDef = JSON.parse(fs.readFileSync("../jaz/sum.json", "utf8")); |
|||
const cir = new Circuit(cirDef); |
|||
|
|||
const setup = zkSnark.setup(cir); |
|||
const strSetup = stringifyBigInts(setup); |
|||
fs.writeFileSync("vk_proof.json", JSON.stringify(strSetup.vk_proof), "utf-8"); |
|||
fs.writeFileSync("vk_verifier.json", JSON.stringify(strSetup.vk_verifier), "utf-8"); |
|||
|
|||
/* |
|||
const setup = {}; |
|||
setup.vk_proof = unstringifyBigInts(JSON.parse(fs.readFileSync("vk_proof.json", "utf8"))); |
|||
setup.vk_verifier = unstringifyBigInts(JSON.parse(fs.readFileSync("vk_verifier.json", "utf8"))); |
|||
*/ |
|||
const witness = cir.calculateWitness({"a": "33", "b": "34"}); |
|||
|
|||
assert.equal(witness[cir.getSignalIdx("main.out")].toString(), "67"); |
|||
|
|||
const {proof, publicSignals} = zkSnark.genProof(setup.vk_proof, witness); |
|||
|
|||
assert( zkSnark.isValid(setup.vk_verifier, proof, publicSignals)); |
|||
}).timeout(10000000); |
|||
}); |
@ -0,0 +1 @@ |
|||
{"nPublic":2,"A":[["0","1","0"],["0","1","0"],["0","1","0"]],"vk_a":[["10910302893854256300335313159192947444388132687074523434871198422054676751347","7128911999163755080071576365381312078199150810378083348330952764137111826309"],["18631850238317279011886579705479432506796416675676074259923090354119752710032","11613125271011748641588689311610150724463404115865535933368983811438235418330"],["1","0"]],"vk_b":["14021005419725675778621050747090735283429719877068464218769467811976154477903","13400327218680122582347155709033494654797979408389561950304209881074672567956","1"],"vk_c":[["3096051994409557504719773510360462097114704303646108617318273214347944304327","21060178932557065464613441158524747948458716806166605021180362439829514495363"],["13711469505507426929293229841903695489923719718740047084134989818704335937579","16689306268247690470861364441748198782838298216373469479699367433528545900642"],["1","0"]],"vk_gb_1":["6323076061844787963801699179984388237278671131058334789970950232032140773376","1289442623160734848462556712373448525459100416297212719395950333399658173112","1"],"vk_gb_2":[["14738403669696391106523308033989669531459082697567002658683173458264070358472","7115351592298265627577071367133297887460251153742186717064165044604072075208"],["5684452168257595880393745672144928966665179424697978770339950828964351397925","16005652883870491274891326398599328665806046577140362628567012925774147115231"],["1","0"]],"vk_g":[["13057967944664071939530697379611124014113572609236714070685841838860689079766","4921285704318374954421284662839198492272478322335189504342768676294475453825"],["16821731243154385058674189668904278548308574642868092417486261078313511500423","14329710484989081757569399730710287771777297111484092478685760712065088557056"],["1","0"]],"vk_z":[["9830782349217318574531840014041507435528173882006141768847850813321843762209","908701408738093737682928637200323566556898851221230193697915803980061312337"],["18420854262130852746249857908832658786725598484918874058527841900342812415992","11905336095877065527602013373361492354917686666454749599264218906638347950295"],["1","0"]]} |