206 lines
5.8 KiB
JavaScript
206 lines
5.8 KiB
JavaScript
/*
|
|
Copyright 2019 0KIMS association.
|
|
|
|
This file is part of websnark (Web Assembly zkSnark Prover).
|
|
|
|
websnark is a free software: you can redistribute it and/or modify it
|
|
under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
websnark is distributed in the hope that it will be useful, but WITHOUT
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with websnark. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
module.exports = function buildMulAcc(windowSize, prefix, curvePrefix, scalarPrefix) {
|
|
const pointN64 = module.modules[curvePrefix].n64;
|
|
const pointN8 = pointN64*8;
|
|
const scalarN64 = module.modules[scalarPrefix].n64;
|
|
const scalarN8 = scalarN64*8;
|
|
|
|
function buildMultiMul64() {
|
|
const f = module.addFunction(prefix+"__multimul");
|
|
f.addParam("pscalars", "i32");
|
|
f.addParam("ppoints", "i32");
|
|
f.addParam("pr", "i32");
|
|
f.addLocal("sel");
|
|
f.addLocal("ppminusone");
|
|
|
|
const c = f.getCodeBuilder();
|
|
|
|
f.addCode(c.setLocal("sel", c.i32_const(0)));
|
|
f.addCode(c.setLocal(
|
|
"ppminusone",
|
|
c.sub(
|
|
c.getLocal("ppoints"),
|
|
c.i32_const(pointN8)
|
|
)
|
|
));
|
|
|
|
for (let i=0; i<64; i++) {
|
|
for (let s=0; s<windowSize; s++) {
|
|
f.addCode(c.setLocal(
|
|
"sel",
|
|
c.i32_or(
|
|
c.getLocal("sel"),
|
|
c.i32_and(
|
|
c.i32_wrap_i64(
|
|
c.i64_rotl(
|
|
c.i64_load(
|
|
c.getLocal("pscalars"),
|
|
i*scalarN64
|
|
),
|
|
c.i64_const(i+s+1)
|
|
)
|
|
),
|
|
c.i32_const(1<<s)
|
|
)
|
|
)
|
|
));
|
|
|
|
f.addCode(c.if(
|
|
c.getLocal("sel"),
|
|
c.call(
|
|
curvePrefix + "_add",
|
|
c.i32_add(
|
|
c.getLocal("ppminusone"),
|
|
c.i32_mul(
|
|
c.getLocal("sel"),
|
|
c.i32_const(pointN8)
|
|
)
|
|
)
|
|
)
|
|
));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
function buildMultiMul() {
|
|
buildMultiMul64();
|
|
const f = module.addFunction(prefix+"__multimul");
|
|
f.addParam("pscalars", "i32");
|
|
f.addParam("ppoints", "i32");
|
|
f.addParam("pr", "i32");
|
|
|
|
const c = f.getCodeBuilder();
|
|
|
|
f.addCode(c.call(prefix + "_zero", c.getLocal("pr")));
|
|
|
|
for (let i=0; i<scalarN64; i++) {
|
|
if (i>0) f.addCode(c.call(curvePrefix + "_double"), c.getLocal("pr"));
|
|
f.addCode(c.call(
|
|
prefix + "__multimul64",
|
|
c.i32_add(c.getLocal("pscalars"), c.const(i*8)),
|
|
c.getLocal("ppoints")
|
|
));
|
|
}
|
|
|
|
}
|
|
|
|
function buildMulAcc() {
|
|
buildMultiMul();
|
|
const f = module.addFunction(prefix+"_mulacc");
|
|
f.addParam("pscalars", "i32");
|
|
f.addParam("ppoints", "i32");
|
|
f.addParam("n", "i32");
|
|
f.addParam("pr", "i32");
|
|
f.addLocal("inc", "i32");
|
|
f.addLocal("pp", "i32");
|
|
f.addLocal("ps", "i32");
|
|
f.addLocal("last", "i32");
|
|
|
|
const c = f.getCodeBuilder();
|
|
|
|
const aux = c.i32_const(module.alloc(pointN8));
|
|
|
|
// Check n is windowSize multiple
|
|
f.addCode(c.if(
|
|
c.eqz(
|
|
c.i32_mod(
|
|
c.getLocal("n"),
|
|
c.i32_const(windowSize)
|
|
)
|
|
),
|
|
c.unreachable()
|
|
));
|
|
|
|
// Set zero the output
|
|
f.addCode(c.call(prefix + "_zero", c.getLocal("pr")));
|
|
|
|
// Calculate the increment
|
|
f.addCode(c.setLocal(
|
|
"incPoint",
|
|
c.i32_const(((1 << windowSize)-1) *pointN8 )
|
|
));
|
|
|
|
f.addCode(c.setLocal(
|
|
"incScalar",
|
|
c.i32_const(windowSize *scalarN8 )
|
|
));
|
|
|
|
// Calculate Initial
|
|
f.addCode(c.setLocal(
|
|
"pp",
|
|
c.getLocal("ppoints")
|
|
));
|
|
|
|
f.addCode(c.setLocal(
|
|
"ps",
|
|
c.getLocal("pscalars")
|
|
));
|
|
|
|
// Calculate Last
|
|
f.addCode(c.setLocal(
|
|
"last",
|
|
c.i32_mul(
|
|
c.getLocal("incPoint"),
|
|
c.getLocal("n")
|
|
)
|
|
));
|
|
|
|
f.addCode(c.block(c.loop(
|
|
c.br_if(
|
|
1,
|
|
c.i32_eq(
|
|
c.getLocal("pp"),
|
|
c.getLocal("last")
|
|
)
|
|
),
|
|
|
|
c.call(prefix + "__multimul", c.getLocal("ps"), c.getLocal("pp"), aux),
|
|
c.call(curvePrefix + "_add", aux, c.getLocal("pr"), c.getLocal("pr")),
|
|
|
|
c.setLocal(
|
|
"pp",
|
|
c.add(
|
|
c.getLocal("pp"),
|
|
c.getLocal("incPoint")
|
|
)
|
|
),
|
|
c.setLocal(
|
|
"ps",
|
|
c.add(
|
|
c.getLocal("ps"),
|
|
c.getLocal("incScalar")
|
|
)
|
|
),
|
|
c.br(0)
|
|
)));
|
|
|
|
}
|
|
|
|
buildMulAcc();
|
|
module.exportFunction(prefix+"_mulacc");
|
|
|
|
|
|
};
|