arnaucube
arnaucube/websnarkPublic Self-hosted repository
websnark/src/f1.js
src/f1.jsRaw
  1/*
  2    Copyright 2019 0KIMS association.
  3
  4    This file is part of websnark (Web Assembly zkSnark Prover).
  5
  6    websnark is a free software: you can redistribute it and/or modify it
  7    under the terms of the GNU General Public License as published by
  8    the Free Software Foundation, either version 3 of the License, or
  9    (at your option) any later version.
 10
 11    websnark is distributed in the hope that it will be useful, but WITHOUT
 12    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 13    or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
 14    License for more details.
 15
 16    You should have received a copy of the GNU General Public License
 17    along with websnark. If not, see <https://www.gnu.org/licenses/>.
 18*/
 19
 20/* globals WebAssembly */
 21const bigInt = require("big-integer");
 22const ModuleBuilder = require("wasmbuilder");
 23const buildF1 = require("./build_f1.js");
 24const buildTestF1 = require("./build_testf1.js");
 25
 26async function build(q) {
 27    const f1 = new F1(q);
 28
 29    f1.q = bigInt(q);
 30    f1.n64 = Math.floor((f1.q.minus(1).bitLength() - 1)/64) +1;
 31    f1.n32 = f1.n64*2;
 32    f1.n8 = f1.n64*8;
 33
 34    f1.memory = new WebAssembly.Memory({initial:1});
 35    f1.i32 = new Uint32Array(f1.memory.buffer);
 36
 37    const moduleBuilder = new ModuleBuilder();
 38    buildF1(moduleBuilder, f1.q);
 39    buildTestF1(moduleBuilder);
 40
 41    const code = moduleBuilder.build();
 42
 43    const wasmModule = await WebAssembly.compile(code);
 44
 45    f1.instance = await WebAssembly.instantiate(wasmModule, {
 46        env: {
 47            "memory": f1.memory
 48        }
 49    });
 50
 51    Object.assign(f1, f1.instance.exports);
 52
 53    return f1;
 54}
 55
 56class F1 {
 57
 58    constructor() {
 59
 60    }
 61
 62    alloc(length) {
 63        const res = this.i32[0];
 64        this.i32[0] += length;
 65        return res;
 66    }
 67
 68    putInt(pos, _a) {
 69        const a = bigInt(_a);
 70        if (pos & 0x7) throw new Error("Pointer must be aligned");
 71        if (a.bitLength > this.n64*64) {
 72            return this.putInt(a.mod(this.q));
 73        }
 74        for (let i=0; i<this.n32; i++) {
 75            this.i32[(pos>>2)+i] = a.shiftRight(i*32).and(0xFFFFFFFF).toJSNumber();
 76        }
 77    }
 78
 79    allocInt(_a) {
 80        const p = this.alloc(this.n8);
 81        if (_a) this.putInt(p, _a);
 82        return p;
 83    }
 84
 85    putInt2(pos, _a) {
 86        const a = bigInt(_a);
 87        if (pos & 0x7) throw new Error("Pointer must be aligned");
 88        if (a.bitLength > this.n64*64*2) {
 89            return this.putInt(a.mod(this.q));
 90        }
 91        for (let i=0; i<this.n32*2; i++) {
 92            this.i32[(pos>>2)+i] = a.shiftRight(i*32).and(0xFFFFFFFF).toJSNumber();
 93        }
 94    }
 95
 96    getInt(pos) {
 97        if (pos & 0x7) throw new Error("Pointer must be aligned");
 98        let acc = bigInt(this.i32[(pos>>2)+this.n32-1]);
 99        for (let i=this.n32-2; i>=0; i--) {
100            acc = acc.shiftLeft(32);
101            acc = acc.add(this.i32[(pos>>2)+i]);
102        }
103        return acc;
104    }
105
106    getInt2(pos) {
107        if (pos & 0x7) throw new Error("Pointer must be aligned");
108        const last = this.n32*2-1;
109        let acc = bigInt(this.i32[(pos>>2)+last]);
110        for (let i=last; i>=0; i--) {
111            acc = acc.shiftLeft(32);
112            acc = acc.add(this.i32[(pos>>2)+i]);
113        }
114        return acc;
115    }
116
117    allocInt2(_a) {
118        const p = this.alloc(this.n8*2);
119        if (_a) this.putInt2(p, _a);
120        return p;
121    }
122
123    test_F1(n) {
124        const start = new Date().getTime();
125
126        this.instance.exports.testF1(n);
127
128        const end = new Date().getTime();
129        const time = end - start;
130
131        return time;
132    }
133/*
134    function test(n) {
135
136        const q = 21888242871839275222246405745257275088696311157297823662689037894645226208583n;
137        let a = (1n << 512n)%q ;
138        let b = a >> 128n;
139
140        let c;
141
142        const start = new Date().getTime();
143        for (let i=0; i<n; i++) c = a+b;
144
145        const end = new Date().getTime();
146        const time = end - start;
147
148        console.log(time);
149    }
150*/
151}
152
153module.exports = build;