Improvement in multiexp
This commit is contained in:
parent
cd5cb59ecd
commit
0c19558260
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -5,7 +5,7 @@
|
||||
<script>
|
||||
|
||||
var witness;
|
||||
var proving_key;
|
||||
var provingKey;
|
||||
|
||||
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>
|
||||
<body onLoad="onLoad()">
|
||||
<h1>iden3</h1>
|
||||
|
@ -1,17 +1,17 @@
|
||||
{
|
||||
"pi_a": [
|
||||
"21266998874284424955919569029881989465699205822263354313670808828909395154496",
|
||||
"13808207576200570409195938017448994370347750586807229689124956313666939364223",
|
||||
"19680154454022615560994181976731030733614160737391726320224655882461434003166",
|
||||
"14506888714805765338667645951908780974880796110792314129555830081443197782938",
|
||||
"1"
|
||||
],
|
||||
"pi_b": [
|
||||
[
|
||||
"20826174028125964218380958569361176477127093215239661788856774751838141561143",
|
||||
"18124837593398705925374973761391356712682789028723957898056733210681657516129"
|
||||
"16059656683940257022054872908684774362474111955649045792819322627462560715137",
|
||||
"13049852697262082406165451331450805322803524667445339527980660565015589621048"
|
||||
],
|
||||
[
|
||||
"11061422325891624289091287264538564377906983481144726751439738589444312205684",
|
||||
"7233025874448062341952037774861209177679802086176943726704101043680595476782"
|
||||
"20605106377063342149927518751710651784145311256228815403731163542864993273015",
|
||||
"21378404564638469836584392472267247126799346914748790175589924808523044347833"
|
||||
],
|
||||
[
|
||||
"1",
|
||||
@ -19,8 +19,8 @@
|
||||
]
|
||||
],
|
||||
"pi_c": [
|
||||
"16878419494624994424179370797390123339814891459464251523862017440818718425099",
|
||||
"2746788445790348352996135341367179450489222192737650564198988415207995710311",
|
||||
"16518590357890849860540962532185420206527846553862686657897809347816474967134",
|
||||
"442279217743037306980955273644081896885475014739846912647180713387538594883",
|
||||
"1"
|
||||
]
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
{
|
||||
{
|
||||
"protocol": "groth",
|
||||
"nVars": 66232,
|
||||
"nPublic": 58,
|
||||
@ -2884580,4 +2884580,4 @@
|
||||
"1"
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
1
main.js
1
main.js
@ -22,6 +22,7 @@
|
||||
const buildGroth16 = require("./src/groth16.js");
|
||||
|
||||
buildGroth16().then( (groth16) => {
|
||||
window.groth16 = groth16;
|
||||
window.genZKSnarkProof = function(witness, provingKey, cb) {
|
||||
|
||||
const p = groth16.proof(witness, provingKey);
|
||||
|
@ -428,6 +428,7 @@ module.exports = function buildMultiexp(module, prefix, curvePrefix, pointFieldP
|
||||
f.addCode(c.getLocal("pr"));
|
||||
}
|
||||
|
||||
|
||||
function buildMulw() {
|
||||
const f = module.addFunction(prefix+"__mulw");
|
||||
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();
|
||||
buildSetIsSet();
|
||||
buildPTableReset();
|
||||
@ -585,7 +844,14 @@ module.exports = function buildMultiexp(module, prefix, curvePrefix, pointFieldP
|
||||
buildPackBits();
|
||||
buildMulw();
|
||||
buildMultiexp();
|
||||
|
||||
buildMulw2();
|
||||
buildResetAccumulators();
|
||||
buildAddAccumulators();
|
||||
buildMultiexp2();
|
||||
|
||||
module.exportFunction(prefix+"_multiexp");
|
||||
module.exportFunction(prefix+"_multiexp2");
|
||||
|
||||
|
||||
};
|
||||
|
@ -101,7 +101,7 @@ function thread(self) {
|
||||
const pPoints = putBin(data.points);
|
||||
const pRes = alloc(96);
|
||||
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);
|
||||
i32[0] = oldAlloc;
|
||||
@ -113,7 +113,7 @@ function thread(self) {
|
||||
const pPoints = putBin(data.points);
|
||||
const pRes = alloc(192);
|
||||
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);
|
||||
i32[0] = oldAlloc;
|
||||
|
@ -7,6 +7,48 @@ const snarkjs = require("snarkjs");
|
||||
const buildGroth16 = require("../index.js").buildGroth16;
|
||||
|
||||
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 () => {
|
||||
const groth16 = await buildGroth16();
|
||||
|
||||
@ -22,4 +64,5 @@ describe("Basic tests for groth16 proof generator", () => {
|
||||
|
||||
groth16.terminate();
|
||||
}).timeout(10000000);
|
||||
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user