Compare commits

5 Commits

Author SHA1 Message Date
arnaucube
ca30f49c67 allow buildpkey & buildwitness to be called from js code in addition to cli usage 2019-05-23 19:08:59 +02:00
Jordi Baylina
e40bd0b701 Merge pull request #3 from kobigurk/master
Make memory grow on overflowing allocation
2019-05-15 10:11:11 +02:00
Kobi Gurkan
30a4b3d7fb Make memory grow on overflowing allocation 2019-05-14 09:53:56 +03:00
Jordi Baylina
bbab2e4c7e 0.0.3 2019-04-27 07:09:49 +02:00
Jordi Baylina
0c19558260 Improvement in multiexp 2019-04-27 07:09:17 +02:00
17 changed files with 520 additions and 157 deletions

View File

@@ -34,17 +34,17 @@ You can use the tool to build the binary file from the witness.json file generat
### IMPORTANT: Please be sure you run your setup with `--protocol groth` websnark only generates groth16 proofs! ### IMPORTANT: Please be sure you run your setup with `--protocol groth` websnark only generates groth16 proofs!
``` ```
node ../tools/buildwitness.js -i witness.json -o witness.bin node ../tools/buildwitness_cli.js -i witness.json -o witness.bin
``` ```
provingKey is the binary buffer with the binary representation of the proving key. provingKey is the binary buffer with the binary representation of the proving key.
Check the tool tools/buildpkey.js to convert a proving_key.json file generated Check the tool tools/buildpkey_cli.js to convert a proving_key.json file generated
in [snarkjs](https://github.com/iden3/snarkjs) to a proving_key.bin file that can in [snarkjs](https://github.com/iden3/snarkjs) to a proving_key.bin file that can
be used directly with this library. be used directly with this library.
``` ```
node ../tools/buildpkey.js -i proving_key.json -o proving_key.bin node ../tools/buildpkey_cli.js -i proving_key.json -o proving_key.bin
``` ```
The result is a JSON object with pi_a, pi_b and pi_c points. The result is a JSON object with pi_a, pi_b and pi_c points.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -5,7 +5,7 @@
<script> <script>
var witness; var witness;
var proving_key; var provingKey;
function onLoad() { function onLoad() {
@@ -35,6 +35,42 @@ function calcProof() {
}); });
} }
function test() {
const groth16 = window.groth16;
const nSignals = 1;
const pkey32 = new Uint32Array(provingKey);
const pPointsA = pkey32[5];
const points = provingKey.slice(pPointsA, pPointsA + nSignals*64);
const signals = witness.slice(0, nSignals*32);
const pr1 = groth16.alloc(96);
const pPoints = groth16.alloc(points.byteLength);
groth16.putBin(pPoints, points);
const pSignals = groth16.alloc(signals.byteLength);
groth16.putBin(pSignals, signals);
groth16.instance.exports.g1_zero(pr1);
groth16.instance.exports.g1_multiexp(pSignals, pPoints, nSignals, 1, pr1);
groth16.instance.exports.g1_affine(pr1, pr1);
groth16.instance.exports.g1_fromMontgomery(pr1, pr1);
const r1 = groth16.bin2g1(groth16.getBin(pr1, 96));
groth16.instance.exports.g1_zero(pr1);
groth16.instance.exports.g1_multiexp2(pSignals, pPoints, nSignals, 1, pr1);
groth16.instance.exports.g1_affine(pr1, pr1);
groth16.instance.exports.g1_fromMontgomery(pr1, pr1);
const r2 = groth16.bin2g1(groth16.getBin(pr1, 96));
console.log(r1);
console.log(r2);
}
</script> </script>
<body onLoad="onLoad()"> <body onLoad="onLoad()">
<h1>iden3</h1> <h1>iden3</h1>

View File

