snarkjs
Version:
zkSNARKs implementation in JavaScript
1,519 lines (1,284 loc) • 537 kB
JavaScript
import { Scalar, BigBuffer, buildBn128, buildBls12381, ChaCha, F1Field, utils, getCurveFromR as getCurveFromR$1 } from 'ffjavascript';
var fs = {};
async function open(fileName, openFlags, cacheSize, pageSize) {
cacheSize = cacheSize || 4096*64;
if (typeof openFlags !== "number" && ["w+", "wx+", "r", "ax+", "a+"].indexOf(openFlags) <0)
throw new Error("Invalid open option");
const fd =await fs.promises.open(fileName, openFlags);
const stats = await fd.stat();
return new FastFile(fd, stats, cacheSize, pageSize, fileName);
}
class FastFile {
constructor(fd, stats, cacheSize, pageSize, fileName) {
this.fileName = fileName;
this.fd = fd;
this.pos = 0;
this.pageSize = pageSize || (1 << 8);
while (this.pageSize < stats.blksize) {
this.pageSize *= 2;
}
this.totalSize = stats.size;
this.totalPages = Math.floor((stats.size -1) / this.pageSize)+1;
this.maxPagesLoaded = Math.floor( cacheSize / this.pageSize)+1;
this.pages = {};
this.pendingLoads = [];
this.writing = false;
this.reading = false;
this.avBuffs = [];
this.history = {};
}
_loadPage(p) {
const self = this;
const P = new Promise((resolve, reject)=> {
self.pendingLoads.push({
page: p,
resolve: resolve,
reject: reject
});
});
self.__statusPage("After Load request: ", p);
return P;
}
__statusPage(s, p) {
const logEntry = [];
const self=this;
if (!self.logHistory) return;
logEntry.push("==" + s+ " " +p);
let S = "";
for (let i=0; i<self.pendingLoads.length; i++) {
if (self.pendingLoads[i].page == p) S = S + " " + i;
}
if (S) logEntry.push("Pending loads:"+S);
if (typeof self.pages[p] != "undefined") {
const page = self.pages[p];
logEntry.push("Loaded");
logEntry.push("pendingOps: "+page.pendingOps);
if (page.loading) logEntry.push("loading: "+page.loading);
if (page.writing) logEntry.push("writing");
if (page.dirty) logEntry.push("dirty");
}
logEntry.push("==");
if (!self.history[p]) self.history[p] = [];
self.history[p].push(logEntry);
}
__printHistory(p) {
const self = this;
if (!self.history[p]) console.log("Empty History ", p);
console.log("History "+p);
for (let i=0; i<self.history[p].length; i++) {
for (let j=0; j<self.history[p][i].length; j++) {
console.log("-> " + self.history[p][i][j]);
}
}
}
_triggerLoad() {
const self = this;
if (self.reading) return;
if (self.pendingLoads.length==0) return;
const pageIdxs = Object.keys(self.pages);
const deletablePages = [];
for (let i=0; i<pageIdxs.length; i++) {
const page = self.pages[parseInt(pageIdxs[i])];
if ((page.dirty == false)&&(page.pendingOps==0)&&(!page.writing)&&(!page.loading)) deletablePages.push(parseInt(pageIdxs[i]));
}
let freePages = self.maxPagesLoaded - pageIdxs.length;
const ops = [];
// while pending loads and
// the page is loaded or I can recover one.
while (
(self.pendingLoads.length>0) &&
( (typeof self.pages[self.pendingLoads[0].page] != "undefined" )
||( (freePages>0)
||(deletablePages.length>0)))) {
const load = self.pendingLoads.shift();
if (typeof self.pages[load.page] != "undefined") {
self.pages[load.page].pendingOps ++;
const idx = deletablePages.indexOf(load.page);
if (idx>=0) deletablePages.splice(idx, 1);
if (self.pages[load.page].loading) {
self.pages[load.page].loading.push(load);
} else {
load.resolve();
}
self.__statusPage("After Load (cached): ", load.page);
} else {
if (freePages) {
freePages--;
} else {
const fp = deletablePages.shift();
self.__statusPage("Before Unload: ", fp);
self.avBuffs.unshift(self.pages[fp]);
delete self.pages[fp];
self.__statusPage("After Unload: ", fp);
}
if (load.page>=self.totalPages) {
self.pages[load.page] = getNewPage();
load.resolve();
self.__statusPage("After Load (new): ", load.page);
} else {
self.reading = true;
self.pages[load.page] = getNewPage();
self.pages[load.page].loading = [load];
ops.push(self.fd.read(self.pages[load.page].buff, 0, self.pageSize, load.page*self.pageSize).then((res)=> {
self.pages[load.page].size = res.bytesRead;
const loading = self.pages[load.page].loading;
delete self.pages[load.page].loading;
for (let i=0; i<loading.length; i++) {
loading[i].resolve();
}
self.__statusPage("After Load (loaded): ", load.page);
return res;
}, (err) => {
load.reject(err);
}));
self.__statusPage("After Load (loading): ", load.page);
}
}
}
// if (ops.length>1) console.log(ops.length);
Promise.all(ops).then( () => {
self.reading = false;
if (self.pendingLoads.length>0) setImmediate(self._triggerLoad.bind(self));
self._tryClose();
});
function getNewPage() {
if (self.avBuffs.length>0) {
const p = self.avBuffs.shift();
p.dirty = false;
p.pendingOps = 1;
p.size =0;
return p;
} else {
return {
dirty: false,
buff: new Uint8Array(self.pageSize),
pendingOps: 1,
size: 0
};
}
}
}
_triggerWrite() {
const self = this;
if (self.writing) return;
const pageIdxs = Object.keys(self.pages);
const ops = [];
for (let i=0; i<pageIdxs.length; i++) {
const page = self.pages[parseInt(pageIdxs[i])];
if (page.dirty) {
page.dirty = false;
page.writing = true;
self.writing = true;
ops.push( self.fd.write(page.buff, 0, page.size, parseInt(pageIdxs[i])*self.pageSize).then(() => {
page.writing = false;
return;
}, (err) => {
console.log("ERROR Writing: "+err);
self.error = err;
self._tryClose();
}));
}
}
if (self.writing) {
Promise.all(ops).then( () => {
self.writing = false;
setImmediate(self._triggerWrite.bind(self));
self._tryClose();
if (self.pendingLoads.length>0) setImmediate(self._triggerLoad.bind(self));
});
}
}
_getDirtyPage() {
for (let p in this.pages) {
if (this.pages[p].dirty) return p;
}
return -1;
}
async write(buff, pos) {
if (buff.byteLength == 0) return;
const self = this;
/*
if (buff.byteLength > self.pageSize*self.maxPagesLoaded*0.8) {
const cacheSize = Math.floor(buff.byteLength * 1.1);
this.maxPagesLoaded = Math.floor( cacheSize / self.pageSize)+1;
}
*/
if (typeof pos == "undefined") pos = self.pos;
self.pos = pos+buff.byteLength;
if (self.totalSize < pos + buff.byteLength) self.totalSize = pos + buff.byteLength;
if (self.pendingClose)
throw new Error("Writing a closing file");
const firstPage = Math.floor(pos / self.pageSize);
const lastPage = Math.floor((pos + buff.byteLength -1) / self.pageSize);
const pagePromises = [];
for (let i=firstPage; i<=lastPage; i++) pagePromises.push(self._loadPage(i));
self._triggerLoad();
let p = firstPage;
let o = pos % self.pageSize;
let r = buff.byteLength;
while (r>0) {
await pagePromises[p-firstPage];
const l = (o+r > self.pageSize) ? (self.pageSize -o) : r;
const srcView = buff.slice( buff.byteLength - r, buff.byteLength - r + l);
const dstView = new Uint8Array(self.pages[p].buff.buffer, o, l);
dstView.set(srcView);
self.pages[p].dirty = true;
self.pages[p].pendingOps --;
self.pages[p].size = Math.max(o+l, self.pages[p].size);
if (p>=self.totalPages) {
self.totalPages = p+1;
}
r = r-l;
p ++;
o = 0;
if (!self.writing) setImmediate(self._triggerWrite.bind(self));
}
}
async read(len, pos) {
const self = this;
let buff = new Uint8Array(len);
await self.readToBuffer(buff, 0, len, pos);
return buff;
}
async readToBuffer(buffDst, offset, len, pos) {
if (len == 0) {
return;
}
const self = this;
if (len > self.pageSize*self.maxPagesLoaded*0.8) {
const cacheSize = Math.floor(len * 1.1);
this.maxPagesLoaded = Math.floor( cacheSize / self.pageSize)+1;
}
if (typeof pos == "undefined") pos = self.pos;
self.pos = pos+len;
if (self.pendingClose)
throw new Error("Reading a closing file");
const firstPage = Math.floor(pos / self.pageSize);
const lastPage = Math.floor((pos + len -1) / self.pageSize);
const pagePromises = [];
for (let i=firstPage; i<=lastPage; i++) pagePromises.push(self._loadPage(i));
self._triggerLoad();
let p = firstPage;
let o = pos % self.pageSize;
// Remaining bytes to read
let r = pos + len > self.totalSize ? len - (pos + len - self.totalSize): len;
while (r>0) {
await pagePromises[p - firstPage];
self.__statusPage("After Await (read): ", p);
// bytes to copy from this page
const l = (o+r > self.pageSize) ? (self.pageSize -o) : r;
const srcView = new Uint8Array(self.pages[p].buff.buffer, self.pages[p].buff.byteOffset + o, l);
buffDst.set(srcView, offset+len-r);
self.pages[p].pendingOps --;
self.__statusPage("After Op done: ", p);
r = r-l;
p ++;
o = 0;
if (self.pendingLoads.length>0) setImmediate(self._triggerLoad.bind(self));
}
this.pos = pos + len;
}
_tryClose() {
const self = this;
if (!self.pendingClose) return;
if (self.error) {
self.pendingCloseReject(self.error);
}
const p = self._getDirtyPage();
if ((p>=0) || (self.writing) || (self.reading) || (self.pendingLoads.length>0)) return;
self.pendingClose();
}
close() {
const self = this;
if (self.pendingClose)
throw new Error("Closing the file twice");
return new Promise((resolve, reject) => {
self.pendingClose = resolve;
self.pendingCloseReject = reject;
self._tryClose();
}).then(()=> {
self.fd.close();
}, (err) => {
self.fd.close();
throw (err);
});
}
async discard() {
const self = this;
await self.close();
await fs.promises.unlink(this.fileName);
}
async writeULE32(v, pos) {
const self = this;
const tmpBuff32 = new Uint8Array(4);
const tmpBuff32v = new DataView(tmpBuff32.buffer);
tmpBuff32v.setUint32(0, v, true);
await self.write(tmpBuff32, pos);
}
async writeUBE32(v, pos) {
const self = this;
const tmpBuff32 = new Uint8Array(4);
const tmpBuff32v = new DataView(tmpBuff32.buffer);
tmpBuff32v.setUint32(0, v, false);
await self.write(tmpBuff32, pos);
}
async writeULE64(v, pos) {
const self = this;
const tmpBuff64 = new Uint8Array(8);
const tmpBuff64v = new DataView(tmpBuff64.buffer);
tmpBuff64v.setUint32(0, v & 0xFFFFFFFF, true);
tmpBuff64v.setUint32(4, Math.floor(v / 0x100000000) , true);
await self.write(tmpBuff64, pos);
}
async readULE32(pos) {
const self = this;
const b = await self.read(4, pos);
const view = new Uint32Array(b.buffer);
return view[0];
}
async readUBE32(pos) {
const self = this;
const b = await self.read(4, pos);
const view = new DataView(b.buffer);
return view.getUint32(0, false);
}
async readULE64(pos) {
const self = this;
const b = await self.read(8, pos);
const view = new Uint32Array(b.buffer);
return view[1] * 0x100000000 + view[0];
}
async readString(pos) {
const self = this;
if (self.pendingClose) {
throw new Error("Reading a closing file");
}
let currentPosition = typeof pos == "undefined" ? self.pos : pos;
let currentPage = Math.floor(currentPosition / self.pageSize);
let endOfStringFound = false;
let str = "";
while (!endOfStringFound) {
//Read page
let pagePromise = self._loadPage(currentPage);
self._triggerLoad();
await pagePromise;
self.__statusPage("After Await (read): ", currentPage);
let offsetOnPage = currentPosition % self.pageSize;
const dataArray = new Uint8Array(
self.pages[currentPage].buff.buffer,
self.pages[currentPage].buff.byteOffset + offsetOnPage,
self.pageSize - offsetOnPage
);
let indexEndOfString = dataArray.findIndex(element => element === 0);
endOfStringFound = indexEndOfString !== -1;
if (endOfStringFound) {
str += new TextDecoder().decode(dataArray.slice(0, indexEndOfString));
self.pos = currentPage * this.pageSize + offsetOnPage + indexEndOfString + 1;
} else {
str += new TextDecoder().decode(dataArray);
self.pos = currentPage * this.pageSize + offsetOnPage + dataArray.length;
}
self.pages[currentPage].pendingOps--;
self.__statusPage("After Op done: ", currentPage);
currentPosition = self.pos;
currentPage++;
if (self.pendingLoads.length > 0) setImmediate(self._triggerLoad.bind(self));
}
return str;
}
}
function createNew$1(o) {
const initialSize = o.initialSize || 1<<20;
const fd = new MemFile();
fd.o = o;
fd.o.data = new Uint8Array(initialSize);
fd.allocSize = initialSize;
fd.totalSize = 0;
fd.readOnly = false;
fd.pos = 0;
return fd;
}
function readExisting$2(o) {
const fd = new MemFile();
fd.o = o;
fd.allocSize = o.data.byteLength;
fd.totalSize = o.data.byteLength;
fd.readOnly = true;
fd.pos = 0;
return fd;
}
const tmpBuff32$1 = new Uint8Array(4);
const tmpBuff32v$1 = new DataView(tmpBuff32$1.buffer);
const tmpBuff64$1 = new Uint8Array(8);
const tmpBuff64v$1 = new DataView(tmpBuff64$1.buffer);
class MemFile {
constructor() {
this.pageSize = 1 << 14; // for compatibility
}
_resizeIfNeeded(newLen) {
if (newLen > this.allocSize) {
const newAllocSize = Math.max(
this.allocSize + (1 << 20),
Math.floor(this.allocSize * 1.1),
newLen
);
const newData = new Uint8Array(newAllocSize);
newData.set(this.o.data);
this.o.data = newData;
this.allocSize = newAllocSize;
}
}
async write(buff, pos) {
const self =this;
if (typeof pos == "undefined") pos = self.pos;
if (this.readOnly) throw new Error("Writing a read only file");
this._resizeIfNeeded(pos + buff.byteLength);
this.o.data.set(buff.slice(), pos);
if (pos + buff.byteLength > this.totalSize) this.totalSize = pos + buff.byteLength;
this.pos = pos + buff.byteLength;
}
async readToBuffer(buffDest, offset, len, pos) {
const self = this;
if (typeof pos == "undefined") pos = self.pos;
if (this.readOnly) {
if (pos + len > this.totalSize) throw new Error("Reading out of bounds");
}
this._resizeIfNeeded(pos + len);
const buffSrc = new Uint8Array(this.o.data.buffer, this.o.data.byteOffset + pos, len);
buffDest.set(buffSrc, offset);
this.pos = pos + len;
}
async read(len, pos) {
const self = this;
const buff = new Uint8Array(len);
await self.readToBuffer(buff, 0, len, pos);
return buff;
}
close() {
if (this.o.data.byteLength != this.totalSize) {
this.o.data = this.o.data.slice(0, this.totalSize);
}
}
async discard() {
}
async writeULE32(v, pos) {
const self = this;
tmpBuff32v$1.setUint32(0, v, true);
await self.write(tmpBuff32$1, pos);
}
async writeUBE32(v, pos) {
const self = this;
tmpBuff32v$1.setUint32(0, v, false);
await self.write(tmpBuff32$1, pos);
}
async writeULE64(v, pos) {
const self = this;
tmpBuff64v$1.setUint32(0, v & 0xFFFFFFFF, true);
tmpBuff64v$1.setUint32(4, Math.floor(v / 0x100000000) , true);
await self.write(tmpBuff64$1, pos);
}
async readULE32(pos) {
const self = this;
const b = await self.read(4, pos);
const view = new Uint32Array(b.buffer);
return view[0];
}
async readUBE32(pos) {
const self = this;
const b = await self.read(4, pos);
const view = new DataView(b.buffer);
return view.getUint32(0, false);
}
async readULE64(pos) {
const self = this;
const b = await self.read(8, pos);
const view = new Uint32Array(b.buffer);
return view[1] * 0x100000000 + view[0];
}
async readString(pos) {
const self = this;
let currentPosition = typeof pos == "undefined" ? self.pos : pos;
if (currentPosition > this.totalSize) {
if (this.readOnly) {
throw new Error("Reading out of bounds");
}
this._resizeIfNeeded(pos);
}
const dataArray = new Uint8Array(
self.o.data.buffer,
currentPosition,
this.totalSize - currentPosition
);
let indexEndOfString = dataArray.findIndex(element => element === 0);
let endOfStringFound = indexEndOfString !== -1;
let str = "";
if (endOfStringFound) {
str = new TextDecoder().decode(dataArray.slice(0, indexEndOfString));
self.pos = currentPosition + indexEndOfString + 1;
} else {
self.pos = currentPosition;
}
return str;
}
}
const PAGE_SIZE = 1<<22;
function createNew(o) {
const initialSize = o.initialSize || 0;
const fd = new BigMemFile();
fd.o = o;
const nPages = initialSize ? Math.floor((initialSize - 1) / PAGE_SIZE)+1 : 0;
fd.o.data = [];
for (let i=0; i<nPages-1; i++) {
fd.o.data.push( new Uint8Array(PAGE_SIZE));
}
if (nPages) fd.o.data.push( new Uint8Array(initialSize - PAGE_SIZE*(nPages-1)));
fd.totalSize = 0;
fd.readOnly = false;
fd.pos = 0;
return fd;
}
function readExisting$1(o) {
const fd = new BigMemFile();
fd.o = o;
fd.totalSize = (o.data.length-1)* PAGE_SIZE + o.data[o.data.length-1].byteLength;
fd.readOnly = true;
fd.pos = 0;
return fd;
}
const tmpBuff32 = new Uint8Array(4);
const tmpBuff32v = new DataView(tmpBuff32.buffer);
const tmpBuff64 = new Uint8Array(8);
const tmpBuff64v = new DataView(tmpBuff64.buffer);
class BigMemFile {
constructor() {
this.pageSize = 1 << 14; // for compatibility
}
_resizeIfNeeded(newLen) {
if (newLen <= this.totalSize) return;
if (this.readOnly) throw new Error("Reading out of file bounds");
const nPages = Math.floor((newLen - 1) / PAGE_SIZE)+1;
for (let i= Math.max(this.o.data.length-1, 0); i<nPages; i++) {
const newSize = i<nPages-1 ? PAGE_SIZE : newLen - (nPages-1)*PAGE_SIZE;
const p = new Uint8Array(newSize);
if (i == this.o.data.length-1) p.set(this.o.data[i]);
this.o.data[i] = p;
}
this.totalSize = newLen;
}
async write(buff, pos) {
const self =this;
if (typeof pos == "undefined") pos = self.pos;
if (this.readOnly) throw new Error("Writing a read only file");
this._resizeIfNeeded(pos + buff.byteLength);
const firstPage = Math.floor(pos / PAGE_SIZE);
let p = firstPage;
let o = pos % PAGE_SIZE;
let r = buff.byteLength;
while (r>0) {
const l = (o+r > PAGE_SIZE) ? (PAGE_SIZE -o) : r;
const srcView = buff.slice(buff.byteLength - r, buff.byteLength - r + l);
const dstView = new Uint8Array(self.o.data[p].buffer, o, l);
dstView.set(srcView);
r = r-l;
p ++;
o = 0;
}
this.pos = pos + buff.byteLength;
}
async readToBuffer(buffDst, offset, len, pos) {
const self = this;
if (typeof pos == "undefined") pos = self.pos;
if (this.readOnly) {
if (pos + len > this.totalSize) throw new Error("Reading out of bounds");
}
this._resizeIfNeeded(pos + len);
const firstPage = Math.floor(pos / PAGE_SIZE);
let p = firstPage;
let o = pos % PAGE_SIZE;
// Remaining bytes to read
let r = len;
while (r>0) {
// bytes to copy from this page
const l = (o+r > PAGE_SIZE) ? (PAGE_SIZE -o) : r;
const srcView = new Uint8Array(self.o.data[p].buffer, o, l);
buffDst.set(srcView, offset+len-r);
r = r-l;
p ++;
o = 0;
}
this.pos = pos + len;
}
async read(len, pos) {
const self = this;
const buff = new Uint8Array(len);
await self.readToBuffer(buff, 0, len, pos);
return buff;
}
close() {
}
async discard() {
}
async writeULE32(v, pos) {
const self = this;
tmpBuff32v.setUint32(0, v, true);
await self.write(tmpBuff32, pos);
}
async writeUBE32(v, pos) {
const self = this;
tmpBuff32v.setUint32(0, v, false);
await self.write(tmpBuff32, pos);
}
async writeULE64(v, pos) {
const self = this;
tmpBuff64v.setUint32(0, v & 0xFFFFFFFF, true);
tmpBuff64v.setUint32(4, Math.floor(v / 0x100000000) , true);
await self.write(tmpBuff64, pos);
}
async readULE32(pos) {
const self = this;
const b = await self.read(4, pos);
const view = new Uint32Array(b.buffer);
return view[0];
}
async readUBE32(pos) {
const self = this;
const b = await self.read(4, pos);
const view = new DataView(b.buffer);
return view.getUint32(0, false);
}
async readULE64(pos) {
const self = this;
const b = await self.read(8, pos);
const view = new Uint32Array(b.buffer);
return view[1] * 0x100000000 + view[0];
}
async readString(pos) {
const self = this;
const fixedSize = 2048;
let currentPosition = typeof pos == "undefined" ? self.pos : pos;
if (currentPosition > this.totalSize) {
if (this.readOnly) {
throw new Error("Reading out of bounds");
}
this._resizeIfNeeded(pos);
}
let endOfStringFound = false;
let str = "";
while (!endOfStringFound) {
let currentPage = Math.floor(currentPosition / PAGE_SIZE);
let offsetOnPage = currentPosition % PAGE_SIZE;
if (self.o.data[currentPage] === undefined) {
throw new Error("ERROR");
}
let readLength = Math.min(fixedSize, self.o.data[currentPage].length - offsetOnPage);
const dataArray = new Uint8Array(self.o.data[currentPage].buffer, offsetOnPage, readLength);
let indexEndOfString = dataArray.findIndex(element => element === 0);
endOfStringFound = indexEndOfString !== -1;
if (endOfStringFound) {
str += new TextDecoder().decode(dataArray.slice(0, indexEndOfString));
self.pos = currentPage * PAGE_SIZE + offsetOnPage + indexEndOfString + 1;
} else {
str += new TextDecoder().decode(dataArray);
self.pos = currentPage * PAGE_SIZE + offsetOnPage + dataArray.length;
}
currentPosition = self.pos;
}
return str;
}
}
const O_TRUNC = 1024;
const O_CREAT = 512;
const O_RDWR = 2;
const O_RDONLY = 0;
/* global fetch */
const DEFAULT_CACHE_SIZE = (1 << 16);
const DEFAULT_PAGE_SIZE = (1 << 13);
async function createOverride(o, b, c) {
if (typeof o === "string") {
o = {
type: "file",
fileName: o,
cacheSize: b || DEFAULT_CACHE_SIZE,
pageSize: c || DEFAULT_PAGE_SIZE
};
}
if (o.type == "file") {
return await open(o.fileName, O_TRUNC | O_CREAT | O_RDWR, o.cacheSize, o.pageSize);
} else if (o.type == "mem") {
return createNew$1(o);
} else if (o.type == "bigMem") {
return createNew(o);
} else {
throw new Error("Invalid FastFile type: "+o.type);
}
}
async function readExisting(o, b, c) {
if (o instanceof Uint8Array) {
o = {
type: "mem",
data: o
};
}
{
if (typeof o === "string") {
const buff = await fetch(o).then( function(res) {
return res.arrayBuffer();
}).then(function (ab) {
return new Uint8Array(ab);
});
o = {
type: "mem",
data: buff
};
}
}
if (o.type == "file") {
return await open(o.fileName, O_RDONLY, o.cacheSize, o.pageSize);
} else if (o.type == "mem") {
return await readExisting$2(o);
} else if (o.type == "bigMem") {
return await readExisting$1(o);
} else {
throw new Error("Invalid FastFile type: "+o.type);
}
}
async function readBinFile(fileName, type, maxVersion, cacheSize, pageSize) {
const fd = await readExisting(fileName);
const b = await fd.read(4);
let readedType = "";
for (let i=0; i<4; i++) readedType += String.fromCharCode(b[i]);
if (readedType != type) throw new Error(fileName + ": Invalid File format");
let v = await fd.readULE32();
if (v>maxVersion) throw new Error("Version not supported");
const nSections = await fd.readULE32();
// Scan sections
let sections = [];
for (let i=0; i<nSections; i++) {
let ht = await fd.readULE32();
let hl = await fd.readULE64();
if (typeof sections[ht] == "undefined") sections[ht] = [];
sections[ht].push({
p: fd.pos,
size: hl
});
fd.pos += hl;
}
return {fd, sections};
}
async function createBinFile(fileName, type, version, nSections, cacheSize, pageSize) {
const fd = await createOverride(fileName, cacheSize, pageSize);
const buff = new Uint8Array(4);
for (let i=0; i<4; i++) buff[i] = type.charCodeAt(i);
await fd.write(buff, 0); // Magic "r1cs"
await fd.writeULE32(version); // Version
await fd.writeULE32(nSections); // Number of Sections
return fd;
}
async function startWriteSection(fd, idSection) {
if (typeof fd.writingSection !== "undefined") throw new Error("Already writing a section");
await fd.writeULE32(idSection); // Header type
fd.writingSection = {
pSectionSize: fd.pos
};
await fd.writeULE64(0); // Temporally set to 0 length
}
async function endWriteSection(fd) {
if (typeof fd.writingSection === "undefined") throw new Error("Not writing a section");
const sectionSize = fd.pos - fd.writingSection.pSectionSize - 8;
const oldPos = fd.pos;
fd.pos = fd.writingSection.pSectionSize;
await fd.writeULE64(sectionSize);
fd.pos = oldPos;
delete fd.writingSection;
}
async function startReadUniqueSection(fd, sections, idSection) {
if (typeof fd.readingSection !== "undefined") throw new Error("Already reading a section");
if (!sections[idSection]) throw new Error(fd.fileName + ": Missing section "+ idSection );
if (sections[idSection].length>1) throw new Error(fd.fileName +": Section Duplicated " +idSection);
fd.pos = sections[idSection][0].p;
fd.readingSection = sections[idSection][0];
}
async function endReadSection(fd, noCheck) {
if (typeof fd.readingSection === "undefined") throw new Error("Not reading a section");
if (!noCheck) {
if (fd.pos-fd.readingSection.p != fd.readingSection.size) throw new Error("Invalid section size reading");
}
delete fd.readingSection;
}
async function writeBigInt(fd, n, n8, pos) {
const buff = new Uint8Array(n8);
Scalar.toRprLE(buff, 0, n, n8);
await fd.write(buff, pos);
}
async function readBigInt(fd, n8, pos) {
const buff = await fd.read(n8, pos);
return Scalar.fromRprLE(buff, 0, n8);
}
async function copySection(fdFrom, sections, fdTo, sectionId, size) {
if (typeof size === "undefined") {
size = sections[sectionId][0].size;
}
const chunkSize = fdFrom.pageSize;
await startReadUniqueSection(fdFrom, sections, sectionId);
await startWriteSection(fdTo, sectionId);
for (let p=0; p<size; p+=chunkSize) {
const l = Math.min(size -p, chunkSize);
const buff = await fdFrom.read(l);
await fdTo.write(buff);
}
await endWriteSection(fdTo);
await endReadSection(fdFrom, size != sections[sectionId][0].size);
}
async function readSection(fd, sections, idSection, offset, length) {
offset = (typeof offset === "undefined") ? 0 : offset;
length = (typeof length === "undefined") ? sections[idSection][0].size - offset : length;
if (offset + length > sections[idSection][0].size) {
throw new Error("Reading out of the range of the section");
}
let buff;
if (length < (1 << 30) ) {
buff = new Uint8Array(length);
} else {
buff = new BigBuffer(length);
}
await fd.readToBuffer(buff, 0, length, sections[idSection][0].p + offset);
return buff;
}
async function sectionIsEqual(fd1, sections1, fd2, sections2, idSection) {
const MAX_BUFF_SIZE = fd1.pageSize * 16;
await startReadUniqueSection(fd1, sections1, idSection);
await startReadUniqueSection(fd2, sections2, idSection);
if (sections1[idSection][0].size != sections2[idSection][0].size) return false;
const totalBytes=sections1[idSection][0].size;
for (let i=0; i<totalBytes; i+= MAX_BUFF_SIZE) {
const n = Math.min(totalBytes-i, MAX_BUFF_SIZE);
const buff1 = await fd1.read(n);
const buff2 = await fd2.read(n);
for (let j=0; j<n; j++) if (buff1[j] != buff2[j]) return false;
}
await endReadSection(fd1);
await endReadSection(fd2);
return true;
}
const bls12381r$1 = Scalar.e("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", 16);
const bn128r$1 = Scalar.e("21888242871839275222246405745257275088548364400416034343698204186575808495617");
const bls12381q = Scalar.e("1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab", 16);
const bn128q = Scalar.e("21888242871839275222246405745257275088696311157297823662689037894645226208583");
async function getCurveFromR(r, options) {
let curve;
// check that options param is defined and that options.singleThread is defined
let singleThread = options && options.singleThread;
if (Scalar.eq(r, bn128r$1)) {
curve = await buildBn128(singleThread);
} else if (Scalar.eq(r, bls12381r$1)) {
curve = await buildBls12381(singleThread);
} else {
throw new Error(`Curve not supported: ${Scalar.toString(r)}`);
}
return curve;
}
async function getCurveFromQ(q, options) {
let curve;
let singleThread = options && options.singleThread;
if (Scalar.eq(q, bn128q)) {
curve = await buildBn128(singleThread);
} else if (Scalar.eq(q, bls12381q)) {
curve = await buildBls12381(singleThread);
} else {
throw new Error(`Curve not supported: ${Scalar.toString(q)}`);
}
return curve;
}
async function getCurveFromName(name, options) {
let curve;
let singleThread = options && options.singleThread;
const normName = normalizeName(name);
if (["BN128", "BN254", "ALTBN128"].indexOf(normName) >= 0) {
curve = await buildBn128(singleThread);
} else if (["BLS12381"].indexOf(normName) >= 0) {
curve = await buildBls12381(singleThread);
} else {
throw new Error(`Curve not supported: ${name}`);
}
return curve;
function normalizeName(n) {
return n.toUpperCase().match(/[A-Za-z0-9]+/g).join("");
}
}
var curves = /*#__PURE__*/Object.freeze({
__proto__: null,
getCurveFromR: getCurveFromR,
getCurveFromQ: getCurveFromQ,
getCurveFromName: getCurveFromName
});
function number(n) {
if (!Number.isSafeInteger(n) || n < 0)
throw new Error(`positive integer expected, not ${n}`);
}
// copied from utils
function isBytes(a) {
return (a instanceof Uint8Array ||
(a != null && typeof a === 'object' && a.constructor.name === 'Uint8Array'));
}
function bytes(b, ...lengths) {
if (!isBytes(b))
throw new Error('Uint8Array expected');
if (lengths.length > 0 && !lengths.includes(b.length))
throw new Error(`Uint8Array expected of length ${lengths}, not of length=${b.length}`);
}
function exists(instance, checkFinished = true) {
if (instance.destroyed)
throw new Error('Hash instance has been destroyed');
if (checkFinished && instance.finished)
throw new Error('Hash#digest() has already been called');
}
function output(out, instance) {
bytes(out);
const min = instance.outputLen;
if (out.length < min) {
throw new Error(`digestInto() expects output buffer of length at least ${min}`);
}
}
/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */
const u32 = (arr) => new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));
const isLE = new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44;
// The byte swap operation for uint32
const byteSwap = (word) => ((word << 24) & 0xff000000) |
((word << 8) & 0xff0000) |
((word >>> 8) & 0xff00) |
((word >>> 24) & 0xff);
// Conditionally byte swap if on a big-endian platform
const byteSwapIfBE = isLE ? (n) => n : (n) => byteSwap(n);
// In place byte swap for Uint32Array
function byteSwap32(arr) {
for (let i = 0; i < arr.length; i++) {
arr[i] = byteSwap(arr[i]);
}
}
/**
* @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99])
*/
function utf8ToBytes(str) {
if (typeof str !== 'string')
throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809
}
/**
* Normalizes (non-hex) string or Uint8Array to Uint8Array.
* Warning: when Uint8Array is passed, it would NOT get copied.
* Keep in mind for future mutable operations.
*/
function toBytes(data) {
if (typeof data === 'string')
data = utf8ToBytes(data);
bytes(data);
return data;
}
// For runtime check if class implements interface
class Hash {
// Safe version that clones internal state
clone() {
return this._cloneInto();
}
}
function wrapConstructor(hashCons) {
const hashC = (msg) => hashCons().update(toBytes(msg)).digest();
const tmp = hashCons();
hashC.outputLen = tmp.outputLen;
hashC.blockLen = tmp.blockLen;
hashC.create = () => hashCons();
return hashC;
}
function wrapConstructorWithOpts(hashCons) {
const hashC = (msg, opts) => hashCons(opts).update(toBytes(msg)).digest();
const tmp = hashCons({});
hashC.outputLen = tmp.outputLen;
hashC.blockLen = tmp.blockLen;
hashC.create = (opts) => hashCons(opts);
return hashC;
}
// Blake is based on ChaCha permutation.
// For BLAKE2b, the two extra permutations for rounds 10 and 11 are SIGMA[10..11] = SIGMA[0..1].
// prettier-ignore
const SIGMA = /* @__PURE__ */ new Uint8Array([
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3,
11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4,
7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8,
9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13,
2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9,
12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11,
13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10,
6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5,
10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3,
]);
class BLAKE extends Hash {
constructor(blockLen, outputLen, opts = {}, keyLen, saltLen, persLen) {
super();
this.blockLen = blockLen;
this.outputLen = outputLen;
this.length = 0;
this.pos = 0;
this.finished = false;
this.destroyed = false;
number(blockLen);
number(outputLen);
number(keyLen);
if (outputLen < 0 || outputLen > keyLen)
throw new Error('outputLen bigger than keyLen');
if (opts.key !== undefined && (opts.key.length < 1 || opts.key.length > keyLen))
throw new Error(`key must be up 1..${keyLen} byte long or undefined`);
if (opts.salt !== undefined && opts.salt.length !== saltLen)
throw new Error(`salt must be ${saltLen} byte long or undefined`);
if (opts.personalization !== undefined && opts.personalization.length !== persLen)
throw new Error(`personalization must be ${persLen} byte long or undefined`);
this.buffer32 = u32((this.buffer = new Uint8Array(blockLen)));
}
update(data) {
exists(this);
// Main difference with other hashes: there is flag for last block,
// so we cannot process current block before we know that there
// is the next one. This significantly complicates logic and reduces ability
// to do zero-copy processing
const { blockLen, buffer, buffer32 } = this;
data = toBytes(data);
const len = data.length;
const offset = data.byteOffset;
const buf = data.buffer;
for (let pos = 0; pos < len;) {
// If buffer is full and we still have input (don't process last block, same as blake2s)
if (this.pos === blockLen) {
if (!isLE)
byteSwap32(buffer32);
this.compress(buffer32, 0, false);
if (!isLE)
byteSwap32(buffer32);
this.pos = 0;
}
const take = Math.min(blockLen - this.pos, len - pos);
const dataOffset = offset + pos;
// full block && aligned to 4 bytes && not last in input
if (take === blockLen && !(dataOffset % 4) && pos + take < len) {
const data32 = new Uint32Array(buf, dataOffset, Math.floor((len - pos) / 4));
if (!isLE)
byteSwap32(data32);
for (let pos32 = 0; pos + blockLen < len; pos32 += buffer32.length, pos += blockLen) {
this.length += blockLen;
this.compress(data32, pos32, false);
}
if (!isLE)
byteSwap32(data32);
continue;
}
buffer.set(data.subarray(pos, pos + take), this.pos);
this.pos += take;
this.length += take;
pos += take;
}
return this;
}
digestInto(out) {
exists(this);
output(out, this);
const { pos, buffer32 } = this;
this.finished = true;
// Padding
this.buffer.subarray(pos).fill(0);
if (!isLE)
byteSwap32(buffer32);
this.compress(buffer32, 0, true);
if (!isLE)
byteSwap32(buffer32);
const out32 = u32(out);
this.get().forEach((v, i) => (out32[i] = byteSwapIfBE(v)));
}
digest() {
const { buffer, outputLen } = this;
this.digestInto(buffer);
const res = buffer.slice(0, outputLen);
this.destroy();
return res;
}
_cloneInto(to) {
const { buffer, length, finished, destroyed, outputLen, pos } = this;
to || (to = new this.constructor({ dkLen: outputLen }));
to.set(...this.get());
to.length = length;
to.finished = finished;
to.destroyed = destroyed;
to.outputLen = outputLen;
to.buffer.set(buffer);
to.pos = pos;
return to;
}
}
const U32_MASK64 = /* @__PURE__ */ BigInt(2 ** 32 - 1);
const _32n = /* @__PURE__ */ BigInt(32);
// We are not using BigUint64Array, because they are extremely slow as per 2022
function fromBig(n, le = false) {
if (le)
return { h: Number(n & U32_MASK64), l: Number((n >> _32n) & U32_MASK64) };
return { h: Number((n >> _32n) & U32_MASK64) | 0, l: Number(n & U32_MASK64) | 0 };
}
function split(lst, le = false) {
let Ah = new Uint32Array(lst.length);
let Al = new Uint32Array(lst.length);
for (let i = 0; i < lst.length; i++) {
const { h, l } = fromBig(lst[i], le);
[Ah[i], Al[i]] = [h, l];
}
return [Ah, Al];
}
const toBig = (h, l) => (BigInt(h >>> 0) << _32n) | BigInt(l >>> 0);
// for Shift in [0, 32)
const shrSH = (h, _l, s) => h >>> s;
const shrSL = (h, l, s) => (h << (32 - s)) | (l >>> s);
// Right rotate for Shift in [1, 32)
const rotrSH = (h, l, s) => (h >>> s) | (l << (32 - s));
const rotrSL = (h, l, s) => (h << (32 - s)) | (l >>> s);
// Right rotate for Shift in (32, 64), NOTE: 32 is special case.
const rotrBH = (h, l, s) => (h << (64 - s)) | (l >>> (s - 32));
const rotrBL = (h, l, s) => (h >>> (s - 32)) | (l << (64 - s));
// Right rotate for shift===32 (just swaps l&h)
const rotr32H = (_h, l) => l;
const rotr32L = (h, _l) => h;
// Left rotate for Shift in [1, 32)
const rotlSH = (h, l, s) => (h << s) | (l >>> (32 - s));
const rotlSL = (h, l, s) => (l << s) | (h >>> (32 - s));
// Left rotate for Shift in (32, 64), NOTE: 32 is special case.
const rotlBH = (h, l, s) => (l << (s - 32)) | (h >>> (64 - s));
const rotlBL = (h, l, s) => (h << (s - 32)) | (l >>> (64 - s));
// JS uses 32-bit signed integers for bitwise operations which means we cannot
// simple take carry out of low bit sum by shift, we need to use division.
function add(Ah, Al, Bh, Bl) {
const l = (Al >>> 0) + (Bl >>> 0);
return { h: (Ah + Bh + ((l / 2 ** 32) | 0)) | 0, l: l | 0 };
}
// Addition with more than 2 elements
const add3L = (Al, Bl, Cl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0);
const add3H = (low, Ah, Bh, Ch) => (Ah + Bh + Ch + ((low / 2 ** 32) | 0)) | 0;
const add4L = (Al, Bl, Cl, Dl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0);
const add4H = (low, Ah, Bh, Ch, Dh) => (Ah + Bh + Ch + Dh + ((low / 2 ** 32) | 0)) | 0;
const add5L = (Al, Bl, Cl, Dl, El) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0) + (El >>> 0);
const add5H = (low, Ah, Bh, Ch, Dh, Eh) => (Ah + Bh + Ch + Dh + Eh + ((low / 2 ** 32) | 0)) | 0;
// prettier-ignore
const u64 = {
fromBig, split, toBig,
shrSH, shrSL,
rotrSH, rotrSL, rotrBH, rotrBL,
rotr32H, rotr32L,
rotlSH, rotlSL, rotlBH, rotlBL,
add, add3L, add3H, add4L, add4H, add5H, add5L,
};
var u64$1 = u64;
// Same as SHA-512 but LE
// prettier-ignore
const B2B_IV = /* @__PURE__ */ new Uint32Array([
0xf3bcc908, 0x6a09e667, 0x84caa73b, 0xbb67ae85, 0xfe94f82b, 0x3c6ef372, 0x5f1d36f1, 0xa54ff53a,
0xade682d1, 0x510e527f, 0x2b3e6c1f, 0x9b05688c, 0xfb41bd6b, 0x1f83d9ab, 0x137e2179, 0x5be0cd19
]);
// Temporary buffer
const BBUF = /* @__PURE__ */ new Uint32Array(32);
// Mixing function G splitted in two halfs
function G1b(a, b, c, d, msg, x) {
// NOTE: V is LE here
const Xl = msg[x], Xh = msg[x + 1]; // prettier-ignore
let Al = BBUF[2 * a], Ah = BBUF[2 * a + 1]; // prettier-ignore
let Bl = BBUF[2 * b], Bh = BBUF[2 * b + 1]; // prettier-ignore
let Cl = BBUF[2 * c], Ch = BBUF[2 * c + 1]; // prettier-ignore
let Dl = BBUF[2 * d], Dh = BBUF[2 * d + 1]; // prettier-ignore
// v[a] = (v[a] + v[b] + x) | 0;
let ll = u64$1.add3L(Al, Bl, Xl);
Ah = u64$1.add3H(ll, Ah, Bh, Xh);
Al = ll | 0;
// v[d] = rotr(v[d] ^ v[a], 32)
({ Dh, Dl } = { Dh: Dh ^ Ah, Dl: Dl ^ Al });
({ Dh, Dl } = { Dh: u64$1.rotr32H(Dh, Dl), Dl: u64$1.rotr32L(Dh, Dl) });
// v[c] = (v[c] + v[d]) | 0;
({ h: Ch, l: Cl } = u64$1.add(Ch, Cl, Dh, Dl));
// v[b] = rotr(v[b] ^ v[c], 24)
({ Bh, Bl } = { Bh: Bh ^ Ch, Bl: Bl ^ Cl });
({ Bh, Bl } = { Bh: u64$1.rotrSH(Bh, Bl, 24), Bl: u64$1.rotrSL(Bh, Bl, 24) });
(BBUF[2 * a] = Al), (BBUF[2 * a + 1] = Ah);
(BBUF[2 * b] = Bl), (BBUF[2 * b + 1] = Bh);
(BBUF[2 * c] = Cl), (BBUF[2 * c + 1] = Ch);
(BBUF[2 * d] = Dl), (BBUF[2 * d + 1] = Dh);
}
function G2b(a, b, c, d, msg, x) {
// NOTE: V is LE here
const Xl = msg[x], Xh = msg[x + 1]; // prettier-ignore
let Al = BBUF[2 * a], Ah = BBUF[2 * a + 1]; // prettier-ignore
let Bl = BBUF[2 * b], Bh = BBUF[2 * b + 1]; // prettier-ignore
let Cl = BBUF[2 * c], Ch = BBUF[2 * c + 1]; // prettier-ignore
let Dl = BBUF[2 * d], Dh = BBUF[2 * d + 1]; // prettier-ignore
// v[a] = (v[a] + v[b] + x) | 0;
let ll = u64$1.add3L(Al, Bl, Xl);
Ah = u64$1.add3H(ll, Ah, Bh, Xh);
Al = ll | 0;
// v[d] = rotr(v[d] ^ v[a], 16)
({ Dh, Dl } = { Dh: Dh ^ Ah, Dl: Dl ^ Al });
({ Dh, Dl } = { Dh: u64$1.rotrSH(Dh, Dl, 16), Dl: u64$1.rotrSL(Dh, Dl, 16) });
// v[c] = (v[c] + v[d]) | 0;
({ h: Ch, l: Cl } = u64$1.add(Ch, Cl, Dh, Dl));
// v[b] = rotr(v[b] ^ v[c], 63)
({ Bh, Bl } = { Bh: Bh ^ Ch, Bl: Bl ^ Cl });
({ Bh, Bl } = { Bh: u64$1.rotrBH(Bh, Bl, 63), Bl: u64$1.rotrBL(Bh, Bl, 63) });
(BBUF[2 * a] = Al), (BBUF[2 * a + 1] = Ah);
(BBUF[2 * b] = Bl), (BBUF[2 * b + 1] = Bh);
(BBUF[2 * c] = Cl), (BBUF[2 * c + 1] = Ch);
(BBUF[2 * d] = Dl), (BBUF[2 * d + 1] = Dh);
}
class BLAKE2b extends BLAKE {
constructor(opts = {}) {
super(128, opts.dkLen === undefined ? 64 : opts.dkLen, opts, 64, 16, 16);
// Same as SHA-512, but LE
this.v0l = B2B_IV[0] | 0;
this.v0h = B2B_IV[1] | 0;
this.v1l = B2B_IV[2] | 0;
this.v1h = B2B_IV[3] | 0;
this.v2l = B2B_IV[4] | 0;
this.v2h = B2B_IV[5] | 0;
this.v3l = B2B_IV[6] | 0;
this.v3h = B2B_IV[7] | 0;
this.v4l = B2B_IV[8] | 0;
this.v4h = B2B_IV[9] | 0;
this.v5l = B2B_IV[10] | 0;
this.v5h = B2B_IV[11] | 0;
this.v6l = B2B_IV[12] | 0;
this.v6h = B2B_IV[13] | 0;
this.v7l = B2B_IV[14] | 0;
this.v7h = B2B_IV[15] | 0;
const keyLength = opts.key ? opts.key.length : 0;
this.v0l ^= this.outputLen | (keyLength << 8) | (0x01 << 16) | (0x01 << 24);
if (opts.salt) {
const salt = u32(toBytes(opts.salt));
this.v4l ^= byteSwapIfBE(salt[0]);
this.v4h ^= byteSwapIfBE(salt[1]);
this.v5l ^= byteSwapIfBE(salt[2]);
this.v5h ^= byteSwapIfBE(salt[3]);
}
if (opts.personalization) {
const pers = u32(toBytes(opts.personalization));
this.v6l ^= byteSwapIfBE(pers[0]);
this.v6h ^= byteSwapIfBE(pers[1]);
this.v7l ^= byteSwapIfBE(pers[2]);
this.v7h ^= byteSwapIfBE(pers[3]);
}
if (opts.key) {
// Pad to blockLen and update
const tmp = new Uint8Array(this.blockLen);
tmp.set(toBytes(opts.key));
this.update(tmp);
}
}
// prettier-ignore
get() {
let { v0l, v0h, v1l, v1h, v2l, v2h, v3l, v3h, v4l, v4h, v5l, v5h, v6l, v6h, v7l, v7h } = this;
return [v0l, v0h, v1l, v1h, v2l, v2h, v3l, v3h, v4l, v4h, v5l, v5h, v6l, v6h, v7l, v7h];
}
// prettier-ignore
set(v0l, v0h, v1l, v1h, v2l, v2h, v3l, v3h, v4l, v4h, v5l, v5h, v6l, v6h, v7l, v7h) {
this.v0l = v0l | 0;
this.