wasmcurves
Version:
elliptic curves implementations in wasm
234 lines (203 loc) • 7.38 kB
JavaScript
/*
Copyright 2019 0KIMS association.
This file is part of wasmsnark (Web Assembly zkSnark Prover).
wasmsnark 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.
wasmsnark 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 wasmsnark. If not, see <https://www.gnu.org/licenses/>.
*/
module.exports = function buildTimesScalarNAF(module, fnName, elementLen, opAB, opAA, opAmB, opCopy, opInit) {
const f = module.addFunction(fnName);
f.addParam("base", "i32");
f.addParam("scalar", "i32");
f.addParam("scalarLength", "i32");
f.addParam("r", "i32");
f.addLocal("old0", "i32");
f.addLocal("nbits", "i32");
f.addLocal("i", "i32");
f.addLocal("last", "i32");
f.addLocal("cur", "i32");
f.addLocal("carry", "i32");
f.addLocal("p", "i32");
const c = f.getCodeBuilder();
const aux = c.i32_const(module.alloc(elementLen));
function getBit(IDX) {
return c.i32_and(
c.i32_shr_u(
c.i32_load(
c.i32_add(
c.getLocal("scalar"),
c.i32_and(
c.i32_shr_u(
IDX,
c.i32_const(3)
),
c.i32_const(0xFFFFFFFC)
)
)
),
c.i32_and(
IDX,
c.i32_const(0x1F)
)
),
c.i32_const(1)
);
}
function pushBit(b) {
return [
...c.i32_store8(
c.getLocal("p"),
c.i32_const(b)
),
...c.setLocal(
"p",
c.i32_add(
c.getLocal("p"),
c.i32_const(1)
)
)
];
}
f.addCode(
c.if(
c.i32_eqz(c.getLocal("scalarLength")),
[
...c.call(opInit, c.getLocal("r")),
...c.ret([])
]
),
c.setLocal("nbits", c.i32_shl(c.getLocal("scalarLength"), c.i32_const(3))),
c.setLocal("old0", c.i32_load(c.i32_const(0))),
c.setLocal("p", c.getLocal("old0")),
c.i32_store(
c.i32_const(0),
c.i32_and(
c.i32_add(
c.i32_add(
c.getLocal("old0"),
c.i32_const(32)
),
c.getLocal("nbits")
),
c.i32_const(0xFFFFFFF8)
)
),
c.setLocal("i", c.i32_const(1)),
c.setLocal("last",getBit(c.i32_const(0))),
c.setLocal("carry",c.i32_const(0)),
c.block(c.loop(
c.br_if(1, c.i32_eq( c.getLocal("i"), c.getLocal("nbits"))),
c.setLocal("cur", getBit(c.getLocal("i"))),
c.if( c.getLocal("last"),
c.if( c.getLocal("cur"),
c.if(c.getLocal("carry"),
[
...c.setLocal("last", c.i32_const(0)),
...c.setLocal("carry", c.i32_const(1)),
...pushBit(1)
]
,
[
...c.setLocal("last", c.i32_const(0)),
...c.setLocal("carry", c.i32_const(1)),
...pushBit(255)
],
),
c.if(c.getLocal("carry"),
[
...c.setLocal("last", c.i32_const(0)),
...c.setLocal("carry", c.i32_const(1)),
...pushBit(255)
]
,
[
...c.setLocal("last", c.i32_const(0)),
...c.setLocal("carry", c.i32_const(0)),
...pushBit(1)
],
),
),
c.if( c.getLocal("cur"),
c.if(c.getLocal("carry"),
[
...c.setLocal("last", c.i32_const(0)),
...c.setLocal("carry", c.i32_const(1)),
...pushBit(0)
]
,
[
...c.setLocal("last", c.i32_const(1)),
...c.setLocal("carry", c.i32_const(0)),
...pushBit(0)
],
),
c.if(c.getLocal("carry"),
[
...c.setLocal("last", c.i32_const(1)),
...c.setLocal("carry", c.i32_const(0)),
...pushBit(0)
]
,
[
...c.setLocal("last", c.i32_const(0)),
...c.setLocal("carry", c.i32_const(0)),
...pushBit(0)
],
),
)
),
c.setLocal("i", c.i32_add(c.getLocal("i"), c.i32_const(1))),
c.br(0)
)),
c.if( c.getLocal("last"),
c.if(c.getLocal("carry"),
[
...pushBit(255),
...pushBit(0),
...pushBit(1)
]
,
[
...pushBit(1)
],
),
c.if(c.getLocal("carry"),
[
...pushBit(0),
...pushBit(1)
]
),
),
c.setLocal("p", c.i32_sub(c.getLocal("p"), c.i32_const(1))),
// p already points to the last bit
c.call(opCopy, c.getLocal("base"), aux),
c.call(opInit, c.getLocal("r")),
c.block(c.loop(
c.call(opAA, c.getLocal("r"), c.getLocal("r")),
c.setLocal("cur",
c.i32_load8_u(
c.getLocal("p")
)
),
c.if(
c.getLocal("cur"),
c.if(
c.i32_eq(c.getLocal("cur"), c.i32_const(1)),
c.call(opAB, c.getLocal("r"), aux, c.getLocal("r")),
c.call(opAmB, c.getLocal("r"), aux, c.getLocal("r")),
)
),
c.br_if(1, c.i32_eq( c.getLocal("old0"), c.getLocal("p"))),
c.setLocal("p", c.i32_sub(c.getLocal("p"), c.i32_const(1))),
c.br(0)
)),
c.i32_store( c.i32_const(0), c.getLocal("old0"))
);
};