@@ -1,17 +1,17 @@
{ {
"pi_a": [ "pi_a": [
"21266998874284424955919569029881989465699205822263354313670808828909395154496", "19680154454022615560994181976731030733614160737391726320224655882461434003166",
"13808207576200570409195938017448994370347750586807229689124956313666939364223", "14506888714805765338667645951908780974880796110792314129555830081443197782938",
"1" "1"
], ],
"pi_b": [ "pi_b": [
[ [
"20826174028125964218380958569361176477127093215239661788856774751838141561143", "16059656683940257022054872908684774362474111955649045792819322627462560715137",
"18124837593398705925374973761391356712682789028723957898056733210681657516129" "13049852697262082406165451331450805322803524667445339527980660565015589621048"
], ],
[ [
"11061422325891624289091287264538564377906983481144726751439738589444312205684", "20605106377063342149927518751710651784145311256228815403731163542864993273015",
"7233025874448062341952037774861209177679802086176943726704101043680595476782" "21378404564638469836584392472267247126799346914748790175589924808523044347833"
], ],
[ [
"1", "1",
@@ -19,8 +19,8 @@
] ]
], ],
"pi_c": [ "pi_c": [
"16878419494624994424179370797390123339814891459464251523862017440818718425099", "16518590357890849860540962532185420206527846553862686657897809347816474967134",
"2746788445790348352996135341367179450489222192737650564198988415207995710311", "442279217743037306980955273644081896885475014739846912647180713387538594883",
"1" "1"
] ]
} }

View File

@@ -1,4 +1,4 @@
{ {
"protocol": "groth", "protocol": "groth",
"nVars": 66232, "nVars": 66232,
"nPublic": 58, "nPublic": 58,
@@ -2884580,4 +2884580,4 @@
"1" "1"
] ]
] ]
} }

File diff suppressed because one or more lines are too long

View File

