/* 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 . */ /* globals WebAssembly */ const bigInt = require("big-integer"); const ModuleBuilder = require("wasmbuilder"); const buildF1 = require("./build_f1.js"); const buildTestF1 = require("./build_testf1.js"); async function build(q) { const f1 = new F1(q); f1.q = bigInt(q); f1.n64 = Math.floor((f1.q.minus(1).bitLength() - 1)/64) +1; f1.n32 = f1.n64*2; f1.n8 = f1.n64*8; f1.memory = new WebAssembly.Memory({initial:1}); f1.i32 = new Uint32Array(f1.memory.buffer); const moduleBuilder = new ModuleBuilder(); buildF1(moduleBuilder, f1.q); buildTestF1(moduleBuilder); const code = moduleBuilder.build(); const wasmModule = await WebAssembly.compile(code); f1.instance = await WebAssembly.instantiate(wasmModule, { env: { "memory": f1.memory } }); Object.assign(f1, f1.instance.exports); return f1; } class F1 { constructor() { } alloc(length) { const res = this.i32[0]; this.i32[0] += length; return res; } putInt(pos, _a) { const a = bigInt(_a); if (pos & 0x7) throw new Error("Pointer must be aligned"); if (a.bitLength > this.n64*64) { return this.putInt(a.mod(this.q)); } for (let i=0; i>2)+i] = a.shiftRight(i*32).and(0xFFFFFFFF).toJSNumber(); } } allocInt(_a) { const p = this.alloc(this.n8); if (_a) this.putInt(p, _a); return p; } putInt2(pos, _a) { const a = bigInt(_a); if (pos & 0x7) throw new Error("Pointer must be aligned"); if (a.bitLength > this.n64*64*2) { return this.putInt(a.mod(this.q)); } for (let i=0; i>2)+i] = a.shiftRight(i*32).and(0xFFFFFFFF).toJSNumber(); } } getInt(pos) { if (pos & 0x7) throw new Error("Pointer must be aligned"); let acc = bigInt(this.i32[(pos>>2)+this.n32-1]); for (let i=this.n32-2; i>=0; i--) { acc = acc.shiftLeft(32); acc = acc.add(this.i32[(pos>>2)+i]); } return acc; } getInt2(pos) { if (pos & 0x7) throw new Error("Pointer must be aligned"); const last = this.n32*2-1; let acc = bigInt(this.i32[(pos>>2)+last]); for (let i=last; i>=0; i--) { acc = acc.shiftLeft(32); acc = acc.add(this.i32[(pos>>2)+i]); } return acc; } allocInt2(_a) { const p = this.alloc(this.n8*2); if (_a) this.putInt2(p, _a); return p; } test_F1(n) { const start = new Date().getTime(); this.instance.exports.testF1(n); const end = new Date().getTime(); const time = end - start; return time; } /* function test(n) { const q = 21888242871839275222246405745257275088696311157297823662689037894645226208583n; let a = (1n << 512n)%q ; let b = a >> 128n; let c; const start = new Date().getTime(); for (let i=0; i