Add witness calculation

This commit is contained in:
poma 2019-07-15 16:55:54 +03:00
parent 236664f194
commit 5907841378
5 changed files with 5319 additions and 2930 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

28
main.js
View File

@ -19,16 +19,17 @@
/* globals window */
const buildGroth16 = require("./src/groth16.js");
const buildGroth16 = require("./src/groth16");
const utils = require("./src/utils");
buildGroth16().then( (groth16) => {
buildGroth16().then((groth16) => {
window.groth16 = groth16;
window.genZKSnarkProof = function(witness, provingKey, cb) {
const p = groth16.proof(witness, provingKey);
window.zkSnarkProofToSolidityInput = utils.toSolidityInput;
window.genZKSnarkProofAndWitness = function (input, circuitJson, provingKey, cb) {
const p = utils.genWitnessAndProve(groth16, input, circuitJson, provingKey);
if (cb) {
p.then( (proof) => {
p.then((proof) => {
cb(null, proof);
}, (err) => {
cb(err);
@ -37,6 +38,17 @@ buildGroth16().then( (groth16) => {
return p;
}
};
});
window.genZKSnarkProof = function (witness, provingKey, cb) {
const p = groth16.proof(witness, provingKey);
if (cb) {
p.then((proof) => {
cb(null, proof);
}, (err) => {
cb(err);
});
} else {
return p;
}
};
});

View File

@ -18,8 +18,14 @@
*/
const bigInt = require("big-integer");
const Circuit = require("snarkjs/src/circuit");
const bigInt2 = require("snarkjs/src/bigint");
const hexifyBigInts = require("../tools/stringifybigint").hexifyBigInts;
const unstringifyBigInts = require("../tools/stringifybigint").unstringifyBigInts;
const stringifyBigInts2 = require("snarkjs/src/stringifybigint").stringifyBigInts;
const unstringifyBigInts2 = require("snarkjs/src/stringifybigint").unstringifyBigInts;
exports.bigInt2BytesLE = function bigInt2BytesLE(_a, len) {
function bigInt2BytesLE(_a, len) {
const b = Array(len);
let v = bigInt(_a);
for (let i=0; i<len; i++) {
@ -27,9 +33,9 @@ exports.bigInt2BytesLE = function bigInt2BytesLE(_a, len) {
v = v.shiftRight(8);
}
return b;
};
}
exports.bigInt2U32LE = function bigInt2BytesLE(_a, len) {
function bigInt2U32LE(_a, len) {
const b = Array(len);
let v = bigInt(_a);
for (let i=0; i<len; i++) {
@ -37,4 +43,51 @@ exports.bigInt2U32LE = function bigInt2BytesLE(_a, len) {
v = v.shiftRight(32);
}
return b;
};
}
function convertWitness(witness) {
const buffLen = witness.length * 32;
const buff = new ArrayBuffer(buffLen);
const h = {
dataView: new DataView(buff),
offset: 0
};
const mask = bigInt2(0xFFFFFFFF);
for (let i = 0; i < witness.length; i++) {
for (let j = 0; j < 8; j++) {
const v = Number(witness[i].shr(j * 32).and(mask));
h.dataView.setUint32(h.offset, v, true);
h.offset += 4;
}
}
return buff;
}
function toSolidityInput(proof) {
const result = {
pi_a: [proof.pi_a[0], proof.pi_a[1]],
pi_b: [[proof.pi_b[0][1], proof.pi_b[0][0]], [proof.pi_b[1][1], proof.pi_b[1][0]]],
pi_c: [proof.pi_c[0], proof.pi_c[1]],
};
if (proof.publicSignals) {
result.publicSignals = proof.publicSignals;
}
return hexifyBigInts(unstringifyBigInts(result));
}
function genWitness(input, circuitJson) {
const circuit = new Circuit(unstringifyBigInts2(circuitJson));
const witness = circuit.calculateWitness(input);
const publicSignals = witness.slice(1, circuit.nPubInputs + circuit.nOutputs + 1);
return {witness, publicSignals};
}
async function genWitnessAndProve(groth16, input, circuitJson, provingKey) {
const witnessData = genWitness(input, circuitJson);
const witnessBin = convertWitness(witnessData.witness);
const result = await groth16.proof(witnessBin, provingKey);
result.publicSignals = stringifyBigInts2(witnessData.publicSignals);
return result;
}
module.exports = {bigInt2BytesLE, bigInt2U32LE, toSolidityInput, genWitnessAndProve};

View File

@ -21,6 +21,7 @@ const bigInt = require("big-integer");
module.exports.stringifyBigInts = stringifyBigInts;
module.exports.unstringifyBigInts = unstringifyBigInts;
module.exports.hexifyBigInts = hexifyBigInts;
function stringifyBigInts(o) {
if ((typeof(o) == "bigint") || (o instanceof bigInt)) {
@ -53,3 +54,22 @@ function unstringifyBigInts(o) {
return o;
}
}
function hexifyBigInts(o) {
if (typeof (o) === "bigInt" || (o instanceof bigInt)) {
let str = o.toString(16);
while (str.length < 64) str = "0" + str;
str = "0x" + str;
return str;
} else if (Array.isArray(o)) {
return o.map(hexifyBigInts);
} else if (typeof o == "object") {
const res = {};
for (let k in o) {
res[k] = hexifyBigInts(o[k]);
}
return res;
} else {
return o;
}
}