@@ -22,6 +22,7 @@
const buildGroth16 = require("./src/groth16.js"); const buildGroth16 = require("./src/groth16.js");
buildGroth16().then( (groth16) => { buildGroth16().then( (groth16) => {
window.groth16 = groth16;
window.genZKSnarkProof = function(witness, provingKey, cb) { window.genZKSnarkProof = function(witness, provingKey, cb) {
const p = groth16.proof(witness, provingKey); const p = groth16.proof(witness, provingKey);

2
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{ {
"name": "websnark", "name": "websnark",
"version": "0.0.2", "version": "0.0.3",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {

View File

@@ -1,6 +1,6 @@
{ {
"name": "websnark", "name": "websnark",
"version": "0.0.2", "version": "0.0.3",
"description": "big integer library to work in Zq", "description": "big integer library to work in Zq",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {

View File

@@ -428,6 +428,7 @@ module.exports = function buildMultiexp(module, prefix, curvePrefix, pointFieldP
f.addCode(c.getLocal("pr")); f.addCode(c.getLocal("pr"));
} }
function buildMulw() { function buildMulw() {
const f = module.addFunction(prefix+"__mulw"); const f = module.addFunction(prefix+"__mulw");
f.addParam("pscalars", "i32"); f.addParam("pscalars", "i32");
@@ -578,6 +579,264 @@ module.exports = function buildMultiexp(module, prefix, curvePrefix, pointFieldP
)); ));
} }
function buildMulw2() {
const f = module.addFunction(prefix+"__mulw2");
f.addParam("pscalars", "i32");
f.addParam("ppoints", "i32");
f.addParam("w", "i32"); // Window size Max 8
f.addParam("pr", "i32");
f.addLocal("i", "i32");
f.addLocal("pd", "i32");
const c = f.getCodeBuilder();
const psels = module.alloc(scalarN8 * 8);
f.addCode(c.call(
prefix + "__packbits",
c.getLocal("pscalars"),
c.getLocal("w"),
c.i32_const(psels)
));
f.addCode(c.call(
prefix + "__ptable_reset",
c.getLocal("ppoints"),
c.getLocal("w")
));
f.addCode(c.setLocal("i", c.i32_const(0)));
f.addCode(c.block(c.loop(
c.br_if(
1,
c.i32_eq(
c.getLocal("i"),
c.i32_const(scalarN8 * 8)
)
),
c.setLocal(
"pd",
c.i32_add(
c.getLocal("pr"),
c.i32_mul(
c.getLocal("i"),
c.i32_const(pointN8)
)
)
),
c.call(curvePrefix + "_add",
c.getLocal("pd"),
c.call(
prefix + "__ptable_get",
c.i32_load8_u(
c.i32_sub(
c.i32_const(psels + scalarN8 * 8 -1),
c.getLocal("i")
)
)
),
c.getLocal("pd")
),
c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(1))),
c.br(0)
)));
}
function buildMultiexp2() {
const f = module.addFunction(prefix+"_multiexp2");
f.addParam("pscalars", "i32");
f.addParam("ppoints", "i32");
f.addParam("n", "i32"); // Number of points
f.addParam("w", "i32"); // Window size Max 8
f.addParam("pr", "i32");
f.addLocal("ps", "i32");
f.addLocal("pp", "i32");
f.addLocal("wf", "i32");
f.addLocal("lastps", "i32");
const c = f.getCodeBuilder();
const accumulators = c.i32_const(module.alloc(pointN8*scalarN8*8));
const aux = c.i32_const(module.alloc(pointN8));
f.addCode(c.call(prefix + "__resetAccumulators", accumulators, c.i32_const(scalarN8*8)));
f.addCode(c.setLocal("ps", c.getLocal("pscalars")));
f.addCode(c.setLocal("pp", c.getLocal("ppoints")));
f.addCode(c.setLocal(
"lastps",
c.i32_add(
c.getLocal("ps"),
c.i32_mul(
c.i32_mul(
c.i32_div_u(
c.getLocal("n"),
c.getLocal("w")
),
c.getLocal("w")
),
c.i32_const(scalarN8)
)
)
));
f.addCode(c.block(c.loop(
c.br_if(
1,
c.i32_eq(
c.getLocal("ps"),
c.getLocal("lastps")
)
),
c.call(prefix + "__mulw2", c.getLocal("ps"), c.getLocal("pp"), c.getLocal("w"), accumulators),
c.setLocal(
"ps",
c.i32_add(
c.getLocal("ps"),
c.i32_mul(
c.i32_const(scalarN8),
c.getLocal("w")
)
)
),
c.setLocal(
"pp",
c.i32_add(
c.getLocal("pp"),
c.i32_mul(
c.i32_const(pointFieldN8*2),
c.getLocal("w")
)
)
),
c.br(0)
)));
f.addCode(c.setLocal("wf", c.i32_rem_u(c.getLocal("n"), c.getLocal("w"))));
f.addCode(c.if(
c.getLocal("wf"),
[
...c.call(prefix + "__mulw2", c.getLocal("ps"), c.getLocal("pp"), c.getLocal("wf"), accumulators),
]
));
f.addCode(c.call(
prefix + "__addAccumulators",
accumulators,
c.i32_const(scalarN8*8),
aux
));
f.addCode(c.call(curvePrefix + "_add", aux, c.getLocal("pr"), c.getLocal("pr")));
}
function buildResetAccumulators() {
const f = module.addFunction(prefix+"__resetAccumulators");
f.addParam("paccumulators", "i32");
f.addParam("n", "i32"); // Number of points
f.addLocal("i", "i32");
const c = f.getCodeBuilder();
f.addCode(c.setLocal("i", c.i32_const(0)));
f.addCode(c.block(c.loop(
c.br_if(
1,
c.i32_eq(
c.getLocal("i"),
c.getLocal("n")
)
),
c.call(
curvePrefix + "_zero",
c.i32_add(
c.getLocal("paccumulators"),
c.i32_mul(
c.getLocal("i"),
c.i32_const(pointN8)
)
)
),
c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(1))),
c.br(0)
)));
}
function buildAddAccumulators() {
const f = module.addFunction(prefix+"__addAccumulators");
f.addParam("paccumulators", "i32");
f.addParam("n", "i32"); // Number of points
f.addParam("pr", "i32");
f.addLocal("i", "i32");
f.addLocal("p", "i32");
const c = f.getCodeBuilder();
/*
f.addCode(c.setLocal(
"p",
c.i32_add(
c.getLocal("paccumulators"),
c.i32_sub(
c.i32_mul(
c.getLocal("n"),
c.i32_const(pointN8)
),
c.i32_const(pointN8)
)
)
));
*/
f.addCode(c.setLocal("p",c.getLocal("paccumulators")));
f.addCode(c.call(curvePrefix + "_copy", c.getLocal("p"), c.getLocal("pr")));
f.addCode(c.setLocal("p", c.i32_add(c.getLocal("p"), c.i32_const(pointN8))));
f.addCode(c.setLocal("i", c.i32_const(1)));
f.addCode(c.block(c.loop(
c.br_if(
1,
c.i32_eq(
c.getLocal("i"),
c.getLocal("n")
)
),
c.call(
curvePrefix + "_double",
c.getLocal("pr"),
c.getLocal("pr")
),
c.call(
curvePrefix + "_add",
c.getLocal("p"),
c.getLocal("pr"),
c.getLocal("pr")
),
c.setLocal("p", c.i32_add(c.getLocal("p"), c.i32_const(pointN8))),
c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(1))),
c.br(0)
)));
}
buildSetSet(); buildSetSet();
buildSetIsSet(); buildSetIsSet();
buildPTableReset(); buildPTableReset();
@@ -585,7 +844,14 @@ module.exports = function buildMultiexp(module, prefix, curvePrefix, pointFieldP
buildPackBits(); buildPackBits();
buildMulw(); buildMulw();
buildMultiexp(); buildMultiexp();
buildMulw2();
buildResetAccumulators();
buildAddAccumulators();
buildMultiexp2();
module.exportFunction(prefix+"_multiexp"); module.exportFunction(prefix+"_multiexp");
module.exportFunction(prefix+"_multiexp2");
}; };

View File

@@ -68,6 +68,10 @@ function thread(self) {
while (i32[0] & 3) i32[0]++; // Return always aligned pointers while (i32[0] & 3) i32[0]++; // Return always aligned pointers
const res = i32[0]; const res = i32[0];
i32[0] += length; i32[0] += length;
while (i32[0] > memory.buffer.byteLength) {
memory.grow(100);
}
i32 = new Uint32Array(memory.buffer);
return res; return res;
} }
@@ -101,7 +105,7 @@ function thread(self) {
const pPoints = putBin(data.points); const pPoints = putBin(data.points);
const pRes = alloc(96); const pRes = alloc(96);
instance.exports.g1_zero(pRes); instance.exports.g1_zero(pRes);
instance.exports.g1_multiexp(pScalars, pPoints, data.n, 5, pRes); instance.exports.g1_multiexp2(pScalars, pPoints, data.n, 7, pRes);
data.result = getBin(pRes, 96); data.result = getBin(pRes, 96);
i32[0] = oldAlloc; i32[0] = oldAlloc;
@@ -113,7 +117,7 @@ function thread(self) {
const pPoints = putBin(data.points); const pPoints = putBin(data.points);
const pRes = alloc(192); const pRes = alloc(192);
instance.exports.g2_zero(pRes); instance.exports.g2_zero(pRes);
instance.exports.g2_multiexp(pScalars, pPoints, data.n, 5, pRes); instance.exports.g2_multiexp(pScalars, pPoints, data.n, 7, pRes);
data.result = getBin(pRes, 192); data.result = getBin(pRes, 192);
i32[0] = oldAlloc; i32[0] = oldAlloc;

View File

@@ -7,6 +7,48 @@ const snarkjs = require("snarkjs");
const buildGroth16 = require("../index.js").buildGroth16; const buildGroth16 = require("../index.js").buildGroth16;
describe("Basic tests for groth16 proof generator", () => { describe("Basic tests for groth16 proof generator", () => {
it("should do basic multiexponentiation", async () => {
const groth16 = await buildGroth16();
const signalsAll = fs.readFileSync(path.join(__dirname, "data", "witness.bin"));
const provingKey = fs.readFileSync(path.join(__dirname, "data", "proving_key.bin"));
const nSignals = 1;
const pkey32 = new Uint32Array(provingKey);
const pPointsA = pkey32[5];
const points = provingKey.slice(pPointsA, pPointsA + nSignals*64);
const signals = signalsAll.slice(0, nSignals*32);
const pr1 = groth16.alloc(96);
const pPoints = groth16.alloc(points.byteLength);
groth16.putBin(pPoints, points);
const pSignals = groth16.alloc(signals.byteLength);
groth16.putBin(pSignals, signals);
groth16.instance.exports.g1_zero(pr1);
groth16.instance.exports.g1_multiexp(pSignals, pPoints, nSignals, 1, pr1);
groth16.instance.exports.g1_affine(pr1, pr1);
groth16.instance.exports.g1_fromMontgomery(pr1, pr1);
const r1 = groth16.bin2g1(groth16.getBin(pr1, 96));
groth16.instance.exports.g1_zero(pr1);
groth16.instance.exports.g1_multiexp2(pSignals, pPoints, nSignals, 1, pr1);
groth16.instance.exports.g1_affine(pr1, pr1);
groth16.instance.exports.g1_fromMontgomery(pr1, pr1);
const r2 = groth16.bin2g1(groth16.getBin(pr1, 96));
assert.equal(r1[0],r2[0]);
assert.equal(r1[1],r2[1]);
groth16.terminate();
});
it("It should do a basic point doubling G1", async () => { it("It should do a basic point doubling G1", async () => {
const groth16 = await buildGroth16(); const groth16 = await buildGroth16();
@@ -22,4 +64,5 @@ describe("Basic tests for groth16 proof generator", () => {
groth16.terminate(); groth16.terminate();
}).timeout(10000000); }).timeout(10000000);
}); });

View File

@@ -1,36 +1,6 @@
const {unstringifyBigInts} = require("./stringifybigint.js");
const fs = require("fs");
const bigInt = require("big-integer"); const bigInt = require("big-integer");
const assert = require("assert"); const assert = require("assert");
const version = require("../package").version;
const argv = require("yargs")
.version(version)
.usage(`node buildpkey.js -i "proving_key.json" -o "proving_key.bin"
Default: circuit.json
`)
.alias("i", "input")
.alias("o", "output")
.help("h")
.alias("h", "help")
.epilogue(`Copyright (C) 2018 0kims association
This program comes with ABSOLUTELY NO WARRANTY;
This is free software, and you are welcome to redistribute it
under certain conditions; see the COPYING file in the official
repo directory at https://github.com/iden3/circom `)
.argv;
const inputName = (argv.input) ? argv.input : "proving_key.json";
const outputName = (argv.output) ? argv.output : "proving_key.bin";
const provingKey = unstringifyBigInts(JSON.parse(fs.readFileSync(inputName, "utf8")));
function writeUint32(h, val) { function writeUint32(h, val) {
h.dataView.setUint32(h.offset, val, true); h.dataView.setUint32(h.offset, val, true);
h.offset += 4; h.offset += 4;
@@ -117,73 +87,75 @@ function calculateBuffLen(provingKey) {
} }
const buffLen = calculateBuffLen(provingKey); function buildPKey(provingKey) {
const buffLen = calculateBuffLen(provingKey);
const buff = new ArrayBuffer(buffLen); const buff = new ArrayBuffer(buffLen);
const h = { const h = {
dataView: new DataView(buff), dataView: new DataView(buff),
offset: 0 offset: 0
}; };
writeUint32(h, provingKey.nVars); writeUint32(h, provingKey.nVars);
writeUint32(h, provingKey.nPublic); writeUint32(h, provingKey.nPublic);
writeUint32(h, provingKey.domainSize); writeUint32(h, provingKey.domainSize);
const pPolsA = alloc(h, 4); const pPolsA = alloc(h, 4);
const pPolsB = alloc(h, 4); const pPolsB = alloc(h, 4);
const pPointsA = alloc(h, 4); const pPointsA = alloc(h, 4);
const pPointsB1 = alloc(h, 4); const pPointsB1 = alloc(h, 4);
const pPointsB2 = alloc(h, 4); const pPointsB2 = alloc(h, 4);
const pPointsC = alloc(h, 4); const pPointsC = alloc(h, 4);
const pPointsHExps = alloc(h, 4); const pPointsHExps = alloc(h, 4);
writePoint(h, provingKey.vk_alfa_1); writePoint(h, provingKey.vk_alfa_1);
writePoint(h, provingKey.vk_beta_1); writePoint(h, provingKey.vk_beta_1);
writePoint(h, provingKey.vk_delta_1); writePoint(h, provingKey.vk_delta_1);
writePoint2(h, provingKey.vk_beta_2); writePoint2(h, provingKey.vk_beta_2);
writePoint2(h, provingKey.vk_delta_2); writePoint2(h, provingKey.vk_delta_2);
writeUint32ToPointer(h, pPolsA, h.offset); writeUint32ToPointer(h, pPolsA, h.offset);
for (let i=0; i<provingKey.nVars; i++) { for (let i=0; i<provingKey.nVars; i++) {
writeTransformedPolynomial(h, provingKey.polsA[i]); writeTransformedPolynomial(h, provingKey.polsA[i]);
}
writeUint32ToPointer(h, pPolsB, h.offset);
for (let i=0; i<provingKey.nVars; i++) {
writeTransformedPolynomial(h, provingKey.polsB[i]);
}
writeUint32ToPointer(h, pPointsA, h.offset);
for (let i=0; i<provingKey.nVars; i++) {
writePoint(h, provingKey.A[i]);
}
writeUint32ToPointer(h, pPointsB1, h.offset);
for (let i=0; i<provingKey.nVars; i++) {
writePoint(h, provingKey.B1[i]);
}
writeUint32ToPointer(h, pPointsB2, h.offset);
for (let i=0; i<provingKey.nVars; i++) {
writePoint2(h, provingKey.B2[i]);
}
writeUint32ToPointer(h, pPointsC, h.offset);
for (let i=provingKey.nPublic+1; i<provingKey.nVars; i++) {
writePoint(h, provingKey.C[i]);
}
writeUint32ToPointer(h, pPointsHExps, h.offset);
for (let i=0; i<provingKey.domainSize; i++) {
writePoint(h, provingKey.hExps[i]);
}
assert.equal(h.offset, buffLen);
return Buffer.from(buff);
} }
writeUint32ToPointer(h, pPolsB, h.offset); module.exports = buildPKey;
for (let i=0; i<provingKey.nVars; i++) {
writeTransformedPolynomial(h, provingKey.polsB[i]);
}
writeUint32ToPointer(h, pPointsA, h.offset);
for (let i=0; i<provingKey.nVars; i++) {
writePoint(h, provingKey.A[i]);
}
writeUint32ToPointer(h, pPointsB1, h.offset);
for (let i=0; i<provingKey.nVars; i++) {
writePoint(h, provingKey.B1[i]);
}
writeUint32ToPointer(h, pPointsB2, h.offset);
for (let i=0; i<provingKey.nVars; i++) {
writePoint2(h, provingKey.B2[i]);
}
writeUint32ToPointer(h, pPointsC, h.offset);
for (let i=provingKey.nPublic+1; i<provingKey.nVars; i++) {
writePoint(h, provingKey.C[i]);
}
writeUint32ToPointer(h, pPointsHExps, h.offset);
for (let i=0; i<provingKey.domainSize; i++) {
writePoint(h, provingKey.hExps[i]);
}
assert.equal(h.offset, buffLen);
var wstream = fs.createWriteStream(outputName);
wstream.write(Buffer.from(buff));
wstream.end();
/* /*
NSignals NSignals

34
tools/buildpkey_cli.js Normal file
View File

@@ -0,0 +1,34 @@
const {unstringifyBigInts} = require("./stringifybigint.js");
const buildPKey = require("./buildpkey.js");
const fs = require("fs");
const version = require("../package").version;
const argv = require("yargs")
.version(version)
.usage(`node buildpkey.js -i "proving_key.json" -o "proving_key.bin"
Default: circuit.json
`)
.alias("i", "input")
.alias("o", "output")
.help("h")
.alias("h", "help")
.epilogue(`Copyright (C) 2018 0kims association
This program comes with ABSOLUTELY NO WARRANTY;
This is free software, and you are welcome to redistribute it
under certain conditions; see the COPYING file in the official
repo directory at https://github.com/iden3/circom `)
.argv;
const inputName = (argv.input) ? argv.input : "proving_key.json";
const outputName = (argv.output) ? argv.output : "proving_key.bin";
const provingKey = unstringifyBigInts(JSON.parse(fs.readFileSync(inputName, "utf8")));
const bin = buildPKey(provingKey);
var wstream = fs.createWriteStream(outputName);
wstream.write(bin);
wstream.end();

View File

@@ -1,32 +1,5 @@
const {unstringifyBigInts} = require("./stringifybigint.js");
const fs = require("fs");
const assert = require("assert"); const assert = require("assert");
const version = require("../package").version;
const argv = require("yargs")
.version(version)
.usage(`node buildpkey.js -i "witness.json" -o "witness.bin"
Default: circuit.json
`)
.alias("i", "input")
.alias("o", "output")
.help("h")
.alias("h", "help")
.epilogue(`Copyright (C) 2018 0kims association
This program comes with ABSOLUTELY NO WARRANTY;
This is free software, and you are welcome to redistribute it
under certain conditions; see the COPYING file in the official
repo directory at https://github.com/iden3/circom `)
.argv;
const inputName = (argv.input) ? argv.input : "witness.json";
const outputName = (argv.output) ? argv.output : "witness.bin";
const witness = unstringifyBigInts(JSON.parse(fs.readFileSync(inputName, "utf8")));
function writeUint32(h, val) { function writeUint32(h, val) {
h.dataView.setUint32(h.offset, val, true); h.dataView.setUint32(h.offset, val, true);
h.offset += 4; h.offset += 4;
@@ -42,7 +15,6 @@ function writeBigInt(h, bi) {
function calculateBuffLen(witness) { function calculateBuffLen(witness) {
let size = 0; let size = 0;
// beta2, delta2 // beta2, delta2
@@ -52,25 +24,25 @@ function calculateBuffLen(witness) {
} }
const buffLen = calculateBuffLen(witness); function buildWitness(witness) {
const buffLen = calculateBuffLen(witness);
const buff = new ArrayBuffer(buffLen); const buff = new ArrayBuffer(buffLen);
const h = { const h = {
dataView: new DataView(buff), dataView: new DataView(buff),
offset: 0 offset: 0
}; };
// writeUint32(h, witness.length);
// writeUint32(h, witness.length); for (let i=0; i<witness.length; i++) {
writeBigInt(h, witness[i]);
}
for (let i=0; i<witness.length; i++) { assert.equal(h.offset, buffLen);
writeBigInt(h, witness[i]);
return Buffer.from(buff);
} }
assert.equal(h.offset, buffLen); module.exports = buildWitness;
var wstream = fs.createWriteStream(outputName);
wstream.write(Buffer.from(buff));
wstream.end();

33
tools/buildwitness_cli.js Normal file
View File

@@ -0,0 +1,33 @@
const {unstringifyBigInts} = require("./stringifybigint.js");
const buildWitness = require("./buildwitness.js");
const fs = require("fs");
const version = require("../package").version;
const argv = require("yargs")
.version(version)
.usage(`node buildpkey.js -i "witness.json" -o "witness.bin"
Default: circuit.json
`)
.alias("i", "input")
.alias("o", "output")
.help("h")
.alias("h", "help")
.epilogue(`Copyright (C) 2018 0kims association
This program comes with ABSOLUTELY NO WARRANTY;
This is free software, and you are welcome to redistribute it
under certain conditions; see the COPYING file in the official
repo directory at https://github.com/iden3/circom `)
.argv;
const inputName = (argv.input) ? argv.input : "witness.json";
const outputName = (argv.output) ? argv.output : "witness.bin";
const witness = unstringifyBigInts(JSON.parse(fs.readFileSync(inputName, "utf8")));
const bin = buildWitness(witness);
var wstream = fs.createWriteStream(outputName);
wstream.write(bin);
wstream.end();