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>
|
<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>
|
||||||
|
@ -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"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
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");
|
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);
|
||||||
|
@ -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");
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -101,7 +101,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 +113,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;
|
||||||
|
@ -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);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user