2020-07-11 10:31:52 +02:00
|
|
|
var snarkjs = (function (exports) {
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
/* global BigInt */
|
|
|
|
const hexLen = [ 0, 1, 2, 2, 3, 3, 3, 3, 4 ,4 ,4 ,4 ,4 ,4 ,4 ,4];
|
|
|
|
|
|
|
|
function fromString(s, radix) {
|
|
|
|
if ((!radix)||(radix==10)) {
|
|
|
|
return BigInt(s);
|
|
|
|
} else if (radix==16) {
|
|
|
|
if (s.slice(0,2) == "0x") {
|
|
|
|
return BigInt(s);
|
|
|
|
} else {
|
|
|
|
return BigInt("0x"+s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const e = fromString;
|
|
|
|
|
|
|
|
function fromArray(a, radix) {
|
|
|
|
let acc =0n;
|
|
|
|
radix = BigInt(radix);
|
|
|
|
for (let i=0; i<a.length; i++) {
|
|
|
|
acc = acc*radix + BigInt(a[i]);
|
|
|
|
}
|
|
|
|
return acc;
|
|
|
|
}
|
|
|
|
|
|
|
|
function bitLength(a) {
|
|
|
|
const aS =a.toString(16);
|
|
|
|
return (aS.length-1)*4 +hexLen[parseInt(aS[0], 16)];
|
|
|
|
}
|
|
|
|
|
|
|
|
function isNegative(a) {
|
|
|
|
return BigInt(a) < 0n;
|
|
|
|
}
|
|
|
|
|
|
|
|
function isZero(a) {
|
|
|
|
return !a;
|
|
|
|
}
|
|
|
|
|
|
|
|
function shiftLeft(a, n) {
|
|
|
|
return BigInt(a) << BigInt(n);
|
|
|
|
}
|
|
|
|
|
|
|
|
function shiftRight(a, n) {
|
|
|
|
return BigInt(a) >> BigInt(n);
|
|
|
|
}
|
|
|
|
|
|
|
|
const shl = shiftLeft;
|
|
|
|
const shr = shiftRight;
|
|
|
|
|
|
|
|
function isOdd(a) {
|
|
|
|
return (BigInt(a) & 1n) == 1n;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function naf(n) {
|
|
|
|
let E = BigInt(n);
|
|
|
|
const res = [];
|
|
|
|
while (E) {
|
|
|
|
if (E & 1n) {
|
|
|
|
const z = 2 - Number(E % 4n);
|
|
|
|
res.push( z );
|
|
|
|
E = E - BigInt(z);
|
|
|
|
} else {
|
|
|
|
res.push( 0 );
|
|
|
|
}
|
|
|
|
E = E >> 1n;
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function bits(n) {
|
|
|
|
let E = BigInt(n);
|
|
|
|
const res = [];
|
|
|
|
while (E) {
|
|
|
|
if (E & 1n) {
|
|
|
|
res.push(1);
|
|
|
|
} else {
|
|
|
|
res.push( 0 );
|
|
|
|
}
|
|
|
|
E = E >> 1n;
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
function toNumber(s) {
|
|
|
|
if (s>BigInt(Number.MAX_SAFE_INTEGER )) {
|
|
|
|
throw new Error("Number too big");
|
|
|
|
}
|
|
|
|
return Number(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
function toArray(s, radix) {
|
|
|
|
const res = [];
|
|
|
|
let rem = BigInt(s);
|
|
|
|
radix = BigInt(radix);
|
|
|
|
while (rem) {
|
|
|
|
res.unshift( Number(rem % radix));
|
|
|
|
rem = rem / radix;
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function add(a, b) {
|
|
|
|
return BigInt(a) + BigInt(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
function sub(a, b) {
|
|
|
|
return BigInt(a) - BigInt(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
function neg(a) {
|
|
|
|
return -BigInt(a);
|
|
|
|
}
|
|
|
|
|
|
|
|
function mul(a, b) {
|
|
|
|
return BigInt(a) * BigInt(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
function square(a) {
|
|
|
|
return BigInt(a) * BigInt(a);
|
|
|
|
}
|
|
|
|
|
|
|
|
function pow(a, b) {
|
|
|
|
return BigInt(a) ** BigInt(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
function exp(a, b) {
|
|
|
|
return BigInt(a) ** BigInt(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
function abs(a) {
|
|
|
|
return BigInt(a) >= 0 ? BigInt(a) : -BigInt(a);
|
|
|
|
}
|
|
|
|
|
|
|
|
function div(a, b) {
|
|
|
|
return BigInt(a) / BigInt(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
function mod(a, b) {
|
|
|
|
return BigInt(a) % BigInt(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
function eq(a, b) {
|
|
|
|
return BigInt(a) == BigInt(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
function neq(a, b) {
|
|
|
|
return BigInt(a) != BigInt(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
function lt(a, b) {
|
|
|
|
return BigInt(a) < BigInt(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
function gt(a, b) {
|
|
|
|
return BigInt(a) > BigInt(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
function leq(a, b) {
|
|
|
|
return BigInt(a) <= BigInt(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
function geq(a, b) {
|
|
|
|
return BigInt(a) >= BigInt(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
function band(a, b) {
|
|
|
|
return BigInt(a) & BigInt(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
function bor(a, b) {
|
|
|
|
return BigInt(a) | BigInt(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
function bxor(a, b) {
|
|
|
|
return BigInt(a) ^ BigInt(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
function land(a, b) {
|
|
|
|
return BigInt(a) && BigInt(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
function lor(a, b) {
|
|
|
|
return BigInt(a) || BigInt(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
function lnot(a) {
|
|
|
|
return !BigInt(a);
|
|
|
|
}
|
|
|
|
|
|
|
|
var Scalar_native = /*#__PURE__*/Object.freeze({
|
|
|
|
__proto__: null,
|
|
|
|
fromString: fromString,
|
|
|
|
e: e,
|
|
|
|
fromArray: fromArray,
|
|
|
|
bitLength: bitLength,
|
|
|
|
isNegative: isNegative,
|
|
|
|
isZero: isZero,
|
|
|
|
shiftLeft: shiftLeft,
|
|
|
|
shiftRight: shiftRight,
|
|
|
|
shl: shl,
|
|
|
|
shr: shr,
|
|
|
|
isOdd: isOdd,
|
|
|
|
naf: naf,
|
|
|
|
bits: bits,
|
|
|
|
toNumber: toNumber,
|
|
|
|
toArray: toArray,
|
|
|
|
add: add,
|
|
|
|
sub: sub,
|
|
|
|
neg: neg,
|
|
|
|
mul: mul,
|
|
|
|
square: square,
|
|
|
|
pow: pow,
|
|
|
|
exp: exp,
|
|
|
|
abs: abs,
|
|
|
|
div: div,
|
|
|
|
mod: mod,
|
|
|
|
eq: eq,
|
|
|
|
neq: neq,
|
|
|
|
lt: lt,
|
|
|
|
gt: gt,
|
|
|
|
leq: leq,
|
|
|
|
geq: geq,
|
|
|
|
band: band,
|
|
|
|
bor: bor,
|
|
|
|
bxor: bxor,
|
|
|
|
land: land,
|
|
|
|
lor: lor,
|
|
|
|
lnot: lnot
|
|
|
|
});
|
|
|
|
|
|
|
|
function commonjsRequire () {
|
|
|
|
throw new Error('Dynamic requires are not currently supported by rollup-plugin-commonjs');
|
|
|
|
}
|
|
|
|
|
|
|
|
function createCommonjsModule(fn, module) {
|
|
|
|
return module = { exports: {} }, fn(module, module.exports), module.exports;
|
|
|
|
}
|
|
|
|
|
|
|
|
var BigInteger = createCommonjsModule(function (module) {
|
|
|
|
var bigInt = (function (undefined$1) {
|
|
|
|
|
|
|
|
var BASE = 1e7,
|
|
|
|
LOG_BASE = 7,
|
|
|
|
MAX_INT = 9007199254740992,
|
|
|
|
MAX_INT_ARR = smallToArray(MAX_INT),
|
|
|
|
DEFAULT_ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyz";
|
|
|
|
|
|
|
|
var supportsNativeBigInt = typeof BigInt === "function";
|
|
|
|
|
|
|
|
function Integer(v, radix, alphabet, caseSensitive) {
|
|
|
|
if (typeof v === "undefined") return Integer[0];
|
|
|
|
if (typeof radix !== "undefined") return +radix === 10 && !alphabet ? parseValue(v) : parseBase(v, radix, alphabet, caseSensitive);
|
|
|
|
return parseValue(v);
|
|
|
|
}
|
|
|
|
|
|
|
|
function BigInteger(value, sign) {
|
|
|
|
this.value = value;
|
|
|
|
this.sign = sign;
|
|
|
|
this.isSmall = false;
|
|
|
|
}
|
|
|
|
BigInteger.prototype = Object.create(Integer.prototype);
|
|
|
|
|
|
|
|
function SmallInteger(value) {
|
|
|
|
this.value = value;
|
|
|
|
this.sign = value < 0;
|
|
|
|
this.isSmall = true;
|
|
|
|
}
|
|
|
|
SmallInteger.prototype = Object.create(Integer.prototype);
|
|
|
|
|
|
|
|
function NativeBigInt(value) {
|
|
|
|
this.value = value;
|
|
|
|
}
|
|
|
|
NativeBigInt.prototype = Object.create(Integer.prototype);
|
|
|
|
|
|
|
|
function isPrecise(n) {
|
|
|
|
return -MAX_INT < n && n < MAX_INT;
|
|
|
|
}
|
|
|
|
|
|
|
|
function smallToArray(n) { // For performance reasons doesn't reference BASE, need to change this function if BASE changes
|
|
|
|
if (n < 1e7)
|
|
|
|
return [n];
|
|
|
|
if (n < 1e14)
|
|
|
|
return [n % 1e7, Math.floor(n / 1e7)];
|
|
|
|
return [n % 1e7, Math.floor(n / 1e7) % 1e7, Math.floor(n / 1e14)];
|
|
|
|
}
|
|
|
|
|
|
|
|
function arrayToSmall(arr) { // If BASE changes this function may need to change
|
|
|
|
trim(arr);
|
|
|
|
var length = arr.length;
|
|
|
|
if (length < 4 && compareAbs(arr, MAX_INT_ARR) < 0) {
|
|
|
|
switch (length) {
|
|
|
|
case 0: return 0;
|
|
|
|
case 1: return arr[0];
|
|
|
|
case 2: return arr[0] + arr[1] * BASE;
|
|
|
|
default: return arr[0] + (arr[1] + arr[2] * BASE) * BASE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return arr;
|
|
|
|
}
|
|
|
|
|
|
|
|
function trim(v) {
|
|
|
|
var i = v.length;
|
|
|
|
while (v[--i] === 0);
|
|
|
|
v.length = i + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
function createArray(length) { // function shamelessly stolen from Yaffle's library https://github.com/Yaffle/BigInteger
|
|
|
|
var x = new Array(length);
|
|
|
|
var i = -1;
|
|
|
|
while (++i < length) {
|
|
|
|
x[i] = 0;
|
|
|
|
}
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
function truncate(n) {
|
|
|
|
if (n > 0) return Math.floor(n);
|
|
|
|
return Math.ceil(n);
|
|
|
|
}
|
|
|
|
|
|
|
|
function add(a, b) { // assumes a and b are arrays with a.length >= b.length
|
|
|
|
var l_a = a.length,
|
|
|
|
l_b = b.length,
|
|
|
|
r = new Array(l_a),
|
|
|
|
carry = 0,
|
|
|
|
base = BASE,
|
|
|
|
sum, i;
|
|
|
|
for (i = 0; i < l_b; i++) {
|
|
|
|
sum = a[i] + b[i] + carry;
|
|
|
|
carry = sum >= base ? 1 : 0;
|
|
|
|
r[i] = sum - carry * base;
|
|
|
|
}
|
|
|
|
while (i < l_a) {
|
|
|
|
sum = a[i] + carry;
|
|
|
|
carry = sum === base ? 1 : 0;
|
|
|
|
r[i++] = sum - carry * base;
|
|
|
|
}
|
|
|
|
if (carry > 0) r.push(carry);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
function addAny(a, b) {
|
|
|
|
if (a.length >= b.length) return add(a, b);
|
|
|
|
return add(b, a);
|
|
|
|
}
|
|
|
|
|
|
|
|
function addSmall(a, carry) { // assumes a is array, carry is number with 0 <= carry < MAX_INT
|
|
|
|
var l = a.length,
|
|
|
|
r = new Array(l),
|
|
|
|
base = BASE,
|
|
|
|
sum, i;
|
|
|
|
for (i = 0; i < l; i++) {
|
|
|
|
sum = a[i] - base + carry;
|
|
|
|
carry = Math.floor(sum / base);
|
|
|
|
r[i] = sum - carry * base;
|
|
|
|
carry += 1;
|
|
|
|
}
|
|
|
|
while (carry > 0) {
|
|
|
|
r[i++] = carry % base;
|
|
|
|
carry = Math.floor(carry / base);
|
|
|
|
}
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
BigInteger.prototype.add = function (v) {
|
|
|
|
var n = parseValue(v);
|
|
|
|
if (this.sign !== n.sign) {
|
|
|
|
return this.subtract(n.negate());
|
|
|
|
}
|
|
|
|
var a = this.value, b = n.value;
|
|
|
|
if (n.isSmall) {
|
|
|
|
return new BigInteger(addSmall(a, Math.abs(b)), this.sign);
|
|
|
|
}
|
|
|
|
return new BigInteger(addAny(a, b), this.sign);
|
|
|
|
};
|
|
|
|
BigInteger.prototype.plus = BigInteger.prototype.add;
|
|
|
|
|
|
|
|
SmallInteger.prototype.add = function (v) {
|
|
|
|
var n = parseValue(v);
|
|
|
|
var a = this.value;
|
|
|
|
if (a < 0 !== n.sign) {
|
|
|
|
return this.subtract(n.negate());
|
|
|
|
}
|
|
|
|
var b = n.value;
|
|
|
|
if (n.isSmall) {
|
|
|
|
if (isPrecise(a + b)) return new SmallInteger(a + b);
|
|
|
|
b = smallToArray(Math.abs(b));
|
|
|
|
}
|
|
|
|
return new BigInteger(addSmall(b, Math.abs(a)), a < 0);
|
|
|
|
};
|
|
|
|
SmallInteger.prototype.plus = SmallInteger.prototype.add;
|
|
|
|
|
|
|
|
NativeBigInt.prototype.add = function (v) {
|
|
|
|
return new NativeBigInt(this.value + parseValue(v).value);
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.plus = NativeBigInt.prototype.add;
|
|
|
|
|
|
|
|
function subtract(a, b) { // assumes a and b are arrays with a >= b
|
|
|
|
var a_l = a.length,
|
|
|
|
b_l = b.length,
|
|
|
|
r = new Array(a_l),
|
|
|
|
borrow = 0,
|
|
|
|
base = BASE,
|
|
|
|
i, difference;
|
|
|
|
for (i = 0; i < b_l; i++) {
|
|
|
|
difference = a[i] - borrow - b[i];
|
|
|
|
if (difference < 0) {
|
|
|
|
difference += base;
|
|
|
|
borrow = 1;
|
|
|
|
} else borrow = 0;
|
|
|
|
r[i] = difference;
|
|
|
|
}
|
|
|
|
for (i = b_l; i < a_l; i++) {
|
|
|
|
difference = a[i] - borrow;
|
|
|
|
if (difference < 0) difference += base;
|
|
|
|
else {
|
|
|
|
r[i++] = difference;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
r[i] = difference;
|
|
|
|
}
|
|
|
|
for (; i < a_l; i++) {
|
|
|
|
r[i] = a[i];
|
|
|
|
}
|
|
|
|
trim(r);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
function subtractAny(a, b, sign) {
|
|
|
|
var value;
|
|
|
|
if (compareAbs(a, b) >= 0) {
|
|
|
|
value = subtract(a, b);
|
|
|
|
} else {
|
|
|
|
value = subtract(b, a);
|
|
|
|
sign = !sign;
|
|
|
|
}
|
|
|
|
value = arrayToSmall(value);
|
|
|
|
if (typeof value === "number") {
|
|
|
|
if (sign) value = -value;
|
|
|
|
return new SmallInteger(value);
|
|
|
|
}
|
|
|
|
return new BigInteger(value, sign);
|
|
|
|
}
|
|
|
|
|
|
|
|
function subtractSmall(a, b, sign) { // assumes a is array, b is number with 0 <= b < MAX_INT
|
|
|
|
var l = a.length,
|
|
|
|
r = new Array(l),
|
|
|
|
carry = -b,
|
|
|
|
base = BASE,
|
|
|
|
i, difference;
|
|
|
|
for (i = 0; i < l; i++) {
|
|
|
|
difference = a[i] + carry;
|
|
|
|
carry = Math.floor(difference / base);
|
|
|
|
difference %= base;
|
|
|
|
r[i] = difference < 0 ? difference + base : difference;
|
|
|
|
}
|
|
|
|
r = arrayToSmall(r);
|
|
|
|
if (typeof r === "number") {
|
|
|
|
if (sign) r = -r;
|
|
|
|
return new SmallInteger(r);
|
|
|
|
} return new BigInteger(r, sign);
|
|
|
|
}
|
|
|
|
|
|
|
|
BigInteger.prototype.subtract = function (v) {
|
|
|
|
var n = parseValue(v);
|
|
|
|
if (this.sign !== n.sign) {
|
|
|
|
return this.add(n.negate());
|
|
|
|
}
|
|
|
|
var a = this.value, b = n.value;
|
|
|
|
if (n.isSmall)
|
|
|
|
return subtractSmall(a, Math.abs(b), this.sign);
|
|
|
|
return subtractAny(a, b, this.sign);
|
|
|
|
};
|
|
|
|
BigInteger.prototype.minus = BigInteger.prototype.subtract;
|
|
|
|
|
|
|
|
SmallInteger.prototype.subtract = function (v) {
|
|
|
|
var n = parseValue(v);
|
|
|
|
var a = this.value;
|
|
|
|
if (a < 0 !== n.sign) {
|
|
|
|
return this.add(n.negate());
|
|
|
|
}
|
|
|
|
var b = n.value;
|
|
|
|
if (n.isSmall) {
|
|
|
|
return new SmallInteger(a - b);
|
|
|
|
}
|
|
|
|
return subtractSmall(b, Math.abs(a), a >= 0);
|
|
|
|
};
|
|
|
|
SmallInteger.prototype.minus = SmallInteger.prototype.subtract;
|
|
|
|
|
|
|
|
NativeBigInt.prototype.subtract = function (v) {
|
|
|
|
return new NativeBigInt(this.value - parseValue(v).value);
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.minus = NativeBigInt.prototype.subtract;
|
|
|
|
|
|
|
|
BigInteger.prototype.negate = function () {
|
|
|
|
return new BigInteger(this.value, !this.sign);
|
|
|
|
};
|
|
|
|
SmallInteger.prototype.negate = function () {
|
|
|
|
var sign = this.sign;
|
|
|
|
var small = new SmallInteger(-this.value);
|
|
|
|
small.sign = !sign;
|
|
|
|
return small;
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.negate = function () {
|
|
|
|
return new NativeBigInt(-this.value);
|
|
|
|
};
|
|
|
|
|
|
|
|
BigInteger.prototype.abs = function () {
|
|
|
|
return new BigInteger(this.value, false);
|
|
|
|
};
|
|
|
|
SmallInteger.prototype.abs = function () {
|
|
|
|
return new SmallInteger(Math.abs(this.value));
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.abs = function () {
|
|
|
|
return new NativeBigInt(this.value >= 0 ? this.value : -this.value);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
function multiplyLong(a, b) {
|
|
|
|
var a_l = a.length,
|
|
|
|
b_l = b.length,
|
|
|
|
l = a_l + b_l,
|
|
|
|
r = createArray(l),
|
|
|
|
base = BASE,
|
|
|
|
product, carry, i, a_i, b_j;
|
|
|
|
for (i = 0; i < a_l; ++i) {
|
|
|
|
a_i = a[i];
|
|
|
|
for (var j = 0; j < b_l; ++j) {
|
|
|
|
b_j = b[j];
|
|
|
|
product = a_i * b_j + r[i + j];
|
|
|
|
carry = Math.floor(product / base);
|
|
|
|
r[i + j] = product - carry * base;
|
|
|
|
r[i + j + 1] += carry;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
trim(r);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
function multiplySmall(a, b) { // assumes a is array, b is number with |b| < BASE
|
|
|
|
var l = a.length,
|
|
|
|
r = new Array(l),
|
|
|
|
base = BASE,
|
|
|
|
carry = 0,
|
|
|
|
product, i;
|
|
|
|
for (i = 0; i < l; i++) {
|
|
|
|
product = a[i] * b + carry;
|
|
|
|
carry = Math.floor(product / base);
|
|
|
|
r[i] = product - carry * base;
|
|
|
|
}
|
|
|
|
while (carry > 0) {
|
|
|
|
r[i++] = carry % base;
|
|
|
|
carry = Math.floor(carry / base);
|
|
|
|
}
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
function shiftLeft(x, n) {
|
|
|
|
var r = [];
|
|
|
|
while (n-- > 0) r.push(0);
|
|
|
|
return r.concat(x);
|
|
|
|
}
|
|
|
|
|
|
|
|
function multiplyKaratsuba(x, y) {
|
|
|
|
var n = Math.max(x.length, y.length);
|
|
|
|
|
|
|
|
if (n <= 30) return multiplyLong(x, y);
|
|
|
|
n = Math.ceil(n / 2);
|
|
|
|
|
|
|
|
var b = x.slice(n),
|
|
|
|
a = x.slice(0, n),
|
|
|
|
d = y.slice(n),
|
|
|
|
c = y.slice(0, n);
|
|
|
|
|
|
|
|
var ac = multiplyKaratsuba(a, c),
|
|
|
|
bd = multiplyKaratsuba(b, d),
|
|
|
|
abcd = multiplyKaratsuba(addAny(a, b), addAny(c, d));
|
|
|
|
|
|
|
|
var product = addAny(addAny(ac, shiftLeft(subtract(subtract(abcd, ac), bd), n)), shiftLeft(bd, 2 * n));
|
|
|
|
trim(product);
|
|
|
|
return product;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The following function is derived from a surface fit of a graph plotting the performance difference
|
|
|
|
// between long multiplication and karatsuba multiplication versus the lengths of the two arrays.
|
|
|
|
function useKaratsuba(l1, l2) {
|
|
|
|
return -0.012 * l1 - 0.012 * l2 + 0.000015 * l1 * l2 > 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
BigInteger.prototype.multiply = function (v) {
|
|
|
|
var n = parseValue(v),
|
|
|
|
a = this.value, b = n.value,
|
|
|
|
sign = this.sign !== n.sign,
|
|
|
|
abs;
|
|
|
|
if (n.isSmall) {
|
|
|
|
if (b === 0) return Integer[0];
|
|
|
|
if (b === 1) return this;
|
|
|
|
if (b === -1) return this.negate();
|
|
|
|
abs = Math.abs(b);
|
|
|
|
if (abs < BASE) {
|
|
|
|
return new BigInteger(multiplySmall(a, abs), sign);
|
|
|
|
}
|
|
|
|
b = smallToArray(abs);
|
|
|
|
}
|
|
|
|
if (useKaratsuba(a.length, b.length)) // Karatsuba is only faster for certain array sizes
|
|
|
|
return new BigInteger(multiplyKaratsuba(a, b), sign);
|
|
|
|
return new BigInteger(multiplyLong(a, b), sign);
|
|
|
|
};
|
|
|
|
|
|
|
|
BigInteger.prototype.times = BigInteger.prototype.multiply;
|
|
|
|
|
|
|
|
function multiplySmallAndArray(a, b, sign) { // a >= 0
|
|
|
|
if (a < BASE) {
|
|
|
|
return new BigInteger(multiplySmall(b, a), sign);
|
|
|
|
}
|
|
|
|
return new BigInteger(multiplyLong(b, smallToArray(a)), sign);
|
|
|
|
}
|
|
|
|
SmallInteger.prototype._multiplyBySmall = function (a) {
|
|
|
|
if (isPrecise(a.value * this.value)) {
|
|
|
|
return new SmallInteger(a.value * this.value);
|
|
|
|
}
|
|
|
|
return multiplySmallAndArray(Math.abs(a.value), smallToArray(Math.abs(this.value)), this.sign !== a.sign);
|
|
|
|
};
|
|
|
|
BigInteger.prototype._multiplyBySmall = function (a) {
|
|
|
|
if (a.value === 0) return Integer[0];
|
|
|
|
if (a.value === 1) return this;
|
|
|
|
if (a.value === -1) return this.negate();
|
|
|
|
return multiplySmallAndArray(Math.abs(a.value), this.value, this.sign !== a.sign);
|
|
|
|
};
|
|
|
|
SmallInteger.prototype.multiply = function (v) {
|
|
|
|
return parseValue(v)._multiplyBySmall(this);
|
|
|
|
};
|
|
|
|
SmallInteger.prototype.times = SmallInteger.prototype.multiply;
|
|
|
|
|
|
|
|
NativeBigInt.prototype.multiply = function (v) {
|
|
|
|
return new NativeBigInt(this.value * parseValue(v).value);
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.times = NativeBigInt.prototype.multiply;
|
|
|
|
|
|
|
|
function square(a) {
|
|
|
|
//console.assert(2 * BASE * BASE < MAX_INT);
|
|
|
|
var l = a.length,
|
|
|
|
r = createArray(l + l),
|
|
|
|
base = BASE,
|
|
|
|
product, carry, i, a_i, a_j;
|
|
|
|
for (i = 0; i < l; i++) {
|
|
|
|
a_i = a[i];
|
|
|
|
carry = 0 - a_i * a_i;
|
|
|
|
for (var j = i; j < l; j++) {
|
|
|
|
a_j = a[j];
|
|
|
|
product = 2 * (a_i * a_j) + r[i + j] + carry;
|
|
|
|
carry = Math.floor(product / base);
|
|
|
|
r[i + j] = product - carry * base;
|
|
|
|
}
|
|
|
|
r[i + l] = carry;
|
|
|
|
}
|
|
|
|
trim(r);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
BigInteger.prototype.square = function () {
|
|
|
|
return new BigInteger(square(this.value), false);
|
|
|
|
};
|
|
|
|
|
|
|
|
SmallInteger.prototype.square = function () {
|
|
|
|
var value = this.value * this.value;
|
|
|
|
if (isPrecise(value)) return new SmallInteger(value);
|
|
|
|
return new BigInteger(square(smallToArray(Math.abs(this.value))), false);
|
|
|
|
};
|
|
|
|
|
|
|
|
NativeBigInt.prototype.square = function (v) {
|
|
|
|
return new NativeBigInt(this.value * this.value);
|
|
|
|
};
|
|
|
|
|
|
|
|
function divMod1(a, b) { // Left over from previous version. Performs faster than divMod2 on smaller input sizes.
|
|
|
|
var a_l = a.length,
|
|
|
|
b_l = b.length,
|
|
|
|
base = BASE,
|
|
|
|
result = createArray(b.length),
|
|
|
|
divisorMostSignificantDigit = b[b_l - 1],
|
|
|
|
// normalization
|
|
|
|
lambda = Math.ceil(base / (2 * divisorMostSignificantDigit)),
|
|
|
|
remainder = multiplySmall(a, lambda),
|
|
|
|
divisor = multiplySmall(b, lambda),
|
|
|
|
quotientDigit, shift, carry, borrow, i, l, q;
|
|
|
|
if (remainder.length <= a_l) remainder.push(0);
|
|
|
|
divisor.push(0);
|
|
|
|
divisorMostSignificantDigit = divisor[b_l - 1];
|
|
|
|
for (shift = a_l - b_l; shift >= 0; shift--) {
|
|
|
|
quotientDigit = base - 1;
|
|
|
|
if (remainder[shift + b_l] !== divisorMostSignificantDigit) {
|
|
|
|
quotientDigit = Math.floor((remainder[shift + b_l] * base + remainder[shift + b_l - 1]) / divisorMostSignificantDigit);
|
|
|
|
}
|
|
|
|
// quotientDigit <= base - 1
|
|
|
|
carry = 0;
|
|
|
|
borrow = 0;
|
|
|
|
l = divisor.length;
|
|
|
|
for (i = 0; i < l; i++) {
|
|
|
|
carry += quotientDigit * divisor[i];
|
|
|
|
q = Math.floor(carry / base);
|
|
|
|
borrow += remainder[shift + i] - (carry - q * base);
|
|
|
|
carry = q;
|
|
|
|
if (borrow < 0) {
|
|
|
|
remainder[shift + i] = borrow + base;
|
|
|
|
borrow = -1;
|
|
|
|
} else {
|
|
|
|
remainder[shift + i] = borrow;
|
|
|
|
borrow = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (borrow !== 0) {
|
|
|
|
quotientDigit -= 1;
|
|
|
|
carry = 0;
|
|
|
|
for (i = 0; i < l; i++) {
|
|
|
|
carry += remainder[shift + i] - base + divisor[i];
|
|
|
|
if (carry < 0) {
|
|
|
|
remainder[shift + i] = carry + base;
|
|
|
|
carry = 0;
|
|
|
|
} else {
|
|
|
|
remainder[shift + i] = carry;
|
|
|
|
carry = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
borrow += carry;
|
|
|
|
}
|
|
|
|
result[shift] = quotientDigit;
|
|
|
|
}
|
|
|
|
// denormalization
|
|
|
|
remainder = divModSmall(remainder, lambda)[0];
|
|
|
|
return [arrayToSmall(result), arrayToSmall(remainder)];
|
|
|
|
}
|
|
|
|
|
|
|
|
function divMod2(a, b) { // Implementation idea shamelessly stolen from Silent Matt's library http://silentmatt.com/biginteger/
|
|
|
|
// Performs faster than divMod1 on larger input sizes.
|
|
|
|
var a_l = a.length,
|
|
|
|
b_l = b.length,
|
|
|
|
result = [],
|
|
|
|
part = [],
|
|
|
|
base = BASE,
|
|
|
|
guess, xlen, highx, highy, check;
|
|
|
|
while (a_l) {
|
|
|
|
part.unshift(a[--a_l]);
|
|
|
|
trim(part);
|
|
|
|
if (compareAbs(part, b) < 0) {
|
|
|
|
result.push(0);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
xlen = part.length;
|
|
|
|
highx = part[xlen - 1] * base + part[xlen - 2];
|
|
|
|
highy = b[b_l - 1] * base + b[b_l - 2];
|
|
|
|
if (xlen > b_l) {
|
|
|
|
highx = (highx + 1) * base;
|
|
|
|
}
|
|
|
|
guess = Math.ceil(highx / highy);
|
|
|
|
do {
|
|
|
|
check = multiplySmall(b, guess);
|
|
|
|
if (compareAbs(check, part) <= 0) break;
|
|
|
|
guess--;
|
|
|
|
} while (guess);
|
|
|
|
result.push(guess);
|
|
|
|
part = subtract(part, check);
|
|
|
|
}
|
|
|
|
result.reverse();
|
|
|
|
return [arrayToSmall(result), arrayToSmall(part)];
|
|
|
|
}
|
|
|
|
|
|
|
|
function divModSmall(value, lambda) {
|
|
|
|
var length = value.length,
|
|
|
|
quotient = createArray(length),
|
|
|
|
base = BASE,
|
|
|
|
i, q, remainder, divisor;
|
|
|
|
remainder = 0;
|
|
|
|
for (i = length - 1; i >= 0; --i) {
|
|
|
|
divisor = remainder * base + value[i];
|
|
|
|
q = truncate(divisor / lambda);
|
|
|
|
remainder = divisor - q * lambda;
|
|
|
|
quotient[i] = q | 0;
|
|
|
|
}
|
|
|
|
return [quotient, remainder | 0];
|
|
|
|
}
|
|
|
|
|
|
|
|
function divModAny(self, v) {
|
|
|
|
var value, n = parseValue(v);
|
|
|
|
if (supportsNativeBigInt) {
|
|
|
|
return [new NativeBigInt(self.value / n.value), new NativeBigInt(self.value % n.value)];
|
|
|
|
}
|
|
|
|
var a = self.value, b = n.value;
|
|
|
|
var quotient;
|
|
|
|
if (b === 0) throw new Error("Cannot divide by zero");
|
|
|
|
if (self.isSmall) {
|
|
|
|
if (n.isSmall) {
|
|
|
|
return [new SmallInteger(truncate(a / b)), new SmallInteger(a % b)];
|
|
|
|
}
|
|
|
|
return [Integer[0], self];
|
|
|
|
}
|
|
|
|
if (n.isSmall) {
|
|
|
|
if (b === 1) return [self, Integer[0]];
|
|
|
|
if (b == -1) return [self.negate(), Integer[0]];
|
|
|
|
var abs = Math.abs(b);
|
|
|
|
if (abs < BASE) {
|
|
|
|
value = divModSmall(a, abs);
|
|
|
|
quotient = arrayToSmall(value[0]);
|
|
|
|
var remainder = value[1];
|
|
|
|
if (self.sign) remainder = -remainder;
|
|
|
|
if (typeof quotient === "number") {
|
|
|
|
if (self.sign !== n.sign) quotient = -quotient;
|
|
|
|
return [new SmallInteger(quotient), new SmallInteger(remainder)];
|
|
|
|
}
|
|
|
|
return [new BigInteger(quotient, self.sign !== n.sign), new SmallInteger(remainder)];
|
|
|
|
}
|
|
|
|
b = smallToArray(abs);
|
|
|
|
}
|
|
|
|
var comparison = compareAbs(a, b);
|
|
|
|
if (comparison === -1) return [Integer[0], self];
|
|
|
|
if (comparison === 0) return [Integer[self.sign === n.sign ? 1 : -1], Integer[0]];
|
|
|
|
|
|
|
|
// divMod1 is faster on smaller input sizes
|
|
|
|
if (a.length + b.length <= 200)
|
|
|
|
value = divMod1(a, b);
|
|
|
|
else value = divMod2(a, b);
|
|
|
|
|
|
|
|
quotient = value[0];
|
|
|
|
var qSign = self.sign !== n.sign,
|
|
|
|
mod = value[1],
|
|
|
|
mSign = self.sign;
|
|
|
|
if (typeof quotient === "number") {
|
|
|
|
if (qSign) quotient = -quotient;
|
|
|
|
quotient = new SmallInteger(quotient);
|
|
|
|
} else quotient = new BigInteger(quotient, qSign);
|
|
|
|
if (typeof mod === "number") {
|
|
|
|
if (mSign) mod = -mod;
|
|
|
|
mod = new SmallInteger(mod);
|
|
|
|
} else mod = new BigInteger(mod, mSign);
|
|
|
|
return [quotient, mod];
|
|
|
|
}
|
|
|
|
|
|
|
|
BigInteger.prototype.divmod = function (v) {
|
|
|
|
var result = divModAny(this, v);
|
|
|
|
return {
|
|
|
|
quotient: result[0],
|
|
|
|
remainder: result[1]
|
|
|
|
};
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.divmod = SmallInteger.prototype.divmod = BigInteger.prototype.divmod;
|
|
|
|
|
|
|
|
|
|
|
|
BigInteger.prototype.divide = function (v) {
|
|
|
|
return divModAny(this, v)[0];
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.over = NativeBigInt.prototype.divide = function (v) {
|
|
|
|
return new NativeBigInt(this.value / parseValue(v).value);
|
|
|
|
};
|
|
|
|
SmallInteger.prototype.over = SmallInteger.prototype.divide = BigInteger.prototype.over = BigInteger.prototype.divide;
|
|
|
|
|
|
|
|
BigInteger.prototype.mod = function (v) {
|
|
|
|
return divModAny(this, v)[1];
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.mod = NativeBigInt.prototype.remainder = function (v) {
|
|
|
|
return new NativeBigInt(this.value % parseValue(v).value);
|
|
|
|
};
|
|
|
|
SmallInteger.prototype.remainder = SmallInteger.prototype.mod = BigInteger.prototype.remainder = BigInteger.prototype.mod;
|
|
|
|
|
|
|
|
BigInteger.prototype.pow = function (v) {
|
|
|
|
var n = parseValue(v),
|
|
|
|
a = this.value,
|
|
|
|
b = n.value,
|
|
|
|
value, x, y;
|
|
|
|
if (b === 0) return Integer[1];
|
|
|
|
if (a === 0) return Integer[0];
|
|
|
|
if (a === 1) return Integer[1];
|
|
|
|
if (a === -1) return n.isEven() ? Integer[1] : Integer[-1];
|
|
|
|
if (n.sign) {
|
|
|
|
return Integer[0];
|
|
|
|
}
|
|
|
|
if (!n.isSmall) throw new Error("The exponent " + n.toString() + " is too large.");
|
|
|
|
if (this.isSmall) {
|
|
|
|
if (isPrecise(value = Math.pow(a, b)))
|
|
|
|
return new SmallInteger(truncate(value));
|
|
|
|
}
|
|
|
|
x = this;
|
|
|
|
y = Integer[1];
|
|
|
|
while (true) {
|
|
|
|
if (b & 1 === 1) {
|
|
|
|
y = y.times(x);
|
|
|
|
--b;
|
|
|
|
}
|
|
|
|
if (b === 0) break;
|
|
|
|
b /= 2;
|
|
|
|
x = x.square();
|
|
|
|
}
|
|
|
|
return y;
|
|
|
|
};
|
|
|
|
SmallInteger.prototype.pow = BigInteger.prototype.pow;
|
|
|
|
|
|
|
|
NativeBigInt.prototype.pow = function (v) {
|
|
|
|
var n = parseValue(v);
|
|
|
|
var a = this.value, b = n.value;
|
|
|
|
var _0 = BigInt(0), _1 = BigInt(1), _2 = BigInt(2);
|
|
|
|
if (b === _0) return Integer[1];
|
|
|
|
if (a === _0) return Integer[0];
|
|
|
|
if (a === _1) return Integer[1];
|
|
|
|
if (a === BigInt(-1)) return n.isEven() ? Integer[1] : Integer[-1];
|
|
|
|
if (n.isNegative()) return new NativeBigInt(_0);
|
|
|
|
var x = this;
|
|
|
|
var y = Integer[1];
|
|
|
|
while (true) {
|
|
|
|
if ((b & _1) === _1) {
|
|
|
|
y = y.times(x);
|
|
|
|
--b;
|
|
|
|
}
|
|
|
|
if (b === _0) break;
|
|
|
|
b /= _2;
|
|
|
|
x = x.square();
|
|
|
|
}
|
|
|
|
return y;
|
|
|
|
};
|
|
|
|
|
|
|
|
BigInteger.prototype.modPow = function (exp, mod) {
|
|
|
|
exp = parseValue(exp);
|
|
|
|
mod = parseValue(mod);
|
|
|
|
if (mod.isZero()) throw new Error("Cannot take modPow with modulus 0");
|
|
|
|
var r = Integer[1],
|
|
|
|
base = this.mod(mod);
|
|
|
|
if (exp.isNegative()) {
|
|
|
|
exp = exp.multiply(Integer[-1]);
|
|
|
|
base = base.modInv(mod);
|
|
|
|
}
|
|
|
|
while (exp.isPositive()) {
|
|
|
|
if (base.isZero()) return Integer[0];
|
|
|
|
if (exp.isOdd()) r = r.multiply(base).mod(mod);
|
|
|
|
exp = exp.divide(2);
|
|
|
|
base = base.square().mod(mod);
|
|
|
|
}
|
|
|
|
return r;
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.modPow = SmallInteger.prototype.modPow = BigInteger.prototype.modPow;
|
|
|
|
|
|
|
|
function compareAbs(a, b) {
|
|
|
|
if (a.length !== b.length) {
|
|
|
|
return a.length > b.length ? 1 : -1;
|
|
|
|
}
|
|
|
|
for (var i = a.length - 1; i >= 0; i--) {
|
|
|
|
if (a[i] !== b[i]) return a[i] > b[i] ? 1 : -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
BigInteger.prototype.compareAbs = function (v) {
|
|
|
|
var n = parseValue(v),
|
|
|
|
a = this.value,
|
|
|
|
b = n.value;
|
|
|
|
if (n.isSmall) return 1;
|
|
|
|
return compareAbs(a, b);
|
|
|
|
};
|
|
|
|
SmallInteger.prototype.compareAbs = function (v) {
|
|
|
|
var n = parseValue(v),
|
|
|
|
a = Math.abs(this.value),
|
|
|
|
b = n.value;
|
|
|
|
if (n.isSmall) {
|
|
|
|
b = Math.abs(b);
|
|
|
|
return a === b ? 0 : a > b ? 1 : -1;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.compareAbs = function (v) {
|
|
|
|
var a = this.value;
|
|
|
|
var b = parseValue(v).value;
|
|
|
|
a = a >= 0 ? a : -a;
|
|
|
|
b = b >= 0 ? b : -b;
|
|
|
|
return a === b ? 0 : a > b ? 1 : -1;
|
|
|
|
};
|
|
|
|
|
|
|
|
BigInteger.prototype.compare = function (v) {
|
|
|
|
// See discussion about comparison with Infinity:
|
|
|
|
// https://github.com/peterolson/BigInteger.js/issues/61
|
|
|
|
if (v === Infinity) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (v === -Infinity) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
var n = parseValue(v),
|
|
|
|
a = this.value,
|
|
|
|
b = n.value;
|
|
|
|
if (this.sign !== n.sign) {
|
|
|
|
return n.sign ? 1 : -1;
|
|
|
|
}
|
|
|
|
if (n.isSmall) {
|
|
|
|
return this.sign ? -1 : 1;
|
|
|
|
}
|
|
|
|
return compareAbs(a, b) * (this.sign ? -1 : 1);
|
|
|
|
};
|
|
|
|
BigInteger.prototype.compareTo = BigInteger.prototype.compare;
|
|
|
|
|
|
|
|
SmallInteger.prototype.compare = function (v) {
|
|
|
|
if (v === Infinity) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (v === -Infinity) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
var n = parseValue(v),
|
|
|
|
a = this.value,
|
|
|
|
b = n.value;
|
|
|
|
if (n.isSmall) {
|
|
|
|
return a == b ? 0 : a > b ? 1 : -1;
|
|
|
|
}
|
|
|
|
if (a < 0 !== n.sign) {
|
|
|
|
return a < 0 ? -1 : 1;
|
|
|
|
}
|
|
|
|
return a < 0 ? 1 : -1;
|
|
|
|
};
|
|
|
|
SmallInteger.prototype.compareTo = SmallInteger.prototype.compare;
|
|
|
|
|
|
|
|
NativeBigInt.prototype.compare = function (v) {
|
|
|
|
if (v === Infinity) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (v === -Infinity) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
var a = this.value;
|
|
|
|
var b = parseValue(v).value;
|
|
|
|
return a === b ? 0 : a > b ? 1 : -1;
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.compareTo = NativeBigInt.prototype.compare;
|
|
|
|
|
|
|
|
BigInteger.prototype.equals = function (v) {
|
|
|
|
return this.compare(v) === 0;
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.eq = NativeBigInt.prototype.equals = SmallInteger.prototype.eq = SmallInteger.prototype.equals = BigInteger.prototype.eq = BigInteger.prototype.equals;
|
|
|
|
|
|
|
|
BigInteger.prototype.notEquals = function (v) {
|
|
|
|
return this.compare(v) !== 0;
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.neq = NativeBigInt.prototype.notEquals = SmallInteger.prototype.neq = SmallInteger.prototype.notEquals = BigInteger.prototype.neq = BigInteger.prototype.notEquals;
|
|
|
|
|
|
|
|
BigInteger.prototype.greater = function (v) {
|
|
|
|
return this.compare(v) > 0;
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.gt = NativeBigInt.prototype.greater = SmallInteger.prototype.gt = SmallInteger.prototype.greater = BigInteger.prototype.gt = BigInteger.prototype.greater;
|
|
|
|
|
|
|
|
BigInteger.prototype.lesser = function (v) {
|
|
|
|
return this.compare(v) < 0;
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.lt = NativeBigInt.prototype.lesser = SmallInteger.prototype.lt = SmallInteger.prototype.lesser = BigInteger.prototype.lt = BigInteger.prototype.lesser;
|
|
|
|
|
|
|
|
BigInteger.prototype.greaterOrEquals = function (v) {
|
|
|
|
return this.compare(v) >= 0;
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.geq = NativeBigInt.prototype.greaterOrEquals = SmallInteger.prototype.geq = SmallInteger.prototype.greaterOrEquals = BigInteger.prototype.geq = BigInteger.prototype.greaterOrEquals;
|
|
|
|
|
|
|
|
BigInteger.prototype.lesserOrEquals = function (v) {
|
|
|
|
return this.compare(v) <= 0;
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.leq = NativeBigInt.prototype.lesserOrEquals = SmallInteger.prototype.leq = SmallInteger.prototype.lesserOrEquals = BigInteger.prototype.leq = BigInteger.prototype.lesserOrEquals;
|
|
|
|
|
|
|
|
BigInteger.prototype.isEven = function () {
|
|
|
|
return (this.value[0] & 1) === 0;
|
|
|
|
};
|
|
|
|
SmallInteger.prototype.isEven = function () {
|
|
|
|
return (this.value & 1) === 0;
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.isEven = function () {
|
|
|
|
return (this.value & BigInt(1)) === BigInt(0);
|
|
|
|
};
|
|
|
|
|
|
|
|
BigInteger.prototype.isOdd = function () {
|
|
|
|
return (this.value[0] & 1) === 1;
|
|
|
|
};
|
|
|
|
SmallInteger.prototype.isOdd = function () {
|
|
|
|
return (this.value & 1) === 1;
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.isOdd = function () {
|
|
|
|
return (this.value & BigInt(1)) === BigInt(1);
|
|
|
|
};
|
|
|
|
|
|
|
|
BigInteger.prototype.isPositive = function () {
|
|
|
|
return !this.sign;
|
|
|
|
};
|
|
|
|
SmallInteger.prototype.isPositive = function () {
|
|
|
|
return this.value > 0;
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.isPositive = SmallInteger.prototype.isPositive;
|
|
|
|
|
|
|
|
BigInteger.prototype.isNegative = function () {
|
|
|
|
return this.sign;
|
|
|
|
};
|
|
|
|
SmallInteger.prototype.isNegative = function () {
|
|
|
|
return this.value < 0;
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.isNegative = SmallInteger.prototype.isNegative;
|
|
|
|
|
|
|
|
BigInteger.prototype.isUnit = function () {
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
SmallInteger.prototype.isUnit = function () {
|
|
|
|
return Math.abs(this.value) === 1;
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.isUnit = function () {
|
|
|
|
return this.abs().value === BigInt(1);
|
|
|
|
};
|
|
|
|
|
|
|
|
BigInteger.prototype.isZero = function () {
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
SmallInteger.prototype.isZero = function () {
|
|
|
|
return this.value === 0;
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.isZero = function () {
|
|
|
|
return this.value === BigInt(0);
|
|
|
|
};
|
|
|
|
|
|
|
|
BigInteger.prototype.isDivisibleBy = function (v) {
|
|
|
|
var n = parseValue(v);
|
|
|
|
if (n.isZero()) return false;
|
|
|
|
if (n.isUnit()) return true;
|
|
|
|
if (n.compareAbs(2) === 0) return this.isEven();
|
|
|
|
return this.mod(n).isZero();
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.isDivisibleBy = SmallInteger.prototype.isDivisibleBy = BigInteger.prototype.isDivisibleBy;
|
|
|
|
|
|
|
|
function isBasicPrime(v) {
|
|
|
|
var n = v.abs();
|
|
|
|
if (n.isUnit()) return false;
|
|
|
|
if (n.equals(2) || n.equals(3) || n.equals(5)) return true;
|
|
|
|
if (n.isEven() || n.isDivisibleBy(3) || n.isDivisibleBy(5)) return false;
|
|
|
|
if (n.lesser(49)) return true;
|
|
|
|
// we don't know if it's prime: let the other functions figure it out
|
|
|
|
}
|
|
|
|
|
|
|
|
function millerRabinTest(n, a) {
|
|
|
|
var nPrev = n.prev(),
|
|
|
|
b = nPrev,
|
|
|
|
r = 0,
|
|
|
|
d, i, x;
|
|
|
|
while (b.isEven()) b = b.divide(2), r++;
|
|
|
|
next: for (i = 0; i < a.length; i++) {
|
|
|
|
if (n.lesser(a[i])) continue;
|
|
|
|
x = bigInt(a[i]).modPow(b, n);
|
|
|
|
if (x.isUnit() || x.equals(nPrev)) continue;
|
|
|
|
for (d = r - 1; d != 0; d--) {
|
|
|
|
x = x.square().mod(n);
|
|
|
|
if (x.isUnit()) return false;
|
|
|
|
if (x.equals(nPrev)) continue next;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set "strict" to true to force GRH-supported lower bound of 2*log(N)^2
|
|
|
|
BigInteger.prototype.isPrime = function (strict) {
|
|
|
|
var isPrime = isBasicPrime(this);
|
|
|
|
if (isPrime !== undefined$1) return isPrime;
|
|
|
|
var n = this.abs();
|
|
|
|
var bits = n.bitLength();
|
|
|
|
if (bits <= 64)
|
|
|
|
return millerRabinTest(n, [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37]);
|
|
|
|
var logN = Math.log(2) * bits.toJSNumber();
|
|
|
|
var t = Math.ceil((strict === true) ? (2 * Math.pow(logN, 2)) : logN);
|
|
|
|
for (var a = [], i = 0; i < t; i++) {
|
|
|
|
a.push(bigInt(i + 2));
|
|
|
|
}
|
|
|
|
return millerRabinTest(n, a);
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.isPrime = SmallInteger.prototype.isPrime = BigInteger.prototype.isPrime;
|
|
|
|
|
|
|
|
BigInteger.prototype.isProbablePrime = function (iterations, rng) {
|
|
|
|
var isPrime = isBasicPrime(this);
|
|
|
|
if (isPrime !== undefined$1) return isPrime;
|
|
|
|
var n = this.abs();
|
|
|
|
var t = iterations === undefined$1 ? 5 : iterations;
|
|
|
|
for (var a = [], i = 0; i < t; i++) {
|
|
|
|
a.push(bigInt.randBetween(2, n.minus(2), rng));
|
|
|
|
}
|
|
|
|
return millerRabinTest(n, a);
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.isProbablePrime = SmallInteger.prototype.isProbablePrime = BigInteger.prototype.isProbablePrime;
|
|
|
|
|
|
|
|
BigInteger.prototype.modInv = function (n) {
|
|
|
|
var t = bigInt.zero, newT = bigInt.one, r = parseValue(n), newR = this.abs(), q, lastT, lastR;
|
|
|
|
while (!newR.isZero()) {
|
|
|
|
q = r.divide(newR);
|
|
|
|
lastT = t;
|
|
|
|
lastR = r;
|
|
|
|
t = newT;
|
|
|
|
r = newR;
|
|
|
|
newT = lastT.subtract(q.multiply(newT));
|
|
|
|
newR = lastR.subtract(q.multiply(newR));
|
|
|
|
}
|
|
|
|
if (!r.isUnit()) throw new Error(this.toString() + " and " + n.toString() + " are not co-prime");
|
|
|
|
if (t.compare(0) === -1) {
|
|
|
|
t = t.add(n);
|
|
|
|
}
|
|
|
|
if (this.isNegative()) {
|
|
|
|
return t.negate();
|
|
|
|
}
|
|
|
|
return t;
|
|
|
|
};
|
|
|
|
|
|
|
|
NativeBigInt.prototype.modInv = SmallInteger.prototype.modInv = BigInteger.prototype.modInv;
|
|
|
|
|
|
|
|
BigInteger.prototype.next = function () {
|
|
|
|
var value = this.value;
|
|
|
|
if (this.sign) {
|
|
|
|
return subtractSmall(value, 1, this.sign);
|
|
|
|
}
|
|
|
|
return new BigInteger(addSmall(value, 1), this.sign);
|
|
|
|
};
|
|
|
|
SmallInteger.prototype.next = function () {
|
|
|
|
var value = this.value;
|
|
|
|
if (value + 1 < MAX_INT) return new SmallInteger(value + 1);
|
|
|
|
return new BigInteger(MAX_INT_ARR, false);
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.next = function () {
|
|
|
|
return new NativeBigInt(this.value + BigInt(1));
|
|
|
|
};
|
|
|
|
|
|
|
|
BigInteger.prototype.prev = function () {
|
|
|
|
var value = this.value;
|
|
|
|
if (this.sign) {
|
|
|
|
return new BigInteger(addSmall(value, 1), true);
|
|
|
|
}
|
|
|
|
return subtractSmall(value, 1, this.sign);
|
|
|
|
};
|
|
|
|
SmallInteger.prototype.prev = function () {
|
|
|
|
var value = this.value;
|
|
|
|
if (value - 1 > -MAX_INT) return new SmallInteger(value - 1);
|
|
|
|
return new BigInteger(MAX_INT_ARR, true);
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.prev = function () {
|
|
|
|
return new NativeBigInt(this.value - BigInt(1));
|
|
|
|
};
|
|
|
|
|
|
|
|
var powersOfTwo = [1];
|
|
|
|
while (2 * powersOfTwo[powersOfTwo.length - 1] <= BASE) powersOfTwo.push(2 * powersOfTwo[powersOfTwo.length - 1]);
|
|
|
|
var powers2Length = powersOfTwo.length, highestPower2 = powersOfTwo[powers2Length - 1];
|
|
|
|
|
|
|
|
function shift_isSmall(n) {
|
|
|
|
return Math.abs(n) <= BASE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BigInteger.prototype.shiftLeft = function (v) {
|
|
|
|
var n = parseValue(v).toJSNumber();
|
|
|
|
if (!shift_isSmall(n)) {
|
|
|
|
throw new Error(String(n) + " is too large for shifting.");
|
|
|
|
}
|
|
|
|
if (n < 0) return this.shiftRight(-n);
|
|
|
|
var result = this;
|
|
|
|
if (result.isZero()) return result;
|
|
|
|
while (n >= powers2Length) {
|
|
|
|
result = result.multiply(highestPower2);
|
|
|
|
n -= powers2Length - 1;
|
|
|
|
}
|
|
|
|
return result.multiply(powersOfTwo[n]);
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.shiftLeft = SmallInteger.prototype.shiftLeft = BigInteger.prototype.shiftLeft;
|
|
|
|
|
|
|
|
BigInteger.prototype.shiftRight = function (v) {
|
|
|
|
var remQuo;
|
|
|
|
var n = parseValue(v).toJSNumber();
|
|
|
|
if (!shift_isSmall(n)) {
|
|
|
|
throw new Error(String(n) + " is too large for shifting.");
|
|
|
|
}
|
|
|
|
if (n < 0) return this.shiftLeft(-n);
|
|
|
|
var result = this;
|
|
|
|
while (n >= powers2Length) {
|
|
|
|
if (result.isZero() || (result.isNegative() && result.isUnit())) return result;
|
|
|
|
remQuo = divModAny(result, highestPower2);
|
|
|
|
result = remQuo[1].isNegative() ? remQuo[0].prev() : remQuo[0];
|
|
|
|
n -= powers2Length - 1;
|
|
|
|
}
|
|
|
|
remQuo = divModAny(result, powersOfTwo[n]);
|
|
|
|
return remQuo[1].isNegative() ? remQuo[0].prev() : remQuo[0];
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.shiftRight = SmallInteger.prototype.shiftRight = BigInteger.prototype.shiftRight;
|
|
|
|
|
|
|
|
function bitwise(x, y, fn) {
|
|
|
|
y = parseValue(y);
|
|
|
|
var xSign = x.isNegative(), ySign = y.isNegative();
|
|
|
|
var xRem = xSign ? x.not() : x,
|
|
|
|
yRem = ySign ? y.not() : y;
|
|
|
|
var xDigit = 0, yDigit = 0;
|
|
|
|
var xDivMod = null, yDivMod = null;
|
|
|
|
var result = [];
|
|
|
|
while (!xRem.isZero() || !yRem.isZero()) {
|
|
|
|
xDivMod = divModAny(xRem, highestPower2);
|
|
|
|
xDigit = xDivMod[1].toJSNumber();
|
|
|
|
if (xSign) {
|
|
|
|
xDigit = highestPower2 - 1 - xDigit; // two's complement for negative numbers
|
|
|
|
}
|
|
|
|
|
|
|
|
yDivMod = divModAny(yRem, highestPower2);
|
|
|
|
yDigit = yDivMod[1].toJSNumber();
|
|
|
|
if (ySign) {
|
|
|
|
yDigit = highestPower2 - 1 - yDigit; // two's complement for negative numbers
|
|
|
|
}
|
|
|
|
|
|
|
|
xRem = xDivMod[0];
|
|
|
|
yRem = yDivMod[0];
|
|
|
|
result.push(fn(xDigit, yDigit));
|
|
|
|
}
|
|
|
|
var sum = fn(xSign ? 1 : 0, ySign ? 1 : 0) !== 0 ? bigInt(-1) : bigInt(0);
|
|
|
|
for (var i = result.length - 1; i >= 0; i -= 1) {
|
|
|
|
sum = sum.multiply(highestPower2).add(bigInt(result[i]));
|
|
|
|
}
|
|
|
|
return sum;
|
|
|
|
}
|
|
|
|
|
|
|
|
BigInteger.prototype.not = function () {
|
|
|
|
return this.negate().prev();
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.not = SmallInteger.prototype.not = BigInteger.prototype.not;
|
|
|
|
|
|
|
|
BigInteger.prototype.and = function (n) {
|
|
|
|
return bitwise(this, n, function (a, b) { return a & b; });
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.and = SmallInteger.prototype.and = BigInteger.prototype.and;
|
|
|
|
|
|
|
|
BigInteger.prototype.or = function (n) {
|
|
|
|
return bitwise(this, n, function (a, b) { return a | b; });
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.or = SmallInteger.prototype.or = BigInteger.prototype.or;
|
|
|
|
|
|
|
|
BigInteger.prototype.xor = function (n) {
|
|
|
|
return bitwise(this, n, function (a, b) { return a ^ b; });
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.xor = SmallInteger.prototype.xor = BigInteger.prototype.xor;
|
|
|
|
|
|
|
|
var LOBMASK_I = 1 << 30, LOBMASK_BI = (BASE & -BASE) * (BASE & -BASE) | LOBMASK_I;
|
|
|
|
function roughLOB(n) { // get lowestOneBit (rough)
|
|
|
|
// SmallInteger: return Min(lowestOneBit(n), 1 << 30)
|
|
|
|
// BigInteger: return Min(lowestOneBit(n), 1 << 14) [BASE=1e7]
|
|
|
|
var v = n.value,
|
|
|
|
x = typeof v === "number" ? v | LOBMASK_I :
|
|
|
|
typeof v === "bigint" ? v | BigInt(LOBMASK_I) :
|
|
|
|
v[0] + v[1] * BASE | LOBMASK_BI;
|
|
|
|
return x & -x;
|
|
|
|
}
|
|
|
|
|
|
|
|
function integerLogarithm(value, base) {
|
|
|
|
if (base.compareTo(value) <= 0) {
|
|
|
|
var tmp = integerLogarithm(value, base.square(base));
|
|
|
|
var p = tmp.p;
|
|
|
|
var e = tmp.e;
|
|
|
|
var t = p.multiply(base);
|
|
|
|
return t.compareTo(value) <= 0 ? { p: t, e: e * 2 + 1 } : { p: p, e: e * 2 };
|
|
|
|
}
|
|
|
|
return { p: bigInt(1), e: 0 };
|
|
|
|
}
|
|
|
|
|
|
|
|
BigInteger.prototype.bitLength = function () {
|
|
|
|
var n = this;
|
|
|
|
if (n.compareTo(bigInt(0)) < 0) {
|
|
|
|
n = n.negate().subtract(bigInt(1));
|
|
|
|
}
|
|
|
|
if (n.compareTo(bigInt(0)) === 0) {
|
|
|
|
return bigInt(0);
|
|
|
|
}
|
|
|
|
return bigInt(integerLogarithm(n, bigInt(2)).e).add(bigInt(1));
|
|
|
|
};
|
|
|
|
NativeBigInt.prototype.bitLength = SmallInteger.prototype.bitLength = BigInteger.prototype.bitLength;
|
|
|
|
|
|
|
|
function max(a, b) {
|
|
|
|
a = parseValue(a);
|
|
|
|
b = parseValue(b);
|
|
|
|
return a.greater(b) ? a : b;
|
|
|
|
}
|
|
|
|
function min(a, b) {
|
|
|
|
a = parseValue(a);
|
|
|
|
b = parseValue(b);
|
|
|
|
return a.lesser(b) ? a : b;
|
|
|
|
}
|
|
|
|
function gcd(a, b) {
|
|
|
|
a = parseValue(a).abs();
|
|
|
|
b = parseValue(b).abs();
|
|
|
|
if (a.equals(b)) return a;
|
|
|
|
if (a.isZero()) return b;
|
|
|
|
if (b.isZero()) return a;
|
|
|
|
var c = Integer[1], d, t;
|
|
|
|
while (a.isEven() && b.isEven()) {
|
|
|
|
d = min(roughLOB(a), roughLOB(b));
|
|
|
|
a = a.divide(d);
|
|
|
|
b = b.divide(d);
|
|
|
|
c = c.multiply(d);
|
|
|
|
}
|
|
|
|
while (a.isEven()) {
|
|
|
|
a = a.divide(roughLOB(a));
|
|
|
|
}
|
|
|
|
do {
|
|
|
|
while (b.isEven()) {
|
|
|
|
b = b.divide(roughLOB(b));
|
|
|
|
}
|
|
|
|
if (a.greater(b)) {
|
|
|
|
t = b; b = a; a = t;
|
|
|
|
}
|
|
|
|
b = b.subtract(a);
|
|
|
|
} while (!b.isZero());
|
|
|
|
return c.isUnit() ? a : a.multiply(c);
|
|
|
|
}
|
|
|
|
function lcm(a, b) {
|
|
|
|
a = parseValue(a).abs();
|
|
|
|
b = parseValue(b).abs();
|
|
|
|
return a.divide(gcd(a, b)).multiply(b);
|
|
|
|
}
|
|
|
|
function randBetween(a, b, rng) {
|
|
|
|
a = parseValue(a);
|
|
|
|
b = parseValue(b);
|
|
|
|
var usedRNG = rng || Math.random;
|
|
|
|
var low = min(a, b), high = max(a, b);
|
|
|
|
var range = high.subtract(low).add(1);
|
|
|
|
if (range.isSmall) return low.add(Math.floor(usedRNG() * range));
|
|
|
|
var digits = toBase(range, BASE).value;
|
|
|
|
var result = [], restricted = true;
|
|
|
|
for (var i = 0; i < digits.length; i++) {
|
|
|
|
var top = restricted ? digits[i] : BASE;
|
|
|
|
var digit = truncate(usedRNG() * top);
|
|
|
|
result.push(digit);
|
|
|
|
if (digit < top) restricted = false;
|
|
|
|
}
|
|
|
|
return low.add(Integer.fromArray(result, BASE, false));
|
|
|
|
}
|
|
|
|
|
|
|
|
var parseBase = function (text, base, alphabet, caseSensitive) {
|
|
|
|
alphabet = alphabet || DEFAULT_ALPHABET;
|
|
|
|
text = String(text);
|
|
|
|
if (!caseSensitive) {
|
|
|
|
text = text.toLowerCase();
|
|
|
|
alphabet = alphabet.toLowerCase();
|
|
|
|
}
|
|
|
|
var length = text.length;
|
|
|
|
var i;
|
|
|
|
var absBase = Math.abs(base);
|
|
|
|
var alphabetValues = {};
|
|
|
|
for (i = 0; i < alphabet.length; i++) {
|
|
|
|
alphabetValues[alphabet[i]] = i;
|
|
|
|
}
|
|
|
|
for (i = 0; i < length; i++) {
|
|
|
|
var c = text[i];
|
|
|
|
if (c === "-") continue;
|
|
|
|
if (c in alphabetValues) {
|
|
|
|
if (alphabetValues[c] >= absBase) {
|
|
|
|
if (c === "1" && absBase === 1) continue;
|
|
|
|
throw new Error(c + " is not a valid digit in base " + base + ".");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
base = parseValue(base);
|
|
|
|
var digits = [];
|
|
|
|
var isNegative = text[0] === "-";
|
|
|
|
for (i = isNegative ? 1 : 0; i < text.length; i++) {
|
|
|
|
var c = text[i];
|
|
|
|
if (c in alphabetValues) digits.push(parseValue(alphabetValues[c]));
|
|
|
|
else if (c === "<") {
|
|
|
|
var start = i;
|
|
|
|
do { i++; } while (text[i] !== ">" && i < text.length);
|
|
|
|
digits.push(parseValue(text.slice(start + 1, i)));
|
|
|
|
}
|
|
|
|
else throw new Error(c + " is not a valid character");
|
|
|
|
}
|
|
|
|
return parseBaseFromArray(digits, base, isNegative);
|
|
|
|
};
|
|
|
|
|
|
|
|
function parseBaseFromArray(digits, base, isNegative) {
|
|
|
|
var val = Integer[0], pow = Integer[1], i;
|
|
|
|
for (i = digits.length - 1; i >= 0; i--) {
|
|
|
|
val = val.add(digits[i].times(pow));
|
|
|
|
pow = pow.times(base);
|
|
|
|
}
|
|
|
|
return isNegative ? val.negate() : val;
|
|
|
|
}
|
|
|
|
|
|
|
|
function stringify(digit, alphabet) {
|
|
|
|
alphabet = alphabet || DEFAULT_ALPHABET;
|
|
|
|
if (digit < alphabet.length) {
|
|
|
|
return alphabet[digit];
|
|
|
|
}
|
|
|
|
return "<" + digit + ">";
|
|
|
|
}
|
|
|
|
|
|
|
|
function toBase(n, base) {
|
|
|
|
base = bigInt(base);
|
|
|
|
if (base.isZero()) {
|
|
|
|
if (n.isZero()) return { value: [0], isNegative: false };
|
|
|
|
throw new Error("Cannot convert nonzero numbers to base 0.");
|
|
|
|
}
|
|
|
|
if (base.equals(-1)) {
|
|
|
|
if (n.isZero()) return { value: [0], isNegative: false };
|
|
|
|
if (n.isNegative())
|
|
|
|
return {
|
|
|
|
value: [].concat.apply([], Array.apply(null, Array(-n.toJSNumber()))
|
|
|
|
.map(Array.prototype.valueOf, [1, 0])
|
|
|
|
),
|
|
|
|
isNegative: false
|
|
|
|
};
|
|
|
|
|
|
|
|
var arr = Array.apply(null, Array(n.toJSNumber() - 1))
|
|
|
|
.map(Array.prototype.valueOf, [0, 1]);
|
|
|
|
arr.unshift([1]);
|
|
|
|
return {
|
|
|
|
value: [].concat.apply([], arr),
|
|
|
|
isNegative: false
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
var neg = false;
|
|
|
|
if (n.isNegative() && base.isPositive()) {
|
|
|
|
neg = true;
|
|
|
|
n = n.abs();
|
|
|
|
}
|
|
|
|
if (base.isUnit()) {
|
|
|
|
if (n.isZero()) return { value: [0], isNegative: false };
|
|
|
|
|
|
|
|
return {
|
|
|
|
value: Array.apply(null, Array(n.toJSNumber()))
|
|
|
|
.map(Number.prototype.valueOf, 1),
|
|
|
|
isNegative: neg
|
|
|
|
};
|
|
|
|
}
|
|
|
|
var out = [];
|
|
|
|
var left = n, divmod;
|
|
|
|
while (left.isNegative() || left.compareAbs(base) >= 0) {
|
|
|
|
divmod = left.divmod(base);
|
|
|
|
left = divmod.quotient;
|
|
|
|
var digit = divmod.remainder;
|
|
|
|
if (digit.isNegative()) {
|
|
|
|
digit = base.minus(digit).abs();
|
|
|
|
left = left.next();
|
|
|
|
}
|
|
|
|
out.push(digit.toJSNumber());
|
|
|
|
}
|
|
|
|
out.push(left.toJSNumber());
|
|
|
|
return { value: out.reverse(), isNegative: neg };
|
|
|
|
}
|
|
|
|
|
|
|
|
function toBaseString(n, base, alphabet) {
|
|
|
|
var arr = toBase(n, base);
|
|
|
|
return (arr.isNegative ? "-" : "") + arr.value.map(function (x) {
|
|
|
|
return stringify(x, alphabet);
|
|
|
|
}).join('');
|
|
|
|
}
|
|
|
|
|
|
|
|
BigInteger.prototype.toArray = function (radix) {
|
|
|
|
return toBase(this, radix);
|
|
|
|
};
|
|
|
|
|
|
|
|
SmallInteger.prototype.toArray = function (radix) {
|
|
|
|
return toBase(this, radix);
|
|
|
|
};
|
|
|
|
|
|
|
|
NativeBigInt.prototype.toArray = function (radix) {
|
|
|
|
return toBase(this, radix);
|
|
|
|
};
|
|
|
|
|
|
|
|
BigInteger.prototype.toString = function (radix, alphabet) {
|
|
|
|
if (radix === undefined$1) radix = 10;
|
|
|
|
if (radix !== 10) return toBaseString(this, radix, alphabet);
|
|
|
|
var v = this.value, l = v.length, str = String(v[--l]), zeros = "0000000", digit;
|
|
|
|
while (--l >= 0) {
|
|
|
|
digit = String(v[l]);
|
|
|
|
str += zeros.slice(digit.length) + digit;
|
|
|
|
}
|
|
|
|
var sign = this.sign ? "-" : "";
|
|
|
|
return sign + str;
|
|
|
|
};
|
|
|
|
|
|
|
|
SmallInteger.prototype.toString = function (radix, alphabet) {
|
|
|
|
if (radix === undefined$1) radix = 10;
|
|
|
|
if (radix != 10) return toBaseString(this, radix, alphabet);
|
|
|
|
return String(this.value);
|
|
|
|
};
|
|
|
|
|
|
|
|
NativeBigInt.prototype.toString = SmallInteger.prototype.toString;
|
|
|
|
|
|
|
|
NativeBigInt.prototype.toJSON = BigInteger.prototype.toJSON = SmallInteger.prototype.toJSON = function () { return this.toString(); };
|
|
|
|
|
|
|
|
BigInteger.prototype.valueOf = function () {
|
|
|
|
return parseInt(this.toString(), 10);
|
|
|
|
};
|
|
|
|
BigInteger.prototype.toJSNumber = BigInteger.prototype.valueOf;
|
|
|
|
|
|
|
|
SmallInteger.prototype.valueOf = function () {
|
|
|
|
return this.value;
|
|
|
|
};
|
|
|
|
SmallInteger.prototype.toJSNumber = SmallInteger.prototype.valueOf;
|
|
|
|
NativeBigInt.prototype.valueOf = NativeBigInt.prototype.toJSNumber = function () {
|
|
|
|
return parseInt(this.toString(), 10);
|
|
|
|
};
|
|
|
|
|
|
|
|
function parseStringValue(v) {
|
|
|
|
if (isPrecise(+v)) {
|
|
|
|
var x = +v;
|
|
|
|
if (x === truncate(x))
|
|
|
|
return supportsNativeBigInt ? new NativeBigInt(BigInt(x)) : new SmallInteger(x);
|
|
|
|
throw new Error("Invalid integer: " + v);
|
|
|
|
}
|
|
|
|
var sign = v[0] === "-";
|
|
|
|
if (sign) v = v.slice(1);
|
|
|
|
var split = v.split(/e/i);
|
|
|
|
if (split.length > 2) throw new Error("Invalid integer: " + split.join("e"));
|
|
|
|
if (split.length === 2) {
|
|
|
|
var exp = split[1];
|
|
|
|
if (exp[0] === "+") exp = exp.slice(1);
|
|
|
|
exp = +exp;
|
|
|
|
if (exp !== truncate(exp) || !isPrecise(exp)) throw new Error("Invalid integer: " + exp + " is not a valid exponent.");
|
|
|
|
var text = split[0];
|
|
|
|
var decimalPlace = text.indexOf(".");
|
|
|
|
if (decimalPlace >= 0) {
|
|
|
|
exp -= text.length - decimalPlace - 1;
|
|
|
|
text = text.slice(0, decimalPlace) + text.slice(decimalPlace + 1);
|
|
|
|
}
|
|
|
|
if (exp < 0) throw new Error("Cannot include negative exponent part for integers");
|
|
|
|
text += (new Array(exp + 1)).join("0");
|
|
|
|
v = text;
|
|
|
|
}
|
|
|
|
var isValid = /^([0-9][0-9]*)$/.test(v);
|
|
|
|
if (!isValid) throw new Error("Invalid integer: " + v);
|
|
|
|
if (supportsNativeBigInt) {
|
|
|
|
return new NativeBigInt(BigInt(sign ? "-" + v : v));
|
|
|
|
}
|
|
|
|
var r = [], max = v.length, l = LOG_BASE, min = max - l;
|
|
|
|
while (max > 0) {
|
|
|
|
r.push(+v.slice(min, max));
|
|
|
|
min -= l;
|
|
|
|
if (min < 0) min = 0;
|
|
|
|
max -= l;
|
|
|
|
}
|
|
|
|
trim(r);
|
|
|
|
return new BigInteger(r, sign);
|
|
|
|
}
|
|
|
|
|
|
|
|
function parseNumberValue(v) {
|
|
|
|
if (supportsNativeBigInt) {
|
|
|
|
return new NativeBigInt(BigInt(v));
|
|
|
|
}
|
|
|
|
if (isPrecise(v)) {
|
|
|
|
if (v !== truncate(v)) throw new Error(v + " is not an integer.");
|
|
|
|
return new SmallInteger(v);
|
|
|
|
}
|
|
|
|
return parseStringValue(v.toString());
|
|
|
|
}
|
|
|
|
|
|
|
|
function parseValue(v) {
|
|
|
|
if (typeof v === "number") {
|
|
|
|
return parseNumberValue(v);
|
|
|
|
}
|
|
|
|
if (typeof v === "string") {
|
|
|
|
return parseStringValue(v);
|
|
|
|
}
|
|
|
|
if (typeof v === "bigint") {
|
|
|
|
return new NativeBigInt(v);
|
|
|
|
}
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
// Pre-define numbers in range [-999,999]
|
|
|
|
for (var i = 0; i < 1000; i++) {
|
|
|
|
Integer[i] = parseValue(i);
|
|
|
|
if (i > 0) Integer[-i] = parseValue(-i);
|
|
|
|
}
|
|
|
|
// Backwards compatibility
|
|
|
|
Integer.one = Integer[1];
|
|
|
|
Integer.zero = Integer[0];
|
|
|
|
Integer.minusOne = Integer[-1];
|
|
|
|
Integer.max = max;
|
|
|
|
Integer.min = min;
|
|
|
|
Integer.gcd = gcd;
|
|
|
|
Integer.lcm = lcm;
|
|
|
|
Integer.isInstance = function (x) { return x instanceof BigInteger || x instanceof SmallInteger || x instanceof NativeBigInt; };
|
|
|
|
Integer.randBetween = randBetween;
|
|
|
|
|
|
|
|
Integer.fromArray = function (digits, base, isNegative) {
|
|
|
|
return parseBaseFromArray(digits.map(parseValue), parseValue(base || 10), isNegative);
|
|
|
|
};
|
|
|
|
|
|
|
|
return Integer;
|
|
|
|
})();
|
|
|
|
|
|
|
|
// Node.js check
|
|
|
|
if ( module.hasOwnProperty("exports")) {
|
|
|
|
module.exports = bigInt;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
function fromString$1(s, radix) {
|
|
|
|
if (typeof s == "string") {
|
|
|
|
if (s.slice(0,2) == "0x") {
|
|
|
|
return BigInteger(s.slice(2), 16);
|
|
|
|
} else {
|
|
|
|
return BigInteger(s,radix);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return BigInteger(s, radix);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const e$1 = fromString$1;
|
|
|
|
|
|
|
|
function fromArray$1(a, radix) {
|
|
|
|
return BigInteger.fromArray(a, radix);
|
|
|
|
}
|
|
|
|
|
|
|
|
function bitLength$1(a) {
|
|
|
|
return BigInteger(a).bitLength();
|
|
|
|
}
|
|
|
|
|
|
|
|
function isNegative$1(a) {
|
|
|
|
return BigInteger(a).isNegative();
|
|
|
|
}
|
|
|
|
|
|
|
|
function isZero$1(a) {
|
|
|
|
return BigInteger(a).isZero();
|
|
|
|
}
|
|
|
|
|
|
|
|
function shiftLeft$1(a, n) {
|
|
|
|
return BigInteger(a).shiftLeft(n);
|
|
|
|
}
|
|
|
|
|
|
|
|
function shiftRight$1(a, n) {
|
|
|
|
return BigInteger(a).shiftRight(n);
|
|
|
|
}
|
|
|
|
|
|
|
|
const shl$1 = shiftLeft$1;
|
|
|
|
const shr$1 = shiftRight$1;
|
|
|
|
|
|
|
|
function isOdd$1(a) {
|
|
|
|
return BigInteger(a).isOdd();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function naf$1(n) {
|
|
|
|
let E = BigInteger(n);
|
|
|
|
const res = [];
|
|
|
|
while (E.gt(BigInteger.zero)) {
|
|
|
|
if (E.isOdd()) {
|
|
|
|
const z = 2 - E.mod(4).toJSNumber();
|
|
|
|
res.push( z );
|
|
|
|
E = E.minus(z);
|
|
|
|
} else {
|
|
|
|
res.push( 0 );
|
|
|
|
}
|
|
|
|
E = E.shiftRight(1);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
function bits$1(n) {
|
|
|
|
let E = BigInteger(n);
|
|
|
|
const res = [];
|
|
|
|
while (E.gt(BigInteger.zero)) {
|
|
|
|
if (E.isOdd()) {
|
|
|
|
res.push(1);
|
|
|
|
} else {
|
|
|
|
res.push( 0 );
|
|
|
|
}
|
|
|
|
E = E.shiftRight(1);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
function toNumber$1(s) {
|
|
|
|
if (!s.lt(BigInteger("9007199254740992", 10))) {
|
|
|
|
throw new Error("Number too big");
|
|
|
|
}
|
|
|
|
return s.toJSNumber();
|
|
|
|
}
|
|
|
|
|
|
|
|
function toArray$1(s, radix) {
|
|
|
|
return BigInteger(s).toArray(radix);
|
|
|
|
}
|
|
|
|
|
|
|
|
function add$1(a, b) {
|
|
|
|
return BigInteger(a).add(BigInteger(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
function sub$1(a, b) {
|
|
|
|
return BigInteger(a).minus(BigInteger(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
function neg$1(a) {
|
|
|
|
return BigInteger.zero.minus(BigInteger(a));
|
|
|
|
}
|
|
|
|
|
|
|
|
function mul$1(a, b) {
|
|
|
|
return BigInteger(a).times(BigInteger(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
function square$1(a) {
|
|
|
|
return BigInteger(a).square();
|
|
|
|
}
|
|
|
|
|
|
|
|
function pow$1(a, b) {
|
|
|
|
return BigInteger(a).pow(BigInteger(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
function exp$1(a, b) {
|
|
|
|
return BigInteger(a).pow(BigInteger(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
function abs$1(a) {
|
|
|
|
return BigInteger(a).abs();
|
|
|
|
}
|
|
|
|
|
|
|
|
function div$1(a, b) {
|
|
|
|
return BigInteger(a).divide(BigInteger(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
function mod$1(a, b) {
|
|
|
|
return BigInteger(a).mod(BigInteger(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
function eq$1(a, b) {
|
|
|
|
return BigInteger(a).eq(BigInteger(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
function neq$1(a, b) {
|
|
|
|
return BigInteger(a).neq(BigInteger(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
function lt$1(a, b) {
|
|
|
|
return BigInteger(a).lt(BigInteger(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
function gt$1(a, b) {
|
|
|
|
return BigInteger(a).gt(BigInteger(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
function leq$1(a, b) {
|
|
|
|
return BigInteger(a).leq(BigInteger(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
function geq$1(a, b) {
|
|
|
|
return BigInteger(a).geq(BigInteger(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
function band$1(a, b) {
|
|
|
|
return BigInteger(a).and(BigInteger(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
function bor$1(a, b) {
|
|
|
|
return BigInteger(a).or(BigInteger(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
function bxor$1(a, b) {
|
|
|
|
return BigInteger(a).xor(BigInteger(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
function land$1(a, b) {
|
|
|
|
return (!BigInteger(a).isZero()) && (!BigInteger(b).isZero());
|
|
|
|
}
|
|
|
|
|
|
|
|
function lor$1(a, b) {
|
|
|
|
return (!BigInteger(a).isZero()) || (!BigInteger(b).isZero());
|
|
|
|
}
|
|
|
|
|
|
|
|
function lnot$1(a) {
|
|
|
|
return BigInteger(a).isZero();
|
|
|
|
}
|
|
|
|
|
|
|
|
var Scalar_bigint = /*#__PURE__*/Object.freeze({
|
|
|
|
__proto__: null,
|
|
|
|
fromString: fromString$1,
|
|
|
|
e: e$1,
|
|
|
|
fromArray: fromArray$1,
|
|
|
|
bitLength: bitLength$1,
|
|
|
|
isNegative: isNegative$1,
|
|
|
|
isZero: isZero$1,
|
|
|
|
shiftLeft: shiftLeft$1,
|
|
|
|
shiftRight: shiftRight$1,
|
|
|
|
shl: shl$1,
|
|
|
|
shr: shr$1,
|
|
|
|
isOdd: isOdd$1,
|
|
|
|
naf: naf$1,
|
|
|
|
bits: bits$1,
|
|
|
|
toNumber: toNumber$1,
|
|
|
|
toArray: toArray$1,
|
|
|
|
add: add$1,
|
|
|
|
sub: sub$1,
|
|
|
|
neg: neg$1,
|
|
|
|
mul: mul$1,
|
|
|
|
square: square$1,
|
|
|
|
pow: pow$1,
|
|
|
|
exp: exp$1,
|
|
|
|
abs: abs$1,
|
|
|
|
div: div$1,
|
|
|
|
mod: mod$1,
|
|
|
|
eq: eq$1,
|
|
|
|
neq: neq$1,
|
|
|
|
lt: lt$1,
|
|
|
|
gt: gt$1,
|
|
|
|
leq: leq$1,
|
|
|
|
geq: geq$1,
|
|
|
|
band: band$1,
|
|
|
|
bor: bor$1,
|
|
|
|
bxor: bxor$1,
|
|
|
|
land: land$1,
|
|
|
|
lor: lor$1,
|
|
|
|
lnot: lnot$1
|
|
|
|
});
|
|
|
|
|
|
|
|
const supportsNativeBigInt = typeof BigInt === "function";
|
|
|
|
|
|
|
|
let Scalar = {};
|
|
|
|
if (supportsNativeBigInt) {
|
|
|
|
Object.assign(Scalar, Scalar_native);
|
|
|
|
} else {
|
|
|
|
Object.assign(Scalar, Scalar_bigint);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Returns a buffer with Little Endian Representation
|
|
|
|
Scalar.toRprLE = function rprBE(buff, o, e, n8) {
|
|
|
|
const s = "0000000" + e.toString(16);
|
|
|
|
const v = new Uint32Array(buff.buffer, o, n8/4);
|
|
|
|
const l = (((s.length-7)*4 - 1) >> 5)+1; // Number of 32bit words;
|
|
|
|
for (let i=0; i<l; i++) v[i] = parseInt(s.substring(s.length-8*i-8, s.length-8*i), 16);
|
|
|
|
for (let i=l; i<v.length; i++) v[i] = 0;
|
|
|
|
for (let i=v.length*4; i<n8; i++) buff[i] = Scalar.toNumber(Scalar.band(Scalar.shiftRight(e, i*8), 0xFF));
|
|
|
|
};
|
|
|
|
|
|
|
|
// Returns a buffer with Big Endian Representation
|
|
|
|
Scalar.toRprBE = function rprLEM(buff, o, e, n8) {
|
|
|
|
const s = "0000000" + e.toString(16);
|
|
|
|
const v = new DataView(buff.buffer, o, n8);
|
|
|
|
const l = (((s.length-7)*4 - 1) >> 5)+1; // Number of 32bit words;
|
|
|
|
for (let i=0; i<l; i++) v.setUint32(n8-i*4 -4, parseInt(s.substring(s.length-8*i-8, s.length-8*i), 16), false);
|
|
|
|
for (let i=0; i<n8/4-l; i++) v[i] = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Pases a buffer with Little Endian Representation
|
|
|
|
Scalar.fromRprLE = function rprLEM(buff, o, n8) {
|
|
|
|
n8 = n8 || buff.byteLength;
|
|
|
|
const v = new Uint32Array(buff.buffer, o, n8/4);
|
|
|
|
const a = new Array(n8/4);
|
|
|
|
v.forEach( (ch,i) => a[a.length-i-1] = ch.toString(16).padStart(8,"0") );
|
|
|
|
return Scalar.fromString(a.join(""), 16);
|
|
|
|
};
|
|
|
|
|
|
|
|
// Pases a buffer with Big Endian Representation
|
|
|
|
Scalar.fromRprBE = function rprLEM(buff, o, n8) {
|
|
|
|
n8 = n8 || buff.byteLength;
|
|
|
|
const v = new DataView(buff.buffer, o, n8);
|
|
|
|
const a = new Array(n8/4);
|
|
|
|
for (let i=0; i<n8/4; i++) {
|
|
|
|
a[i] = v.getUint32(i*4, false).toString(16).padStart(8, "0");
|
|
|
|
}
|
|
|
|
return Scalar.fromString(a.join(""), 16);
|
|
|
|
};
|
|
|
|
|
|
|
|
Scalar.toString = function toString(a, radix) {
|
|
|
|
return a.toString(radix);
|
|
|
|
};
|
|
|
|
|
|
|
|
Scalar.toLEBuff = function toLEBuff(a) {
|
|
|
|
const buff = new Uint8Array(Math.floor((Scalar.bitLength(a) - 1) / 8) +1);
|
|
|
|
Scalar.toRprLE(buff, 0, a, buff.byteLength);
|
|
|
|
return buff;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Scalar.zero = Scalar.e(0);
|
|
|
|
Scalar.one = Scalar.e(1);
|
|
|
|
|
|
|
|
let {
|
|
|
|
toRprLE,
|
|
|
|
toRprBE,
|
|
|
|
fromRprLE,
|
|
|
|
fromRprBE,
|
|
|
|
toString,
|
|
|
|
toLEBuff,
|
|
|
|
zero,
|
|
|
|
one,
|
|
|
|
fromString: fromString$2,
|
|
|
|
e: e$2,
|
|
|
|
fromArray: fromArray$2,
|
|
|
|
bitLength: bitLength$2,
|
|
|
|
isNegative: isNegative$2,
|
|
|
|
isZero: isZero$2,
|
|
|
|
shiftLeft: shiftLeft$2,
|
|
|
|
shiftRight: shiftRight$2,
|
|
|
|
shl: shl$2,
|
|
|
|
shr: shr$2,
|
|
|
|
isOdd: isOdd$2,
|
|
|
|
naf: naf$2,
|
|
|
|
bits: bits$2,
|
|
|
|
toNumber: toNumber$2,
|
|
|
|
toArray: toArray$2,
|
|
|
|
add: add$2,
|
|
|
|
sub: sub$2,
|
|
|
|
neg: neg$2,
|
|
|
|
mul: mul$2,
|
|
|
|
square: square$2,
|
|
|
|
pow: pow$2,
|
|
|
|
exp: exp$2,
|
|
|
|
abs: abs$2,
|
|
|
|
div: div$2,
|
|
|
|
mod: mod$2,
|
|
|
|
eq: eq$2,
|
|
|
|
neq: neq$2,
|
|
|
|
lt: lt$2,
|
|
|
|
gt: gt$2,
|
|
|
|
leq: leq$2,
|
|
|
|
geq: geq$2,
|
|
|
|
band: band$2,
|
|
|
|
bor: bor$2,
|
|
|
|
bxor: bxor$2,
|
|
|
|
land: land$2,
|
|
|
|
lor: lor$2,
|
|
|
|
lnot: lnot$2,
|
|
|
|
} = Scalar;
|
|
|
|
|
|
|
|
var _Scalar = /*#__PURE__*/Object.freeze({
|
|
|
|
__proto__: null,
|
|
|
|
toRprLE: toRprLE,
|
|
|
|
toRprBE: toRprBE,
|
|
|
|
fromRprLE: fromRprLE,
|
|
|
|
fromRprBE: fromRprBE,
|
|
|
|
toString: toString,
|
|
|
|
toLEBuff: toLEBuff,
|
|
|
|
zero: zero,
|
|
|
|
one: one,
|
|
|
|
fromString: fromString$2,
|
|
|
|
e: e$2,
|
|
|
|
fromArray: fromArray$2,
|
|
|
|
bitLength: bitLength$2,
|
|
|
|
isNegative: isNegative$2,
|
|
|
|
isZero: isZero$2,
|
|
|
|
shiftLeft: shiftLeft$2,
|
|
|
|
shiftRight: shiftRight$2,
|
|
|
|
shl: shl$2,
|
|
|
|
shr: shr$2,
|
|
|
|
isOdd: isOdd$2,
|
|
|
|
naf: naf$2,
|
|
|
|
bits: bits$2,
|
|
|
|
toNumber: toNumber$2,
|
|
|
|
toArray: toArray$2,
|
|
|
|
add: add$2,
|
|
|
|
sub: sub$2,
|
|
|
|
neg: neg$2,
|
|
|
|
mul: mul$2,
|
|
|
|
square: square$2,
|
|
|
|
pow: pow$2,
|
|
|
|
exp: exp$2,
|
|
|
|
abs: abs$2,
|
|
|
|
div: div$2,
|
|
|
|
mod: mod$2,
|
|
|
|
eq: eq$2,
|
|
|
|
neq: neq$2,
|
|
|
|
lt: lt$2,
|
|
|
|
gt: gt$2,
|
|
|
|
leq: leq$2,
|
|
|
|
geq: geq$2,
|
|
|
|
band: band$2,
|
|
|
|
bor: bor$2,
|
|
|
|
bxor: bxor$2,
|
|
|
|
land: land$2,
|
|
|
|
lor: lor$2,
|
|
|
|
lnot: lnot$2
|
|
|
|
});
|
|
|
|
|
|
|
|
/*
|
|
|
|
Copyright 2018 0kims association.
|
|
|
|
|
|
|
|
This file is part of snarkjs.
|
|
|
|
|
|
|
|
snarkjs 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.
|
|
|
|
|
|
|
|
snarkjs 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
|
|
|
|
snarkjs. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
This library does operations on polynomials with coefficients in a field F.
|
|
|
|
|
|
|
|
A polynomial P(x) = p0 + p1 * x + p2 * x^2 + ... + pn * x^n is represented
|
|
|
|
by the array [ p0, p1, p2, ... , pn ].
|
|
|
|
*/
|
|
|
|
|
|
|
|
class PolField {
|
|
|
|
constructor (F) {
|
|
|
|
this.F = F;
|
|
|
|
|
|
|
|
let rem = F.sqrt_t;
|
|
|
|
let s = F.sqrt_s;
|
|
|
|
|
|
|
|
const five = this.F.add(this.F.add(this.F.two, this.F.two), this.F.one);
|
|
|
|
|
|
|
|
this.w = new Array(s+1);
|
|
|
|
this.wi = new Array(s+1);
|
|
|
|
this.w[s] = this.F.pow(five, rem);
|
|
|
|
this.wi[s] = this.F.inv(this.w[s]);
|
|
|
|
|
|
|
|
let n=s-1;
|
|
|
|
while (n>=0) {
|
|
|
|
this.w[n] = this.F.square(this.w[n+1]);
|
|
|
|
this.wi[n] = this.F.square(this.wi[n+1]);
|
|
|
|
n--;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
this.roots = [];
|
|
|
|
/* for (let i=0; i<16; i++) {
|
|
|
|
let r = this.F.one;
|
|
|
|
n = 1 << i;
|
|
|
|
const rootsi = new Array(n);
|
|
|
|
for (let j=0; j<n; j++) {
|
|
|
|
rootsi[j] = r;
|
|
|
|
r = this.F.mul(r, this.w[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.roots.push(rootsi);
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
this._setRoots(15);
|
|
|
|
}
|
|
|
|
|
|
|
|
_setRoots(n) {
|
|
|
|
for (let i=n; (i>=0) && (!this.roots[i]); i--) {
|
|
|
|
let r = this.F.one;
|
|
|
|
const nroots = 1 << i;
|
|
|
|
const rootsi = new Array(nroots);
|
|
|
|
for (let j=0; j<nroots; j++) {
|
|
|
|
rootsi[j] = r;
|
|
|
|
r = this.F.mul(r, this.w[i]);
|
|
|
|
}
|
|
|
|
this.roots[i] = rootsi;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
add(a, b) {
|
|
|
|
const m = Math.max(a.length, b.length);
|
|
|
|
const res = new Array(m);
|
|
|
|
for (let i=0; i<m; i++) {
|
|
|
|
res[i] = this.F.add(a[i] || this.F.zero, b[i] || this.F.zero);
|
|
|
|
}
|
|
|
|
return this.reduce(res);
|
|
|
|
}
|
|
|
|
|
|
|
|
double(a) {
|
|
|
|
return this.add(a,a);
|
|
|
|
}
|
|
|
|
|
|
|
|
sub(a, b) {
|
|
|
|
const m = Math.max(a.length, b.length);
|
|
|
|
const res = new Array(m);
|
|
|
|
for (let i=0; i<m; i++) {
|
|
|
|
res[i] = this.F.sub(a[i] || this.F.zero, b[i] || this.F.zero);
|
|
|
|
}
|
|
|
|
return this.reduce(res);
|
|
|
|
}
|
|
|
|
|
|
|
|
mulScalar(p, b) {
|
|
|
|
if (this.F.eq(b, this.F.zero)) return [];
|
|
|
|
if (this.F.eq(b, this.F.one)) return p;
|
|
|
|
const res = new Array(p.length);
|
|
|
|
for (let i=0; i<p.length; i++) {
|
|
|
|
res[i] = this.F.mul(p[i], b);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mul(a, b) {
|
|
|
|
if (a.length == 0) return [];
|
|
|
|
if (b.length == 0) return [];
|
|
|
|
if (a.length == 1) return this.mulScalar(b, a[0]);
|
|
|
|
if (b.length == 1) return this.mulScalar(a, b[0]);
|
|
|
|
|
|
|
|
if (b.length > a.length) {
|
|
|
|
[b, a] = [a, b];
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((b.length <= 2) || (b.length < log2(a.length))) {
|
|
|
|
return this.mulNormal(a,b);
|
|
|
|
} else {
|
|
|
|
return this.mulFFT(a,b);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mulNormal(a, b) {
|
|
|
|
let res = [];
|
|
|
|
for (let i=0; i<b.length; i++) {
|
|
|
|
res = this.add(res, this.scaleX(this.mulScalar(a, b[i]), i) );
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
mulFFT(a,b) {
|
|
|
|
const longestN = Math.max(a.length, b.length);
|
|
|
|
const bitsResult = log2(longestN-1)+2;
|
|
|
|
this._setRoots(bitsResult);
|
|
|
|
|
|
|
|
const m = 1 << bitsResult;
|
|
|
|
const ea = this.extend(a,m);
|
|
|
|
const eb = this.extend(b,m);
|
|
|
|
|
|
|
|
const ta = __fft(this, ea, bitsResult, 0, 1);
|
|
|
|
const tb = __fft(this, eb, bitsResult, 0, 1);
|
|
|
|
|
|
|
|
const tres = new Array(m);
|
|
|
|
|
|
|
|
for (let i=0; i<m; i++) {
|
|
|
|
tres[i] = this.F.mul(ta[i], tb[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
const res = __fft(this, tres, bitsResult, 0, 1);
|
|
|
|
|
|
|
|
const twoinvm = this.F.inv( this.F.mulScalar(this.F.one, m) );
|
|
|
|
const resn = new Array(m);
|
|
|
|
for (let i=0; i<m; i++) {
|
|
|
|
resn[i] = this.F.mul(res[(m-i)%m], twoinvm);
|
|
|
|
}
|
|
|
|
|
|
|
|
return this.reduce(resn);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
square(a) {
|
|
|
|
return this.mul(a,a);
|
|
|
|
}
|
|
|
|
|
|
|
|
scaleX(p, n) {
|
|
|
|
if (n==0) {
|
|
|
|
return p;
|
|
|
|
} else if (n>0) {
|
|
|
|
const z = new Array(n).fill(this.F.zero);
|
|
|
|
return z.concat(p);
|
|
|
|
} else {
|
|
|
|
if (-n >= p.length) return [];
|
|
|
|
return p.slice(-n);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
eval2(p, x) {
|
|
|
|
let v = this.F.zero;
|
|
|
|
let ix = this.F.one;
|
|
|
|
for (let i=0; i<p.length; i++) {
|
|
|
|
v = this.F.add(v, this.F.mul(p[i], ix));
|
|
|
|
ix = this.F.mul(ix, x);
|
|
|
|
}
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
eval(p,x) {
|
|
|
|
const F = this.F;
|
|
|
|
if (p.length == 0) return F.zero;
|
|
|
|
const m = this._next2Power(p.length);
|
|
|
|
const ep = this.extend(p, m);
|
|
|
|
|
|
|
|
return _eval(ep, x, 0, 1, m);
|
|
|
|
|
|
|
|
function _eval(p, x, offset, step, n) {
|
|
|
|
if (n==1) return p[offset];
|
|
|
|
const newX = F.square(x);
|
|
|
|
const res= F.add(
|
|
|
|
_eval(p, newX, offset, step << 1, n >> 1),
|
|
|
|
F.mul(
|
|
|
|
x,
|
|
|
|
_eval(p, newX, offset+step , step << 1, n >> 1)));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
lagrange(points) {
|
|
|
|
let roots = [this.F.one];
|
|
|
|
for (let i=0; i<points.length; i++) {
|
|
|
|
roots = this.mul(roots, [this.F.neg(points[i][0]), this.F.one]);
|
|
|
|
}
|
|
|
|
|
|
|
|
let sum = [];
|
|
|
|
for (let i=0; i<points.length; i++) {
|
|
|
|
let mpol = this.ruffini(roots, points[i][0]);
|
|
|
|
const factor =
|
|
|
|
this.F.mul(
|
|
|
|
this.F.inv(this.eval(mpol, points[i][0])),
|
|
|
|
points[i][1]);
|
|
|
|
mpol = this.mulScalar(mpol, factor);
|
|
|
|
sum = this.add(sum, mpol);
|
|
|
|
}
|
|
|
|
return sum;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fft(p) {
|
|
|
|
if (p.length <= 1) return p;
|
|
|
|
const bits = log2(p.length-1)+1;
|
|
|
|
this._setRoots(bits);
|
|
|
|
|
|
|
|
const m = 1 << bits;
|
|
|
|
const ep = this.extend(p, m);
|
|
|
|
const res = __fft(this, ep, bits, 0, 1);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
fft2(p) {
|
|
|
|
if (p.length <= 1) return p;
|
|
|
|
const bits = log2(p.length-1)+1;
|
|
|
|
this._setRoots(bits);
|
|
|
|
|
|
|
|
const m = 1 << bits;
|
|
|
|
const ep = this.extend(p, m);
|
|
|
|
__bitReverse(ep, bits);
|
|
|
|
const res = __fft2(this, ep, bits);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ifft(p) {
|
|
|
|
|
|
|
|
if (p.length <= 1) return p;
|
|
|
|
const bits = log2(p.length-1)+1;
|
|
|
|
this._setRoots(bits);
|
|
|
|
const m = 1 << bits;
|
|
|
|
const ep = this.extend(p, m);
|
|
|
|
const res = __fft(this, ep, bits, 0, 1);
|
|
|
|
|
|
|
|
const twoinvm = this.F.inv( this.F.mulScalar(this.F.one, m) );
|
|
|
|
const resn = new Array(m);
|
|
|
|
for (let i=0; i<m; i++) {
|
|
|
|
resn[i] = this.F.mul(res[(m-i)%m], twoinvm);
|
|
|
|
}
|
|
|
|
|
|
|
|
return resn;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ifft2(p) {
|
|
|
|
|
|
|
|
if (p.length <= 1) return p;
|
|
|
|
const bits = log2(p.length-1)+1;
|
|
|
|
this._setRoots(bits);
|
|
|
|
const m = 1 << bits;
|
|
|
|
const ep = this.extend(p, m);
|
|
|
|
__bitReverse(ep, bits);
|
|
|
|
const res = __fft2(this, ep, bits);
|
|
|
|
|
|
|
|
const twoinvm = this.F.inv( this.F.mulScalar(this.F.one, m) );
|
|
|
|
const resn = new Array(m);
|
|
|
|
for (let i=0; i<m; i++) {
|
|
|
|
resn[i] = this.F.mul(res[(m-i)%m], twoinvm);
|
|
|
|
}
|
|
|
|
|
|
|
|
return resn;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
_fft(pall, bits, offset, step) {
|
|
|
|
|
|
|
|
const n = 1 << bits;
|
|
|
|
if (n==1) {
|
|
|
|
return [ pall[offset] ];
|
|
|
|
}
|
|
|
|
|
|
|
|
const ndiv2 = n >> 1;
|
|
|
|
const p1 = this._fft(pall, bits-1, offset, step*2);
|
|
|
|
const p2 = this._fft(pall, bits-1, offset+step, step*2);
|
|
|
|
|
|
|
|
const out = new Array(n);
|
|
|
|
|
|
|
|
let m= this.F.one;
|
|
|
|
for (let i=0; i<ndiv2; i++) {
|
|
|
|
out[i] = this.F.add(p1[i], this.F.mul(m, p2[i]));
|
|
|
|
out[i+ndiv2] = this.F.sub(p1[i], this.F.mul(m, p2[i]));
|
|
|
|
m = this.F.mul(m, this.w[bits]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
|
|
|
extend(p, e) {
|
|
|
|
if (e == p.length) return p;
|
|
|
|
const z = new Array(e-p.length).fill(this.F.zero);
|
|
|
|
|
|
|
|
return p.concat(z);
|
|
|
|
}
|
|
|
|
|
|
|
|
reduce(p) {
|
|
|
|
if (p.length == 0) return p;
|
|
|
|
if (! this.F.eq(p[p.length-1], this.F.zero) ) return p;
|
|
|
|
let i=p.length-1;
|
|
|
|
while( i>0 && this.F.eq(p[i], this.F.zero) ) i--;
|
|
|
|
return p.slice(0, i+1);
|
|
|
|
}
|
|
|
|
|
|
|
|
eq(a, b) {
|
|
|
|
const pa = this.reduce(a);
|
|
|
|
const pb = this.reduce(b);
|
|
|
|
|
|
|
|
if (pa.length != pb.length) return false;
|
|
|
|
for (let i=0; i<pb.length; i++) {
|
|
|
|
if (!this.F.eq(pa[i], pb[i])) return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
ruffini(p, r) {
|
|
|
|
const res = new Array(p.length-1);
|
|
|
|
res[res.length-1] = p[p.length-1];
|
|
|
|
for (let i = res.length-2; i>=0; i--) {
|
|
|
|
res[i] = this.F.add(this.F.mul(res[i+1], r), p[i+1]);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
_next2Power(v) {
|
|
|
|
v--;
|
|
|
|
v |= v >> 1;
|
|
|
|
v |= v >> 2;
|
|
|
|
v |= v >> 4;
|
|
|
|
v |= v >> 8;
|
|
|
|
v |= v >> 16;
|
|
|
|
v++;
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
toString(p) {
|
|
|
|
const ap = this.normalize(p);
|
|
|
|
let S = "";
|
|
|
|
for (let i=ap.length-1; i>=0; i--) {
|
|
|
|
if (!this.F.eq(p[i], this.F.zero)) {
|
|
|
|
if (S!="") S += " + ";
|
|
|
|
S = S + p[i].toString(10);
|
|
|
|
if (i>0) {
|
|
|
|
S = S + "x";
|
|
|
|
if (i>1) {
|
|
|
|
S = S + "^" +i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return S;
|
|
|
|
}
|
|
|
|
|
|
|
|
normalize(p) {
|
|
|
|
const res = new Array(p.length);
|
|
|
|
for (let i=0; i<p.length; i++) {
|
|
|
|
res[i] = this.F.normalize(p[i]);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_reciprocal(p, bits) {
|
|
|
|
const k = 1 << bits;
|
|
|
|
if (k==1) {
|
|
|
|
return [ this.F.inv(p[0]) ];
|
|
|
|
}
|
|
|
|
const np = this.scaleX(p, -k/2);
|
|
|
|
const q = this._reciprocal(np, bits-1);
|
|
|
|
const a = this.scaleX(this.double(q), 3*k/2-2);
|
|
|
|
const b = this.mul( this.square(q), p);
|
|
|
|
|
|
|
|
return this.scaleX(this.sub(a,b), -(k-2));
|
|
|
|
}
|
|
|
|
|
|
|
|
// divides x^m / v
|
|
|
|
_div2(m, v) {
|
|
|
|
const kbits = log2(v.length-1)+1;
|
|
|
|
const k = 1 << kbits;
|
|
|
|
|
|
|
|
const scaleV = k - v.length;
|
|
|
|
|
|
|
|
// rec = x^(k - 2) / v* x^scaleV =>
|
|
|
|
// rec = x^(k-2-scaleV)/ v
|
|
|
|
//
|
|
|
|
// res = x^m/v = x^(m + (2*k-2 - scaleV) - (2*k-2 - scaleV)) /v =>
|
|
|
|
// res = rec * x^(m - (2*k-2 - scaleV)) =>
|
|
|
|
// res = rec * x^(m - 2*k + 2 + scaleV)
|
|
|
|
|
|
|
|
const rec = this._reciprocal(this.scaleX(v, scaleV), kbits);
|
|
|
|
const res = this.scaleX(rec, m - 2*k + 2 + scaleV);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
div(_u, _v) {
|
|
|
|
if (_u.length < _v.length) return [];
|
|
|
|
const kbits = log2(_v.length-1)+1;
|
|
|
|
const k = 1 << kbits;
|
|
|
|
|
|
|
|
const u = this.scaleX(_u, k-_v.length);
|
|
|
|
const v = this.scaleX(_v, k-_v.length);
|
|
|
|
|
|
|
|
const n = v.length-1;
|
|
|
|
let m = u.length-1;
|
|
|
|
|
|
|
|
const s = this._reciprocal(v, kbits);
|
|
|
|
let t;
|
|
|
|
if (m>2*n) {
|
|
|
|
t = this.sub(this.scaleX([this.F.one], 2*n), this.mul(s, v));
|
|
|
|
}
|
|
|
|
|
|
|
|
let q = [];
|
|
|
|
let rem = u;
|
|
|
|
let us, ut;
|
|
|
|
let finish = false;
|
|
|
|
|
|
|
|
while (!finish) {
|
|
|
|
us = this.mul(rem, s);
|
|
|
|
q = this.add(q, this.scaleX(us, -2*n));
|
|
|
|
|
|
|
|
if ( m > 2*n ) {
|
|
|
|
ut = this.mul(rem, t);
|
|
|
|
rem = this.scaleX(ut, -2*n);
|
|
|
|
m = rem.length-1;
|
|
|
|
} else {
|
|
|
|
finish = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return q;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// returns the ith nth-root of one
|
|
|
|
oneRoot(n, i) {
|
|
|
|
let nbits = log2(n-1)+1;
|
|
|
|
let res = this.F.one;
|
|
|
|
let r = i;
|
|
|
|
|
|
|
|
if(i>=n) {
|
|
|
|
throw new Error("Given 'i' should be lower than 'n'");
|
|
|
|
}
|
|
|
|
else if (1<<nbits !== n) {
|
|
|
|
throw new Error(`Internal errlr: ${n} should equal ${1<<nbits}`);
|
|
|
|
}
|
|
|
|
|
|
|
|
while (r>0) {
|
|
|
|
if (r & 1 == 1) {
|
|
|
|
res = this.F.mul(res, this.w[nbits]);
|
|
|
|
}
|
|
|
|
r = r >> 1;
|
|
|
|
nbits --;
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
computeVanishingPolinomial(bits, t) {
|
|
|
|
const m = 1 << bits;
|
|
|
|
return this.F.sub(this.F.pow(t, m), this.F.one);
|
|
|
|
}
|
|
|
|
|
|
|
|
evaluateLagrangePolynomials(bits, t) {
|
|
|
|
const m= 1 << bits;
|
|
|
|
const tm = this.F.pow(t, m);
|
|
|
|
const u= new Array(m).fill(this.F.zero);
|
|
|
|
this._setRoots(bits);
|
|
|
|
const omega = this.w[bits];
|
|
|
|
|
|
|
|
if (this.F.eq(tm, this.F.one)) {
|
|
|
|
for (let i = 0; i < m; i++) {
|
|
|
|
if (this.F.eq(this.roots[bits][0],t)) { // i.e., t equals omega^i
|
|
|
|
u[i] = this.F.one;
|
|
|
|
return u;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const z = this.F.sub(tm, this.F.one);
|
|
|
|
// let l = this.F.mul(z, this.F.pow(this.F.twoinv, m));
|
|
|
|
let l = this.F.mul(z, this.F.inv(this.F.e(m)));
|
|
|
|
for (let i = 0; i < m; i++) {
|
|
|
|
u[i] = this.F.mul(l, this.F.inv(this.F.sub(t,this.roots[bits][i])));
|
|
|
|
l = this.F.mul(l, omega);
|
|
|
|
}
|
|
|
|
|
|
|
|
return u;
|
|
|
|
}
|
|
|
|
|
|
|
|
log2(V) {
|
|
|
|
return log2(V);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function log2( V )
|
|
|
|
{
|
|
|
|
return( ( ( V & 0xFFFF0000 ) !== 0 ? ( V &= 0xFFFF0000, 16 ) : 0 ) | ( ( V & 0xFF00FF00 ) !== 0 ? ( V &= 0xFF00FF00, 8 ) : 0 ) | ( ( V & 0xF0F0F0F0 ) !== 0 ? ( V &= 0xF0F0F0F0, 4 ) : 0 ) | ( ( V & 0xCCCCCCCC ) !== 0 ? ( V &= 0xCCCCCCCC, 2 ) : 0 ) | ( ( V & 0xAAAAAAAA ) !== 0 ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function __fft(PF, pall, bits, offset, step) {
|
|
|
|
|
|
|
|
const n = 1 << bits;
|
|
|
|
if (n==1) {
|
|
|
|
return [ pall[offset] ];
|
|
|
|
} else if (n==2) {
|
|
|
|
return [
|
|
|
|
PF.F.add(pall[offset], pall[offset + step]),
|
|
|
|
PF.F.sub(pall[offset], pall[offset + step])];
|
|
|
|
}
|
|
|
|
|
|
|
|
const ndiv2 = n >> 1;
|
|
|
|
const p1 = __fft(PF, pall, bits-1, offset, step*2);
|
|
|
|
const p2 = __fft(PF, pall, bits-1, offset+step, step*2);
|
|
|
|
|
|
|
|
const out = new Array(n);
|
|
|
|
|
|
|
|
for (let i=0; i<ndiv2; i++) {
|
|
|
|
out[i] = PF.F.add(p1[i], PF.F.mul(PF.roots[bits][i], p2[i]));
|
|
|
|
out[i+ndiv2] = PF.F.sub(p1[i], PF.F.mul(PF.roots[bits][i], p2[i]));
|
|
|
|
}
|
|
|
|
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function __fft2(PF, pall, bits) {
|
|
|
|
|
|
|
|
const n = 1 << bits;
|
|
|
|
if (n==1) {
|
|
|
|
return [ pall[0] ];
|
|
|
|
}
|
|
|
|
|
|
|
|
const ndiv2 = n >> 1;
|
|
|
|
const p1 = __fft2(PF, pall.slice(0, ndiv2), bits-1);
|
|
|
|
const p2 = __fft2(PF, pall.slice(ndiv2), bits-1);
|
|
|
|
|
|
|
|
const out = new Array(n);
|
|
|
|
|
|
|
|
for (let i=0; i<ndiv2; i++) {
|
|
|
|
out[i] = PF.F.add(p1[i], PF.F.mul(PF.roots[bits][i], p2[i]));
|
|
|
|
out[i+ndiv2] = PF.F.sub(p1[i], PF.F.mul(PF.roots[bits][i], p2[i]));
|
|
|
|
}
|
|
|
|
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
|
|
|
const _revTable = [];
|
|
|
|
for (let i=0; i<256; i++) {
|
|
|
|
_revTable[i] = _revSlow(i, 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
function _revSlow(idx, bits) {
|
|
|
|
let res =0;
|
|
|
|
let a = idx;
|
|
|
|
for (let i=0; i<bits; i++) {
|
|
|
|
res <<= 1;
|
|
|
|
res = res | (a &1);
|
|
|
|
a >>=1;
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
function rev(idx, bits) {
|
|
|
|
return (
|
|
|
|
_revTable[idx >>> 24] |
|
|
|
|
(_revTable[(idx >>> 16) & 0xFF] << 8) |
|
|
|
|
(_revTable[(idx >>> 8) & 0xFF] << 16) |
|
|
|
|
(_revTable[idx & 0xFF] << 24)
|
|
|
|
) >>> (32-bits);
|
|
|
|
}
|
|
|
|
|
|
|
|
function __bitReverse(p, bits) {
|
|
|
|
for (let k=0; k<p.length; k++) {
|
|
|
|
const r = rev(k, bits);
|
|
|
|
if (r>k) {
|
|
|
|
const tmp= p[k];
|
|
|
|
p[k] = p[r];
|
|
|
|
p[r] = tmp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Copyright 2018 0kims association.
|
|
|
|
|
|
|
|
This file is part of snarkjs.
|
|
|
|
|
|
|
|
snarkjs 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.
|
|
|
|
|
|
|
|
snarkjs 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
|
|
|
|
snarkjs. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
function mulScalar(F, base, e) {
|
|
|
|
let res;
|
|
|
|
|
|
|
|
if (isZero$2(e)) return F.zero;
|
|
|
|
|
|
|
|
const n = naf$2(e);
|
|
|
|
|
|
|
|
if (n[n.length-1] == 1) {
|
|
|
|
res = base;
|
|
|
|
} else if (n[n.length-1] == -1) {
|
|
|
|
res = F.neg(base);
|
|
|
|
} else {
|
|
|
|
throw new Error("invlaud NAF");
|
|
|
|
}
|
|
|
|
|
|
|
|
for (let i=n.length-2; i>=0; i--) {
|
|
|
|
|
|
|
|
res = F.double(res);
|
|
|
|
|
|
|
|
if (n[i] == 1) {
|
|
|
|
res = F.add(res, base);
|
|
|
|
} else if (n[i] == -1) {
|
|
|
|
res = F.sub(res, base);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
exports.mulScalar = (F, base, e) =>{
|
|
|
|
let res = F.zero;
|
|
|
|
let rem = bigInt(e);
|
|
|
|
let exp = base;
|
|
|
|
|
|
|
|
while (! rem.eq(bigInt.zero)) {
|
|
|
|
if (rem.and(bigInt.one).eq(bigInt.one)) {
|
|
|
|
res = F.add(res, exp);
|
|
|
|
}
|
|
|
|
exp = F.double(exp);
|
|
|
|
rem = rem.shiftRight(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
};
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
function exp$3(F, base, e) {
|
|
|
|
|
|
|
|
if (isZero$2(e)) return F.one;
|
|
|
|
|
|
|
|
const n = bits$2(e);
|
|
|
|
|
|
|
|
if (n.legth==0) return F.one;
|
|
|
|
|
|
|
|
let res = base;
|
|
|
|
|
|
|
|
for (let i=n.length-2; i>=0; i--) {
|
|
|
|
|
|
|
|
res = F.square(res);
|
|
|
|
|
|
|
|
if (n[i]) {
|
|
|
|
res = F.mul(res, base);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check here: https://eprint.iacr.org/2012/685.pdf
|
|
|
|
|
|
|
|
function buildSqrt (F) {
|
|
|
|
if ((F.m % 2) == 1) {
|
|
|
|
if (eq$2(mod$2(F.p, 4), 1 )) {
|
|
|
|
if (eq$2(mod$2(F.p, 8), 1 )) {
|
|
|
|
if (eq$2(mod$2(F.p, 16), 1 )) {
|
|
|
|
// alg7_muller(F);
|
|
|
|
alg5_tonelliShanks(F);
|
|
|
|
} else if (eq$2(mod$2(F.p, 16), 9 )) {
|
|
|
|
alg4_kong(F);
|
|
|
|
} else {
|
|
|
|
throw new Error("Field withot sqrt");
|
|
|
|
}
|
|
|
|
} else if (eq$2(mod$2(F.p, 8), 5 )) {
|
|
|
|
alg3_atkin(F);
|
|
|
|
} else {
|
|
|
|
throw new Error("Field withot sqrt");
|
|
|
|
}
|
|
|
|
} else if (eq$2(mod$2(F.p, 4), 3 )) {
|
|
|
|
alg2_shanks(F);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
const pm2mod4 = mod$2(pow$2(F.p, F.m/2), 4);
|
|
|
|
if (pm2mod4 == 1) {
|
|
|
|
alg10_adj(F);
|
|
|
|
} else if (pm2mod4 == 3) {
|
|
|
|
alg9_adj(F);
|
|
|
|
} else {
|
|
|
|
alg8_complex(F);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function alg5_tonelliShanks(F) {
|
|
|
|
F.sqrt_q = pow$2(F.p, F.m);
|
|
|
|
|
|
|
|
F.sqrt_s = 0;
|
|
|
|
F.sqrt_t = sub$2(F.sqrt_q, 1);
|
|
|
|
|
|
|
|
while (!isOdd$2(F.sqrt_t)) {
|
|
|
|
F.sqrt_s = F.sqrt_s + 1;
|
|
|
|
F.sqrt_t = div$2(F.sqrt_t, 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
let c0 = F.one;
|
|
|
|
|
|
|
|
while (F.eq(c0, F.one)) {
|
|
|
|
const c = F.random();
|
|
|
|
F.sqrt_z = F.pow(c, F.sqrt_t);
|
|
|
|
c0 = F.pow(F.sqrt_z, 1 << (F.sqrt_s-1) );
|
|
|
|
}
|
|
|
|
|
|
|
|
F.sqrt_tm1d2 = div$2(sub$2(F.sqrt_t, 1),2);
|
|
|
|
|
|
|
|
F.sqrt = function(a) {
|
|
|
|
const F=this;
|
|
|
|
if (F.isZero(a)) return F.zero;
|
|
|
|
let w = F.pow(a, F.sqrt_tm1d2);
|
|
|
|
const a0 = F.pow( F.mul(F.square(w), a), 1 << (F.sqrt_s-1) );
|
|
|
|
if (F.eq(a0, F.negone)) return null;
|
|
|
|
|
|
|
|
let v = F.sqrt_s;
|
|
|
|
let x = F.mul(a, w);
|
|
|
|
let b = F.mul(x, w);
|
|
|
|
let z = F.sqrt_z;
|
|
|
|
while (!F.eq(b, F.one)) {
|
|
|
|
let b2k = F.square(b);
|
|
|
|
let k=1;
|
|
|
|
while (!F.eq(b2k, F.one)) {
|
|
|
|
b2k = F.square(b2k);
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
|
|
|
|
w = z;
|
|
|
|
for (let i=0; i<v-k-1; i++) {
|
|
|
|
w = F.square(w);
|
|
|
|
}
|
|
|
|
z = F.square(w);
|
|
|
|
b = F.mul(b, z);
|
|
|
|
x = F.mul(x, w);
|
|
|
|
v = k;
|
|
|
|
}
|
|
|
|
return F.geq(x, F.zero) ? x : F.neg(x);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function alg4_kong(F) {
|
|
|
|
F.sqrt = function() {
|
|
|
|
throw new Error("Sqrt alg 4 not implemented");
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function alg3_atkin(F) {
|
|
|
|
F.sqrt = function() {
|
|
|
|
throw new Error("Sqrt alg 3 not implemented");
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function alg2_shanks(F) {
|
|
|
|
|
|
|
|
F.sqrt_q = pow$2(F.p, F.m);
|
|
|
|
F.sqrt_e1 = div$2( sub$2(F.sqrt_q, 3) , 4);
|
|
|
|
|
|
|
|
F.sqrt = function(a) {
|
|
|
|
if (this.isZero(a)) return this.zero;
|
|
|
|
|
|
|
|
// Test that have solution
|
|
|
|
const a1 = this.pow(a, this.sqrt_e1);
|
|
|
|
|
|
|
|
const a0 = this.mul(this.square(a1), a);
|
|
|
|
|
|
|
|
if ( this.eq(a0, this.negone) ) return null;
|
|
|
|
|
|
|
|
const x = this.mul(a1, a);
|
|
|
|
|
|
|
|
return F.geq(x, F.zero) ? x : F.neg(x);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function alg10_adj(F) {
|
|
|
|
F.sqrt = function() {
|
|
|
|
throw new Error("Sqrt alg 10 not implemented");
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function alg9_adj(F) {
|
|
|
|
F.sqrt_q = pow$2(F.p, F.m/2);
|
|
|
|
F.sqrt_e34 = div$2( sub$2(F.sqrt_q, 3) , 4);
|
|
|
|
F.sqrt_e12 = div$2( sub$2(F.sqrt_q, 1) , 2);
|
|
|
|
|
|
|
|
F.frobenius = function(n, x) {
|
|
|
|
if ((n%2) == 1) {
|
|
|
|
return F.conjugate(x);
|
|
|
|
} else {
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
F.sqrt = function(a) {
|
|
|
|
const F = this;
|
|
|
|
const a1 = F.pow(a, F.sqrt_e34);
|
|
|
|
const alfa = F.mul(F.square(a1), a);
|
|
|
|
const a0 = F.mul(F.frobenius(1, alfa), alfa);
|
|
|
|
if (F.eq(a0, F.negone)) return null;
|
|
|
|
const x0 = F.mul(a1, a);
|
|
|
|
let x;
|
|
|
|
if (F.eq(alfa, F.negone)) {
|
|
|
|
x = F.mul(x0, [F.F.zero, F.F.one]);
|
|
|
|
} else {
|
|
|
|
const b = F.pow(F.add(F.one, alfa), F.sqrt_e12);
|
|
|
|
x = F.mul(b, x0);
|
|
|
|
}
|
|
|
|
return F.geq(x, F.zero) ? x : F.neg(x);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function alg8_complex(F) {
|
|
|
|
F.sqrt = function() {
|
|
|
|
throw new Error("Sqrt alg 8 not implemented");
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function quarterRound(st, a, b, c, d) {
|
|
|
|
|
|
|
|
st[a] = (st[a] + st[b]) >>> 0;
|
|
|
|
st[d] = (st[d] ^ st[a]) >>> 0;
|
|
|
|
st[d] = ((st[d] << 16) | ((st[d]>>>16) & 0xFFFF)) >>> 0;
|
|
|
|
|
|
|
|
st[c] = (st[c] + st[d]) >>> 0;
|
|
|
|
st[b] = (st[b] ^ st[c]) >>> 0;
|
|
|
|
st[b] = ((st[b] << 12) | ((st[b]>>>20) & 0xFFF)) >>> 0;
|
|
|
|
|
|
|
|
st[a] = (st[a] + st[b]) >>> 0;
|
|
|
|
st[d] = (st[d] ^ st[a]) >>> 0;
|
|
|
|
st[d] = ((st[d] << 8) | ((st[d]>>>24) & 0xFF)) >>> 0;
|
|
|
|
|
|
|
|
st[c] = (st[c] + st[d]) >>> 0;
|
|
|
|
st[b] = (st[b] ^ st[c]) >>> 0;
|
|
|
|
st[b] = ((st[b] << 7) | ((st[b]>>>25) & 0x7F)) >>> 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
function doubleRound(st) {
|
|
|
|
quarterRound(st, 0, 4, 8,12);
|
|
|
|
quarterRound(st, 1, 5, 9,13);
|
|
|
|
quarterRound(st, 2, 6,10,14);
|
|
|
|
quarterRound(st, 3, 7,11,15);
|
|
|
|
|
|
|
|
quarterRound(st, 0, 5,10,15);
|
|
|
|
quarterRound(st, 1, 6,11,12);
|
|
|
|
quarterRound(st, 2, 7, 8,13);
|
|
|
|
quarterRound(st, 3, 4, 9,14);
|
|
|
|
}
|
|
|
|
|
|
|
|
class ChaCha {
|
|
|
|
|
|
|
|
constructor(seed) {
|
|
|
|
seed = seed || [0,0,0,0,0,0,0,0];
|
|
|
|
this.state = [
|
|
|
|
0x61707865,
|
|
|
|
0x3320646E,
|
|
|
|
0x79622D32,
|
|
|
|
0x6B206574,
|
|
|
|
seed[0],
|
|
|
|
seed[1],
|
|
|
|
seed[2],
|
|
|
|
seed[3],
|
|
|
|
seed[4],
|
|
|
|
seed[5],
|
|
|
|
seed[6],
|
|
|
|
seed[7],
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0
|
|
|
|
];
|
|
|
|
this.idx = 16;
|
|
|
|
this.buff = new Array(16);
|
|
|
|
}
|
|
|
|
|
|
|
|
nextU32() {
|
|
|
|
if (this.idx == 16) this.update();
|
|
|
|
return this.buff[this.idx++];
|
|
|
|
}
|
|
|
|
|
|
|
|
nextU64() {
|
|
|
|
return add$2(mul$2(this.nextU32(), 0x100000000), this.nextU32());
|
|
|
|
}
|
|
|
|
|
|
|
|
nextBool() {
|
|
|
|
return (this.nextU32() & 1) == 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
update() {
|
|
|
|
// Copy the state
|
|
|
|
for (let i=0; i<16; i++) this.buff[i] = this.state[i];
|
|
|
|
|
|
|
|
// Apply the rounds
|
|
|
|
for (let i=0; i<10; i++) doubleRound(this.buff);
|
|
|
|
|
|
|
|
// Add to the initial
|
|
|
|
for (let i=0; i<16; i++) this.buff[i] = (this.buff[i] + this.state[i]) >>> 0;
|
|
|
|
|
|
|
|
this.idx = 0;
|
|
|
|
|
|
|
|
this.state[12] = (this.state[12] + 1) >>> 0;
|
|
|
|
if (this.state[12] != 0) return;
|
|
|
|
this.state[13] = (this.state[13] + 1) >>> 0;
|
|
|
|
if (this.state[13] != 0) return;
|
|
|
|
this.state[14] = (this.state[14] + 1) >>> 0;
|
|
|
|
if (this.state[14] != 0) return;
|
|
|
|
this.state[15] = (this.state[15] + 1) >>> 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var crypto = {};
|
|
|
|
|
|
|
|
/* global window */
|
|
|
|
|
|
|
|
function getRandomBytes(n) {
|
|
|
|
let array = new Uint8Array(n);
|
|
|
|
if (typeof window !== "undefined") { // Browser
|
|
|
|
if (typeof window.crypto !== "undefined") { // Supported
|
|
|
|
window.crypto.getRandomValues(array);
|
|
|
|
} else { // fallback
|
|
|
|
for (let i=0; i<n; i++) {
|
|
|
|
array[i] = (Math.random()*4294967296)>>>0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else { // NodeJS
|
|
|
|
crypto.randomFillSync(array);
|
|
|
|
}
|
|
|
|
return array;
|
|
|
|
}
|
|
|
|
|
|
|
|
function getRandomSeed() {
|
|
|
|
const arr = getRandomBytes(32);
|
|
|
|
const arrV = new Uint32Array(arr.buffer);
|
|
|
|
const seed = [];
|
|
|
|
for (let i=0; i<8; i++) {
|
|
|
|
seed.push(arrV[i]);
|
|
|
|
}
|
|
|
|
return seed;
|
|
|
|
}
|
|
|
|
|
|
|
|
let threadRng = null;
|
|
|
|
|
|
|
|
function getThreadRng() {
|
|
|
|
if (threadRng) return threadRng;
|
|
|
|
threadRng = new ChaCha(getRandomSeed());
|
|
|
|
return threadRng;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* global BigInt */
|
|
|
|
|
|
|
|
class ZqField {
|
|
|
|
constructor(p) {
|
|
|
|
this.type="F1";
|
|
|
|
this.one = 1n;
|
|
|
|
this.zero = 0n;
|
|
|
|
this.p = BigInt(p);
|
|
|
|
this.m = 1;
|
|
|
|
this.negone = this.p-1n;
|
|
|
|
this.two = 2n;
|
|
|
|
this.half = this.p >> 1n;
|
|
|
|
this.bitLength = bitLength$2(this.p);
|
|
|
|
this.mask = (1n << BigInt(this.bitLength)) - 1n;
|
|
|
|
|
|
|
|
this.n64 = Math.floor((this.bitLength - 1) / 64)+1;
|
|
|
|
this.n32 = this.n64*2;
|
|
|
|
this.n8 = this.n64*8;
|
|
|
|
this.R = this.e(1n << BigInt(this.n64*64));
|
|
|
|
this.Ri = this.inv(this.R);
|
|
|
|
|
|
|
|
const e = this.negone >> 1n;
|
|
|
|
this.nqr = this.two;
|
|
|
|
let r = this.pow(this.nqr, e);
|
|
|
|
while (!this.eq(r, this.negone)) {
|
|
|
|
this.nqr = this.nqr + 1n;
|
|
|
|
r = this.pow(this.nqr, e);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
this.s = 0;
|
|
|
|
this.t = this.negone;
|
|
|
|
|
|
|
|
while ((this.t & 1n) == 0n) {
|
|
|
|
this.s = this.s + 1;
|
|
|
|
this.t = this.t >> 1n;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.nqr_to_t = this.pow(this.nqr, this.t);
|
|
|
|
|
|
|
|
buildSqrt(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
e(a,b) {
|
|
|
|
let res;
|
|
|
|
if (!b) {
|
|
|
|
res = BigInt(a);
|
|
|
|
} else if (b==16) {
|
|
|
|
res = BigInt("0x"+a);
|
|
|
|
}
|
|
|
|
if (res < 0) {
|
|
|
|
let nres = -res;
|
|
|
|
if (nres >= this.p) nres = nres % this.p;
|
|
|
|
return this.p - nres;
|
|
|
|
} else {
|
|
|
|
return (res>= this.p) ? res%this.p : res;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
add(a, b) {
|
|
|
|
const res = a + b;
|
|
|
|
return res >= this.p ? res-this.p : res;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub(a, b) {
|
|
|
|
return (a >= b) ? a-b : this.p-b+a;
|
|
|
|
}
|
|
|
|
|
|
|
|
neg(a) {
|
|
|
|
return a ? this.p-a : a;
|
|
|
|
}
|
|
|
|
|
|
|
|
mul(a, b) {
|
|
|
|
return (a*b)%this.p;
|
|
|
|
}
|
|
|
|
|
|
|
|
mulScalar(base, s) {
|
|
|
|
return (base * this.e(s)) % this.p;
|
|
|
|
}
|
|
|
|
|
|
|
|
square(a) {
|
|
|
|
return (a*a) % this.p;
|
|
|
|
}
|
|
|
|
|
|
|
|
eq(a, b) {
|
|
|
|
return a==b;
|
|
|
|
}
|
|
|
|
|
|
|
|
neq(a, b) {
|
|
|
|
return a!=b;
|
|
|
|
}
|
|
|
|
|
|
|
|
lt(a, b) {
|
|
|
|
const aa = (a > this.half) ? a - this.p : a;
|
|
|
|
const bb = (b > this.half) ? b - this.p : b;
|
|
|
|
return aa < bb;
|
|
|
|
}
|
|
|
|
|
|
|
|
gt(a, b) {
|
|
|
|
const aa = (a > this.half) ? a - this.p : a;
|
|
|
|
const bb = (b > this.half) ? b - this.p : b;
|
|
|
|
return aa > bb;
|
|
|
|
}
|
|
|
|
|
|
|
|
leq(a, b) {
|
|
|
|
const aa = (a > this.half) ? a - this.p : a;
|
|
|
|
const bb = (b > this.half) ? b - this.p : b;
|
|
|
|
return aa <= bb;
|
|
|
|
}
|
|
|
|
|
|
|
|
geq(a, b) {
|
|
|
|
const aa = (a > this.half) ? a - this.p : a;
|
|
|
|
const bb = (b > this.half) ? b - this.p : b;
|
|
|
|
return aa >= bb;
|
|
|
|
}
|
|
|
|
|
|
|
|
div(a, b) {
|
|
|
|
return this.mul(a, this.inv(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
idiv(a, b) {
|
|
|
|
if (!b) throw new Error("Division by zero");
|
|
|
|
return a / b;
|
|
|
|
}
|
|
|
|
|
|
|
|
inv(a) {
|
|
|
|
if (!a) throw new Error("Division by zero");
|
|
|
|
|
|
|
|
let t = 0n;
|
|
|
|
let r = this.p;
|
|
|
|
let newt = 1n;
|
|
|
|
let newr = a % this.p;
|
|
|
|
while (newr) {
|
|
|
|
let q = r/newr;
|
|
|
|
[t, newt] = [newt, t-q*newt];
|
|
|
|
[r, newr] = [newr, r-q*newr];
|
|
|
|
}
|
|
|
|
if (t<0n) t += this.p;
|
|
|
|
return t;
|
|
|
|
}
|
|
|
|
|
|
|
|
mod(a, b) {
|
|
|
|
return a % b;
|
|
|
|
}
|
|
|
|
|
|
|
|
pow(b, e) {
|
|
|
|
return exp$3(this, b, e);
|
|
|
|
}
|
|
|
|
|
|
|
|
exp(b, e) {
|
|
|
|
return exp$3(this, b, e);
|
|
|
|
}
|
|
|
|
|
|
|
|
band(a, b) {
|
|
|
|
const res = ((a & b) & this.mask);
|
|
|
|
return res >= this.p ? res-this.p : res;
|
|
|
|
}
|
|
|
|
|
|
|
|
bor(a, b) {
|
|
|
|
const res = ((a | b) & this.mask);
|
|
|
|
return res >= this.p ? res-this.p : res;
|
|
|
|
}
|
|
|
|
|
|
|
|
bxor(a, b) {
|
|
|
|
const res = ((a ^ b) & this.mask);
|
|
|
|
return res >= this.p ? res-this.p : res;
|
|
|
|
}
|
|
|
|
|
|
|
|
bnot(a) {
|
|
|
|
const res = a ^ this.mask;
|
|
|
|
return res >= this.p ? res-this.p : res;
|
|
|
|
}
|
|
|
|
|
|
|
|
shl(a, b) {
|
|
|
|
if (Number(b) < this.bitLength) {
|
|
|
|
const res = (a << b) & this.mask;
|
|
|
|
return res >= this.p ? res-this.p : res;
|
|
|
|
} else {
|
|
|
|
const nb = this.p - b;
|
|
|
|
if (Number(nb) < this.bitLength) {
|
|
|
|
return a >> nb;
|
|
|
|
} else {
|
|
|
|
return 0n;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
shr(a, b) {
|
|
|
|
if (Number(b) < this.bitLength) {
|
|
|
|
return a >> b;
|
|
|
|
} else {
|
|
|
|
const nb = this.p - b;
|
|
|
|
if (Number(nb) < this.bitLength) {
|
|
|
|
const res = (a << nb) & this.mask;
|
|
|
|
return res >= this.p ? res-this.p : res;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
land(a, b) {
|
|
|
|
return (a && b) ? 1n : 0n;
|
|
|
|
}
|
|
|
|
|
|
|
|
lor(a, b) {
|
|
|
|
return (a || b) ? 1n : 0n;
|
|
|
|
}
|
|
|
|
|
|
|
|
lnot(a) {
|
|
|
|
return (a) ? 0n : 1n;
|
|
|
|
}
|
|
|
|
|
|
|
|
sqrt_old(n) {
|
|
|
|
|
|
|
|
if (n == 0n) return this.zero;
|
|
|
|
|
|
|
|
// Test that have solution
|
|
|
|
const res = this.pow(n, this.negone >> this.one);
|
|
|
|
if ( res != 1n ) return null;
|
|
|
|
|
|
|
|
let m = this.s;
|
|
|
|
let c = this.nqr_to_t;
|
|
|
|
let t = this.pow(n, this.t);
|
|
|
|
let r = this.pow(n, this.add(this.t, this.one) >> 1n );
|
|
|
|
|
|
|
|
while ( t != 1n ) {
|
|
|
|
let sq = this.square(t);
|
|
|
|
let i = 1;
|
|
|
|
while (sq != 1n ) {
|
|
|
|
i++;
|
|
|
|
sq = this.square(sq);
|
|
|
|
}
|
|
|
|
|
|
|
|
// b = c ^ m-i-1
|
|
|
|
let b = c;
|
|
|
|
for (let j=0; j< m-i-1; j ++) b = this.square(b);
|
|
|
|
|
|
|
|
m = i;
|
|
|
|
c = this.square(b);
|
|
|
|
t = this.mul(t, c);
|
|
|
|
r = this.mul(r, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (r > (this.p >> 1n)) {
|
|
|
|
r = this.neg(r);
|
|
|
|
}
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
normalize(a, b) {
|
|
|
|
a = BigInt(a,b);
|
|
|
|
if (a < 0) {
|
|
|
|
let na = -a;
|
|
|
|
if (na >= this.p) na = na % this.p;
|
|
|
|
return this.p - na;
|
|
|
|
} else {
|
|
|
|
return (a>= this.p) ? a%this.p : a;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
random() {
|
|
|
|
const nBytes = (this.bitLength*2 / 8);
|
|
|
|
let res =0n;
|
|
|
|
for (let i=0; i<nBytes; i++) {
|
|
|
|
res = (res << 8n) + BigInt(getRandomBytes(1)[0]);
|
|
|
|
}
|
|
|
|
return res % this.p;
|
|
|
|
}
|
|
|
|
|
|
|
|
toString(a, base) {
|
|
|
|
let vs;
|
|
|
|
if (a > this.half) {
|
|
|
|
const v = this.p-a;
|
|
|
|
vs = "-"+v.toString(base);
|
|
|
|
} else {
|
|
|
|
vs = a.toString(base);
|
|
|
|
}
|
|
|
|
return vs;
|
|
|
|
}
|
|
|
|
|
|
|
|
isZero(a) {
|
|
|
|
return a == 0n;
|
|
|
|
}
|
|
|
|
|
|
|
|
fromRng(rng) {
|
|
|
|
let v;
|
|
|
|
do {
|
|
|
|
v=0n;
|
|
|
|
for (let i=0; i<this.n64; i++) {
|
|
|
|
v += rng.nextU64() << BigInt(64 *i);
|
|
|
|
}
|
|
|
|
v &= this.mask;
|
|
|
|
} while (v >= this.p);
|
|
|
|
v = (v * this.Ri) % this.p; // Convert from montgomery
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
class ZqField$1 {
|
|
|
|
constructor(p) {
|
|
|
|
this.type="F1";
|
|
|
|
this.one = BigInteger.one;
|
|
|
|
this.zero = BigInteger.zero;
|
|
|
|
this.p = BigInteger(p);
|
|
|
|
this.m = 1;
|
|
|
|
this.negone = this.p.minus(BigInteger.one);
|
|
|
|
this.two = BigInteger(2);
|
|
|
|
this.half = this.p.shiftRight(1);
|
|
|
|
this.bitLength = this.p.bitLength();
|
|
|
|
this.mask = BigInteger.one.shiftLeft(this.bitLength).minus(BigInteger.one);
|
|
|
|
|
|
|
|
this.n64 = Math.floor((this.bitLength - 1) / 64)+1;
|
|
|
|
this.n32 = this.n64*2;
|
|
|
|
this.n8 = this.n64*8;
|
|
|
|
this.R = BigInteger.one.shiftLeft(this.n64*64);
|
|
|
|
this.Ri = this.inv(this.R);
|
|
|
|
|
|
|
|
const e = this.negone.shiftRight(this.one);
|
|
|
|
this.nqr = this.two;
|
|
|
|
let r = this.pow(this.nqr, e);
|
|
|
|
while (!r.equals(this.negone)) {
|
|
|
|
this.nqr = this.nqr.add(this.one);
|
|
|
|
r = this.pow(this.nqr, e);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.s = this.zero;
|
|
|
|
this.t = this.negone;
|
|
|
|
|
|
|
|
while (!this.t.isOdd()) {
|
|
|
|
this.s = this.s.add(this.one);
|
|
|
|
this.t = this.t.shiftRight(this.one);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.nqr_to_t = this.pow(this.nqr, this.t);
|
|
|
|
|
|
|
|
buildSqrt(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
e(a,b) {
|
|
|
|
|
|
|
|
const res = BigInteger(a,b);
|
|
|
|
|
|
|
|
return this.normalize(res);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
add(a, b) {
|
|
|
|
let res = a.add(b);
|
|
|
|
if (res.geq(this.p)) {
|
|
|
|
res = res.minus(this.p);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub(a, b) {
|
|
|
|
if (a.geq(b)) {
|
|
|
|
return a.minus(b);
|
|
|
|
} else {
|
|
|
|
return this.p.minus(b.minus(a));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
neg(a) {
|
|
|
|
if (a.isZero()) return a;
|
|
|
|
return this.p.minus(a);
|
|
|
|
}
|
|
|
|
|
|
|
|
mul(a, b) {
|
|
|
|
return a.times(b).mod(this.p);
|
|
|
|
}
|
|
|
|
|
|
|
|
mulScalar(base, s) {
|
|
|
|
return base.times(BigInteger(s)).mod(this.p);
|
|
|
|
}
|
|
|
|
|
|
|
|
square(a) {
|
|
|
|
return a.square().mod(this.p);
|
|
|
|
}
|
|
|
|
|
|
|
|
eq(a, b) {
|
|
|
|
return a.eq(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
neq(a, b) {
|
|
|
|
return a.neq(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
lt(a, b) {
|
|
|
|
const aa = a.gt(this.half) ? a.minus(this.p) : a;
|
|
|
|
const bb = b.gt(this.half) ? b.minus(this.p) : b;
|
|
|
|
return aa.lt(bb);
|
|
|
|
}
|
|
|
|
|
|
|
|
gt(a, b) {
|
|
|
|
const aa = a.gt(this.half) ? a.minus(this.p) : a;
|
|
|
|
const bb = b.gt(this.half) ? b.minus(this.p) : b;
|
|
|
|
return aa.gt(bb);
|
|
|
|
}
|
|
|
|
|
|
|
|
leq(a, b) {
|
|
|
|
const aa = a.gt(this.half) ? a.minus(this.p) : a;
|
|
|
|
const bb = b.gt(this.half) ? b.minus(this.p) : b;
|
|
|
|
return aa.leq(bb);
|
|
|
|
}
|
|
|
|
|
|
|
|
geq(a, b) {
|
|
|
|
const aa = a.gt(this.half) ? a.minus(this.p) : a;
|
|
|
|
const bb = b.gt(this.half) ? b.minus(this.p) : b;
|
|
|
|
return aa.geq(bb);
|
|
|
|
}
|
|
|
|
|
|
|
|
div(a, b) {
|
|
|
|
if (b.isZero()) throw new Error("Division by zero");
|
|
|
|
return a.times(b.modInv(this.p)).mod(this.p);
|
|
|
|
}
|
|
|
|
|
|
|
|
idiv(a, b) {
|
|
|
|
if (b.isZero()) throw new Error("Division by zero");
|
|
|
|
return a.divide(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
inv(a) {
|
|
|
|
if (a.isZero()) throw new Error("Division by zero");
|
|
|
|
return a.modInv(this.p);
|
|
|
|
}
|
|
|
|
|
|
|
|
mod(a, b) {
|
|
|
|
return a.mod(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
pow(a, b) {
|
|
|
|
return a.modPow(b, this.p);
|
|
|
|
}
|
|
|
|
|
|
|
|
exp(a, b) {
|
|
|
|
return a.modPow(b, this.p);
|
|
|
|
}
|
|
|
|
|
|
|
|
band(a, b) {
|
|
|
|
return a.and(b).and(this.mask).mod(this.p);
|
|
|
|
}
|
|
|
|
|
|
|
|
bor(a, b) {
|
|
|
|
return a.or(b).and(this.mask).mod(this.p);
|
|
|
|
}
|
|
|
|
|
|
|
|
bxor(a, b) {
|
|
|
|
return a.xor(b).and(this.mask).mod(this.p);
|
|
|
|
}
|
|
|
|
|
|
|
|
bnot(a) {
|
|
|
|
return a.xor(this.mask).mod(this.p);
|
|
|
|
}
|
|
|
|
|
|
|
|
shl(a, b) {
|
|
|
|
if (b.lt(this.bitLength)) {
|
|
|
|
return a.shiftLeft(b).and(this.mask).mod(this.p);
|
|
|
|
} else {
|
|
|
|
const nb = this.p.minus(b);
|
|
|
|
if (nb.lt(this.bitLength)) {
|
|
|
|
return this.shr(a, nb);
|
|
|
|
} else {
|
|
|
|
return BigInteger.zero;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
shr(a, b) {
|
|
|
|
if (b.lt(this.bitLength)) {
|
|
|
|
return a.shiftRight(b);
|
|
|
|
} else {
|
|
|
|
const nb = this.p.minus(b);
|
|
|
|
if (nb.lt(this.bitLength)) {
|
|
|
|
return this.shl(a, nb);
|
|
|
|
} else {
|
|
|
|
return BigInteger.zero;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
land(a, b) {
|
|
|
|
return (a.isZero() || b.isZero()) ? BigInteger.zero : BigInteger.one;
|
|
|
|
}
|
|
|
|
|
|
|
|
lor(a, b) {
|
|
|
|
return (a.isZero() && b.isZero()) ? BigInteger.zero : BigInteger.one;
|
|
|
|
}
|
|
|
|
|
|
|
|
lnot(a) {
|
|
|
|
return a.isZero() ? BigInteger.one : BigInteger.zero;
|
|
|
|
}
|
|
|
|
|
|
|
|
sqrt_old(n) {
|
|
|
|
|
|
|
|
if (n.equals(this.zero)) return this.zero;
|
|
|
|
|
|
|
|
// Test that have solution
|
|
|
|
const res = this.pow(n, this.negone.shiftRight(this.one));
|
|
|
|
if (!res.equals(this.one)) return null;
|
|
|
|
|
|
|
|
let m = parseInt(this.s);
|
|
|
|
let c = this.nqr_to_t;
|
|
|
|
let t = this.pow(n, this.t);
|
|
|
|
let r = this.pow(n, this.add(this.t, this.one).shiftRight(this.one) );
|
|
|
|
|
|
|
|
while (!t.equals(this.one)) {
|
|
|
|
let sq = this.square(t);
|
|
|
|
let i = 1;
|
|
|
|
while (!sq.equals(this.one)) {
|
|
|
|
i++;
|
|
|
|
sq = this.square(sq);
|
|
|
|
}
|
|
|
|
|
|
|
|
// b = c ^ m-i-1
|
|
|
|
let b = c;
|
|
|
|
for (let j=0; j< m-i-1; j ++) b = this.square(b);
|
|
|
|
|
|
|
|
m = i;
|
|
|
|
c = this.square(b);
|
|
|
|
t = this.mul(t, c);
|
|
|
|
r = this.mul(r, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (r.greater(this.p.shiftRight(this.one))) {
|
|
|
|
r = this.neg(r);
|
|
|
|
}
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
normalize(a) {
|
|
|
|
a = BigInteger(a);
|
|
|
|
if (a.isNegative()) {
|
|
|
|
return this.p.minus(a.abs().mod(this.p));
|
|
|
|
} else {
|
|
|
|
return a.mod(this.p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
random() {
|
|
|
|
let res = BigInteger(0);
|
|
|
|
let n = BigInteger(this.p.square());
|
|
|
|
while (!n.isZero()) {
|
|
|
|
res = res.shiftLeft(8).add(BigInteger(getRandomBytes(1)[0]));
|
|
|
|
n = n.shiftRight(8);
|
|
|
|
}
|
|
|
|
return res.mod(this.p);
|
|
|
|
}
|
|
|
|
|
|
|
|
toString(a, base) {
|
|
|
|
let vs;
|
|
|
|
if (!a.lesserOrEquals(this.p.shiftRight(BigInteger(1)))) {
|
|
|
|
const v = this.p.minus(a);
|
|
|
|
vs = "-"+v.toString(base);
|
|
|
|
} else {
|
|
|
|
vs = a.toString(base);
|
|
|
|
}
|
|
|
|
|
|
|
|
return vs;
|
|
|
|
}
|
|
|
|
|
|
|
|
isZero(a) {
|
|
|
|
return a.isZero();
|
|
|
|
}
|
|
|
|
|
|
|
|
fromRng(rng) {
|
|
|
|
let v;
|
|
|
|
do {
|
|
|
|
v = BigInteger(0);
|
|
|
|
for (let i=0; i<this.n64; i++) {
|
|
|
|
v = v.add(v, rng.nextU64().shiftLeft(64*i));
|
|
|
|
}
|
|
|
|
v = v.and(this.mask);
|
|
|
|
} while (v.geq(this.p));
|
|
|
|
v = v.times(this.Ri).mod(this.q);
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const supportsNativeBigInt$1 = typeof BigInt === "function";
|
|
|
|
let _F1Field;
|
|
|
|
if (supportsNativeBigInt$1) {
|
|
|
|
_F1Field = ZqField;
|
|
|
|
} else {
|
|
|
|
_F1Field = ZqField$1;
|
|
|
|
}
|
|
|
|
|
|
|
|
class F1Field extends _F1Field {
|
|
|
|
|
|
|
|
// Returns a buffer with Little Endian Representation
|
|
|
|
toRprLE(buff, o, e) {
|
|
|
|
toRprLE(buff, o, e, this.n64*8);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns a buffer with Big Endian Representation
|
|
|
|
toRprBE(buff, o, e) {
|
|
|
|
toRprBE(buff, o, e, this.n64*8);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns a buffer with Big Endian Montgomery Representation
|
|
|
|
toRprBEM(buff, o, e) {
|
|
|
|
return this.toRprBE(buff, o, this.mul(this.R, e));
|
|
|
|
}
|
|
|
|
|
|
|
|
toRprLEM(buff, o, e) {
|
|
|
|
return this.toRprLE(buff, o, this.mul(this.R, e));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Pases a buffer with Little Endian Representation
|
|
|
|
fromRprLE(buff, o) {
|
|
|
|
return fromRprLE(buff, o, this.n8);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Pases a buffer with Big Endian Representation
|
|
|
|
fromRprBE(buff, o) {
|
|
|
|
return fromRprBE(buff, o, this.n8);
|
|
|
|
}
|
|
|
|
|
|
|
|
fromRprLEM(buff, o) {
|
|
|
|
return this.mul(this.fromRprLE(buff, o), this.Ri);
|
|
|
|
}
|
|
|
|
|
|
|
|
fromRprBEM(buff, o) {
|
|
|
|
return this.mul(this.fromRprBE(buff, o), this.Ri);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Copyright 2018 0kims association.
|
|
|
|
|
|
|
|
This file is part of snarkjs.
|
|
|
|
|
|
|
|
snarkjs 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.
|
|
|
|
|
|
|
|
snarkjs 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
|
|
|
|
snarkjs. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
class F2Field {
|
|
|
|
constructor(F, nonResidue) {
|
|
|
|
this.type="F2";
|
|
|
|
this.F = F;
|
|
|
|
this.zero = [this.F.zero, this.F.zero];
|
|
|
|
this.one = [this.F.one, this.F.zero];
|
|
|
|
this.negone = this.neg(this.one);
|
|
|
|
this.nonResidue = nonResidue;
|
|
|
|
this.m = F.m*2;
|
|
|
|
this.p = F.p;
|
|
|
|
this.n64 = F.n64*2;
|
|
|
|
this.n32 = this.n64*2;
|
|
|
|
this.n8 = this.n64*8;
|
|
|
|
|
|
|
|
buildSqrt(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
_mulByNonResidue(a) {
|
|
|
|
return this.F.mul(this.nonResidue, a);
|
|
|
|
}
|
|
|
|
|
|
|
|
copy(a) {
|
|
|
|
return [this.F.copy(a[0]), this.F.copy(a[1])];
|
|
|
|
}
|
|
|
|
|
|
|
|
add(a, b) {
|
|
|
|
return [
|
|
|
|
this.F.add(a[0], b[0]),
|
|
|
|
this.F.add(a[1], b[1])
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
double(a) {
|
|
|
|
return this.add(a,a);
|
|
|
|
}
|
|
|
|
|
|
|
|
sub(a, b) {
|
|
|
|
return [
|
|
|
|
this.F.sub(a[0], b[0]),
|
|
|
|
this.F.sub(a[1], b[1])
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
neg(a) {
|
|
|
|
return this.sub(this.zero, a);
|
|
|
|
}
|
|
|
|
|
|
|
|
conjugate(a) {
|
|
|
|
return [
|
|
|
|
a[0],
|
|
|
|
this.F.neg(a[1])
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
mul(a, b) {
|
|
|
|
const aA = this.F.mul(a[0] , b[0]);
|
|
|
|
const bB = this.F.mul(a[1] , b[1]);
|
|
|
|
|
|
|
|
return [
|
|
|
|
this.F.add( aA , this._mulByNonResidue(bB)),
|
|
|
|
this.F.sub(
|
|
|
|
this.F.mul(
|
|
|
|
this.F.add(a[0], a[1]),
|
|
|
|
this.F.add(b[0], b[1])),
|
|
|
|
this.F.add(aA, bB))];
|
|
|
|
}
|
|
|
|
|
|
|
|
inv(a) {
|
|
|
|
const t0 = this.F.square(a[0]);
|
|
|
|
const t1 = this.F.square(a[1]);
|
|
|
|
const t2 = this.F.sub(t0, this._mulByNonResidue(t1));
|
|
|
|
const t3 = this.F.inv(t2);
|
|
|
|
return [
|
|
|
|
this.F.mul(a[0], t3),
|
|
|
|
this.F.neg(this.F.mul( a[1], t3)) ];
|
|
|
|
}
|
|
|
|
|
|
|
|
div(a, b) {
|
|
|
|
return this.mul(a, this.inv(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
square(a) {
|
|
|
|
const ab = this.F.mul(a[0] , a[1]);
|
|
|
|
|
|
|
|
/*
|
|
|
|
[
|
|
|
|
(a + b) * (a + non_residue * b) - ab - non_residue * ab,
|
|
|
|
ab + ab
|
|
|
|
];
|
|
|
|
*/
|
|
|
|
|
|
|
|
return [
|
|
|
|
this.F.sub(
|
|
|
|
this.F.mul(
|
|
|
|
this.F.add(a[0], a[1]) ,
|
|
|
|
this.F.add(
|
|
|
|
a[0] ,
|
|
|
|
this._mulByNonResidue(a[1]))),
|
|
|
|
this.F.add(
|
|
|
|
ab,
|
|
|
|
this._mulByNonResidue(ab))),
|
|
|
|
this.F.add(ab, ab)
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
isZero(a) {
|
|
|
|
return this.F.isZero(a[0]) && this.F.isZero(a[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
eq(a, b) {
|
|
|
|
return this.F.eq(a[0], b[0]) && this.F.eq(a[1], b[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
mulScalar(base, e) {
|
|
|
|
return mulScalar(this, base, e);
|
|
|
|
}
|
|
|
|
|
|
|
|
pow(base, e) {
|
|
|
|
return exp$3(this, base, e);
|
|
|
|
}
|
|
|
|
|
|
|
|
exp(base, e) {
|
|
|
|
return exp$3(this, base, e);
|
|
|
|
}
|
|
|
|
|
|
|
|
toString(a) {
|
|
|
|
return `[ ${this.F.toString(a[0])} , ${this.F.toString(a[1])} ]`;
|
|
|
|
}
|
|
|
|
|
|
|
|
fromRng(rng) {
|
|
|
|
const c0 = this.F.fromRng(rng);
|
|
|
|
const c1 = this.F.fromRng(rng);
|
|
|
|
return [c0, c1];
|
|
|
|
}
|
|
|
|
|
|
|
|
gt(a, b) {
|
|
|
|
if (this.F.gt(a[0], b[0])) return true;
|
|
|
|
if (this.F.gt(b[0], a[0])) return false;
|
|
|
|
if (this.F.gt(a[1], b[1])) return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
geq(a, b) {
|
|
|
|
return this.gt(a, b) || this.eq(a, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
lt(a, b) {
|
|
|
|
return !this.geq(a,b);
|
|
|
|
}
|
|
|
|
|
|
|
|
leq(a, b) {
|
|
|
|
return !this.gt(a,b);
|
|
|
|
}
|
|
|
|
|
|
|
|
neq(a, b) {
|
|
|
|
return !this.eq(a,b);
|
|
|
|
}
|
|
|
|
|
|
|
|
random() {
|
|
|
|
return [this.F.random(), this.F.random()];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
toRprLE(buff, o, e) {
|
|
|
|
this.F.toRprLE(buff, o, e[0]);
|
|
|
|
this.F.toRprLE(buff, o+this.F.n8, e[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
toRprBE(buff, o, e) {
|
|
|
|
this.F.toRprBE(buff, o, e[1]);
|
|
|
|
this.F.toRprBE(buff, o+this.F.n8, e[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
toRprLEM(buff, o, e) {
|
|
|
|
this.F.toRprLEM(buff, o, e[0]);
|
|
|
|
this.F.toRprLEM(buff, o+this.F.n8, e[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
toRprBEM(buff, o, e) {
|
|
|
|
this.F.toRprBEM(buff, o, e[1]);
|
|
|
|
this.F.toRprBEM(buff, o+this.F.n8, e[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
fromRprLE(buff, o) {
|
|
|
|
o = o || 0;
|
|
|
|
const c0 = this.F.fromRprLE(buff, o);
|
|
|
|
const c1 = this.F.fromRprLE(buff, o+this.F.n8);
|
|
|
|
return [c0, c1];
|
|
|
|
}
|
|
|
|
|
|
|
|
fromRprBE(buff, o) {
|
|
|
|
o = o || 0;
|
|
|
|
const c1 = this.F.fromRprBE(buff, o);
|
|
|
|
const c0 = this.F.fromRprBE(buff, o+this.F.n8);
|
|
|
|
return [c0, c1];
|
|
|
|
}
|
|
|
|
|
|
|
|
fromRprLEM(buff, o) {
|
|
|
|
o = o || 0;
|
|
|
|
const c0 = this.F.fromRprLEM(buff, o);
|
|
|
|
const c1 = this.F.fromRprLEM(buff, o+this.F.n8);
|
|
|
|
return [c0, c1];
|
|
|
|
}
|
|
|
|
|
|
|
|
fromRprBEM(buff, o) {
|
|
|
|
o = o || 0;
|
|
|
|
const c1 = this.F.fromRprBEM(buff, o);
|
|
|
|
const c0 = this.F.fromRprBEM(buff, o+this.F.n8);
|
|
|
|
return [c0, c1];
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Copyright 2018 0kims association.
|
|
|
|
|
|
|
|
This file is part of snarkjs.
|
|
|
|
|
|
|
|
snarkjs 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.
|
|
|
|
|
|
|
|
snarkjs 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
|
|
|
|
snarkjs. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
class F3Field {
|
|
|
|
constructor(F, nonResidue) {
|
|
|
|
this.type="F3";
|
|
|
|
this.F = F;
|
|
|
|
this.zero = [this.F.zero, this.F.zero, this.F.zero];
|
|
|
|
this.one = [this.F.one, this.F.zero, this.F.zero];
|
|
|
|
this.negone = this.neg(this.one);
|
|
|
|
this.nonResidue = nonResidue;
|
|
|
|
this.m = F.m*3;
|
|
|
|
this.p = F.p;
|
|
|
|
this.n64 = F.n64*3;
|
|
|
|
this.n32 = this.n64*2;
|
|
|
|
this.n8 = this.n64*8;
|
|
|
|
}
|
|
|
|
|
|
|
|
_mulByNonResidue(a) {
|
|
|
|
return this.F.mul(this.nonResidue, a);
|
|
|
|
}
|
|
|
|
|
|
|
|
copy(a) {
|
|
|
|
return [this.F.copy(a[0]), this.F.copy(a[1]), this.F.copy(a[2])];
|
|
|
|
}
|
|
|
|
|
|
|
|
add(a, b) {
|
|
|
|
return [
|
|
|
|
this.F.add(a[0], b[0]),
|
|
|
|
this.F.add(a[1], b[1]),
|
|
|
|
this.F.add(a[2], b[2])
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
double(a) {
|
|
|
|
return this.add(a,a);
|
|
|
|
}
|
|
|
|
|
|
|
|
sub(a, b) {
|
|
|
|
return [
|
|
|
|
this.F.sub(a[0], b[0]),
|
|
|
|
this.F.sub(a[1], b[1]),
|
|
|
|
this.F.sub(a[2], b[2])
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
neg(a) {
|
|
|
|
return this.sub(this.zero, a);
|
|
|
|
}
|
|
|
|
|
|
|
|
mul(a, b) {
|
|
|
|
|
|
|
|
const aA = this.F.mul(a[0] , b[0]);
|
|
|
|
const bB = this.F.mul(a[1] , b[1]);
|
|
|
|
const cC = this.F.mul(a[2] , b[2]);
|
|
|
|
|
|
|
|
return [
|
|
|
|
this.F.add(
|
|
|
|
aA,
|
|
|
|
this._mulByNonResidue(
|
|
|
|
this.F.sub(
|
|
|
|
this.F.mul(
|
|
|
|
this.F.add(a[1], a[2]),
|
|
|
|
this.F.add(b[1], b[2])),
|
|
|
|
this.F.add(bB, cC)))), // aA + non_residue*((b+c)*(B+C)-bB-cC),
|
|
|
|
|
|
|
|
this.F.add(
|
|
|
|
this.F.sub(
|
|
|
|
this.F.mul(
|
|
|
|
this.F.add(a[0], a[1]),
|
|
|
|
this.F.add(b[0], b[1])),
|
|
|
|
this.F.add(aA, bB)),
|
|
|
|
this._mulByNonResidue( cC)), // (a+b)*(A+B)-aA-bB+non_residue*cC
|
|
|
|
|
|
|
|
this.F.add(
|
|
|
|
this.F.sub(
|
|
|
|
this.F.mul(
|
|
|
|
this.F.add(a[0], a[2]),
|
|
|
|
this.F.add(b[0], b[2])),
|
|
|
|
this.F.add(aA, cC)),
|
|
|
|
bB)]; // (a+c)*(A+C)-aA+bB-cC)
|
|
|
|
}
|
|
|
|
|
|
|
|
inv(a) {
|
|
|
|
const t0 = this.F.square(a[0]); // t0 = a^2 ;
|
|
|
|
const t1 = this.F.square(a[1]); // t1 = b^2 ;
|
|
|
|
const t2 = this.F.square(a[2]); // t2 = c^2;
|
|
|
|
const t3 = this.F.mul(a[0],a[1]); // t3 = ab
|
|
|
|
const t4 = this.F.mul(a[0],a[2]); // t4 = ac
|
|
|
|
const t5 = this.F.mul(a[1],a[2]); // t5 = bc;
|
|
|
|
// c0 = t0 - non_residue * t5;
|
|
|
|
const c0 = this.F.sub(t0, this._mulByNonResidue(t5));
|
|
|
|
// c1 = non_residue * t2 - t3;
|
|
|
|
const c1 = this.F.sub(this._mulByNonResidue(t2), t3);
|
|
|
|
const c2 = this.F.sub(t1, t4); // c2 = t1-t4
|
|
|
|
|
|
|
|
// t6 = (a * c0 + non_residue * (c * c1 + b * c2)).inv();
|
|
|
|
const t6 =
|
|
|
|
this.F.inv(
|
|
|
|
this.F.add(
|
|
|
|
this.F.mul(a[0], c0),
|
|
|
|
this._mulByNonResidue(
|
|
|
|
this.F.add(
|
|
|
|
this.F.mul(a[2], c1),
|
|
|
|
this.F.mul(a[1], c2)))));
|
|
|
|
|
|
|
|
return [
|
|
|
|
this.F.mul(t6, c0), // t6*c0
|
|
|
|
this.F.mul(t6, c1), // t6*c1
|
|
|
|
this.F.mul(t6, c2)]; // t6*c2
|
|
|
|
}
|
|
|
|
|
|
|
|
div(a, b) {
|
|
|
|
return this.mul(a, this.inv(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
square(a) {
|
|
|
|
const s0 = this.F.square(a[0]); // s0 = a^2
|
|
|
|
const ab = this.F.mul(a[0], a[1]); // ab = a*b
|
|
|
|
const s1 = this.F.add(ab, ab); // s1 = 2ab;
|
|
|
|
const s2 = this.F.square(
|
|
|
|
this.F.add(this.F.sub(a[0],a[1]), a[2])); // s2 = (a - b + c)^2;
|
|
|
|
const bc = this.F.mul(a[1],a[2]); // bc = b*c
|
|
|
|
const s3 = this.F.add(bc, bc); // s3 = 2*bc
|
|
|
|
const s4 = this.F.square(a[2]); // s4 = c^2
|
|
|
|
|
|
|
|
|
|
|
|
return [
|
|
|
|
this.F.add(
|
|
|
|
s0,
|
|
|
|
this._mulByNonResidue(s3)), // s0 + non_residue * s3,
|
|
|
|
this.F.add(
|
|
|
|
s1,
|
|
|
|
this._mulByNonResidue(s4)), // s1 + non_residue * s4,
|
|
|
|
this.F.sub(
|
|
|
|
this.F.add( this.F.add(s1, s2) , s3 ),
|
|
|
|
this.F.add(s0, s4))]; // s1 + s2 + s3 - s0 - s4
|
|
|
|
}
|
|
|
|
|
|
|
|
isZero(a) {
|
|
|
|
return this.F.isZero(a[0]) && this.F.isZero(a[1]) && this.F.isZero(a[2]);
|
|
|
|
}
|
|
|
|
|
|
|
|
eq(a, b) {
|
|
|
|
return this.F.eq(a[0], b[0]) && this.F.eq(a[1], b[1]) && this.F.eq(a[2], b[2]);
|
|
|
|
}
|
|
|
|
|
|
|
|
affine(a) {
|
|
|
|
return [this.F.affine(a[0]), this.F.affine(a[1]), this.F.affine(a[2])];
|
|
|
|
}
|
|
|
|
|
|
|
|
mulScalar(base, e) {
|
|
|
|
return mulScalar(this, base, e);
|
|
|
|
}
|
|
|
|
|
|
|
|
pow(base, e) {
|
|
|
|
return exp$3(this, base, e);
|
|
|
|
}
|
|
|
|
|
|
|
|
exp(base, e) {
|
|
|
|
return exp$3(this, base, e);
|
|
|
|
}
|
|
|
|
|
|
|
|
toString(a) {
|
|
|
|
return `[ ${this.F.toString(a[0])} , ${this.F.toString(a[1])}, ${this.F.toString(a[2])} ]`;
|
|
|
|
}
|
|
|
|
|
|
|
|
fromRng(rng) {
|
|
|
|
const c0 = this.F.fromRng(rng);
|
|
|
|
const c1 = this.F.fromRng(rng);
|
|
|
|
const c2 = this.F.fromRng(rng);
|
|
|
|
return [c0, c1, c2];
|
|
|
|
}
|
|
|
|
|
|
|
|
gt(a, b) {
|
|
|
|
if (this.F.gt(a[0], b[0])) return true;
|
|
|
|
if (this.F.gt(b[0], a[0])) return false;
|
|
|
|
if (this.F.gt(a[1], b[1])) return true;
|
|
|
|
if (this.F.gt(b[1], a[1])) return false;
|
|
|
|
if (this.F.gt(a[2], b[2])) return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
geq(a, b) {
|
|
|
|
return this.gt(a, b) || this.eq(a, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
lt(a, b) {
|
|
|
|
return !this.geq(a,b);
|
|
|
|
}
|
|
|
|
|
|
|
|
leq(a, b) {
|
|
|
|
return !this.gt(a,b);
|
|
|
|
}
|
|
|
|
|
|
|
|
neq(a, b) {
|
|
|
|
return !this.eq(a,b);
|
|
|
|
}
|
|
|
|
|
|
|
|
random() {
|
|
|
|
return [this.F.random(), this.F.random(), this.F.random()];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
toRprLE(buff, o, e) {
|
|
|
|
this.F.toRprLE(buff, o, e[0]);
|
|
|
|
this.F.toRprLE(buff, o+this.F.n8, e[1]);
|
|
|
|
this.F.toRprLE(buff, o+this.F.n8*2, e[2]);
|
|
|
|
}
|
|
|
|
|
|
|
|
toRprBE(buff, o, e) {
|
|
|
|
this.F.toRprBE(buff, o, e[2]);
|
|
|
|
this.F.toRprBE(buff, o+this.F.n8, e[1]);
|
|
|
|
this.F.toRprBE(buff, o+this.F.n8*2, e[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
toRprLEM(buff, o, e) {
|
|
|
|
this.F.toRprLEM(buff, o, e[0]);
|
|
|
|
this.F.toRprLEM(buff, o+this.F.n8, e[1]);
|
|
|
|
this.F.toRprLEM(buff, o+this.F.n8*2, e[2]);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
toRprBEM(buff, o, e) {
|
|
|
|
this.F.toRprBEM(buff, o, e[2]);
|
|
|
|
this.F.toRprBEM(buff, o+this.F.n8, e[1]);
|
|
|
|
this.F.toRprBEM(buff, o+this.F.n8*2, e[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
fromRprLE(buff, o) {
|
|
|
|
o = o || 0;
|
|
|
|
const c0 = this.F.fromRprLE(buff, o);
|
|
|
|
const c1 = this.F.fromRprLE(buff, o+this.n8);
|
|
|
|
const c2 = this.F.fromRprLE(buff, o+this.n8*2);
|
|
|
|
return [c0, c1, c2];
|
|
|
|
}
|
|
|
|
|
|
|
|
fromRprBE(buff, o) {
|
|
|
|
o = o || 0;
|
|
|
|
const c2 = this.F.fromRprBE(buff, o);
|
|
|
|
const c1 = this.F.fromRprBE(buff, o+this.n8);
|
|
|
|
const c0 = this.F.fromRprBE(buff, o+this.n8*2);
|
|
|
|
return [c0, c1, c2];
|
|
|
|
}
|
|
|
|
|
|
|
|
fromRprLEM(buff, o) {
|
|
|
|
o = o || 0;
|
|
|
|
const c0 = this.F.fromRprLEM(buff, o);
|
|
|
|
const c1 = this.F.fromRprLEM(buff, o+this.n8);
|
|
|
|
const c2 = this.F.fromRprLEM(buff, o+this.n8*2);
|
|
|
|
return [c0, c1, c2];
|
|
|
|
}
|
|
|
|
|
|
|
|
fromRprBEM(buff, o) {
|
|
|
|
o = o || 0;
|
|
|
|
const c2 = this.F.fromRprBEM(buff, o);
|
|
|
|
const c1 = this.F.fromRprBEM(buff, o+this.n8);
|
|
|
|
const c0 = this.F.fromRprBEM(buff, o+this.n8*2);
|
|
|
|
return [c0, c1, c2];
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Copyright 2018 0kims association.
|
|
|
|
|
|
|
|
This file is part of snarkjs.
|
|
|
|
|
|
|
|
snarkjs 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.
|
|
|
|
|
|
|
|
snarkjs 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
|
|
|
|
snarkjs. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
function isGreatest(F, a) {
|
|
|
|
if (Array.isArray(a)) {
|
|
|
|
for (let i=a.length-1; i>=0; i--) {
|
|
|
|
if (!F.F.isZero(a[i])) {
|
|
|
|
return isGreatest(F.F, a[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
const na = F.neg(a);
|
|
|
|
return gt$2(a, na);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class EC {
|
|
|
|
|
|
|
|
constructor(F, g) {
|
|
|
|
this.F = F;
|
|
|
|
this.g = g;
|
|
|
|
if (this.g.length == 2) this.g[2] = this.F.one;
|
|
|
|
this.zero = [this.F.zero, this.F.one, this.F.zero];
|
|
|
|
}
|
|
|
|
|
|
|
|
add(p1, p2) {
|
|
|
|
|
|
|
|
const F = this.F;
|
|
|
|
|
|
|
|
if (this.eq(p1, this.zero)) return p2;
|
|
|
|
if (this.eq(p2, this.zero)) return p1;
|
|
|
|
|
|
|
|
const res = new Array(3);
|
|
|
|
|
|
|
|
const Z1Z1 = F.square( p1[2] );
|
|
|
|
const Z2Z2 = F.square( p2[2] );
|
|
|
|
|
|
|
|
const U1 = F.mul( p1[0] , Z2Z2 ); // U1 = X1 * Z2Z2
|
|
|
|
const U2 = F.mul( p2[0] , Z1Z1 ); // U2 = X2 * Z1Z1
|
|
|
|
|
|
|
|
const Z1_cubed = F.mul( p1[2] , Z1Z1);
|
|
|
|
const Z2_cubed = F.mul( p2[2] , Z2Z2);
|
|
|
|
|
|
|
|
const S1 = F.mul( p1[1] , Z2_cubed); // S1 = Y1 * Z2 * Z2Z2
|
|
|
|
const S2 = F.mul( p2[1] , Z1_cubed); // S2 = Y2 * Z1 * Z1Z1
|
|
|
|
|
|
|
|
if (F.eq(U1,U2) && F.eq(S1,S2)) {
|
|
|
|
return this.double(p1);
|
|
|
|
}
|
|
|
|
|
|
|
|
const H = F.sub( U2 , U1 ); // H = U2-U1
|
|
|
|
|
|
|
|
const S2_minus_S1 = F.sub( S2 , S1 );
|
|
|
|
|
|
|
|
const I = F.square( F.add(H,H) ); // I = (2 * H)^2
|
|
|
|
const J = F.mul( H , I ); // J = H * I
|
|
|
|
|
|
|
|
const r = F.add( S2_minus_S1 , S2_minus_S1 ); // r = 2 * (S2-S1)
|
|
|
|
const V = F.mul( U1 , I ); // V = U1 * I
|
|
|
|
|
|
|
|
res[0] =
|
|
|
|
F.sub(
|
|
|
|
F.sub( F.square(r) , J ),
|
|
|
|
F.add( V , V )); // X3 = r^2 - J - 2 * V
|
|
|
|
|
|
|
|
const S1_J = F.mul( S1 , J );
|
|
|
|
|
|
|
|
res[1] =
|
|
|
|
F.sub(
|
|
|
|
F.mul( r , F.sub(V,res[0])),
|
|
|
|
F.add( S1_J,S1_J )); // Y3 = r * (V-X3)-2 S1 J
|
|
|
|
|
|
|
|
res[2] =
|
|
|
|
F.mul(
|
|
|
|
H,
|
|
|
|
F.sub(
|
|
|
|
F.square( F.add(p1[2],p2[2]) ),
|
|
|
|
F.add( Z1Z1 , Z2Z2 ))); // Z3 = ((Z1+Z2)^2-Z1Z1-Z2Z2) * H
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
neg(p) {
|
|
|
|
return [p[0], this.F.neg(p[1]), p[2]];
|
|
|
|
}
|
|
|
|
|
|
|
|
sub(a, b) {
|
|
|
|
return this.add(a, this.neg(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
double(p) {
|
|
|
|
const F = this.F;
|
|
|
|
|
|
|
|
const res = new Array(3);
|
|
|
|
|
|
|
|
if (this.eq(p, this.zero)) return p;
|
|
|
|
|
|
|
|
const A = F.square( p[0] ); // A = X1^2
|
|
|
|
const B = F.square( p[1] ); // B = Y1^2
|
|
|
|
const C = F.square( B ); // C = B^2
|
|
|
|
|
|
|
|
let D =
|
|
|
|
F.sub(
|
|
|
|
F.square( F.add(p[0] , B )),
|
|
|
|
F.add( A , C));
|
|
|
|
D = F.add(D,D); // D = 2 * ((X1 + B)^2 - A - C)
|
|
|
|
|
|
|
|
const E = F.add( F.add(A,A), A); // E = 3 * A
|
|
|
|
const FF =F.square( E ); // F = E^2
|
|
|
|
|
|
|
|
res[0] = F.sub( FF , F.add(D,D) ); // X3 = F - 2 D
|
|
|
|
|
|
|
|
let eightC = F.add( C , C );
|
|
|
|
eightC = F.add( eightC , eightC );
|
|
|
|
eightC = F.add( eightC , eightC );
|
|
|
|
|
|
|
|
res[1] =
|
|
|
|
F.sub(
|
|
|
|
F.mul(
|
|
|
|
E,
|
|
|
|
F.sub( D, res[0] )),
|
|
|
|
eightC); // Y3 = E * (D - X3) - 8 * C
|
|
|
|
|
|
|
|
const Y1Z1 = F.mul( p[1] , p[2] );
|
|
|
|
res[2] = F.add( Y1Z1 , Y1Z1 ); // Z3 = 2 * Y1 * Z1
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
timesScalar(base, e) {
|
|
|
|
return mulScalar(this, base, e);
|
|
|
|
}
|
|
|
|
|
|
|
|
mulScalar(base, e) {
|
|
|
|
return mulScalar(this, base, e);
|
|
|
|
}
|
|
|
|
|
|
|
|
affine(p) {
|
|
|
|
const F = this.F;
|
|
|
|
if (this.isZero(p)) {
|
|
|
|
return this.zero;
|
|
|
|
} else if (F.eq(p[2], F.one)) {
|
|
|
|
return p;
|
|
|
|
} else {
|
|
|
|
const Z_inv = F.inv(p[2]);
|
|
|
|
const Z2_inv = F.square(Z_inv);
|
|
|
|
const Z3_inv = F.mul(Z2_inv, Z_inv);
|
|
|
|
|
|
|
|
const res = new Array(3);
|
|
|
|
res[0] = F.mul(p[0],Z2_inv);
|
|
|
|
res[1] = F.mul(p[1],Z3_inv);
|
|
|
|
res[2] = F.one;
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
multiAffine(arr) {
|
|
|
|
const keys = Object.keys(arr);
|
|
|
|
const F = this.F;
|
|
|
|
const accMul = new Array(keys.length+1);
|
|
|
|
accMul[0] = F.one;
|
|
|
|
for (let i = 0; i< keys.length; i++) {
|
|
|
|
if (F.eq(arr[keys[i]][2], F.zero)) {
|
|
|
|
accMul[i+1] = accMul[i];
|
|
|
|
} else {
|
|
|
|
accMul[i+1] = F.mul(accMul[i], arr[keys[i]][2]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
accMul[keys.length] = F.inv(accMul[keys.length]);
|
|
|
|
|
|
|
|
for (let i = keys.length-1; i>=0; i--) {
|
|
|
|
if (F.eq(arr[keys[i]][2], F.zero)) {
|
|
|
|
accMul[i] = accMul[i+1];
|
|
|
|
arr[keys[i]] = this.zero;
|
|
|
|
} else {
|
|
|
|
const Z_inv = F.mul(accMul[i], accMul[i+1]);
|
|
|
|
accMul[i] = F.mul(arr[keys[i]][2], accMul[i+1]);
|
|
|
|
|
|
|
|
const Z2_inv = F.square(Z_inv);
|
|
|
|
const Z3_inv = F.mul(Z2_inv, Z_inv);
|
|
|
|
|
|
|
|
arr[keys[i]][0] = F.mul(arr[keys[i]][0],Z2_inv);
|
|
|
|
arr[keys[i]][1] = F.mul(arr[keys[i]][1],Z3_inv);
|
|
|
|
arr[keys[i]][2] = F.one;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
eq(p1, p2) {
|
|
|
|
const F = this.F;
|
|
|
|
|
|
|
|
if (this.F.eq(p1[2], this.F.zero)) return this.F.eq(p2[2], this.F.zero);
|
|
|
|
if (this.F.eq(p2[2], this.F.zero)) return false;
|
|
|
|
|
|
|
|
const Z1Z1 = F.square( p1[2] );
|
|
|
|
const Z2Z2 = F.square( p2[2] );
|
|
|
|
|
|
|
|
const U1 = F.mul( p1[0] , Z2Z2 );
|
|
|
|
const U2 = F.mul( p2[0] , Z1Z1 );
|
|
|
|
|
|
|
|
const Z1_cubed = F.mul( p1[2] , Z1Z1);
|
|
|
|
const Z2_cubed = F.mul( p2[2] , Z2Z2);
|
|
|
|
|
|
|
|
const S1 = F.mul( p1[1] , Z2_cubed);
|
|
|
|
const S2 = F.mul( p2[1] , Z1_cubed);
|
|
|
|
|
|
|
|
return (F.eq(U1,U2) && F.eq(S1,S2));
|
|
|
|
}
|
|
|
|
|
|
|
|
isZero(p) {
|
|
|
|
return this.F.isZero(p[2]);
|
|
|
|
}
|
|
|
|
|
|
|
|
toString(p) {
|
|
|
|
const cp = this.affine(p);
|
|
|
|
return `[ ${this.F.toString(cp[0])} , ${this.F.toString(cp[1])} ]`;
|
|
|
|
}
|
|
|
|
|
|
|
|
fromRng(rng) {
|
|
|
|
const F = this.F;
|
|
|
|
let P = [];
|
|
|
|
let greatest;
|
|
|
|
do {
|
|
|
|
P[0] = F.fromRng(rng);
|
|
|
|
greatest = rng.nextBool();
|
|
|
|
const x3b = F.add(F.mul(F.square(P[0]), P[0]), this.b);
|
|
|
|
P[1] = F.sqrt(x3b);
|
|
|
|
} while ((P[1] == null)||(F.isZero[P]));
|
|
|
|
|
|
|
|
const s = isGreatest(F, P[1]);
|
|
|
|
if (greatest ^ s) P[1] = F.neg(P[1]);
|
|
|
|
P[2] = F.one;
|
|
|
|
|
|
|
|
if (this.cofactor) {
|
|
|
|
P = this.mulScalar(P, this.cofactor);
|
|
|
|
}
|
|
|
|
|
|
|
|
P = this.affine(P);
|
|
|
|
|
|
|
|
return P;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
toRprLE(buff, o, p) {
|
|
|
|
p = this.affine(p);
|
|
|
|
if (this.isZero(p)) {
|
|
|
|
const BuffV = new Uint8Array(buff, o, this.F.n8*2);
|
|
|
|
BuffV.fill(0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.F.toRprLE(buff, o, p[0]);
|
|
|
|
this.F.toRprLE(buff, o+this.F.n8, p[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
toRprBE(buff, o, p) {
|
|
|
|
p = this.affine(p);
|
|
|
|
if (this.isZero(p)) {
|
|
|
|
const BuffV = new Uint8Array(buff, o, this.F.n8*2);
|
|
|
|
BuffV.fill(0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.F.toRprBE(buff, o, p[0]);
|
|
|
|
this.F.toRprBE(buff, o+this.F.n8, p[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
toRprLEM(buff, o, p) {
|
|
|
|
p = this.affine(p);
|
|
|
|
if (this.isZero(p)) {
|
|
|
|
const BuffV = new Uint8Array(buff, o, this.F.n8*2);
|
|
|
|
BuffV.fill(0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.F.toRprLEM(buff, o, p[0]);
|
|
|
|
this.F.toRprLEM(buff, o+this.F.n8, p[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
toRprLEJM(buff, o, p) {
|
|
|
|
p = this.affine(p);
|
|
|
|
if (this.isZero(p)) {
|
|
|
|
const BuffV = new Uint8Array(buff, o, this.F.n8*2);
|
|
|
|
BuffV.fill(0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.F.toRprLEM(buff, o, p[0]);
|
|
|
|
this.F.toRprLEM(buff, o+this.F.n8, p[1]);
|
|
|
|
this.F.toRprLEM(buff, o+2*this.F.n8, p[2]);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
toRprBEM(buff, o, p) {
|
|
|
|
p = this.affine(p);
|
|
|
|
if (this.isZero(p)) {
|
|
|
|
const BuffV = new Uint8Array(buff, o, this.F.n8*2);
|
|
|
|
BuffV.fill(0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.F.toRprBEM(buff, o, p[0]);
|
|
|
|
this.F.toRprBEM(buff, o+this.F.n8, p[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
fromRprLE(buff, o) {
|
|
|
|
o = o || 0;
|
|
|
|
const x = this.F.fromRprLE(buff, o);
|
|
|
|
const y = this.F.fromRprLE(buff, o+this.F.n8);
|
|
|
|
if (this.F.isZero(x) && this.F.isZero(y)) {
|
|
|
|
return this.zero;
|
|
|
|
}
|
|
|
|
return [x, y, this.F.one];
|
|
|
|
}
|
|
|
|
|
|
|
|
fromRprBE(buff, o) {
|
|
|
|
o = o || 0;
|
|
|
|
const x = this.F.fromRprBE(buff, o);
|
|
|
|
const y = this.F.fromRprBE(buff, o+this.F.n8);
|
|
|
|
if (this.F.isZero(x) && this.F.isZero(y)) {
|
|
|
|
return this.zero;
|
|
|
|
}
|
|
|
|
return [x, y, this.F.one];
|
|
|
|
}
|
|
|
|
|
|
|
|
fromRprLEM(buff, o) {
|
|
|
|
o = o || 0;
|
|
|
|
const x = this.F.fromRprLEM(buff, o);
|
|
|
|
const y = this.F.fromRprLEM(buff, o+this.F.n8);
|
|
|
|
if (this.F.isZero(x) && this.F.isZero(y)) {
|
|
|
|
return this.zero;
|
|
|
|
}
|
|
|
|
return [x, y, this.F.one];
|
|
|
|
}
|
|
|
|
|
|
|
|
fromRprLEJM(buff, o) {
|
|
|
|
o = o || 0;
|
|
|
|
const x = this.F.fromRprLEM(buff, o);
|
|
|
|
const y = this.F.fromRprLEM(buff, o+this.F.n8);
|
|
|
|
const z = this.F.fromRprLEM(buff, o+this.F.n8*2);
|
|
|
|
if (this.F.isZero(x) && this.F.isZero(y)) {
|
|
|
|
return this.zero;
|
|
|
|
}
|
|
|
|
return [x, y, z];
|
|
|
|
}
|
|
|
|
|
|
|
|
fromRprBEM(buff, o) {
|
|
|
|
o = o || 0;
|
|
|
|
const x = this.F.fromRprBEM(buff, o);
|
|
|
|
const y = this.F.fromRprBEM(buff, o+this.F.n8);
|
|
|
|
if (this.F.isZero(x) && this.F.isZero(y)) {
|
|
|
|
return this.zero;
|
|
|
|
}
|
|
|
|
return [x, y, this.F.one];
|
|
|
|
}
|
|
|
|
|
|
|
|
fromRprCompressed(buff, o) {
|
|
|
|
const F = this.F;
|
|
|
|
const v = new Uint8Array(buff.buffer, o, F.n8);
|
|
|
|
if (v[0] & 0x40) return this.zero;
|
|
|
|
const P = new Array(3);
|
|
|
|
|
|
|
|
const greatest = ((v[0] & 0x80) != 0);
|
|
|
|
v[0] = v[0] & 0x7F;
|
|
|
|
P[0] = F.fromRprBE(buff, o);
|
|
|
|
if (greatest) v[0] = v[0] | 0x80; // set back again the old value
|
|
|
|
|
|
|
|
const x3b = F.add(F.mul(F.square(P[0]), P[0]), this.b);
|
|
|
|
P[1] = F.sqrt(x3b);
|
|
|
|
|
|
|
|
if (P[1] === null) {
|
|
|
|
throw new Error("Invalid Point!");
|
|
|
|
}
|
|
|
|
|
|
|
|
const s = isGreatest(F, P[1]);
|
|
|
|
if (greatest ^ s) P[1] = F.neg(P[1]);
|
|
|
|
P[2] = F.one;
|
|
|
|
|
|
|
|
return P;
|
|
|
|
}
|
|
|
|
|
|
|
|
toRprCompressed(buff, o, p) {
|
|
|
|
p = this.affine(p);
|
|
|
|
const v = new Uint8Array(buff.buffer, o, this.F.n8);
|
|
|
|
if (this.isZero(p)) {
|
|
|
|
v.fill(0);
|
|
|
|
v[0] = 0x40;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.F.toRprBE(buff, o, p[0]);
|
|
|
|
|
|
|
|
if (isGreatest(this.F, p[1])) {
|
|
|
|
v[0] = v[0] | 0x80;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fromRprUncompressed(buff, o) {
|
|
|
|
if (buff[0] & 0x40) return this.zero;
|
|
|
|
|
|
|
|
return this.fromRprBE(buff, o);
|
|
|
|
}
|
|
|
|
|
|
|
|
toRprUncompressed(buff, o, p) {
|
|
|
|
this.toRprBE(buff, o, p);
|
|
|
|
|
|
|
|
if (this.isZero(p)) {
|
|
|
|
buff[o] = buff[o] | 0x40;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
var code = "AGFzbQEAAAABiQERYAJ/fwBgAX8AYAF/AX9gAn9/AX9gA39/fwF/YAN/f38AYAN/fn8AYAJ/fgBgBH9/f38AYAV/f39/fwBgBH9/f38Bf2AHf39/f39/fwBgCH9/f39/f39/AGAFf39/f38Bf2AHf39/f39/fwF/YAl/f39/f39/f38Bf2ALf39/f39/f39/f38BfwIQAQNlbnYGbWVtb3J5AgDoBwOrAqkCAAECAQMDBAQFAAAGBwgFAgUFAAAFAAAAAAICAAEFCAkFBQgAAgIFBQAABQAAAAACAgABBQgJBQUIAAIFAAACAgIBAQAAAAMDAwAABQUFAAAFBQUAAAAAAAUABQAAAAAFBQUFBQoACwkKAAsJCAgDAAgIAgAACQUFAAgMCQICAQEABQUABQUAAAAAAwAIAgIJCAACAgIBAQAAAAMDAwAABQUFAAAFBQUAAAAAAAUABQAAAAAFBQUFBQoACwkKAAsJCAgFAwAICAIAAAkFBQUDAAgIAgAACQUFBQUJCQkJCQACAgEBAAUABQUAAgAAAwAIAgkIAAICAQEABQUABQUAAAAAAwAIAgIJCAACBQAAAAAICAUAAAAAAAAAAAAAAAAAAAAABA0ODxAFB70imgIIaW50X2NvcHkAAAhpbnRfemVybwABB2ludF9vbmUAAwppbnRfaXNaZXJvAAIGaW50X2VxAAQHaW50X2d0ZQAFB2ludF9hZGQABgdpbnRfc3ViAAcHaW50X211bAAICmludF9zcXVhcmUACQ1pbnRfc3F1YXJlT2xkAAoHaW50X2RpdgANDmludF9pbnZlcnNlTW9kAA4IZjFtX2NvcHkAAAhmMW1femVybwABCmYxbV9pc1plcm8AAgZmMW1fZXEABAdmMW1fYWRkABAHZjFtX3N1YgARB2YxbV9uZWcAEg5mMW1faXNOZWdhdGl2ZQAZCWYxbV9pc09uZQAPCGYxbV9zaWduABoLZjFtX21SZWR1Y3QAEwdmMW1fbXVsABQKZjFtX3NxdWFyZQAVDWYxbV9zcXVhcmVPbGQAFhJmMW1fZnJvbU1vbnRnb21lcnkAGBBmMW1fdG9Nb250Z29tZXJ5ABcLZjFtX2ludmVyc2UAGwdmMW1fb25lABwIZjFtX2xvYWQAHQ9mMW1fdGltZXNTY2FsYXIAHgdmMW1fZXhwACIQZjFtX2JhdGNoSW52ZXJzZQAfCGYxbV9zcXJ0ACMMZjFtX2lzU3F1YXJlACQVZjFtX2JhdGNoVG9Nb250Z29tZXJ5ACAXZjFtX2JhdGNoRnJvbU1vbnRnb21lcnkAIQhmcm1fY29weQAACGZybV96ZXJvAAEKZnJtX2lzWmVybwACBmZybV9lcQAEB2ZybV9hZGQAJgdmcm1fc3ViACcHZnJtX25lZwAoDmZybV9pc05lZ2F0aXZlAC8JZnJtX2lzT25lACUIZnJtX3NpZ24AMAtmcm1fbVJlZHVjdAApB2ZybV9tdWwAKgpmcm1fc3F1YXJlACsNZnJtX3NxdWFyZU9sZAAsEmZybV9mcm9tTW9udGdvbWVyeQAuEGZybV90b01vbnRnb21lcnkALQtmcm1faW52ZXJzZQAxB2ZybV9vbmUAMghmcm1fbG9hZAAzD2ZybV90aW1lc1NjYWxhcgA0B2ZybV9leHAAOBBmcm1fYmF0Y2hJbnZlcnNlADUIZnJtX3NxcnQAOQxmcm1faXNTcXVhcmUAOhVmcm1fYmF0Y2hUb01vbnRnb21lcnkANhdmcm1fYmF0Y2hGcm9tTW9udGdvbWVyeQA3BmZyX2FkZAAmBmZyX3N1YgAnBmZyX25lZwAoBmZyX211bAA7CWZyX3NxdWFyZQA8CmZyX2ludmVyc2UAPQ1mcl9pc05lZ2F0aXZlAD4HZnJfY29weQAAB2ZyX3plcm8AAQZmcl9vbmUAMglmcl9pc1plcm8AAgVmcl9lcQAEDGcxbV9tdWx0aWV4cABnEmcxbV9tdWx0aWV4cF9jaHVuawBmEmcxbV9tdWx0aWV4cEFmZmluZQBrGGcxbV9tdWx0aWV4cEFmZmluZV9jaHVuawBqCmcxbV9pc1plcm8AQBBnMW1faXNaZXJvQWZmaW5lAD8GZzFtX2VxAEgLZzFtX2VxTWl4ZWQARwxnMW1fZXFBZmZpbmUARghnMW1fY29weQBEDmcxbV9jb3B5QWZmaW5lAEMIZzFtX3plcm8AQg5nMW1femVyb0FmZmluZQBBCmcxbV9kb3VibGUAShBnMW1fZG91YmxlQWZmaW5lAEkHZzFtX2FkZABNDGcxbV9hZGRNaXhlZABMDWcxbV9hZGRBZmZpbmUASwdnMW1fbmVnAE8NZzFtX25lZ0FmZmluZQBOB2cxbV9zdWIAUgxnMW1fc3ViTWl4ZWQAUQ1nMW1fc3ViQWZmaW5lAFASZzFtX2Zyb21Nb250Z29tZXJ5AFQYZzFtX2Zyb21Nb250Z29tZXJ5QWZmaW5lAFMQZzFtX3RvTW9udGdvbWVyeQBWFmcxbV90b01vbnRnb21lcnlBZmZpbmUAVQ9nMW1fdGltZXNTY2FsYXIAbBVnMW1fdGltZXNTY2FsYXJBZmZpbmUAbQ1nMW1fbm9ybWFsaXplAFkKZzFtX0xFTXRvVQBbCmcxbV9MRU10b0MAXApnMW1fVXRvTEVNAF0KZzFtX0N0b0xFTQBeD2cxbV9iYXRjaExFTXRvVQBfD2cxbV9iYXRjaExFTXRvQwBgD2cxbV9iYXRjaFV0b0xFTQBhD2cxbV9iYXRjaEN0b0xFTQBiDGcxbV90b0FmZmluZQBXDmcxbV90b0phY29iaWFuAEURZzFtX2JhdGNoVG9BZmZpbmUAWBNnMW1fYmF0Y2hUb0phY29iaWFuAGMHZnJtX2ZmdABzCGZybV9pZmZ0AHQKZnJtX3Jhd2ZmdABxC2ZybV9mZnRKb2luAHUKZnJtX2ZmdE1peAB2DGZybV9mZnRGaW5hbAB3CHBvbF96ZXJvAHgPcG9sX2NvbnN0cnVjdExDAHkMcWFwX2J1aWxkQUJDAHoLcWFwX2pvaW5BQkMAewpmMm1faXNaZXJvAHwJZjJtX2lzT25lAH0IZjJtX3plcm8AfgdmMm1fb25lAH8IZjJtX2NvcHkAgAEHZjJtX211bACBAQhmMm1fbXVsMQCCAQpmMm1fc3F1YXJlAIMBB2YybV9hZGQAhAEHZjJtX3N1YgCFAQdmMm1fbmVnAIYBCGYybV9zaWduAI0BDWYybV9jb25qdWdhdGUAhwESZjJtX2Zyb21Nb250Z29tZXJ5AIkBEGYybV90b01vbnRnb21lcnkAiAEGZjJtX2VxAIoBC2YybV9pbnZlcnNlAIsBB2YybV9leHAAkAEPZjJtX3RpbWVzU2NhbGFyAIwBEGYybV9iYXRjaEludmVyc2UAjwEIZjJtX3NxcnQAkQEMZjJtX2lzU3F1YXJlAJIBDmYybV9pc05lZ2F0aXZlAI4BDGcybV9tdWx0aWV4cAC7ARJnMm1fbXVsdGlleHBfY2h1bmsAugESZzJtX211bHRpZXhwQWZmaW5lAL8BGGcybV9tdWx0aWV4cEFmZmluZV9jaHVuawC+AQpnMm1faXNaZXJvAJQBEGcybV9pc1plcm9BZmZpbmUAkwEGZzJtX2VxAJwBC2cybV9lcU1peGVkAJsBDGcybV9lcUFmZmluZQCaAQhnMm1fY29weQCYAQ5nMm1fY29weUFmZmluZQCXAQhnMm1femVybwCWAQ5nMm1femVyb0FmZmluZQCVAQpnMm1fZG91YmxlAJ4BEGcybV9kb3VibGVBZmZpbmUAnQEHZzJtX2FkZAChAQxnMm1fYWRkTWl4ZWQAoAENZzJtX2FkZEFmZmluZQCfAQdnMm1fbmVnAKMBDWcybV9uZWdBZmZpbmUAogEHZzJtX3N1YgCmAQxnMm1fc3ViTWl4ZWQApQENZzJtX3N1YkFmZmluZQCkARJnMm1fZnJvbU1vbnRnb21lcnkAqAEYZzJtX2Zyb21Nb250Z29tZXJ5QWZmaW5lAKcBEGcybV9
|
|
|
|
var pq = 520;
|
|
|
|
var pr = 1864;
|
|
|
|
var pG1gen = 24392;
|
|
|
|
var pG1zero = 24488;
|
|
|
|
var pG1b = 3240;
|
|
|
|
var pG2gen = 24584;
|
|
|
|
var pG2zero = 24776;
|
|
|
|
var pG2b = 10440;
|
|
|
|
var pOneT = 24968;
|
|
|
|
var prePSize = 192;
|
|
|
|
var preQSize = 19776;
|
|
|
|
var n8q = 32;
|
|
|
|
var n8r = 32;
|
|
|
|
var q = "21888242871839275222246405745257275088696311157297823662689037894645226208583";
|
|
|
|
var r = "21888242871839275222246405745257275088548364400416034343698204186575808495617";
|
|
|
|
|
|
|
|
var bn128_wasm = {
|
|
|
|
code: code,
|
|
|
|
pq: pq,
|
|
|
|
pr: pr,
|
|
|
|
pG1gen: pG1gen,
|
|
|
|
pG1zero: pG1zero,
|
|
|
|
pG1b: pG1b,
|
|
|
|
pG2gen: pG2gen,
|
|
|
|
pG2zero: pG2zero,
|
|
|
|
pG2b: pG2b,
|
|
|
|
pOneT: pOneT,
|
|
|
|
prePSize: prePSize,
|
|
|
|
preQSize: preQSize,
|
|
|
|
n8q: n8q,
|
|
|
|
n8r: n8r,
|
|
|
|
q: q,
|
|
|
|
r: r
|
|
|
|
};
|
|
|
|
|
|
|
|
var code$1 = "AGFzbQEAAAABiQERYAJ/fwBgAX8AYAF/AX9gAn9/AX9gA39/fwF/YAN/f38AYAN/fn8AYAJ/fgBgBH9/f38AYAV/f39/fwBgBH9/f38Bf2AHf39/f39/fwBgCH9/f39/f39/AGAFf39/f38Bf2AHf39/f39/fwF/YAl/f39/f39/f38Bf2ALf39/f39/f39/f38BfwIQAQNlbnYGbWVtb3J5AgDoBwO5ArcCAAECAQMDBAQFAAAGBwgFAgUFAAAFAAAAAAICAAEFCAkFBQgAAgABAgEDAwQEBQAABgcIBQIFBQAABQAAAAACAgABBQgJBQUIAAIFAAACAgIBAQAAAAMDAwAABQUFAAAFBQUAAAAAAAUABQAAAAAFBQUFBQoACwkKAAsJCAgDAAgIAgAACQUFAAgMCQICAQEABQUABQUAAAAAAwAIAgIJCAACAgIBAQAAAAMDAwAABQUFAAAFBQUAAAAAAAUABQAAAAAFBQUFBQoACwkKAAsJCAgFAwAICAIAAAkFBQUDAAgIAgAACQUFBQUJCQkJCQACAgEBAAUABQUAAgAAAwAIAgkIAAICAQEABQUABQUAAAAAAwAIAgIJCAACBQgJBQAAAAAAAAAAAAAFAAAABQAAAAAEDQ4PEAUHviSoAglpbnRxX2NvcHkAAAlpbnRxX3plcm8AAQhpbnRxX29uZQADC2ludHFfaXNaZXJvAAIHaW50cV9lcQAECGludHFfZ3RlAAUIaW50cV9hZGQABghpbnRxX3N1YgAHCGludHFfbXVsAAgLaW50cV9zcXVhcmUACQ5pbnRxX3NxdWFyZU9sZAAKCGludHFfZGl2AA0PaW50cV9pbnZlcnNlTW9kAA4IZjFtX2NvcHkAAAhmMW1femVybwABCmYxbV9pc1plcm8AAgZmMW1fZXEABAdmMW1fYWRkABAHZjFtX3N1YgARB2YxbV9uZWcAEg5mMW1faXNOZWdhdGl2ZQAZCWYxbV9pc09uZQAPCGYxbV9zaWduABoLZjFtX21SZWR1Y3QAEwdmMW1fbXVsABQKZjFtX3NxdWFyZQAVDWYxbV9zcXVhcmVPbGQAFhJmMW1fZnJvbU1vbnRnb21lcnkAGBBmMW1fdG9Nb250Z29tZXJ5ABcLZjFtX2ludmVyc2UAGwdmMW1fb25lABwIZjFtX2xvYWQAHQ9mMW1fdGltZXNTY2FsYXIAHgdmMW1fZXhwACIQZjFtX2JhdGNoSW52ZXJzZQAfCGYxbV9zcXJ0ACMMZjFtX2lzU3F1YXJlACQVZjFtX2JhdGNoVG9Nb250Z29tZXJ5ACAXZjFtX2JhdGNoRnJvbU1vbnRnb21lcnkAIQlpbnRyX2NvcHkAJQlpbnRyX3plcm8AJghpbnRyX29uZQAoC2ludHJfaXNaZXJvACcHaW50cl9lcQApCGludHJfZ3RlACoIaW50cl9hZGQAKwhpbnRyX3N1YgAsCGludHJfbXVsAC0LaW50cl9zcXVhcmUALg5pbnRyX3NxdWFyZU9sZAAvCGludHJfZGl2ADIPaW50cl9pbnZlcnNlTW9kADMIZnJtX2NvcHkAJQhmcm1femVybwAmCmZybV9pc1plcm8AJwZmcm1fZXEAKQdmcm1fYWRkADUHZnJtX3N1YgA2B2ZybV9uZWcANw5mcm1faXNOZWdhdGl2ZQA+CWZybV9pc09uZQA0CGZybV9zaWduAD8LZnJtX21SZWR1Y3QAOAdmcm1fbXVsADkKZnJtX3NxdWFyZQA6DWZybV9zcXVhcmVPbGQAOxJmcm1fZnJvbU1vbnRnb21lcnkAPRBmcm1fdG9Nb250Z29tZXJ5ADwLZnJtX2ludmVyc2UAQAdmcm1fb25lAEEIZnJtX2xvYWQAQg9mcm1fdGltZXNTY2FsYXIAQwdmcm1fZXhwAEcQZnJtX2JhdGNoSW52ZXJzZQBECGZybV9zcXJ0AEgMZnJtX2lzU3F1YXJlAEkVZnJtX2JhdGNoVG9Nb250Z29tZXJ5AEUXZnJtX2JhdGNoRnJvbU1vbnRnb21lcnkARgZmcl9hZGQANQZmcl9zdWIANgZmcl9uZWcANwZmcl9tdWwASglmcl9zcXVhcmUASwpmcl9pbnZlcnNlAEwNZnJfaXNOZWdhdGl2ZQBNB2ZyX2NvcHkAJQdmcl96ZXJvACYGZnJfb25lAEEJZnJfaXNaZXJvACcFZnJfZXEAKQxnMW1fbXVsdGlleHAAdhJnMW1fbXVsdGlleHBfY2h1bmsAdRJnMW1fbXVsdGlleHBBZmZpbmUAehhnMW1fbXVsdGlleHBBZmZpbmVfY2h1bmsAeQpnMW1faXNaZXJvAE8QZzFtX2lzWmVyb0FmZmluZQBOBmcxbV9lcQBXC2cxbV9lcU1peGVkAFYMZzFtX2VxQWZmaW5lAFUIZzFtX2NvcHkAUw5nMW1fY29weUFmZmluZQBSCGcxbV96ZXJvAFEOZzFtX3plcm9BZmZpbmUAUApnMW1fZG91YmxlAFkQZzFtX2RvdWJsZUFmZmluZQBYB2cxbV9hZGQAXAxnMW1fYWRkTWl4ZWQAWw1nMW1fYWRkQWZmaW5lAFoHZzFtX25lZwBeDWcxbV9uZWdBZmZpbmUAXQdnMW1fc3ViAGEMZzFtX3N1Yk1peGVkAGANZzFtX3N1YkFmZmluZQBfEmcxbV9mcm9tTW9udGdvbWVyeQBjGGcxbV9mcm9tTW9udGdvbWVyeUFmZmluZQBiEGcxbV90b01vbnRnb21lcnkAZRZnMW1fdG9Nb250Z29tZXJ5QWZmaW5lAGQPZzFtX3RpbWVzU2NhbGFyAHsVZzFtX3RpbWVzU2NhbGFyQWZmaW5lAHwNZzFtX25vcm1hbGl6ZQBoCmcxbV9MRU10b1UAagpnMW1fTEVNdG9DAGsKZzFtX1V0b0xFTQBsCmcxbV9DdG9MRU0AbQ9nMW1fYmF0Y2hMRU10b1UAbg9nMW1fYmF0Y2hMRU10b0MAbw9nMW1fYmF0Y2hVdG9MRU0AcA9nMW1fYmF0Y2hDdG9MRU0AcQxnMW1fdG9BZmZpbmUAZg5nMW1fdG9KYWNvYmlhbgBUEWcxbV9iYXRjaFRvQWZmaW5lAGcTZzFtX2JhdGNoVG9KYWNvYmlhbgByB2ZybV9mZnQAggEIZnJtX2lmZnQAgwEKZnJtX3Jhd2ZmdACAAQtmcm1fZmZ0Sm9pbgCEAQpmcm1fZmZ0TWl4AIUBDGZybV9mZnRGaW5hbACGAQhwb2xfemVybwCHAQ9wb2xfY29uc3RydWN0TEMAiAEMcWFwX2J1aWxkQUJDAIkBC3FhcF9qb2luQUJDAIoBCmYybV9pc1plcm8AiwEJZjJtX2lzT25lAIwBCGYybV96ZXJvAI0BB2YybV9vbmUAjgEIZjJtX2NvcHkAjwEHZjJtX211bACQAQhmMm1fbXVsMQCRAQpmMm1fc3F1YXJlAJIBB2YybV9hZGQAkwEHZjJtX3N1YgCUAQdmMm1fbmVnAJUBCGYybV9zaWduAJwBDWYybV9jb25qdWdhdGUAlgESZjJtX2Zyb21Nb250Z29tZXJ5AJgBEGYybV90b01vbnRnb21lcnkAlwEGZjJtX2VxAJkBC2YybV9pbnZlcnNlAJoBB2YybV9leHAAnwEPZjJtX3RpbWVzU2NhbGFyAJsBEGYybV9iYXRjaEludmVyc2UAngEIZjJtX3NxcnQAoAEMZjJtX2lzU3F1YXJlAKEBDmYybV9pc05lZ2F0aXZlAJ0BDGcybV9tdWx0aWV4cADKARJnMm1fbXVsdGlleHBfY2h1bmsAyQESZzJtX211bHRpZXhwQWZmaW5lAM4BGGcybV9tdWx0aWV4cEFmZmluZV9jaHVuawDNAQpnMm1faXNaZXJvAKMBEGcybV9pc1plcm9BZmZpbmUAogEGZzJtX2VxAKsBC2cybV9lcU1peGVkAKoBDGcybV9lcUFmZmluZQCpAQhnMm1fY29weQCnAQ5nMm1fY29weUFmZmluZQCmAQhnMm1femVybwClAQ5nMm1femVyb0FmZmluZQCkA
|
|
|
|
var pq$1 = 760;
|
|
|
|
var pr$1 = 3640;
|
|
|
|
var pG1gen$1 = 33752;
|
|
|
|
var pG1zero$1 = 33896;
|
|
|
|
var pG1b$1 = 5016;
|
|
|
|
var pG2gen$1 = 34040;
|
|
|
|
var pG2zero$1 = 34328;
|
|
|
|
var pG2b$1 = 14728;
|
|
|
|
var pOneT$1 = 34616;
|
|
|
|
var prePSize$1 = 288;
|
|
|
|
var preQSize$1 = 20448;
|
|
|
|
var n8q$1 = 48;
|
|
|
|
var n8r$1 = 32;
|
|
|
|
var q$1 = "4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787";
|
|
|
|
var r$1 = "52435875175126190479447740508185965837690552500527637822603658699938581184513";
|
|
|
|
|
|
|
|
var bls12381_wasm = {
|
|
|
|
code: code$1,
|
|
|
|
pq: pq$1,
|
|
|
|
pr: pr$1,
|
|
|
|
pG1gen: pG1gen$1,
|
|
|
|
pG1zero: pG1zero$1,
|
|
|
|
pG1b: pG1b$1,
|
|
|
|
pG2gen: pG2gen$1,
|
|
|
|
pG2zero: pG2zero$1,
|
|
|
|
pG2b: pG2b$1,
|
|
|
|
pOneT: pOneT$1,
|
|
|
|
prePSize: prePSize$1,
|
|
|
|
preQSize: preQSize$1,
|
|
|
|
n8q: n8q$1,
|
|
|
|
n8r: n8r$1,
|
|
|
|
q: q$1,
|
|
|
|
r: r$1
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
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.buildF1 = require("./src/f1.js");
|
|
|
|
// module.exports.buildBn128 = require("./src/bn128.js");
|
|
|
|
// module.exports.buildMnt6753 = require("./src/mnt6753.js");
|
|
|
|
|
|
|
|
var bn128_wasm$1 = bn128_wasm;
|
|
|
|
var bls12381_wasm$1 = bls12381_wasm;
|
|
|
|
// module.exports.mnt6753_wasm = require("./build/mnt6753_wasm.js");
|
|
|
|
|
|
|
|
var wasmcurves = {
|
|
|
|
bn128_wasm: bn128_wasm$1,
|
|
|
|
bls12381_wasm: bls12381_wasm$1
|
|
|
|
};
|
|
|
|
|
|
|
|
/* global BigInt */
|
|
|
|
|
|
|
|
function stringifyBigInts(o) {
|
|
|
|
if ((typeof(o) == "bigint") || o.eq !== undefined) {
|
|
|
|
return o.toString(10);
|
|
|
|
} else if (Array.isArray(o)) {
|
|
|
|
return o.map(stringifyBigInts);
|
|
|
|
} else if (typeof o == "object") {
|
|
|
|
const res = {};
|
|
|
|
const keys = Object.keys(o);
|
|
|
|
keys.forEach( (k) => {
|
|
|
|
res[k] = stringifyBigInts(o[k]);
|
|
|
|
});
|
|
|
|
return res;
|
|
|
|
} else {
|
|
|
|
return o;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function unstringifyBigInts(o) {
|
|
|
|
if ((typeof(o) == "string") && (/^[0-9]+$/.test(o) )) {
|
|
|
|
return BigInt(o);
|
|
|
|
} else if (Array.isArray(o)) {
|
|
|
|
return o.map(unstringifyBigInts);
|
|
|
|
} else if (typeof o == "object") {
|
|
|
|
if (o===null) return null;
|
|
|
|
const res = {};
|
|
|
|
const keys = Object.keys(o);
|
|
|
|
keys.forEach( (k) => {
|
|
|
|
res[k] = unstringifyBigInts(o[k]);
|
|
|
|
});
|
|
|
|
return res;
|
|
|
|
} else {
|
|
|
|
return o;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function beBuff2int(buff) {
|
|
|
|
let res = 0n;
|
|
|
|
let i = buff.length;
|
|
|
|
let offset = 0;
|
|
|
|
const buffV = new DataView(buff.buffer);
|
|
|
|
while (i>0) {
|
|
|
|
if (i >= 4) {
|
|
|
|
i -= 4;
|
|
|
|
res += BigInt(buffV.getUint32(i)) << BigInt(offset*8);
|
|
|
|
offset += 4;
|
|
|
|
} else if (i >= 2) {
|
|
|
|
i -= 2;
|
|
|
|
res += BigInt(buffV.getUint16(i)) << BigInt(offset*8);
|
|
|
|
offset += 2;
|
|
|
|
} else {
|
|
|
|
i -= 1;
|
|
|
|
res += BigInt(buffV.getUint8(i)) << BigInt(offset*8);
|
|
|
|
offset += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
function beInt2Buff(n, len) {
|
|
|
|
let r = n;
|
|
|
|
const buff = new Uint8Array(len);
|
|
|
|
const buffV = new DataView(buff.buffer);
|
|
|
|
let o = len;
|
|
|
|
while (o > 0) {
|
|
|
|
if (o-4 >= 0) {
|
|
|
|
o -= 4;
|
|
|
|
buffV.setUint32(o, Number(r & 0xFFFFFFFFn));
|
|
|
|
r = r >> 32n;
|
|
|
|
} else if (o-2 >= 0) {
|
|
|
|
o -= 2;
|
|
|
|
buffV.setUint16(o, Number(r & 0xFFFFn));
|
|
|
|
r = r >> 16n;
|
|
|
|
} else {
|
|
|
|
o -= 1;
|
|
|
|
buffV.setUint8(o, Number(r & 0xFFn));
|
|
|
|
r = r >> 8n;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (r) {
|
|
|
|
throw new Error("Number does not fit in this length");
|
|
|
|
}
|
|
|
|
return buff;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function leBuff2int(buff) {
|
|
|
|
let res = 0n;
|
|
|
|
let i = 0;
|
|
|
|
const buffV = new DataView(buff.buffer);
|
|
|
|
while (i<buff.length) {
|
|
|
|
if (i + 4 <= buff.length) {
|
|
|
|
res += BigInt(buffV.getUint32(i, true)) << BigInt( i*8);
|
|
|
|
i += 4;
|
|
|
|
} else if (i + 4 <= buff.length) {
|
|
|
|
res += BigInt(buffV.getUint16(i, true)) << BigInt( i*8);
|
|
|
|
i += 2;
|
|
|
|
} else {
|
|
|
|
res += BigInt(buffV.getUint8(i, true)) << BigInt( i*8);
|
|
|
|
i += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
function leInt2Buff(n, len) {
|
|
|
|
let r = n;
|
|
|
|
if (typeof len === "undefined") {
|
|
|
|
len = Math.floor((bitLength$2(n) - 1) / 8) +1;
|
|
|
|
if (len==0) len = 1;
|
|
|
|
}
|
|
|
|
const buff = new Uint8Array(len);
|
|
|
|
const buffV = new DataView(buff.buffer);
|
|
|
|
let o = 0;
|
|
|
|
while (o < len) {
|
|
|
|
if (o+4 <= len) {
|
|
|
|
buffV.setUint32(o, Number(r & 0xFFFFFFFFn), true );
|
|
|
|
o += 4;
|
|
|
|
r = r >> 32n;
|
|
|
|
} else if (o+2 <= len) {
|
|
|
|
buff.setUint16(Number(o, r & 0xFFFFn), true );
|
|
|
|
o += 2;
|
|
|
|
r = r >> 16n;
|
|
|
|
} else {
|
|
|
|
buff.setUint8(Number(o, r & 0xFFn), true );
|
|
|
|
o += 1;
|
|
|
|
r = r >> 8n;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (r) {
|
|
|
|
throw new Error("Number does not fit in this length");
|
|
|
|
}
|
|
|
|
return buff;
|
|
|
|
}
|
|
|
|
|
|
|
|
var utils_native = /*#__PURE__*/Object.freeze({
|
|
|
|
__proto__: null,
|
|
|
|
stringifyBigInts: stringifyBigInts,
|
|
|
|
unstringifyBigInts: unstringifyBigInts,
|
|
|
|
beBuff2int: beBuff2int,
|
|
|
|
beInt2Buff: beInt2Buff,
|
|
|
|
leBuff2int: leBuff2int,
|
|
|
|
leInt2Buff: leInt2Buff
|
|
|
|
});
|
|
|
|
|
|
|
|
function stringifyBigInts$1(o) {
|
|
|
|
if ((typeof(o) == "bigint") || o.eq !== undefined) {
|
|
|
|
return o.toString(10);
|
|
|
|
} else if (Array.isArray(o)) {
|
|
|
|
return o.map(stringifyBigInts$1);
|
|
|
|
} else if (typeof o == "object") {
|
|
|
|
const res = {};
|
|
|
|
const keys = Object.keys(o);
|
|
|
|
keys.forEach( (k) => {
|
|
|
|
res[k] = stringifyBigInts$1(o[k]);
|
|
|
|
});
|
|
|
|
return res;
|
|
|
|
} else {
|
|
|
|
return o;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function unstringifyBigInts$1(o) {
|
|
|
|
if ((typeof(o) == "string") && (/^[0-9]+$/.test(o) )) {
|
|
|
|
return BigInteger(o);
|
|
|
|
} else if (Array.isArray(o)) {
|
|
|
|
return o.map(unstringifyBigInts$1);
|
|
|
|
} else if (typeof o == "object") {
|
|
|
|
const res = {};
|
|
|
|
const keys = Object.keys(o);
|
|
|
|
keys.forEach( (k) => {
|
|
|
|
res[k] = unstringifyBigInts$1(o[k]);
|
|
|
|
});
|
|
|
|
return res;
|
|
|
|
} else {
|
|
|
|
return o;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function beBuff2int$1(buff) {
|
|
|
|
let res = BigInteger.zero;
|
|
|
|
for (let i=0; i<buff.length; i++) {
|
|
|
|
const n = BigInteger(buff[buff.length - i - 1]);
|
|
|
|
res = res.add(n.shiftLeft(i*8));
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
function beInt2Buff$1(n, len) {
|
|
|
|
let r = n;
|
|
|
|
let o =len-1;
|
|
|
|
const buff = new Uint8Array(len);
|
|
|
|
while ((r.gt(BigInteger.zero))&&(o>=0)) {
|
|
|
|
let c = Number(r.and(BigInteger("255")));
|
|
|
|
buff[o] = c;
|
|
|
|
o--;
|
|
|
|
r = r.shiftRight(8);
|
|
|
|
}
|
|
|
|
if (!r.eq(BigInteger.zero)) {
|
|
|
|
throw new Error("Number does not fit in this length");
|
|
|
|
}
|
|
|
|
return buff;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function leBuff2int$1 (buff) {
|
|
|
|
let res = BigInteger.zero;
|
|
|
|
for (let i=0; i<buff.length; i++) {
|
|
|
|
const n = BigInteger(buff[i]);
|
|
|
|
res = res.add(n.shiftLeft(i*8));
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
function leInt2Buff$1(n, len) {
|
|
|
|
let r = n;
|
|
|
|
let o =0;
|
|
|
|
const buff = new Uint8Array(len);
|
|
|
|
while ((r.gt(BigInteger.zero))&&(o<buff.length)) {
|
|
|
|
let c = Number(r.and(BigInteger(255)));
|
|
|
|
buff[o] = c;
|
|
|
|
o++;
|
|
|
|
r = r.shiftRight(8);
|
|
|
|
}
|
|
|
|
if (!r.eq(BigInteger.zero)) {
|
|
|
|
throw new Error("Number does not fit in this length");
|
|
|
|
}
|
|
|
|
return buff;
|
|
|
|
}
|
|
|
|
|
|
|
|
var utils_bigint = /*#__PURE__*/Object.freeze({
|
|
|
|
__proto__: null,
|
|
|
|
stringifyBigInts: stringifyBigInts$1,
|
|
|
|
unstringifyBigInts: unstringifyBigInts$1,
|
|
|
|
beBuff2int: beBuff2int$1,
|
|
|
|
beInt2Buff: beInt2Buff$1,
|
|
|
|
leBuff2int: leBuff2int$1,
|
|
|
|
leInt2Buff: leInt2Buff$1
|
|
|
|
});
|
|
|
|
|
|
|
|
let utils = {};
|
|
|
|
|
|
|
|
const supportsNativeBigInt$2 = typeof BigInt === "function";
|
|
|
|
if (supportsNativeBigInt$2) {
|
|
|
|
Object.assign(utils, utils_native);
|
|
|
|
} else {
|
|
|
|
Object.assign(utils, utils_bigint);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const _revTable$1 = [];
|
|
|
|
for (let i=0; i<256; i++) {
|
|
|
|
_revTable$1[i] = _revSlow$1(i, 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
function _revSlow$1(idx, bits) {
|
|
|
|
let res =0;
|
|
|
|
let a = idx;
|
|
|
|
for (let i=0; i<bits; i++) {
|
|
|
|
res <<= 1;
|
|
|
|
res = res | (a &1);
|
|
|
|
a >>=1;
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
utils.bitReverse = function bitReverse(idx, bits) {
|
|
|
|
return (
|
|
|
|
_revTable$1[idx >>> 24] |
|
|
|
|
(_revTable$1[(idx >>> 16) & 0xFF] << 8) |
|
|
|
|
(_revTable$1[(idx >>> 8) & 0xFF] << 16) |
|
|
|
|
(_revTable$1[idx & 0xFF] << 24)
|
|
|
|
) >>> (32-bits);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
utils.log2 = function log2( V )
|
|
|
|
{
|
|
|
|
return( ( ( V & 0xFFFF0000 ) !== 0 ? ( V &= 0xFFFF0000, 16 ) : 0 ) | ( ( V & 0xFF00FF00 ) !== 0 ? ( V &= 0xFF00FF00, 8 ) : 0 ) | ( ( V & 0xF0F0F0F0 ) !== 0 ? ( V &= 0xF0F0F0F0, 4 ) : 0 ) | ( ( V & 0xCCCCCCCC ) !== 0 ? ( V &= 0xCCCCCCCC, 2 ) : 0 ) | ( ( V & 0xAAAAAAAA ) !== 0 ) );
|
|
|
|
};
|
|
|
|
|
|
|
|
utils.buffReverseBits = function buffReverseBits(buff, eSize) {
|
|
|
|
const n = buff.byteLength /eSize;
|
|
|
|
const bits = utils.log2(n);
|
|
|
|
if (n != (1 << bits)) {
|
|
|
|
throw new Error("Invalid number of pointers");
|
|
|
|
}
|
|
|
|
for (let i=0; i<n; i++) {
|
|
|
|
const r = utils.bitReverse(i,bits);
|
|
|
|
if (i>r) {
|
|
|
|
const tmp = buff.slice(i*eSize, (i+1)*eSize);
|
|
|
|
buff.set( buff.slice(r*eSize, (r+1)*eSize), i*eSize);
|
|
|
|
buff.set(tmp, r*eSize);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let {
|
|
|
|
bitReverse,
|
|
|
|
log2: log2$1,
|
|
|
|
buffReverseBits,
|
|
|
|
stringifyBigInts: stringifyBigInts$2,
|
|
|
|
unstringifyBigInts: unstringifyBigInts$2,
|
|
|
|
beBuff2int: beBuff2int$2,
|
|
|
|
beInt2Buff: beInt2Buff$2,
|
|
|
|
leBuff2int: leBuff2int$2,
|
|
|
|
leInt2Buff: leInt2Buff$2,
|
|
|
|
} = utils;
|
|
|
|
|
|
|
|
var _utils = /*#__PURE__*/Object.freeze({
|
|
|
|
__proto__: null,
|
|
|
|
bitReverse: bitReverse,
|
|
|
|
log2: log2$1,
|
|
|
|
buffReverseBits: buffReverseBits,
|
|
|
|
stringifyBigInts: stringifyBigInts$2,
|
|
|
|
unstringifyBigInts: unstringifyBigInts$2,
|
|
|
|
beBuff2int: beBuff2int$2,
|
|
|
|
beInt2Buff: beInt2Buff$2,
|
|
|
|
leBuff2int: leBuff2int$2,
|
|
|
|
leInt2Buff: leInt2Buff$2
|
|
|
|
});
|
|
|
|
|
|
|
|
function buildBatchConvert(tm, fnName, sIn, sOut) {
|
|
|
|
return async function batchConvert(buffIn) {
|
|
|
|
const nPoints = Math.floor(buffIn.byteLength / sIn);
|
|
|
|
if ( nPoints * sIn !== buffIn.byteLength) {
|
|
|
|
throw new Error("Invalid buffer size");
|
|
|
|
}
|
|
|
|
const pointsPerChunk = Math.floor(nPoints/tm.concurrency);
|
|
|
|
const opPromises = [];
|
|
|
|
for (let i=0; i<tm.concurrency; i++) {
|
|
|
|
let n;
|
|
|
|
if (i< tm.concurrency-1) {
|
|
|
|
n = pointsPerChunk;
|
|
|
|
} else {
|
|
|
|
n = nPoints - i*pointsPerChunk;
|
|
|
|
}
|
|
|
|
if (n==0) continue;
|
|
|
|
|
|
|
|
const buffChunk = buffIn.slice(i*pointsPerChunk*sIn, i*pointsPerChunk*sIn + n*sIn);
|
|
|
|
const task = [
|
|
|
|
{cmd: "ALLOCSET", var: 0, buff:buffChunk},
|
|
|
|
{cmd: "ALLOC", var: 1, len:sOut * n},
|
|
|
|
{cmd: "CALL", fnName: fnName, params: [
|
|
|
|
{var: 0},
|
|
|
|
{val: n},
|
|
|
|
{var: 1}
|
|
|
|
]},
|
|
|
|
{cmd: "GET", out: 0, var: 1, len:sOut * n},
|
|
|
|
];
|
|
|
|
opPromises.push(
|
|
|
|
tm.queueAction(task)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
const result = await Promise.all(opPromises);
|
|
|
|
|
|
|
|
const fullBuffOut = new Uint8Array(nPoints*sOut);
|
|
|
|
let p =0;
|
|
|
|
for (let i=0; i<result.length; i++) {
|
|
|
|
fullBuffOut.set(result[i][0], p);
|
|
|
|
p+=result[i][0].byteLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
return fullBuffOut;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
class WasmField1 {
|
|
|
|
|
|
|
|
constructor(tm, prefix, n8, p) {
|
|
|
|
this.tm = tm;
|
|
|
|
this.prefix = prefix;
|
|
|
|
|
|
|
|
this.p = p;
|
|
|
|
this.n8 = n8;
|
|
|
|
this.type = "F1";
|
|
|
|
this.m = 1;
|
|
|
|
|
|
|
|
this.half = shiftRight$2(p, one);
|
|
|
|
this.bitLength = bitLength$2(p);
|
|
|
|
this.mask = sub$2(shiftLeft$2(one, this.bitLength), one);
|
|
|
|
|
|
|
|
this.pOp1 = tm.alloc(n8);
|
|
|
|
this.pOp2 = tm.alloc(n8);
|
|
|
|
this.pOp3 = tm.alloc(n8);
|
|
|
|
this.tm.instance.exports[prefix + "_zero"](this.pOp1);
|
|
|
|
this.zero = this.tm.getBuff(this.pOp1, this.n8);
|
|
|
|
this.tm.instance.exports[prefix + "_one"](this.pOp1);
|
|
|
|
this.one = this.tm.getBuff(this.pOp1, this.n8);
|
|
|
|
|
|
|
|
this.negone = this.neg(this.one);
|
|
|
|
this.two = this.add(this.one, this.one);
|
|
|
|
|
|
|
|
this.n64 = Math.floor(n8/8);
|
|
|
|
this.n32 = Math.floor(n8/4);
|
|
|
|
|
|
|
|
if(this.n64*8 != this.n8) {
|
|
|
|
throw new Error("n8 must be a multiple of 8");
|
|
|
|
}
|
|
|
|
|
|
|
|
this.half = shiftRight$2(this.p, one);
|
|
|
|
this.nqr = this.two;
|
|
|
|
let r = this.exp(this.nqr, this.half);
|
|
|
|
while (!this.eq(r, this.negone)) {
|
|
|
|
this.nqr = this.add(this.nqr, this.one);
|
|
|
|
r = this.exp(this.nqr, this.half);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
this.s = 0;
|
|
|
|
let t = sub$2(this.p, one);
|
|
|
|
|
|
|
|
while ( !isOdd$2(t) ) {
|
|
|
|
this.s = this.s + 1;
|
|
|
|
t = shiftRight$2(t, one);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.w = [];
|
|
|
|
this.w[this.s] = this.exp(this.nqr, t);
|
|
|
|
|
|
|
|
for (let i= this.s-1; i>=0; i--) {
|
|
|
|
this.w[i] = this.square(this.w[i+1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!this.eq(this.w[0], this.one)) {
|
|
|
|
throw new Error("Error calculating roots of unity");
|
|
|
|
}
|
|
|
|
|
|
|
|
this.batchToMontgomery = buildBatchConvert(tm, prefix + "_batchToMontgomery", this.n8, this.n8);
|
|
|
|
this.batchFromMontgomery = buildBatchConvert(tm, prefix + "_batchFromMontgomery", this.n8, this.n8);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
op2(opName, a, b) {
|
|
|
|
this.tm.setBuff(this.pOp1, a);
|
|
|
|
this.tm.setBuff(this.pOp2, b);
|
|
|
|
this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp2, this.pOp3);
|
|
|
|
return this.tm.getBuff(this.pOp3, this.n8);
|
|
|
|
}
|
|
|
|
|
|
|
|
op2Bool(opName, a, b) {
|
|
|
|
this.tm.setBuff(this.pOp1, a);
|
|
|
|
this.tm.setBuff(this.pOp2, b);
|
|
|
|
return !!this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp2);
|
|
|
|
}
|
|
|
|
|
|
|
|
op1(opName, a) {
|
|
|
|
this.tm.setBuff(this.pOp1, a);
|
|
|
|
this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp3);
|
|
|
|
return this.tm.getBuff(this.pOp3, this.n8);
|
|
|
|
}
|
|
|
|
|
|
|
|
op1Bool(opName, a) {
|
|
|
|
this.tm.setBuff(this.pOp1, a);
|
|
|
|
return !!this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp3);
|
|
|
|
}
|
|
|
|
|
|
|
|
add(a,b) {
|
|
|
|
return this.op2("_add", a, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
eq(a,b) {
|
|
|
|
return this.op2Bool("_eq", a, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
isZero(a) {
|
|
|
|
return this.op1Bool("_isZero", a);
|
|
|
|
}
|
|
|
|
|
|
|
|
sub(a,b) {
|
|
|
|
return this.op2("_sub", a, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
neg(a) {
|
|
|
|
return this.op1("_neg", a);
|
|
|
|
}
|
|
|
|
|
|
|
|
inv(a) {
|
|
|
|
return this.op1("_inverse", a);
|
|
|
|
}
|
|
|
|
|
|
|
|
toMontgomery(a) {
|
|
|
|
return this.op1("_toMontgomery", a);
|
|
|
|
}
|
|
|
|
|
|
|
|
fromMontgomery(a) {
|
|
|
|
return this.op1("_fromMontgomery", a);
|
|
|
|
}
|
|
|
|
|
|
|
|
mul(a,b) {
|
|
|
|
return this.op2("_mul", a, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
div(a, b) {
|
|
|
|
this.tm.setBuff(this.pOp1, a);
|
|
|
|
this.tm.setBuff(this.pOp2, b);
|
|
|
|
this.tm.instance.exports[this.prefix + "_inverse"](this.pOp2, this.pOp2);
|
|
|
|
this.tm.instance.exports[this.prefix + "_mul"](this.pOp1, this.pOp2, this.pOp3);
|
|
|
|
return this.tm.getBuff(this.pOp3, this.n8);
|
|
|
|
}
|
|
|
|
|
|
|
|
square(a) {
|
|
|
|
return this.op1("_square", a);
|
|
|
|
}
|
|
|
|
|
|
|
|
isSquare(a) {
|
|
|
|
return this.op1Bool("_isSquare", a);
|
|
|
|
}
|
|
|
|
|
|
|
|
sqrt(a) {
|
|
|
|
return this.op1("_sqrt", a);
|
|
|
|
}
|
|
|
|
|
|
|
|
exp(a, b) {
|
|
|
|
if (!(b instanceof Uint8Array)) {
|
|
|
|
b = toLEBuff(e$2(b));
|
|
|
|
}
|
|
|
|
this.tm.setBuff(this.pOp1, a);
|
|
|
|
this.tm.setBuff(this.pOp2, b);
|
|
|
|
this.tm.instance.exports[this.prefix + "_exp"](this.pOp1, this.pOp2, b.byteLength, this.pOp3);
|
|
|
|
return this.tm.getBuff(this.pOp3, this.n8);
|
|
|
|
}
|
|
|
|
|
|
|
|
isNegative(a) {
|
|
|
|
return this.op1Bool("_isNegative", a);
|
|
|
|
}
|
|
|
|
|
|
|
|
e(a, b) {
|
|
|
|
if (a instanceof Uint8Array) return a;
|
|
|
|
let ra = e$2(a, b);
|
|
|
|
if (isNegative$2(ra)) {
|
|
|
|
ra = neg$2(ra);
|
|
|
|
if (gt$2(ra, this.p)) {
|
|
|
|
ra = mod$2(ra, this.p);
|
|
|
|
}
|
|
|
|
ra = sub$2(this.p, ra);
|
|
|
|
} else {
|
|
|
|
if (gt$2(ra, this.p)) {
|
|
|
|
ra = mod$2(ra, this.p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const buff = leInt2Buff$2(ra, this.n8);
|
|
|
|
return this.toMontgomery(buff);
|
|
|
|
}
|
|
|
|
|
|
|
|
toString(a, radix) {
|
|
|
|
const an = this.fromMontgomery(a);
|
|
|
|
const s = fromRprLE(an, 0);
|
|
|
|
return toString(s, radix);
|
|
|
|
}
|
|
|
|
|
|
|
|
fromRng(rng) {
|
|
|
|
let v;
|
|
|
|
const buff = new Uint8Array(this.n8);
|
|
|
|
do {
|
|
|
|
v = zero;
|
|
|
|
for (let i=0; i<this.n64; i++) {
|
|
|
|
v = add$2(v, shiftLeft$2(rng.nextU64(), 64*i));
|
|
|
|
}
|
|
|
|
v = band$2(v, this.mask);
|
|
|
|
} while (geq$2(v, this.p));
|
|
|
|
toRprLE(buff, 0, v, this.n8);
|
|
|
|
return buff;
|
|
|
|
}
|
|
|
|
|
|
|
|
random() {
|
|
|
|
return this.fromRng(getThreadRng());
|
|
|
|
}
|
|
|
|
|
|
|
|
toObject(a) {
|
|
|
|
const an = this.fromMontgomery(a);
|
|
|
|
return fromRprLE(an, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
fromObject(a) {
|
|
|
|
const buff = new Uint8Array(this.n8);
|
|
|
|
toRprLE(buff, 0, a, this.n8);
|
|
|
|
return this.toMontgomery(buff);
|
|
|
|
}
|
|
|
|
|
|
|
|
toRprLE(buff, offset, a) {
|
|
|
|
buff.set(this.fromMontgomery(a), offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
fromRprLE(buff, offset) {
|
|
|
|
const res = buff.slice(offset, offset + this.n8);
|
|
|
|
return this.toMontgomery(res);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
class WasmField2 {
|
|
|
|
|
|
|
|
constructor(tm, prefix, F) {
|
|
|
|
this.tm = tm;
|
|
|
|
this.prefix = prefix;
|
|
|
|
|
|
|
|
this.F = F;
|
|
|
|
this.type = "F2";
|
|
|
|
this.m = F.m * 2;
|
|
|
|
this.n8 = this.F.n8*2;
|
|
|
|
this.n32 = this.F.n32*2;
|
|
|
|
this.n64 = this.F.n64*2;
|
|
|
|
|
|
|
|
this.pOp1 = tm.alloc(F.n8*2);
|
|
|
|
this.pOp2 = tm.alloc(F.n8*2);
|
|
|
|
this.pOp3 = tm.alloc(F.n8*2);
|
|
|
|
this.tm.instance.exports[prefix + "_zero"](this.pOp1);
|
|
|
|
this.zero = tm.getBuff(this.pOp1, this.n8);
|
|
|
|
this.tm.instance.exports[prefix + "_one"](this.pOp1);
|
|
|
|
this.one = tm.getBuff(this.pOp1, this.n8);
|
|
|
|
|
|
|
|
this.negone = this.neg(this.one);
|
|
|
|
this.two = this.add(this.one, this.one);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
op2(opName, a, b) {
|
|
|
|
this.tm.setBuff(this.pOp1, a);
|
|
|
|
this.tm.setBuff(this.pOp2, b);
|
|
|
|
this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp2, this.pOp3);
|
|
|
|
return this.tm.getBuff(this.pOp3, this.n8);
|
|
|
|
}
|
|
|
|
|
|
|
|
op2Bool(opName, a, b) {
|
|
|
|
this.tm.setBuff(this.pOp1, a);
|
|
|
|
this.tm.setBuff(this.pOp2, b);
|
|
|
|
return !!this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp2);
|
|
|
|
}
|
|
|
|
|
|
|
|
op1(opName, a) {
|
|
|
|
this.tm.setBuff(this.pOp1, a);
|
|
|
|
this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp3);
|
|
|
|
return this.tm.getBuff(this.pOp3, this.n8);
|
|
|
|
}
|
|
|
|
|
|
|
|
op1Bool(opName, a) {
|
|
|
|
this.tm.setBuff(this.pOp1, a);
|
|
|
|
return !!this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp3);
|
|
|
|
}
|
|
|
|
|
|
|
|
add(a,b) {
|
|
|
|
return this.op2("_add", a, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
eq(a,b) {
|
|
|
|
return this.op2Bool("_eq", a, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
isZero(a) {
|
|
|
|
return this.op1Bool("_isZero", a);
|
|
|
|
}
|
|
|
|
|
|
|
|
sub(a,b) {
|
|
|
|
return this.op2("_sub", a, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
neg(a) {
|
|
|
|
return this.op1("_neg", a);
|
|
|
|
}
|
|
|
|
|
|
|
|
inv(a) {
|
|
|
|
return this.op1("_inverse", a);
|
|
|
|
}
|
|
|
|
|
|
|
|
isNegative(a) {
|
|
|
|
return this.op1Bool("_isNegative", a);
|
|
|
|
}
|
|
|
|
|
|
|
|
toMontgomery(a) {
|
|
|
|
return this.op1("_toMontgomery", a);
|
|
|
|
}
|
|
|
|
|
|
|
|
fromMontgomery(a) {
|
|
|
|
return this.op1("_fromMontgomery", a);
|
|
|
|
}
|
|
|
|
|
|
|
|
mul(a,b) {
|
|
|
|
return this.op2("_mul", a, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
div(a, b) {
|
|
|
|
this.tm.setBuff(this.pOp1, a);
|
|
|
|
this.tm.setBuff(this.pOp2, b);
|
|
|
|
this.tm.instance.exports[this.prefix + "_inverse"](this.pOp2, this.pOp2);
|
|
|
|
this.tm.instance.exports[this.prefix + "_mul"](this.pOp1, this.pOp2, this.pOp3);
|
|
|
|
return this.tm.getBuff(this.pOp3, this.n8);
|
|
|
|
}
|
|
|
|
|
|
|
|
square(a) {
|
|
|
|
return this.op1("_square", a);
|
|
|
|
}
|
|
|
|
|
|
|
|
isSquare(a) {
|
|
|
|
return this.op1Bool("_isSquare", a);
|
|
|
|
}
|
|
|
|
|
|
|
|
sqrt(a) {
|
|
|
|
return this.op1("_sqrt", a);
|
|
|
|
}
|
|
|
|
|
|
|
|
exp(a, b) {
|
|
|
|
if (!(b instanceof Uint8Array)) {
|
|
|
|
b = toLEBuff(e$2(b));
|
|
|
|
}
|
|
|
|
this.tm.setBuff(this.pOp1, a);
|
|
|
|
this.tm.setBuff(this.pOp2, b);
|
|
|
|
this.tm.instance.exports[this.prefix + "_exp"](this.pOp1, this.pOp2, b.byteLength, this.pOp3);
|
|
|
|
return this.tm.getBuff(this.pOp3, this.n8);
|
|
|
|
}
|
|
|
|
|
|
|
|
e(a, b) {
|
|
|
|
if (a instanceof Uint8Array) return a;
|
|
|
|
if ((Array.isArray(a)) && (a.length == 2)) {
|
|
|
|
const c1 = this.F.e(a[0], b);
|
|
|
|
const c2 = this.F.e(a[1], b);
|
|
|
|
const res = new Uint8Array(this.F.n8*2);
|
|
|
|
res.set(c1);
|
|
|
|
res.set(c2, this.F.n8*2);
|
|
|
|
return res;
|
|
|
|
} else {
|
|
|
|
throw new Error("invalid F2");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
toString(a, radix) {
|
|
|
|
const s1 = this.F.toString(a.slice(0, this.F.n8), radix);
|
|
|
|
const s2 = this.F.toString(a.slice(this.F.n8), radix);
|
|
|
|
return `[${s1}, ${s2}]`;
|
|
|
|
}
|
|
|
|
|
|
|
|
fromRng(rng) {
|
|
|
|
const c1 = this.F.fromRng(rng);
|
|
|
|
const c2 = this.F.fromRng(rng);
|
|
|
|
const res = new Uint8Array(this.F.n8*2);
|
|
|
|
res.set(c1);
|
|
|
|
res.set(c2, this.F.n8);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
random() {
|
|
|
|
return this.fromRng(getThreadRng());
|
|
|
|
}
|
|
|
|
|
|
|
|
toObject(a) {
|
|
|
|
const c1 = this.F.toObject(a.slice(0, this.F.n8));
|
|
|
|
const c2 = this.F.toObject(a.slice(this.F.n8, this.F.n8*2));
|
|
|
|
return [c1, c2];
|
|
|
|
}
|
|
|
|
|
|
|
|
fromObject(a) {
|
|
|
|
const buff = new Uint8Array(this.F.n8*2);
|
|
|
|
const b1 = this.F.fromObject(a[0]);
|
|
|
|
const b2 = this.F.fromObject(a[1]);
|
|
|
|
buff.set(b1);
|
|
|
|
buff.set(b2, this.F.n8);
|
|
|
|
return buff;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
class WasmField3 {
|
|
|
|
|
|
|
|
constructor(tm, prefix, F) {
|
|
|
|
this.tm = tm;
|
|
|
|
this.prefix = prefix;
|
|
|
|
|
|
|
|
this.F = F;
|
|
|
|
this.type = "F3";
|
|
|
|
this.m = F.m * 3;
|
|
|
|
this.n8 = this.F.n8*3;
|
|
|
|
this.n32 = this.F.n32*3;
|
|
|
|
this.n64 = this.F.n64*3;
|
|
|
|
|
|
|
|
this.pOp1 = tm.alloc(F.n8*3);
|
|
|
|
this.pOp2 = tm.alloc(F.n8*3);
|
|
|
|
this.pOp3 = tm.alloc(F.n8*3);
|
|
|
|
this.tm.instance.exports[prefix + "_zero"](this.pOp1);
|
|
|
|
this.zero = tm.getBuff(this.pOp1, this.n8);
|
|
|
|
this.tm.instance.exports[prefix + "_one"](this.pOp1);
|
|
|
|
this.one = tm.getBuff(this.pOp1, this.n8);
|
|
|
|
|
|
|
|
this.negone = this.neg(this.one);
|
|
|
|
this.two = this.add(this.one, this.one);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
op2(opName, a, b) {
|
|
|
|
this.tm.setBuff(this.pOp1, a);
|
|
|
|
this.tm.setBuff(this.pOp2, b);
|
|
|
|
this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp2, this.pOp3);
|
|
|
|
return this.tm.getBuff(this.pOp3, this.n8);
|
|
|
|
}
|
|
|
|
|
|
|
|
op2Bool(opName, a, b) {
|
|
|
|
this.tm.setBuff(this.pOp1, a);
|
|
|
|
this.tm.setBuff(this.pOp2, b);
|
|
|
|
return !!this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp2);
|
|
|
|
}
|
|
|
|
|
|
|
|
op1(opName, a) {
|
|
|
|
this.tm.setBuff(this.pOp1, a);
|
|
|
|
this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp3);
|
|
|
|
return this.tm.getBuff(this.pOp3, this.n8);
|
|
|
|
}
|
|
|
|
|
|
|
|
op1Bool(opName, a) {
|
|
|
|
this.tm.setBuff(this.pOp1, a);
|
|
|
|
return !!this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp3);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
eq(a,b) {
|
|
|
|
return this.op2Bool("_eq", a, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
isZero(a) {
|
|
|
|
return this.op1Bool("_isZero", a);
|
|
|
|
}
|
|
|
|
|
|
|
|
add(a,b) {
|
|
|
|
return this.op2("_add", a, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
sub(a,b) {
|
|
|
|
return this.op2("_sub", a, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
neg(a) {
|
|
|
|
return this.op1("_neg", a);
|
|
|
|
}
|
|
|
|
|
|
|
|
inv(a) {
|
|
|
|
return this.op1("_inverse", a);
|
|
|
|
}
|
|
|
|
|
|
|
|
isNegative(a) {
|
|
|
|
return this.op1Bool("_isNegative", a);
|
|
|
|
}
|
|
|
|
|
|
|
|
toMontgomery(a) {
|
|
|
|
return this.op1("_toMontgomery", a);
|
|
|
|
}
|
|
|
|
|
|
|
|
fromMontgomery(a) {
|
|
|
|
return this.op1("_fromMontgomery", a);
|
|
|
|
}
|
|
|
|
|
|
|
|
mul(a,b) {
|
|
|
|
return this.op2("_mul", a, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
div(a, b) {
|
|
|
|
this.tm.setBuff(this.pOp1, a);
|
|
|
|
this.tm.setBuff(this.pOp2, b);
|
|
|
|
this.tm.instance.exports[this.prefix + "_inverse"](this.pOp2, this.pOp2);
|
|
|
|
this.tm.instance.exports[this.prefix + "_mul"](this.pOp1, this.pOp2, this.pOp3);
|
|
|
|
return this.tm.getBuff(this.pOp3, this.n8);
|
|
|
|
}
|
|
|
|
|
|
|
|
square(a) {
|
|
|
|
return this.op1("_square", a);
|
|
|
|
}
|
|
|
|
|
|
|
|
isSquare(a) {
|
|
|
|
return this.op1Bool("_isSquare", a);
|
|
|
|
}
|
|
|
|
|
|
|
|
sqrt(a) {
|
|
|
|
return this.op1("_sqrt", a);
|
|
|
|
}
|
|
|
|
|
|
|
|
exp(a, b) {
|
|
|
|
if (!(b instanceof Uint8Array)) {
|
|
|
|
b = toLEBuff(e$2(b));
|
|
|
|
}
|
|
|
|
this.tm.setBuff(this.pOp1, a);
|
|
|
|
this.tm.setBuff(this.pOp2, b);
|
|
|
|
this.tm.instance.exports[this.prefix + "_exp"](this.pOp1, this.pOp2, b.byteLength, this.pOp3);
|
|
|
|
return this.getBuff(this.pOp3, this.n8);
|
|
|
|
}
|
|
|
|
|
|
|
|
e(a, b) {
|
|
|
|
if (a instanceof Uint8Array) return a;
|
|
|
|
if ((Array.isArray(a)) && (a.length == 3)) {
|
|
|
|
const c1 = this.F.e(a[0], b);
|
|
|
|
const c2 = this.F.e(a[1], b);
|
|
|
|
const c3 = this.F.e(a[2], b);
|
|
|
|
const res = new Uint8Array(this.F.n8*3);
|
|
|
|
res.set(c1);
|
|
|
|
res.set(c2, this.F.n8);
|
|
|
|
res.set(c3, this.F.n8*2);
|
|
|
|
return res;
|
|
|
|
} else {
|
|
|
|
throw new Error("invalid F3");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
toString(a, radix) {
|
|
|
|
const s1 = this.F.toString(a.slice(0, this.F.n8), radix);
|
|
|
|
const s2 = this.F.toString(a.slice(this.F.n8, this.F.n8*2), radix);
|
|
|
|
const s3 = this.F.toString(a.slice(this.F.n8*2), radix);
|
|
|
|
return `[${s1}, ${s2}, ${s3}]`;
|
|
|
|
}
|
|
|
|
|
|
|
|
fromRng(rng) {
|
|
|
|
const c1 = this.F.fromRng(rng);
|
|
|
|
const c2 = this.F.fromRng(rng);
|
|
|
|
const c3 = this.F.fromRng(rng);
|
|
|
|
const res = new Uint8Array(this.F.n8*3);
|
|
|
|
res.set(c1);
|
|
|
|
res.set(c2, this.F.n8);
|
|
|
|
res.set(c3, this.F.n8*2);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
random() {
|
|
|
|
return this.fromRng(getThreadRng());
|
|
|
|
}
|
|
|
|
|
|
|
|
toObject(a) {
|
|
|
|
const c1 = this.F.toObject(a.slice(0, this.F.n8));
|
|
|
|
const c2 = this.F.toObject(a.slice(this.F.n8, this.F.n8*2));
|
|
|
|
const c3 = this.F.toObject(a.slice(this.F.n8*2, this.F.n8*3));
|
|
|
|
return [c1, c2, c3];
|
|
|
|
}
|
|
|
|
|
|
|
|
fromObject(a) {
|
|
|
|
const buff = new Uint8Array(this.F.n8*3);
|
|
|
|
const b1 = this.F.fromObject(a[0]);
|
|
|
|
const b2 = this.F.fromObject(a[1]);
|
|
|
|
const b3 = this.F.fromObject(a[2]);
|
|
|
|
buff.set(b1);
|
|
|
|
buff.set(b2, this.F.n8);
|
|
|
|
buff.set(b3, this.F.n8*2);
|
|
|
|
return buff;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
class WasmCurve {
|
|
|
|
|
|
|
|
constructor(tm, prefix, F, pGen, pGb, cofactor) {
|
|
|
|
this.tm = tm;
|
|
|
|
this.prefix = prefix;
|
|
|
|
this.F = F;
|
|
|
|
|
|
|
|
this.pOp1 = tm.alloc(F.n8*3);
|
|
|
|
this.pOp2 = tm.alloc(F.n8*3);
|
|
|
|
this.pOp3 = tm.alloc(F.n8*3);
|
|
|
|
this.tm.instance.exports[prefix + "_zero"](this.pOp1);
|
|
|
|
this.zero = this.tm.getBuff(this.pOp1, F.n8*3);
|
|
|
|
this.tm.instance.exports[prefix + "_zeroAffine"](this.pOp1);
|
|
|
|
this.zeroAffine = this.tm.getBuff(this.pOp1, F.n8*2);
|
|
|
|
this.one = this.tm.getBuff(pGen, F.n8*3);
|
|
|
|
this.g = this.one;
|
|
|
|
this.oneAffine = this.tm.getBuff(pGen, F.n8*2);
|
|
|
|
this.gAffine = this.oneAffine;
|
|
|
|
this.b = this.tm.getBuff(pGb, F.n8);
|
|
|
|
|
|
|
|
if (cofactor) {
|
|
|
|
this.cofactor = toLEBuff(cofactor);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.negone = this.neg(this.one);
|
|
|
|
this.two = this.add(this.one, this.one);
|
|
|
|
|
|
|
|
this.batchLEMtoC = buildBatchConvert(tm, prefix + "_batchLEMtoC", F.n8*2, F.n8);
|
|
|
|
this.batchLEMtoU = buildBatchConvert(tm, prefix + "_batchLEMtoU", F.n8*2, F.n8*2);
|
|
|
|
this.batchCtoLEM = buildBatchConvert(tm, prefix + "_batchCtoLEM", F.n8, F.n8*2);
|
|
|
|
this.batchUtoLEM = buildBatchConvert(tm, prefix + "_batchUtoLEM", F.n8*2, F.n8*2);
|
|
|
|
this.batchToJacobian = buildBatchConvert(tm, prefix + "_batchToJacobian", F.n8*2, F.n8*3);
|
|
|
|
this.batchToAffine = buildBatchConvert(tm, prefix + "_batchToAffine", F.n8*3, F.n8*2);
|
|
|
|
}
|
|
|
|
|
|
|
|
op2(opName, a, b) {
|
|
|
|
this.tm.setBuff(this.pOp1, a);
|
|
|
|
this.tm.setBuff(this.pOp2, b);
|
|
|
|
this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp2, this.pOp3);
|
|
|
|
return this.tm.getBuff(this.pOp3, this.F.n8*3);
|
|
|
|
}
|
|
|
|
|
|
|
|
op2bool(opName, a, b) {
|
|
|
|
this.tm.setBuff(this.pOp1, a);
|
|
|
|
this.tm.setBuff(this.pOp2, b);
|
|
|
|
return !!this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp2, this.pOp3);
|
|
|
|
}
|
|
|
|
|
|
|
|
op1(opName, a) {
|
|
|
|
this.tm.setBuff(this.pOp1, a);
|
|
|
|
this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp3);
|
|
|
|
return this.tm.getBuff(this.pOp3, this.F.n8*3);
|
|
|
|
}
|
|
|
|
|
|
|
|
op1Affine(opName, a) {
|
|
|
|
this.tm.setBuff(this.pOp1, a);
|
|
|
|
this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp3);
|
|
|
|
return this.tm.getBuff(this.pOp3, this.F.n8*2);
|
|
|
|
}
|
|
|
|
|
|
|
|
op1Bool(opName, a) {
|
|
|
|
this.tm.setBuff(this.pOp1, a);
|
|
|
|
return !!this.tm.instance.exports[this.prefix + opName](this.pOp1, this.pOp3);
|
|
|
|
}
|
|
|
|
|
|
|
|
add(a,b) {
|
|
|
|
if (a.byteLength == this.F.n8*3) {
|
|
|
|
if (b.byteLength == this.F.n8*3) {
|
|
|
|
return this.op2("_add", a, b);
|
|
|
|
} else if (b.byteLength == this.F.n8*2) {
|
|
|
|
return this.op2("_addMixed", a, b);
|
|
|
|
} else {
|
|
|
|
throw new Error("invalid point size");
|
|
|
|
}
|
|
|
|
} else if (a.byteLength == this.F.n8*2) {
|
|
|
|
if (b.byteLength == this.F.n8*3) {
|
|
|
|
return this.op2("_addMixed", b, a);
|
|
|
|
} else if (b.byteLength == this.F.n8*2) {
|
|
|
|
return this.op2("_addAffine", a, b);
|
|
|
|
} else {
|
|
|
|
throw new Error("invalid point size");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
throw new Error("invalid point size");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub(a,b) {
|
|
|
|
if (a.byteLength == this.F.n8*3) {
|
|
|
|
if (b.byteLength == this.F.n8*3) {
|
|
|
|
return this.op2("_sub", a, b);
|
|
|
|
} else if (b.byteLength == this.F.n8*2) {
|
|
|
|
return this.op2("_subMixed", a, b);
|
|
|
|
} else {
|
|
|
|
throw new Error("invalid point size");
|
|
|
|
}
|
|
|
|
} else if (a.byteLength == this.F.n8*2) {
|
|
|
|
if (b.byteLength == this.F.n8*3) {
|
|
|
|
return this.op2("_subMixed", b, a);
|
|
|
|
} else if (b.byteLength == this.F.n8*2) {
|
|
|
|
return this.op2("_subAffine", a, b);
|
|
|
|
} else {
|
|
|
|
throw new Error("invalid point size");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
throw new Error("invalid point size");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
neg(a) {
|
|
|
|
if (a.byteLength == this.F.n8*3) {
|
|
|
|
return this.op1("_neg", a);
|
|
|
|
} else if (a.byteLength == this.F.n8*2) {
|
|
|
|
return this.op1Affine("_negAffine", a);
|
|
|
|
} else {
|
|
|
|
throw new Error("invalid point size");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
double(a) {
|
|
|
|
if (a.byteLength == this.F.n8*3) {
|
|
|
|
return this.op1("_double", a);
|
|
|
|
} else if (a.byteLength == this.F.n8*2) {
|
|
|
|
return this.op1("_doubleAffine", a);
|
|
|
|
} else {
|
|
|
|
throw new Error("invalid point size");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
isZero(a) {
|
|
|
|
if (a.byteLength == this.F.n8*3) {
|
|
|
|
return this.op1Bool("_isZero", a);
|
|
|
|
} else if (a.byteLength == this.F.n8*2) {
|
|
|
|
return this.op1Bool("_isZeroAffine", a);
|
|
|
|
} else {
|
|
|
|
throw new Error("invalid point size");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
timesScalar(a, s) {
|
|
|
|
if (!(s instanceof Uint8Array)) {
|
|
|
|
s = toLEBuff(e$2(s));
|
|
|
|
}
|
|
|
|
let fnName;
|
|
|
|
if (a.byteLength == this.F.n8*3) {
|
|
|
|
fnName = this.prefix + "_timesScalar";
|
|
|
|
} else if (a.byteLength == this.F.n8*2) {
|
|
|
|
fnName = this.prefix + "_timesScalarAffine";
|
|
|
|
} else {
|
|
|
|
throw new Error("invalid point size");
|
|
|
|
}
|
|
|
|
this.tm.setBuff(this.pOp1, a);
|
|
|
|
this.tm.setBuff(this.pOp2, s);
|
|
|
|
this.tm.instance.exports[fnName](this.pOp1, this.pOp2, s.byteLength, this.pOp3);
|
|
|
|
return this.tm.getBuff(this.pOp3, this.F.n8*3);
|
|
|
|
}
|
|
|
|
|
|
|
|
timesFr(a, s) {
|
|
|
|
let fnName;
|
|
|
|
if (a.byteLength == this.F.n8*3) {
|
|
|
|
fnName = this.prefix + "_timesFr";
|
|
|
|
} else if (a.byteLength == this.F.n8*2) {
|
|
|
|
fnName = this.prefix + "_timesFrAffine";
|
|
|
|
} else {
|
|
|
|
throw new Error("invalid point size");
|
|
|
|
}
|
|
|
|
this.tm.setBuff(this.pOp1, a);
|
|
|
|
this.tm.setBuff(this.pOp2, s);
|
|
|
|
this.tm.instance.exports[fnName](this.pOp1, this.pOp2, this.pOp3);
|
|
|
|
return this.tm.getBuff(this.pOp3, this.F.n8*3);
|
|
|
|
}
|
|
|
|
|
|
|
|
eq(a,b) {
|
|
|
|
if (a.byteLength == this.F.n8*3) {
|
|
|
|
if (b.byteLength == this.F.n8*3) {
|
|
|
|
return this.op2bool("_eq", a, b);
|
|
|
|
} else if (b.byteLength == this.F.n8*2) {
|
|
|
|
return this.op2bool("_eqMixed", a, b);
|
|
|
|
} else {
|
|
|
|
throw new Error("invalid point size");
|
|
|
|
}
|
|
|
|
} else if (a.byteLength == this.F.n8*2) {
|
|
|
|
if (b.byteLength == this.F.n8*3) {
|
|
|
|
return this.op2bool("_eqMixed", b, a);
|
|
|
|
} else if (b.byteLength == this.F.n8*2) {
|
|
|
|
return this.op2bool("_eqAffine", a, b);
|
|
|
|
} else {
|
|
|
|
throw new Error("invalid point size");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
throw new Error("invalid point size");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
toAffine(a) {
|
|
|
|
if (a.byteLength == this.F.n8*3) {
|
|
|
|
return this.op1Affine("_toAffine", a);
|
|
|
|
} else if (a.byteLength == this.F.n8*2) {
|
|
|
|
return a;
|
|
|
|
} else {
|
|
|
|
throw new Error("invalid point size");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
toJacobian(a) {
|
|
|
|
if (a.byteLength == this.F.n8*3) {
|
|
|
|
return a;
|
|
|
|
} else if (a.byteLength == this.F.n8*2) {
|
|
|
|
return this.op1("_toJacobian", a);
|
|
|
|
} else {
|
|
|
|
throw new Error("invalid point size");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
toRprUncompressed(arr, offset, a) {
|
|
|
|
this.tm.setBuff(this.pOp1, a);
|
|
|
|
if (a.byteLength == this.F.n8*3) {
|
|
|
|
this.tm.instance.exports[this.prefix + "_toAffine"](this.pOp1, this.pOp1);
|
|
|
|
} else if (a.byteLength != this.F.n8*2) {
|
|
|
|
throw new Error("invalid point size");
|
|
|
|
}
|
|
|
|
this.tm.instance.exports[this.prefix + "_LEMtoU"](this.pOp1, this.pOp1);
|
|
|
|
const res = this.tm.getBuff(this.pOp1, this.F.n8*2);
|
|
|
|
arr.set(res, offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
fromRprUncompressed(arr, offset) {
|
|
|
|
const buff = arr.slice(offset, offset + this.F.n8*2);
|
|
|
|
this.tm.setBuff(this.pOp1, buff);
|
|
|
|
this.tm.instance.exports[this.prefix + "_UtoLEM"](this.pOp1, this.pOp1);
|
|
|
|
return this.tm.getBuff(this.pOp1, this.F.n8*2);
|
|
|
|
}
|
|
|
|
|
|
|
|
toRprCompressed(arr, offset, a) {
|
|
|
|
this.tm.setBuff(this.pOp1, a);
|
|
|
|
if (a.byteLength == this.F.n8*3) {
|
|
|
|
this.tm.instance.exports[this.prefix + "_toAffine"](this.pOp1, this.pOp1);
|
|
|
|
} else if (a.byteLength != this.F.n8*2) {
|
|
|
|
throw new Error("invalid point size");
|
|
|
|
}
|
|
|
|
this.tm.instance.exports[this.prefix + "_LEMtoC"](this.pOp1, this.pOp1);
|
|
|
|
const res = this.tm.getBuff(this.pOp1, this.F.n8);
|
|
|
|
arr.set(res, offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
fromRprCompressed(arr, offset) {
|
|
|
|
const buff = arr.slice(offset, offset + this.F.n8);
|
|
|
|
this.tm.setBuff(this.pOp1, buff);
|
|
|
|
this.tm.instance.exports[this.prefix + "_CtoLEM"](this.pOp1, this.pOp2);
|
|
|
|
return this.tm.getBuff(this.pOp2, this.F.n8*2);
|
|
|
|
}
|
|
|
|
|
|
|
|
toUncompressed(a) {
|
|
|
|
const buff = new Uint8Array(this.F.n8*2);
|
|
|
|
this.toRprUncompressed(buff, 0, a);
|
|
|
|
return buff;
|
|
|
|
}
|
|
|
|
|
|
|
|
toRprLEM(arr, offset, a) {
|
|
|
|
if (a.byteLength == this.F.n8*2) {
|
|
|
|
arr.set(a, offset);
|
|
|
|
return;
|
|
|
|
} else if (a.byteLength == this.F.n8*3) {
|
|
|
|
this.tm.setBuff(this.pOp1, a);
|
|
|
|
this.tm.instance.exports[this.prefix + "_toAffine"](this.pOp1, this.pOp1);
|
|
|
|
const res = this.tm.getBuff(this.pOp1, this.F.n8*2);
|
|
|
|
arr.set(res, offset);
|
|
|
|
} else {
|
|
|
|
throw new Error("invalid point size");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fromRprLEM(arr, offset) {
|
|
|
|
offset = offset || 0;
|
|
|
|
return arr.slice(offset, offset+this.F.n8*2);
|
|
|
|
}
|
|
|
|
|
|
|
|
toString(a, radix) {
|
|
|
|
if (a.byteLength == this.F.n8*3) {
|
|
|
|
const x = this.F.toString(a.slice(0, this.F.n8), radix);
|
|
|
|
const y = this.F.toString(a.slice(this.F.n8, this.F.n8*2), radix);
|
|
|
|
const z = this.F.toString(a.slice(this.F.n8*2), radix);
|
|
|
|
return `[ ${x}, ${y}, ${z} ]`;
|
|
|
|
} else if (a.byteLength == this.F.n8*2) {
|
|
|
|
const x = this.F.toString(a.slice(0, this.F.n8), radix);
|
|
|
|
const y = this.F.toString(a.slice(this.F.n8), radix);
|
|
|
|
return `[ ${x}, ${y} ]`;
|
|
|
|
} else {
|
|
|
|
throw new Error("invalid point size");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fromRng(rng) {
|
|
|
|
const F = this.F;
|
|
|
|
let P = [];
|
|
|
|
let greatest;
|
|
|
|
let x3b;
|
|
|
|
do {
|
|
|
|
P[0] = F.fromRng(rng);
|
|
|
|
greatest = rng.nextBool();
|
|
|
|
x3b = F.add(F.mul(F.square(P[0]), P[0]), this.b);
|
|
|
|
} while (!F.isSquare(x3b));
|
|
|
|
|
|
|
|
P[1] = F.sqrt(x3b);
|
|
|
|
|
|
|
|
const s = F.isNegative(P[1]);
|
|
|
|
if (greatest ^ s) P[1] = F.neg(P[1]);
|
|
|
|
|
|
|
|
let Pbuff = new Uint8Array(this.F.n8*2);
|
|
|
|
Pbuff.set(P[0]);
|
|
|
|
Pbuff.set(P[1], this.F.n8);
|
|
|
|
|
|
|
|
if (this.cofactor) {
|
|
|
|
Pbuff = this.timesScalar(Pbuff, this.cofactor);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Pbuff;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
toObject(a) {
|
|
|
|
if (this.isZero(a)) {
|
|
|
|
return [
|
|
|
|
this.F.toObject(this.F.zero),
|
|
|
|
this.F.toObject(this.F.one),
|
|
|
|
this.F.toObject(this.F.zero),
|
|
|
|
];
|
|
|
|
}
|
|
|
|
const x = this.F.toObject(a.slice(0, this.F.n8));
|
|
|
|
const y = this.F.toObject(a.slice(this.F.n8, this.F.n8*2));
|
|
|
|
let z;
|
|
|
|
if (a.byteLength == this.F.n8*3) {
|
|
|
|
z = this.F.toObject(a.slice(this.F.n8*2, this.F.n8*3));
|
|
|
|
} else {
|
|
|
|
z = this.F.toObject(this.F.one);
|
|
|
|
}
|
|
|
|
return [x, y, z];
|
|
|
|
}
|
|
|
|
|
|
|
|
fromObject(a) {
|
|
|
|
const x = this.F.fromObject(a[0]);
|
|
|
|
const y = this.F.fromObject(a[1]);
|
|
|
|
let z;
|
|
|
|
if (a.length==3) {
|
|
|
|
z = this.F.fromObject(a[2]);
|
|
|
|
} else {
|
|
|
|
z = this.F.one;
|
|
|
|
}
|
|
|
|
if (this.F.isZero(z, this.F.one)) {
|
|
|
|
return this.zeroAffine;
|
|
|
|
} else if (this.F.eq(z, this.F.one)) {
|
|
|
|
const buff = new Uint8Array(this.F.n8*2);
|
|
|
|
buff.set(x);
|
|
|
|
buff.set(y, this.F.n8);
|
|
|
|
return buff;
|
|
|
|
} else {
|
|
|
|
const buff = new Uint8Array(this.F.n8*3);
|
|
|
|
buff.set(x);
|
|
|
|
buff.set(y, this.F.n8);
|
|
|
|
buff.set(z, this.F.n8*2);
|
|
|
|
return buff;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
e(a) {
|
|
|
|
if (a instanceof Uint8Array) return a;
|
|
|
|
return this.fromObject(a);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* global WebAssembly */
|
|
|
|
|
|
|
|
function thread(self) {
|
|
|
|
let instance;
|
|
|
|
let memory;
|
|
|
|
let u32;
|
|
|
|
let u8;
|
|
|
|
|
|
|
|
if (self) {
|
|
|
|
self.onmessage = function(e) {
|
|
|
|
let data;
|
|
|
|
if (e.data) {
|
|
|
|
data = e.data;
|
|
|
|
} else {
|
|
|
|
data = e;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (data[0].cmd == "INIT") {
|
|
|
|
init(data[0]).then(function() {
|
|
|
|
self.postMessage(data.result);
|
|
|
|
});
|
|
|
|
} else if (data[0].cmd == "TERMINATE") {
|
|
|
|
process.exit();
|
|
|
|
} else {
|
|
|
|
const res = runTask(data);
|
|
|
|
self.postMessage(res);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
async function init(data) {
|
|
|
|
const code = new Uint8Array(data.code);
|
|
|
|
const wasmModule = await WebAssembly.compile(code);
|
|
|
|
memory = new WebAssembly.Memory({initial:data.init});
|
|
|
|
u32 = new Uint32Array(memory.buffer);
|
|
|
|
u8 = new Uint8Array(memory.buffer);
|
|
|
|
|
|
|
|
instance = await WebAssembly.instantiate(wasmModule, {
|
|
|
|
env: {
|
|
|
|
"memory": memory
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function alloc(length) {
|
|
|
|
while (u32[0] & 3) u32[0]++; // Return always aligned pointers
|
|
|
|
const res = u32[0];
|
|
|
|
u32[0] += length;
|
|
|
|
while (u32[0] > memory.buffer.byteLength) {
|
|
|
|
memory.grow(100);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
function allocBuffer(buffer) {
|
|
|
|
const p = alloc(buffer.byteLength);
|
|
|
|
setBuffer(p, buffer);
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
function getBuffer(pointer, length) {
|
|
|
|
return new Uint8Array(u8.buffer, u8.byteOffset + pointer, length);
|
|
|
|
}
|
|
|
|
|
|
|
|
function setBuffer(pointer, buffer) {
|
|
|
|
u8.set(new Uint8Array(buffer), pointer);
|
|
|
|
}
|
|
|
|
|
|
|
|
function runTask(task) {
|
|
|
|
if (task[0].cmd == "INIT") {
|
|
|
|
return init(task[0]);
|
|
|
|
}
|
|
|
|
const ctx = {
|
|
|
|
vars: [],
|
|
|
|
out: []
|
|
|
|
};
|
|
|
|
const oldAlloc = u32[0];
|
|
|
|
for (let i=0; i<task.length; i++) {
|
|
|
|
switch (task[i].cmd) {
|
|
|
|
case "ALLOCSET":
|
|
|
|
ctx.vars[task[i].var] = allocBuffer(task[i].buff);
|
|
|
|
break;
|
|
|
|
case "ALLOC":
|
|
|
|
ctx.vars[task[i].var] = alloc(task[i].len);
|
|
|
|
break;
|
|
|
|
case "SET":
|
|
|
|
setBuffer(ctx.vars[task[i].var], task[i].buff);
|
|
|
|
break;
|
|
|
|
case "CALL": {
|
|
|
|
const params = [];
|
|
|
|
for (let j=0; j<task[i].params.length; j++) {
|
|
|
|
const p = task[i].params[j];
|
|
|
|
if (typeof p.var !== "undefined") {
|
|
|
|
params.push(ctx.vars[p.var] + (p.offset || 0));
|
|
|
|
} else if (typeof p.val != "undefined") {
|
|
|
|
params.push(p.val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
instance.exports[task[i].fnName](...params);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case "GET":
|
|
|
|
ctx.out[task[i].out] = getBuffer(ctx.vars[task[i].var], task[i].len).slice();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
throw new Error("Invalid cmd");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
u32[0] = oldAlloc;
|
|
|
|
return ctx.out;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return runTask;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* global window, navigator, Blob, Worker, WebAssembly */
|
|
|
|
/*
|
|
|
|
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/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
const MEM_SIZE = 4096; // Memory size in 64K Pakes (256Mb)
|
|
|
|
const inBrowser = (typeof window !== "undefined");
|
|
|
|
let NodeWorker;
|
|
|
|
if (!inBrowser) {
|
|
|
|
NodeWorker = crypto.Worker;
|
|
|
|
}
|
|
|
|
|
|
|
|
class Deferred {
|
|
|
|
constructor() {
|
|
|
|
this.promise = new Promise((resolve, reject)=> {
|
|
|
|
this.reject = reject;
|
|
|
|
this.resolve = resolve;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function sleep(ms) {
|
|
|
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
|
|
}
|
|
|
|
|
|
|
|
function base64ToArrayBuffer(base64) {
|
|
|
|
{
|
|
|
|
var binary_string = window.atob(base64);
|
|
|
|
var len = binary_string.length;
|
|
|
|
var bytes = new Uint8Array(len);
|
|
|
|
for (var i = 0; i < len; i++) {
|
|
|
|
bytes[i] = binary_string.charCodeAt(i);
|
|
|
|
}
|
|
|
|
return bytes;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async function buildThreadManager(wasm, singleThread) {
|
|
|
|
const tm = new ThreadManager();
|
|
|
|
|
|
|
|
tm.memory = new WebAssembly.Memory({initial:MEM_SIZE});
|
|
|
|
tm.u8 = new Uint8Array(tm.memory.buffer);
|
|
|
|
tm.u32 = new Uint32Array(tm.memory.buffer);
|
|
|
|
|
|
|
|
const wasmModule = await WebAssembly.compile(base64ToArrayBuffer(wasm.code));
|
|
|
|
|
|
|
|
tm.instance = await WebAssembly.instantiate(wasmModule, {
|
|
|
|
env: {
|
|
|
|
"memory": tm.memory
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
tm.singleThread = singleThread;
|
|
|
|
tm.initalPFree = tm.u32[0]; // Save the Pointer to free space.
|
|
|
|
tm.pq = wasm.pq;
|
|
|
|
tm.pr = wasm.pr;
|
|
|
|
tm.pG1gen = wasm.pG1gen;
|
|
|
|
tm.pG1zero = wasm.pG1zero;
|
|
|
|
tm.pG2gen = wasm.pG2gen;
|
|
|
|
tm.pG2zero = wasm.pG2zero;
|
|
|
|
tm.pOneT = wasm.pOneT;
|
|
|
|
|
|
|
|
// tm.pTmp0 = tm.alloc(curve.G2.F.n8*3);
|
|
|
|
// tm.pTmp1 = tm.alloc(curve.G2.F.n8*3);
|
|
|
|
|
|
|
|
|
|
|
|
if (singleThread) {
|
|
|
|
tm.code = base64ToArrayBuffer(wasm.code);
|
|
|
|
tm.taskManager = thread();
|
|
|
|
await tm.taskManager([{
|
|
|
|
cmd: "INIT",
|
|
|
|
init: MEM_SIZE,
|
|
|
|
code: tm.code.slice()
|
|
|
|
}]);
|
|
|
|
tm.concurrency = 1;
|
|
|
|
} else {
|
|
|
|
tm.workers = [];
|
|
|
|
tm.pendingDeferreds = [];
|
|
|
|
tm.working = [];
|
|
|
|
|
|
|
|
let concurrency;
|
|
|
|
|
|
|
|
if ((typeof(navigator) === "object") && navigator.hardwareConcurrency) {
|
|
|
|
concurrency = navigator.hardwareConcurrency;
|
|
|
|
} else {
|
|
|
|
concurrency = crypto.cpus().length;
|
|
|
|
}
|
|
|
|
tm.concurrency = concurrency;
|
|
|
|
|
|
|
|
for (let i = 0; i<concurrency; i++) {
|
|
|
|
|
|
|
|
if (inBrowser) {
|
|
|
|
const blob = new Blob(["(", thread.toString(), ")(self);"], { type: "text/javascript" });
|
|
|
|
const url = URL.createObjectURL(blob);
|
|
|
|
|
|
|
|
tm.workers[i] = new Worker(url);
|
|
|
|
|
|
|
|
tm.workers[i].onmessage = getOnMsg(i);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
tm.workers[i] = new NodeWorker("(" + thread.toString()+ ")(require('worker_threads').parentPort);", {eval: true});
|
|
|
|
|
|
|
|
tm.workers[i].on("message", getOnMsg(i));
|
|
|
|
}
|
|
|
|
|
|
|
|
tm.working[i]=false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const initPromises = [];
|
|
|
|
for (let i=0; i<tm.workers.length;i++) {
|
|
|
|
const copyCode = base64ToArrayBuffer(wasm.code).slice();
|
|
|
|
initPromises.push(tm.postAction(i, [{
|
|
|
|
cmd: "INIT",
|
|
|
|
init: MEM_SIZE,
|
|
|
|
code: copyCode
|
|
|
|
}], [copyCode.buffer]));
|
|
|
|
}
|
|
|
|
|
|
|
|
await Promise.all(initPromises);
|
|
|
|
|
|
|
|
}
|
|
|
|
return tm;
|
|
|
|
|
|
|
|
function getOnMsg(i) {
|
|
|
|
return function(e) {
|
|
|
|
let data;
|
|
|
|
if ((e)&&(e.data)) {
|
|
|
|
data = e.data;
|
|
|
|
} else {
|
|
|
|
data = e;
|
|
|
|
}
|
|
|
|
|
|
|
|
tm.working[i]=false;
|
|
|
|
tm.pendingDeferreds[i].resolve(data);
|
|
|
|
tm.processWorks();
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
class ThreadManager {
|
|
|
|
constructor() {
|
|
|
|
this.actionQueue = [];
|
|
|
|
this.oldPFree = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
startSyncOp() {
|
|
|
|
if (this.oldPFree != 0) throw new Error("Sync operation in progress");
|
|
|
|
this.oldPFree = this.u32[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
endSyncOp() {
|
|
|
|
if (this.oldPFree == 0) throw new Error("No sync operation in progress");
|
|
|
|
this.u32[0] = this.oldPFree;
|
|
|
|
this.oldPFree = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
postAction(workerId, e, transfers, _deferred) {
|
|
|
|
if (this.working[workerId]) {
|
|
|
|
throw new Error("Posting a job t a working worker");
|
|
|
|
}
|
|
|
|
this.working[workerId] = true;
|
|
|
|
|
|
|
|
this.pendingDeferreds[workerId] = _deferred ? _deferred : new Deferred();
|
|
|
|
this.workers[workerId].postMessage(e, transfers);
|
|
|
|
|
|
|
|
return this.pendingDeferreds[workerId].promise;
|
|
|
|
}
|
|
|
|
|
|
|
|
processWorks() {
|
|
|
|
for (let i=0; (i<this.workers.length)&&(this.actionQueue.length > 0); i++) {
|
|
|
|
if (this.working[i] == false) {
|
|
|
|
const work = this.actionQueue.shift();
|
|
|
|
this.postAction(i, work.data, work.transfers, work.deferred);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
queueAction(actionData, transfers) {
|
|
|
|
const d = new Deferred();
|
|
|
|
|
|
|
|
if (this.singleThread) {
|
|
|
|
const res = this.taskManager(actionData);
|
|
|
|
d.resolve(res);
|
|
|
|
} else {
|
|
|
|
this.actionQueue.push({
|
|
|
|
data: actionData,
|
|
|
|
transfers: transfers,
|
|
|
|
deferred: d
|
|
|
|
});
|
|
|
|
this.processWorks();
|
|
|
|
}
|
|
|
|
return d.promise;
|
|
|
|
}
|
|
|
|
|
|
|
|
resetMemory() {
|
|
|
|
this.u32[0] = this.initalPFree;
|
|
|
|
}
|
|
|
|
|
|
|
|
allocBuff(buff) {
|
|
|
|
const pointer = this.alloc(buff.byteLength);
|
|
|
|
this.setBuff(pointer, buff);
|
|
|
|
return pointer;
|
|
|
|
}
|
|
|
|
|
|
|
|
getBuff(pointer, length) {
|
|
|
|
return this.u8.slice(pointer, pointer+ length);
|
|
|
|
}
|
|
|
|
|
|
|
|
setBuff(pointer, buffer) {
|
|
|
|
this.u8.set(new Uint8Array(buffer), pointer);
|
|
|
|
}
|
|
|
|
|
|
|
|
alloc(length) {
|
|
|
|
while (this.u32[0] & 3) this.u32[0]++; // Return always aligned pointers
|
|
|
|
const res = this.u32[0];
|
|
|
|
this.u32[0] += length;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
async terminate() {
|
|
|
|
for (let i=0; i<this.workers.length; i++) {
|
|
|
|
this.workers[i].postMessage([{cmd: "TERMINATE"}]);
|
|
|
|
}
|
|
|
|
await sleep(200);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
function buildBatchApplyKey(curve, groupName) {
|
|
|
|
const G = curve[groupName];
|
|
|
|
const Fr = curve.Fr;
|
|
|
|
const tm = curve.tm;
|
|
|
|
|
|
|
|
curve[groupName].batchApplyKey = async function(buff, first, inc, inType, outType) {
|
|
|
|
inType = inType || "affine";
|
|
|
|
outType = outType || "affine";
|
|
|
|
let fnName, fnAffine;
|
|
|
|
let sGin, sGmid, sGout;
|
|
|
|
if (groupName == "G1") {
|
|
|
|
if (inType == "jacobian") {
|
|
|
|
sGin = G.F.n8*3;
|
|
|
|
fnName = "g1m_batchApplyKey";
|
|
|
|
} else {
|
|
|
|
sGin = G.F.n8*2;
|
|
|
|
fnName = "g1m_batchApplyKeyMixed";
|
|
|
|
}
|
|
|
|
sGmid = G.F.n8*3;
|
|
|
|
if (outType == "jacobian") {
|
|
|
|
sGout = G.F.n8*3;
|
|
|
|
} else {
|
|
|
|
fnAffine = "g1m_batchToAffine";
|
|
|
|
sGout = G.F.n8*2;
|
|
|
|
}
|
|
|
|
} else if (groupName == "G2") {
|
|
|
|
if (inType == "jacobian") {
|
|
|
|
sGin = G.F.n8*3;
|
|
|
|
fnName = "g2m_batchApplyKey";
|
|
|
|
} else {
|
|
|
|
sGin = G.F.n8*2;
|
|
|
|
fnName = "g2m_batchApplyKeyMixed";
|
|
|
|
}
|
|
|
|
sGmid = G.F.n8*3;
|
|
|
|
if (outType == "jacobian") {
|
|
|
|
sGout = G.F.n8*3;
|
|
|
|
} else {
|
|
|
|
fnAffine = "g2m_batchToAffine";
|
|
|
|
sGout = G.F.n8*2;
|
|
|
|
}
|
|
|
|
} else if (groupName == "Fr") {
|
|
|
|
fnName = "frm_batchApplyKey";
|
|
|
|
sGin = G.n8;
|
|
|
|
sGmid = G.n8;
|
|
|
|
sGout = G.n8;
|
|
|
|
} else {
|
|
|
|
throw new Error("Invalid group: " + groupName);
|
|
|
|
}
|
|
|
|
const nPoints = Math.floor(buff.byteLength / sGin);
|
|
|
|
const pointsPerChunk = Math.floor(nPoints/tm.concurrency);
|
|
|
|
const opPromises = [];
|
|
|
|
inc = Fr.e(inc);
|
|
|
|
let t = Fr.e(first);
|
|
|
|
for (let i=0; i<tm.concurrency; i++) {
|
|
|
|
let n;
|
|
|
|
if (i< tm.concurrency-1) {
|
|
|
|
n = pointsPerChunk;
|
|
|
|
} else {
|
|
|
|
n = nPoints - i*pointsPerChunk;
|
|
|
|
}
|
|
|
|
if (n==0) continue;
|
|
|
|
|
|
|
|
const task = [];
|
|
|
|
|
|
|
|
task.push({
|
|
|
|
cmd: "ALLOCSET",
|
|
|
|
var: 0,
|
|
|
|
buff: buff.slice(i*pointsPerChunk*sGin, i*pointsPerChunk*sGin + n*sGin)
|
|
|
|
});
|
|
|
|
task.push({cmd: "ALLOCSET", var: 1, buff: t});
|
|
|
|
task.push({cmd: "ALLOCSET", var: 2, buff: inc});
|
|
|
|
task.push({cmd: "ALLOC", var: 3, len: n*Math.max(sGmid, sGout)});
|
|
|
|
task.push({
|
|
|
|
cmd: "CALL",
|
|
|
|
fnName: fnName,
|
|
|
|
params: [
|
|
|
|
{var: 0},
|
|
|
|
{val: n},
|
|
|
|
{var: 1},
|
|
|
|
{var: 2},
|
|
|
|
{var:3}
|
|
|
|
]
|
|
|
|
});
|
|
|
|
if (fnAffine) {
|
|
|
|
task.push({
|
|
|
|
cmd: "CALL",
|
|
|
|
fnName: fnAffine,
|
|
|
|
params: [
|
|
|
|
{var: 3},
|
|
|
|
{val: n},
|
|
|
|
{var: 3},
|
|
|
|
]
|
|
|
|
});
|
|
|
|
}
|
|
|
|
task.push({cmd: "GET", out: 0, var: 3, len: n*sGout});
|
|
|
|
|
|
|
|
opPromises.push(tm.queueAction(task));
|
|
|
|
t = Fr.mul(t, Fr.exp(inc, n));
|
|
|
|
}
|
|
|
|
|
|
|
|
const result = await Promise.all(opPromises);
|
|
|
|
|
|
|
|
const outBuff = new Uint8Array(nPoints*sGout);
|
|
|
|
let p=0;
|
|
|
|
for (let i=0; i<result.length; i++) {
|
|
|
|
outBuff.set(result[i][0], p);
|
|
|
|
p += result[i][0].byteLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
return outBuff;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function buildPairing(curve) {
|
|
|
|
const tm = curve.tm;
|
|
|
|
curve.pairing = function pairing(a, b) {
|
|
|
|
|
|
|
|
tm.startSyncOp();
|
|
|
|
const pA = tm.allocBuff(curve.G1.toJacobian(a));
|
|
|
|
const pB = tm.allocBuff(curve.G2.toJacobian(b));
|
|
|
|
const pRes = tm.alloc(curve.Gt.n8);
|
|
|
|
tm.instance.exports[curve.name + "_pairing"](pA, pB, pRes);
|
|
|
|
|
|
|
|
const res = tm.getBuff(pRes, curve.Gt.n8);
|
|
|
|
|
|
|
|
tm.endSyncOp();
|
|
|
|
return res;
|
|
|
|
};
|
|
|
|
|
|
|
|
curve.pairingEq = async function pairingEq() {
|
|
|
|
let buffCt;
|
|
|
|
let nEqs;
|
|
|
|
if ((arguments.length % 2) == 1) {
|
|
|
|
buffCt = arguments[arguments.length-1];
|
|
|
|
nEqs = (arguments.length -1) /2;
|
|
|
|
} else {
|
|
|
|
buffCt = curve.Gt.one;
|
|
|
|
nEqs = arguments.length /2;
|
|
|
|
}
|
|
|
|
|
|
|
|
const opPromises = [];
|
|
|
|
for (let i=0; i<nEqs; i++) {
|
|
|
|
|
|
|
|
const task = [];
|
|
|
|
|
|
|
|
const g1Buff = curve.G1.toJacobian(arguments[i*2]);
|
|
|
|
task.push({cmd: "ALLOCSET", var: 0, buff: g1Buff});
|
|
|
|
task.push({cmd: "ALLOC", var: 1, len: curve.prePSize});
|
|
|
|
|
|
|
|
const g2Buff = curve.G2.toJacobian(arguments[i*2 +1]);
|
|
|
|
task.push({cmd: "ALLOCSET", var: 2, buff: g2Buff});
|
|
|
|
task.push({cmd: "ALLOC", var: 3, len: curve.preQSize});
|
|
|
|
|
|
|
|
task.push({cmd: "ALLOC", var: 4, len: curve.Gt.n8});
|
|
|
|
|
|
|
|
task.push({cmd: "CALL", fnName: curve.name + "_prepareG1", params: [
|
|
|
|
{var: 0},
|
|
|
|
{var: 1}
|
|
|
|
]});
|
|
|
|
|
|
|
|
task.push({cmd: "CALL", fnName: curve.name + "_prepareG2", params: [
|
|
|
|
{var: 2},
|
|
|
|
{var: 3}
|
|
|
|
]});
|
|
|
|
|
|
|
|
task.push({cmd: "CALL", fnName: curve.name + "_millerLoop", params: [
|
|
|
|
{var: 1},
|
|
|
|
{var: 3},
|
|
|
|
{var: 4}
|
|
|
|
]});
|
|
|
|
|
|
|
|
task.push({cmd: "GET", out: 0, var: 4, len: curve.Gt.n8});
|
|
|
|
|
|
|
|
opPromises.push(
|
|
|
|
tm.queueAction(task)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const result = await Promise.all(opPromises);
|
|
|
|
|
|
|
|
tm.startSyncOp();
|
|
|
|
const pRes = tm.alloc(curve.Gt.n8);
|
|
|
|
tm.instance.exports.ftm_one(pRes);
|
|
|
|
|
|
|
|
for (let i=0; i<result.length; i++) {
|
|
|
|
const pMR = tm.allocBuff(result[i][0]);
|
|
|
|
tm.instance.exports.ftm_mul(pRes, pMR, pRes);
|
|
|
|
}
|
|
|
|
tm.instance.exports[curve.name + "_finalExponentiation"](pRes, pRes);
|
|
|
|
|
|
|
|
const pCt = tm.allocBuff(buffCt);
|
|
|
|
|
|
|
|
const r = !!tm.instance.exports.ftm_eq(pRes, pCt);
|
|
|
|
|
|
|
|
tm.endSyncOp();
|
|
|
|
|
|
|
|
return r;
|
|
|
|
};
|
|
|
|
|
|
|
|
curve.prepareG1 = function(p) {
|
|
|
|
this.tm.startSyncOp();
|
|
|
|
const pP = this.tm.allocBuff(p);
|
|
|
|
const pPrepP = this.tm.alloc(this.prePSize);
|
|
|
|
this.tm.instance.exports[this.name + "_prepareG1"](pP, pPrepP);
|
|
|
|
const res = this.tm.getBuff(pPrepP, this.prePSize);
|
|
|
|
this.tm.endSyncOp();
|
|
|
|
return res;
|
|
|
|
};
|
|
|
|
|
|
|
|
curve.prepareG2 = function(q) {
|
|
|
|
this.tm.startSyncOp();
|
|
|
|
const pQ = this.tm.allocBuff(q);
|
|
|
|
const pPrepQ = this.tm.alloc(this.preQSize);
|
|
|
|
this.tm.instance.exports[this.name + "_prepareG2"](pQ, pPrepQ);
|
|
|
|
const res = this.tm.getBuff(pPrepQ, this.preQSize);
|
|
|
|
this.tm.endSyncOp();
|
|
|
|
return res;
|
|
|
|
};
|
|
|
|
|
|
|
|
curve.millerLoop = function(preP, preQ) {
|
|
|
|
this.tm.startSyncOp();
|
|
|
|
const pPreP = this.tm.allocBuff(preP);
|
|
|
|
const pPreQ = this.tm.allocBuff(preQ);
|
|
|
|
const pRes = this.tm.alloc(this.Gt.n8);
|
|
|
|
this.tm.instance.exports[this.name + "_millerLoop"](pPreP, pPreQ, pRes);
|
|
|
|
const res = this.tm.getBuff(pRes, this.Gt.n8);
|
|
|
|
this.tm.endSyncOp();
|
|
|
|
return res;
|
|
|
|
};
|
|
|
|
|
|
|
|
curve.finalExponentiation = function(a) {
|
|
|
|
this.tm.startSyncOp();
|
|
|
|
const pA = this.tm.allocBuff(a);
|
|
|
|
const pRes = this.tm.alloc(this.Gt.n8);
|
|
|
|
this.tm.instance.exports[this.name + "_finalExponentiation"](pA, pRes);
|
|
|
|
const res = this.tm.getBuff(pRes, this.Gt.n8);
|
|
|
|
this.tm.endSyncOp();
|
|
|
|
return res;
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const pTSizes = [
|
|
|
|
1 , 1, 1, 1, 2, 3, 4, 5,
|
|
|
|
6 , 7, 7, 8, 9, 10, 11, 12,
|
|
|
|
13, 13, 14, 15, 16, 16, 17, 17,
|
|
|
|
17, 17, 17, 17, 17, 17, 17, 17
|
|
|
|
];
|
|
|
|
|
|
|
|
function buildMultiexp(curve, groupName) {
|
|
|
|
const G = curve[groupName];
|
|
|
|
async function _multiExp(buffBases, buffScalars, inType) {
|
|
|
|
inType = inType || "affine";
|
|
|
|
|
|
|
|
let sGIn;
|
|
|
|
let fnName;
|
|
|
|
if (groupName == "G1") {
|
|
|
|
if (inType == "affine") {
|
|
|
|
fnName = "g1m_multiexpAffine_chunk";
|
|
|
|
sGIn = G.F.n8*2;
|
|
|
|
} else {
|
|
|
|
fnName = "g1m_multiexp_chunk";
|
|
|
|
sGIn = G.F.n8*3;
|
|
|
|
}
|
|
|
|
} else if (groupName == "G2") {
|
|
|
|
if (inType == "affine") {
|
|
|
|
fnName = "g2m_multiexpAffine_chunk";
|
|
|
|
sGIn = G.F.n8*2;
|
|
|
|
} else {
|
|
|
|
fnName = "g2m_multiexp_chunk";
|
|
|
|
sGIn = G.F.n8*3;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
throw new Error("Invalid group");
|
|
|
|
}
|
|
|
|
const nPoints = Math.floor(buffBases.byteLength / sGIn);
|
|
|
|
const sScalar = Math.floor(buffScalars.byteLength / nPoints);
|
|
|
|
if( sScalar * nPoints != buffScalars.byteLength) {
|
|
|
|
throw new Error("Scalar size does not match");
|
|
|
|
}
|
|
|
|
|
|
|
|
const bitChunkSize = pTSizes[log2$1(nPoints)];
|
|
|
|
const nChunks = Math.floor((sScalar*8 - 1) / bitChunkSize) +1;
|
|
|
|
|
|
|
|
const opPromises = [];
|
|
|
|
for (let i=0; i<nChunks; i++) {
|
|
|
|
const task = [
|
|
|
|
{cmd: "ALLOCSET", var: 0, buff: buffBases},
|
|
|
|
{cmd: "ALLOCSET", var: 1, buff: buffScalars},
|
|
|
|
{cmd: "ALLOC", var: 2, len: G.F.n8*3},
|
|
|
|
{cmd: "CALL", fnName: fnName, params: [
|
|
|
|
{var: 0},
|
|
|
|
{var: 1},
|
|
|
|
{val: sScalar},
|
|
|
|
{val: nPoints},
|
|
|
|
{val: i*bitChunkSize},
|
|
|
|
{val: Math.min(sScalar*8 - i*bitChunkSize, bitChunkSize)},
|
|
|
|
{var: 2}
|
|
|
|
]},
|
|
|
|
{cmd: "GET", out: 0, var: 2, len: G.F.n8*3}
|
|
|
|
];
|
|
|
|
opPromises.push(
|
|
|
|
G.tm.queueAction(task)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
const result = await Promise.all(opPromises);
|
|
|
|
|
|
|
|
let res = G.zero;
|
|
|
|
for (let i=result.length-1; i>=0; i--) {
|
|
|
|
if (!G.isZero(res)) {
|
|
|
|
for (let j=0; j<bitChunkSize; j++) res = G.double(res);
|
|
|
|
}
|
|
|
|
res = G.add(res, result[i][0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
G.multiExp = async function multiExpAffine(buffBases, buffScalars) {
|
|
|
|
return await _multiExp(buffBases, buffScalars, "jacobian");
|
|
|
|
};
|
|
|
|
G.multiExpAffine = async function multiExpAffine(buffBases, buffScalars) {
|
|
|
|
return await _multiExp(buffBases, buffScalars, "affine");
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function buildFFT(curve, groupName) {
|
|
|
|
const G = curve[groupName];
|
|
|
|
const Fr = curve.Fr;
|
|
|
|
const tm = G.tm;
|
|
|
|
async function _fft(buff, inverse, inType, outType, logger) {
|
|
|
|
|
|
|
|
inType = inType || "affine";
|
|
|
|
outType = outType || "affine";
|
|
|
|
const MAX_BITS_THREAD = 12;
|
|
|
|
|
|
|
|
let sIn, sMid, sOut, fnIn2Mid, fnMid2Out, fnName, fnFFTMix, fnFFTJoin, fnFFTFinal;
|
|
|
|
if (groupName == "G1") {
|
|
|
|
if (inType == "affine") {
|
|
|
|
sIn = G.F.n8*2;
|
|
|
|
fnIn2Mid = "g1m_batchToJacobian";
|
|
|
|
} else {
|
|
|
|
sIn = G.F.n8*3;
|
|
|
|
}
|
|
|
|
sMid = G.F.n8*3;
|
|
|
|
if (inverse) {
|
|
|
|
fnName = "g1m_ifft";
|
|
|
|
fnFFTFinal = "g1m_fftFinal";
|
|
|
|
} else {
|
|
|
|
fnName = "g1m_fft";
|
|
|
|
}
|
|
|
|
fnFFTJoin = "g1m_fftJoin";
|
|
|
|
fnFFTMix = "g1m_fftMix";
|
|
|
|
|
|
|
|
if (outType == "affine") {
|
|
|
|
sOut = G.F.n8*2;
|
|
|
|
fnMid2Out = "g1m_batchToAffine";
|
|
|
|
} else {
|
|
|
|
sOut = G.F.n8*3;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (groupName == "G2") {
|
|
|
|
if (inType == "affine") {
|
|
|
|
sIn = G.F.n8*2;
|
|
|
|
fnIn2Mid = "g2m_batchToJacobian";
|
|
|
|
} else {
|
|
|
|
sIn = G.F.n8*3;
|
|
|
|
}
|
|
|
|
sMid = G.F.n8*3;
|
|
|
|
if (inverse) {
|
|
|
|
fnName = "g2m_ifft";
|
|
|
|
fnFFTFinal = "g2m_fftFinal";
|
|
|
|
} else {
|
|
|
|
fnName = "g2m_fft";
|
|
|
|
}
|
|
|
|
fnFFTJoin = "g2m_fftJoin";
|
|
|
|
fnFFTMix = "g2m_fftMix";
|
|
|
|
if (outType == "affine") {
|
|
|
|
sOut = G.F.n8*2;
|
|
|
|
fnMid2Out = "g2m_batchToAffine";
|
|
|
|
} else {
|
|
|
|
sOut = G.F.n8*3;
|
|
|
|
}
|
|
|
|
} else if (groupName == "Fr") {
|
|
|
|
sIn = G.n8;
|
|
|
|
sMid = G.n8;
|
|
|
|
sOut = G.n8;
|
|
|
|
if (inverse) {
|
|
|
|
fnName = "frm_ifft";
|
|
|
|
fnFFTFinal = "frm_fftFinal";
|
|
|
|
} else {
|
|
|
|
fnName = "frm_fft";
|
|
|
|
}
|
|
|
|
fnFFTMix = "frm_fftMix";
|
|
|
|
fnFFTJoin = "frm_fftJoin";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let returnArray = false;
|
|
|
|
if (Array.isArray(buff)) {
|
|
|
|
buff = curve.array2buffer(buff, sIn);
|
|
|
|
returnArray = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
const nPoints = buff.byteLength / sIn;
|
|
|
|
const bits = log2$1(nPoints);
|
|
|
|
|
|
|
|
if ((1 << bits) != nPoints) {
|
|
|
|
throw new Error("fft must be multiple of 2" );
|
|
|
|
}
|
|
|
|
|
|
|
|
let inv;
|
|
|
|
if (inverse) {
|
|
|
|
inv = Fr.inv(Fr.e(nPoints));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let buffOut;
|
|
|
|
if (nPoints <= (1 << MAX_BITS_THREAD)) {
|
|
|
|
const task = [];
|
|
|
|
task.push({cmd: "ALLOC", var: 0, len: sMid*nPoints});
|
|
|
|
task.push({cmd: "SET", var: 0, buff: buff});
|
|
|
|
if (fnIn2Mid) {
|
|
|
|
task.push({cmd: "CALL", fnName:fnIn2Mid, params: [{var:0}, {val: nPoints}, {var: 0}]});
|
|
|
|
}
|
|
|
|
task.push({cmd: "CALL", fnName:fnName, params: [{var:0}, {val: nPoints}]});
|
|
|
|
if (fnMid2Out) {
|
|
|
|
task.push({cmd: "CALL", fnName:fnMid2Out, params: [{var:0}, {val: nPoints}, {var: 0}]});
|
|
|
|
}
|
|
|
|
task.push({cmd: "GET", out: 0, var: 0, len: sOut*nPoints});
|
|
|
|
|
|
|
|
const res = await tm.queueAction(task);
|
|
|
|
buffOut = res[0];
|
|
|
|
} else {
|
|
|
|
|
|
|
|
buffReverseBits(buff, sIn);
|
|
|
|
|
|
|
|
let chunks;
|
|
|
|
const pointsInChunk = 1 << MAX_BITS_THREAD;
|
|
|
|
const chunkSize = pointsInChunk * sIn;
|
|
|
|
const nChunks = nPoints / pointsInChunk;
|
|
|
|
|
|
|
|
const promises = [];
|
|
|
|
for (let i = 0; i< nChunks; i++) {
|
|
|
|
const task = [];
|
|
|
|
task.push({cmd: "ALLOC", var: 0, len: sMid*pointsInChunk});
|
|
|
|
const buffChunk = buff.slice( (pointsInChunk * i)*sIn, (pointsInChunk * (i+1))*sIn);
|
|
|
|
task.push({cmd: "SET", var: 0, buff: buffChunk});
|
|
|
|
if (fnIn2Mid) {
|
|
|
|
task.push({cmd: "CALL", fnName:fnIn2Mid, params: [{var:0}, {val: pointsInChunk}, {var: 0}]});
|
|
|
|
}
|
|
|
|
for (let j=1; j<=MAX_BITS_THREAD;j++) {
|
|
|
|
task.push({cmd: "CALL", fnName:fnFFTMix, params: [{var:0}, {val: pointsInChunk}, {val: j}]});
|
|
|
|
}
|
|
|
|
task.push({cmd: "GET", out:0, var: 0, len: sMid*pointsInChunk});
|
|
|
|
promises.push(tm.queueAction(task).then( (r) => {
|
|
|
|
if (logger) logger.debug(`fft: ${i}/${nChunks}`);
|
|
|
|
return r;
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
chunks = await Promise.all(promises);
|
|
|
|
for (let i = 0; i< nChunks; i++) chunks[i] = chunks[i][0];
|
|
|
|
|
|
|
|
for (let i = MAX_BITS_THREAD+1; i<=bits; i++) {
|
|
|
|
if (logger) logger.debug(`fft join ${i}/${bits}`);
|
|
|
|
const nGroups = 1 << (bits - i);
|
|
|
|
const nChunksPerGroup = nChunks / nGroups;
|
|
|
|
const opPromises = [];
|
|
|
|
for (let j=0; j<nGroups; j++) {
|
|
|
|
for (let k=0; k <nChunksPerGroup/2; k++) {
|
|
|
|
const first = Fr.exp( Fr.w[i], k*pointsInChunk);
|
|
|
|
const inc = Fr.w[i];
|
|
|
|
const o1 = j*nChunksPerGroup + k;
|
|
|
|
const o2 = j*nChunksPerGroup + k + nChunksPerGroup/2;
|
|
|
|
|
|
|
|
const task = [];
|
|
|
|
task.push({cmd: "ALLOCSET", var: 0, buff: chunks[o1]});
|
|
|
|
task.push({cmd: "ALLOCSET", var: 1, buff: chunks[o2]});
|
|
|
|
task.push({cmd: "ALLOCSET", var: 2, buff: first});
|
|
|
|
task.push({cmd: "ALLOCSET", var: 3, buff: inc});
|
|
|
|
task.push({cmd: "CALL", fnName: fnFFTJoin, params:[
|
|
|
|
{var: 0},
|
|
|
|
{var: 1},
|
|
|
|
{val: pointsInChunk},
|
|
|
|
{var: 2},
|
|
|
|
{var: 3}
|
|
|
|
]});
|
|
|
|
if (i==bits) {
|
|
|
|
if (fnFFTFinal) {
|
|
|
|
task.push({cmd: "ALLOCSET", var: 4, buff: inv});
|
|
|
|
task.push({cmd: "CALL", fnName: fnFFTFinal, params:[
|
|
|
|
{var: 0},
|
|
|
|
{val: pointsInChunk},
|
|
|
|
{var: 4},
|
|
|
|
]});
|
|
|
|
task.push({cmd: "CALL", fnName: fnFFTFinal, params:[
|
|
|
|
{var: 1},
|
|
|
|
{val: pointsInChunk},
|
|
|
|
{var: 4},
|
|
|
|
]});
|
|
|
|
}
|
|
|
|
if (fnMid2Out) {
|
|
|
|
task.push({cmd: "CALL", fnName:fnMid2Out, params: [{var:0}, {val: pointsInChunk}, {var: 0}]});
|
|
|
|
task.push({cmd: "CALL", fnName:fnMid2Out, params: [{var:1}, {val: pointsInChunk}, {var: 1}]});
|
|
|
|
}
|
|
|
|
task.push({cmd: "GET", out: 0, var: 0, len: pointsInChunk*sOut});
|
|
|
|
task.push({cmd: "GET", out: 1, var: 1, len: pointsInChunk*sOut});
|
|
|
|
} else {
|
|
|
|
task.push({cmd: "GET", out: 0, var: 0, len: pointsInChunk*sMid});
|
|
|
|
task.push({cmd: "GET", out: 1, var: 1, len: pointsInChunk*sMid});
|
|
|
|
}
|
|
|
|
opPromises.push(tm.queueAction(task));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const res = await Promise.all(opPromises);
|
|
|
|
for (let j=0; j<nGroups; j++) {
|
|
|
|
for (let k=0; k <nChunksPerGroup/2; k++) {
|
|
|
|
const o1 = j*nChunksPerGroup + k;
|
|
|
|
const o2 = j*nChunksPerGroup + k + nChunksPerGroup/2;
|
|
|
|
const resChunk = res.shift();
|
|
|
|
chunks[o1] = resChunk[0];
|
|
|
|
chunks[o2] = resChunk[1];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
buffOut = new Uint8Array(nPoints * sOut);
|
|
|
|
if (inverse) {
|
|
|
|
buffOut.set(chunks[0].slice((pointsInChunk-1)*sOut));
|
|
|
|
let p= sOut;
|
|
|
|
for (let i=nChunks-1; i>0; i--) {
|
|
|
|
buffOut.set(chunks[i], p);
|
|
|
|
p += chunkSize;
|
|
|
|
delete chunks[i]; // Liberate mem
|
|
|
|
}
|
|
|
|
buffOut.set(chunks[0].slice(0, (pointsInChunk-1)*sOut), p);
|
|
|
|
delete chunks[nChunks-1];
|
|
|
|
} else {
|
|
|
|
for (let i=0; i<nChunks; i++) {
|
|
|
|
buffOut.set(chunks[i], pointsInChunk*sOut*i);
|
|
|
|
delete chunks[i];
|
|
|
|
}
|
|
|
|
return buffOut;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (returnArray) {
|
|
|
|
return curve.buffer2array(buffOut, sOut);
|
|
|
|
} else {
|
|
|
|
return buffOut;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
G.fft = async function(buff, inType, outType, logger) {
|
|
|
|
return await _fft(buff, false, inType, outType, logger);
|
|
|
|
};
|
|
|
|
|
|
|
|
G.ifft = async function(buff, inType, outType, logger) {
|
|
|
|
return await _fft(buff, true, inType, outType, logger);
|
|
|
|
};
|
|
|
|
|
|
|
|
G.fftMix = async function fftMix(buff) {
|
|
|
|
const sG = G.F.n8*3;
|
|
|
|
let fnName, fnFFTJoin;
|
|
|
|
if (groupName == "G1") {
|
|
|
|
fnName = "g1m_fftMix";
|
|
|
|
fnFFTJoin = "g1m_fftJoin";
|
|
|
|
} else if (groupName == "G2") {
|
|
|
|
fnName = "g2m_fftMix";
|
|
|
|
fnFFTJoin = "g2m_fftJoin";
|
|
|
|
} else if (groupName == "Fr") {
|
|
|
|
fnName = "frm_fftMix";
|
|
|
|
fnFFTJoin = "frm_fftJoin";
|
|
|
|
} else {
|
|
|
|
throw new Error("Invalid group");
|
|
|
|
}
|
|
|
|
|
|
|
|
const nPoints = Math.floor(buff.byteLength / sG);
|
|
|
|
const power = log2$1(nPoints);
|
|
|
|
|
|
|
|
let nChunks = 1 << log2$1(tm.concurrency);
|
|
|
|
|
|
|
|
if (nPoints <= nChunks*2) nChunks = 1;
|
|
|
|
|
|
|
|
const pointsPerChunk = nPoints / nChunks;
|
|
|
|
|
|
|
|
const powerChunk = log2$1(pointsPerChunk);
|
|
|
|
|
|
|
|
const opPromises = [];
|
|
|
|
for (let i=0; i<nChunks; i++) {
|
|
|
|
const task = [];
|
|
|
|
const b = buff.slice((i* pointsPerChunk)*sG, ((i+1)* pointsPerChunk)*sG);
|
|
|
|
task.push({cmd: "ALLOCSET", var: 0, buff: b});
|
|
|
|
for (let j=1; j<=powerChunk; j++) {
|
|
|
|
task.push({cmd: "CALL", fnName: fnName, params: [
|
|
|
|
{var: 0},
|
|
|
|
{val: pointsPerChunk},
|
|
|
|
{val: j}
|
|
|
|
]});
|
|
|
|
}
|
|
|
|
task.push({cmd: "GET", out: 0, var: 0, len: pointsPerChunk*sG});
|
|
|
|
opPromises.push(
|
|
|
|
tm.queueAction(task)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
const result = await Promise.all(opPromises);
|
|
|
|
|
|
|
|
const chunks = [];
|
|
|
|
for (let i=0; i<result.length; i++) chunks[i] = result[i][0];
|
|
|
|
|
|
|
|
|
|
|
|
for (let i = powerChunk+1; i<=power; i++) {
|
|
|
|
const nGroups = 1 << (power - i);
|
|
|
|
const nChunksPerGroup = nChunks / nGroups;
|
|
|
|
const opPromises = [];
|
|
|
|
for (let j=0; j<nGroups; j++) {
|
|
|
|
for (let k=0; k <nChunksPerGroup/2; k++) {
|
|
|
|
const first = Fr.exp( Fr.w[i], k*pointsPerChunk);
|
|
|
|
const inc = Fr.w[i];
|
|
|
|
const o1 = j*nChunksPerGroup + k;
|
|
|
|
const o2 = j*nChunksPerGroup + k + nChunksPerGroup/2;
|
|
|
|
|
|
|
|
const task = [];
|
|
|
|
task.push({cmd: "ALLOCSET", var: 0, buff: chunks[o1]});
|
|
|
|
task.push({cmd: "ALLOCSET", var: 1, buff: chunks[o2]});
|
|
|
|
task.push({cmd: "ALLOCSET", var: 2, buff: first});
|
|
|
|
task.push({cmd: "ALLOCSET", var: 3, buff: inc});
|
|
|
|
task.push({cmd: "CALL", fnName: fnFFTJoin, params:[
|
|
|
|
{var: 0},
|
|
|
|
{var: 1},
|
|
|
|
{val: pointsPerChunk},
|
|
|
|
{var: 2},
|
|
|
|
{var: 3}
|
|
|
|
]});
|
|
|
|
task.push({cmd: "GET", out: 0, var: 0, len: pointsPerChunk*sG});
|
|
|
|
task.push({cmd: "GET", out: 1, var: 1, len: pointsPerChunk*sG});
|
|
|
|
opPromises.push(tm.queueAction(task));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const res = await Promise.all(opPromises);
|
|
|
|
for (let j=0; j<nGroups; j++) {
|
|
|
|
for (let k=0; k <nChunksPerGroup/2; k++) {
|
|
|
|
const o1 = j*nChunksPerGroup + k;
|
|
|
|
const o2 = j*nChunksPerGroup + k + nChunksPerGroup/2;
|
|
|
|
const resChunk = res.shift();
|
|
|
|
chunks[o1] = resChunk[0];
|
|
|
|
chunks[o2] = resChunk[1];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const fullBuffOut = new Uint8Array(nPoints*sG);
|
|
|
|
let p =0;
|
|
|
|
for (let i=0; i<nChunks; i++) {
|
|
|
|
fullBuffOut.set(chunks[i], p);
|
|
|
|
p+=chunks[i].byteLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
return fullBuffOut;
|
|
|
|
};
|
|
|
|
|
|
|
|
G.fftJoin = async function fftJoin(buff1, buff2, first, inc) {
|
|
|
|
const sG = G.F.n8*3;
|
|
|
|
let fnName;
|
|
|
|
if (groupName == "G1") {
|
|
|
|
fnName = "g1m_fftJoin";
|
|
|
|
} else if (groupName == "G2") {
|
|
|
|
fnName = "g2m_fftJoin";
|
|
|
|
} else {
|
|
|
|
throw new Error("Invalid group");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (buff1.byteLength != buff2.byteLength) {
|
|
|
|
throw new Error("Invalid buffer size");
|
|
|
|
}
|
|
|
|
const nPoints = Math.floor(buff1.byteLength / sG);
|
|
|
|
if (nPoints != 1 << log2$1(nPoints)) {
|
|
|
|
throw new Error("Invalid number of points");
|
|
|
|
}
|
|
|
|
|
|
|
|
let nChunks = 1 << log2$1(tm.concurrency);
|
|
|
|
if (nPoints <= nChunks*2) nChunks = 1;
|
|
|
|
|
|
|
|
const pointsPerChunk = nPoints / nChunks;
|
|
|
|
|
|
|
|
|
|
|
|
const opPromises = [];
|
|
|
|
for (let i=0; i<nChunks; i++) {
|
|
|
|
const task = [];
|
|
|
|
|
|
|
|
const firstChunk = Fr.mul(first, Fr.exp(inc, i*pointsPerChunk));
|
|
|
|
const b1 = buff1.slice((i* pointsPerChunk)*sG, ((i+1)* pointsPerChunk)*sG);
|
|
|
|
const b2 = buff2.slice((i* pointsPerChunk)*sG, ((i+1)* pointsPerChunk)*sG);
|
|
|
|
task.push({cmd: "ALLOCSET", var: 0, buff: b1});
|
|
|
|
task.push({cmd: "ALLOCSET", var: 1, buff: b2});
|
|
|
|
task.push({cmd: "ALLOCSET", var: 2, buff: firstChunk});
|
|
|
|
task.push({cmd: "ALLOCSET", var: 3, buff: inc});
|
|
|
|
task.push({cmd: "CALL", fnName: fnName, params: [
|
|
|
|
{var: 0},
|
|
|
|
{var: 1},
|
|
|
|
{val: pointsPerChunk},
|
|
|
|
{var: 2},
|
|
|
|
{var: 3}
|
|
|
|
]});
|
|
|
|
task.push({cmd: "GET", out: 0, var: 0, len: pointsPerChunk*sG});
|
|
|
|
task.push({cmd: "GET", out: 1, var: 1, len: pointsPerChunk*sG});
|
|
|
|
opPromises.push(
|
|
|
|
tm.queueAction(task)
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const result = await Promise.all(opPromises);
|
|
|
|
|
|
|
|
const fullBuffOut1 = new Uint8Array(nPoints*sG);
|
|
|
|
const fullBuffOut2 = new Uint8Array(nPoints*sG);
|
|
|
|
let p =0;
|
|
|
|
for (let i=0; i<result.length; i++) {
|
|
|
|
fullBuffOut1.set(result[i][0], p);
|
|
|
|
fullBuffOut2.set(result[i][1], p);
|
|
|
|
p+=result[i][0].byteLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
return [fullBuffOut1, fullBuffOut2];
|
|
|
|
};
|
|
|
|
|
|
|
|
G.fftFinal = async function fftFinal(buff, factor) {
|
|
|
|
const sG = G.F.n8*3;
|
|
|
|
const sGout = G.F.n8*2;
|
|
|
|
let fnName, fnToAffine;
|
|
|
|
if (groupName == "G1") {
|
|
|
|
fnName = "g1m_fftFinal";
|
|
|
|
fnToAffine = "g1m_batchToAffine";
|
|
|
|
} else if (groupName == "G2") {
|
|
|
|
fnName = "g2m_fftFinal";
|
|
|
|
fnToAffine = "g2m_batchToAffine";
|
|
|
|
} else {
|
|
|
|
throw new Error("Invalid group");
|
|
|
|
}
|
|
|
|
|
|
|
|
const nPoints = Math.floor(buff.byteLength / sG);
|
|
|
|
if (nPoints != 1 << log2$1(nPoints)) {
|
|
|
|
throw new Error("Invalid number of points");
|
|
|
|
}
|
|
|
|
|
|
|
|
const pointsPerChunk = Math.floor(nPoints / tm.concurrency);
|
|
|
|
|
|
|
|
const opPromises = [];
|
|
|
|
for (let i=0; i<tm.concurrency; i++) {
|
|
|
|
let n;
|
|
|
|
if (i< tm.concurrency-1) {
|
|
|
|
n = pointsPerChunk;
|
|
|
|
} else {
|
|
|
|
n = nPoints - i*pointsPerChunk;
|
|
|
|
}
|
|
|
|
if (n==0) continue;
|
|
|
|
const task = [];
|
|
|
|
const b = buff.slice((i* pointsPerChunk)*sG, (i*pointsPerChunk+n)*sG);
|
|
|
|
task.push({cmd: "ALLOCSET", var: 0, buff: b});
|
|
|
|
task.push({cmd: "ALLOCSET", var: 1, buff: factor});
|
|
|
|
task.push({cmd: "CALL", fnName: fnName, params: [
|
|
|
|
{var: 0},
|
|
|
|
{val: n},
|
|
|
|
{var: 1},
|
|
|
|
]});
|
|
|
|
task.push({cmd: "CALL", fnName: fnToAffine, params: [
|
|
|
|
{var: 0},
|
|
|
|
{val: n},
|
|
|
|
{var: 0},
|
|
|
|
]});
|
|
|
|
task.push({cmd: "GET", out: 0, var: 0, len: n*sGout});
|
|
|
|
opPromises.push(
|
|
|
|
tm.queueAction(task)
|
|
|
|
);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const result = await Promise.all(opPromises);
|
|
|
|
|
|
|
|
const fullBuffOut = new Uint8Array(nPoints*sGout);
|
|
|
|
let p =0;
|
|
|
|
for (let i=result.length-1; i>=0; i--) {
|
|
|
|
fullBuffOut.set(result[i][0], p);
|
|
|
|
p+=result[i][0].byteLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
return fullBuffOut;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
async function buildEngine(params) {
|
|
|
|
|
|
|
|
const tm = await buildThreadManager(params.wasm, params.singleThread);
|
|
|
|
|
|
|
|
|
|
|
|
const curve = {};
|
|
|
|
|
|
|
|
curve.q = e$2(params.wasm.q);
|
|
|
|
curve.r = e$2(params.wasm.r);
|
|
|
|
curve.name = params.name;
|
|
|
|
curve.tm = tm;
|
|
|
|
curve.prePSize = params.wasm.prePSize;
|
|
|
|
curve.preQSize = params.wasm.preQSize;
|
|
|
|
curve.Fr = new WasmField1(tm, "frm", params.n8r, params.r);
|
|
|
|
curve.F1 = new WasmField1(tm, "f1m", params.n8q, params.q);
|
|
|
|
curve.F2 = new WasmField2(tm, "f2m", curve.F1);
|
|
|
|
curve.G1 = new WasmCurve(tm, "g1m", curve.F1, params.wasm.pG1gen, params.wasm.pG1b, params.cofactorG1);
|
|
|
|
curve.G2 = new WasmCurve(tm, "g2m", curve.F2, params.wasm.pG2gen, params.wasm.pG2b, params.cofactorG2);
|
|
|
|
curve.F6 = new WasmField3(tm, "f6m", curve.F2);
|
|
|
|
curve.F12 = new WasmField2(tm, "ftm", curve.F6);
|
|
|
|
|
|
|
|
curve.Gt = curve.F12;
|
|
|
|
|
|
|
|
buildBatchApplyKey(curve, "G1");
|
|
|
|
buildBatchApplyKey(curve, "G2");
|
|
|
|
buildBatchApplyKey(curve, "Fr");
|
|
|
|
|
|
|
|
buildMultiexp(curve, "G1");
|
|
|
|
buildMultiexp(curve, "G2");
|
|
|
|
|
|
|
|
buildFFT(curve, "G1");
|
|
|
|
buildFFT(curve, "G2");
|
|
|
|
buildFFT(curve, "Fr");
|
|
|
|
|
|
|
|
buildPairing(curve);
|
|
|
|
|
|
|
|
curve.array2buffer = function(arr, sG) {
|
|
|
|
const buff = new Uint8Array(sG*arr.length);
|
|
|
|
|
|
|
|
for (let i=0; i<arr.length; i++) {
|
|
|
|
buff.set(arr[i], i*sG);
|
|
|
|
}
|
|
|
|
|
|
|
|
return buff;
|
|
|
|
};
|
|
|
|
|
|
|
|
curve.buffer2array = function(buff , sG) {
|
|
|
|
const n= buff.length / sG;
|
|
|
|
const arr = new Array(n);
|
|
|
|
for (let i=0; i<n; i++) {
|
|
|
|
arr[i] = buff.slice(i*sG, i*sG+sG);
|
|
|
|
}
|
|
|
|
return arr;
|
|
|
|
};
|
|
|
|
|
|
|
|
return curve;
|
|
|
|
}
|
|
|
|
|
|
|
|
let curve;
|
|
|
|
|
|
|
|
async function buildBn128() {
|
|
|
|
|
|
|
|
if (curve) return curve;
|
|
|
|
const params = {
|
|
|
|
name: "bn128",
|
|
|
|
wasm: wasmcurves.bn128_wasm,
|
|
|
|
q: e$2("21888242871839275222246405745257275088696311157297823662689037894645226208583"),
|
|
|
|
r: e$2("21888242871839275222246405745257275088548364400416034343698204186575808495617"),
|
|
|
|
n8q: 32,
|
|
|
|
n8r: 32,
|
|
|
|
cofactorG2: e$2("30644e72e131a029b85045b68181585e06ceecda572a2489345f2299c0f9fa8d", 16),
|
|
|
|
singleThread: false
|
|
|
|
};
|
|
|
|
|
|
|
|
curve = await buildEngine(params);
|
|
|
|
curve.terminate = async function() {
|
|
|
|
curve = null;
|
|
|
|
await this.tm.terminate();
|
|
|
|
};
|
|
|
|
|
|
|
|
return curve;
|
|
|
|
}
|
|
|
|
|
|
|
|
let curve$1;
|
|
|
|
|
|
|
|
async function buildBls12381() {
|
|
|
|
|
|
|
|
if (curve$1) return curve$1;
|
|
|
|
const params = {
|
|
|
|
name: "bls12381",
|
|
|
|
wasm: wasmcurves.bls12381_wasm,
|
|
|
|
q: e$2("1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab", 16),
|
|
|
|
r: e$2("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", 16),
|
|
|
|
n8q: 48,
|
|
|
|
n8r: 32,
|
|
|
|
cofactorG1: e$2("0x396c8c005555e1568c00aaab0000aaab", 16),
|
|
|
|
cofactorG2: e$2("0x5d543a95414e7f1091d50792876a202cd91de4547085abaa68a205b2e5a7ddfa628f1cb4d9e82ef21537e293a6691ae1616ec6e786f0c70cf1c38e31c7238e5", 16),
|
|
|
|
singleThread: false
|
|
|
|
};
|
|
|
|
|
|
|
|
curve$1 = await buildEngine(params);
|
|
|
|
|
|
|
|
curve$1.terminate = async function() {
|
|
|
|
curve$1 = null;
|
|
|
|
await this.tm.terminate();
|
|
|
|
};
|
|
|
|
return curve$1;
|
|
|
|
}
|
|
|
|
|
|
|
|
const Scalar$1=_Scalar;
|
|
|
|
const utils$1 = _utils;
|
|
|
|
|
|
|
|
var main = /*#__PURE__*/Object.freeze({
|
|
|
|
__proto__: null,
|
|
|
|
Scalar: Scalar$1,
|
|
|
|
utils: utils$1,
|
|
|
|
PolField: PolField,
|
|
|
|
F1Field: F1Field,
|
|
|
|
F2Field: F2Field,
|
|
|
|
F3Field: F3Field,
|
|
|
|
ZqField: F1Field,
|
|
|
|
EC: EC,
|
|
|
|
buildBn128: buildBn128,
|
|
|
|
buildBls12381: buildBls12381,
|
|
|
|
ChaCha: ChaCha
|
|
|
|
});
|
|
|
|
|
|
|
|
async function open(fileName, openFlags, cacheSize) {
|
|
|
|
cacheSize = cacheSize || 4096*64;
|
|
|
|
if (["w+", "wx+", "r", "ax+", "a+"].indexOf(openFlags) <0)
|
|
|
|
throw new Error("Invalid open option");
|
|
|
|
const fd =await crypto.promises.open(fileName, openFlags);
|
|
|
|
|
|
|
|
const stats = await fd.stat();
|
|
|
|
|
|
|
|
return new FastFile(fd, stats, cacheSize, fileName);
|
|
|
|
}
|
|
|
|
|
2020-07-26 14:05:23 +02:00
|
|
|
const tmpBuff32 = new Uint8Array(4);
|
|
|
|
const tmpBuff32v = new DataView(tmpBuff32.buffer);
|
|
|
|
const tmpBuff64 = new Uint8Array(8);
|
|
|
|
const tmpBuff64v = new DataView(tmpBuff64.buffer);
|
|
|
|
|
2020-07-11 10:31:52 +02:00
|
|
|
class FastFile {
|
|
|
|
|
|
|
|
constructor(fd, stats, cacheSize, fileName) {
|
|
|
|
this.fileName = fileName;
|
|
|
|
this.fd = fd;
|
|
|
|
this.pos = 0;
|
|
|
|
this.pageBits = 8;
|
|
|
|
this.pageSize = (1 << this.pageBits);
|
|
|
|
while (this.pageSize < stats.blksize*4) {
|
|
|
|
this.pageBits ++;
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
_loadPage(p) {
|
|
|
|
const self = this;
|
|
|
|
return new Promise((resolve, reject)=> {
|
|
|
|
self.pendingLoads.push({
|
|
|
|
page: p,
|
|
|
|
resolve: resolve,
|
|
|
|
reject: reject
|
|
|
|
});
|
|
|
|
setImmediate(self._triggerLoad.bind(self));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_triggerLoad() {
|
|
|
|
const self = this;
|
|
|
|
processPendingLoads();
|
|
|
|
if (self.pendingLoads.length == 0) return;
|
|
|
|
if (Object.keys(self.pages).length >= self.maxPagesLoaded) {
|
|
|
|
const dp = getDeletablePage();
|
|
|
|
if (dp<0) { // // No sizes available
|
|
|
|
// setTimeout(self._triggerLoad.bind(self), 10000);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
delete self.pages[dp];
|
|
|
|
}
|
|
|
|
const load = self.pendingLoads.shift();
|
|
|
|
if (load.page>=self.totalPages) {
|
|
|
|
self.pages[load.page] = {
|
|
|
|
dirty: false,
|
|
|
|
buff: new Uint8Array(self.pageSize),
|
|
|
|
pendingOps: 1,
|
|
|
|
size: 0
|
|
|
|
};
|
|
|
|
load.resolve();
|
|
|
|
setImmediate(self._triggerLoad.bind(self));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (self.reading) {
|
|
|
|
self.pendingLoads.unshift(load);
|
|
|
|
return; // Only one read at a time.
|
|
|
|
}
|
|
|
|
|
|
|
|
self.reading = true;
|
|
|
|
const page = {
|
|
|
|
dirty: false,
|
|
|
|
buff: new Uint8Array(self.pageSize),
|
|
|
|
pendingOps: 1,
|
|
|
|
size: 0
|
|
|
|
};
|
|
|
|
self.fd.read(page.buff, 0, self.pageSize, load.page*self.pageSize).then((res)=> {
|
|
|
|
page.size = res.bytesRead;
|
|
|
|
self.pages[load.page] = page;
|
|
|
|
self.reading = false;
|
|
|
|
load.resolve();
|
|
|
|
setImmediate(self._triggerLoad.bind(self));
|
|
|
|
}, (err) => {
|
|
|
|
load.reject(err);
|
|
|
|
});
|
|
|
|
|
|
|
|
function processPendingLoads() {
|
|
|
|
const newPendingLoads = [];
|
|
|
|
for (let i=0; i<self.pendingLoads.length; i++) {
|
|
|
|
const load = self.pendingLoads[i];
|
|
|
|
if (typeof self.pages[load.page] != "undefined") {
|
|
|
|
self.pages[load.page].pendingOps ++;
|
|
|
|
load.resolve();
|
|
|
|
} else {
|
|
|
|
newPendingLoads.push(load);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
self.pendingLoads = newPendingLoads;
|
|
|
|
}
|
|
|
|
|
|
|
|
function getDeletablePage() {
|
|
|
|
for (let p in self.pages) {
|
|
|
|
const page = self.pages[p];
|
|
|
|
if ((page.dirty == false)&&(page.pendingOps==0)) return p;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_triggerWrite() {
|
|
|
|
const self = this;
|
|
|
|
if (self.writing) return;
|
|
|
|
const p = self._getDirtyPage();
|
|
|
|
if (p<0) {
|
|
|
|
if (self.pendingClose) self.pendingClose();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
self.writing=true;
|
|
|
|
self.pages[p].dirty = false;
|
|
|
|
self.fd.write(self.pages[p].buff, 0, self.pages[p].size, p*self.pageSize).then(() => {
|
|
|
|
self.writing = false;
|
|
|
|
setImmediate(self._triggerWrite.bind(self));
|
|
|
|
setImmediate(self._triggerLoad.bind(self));
|
|
|
|
}, (err) => {
|
|
|
|
console.log("ERROR Writing: "+err);
|
|
|
|
self.error = err;
|
|
|
|
self._tryClose();
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
_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;
|
2020-07-26 14:05:23 +02:00
|
|
|
/*
|
2020-07-11 10:31:52 +02:00
|
|
|
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;
|
|
|
|
}
|
2020-07-26 14:05:23 +02:00
|
|
|
*/
|
2020-07-11 10:31:52 +02:00
|
|
|
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);
|
|
|
|
|
2020-07-26 14:05:23 +02:00
|
|
|
// for (let i=firstPage; i<=lastPage; i++) await self._loadPage(i);
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
let p = firstPage;
|
|
|
|
let o = pos % self.pageSize;
|
|
|
|
let r = buff.byteLength;
|
|
|
|
while (r>0) {
|
2020-07-26 14:05:23 +02:00
|
|
|
await self._loadPage(p);
|
2020-07-11 10:31:52 +02:00
|
|
|
const l = (o+r > self.pageSize) ? (self.pageSize -o) : r;
|
|
|
|
const srcView = new Uint8Array(buff.buffer, 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;
|
2020-07-29 09:08:09 +02:00
|
|
|
setImmediate(self._triggerWrite.bind(self));
|
2020-07-11 10:31:52 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async read(len, pos) {
|
|
|
|
if (len == 0) {
|
|
|
|
return new Uint8Array(0);
|
|
|
|
}
|
|
|
|
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);
|
|
|
|
|
|
|
|
for (let i=firstPage; i<=lastPage; i++) await self._loadPage(i);
|
|
|
|
|
|
|
|
let buff = new Uint8Array(len);
|
|
|
|
let dstView = new Uint8Array(buff);
|
|
|
|
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) {
|
|
|
|
// 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, o, l);
|
|
|
|
buff.set(srcView, dstView.byteLength-r);
|
|
|
|
self.pages[p].pendingOps --;
|
|
|
|
r = r-l;
|
|
|
|
p ++;
|
|
|
|
o = 0;
|
|
|
|
}
|
|
|
|
setImmediate(self._triggerLoad.bind(self));
|
|
|
|
return buff;
|
|
|
|
}
|
|
|
|
|
|
|
|
_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 crypto.promises.unlink(this.fileName);
|
|
|
|
}
|
|
|
|
|
|
|
|
async writeULE32(v, pos) {
|
|
|
|
const self = this;
|
|
|
|
|
2020-07-26 14:05:23 +02:00
|
|
|
tmpBuff32v.setUint32(0, v, true);
|
2020-07-11 10:31:52 +02:00
|
|
|
|
2020-07-26 14:05:23 +02:00
|
|
|
await self.write(tmpBuff32, pos);
|
2020-07-11 10:31:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
async writeUBE32(v, pos) {
|
|
|
|
const self = this;
|
|
|
|
|
2020-07-26 19:50:50 +02:00
|
|
|
tmpBuff32v.setUint32(0, v, false);
|
2020-07-11 10:31:52 +02:00
|
|
|
|
2020-07-26 14:05:23 +02:00
|
|
|
await self.write(tmpBuff32, pos);
|
2020-07-11 10:31:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async writeULE64(v, pos) {
|
|
|
|
const self = this;
|
|
|
|
|
2020-07-26 14:05:23 +02:00
|
|
|
tmpBuff64v.setUint32(0, v & 0xFFFFFFFF, true);
|
|
|
|
tmpBuff64v.setUint32(4, Math.floor(v / 0x100000000) , true);
|
2020-07-11 10:31:52 +02:00
|
|
|
|
2020-07-26 14:05:23 +02:00
|
|
|
await self.write(tmpBuff64, pos);
|
2020-07-11 10:31:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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];
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
function createNew(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(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;
|
|
|
|
}
|
|
|
|
|
2020-07-26 19:50:50 +02:00
|
|
|
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);
|
|
|
|
|
2020-07-11 10:31:52 +02:00
|
|
|
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, pos);
|
|
|
|
|
|
|
|
if (pos + buff.byteLength > this.totalSize) this.totalSize = pos + buff.byteLength;
|
|
|
|
|
|
|
|
this.pos = pos + buff.byteLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
async read(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 buff = this.o.data.slice(pos, pos+len);
|
|
|
|
this.pos = pos + len;
|
|
|
|
return buff;
|
|
|
|
}
|
|
|
|
|
|
|
|
close() {
|
|
|
|
if (this.o.data.byteLength != this.totalSize) {
|
|
|
|
this.o.data = this.o.data.slice(0, this.totalSize);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async discard() {
|
|
|
|
}
|
|
|
|
|
2020-07-26 19:50:50 +02:00
|
|
|
|
2020-07-11 10:31:52 +02:00
|
|
|
async writeULE32(v, pos) {
|
|
|
|
const self = this;
|
|
|
|
|
2020-07-26 19:50:50 +02:00
|
|
|
tmpBuff32v$1.setUint32(0, v, true);
|
2020-07-11 10:31:52 +02:00
|
|
|
|
2020-07-26 19:50:50 +02:00
|
|
|
await self.write(tmpBuff32$1, pos);
|
2020-07-11 10:31:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
async writeUBE32(v, pos) {
|
|
|
|
const self = this;
|
|
|
|
|
2020-07-26 19:50:50 +02:00
|
|
|
tmpBuff32v$1.setUint32(0, v, false);
|
2020-07-11 10:31:52 +02:00
|
|
|
|
2020-07-26 19:50:50 +02:00
|
|
|
await self.write(tmpBuff32$1, pos);
|
2020-07-11 10:31:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async writeULE64(v, pos) {
|
|
|
|
const self = this;
|
|
|
|
|
2020-07-26 19:50:50 +02:00
|
|
|
tmpBuff64v$1.setUint32(0, v & 0xFFFFFFFF, true);
|
|
|
|
tmpBuff64v$1.setUint32(4, Math.floor(v / 0x100000000) , true);
|
2020-07-11 10:31:52 +02:00
|
|
|
|
2020-07-26 19:50:50 +02:00
|
|
|
await self.write(tmpBuff64$1, pos);
|
2020-07-11 10:31:52 +02:00
|
|
|
}
|
|
|
|
|
2020-07-26 19:50:50 +02:00
|
|
|
|
2020-07-11 10:31:52 +02:00
|
|
|
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];
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-07-13 07:21:03 +02:00
|
|
|
/* global fetch */
|
|
|
|
|
|
|
|
|
2020-07-11 10:31:52 +02:00
|
|
|
async function createOverride(o, b) {
|
|
|
|
if (typeof o === "string") {
|
|
|
|
o = {
|
|
|
|
type: "file",
|
|
|
|
fileName: o,
|
|
|
|
cacheSize: b
|
|
|
|
};
|
|
|
|
}
|
|
|
|
if (o.type == "file") {
|
|
|
|
return await open(o.fileName, "w+", o.cacheSize);
|
|
|
|
} else if (o.type == "mem") {
|
|
|
|
return createNew(o);
|
|
|
|
} else {
|
|
|
|
throw new Error("Invalid FastFile type: "+o.type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-13 07:21:03 +02:00
|
|
|
async function readExisting$1(o, b) {
|
2020-07-11 10:31:52 +02:00
|
|
|
if (o instanceof Uint8Array) {
|
|
|
|
o = {
|
|
|
|
type: "mem",
|
|
|
|
data: o
|
|
|
|
};
|
|
|
|
}
|
2020-07-13 07:21:03 +02:00
|
|
|
{
|
|
|
|
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
|
|
|
|
};
|
|
|
|
}
|
2020-07-11 10:31:52 +02:00
|
|
|
}
|
|
|
|
if (o.type == "file") {
|
2020-07-13 07:21:03 +02:00
|
|
|
return await open(o.fileName, "r", o.cacheSize);
|
2020-07-11 10:31:52 +02:00
|
|
|
} else if (o.type == "mem") {
|
2020-07-13 07:21:03 +02:00
|
|
|
return await readExisting(o);
|
2020-07-11 10:31:52 +02:00
|
|
|
} else {
|
|
|
|
throw new Error("Invalid FastFile type: "+o.type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function readBinFile(fileName, type, maxVersion) {
|
|
|
|
|
|
|
|
const fd = await readExisting$1(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) {
|
|
|
|
|
|
|
|
const fd = await createOverride(fileName);
|
|
|
|
|
|
|
|
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;
|
2020-07-28 13:16:43 +02:00
|
|
|
await fd.writeULE64(sectionSize);
|
2020-07-11 10:31:52 +02:00
|
|
|
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$1.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$1.fromRprLE(buff, 0, n8);
|
|
|
|
}
|
|
|
|
|
|
|
|
async function copySection(fdFrom, sections, fdTo, sectionId) {
|
|
|
|
const chunkSize = fdFrom.pageSize;
|
|
|
|
await startReadUniqueSection(fdFrom, sections, sectionId);
|
|
|
|
await startWriteSection(fdTo, sectionId);
|
|
|
|
for (let p=0; p<sections[sectionId][0].size; p+=chunkSize) {
|
|
|
|
const l = Math.min(sections[sectionId][0].size -p, chunkSize);
|
|
|
|
const buff = await fdFrom.read(l);
|
|
|
|
await fdTo.write(buff);
|
|
|
|
}
|
|
|
|
await endWriteSection(fdTo);
|
|
|
|
await endReadSection(fdFrom);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
async function readFullSection(fd, sections, idSection) {
|
|
|
|
await startReadUniqueSection(fd, sections, idSection);
|
|
|
|
const res = await fd.read(fd.readingSection.size);
|
|
|
|
await endReadSection(fd);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2020-07-26 14:05:23 +02:00
|
|
|
for (let j=0; j<n; j++) if (buff1[j] != buff2[j]) return false;
|
2020-07-11 10:31:52 +02:00
|
|
|
}
|
|
|
|
await endReadSection(fd1);
|
|
|
|
await endReadSection(fd2);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
const bls12381r = Scalar$1.e("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", 16);
|
|
|
|
const bn128r = Scalar$1.e("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
|
|
|
|
|
|
|
const bls12381q = Scalar$1.e("1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab", 16);
|
|
|
|
const bn128q = Scalar$1.e("21888242871839275222246405745257275088696311157297823662689037894645226208583");
|
|
|
|
|
|
|
|
async function getCurveFromQ(q) {
|
|
|
|
let curve;
|
|
|
|
if (Scalar$1.eq(q, bn128q)) {
|
|
|
|
curve = await buildBn128();
|
|
|
|
} else if (Scalar$1.eq(q, bls12381q)) {
|
|
|
|
curve = await buildBls12381();
|
|
|
|
} else {
|
|
|
|
throw new Error(`Curve not supported: ${Scalar$1.toString(q)}`);
|
|
|
|
}
|
|
|
|
return curve;
|
|
|
|
}
|
|
|
|
async function getCurveFromName(name) {
|
|
|
|
let curve;
|
|
|
|
const normName = normalizeName(name);
|
|
|
|
if (["BN128", "BN254", "ALTBN128"].indexOf(normName) >= 0) {
|
|
|
|
curve = await buildBn128();
|
|
|
|
} else if (["BLS12381"].indexOf(normName) >= 0) {
|
|
|
|
curve = await buildBls12381();
|
|
|
|
} else {
|
|
|
|
throw new Error(`Curve not supported: ${name}`);
|
|
|
|
}
|
|
|
|
return curve;
|
|
|
|
|
|
|
|
function normalizeName(n) {
|
|
|
|
return n.toUpperCase().match(/[A-Za-z0-9]+/g).join("");
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
assert.notEqual = notEqual;
|
|
|
|
assert.notOk = notOk;
|
|
|
|
assert.equal = equal;
|
|
|
|
assert.ok = assert;
|
|
|
|
|
|
|
|
var nanoassert = assert;
|
|
|
|
|
|
|
|
function equal (a, b, m) {
|
|
|
|
assert(a == b, m); // eslint-disable-line eqeqeq
|
|
|
|
}
|
|
|
|
|
|
|
|
function notEqual (a, b, m) {
|
|
|
|
assert(a != b, m); // eslint-disable-line eqeqeq
|
|
|
|
}
|
|
|
|
|
|
|
|
function notOk (t, m) {
|
|
|
|
assert(!t, m);
|
|
|
|
}
|
|
|
|
|
|
|
|
function assert (t, m) {
|
|
|
|
if (!t) throw new Error(m || 'AssertionError')
|
|
|
|
}
|
|
|
|
|
|
|
|
var blake2b = loadWebAssembly;
|
|
|
|
|
|
|
|
loadWebAssembly.supported = typeof WebAssembly !== 'undefined';
|
|
|
|
|
|
|
|
function loadWebAssembly (opts) {
|
|
|
|
if (!loadWebAssembly.supported) return null
|
|
|
|
|
|
|
|
var imp = opts && opts.imports;
|
|
|
|
var wasm = toUint8Array('AGFzbQEAAAABEANgAn9/AGADf39/AGABfwADBQQAAQICBQUBAQroBwdNBQZtZW1vcnkCAAxibGFrZTJiX2luaXQAAA5ibGFrZTJiX3VwZGF0ZQABDWJsYWtlMmJfZmluYWwAAhBibGFrZTJiX2NvbXByZXNzAAMKvz8EwAIAIABCADcDACAAQgA3AwggAEIANwMQIABCADcDGCAAQgA3AyAgAEIANwMoIABCADcDMCAAQgA3AzggAEIANwNAIABCADcDSCAAQgA3A1AgAEIANwNYIABCADcDYCAAQgA3A2ggAEIANwNwIABCADcDeCAAQoiS853/zPmE6gBBACkDAIU3A4ABIABCu86qptjQ67O7f0EIKQMAhTcDiAEgAEKr8NP0r+68tzxBECkDAIU3A5ABIABC8e30+KWn/aelf0EYKQMAhTcDmAEgAELRhZrv+s+Uh9EAQSApAwCFNwOgASAAQp/Y+dnCkdqCm39BKCkDAIU3A6gBIABC6/qG2r+19sEfQTApAwCFNwOwASAAQvnC+JuRo7Pw2wBBOCkDAIU3A7gBIABCADcDwAEgAEIANwPIASAAQgA3A9ABC20BA38gAEHAAWohAyAAQcgBaiEEIAQpAwCnIQUCQANAIAEgAkYNASAFQYABRgRAIAMgAykDACAFrXw3AwBBACEFIAAQAwsgACAFaiABLQAAOgAAIAVBAWohBSABQQFqIQEMAAsLIAQgBa03AwALYQEDfyAAQcABaiEBIABByAFqIQIgASABKQMAIAIpAwB8NwMAIABCfzcD0AEgAikDAKchAwJAA0AgA0GAAUYNASAAIANqQQA6AAAgA0EBaiEDDAALCyACIAOtNwMAIAAQAwuqOwIgfgl/IABBgAFqISEgAEGIAWohIiAAQZABaiEjIABBmAFqISQgAEGgAWohJSAAQagBaiEmIABBsAFqIScgAEG4AWohKCAhKQMAIQEgIikDACECICMpAwAhAyAkKQMAIQQgJSkDACEFICYpAwAhBiAnKQMAIQcgKCkDACEIQoiS853/zPmE6gAhCUK7zqqm2NDrs7t/IQpCq/DT9K/uvLc8IQtC8e30+KWn/aelfyEMQtGFmu/6z5SH0QAhDUKf2PnZwpHagpt/IQ5C6/qG2r+19sEfIQ9C+cL4m5Gjs/DbACEQIAApAwAhESAAKQMIIRIgACkDECETIAApAxghFCAAKQMgIRUgACkDKCEWIAApAzAhFyAAKQM4IRggACkDQCEZIAApA0ghGiAAKQNQIRsgACkDWCEcIAApA2AhHSAAKQNoIR4gACkDcCEfIAApA3ghICANIAApA8ABhSENIA8gACkD0AGFIQ8gASAFIBF8fCEBIA0gAYVCIIohDSAJIA18IQkgBSAJhUIYiiEFIAEgBSASfHwhASANIAGFQhCKIQ0gCSANfCEJIAUgCYVCP4ohBSACIAYgE3x8IQIgDiAChUIgiiEOIAogDnwhCiAGIAqFQhiKIQYgAiAGIBR8fCECIA4gAoVCEIohDiAKIA58IQogBiAKhUI/iiEGIAMgByAVfHwhAyAPIAOFQiCKIQ8gCyAPfCELIAcgC4VCGIohByADIAcgFnx8IQMgDyADhUIQiiEPIAsgD3whCyAHIAuFQj+KIQcgBCAIIBd8fCEEIBAgBIVCIIohECAMIBB8IQwgCCAMhUIYiiEIIAQgCCAYfHwhBCAQIASFQhCKIRAgDCAQfCEMIAggDIVCP4ohCCABIAYgGXx8IQEgECABhUIgiiEQIAsgEHwhCyAGIAuFQhiKIQYgASAGIBp8fCEBIBAgAYVCEIohECALIBB8IQsgBiALhUI/iiEGIAIgByAbfHwhAiANIAKFQiCKIQ0gDCANfCEMIAcgDIVCGIohByACIAcgHHx8IQIgDSAChUIQiiENIAwgDXwhDCAHIAyFQj+KIQcgAyAIIB18fCEDIA4gA4VCIIohDiAJIA58IQkgCCAJhUIYiiEIIAMgCCAefHwhAyAOIAOFQhCKIQ4gCSAOfCEJIAggCYVCP4ohCCAEIAUgH3x8IQQgDyAEhUIgiiEPIAogD3whCiAFIAqFQhiKIQUgBCAFICB8fCEEIA8gBIVCEIohDyAKIA98IQogBSAKhUI/iiEFIAEgBSAffHwhASANIAGFQiCKIQ0gCSANfCEJIAUgCYVCGIohBSABIAUgG3x8IQEgDSABhUIQiiENIAkgDXwhCSAFIAmFQj+KIQUgAiAGIBV8fCECIA4gAoVCIIohDiAKIA58IQogBiAKhUIYiiEGIAIgBiAZfHwhAiAOIAKFQhCKIQ4gCiAOfCEKIAYgCoVCP4ohBiADIAcgGnx8IQMgDyADhUIgiiEPIAsgD3whCyAHIAuFQhiKIQcgAyAHICB8fCEDIA8gA4VCEIohDyALIA98IQsgByALhUI/iiEHIAQgCCAefHwhBCAQIASFQiCKIRAgDCAQfCEMIAggDIVCGIohCCAEIAggF3x8IQQgECAEhUIQiiEQIAwgEHwhDCAIIAyFQj+KIQggASAGIBJ8fCEBIBAgAYVCIIohECALIBB8IQsgBiALhUIYiiEGIAEgBiAdfHwhASAQIAGFQhCKIRAgCyAQfCELIAYgC4VCP4ohBiACIAcgEXx8IQIgDSAChUIgiiENIAwgDXwhDCAHIAyFQhiKIQcgAiAHIBN8fCECIA0gAoVCEIohDSAMIA18IQwgByAMhUI/iiEHIAMgCCAcfHwhAyAOIAOFQiCKIQ4gCSAOfCEJIAggCYVCGIohCCADIAggGHx8IQMgDiADhUIQiiEOIAkgDnwhCSAIIAmFQj+KIQggBCAFIBZ8fCEEIA8gBIVCIIohDyAKIA98IQogBSAKhUIYiiEFIAQgBSAUfHwhBCAPIASFQhCKIQ8gCiAPfCEKIAUgCoVCP4ohBSABIAUgHHx8IQEgDSABhUIgiiENIAkgDXwhCSAFIAmFQhiKIQUgASAFIBl8fCEBIA0gAYVCEIohDSAJIA18IQkgBSAJhUI/iiEFIAIgBiAdfHwhAiAOIAKFQiCKIQ4gCiAOfCEKIAYgCoVCGIohBiACIAYgEXx8IQIgDiAChUIQiiEOIAogDnwhCiAGIAqFQj+KIQYgAyAHIBZ8fCEDIA8gA4VCIIohDyALIA98IQsgByALhUIYiiEHIAMgByATfHwhAyAPIAOFQhCKIQ8gCyAPfCELIAcgC4VCP4ohByAEIAggIHx8IQQgECAEhUIgiiEQIAwgEHwhDCAIIAyFQhiKIQggBCAIIB58fCEEIBAgBIVCEIohECAMIBB8IQwgCCAMhUI/iiEIIAEgBiAbfHwhASAQIAGFQiCKIRAgCyAQfCELIAYgC4VCGIohBiABIAYgH3x8IQEgECABhUIQiiEQIAsgEHwhCyAGIAuFQj+KIQYgAiAHIBR8fCECIA0gAoVCIIohDSAMIA18IQwgByAMhUIYiiEHIAIgByAXfHwhAiANIAKFQhCKIQ0gDCANfCEMIAcgDIVCP4ohByADIAggGHx8IQMgDiADhUIgiiEOIAkgDnwhCSAIIAmFQhiKIQggAyAIIBJ8fCEDIA4gA4VCEIohDiAJIA58IQkgCCAJhUI/iiEIIAQgBSAafHwhBCAPIASFQiCKIQ8gCiAPfCEKIAUgCoVCGIohBSAEIAUgFXx8IQQgDyAEhUIQiiEPIAogD3whCiAFIAqFQj+KIQUgASAFIBh8fCEBIA0gAYVCIIohDSAJIA18IQkgBSAJhUIYiiEFIAEgBSAafHwhASANIAGFQhCKIQ0gCSANfCEJIAUgCYVCP4ohBSACIAYgFHx8IQIgDiAChUIgiiEOIAogDnwhCiAGIAqFQhiKIQYgAiAGIBJ8fCECIA4gAoVCEIohDiAKIA58IQogBiAKhUI/iiEGIAMgByAefHwhAyAPIAOFQiCKIQ8gCyAPfCELIAcgC4VCGIohByADIAcgHXx8IQMgDyADhUIQiiEPIAsgD3whCyAHIAuFQj+KIQcgBCAIIBx8fCEEIBAgBIVCIIohECAMIBB8IQwgCCAMhUIY
|
|
|
|
var ready = null;
|
|
|
|
|
|
|
|
var mod = {
|
|
|
|
buffer: wasm,
|
|
|
|
memory: null,
|
|
|
|
exports: null,
|
|
|
|
realloc: realloc,
|
|
|
|
onload: onload
|
|
|
|
};
|
|
|
|
|
|
|
|
onload(function () {});
|
|
|
|
|
|
|
|
return mod
|
|
|
|
|
|
|
|
function realloc (size) {
|
|
|
|
mod.exports.memory.grow(Math.max(0, Math.ceil(Math.abs(size - mod.memory.length) / 65536)));
|
|
|
|
mod.memory = new Uint8Array(mod.exports.memory.buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
function onload (cb) {
|
|
|
|
if (mod.exports) return cb()
|
|
|
|
|
|
|
|
if (ready) {
|
|
|
|
ready.then(cb.bind(null, null)).catch(cb);
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
if (opts && opts.async) throw new Error('async')
|
|
|
|
setup({instance: new WebAssembly.Instance(new WebAssembly.Module(wasm), imp)});
|
|
|
|
} catch (err) {
|
|
|
|
ready = WebAssembly.instantiate(wasm, imp).then(setup);
|
|
|
|
}
|
|
|
|
|
|
|
|
onload(cb);
|
|
|
|
}
|
|
|
|
|
|
|
|
function setup (w) {
|
|
|
|
mod.exports = w.instance.exports;
|
|
|
|
mod.memory = mod.exports.memory && mod.exports.memory.buffer && new Uint8Array(mod.exports.memory.buffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function toUint8Array (s) {
|
|
|
|
if (typeof atob === 'function') return new Uint8Array(atob(s).split('').map(charCodeAt))
|
|
|
|
return (commonjsRequire().Buffer).from(s, 'base64')
|
|
|
|
}
|
|
|
|
|
|
|
|
function charCodeAt (c) {
|
|
|
|
return c.charCodeAt(0)
|
|
|
|
}
|
|
|
|
|
|
|
|
var blake2bWasm = createCommonjsModule(function (module) {
|
|
|
|
var wasm = blake2b();
|
|
|
|
|
|
|
|
var head = 64;
|
|
|
|
var freeList = [];
|
|
|
|
|
|
|
|
module.exports = Blake2b;
|
|
|
|
var BYTES_MIN = module.exports.BYTES_MIN = 16;
|
|
|
|
var BYTES_MAX = module.exports.BYTES_MAX = 64;
|
|
|
|
var BYTES = module.exports.BYTES = 32;
|
|
|
|
var KEYBYTES_MIN = module.exports.KEYBYTES_MIN = 16;
|
|
|
|
var KEYBYTES_MAX = module.exports.KEYBYTES_MAX = 64;
|
|
|
|
var KEYBYTES = module.exports.KEYBYTES = 32;
|
|
|
|
var SALTBYTES = module.exports.SALTBYTES = 16;
|
|
|
|
var PERSONALBYTES = module.exports.PERSONALBYTES = 16;
|
|
|
|
|
|
|
|
function Blake2b (digestLength, key, salt, personal, noAssert) {
|
|
|
|
if (!(this instanceof Blake2b)) return new Blake2b(digestLength, key, salt, personal, noAssert)
|
|
|
|
if (!(wasm && wasm.exports)) throw new Error('WASM not loaded. Wait for Blake2b.ready(cb)')
|
|
|
|
if (!digestLength) digestLength = 32;
|
|
|
|
|
|
|
|
if (noAssert !== true) {
|
|
|
|
nanoassert(digestLength >= BYTES_MIN, 'digestLength must be at least ' + BYTES_MIN + ', was given ' + digestLength);
|
|
|
|
nanoassert(digestLength <= BYTES_MAX, 'digestLength must be at most ' + BYTES_MAX + ', was given ' + digestLength);
|
|
|
|
if (key != null) {
|
|
|
|
nanoassert(key instanceof Uint8Array, 'key must be Uint8Array or Buffer');
|
|
|
|
nanoassert(key.length >= KEYBYTES_MIN, 'key must be at least ' + KEYBYTES_MIN + ', was given ' + key.length);
|
|
|
|
nanoassert(key.length <= KEYBYTES_MAX, 'key must be at least ' + KEYBYTES_MAX + ', was given ' + key.length);
|
|
|
|
}
|
|
|
|
if (salt != null) {
|
|
|
|
nanoassert(salt instanceof Uint8Array, 'salt must be Uint8Array or Buffer');
|
|
|
|
nanoassert(salt.length === SALTBYTES, 'salt must be exactly ' + SALTBYTES + ', was given ' + salt.length);
|
|
|
|
}
|
|
|
|
if (personal != null) {
|
|
|
|
nanoassert(personal instanceof Uint8Array, 'personal must be Uint8Array or Buffer');
|
|
|
|
nanoassert(personal.length === PERSONALBYTES, 'personal must be exactly ' + PERSONALBYTES + ', was given ' + personal.length);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!freeList.length) {
|
|
|
|
freeList.push(head);
|
|
|
|
head += 216;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.digestLength = digestLength;
|
|
|
|
this.finalized = false;
|
|
|
|
this.pointer = freeList.pop();
|
|
|
|
|
|
|
|
wasm.memory.fill(0, 0, 64);
|
|
|
|
wasm.memory[0] = this.digestLength;
|
|
|
|
wasm.memory[1] = key ? key.length : 0;
|
|
|
|
wasm.memory[2] = 1; // fanout
|
|
|
|
wasm.memory[3] = 1; // depth
|
|
|
|
|
|
|
|
if (salt) wasm.memory.set(salt, 32);
|
|
|
|
if (personal) wasm.memory.set(personal, 48);
|
|
|
|
|
|
|
|
if (this.pointer + 216 > wasm.memory.length) wasm.realloc(this.pointer + 216); // we need 216 bytes for the state
|
|
|
|
wasm.exports.blake2b_init(this.pointer, this.digestLength);
|
|
|
|
|
|
|
|
if (key) {
|
|
|
|
this.update(key);
|
|
|
|
wasm.memory.fill(0, head, head + key.length); // whiteout key
|
|
|
|
wasm.memory[this.pointer + 200] = 128;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Blake2b.prototype.update = function (input) {
|
|
|
|
nanoassert(this.finalized === false, 'Hash instance finalized');
|
|
|
|
nanoassert(input instanceof Uint8Array, 'input must be Uint8Array or Buffer');
|
|
|
|
|
|
|
|
if (head + input.length > wasm.memory.length) wasm.realloc(head + input.length);
|
|
|
|
wasm.memory.set(input, head);
|
|
|
|
wasm.exports.blake2b_update(this.pointer, head, head + input.length);
|
|
|
|
return this
|
|
|
|
};
|
|
|
|
|
|
|
|
Blake2b.prototype.getPartialHash = function () {
|
|
|
|
return wasm.memory.slice(this.pointer, this.pointer+216);
|
|
|
|
};
|
|
|
|
|
|
|
|
Blake2b.prototype.setPartialHash = function (ph) {
|
|
|
|
wasm.memory.set(ph, this.pointer);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Blake2b.prototype.digest = function (enc) {
|
|
|
|
nanoassert(this.finalized === false, 'Hash instance finalized');
|
|
|
|
this.finalized = true;
|
|
|
|
|
|
|
|
freeList.push(this.pointer);
|
|
|
|
wasm.exports.blake2b_final(this.pointer);
|
|
|
|
|
|
|
|
if (!enc || enc === 'binary') {
|
|
|
|
return wasm.memory.slice(this.pointer + 128, this.pointer + 128 + this.digestLength)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (enc === 'hex') {
|
|
|
|
return hexSlice(wasm.memory, this.pointer + 128, this.digestLength)
|
|
|
|
}
|
|
|
|
|
|
|
|
nanoassert(enc instanceof Uint8Array && enc.length >= this.digestLength, 'input must be Uint8Array or Buffer');
|
|
|
|
for (var i = 0; i < this.digestLength; i++) {
|
|
|
|
enc[i] = wasm.memory[this.pointer + 128 + i];
|
|
|
|
}
|
|
|
|
|
|
|
|
return enc
|
|
|
|
};
|
|
|
|
|
|
|
|
// libsodium compat
|
|
|
|
Blake2b.prototype.final = Blake2b.prototype.digest;
|
|
|
|
|
|
|
|
Blake2b.WASM = wasm && wasm.buffer;
|
|
|
|
Blake2b.SUPPORTED = typeof WebAssembly !== 'undefined';
|
|
|
|
|
|
|
|
Blake2b.ready = function (cb) {
|
|
|
|
if (!cb) cb = noop;
|
|
|
|
if (!wasm) return cb(new Error('WebAssembly not supported'))
|
|
|
|
|
|
|
|
// backwards compat, can be removed in a new major
|
|
|
|
var p = new Promise(function (reject, resolve) {
|
|
|
|
wasm.onload(function (err) {
|
|
|
|
if (err) resolve();
|
|
|
|
else reject();
|
|
|
|
cb(err);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
return p
|
|
|
|
};
|
|
|
|
|
|
|
|
Blake2b.prototype.ready = Blake2b.ready;
|
|
|
|
|
|
|
|
function noop () {}
|
|
|
|
|
|
|
|
function hexSlice (buf, start, len) {
|
|
|
|
var str = '';
|
|
|
|
for (var i = 0; i < len; i++) str += toHex(buf[start + i]);
|
|
|
|
return str
|
|
|
|
}
|
|
|
|
|
|
|
|
function toHex (n) {
|
|
|
|
if (n < 16) return '0' + n.toString(16)
|
|
|
|
return n.toString(16)
|
|
|
|
}
|
|
|
|
});
|
|
|
|
var blake2bWasm_1 = blake2bWasm.BYTES_MIN;
|
|
|
|
var blake2bWasm_2 = blake2bWasm.BYTES_MAX;
|
|
|
|
var blake2bWasm_3 = blake2bWasm.BYTES;
|
|
|
|
var blake2bWasm_4 = blake2bWasm.KEYBYTES_MIN;
|
|
|
|
var blake2bWasm_5 = blake2bWasm.KEYBYTES_MAX;
|
|
|
|
var blake2bWasm_6 = blake2bWasm.KEYBYTES;
|
|
|
|
var blake2bWasm_7 = blake2bWasm.SALTBYTES;
|
|
|
|
var blake2bWasm_8 = blake2bWasm.PERSONALBYTES;
|
|
|
|
|
|
|
|
/* global window */
|
|
|
|
|
|
|
|
const _revTable$2 = [];
|
|
|
|
for (let i=0; i<256; i++) {
|
|
|
|
_revTable$2[i] = _revSlow$2(i, 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
function _revSlow$2(idx, bits) {
|
|
|
|
let res =0;
|
|
|
|
let a = idx;
|
|
|
|
for (let i=0; i<bits; i++) {
|
|
|
|
res <<= 1;
|
|
|
|
res = res | (a &1);
|
|
|
|
a >>=1;
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
function bitReverse$1(idx, bits) {
|
|
|
|
return (
|
|
|
|
_revTable$2[idx >>> 24] |
|
|
|
|
(_revTable$2[(idx >>> 16) & 0xFF] << 8) |
|
|
|
|
(_revTable$2[(idx >>> 8) & 0xFF] << 16) |
|
|
|
|
(_revTable$2[idx & 0xFF] << 24)
|
|
|
|
) >>> (32-bits);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function log2$2( V )
|
|
|
|
{
|
|
|
|
return( ( ( V & 0xFFFF0000 ) !== 0 ? ( V &= 0xFFFF0000, 16 ) : 0 ) | ( ( V & 0xFF00FF00 ) !== 0 ? ( V &= 0xFF00FF00, 8 ) : 0 ) | ( ( V & 0xF0F0F0F0 ) !== 0 ? ( V &= 0xF0F0F0F0, 4 ) : 0 ) | ( ( V & 0xCCCCCCCC ) !== 0 ? ( V &= 0xCCCCCCCC, 2 ) : 0 ) | ( ( V & 0xAAAAAAAA ) !== 0 ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function formatHash(b, title) {
|
|
|
|
const a = new DataView(b.buffer, b.byteOffset, b.byteLength);
|
|
|
|
let S = "";
|
|
|
|
for (let i=0; i<4; i++) {
|
|
|
|
if (i>0) S += "\n";
|
|
|
|
S += "\t\t";
|
|
|
|
for (let j=0; j<4; j++) {
|
|
|
|
if (j>0) S += " ";
|
|
|
|
S += a.getUint32(i*16+j*4).toString(16).padStart(8, "0");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (title) S = title + "\n" + S;
|
|
|
|
return S;
|
|
|
|
}
|
|
|
|
|
|
|
|
function hashIsEqual(h1, h2) {
|
|
|
|
if (h1.byteLength != h2.byteLength) return false;
|
|
|
|
var dv1 = new Int8Array(h1);
|
|
|
|
var dv2 = new Int8Array(h2);
|
|
|
|
for (var i = 0 ; i != h1.byteLength ; i++)
|
|
|
|
{
|
|
|
|
if (dv1[i] != dv2[i]) return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
function cloneHasher(h) {
|
|
|
|
const ph = h.getPartialHash();
|
|
|
|
const res = blake2bWasm(64);
|
|
|
|
res.setPartialHash(ph);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
async function sameRatio(curve, g1s, g1sx, g2s, g2sx) {
|
|
|
|
if (curve.G1.isZero(g1s)) return false;
|
|
|
|
if (curve.G1.isZero(g1sx)) return false;
|
|
|
|
if (curve.G2.isZero(g2s)) return false;
|
|
|
|
if (curve.G2.isZero(g2sx)) return false;
|
|
|
|
// return curve.F12.eq(curve.pairing(g1s, g2sx), curve.pairing(g1sx, g2s));
|
|
|
|
const res = await curve.pairingEq(g1s, g2sx, curve.G1.neg(g1sx), g2s);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function askEntropy() {
|
|
|
|
{
|
|
|
|
return window.prompt("Enter a random text. (Entropy): ", "");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function getRandomRng(entropy) {
|
|
|
|
// Generate a random Rng
|
|
|
|
while (!entropy) {
|
|
|
|
entropy = await askEntropy();
|
|
|
|
}
|
|
|
|
const hasher = blake2bWasm(64);
|
|
|
|
hasher.update(crypto.randomBytes(64));
|
|
|
|
const enc = new TextEncoder(); // always utf-8
|
|
|
|
hasher.update(enc.encode(entropy));
|
|
|
|
const hash = Buffer.from(hasher.digest());
|
|
|
|
|
|
|
|
const seed = [];
|
|
|
|
for (let i=0;i<8;i++) {
|
|
|
|
seed[i] = hash.readUInt32BE(i*4);
|
|
|
|
}
|
|
|
|
const rng = new ChaCha(seed);
|
|
|
|
return rng;
|
|
|
|
}
|
|
|
|
|
|
|
|
function rngFromBeaconParams(beaconHash, numIterationsExp) {
|
|
|
|
let nIterationsInner;
|
|
|
|
let nIterationsOuter;
|
|
|
|
if (numIterationsExp<32) {
|
|
|
|
nIterationsInner = (1 << numIterationsExp) >>> 0;
|
|
|
|
nIterationsOuter = 1;
|
|
|
|
} else {
|
|
|
|
nIterationsInner = 0x100000000;
|
|
|
|
nIterationsOuter = (1 << (numIterationsExp-32)) >>> 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
let curHash = beaconHash;
|
|
|
|
for (let i=0; i<nIterationsOuter; i++) {
|
|
|
|
for (let j=0; j<nIterationsInner; j++) {
|
|
|
|
curHash = crypto.createHash("sha256").update(curHash).digest();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const curHashV = new DataView(curHash.buffer, curHash.byteOffset, curHash.byteLength);
|
|
|
|
const seed = [];
|
|
|
|
for (let i=0; i<8; i++) {
|
|
|
|
seed[i] = curHashV.getUint32(i*4, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
const rng = new ChaCha(seed);
|
|
|
|
|
|
|
|
return rng;
|
|
|
|
}
|
|
|
|
|
|
|
|
function hex2ByteArray(s) {
|
|
|
|
if (s instanceof Uint8Array) return s;
|
|
|
|
if (s.slice(0,2) == "0x") s= s.slice(2);
|
|
|
|
return new Uint8Array(s.match(/[\da-f]{2}/gi).map(function (h) {
|
|
|
|
return parseInt(h, 16);
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
function byteArray2hex(byteArray) {
|
|
|
|
return Array.prototype.map.call(byteArray, function(byte) {
|
|
|
|
return ("0" + (byte & 0xFF).toString(16)).slice(-2);
|
|
|
|
}).join("");
|
|
|
|
}
|
|
|
|
|
|
|
|
async function writeHeader(fd, zkey) {
|
|
|
|
|
|
|
|
// Write the header
|
|
|
|
///////////
|
|
|
|
await startWriteSection(fd, 1);
|
|
|
|
await fd.writeULE32(1); // Groth
|
|
|
|
await endWriteSection(fd);
|
|
|
|
|
|
|
|
// Write the Groth header section
|
|
|
|
///////////
|
|
|
|
|
|
|
|
const curve = await getCurveFromQ(zkey.q);
|
|
|
|
|
|
|
|
await startWriteSection(fd, 2);
|
|
|
|
const primeQ = curve.q;
|
|
|
|
const n8q = (Math.floor( (Scalar$1.bitLength(primeQ) - 1) / 64) +1)*8;
|
|
|
|
|
|
|
|
const primeR = curve.r;
|
|
|
|
const n8r = (Math.floor( (Scalar$1.bitLength(primeR) - 1) / 64) +1)*8;
|
|
|
|
|
|
|
|
await fd.writeULE32(n8q);
|
|
|
|
await writeBigInt(fd, primeQ, n8q);
|
|
|
|
await fd.writeULE32(n8r);
|
|
|
|
await writeBigInt(fd, primeR, n8r);
|
|
|
|
await fd.writeULE32(zkey.nVars); // Total number of bars
|
|
|
|
await fd.writeULE32(zkey.nPublic); // Total number of public vars (not including ONE)
|
|
|
|
await fd.writeULE32(zkey.domainSize); // domainSize
|
|
|
|
await writeG1(fd, curve, zkey.vk_alpha_1);
|
|
|
|
await writeG1(fd, curve, zkey.vk_beta_1);
|
|
|
|
await writeG2(fd, curve, zkey.vk_beta_2);
|
|
|
|
await writeG2(fd, curve, zkey.vk_gamma_2);
|
|
|
|
await writeG1(fd, curve, zkey.vk_delta_1);
|
|
|
|
await writeG2(fd, curve, zkey.vk_delta_2);
|
|
|
|
|
|
|
|
await endWriteSection(fd);
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
async function writeG1(fd, curve, p) {
|
|
|
|
const buff = new Uint8Array(curve.G1.F.n8*2);
|
|
|
|
curve.G1.toRprLEM(buff, 0, p);
|
|
|
|
await fd.write(buff);
|
|
|
|
}
|
|
|
|
|
|
|
|
async function writeG2(fd, curve, p) {
|
|
|
|
const buff = new Uint8Array(curve.G2.F.n8*2);
|
|
|
|
curve.G2.toRprLEM(buff, 0, p);
|
|
|
|
await fd.write(buff);
|
|
|
|
}
|
|
|
|
|
|
|
|
async function readG1(fd, curve) {
|
|
|
|
const buff = await fd.read(curve.G1.F.n8*2);
|
|
|
|
return curve.G1.fromRprLEM(buff, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
async function readG2(fd, curve) {
|
|
|
|
const buff = await fd.read(curve.G2.F.n8*2);
|
|
|
|
return curve.G2.fromRprLEM(buff, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async function readHeader(fd, sections, protocol) {
|
|
|
|
if (protocol != "groth16") throw new Error("Protocol not supported: "+protocol);
|
|
|
|
|
|
|
|
const zkey = {};
|
|
|
|
|
|
|
|
// Read Header
|
|
|
|
/////////////////////
|
|
|
|
await startReadUniqueSection(fd, sections, 1);
|
|
|
|
const protocolId = await fd.readULE32();
|
|
|
|
if (protocolId != 1) throw new Error("File is not groth");
|
|
|
|
zkey.protocol = "groth16";
|
|
|
|
await endReadSection(fd);
|
|
|
|
|
|
|
|
// Read Groth Header
|
|
|
|
/////////////////////
|
|
|
|
await startReadUniqueSection(fd, sections, 2);
|
|
|
|
const n8q = await fd.readULE32();
|
|
|
|
zkey.n8q = n8q;
|
|
|
|
zkey.q = await readBigInt(fd, n8q);
|
|
|
|
|
|
|
|
const n8r = await fd.readULE32();
|
|
|
|
zkey.n8r = n8r;
|
|
|
|
zkey.r = await readBigInt(fd, n8r);
|
|
|
|
|
|
|
|
let curve = await getCurveFromQ(zkey.q);
|
|
|
|
|
|
|
|
zkey.nVars = await fd.readULE32();
|
|
|
|
zkey.nPublic = await fd.readULE32();
|
|
|
|
zkey.domainSize = await fd.readULE32();
|
|
|
|
zkey.power = log2$2(zkey.domainSize);
|
|
|
|
zkey.vk_alpha_1 = await readG1(fd, curve);
|
|
|
|
zkey.vk_beta_1 = await readG1(fd, curve);
|
|
|
|
zkey.vk_beta_2 = await readG2(fd, curve);
|
|
|
|
zkey.vk_gamma_2 = await readG2(fd, curve);
|
|
|
|
zkey.vk_delta_1 = await readG1(fd, curve);
|
|
|
|
zkey.vk_delta_2 = await readG2(fd, curve);
|
|
|
|
await endReadSection(fd);
|
|
|
|
|
|
|
|
return zkey;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
async function readZKey(fileName) {
|
|
|
|
const {fd, sections} = await readBinFile(fileName, "zkey", 1);
|
|
|
|
|
|
|
|
const zkey = await readHeader(fd, sections, "groth16");
|
|
|
|
|
|
|
|
const Fr = new F1Field(zkey.r);
|
|
|
|
const Rr = Scalar$1.mod(Scalar$1.shl(1, zkey.n8r*8), zkey.r);
|
|
|
|
const Rri = Fr.inv(Rr);
|
|
|
|
const Rri2 = Fr.mul(Rri, Rri);
|
|
|
|
|
|
|
|
let curve = getCurveFromQ(zkey.q);
|
|
|
|
|
|
|
|
// Read IC Section
|
|
|
|
///////////
|
|
|
|
await startReadUniqueSection(fd, sections, 3);
|
|
|
|
zkey.IC = [];
|
|
|
|
for (let i=0; i<= zkey.nPublic; i++) {
|
|
|
|
const P = await readG1(fd, curve);
|
|
|
|
zkey.IC.push(P);
|
|
|
|
}
|
|
|
|
await endReadSection(fd);
|
|
|
|
|
|
|
|
|
|
|
|
// Read Coefs
|
|
|
|
///////////
|
|
|
|
await startReadUniqueSection(fd, sections, 4);
|
|
|
|
const nCCoefs = await fd.readULE32();
|
|
|
|
zkey.ccoefs = [];
|
|
|
|
for (let i=0; i<nCCoefs; i++) {
|
|
|
|
const m = await fd.readULE32();
|
|
|
|
const c = await fd.readULE32();
|
|
|
|
const s = await fd.readULE32();
|
|
|
|
const v = await readFr2();
|
|
|
|
zkey.ccoefs.push({
|
|
|
|
matrix: m,
|
|
|
|
constraint: c,
|
|
|
|
signal: s,
|
|
|
|
value: v
|
|
|
|
});
|
|
|
|
}
|
|
|
|
await endReadSection(fd);
|
|
|
|
|
|
|
|
// Read A points
|
|
|
|
///////////
|
|
|
|
await startReadUniqueSection(fd, sections, 5);
|
|
|
|
zkey.A = [];
|
|
|
|
for (let i=0; i<zkey.nVars; i++) {
|
|
|
|
const A = await readG1(fd, curve);
|
|
|
|
zkey.A[i] = A;
|
|
|
|
}
|
|
|
|
await endReadSection(fd);
|
|
|
|
|
|
|
|
|
|
|
|
// Read B1
|
|
|
|
///////////
|
|
|
|
await startReadUniqueSection(fd, sections, 6);
|
|
|
|
zkey.B1 = [];
|
|
|
|
for (let i=0; i<zkey.nVars; i++) {
|
|
|
|
const B1 = await readG1(fd, curve);
|
|
|
|
|
|
|
|
zkey.B1[i] = B1;
|
|
|
|
}
|
|
|
|
await endReadSection(fd);
|
|
|
|
|
|
|
|
|
|
|
|
// Read B2 points
|
|
|
|
///////////
|
|
|
|
await startReadUniqueSection(fd, sections, 7);
|
|
|
|
zkey.B2 = [];
|
|
|
|
for (let i=0; i<zkey.nVars; i++) {
|
|
|
|
const B2 = await readG2(fd, curve);
|
|
|
|
zkey.B2[i] = B2;
|
|
|
|
}
|
|
|
|
await endReadSection(fd);
|
|
|
|
|
|
|
|
|
|
|
|
// Read C points
|
|
|
|
///////////
|
|
|
|
await startReadUniqueSection(fd, sections, 8);
|
|
|
|
zkey.C = [];
|
|
|
|
for (let i=zkey.nPublic+1; i<zkey.nVars; i++) {
|
|
|
|
const C = await readG1(fd, curve);
|
|
|
|
|
|
|
|
zkey.C[i] = C;
|
|
|
|
}
|
|
|
|
await endReadSection(fd);
|
|
|
|
|
|
|
|
|
|
|
|
// Read H points
|
|
|
|
///////////
|
|
|
|
await startReadUniqueSection(fd, sections, 9);
|
|
|
|
zkey.hExps = [];
|
|
|
|
for (let i=0; i<zkey.domainSize; i++) {
|
|
|
|
const H = await readG1(fd, curve);
|
|
|
|
zkey.hExps.push(H);
|
|
|
|
}
|
|
|
|
await endReadSection(fd);
|
|
|
|
|
|
|
|
await fd.close();
|
|
|
|
|
|
|
|
return zkey;
|
|
|
|
|
|
|
|
async function readFr2() {
|
|
|
|
const n = await readBigInt(fd, zkey.n8r);
|
|
|
|
return Fr.mul(n, Rri2);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function readContribution(fd, curve) {
|
|
|
|
const c = {delta:{}};
|
|
|
|
c.deltaAfter = await readG1(fd, curve);
|
|
|
|
c.delta.g1_s = await readG1(fd, curve);
|
|
|
|
c.delta.g1_sx = await readG1(fd, curve);
|
|
|
|
c.delta.g2_spx = await readG2(fd, curve);
|
|
|
|
c.transcript = await fd.read(64);
|
|
|
|
c.type = await fd.readULE32();
|
|
|
|
|
|
|
|
const paramLength = await fd.readULE32();
|
|
|
|
const curPos = fd.pos;
|
|
|
|
let lastType =0;
|
|
|
|
while (fd.pos-curPos < paramLength) {
|
|
|
|
const buffType = await fd.read(1);
|
|
|
|
if (buffType[0]<= lastType) throw new Error("Parameters in the contribution must be sorted");
|
|
|
|
lastType = buffType[0];
|
|
|
|
if (buffType[0]==1) { // Name
|
|
|
|
const buffLen = await fd.read(1);
|
|
|
|
const buffStr = await fd.read(buffLen[0]);
|
|
|
|
c.name = new TextDecoder().decode(buffStr);
|
|
|
|
} else if (buffType[0]==2) {
|
|
|
|
const buffExp = await fd.read(1);
|
|
|
|
c.numIterationsExp = buffExp[0];
|
|
|
|
} else if (buffType[0]==3) {
|
|
|
|
const buffLen = await fd.read(1);
|
|
|
|
c.beaconHash = await fd.read(buffLen[0]);
|
|
|
|
} else {
|
|
|
|
throw new Error("Parameter not recognized");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (fd.pos != curPos + paramLength) {
|
|
|
|
throw new Error("Parametes do not match");
|
|
|
|
}
|
|
|
|
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function readMPCParams(fd, curve, sections) {
|
|
|
|
await startReadUniqueSection(fd, sections, 10);
|
|
|
|
const res = { contributions: []};
|
|
|
|
res.csHash = await fd.read(64);
|
|
|
|
const n = await fd.readULE32();
|
|
|
|
for (let i=0; i<n; i++) {
|
|
|
|
const c = await readContribution(fd, curve);
|
|
|
|
res.contributions.push(c);
|
|
|
|
}
|
|
|
|
await endReadSection(fd);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
async function writeContribution(fd, curve, c) {
|
|
|
|
await writeG1(fd, curve, c.deltaAfter);
|
|
|
|
await writeG1(fd, curve, c.delta.g1_s);
|
|
|
|
await writeG1(fd, curve, c.delta.g1_sx);
|
|
|
|
await writeG2(fd, curve, c.delta.g2_spx);
|
|
|
|
await fd.write(c.transcript);
|
|
|
|
await fd.writeULE32(c.type || 0);
|
|
|
|
|
|
|
|
const params = [];
|
|
|
|
if (c.name) {
|
|
|
|
params.push(1); // Param Name
|
|
|
|
const nameData = new TextEncoder("utf-8").encode(c.name.substring(0,64));
|
|
|
|
params.push(nameData.byteLength);
|
|
|
|
for (let i=0; i<nameData.byteLength; i++) params.push(nameData[i]);
|
|
|
|
}
|
|
|
|
if (c.type == 1) {
|
|
|
|
params.push(2); // Param numIterationsExp
|
|
|
|
params.push(c.numIterationsExp);
|
|
|
|
|
|
|
|
params.push(3); // Beacon Hash
|
|
|
|
params.push(c.beaconHash.byteLength);
|
|
|
|
for (let i=0; i<c.beaconHash.byteLength; i++) params.push(c.beaconHash[i]);
|
|
|
|
}
|
|
|
|
if (params.length>0) {
|
|
|
|
const paramsBuff = new Uint8Array(params);
|
|
|
|
await fd.writeULE32(paramsBuff.byteLength);
|
|
|
|
await fd.write(paramsBuff);
|
|
|
|
} else {
|
|
|
|
await fd.writeULE32(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
async function writeMPCParams(fd, curve, mpcParams) {
|
|
|
|
await startWriteSection(fd, 10);
|
|
|
|
await fd.write(mpcParams.csHash);
|
|
|
|
await fd.writeULE32(mpcParams.contributions.length);
|
|
|
|
for (let i=0; i<mpcParams.contributions.length; i++) {
|
|
|
|
await writeContribution(fd, curve,mpcParams.contributions[i]);
|
|
|
|
}
|
|
|
|
await endWriteSection(fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
function hashG1(hasher, curve, p) {
|
|
|
|
const buff = new Uint8Array(curve.G1.F.n8*2);
|
|
|
|
curve.G1.toRprUncompressed(buff, 0, p);
|
|
|
|
hasher.update(buff);
|
|
|
|
}
|
|
|
|
|
|
|
|
function hashG2(hasher,curve, p) {
|
|
|
|
const buff = new Uint8Array(curve.G2.F.n8*2);
|
|
|
|
curve.G2.toRprUncompressed(buff, 0, p);
|
|
|
|
hasher.update(buff);
|
|
|
|
}
|
|
|
|
|
|
|
|
function hashPubKey(hasher, curve, c) {
|
|
|
|
hashG1(hasher, curve, c.deltaAfter);
|
|
|
|
hashG1(hasher, curve, c.delta.g1_s);
|
|
|
|
hashG1(hasher, curve, c.delta.g1_sx);
|
|
|
|
hashG2(hasher, curve, c.delta.g2_spx);
|
|
|
|
hasher.update(c.transcript);
|
|
|
|
}
|
|
|
|
|
|
|
|
async function write(fd, witness, prime) {
|
|
|
|
|
|
|
|
await startWriteSection(fd, 1);
|
|
|
|
const n8 = (Math.floor( (Scalar$1.bitLength(prime) - 1) / 64) +1)*8;
|
|
|
|
await fd.writeULE32(n8);
|
|
|
|
await writeBigInt(fd, prime, n8);
|
|
|
|
await fd.writeULE32(witness.length);
|
|
|
|
await endWriteSection(fd);
|
|
|
|
|
|
|
|
await startWriteSection(fd, 2);
|
|
|
|
for (let i=0; i<witness.length; i++) {
|
|
|
|
await writeBigInt(fd, witness[i], n8);
|
|
|
|
}
|
|
|
|
await endWriteSection(fd);
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
async function writeBin(fd, witnessBin, prime) {
|
|
|
|
|
|
|
|
await startWriteSection(fd, 1);
|
|
|
|
const n8 = (Math.floor( (Scalar$1.bitLength(prime) - 1) / 64) +1)*8;
|
|
|
|
await fd.writeULE32(n8);
|
|
|
|
await writeBigInt(fd, prime, n8);
|
|
|
|
if (witnessBin.byteLength % n8 != 0) {
|
|
|
|
throw new Error("Invalid witness length");
|
|
|
|
}
|
|
|
|
await fd.writeULE32(witnessBin.byteLength / n8);
|
|
|
|
await endWriteSection(fd);
|
|
|
|
|
|
|
|
|
|
|
|
await startWriteSection(fd, 2);
|
|
|
|
await fd.write(witnessBin);
|
|
|
|
await endWriteSection(fd);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
async function readHeader$1(fd, sections) {
|
|
|
|
|
|
|
|
await startReadUniqueSection(fd, sections, 1);
|
|
|
|
const n8 = await fd.readULE32();
|
|
|
|
const q = await readBigInt(fd, n8);
|
|
|
|
const nWitness = await fd.readULE32();
|
|
|
|
await endReadSection(fd);
|
|
|
|
|
|
|
|
return {n8, q, nWitness};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
async function read(fileName) {
|
|
|
|
|
|
|
|
const {fd, sections} = await readBinFile(fileName, "wtns", 2);
|
|
|
|
|
|
|
|
const {n8, nWitness} = await readHeader$1(fd, sections);
|
|
|
|
|
|
|
|
await startReadUniqueSection(fd, sections, 2);
|
|
|
|
const res = [];
|
|
|
|
for (let i=0; i<nWitness; i++) {
|
|
|
|
const v = await readBigInt(fd, n8);
|
|
|
|
res.push(v);
|
|
|
|
}
|
|
|
|
await endReadSection(fd);
|
|
|
|
|
|
|
|
await fd.close();
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
const {stringifyBigInts: stringifyBigInts$3} = utils$1;
|
|
|
|
|
2020-07-13 07:21:03 +02:00
|
|
|
async function groth16Prove(zkeyFileName, witnessFileName, logger) {
|
2020-07-11 10:31:52 +02:00
|
|
|
const {fd: fdWtns, sections: sectionsWtns} = await readBinFile(witnessFileName, "wtns", 2);
|
|
|
|
|
|
|
|
const wtns = await readHeader$1(fdWtns, sectionsWtns);
|
|
|
|
|
|
|
|
const {fd: fdZKey, sections: sectionsZKey} = await readBinFile(zkeyFileName, "zkey", 2);
|
|
|
|
|
|
|
|
const zkey = await readHeader(fdZKey, sectionsZKey, "groth16");
|
|
|
|
|
|
|
|
if (!Scalar$1.eq(zkey.r, wtns.q)) {
|
|
|
|
throw new Error("Curve of the witness does not match the curve of the proving key");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (wtns.nWitness != zkey.nVars) {
|
|
|
|
throw new Error(`Invalid witness length. Circuit: ${zkey.nVars}, witness: ${wtns.nWitness}`);
|
|
|
|
}
|
|
|
|
|
|
|
|
const curve = await getCurveFromQ(zkey.q);
|
|
|
|
const Fr = curve.Fr;
|
|
|
|
const G1 = curve.G1;
|
|
|
|
const G2 = curve.G2;
|
|
|
|
|
|
|
|
const power = log2$2(zkey.domainSize);
|
|
|
|
|
|
|
|
const buffWitness = await readFullSection(fdWtns, sectionsWtns, 2);
|
|
|
|
const buffCoeffs = await readFullSection(fdZKey, sectionsZKey, 4);
|
|
|
|
const buffBasesA = await readFullSection(fdZKey, sectionsZKey, 5);
|
|
|
|
const buffBasesB1 = await readFullSection(fdZKey, sectionsZKey, 6);
|
|
|
|
const buffBasesB2 = await readFullSection(fdZKey, sectionsZKey, 7);
|
|
|
|
const buffBasesC = await readFullSection(fdZKey, sectionsZKey, 8);
|
|
|
|
const buffBasesH = await readFullSection(fdZKey, sectionsZKey, 9);
|
|
|
|
|
|
|
|
const [buffA_T, buffB_T, buffC_T] = await buldABC(curve, zkey, buffWitness, buffCoeffs);
|
|
|
|
|
|
|
|
const buffA = await Fr.ifft(buffA_T);
|
|
|
|
const buffAodd = await Fr.batchApplyKey(buffA, Fr.e(1), curve.Fr.w[power+1]);
|
|
|
|
const buffAodd_T = await Fr.fft(buffAodd);
|
|
|
|
|
|
|
|
const buffB = await Fr.ifft(buffB_T);
|
|
|
|
const buffBodd = await Fr.batchApplyKey(buffB, Fr.e(1), curve.Fr.w[power+1]);
|
|
|
|
const buffBodd_T = await Fr.fft(buffBodd);
|
|
|
|
|
|
|
|
const buffC = await Fr.ifft(buffC_T);
|
|
|
|
const buffCodd = await Fr.batchApplyKey(buffC, Fr.e(1), curve.Fr.w[power+1]);
|
|
|
|
const buffCodd_T = await Fr.fft(buffCodd);
|
|
|
|
|
|
|
|
const buffPodd_T = await joinABC(curve, zkey, buffAodd_T, buffBodd_T, buffCodd_T);
|
|
|
|
|
|
|
|
let proof = {};
|
|
|
|
|
|
|
|
proof.pi_a = await curve.G1.multiExpAffine(buffBasesA, buffWitness);
|
|
|
|
let pib1 = await curve.G1.multiExpAffine(buffBasesB1, buffWitness);
|
|
|
|
proof.pi_b = await curve.G2.multiExpAffine(buffBasesB2, buffWitness);
|
|
|
|
proof.pi_c = await curve.G1.multiExpAffine(buffBasesC, buffWitness.slice((zkey.nPublic+1)*curve.Fr.n8));
|
|
|
|
const resH = await curve.G1.multiExpAffine(buffBasesH, buffPodd_T);
|
|
|
|
|
|
|
|
const r = curve.Fr.random();
|
|
|
|
const s = curve.Fr.random();
|
|
|
|
|
|
|
|
proof.pi_a = G1.add( proof.pi_a, zkey.vk_alpha_1 );
|
|
|
|
proof.pi_a = G1.add( proof.pi_a, G1.timesFr( zkey.vk_delta_1, r ));
|
|
|
|
|
|
|
|
proof.pi_b = G2.add( proof.pi_b, zkey.vk_beta_2 );
|
|
|
|
proof.pi_b = G2.add( proof.pi_b, G2.timesFr( zkey.vk_delta_2, s ));
|
|
|
|
|
|
|
|
pib1 = G1.add( pib1, zkey.vk_beta_1 );
|
|
|
|
pib1 = G1.add( pib1, G1.timesFr( zkey.vk_delta_1, s ));
|
|
|
|
|
|
|
|
proof.pi_c = G1.add(proof.pi_c, resH);
|
|
|
|
|
|
|
|
|
|
|
|
proof.pi_c = G1.add( proof.pi_c, G1.timesFr( proof.pi_a, s ));
|
|
|
|
proof.pi_c = G1.add( proof.pi_c, G1.timesFr( pib1, r ));
|
|
|
|
proof.pi_c = G1.add( proof.pi_c, G1.timesFr( zkey.vk_delta_1, Fr.neg(Fr.mul(r,s) )));
|
|
|
|
|
|
|
|
|
|
|
|
let publicSignals = [];
|
|
|
|
|
|
|
|
for (let i=1; i<= zkey.nPublic; i++) {
|
|
|
|
const b = buffWitness.slice(i*Fr.n8, i*Fr.n8+Fr.n8);
|
|
|
|
publicSignals.push(Scalar$1.fromRprLE(b));
|
|
|
|
}
|
|
|
|
|
|
|
|
proof.pi_a = G1.toObject(G1.toAffine(proof.pi_a));
|
|
|
|
proof.pi_b = G2.toObject(G2.toAffine(proof.pi_b));
|
|
|
|
proof.pi_c = G1.toObject(G1.toAffine(proof.pi_c));
|
|
|
|
|
|
|
|
proof.protocol = "groth16";
|
|
|
|
|
|
|
|
await fdZKey.close();
|
|
|
|
await fdWtns.close();
|
|
|
|
|
|
|
|
proof = stringifyBigInts$3(proof);
|
|
|
|
publicSignals = stringifyBigInts$3(publicSignals);
|
|
|
|
|
|
|
|
return {proof, publicSignals};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function buldABC(curve, zkey, witness, coeffs) {
|
|
|
|
const concurrency = curve.tm.concurrency;
|
|
|
|
const sCoef = 4*3 + zkey.n8r;
|
|
|
|
|
|
|
|
const elementsPerChunk = Math.floor(zkey.domainSize/concurrency);
|
|
|
|
const coeffsDV = new DataView(coeffs.buffer, coeffs.byteOffset, coeffs.byteLength);
|
|
|
|
const promises = [];
|
|
|
|
|
|
|
|
const cutPoints = [];
|
|
|
|
for (let i=0; i<concurrency; i++) {
|
|
|
|
cutPoints.push( getCutPoint( Math.floor(i*zkey.domainSize /concurrency) ));
|
|
|
|
}
|
|
|
|
cutPoints.push(coeffs.byteLength);
|
|
|
|
|
|
|
|
for (let i=0; i<concurrency; i++) {
|
|
|
|
let n;
|
|
|
|
if (i< concurrency-1) {
|
|
|
|
n = elementsPerChunk;
|
|
|
|
} else {
|
|
|
|
n = zkey.domainSize - i*elementsPerChunk;
|
|
|
|
}
|
|
|
|
if (n==0) continue;
|
|
|
|
|
|
|
|
const task = [];
|
|
|
|
|
|
|
|
task.push({cmd: "ALLOCSET", var: 0, buff: coeffs.slice(cutPoints[i], cutPoints[i+1])});
|
|
|
|
task.push({cmd: "ALLOCSET", var: 1, buff: witness.slice()});
|
|
|
|
task.push({cmd: "ALLOC", var: 2, len: n*curve.Fr.n8});
|
|
|
|
task.push({cmd: "ALLOC", var: 3, len: n*curve.Fr.n8});
|
|
|
|
task.push({cmd: "ALLOC", var: 4, len: n*curve.Fr.n8});
|
|
|
|
task.push({cmd: "CALL", fnName: "qap_buildABC", params:[
|
|
|
|
{var: 0},
|
|
|
|
{val: (cutPoints[i+1] - cutPoints[i])/sCoef},
|
|
|
|
{var: 1},
|
|
|
|
{var: 2},
|
|
|
|
{var: 3},
|
|
|
|
{var: 4},
|
|
|
|
{val: i*elementsPerChunk},
|
|
|
|
{val: n}
|
|
|
|
]});
|
|
|
|
task.push({cmd: "GET", out: 0, var: 2, len: n*curve.Fr.n8});
|
|
|
|
task.push({cmd: "GET", out: 1, var: 3, len: n*curve.Fr.n8});
|
|
|
|
task.push({cmd: "GET", out: 2, var: 4, len: n*curve.Fr.n8});
|
|
|
|
promises.push(curve.tm.queueAction(task));
|
|
|
|
}
|
|
|
|
|
|
|
|
const result = await Promise.all(promises);
|
|
|
|
|
|
|
|
const outBuffA = new Uint8Array(zkey.domainSize * curve.Fr.n8);
|
|
|
|
const outBuffB = new Uint8Array(zkey.domainSize * curve.Fr.n8);
|
|
|
|
const outBuffC = new Uint8Array(zkey.domainSize * curve.Fr.n8);
|
|
|
|
let p=0;
|
|
|
|
for (let i=0; i<result.length; i++) {
|
|
|
|
outBuffA.set(result[i][0], p);
|
|
|
|
outBuffB.set(result[i][1], p);
|
|
|
|
outBuffC.set(result[i][2], p);
|
|
|
|
p += result[i][0].byteLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
return [outBuffA, outBuffB, outBuffC];
|
|
|
|
|
|
|
|
function getCutPoint(v) {
|
|
|
|
let m = 0;
|
|
|
|
let n = coeffsDV.getUint32(0, true);
|
|
|
|
while (m < n) {
|
|
|
|
var k = (n + m) >> 1;
|
|
|
|
const va = coeffsDV.getUint32(4 + k*sCoef + 4, true);
|
|
|
|
if (va > v) {
|
|
|
|
n = k - 1;
|
|
|
|
} else if (va < v) {
|
|
|
|
m = k + 1;
|
|
|
|
} else {
|
|
|
|
n = k;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 4 + m*sCoef;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function joinABC(curve, zkey, a, b, c) {
|
|
|
|
const concurrency = curve.tm.concurrency;
|
|
|
|
|
|
|
|
const n8 = curve.Fr.n8;
|
|
|
|
const nElements = Math.floor(a.byteLength / curve.Fr.n8);
|
|
|
|
const elementsPerChunk = Math.floor(nElements/concurrency);
|
|
|
|
|
|
|
|
const promises = [];
|
|
|
|
|
|
|
|
for (let i=0; i<concurrency; i++) {
|
|
|
|
let n;
|
|
|
|
if (i< concurrency-1) {
|
|
|
|
n = elementsPerChunk;
|
|
|
|
} else {
|
|
|
|
n = nElements - i*elementsPerChunk;
|
|
|
|
}
|
|
|
|
if (n==0) continue;
|
|
|
|
|
|
|
|
const task = [];
|
|
|
|
|
|
|
|
const aChunk = a.slice(i*elementsPerChunk*n8, (i*elementsPerChunk + n)*n8 );
|
|
|
|
const bChunk = b.slice(i*elementsPerChunk*n8, (i*elementsPerChunk + n)*n8 );
|
|
|
|
const cChunk = c.slice(i*elementsPerChunk*n8, (i*elementsPerChunk + n)*n8 );
|
|
|
|
|
|
|
|
task.push({cmd: "ALLOCSET", var: 0, buff: aChunk});
|
|
|
|
task.push({cmd: "ALLOCSET", var: 1, buff: bChunk});
|
|
|
|
task.push({cmd: "ALLOCSET", var: 2, buff: cChunk});
|
|
|
|
task.push({cmd: "ALLOC", var: 3, len: n*n8});
|
|
|
|
task.push({cmd: "CALL", fnName: "qap_joinABC", params:[
|
|
|
|
{var: 0},
|
|
|
|
{var: 1},
|
|
|
|
{var: 2},
|
|
|
|
{val: n},
|
|
|
|
{var: 3},
|
|
|
|
]});
|
|
|
|
task.push({cmd: "CALL", fnName: "frm_batchFromMontgomery", params:[
|
|
|
|
{var: 3},
|
|
|
|
{val: n},
|
|
|
|
{var: 3}
|
|
|
|
]});
|
|
|
|
task.push({cmd: "GET", out: 0, var: 3, len: n*n8});
|
|
|
|
promises.push(curve.tm.queueAction(task));
|
|
|
|
}
|
|
|
|
|
|
|
|
const result = await Promise.all(promises);
|
|
|
|
|
|
|
|
const outBuff = new Uint8Array(a.byteLength);
|
|
|
|
let p=0;
|
|
|
|
for (let i=0; i<result.length; i++) {
|
|
|
|
outBuff.set(result[i][0], p);
|
|
|
|
p += result[i][0].byteLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
return outBuff;
|
|
|
|
}
|
|
|
|
|
|
|
|
var fnvPlus = createCommonjsModule(function (module) {
|
|
|
|
/**
|
|
|
|
* FNV-1a Hash implementation (32, 64, 128, 256, 512, and 1024 bit)
|
|
|
|
* @author Travis Webb <me@traviswebb.com>
|
|
|
|
* @see http://tools.ietf.org/html/draft-eastlake-fnv-06
|
|
|
|
*/
|
|
|
|
var fnvplus = (function(){
|
|
|
|
var i, hl = [], hl16 = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'],
|
|
|
|
version = '1a',
|
|
|
|
useUTF8 = false,
|
|
|
|
_hash32, _hash52, _hash64, _hash128, _hash256, _hash512, _hash1024,
|
|
|
|
referenceSeed = 'chongo <Landon Curt Noll> /\\../\\',
|
|
|
|
defaultKeyspace = 52,
|
|
|
|
fnvConstants = {
|
|
|
|
32: {offset: 0},
|
|
|
|
64: {offset: [0,0,0,0]},
|
|
|
|
128: {offset: [0,0,0,0,0,0,0,0]},
|
|
|
|
256: {offset: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},
|
|
|
|
512: {offset: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},
|
|
|
|
1024: {offset: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}};
|
|
|
|
|
|
|
|
for(i=0; i < 256; i++){
|
|
|
|
hl[i] = ((i >> 4) & 15).toString(16) + (i & 15).toString(16);
|
|
|
|
}
|
|
|
|
|
|
|
|
function hexToBase(hex, base){
|
|
|
|
var alphabet = '0123456789abcdefghijklmnopqrstuvwxyz',
|
|
|
|
digits = [0], carry, i, j, string = '';
|
|
|
|
|
|
|
|
for(i = 0; i < hex.length; i+=2){
|
|
|
|
carry = parseInt(hex.substr(i,2),16);
|
|
|
|
for(j = 0; j < digits.length; j++){
|
|
|
|
carry += digits[j] << 8;
|
|
|
|
digits[j] = carry % base;
|
|
|
|
carry = (carry / base) | 0;
|
|
|
|
}
|
|
|
|
while (carry > 0) {
|
|
|
|
digits.push(carry % base);
|
|
|
|
carry = (carry / base) | 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = digits.length - 1; i >= 0; --i){
|
|
|
|
string += alphabet[digits[i]];
|
|
|
|
}
|
|
|
|
|
|
|
|
return string;
|
|
|
|
}
|
|
|
|
|
|
|
|
function hashValHex(value, keyspace) {
|
|
|
|
return {
|
|
|
|
bits: keyspace,
|
|
|
|
value: value,
|
|
|
|
dec: function(){return hexToBase(value, 10);},
|
|
|
|
hex: function(){return value;},
|
|
|
|
str: function(){return hexToBase(value, 36);}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function hashValInt32(value, keyspace) {
|
|
|
|
return {
|
|
|
|
bits: keyspace,
|
|
|
|
value: value,
|
|
|
|
dec: function(){return value.toString();},
|
|
|
|
hex: function(){return hl[value>>>24]+ hl[(value>>>16)&255]+hl[(value>>>8)&255]+hl[value&255];},
|
|
|
|
str: function(){return value.toString(36);}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function hashValInt52(value, keyspace) {
|
|
|
|
return {
|
|
|
|
bits: keyspace,
|
|
|
|
value: value,
|
|
|
|
dec: function(){return value.toString();},
|
|
|
|
hex: function(){return ('0000000000000000'+value.toString(16)).substr(-13);},
|
|
|
|
str: function(){return value.toString(36);}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function hash(message, keyspace) {
|
|
|
|
var str = (typeof message === 'object') ? JSON.stringify(message) : message;
|
|
|
|
|
|
|
|
switch(keyspace || defaultKeyspace){
|
|
|
|
case 32:
|
|
|
|
return _hash32(str);
|
|
|
|
case 64:
|
|
|
|
return _hash64(str);
|
|
|
|
case 128:
|
|
|
|
return _hash128(str);
|
|
|
|
case 256:
|
|
|
|
return _hash256(str);
|
|
|
|
case 512:
|
|
|
|
return _hash512(str);
|
|
|
|
case 1024:
|
|
|
|
return _hash1024(str);
|
|
|
|
default:
|
|
|
|
return _hash52(str);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function setKeyspace(keyspace) {
|
|
|
|
if (keyspace === 52 || fnvConstants[keyspace]) {
|
|
|
|
defaultKeyspace = keyspace;
|
|
|
|
} else {
|
|
|
|
throw new Error('Supported FNV keyspacs: 32, 52, 64, 128, 256, 512, and 1024 bit');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function setVersion(_version) {
|
|
|
|
if (_version === '1a' ) {
|
|
|
|
version = _version;
|
|
|
|
_hash32 = useUTF8 ? _hash32_1a_utf : _hash32_1a;
|
|
|
|
_hash52 = useUTF8 ? _hash52_1a_utf : _hash52_1a;
|
|
|
|
_hash64 = useUTF8 ? _hash64_1a_utf : _hash64_1a;
|
|
|
|
_hash128 = useUTF8 ? _hash128_1a_utf : _hash128_1a;
|
|
|
|
_hash256 = useUTF8 ? _hash256_1a_utf : _hash256_1a;
|
|
|
|
_hash512 = useUTF8 ? _hash512_1a_utf : _hash512_1a;
|
|
|
|
_hash1024 = useUTF8 ? _hash1024_1a_utf : _hash1024_1a;
|
|
|
|
} else if (_version === '1') {
|
|
|
|
version = _version;
|
|
|
|
_hash32 = useUTF8 ? _hash32_1_utf : _hash32_1;
|
|
|
|
_hash52 = useUTF8 ? _hash52_1_utf : _hash52_1;
|
|
|
|
_hash64 = useUTF8 ? _hash64_1_utf : _hash64_1;
|
|
|
|
_hash128 = useUTF8 ? _hash128_1_utf : _hash128_1;
|
|
|
|
_hash256 = useUTF8 ? _hash256_1_utf : _hash256_1;
|
|
|
|
_hash512 = useUTF8 ? _hash512_1_utf : _hash512_1;
|
|
|
|
_hash1024 = useUTF8 ? _hash1024_1_utf : _hash1024_1;
|
|
|
|
} else {
|
|
|
|
throw new Error('Supported FNV versions: 1, 1a');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function setUTF8(utf8) {
|
|
|
|
if (utf8) {
|
|
|
|
useUTF8 = true;
|
|
|
|
_hash32 = version == '1a' ? _hash32_1a_utf : _hash32_1_utf;
|
|
|
|
_hash52 = version == '1a' ? _hash52_1a_utf : _hash52_1_utf;
|
|
|
|
_hash64 = version == '1a' ? _hash64_1a_utf : _hash64_1_utf;
|
|
|
|
_hash128 = version == '1a' ? _hash128_1a_utf : _hash128_1_utf;
|
|
|
|
_hash256 = version == '1a' ? _hash256_1a_utf : _hash256_1_utf;
|
|
|
|
_hash512 = version == '1a' ? _hash512_1a_utf : _hash512_1_utf;
|
|
|
|
_hash1024 = version == '1a' ? _hash1024_1a_utf : _hash1024_1_utf;
|
|
|
|
} else {
|
|
|
|
useUTF8 = false;
|
|
|
|
_hash32 = version == '1a' ? _hash32_1a : _hash32_1;
|
|
|
|
_hash52 = version == '1a' ? _hash52_1a : _hash52_1;
|
|
|
|
_hash64 = version == '1a' ? _hash64_1a : _hash64_1;
|
|
|
|
_hash128 = version == '1a' ? _hash128_1a : _hash128_1;
|
|
|
|
_hash256 = version == '1a' ? _hash256_1a : _hash256_1;
|
|
|
|
_hash512 = version == '1a' ? _hash512_1a : _hash512_1;
|
|
|
|
_hash1024 = version == '1a' ? _hash1024_1a : _hash1024_1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function seed(seed) {
|
|
|
|
var oldVersion = version, res, i;
|
|
|
|
|
|
|
|
seed = (seed || seed === 0) ? seed : referenceSeed;
|
|
|
|
|
|
|
|
if (seed === referenceSeed) setVersion('1');
|
|
|
|
|
|
|
|
for (var keysize in fnvConstants) {
|
|
|
|
fnvConstants[keysize].offset = [];
|
|
|
|
for(i = 0; i < keysize / 16; i++){
|
|
|
|
fnvConstants[keysize].offset[i] = 0;
|
|
|
|
}
|
|
|
|
res = hash(seed, parseInt(keysize, 10)).hex();
|
|
|
|
for(i = 0; i < keysize / 16; i++){
|
|
|
|
fnvConstants[keysize].offset[i] = parseInt(res.substr(i*4,4), 16);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
setVersion(oldVersion);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Implementation without library overhead.
|
|
|
|
*/
|
|
|
|
|
|
|
|
function _hash32_1a_fast(str) {
|
|
|
|
var i, l = str.length-3, t0=0,v0=0x9dc5,t1=0,v1=0x811c;
|
|
|
|
|
|
|
|
for (i = 0; i < l;) {
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
while(i<l+3){
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return ((v1<<16)>>>0)+v0;
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash32_1a_fast_hex(str) {
|
|
|
|
var i, l = str.length-3, t0=0,v0=0x9dc5,t1=0,v1=0x811c;
|
|
|
|
|
|
|
|
for (i = 0; i < l;) {
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
while(i<l+3){
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return hl[(v1>>>8)&255]+hl[v1&255]+hl[(v0>>>8)&255]+hl[v0&255];
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash52_1a_fast(str){
|
|
|
|
var i,l=str.length-3,t0=0,v0=0x2325,t1=0,v1=0x8422,t2=0,v2=0x9ce4,t3=0,v3=0xcbf2;
|
|
|
|
|
|
|
|
for (i = 0; i < l;) {
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
while(i<l+3){
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (v3&15) * 281474976710656 + v2 * 4294967296 + v1 * 65536 + (v0^(v3>>4));
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash52_1a_fast_hex(str){
|
|
|
|
var i,l=str.length-3,t0=0,v0=0x2325,t1=0,v1=0x8422,t2=0,v2=0x9ce4,t3=0,v3=0xcbf2;
|
|
|
|
|
|
|
|
for (i = 0; i < l;) {
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
while(i<l+3){
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hl16[v3&15]+hl[v2>>8]+hl[v2&255]+hl[v1>>8]+hl[v1&255]+hl[(v0>>8)^(v3>>12)]+hl[(v0^(v3>>4))&255];
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash64_1a_fast(str){
|
|
|
|
var i,l=str.length-3,t0=0,v0=0x2325,t1=0,v1=0x8422,t2=0,v2=0x9ce4,t3=0,v3=0xcbf2;
|
|
|
|
|
|
|
|
for (i = 0; i < l;) {
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
while(i<l+3){
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hl[v3>>8]+hl[v3&255]+hl[v2>>8]+hl[v2&255]+hl[v1>>8]+hl[v1&255]+hl[v0>>8]+hl[v0&255];
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash32_1a_fast_utf(str) {
|
|
|
|
var c,i,l=str.length,t0=0,v0=0x9dc5,t1=0,v1=0x811c;
|
|
|
|
|
|
|
|
for (i = 0; i < l; i++) {
|
|
|
|
c = str.charCodeAt(i);
|
|
|
|
if(c < 128){
|
|
|
|
v0^=c;
|
|
|
|
}else if(c < 2048){
|
|
|
|
v0^=(c>>6)|192;
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else if(((c&64512)==55296)&&(i+1)<l&&((str.charCodeAt(i+1)&64512)==56320)){
|
|
|
|
c=65536+((c&1023)<<10)+(str.charCodeAt(++i)&1023);
|
|
|
|
v0^=(c>>18)|240;
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=((c>>12)&63)|128;
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else {
|
|
|
|
v0^=(c>>12)|224;
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ((v1<<16)>>>0)+v0;
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash32_1a_fast_hex_utf(str) {
|
|
|
|
var c,i,l=str.length,t0=0,v0=0x9dc5,t1=0,v1=0x811c;
|
|
|
|
|
|
|
|
for (i = 0; i < l; i++) {
|
|
|
|
c = str.charCodeAt(i);
|
|
|
|
if(c < 128){
|
|
|
|
v0^=c;
|
|
|
|
}else if(c < 2048){
|
|
|
|
v0^=(c>>6)|192;
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else if(((c&64512)==55296)&&(i+1)<l&&((str.charCodeAt(i+1)&64512)==56320)){
|
|
|
|
c=65536+((c&1023)<<10)+(str.charCodeAt(++i)&1023);
|
|
|
|
v0^=(c>>18)|240;
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=((c>>12)&63)|128;
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else {
|
|
|
|
v0^=(c>>12)|224;
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return hl[(v1>>>8)&255]+hl[v1&255]+hl[(v0>>>8)&255]+hl[v0&255];
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash52_1a_fast_utf(str){
|
|
|
|
var c,i,l=str.length,t0=0,v0=0x2325,t1=0,v1=0x8422,t2=0,v2=0x9ce4,t3=0,v3=0xcbf2;
|
|
|
|
|
|
|
|
for (i = 0; i < l; i++) {
|
|
|
|
c = str.charCodeAt(i);
|
|
|
|
if(c < 128){
|
|
|
|
v0^=c;
|
|
|
|
}else if(c < 2048){
|
|
|
|
v0^=(c>>6)|192;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else if(((c&64512)==55296)&&(i+1)<l&&((str.charCodeAt(i+1)&64512)==56320)){
|
|
|
|
c=65536+((c&1023)<<10)+(str.charCodeAt(++i)&1023);
|
|
|
|
v0^=(c>>18)|240;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=((c>>12)&63)|128;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else {
|
|
|
|
v0^=(c>>12)|224;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (v3&15) * 281474976710656 + v2 * 4294967296 + v1 * 65536 + (v0^(v3>>4));
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash52_1a_fast_hex_utf (str){
|
|
|
|
var c,i,l=str.length,t0=0,v0=0x2325,t1=0,v1=0x8422,t2=0,v2=0x9ce4,t3=0,v3=0xcbf2;
|
|
|
|
|
|
|
|
for (i = 0; i < l; i++) {
|
|
|
|
c = str.charCodeAt(i);
|
|
|
|
if(c < 128){
|
|
|
|
v0^=c;
|
|
|
|
}else if(c < 2048){
|
|
|
|
v0^=(c>>6)|192;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else if(((c&64512)==55296)&&(i+1)<l&&((str.charCodeAt(i+1)&64512)==56320)){
|
|
|
|
c=65536+((c&1023)<<10)+(str.charCodeAt(++i)&1023);
|
|
|
|
v0^=(c>>18)|240;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=((c>>12)&63)|128;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else {
|
|
|
|
v0^=(c>>12)|224;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hl16[v3&15]+hl[v2>>8]+hl[v2&255]+hl[v1>>8]+hl[v1&255]+hl[(v0>>8)^(v3>>12)]+hl[(v0^(v3>>4))&255];
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash64_1a_fast_utf(str){
|
|
|
|
var c,i,l=str.length,t0=0,v0=0x2325,t1=0,v1=0x8422,t2=0,v2=0x9ce4,t3=0,v3=0xcbf2;
|
|
|
|
|
|
|
|
for (i = 0; i < l; i++) {
|
|
|
|
c = str.charCodeAt(i);
|
|
|
|
if(c < 128){
|
|
|
|
v0^=c;
|
|
|
|
}else if(c < 2048){
|
|
|
|
v0^=(c>>6)|192;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else if(((c&64512)==55296)&&(i+1)<l&&((str.charCodeAt(i+1)&64512)==56320)){
|
|
|
|
c=65536+((c&1023)<<10)+(str.charCodeAt(++i)&1023);
|
|
|
|
v0^=(c>>18)|240;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=((c>>12)&63)|128;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else {
|
|
|
|
v0^=(c>>12)|224;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hl[v3>>8]+hl[v3&255]+hl[v2>>8]+hl[v2&255]+hl[v1>>8]+hl[v1&255]+hl[v0>>8]+hl[v0&255];
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Regular functions. This versions are accessible through API
|
|
|
|
*/
|
|
|
|
|
|
|
|
function _hash32_1a(str){
|
|
|
|
var i,l=str.length-3,s=fnvConstants[32].offset,t0=0,v0=s[1]|0,t1=0,v1=s[0]|0;
|
|
|
|
|
|
|
|
for (i = 0; i < l;) {
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
while(i<l+3){
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hashValInt32(((v1<<16)>>>0)+v0,32);
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash32_1(str){
|
|
|
|
var i,l=str.length-3,s=fnvConstants[32].offset,t0=0,v0=s[1]|0,t1=0,v1=s[0]|0;
|
|
|
|
|
|
|
|
for (i = 0; i < l;) {
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
}
|
|
|
|
|
|
|
|
while(i<l+3){
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
}
|
|
|
|
|
|
|
|
return hashValInt32(((v1<<16)>>>0)+v0,32);
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash32_1a_utf(str){
|
|
|
|
var c,i,l=str.length,s=fnvConstants[32].offset,t0=0,v0=s[1]|0,t1=0,v1=s[0]|0;
|
|
|
|
|
|
|
|
for (i = 0; i < l; i++) {
|
|
|
|
c = str.charCodeAt(i);
|
|
|
|
if(c < 128){
|
|
|
|
v0^=c;
|
|
|
|
}else if(c < 2048){
|
|
|
|
v0^=(c>>6)|192;
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else if(((c&64512)==55296)&&(i+1)<l&&((str.charCodeAt(i+1)&64512)==56320)){
|
|
|
|
c=65536+((c&1023)<<10)+(str.charCodeAt(++i)&1023);
|
|
|
|
v0^=(c>>18)|240;
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=((c>>12)&63)|128;
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else {
|
|
|
|
v0^=(c>>12)|224;
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hashValInt32(((v1<<16)>>>0)+v0,32);
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash32_1_utf(str){
|
|
|
|
var c,i,l=str.length,s=fnvConstants[32].offset,t0=0,v0=s[1]|0,t1=0,v1=s[0]|0;
|
|
|
|
|
|
|
|
for (i = 0; i < l; i++) {
|
|
|
|
c = str.charCodeAt(i);
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
if(c < 128){
|
|
|
|
v0^=c;
|
|
|
|
}else if(c < 2048){
|
|
|
|
v0^=(c>>6)|192;
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else if(((c&64512)==55296)&&(i+1)<l&&((str.charCodeAt(i+1)&64512)==56320)){
|
|
|
|
c=65536+((c&1023)<<10)+(str.charCodeAt(++i)&1023);
|
|
|
|
v0^=(c>>18)|240;
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=((c>>12)&63)|128;
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else {
|
|
|
|
v0^=(c>>12)|224;
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*403;t1=v1*403;
|
|
|
|
t1+=v0<<8;
|
|
|
|
v1=(t1+(t0>>>16))&65535;v0=t0&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return hashValInt32(((v1<<16)>>>0)+v0,32);
|
|
|
|
}
|
|
|
|
|
|
|
|
_hash32 = _hash32_1a;
|
|
|
|
|
|
|
|
function _hash52_1a(str){
|
|
|
|
var i,l=str.length-3,s=fnvConstants[64].offset,t0=0,v0=s[3]|0,t1=0,v1=s[2]|0,t2=0,v2=s[1]|0,t3=0,v3=s[0]|0;
|
|
|
|
|
|
|
|
for (i = 0; i < l;) {
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
while(i<l+3){
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hashValInt52((v3&15)*281474976710656+v2*4294967296+v1*65536+(v0^(v3>>4)),52);
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash52_1(str){
|
|
|
|
var i,l=str.length-3,s=fnvConstants[64].offset,t0=0,v0=s[3]|0,t1=0,v1=s[2]|0,t2=0,v2=s[1]|0,t3=0,v3=s[0]|0;
|
|
|
|
|
|
|
|
for (i = 0; i < l;) {
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
}
|
|
|
|
|
|
|
|
while(i<l+3){
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
}
|
|
|
|
|
|
|
|
return hashValInt52((v3&15)*281474976710656+v2*4294967296+v1*65536+(v0^(v3>>4)),52);
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash52_1a_utf(str){
|
|
|
|
var c,i,l=str.length,s=fnvConstants[64].offset,t0=0,v0=s[3]|0,t1=0,v1=s[2]|0,t2=0,v2=s[1]|0,t3=0,v3=s[0]|0;
|
|
|
|
|
|
|
|
for (i = 0; i < l; i++) {
|
|
|
|
c = str.charCodeAt(i);
|
|
|
|
if(c < 128){
|
|
|
|
v0^=c;
|
|
|
|
}else if(c < 2048){
|
|
|
|
v0^=(c>>6)|192;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else if(((c&64512)==55296)&&(i+1)<l&&((str.charCodeAt(i+1)&64512)==56320)){
|
|
|
|
c=65536+((c&1023)<<10)+(str.charCodeAt(++i)&1023);
|
|
|
|
v0^=(c>>18)|240;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=((c>>12)&63)|128;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else {
|
|
|
|
v0^=(c>>12)|224;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hashValInt52((v3&15)*281474976710656+v2*4294967296+v1*65536+(v0^(v3>>4)),52);
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash52_1_utf(str){
|
|
|
|
var c,i,l=str.length,s=fnvConstants[64].offset,t0=0,v0=s[3]|0,t1=0,v1=s[2]|0,t2=0,v2=s[1]|0,t3=0,v3=s[0]|0;
|
|
|
|
|
|
|
|
for (i = 0; i < l; i++) {
|
|
|
|
c = str.charCodeAt(i);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
if(c < 128){
|
|
|
|
v0^=c;
|
|
|
|
}else if(c < 2048){
|
|
|
|
v0^=(c>>6)|192;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else if(((c&64512)==55296)&&(i+1)<l&&((str.charCodeAt(i+1)&64512)==56320)){
|
|
|
|
c=65536+((c&1023)<<10)+(str.charCodeAt(++i)&1023);
|
|
|
|
v0^=(c>>18)|240;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=((c>>12)&63)|128;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else {
|
|
|
|
v0^=(c>>12)|224;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return hashValInt52((v3&15)*281474976710656+v2*4294967296+v1*65536+(v0^(v3>>4)),52);
|
|
|
|
}
|
|
|
|
|
|
|
|
_hash52 = _hash52_1a;
|
|
|
|
|
|
|
|
function _hash64_1a(str){
|
|
|
|
var i,l=str.length-3,s=fnvConstants[64].offset,t0=0,v0=s[3]|0,t1=0,v1=s[2]|0,t2=0,v2=s[1]|0,t3=0,v3=s[0]|0;
|
|
|
|
|
|
|
|
for (i = 0; i < l;) {
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
while(i<l+3){
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hashValHex(hl[v3>>8]+hl[v3&255]+hl[v2>>8]+hl[v2&255]+hl[v1>>8]+hl[v1&255]+hl[v0>>8]+hl[v0&255],64);
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash64_1(str){
|
|
|
|
var i,l=str.length-3,s=fnvConstants[64].offset,t0=0,v0=s[3]|0,t1=0,v1=s[2]|0,t2=0,v2=s[1]|0,t3=0,v3=s[0]|0;
|
|
|
|
|
|
|
|
for (i = 0; i < l;) {
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
}
|
|
|
|
|
|
|
|
while(i<l+3){
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
}
|
|
|
|
|
|
|
|
return hashValHex(hl[v3>>8]+hl[v3&255]+hl[v2>>8]+hl[v2&255]+hl[v1>>8]+hl[v1&255]+hl[v0>>8]+hl[v0&255],64);
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash64_1a_utf(str){
|
|
|
|
var c,i,l=str.length,s=fnvConstants[64].offset,t0=0,v0=s[3]|0,t1=0,v1=s[2]|0,t2=0,v2=s[1]|0,t3=0,v3=s[0]|0;
|
|
|
|
|
|
|
|
for (i = 0; i < l; i++) {
|
|
|
|
c = str.charCodeAt(i);
|
|
|
|
if(c < 128){
|
|
|
|
v0^=c;
|
|
|
|
}else if(c < 2048){
|
|
|
|
v0^=(c>>6)|192;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else if(((c&64512)==55296)&&(i+1)<l&&((str.charCodeAt(i+1)&64512)==56320)){
|
|
|
|
c=65536+((c&1023)<<10)+(str.charCodeAt(++i)&1023);
|
|
|
|
v0^=(c>>18)|240;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=((c>>12)&63)|128;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else {
|
|
|
|
v0^=(c>>12)|224;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hashValHex(hl[v3>>8]+hl[v3&255]+hl[v2>>8]+hl[v2&255]+hl[v1>>8]+hl[v1&255]+hl[v0>>8]+hl[v0&255],64);
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash64_1_utf(str){
|
|
|
|
var c,i,l=str.length,s=fnvConstants[64].offset,t0=0,v0=s[3]|0,t1=0,v1=s[2]|0,t2=0,v2=s[1]|0,t3=0,v3=s[0]|0;
|
|
|
|
|
|
|
|
for (i = 0; i < l; i++) {
|
|
|
|
c = str.charCodeAt(i);
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
if(c < 128){
|
|
|
|
v0^=c;
|
|
|
|
}else if(c < 2048){
|
|
|
|
v0^=(c>>6)|192;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else if(((c&64512)==55296)&&(i+1)<l&&((str.charCodeAt(i+1)&64512)==56320)){
|
|
|
|
c=65536+((c&1023)<<10)+(str.charCodeAt(++i)&1023);
|
|
|
|
v0^=(c>>18)|240;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=((c>>12)&63)|128;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else {
|
|
|
|
v0^=(c>>12)|224;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*435;t1=v1*435;t2=v2*435;t3=v3*435;
|
|
|
|
t2+=v0<<8;t3+=v1<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;v3=(t3+(t2>>>16))&65535;v2=t2&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return hashValHex(hl[v3>>8]+hl[v3&255]+hl[v2>>8]+hl[v2&255]+hl[v1>>8]+hl[v1&255]+hl[v0>>8]+hl[v0&255],64);
|
|
|
|
}
|
|
|
|
|
|
|
|
_hash64 = _hash64_1a;
|
|
|
|
|
|
|
|
function _hash128_1a(str){
|
|
|
|
var i,l=str.length-3,s=fnvConstants[128].offset,t0=0,v0=s[7]|0,t1=0,v1=s[6]|0,t2=0,v2=s[5]|0,t3=0,v3=s[4]|0,t4=0,v4=s[3]|0,t5=0,v5=s[2]|0,t6=0,v6=s[1]|0,t7=0,v7=s[0]|0;
|
|
|
|
|
|
|
|
for (i = 0; i < l;) {
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*315;t1=v1*315;t2=v2*315;t3=v3*315;t4=v4*315;t5=v5*315;t6=v6*315;t7=v7*315;
|
|
|
|
t5+=v0<<8;t6+=v1<<8;t7+=v2<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;v7=(t7+(t6>>>16))&65535;v6=t6&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*315;t1=v1*315;t2=v2*315;t3=v3*315;t4=v4*315;t5=v5*315;t6=v6*315;t7=v7*315;
|
|
|
|
t5+=v0<<8;t6+=v1<<8;t7+=v2<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;v7=(t7+(t6>>>16))&65535;v6=t6&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*315;t1=v1*315;t2=v2*315;t3=v3*315;t4=v4*315;t5=v5*315;t6=v6*315;t7=v7*315;
|
|
|
|
t5+=v0<<8;t6+=v1<<8;t7+=v2<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;v7=(t7+(t6>>>16))&65535;v6=t6&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*315;t1=v1*315;t2=v2*315;t3=v3*315;t4=v4*315;t5=v5*315;t6=v6*315;t7=v7*315;
|
|
|
|
t5+=v0<<8;t6+=v1<<8;t7+=v2<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;v7=(t7+(t6>>>16))&65535;v6=t6&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
while(i<l+3){
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*315;t1=v1*315;t2=v2*315;t3=v3*315;t4=v4*315;t5=v5*315;t6=v6*315;t7=v7*315;
|
|
|
|
t5+=v0<<8;t6+=v1<<8;t7+=v2<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;v7=(t7+(t6>>>16))&65535;v6=t6&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hashValHex(hl[v7>>8]+hl[v7&255]+hl[v6>>8]+hl[v6&255]+hl[v5>>8]+hl[v5&255]+hl[v4>>8]+hl[v4&255]+hl[v3>>8]+hl[v3&255]+hl[v2>>8]+hl[v2&255]+hl[v1>>8]+hl[v1&255]+hl[v0>>8]+hl[v0&255],128);
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash128_1(str){
|
|
|
|
var i,l=str.length-3,s=fnvConstants[128].offset,t0=0,v0=s[7]|0,t1=0,v1=s[6]|0,t2=0,v2=s[5]|0,t3=0,v3=s[4]|0,t4=0,v4=s[3]|0,t5=0,v5=s[2]|0,t6=0,v6=s[1]|0,t7=0,v7=s[0]|0;
|
|
|
|
|
|
|
|
for (i = 0; i < l;) {
|
|
|
|
t0=v0*315;t1=v1*315;t2=v2*315;t3=v3*315;t4=v4*315;t5=v5*315;t6=v6*315;t7=v7*315;
|
|
|
|
t5+=v0<<8;t6+=v1<<8;t7+=v2<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;v7=(t7+(t6>>>16))&65535;v6=t6&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*315;t1=v1*315;t2=v2*315;t3=v3*315;t4=v4*315;t5=v5*315;t6=v6*315;t7=v7*315;
|
|
|
|
t5+=v0<<8;t6+=v1<<8;t7+=v2<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;v7=(t7+(t6>>>16))&65535;v6=t6&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*315;t1=v1*315;t2=v2*315;t3=v3*315;t4=v4*315;t5=v5*315;t6=v6*315;t7=v7*315;
|
|
|
|
t5+=v0<<8;t6+=v1<<8;t7+=v2<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;v7=(t7+(t6>>>16))&65535;v6=t6&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*315;t1=v1*315;t2=v2*315;t3=v3*315;t4=v4*315;t5=v5*315;t6=v6*315;t7=v7*315;
|
|
|
|
t5+=v0<<8;t6+=v1<<8;t7+=v2<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;v7=(t7+(t6>>>16))&65535;v6=t6&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
}
|
|
|
|
|
|
|
|
while(i<l+3){
|
|
|
|
t0=v0*315;t1=v1*315;t2=v2*315;t3=v3*315;t4=v4*315;t5=v5*315;t6=v6*315;t7=v7*315;
|
|
|
|
t5+=v0<<8;t6+=v1<<8;t7+=v2<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;v7=(t7+(t6>>>16))&65535;v6=t6&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
}
|
|
|
|
|
|
|
|
return hashValHex(hl[v7>>8]+hl[v7&255]+hl[v6>>8]+hl[v6&255]+hl[v5>>8]+hl[v5&255]+hl[v4>>8]+hl[v4&255]+hl[v3>>8]+hl[v3&255]+hl[v2>>8]+hl[v2&255]+hl[v1>>8]+hl[v1&255]+hl[v0>>8]+hl[v0&255],128);
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash128_1a_utf(str){
|
|
|
|
var c,i,l=str.length,s=fnvConstants[128].offset,t0=0,v0=s[7]|0,t1=0,v1=s[6]|0,t2=0,v2=s[5]|0,t3=0,v3=s[4]|0,t4=0,v4=s[3]|0,t5=0,v5=s[2]|0,t6=0,v6=s[1]|0,t7=0,v7=s[0]|0;
|
|
|
|
|
|
|
|
for (i = 0; i < l; i++) {
|
|
|
|
c = str.charCodeAt(i);
|
|
|
|
if(c < 128){
|
|
|
|
v0^=c;
|
|
|
|
}else if(c < 2048){
|
|
|
|
v0^=(c>>6)|192;
|
|
|
|
t0=v0*315;t1=v1*315;t2=v2*315;t3=v3*315;t4=v4*315;t5=v5*315;t6=v6*315;t7=v7*315;
|
|
|
|
t5+=v0<<8;t6+=v1<<8;t7+=v2<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;v7=(t7+(t6>>>16))&65535;v6=t6&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else if(((c&64512)==55296)&&(i+1)<l&&((str.charCodeAt(i+1)&64512)==56320)){
|
|
|
|
c=65536+((c&1023)<<10)+(str.charCodeAt(++i)&1023);
|
|
|
|
v0^=(c>>18)|240;
|
|
|
|
t0=v0*315;t1=v1*315;t2=v2*315;t3=v3*315;t4=v4*315;t5=v5*315;t6=v6*315;t7=v7*315;
|
|
|
|
t5+=v0<<8;t6+=v1<<8;t7+=v2<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;v7=(t7+(t6>>>16))&65535;v6=t6&65535;
|
|
|
|
v0^=((c>>12)&63)|128;
|
|
|
|
t0=v0*315;t1=v1*315;t2=v2*315;t3=v3*315;t4=v4*315;t5=v5*315;t6=v6*315;t7=v7*315;
|
|
|
|
t5+=v0<<8;t6+=v1<<8;t7+=v2<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;v7=(t7+(t6>>>16))&65535;v6=t6&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*315;t1=v1*315;t2=v2*315;t3=v3*315;t4=v4*315;t5=v5*315;t6=v6*315;t7=v7*315;
|
|
|
|
t5+=v0<<8;t6+=v1<<8;t7+=v2<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;v7=(t7+(t6>>>16))&65535;v6=t6&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else {
|
|
|
|
v0^=(c>>12)|224;
|
|
|
|
t0=v0*315;t1=v1*315;t2=v2*315;t3=v3*315;t4=v4*315;t5=v5*315;t6=v6*315;t7=v7*315;
|
|
|
|
t5+=v0<<8;t6+=v1<<8;t7+=v2<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;v7=(t7+(t6>>>16))&65535;v6=t6&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*315;t1=v1*315;t2=v2*315;t3=v3*315;t4=v4*315;t5=v5*315;t6=v6*315;t7=v7*315;
|
|
|
|
t5+=v0<<8;t6+=v1<<8;t7+=v2<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;v7=(t7+(t6>>>16))&65535;v6=t6&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}
|
|
|
|
t0=v0*315;t1=v1*315;t2=v2*315;t3=v3*315;t4=v4*315;t5=v5*315;t6=v6*315;t7=v7*315;
|
|
|
|
t5+=v0<<8;t6+=v1<<8;t7+=v2<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;v7=(t7+(t6>>>16))&65535;v6=t6&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hashValHex(hl[v7>>8]+hl[v7&255]+hl[v6>>8]+hl[v6&255]+hl[v5>>8]+hl[v5&255]+hl[v4>>8]+hl[v4&255]+hl[v3>>8]+hl[v3&255]+hl[v2>>8]+hl[v2&255]+hl[v1>>8]+hl[v1&255]+hl[v0>>8]+hl[v0&255],128);
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash128_1_utf(str){
|
|
|
|
var c,i,l=str.length,s=fnvConstants[128].offset,t0=0,v0=s[7]|0,t1=0,v1=s[6]|0,t2=0,v2=s[5]|0,t3=0,v3=s[4]|0,t4=0,v4=s[3]|0,t5=0,v5=s[2]|0,t6=0,v6=s[1]|0,t7=0,v7=s[0]|0;
|
|
|
|
|
|
|
|
for (i = 0; i < l; i++) {
|
|
|
|
c = str.charCodeAt(i);
|
|
|
|
t0=v0*315;t1=v1*315;t2=v2*315;t3=v3*315;t4=v4*315;t5=v5*315;t6=v6*315;t7=v7*315;
|
|
|
|
t5+=v0<<8;t6+=v1<<8;t7+=v2<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;v7=(t7+(t6>>>16))&65535;v6=t6&65535;
|
|
|
|
if(c < 128){
|
|
|
|
v0^=c;
|
|
|
|
}else if(c < 2048){
|
|
|
|
v0^=(c>>6)|192;
|
|
|
|
t0=v0*315;t1=v1*315;t2=v2*315;t3=v3*315;t4=v4*315;t5=v5*315;t6=v6*315;t7=v7*315;
|
|
|
|
t5+=v0<<8;t6+=v1<<8;t7+=v2<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;v7=(t7+(t6>>>16))&65535;v6=t6&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else if(((c&64512)==55296)&&(i+1)<l&&((str.charCodeAt(i+1)&64512)==56320)){
|
|
|
|
c=65536+((c&1023)<<10)+(str.charCodeAt(++i)&1023);
|
|
|
|
v0^=(c>>18)|240;
|
|
|
|
t0=v0*315;t1=v1*315;t2=v2*315;t3=v3*315;t4=v4*315;t5=v5*315;t6=v6*315;t7=v7*315;
|
|
|
|
t5+=v0<<8;t6+=v1<<8;t7+=v2<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;v7=(t7+(t6>>>16))&65535;v6=t6&65535;
|
|
|
|
v0^=((c>>12)&63)|128;
|
|
|
|
t0=v0*315;t1=v1*315;t2=v2*315;t3=v3*315;t4=v4*315;t5=v5*315;t6=v6*315;t7=v7*315;
|
|
|
|
t5+=v0<<8;t6+=v1<<8;t7+=v2<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;v7=(t7+(t6>>>16))&65535;v6=t6&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*315;t1=v1*315;t2=v2*315;t3=v3*315;t4=v4*315;t5=v5*315;t6=v6*315;t7=v7*315;
|
|
|
|
t5+=v0<<8;t6+=v1<<8;t7+=v2<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;v7=(t7+(t6>>>16))&65535;v6=t6&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else {
|
|
|
|
v0^=(c>>12)|224;
|
|
|
|
t0=v0*315;t1=v1*315;t2=v2*315;t3=v3*315;t4=v4*315;t5=v5*315;t6=v6*315;t7=v7*315;
|
|
|
|
t5+=v0<<8;t6+=v1<<8;t7+=v2<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;v7=(t7+(t6>>>16))&65535;v6=t6&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*315;t1=v1*315;t2=v2*315;t3=v3*315;t4=v4*315;t5=v5*315;t6=v6*315;t7=v7*315;
|
|
|
|
t5+=v0<<8;t6+=v1<<8;t7+=v2<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;v7=(t7+(t6>>>16))&65535;v6=t6&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return hashValHex(hl[v7>>8]+hl[v7&255]+hl[v6>>8]+hl[v6&255]+hl[v5>>8]+hl[v5&255]+hl[v4>>8]+hl[v4&255]+hl[v3>>8]+hl[v3&255]+hl[v2>>8]+hl[v2&255]+hl[v1>>8]+hl[v1&255]+hl[v0>>8]+hl[v0&255],128);
|
|
|
|
}
|
|
|
|
|
|
|
|
_hash128 = _hash128_1a;
|
|
|
|
|
|
|
|
function _hash256_1a(str){
|
|
|
|
var i,l=str.length-3,s=fnvConstants[256].offset,t0=0,v0=s[15]|0,t1=0,v1=s[14]|0,t2=0,v2=s[13]|0,t3=0,v3=s[12]|0,t4=0,v4=s[11]|0,t5=0,v5=s[10]|0,t6=0,v6=s[9]|0,t7=0,v7=s[8]|0,t8=0,v8=s[7]|0,t9=0,v9=s[6]|0,t10=0,v10=s[5]|0,t11=0,v11=s[4]|0,t12=0,v12=s[3]|0,t13=0,v13=s[2]|0,t14=0,v14=s[1]|0,t15=0,v15=s[0]|0;
|
|
|
|
|
|
|
|
for (i = 0; i < l;) {
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*355;t1=v1*355;t2=v2*355;t3=v3*355;t4=v4*355;t5=v5*355;t6=v6*355;t7=v7*355;t8=v8*355;t9=v9*355;t10=v10*355;t11=v11*355;t12=v12*355;t13=v13*355;t14=v14*355;t15=v15*355;
|
|
|
|
t10+=v0<<8;t11+=v1<<8;t12+=v2<<8;t13+=v3<<8;t14+=v4<<8;t15+=v5<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;v15=(t15+(t14>>>16))&65535;v14=t14&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*355;t1=v1*355;t2=v2*355;t3=v3*355;t4=v4*355;t5=v5*355;t6=v6*355;t7=v7*355;t8=v8*355;t9=v9*355;t10=v10*355;t11=v11*355;t12=v12*355;t13=v13*355;t14=v14*355;t15=v15*355;
|
|
|
|
t10+=v0<<8;t11+=v1<<8;t12+=v2<<8;t13+=v3<<8;t14+=v4<<8;t15+=v5<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;v15=(t15+(t14>>>16))&65535;v14=t14&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*355;t1=v1*355;t2=v2*355;t3=v3*355;t4=v4*355;t5=v5*355;t6=v6*355;t7=v7*355;t8=v8*355;t9=v9*355;t10=v10*355;t11=v11*355;t12=v12*355;t13=v13*355;t14=v14*355;t15=v15*355;
|
|
|
|
t10+=v0<<8;t11+=v1<<8;t12+=v2<<8;t13+=v3<<8;t14+=v4<<8;t15+=v5<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;v15=(t15+(t14>>>16))&65535;v14=t14&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*355;t1=v1*355;t2=v2*355;t3=v3*355;t4=v4*355;t5=v5*355;t6=v6*355;t7=v7*355;t8=v8*355;t9=v9*355;t10=v10*355;t11=v11*355;t12=v12*355;t13=v13*355;t14=v14*355;t15=v15*355;
|
|
|
|
t10+=v0<<8;t11+=v1<<8;t12+=v2<<8;t13+=v3<<8;t14+=v4<<8;t15+=v5<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;v15=(t15+(t14>>>16))&65535;v14=t14&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
while(i<l+3){
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*355;t1=v1*355;t2=v2*355;t3=v3*355;t4=v4*355;t5=v5*355;t6=v6*355;t7=v7*355;t8=v8*355;t9=v9*355;t10=v10*355;t11=v11*355;t12=v12*355;t13=v13*355;t14=v14*355;t15=v15*355;
|
|
|
|
t10+=v0<<8;t11+=v1<<8;t12+=v2<<8;t13+=v3<<8;t14+=v4<<8;t15+=v5<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;v15=(t15+(t14>>>16))&65535;v14=t14&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hashValHex(hl[v15>>8]+hl[v15&255]+hl[v14>>8]+hl[v14&255]+hl[v13>>8]+hl[v13&255]+hl[v12>>8]+hl[v12&255]+hl[v11>>8]+hl[v11&255]+hl[v10>>8]+hl[v10&255]+hl[v9>>8]+hl[v9&255]+hl[v8>>8]+hl[v8&255]+hl[v7>>8]+hl[v7&255]+hl[v6>>8]+hl[v6&255]+hl[v5>>8]+hl[v5&255]+hl[v4>>8]+hl[v4&255]+hl[v3>>8]+hl[v3&255]+hl[v2>>8]+hl[v2&255]+hl[v1>>8]+hl[v1&255]+hl[v0>>8]+hl[v0&255],256);
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash256_1(str){
|
|
|
|
var i,l=str.length-3,s=fnvConstants[256].offset,t0=0,v0=s[15]|0,t1=0,v1=s[14]|0,t2=0,v2=s[13]|0,t3=0,v3=s[12]|0,t4=0,v4=s[11]|0,t5=0,v5=s[10]|0,t6=0,v6=s[9]|0,t7=0,v7=s[8]|0,t8=0,v8=s[7]|0,t9=0,v9=s[6]|0,t10=0,v10=s[5]|0,t11=0,v11=s[4]|0,t12=0,v12=s[3]|0,t13=0,v13=s[2]|0,t14=0,v14=s[1]|0,t15=0,v15=s[0]|0;
|
|
|
|
|
|
|
|
for (i = 0; i < l;) {
|
|
|
|
t0=v0*355;t1=v1*355;t2=v2*355;t3=v3*355;t4=v4*355;t5=v5*355;t6=v6*355;t7=v7*355;t8=v8*355;t9=v9*355;t10=v10*355;t11=v11*355;t12=v12*355;t13=v13*355;t14=v14*355;t15=v15*355;
|
|
|
|
t10+=v0<<8;t11+=v1<<8;t12+=v2<<8;t13+=v3<<8;t14+=v4<<8;t15+=v5<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;v15=(t15+(t14>>>16))&65535;v14=t14&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*355;t1=v1*355;t2=v2*355;t3=v3*355;t4=v4*355;t5=v5*355;t6=v6*355;t7=v7*355;t8=v8*355;t9=v9*355;t10=v10*355;t11=v11*355;t12=v12*355;t13=v13*355;t14=v14*355;t15=v15*355;
|
|
|
|
t10+=v0<<8;t11+=v1<<8;t12+=v2<<8;t13+=v3<<8;t14+=v4<<8;t15+=v5<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;v15=(t15+(t14>>>16))&65535;v14=t14&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*355;t1=v1*355;t2=v2*355;t3=v3*355;t4=v4*355;t5=v5*355;t6=v6*355;t7=v7*355;t8=v8*355;t9=v9*355;t10=v10*355;t11=v11*355;t12=v12*355;t13=v13*355;t14=v14*355;t15=v15*355;
|
|
|
|
t10+=v0<<8;t11+=v1<<8;t12+=v2<<8;t13+=v3<<8;t14+=v4<<8;t15+=v5<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;v15=(t15+(t14>>>16))&65535;v14=t14&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*355;t1=v1*355;t2=v2*355;t3=v3*355;t4=v4*355;t5=v5*355;t6=v6*355;t7=v7*355;t8=v8*355;t9=v9*355;t10=v10*355;t11=v11*355;t12=v12*355;t13=v13*355;t14=v14*355;t15=v15*355;
|
|
|
|
t10+=v0<<8;t11+=v1<<8;t12+=v2<<8;t13+=v3<<8;t14+=v4<<8;t15+=v5<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;v15=(t15+(t14>>>16))&65535;v14=t14&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
}
|
|
|
|
|
|
|
|
while(i<l+3){
|
|
|
|
t0=v0*355;t1=v1*355;t2=v2*355;t3=v3*355;t4=v4*355;t5=v5*355;t6=v6*355;t7=v7*355;t8=v8*355;t9=v9*355;t10=v10*355;t11=v11*355;t12=v12*355;t13=v13*355;t14=v14*355;t15=v15*355;
|
|
|
|
t10+=v0<<8;t11+=v1<<8;t12+=v2<<8;t13+=v3<<8;t14+=v4<<8;t15+=v5<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;v15=(t15+(t14>>>16))&65535;v14=t14&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
}
|
|
|
|
|
|
|
|
return hashValHex(hl[v15>>8]+hl[v15&255]+hl[v14>>8]+hl[v14&255]+hl[v13>>8]+hl[v13&255]+hl[v12>>8]+hl[v12&255]+hl[v11>>8]+hl[v11&255]+hl[v10>>8]+hl[v10&255]+hl[v9>>8]+hl[v9&255]+hl[v8>>8]+hl[v8&255]+hl[v7>>8]+hl[v7&255]+hl[v6>>8]+hl[v6&255]+hl[v5>>8]+hl[v5&255]+hl[v4>>8]+hl[v4&255]+hl[v3>>8]+hl[v3&255]+hl[v2>>8]+hl[v2&255]+hl[v1>>8]+hl[v1&255]+hl[v0>>8]+hl[v0&255],256);
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash256_1a_utf(str){
|
|
|
|
var c,i,l=str.length,s=fnvConstants[256].offset,t0=0,v0=s[15]|0,t1=0,v1=s[14]|0,t2=0,v2=s[13]|0,t3=0,v3=s[12]|0,t4=0,v4=s[11]|0,t5=0,v5=s[10]|0,t6=0,v6=s[9]|0,t7=0,v7=s[8]|0,t8=0,v8=s[7]|0,t9=0,v9=s[6]|0,t10=0,v10=s[5]|0,t11=0,v11=s[4]|0,t12=0,v12=s[3]|0,t13=0,v13=s[2]|0,t14=0,v14=s[1]|0,t15=0,v15=s[0]|0;
|
|
|
|
|
|
|
|
for (i = 0; i < l; i++) {
|
|
|
|
c = str.charCodeAt(i);
|
|
|
|
if(c < 128){
|
|
|
|
v0^=c;
|
|
|
|
}else if(c < 2048){
|
|
|
|
v0^=(c>>6)|192;
|
|
|
|
t0=v0*355;t1=v1*355;t2=v2*355;t3=v3*355;t4=v4*355;t5=v5*355;t6=v6*355;t7=v7*355;t8=v8*355;t9=v9*355;t10=v10*355;t11=v11*355;t12=v12*355;t13=v13*355;t14=v14*355;t15=v15*355;
|
|
|
|
t10+=v0<<8;t11+=v1<<8;t12+=v2<<8;t13+=v3<<8;t14+=v4<<8;t15+=v5<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;v15=(t15+(t14>>>16))&65535;v14=t14&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else if(((c&64512)==55296)&&(i+1)<l&&((str.charCodeAt(i+1)&64512)==56320)){
|
|
|
|
c=65536+((c&1023)<<10)+(str.charCodeAt(++i)&1023);
|
|
|
|
v0^=(c>>18)|240;
|
|
|
|
t0=v0*355;t1=v1*355;t2=v2*355;t3=v3*355;t4=v4*355;t5=v5*355;t6=v6*355;t7=v7*355;t8=v8*355;t9=v9*355;t10=v10*355;t11=v11*355;t12=v12*355;t13=v13*355;t14=v14*355;t15=v15*355;
|
|
|
|
t10+=v0<<8;t11+=v1<<8;t12+=v2<<8;t13+=v3<<8;t14+=v4<<8;t15+=v5<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;v15=(t15+(t14>>>16))&65535;v14=t14&65535;
|
|
|
|
v0^=((c>>12)&63)|128;
|
|
|
|
t0=v0*355;t1=v1*355;t2=v2*355;t3=v3*355;t4=v4*355;t5=v5*355;t6=v6*355;t7=v7*355;t8=v8*355;t9=v9*355;t10=v10*355;t11=v11*355;t12=v12*355;t13=v13*355;t14=v14*355;t15=v15*355;
|
|
|
|
t10+=v0<<8;t11+=v1<<8;t12+=v2<<8;t13+=v3<<8;t14+=v4<<8;t15+=v5<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;v15=(t15+(t14>>>16))&65535;v14=t14&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*355;t1=v1*355;t2=v2*355;t3=v3*355;t4=v4*355;t5=v5*355;t6=v6*355;t7=v7*355;t8=v8*355;t9=v9*355;t10=v10*355;t11=v11*355;t12=v12*355;t13=v13*355;t14=v14*355;t15=v15*355;
|
|
|
|
t10+=v0<<8;t11+=v1<<8;t12+=v2<<8;t13+=v3<<8;t14+=v4<<8;t15+=v5<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;v15=(t15+(t14>>>16))&65535;v14=t14&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else {
|
|
|
|
v0^=(c>>12)|224;
|
|
|
|
t0=v0*355;t1=v1*355;t2=v2*355;t3=v3*355;t4=v4*355;t5=v5*355;t6=v6*355;t7=v7*355;t8=v8*355;t9=v9*355;t10=v10*355;t11=v11*355;t12=v12*355;t13=v13*355;t14=v14*355;t15=v15*355;
|
|
|
|
t10+=v0<<8;t11+=v1<<8;t12+=v2<<8;t13+=v3<<8;t14+=v4<<8;t15+=v5<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;v15=(t15+(t14>>>16))&65535;v14=t14&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*355;t1=v1*355;t2=v2*355;t3=v3*355;t4=v4*355;t5=v5*355;t6=v6*355;t7=v7*355;t8=v8*355;t9=v9*355;t10=v10*355;t11=v11*355;t12=v12*355;t13=v13*355;t14=v14*355;t15=v15*355;
|
|
|
|
t10+=v0<<8;t11+=v1<<8;t12+=v2<<8;t13+=v3<<8;t14+=v4<<8;t15+=v5<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;v15=(t15+(t14>>>16))&65535;v14=t14&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}
|
|
|
|
t0=v0*355;t1=v1*355;t2=v2*355;t3=v3*355;t4=v4*355;t5=v5*355;t6=v6*355;t7=v7*355;t8=v8*355;t9=v9*355;t10=v10*355;t11=v11*355;t12=v12*355;t13=v13*355;t14=v14*355;t15=v15*355;
|
|
|
|
t10+=v0<<8;t11+=v1<<8;t12+=v2<<8;t13+=v3<<8;t14+=v4<<8;t15+=v5<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;v15=(t15+(t14>>>16))&65535;v14=t14&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hashValHex(hl[v15>>8]+hl[v15&255]+hl[v14>>8]+hl[v14&255]+hl[v13>>8]+hl[v13&255]+hl[v12>>8]+hl[v12&255]+hl[v11>>8]+hl[v11&255]+hl[v10>>8]+hl[v10&255]+hl[v9>>8]+hl[v9&255]+hl[v8>>8]+hl[v8&255]+hl[v7>>8]+hl[v7&255]+hl[v6>>8]+hl[v6&255]+hl[v5>>8]+hl[v5&255]+hl[v4>>8]+hl[v4&255]+hl[v3>>8]+hl[v3&255]+hl[v2>>8]+hl[v2&255]+hl[v1>>8]+hl[v1&255]+hl[v0>>8]+hl[v0&255],256);
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash256_1_utf(str){
|
|
|
|
var c,i,l=str.length,s=fnvConstants[256].offset,t0=0,v0=s[15]|0,t1=0,v1=s[14]|0,t2=0,v2=s[13]|0,t3=0,v3=s[12]|0,t4=0,v4=s[11]|0,t5=0,v5=s[10]|0,t6=0,v6=s[9]|0,t7=0,v7=s[8]|0,t8=0,v8=s[7]|0,t9=0,v9=s[6]|0,t10=0,v10=s[5]|0,t11=0,v11=s[4]|0,t12=0,v12=s[3]|0,t13=0,v13=s[2]|0,t14=0,v14=s[1]|0,t15=0,v15=s[0]|0;
|
|
|
|
|
|
|
|
for (i = 0; i < l; i++) {
|
|
|
|
c = str.charCodeAt(i);
|
|
|
|
t0=v0*355;t1=v1*355;t2=v2*355;t3=v3*355;t4=v4*355;t5=v5*355;t6=v6*355;t7=v7*355;t8=v8*355;t9=v9*355;t10=v10*355;t11=v11*355;t12=v12*355;t13=v13*355;t14=v14*355;t15=v15*355;
|
|
|
|
t10+=v0<<8;t11+=v1<<8;t12+=v2<<8;t13+=v3<<8;t14+=v4<<8;t15+=v5<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;v15=(t15+(t14>>>16))&65535;v14=t14&65535;
|
|
|
|
if(c < 128){
|
|
|
|
v0^=c;
|
|
|
|
}else if(c < 2048){
|
|
|
|
v0^=(c>>6)|192;
|
|
|
|
t0=v0*355;t1=v1*355;t2=v2*355;t3=v3*355;t4=v4*355;t5=v5*355;t6=v6*355;t7=v7*355;t8=v8*355;t9=v9*355;t10=v10*355;t11=v11*355;t12=v12*355;t13=v13*355;t14=v14*355;t15=v15*355;
|
|
|
|
t10+=v0<<8;t11+=v1<<8;t12+=v2<<8;t13+=v3<<8;t14+=v4<<8;t15+=v5<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;v15=(t15+(t14>>>16))&65535;v14=t14&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else if(((c&64512)==55296)&&(i+1)<l&&((str.charCodeAt(i+1)&64512)==56320)){
|
|
|
|
c=65536+((c&1023)<<10)+(str.charCodeAt(++i)&1023);
|
|
|
|
v0^=(c>>18)|240;
|
|
|
|
t0=v0*355;t1=v1*355;t2=v2*355;t3=v3*355;t4=v4*355;t5=v5*355;t6=v6*355;t7=v7*355;t8=v8*355;t9=v9*355;t10=v10*355;t11=v11*355;t12=v12*355;t13=v13*355;t14=v14*355;t15=v15*355;
|
|
|
|
t10+=v0<<8;t11+=v1<<8;t12+=v2<<8;t13+=v3<<8;t14+=v4<<8;t15+=v5<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;v15=(t15+(t14>>>16))&65535;v14=t14&65535;
|
|
|
|
v0^=((c>>12)&63)|128;
|
|
|
|
t0=v0*355;t1=v1*355;t2=v2*355;t3=v3*355;t4=v4*355;t5=v5*355;t6=v6*355;t7=v7*355;t8=v8*355;t9=v9*355;t10=v10*355;t11=v11*355;t12=v12*355;t13=v13*355;t14=v14*355;t15=v15*355;
|
|
|
|
t10+=v0<<8;t11+=v1<<8;t12+=v2<<8;t13+=v3<<8;t14+=v4<<8;t15+=v5<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;v15=(t15+(t14>>>16))&65535;v14=t14&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*355;t1=v1*355;t2=v2*355;t3=v3*355;t4=v4*355;t5=v5*355;t6=v6*355;t7=v7*355;t8=v8*355;t9=v9*355;t10=v10*355;t11=v11*355;t12=v12*355;t13=v13*355;t14=v14*355;t15=v15*355;
|
|
|
|
t10+=v0<<8;t11+=v1<<8;t12+=v2<<8;t13+=v3<<8;t14+=v4<<8;t15+=v5<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;v15=(t15+(t14>>>16))&65535;v14=t14&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else {
|
|
|
|
v0^=(c>>12)|224;
|
|
|
|
t0=v0*355;t1=v1*355;t2=v2*355;t3=v3*355;t4=v4*355;t5=v5*355;t6=v6*355;t7=v7*355;t8=v8*355;t9=v9*355;t10=v10*355;t11=v11*355;t12=v12*355;t13=v13*355;t14=v14*355;t15=v15*355;
|
|
|
|
t10+=v0<<8;t11+=v1<<8;t12+=v2<<8;t13+=v3<<8;t14+=v4<<8;t15+=v5<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;v15=(t15+(t14>>>16))&65535;v14=t14&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*355;t1=v1*355;t2=v2*355;t3=v3*355;t4=v4*355;t5=v5*355;t6=v6*355;t7=v7*355;t8=v8*355;t9=v9*355;t10=v10*355;t11=v11*355;t12=v12*355;t13=v13*355;t14=v14*355;t15=v15*355;
|
|
|
|
t10+=v0<<8;t11+=v1<<8;t12+=v2<<8;t13+=v3<<8;t14+=v4<<8;t15+=v5<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;v15=(t15+(t14>>>16))&65535;v14=t14&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return hashValHex(hl[v15>>8]+hl[v15&255]+hl[v14>>8]+hl[v14&255]+hl[v13>>8]+hl[v13&255]+hl[v12>>8]+hl[v12&255]+hl[v11>>8]+hl[v11&255]+hl[v10>>8]+hl[v10&255]+hl[v9>>8]+hl[v9&255]+hl[v8>>8]+hl[v8&255]+hl[v7>>8]+hl[v7&255]+hl[v6>>8]+hl[v6&255]+hl[v5>>8]+hl[v5&255]+hl[v4>>8]+hl[v4&255]+hl[v3>>8]+hl[v3&255]+hl[v2>>8]+hl[v2&255]+hl[v1>>8]+hl[v1&255]+hl[v0>>8]+hl[v0&255],256);
|
|
|
|
}
|
|
|
|
|
|
|
|
_hash256 = _hash256_1a;
|
|
|
|
|
|
|
|
function _hash512_1a(str){
|
|
|
|
var i,l=str.length-3,s=fnvConstants[512].offset,t0=0,v0=s[31]|0,t1=0,v1=s[30]|0,t2=0,v2=s[29]|0,t3=0,v3=s[28]|0,t4=0,v4=s[27]|0,t5=0,v5=s[26]|0,t6=0,v6=s[25]|0,t7=0,v7=s[24]|0,t8=0,v8=s[23]|0,t9=0,v9=s[22]|0,t10=0,v10=s[21]|0,t11=0,v11=s[20]|0,t12=0,v12=s[19]|0,t13=0,v13=s[18]|0,t14=0,v14=s[17]|0,t15=0,v15=s[16]|0,t16=0,v16=s[15]|0,t17=0,v17=s[14]|0,t18=0,v18=s[13]|0,t19=0,v19=s[12]|0,t20=0,v20=s[11]|0,t21=0,v21=s[10]|0,t22=0,v22=s[9]|0,t23=0,v23=s[8]|0,t24=0,v24=s[7]|0,t25=0,v25=s[6]|0,t26=0,v26=s[5]|0,t27=0,v27=s[4]|0,t28=0,v28=s[3]|0,t29=0,v29=s[2]|0,t30=0,v30=s[1]|0,t31=0,v31=s[0]|0;
|
|
|
|
|
|
|
|
for (i = 0; i < l;) {
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*343;t1=v1*343;t2=v2*343;t3=v3*343;t4=v4*343;t5=v5*343;t6=v6*343;t7=v7*343;t8=v8*343;t9=v9*343;t10=v10*343;t11=v11*343;t12=v12*343;t13=v13*343;t14=v14*343;t15=v15*343;t16=v16*343;t17=v17*343;t18=v18*343;t19=v19*343;t20=v20*343;t21=v21*343;t22=v22*343;t23=v23*343;t24=v24*343;t25=v25*343;t26=v26*343;t27=v27*343;t28=v28*343;t29=v29*343;t30=v30*343;t31=v31*343;
|
|
|
|
t21+=v0<<8;t22+=v1<<8;t23+=v2<<8;t24+=v3<<8;t25+=v4<<8;t26+=v5<<8;t27+=v6<<8;t28+=v7<<8;t29+=v8<<8;t30+=v9<<8;t31+=v10<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;v31=(t31+(t30>>>16))&65535;v30=t30&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*343;t1=v1*343;t2=v2*343;t3=v3*343;t4=v4*343;t5=v5*343;t6=v6*343;t7=v7*343;t8=v8*343;t9=v9*343;t10=v10*343;t11=v11*343;t12=v12*343;t13=v13*343;t14=v14*343;t15=v15*343;t16=v16*343;t17=v17*343;t18=v18*343;t19=v19*343;t20=v20*343;t21=v21*343;t22=v22*343;t23=v23*343;t24=v24*343;t25=v25*343;t26=v26*343;t27=v27*343;t28=v28*343;t29=v29*343;t30=v30*343;t31=v31*343;
|
|
|
|
t21+=v0<<8;t22+=v1<<8;t23+=v2<<8;t24+=v3<<8;t25+=v4<<8;t26+=v5<<8;t27+=v6<<8;t28+=v7<<8;t29+=v8<<8;t30+=v9<<8;t31+=v10<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;v31=(t31+(t30>>>16))&65535;v30=t30&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*343;t1=v1*343;t2=v2*343;t3=v3*343;t4=v4*343;t5=v5*343;t6=v6*343;t7=v7*343;t8=v8*343;t9=v9*343;t10=v10*343;t11=v11*343;t12=v12*343;t13=v13*343;t14=v14*343;t15=v15*343;t16=v16*343;t17=v17*343;t18=v18*343;t19=v19*343;t20=v20*343;t21=v21*343;t22=v22*343;t23=v23*343;t24=v24*343;t25=v25*343;t26=v26*343;t27=v27*343;t28=v28*343;t29=v29*343;t30=v30*343;t31=v31*343;
|
|
|
|
t21+=v0<<8;t22+=v1<<8;t23+=v2<<8;t24+=v3<<8;t25+=v4<<8;t26+=v5<<8;t27+=v6<<8;t28+=v7<<8;t29+=v8<<8;t30+=v9<<8;t31+=v10<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;v31=(t31+(t30>>>16))&65535;v30=t30&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*343;t1=v1*343;t2=v2*343;t3=v3*343;t4=v4*343;t5=v5*343;t6=v6*343;t7=v7*343;t8=v8*343;t9=v9*343;t10=v10*343;t11=v11*343;t12=v12*343;t13=v13*343;t14=v14*343;t15=v15*343;t16=v16*343;t17=v17*343;t18=v18*343;t19=v19*343;t20=v20*343;t21=v21*343;t22=v22*343;t23=v23*343;t24=v24*343;t25=v25*343;t26=v26*343;t27=v27*343;t28=v28*343;t29=v29*343;t30=v30*343;t31=v31*343;
|
|
|
|
t21+=v0<<8;t22+=v1<<8;t23+=v2<<8;t24+=v3<<8;t25+=v4<<8;t26+=v5<<8;t27+=v6<<8;t28+=v7<<8;t29+=v8<<8;t30+=v9<<8;t31+=v10<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;v31=(t31+(t30>>>16))&65535;v30=t30&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
while(i<l+3){
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*343;t1=v1*343;t2=v2*343;t3=v3*343;t4=v4*343;t5=v5*343;t6=v6*343;t7=v7*343;t8=v8*343;t9=v9*343;t10=v10*343;t11=v11*343;t12=v12*343;t13=v13*343;t14=v14*343;t15=v15*343;t16=v16*343;t17=v17*343;t18=v18*343;t19=v19*343;t20=v20*343;t21=v21*343;t22=v22*343;t23=v23*343;t24=v24*343;t25=v25*343;t26=v26*343;t27=v27*343;t28=v28*343;t29=v29*343;t30=v30*343;t31=v31*343;
|
|
|
|
t21+=v0<<8;t22+=v1<<8;t23+=v2<<8;t24+=v3<<8;t25+=v4<<8;t26+=v5<<8;t27+=v6<<8;t28+=v7<<8;t29+=v8<<8;t30+=v9<<8;t31+=v10<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;v31=(t31+(t30>>>16))&65535;v30=t30&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hashValHex(hl[v31>>8]+hl[v31&255]+hl[v30>>8]+hl[v30&255]+hl[v29>>8]+hl[v29&255]+hl[v28>>8]+hl[v28&255]+hl[v27>>8]+hl[v27&255]+hl[v26>>8]+hl[v26&255]+hl[v25>>8]+hl[v25&255]+hl[v24>>8]+hl[v24&255]+hl[v23>>8]+hl[v23&255]+hl[v22>>8]+hl[v22&255]+hl[v21>>8]+hl[v21&255]+hl[v20>>8]+hl[v20&255]+hl[v19>>8]+hl[v19&255]+hl[v18>>8]+hl[v18&255]+hl[v17>>8]+hl[v17&255]+hl[v16>>8]+hl[v16&255]+hl[v15>>8]+hl[v15&255]+hl[v14>>8]+hl[v14&255]+hl[v13>>8]+hl[v13&255]+hl[v12>>8]+hl[v12&255]+hl[v11>>8]+hl[v11&255]+hl[v10>>8]+hl[v10&255]+hl[v9>>8]+hl[v9&255]+hl[v8>>8]+hl[v8&255]+hl[v7>>8]+hl[v7&255]+hl[v6>>8]+hl[v6&255]+hl[v5>>8]+hl[v5&255]+hl[v4>>8]+hl[v4&255]+hl[v3>>8]+hl[v3&255]+hl[v2>>8]+hl[v2&255]+hl[v1>>8]+hl[v1&255]+hl[v0>>8]+hl[v0&255],512);
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash512_1(str){
|
|
|
|
var i,l=str.length-3,s=fnvConstants[512].offset,t0=0,v0=s[31]|0,t1=0,v1=s[30]|0,t2=0,v2=s[29]|0,t3=0,v3=s[28]|0,t4=0,v4=s[27]|0,t5=0,v5=s[26]|0,t6=0,v6=s[25]|0,t7=0,v7=s[24]|0,t8=0,v8=s[23]|0,t9=0,v9=s[22]|0,t10=0,v10=s[21]|0,t11=0,v11=s[20]|0,t12=0,v12=s[19]|0,t13=0,v13=s[18]|0,t14=0,v14=s[17]|0,t15=0,v15=s[16]|0,t16=0,v16=s[15]|0,t17=0,v17=s[14]|0,t18=0,v18=s[13]|0,t19=0,v19=s[12]|0,t20=0,v20=s[11]|0,t21=0,v21=s[10]|0,t22=0,v22=s[9]|0,t23=0,v23=s[8]|0,t24=0,v24=s[7]|0,t25=0,v25=s[6]|0,t26=0,v26=s[5]|0,t27=0,v27=s[4]|0,t28=0,v28=s[3]|0,t29=0,v29=s[2]|0,t30=0,v30=s[1]|0,t31=0,v31=s[0]|0;
|
|
|
|
|
|
|
|
for (i = 0; i < l;) {
|
|
|
|
t0=v0*343;t1=v1*343;t2=v2*343;t3=v3*343;t4=v4*343;t5=v5*343;t6=v6*343;t7=v7*343;t8=v8*343;t9=v9*343;t10=v10*343;t11=v11*343;t12=v12*343;t13=v13*343;t14=v14*343;t15=v15*343;t16=v16*343;t17=v17*343;t18=v18*343;t19=v19*343;t20=v20*343;t21=v21*343;t22=v22*343;t23=v23*343;t24=v24*343;t25=v25*343;t26=v26*343;t27=v27*343;t28=v28*343;t29=v29*343;t30=v30*343;t31=v31*343;
|
|
|
|
t21+=v0<<8;t22+=v1<<8;t23+=v2<<8;t24+=v3<<8;t25+=v4<<8;t26+=v5<<8;t27+=v6<<8;t28+=v7<<8;t29+=v8<<8;t30+=v9<<8;t31+=v10<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;v31=(t31+(t30>>>16))&65535;v30=t30&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*343;t1=v1*343;t2=v2*343;t3=v3*343;t4=v4*343;t5=v5*343;t6=v6*343;t7=v7*343;t8=v8*343;t9=v9*343;t10=v10*343;t11=v11*343;t12=v12*343;t13=v13*343;t14=v14*343;t15=v15*343;t16=v16*343;t17=v17*343;t18=v18*343;t19=v19*343;t20=v20*343;t21=v21*343;t22=v22*343;t23=v23*343;t24=v24*343;t25=v25*343;t26=v26*343;t27=v27*343;t28=v28*343;t29=v29*343;t30=v30*343;t31=v31*343;
|
|
|
|
t21+=v0<<8;t22+=v1<<8;t23+=v2<<8;t24+=v3<<8;t25+=v4<<8;t26+=v5<<8;t27+=v6<<8;t28+=v7<<8;t29+=v8<<8;t30+=v9<<8;t31+=v10<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;v31=(t31+(t30>>>16))&65535;v30=t30&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*343;t1=v1*343;t2=v2*343;t3=v3*343;t4=v4*343;t5=v5*343;t6=v6*343;t7=v7*343;t8=v8*343;t9=v9*343;t10=v10*343;t11=v11*343;t12=v12*343;t13=v13*343;t14=v14*343;t15=v15*343;t16=v16*343;t17=v17*343;t18=v18*343;t19=v19*343;t20=v20*343;t21=v21*343;t22=v22*343;t23=v23*343;t24=v24*343;t25=v25*343;t26=v26*343;t27=v27*343;t28=v28*343;t29=v29*343;t30=v30*343;t31=v31*343;
|
|
|
|
t21+=v0<<8;t22+=v1<<8;t23+=v2<<8;t24+=v3<<8;t25+=v4<<8;t26+=v5<<8;t27+=v6<<8;t28+=v7<<8;t29+=v8<<8;t30+=v9<<8;t31+=v10<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;v31=(t31+(t30>>>16))&65535;v30=t30&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*343;t1=v1*343;t2=v2*343;t3=v3*343;t4=v4*343;t5=v5*343;t6=v6*343;t7=v7*343;t8=v8*343;t9=v9*343;t10=v10*343;t11=v11*343;t12=v12*343;t13=v13*343;t14=v14*343;t15=v15*343;t16=v16*343;t17=v17*343;t18=v18*343;t19=v19*343;t20=v20*343;t21=v21*343;t22=v22*343;t23=v23*343;t24=v24*343;t25=v25*343;t26=v26*343;t27=v27*343;t28=v28*343;t29=v29*343;t30=v30*343;t31=v31*343;
|
|
|
|
t21+=v0<<8;t22+=v1<<8;t23+=v2<<8;t24+=v3<<8;t25+=v4<<8;t26+=v5<<8;t27+=v6<<8;t28+=v7<<8;t29+=v8<<8;t30+=v9<<8;t31+=v10<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;v31=(t31+(t30>>>16))&65535;v30=t30&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
}
|
|
|
|
|
|
|
|
while(i<l+3){
|
|
|
|
t0=v0*343;t1=v1*343;t2=v2*343;t3=v3*343;t4=v4*343;t5=v5*343;t6=v6*343;t7=v7*343;t8=v8*343;t9=v9*343;t10=v10*343;t11=v11*343;t12=v12*343;t13=v13*343;t14=v14*343;t15=v15*343;t16=v16*343;t17=v17*343;t18=v18*343;t19=v19*343;t20=v20*343;t21=v21*343;t22=v22*343;t23=v23*343;t24=v24*343;t25=v25*343;t26=v26*343;t27=v27*343;t28=v28*343;t29=v29*343;t30=v30*343;t31=v31*343;
|
|
|
|
t21+=v0<<8;t22+=v1<<8;t23+=v2<<8;t24+=v3<<8;t25+=v4<<8;t26+=v5<<8;t27+=v6<<8;t28+=v7<<8;t29+=v8<<8;t30+=v9<<8;t31+=v10<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;v31=(t31+(t30>>>16))&65535;v30=t30&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
}
|
|
|
|
|
|
|
|
return hashValHex(hl[v31>>8]+hl[v31&255]+hl[v30>>8]+hl[v30&255]+hl[v29>>8]+hl[v29&255]+hl[v28>>8]+hl[v28&255]+hl[v27>>8]+hl[v27&255]+hl[v26>>8]+hl[v26&255]+hl[v25>>8]+hl[v25&255]+hl[v24>>8]+hl[v24&255]+hl[v23>>8]+hl[v23&255]+hl[v22>>8]+hl[v22&255]+hl[v21>>8]+hl[v21&255]+hl[v20>>8]+hl[v20&255]+hl[v19>>8]+hl[v19&255]+hl[v18>>8]+hl[v18&255]+hl[v17>>8]+hl[v17&255]+hl[v16>>8]+hl[v16&255]+hl[v15>>8]+hl[v15&255]+hl[v14>>8]+hl[v14&255]+hl[v13>>8]+hl[v13&255]+hl[v12>>8]+hl[v12&255]+hl[v11>>8]+hl[v11&255]+hl[v10>>8]+hl[v10&255]+hl[v9>>8]+hl[v9&255]+hl[v8>>8]+hl[v8&255]+hl[v7>>8]+hl[v7&255]+hl[v6>>8]+hl[v6&255]+hl[v5>>8]+hl[v5&255]+hl[v4>>8]+hl[v4&255]+hl[v3>>8]+hl[v3&255]+hl[v2>>8]+hl[v2&255]+hl[v1>>8]+hl[v1&255]+hl[v0>>8]+hl[v0&255],512);
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash512_1a_utf(str){
|
|
|
|
var c,i,l=str.length,s=fnvConstants[512].offset,t0=0,v0=s[31]|0,t1=0,v1=s[30]|0,t2=0,v2=s[29]|0,t3=0,v3=s[28]|0,t4=0,v4=s[27]|0,t5=0,v5=s[26]|0,t6=0,v6=s[25]|0,t7=0,v7=s[24]|0,t8=0,v8=s[23]|0,t9=0,v9=s[22]|0,t10=0,v10=s[21]|0,t11=0,v11=s[20]|0,t12=0,v12=s[19]|0,t13=0,v13=s[18]|0,t14=0,v14=s[17]|0,t15=0,v15=s[16]|0,t16=0,v16=s[15]|0,t17=0,v17=s[14]|0,t18=0,v18=s[13]|0,t19=0,v19=s[12]|0,t20=0,v20=s[11]|0,t21=0,v21=s[10]|0,t22=0,v22=s[9]|0,t23=0,v23=s[8]|0,t24=0,v24=s[7]|0,t25=0,v25=s[6]|0,t26=0,v26=s[5]|0,t27=0,v27=s[4]|0,t28=0,v28=s[3]|0,t29=0,v29=s[2]|0,t30=0,v30=s[1]|0,t31=0,v31=s[0]|0;
|
|
|
|
|
|
|
|
for (i = 0; i < l; i++) {
|
|
|
|
c = str.charCodeAt(i);
|
|
|
|
if(c < 128){
|
|
|
|
v0^=c;
|
|
|
|
}else if(c < 2048){
|
|
|
|
v0^=(c>>6)|192;
|
|
|
|
t0=v0*343;t1=v1*343;t2=v2*343;t3=v3*343;t4=v4*343;t5=v5*343;t6=v6*343;t7=v7*343;t8=v8*343;t9=v9*343;t10=v10*343;t11=v11*343;t12=v12*343;t13=v13*343;t14=v14*343;t15=v15*343;t16=v16*343;t17=v17*343;t18=v18*343;t19=v19*343;t20=v20*343;t21=v21*343;t22=v22*343;t23=v23*343;t24=v24*343;t25=v25*343;t26=v26*343;t27=v27*343;t28=v28*343;t29=v29*343;t30=v30*343;t31=v31*343;
|
|
|
|
t21+=v0<<8;t22+=v1<<8;t23+=v2<<8;t24+=v3<<8;t25+=v4<<8;t26+=v5<<8;t27+=v6<<8;t28+=v7<<8;t29+=v8<<8;t30+=v9<<8;t31+=v10<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;v31=(t31+(t30>>>16))&65535;v30=t30&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else if(((c&64512)==55296)&&(i+1)<l&&((str.charCodeAt(i+1)&64512)==56320)){
|
|
|
|
c=65536+((c&1023)<<10)+(str.charCodeAt(++i)&1023);
|
|
|
|
v0^=(c>>18)|240;
|
|
|
|
t0=v0*343;t1=v1*343;t2=v2*343;t3=v3*343;t4=v4*343;t5=v5*343;t6=v6*343;t7=v7*343;t8=v8*343;t9=v9*343;t10=v10*343;t11=v11*343;t12=v12*343;t13=v13*343;t14=v14*343;t15=v15*343;t16=v16*343;t17=v17*343;t18=v18*343;t19=v19*343;t20=v20*343;t21=v21*343;t22=v22*343;t23=v23*343;t24=v24*343;t25=v25*343;t26=v26*343;t27=v27*343;t28=v28*343;t29=v29*343;t30=v30*343;t31=v31*343;
|
|
|
|
t21+=v0<<8;t22+=v1<<8;t23+=v2<<8;t24+=v3<<8;t25+=v4<<8;t26+=v5<<8;t27+=v6<<8;t28+=v7<<8;t29+=v8<<8;t30+=v9<<8;t31+=v10<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;v31=(t31+(t30>>>16))&65535;v30=t30&65535;
|
|
|
|
v0^=((c>>12)&63)|128;
|
|
|
|
t0=v0*343;t1=v1*343;t2=v2*343;t3=v3*343;t4=v4*343;t5=v5*343;t6=v6*343;t7=v7*343;t8=v8*343;t9=v9*343;t10=v10*343;t11=v11*343;t12=v12*343;t13=v13*343;t14=v14*343;t15=v15*343;t16=v16*343;t17=v17*343;t18=v18*343;t19=v19*343;t20=v20*343;t21=v21*343;t22=v22*343;t23=v23*343;t24=v24*343;t25=v25*343;t26=v26*343;t27=v27*343;t28=v28*343;t29=v29*343;t30=v30*343;t31=v31*343;
|
|
|
|
t21+=v0<<8;t22+=v1<<8;t23+=v2<<8;t24+=v3<<8;t25+=v4<<8;t26+=v5<<8;t27+=v6<<8;t28+=v7<<8;t29+=v8<<8;t30+=v9<<8;t31+=v10<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;v31=(t31+(t30>>>16))&65535;v30=t30&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*343;t1=v1*343;t2=v2*343;t3=v3*343;t4=v4*343;t5=v5*343;t6=v6*343;t7=v7*343;t8=v8*343;t9=v9*343;t10=v10*343;t11=v11*343;t12=v12*343;t13=v13*343;t14=v14*343;t15=v15*343;t16=v16*343;t17=v17*343;t18=v18*343;t19=v19*343;t20=v20*343;t21=v21*343;t22=v22*343;t23=v23*343;t24=v24*343;t25=v25*343;t26=v26*343;t27=v27*343;t28=v28*343;t29=v29*343;t30=v30*343;t31=v31*343;
|
|
|
|
t21+=v0<<8;t22+=v1<<8;t23+=v2<<8;t24+=v3<<8;t25+=v4<<8;t26+=v5<<8;t27+=v6<<8;t28+=v7<<8;t29+=v8<<8;t30+=v9<<8;t31+=v10<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;v31=(t31+(t30>>>16))&65535;v30=t30&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else {
|
|
|
|
v0^=(c>>12)|224;
|
|
|
|
t0=v0*343;t1=v1*343;t2=v2*343;t3=v3*343;t4=v4*343;t5=v5*343;t6=v6*343;t7=v7*343;t8=v8*343;t9=v9*343;t10=v10*343;t11=v11*343;t12=v12*343;t13=v13*343;t14=v14*343;t15=v15*343;t16=v16*343;t17=v17*343;t18=v18*343;t19=v19*343;t20=v20*343;t21=v21*343;t22=v22*343;t23=v23*343;t24=v24*343;t25=v25*343;t26=v26*343;t27=v27*343;t28=v28*343;t29=v29*343;t30=v30*343;t31=v31*343;
|
|
|
|
t21+=v0<<8;t22+=v1<<8;t23+=v2<<8;t24+=v3<<8;t25+=v4<<8;t26+=v5<<8;t27+=v6<<8;t28+=v7<<8;t29+=v8<<8;t30+=v9<<8;t31+=v10<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;v31=(t31+(t30>>>16))&65535;v30=t30&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*343;t1=v1*343;t2=v2*343;t3=v3*343;t4=v4*343;t5=v5*343;t6=v6*343;t7=v7*343;t8=v8*343;t9=v9*343;t10=v10*343;t11=v11*343;t12=v12*343;t13=v13*343;t14=v14*343;t15=v15*343;t16=v16*343;t17=v17*343;t18=v18*343;t19=v19*343;t20=v20*343;t21=v21*343;t22=v22*343;t23=v23*343;t24=v24*343;t25=v25*343;t26=v26*343;t27=v27*343;t28=v28*343;t29=v29*343;t30=v30*343;t31=v31*343;
|
|
|
|
t21+=v0<<8;t22+=v1<<8;t23+=v2<<8;t24+=v3<<8;t25+=v4<<8;t26+=v5<<8;t27+=v6<<8;t28+=v7<<8;t29+=v8<<8;t30+=v9<<8;t31+=v10<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;v31=(t31+(t30>>>16))&65535;v30=t30&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}
|
|
|
|
t0=v0*343;t1=v1*343;t2=v2*343;t3=v3*343;t4=v4*343;t5=v5*343;t6=v6*343;t7=v7*343;t8=v8*343;t9=v9*343;t10=v10*343;t11=v11*343;t12=v12*343;t13=v13*343;t14=v14*343;t15=v15*343;t16=v16*343;t17=v17*343;t18=v18*343;t19=v19*343;t20=v20*343;t21=v21*343;t22=v22*343;t23=v23*343;t24=v24*343;t25=v25*343;t26=v26*343;t27=v27*343;t28=v28*343;t29=v29*343;t30=v30*343;t31=v31*343;
|
|
|
|
t21+=v0<<8;t22+=v1<<8;t23+=v2<<8;t24+=v3<<8;t25+=v4<<8;t26+=v5<<8;t27+=v6<<8;t28+=v7<<8;t29+=v8<<8;t30+=v9<<8;t31+=v10<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;v31=(t31+(t30>>>16))&65535;v30=t30&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hashValHex(hl[v31>>8]+hl[v31&255]+hl[v30>>8]+hl[v30&255]+hl[v29>>8]+hl[v29&255]+hl[v28>>8]+hl[v28&255]+hl[v27>>8]+hl[v27&255]+hl[v26>>8]+hl[v26&255]+hl[v25>>8]+hl[v25&255]+hl[v24>>8]+hl[v24&255]+hl[v23>>8]+hl[v23&255]+hl[v22>>8]+hl[v22&255]+hl[v21>>8]+hl[v21&255]+hl[v20>>8]+hl[v20&255]+hl[v19>>8]+hl[v19&255]+hl[v18>>8]+hl[v18&255]+hl[v17>>8]+hl[v17&255]+hl[v16>>8]+hl[v16&255]+hl[v15>>8]+hl[v15&255]+hl[v14>>8]+hl[v14&255]+hl[v13>>8]+hl[v13&255]+hl[v12>>8]+hl[v12&255]+hl[v11>>8]+hl[v11&255]+hl[v10>>8]+hl[v10&255]+hl[v9>>8]+hl[v9&255]+hl[v8>>8]+hl[v8&255]+hl[v7>>8]+hl[v7&255]+hl[v6>>8]+hl[v6&255]+hl[v5>>8]+hl[v5&255]+hl[v4>>8]+hl[v4&255]+hl[v3>>8]+hl[v3&255]+hl[v2>>8]+hl[v2&255]+hl[v1>>8]+hl[v1&255]+hl[v0>>8]+hl[v0&255],512);
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash512_1_utf(str){
|
|
|
|
var c,i,l=str.length,s=fnvConstants[512].offset,t0=0,v0=s[31]|0,t1=0,v1=s[30]|0,t2=0,v2=s[29]|0,t3=0,v3=s[28]|0,t4=0,v4=s[27]|0,t5=0,v5=s[26]|0,t6=0,v6=s[25]|0,t7=0,v7=s[24]|0,t8=0,v8=s[23]|0,t9=0,v9=s[22]|0,t10=0,v10=s[21]|0,t11=0,v11=s[20]|0,t12=0,v12=s[19]|0,t13=0,v13=s[18]|0,t14=0,v14=s[17]|0,t15=0,v15=s[16]|0,t16=0,v16=s[15]|0,t17=0,v17=s[14]|0,t18=0,v18=s[13]|0,t19=0,v19=s[12]|0,t20=0,v20=s[11]|0,t21=0,v21=s[10]|0,t22=0,v22=s[9]|0,t23=0,v23=s[8]|0,t24=0,v24=s[7]|0,t25=0,v25=s[6]|0,t26=0,v26=s[5]|0,t27=0,v27=s[4]|0,t28=0,v28=s[3]|0,t29=0,v29=s[2]|0,t30=0,v30=s[1]|0,t31=0,v31=s[0]|0;
|
|
|
|
|
|
|
|
for (i = 0; i < l; i++) {
|
|
|
|
c = str.charCodeAt(i);
|
|
|
|
t0=v0*343;t1=v1*343;t2=v2*343;t3=v3*343;t4=v4*343;t5=v5*343;t6=v6*343;t7=v7*343;t8=v8*343;t9=v9*343;t10=v10*343;t11=v11*343;t12=v12*343;t13=v13*343;t14=v14*343;t15=v15*343;t16=v16*343;t17=v17*343;t18=v18*343;t19=v19*343;t20=v20*343;t21=v21*343;t22=v22*343;t23=v23*343;t24=v24*343;t25=v25*343;t26=v26*343;t27=v27*343;t28=v28*343;t29=v29*343;t30=v30*343;t31=v31*343;
|
|
|
|
t21+=v0<<8;t22+=v1<<8;t23+=v2<<8;t24+=v3<<8;t25+=v4<<8;t26+=v5<<8;t27+=v6<<8;t28+=v7<<8;t29+=v8<<8;t30+=v9<<8;t31+=v10<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;v31=(t31+(t30>>>16))&65535;v30=t30&65535;
|
|
|
|
if(c < 128){
|
|
|
|
v0^=c;
|
|
|
|
}else if(c < 2048){
|
|
|
|
v0^=(c>>6)|192;
|
|
|
|
t0=v0*343;t1=v1*343;t2=v2*343;t3=v3*343;t4=v4*343;t5=v5*343;t6=v6*343;t7=v7*343;t8=v8*343;t9=v9*343;t10=v10*343;t11=v11*343;t12=v12*343;t13=v13*343;t14=v14*343;t15=v15*343;t16=v16*343;t17=v17*343;t18=v18*343;t19=v19*343;t20=v20*343;t21=v21*343;t22=v22*343;t23=v23*343;t24=v24*343;t25=v25*343;t26=v26*343;t27=v27*343;t28=v28*343;t29=v29*343;t30=v30*343;t31=v31*343;
|
|
|
|
t21+=v0<<8;t22+=v1<<8;t23+=v2<<8;t24+=v3<<8;t25+=v4<<8;t26+=v5<<8;t27+=v6<<8;t28+=v7<<8;t29+=v8<<8;t30+=v9<<8;t31+=v10<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;v31=(t31+(t30>>>16))&65535;v30=t30&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else if(((c&64512)==55296)&&(i+1)<l&&((str.charCodeAt(i+1)&64512)==56320)){
|
|
|
|
c=65536+((c&1023)<<10)+(str.charCodeAt(++i)&1023);
|
|
|
|
v0^=(c>>18)|240;
|
|
|
|
t0=v0*343;t1=v1*343;t2=v2*343;t3=v3*343;t4=v4*343;t5=v5*343;t6=v6*343;t7=v7*343;t8=v8*343;t9=v9*343;t10=v10*343;t11=v11*343;t12=v12*343;t13=v13*343;t14=v14*343;t15=v15*343;t16=v16*343;t17=v17*343;t18=v18*343;t19=v19*343;t20=v20*343;t21=v21*343;t22=v22*343;t23=v23*343;t24=v24*343;t25=v25*343;t26=v26*343;t27=v27*343;t28=v28*343;t29=v29*343;t30=v30*343;t31=v31*343;
|
|
|
|
t21+=v0<<8;t22+=v1<<8;t23+=v2<<8;t24+=v3<<8;t25+=v4<<8;t26+=v5<<8;t27+=v6<<8;t28+=v7<<8;t29+=v8<<8;t30+=v9<<8;t31+=v10<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;v31=(t31+(t30>>>16))&65535;v30=t30&65535;
|
|
|
|
v0^=((c>>12)&63)|128;
|
|
|
|
t0=v0*343;t1=v1*343;t2=v2*343;t3=v3*343;t4=v4*343;t5=v5*343;t6=v6*343;t7=v7*343;t8=v8*343;t9=v9*343;t10=v10*343;t11=v11*343;t12=v12*343;t13=v13*343;t14=v14*343;t15=v15*343;t16=v16*343;t17=v17*343;t18=v18*343;t19=v19*343;t20=v20*343;t21=v21*343;t22=v22*343;t23=v23*343;t24=v24*343;t25=v25*343;t26=v26*343;t27=v27*343;t28=v28*343;t29=v29*343;t30=v30*343;t31=v31*343;
|
|
|
|
t21+=v0<<8;t22+=v1<<8;t23+=v2<<8;t24+=v3<<8;t25+=v4<<8;t26+=v5<<8;t27+=v6<<8;t28+=v7<<8;t29+=v8<<8;t30+=v9<<8;t31+=v10<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;v31=(t31+(t30>>>16))&65535;v30=t30&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*343;t1=v1*343;t2=v2*343;t3=v3*343;t4=v4*343;t5=v5*343;t6=v6*343;t7=v7*343;t8=v8*343;t9=v9*343;t10=v10*343;t11=v11*343;t12=v12*343;t13=v13*343;t14=v14*343;t15=v15*343;t16=v16*343;t17=v17*343;t18=v18*343;t19=v19*343;t20=v20*343;t21=v21*343;t22=v22*343;t23=v23*343;t24=v24*343;t25=v25*343;t26=v26*343;t27=v27*343;t28=v28*343;t29=v29*343;t30=v30*343;t31=v31*343;
|
|
|
|
t21+=v0<<8;t22+=v1<<8;t23+=v2<<8;t24+=v3<<8;t25+=v4<<8;t26+=v5<<8;t27+=v6<<8;t28+=v7<<8;t29+=v8<<8;t30+=v9<<8;t31+=v10<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;v31=(t31+(t30>>>16))&65535;v30=t30&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else {
|
|
|
|
v0^=(c>>12)|224;
|
|
|
|
t0=v0*343;t1=v1*343;t2=v2*343;t3=v3*343;t4=v4*343;t5=v5*343;t6=v6*343;t7=v7*343;t8=v8*343;t9=v9*343;t10=v10*343;t11=v11*343;t12=v12*343;t13=v13*343;t14=v14*343;t15=v15*343;t16=v16*343;t17=v17*343;t18=v18*343;t19=v19*343;t20=v20*343;t21=v21*343;t22=v22*343;t23=v23*343;t24=v24*343;t25=v25*343;t26=v26*343;t27=v27*343;t28=v28*343;t29=v29*343;t30=v30*343;t31=v31*343;
|
|
|
|
t21+=v0<<8;t22+=v1<<8;t23+=v2<<8;t24+=v3<<8;t25+=v4<<8;t26+=v5<<8;t27+=v6<<8;t28+=v7<<8;t29+=v8<<8;t30+=v9<<8;t31+=v10<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;v31=(t31+(t30>>>16))&65535;v30=t30&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*343;t1=v1*343;t2=v2*343;t3=v3*343;t4=v4*343;t5=v5*343;t6=v6*343;t7=v7*343;t8=v8*343;t9=v9*343;t10=v10*343;t11=v11*343;t12=v12*343;t13=v13*343;t14=v14*343;t15=v15*343;t16=v16*343;t17=v17*343;t18=v18*343;t19=v19*343;t20=v20*343;t21=v21*343;t22=v22*343;t23=v23*343;t24=v24*343;t25=v25*343;t26=v26*343;t27=v27*343;t28=v28*343;t29=v29*343;t30=v30*343;t31=v31*343;
|
|
|
|
t21+=v0<<8;t22+=v1<<8;t23+=v2<<8;t24+=v3<<8;t25+=v4<<8;t26+=v5<<8;t27+=v6<<8;t28+=v7<<8;t29+=v8<<8;t30+=v9<<8;t31+=v10<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;v31=(t31+(t30>>>16))&65535;v30=t30&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return hashValHex(hl[v31>>8]+hl[v31&255]+hl[v30>>8]+hl[v30&255]+hl[v29>>8]+hl[v29&255]+hl[v28>>8]+hl[v28&255]+hl[v27>>8]+hl[v27&255]+hl[v26>>8]+hl[v26&255]+hl[v25>>8]+hl[v25&255]+hl[v24>>8]+hl[v24&255]+hl[v23>>8]+hl[v23&255]+hl[v22>>8]+hl[v22&255]+hl[v21>>8]+hl[v21&255]+hl[v20>>8]+hl[v20&255]+hl[v19>>8]+hl[v19&255]+hl[v18>>8]+hl[v18&255]+hl[v17>>8]+hl[v17&255]+hl[v16>>8]+hl[v16&255]+hl[v15>>8]+hl[v15&255]+hl[v14>>8]+hl[v14&255]+hl[v13>>8]+hl[v13&255]+hl[v12>>8]+hl[v12&255]+hl[v11>>8]+hl[v11&255]+hl[v10>>8]+hl[v10&255]+hl[v9>>8]+hl[v9&255]+hl[v8>>8]+hl[v8&255]+hl[v7>>8]+hl[v7&255]+hl[v6>>8]+hl[v6&255]+hl[v5>>8]+hl[v5&255]+hl[v4>>8]+hl[v4&255]+hl[v3>>8]+hl[v3&255]+hl[v2>>8]+hl[v2&255]+hl[v1>>8]+hl[v1&255]+hl[v0>>8]+hl[v0&255],512);
|
|
|
|
}
|
|
|
|
|
|
|
|
_hash512 = _hash512_1a;
|
|
|
|
|
|
|
|
function _hash1024_1a(str){
|
|
|
|
var i,l=str.length-3,s=fnvConstants[1024].offset,t0=0,v0=s[63]|0,t1=0,v1=s[62]|0,t2=0,v2=s[61]|0,t3=0,v3=s[60]|0,t4=0,v4=s[59]|0,t5=0,v5=s[58]|0,t6=0,v6=s[57]|0,t7=0,v7=s[56]|0,t8=0,v8=s[55]|0,t9=0,v9=s[54]|0,t10=0,v10=s[53]|0,t11=0,v11=s[52]|0,t12=0,v12=s[51]|0,t13=0,v13=s[50]|0,t14=0,v14=s[49]|0,t15=0,v15=s[48]|0,t16=0,v16=s[47]|0,t17=0,v17=s[46]|0,t18=0,v18=s[45]|0,t19=0,v19=s[44]|0,t20=0,v20=s[43]|0,t21=0,v21=s[42]|0,t22=0,v22=s[41]|0,t23=0,v23=s[40]|0,t24=0,v24=s[39]|0,t25=0,v25=s[38]|0,t26=0,v26=s[37]|0,t27=0,v27=s[36]|0,t28=0,v28=s[35]|0,t29=0,v29=s[34]|0,t30=0,v30=s[33]|0,t31=0,v31=s[32]|0,t32=0,v32=s[31]|0,t33=0,v33=s[30]|0,t34=0,v34=s[29]|0,t35=0,v35=s[28]|0,t36=0,v36=s[27]|0,t37=0,v37=s[26]|0,t38=0,v38=s[25]|0,t39=0,v39=s[24]|0,t40=0,v40=s[23]|0,t41=0,v41=s[22]|0,t42=0,v42=s[21]|0,t43=0,v43=s[20]|0,t44=0,v44=s[19]|0,t45=0,v45=s[18]|0,t46=0,v46=s[17]|0,t47=0,v47=s[16]|0,t48=0,v48=s[15]|0,t49=0,v49=s[14]|0,t50=0,v50=s[13]|0,t51=0,v51=s[12]|0,t52=0,v52=s[11]|0,t53=0,v53=s[10]|0,t54=0,v54=s[9]|0,t55=0,v55=s[8]|0,t56=0,v56=s[7]|0,t57=0,v57=s[6]|0,t58=0,v58=s[5]|0,t59=0,v59=s[4]|0,t60=0,v60=s[3]|0,t61=0,v61=s[2]|0,t62=0,v62=s[1]|0,t63=0,v63=s[0]|0;
|
|
|
|
|
|
|
|
for (i = 0; i < l;) {
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*397;t1=v1*397;t2=v2*397;t3=v3*397;t4=v4*397;t5=v5*397;t6=v6*397;t7=v7*397;t8=v8*397;t9=v9*397;t10=v10*397;t11=v11*397;t12=v12*397;t13=v13*397;t14=v14*397;t15=v15*397;t16=v16*397;t17=v17*397;t18=v18*397;t19=v19*397;t20=v20*397;t21=v21*397;t22=v22*397;t23=v23*397;t24=v24*397;t25=v25*397;t26=v26*397;t27=v27*397;t28=v28*397;t29=v29*397;t30=v30*397;t31=v31*397;t32=v32*397;t33=v33*397;t34=v34*397;t35=v35*397;t36=v36*397;t37=v37*397;t38=v38*397;t39=v39*397;t40=v40*397;t41=v41*397;t42=v42*397;t43=v43*397;t44=v44*397;t45=v45*397;t46=v46*397;t47=v47*397;t48=v48*397;t49=v49*397;t50=v50*397;t51=v51*397;t52=v52*397;t53=v53*397;t54=v54*397;t55=v55*397;t56=v56*397;t57=v57*397;t58=v58*397;t59=v59*397;t60=v60*397;t61=v61*397;t62=v62*397;t63=v63*397;
|
|
|
|
t42+=v0<<8;t43+=v1<<8;t44+=v2<<8;t45+=v3<<8;t46+=v4<<8;t47+=v5<<8;t48+=v6<<8;t49+=v7<<8;t50+=v8<<8;t51+=v9<<8;t52+=v10<<8;t53+=v11<<8;t54+=v12<<8;t55+=v13<<8;t56+=v14<<8;t57+=v15<<8;t58+=v16<<8;t59+=v17<<8;t60+=v18<<8;t61+=v19<<8;t62+=v20<<8;t63+=v21<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;t31+=t30>>>16;v30=t30&65535;t32+=t31>>>16;v31=t31&65535;t33+=t32>>>16;v32=t32&65535;t34+=t33>>>16;v33=t33&65535;t35+=t34>>>16;v34=t34&65535;t36+=t35>>>16;v35=t35&65535;t37+=t36>>>16;v36=t36&65535;t38+=t37>>>16;v37=t37&65535;t39+=t38>>>16;v38=t38&65535;t40+=t39>>>16;v39=t39&65535;t41+=t40>>>16;v40=t40&65535;t42+=t41>>>16;v41=t41&65535;t43+=t42>>>16;v42=t42&65535;t44+=t43>>>16;v43=t43&65535;t45+=t44>>>16;v44=t44&65535;t46+=t45>>>16;v45=t45&65535;t47+=t46>>>16;v46=t46&65535;t48+=t47>>>16;v47=t47&65535;t49+=t48>>>16;v48=t48&65535;t50+=t49>>>16;v49=t49&65535;t51+=t50>>>16;v50=t50&65535;t52+=t51>>>16;v51=t51&65535;t53+=t52>>>16;v52=t52&65535;t54+=t53>>>16;v53=t53&65535;t55+=t54>>>16;v54=t54&65535;t56+=t55>>>16;v55=t55&65535;t57+=t56>>>16;v56=t56&65535;t58+=t57>>>16;v57=t57&65535;t59+=t58>>>16;v58=t58&65535;t60+=t59>>>16;v59=t59&65535;t61+=t60>>>16;v60=t60&65535;t62+=t61>>>16;v61=t61&65535;v63=(t63+(t62>>>16))&65535;v62=t62&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*397;t1=v1*397;t2=v2*397;t3=v3*397;t4=v4*397;t5=v5*397;t6=v6*397;t7=v7*397;t8=v8*397;t9=v9*397;t10=v10*397;t11=v11*397;t12=v12*397;t13=v13*397;t14=v14*397;t15=v15*397;t16=v16*397;t17=v17*397;t18=v18*397;t19=v19*397;t20=v20*397;t21=v21*397;t22=v22*397;t23=v23*397;t24=v24*397;t25=v25*397;t26=v26*397;t27=v27*397;t28=v28*397;t29=v29*397;t30=v30*397;t31=v31*397;t32=v32*397;t33=v33*397;t34=v34*397;t35=v35*397;t36=v36*397;t37=v37*397;t38=v38*397;t39=v39*397;t40=v40*397;t41=v41*397;t42=v42*397;t43=v43*397;t44=v44*397;t45=v45*397;t46=v46*397;t47=v47*397;t48=v48*397;t49=v49*397;t50=v50*397;t51=v51*397;t52=v52*397;t53=v53*397;t54=v54*397;t55=v55*397;t56=v56*397;t57=v57*397;t58=v58*397;t59=v59*397;t60=v60*397;t61=v61*397;t62=v62*397;t63=v63*397;
|
|
|
|
t42+=v0<<8;t43+=v1<<8;t44+=v2<<8;t45+=v3<<8;t46+=v4<<8;t47+=v5<<8;t48+=v6<<8;t49+=v7<<8;t50+=v8<<8;t51+=v9<<8;t52+=v10<<8;t53+=v11<<8;t54+=v12<<8;t55+=v13<<8;t56+=v14<<8;t57+=v15<<8;t58+=v16<<8;t59+=v17<<8;t60+=v18<<8;t61+=v19<<8;t62+=v20<<8;t63+=v21<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;t31+=t30>>>16;v30=t30&65535;t32+=t31>>>16;v31=t31&65535;t33+=t32>>>16;v32=t32&65535;t34+=t33>>>16;v33=t33&65535;t35+=t34>>>16;v34=t34&65535;t36+=t35>>>16;v35=t35&65535;t37+=t36>>>16;v36=t36&65535;t38+=t37>>>16;v37=t37&65535;t39+=t38>>>16;v38=t38&65535;t40+=t39>>>16;v39=t39&65535;t41+=t40>>>16;v40=t40&65535;t42+=t41>>>16;v41=t41&65535;t43+=t42>>>16;v42=t42&65535;t44+=t43>>>16;v43=t43&65535;t45+=t44>>>16;v44=t44&65535;t46+=t45>>>16;v45=t45&65535;t47+=t46>>>16;v46=t46&65535;t48+=t47>>>16;v47=t47&65535;t49+=t48>>>16;v48=t48&65535;t50+=t49>>>16;v49=t49&65535;t51+=t50>>>16;v50=t50&65535;t52+=t51>>>16;v51=t51&65535;t53+=t52>>>16;v52=t52&65535;t54+=t53>>>16;v53=t53&65535;t55+=t54>>>16;v54=t54&65535;t56+=t55>>>16;v55=t55&65535;t57+=t56>>>16;v56=t56&65535;t58+=t57>>>16;v57=t57&65535;t59+=t58>>>16;v58=t58&65535;t60+=t59>>>16;v59=t59&65535;t61+=t60>>>16;v60=t60&65535;t62+=t61>>>16;v61=t61&65535;v63=(t63+(t62>>>16))&65535;v62=t62&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*397;t1=v1*397;t2=v2*397;t3=v3*397;t4=v4*397;t5=v5*397;t6=v6*397;t7=v7*397;t8=v8*397;t9=v9*397;t10=v10*397;t11=v11*397;t12=v12*397;t13=v13*397;t14=v14*397;t15=v15*397;t16=v16*397;t17=v17*397;t18=v18*397;t19=v19*397;t20=v20*397;t21=v21*397;t22=v22*397;t23=v23*397;t24=v24*397;t25=v25*397;t26=v26*397;t27=v27*397;t28=v28*397;t29=v29*397;t30=v30*397;t31=v31*397;t32=v32*397;t33=v33*397;t34=v34*397;t35=v35*397;t36=v36*397;t37=v37*397;t38=v38*397;t39=v39*397;t40=v40*397;t41=v41*397;t42=v42*397;t43=v43*397;t44=v44*397;t45=v45*397;t46=v46*397;t47=v47*397;t48=v48*397;t49=v49*397;t50=v50*397;t51=v51*397;t52=v52*397;t53=v53*397;t54=v54*397;t55=v55*397;t56=v56*397;t57=v57*397;t58=v58*397;t59=v59*397;t60=v60*397;t61=v61*397;t62=v62*397;t63=v63*397;
|
|
|
|
t42+=v0<<8;t43+=v1<<8;t44+=v2<<8;t45+=v3<<8;t46+=v4<<8;t47+=v5<<8;t48+=v6<<8;t49+=v7<<8;t50+=v8<<8;t51+=v9<<8;t52+=v10<<8;t53+=v11<<8;t54+=v12<<8;t55+=v13<<8;t56+=v14<<8;t57+=v15<<8;t58+=v16<<8;t59+=v17<<8;t60+=v18<<8;t61+=v19<<8;t62+=v20<<8;t63+=v21<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;t31+=t30>>>16;v30=t30&65535;t32+=t31>>>16;v31=t31&65535;t33+=t32>>>16;v32=t32&65535;t34+=t33>>>16;v33=t33&65535;t35+=t34>>>16;v34=t34&65535;t36+=t35>>>16;v35=t35&65535;t37+=t36>>>16;v36=t36&65535;t38+=t37>>>16;v37=t37&65535;t39+=t38>>>16;v38=t38&65535;t40+=t39>>>16;v39=t39&65535;t41+=t40>>>16;v40=t40&65535;t42+=t41>>>16;v41=t41&65535;t43+=t42>>>16;v42=t42&65535;t44+=t43>>>16;v43=t43&65535;t45+=t44>>>16;v44=t44&65535;t46+=t45>>>16;v45=t45&65535;t47+=t46>>>16;v46=t46&65535;t48+=t47>>>16;v47=t47&65535;t49+=t48>>>16;v48=t48&65535;t50+=t49>>>16;v49=t49&65535;t51+=t50>>>16;v50=t50&65535;t52+=t51>>>16;v51=t51&65535;t53+=t52>>>16;v52=t52&65535;t54+=t53>>>16;v53=t53&65535;t55+=t54>>>16;v54=t54&65535;t56+=t55>>>16;v55=t55&65535;t57+=t56>>>16;v56=t56&65535;t58+=t57>>>16;v57=t57&65535;t59+=t58>>>16;v58=t58&65535;t60+=t59>>>16;v59=t59&65535;t61+=t60>>>16;v60=t60&65535;t62+=t61>>>16;v61=t61&65535;v63=(t63+(t62>>>16))&65535;v62=t62&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*397;t1=v1*397;t2=v2*397;t3=v3*397;t4=v4*397;t5=v5*397;t6=v6*397;t7=v7*397;t8=v8*397;t9=v9*397;t10=v10*397;t11=v11*397;t12=v12*397;t13=v13*397;t14=v14*397;t15=v15*397;t16=v16*397;t17=v17*397;t18=v18*397;t19=v19*397;t20=v20*397;t21=v21*397;t22=v22*397;t23=v23*397;t24=v24*397;t25=v25*397;t26=v26*397;t27=v27*397;t28=v28*397;t29=v29*397;t30=v30*397;t31=v31*397;t32=v32*397;t33=v33*397;t34=v34*397;t35=v35*397;t36=v36*397;t37=v37*397;t38=v38*397;t39=v39*397;t40=v40*397;t41=v41*397;t42=v42*397;t43=v43*397;t44=v44*397;t45=v45*397;t46=v46*397;t47=v47*397;t48=v48*397;t49=v49*397;t50=v50*397;t51=v51*397;t52=v52*397;t53=v53*397;t54=v54*397;t55=v55*397;t56=v56*397;t57=v57*397;t58=v58*397;t59=v59*397;t60=v60*397;t61=v61*397;t62=v62*397;t63=v63*397;
|
|
|
|
t42+=v0<<8;t43+=v1<<8;t44+=v2<<8;t45+=v3<<8;t46+=v4<<8;t47+=v5<<8;t48+=v6<<8;t49+=v7<<8;t50+=v8<<8;t51+=v9<<8;t52+=v10<<8;t53+=v11<<8;t54+=v12<<8;t55+=v13<<8;t56+=v14<<8;t57+=v15<<8;t58+=v16<<8;t59+=v17<<8;t60+=v18<<8;t61+=v19<<8;t62+=v20<<8;t63+=v21<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;t31+=t30>>>16;v30=t30&65535;t32+=t31>>>16;v31=t31&65535;t33+=t32>>>16;v32=t32&65535;t34+=t33>>>16;v33=t33&65535;t35+=t34>>>16;v34=t34&65535;t36+=t35>>>16;v35=t35&65535;t37+=t36>>>16;v36=t36&65535;t38+=t37>>>16;v37=t37&65535;t39+=t38>>>16;v38=t38&65535;t40+=t39>>>16;v39=t39&65535;t41+=t40>>>16;v40=t40&65535;t42+=t41>>>16;v41=t41&65535;t43+=t42>>>16;v42=t42&65535;t44+=t43>>>16;v43=t43&65535;t45+=t44>>>16;v44=t44&65535;t46+=t45>>>16;v45=t45&65535;t47+=t46>>>16;v46=t46&65535;t48+=t47>>>16;v47=t47&65535;t49+=t48>>>16;v48=t48&65535;t50+=t49>>>16;v49=t49&65535;t51+=t50>>>16;v50=t50&65535;t52+=t51>>>16;v51=t51&65535;t53+=t52>>>16;v52=t52&65535;t54+=t53>>>16;v53=t53&65535;t55+=t54>>>16;v54=t54&65535;t56+=t55>>>16;v55=t55&65535;t57+=t56>>>16;v56=t56&65535;t58+=t57>>>16;v57=t57&65535;t59+=t58>>>16;v58=t58&65535;t60+=t59>>>16;v59=t59&65535;t61+=t60>>>16;v60=t60&65535;t62+=t61>>>16;v61=t61&65535;v63=(t63+(t62>>>16))&65535;v62=t62&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
while(i<l+3){
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*397;t1=v1*397;t2=v2*397;t3=v3*397;t4=v4*397;t5=v5*397;t6=v6*397;t7=v7*397;t8=v8*397;t9=v9*397;t10=v10*397;t11=v11*397;t12=v12*397;t13=v13*397;t14=v14*397;t15=v15*397;t16=v16*397;t17=v17*397;t18=v18*397;t19=v19*397;t20=v20*397;t21=v21*397;t22=v22*397;t23=v23*397;t24=v24*397;t25=v25*397;t26=v26*397;t27=v27*397;t28=v28*397;t29=v29*397;t30=v30*397;t31=v31*397;t32=v32*397;t33=v33*397;t34=v34*397;t35=v35*397;t36=v36*397;t37=v37*397;t38=v38*397;t39=v39*397;t40=v40*397;t41=v41*397;t42=v42*397;t43=v43*397;t44=v44*397;t45=v45*397;t46=v46*397;t47=v47*397;t48=v48*397;t49=v49*397;t50=v50*397;t51=v51*397;t52=v52*397;t53=v53*397;t54=v54*397;t55=v55*397;t56=v56*397;t57=v57*397;t58=v58*397;t59=v59*397;t60=v60*397;t61=v61*397;t62=v62*397;t63=v63*397;
|
|
|
|
t42+=v0<<8;t43+=v1<<8;t44+=v2<<8;t45+=v3<<8;t46+=v4<<8;t47+=v5<<8;t48+=v6<<8;t49+=v7<<8;t50+=v8<<8;t51+=v9<<8;t52+=v10<<8;t53+=v11<<8;t54+=v12<<8;t55+=v13<<8;t56+=v14<<8;t57+=v15<<8;t58+=v16<<8;t59+=v17<<8;t60+=v18<<8;t61+=v19<<8;t62+=v20<<8;t63+=v21<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;t31+=t30>>>16;v30=t30&65535;t32+=t31>>>16;v31=t31&65535;t33+=t32>>>16;v32=t32&65535;t34+=t33>>>16;v33=t33&65535;t35+=t34>>>16;v34=t34&65535;t36+=t35>>>16;v35=t35&65535;t37+=t36>>>16;v36=t36&65535;t38+=t37>>>16;v37=t37&65535;t39+=t38>>>16;v38=t38&65535;t40+=t39>>>16;v39=t39&65535;t41+=t40>>>16;v40=t40&65535;t42+=t41>>>16;v41=t41&65535;t43+=t42>>>16;v42=t42&65535;t44+=t43>>>16;v43=t43&65535;t45+=t44>>>16;v44=t44&65535;t46+=t45>>>16;v45=t45&65535;t47+=t46>>>16;v46=t46&65535;t48+=t47>>>16;v47=t47&65535;t49+=t48>>>16;v48=t48&65535;t50+=t49>>>16;v49=t49&65535;t51+=t50>>>16;v50=t50&65535;t52+=t51>>>16;v51=t51&65535;t53+=t52>>>16;v52=t52&65535;t54+=t53>>>16;v53=t53&65535;t55+=t54>>>16;v54=t54&65535;t56+=t55>>>16;v55=t55&65535;t57+=t56>>>16;v56=t56&65535;t58+=t57>>>16;v57=t57&65535;t59+=t58>>>16;v58=t58&65535;t60+=t59>>>16;v59=t59&65535;t61+=t60>>>16;v60=t60&65535;t62+=t61>>>16;v61=t61&65535;v63=(t63+(t62>>>16))&65535;v62=t62&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hashValHex(hl[v63>>8]+hl[v63&255]+hl[v62>>8]+hl[v62&255]+hl[v61>>8]+hl[v61&255]+hl[v60>>8]+hl[v60&255]+hl[v59>>8]+hl[v59&255]+hl[v58>>8]+hl[v58&255]+hl[v57>>8]+hl[v57&255]+hl[v56>>8]+hl[v56&255]+hl[v55>>8]+hl[v55&255]+hl[v54>>8]+hl[v54&255]+hl[v53>>8]+hl[v53&255]+hl[v52>>8]+hl[v52&255]+hl[v51>>8]+hl[v51&255]+hl[v50>>8]+hl[v50&255]+hl[v49>>8]+hl[v49&255]+hl[v48>>8]+hl[v48&255]+hl[v47>>8]+hl[v47&255]+hl[v46>>8]+hl[v46&255]+hl[v45>>8]+hl[v45&255]+hl[v44>>8]+hl[v44&255]+hl[v43>>8]+hl[v43&255]+hl[v42>>8]+hl[v42&255]+hl[v41>>8]+hl[v41&255]+hl[v40>>8]+hl[v40&255]+hl[v39>>8]+hl[v39&255]+hl[v38>>8]+hl[v38&255]+hl[v37>>8]+hl[v37&255]+hl[v36>>8]+hl[v36&255]+hl[v35>>8]+hl[v35&255]+hl[v34>>8]+hl[v34&255]+hl[v33>>8]+hl[v33&255]+hl[v32>>8]+hl[v32&255]+hl[v31>>8]+hl[v31&255]+hl[v30>>8]+hl[v30&255]+hl[v29>>8]+hl[v29&255]+hl[v28>>8]+hl[v28&255]+hl[v27>>8]+hl[v27&255]+hl[v26>>8]+hl[v26&255]+hl[v25>>8]+hl[v25&255]+hl[v24>>8]+hl[v24&255]+hl[v23>>8]+hl[v23&255]+hl[v22>>8]+hl[v22&255]+hl[v21>>8]+hl[v21&255]+hl[v20>>8]+hl[v20&255]+hl[v19>>8]+hl[v19&255]+hl[v18>>8]+hl[v18&255]+hl[v17>>8]+hl[v17&255]+hl[v16>>8]+hl[v16&255]+hl[v15>>8]+hl[v15&255]+hl[v14>>8]+hl[v14&255]+hl[v13>>8]+hl[v13&255]+hl[v12>>8]+hl[v12&255]+hl[v11>>8]+hl[v11&255]+hl[v10>>8]+hl[v10&255]+hl[v9>>8]+hl[v9&255]+hl[v8>>8]+hl[v8&255]+hl[v7>>8]+hl[v7&255]+hl[v6>>8]+hl[v6&255]+hl[v5>>8]+hl[v5&255]+hl[v4>>8]+hl[v4&255]+hl[v3>>8]+hl[v3&255]+hl[v2>>8]+hl[v2&255]+hl[v1>>8]+hl[v1&255]+hl[v0>>8]+hl[v0&255],1024);
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash1024_1(str){
|
|
|
|
var i,l=str.length-3,s=fnvConstants[1024].offset,t0=0,v0=s[63]|0,t1=0,v1=s[62]|0,t2=0,v2=s[61]|0,t3=0,v3=s[60]|0,t4=0,v4=s[59]|0,t5=0,v5=s[58]|0,t6=0,v6=s[57]|0,t7=0,v7=s[56]|0,t8=0,v8=s[55]|0,t9=0,v9=s[54]|0,t10=0,v10=s[53]|0,t11=0,v11=s[52]|0,t12=0,v12=s[51]|0,t13=0,v13=s[50]|0,t14=0,v14=s[49]|0,t15=0,v15=s[48]|0,t16=0,v16=s[47]|0,t17=0,v17=s[46]|0,t18=0,v18=s[45]|0,t19=0,v19=s[44]|0,t20=0,v20=s[43]|0,t21=0,v21=s[42]|0,t22=0,v22=s[41]|0,t23=0,v23=s[40]|0,t24=0,v24=s[39]|0,t25=0,v25=s[38]|0,t26=0,v26=s[37]|0,t27=0,v27=s[36]|0,t28=0,v28=s[35]|0,t29=0,v29=s[34]|0,t30=0,v30=s[33]|0,t31=0,v31=s[32]|0,t32=0,v32=s[31]|0,t33=0,v33=s[30]|0,t34=0,v34=s[29]|0,t35=0,v35=s[28]|0,t36=0,v36=s[27]|0,t37=0,v37=s[26]|0,t38=0,v38=s[25]|0,t39=0,v39=s[24]|0,t40=0,v40=s[23]|0,t41=0,v41=s[22]|0,t42=0,v42=s[21]|0,t43=0,v43=s[20]|0,t44=0,v44=s[19]|0,t45=0,v45=s[18]|0,t46=0,v46=s[17]|0,t47=0,v47=s[16]|0,t48=0,v48=s[15]|0,t49=0,v49=s[14]|0,t50=0,v50=s[13]|0,t51=0,v51=s[12]|0,t52=0,v52=s[11]|0,t53=0,v53=s[10]|0,t54=0,v54=s[9]|0,t55=0,v55=s[8]|0,t56=0,v56=s[7]|0,t57=0,v57=s[6]|0,t58=0,v58=s[5]|0,t59=0,v59=s[4]|0,t60=0,v60=s[3]|0,t61=0,v61=s[2]|0,t62=0,v62=s[1]|0,t63=0,v63=s[0]|0;
|
|
|
|
|
|
|
|
for (i = 0; i < l;) {
|
|
|
|
t0=v0*397;t1=v1*397;t2=v2*397;t3=v3*397;t4=v4*397;t5=v5*397;t6=v6*397;t7=v7*397;t8=v8*397;t9=v9*397;t10=v10*397;t11=v11*397;t12=v12*397;t13=v13*397;t14=v14*397;t15=v15*397;t16=v16*397;t17=v17*397;t18=v18*397;t19=v19*397;t20=v20*397;t21=v21*397;t22=v22*397;t23=v23*397;t24=v24*397;t25=v25*397;t26=v26*397;t27=v27*397;t28=v28*397;t29=v29*397;t30=v30*397;t31=v31*397;t32=v32*397;t33=v33*397;t34=v34*397;t35=v35*397;t36=v36*397;t37=v37*397;t38=v38*397;t39=v39*397;t40=v40*397;t41=v41*397;t42=v42*397;t43=v43*397;t44=v44*397;t45=v45*397;t46=v46*397;t47=v47*397;t48=v48*397;t49=v49*397;t50=v50*397;t51=v51*397;t52=v52*397;t53=v53*397;t54=v54*397;t55=v55*397;t56=v56*397;t57=v57*397;t58=v58*397;t59=v59*397;t60=v60*397;t61=v61*397;t62=v62*397;t63=v63*397;
|
|
|
|
t42+=v0<<8;t43+=v1<<8;t44+=v2<<8;t45+=v3<<8;t46+=v4<<8;t47+=v5<<8;t48+=v6<<8;t49+=v7<<8;t50+=v8<<8;t51+=v9<<8;t52+=v10<<8;t53+=v11<<8;t54+=v12<<8;t55+=v13<<8;t56+=v14<<8;t57+=v15<<8;t58+=v16<<8;t59+=v17<<8;t60+=v18<<8;t61+=v19<<8;t62+=v20<<8;t63+=v21<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;t31+=t30>>>16;v30=t30&65535;t32+=t31>>>16;v31=t31&65535;t33+=t32>>>16;v32=t32&65535;t34+=t33>>>16;v33=t33&65535;t35+=t34>>>16;v34=t34&65535;t36+=t35>>>16;v35=t35&65535;t37+=t36>>>16;v36=t36&65535;t38+=t37>>>16;v37=t37&65535;t39+=t38>>>16;v38=t38&65535;t40+=t39>>>16;v39=t39&65535;t41+=t40>>>16;v40=t40&65535;t42+=t41>>>16;v41=t41&65535;t43+=t42>>>16;v42=t42&65535;t44+=t43>>>16;v43=t43&65535;t45+=t44>>>16;v44=t44&65535;t46+=t45>>>16;v45=t45&65535;t47+=t46>>>16;v46=t46&65535;t48+=t47>>>16;v47=t47&65535;t49+=t48>>>16;v48=t48&65535;t50+=t49>>>16;v49=t49&65535;t51+=t50>>>16;v50=t50&65535;t52+=t51>>>16;v51=t51&65535;t53+=t52>>>16;v52=t52&65535;t54+=t53>>>16;v53=t53&65535;t55+=t54>>>16;v54=t54&65535;t56+=t55>>>16;v55=t55&65535;t57+=t56>>>16;v56=t56&65535;t58+=t57>>>16;v57=t57&65535;t59+=t58>>>16;v58=t58&65535;t60+=t59>>>16;v59=t59&65535;t61+=t60>>>16;v60=t60&65535;t62+=t61>>>16;v61=t61&65535;v63=(t63+(t62>>>16))&65535;v62=t62&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*397;t1=v1*397;t2=v2*397;t3=v3*397;t4=v4*397;t5=v5*397;t6=v6*397;t7=v7*397;t8=v8*397;t9=v9*397;t10=v10*397;t11=v11*397;t12=v12*397;t13=v13*397;t14=v14*397;t15=v15*397;t16=v16*397;t17=v17*397;t18=v18*397;t19=v19*397;t20=v20*397;t21=v21*397;t22=v22*397;t23=v23*397;t24=v24*397;t25=v25*397;t26=v26*397;t27=v27*397;t28=v28*397;t29=v29*397;t30=v30*397;t31=v31*397;t32=v32*397;t33=v33*397;t34=v34*397;t35=v35*397;t36=v36*397;t37=v37*397;t38=v38*397;t39=v39*397;t40=v40*397;t41=v41*397;t42=v42*397;t43=v43*397;t44=v44*397;t45=v45*397;t46=v46*397;t47=v47*397;t48=v48*397;t49=v49*397;t50=v50*397;t51=v51*397;t52=v52*397;t53=v53*397;t54=v54*397;t55=v55*397;t56=v56*397;t57=v57*397;t58=v58*397;t59=v59*397;t60=v60*397;t61=v61*397;t62=v62*397;t63=v63*397;
|
|
|
|
t42+=v0<<8;t43+=v1<<8;t44+=v2<<8;t45+=v3<<8;t46+=v4<<8;t47+=v5<<8;t48+=v6<<8;t49+=v7<<8;t50+=v8<<8;t51+=v9<<8;t52+=v10<<8;t53+=v11<<8;t54+=v12<<8;t55+=v13<<8;t56+=v14<<8;t57+=v15<<8;t58+=v16<<8;t59+=v17<<8;t60+=v18<<8;t61+=v19<<8;t62+=v20<<8;t63+=v21<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;t31+=t30>>>16;v30=t30&65535;t32+=t31>>>16;v31=t31&65535;t33+=t32>>>16;v32=t32&65535;t34+=t33>>>16;v33=t33&65535;t35+=t34>>>16;v34=t34&65535;t36+=t35>>>16;v35=t35&65535;t37+=t36>>>16;v36=t36&65535;t38+=t37>>>16;v37=t37&65535;t39+=t38>>>16;v38=t38&65535;t40+=t39>>>16;v39=t39&65535;t41+=t40>>>16;v40=t40&65535;t42+=t41>>>16;v41=t41&65535;t43+=t42>>>16;v42=t42&65535;t44+=t43>>>16;v43=t43&65535;t45+=t44>>>16;v44=t44&65535;t46+=t45>>>16;v45=t45&65535;t47+=t46>>>16;v46=t46&65535;t48+=t47>>>16;v47=t47&65535;t49+=t48>>>16;v48=t48&65535;t50+=t49>>>16;v49=t49&65535;t51+=t50>>>16;v50=t50&65535;t52+=t51>>>16;v51=t51&65535;t53+=t52>>>16;v52=t52&65535;t54+=t53>>>16;v53=t53&65535;t55+=t54>>>16;v54=t54&65535;t56+=t55>>>16;v55=t55&65535;t57+=t56>>>16;v56=t56&65535;t58+=t57>>>16;v57=t57&65535;t59+=t58>>>16;v58=t58&65535;t60+=t59>>>16;v59=t59&65535;t61+=t60>>>16;v60=t60&65535;t62+=t61>>>16;v61=t61&65535;v63=(t63+(t62>>>16))&65535;v62=t62&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*397;t1=v1*397;t2=v2*397;t3=v3*397;t4=v4*397;t5=v5*397;t6=v6*397;t7=v7*397;t8=v8*397;t9=v9*397;t10=v10*397;t11=v11*397;t12=v12*397;t13=v13*397;t14=v14*397;t15=v15*397;t16=v16*397;t17=v17*397;t18=v18*397;t19=v19*397;t20=v20*397;t21=v21*397;t22=v22*397;t23=v23*397;t24=v24*397;t25=v25*397;t26=v26*397;t27=v27*397;t28=v28*397;t29=v29*397;t30=v30*397;t31=v31*397;t32=v32*397;t33=v33*397;t34=v34*397;t35=v35*397;t36=v36*397;t37=v37*397;t38=v38*397;t39=v39*397;t40=v40*397;t41=v41*397;t42=v42*397;t43=v43*397;t44=v44*397;t45=v45*397;t46=v46*397;t47=v47*397;t48=v48*397;t49=v49*397;t50=v50*397;t51=v51*397;t52=v52*397;t53=v53*397;t54=v54*397;t55=v55*397;t56=v56*397;t57=v57*397;t58=v58*397;t59=v59*397;t60=v60*397;t61=v61*397;t62=v62*397;t63=v63*397;
|
|
|
|
t42+=v0<<8;t43+=v1<<8;t44+=v2<<8;t45+=v3<<8;t46+=v4<<8;t47+=v5<<8;t48+=v6<<8;t49+=v7<<8;t50+=v8<<8;t51+=v9<<8;t52+=v10<<8;t53+=v11<<8;t54+=v12<<8;t55+=v13<<8;t56+=v14<<8;t57+=v15<<8;t58+=v16<<8;t59+=v17<<8;t60+=v18<<8;t61+=v19<<8;t62+=v20<<8;t63+=v21<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;t31+=t30>>>16;v30=t30&65535;t32+=t31>>>16;v31=t31&65535;t33+=t32>>>16;v32=t32&65535;t34+=t33>>>16;v33=t33&65535;t35+=t34>>>16;v34=t34&65535;t36+=t35>>>16;v35=t35&65535;t37+=t36>>>16;v36=t36&65535;t38+=t37>>>16;v37=t37&65535;t39+=t38>>>16;v38=t38&65535;t40+=t39>>>16;v39=t39&65535;t41+=t40>>>16;v40=t40&65535;t42+=t41>>>16;v41=t41&65535;t43+=t42>>>16;v42=t42&65535;t44+=t43>>>16;v43=t43&65535;t45+=t44>>>16;v44=t44&65535;t46+=t45>>>16;v45=t45&65535;t47+=t46>>>16;v46=t46&65535;t48+=t47>>>16;v47=t47&65535;t49+=t48>>>16;v48=t48&65535;t50+=t49>>>16;v49=t49&65535;t51+=t50>>>16;v50=t50&65535;t52+=t51>>>16;v51=t51&65535;t53+=t52>>>16;v52=t52&65535;t54+=t53>>>16;v53=t53&65535;t55+=t54>>>16;v54=t54&65535;t56+=t55>>>16;v55=t55&65535;t57+=t56>>>16;v56=t56&65535;t58+=t57>>>16;v57=t57&65535;t59+=t58>>>16;v58=t58&65535;t60+=t59>>>16;v59=t59&65535;t61+=t60>>>16;v60=t60&65535;t62+=t61>>>16;v61=t61&65535;v63=(t63+(t62>>>16))&65535;v62=t62&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
t0=v0*397;t1=v1*397;t2=v2*397;t3=v3*397;t4=v4*397;t5=v5*397;t6=v6*397;t7=v7*397;t8=v8*397;t9=v9*397;t10=v10*397;t11=v11*397;t12=v12*397;t13=v13*397;t14=v14*397;t15=v15*397;t16=v16*397;t17=v17*397;t18=v18*397;t19=v19*397;t20=v20*397;t21=v21*397;t22=v22*397;t23=v23*397;t24=v24*397;t25=v25*397;t26=v26*397;t27=v27*397;t28=v28*397;t29=v29*397;t30=v30*397;t31=v31*397;t32=v32*397;t33=v33*397;t34=v34*397;t35=v35*397;t36=v36*397;t37=v37*397;t38=v38*397;t39=v39*397;t40=v40*397;t41=v41*397;t42=v42*397;t43=v43*397;t44=v44*397;t45=v45*397;t46=v46*397;t47=v47*397;t48=v48*397;t49=v49*397;t50=v50*397;t51=v51*397;t52=v52*397;t53=v53*397;t54=v54*397;t55=v55*397;t56=v56*397;t57=v57*397;t58=v58*397;t59=v59*397;t60=v60*397;t61=v61*397;t62=v62*397;t63=v63*397;
|
|
|
|
t42+=v0<<8;t43+=v1<<8;t44+=v2<<8;t45+=v3<<8;t46+=v4<<8;t47+=v5<<8;t48+=v6<<8;t49+=v7<<8;t50+=v8<<8;t51+=v9<<8;t52+=v10<<8;t53+=v11<<8;t54+=v12<<8;t55+=v13<<8;t56+=v14<<8;t57+=v15<<8;t58+=v16<<8;t59+=v17<<8;t60+=v18<<8;t61+=v19<<8;t62+=v20<<8;t63+=v21<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;t31+=t30>>>16;v30=t30&65535;t32+=t31>>>16;v31=t31&65535;t33+=t32>>>16;v32=t32&65535;t34+=t33>>>16;v33=t33&65535;t35+=t34>>>16;v34=t34&65535;t36+=t35>>>16;v35=t35&65535;t37+=t36>>>16;v36=t36&65535;t38+=t37>>>16;v37=t37&65535;t39+=t38>>>16;v38=t38&65535;t40+=t39>>>16;v39=t39&65535;t41+=t40>>>16;v40=t40&65535;t42+=t41>>>16;v41=t41&65535;t43+=t42>>>16;v42=t42&65535;t44+=t43>>>16;v43=t43&65535;t45+=t44>>>16;v44=t44&65535;t46+=t45>>>16;v45=t45&65535;t47+=t46>>>16;v46=t46&65535;t48+=t47>>>16;v47=t47&65535;t49+=t48>>>16;v48=t48&65535;t50+=t49>>>16;v49=t49&65535;t51+=t50>>>16;v50=t50&65535;t52+=t51>>>16;v51=t51&65535;t53+=t52>>>16;v52=t52&65535;t54+=t53>>>16;v53=t53&65535;t55+=t54>>>16;v54=t54&65535;t56+=t55>>>16;v55=t55&65535;t57+=t56>>>16;v56=t56&65535;t58+=t57>>>16;v57=t57&65535;t59+=t58>>>16;v58=t58&65535;t60+=t59>>>16;v59=t59&65535;t61+=t60>>>16;v60=t60&65535;t62+=t61>>>16;v61=t61&65535;v63=(t63+(t62>>>16))&65535;v62=t62&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
}
|
|
|
|
|
|
|
|
while(i<l+3){
|
|
|
|
t0=v0*397;t1=v1*397;t2=v2*397;t3=v3*397;t4=v4*397;t5=v5*397;t6=v6*397;t7=v7*397;t8=v8*397;t9=v9*397;t10=v10*397;t11=v11*397;t12=v12*397;t13=v13*397;t14=v14*397;t15=v15*397;t16=v16*397;t17=v17*397;t18=v18*397;t19=v19*397;t20=v20*397;t21=v21*397;t22=v22*397;t23=v23*397;t24=v24*397;t25=v25*397;t26=v26*397;t27=v27*397;t28=v28*397;t29=v29*397;t30=v30*397;t31=v31*397;t32=v32*397;t33=v33*397;t34=v34*397;t35=v35*397;t36=v36*397;t37=v37*397;t38=v38*397;t39=v39*397;t40=v40*397;t41=v41*397;t42=v42*397;t43=v43*397;t44=v44*397;t45=v45*397;t46=v46*397;t47=v47*397;t48=v48*397;t49=v49*397;t50=v50*397;t51=v51*397;t52=v52*397;t53=v53*397;t54=v54*397;t55=v55*397;t56=v56*397;t57=v57*397;t58=v58*397;t59=v59*397;t60=v60*397;t61=v61*397;t62=v62*397;t63=v63*397;
|
|
|
|
t42+=v0<<8;t43+=v1<<8;t44+=v2<<8;t45+=v3<<8;t46+=v4<<8;t47+=v5<<8;t48+=v6<<8;t49+=v7<<8;t50+=v8<<8;t51+=v9<<8;t52+=v10<<8;t53+=v11<<8;t54+=v12<<8;t55+=v13<<8;t56+=v14<<8;t57+=v15<<8;t58+=v16<<8;t59+=v17<<8;t60+=v18<<8;t61+=v19<<8;t62+=v20<<8;t63+=v21<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;t31+=t30>>>16;v30=t30&65535;t32+=t31>>>16;v31=t31&65535;t33+=t32>>>16;v32=t32&65535;t34+=t33>>>16;v33=t33&65535;t35+=t34>>>16;v34=t34&65535;t36+=t35>>>16;v35=t35&65535;t37+=t36>>>16;v36=t36&65535;t38+=t37>>>16;v37=t37&65535;t39+=t38>>>16;v38=t38&65535;t40+=t39>>>16;v39=t39&65535;t41+=t40>>>16;v40=t40&65535;t42+=t41>>>16;v41=t41&65535;t43+=t42>>>16;v42=t42&65535;t44+=t43>>>16;v43=t43&65535;t45+=t44>>>16;v44=t44&65535;t46+=t45>>>16;v45=t45&65535;t47+=t46>>>16;v46=t46&65535;t48+=t47>>>16;v47=t47&65535;t49+=t48>>>16;v48=t48&65535;t50+=t49>>>16;v49=t49&65535;t51+=t50>>>16;v50=t50&65535;t52+=t51>>>16;v51=t51&65535;t53+=t52>>>16;v52=t52&65535;t54+=t53>>>16;v53=t53&65535;t55+=t54>>>16;v54=t54&65535;t56+=t55>>>16;v55=t55&65535;t57+=t56>>>16;v56=t56&65535;t58+=t57>>>16;v57=t57&65535;t59+=t58>>>16;v58=t58&65535;t60+=t59>>>16;v59=t59&65535;t61+=t60>>>16;v60=t60&65535;t62+=t61>>>16;v61=t61&65535;v63=(t63+(t62>>>16))&65535;v62=t62&65535;
|
|
|
|
v0^=str.charCodeAt(i++);
|
|
|
|
}
|
|
|
|
|
|
|
|
return hashValHex(hl[v63>>8]+hl[v63&255]+hl[v62>>8]+hl[v62&255]+hl[v61>>8]+hl[v61&255]+hl[v60>>8]+hl[v60&255]+hl[v59>>8]+hl[v59&255]+hl[v58>>8]+hl[v58&255]+hl[v57>>8]+hl[v57&255]+hl[v56>>8]+hl[v56&255]+hl[v55>>8]+hl[v55&255]+hl[v54>>8]+hl[v54&255]+hl[v53>>8]+hl[v53&255]+hl[v52>>8]+hl[v52&255]+hl[v51>>8]+hl[v51&255]+hl[v50>>8]+hl[v50&255]+hl[v49>>8]+hl[v49&255]+hl[v48>>8]+hl[v48&255]+hl[v47>>8]+hl[v47&255]+hl[v46>>8]+hl[v46&255]+hl[v45>>8]+hl[v45&255]+hl[v44>>8]+hl[v44&255]+hl[v43>>8]+hl[v43&255]+hl[v42>>8]+hl[v42&255]+hl[v41>>8]+hl[v41&255]+hl[v40>>8]+hl[v40&255]+hl[v39>>8]+hl[v39&255]+hl[v38>>8]+hl[v38&255]+hl[v37>>8]+hl[v37&255]+hl[v36>>8]+hl[v36&255]+hl[v35>>8]+hl[v35&255]+hl[v34>>8]+hl[v34&255]+hl[v33>>8]+hl[v33&255]+hl[v32>>8]+hl[v32&255]+hl[v31>>8]+hl[v31&255]+hl[v30>>8]+hl[v30&255]+hl[v29>>8]+hl[v29&255]+hl[v28>>8]+hl[v28&255]+hl[v27>>8]+hl[v27&255]+hl[v26>>8]+hl[v26&255]+hl[v25>>8]+hl[v25&255]+hl[v24>>8]+hl[v24&255]+hl[v23>>8]+hl[v23&255]+hl[v22>>8]+hl[v22&255]+hl[v21>>8]+hl[v21&255]+hl[v20>>8]+hl[v20&255]+hl[v19>>8]+hl[v19&255]+hl[v18>>8]+hl[v18&255]+hl[v17>>8]+hl[v17&255]+hl[v16>>8]+hl[v16&255]+hl[v15>>8]+hl[v15&255]+hl[v14>>8]+hl[v14&255]+hl[v13>>8]+hl[v13&255]+hl[v12>>8]+hl[v12&255]+hl[v11>>8]+hl[v11&255]+hl[v10>>8]+hl[v10&255]+hl[v9>>8]+hl[v9&255]+hl[v8>>8]+hl[v8&255]+hl[v7>>8]+hl[v7&255]+hl[v6>>8]+hl[v6&255]+hl[v5>>8]+hl[v5&255]+hl[v4>>8]+hl[v4&255]+hl[v3>>8]+hl[v3&255]+hl[v2>>8]+hl[v2&255]+hl[v1>>8]+hl[v1&255]+hl[v0>>8]+hl[v0&255],1024);
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash1024_1a_utf(str){
|
|
|
|
var c,i,l=str.length,s=fnvConstants[1024].offset,t0=0,v0=s[63]|0,t1=0,v1=s[62]|0,t2=0,v2=s[61]|0,t3=0,v3=s[60]|0,t4=0,v4=s[59]|0,t5=0,v5=s[58]|0,t6=0,v6=s[57]|0,t7=0,v7=s[56]|0,t8=0,v8=s[55]|0,t9=0,v9=s[54]|0,t10=0,v10=s[53]|0,t11=0,v11=s[52]|0,t12=0,v12=s[51]|0,t13=0,v13=s[50]|0,t14=0,v14=s[49]|0,t15=0,v15=s[48]|0,t16=0,v16=s[47]|0,t17=0,v17=s[46]|0,t18=0,v18=s[45]|0,t19=0,v19=s[44]|0,t20=0,v20=s[43]|0,t21=0,v21=s[42]|0,t22=0,v22=s[41]|0,t23=0,v23=s[40]|0,t24=0,v24=s[39]|0,t25=0,v25=s[38]|0,t26=0,v26=s[37]|0,t27=0,v27=s[36]|0,t28=0,v28=s[35]|0,t29=0,v29=s[34]|0,t30=0,v30=s[33]|0,t31=0,v31=s[32]|0,t32=0,v32=s[31]|0,t33=0,v33=s[30]|0,t34=0,v34=s[29]|0,t35=0,v35=s[28]|0,t36=0,v36=s[27]|0,t37=0,v37=s[26]|0,t38=0,v38=s[25]|0,t39=0,v39=s[24]|0,t40=0,v40=s[23]|0,t41=0,v41=s[22]|0,t42=0,v42=s[21]|0,t43=0,v43=s[20]|0,t44=0,v44=s[19]|0,t45=0,v45=s[18]|0,t46=0,v46=s[17]|0,t47=0,v47=s[16]|0,t48=0,v48=s[15]|0,t49=0,v49=s[14]|0,t50=0,v50=s[13]|0,t51=0,v51=s[12]|0,t52=0,v52=s[11]|0,t53=0,v53=s[10]|0,t54=0,v54=s[9]|0,t55=0,v55=s[8]|0,t56=0,v56=s[7]|0,t57=0,v57=s[6]|0,t58=0,v58=s[5]|0,t59=0,v59=s[4]|0,t60=0,v60=s[3]|0,t61=0,v61=s[2]|0,t62=0,v62=s[1]|0,t63=0,v63=s[0]|0;
|
|
|
|
|
|
|
|
for (i = 0; i < l; i++) {
|
|
|
|
c = str.charCodeAt(i);
|
|
|
|
if(c < 128){
|
|
|
|
v0^=c;
|
|
|
|
}else if(c < 2048){
|
|
|
|
v0^=(c>>6)|192;
|
|
|
|
t0=v0*397;t1=v1*397;t2=v2*397;t3=v3*397;t4=v4*397;t5=v5*397;t6=v6*397;t7=v7*397;t8=v8*397;t9=v9*397;t10=v10*397;t11=v11*397;t12=v12*397;t13=v13*397;t14=v14*397;t15=v15*397;t16=v16*397;t17=v17*397;t18=v18*397;t19=v19*397;t20=v20*397;t21=v21*397;t22=v22*397;t23=v23*397;t24=v24*397;t25=v25*397;t26=v26*397;t27=v27*397;t28=v28*397;t29=v29*397;t30=v30*397;t31=v31*397;t32=v32*397;t33=v33*397;t34=v34*397;t35=v35*397;t36=v36*397;t37=v37*397;t38=v38*397;t39=v39*397;t40=v40*397;t41=v41*397;t42=v42*397;t43=v43*397;t44=v44*397;t45=v45*397;t46=v46*397;t47=v47*397;t48=v48*397;t49=v49*397;t50=v50*397;t51=v51*397;t52=v52*397;t53=v53*397;t54=v54*397;t55=v55*397;t56=v56*397;t57=v57*397;t58=v58*397;t59=v59*397;t60=v60*397;t61=v61*397;t62=v62*397;t63=v63*397;
|
|
|
|
t42+=v0<<8;t43+=v1<<8;t44+=v2<<8;t45+=v3<<8;t46+=v4<<8;t47+=v5<<8;t48+=v6<<8;t49+=v7<<8;t50+=v8<<8;t51+=v9<<8;t52+=v10<<8;t53+=v11<<8;t54+=v12<<8;t55+=v13<<8;t56+=v14<<8;t57+=v15<<8;t58+=v16<<8;t59+=v17<<8;t60+=v18<<8;t61+=v19<<8;t62+=v20<<8;t63+=v21<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;t31+=t30>>>16;v30=t30&65535;t32+=t31>>>16;v31=t31&65535;t33+=t32>>>16;v32=t32&65535;t34+=t33>>>16;v33=t33&65535;t35+=t34>>>16;v34=t34&65535;t36+=t35>>>16;v35=t35&65535;t37+=t36>>>16;v36=t36&65535;t38+=t37>>>16;v37=t37&65535;t39+=t38>>>16;v38=t38&65535;t40+=t39>>>16;v39=t39&65535;t41+=t40>>>16;v40=t40&65535;t42+=t41>>>16;v41=t41&65535;t43+=t42>>>16;v42=t42&65535;t44+=t43>>>16;v43=t43&65535;t45+=t44>>>16;v44=t44&65535;t46+=t45>>>16;v45=t45&65535;t47+=t46>>>16;v46=t46&65535;t48+=t47>>>16;v47=t47&65535;t49+=t48>>>16;v48=t48&65535;t50+=t49>>>16;v49=t49&65535;t51+=t50>>>16;v50=t50&65535;t52+=t51>>>16;v51=t51&65535;t53+=t52>>>16;v52=t52&65535;t54+=t53>>>16;v53=t53&65535;t55+=t54>>>16;v54=t54&65535;t56+=t55>>>16;v55=t55&65535;t57+=t56>>>16;v56=t56&65535;t58+=t57>>>16;v57=t57&65535;t59+=t58>>>16;v58=t58&65535;t60+=t59>>>16;v59=t59&65535;t61+=t60>>>16;v60=t60&65535;t62+=t61>>>16;v61=t61&65535;v63=(t63+(t62>>>16))&65535;v62=t62&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else if(((c&64512)==55296)&&(i+1)<l&&((str.charCodeAt(i+1)&64512)==56320)){
|
|
|
|
c=65536+((c&1023)<<10)+(str.charCodeAt(++i)&1023);
|
|
|
|
v0^=(c>>18)|240;
|
|
|
|
t0=v0*397;t1=v1*397;t2=v2*397;t3=v3*397;t4=v4*397;t5=v5*397;t6=v6*397;t7=v7*397;t8=v8*397;t9=v9*397;t10=v10*397;t11=v11*397;t12=v12*397;t13=v13*397;t14=v14*397;t15=v15*397;t16=v16*397;t17=v17*397;t18=v18*397;t19=v19*397;t20=v20*397;t21=v21*397;t22=v22*397;t23=v23*397;t24=v24*397;t25=v25*397;t26=v26*397;t27=v27*397;t28=v28*397;t29=v29*397;t30=v30*397;t31=v31*397;t32=v32*397;t33=v33*397;t34=v34*397;t35=v35*397;t36=v36*397;t37=v37*397;t38=v38*397;t39=v39*397;t40=v40*397;t41=v41*397;t42=v42*397;t43=v43*397;t44=v44*397;t45=v45*397;t46=v46*397;t47=v47*397;t48=v48*397;t49=v49*397;t50=v50*397;t51=v51*397;t52=v52*397;t53=v53*397;t54=v54*397;t55=v55*397;t56=v56*397;t57=v57*397;t58=v58*397;t59=v59*397;t60=v60*397;t61=v61*397;t62=v62*397;t63=v63*397;
|
|
|
|
t42+=v0<<8;t43+=v1<<8;t44+=v2<<8;t45+=v3<<8;t46+=v4<<8;t47+=v5<<8;t48+=v6<<8;t49+=v7<<8;t50+=v8<<8;t51+=v9<<8;t52+=v10<<8;t53+=v11<<8;t54+=v12<<8;t55+=v13<<8;t56+=v14<<8;t57+=v15<<8;t58+=v16<<8;t59+=v17<<8;t60+=v18<<8;t61+=v19<<8;t62+=v20<<8;t63+=v21<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;t31+=t30>>>16;v30=t30&65535;t32+=t31>>>16;v31=t31&65535;t33+=t32>>>16;v32=t32&65535;t34+=t33>>>16;v33=t33&65535;t35+=t34>>>16;v34=t34&65535;t36+=t35>>>16;v35=t35&65535;t37+=t36>>>16;v36=t36&65535;t38+=t37>>>16;v37=t37&65535;t39+=t38>>>16;v38=t38&65535;t40+=t39>>>16;v39=t39&65535;t41+=t40>>>16;v40=t40&65535;t42+=t41>>>16;v41=t41&65535;t43+=t42>>>16;v42=t42&65535;t44+=t43>>>16;v43=t43&65535;t45+=t44>>>16;v44=t44&65535;t46+=t45>>>16;v45=t45&65535;t47+=t46>>>16;v46=t46&65535;t48+=t47>>>16;v47=t47&65535;t49+=t48>>>16;v48=t48&65535;t50+=t49>>>16;v49=t49&65535;t51+=t50>>>16;v50=t50&65535;t52+=t51>>>16;v51=t51&65535;t53+=t52>>>16;v52=t52&65535;t54+=t53>>>16;v53=t53&65535;t55+=t54>>>16;v54=t54&65535;t56+=t55>>>16;v55=t55&65535;t57+=t56>>>16;v56=t56&65535;t58+=t57>>>16;v57=t57&65535;t59+=t58>>>16;v58=t58&65535;t60+=t59>>>16;v59=t59&65535;t61+=t60>>>16;v60=t60&65535;t62+=t61>>>16;v61=t61&65535;v63=(t63+(t62>>>16))&65535;v62=t62&65535;
|
|
|
|
v0^=((c>>12)&63)|128;
|
|
|
|
t0=v0*397;t1=v1*397;t2=v2*397;t3=v3*397;t4=v4*397;t5=v5*397;t6=v6*397;t7=v7*397;t8=v8*397;t9=v9*397;t10=v10*397;t11=v11*397;t12=v12*397;t13=v13*397;t14=v14*397;t15=v15*397;t16=v16*397;t17=v17*397;t18=v18*397;t19=v19*397;t20=v20*397;t21=v21*397;t22=v22*397;t23=v23*397;t24=v24*397;t25=v25*397;t26=v26*397;t27=v27*397;t28=v28*397;t29=v29*397;t30=v30*397;t31=v31*397;t32=v32*397;t33=v33*397;t34=v34*397;t35=v35*397;t36=v36*397;t37=v37*397;t38=v38*397;t39=v39*397;t40=v40*397;t41=v41*397;t42=v42*397;t43=v43*397;t44=v44*397;t45=v45*397;t46=v46*397;t47=v47*397;t48=v48*397;t49=v49*397;t50=v50*397;t51=v51*397;t52=v52*397;t53=v53*397;t54=v54*397;t55=v55*397;t56=v56*397;t57=v57*397;t58=v58*397;t59=v59*397;t60=v60*397;t61=v61*397;t62=v62*397;t63=v63*397;
|
|
|
|
t42+=v0<<8;t43+=v1<<8;t44+=v2<<8;t45+=v3<<8;t46+=v4<<8;t47+=v5<<8;t48+=v6<<8;t49+=v7<<8;t50+=v8<<8;t51+=v9<<8;t52+=v10<<8;t53+=v11<<8;t54+=v12<<8;t55+=v13<<8;t56+=v14<<8;t57+=v15<<8;t58+=v16<<8;t59+=v17<<8;t60+=v18<<8;t61+=v19<<8;t62+=v20<<8;t63+=v21<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;t31+=t30>>>16;v30=t30&65535;t32+=t31>>>16;v31=t31&65535;t33+=t32>>>16;v32=t32&65535;t34+=t33>>>16;v33=t33&65535;t35+=t34>>>16;v34=t34&65535;t36+=t35>>>16;v35=t35&65535;t37+=t36>>>16;v36=t36&65535;t38+=t37>>>16;v37=t37&65535;t39+=t38>>>16;v38=t38&65535;t40+=t39>>>16;v39=t39&65535;t41+=t40>>>16;v40=t40&65535;t42+=t41>>>16;v41=t41&65535;t43+=t42>>>16;v42=t42&65535;t44+=t43>>>16;v43=t43&65535;t45+=t44>>>16;v44=t44&65535;t46+=t45>>>16;v45=t45&65535;t47+=t46>>>16;v46=t46&65535;t48+=t47>>>16;v47=t47&65535;t49+=t48>>>16;v48=t48&65535;t50+=t49>>>16;v49=t49&65535;t51+=t50>>>16;v50=t50&65535;t52+=t51>>>16;v51=t51&65535;t53+=t52>>>16;v52=t52&65535;t54+=t53>>>16;v53=t53&65535;t55+=t54>>>16;v54=t54&65535;t56+=t55>>>16;v55=t55&65535;t57+=t56>>>16;v56=t56&65535;t58+=t57>>>16;v57=t57&65535;t59+=t58>>>16;v58=t58&65535;t60+=t59>>>16;v59=t59&65535;t61+=t60>>>16;v60=t60&65535;t62+=t61>>>16;v61=t61&65535;v63=(t63+(t62>>>16))&65535;v62=t62&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*397;t1=v1*397;t2=v2*397;t3=v3*397;t4=v4*397;t5=v5*397;t6=v6*397;t7=v7*397;t8=v8*397;t9=v9*397;t10=v10*397;t11=v11*397;t12=v12*397;t13=v13*397;t14=v14*397;t15=v15*397;t16=v16*397;t17=v17*397;t18=v18*397;t19=v19*397;t20=v20*397;t21=v21*397;t22=v22*397;t23=v23*397;t24=v24*397;t25=v25*397;t26=v26*397;t27=v27*397;t28=v28*397;t29=v29*397;t30=v30*397;t31=v31*397;t32=v32*397;t33=v33*397;t34=v34*397;t35=v35*397;t36=v36*397;t37=v37*397;t38=v38*397;t39=v39*397;t40=v40*397;t41=v41*397;t42=v42*397;t43=v43*397;t44=v44*397;t45=v45*397;t46=v46*397;t47=v47*397;t48=v48*397;t49=v49*397;t50=v50*397;t51=v51*397;t52=v52*397;t53=v53*397;t54=v54*397;t55=v55*397;t56=v56*397;t57=v57*397;t58=v58*397;t59=v59*397;t60=v60*397;t61=v61*397;t62=v62*397;t63=v63*397;
|
|
|
|
t42+=v0<<8;t43+=v1<<8;t44+=v2<<8;t45+=v3<<8;t46+=v4<<8;t47+=v5<<8;t48+=v6<<8;t49+=v7<<8;t50+=v8<<8;t51+=v9<<8;t52+=v10<<8;t53+=v11<<8;t54+=v12<<8;t55+=v13<<8;t56+=v14<<8;t57+=v15<<8;t58+=v16<<8;t59+=v17<<8;t60+=v18<<8;t61+=v19<<8;t62+=v20<<8;t63+=v21<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;t31+=t30>>>16;v30=t30&65535;t32+=t31>>>16;v31=t31&65535;t33+=t32>>>16;v32=t32&65535;t34+=t33>>>16;v33=t33&65535;t35+=t34>>>16;v34=t34&65535;t36+=t35>>>16;v35=t35&65535;t37+=t36>>>16;v36=t36&65535;t38+=t37>>>16;v37=t37&65535;t39+=t38>>>16;v38=t38&65535;t40+=t39>>>16;v39=t39&65535;t41+=t40>>>16;v40=t40&65535;t42+=t41>>>16;v41=t41&65535;t43+=t42>>>16;v42=t42&65535;t44+=t43>>>16;v43=t43&65535;t45+=t44>>>16;v44=t44&65535;t46+=t45>>>16;v45=t45&65535;t47+=t46>>>16;v46=t46&65535;t48+=t47>>>16;v47=t47&65535;t49+=t48>>>16;v48=t48&65535;t50+=t49>>>16;v49=t49&65535;t51+=t50>>>16;v50=t50&65535;t52+=t51>>>16;v51=t51&65535;t53+=t52>>>16;v52=t52&65535;t54+=t53>>>16;v53=t53&65535;t55+=t54>>>16;v54=t54&65535;t56+=t55>>>16;v55=t55&65535;t57+=t56>>>16;v56=t56&65535;t58+=t57>>>16;v57=t57&65535;t59+=t58>>>16;v58=t58&65535;t60+=t59>>>16;v59=t59&65535;t61+=t60>>>16;v60=t60&65535;t62+=t61>>>16;v61=t61&65535;v63=(t63+(t62>>>16))&65535;v62=t62&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else {
|
|
|
|
v0^=(c>>12)|224;
|
|
|
|
t0=v0*397;t1=v1*397;t2=v2*397;t3=v3*397;t4=v4*397;t5=v5*397;t6=v6*397;t7=v7*397;t8=v8*397;t9=v9*397;t10=v10*397;t11=v11*397;t12=v12*397;t13=v13*397;t14=v14*397;t15=v15*397;t16=v16*397;t17=v17*397;t18=v18*397;t19=v19*397;t20=v20*397;t21=v21*397;t22=v22*397;t23=v23*397;t24=v24*397;t25=v25*397;t26=v26*397;t27=v27*397;t28=v28*397;t29=v29*397;t30=v30*397;t31=v31*397;t32=v32*397;t33=v33*397;t34=v34*397;t35=v35*397;t36=v36*397;t37=v37*397;t38=v38*397;t39=v39*397;t40=v40*397;t41=v41*397;t42=v42*397;t43=v43*397;t44=v44*397;t45=v45*397;t46=v46*397;t47=v47*397;t48=v48*397;t49=v49*397;t50=v50*397;t51=v51*397;t52=v52*397;t53=v53*397;t54=v54*397;t55=v55*397;t56=v56*397;t57=v57*397;t58=v58*397;t59=v59*397;t60=v60*397;t61=v61*397;t62=v62*397;t63=v63*397;
|
|
|
|
t42+=v0<<8;t43+=v1<<8;t44+=v2<<8;t45+=v3<<8;t46+=v4<<8;t47+=v5<<8;t48+=v6<<8;t49+=v7<<8;t50+=v8<<8;t51+=v9<<8;t52+=v10<<8;t53+=v11<<8;t54+=v12<<8;t55+=v13<<8;t56+=v14<<8;t57+=v15<<8;t58+=v16<<8;t59+=v17<<8;t60+=v18<<8;t61+=v19<<8;t62+=v20<<8;t63+=v21<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;t31+=t30>>>16;v30=t30&65535;t32+=t31>>>16;v31=t31&65535;t33+=t32>>>16;v32=t32&65535;t34+=t33>>>16;v33=t33&65535;t35+=t34>>>16;v34=t34&65535;t36+=t35>>>16;v35=t35&65535;t37+=t36>>>16;v36=t36&65535;t38+=t37>>>16;v37=t37&65535;t39+=t38>>>16;v38=t38&65535;t40+=t39>>>16;v39=t39&65535;t41+=t40>>>16;v40=t40&65535;t42+=t41>>>16;v41=t41&65535;t43+=t42>>>16;v42=t42&65535;t44+=t43>>>16;v43=t43&65535;t45+=t44>>>16;v44=t44&65535;t46+=t45>>>16;v45=t45&65535;t47+=t46>>>16;v46=t46&65535;t48+=t47>>>16;v47=t47&65535;t49+=t48>>>16;v48=t48&65535;t50+=t49>>>16;v49=t49&65535;t51+=t50>>>16;v50=t50&65535;t52+=t51>>>16;v51=t51&65535;t53+=t52>>>16;v52=t52&65535;t54+=t53>>>16;v53=t53&65535;t55+=t54>>>16;v54=t54&65535;t56+=t55>>>16;v55=t55&65535;t57+=t56>>>16;v56=t56&65535;t58+=t57>>>16;v57=t57&65535;t59+=t58>>>16;v58=t58&65535;t60+=t59>>>16;v59=t59&65535;t61+=t60>>>16;v60=t60&65535;t62+=t61>>>16;v61=t61&65535;v63=(t63+(t62>>>16))&65535;v62=t62&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*397;t1=v1*397;t2=v2*397;t3=v3*397;t4=v4*397;t5=v5*397;t6=v6*397;t7=v7*397;t8=v8*397;t9=v9*397;t10=v10*397;t11=v11*397;t12=v12*397;t13=v13*397;t14=v14*397;t15=v15*397;t16=v16*397;t17=v17*397;t18=v18*397;t19=v19*397;t20=v20*397;t21=v21*397;t22=v22*397;t23=v23*397;t24=v24*397;t25=v25*397;t26=v26*397;t27=v27*397;t28=v28*397;t29=v29*397;t30=v30*397;t31=v31*397;t32=v32*397;t33=v33*397;t34=v34*397;t35=v35*397;t36=v36*397;t37=v37*397;t38=v38*397;t39=v39*397;t40=v40*397;t41=v41*397;t42=v42*397;t43=v43*397;t44=v44*397;t45=v45*397;t46=v46*397;t47=v47*397;t48=v48*397;t49=v49*397;t50=v50*397;t51=v51*397;t52=v52*397;t53=v53*397;t54=v54*397;t55=v55*397;t56=v56*397;t57=v57*397;t58=v58*397;t59=v59*397;t60=v60*397;t61=v61*397;t62=v62*397;t63=v63*397;
|
|
|
|
t42+=v0<<8;t43+=v1<<8;t44+=v2<<8;t45+=v3<<8;t46+=v4<<8;t47+=v5<<8;t48+=v6<<8;t49+=v7<<8;t50+=v8<<8;t51+=v9<<8;t52+=v10<<8;t53+=v11<<8;t54+=v12<<8;t55+=v13<<8;t56+=v14<<8;t57+=v15<<8;t58+=v16<<8;t59+=v17<<8;t60+=v18<<8;t61+=v19<<8;t62+=v20<<8;t63+=v21<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;t31+=t30>>>16;v30=t30&65535;t32+=t31>>>16;v31=t31&65535;t33+=t32>>>16;v32=t32&65535;t34+=t33>>>16;v33=t33&65535;t35+=t34>>>16;v34=t34&65535;t36+=t35>>>16;v35=t35&65535;t37+=t36>>>16;v36=t36&65535;t38+=t37>>>16;v37=t37&65535;t39+=t38>>>16;v38=t38&65535;t40+=t39>>>16;v39=t39&65535;t41+=t40>>>16;v40=t40&65535;t42+=t41>>>16;v41=t41&65535;t43+=t42>>>16;v42=t42&65535;t44+=t43>>>16;v43=t43&65535;t45+=t44>>>16;v44=t44&65535;t46+=t45>>>16;v45=t45&65535;t47+=t46>>>16;v46=t46&65535;t48+=t47>>>16;v47=t47&65535;t49+=t48>>>16;v48=t48&65535;t50+=t49>>>16;v49=t49&65535;t51+=t50>>>16;v50=t50&65535;t52+=t51>>>16;v51=t51&65535;t53+=t52>>>16;v52=t52&65535;t54+=t53>>>16;v53=t53&65535;t55+=t54>>>16;v54=t54&65535;t56+=t55>>>16;v55=t55&65535;t57+=t56>>>16;v56=t56&65535;t58+=t57>>>16;v57=t57&65535;t59+=t58>>>16;v58=t58&65535;t60+=t59>>>16;v59=t59&65535;t61+=t60>>>16;v60=t60&65535;t62+=t61>>>16;v61=t61&65535;v63=(t63+(t62>>>16))&65535;v62=t62&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}
|
|
|
|
t0=v0*397;t1=v1*397;t2=v2*397;t3=v3*397;t4=v4*397;t5=v5*397;t6=v6*397;t7=v7*397;t8=v8*397;t9=v9*397;t10=v10*397;t11=v11*397;t12=v12*397;t13=v13*397;t14=v14*397;t15=v15*397;t16=v16*397;t17=v17*397;t18=v18*397;t19=v19*397;t20=v20*397;t21=v21*397;t22=v22*397;t23=v23*397;t24=v24*397;t25=v25*397;t26=v26*397;t27=v27*397;t28=v28*397;t29=v29*397;t30=v30*397;t31=v31*397;t32=v32*397;t33=v33*397;t34=v34*397;t35=v35*397;t36=v36*397;t37=v37*397;t38=v38*397;t39=v39*397;t40=v40*397;t41=v41*397;t42=v42*397;t43=v43*397;t44=v44*397;t45=v45*397;t46=v46*397;t47=v47*397;t48=v48*397;t49=v49*397;t50=v50*397;t51=v51*397;t52=v52*397;t53=v53*397;t54=v54*397;t55=v55*397;t56=v56*397;t57=v57*397;t58=v58*397;t59=v59*397;t60=v60*397;t61=v61*397;t62=v62*397;t63=v63*397;
|
|
|
|
t42+=v0<<8;t43+=v1<<8;t44+=v2<<8;t45+=v3<<8;t46+=v4<<8;t47+=v5<<8;t48+=v6<<8;t49+=v7<<8;t50+=v8<<8;t51+=v9<<8;t52+=v10<<8;t53+=v11<<8;t54+=v12<<8;t55+=v13<<8;t56+=v14<<8;t57+=v15<<8;t58+=v16<<8;t59+=v17<<8;t60+=v18<<8;t61+=v19<<8;t62+=v20<<8;t63+=v21<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;t31+=t30>>>16;v30=t30&65535;t32+=t31>>>16;v31=t31&65535;t33+=t32>>>16;v32=t32&65535;t34+=t33>>>16;v33=t33&65535;t35+=t34>>>16;v34=t34&65535;t36+=t35>>>16;v35=t35&65535;t37+=t36>>>16;v36=t36&65535;t38+=t37>>>16;v37=t37&65535;t39+=t38>>>16;v38=t38&65535;t40+=t39>>>16;v39=t39&65535;t41+=t40>>>16;v40=t40&65535;t42+=t41>>>16;v41=t41&65535;t43+=t42>>>16;v42=t42&65535;t44+=t43>>>16;v43=t43&65535;t45+=t44>>>16;v44=t44&65535;t46+=t45>>>16;v45=t45&65535;t47+=t46>>>16;v46=t46&65535;t48+=t47>>>16;v47=t47&65535;t49+=t48>>>16;v48=t48&65535;t50+=t49>>>16;v49=t49&65535;t51+=t50>>>16;v50=t50&65535;t52+=t51>>>16;v51=t51&65535;t53+=t52>>>16;v52=t52&65535;t54+=t53>>>16;v53=t53&65535;t55+=t54>>>16;v54=t54&65535;t56+=t55>>>16;v55=t55&65535;t57+=t56>>>16;v56=t56&65535;t58+=t57>>>16;v57=t57&65535;t59+=t58>>>16;v58=t58&65535;t60+=t59>>>16;v59=t59&65535;t61+=t60>>>16;v60=t60&65535;t62+=t61>>>16;v61=t61&65535;v63=(t63+(t62>>>16))&65535;v62=t62&65535;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hashValHex(hl[v63>>8]+hl[v63&255]+hl[v62>>8]+hl[v62&255]+hl[v61>>8]+hl[v61&255]+hl[v60>>8]+hl[v60&255]+hl[v59>>8]+hl[v59&255]+hl[v58>>8]+hl[v58&255]+hl[v57>>8]+hl[v57&255]+hl[v56>>8]+hl[v56&255]+hl[v55>>8]+hl[v55&255]+hl[v54>>8]+hl[v54&255]+hl[v53>>8]+hl[v53&255]+hl[v52>>8]+hl[v52&255]+hl[v51>>8]+hl[v51&255]+hl[v50>>8]+hl[v50&255]+hl[v49>>8]+hl[v49&255]+hl[v48>>8]+hl[v48&255]+hl[v47>>8]+hl[v47&255]+hl[v46>>8]+hl[v46&255]+hl[v45>>8]+hl[v45&255]+hl[v44>>8]+hl[v44&255]+hl[v43>>8]+hl[v43&255]+hl[v42>>8]+hl[v42&255]+hl[v41>>8]+hl[v41&255]+hl[v40>>8]+hl[v40&255]+hl[v39>>8]+hl[v39&255]+hl[v38>>8]+hl[v38&255]+hl[v37>>8]+hl[v37&255]+hl[v36>>8]+hl[v36&255]+hl[v35>>8]+hl[v35&255]+hl[v34>>8]+hl[v34&255]+hl[v33>>8]+hl[v33&255]+hl[v32>>8]+hl[v32&255]+hl[v31>>8]+hl[v31&255]+hl[v30>>8]+hl[v30&255]+hl[v29>>8]+hl[v29&255]+hl[v28>>8]+hl[v28&255]+hl[v27>>8]+hl[v27&255]+hl[v26>>8]+hl[v26&255]+hl[v25>>8]+hl[v25&255]+hl[v24>>8]+hl[v24&255]+hl[v23>>8]+hl[v23&255]+hl[v22>>8]+hl[v22&255]+hl[v21>>8]+hl[v21&255]+hl[v20>>8]+hl[v20&255]+hl[v19>>8]+hl[v19&255]+hl[v18>>8]+hl[v18&255]+hl[v17>>8]+hl[v17&255]+hl[v16>>8]+hl[v16&255]+hl[v15>>8]+hl[v15&255]+hl[v14>>8]+hl[v14&255]+hl[v13>>8]+hl[v13&255]+hl[v12>>8]+hl[v12&255]+hl[v11>>8]+hl[v11&255]+hl[v10>>8]+hl[v10&255]+hl[v9>>8]+hl[v9&255]+hl[v8>>8]+hl[v8&255]+hl[v7>>8]+hl[v7&255]+hl[v6>>8]+hl[v6&255]+hl[v5>>8]+hl[v5&255]+hl[v4>>8]+hl[v4&255]+hl[v3>>8]+hl[v3&255]+hl[v2>>8]+hl[v2&255]+hl[v1>>8]+hl[v1&255]+hl[v0>>8]+hl[v0&255],1024);
|
|
|
|
}
|
|
|
|
|
|
|
|
function _hash1024_1_utf(str){
|
|
|
|
var c,i,l=str.length,s=fnvConstants[1024].offset,t0=0,v0=s[63]|0,t1=0,v1=s[62]|0,t2=0,v2=s[61]|0,t3=0,v3=s[60]|0,t4=0,v4=s[59]|0,t5=0,v5=s[58]|0,t6=0,v6=s[57]|0,t7=0,v7=s[56]|0,t8=0,v8=s[55]|0,t9=0,v9=s[54]|0,t10=0,v10=s[53]|0,t11=0,v11=s[52]|0,t12=0,v12=s[51]|0,t13=0,v13=s[50]|0,t14=0,v14=s[49]|0,t15=0,v15=s[48]|0,t16=0,v16=s[47]|0,t17=0,v17=s[46]|0,t18=0,v18=s[45]|0,t19=0,v19=s[44]|0,t20=0,v20=s[43]|0,t21=0,v21=s[42]|0,t22=0,v22=s[41]|0,t23=0,v23=s[40]|0,t24=0,v24=s[39]|0,t25=0,v25=s[38]|0,t26=0,v26=s[37]|0,t27=0,v27=s[36]|0,t28=0,v28=s[35]|0,t29=0,v29=s[34]|0,t30=0,v30=s[33]|0,t31=0,v31=s[32]|0,t32=0,v32=s[31]|0,t33=0,v33=s[30]|0,t34=0,v34=s[29]|0,t35=0,v35=s[28]|0,t36=0,v36=s[27]|0,t37=0,v37=s[26]|0,t38=0,v38=s[25]|0,t39=0,v39=s[24]|0,t40=0,v40=s[23]|0,t41=0,v41=s[22]|0,t42=0,v42=s[21]|0,t43=0,v43=s[20]|0,t44=0,v44=s[19]|0,t45=0,v45=s[18]|0,t46=0,v46=s[17]|0,t47=0,v47=s[16]|0,t48=0,v48=s[15]|0,t49=0,v49=s[14]|0,t50=0,v50=s[13]|0,t51=0,v51=s[12]|0,t52=0,v52=s[11]|0,t53=0,v53=s[10]|0,t54=0,v54=s[9]|0,t55=0,v55=s[8]|0,t56=0,v56=s[7]|0,t57=0,v57=s[6]|0,t58=0,v58=s[5]|0,t59=0,v59=s[4]|0,t60=0,v60=s[3]|0,t61=0,v61=s[2]|0,t62=0,v62=s[1]|0,t63=0,v63=s[0]|0;
|
|
|
|
|
|
|
|
for (i = 0; i < l; i++) {
|
|
|
|
c = str.charCodeAt(i);
|
|
|
|
t0=v0*397;t1=v1*397;t2=v2*397;t3=v3*397;t4=v4*397;t5=v5*397;t6=v6*397;t7=v7*397;t8=v8*397;t9=v9*397;t10=v10*397;t11=v11*397;t12=v12*397;t13=v13*397;t14=v14*397;t15=v15*397;t16=v16*397;t17=v17*397;t18=v18*397;t19=v19*397;t20=v20*397;t21=v21*397;t22=v22*397;t23=v23*397;t24=v24*397;t25=v25*397;t26=v26*397;t27=v27*397;t28=v28*397;t29=v29*397;t30=v30*397;t31=v31*397;t32=v32*397;t33=v33*397;t34=v34*397;t35=v35*397;t36=v36*397;t37=v37*397;t38=v38*397;t39=v39*397;t40=v40*397;t41=v41*397;t42=v42*397;t43=v43*397;t44=v44*397;t45=v45*397;t46=v46*397;t47=v47*397;t48=v48*397;t49=v49*397;t50=v50*397;t51=v51*397;t52=v52*397;t53=v53*397;t54=v54*397;t55=v55*397;t56=v56*397;t57=v57*397;t58=v58*397;t59=v59*397;t60=v60*397;t61=v61*397;t62=v62*397;t63=v63*397;
|
|
|
|
t42+=v0<<8;t43+=v1<<8;t44+=v2<<8;t45+=v3<<8;t46+=v4<<8;t47+=v5<<8;t48+=v6<<8;t49+=v7<<8;t50+=v8<<8;t51+=v9<<8;t52+=v10<<8;t53+=v11<<8;t54+=v12<<8;t55+=v13<<8;t56+=v14<<8;t57+=v15<<8;t58+=v16<<8;t59+=v17<<8;t60+=v18<<8;t61+=v19<<8;t62+=v20<<8;t63+=v21<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;t31+=t30>>>16;v30=t30&65535;t32+=t31>>>16;v31=t31&65535;t33+=t32>>>16;v32=t32&65535;t34+=t33>>>16;v33=t33&65535;t35+=t34>>>16;v34=t34&65535;t36+=t35>>>16;v35=t35&65535;t37+=t36>>>16;v36=t36&65535;t38+=t37>>>16;v37=t37&65535;t39+=t38>>>16;v38=t38&65535;t40+=t39>>>16;v39=t39&65535;t41+=t40>>>16;v40=t40&65535;t42+=t41>>>16;v41=t41&65535;t43+=t42>>>16;v42=t42&65535;t44+=t43>>>16;v43=t43&65535;t45+=t44>>>16;v44=t44&65535;t46+=t45>>>16;v45=t45&65535;t47+=t46>>>16;v46=t46&65535;t48+=t47>>>16;v47=t47&65535;t49+=t48>>>16;v48=t48&65535;t50+=t49>>>16;v49=t49&65535;t51+=t50>>>16;v50=t50&65535;t52+=t51>>>16;v51=t51&65535;t53+=t52>>>16;v52=t52&65535;t54+=t53>>>16;v53=t53&65535;t55+=t54>>>16;v54=t54&65535;t56+=t55>>>16;v55=t55&65535;t57+=t56>>>16;v56=t56&65535;t58+=t57>>>16;v57=t57&65535;t59+=t58>>>16;v58=t58&65535;t60+=t59>>>16;v59=t59&65535;t61+=t60>>>16;v60=t60&65535;t62+=t61>>>16;v61=t61&65535;v63=(t63+(t62>>>16))&65535;v62=t62&65535;
|
|
|
|
if(c < 128){
|
|
|
|
v0^=c;
|
|
|
|
}else if(c < 2048){
|
|
|
|
v0^=(c>>6)|192;
|
|
|
|
t0=v0*397;t1=v1*397;t2=v2*397;t3=v3*397;t4=v4*397;t5=v5*397;t6=v6*397;t7=v7*397;t8=v8*397;t9=v9*397;t10=v10*397;t11=v11*397;t12=v12*397;t13=v13*397;t14=v14*397;t15=v15*397;t16=v16*397;t17=v17*397;t18=v18*397;t19=v19*397;t20=v20*397;t21=v21*397;t22=v22*397;t23=v23*397;t24=v24*397;t25=v25*397;t26=v26*397;t27=v27*397;t28=v28*397;t29=v29*397;t30=v30*397;t31=v31*397;t32=v32*397;t33=v33*397;t34=v34*397;t35=v35*397;t36=v36*397;t37=v37*397;t38=v38*397;t39=v39*397;t40=v40*397;t41=v41*397;t42=v42*397;t43=v43*397;t44=v44*397;t45=v45*397;t46=v46*397;t47=v47*397;t48=v48*397;t49=v49*397;t50=v50*397;t51=v51*397;t52=v52*397;t53=v53*397;t54=v54*397;t55=v55*397;t56=v56*397;t57=v57*397;t58=v58*397;t59=v59*397;t60=v60*397;t61=v61*397;t62=v62*397;t63=v63*397;
|
|
|
|
t42+=v0<<8;t43+=v1<<8;t44+=v2<<8;t45+=v3<<8;t46+=v4<<8;t47+=v5<<8;t48+=v6<<8;t49+=v7<<8;t50+=v8<<8;t51+=v9<<8;t52+=v10<<8;t53+=v11<<8;t54+=v12<<8;t55+=v13<<8;t56+=v14<<8;t57+=v15<<8;t58+=v16<<8;t59+=v17<<8;t60+=v18<<8;t61+=v19<<8;t62+=v20<<8;t63+=v21<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;t31+=t30>>>16;v30=t30&65535;t32+=t31>>>16;v31=t31&65535;t33+=t32>>>16;v32=t32&65535;t34+=t33>>>16;v33=t33&65535;t35+=t34>>>16;v34=t34&65535;t36+=t35>>>16;v35=t35&65535;t37+=t36>>>16;v36=t36&65535;t38+=t37>>>16;v37=t37&65535;t39+=t38>>>16;v38=t38&65535;t40+=t39>>>16;v39=t39&65535;t41+=t40>>>16;v40=t40&65535;t42+=t41>>>16;v41=t41&65535;t43+=t42>>>16;v42=t42&65535;t44+=t43>>>16;v43=t43&65535;t45+=t44>>>16;v44=t44&65535;t46+=t45>>>16;v45=t45&65535;t47+=t46>>>16;v46=t46&65535;t48+=t47>>>16;v47=t47&65535;t49+=t48>>>16;v48=t48&65535;t50+=t49>>>16;v49=t49&65535;t51+=t50>>>16;v50=t50&65535;t52+=t51>>>16;v51=t51&65535;t53+=t52>>>16;v52=t52&65535;t54+=t53>>>16;v53=t53&65535;t55+=t54>>>16;v54=t54&65535;t56+=t55>>>16;v55=t55&65535;t57+=t56>>>16;v56=t56&65535;t58+=t57>>>16;v57=t57&65535;t59+=t58>>>16;v58=t58&65535;t60+=t59>>>16;v59=t59&65535;t61+=t60>>>16;v60=t60&65535;t62+=t61>>>16;v61=t61&65535;v63=(t63+(t62>>>16))&65535;v62=t62&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else if(((c&64512)==55296)&&(i+1)<l&&((str.charCodeAt(i+1)&64512)==56320)){
|
|
|
|
c=65536+((c&1023)<<10)+(str.charCodeAt(++i)&1023);
|
|
|
|
v0^=(c>>18)|240;
|
|
|
|
t0=v0*397;t1=v1*397;t2=v2*397;t3=v3*397;t4=v4*397;t5=v5*397;t6=v6*397;t7=v7*397;t8=v8*397;t9=v9*397;t10=v10*397;t11=v11*397;t12=v12*397;t13=v13*397;t14=v14*397;t15=v15*397;t16=v16*397;t17=v17*397;t18=v18*397;t19=v19*397;t20=v20*397;t21=v21*397;t22=v22*397;t23=v23*397;t24=v24*397;t25=v25*397;t26=v26*397;t27=v27*397;t28=v28*397;t29=v29*397;t30=v30*397;t31=v31*397;t32=v32*397;t33=v33*397;t34=v34*397;t35=v35*397;t36=v36*397;t37=v37*397;t38=v38*397;t39=v39*397;t40=v40*397;t41=v41*397;t42=v42*397;t43=v43*397;t44=v44*397;t45=v45*397;t46=v46*397;t47=v47*397;t48=v48*397;t49=v49*397;t50=v50*397;t51=v51*397;t52=v52*397;t53=v53*397;t54=v54*397;t55=v55*397;t56=v56*397;t57=v57*397;t58=v58*397;t59=v59*397;t60=v60*397;t61=v61*397;t62=v62*397;t63=v63*397;
|
|
|
|
t42+=v0<<8;t43+=v1<<8;t44+=v2<<8;t45+=v3<<8;t46+=v4<<8;t47+=v5<<8;t48+=v6<<8;t49+=v7<<8;t50+=v8<<8;t51+=v9<<8;t52+=v10<<8;t53+=v11<<8;t54+=v12<<8;t55+=v13<<8;t56+=v14<<8;t57+=v15<<8;t58+=v16<<8;t59+=v17<<8;t60+=v18<<8;t61+=v19<<8;t62+=v20<<8;t63+=v21<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;t31+=t30>>>16;v30=t30&65535;t32+=t31>>>16;v31=t31&65535;t33+=t32>>>16;v32=t32&65535;t34+=t33>>>16;v33=t33&65535;t35+=t34>>>16;v34=t34&65535;t36+=t35>>>16;v35=t35&65535;t37+=t36>>>16;v36=t36&65535;t38+=t37>>>16;v37=t37&65535;t39+=t38>>>16;v38=t38&65535;t40+=t39>>>16;v39=t39&65535;t41+=t40>>>16;v40=t40&65535;t42+=t41>>>16;v41=t41&65535;t43+=t42>>>16;v42=t42&65535;t44+=t43>>>16;v43=t43&65535;t45+=t44>>>16;v44=t44&65535;t46+=t45>>>16;v45=t45&65535;t47+=t46>>>16;v46=t46&65535;t48+=t47>>>16;v47=t47&65535;t49+=t48>>>16;v48=t48&65535;t50+=t49>>>16;v49=t49&65535;t51+=t50>>>16;v50=t50&65535;t52+=t51>>>16;v51=t51&65535;t53+=t52>>>16;v52=t52&65535;t54+=t53>>>16;v53=t53&65535;t55+=t54>>>16;v54=t54&65535;t56+=t55>>>16;v55=t55&65535;t57+=t56>>>16;v56=t56&65535;t58+=t57>>>16;v57=t57&65535;t59+=t58>>>16;v58=t58&65535;t60+=t59>>>16;v59=t59&65535;t61+=t60>>>16;v60=t60&65535;t62+=t61>>>16;v61=t61&65535;v63=(t63+(t62>>>16))&65535;v62=t62&65535;
|
|
|
|
v0^=((c>>12)&63)|128;
|
|
|
|
t0=v0*397;t1=v1*397;t2=v2*397;t3=v3*397;t4=v4*397;t5=v5*397;t6=v6*397;t7=v7*397;t8=v8*397;t9=v9*397;t10=v10*397;t11=v11*397;t12=v12*397;t13=v13*397;t14=v14*397;t15=v15*397;t16=v16*397;t17=v17*397;t18=v18*397;t19=v19*397;t20=v20*397;t21=v21*397;t22=v22*397;t23=v23*397;t24=v24*397;t25=v25*397;t26=v26*397;t27=v27*397;t28=v28*397;t29=v29*397;t30=v30*397;t31=v31*397;t32=v32*397;t33=v33*397;t34=v34*397;t35=v35*397;t36=v36*397;t37=v37*397;t38=v38*397;t39=v39*397;t40=v40*397;t41=v41*397;t42=v42*397;t43=v43*397;t44=v44*397;t45=v45*397;t46=v46*397;t47=v47*397;t48=v48*397;t49=v49*397;t50=v50*397;t51=v51*397;t52=v52*397;t53=v53*397;t54=v54*397;t55=v55*397;t56=v56*397;t57=v57*397;t58=v58*397;t59=v59*397;t60=v60*397;t61=v61*397;t62=v62*397;t63=v63*397;
|
|
|
|
t42+=v0<<8;t43+=v1<<8;t44+=v2<<8;t45+=v3<<8;t46+=v4<<8;t47+=v5<<8;t48+=v6<<8;t49+=v7<<8;t50+=v8<<8;t51+=v9<<8;t52+=v10<<8;t53+=v11<<8;t54+=v12<<8;t55+=v13<<8;t56+=v14<<8;t57+=v15<<8;t58+=v16<<8;t59+=v17<<8;t60+=v18<<8;t61+=v19<<8;t62+=v20<<8;t63+=v21<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;t31+=t30>>>16;v30=t30&65535;t32+=t31>>>16;v31=t31&65535;t33+=t32>>>16;v32=t32&65535;t34+=t33>>>16;v33=t33&65535;t35+=t34>>>16;v34=t34&65535;t36+=t35>>>16;v35=t35&65535;t37+=t36>>>16;v36=t36&65535;t38+=t37>>>16;v37=t37&65535;t39+=t38>>>16;v38=t38&65535;t40+=t39>>>16;v39=t39&65535;t41+=t40>>>16;v40=t40&65535;t42+=t41>>>16;v41=t41&65535;t43+=t42>>>16;v42=t42&65535;t44+=t43>>>16;v43=t43&65535;t45+=t44>>>16;v44=t44&65535;t46+=t45>>>16;v45=t45&65535;t47+=t46>>>16;v46=t46&65535;t48+=t47>>>16;v47=t47&65535;t49+=t48>>>16;v48=t48&65535;t50+=t49>>>16;v49=t49&65535;t51+=t50>>>16;v50=t50&65535;t52+=t51>>>16;v51=t51&65535;t53+=t52>>>16;v52=t52&65535;t54+=t53>>>16;v53=t53&65535;t55+=t54>>>16;v54=t54&65535;t56+=t55>>>16;v55=t55&65535;t57+=t56>>>16;v56=t56&65535;t58+=t57>>>16;v57=t57&65535;t59+=t58>>>16;v58=t58&65535;t60+=t59>>>16;v59=t59&65535;t61+=t60>>>16;v60=t60&65535;t62+=t61>>>16;v61=t61&65535;v63=(t63+(t62>>>16))&65535;v62=t62&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*397;t1=v1*397;t2=v2*397;t3=v3*397;t4=v4*397;t5=v5*397;t6=v6*397;t7=v7*397;t8=v8*397;t9=v9*397;t10=v10*397;t11=v11*397;t12=v12*397;t13=v13*397;t14=v14*397;t15=v15*397;t16=v16*397;t17=v17*397;t18=v18*397;t19=v19*397;t20=v20*397;t21=v21*397;t22=v22*397;t23=v23*397;t24=v24*397;t25=v25*397;t26=v26*397;t27=v27*397;t28=v28*397;t29=v29*397;t30=v30*397;t31=v31*397;t32=v32*397;t33=v33*397;t34=v34*397;t35=v35*397;t36=v36*397;t37=v37*397;t38=v38*397;t39=v39*397;t40=v40*397;t41=v41*397;t42=v42*397;t43=v43*397;t44=v44*397;t45=v45*397;t46=v46*397;t47=v47*397;t48=v48*397;t49=v49*397;t50=v50*397;t51=v51*397;t52=v52*397;t53=v53*397;t54=v54*397;t55=v55*397;t56=v56*397;t57=v57*397;t58=v58*397;t59=v59*397;t60=v60*397;t61=v61*397;t62=v62*397;t63=v63*397;
|
|
|
|
t42+=v0<<8;t43+=v1<<8;t44+=v2<<8;t45+=v3<<8;t46+=v4<<8;t47+=v5<<8;t48+=v6<<8;t49+=v7<<8;t50+=v8<<8;t51+=v9<<8;t52+=v10<<8;t53+=v11<<8;t54+=v12<<8;t55+=v13<<8;t56+=v14<<8;t57+=v15<<8;t58+=v16<<8;t59+=v17<<8;t60+=v18<<8;t61+=v19<<8;t62+=v20<<8;t63+=v21<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;t31+=t30>>>16;v30=t30&65535;t32+=t31>>>16;v31=t31&65535;t33+=t32>>>16;v32=t32&65535;t34+=t33>>>16;v33=t33&65535;t35+=t34>>>16;v34=t34&65535;t36+=t35>>>16;v35=t35&65535;t37+=t36>>>16;v36=t36&65535;t38+=t37>>>16;v37=t37&65535;t39+=t38>>>16;v38=t38&65535;t40+=t39>>>16;v39=t39&65535;t41+=t40>>>16;v40=t40&65535;t42+=t41>>>16;v41=t41&65535;t43+=t42>>>16;v42=t42&65535;t44+=t43>>>16;v43=t43&65535;t45+=t44>>>16;v44=t44&65535;t46+=t45>>>16;v45=t45&65535;t47+=t46>>>16;v46=t46&65535;t48+=t47>>>16;v47=t47&65535;t49+=t48>>>16;v48=t48&65535;t50+=t49>>>16;v49=t49&65535;t51+=t50>>>16;v50=t50&65535;t52+=t51>>>16;v51=t51&65535;t53+=t52>>>16;v52=t52&65535;t54+=t53>>>16;v53=t53&65535;t55+=t54>>>16;v54=t54&65535;t56+=t55>>>16;v55=t55&65535;t57+=t56>>>16;v56=t56&65535;t58+=t57>>>16;v57=t57&65535;t59+=t58>>>16;v58=t58&65535;t60+=t59>>>16;v59=t59&65535;t61+=t60>>>16;v60=t60&65535;t62+=t61>>>16;v61=t61&65535;v63=(t63+(t62>>>16))&65535;v62=t62&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}else {
|
|
|
|
v0^=(c>>12)|224;
|
|
|
|
t0=v0*397;t1=v1*397;t2=v2*397;t3=v3*397;t4=v4*397;t5=v5*397;t6=v6*397;t7=v7*397;t8=v8*397;t9=v9*397;t10=v10*397;t11=v11*397;t12=v12*397;t13=v13*397;t14=v14*397;t15=v15*397;t16=v16*397;t17=v17*397;t18=v18*397;t19=v19*397;t20=v20*397;t21=v21*397;t22=v22*397;t23=v23*397;t24=v24*397;t25=v25*397;t26=v26*397;t27=v27*397;t28=v28*397;t29=v29*397;t30=v30*397;t31=v31*397;t32=v32*397;t33=v33*397;t34=v34*397;t35=v35*397;t36=v36*397;t37=v37*397;t38=v38*397;t39=v39*397;t40=v40*397;t41=v41*397;t42=v42*397;t43=v43*397;t44=v44*397;t45=v45*397;t46=v46*397;t47=v47*397;t48=v48*397;t49=v49*397;t50=v50*397;t51=v51*397;t52=v52*397;t53=v53*397;t54=v54*397;t55=v55*397;t56=v56*397;t57=v57*397;t58=v58*397;t59=v59*397;t60=v60*397;t61=v61*397;t62=v62*397;t63=v63*397;
|
|
|
|
t42+=v0<<8;t43+=v1<<8;t44+=v2<<8;t45+=v3<<8;t46+=v4<<8;t47+=v5<<8;t48+=v6<<8;t49+=v7<<8;t50+=v8<<8;t51+=v9<<8;t52+=v10<<8;t53+=v11<<8;t54+=v12<<8;t55+=v13<<8;t56+=v14<<8;t57+=v15<<8;t58+=v16<<8;t59+=v17<<8;t60+=v18<<8;t61+=v19<<8;t62+=v20<<8;t63+=v21<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;t31+=t30>>>16;v30=t30&65535;t32+=t31>>>16;v31=t31&65535;t33+=t32>>>16;v32=t32&65535;t34+=t33>>>16;v33=t33&65535;t35+=t34>>>16;v34=t34&65535;t36+=t35>>>16;v35=t35&65535;t37+=t36>>>16;v36=t36&65535;t38+=t37>>>16;v37=t37&65535;t39+=t38>>>16;v38=t38&65535;t40+=t39>>>16;v39=t39&65535;t41+=t40>>>16;v40=t40&65535;t42+=t41>>>16;v41=t41&65535;t43+=t42>>>16;v42=t42&65535;t44+=t43>>>16;v43=t43&65535;t45+=t44>>>16;v44=t44&65535;t46+=t45>>>16;v45=t45&65535;t47+=t46>>>16;v46=t46&65535;t48+=t47>>>16;v47=t47&65535;t49+=t48>>>16;v48=t48&65535;t50+=t49>>>16;v49=t49&65535;t51+=t50>>>16;v50=t50&65535;t52+=t51>>>16;v51=t51&65535;t53+=t52>>>16;v52=t52&65535;t54+=t53>>>16;v53=t53&65535;t55+=t54>>>16;v54=t54&65535;t56+=t55>>>16;v55=t55&65535;t57+=t56>>>16;v56=t56&65535;t58+=t57>>>16;v57=t57&65535;t59+=t58>>>16;v58=t58&65535;t60+=t59>>>16;v59=t59&65535;t61+=t60>>>16;v60=t60&65535;t62+=t61>>>16;v61=t61&65535;v63=(t63+(t62>>>16))&65535;v62=t62&65535;
|
|
|
|
v0^=((c>>6)&63)|128;
|
|
|
|
t0=v0*397;t1=v1*397;t2=v2*397;t3=v3*397;t4=v4*397;t5=v5*397;t6=v6*397;t7=v7*397;t8=v8*397;t9=v9*397;t10=v10*397;t11=v11*397;t12=v12*397;t13=v13*397;t14=v14*397;t15=v15*397;t16=v16*397;t17=v17*397;t18=v18*397;t19=v19*397;t20=v20*397;t21=v21*397;t22=v22*397;t23=v23*397;t24=v24*397;t25=v25*397;t26=v26*397;t27=v27*397;t28=v28*397;t29=v29*397;t30=v30*397;t31=v31*397;t32=v32*397;t33=v33*397;t34=v34*397;t35=v35*397;t36=v36*397;t37=v37*397;t38=v38*397;t39=v39*397;t40=v40*397;t41=v41*397;t42=v42*397;t43=v43*397;t44=v44*397;t45=v45*397;t46=v46*397;t47=v47*397;t48=v48*397;t49=v49*397;t50=v50*397;t51=v51*397;t52=v52*397;t53=v53*397;t54=v54*397;t55=v55*397;t56=v56*397;t57=v57*397;t58=v58*397;t59=v59*397;t60=v60*397;t61=v61*397;t62=v62*397;t63=v63*397;
|
|
|
|
t42+=v0<<8;t43+=v1<<8;t44+=v2<<8;t45+=v3<<8;t46+=v4<<8;t47+=v5<<8;t48+=v6<<8;t49+=v7<<8;t50+=v8<<8;t51+=v9<<8;t52+=v10<<8;t53+=v11<<8;t54+=v12<<8;t55+=v13<<8;t56+=v14<<8;t57+=v15<<8;t58+=v16<<8;t59+=v17<<8;t60+=v18<<8;t61+=v19<<8;t62+=v20<<8;t63+=v21<<8;
|
|
|
|
t1+=t0>>>16;v0=t0&65535;t2+=t1>>>16;v1=t1&65535;t3+=t2>>>16;v2=t2&65535;t4+=t3>>>16;v3=t3&65535;t5+=t4>>>16;v4=t4&65535;t6+=t5>>>16;v5=t5&65535;t7+=t6>>>16;v6=t6&65535;t8+=t7>>>16;v7=t7&65535;t9+=t8>>>16;v8=t8&65535;t10+=t9>>>16;v9=t9&65535;t11+=t10>>>16;v10=t10&65535;t12+=t11>>>16;v11=t11&65535;t13+=t12>>>16;v12=t12&65535;t14+=t13>>>16;v13=t13&65535;t15+=t14>>>16;v14=t14&65535;t16+=t15>>>16;v15=t15&65535;t17+=t16>>>16;v16=t16&65535;t18+=t17>>>16;v17=t17&65535;t19+=t18>>>16;v18=t18&65535;t20+=t19>>>16;v19=t19&65535;t21+=t20>>>16;v20=t20&65535;t22+=t21>>>16;v21=t21&65535;t23+=t22>>>16;v22=t22&65535;t24+=t23>>>16;v23=t23&65535;t25+=t24>>>16;v24=t24&65535;t26+=t25>>>16;v25=t25&65535;t27+=t26>>>16;v26=t26&65535;t28+=t27>>>16;v27=t27&65535;t29+=t28>>>16;v28=t28&65535;t30+=t29>>>16;v29=t29&65535;t31+=t30>>>16;v30=t30&65535;t32+=t31>>>16;v31=t31&65535;t33+=t32>>>16;v32=t32&65535;t34+=t33>>>16;v33=t33&65535;t35+=t34>>>16;v34=t34&65535;t36+=t35>>>16;v35=t35&65535;t37+=t36>>>16;v36=t36&65535;t38+=t37>>>16;v37=t37&65535;t39+=t38>>>16;v38=t38&65535;t40+=t39>>>16;v39=t39&65535;t41+=t40>>>16;v40=t40&65535;t42+=t41>>>16;v41=t41&65535;t43+=t42>>>16;v42=t42&65535;t44+=t43>>>16;v43=t43&65535;t45+=t44>>>16;v44=t44&65535;t46+=t45>>>16;v45=t45&65535;t47+=t46>>>16;v46=t46&65535;t48+=t47>>>16;v47=t47&65535;t49+=t48>>>16;v48=t48&65535;t50+=t49>>>16;v49=t49&65535;t51+=t50>>>16;v50=t50&65535;t52+=t51>>>16;v51=t51&65535;t53+=t52>>>16;v52=t52&65535;t54+=t53>>>16;v53=t53&65535;t55+=t54>>>16;v54=t54&65535;t56+=t55>>>16;v55=t55&65535;t57+=t56>>>16;v56=t56&65535;t58+=t57>>>16;v57=t57&65535;t59+=t58>>>16;v58=t58&65535;t60+=t59>>>16;v59=t59&65535;t61+=t60>>>16;v60=t60&65535;t62+=t61>>>16;v61=t61&65535;v63=(t63+(t62>>>16))&65535;v62=t62&65535;
|
|
|
|
v0^=(c&63)|128;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return hashValHex(hl[v63>>8]+hl[v63&255]+hl[v62>>8]+hl[v62&255]+hl[v61>>8]+hl[v61&255]+hl[v60>>8]+hl[v60&255]+hl[v59>>8]+hl[v59&255]+hl[v58>>8]+hl[v58&255]+hl[v57>>8]+hl[v57&255]+hl[v56>>8]+hl[v56&255]+hl[v55>>8]+hl[v55&255]+hl[v54>>8]+hl[v54&255]+hl[v53>>8]+hl[v53&255]+hl[v52>>8]+hl[v52&255]+hl[v51>>8]+hl[v51&255]+hl[v50>>8]+hl[v50&255]+hl[v49>>8]+hl[v49&255]+hl[v48>>8]+hl[v48&255]+hl[v47>>8]+hl[v47&255]+hl[v46>>8]+hl[v46&255]+hl[v45>>8]+hl[v45&255]+hl[v44>>8]+hl[v44&255]+hl[v43>>8]+hl[v43&255]+hl[v42>>8]+hl[v42&255]+hl[v41>>8]+hl[v41&255]+hl[v40>>8]+hl[v40&255]+hl[v39>>8]+hl[v39&255]+hl[v38>>8]+hl[v38&255]+hl[v37>>8]+hl[v37&255]+hl[v36>>8]+hl[v36&255]+hl[v35>>8]+hl[v35&255]+hl[v34>>8]+hl[v34&255]+hl[v33>>8]+hl[v33&255]+hl[v32>>8]+hl[v32&255]+hl[v31>>8]+hl[v31&255]+hl[v30>>8]+hl[v30&255]+hl[v29>>8]+hl[v29&255]+hl[v28>>8]+hl[v28&255]+hl[v27>>8]+hl[v27&255]+hl[v26>>8]+hl[v26&255]+hl[v25>>8]+hl[v25&255]+hl[v24>>8]+hl[v24&255]+hl[v23>>8]+hl[v23&255]+hl[v22>>8]+hl[v22&255]+hl[v21>>8]+hl[v21&255]+hl[v20>>8]+hl[v20&255]+hl[v19>>8]+hl[v19&255]+hl[v18>>8]+hl[v18&255]+hl[v17>>8]+hl[v17&255]+hl[v16>>8]+hl[v16&255]+hl[v15>>8]+hl[v15&255]+hl[v14>>8]+hl[v14&255]+hl[v13>>8]+hl[v13&255]+hl[v12>>8]+hl[v12&255]+hl[v11>>8]+hl[v11&255]+hl[v10>>8]+hl[v10&255]+hl[v9>>8]+hl[v9&255]+hl[v8>>8]+hl[v8&255]+hl[v7>>8]+hl[v7&255]+hl[v6>>8]+hl[v6&255]+hl[v5>>8]+hl[v5&255]+hl[v4>>8]+hl[v4&255]+hl[v3>>8]+hl[v3&255]+hl[v2>>8]+hl[v2&255]+hl[v1>>8]+hl[v1&255]+hl[v0>>8]+hl[v0&255],1024);
|
|
|
|
}
|
|
|
|
|
|
|
|
_hash1024 = _hash1024_1a;
|
|
|
|
|
|
|
|
// Init library.
|
|
|
|
setVersion('1a');
|
|
|
|
setUTF8(false);
|
|
|
|
seed();
|
|
|
|
|
|
|
|
return {
|
|
|
|
hash: hash,
|
|
|
|
setKeyspace: setKeyspace,
|
|
|
|
version: setVersion,
|
|
|
|
useUTF8: setUTF8,
|
|
|
|
seed: seed,
|
|
|
|
fast1a32: _hash32_1a_fast,
|
|
|
|
fast1a32hex:_hash32_1a_fast_hex,
|
|
|
|
fast1a52: _hash52_1a_fast,
|
|
|
|
fast1a52hex: _hash52_1a_fast_hex,
|
|
|
|
fast1a64: _hash64_1a_fast,
|
|
|
|
fast1a32utf: _hash32_1a_fast_utf,
|
|
|
|
fast1a32hexutf:_hash32_1a_fast_hex_utf,
|
|
|
|
fast1a52utf: _hash52_1a_fast_utf,
|
|
|
|
fast1a52hexutf: _hash52_1a_fast_hex_utf,
|
|
|
|
fast1a64utf: _hash64_1a_fast_utf
|
|
|
|
};
|
|
|
|
})();
|
|
|
|
|
|
|
|
module.exports = fnvplus;
|
|
|
|
});
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
Copyright 2020 0KIMS association.
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var fnvHash_1 = fnvHash;
|
|
|
|
var flatArray_1 = flatArray;
|
|
|
|
|
|
|
|
function flatArray(a) {
|
|
|
|
var res = [];
|
|
|
|
fillArray(res, a);
|
|
|
|
return res;
|
|
|
|
|
|
|
|
function fillArray(res, a) {
|
|
|
|
if (Array.isArray(a)) {
|
|
|
|
for (let i=0; i<a.length; i++) {
|
|
|
|
fillArray(res, a[i]);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
res.push(a);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function fnvHash(str) {
|
|
|
|
return fnvPlus.hash(str, 64).hex();
|
|
|
|
}
|
|
|
|
|
|
|
|
var utils$2 = {
|
|
|
|
fnvHash: fnvHash_1,
|
|
|
|
flatArray: flatArray_1
|
|
|
|
};
|
|
|
|
|
|
|
|
/* globals WebAssembly */
|
|
|
|
/*
|
|
|
|
|
|
|
|
Copyright 2020 0KIMS association.
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
const Scalar$2 = main.Scalar;
|
|
|
|
const F1Field$1 = main.F1Field;
|
|
|
|
|
|
|
|
|
|
|
|
var witness_calculator = async function builder(code, options) {
|
|
|
|
|
|
|
|
options = options || {};
|
|
|
|
|
|
|
|
const memory = new WebAssembly.Memory({initial:20000});
|
|
|
|
const wasmModule = await WebAssembly.compile(code);
|
|
|
|
|
|
|
|
let wc;
|
|
|
|
|
|
|
|
const instance = await WebAssembly.instantiate(wasmModule, {
|
|
|
|
env: {
|
|
|
|
"memory": memory
|
|
|
|
},
|
|
|
|
runtime: {
|
|
|
|
error: function(code, pstr, a,b,c,d) {
|
|
|
|
let errStr;
|
|
|
|
if (code == 7) {
|
|
|
|
errStr=p2str(pstr) + " " + wc.getFr(b).toString() + " != " + wc.getFr(c).toString() + " " +p2str(d);
|
|
|
|
} else {
|
|
|
|
errStr=p2str(pstr)+ " " + a + " " + b + " " + c + " " + d;
|
|
|
|
}
|
|
|
|
console.log("ERROR: ", code, errStr);
|
|
|
|
throw new Error(errStr);
|
|
|
|
},
|
|
|
|
log: function(a) {
|
|
|
|
console.log(wc.getFr(a).toString());
|
|
|
|
},
|
|
|
|
logGetSignal: function(signal, pVal) {
|
|
|
|
if (options.logGetSignal) {
|
|
|
|
options.logGetSignal(signal, wc.getFr(pVal) );
|
|
|
|
}
|
|
|
|
},
|
|
|
|
logSetSignal: function(signal, pVal) {
|
|
|
|
if (options.logSetSignal) {
|
|
|
|
options.logSetSignal(signal, wc.getFr(pVal) );
|
|
|
|
}
|
|
|
|
},
|
|
|
|
logStartComponent: function(cIdx) {
|
|
|
|
if (options.logStartComponent) {
|
|
|
|
options.logStartComponent(cIdx);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
logFinishComponent: function(cIdx) {
|
|
|
|
if (options.logFinishComponent) {
|
|
|
|
options.logFinishComponent(cIdx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
const sanityCheck =
|
|
|
|
options &&
|
|
|
|
(
|
|
|
|
options.sanityCheck ||
|
|
|
|
options.logGetSignal ||
|
|
|
|
options.logSetSignal ||
|
|
|
|
options.logStartComponent ||
|
|
|
|
options.logFinishComponent
|
|
|
|
);
|
|
|
|
|
|
|
|
wc = new WitnessCalculator(memory, instance, sanityCheck);
|
|
|
|
return wc;
|
|
|
|
|
|
|
|
function p2str(p) {
|
|
|
|
const i8 = new Uint8Array(memory.buffer);
|
|
|
|
|
|
|
|
const bytes = [];
|
|
|
|
|
|
|
|
for (let i=0; i8[p+i]>0; i++) bytes.push(i8[p+i]);
|
|
|
|
|
|
|
|
return String.fromCharCode.apply(null, bytes);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class WitnessCalculator {
|
|
|
|
constructor(memory, instance, sanityCheck) {
|
|
|
|
this.memory = memory;
|
|
|
|
this.i32 = new Uint32Array(memory.buffer);
|
|
|
|
this.instance = instance;
|
|
|
|
|
|
|
|
this.n32 = (this.instance.exports.getFrLen() >> 2) - 2;
|
|
|
|
const pRawPrime = this.instance.exports.getPRawPrime();
|
|
|
|
|
|
|
|
const arr = new Array(this.n32);
|
|
|
|
for (let i=0; i<this.n32; i++) {
|
|
|
|
arr[this.n32-1-i] = this.i32[(pRawPrime >> 2) + i];
|
|
|
|
}
|
|
|
|
|
|
|
|
this.prime = Scalar$2.fromArray(arr, 0x100000000);
|
|
|
|
|
|
|
|
this.Fr = new F1Field$1(this.prime);
|
|
|
|
|
|
|
|
this.mask32 = Scalar$2.fromString("FFFFFFFF", 16);
|
|
|
|
this.NVars = this.instance.exports.getNVars();
|
|
|
|
this.n64 = Math.floor((this.Fr.bitLength - 1) / 64)+1;
|
|
|
|
this.R = this.Fr.e( Scalar$2.shiftLeft(1 , this.n64*64));
|
|
|
|
this.RInv = this.Fr.inv(this.R);
|
|
|
|
this.sanityCheck = sanityCheck;
|
|
|
|
}
|
|
|
|
|
|
|
|
async _doCalculateWitness(input, sanityCheck) {
|
|
|
|
this.instance.exports.init((this.sanityCheck || sanityCheck) ? 1 : 0);
|
|
|
|
const pSigOffset = this.allocInt();
|
|
|
|
const pFr = this.allocFr();
|
|
|
|
const keys = Object.keys(input);
|
|
|
|
keys.forEach( (k) => {
|
|
|
|
const h = utils$2.fnvHash(k);
|
|
|
|
const hMSB = parseInt(h.slice(0,8), 16);
|
|
|
|
const hLSB = parseInt(h.slice(8,16), 16);
|
|
|
|
try {
|
|
|
|
this.instance.exports.getSignalOffset32(pSigOffset, 0, hMSB, hLSB);
|
|
|
|
} catch (err) {
|
|
|
|
throw new Error(`Signal ${k} is not an input of the circuit.`);
|
|
|
|
}
|
|
|
|
const sigOffset = this.getInt(pSigOffset);
|
|
|
|
const fArr = utils$2.flatArray(input[k]);
|
|
|
|
for (let i=0; i<fArr.length; i++) {
|
|
|
|
this.setFr(pFr, fArr[i]);
|
|
|
|
this.instance.exports.setSignal(0, 0, sigOffset + i, pFr);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
async calculateWitness(input, sanityCheck) {
|
|
|
|
const self = this;
|
|
|
|
|
|
|
|
const old0 = self.i32[0];
|
|
|
|
const w = [];
|
|
|
|
|
|
|
|
await self._doCalculateWitness(input, sanityCheck);
|
|
|
|
|
|
|
|
for (let i=0; i<self.NVars; i++) {
|
|
|
|
const pWitness = self.instance.exports.getPWitness(i);
|
|
|
|
w.push(self.getFr(pWitness));
|
|
|
|
}
|
|
|
|
|
|
|
|
self.i32[0] = old0;
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
|
|
|
async calculateBinWitness(input, sanityCheck) {
|
|
|
|
const self = this;
|
|
|
|
|
|
|
|
const old0 = self.i32[0];
|
|
|
|
|
|
|
|
await self._doCalculateWitness(input, sanityCheck);
|
|
|
|
|
|
|
|
const pWitnessBuffer = self.instance.exports.getWitnessBuffer();
|
|
|
|
|
|
|
|
self.i32[0] = old0;
|
|
|
|
|
|
|
|
const buff = self.memory.buffer.slice(pWitnessBuffer, pWitnessBuffer + (self.NVars * self.n64 * 8));
|
|
|
|
return new Uint8Array(buff);
|
|
|
|
}
|
|
|
|
|
|
|
|
allocInt() {
|
|
|
|
const p = this.i32[0];
|
|
|
|
this.i32[0] = p+8;
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
allocFr() {
|
|
|
|
const p = this.i32[0];
|
|
|
|
this.i32[0] = p+this.n32*4 + 8;
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
getInt(p) {
|
|
|
|
return this.i32[p>>2];
|
|
|
|
}
|
|
|
|
|
|
|
|
setInt(p, v) {
|
|
|
|
this.i32[p>>2] = v;
|
|
|
|
}
|
|
|
|
|
|
|
|
getFr(p) {
|
|
|
|
const self = this;
|
|
|
|
const idx = (p>>2);
|
|
|
|
|
|
|
|
if (self.i32[idx + 1] & 0x80000000) {
|
|
|
|
const arr = new Array(self.n32);
|
|
|
|
for (let i=0; i<self.n32; i++) {
|
|
|
|
arr[self.n32-1-i] = self.i32[idx+2+i];
|
|
|
|
}
|
|
|
|
const res = self.Fr.e(Scalar$2.fromArray(arr, 0x100000000));
|
|
|
|
if (self.i32[idx + 1] & 0x40000000) {
|
|
|
|
return fromMontgomery(res);
|
|
|
|
} else {
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
if (self.i32[idx] & 0x80000000) {
|
|
|
|
return self.Fr.e( self.i32[idx] - 0x100000000);
|
|
|
|
} else {
|
|
|
|
return self.Fr.e(self.i32[idx]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function fromMontgomery(n) {
|
|
|
|
return self.Fr.mul(self.RInv, n);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
setFr(p, v) {
|
|
|
|
const self = this;
|
|
|
|
|
|
|
|
v = self.Fr.e(v);
|
|
|
|
|
|
|
|
const minShort = self.Fr.neg(self.Fr.e("80000000", 16));
|
|
|
|
const maxShort = self.Fr.e("7FFFFFFF", 16);
|
|
|
|
|
|
|
|
if ( (self.Fr.geq(v, minShort))
|
|
|
|
&&(self.Fr.leq(v, maxShort)))
|
|
|
|
{
|
|
|
|
let a;
|
|
|
|
if (self.Fr.geq(v, self.Fr.zero)) {
|
|
|
|
a = Scalar$2.toNumber(v);
|
|
|
|
} else {
|
|
|
|
a = Scalar$2.toNumber( self.Fr.sub(v, minShort));
|
|
|
|
a = a - 0x80000000;
|
|
|
|
a = 0x100000000 + a;
|
|
|
|
}
|
|
|
|
self.i32[(p >> 2)] = a;
|
|
|
|
self.i32[(p >> 2) + 1] = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.i32[(p >> 2)] = 0;
|
|
|
|
self.i32[(p >> 2) + 1] = 0x80000000;
|
|
|
|
const arr = Scalar$2.toArray(v, 0x100000000);
|
|
|
|
for (let i=0; i<self.n32; i++) {
|
|
|
|
const idx = arr.length-1-i;
|
|
|
|
|
|
|
|
if ( idx >=0) {
|
|
|
|
self.i32[(p >> 2) + 2 + i] = arr[idx];
|
|
|
|
} else {
|
|
|
|
self.i32[(p >> 2) + 2 + i] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var WitnessCalculatorBuilder = witness_calculator;
|
|
|
|
|
|
|
|
var circom_runtime = {
|
|
|
|
WitnessCalculatorBuilder: WitnessCalculatorBuilder
|
|
|
|
};
|
|
|
|
|
|
|
|
const { WitnessCalculatorBuilder: WitnessCalculatorBuilder$1 } = circom_runtime;
|
|
|
|
|
|
|
|
async function wtnsCalculate(input, wasmFileName, wtnsFileName, options) {
|
|
|
|
|
|
|
|
const fdWasm = await readExisting$1(wasmFileName);
|
|
|
|
const wasm = await fdWasm.read(fdWasm.totalSize);
|
|
|
|
await fdWasm.close();
|
|
|
|
|
|
|
|
const wc = await WitnessCalculatorBuilder$1(wasm);
|
|
|
|
const w = await wc.calculateBinWitness(input);
|
|
|
|
|
|
|
|
const fdWtns = await createBinFile(wtnsFileName, "wtns", 2, 2);
|
|
|
|
|
|
|
|
await writeBin(fdWtns, w, wc.prime);
|
|
|
|
await fdWtns.close();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-07-13 07:21:03 +02:00
|
|
|
async function groth16FullProve(input, wasmFile, zkeyFileName, logger) {
|
2020-07-11 10:31:52 +02:00
|
|
|
const wtns= {
|
|
|
|
type: "mem"
|
|
|
|
};
|
|
|
|
await wtnsCalculate(input, wasmFile, wtns);
|
2020-07-13 07:21:03 +02:00
|
|
|
return await groth16Prove(zkeyFileName, wtns);
|
2020-07-11 10:31:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Copyright 2018 0kims association.
|
|
|
|
|
|
|
|
This file is part of snarkjs.
|
|
|
|
|
|
|
|
snarkjs 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.
|
|
|
|
|
|
|
|
snarkjs 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
|
|
|
|
snarkjs. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
const {unstringifyBigInts: unstringifyBigInts$3} = utils$1;
|
|
|
|
|
2020-07-13 07:21:03 +02:00
|
|
|
async function groth16Verify(vk_verifier, publicSignals, proof, logger) {
|
2020-07-11 10:31:52 +02:00
|
|
|
/*
|
|
|
|
let cpub = vk_verifier.IC[0];
|
|
|
|
for (let s= 0; s< vk_verifier.nPublic; s++) {
|
|
|
|
cpub = G1.add( cpub, G1.timesScalar( vk_verifier.IC[s+1], publicSignals[s]));
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
vk_verifier = unstringifyBigInts$3(vk_verifier);
|
|
|
|
proof = unstringifyBigInts$3(proof);
|
|
|
|
publicSignals = unstringifyBigInts$3(publicSignals);
|
|
|
|
|
|
|
|
const curve = await getCurveFromName(vk_verifier.curve);
|
|
|
|
|
|
|
|
const IC0 = curve.G1.fromObject(vk_verifier.IC[0]);
|
|
|
|
const IC = new Uint8Array(curve.G1.F.n8*2 * publicSignals.length);
|
|
|
|
const w = new Uint8Array(curve.Fr.n8 * publicSignals.length);
|
|
|
|
|
|
|
|
for (let i=0; i<publicSignals.length; i++) {
|
|
|
|
const buffP = curve.G1.fromObject(vk_verifier.IC[i+1]);
|
|
|
|
IC.set(buffP, i*curve.G1.F.n8*2);
|
|
|
|
Scalar$1.toRprLE(w, curve.Fr.n8*i, publicSignals[i], curve.Fr.n8);
|
|
|
|
}
|
|
|
|
|
|
|
|
let cpub = await curve.G1.multiExpAffine(IC, w);
|
|
|
|
cpub = curve.G1.add(cpub, IC0);
|
|
|
|
|
|
|
|
const pi_a = curve.G1.fromObject(proof.pi_a);
|
|
|
|
const pi_b = curve.G2.fromObject(proof.pi_b);
|
|
|
|
const pi_c = curve.G1.fromObject(proof.pi_c);
|
|
|
|
|
|
|
|
const vk_gamma_2 = curve.G2.fromObject(vk_verifier.vk_gamma_2);
|
|
|
|
const vk_delta_2 = curve.G2.fromObject(vk_verifier.vk_delta_2);
|
|
|
|
const vk_alpha_1 = curve.G1.fromObject(vk_verifier.vk_alpha_1);
|
|
|
|
const vk_beta_2 = curve.G2.fromObject(vk_verifier.vk_beta_2);
|
|
|
|
|
|
|
|
const res = await curve.pairingEq(
|
|
|
|
curve.G1.neg(pi_a) , pi_b,
|
|
|
|
cpub , vk_gamma_2,
|
|
|
|
pi_c , vk_delta_2,
|
|
|
|
|
|
|
|
vk_alpha_1, vk_beta_2
|
|
|
|
);
|
|
|
|
|
|
|
|
if (! res) {
|
|
|
|
if (logger) logger.error("Invalid proof");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (logger) logger.info("OK!");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
var groth16 = /*#__PURE__*/Object.freeze({
|
|
|
|
__proto__: null,
|
2020-07-13 07:21:03 +02:00
|
|
|
fullProve: groth16FullProve,
|
|
|
|
prove: groth16Prove,
|
|
|
|
verify: groth16Verify
|
2020-07-11 10:31:52 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
function hashToG2(curve, hash) {
|
|
|
|
const hashV = new DataView(hash.buffer, hash.byteOffset, hash.byteLength);
|
|
|
|
const seed = [];
|
|
|
|
for (let i=0; i<8; i++) {
|
|
|
|
seed[i] = hashV.getUint32(i*4);
|
|
|
|
}
|
|
|
|
|
|
|
|
const rng = new ChaCha(seed);
|
|
|
|
|
|
|
|
const g2_sp = curve.G2.fromRng(rng);
|
|
|
|
|
|
|
|
return g2_sp;
|
|
|
|
}
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
function getG2sp(curve, persinalization, challenge, g1s, g1sx) {
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
const h = blake2bWasm(64);
|
|
|
|
const b1 = new Uint8Array([persinalization]);
|
|
|
|
h.update(b1);
|
2020-07-14 11:55:12 +02:00
|
|
|
h.update(challenge);
|
2020-07-11 10:31:52 +02:00
|
|
|
const b3 = curve.G1.toUncompressed(g1s);
|
|
|
|
h.update( b3);
|
|
|
|
const b4 = curve.G1.toUncompressed(g1sx);
|
|
|
|
h.update( b4);
|
|
|
|
const hash =h.digest();
|
|
|
|
|
|
|
|
return hashToG2(curve, hash);
|
|
|
|
}
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
function calculatePubKey(k, curve, personalization, challengeHash, rng ) {
|
2020-07-11 10:31:52 +02:00
|
|
|
k.g1_s = curve.G1.toAffine(curve.G1.fromRng(rng));
|
|
|
|
k.g1_sx = curve.G1.toAffine(curve.G1.timesFr(k.g1_s, k.prvKey));
|
2020-07-14 11:55:12 +02:00
|
|
|
k.g2_sp = curve.G2.toAffine(getG2sp(curve, personalization, challengeHash, k.g1_s, k.g1_sx));
|
2020-07-11 10:31:52 +02:00
|
|
|
k.g2_spx = curve.G2.toAffine(curve.G2.timesFr(k.g2_sp, k.prvKey));
|
|
|
|
return k;
|
|
|
|
}
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
function createPTauKey(curve, challengeHash, rng) {
|
2020-07-11 10:31:52 +02:00
|
|
|
const key = {
|
|
|
|
tau: {},
|
|
|
|
alpha: {},
|
|
|
|
beta: {}
|
|
|
|
};
|
|
|
|
key.tau.prvKey = curve.Fr.fromRng(rng);
|
|
|
|
key.alpha.prvKey = curve.Fr.fromRng(rng);
|
|
|
|
key.beta.prvKey = curve.Fr.fromRng(rng);
|
2020-07-14 11:55:12 +02:00
|
|
|
calculatePubKey(key.tau, curve, 0, challengeHash, rng);
|
|
|
|
calculatePubKey(key.alpha, curve, 1, challengeHash, rng);
|
|
|
|
calculatePubKey(key.beta, curve, 2, challengeHash, rng);
|
2020-07-11 10:31:52 +02:00
|
|
|
return key;
|
|
|
|
}
|
|
|
|
|
|
|
|
async function writePTauHeader(fd, curve, power, ceremonyPower) {
|
|
|
|
// Write the header
|
|
|
|
///////////
|
|
|
|
|
|
|
|
if (! ceremonyPower) ceremonyPower = power;
|
|
|
|
await fd.writeULE32(1); // Header type
|
|
|
|
const pHeaderSize = fd.pos;
|
|
|
|
await fd.writeULE64(0); // Temporally set to 0 length
|
|
|
|
|
|
|
|
await fd.writeULE32(curve.F1.n64*8);
|
|
|
|
|
|
|
|
const buff = new Uint8Array(curve.F1.n8);
|
|
|
|
Scalar$1.toRprLE(buff, 0, curve.q, curve.F1.n8);
|
|
|
|
await fd.write(buff);
|
|
|
|
await fd.writeULE32(power); // power
|
|
|
|
await fd.writeULE32(ceremonyPower); // power
|
|
|
|
|
|
|
|
const headerSize = fd.pos - pHeaderSize - 8;
|
|
|
|
|
|
|
|
const oldPos = fd.pos;
|
|
|
|
|
2020-07-28 13:16:43 +02:00
|
|
|
await fd.writeULE64(headerSize, pHeaderSize);
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
fd.pos = oldPos;
|
|
|
|
}
|
|
|
|
|
|
|
|
async function readPTauHeader(fd, sections) {
|
|
|
|
if (!sections[1]) throw new Error(fd.fileName + ": File has no header");
|
|
|
|
if (sections[1].length>1) throw new Error(fd.fileName +": File has more than one header");
|
|
|
|
|
|
|
|
fd.pos = sections[1][0].p;
|
|
|
|
const n8 = await fd.readULE32();
|
|
|
|
const buff = await fd.read(n8);
|
|
|
|
const q = Scalar$1.fromRprLE(buff);
|
|
|
|
|
|
|
|
const curve = await getCurveFromQ(q);
|
|
|
|
|
|
|
|
if (curve.F1.n64*8 != n8) throw new Error(fd.fileName +": Invalid size");
|
|
|
|
|
|
|
|
const power = await fd.readULE32();
|
|
|
|
const ceremonyPower = await fd.readULE32();
|
|
|
|
|
|
|
|
if (fd.pos-sections[1][0].p != sections[1][0].size) throw new Error("Invalid PTau header size");
|
|
|
|
|
|
|
|
return {curve, power, ceremonyPower};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function readPtauPubKey(fd, curve, montgomery) {
|
|
|
|
|
|
|
|
const buff = await fd.read(curve.F1.n8*2*6 + curve.F2.n8*2*3);
|
|
|
|
|
|
|
|
return fromPtauPubKeyRpr(buff, 0, curve, montgomery);
|
|
|
|
}
|
|
|
|
|
|
|
|
function fromPtauPubKeyRpr(buff, pos, curve, montgomery) {
|
|
|
|
|
|
|
|
const key = {
|
|
|
|
tau: {},
|
|
|
|
alpha: {},
|
|
|
|
beta: {}
|
|
|
|
};
|
|
|
|
|
|
|
|
key.tau.g1_s = readG1();
|
|
|
|
key.tau.g1_sx = readG1();
|
|
|
|
key.alpha.g1_s = readG1();
|
|
|
|
key.alpha.g1_sx = readG1();
|
|
|
|
key.beta.g1_s = readG1();
|
|
|
|
key.beta.g1_sx = readG1();
|
|
|
|
key.tau.g2_spx = readG2();
|
|
|
|
key.alpha.g2_spx = readG2();
|
|
|
|
key.beta.g2_spx = readG2();
|
|
|
|
|
|
|
|
return key;
|
|
|
|
|
|
|
|
function readG1() {
|
|
|
|
let p;
|
|
|
|
if (montgomery) {
|
|
|
|
p = curve.G1.fromRprLEM( buff, pos );
|
|
|
|
} else {
|
|
|
|
p = curve.G1.fromRprUncompressed( buff, pos );
|
|
|
|
}
|
|
|
|
pos += curve.G1.F.n8*2;
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
function readG2() {
|
|
|
|
let p;
|
|
|
|
if (montgomery) {
|
|
|
|
p = curve.G2.fromRprLEM( buff, pos );
|
|
|
|
} else {
|
|
|
|
p = curve.G2.fromRprUncompressed( buff, pos );
|
|
|
|
}
|
|
|
|
pos += curve.G2.F.n8*2;
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function toPtauPubKeyRpr(buff, pos, curve, key, montgomery) {
|
|
|
|
|
|
|
|
writeG1(key.tau.g1_s);
|
|
|
|
writeG1(key.tau.g1_sx);
|
|
|
|
writeG1(key.alpha.g1_s);
|
|
|
|
writeG1(key.alpha.g1_sx);
|
|
|
|
writeG1(key.beta.g1_s);
|
|
|
|
writeG1(key.beta.g1_sx);
|
|
|
|
writeG2(key.tau.g2_spx);
|
|
|
|
writeG2(key.alpha.g2_spx);
|
|
|
|
writeG2(key.beta.g2_spx);
|
|
|
|
|
|
|
|
async function writeG1(p) {
|
|
|
|
if (montgomery) {
|
|
|
|
curve.G1.toRprLEM(buff, pos, p);
|
|
|
|
} else {
|
|
|
|
curve.G1.toRprUncompressed(buff, pos, p);
|
|
|
|
}
|
|
|
|
pos += curve.F1.n8*2;
|
|
|
|
}
|
|
|
|
|
|
|
|
async function writeG2(p) {
|
|
|
|
if (montgomery) {
|
|
|
|
curve.G2.toRprLEM(buff, pos, p);
|
|
|
|
} else {
|
|
|
|
curve.G2.toRprUncompressed(buff, pos, p);
|
|
|
|
}
|
|
|
|
pos += curve.F2.n8*2;
|
|
|
|
}
|
|
|
|
|
|
|
|
return buff;
|
|
|
|
}
|
|
|
|
|
|
|
|
async function writePtauPubKey(fd, curve, key, montgomery) {
|
|
|
|
const buff = new Uint8Array(curve.F1.n8*2*6 + curve.F2.n8*2*3);
|
|
|
|
toPtauPubKeyRpr(buff, 0, curve, key, montgomery);
|
|
|
|
await fd.write(buff);
|
|
|
|
}
|
|
|
|
|
|
|
|
async function readContribution$1(fd, curve) {
|
|
|
|
const c = {};
|
|
|
|
|
|
|
|
c.tauG1 = await readG1();
|
|
|
|
c.tauG2 = await readG2();
|
|
|
|
c.alphaG1 = await readG1();
|
|
|
|
c.betaG1 = await readG1();
|
|
|
|
c.betaG2 = await readG2();
|
|
|
|
c.key = await readPtauPubKey(fd, curve, true);
|
|
|
|
c.partialHash = await fd.read(216);
|
2020-07-14 11:55:12 +02:00
|
|
|
c.nextChallenge = await fd.read(64);
|
2020-07-11 10:31:52 +02:00
|
|
|
c.type = await fd.readULE32();
|
|
|
|
|
|
|
|
const buffV = new Uint8Array(curve.G1.F.n8*2*6+curve.G2.F.n8*2*3);
|
|
|
|
toPtauPubKeyRpr(buffV, 0, curve, c.key, false);
|
|
|
|
|
|
|
|
const responseHasher = blake2bWasm(64);
|
|
|
|
responseHasher.setPartialHash(c.partialHash);
|
|
|
|
responseHasher.update(buffV);
|
|
|
|
c.responseHash = responseHasher.digest();
|
|
|
|
|
|
|
|
const paramLength = await fd.readULE32();
|
|
|
|
const curPos = fd.pos;
|
|
|
|
let lastType =0;
|
|
|
|
while (fd.pos-curPos < paramLength) {
|
|
|
|
const buffType = await readDV(1);
|
|
|
|
if (buffType[0]<= lastType) throw new Error("Parameters in the contribution must be sorted");
|
|
|
|
lastType = buffType[0];
|
|
|
|
if (buffType[0]==1) { // Name
|
|
|
|
const buffLen = await readDV(1);
|
|
|
|
const buffStr = await readDV(buffLen[0]);
|
|
|
|
c.name = new TextDecoder().decode(buffStr);
|
|
|
|
} else if (buffType[0]==2) {
|
|
|
|
const buffExp = await readDV(1);
|
|
|
|
c.numIterationsExp = buffExp[0];
|
|
|
|
} else if (buffType[0]==3) {
|
|
|
|
const buffLen = await readDV(1);
|
|
|
|
c.beaconHash = await readDV(buffLen[0]);
|
|
|
|
} else {
|
|
|
|
throw new Error("Parameter not recognized");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (fd.pos != curPos + paramLength) {
|
|
|
|
throw new Error("Parametes do not match");
|
|
|
|
}
|
|
|
|
|
|
|
|
return c;
|
|
|
|
|
|
|
|
async function readG1() {
|
|
|
|
const pBuff = await fd.read(curve.G1.F.n8*2);
|
|
|
|
return curve.G1.fromRprLEM( pBuff );
|
|
|
|
}
|
|
|
|
|
|
|
|
async function readG2() {
|
|
|
|
const pBuff = await fd.read(curve.G2.F.n8*2);
|
|
|
|
return curve.G2.fromRprLEM( pBuff );
|
|
|
|
}
|
|
|
|
|
|
|
|
async function readDV(n) {
|
|
|
|
const b = await fd.read(n);
|
|
|
|
return new Uint8Array(b);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function readContributions(fd, curve, sections) {
|
|
|
|
if (!sections[7]) throw new Error(fd.fileName + ": File has no contributions");
|
|
|
|
if (sections[7][0].length>1) throw new Error(fd.fileName +": File has more than one contributions section");
|
|
|
|
|
|
|
|
fd.pos = sections[7][0].p;
|
|
|
|
const nContributions = await fd.readULE32();
|
|
|
|
const contributions = [];
|
|
|
|
for (let i=0; i<nContributions; i++) {
|
|
|
|
const c = await readContribution$1(fd, curve);
|
|
|
|
c.id = i+1;
|
|
|
|
contributions.push(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fd.pos-sections[7][0].p != sections[7][0].size) throw new Error("Invalid contribution section size");
|
|
|
|
|
|
|
|
return contributions;
|
|
|
|
}
|
|
|
|
|
|
|
|
async function writeContribution$1(fd, curve, contribution) {
|
|
|
|
|
|
|
|
const buffG1 = new Uint8Array(curve.F1.n8*2);
|
|
|
|
const buffG2 = new Uint8Array(curve.F2.n8*2);
|
|
|
|
await writeG1(contribution.tauG1);
|
|
|
|
await writeG2(contribution.tauG2);
|
|
|
|
await writeG1(contribution.alphaG1);
|
|
|
|
await writeG1(contribution.betaG1);
|
|
|
|
await writeG2(contribution.betaG2);
|
|
|
|
await writePtauPubKey(fd, curve, contribution.key, true);
|
|
|
|
await fd.write(contribution.partialHash);
|
2020-07-14 11:55:12 +02:00
|
|
|
await fd.write(contribution.nextChallenge);
|
2020-07-11 10:31:52 +02:00
|
|
|
await fd.writeULE32(contribution.type || 0);
|
|
|
|
|
|
|
|
const params = [];
|
|
|
|
if (contribution.name) {
|
|
|
|
params.push(1); // Param Name
|
|
|
|
const nameData = new TextEncoder("utf-8").encode(contribution.name.substring(0,64));
|
|
|
|
params.push(nameData.byteLength);
|
|
|
|
for (let i=0; i<nameData.byteLength; i++) params.push(nameData[i]);
|
|
|
|
}
|
|
|
|
if (contribution.type == 1) {
|
|
|
|
params.push(2); // Param numIterationsExp
|
|
|
|
params.push(contribution.numIterationsExp);
|
|
|
|
|
|
|
|
params.push(3); // Beacon Hash
|
|
|
|
params.push(contribution.beaconHash.byteLength);
|
|
|
|
for (let i=0; i<contribution.beaconHash.byteLength; i++) params.push(contribution.beaconHash[i]);
|
|
|
|
}
|
|
|
|
if (params.length>0) {
|
|
|
|
const paramsBuff = new Uint8Array(params);
|
|
|
|
await fd.writeULE32(paramsBuff.byteLength);
|
|
|
|
await fd.write(paramsBuff);
|
|
|
|
} else {
|
|
|
|
await fd.writeULE32(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function writeG1(p) {
|
|
|
|
curve.G1.toRprLEM(buffG1, 0, p);
|
|
|
|
await fd.write(buffG1);
|
|
|
|
}
|
|
|
|
|
|
|
|
async function writeG2(p) {
|
|
|
|
curve.G2.toRprLEM(buffG2, 0, p);
|
|
|
|
await fd.write(buffG2);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
async function writeContributions(fd, curve, contributions) {
|
|
|
|
|
|
|
|
await fd.writeULE32(7); // Header type
|
|
|
|
const pContributionsSize = fd.pos;
|
|
|
|
await fd.writeULE64(0); // Temporally set to 0 length
|
|
|
|
|
|
|
|
await fd.writeULE32(contributions.length);
|
|
|
|
for (let i=0; i< contributions.length; i++) {
|
|
|
|
await writeContribution$1(fd, curve, contributions[i]);
|
|
|
|
}
|
|
|
|
const contributionsSize = fd.pos - pContributionsSize - 8;
|
|
|
|
|
|
|
|
const oldPos = fd.pos;
|
|
|
|
|
2020-07-28 13:16:43 +02:00
|
|
|
await fd.writeULE64(contributionsSize, pContributionsSize);
|
2020-07-11 10:31:52 +02:00
|
|
|
fd.pos = oldPos;
|
|
|
|
}
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
function calculateFirstChallengeHash(curve, power, logger) {
|
|
|
|
if (logger) logger.debug("Calculating First Challenge Hash");
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
const hasher = new blake2bWasm(64);
|
|
|
|
|
|
|
|
const vG1 = new Uint8Array(curve.G1.F.n8*2);
|
|
|
|
const vG2 = new Uint8Array(curve.G2.F.n8*2);
|
|
|
|
curve.G1.toRprUncompressed(vG1, 0, curve.G1.g);
|
|
|
|
curve.G2.toRprUncompressed(vG2, 0, curve.G2.g);
|
|
|
|
|
|
|
|
hasher.update(blake2bWasm(64).digest());
|
|
|
|
|
|
|
|
let n;
|
|
|
|
|
|
|
|
n=(1 << power)*2 -1;
|
|
|
|
if (logger) logger.debug("Calculate Initial Hash: tauG1");
|
|
|
|
hashBlock(vG1, n);
|
|
|
|
n= 1 << power;
|
|
|
|
if (logger) logger.debug("Calculate Initial Hash: tauG2");
|
|
|
|
hashBlock(vG2, n);
|
|
|
|
if (logger) logger.debug("Calculate Initial Hash: alphaTauG1");
|
|
|
|
hashBlock(vG1, n);
|
|
|
|
if (logger) logger.debug("Calculate Initial Hash: betaTauG1");
|
|
|
|
hashBlock(vG1, n);
|
|
|
|
hasher.update(vG2);
|
|
|
|
|
|
|
|
return hasher.digest();
|
|
|
|
|
|
|
|
function hashBlock(buff, n) {
|
|
|
|
const blockSize = 500000;
|
|
|
|
const nBlocks = Math.floor(n / blockSize);
|
|
|
|
const rem = n % blockSize;
|
|
|
|
const bigBuff = new Uint8Array(blockSize * buff.byteLength);
|
|
|
|
for (let i=0; i<blockSize; i++) {
|
|
|
|
bigBuff.set(buff, i*buff.byteLength);
|
|
|
|
}
|
|
|
|
for (let i=0; i<nBlocks; i++) {
|
|
|
|
hasher.update(bigBuff);
|
|
|
|
if (logger) logger.debug("Initial hash: " +i*blockSize);
|
|
|
|
}
|
|
|
|
for (let i=0; i<rem; i++) {
|
|
|
|
hasher.update(buff);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
function keyFromBeacon(curve, challengeHash, beaconHash, numIterationsExp) {
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
const rng = rngFromBeaconParams(beaconHash, numIterationsExp);
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
const key = createPTauKey(curve, challengeHash, rng);
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
return key;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Header(1)
|
|
|
|
n8
|
|
|
|
prime
|
|
|
|
power
|
|
|
|
tauG1(2)
|
|
|
|
{(1<<power)*2-1} [
|
|
|
|
G1, tau*G1, tau^2 * G1, ....
|
|
|
|
]
|
|
|
|
tauG2(3)
|
|
|
|
{1<<power}[
|
|
|
|
G2, tau*G2, tau^2 * G2, ...
|
|
|
|
]
|
|
|
|
alphaTauG1(4)
|
|
|
|
{1<<power}[
|
|
|
|
alpha*G1, alpha*tau*G1, alpha*tau^2*G1,....
|
|
|
|
]
|
|
|
|
betaTauG1(5)
|
|
|
|
{1<<power} []
|
|
|
|
beta*G1, beta*tau*G1, beta*tau^2*G1, ....
|
|
|
|
]
|
|
|
|
betaG2(6)
|
|
|
|
{1}[
|
|
|
|
beta*G2
|
|
|
|
]
|
|
|
|
contributions(7)
|
|
|
|
NContributions
|
|
|
|
{NContributions}[
|
|
|
|
tau*G1
|
|
|
|
tau*G2
|
|
|
|
alpha*G1
|
|
|
|
beta*G1
|
|
|
|
beta*G2
|
|
|
|
pubKey
|
|
|
|
tau_g1s
|
|
|
|
tau_g1sx
|
|
|
|
tau_g2spx
|
|
|
|
alpha_g1s
|
|
|
|
alpha_g1sx
|
|
|
|
alpha_g1spx
|
|
|
|
beta_g1s
|
|
|
|
beta_g1sx
|
|
|
|
beta_g1spx
|
|
|
|
partialHash (216 bytes) See https://github.com/mafintosh/blake2b-wasm/blob/23bee06945806309977af802bc374727542617c7/blake2b.wat#L9
|
2020-07-14 11:55:12 +02:00
|
|
|
hashNewChallenge
|
2020-07-11 10:31:52 +02:00
|
|
|
]
|
|
|
|
*/
|
|
|
|
|
|
|
|
async function newAccumulator(curve, power, fileName, logger) {
|
|
|
|
|
|
|
|
await blake2bWasm.ready();
|
|
|
|
|
|
|
|
const fd = await createBinFile(fileName, "ptau", 1, 7);
|
|
|
|
|
|
|
|
await writePTauHeader(fd, curve, power, 0);
|
|
|
|
|
|
|
|
const buffG1 = curve.G1.oneAffine;
|
|
|
|
const buffG2 = curve.G2.oneAffine;
|
|
|
|
|
|
|
|
// Write tauG1
|
|
|
|
///////////
|
|
|
|
await startWriteSection(fd, 2);
|
|
|
|
const nTauG1 = (1 << power) * 2 -1;
|
|
|
|
for (let i=0; i< nTauG1; i++) {
|
|
|
|
await fd.write(buffG1);
|
|
|
|
if ((logger)&&((i%100000) == 0)&&i) logger.info("tauG1: " + i);
|
|
|
|
}
|
|
|
|
await endWriteSection(fd);
|
|
|
|
|
|
|
|
// Write tauG2
|
|
|
|
///////////
|
|
|
|
await startWriteSection(fd, 3);
|
|
|
|
const nTauG2 = (1 << power);
|
|
|
|
for (let i=0; i< nTauG2; i++) {
|
|
|
|
await fd.write(buffG2);
|
|
|
|
if ((logger)&&((i%100000) == 0)&&i) logger.log("tauG2: " + i);
|
|
|
|
}
|
|
|
|
await endWriteSection(fd);
|
|
|
|
|
|
|
|
// Write alphaTauG1
|
|
|
|
///////////
|
|
|
|
await startWriteSection(fd, 4);
|
|
|
|
const nAlfaTauG1 = (1 << power);
|
|
|
|
for (let i=0; i< nAlfaTauG1; i++) {
|
|
|
|
await fd.write(buffG1);
|
|
|
|
if ((logger)&&((i%100000) == 0)&&i) logger.log("alphaTauG1: " + i);
|
|
|
|
}
|
|
|
|
await endWriteSection(fd);
|
|
|
|
|
|
|
|
// Write betaTauG1
|
|
|
|
///////////
|
|
|
|
await startWriteSection(fd, 5);
|
|
|
|
const nBetaTauG1 = (1 << power);
|
|
|
|
for (let i=0; i< nBetaTauG1; i++) {
|
|
|
|
await fd.write(buffG1);
|
|
|
|
if ((logger)&&((i%100000) == 0)&&i) logger.log("betaTauG1: " + i);
|
|
|
|
}
|
|
|
|
await endWriteSection(fd);
|
|
|
|
|
|
|
|
// Write betaG2
|
|
|
|
///////////
|
|
|
|
await startWriteSection(fd, 6);
|
|
|
|
await fd.write(buffG2);
|
|
|
|
await endWriteSection(fd);
|
|
|
|
|
|
|
|
// Contributions
|
|
|
|
///////////
|
|
|
|
await startWriteSection(fd, 7);
|
|
|
|
await fd.writeULE32(0); // 0 Contributions
|
|
|
|
await endWriteSection(fd);
|
|
|
|
|
|
|
|
await fd.close();
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
const firstChallengeHash = calculateFirstChallengeHash(curve, power, logger);
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
if (logger) logger.debug(formatHash(blake2bWasm(64).digest(), "Blank Contribution Hash:"));
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
if (logger) logger.info(formatHash(firstChallengeHash, "First Contribution Hash:"));
|
2020-07-11 10:31:52 +02:00
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
return firstChallengeHash;
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Format of the outpu
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
async function exportChallenge(pTauFilename, challengeFilename, logger) {
|
2020-07-11 10:31:52 +02:00
|
|
|
await blake2bWasm.ready();
|
|
|
|
const {fd: fdFrom, sections} = await readBinFile(pTauFilename, "ptau", 1);
|
|
|
|
|
|
|
|
const {curve, power} = await readPTauHeader(fdFrom, sections);
|
|
|
|
|
|
|
|
const contributions = await readContributions(fdFrom, curve, sections);
|
2020-07-14 11:55:12 +02:00
|
|
|
let lastResponseHash, curChallengeHash;
|
2020-07-11 10:31:52 +02:00
|
|
|
if (contributions.length == 0) {
|
|
|
|
lastResponseHash = blake2bWasm(64).digest();
|
2020-07-14 11:55:12 +02:00
|
|
|
curChallengeHash = calculateFirstChallengeHash(curve, power);
|
2020-07-11 10:31:52 +02:00
|
|
|
} else {
|
|
|
|
lastResponseHash = contributions[contributions.length-1].responseHash;
|
2020-07-14 11:55:12 +02:00
|
|
|
curChallengeHash = contributions[contributions.length-1].nextChallenge;
|
2020-07-11 10:31:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (logger) logger.info(formatHash(lastResponseHash, "Last Response Hash: "));
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
if (logger) logger.info(formatHash(curChallengeHash, "New Challenge Hash: "));
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
const fdTo = await createOverride(challengeFilename);
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
const toHash = blake2bWasm(64);
|
|
|
|
await fdTo.write(lastResponseHash);
|
|
|
|
toHash.update(lastResponseHash);
|
|
|
|
|
|
|
|
await exportSection(2, "G1", (1 << power) * 2 -1, "tauG1");
|
|
|
|
await exportSection(3, "G2", (1 << power) , "tauG2");
|
|
|
|
await exportSection(4, "G1", (1 << power) , "alphaTauG1");
|
|
|
|
await exportSection(5, "G1", (1 << power) , "betaTauG1");
|
|
|
|
await exportSection(6, "G2", 1 , "betaG2");
|
|
|
|
|
|
|
|
await fdFrom.close();
|
|
|
|
await fdTo.close();
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
const calcCurChallengeHash = toHash.digest();
|
2020-07-11 10:31:52 +02:00
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
if (!hashIsEqual (curChallengeHash, calcCurChallengeHash)) {
|
|
|
|
if (logger) logger.info(formatHash(calcCurChallengeHash, "Calc Curret Challenge Hash: "));
|
2020-07-11 10:31:52 +02:00
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
if (logger) logger.error("PTau file is corrupted. Calculated new challenge hash does not match with the eclared one");
|
|
|
|
throw new Error("PTau file is corrupted. Calculated new challenge hash does not match with the eclared one");
|
2020-07-11 10:31:52 +02:00
|
|
|
}
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
return curChallengeHash;
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
async function exportSection(sectionId, groupName, nPoints, sectionName) {
|
|
|
|
const G = curve[groupName];
|
|
|
|
const sG = G.F.n8*2;
|
|
|
|
const nPointsChunk = Math.floor((1<<24)/sG);
|
|
|
|
|
|
|
|
await startReadUniqueSection(fdFrom, sections, sectionId);
|
|
|
|
for (let i=0; i< nPoints; i+= nPointsChunk) {
|
|
|
|
if (logger) logger.debug(`Exporting ${sectionName}: ${i}/${nPoints}`);
|
|
|
|
const n = Math.min(nPoints-i, nPointsChunk);
|
|
|
|
let buff;
|
|
|
|
buff = await fdFrom.read(n*sG);
|
|
|
|
buff = await G.batchLEMtoU(buff);
|
|
|
|
await fdTo.write(buff);
|
|
|
|
toHash.update(buff);
|
|
|
|
}
|
|
|
|
await endReadSection(fdFrom);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
async function importResponse(oldPtauFilename, contributionFilename, newPTauFilename, name, importPoints, logger) {
|
|
|
|
|
|
|
|
await blake2bWasm.ready();
|
|
|
|
|
|
|
|
const {fd: fdOld, sections} = await readBinFile(oldPtauFilename, "ptau", 1);
|
|
|
|
const {curve, power} = await readPTauHeader(fdOld, sections);
|
|
|
|
const contributions = await readContributions(fdOld, curve, sections);
|
|
|
|
const currentContribution = {};
|
|
|
|
|
|
|
|
if (name) currentContribution.name = name;
|
|
|
|
|
|
|
|
const sG1 = curve.F1.n8*2;
|
|
|
|
const scG1 = curve.F1.n8; // Compresed size
|
|
|
|
const sG2 = curve.F2.n8*2;
|
|
|
|
const scG2 = curve.F2.n8; // Compresed size
|
|
|
|
|
|
|
|
const fdResponse = await readExisting$1(contributionFilename);
|
|
|
|
|
|
|
|
if (fdResponse.totalSize !=
|
|
|
|
64 + // Old Hash
|
|
|
|
((1<<power)*2-1)*scG1 +
|
|
|
|
(1<<power)*scG2 +
|
|
|
|
(1<<power)*scG1 +
|
|
|
|
(1<<power)*scG1 +
|
|
|
|
scG2 +
|
|
|
|
sG1*6 + sG2*3)
|
|
|
|
throw new Error("Size of the contribution is invalid");
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
let lastChallengeHash;
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
if (contributions.length>0) {
|
2020-07-14 11:55:12 +02:00
|
|
|
lastChallengeHash = contributions[contributions.length-1].nextChallenge;
|
2020-07-11 10:31:52 +02:00
|
|
|
} else {
|
2020-07-14 11:55:12 +02:00
|
|
|
lastChallengeHash = calculateFirstChallengeHash(curve, power, logger);
|
2020-07-11 10:31:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const fdNew = await createBinFile(newPTauFilename, "ptau", 1, 7);
|
|
|
|
await writePTauHeader(fdNew, curve, power);
|
|
|
|
|
|
|
|
const contributionPreviousHash = await fdResponse.read(64);
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
if(!hashIsEqual(contributionPreviousHash,lastChallengeHash))
|
2020-07-11 10:31:52 +02:00
|
|
|
throw new Error("Wrong contribution. this contribution is not based on the previus hash");
|
|
|
|
|
|
|
|
const hasherResponse = new blake2bWasm(64);
|
|
|
|
hasherResponse.update(contributionPreviousHash);
|
|
|
|
|
|
|
|
const startSections = [];
|
|
|
|
let res;
|
|
|
|
res = await processSection(fdResponse, fdNew, "G1", 2, (1 << power) * 2 -1, [1], "tauG1");
|
|
|
|
currentContribution.tauG1 = res[0];
|
|
|
|
res = await processSection(fdResponse, fdNew, "G2", 3, (1 << power) , [1], "tauG2");
|
|
|
|
currentContribution.tauG2 = res[0];
|
|
|
|
res = await processSection(fdResponse, fdNew, "G1", 4, (1 << power) , [0], "alphaG1");
|
|
|
|
currentContribution.alphaG1 = res[0];
|
|
|
|
res = await processSection(fdResponse, fdNew, "G1", 5, (1 << power) , [0], "betaG1");
|
|
|
|
currentContribution.betaG1 = res[0];
|
|
|
|
res = await processSection(fdResponse, fdNew, "G2", 6, 1 , [0], "betaG2");
|
|
|
|
currentContribution.betaG2 = res[0];
|
|
|
|
|
|
|
|
currentContribution.partialHash = hasherResponse.getPartialHash();
|
|
|
|
|
|
|
|
|
|
|
|
const buffKey = await fdResponse.read(curve.F1.n8*2*6+curve.F2.n8*2*3);
|
|
|
|
|
|
|
|
currentContribution.key = fromPtauPubKeyRpr(buffKey, 0, curve, false);
|
|
|
|
|
|
|
|
hasherResponse.update(new Uint8Array(buffKey));
|
|
|
|
const hashResponse = hasherResponse.digest();
|
|
|
|
|
|
|
|
if (logger) logger.info(formatHash(hashResponse, "Contribution Response Hash imported: "));
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
const nextChallengeHasher = new blake2bWasm(64);
|
|
|
|
nextChallengeHasher.update(hashResponse);
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
await hashSection(fdNew, "G1", 2, (1 << power) * 2 -1, "tauG1", logger);
|
|
|
|
await hashSection(fdNew, "G2", 3, (1 << power) , "tauG2", logger);
|
|
|
|
await hashSection(fdNew, "G1", 4, (1 << power) , "alphaTauG1", logger);
|
|
|
|
await hashSection(fdNew, "G1", 5, (1 << power) , "betaTauG1", logger);
|
|
|
|
await hashSection(fdNew, "G2", 6, 1 , "betaG2", logger);
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
currentContribution.nextChallenge = nextChallengeHasher.digest();
|
2020-07-11 10:31:52 +02:00
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
if (logger) logger.info(formatHash(currentContribution.nextChallenge, "Next Challenge Hash: "));
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
contributions.push(currentContribution);
|
|
|
|
|
|
|
|
await writeContributions(fdNew, curve, contributions);
|
|
|
|
|
|
|
|
await fdResponse.close();
|
|
|
|
await fdNew.close();
|
|
|
|
await fdOld.close();
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
return currentContribution.nextChallenge;
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
async function processSection(fdFrom, fdTo, groupName, sectionId, nPoints, singularPointIndexes, sectionName) {
|
|
|
|
|
|
|
|
const G = curve[groupName];
|
|
|
|
const scG = G.F.n8;
|
|
|
|
const sG = G.F.n8*2;
|
|
|
|
|
|
|
|
const singularPoints = [];
|
|
|
|
|
|
|
|
await startWriteSection(fdTo, sectionId);
|
|
|
|
const nPointsChunk = Math.floor((1<<24)/sG);
|
|
|
|
|
|
|
|
startSections[sectionId] = fdTo.pos;
|
|
|
|
|
|
|
|
for (let i=0; i< nPoints; i += nPointsChunk) {
|
|
|
|
if (logger) logger.debug(`Importing ${sectionName}: ${i}/${nPoints}`);
|
|
|
|
const n = Math.min(nPoints-i, nPointsChunk);
|
|
|
|
|
|
|
|
const buffC = await fdFrom.read(n * scG);
|
|
|
|
hasherResponse.update(buffC);
|
|
|
|
|
|
|
|
const buffLEM = await G.batchCtoLEM(buffC);
|
|
|
|
|
|
|
|
await fdTo.write(buffLEM);
|
|
|
|
for (let j=0; j<singularPointIndexes.length; j++) {
|
|
|
|
const sp = singularPointIndexes[j];
|
|
|
|
if ((sp >=i) && (sp < i+n)) {
|
|
|
|
const P = G.fromRprLEM(buffLEM, (sp-i)*sG);
|
|
|
|
singularPoints.push(P);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
await endWriteSection(fdTo);
|
|
|
|
|
|
|
|
return singularPoints;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function hashSection(fdTo, groupName, sectionId, nPoints, sectionName, logger) {
|
|
|
|
|
|
|
|
const G = curve[groupName];
|
|
|
|
const sG = G.F.n8*2;
|
|
|
|
const nPointsChunk = Math.floor((1<<24)/sG);
|
|
|
|
|
|
|
|
const oldPos = fdTo.pos;
|
|
|
|
fdTo.pos = startSections[sectionId];
|
|
|
|
|
|
|
|
for (let i=0; i< nPoints; i += nPointsChunk) {
|
|
|
|
if (logger) logger.debug(`Hashing ${sectionName}: ${i}/${nPoints}`);
|
|
|
|
const n = Math.min(nPoints-i, nPointsChunk);
|
|
|
|
|
|
|
|
const buffLEM = await fdTo.read(n * sG);
|
|
|
|
|
|
|
|
const buffU = await G.batchLEMtoU(buffLEM);
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
nextChallengeHasher.update(buffU);
|
2020-07-11 10:31:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fdTo.pos = oldPos;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const sameRatio$1 = sameRatio;
|
|
|
|
|
|
|
|
async function verifyContribution(curve, cur, prev, logger) {
|
|
|
|
let sr;
|
|
|
|
if (cur.type == 1) { // Verify the beacon.
|
2020-07-14 11:55:12 +02:00
|
|
|
const beaconKey = keyFromBeacon(curve, prev.nextChallenge, cur.beaconHash, cur.numIterationsExp);
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
if (!curve.G1.eq(cur.key.tau.g1_s, beaconKey.tau.g1_s)) {
|
2020-07-14 11:55:12 +02:00
|
|
|
if (logger) logger.error(`BEACON key (tauG1_s) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` );
|
2020-07-11 10:31:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!curve.G1.eq(cur.key.tau.g1_sx, beaconKey.tau.g1_sx)) {
|
2020-07-14 11:55:12 +02:00
|
|
|
if (logger) logger.error(`BEACON key (tauG1_sx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` );
|
2020-07-11 10:31:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!curve.G2.eq(cur.key.tau.g2_spx, beaconKey.tau.g2_spx)) {
|
2020-07-14 11:55:12 +02:00
|
|
|
if (logger) logger.error(`BEACON key (tauG2_spx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` );
|
2020-07-11 10:31:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!curve.G1.eq(cur.key.alpha.g1_s, beaconKey.alpha.g1_s)) {
|
2020-07-14 11:55:12 +02:00
|
|
|
if (logger) logger.error(`BEACON key (alphaG1_s) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` );
|
2020-07-11 10:31:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!curve.G1.eq(cur.key.alpha.g1_sx, beaconKey.alpha.g1_sx)) {
|
2020-07-14 11:55:12 +02:00
|
|
|
if (logger) logger.error(`BEACON key (alphaG1_sx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` );
|
2020-07-11 10:31:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!curve.G2.eq(cur.key.alpha.g2_spx, beaconKey.alpha.g2_spx)) {
|
2020-07-14 11:55:12 +02:00
|
|
|
if (logger) logger.error(`BEACON key (alphaG2_spx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` );
|
2020-07-11 10:31:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!curve.G1.eq(cur.key.beta.g1_s, beaconKey.beta.g1_s)) {
|
2020-07-14 11:55:12 +02:00
|
|
|
if (logger) logger.error(`BEACON key (betaG1_s) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` );
|
2020-07-11 10:31:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!curve.G1.eq(cur.key.beta.g1_sx, beaconKey.beta.g1_sx)) {
|
2020-07-14 11:55:12 +02:00
|
|
|
if (logger) logger.error(`BEACON key (betaG1_sx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` );
|
2020-07-11 10:31:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!curve.G2.eq(cur.key.beta.g2_spx, beaconKey.beta.g2_spx)) {
|
2020-07-14 11:55:12 +02:00
|
|
|
if (logger) logger.error(`BEACON key (betaG2_spx) is not generated correctly in challenge #${cur.id} ${cur.name || ""}` );
|
2020-07-11 10:31:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
cur.key.tau.g2_sp = curve.G2.toAffine(getG2sp(curve, 0, prev.nextChallenge, cur.key.tau.g1_s, cur.key.tau.g1_sx));
|
|
|
|
cur.key.alpha.g2_sp = curve.G2.toAffine(getG2sp(curve, 1, prev.nextChallenge, cur.key.alpha.g1_s, cur.key.alpha.g1_sx));
|
|
|
|
cur.key.beta.g2_sp = curve.G2.toAffine(getG2sp(curve, 2, prev.nextChallenge, cur.key.beta.g1_s, cur.key.beta.g1_sx));
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
sr = await sameRatio$1(curve, cur.key.tau.g1_s, cur.key.tau.g1_sx, cur.key.tau.g2_sp, cur.key.tau.g2_spx);
|
|
|
|
if (sr !== true) {
|
2020-07-14 11:55:12 +02:00
|
|
|
if (logger) logger.error("INVALID key (tau) in challenge #"+cur.id);
|
2020-07-11 10:31:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
sr = await sameRatio$1(curve, cur.key.alpha.g1_s, cur.key.alpha.g1_sx, cur.key.alpha.g2_sp, cur.key.alpha.g2_spx);
|
|
|
|
if (sr !== true) {
|
2020-07-14 11:55:12 +02:00
|
|
|
if (logger) logger.error("INVALID key (alpha) in challenge #"+cur.id);
|
2020-07-11 10:31:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
sr = await sameRatio$1(curve, cur.key.beta.g1_s, cur.key.beta.g1_sx, cur.key.beta.g2_sp, cur.key.beta.g2_spx);
|
|
|
|
if (sr !== true) {
|
2020-07-14 11:55:12 +02:00
|
|
|
if (logger) logger.error("INVALID key (beta) in challenge #"+cur.id);
|
2020-07-11 10:31:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
sr = await sameRatio$1(curve, prev.tauG1, cur.tauG1, cur.key.tau.g2_sp, cur.key.tau.g2_spx);
|
|
|
|
if (sr !== true) {
|
2020-07-14 11:55:12 +02:00
|
|
|
if (logger) logger.error("INVALID tau*G1. challenge #"+cur.id+" It does not follow the previous contribution");
|
2020-07-11 10:31:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
sr = await sameRatio$1(curve, cur.key.tau.g1_s, cur.key.tau.g1_sx, prev.tauG2, cur.tauG2);
|
|
|
|
if (sr !== true) {
|
2020-07-14 11:55:12 +02:00
|
|
|
if (logger) logger.error("INVALID tau*G2. challenge #"+cur.id+" It does not follow the previous contribution");
|
2020-07-11 10:31:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
sr = await sameRatio$1(curve, prev.alphaG1, cur.alphaG1, cur.key.alpha.g2_sp, cur.key.alpha.g2_spx);
|
|
|
|
if (sr !== true) {
|
2020-07-14 11:55:12 +02:00
|
|
|
if (logger) logger.error("INVALID alpha*G1. challenge #"+cur.id+" It does not follow the previous contribution");
|
2020-07-11 10:31:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
sr = await sameRatio$1(curve, prev.betaG1, cur.betaG1, cur.key.beta.g2_sp, cur.key.beta.g2_spx);
|
|
|
|
if (sr !== true) {
|
2020-07-14 11:55:12 +02:00
|
|
|
if (logger) logger.error("INVALID beta*G1. challenge #"+cur.id+" It does not follow the previous contribution");
|
2020-07-11 10:31:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
sr = await sameRatio$1(curve, cur.key.beta.g1_s, cur.key.beta.g1_sx, prev.betaG2, cur.betaG2);
|
|
|
|
if (sr !== true) {
|
2020-07-14 11:55:12 +02:00
|
|
|
if (logger) logger.error("INVALID beta*G2. challenge #"+cur.id+"It does not follow the previous contribution");
|
2020-07-11 10:31:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (logger) logger.info("Powers Of tau file OK!");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
async function verify(tauFilename, logger) {
|
|
|
|
let sr;
|
|
|
|
await blake2bWasm.ready();
|
|
|
|
|
|
|
|
const {fd, sections} = await readBinFile(tauFilename, "ptau", 1);
|
|
|
|
const {curve, power, ceremonyPower} = await readPTauHeader(fd, sections);
|
|
|
|
const contrs = await readContributions(fd, curve, sections);
|
|
|
|
|
|
|
|
if (logger) logger.debug("power: 2**" + power);
|
|
|
|
// Verify Last contribution
|
|
|
|
|
|
|
|
if (logger) logger.debug("Computing initial contribution hash");
|
|
|
|
const initialContribution = {
|
|
|
|
tauG1: curve.G1.g,
|
|
|
|
tauG2: curve.G2.g,
|
|
|
|
alphaG1: curve.G1.g,
|
|
|
|
betaG1: curve.G1.g,
|
|
|
|
betaG2: curve.G2.g,
|
2020-07-14 11:55:12 +02:00
|
|
|
nextChallenge: calculateFirstChallengeHash(curve, ceremonyPower, logger),
|
2020-07-11 10:31:52 +02:00
|
|
|
responseHash: blake2bWasm(64).digest()
|
|
|
|
};
|
|
|
|
|
|
|
|
if (contrs.length == 0) {
|
|
|
|
if (logger) logger.error("This file has no contribution! It cannot be used in production");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
let prevContr;
|
|
|
|
if (contrs.length>1) {
|
|
|
|
prevContr = contrs[contrs.length-2];
|
|
|
|
} else {
|
|
|
|
prevContr = initialContribution;
|
|
|
|
}
|
|
|
|
const curContr = contrs[contrs.length-1];
|
|
|
|
if (logger) logger.debug("Validating contribution #"+contrs[contrs.length-1].id);
|
|
|
|
const res = await verifyContribution(curve, curContr, prevContr, logger);
|
|
|
|
if (!res) return false;
|
|
|
|
|
|
|
|
|
|
|
|
const nextContributionHasher = blake2bWasm(64);
|
|
|
|
nextContributionHasher.update(curContr.responseHash);
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
// Verify powers and compute nextChallengeHash
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
// await test();
|
|
|
|
|
|
|
|
// Verify Section tau*G1
|
|
|
|
if (logger) logger.debug("Verifying powers in tau*G1 section");
|
|
|
|
const rTau1 = await processSection(2, "G1", "tauG1", (1 << power)*2-1, [0, 1], logger);
|
|
|
|
sr = await sameRatio$1(curve, rTau1.R1, rTau1.R2, curve.G2.g, curContr.tauG2);
|
|
|
|
if (sr !== true) {
|
|
|
|
if (logger) logger.error("tauG1 section. Powers do not match");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!curve.G1.eq(curve.G1.g, rTau1.singularPoints[0])) {
|
|
|
|
if (logger) logger.error("First element of tau*G1 section must be the generator");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!curve.G1.eq(curContr.tauG1, rTau1.singularPoints[1])) {
|
|
|
|
if (logger) logger.error("Second element of tau*G1 section does not match the one in the contribution section");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// await test();
|
|
|
|
|
|
|
|
// Verify Section tau*G2
|
|
|
|
if (logger) logger.debug("Verifying powers in tau*G2 section");
|
|
|
|
const rTau2 = await processSection(3, "G2", "tauG2", 1 << power, [0, 1], logger);
|
|
|
|
sr = await sameRatio$1(curve, curve.G1.g, curContr.tauG1, rTau2.R1, rTau2.R2);
|
|
|
|
if (sr !== true) {
|
|
|
|
if (logger) logger.error("tauG2 section. Powers do not match");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!curve.G2.eq(curve.G2.g, rTau2.singularPoints[0])) {
|
|
|
|
if (logger) logger.error("First element of tau*G2 section must be the generator");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!curve.G2.eq(curContr.tauG2, rTau2.singularPoints[1])) {
|
|
|
|
if (logger) logger.error("Second element of tau*G2 section does not match the one in the contribution section");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify Section alpha*tau*G1
|
|
|
|
if (logger) logger.debug("Verifying powers in alpha*tau*G1 section");
|
|
|
|
const rAlphaTauG1 = await processSection(4, "G1", "alphatauG1", 1 << power, [0], logger);
|
|
|
|
sr = await sameRatio$1(curve, rAlphaTauG1.R1, rAlphaTauG1.R2, curve.G2.g, curContr.tauG2);
|
|
|
|
if (sr !== true) {
|
|
|
|
if (logger) logger.error("alphaTauG1 section. Powers do not match");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!curve.G1.eq(curContr.alphaG1, rAlphaTauG1.singularPoints[0])) {
|
|
|
|
if (logger) logger.error("First element of alpha*tau*G1 section (alpha*G1) does not match the one in the contribution section");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify Section beta*tau*G1
|
|
|
|
if (logger) logger.debug("Verifying powers in beta*tau*G1 section");
|
|
|
|
const rBetaTauG1 = await processSection(5, "G1", "betatauG1", 1 << power, [0], logger);
|
|
|
|
sr = await sameRatio$1(curve, rBetaTauG1.R1, rBetaTauG1.R2, curve.G2.g, curContr.tauG2);
|
|
|
|
if (sr !== true) {
|
|
|
|
if (logger) logger.error("betaTauG1 section. Powers do not match");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!curve.G1.eq(curContr.betaG1, rBetaTauG1.singularPoints[0])) {
|
|
|
|
if (logger) logger.error("First element of beta*tau*G1 section (beta*G1) does not match the one in the contribution section");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Verify Beta G2
|
|
|
|
const betaG2 = await processSectionBetaG2(logger);
|
|
|
|
if (!curve.G2.eq(curContr.betaG2, betaG2)) {
|
|
|
|
if (logger) logger.error("betaG2 element in betaG2 section does not match the one in the contribution section");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const nextContributionHash = nextContributionHasher.digest();
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
// Check the nextChallengeHash
|
|
|
|
if (!hashIsEqual(nextContributionHash,curContr.nextChallenge)) {
|
|
|
|
if (logger) logger.error("Hash of the values does not match the next challenge of the last contributor in the contributions section");
|
2020-07-11 10:31:52 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
if (logger) logger.info(formatHash(nextContributionHash, "Next challenge hash: "));
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
// Verify Previous contributions
|
|
|
|
|
|
|
|
printContribution(curContr, prevContr);
|
|
|
|
for (let i = contrs.length-2; i>=0; i--) {
|
|
|
|
const curContr = contrs[i];
|
|
|
|
const prevContr = (i>0) ? contrs[i-1] : initialContribution;
|
|
|
|
const res = await verifyContribution(curve, curContr, prevContr, logger);
|
|
|
|
if (!res) return false;
|
|
|
|
printContribution(curContr, prevContr);
|
|
|
|
}
|
|
|
|
if (logger) logger.info("-----------------------------------------------------");
|
|
|
|
|
|
|
|
if ((!sections[12]) || (!sections[13]) || (!sections[14]) || (!sections[15])) {
|
|
|
|
if (logger) logger.warn(
|
|
|
|
"this file does not contain phase2 precalculated values. Please run: \n" +
|
|
|
|
" snarkjs \"powersoftau preparephase2\" to prepare this file to be used in the phase2 ceremony."
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
let res;
|
|
|
|
res = await verifyLagrangeEvaluations("G1", 2, 12, "tauG1", logger);
|
|
|
|
if (!res) return false;
|
|
|
|
res = await verifyLagrangeEvaluations("G2", 3, 13, "tauG2", logger);
|
|
|
|
if (!res) return false;
|
|
|
|
res = await verifyLagrangeEvaluations("G1", 4, 14, "alphaTauG1", logger);
|
|
|
|
if (!res) return false;
|
|
|
|
res = await verifyLagrangeEvaluations("G1", 5, 15, "betaTauG1", logger);
|
|
|
|
if (!res) return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
await fd.close();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
function printContribution(curContr, prevContr) {
|
|
|
|
if (!logger) return;
|
|
|
|
logger.info("-----------------------------------------------------");
|
|
|
|
logger.info(`Contribution #${curContr.id}: ${curContr.name ||""}`);
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
logger.info(formatHash(curContr.nextChallenge, "Next Challenge: "));
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
const buffV = new Uint8Array(curve.G1.F.n8*2*6+curve.G2.F.n8*2*3);
|
|
|
|
toPtauPubKeyRpr(buffV, 0, curve, curContr.key, false);
|
|
|
|
|
|
|
|
const responseHasher = blake2bWasm(64);
|
|
|
|
responseHasher.setPartialHash(curContr.partialHash);
|
|
|
|
responseHasher.update(buffV);
|
|
|
|
const responseHash = responseHasher.digest();
|
|
|
|
|
|
|
|
logger.info(formatHash(responseHash, "Response Hash:"));
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
logger.info(formatHash(prevContr.nextChallenge, "Response Hash:"));
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
if (curContr.type == 1) {
|
|
|
|
logger.info(`Beacon generator: ${byteArray2hex(curContr.beaconHash)}`);
|
|
|
|
logger.info(`Beacon iterations Exp: ${curContr.numIterationsExp}`);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
async function processSectionBetaG2(logger) {
|
|
|
|
const G = curve.G2;
|
|
|
|
const sG = G.F.n8*2;
|
|
|
|
const buffUv = new Uint8Array(sG);
|
|
|
|
|
|
|
|
if (!sections[6]) {
|
|
|
|
logger.error("File has no BetaG2 section");
|
|
|
|
throw new Error("File has no BetaG2 section");
|
|
|
|
}
|
|
|
|
if (sections[6].length>1) {
|
|
|
|
logger.error("File has no BetaG2 section");
|
|
|
|
throw new Error("File has more than one GetaG2 section");
|
|
|
|
}
|
|
|
|
fd.pos = sections[6][0].p;
|
|
|
|
|
|
|
|
const buff = await fd.read(sG);
|
|
|
|
const P = G.fromRprLEM(buff);
|
|
|
|
|
|
|
|
G.toRprUncompressed(buffUv, 0, P);
|
|
|
|
nextContributionHasher.update(buffUv);
|
|
|
|
|
|
|
|
return P;
|
|
|
|
}
|
|
|
|
|
|
|
|
async function processSection(idSection, groupName, sectionName, nPoints, singularPointIndexes, logger) {
|
|
|
|
const MAX_CHUNK_SIZE = 1<<16;
|
|
|
|
const G = curve[groupName];
|
|
|
|
const sG = G.F.n8*2;
|
|
|
|
await startReadUniqueSection(fd, sections, idSection);
|
|
|
|
|
|
|
|
const singularPoints = [];
|
|
|
|
|
|
|
|
let R1 = G.zero;
|
|
|
|
let R2 = G.zero;
|
|
|
|
|
|
|
|
let lastBase = G.zero;
|
|
|
|
|
|
|
|
for (let i=0; i<nPoints; i += MAX_CHUNK_SIZE) {
|
|
|
|
if (logger) logger.debug(`points relations: ${sectionName}: ${i}/${nPoints} `);
|
|
|
|
const n = Math.min(nPoints - i, MAX_CHUNK_SIZE);
|
|
|
|
const bases = await fd.read(n*sG);
|
|
|
|
|
|
|
|
const basesU = await G.batchLEMtoU(bases);
|
|
|
|
nextContributionHasher.update(basesU);
|
|
|
|
|
|
|
|
const scalars = new Uint8Array(4*(n-1));
|
|
|
|
crypto.randomFillSync(scalars);
|
|
|
|
|
|
|
|
|
|
|
|
if (i>0) {
|
|
|
|
const firstBase = G.fromRprLEM(bases, 0);
|
|
|
|
const r = crypto.randomBytes(4).readUInt32BE(0, true);
|
|
|
|
|
|
|
|
R1 = G.add(R1, G.timesScalar(lastBase, r));
|
|
|
|
R2 = G.add(R2, G.timesScalar(firstBase, r));
|
|
|
|
}
|
|
|
|
|
|
|
|
const r1 = await G.multiExpAffine(bases.slice(0, (n-1)*sG), scalars);
|
|
|
|
const r2 = await G.multiExpAffine(bases.slice(sG), scalars);
|
|
|
|
|
|
|
|
R1 = G.add(R1, r1);
|
|
|
|
R2 = G.add(R2, r2);
|
|
|
|
|
|
|
|
lastBase = G.fromRprLEM( bases, (n-1)*sG);
|
|
|
|
|
|
|
|
for (let j=0; j<singularPointIndexes.length; j++) {
|
|
|
|
const sp = singularPointIndexes[j];
|
|
|
|
if ((sp >=i) && (sp < i+n)) {
|
|
|
|
const P = G.fromRprLEM(bases, (sp-i)*sG);
|
|
|
|
singularPoints.push(P);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
await endReadSection(fd);
|
|
|
|
|
|
|
|
return {
|
|
|
|
R1: R1,
|
|
|
|
R2: R2,
|
|
|
|
singularPoints: singularPoints
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
async function verifyLagrangeEvaluations(gName, tauSection, lagrangeSection, sectionName, logger) {
|
|
|
|
|
|
|
|
if (logger) logger.debug(`Verifying phase2 calculated values ${sectionName}...`);
|
|
|
|
const G = curve[gName];
|
|
|
|
const sG = G.F.n8*2;
|
|
|
|
|
|
|
|
const seed= new Array(8);
|
|
|
|
for (let i=0; i<8; i++) {
|
|
|
|
seed[i] = crypto.randomBytes(4).readUInt32BE(0, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
const rng = new ChaCha(seed);
|
|
|
|
|
|
|
|
|
|
|
|
for (let p=0; p<= power; p ++) {
|
|
|
|
const res = await verifyPower(p);
|
|
|
|
if (!res) return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
async function verifyPower(p) {
|
|
|
|
if (logger) logger.debug(`Power ${p}...`);
|
|
|
|
const n8r = curve.Fr.n8;
|
|
|
|
const nPoints = 1<<p;
|
|
|
|
let buff_r = new Uint8Array(nPoints * n8r);
|
|
|
|
let buffG;
|
|
|
|
|
|
|
|
for (let i=0; i<nPoints; i++) {
|
|
|
|
const e = curve.Fr.fromRng(rng);
|
|
|
|
curve.Fr.toRprLE(buff_r, i*n8r, e);
|
|
|
|
}
|
|
|
|
|
|
|
|
await startReadUniqueSection(fd, sections, tauSection);
|
|
|
|
buffG = await fd.read(nPoints*sG);
|
|
|
|
await endReadSection(fd, true);
|
|
|
|
|
|
|
|
const resTau = await G.multiExpAffine(buffG, buff_r);
|
|
|
|
|
|
|
|
buff_r = await curve.Fr.batchToMontgomery(buff_r);
|
|
|
|
buff_r = await curve.Fr.fft(buff_r);
|
|
|
|
buff_r = await curve.Fr.batchFromMontgomery(buff_r);
|
|
|
|
|
|
|
|
await startReadUniqueSection(fd, sections, lagrangeSection);
|
|
|
|
fd.pos += sG*((1 << p)-1);
|
|
|
|
buffG = await fd.read(nPoints*sG);
|
|
|
|
await endReadSection(fd, true);
|
|
|
|
|
|
|
|
const resLagrange = await G.multiExpAffine(buffG, buff_r);
|
|
|
|
|
|
|
|
if (!G.eq(resTau, resLagrange)) {
|
|
|
|
if (logger) logger.error("Phase2 caclutation does not match with powers of tau");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
This function creates a new section in the fdTo file with id idSection.
|
|
|
|
It multiplies the pooints in fdFrom by first, first*inc, first*inc^2, ....
|
|
|
|
nPoint Times.
|
2020-07-14 11:55:12 +02:00
|
|
|
It also updates the newChallengeHasher with the new points
|
2020-07-11 10:31:52 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
async function applyKeyToSection(fdOld, sections, fdNew, idSection, curve, groupName, first, inc, sectionName, logger) {
|
|
|
|
const MAX_CHUNK_SIZE = 1 << 16;
|
|
|
|
const G = curve[groupName];
|
|
|
|
const sG = G.F.n8*2;
|
|
|
|
const nPoints = sections[idSection][0].size / sG;
|
|
|
|
|
|
|
|
await startReadUniqueSection(fdOld, sections,idSection );
|
|
|
|
await startWriteSection(fdNew, idSection);
|
|
|
|
|
|
|
|
let t = first;
|
|
|
|
for (let i=0; i<nPoints; i += MAX_CHUNK_SIZE) {
|
|
|
|
if (logger) logger.debug(`Applying key: ${sectionName}: ${i}/${nPoints}`);
|
|
|
|
const n= Math.min(nPoints - i, MAX_CHUNK_SIZE);
|
|
|
|
let buff;
|
|
|
|
buff = await fdOld.read(n*sG);
|
|
|
|
buff = await G.batchApplyKey(buff, t, inc);
|
|
|
|
await fdNew.write(buff);
|
|
|
|
t = curve.Fr.mul(t, curve.Fr.exp(inc, n));
|
|
|
|
}
|
|
|
|
|
|
|
|
await endWriteSection(fdNew);
|
|
|
|
await endReadSection(fdOld);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
async function applyKeyToChallengeSection(fdOld, fdNew, responseHasher, curve, groupName, nPoints, first, inc, formatOut, sectionName, logger) {
|
2020-07-11 10:31:52 +02:00
|
|
|
const G = curve[groupName];
|
|
|
|
const sG = G.F.n8*2;
|
|
|
|
const chunkSize = Math.floor((1<<20) / sG); // 128Mb chunks
|
|
|
|
let t = first;
|
|
|
|
for (let i=0 ; i<nPoints ; i+= chunkSize) {
|
|
|
|
if (logger) logger.debug(`Applying key ${sectionName}: ${i}/${nPoints}`);
|
|
|
|
const n= Math.min(nPoints-i, chunkSize );
|
|
|
|
const buffInU = await fdOld.read(n * sG);
|
|
|
|
const buffInLEM = await G.batchUtoLEM(buffInU);
|
|
|
|
const buffOutLEM = await G.batchApplyKey(buffInLEM, t, inc);
|
|
|
|
let buffOut;
|
|
|
|
if (formatOut == "COMPRESSED") {
|
|
|
|
buffOut = await G.batchLEMtoC(buffOutLEM);
|
|
|
|
} else {
|
|
|
|
buffOut = await G.batchLEMtoU(buffOutLEM);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (responseHasher) responseHasher.update(buffOut);
|
|
|
|
await fdNew.write(buffOut);
|
|
|
|
t = curve.Fr.mul(t, curve.Fr.exp(inc, n));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Format of the output
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
async function challengeContribute(curve, challengeFilename, responesFileName, entropy, logger) {
|
2020-07-11 10:31:52 +02:00
|
|
|
await blake2bWasm.ready();
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
const fdFrom = await readExisting$1(challengeFilename);
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
|
|
|
|
const sG1 = curve.F1.n64*8*2;
|
|
|
|
const sG2 = curve.F2.n64*8*2;
|
|
|
|
const domainSize = (fdFrom.totalSize + sG1 - 64 - sG2) / (4*sG1 + sG2);
|
|
|
|
let e = domainSize;
|
|
|
|
let power = 0;
|
|
|
|
while (e>1) {
|
|
|
|
e = e /2;
|
|
|
|
power += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (1<<power != domainSize) throw new Error("Invalid file size");
|
|
|
|
if (logger) logger.debug("Power to tau size: "+power);
|
|
|
|
|
|
|
|
const rng = await getRandomRng(entropy);
|
|
|
|
|
|
|
|
const fdTo = await createOverride(responesFileName);
|
|
|
|
|
|
|
|
// Calculate the hash
|
2020-07-14 11:55:12 +02:00
|
|
|
const challengeHasher = blake2bWasm(64);
|
2020-07-11 10:31:52 +02:00
|
|
|
for (let i=0; i<fdFrom.totalSize; i+= fdFrom.pageSize) {
|
2020-07-15 06:30:52 +02:00
|
|
|
if (logger) logger.debug(`Hashing challenge ${i}/${fdFrom.totalSize}`);
|
2020-07-11 10:31:52 +02:00
|
|
|
const s = Math.min(fdFrom.totalSize - i, fdFrom.pageSize);
|
|
|
|
const buff = await fdFrom.read(s);
|
2020-07-14 11:55:12 +02:00
|
|
|
challengeHasher.update(buff);
|
2020-07-11 10:31:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const claimedHash = await fdFrom.read(64, 0);
|
2020-07-29 09:11:59 +02:00
|
|
|
if (logger) logger.info(formatHash(claimedHash, "Claimed Previous Response Hash: "));
|
2020-07-11 10:31:52 +02:00
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
const challengeHash = challengeHasher.digest();
|
|
|
|
if (logger) logger.info(formatHash(challengeHash, "Current Challenge Hash: "));
|
2020-07-11 10:31:52 +02:00
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
const key = createPTauKey(curve, challengeHash, rng);
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
if (logger) {
|
|
|
|
["tau", "alpha", "beta"].forEach( (k) => {
|
|
|
|
logger.debug(k + ".g1_s: " + curve.G1.toString(key[k].g1_s, 16));
|
|
|
|
logger.debug(k + ".g1_sx: " + curve.G1.toString(key[k].g1_sx, 16));
|
|
|
|
logger.debug(k + ".g2_sp: " + curve.G2.toString(key[k].g2_sp, 16));
|
|
|
|
logger.debug(k + ".g2_spx: " + curve.G2.toString(key[k].g2_spx, 16));
|
|
|
|
logger.debug("");
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
const responseHasher = blake2bWasm(64);
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
await fdTo.write(challengeHash);
|
|
|
|
responseHasher.update(challengeHash);
|
2020-07-11 10:31:52 +02:00
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G1", (1<<power)*2-1, curve.Fr.one , key.tau.prvKey, "COMPRESSED", "tauG1" , logger );
|
|
|
|
await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G2", (1<<power) , curve.Fr.one , key.tau.prvKey, "COMPRESSED", "tauG2" , logger );
|
|
|
|
await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G1", (1<<power) , key.alpha.prvKey, key.tau.prvKey, "COMPRESSED", "alphaTauG1", logger );
|
|
|
|
await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G1", (1<<power) , key.beta.prvKey , key.tau.prvKey, "COMPRESSED", "betaTauG1" , logger );
|
|
|
|
await applyKeyToChallengeSection(fdFrom, fdTo, responseHasher, curve, "G2", 1 , key.beta.prvKey , key.tau.prvKey, "COMPRESSED", "betaTauG2" , logger );
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
// Write and hash key
|
|
|
|
const buffKey = new Uint8Array(curve.F1.n8*2*6+curve.F2.n8*2*3);
|
|
|
|
toPtauPubKeyRpr(buffKey, 0, curve, key, false);
|
|
|
|
await fdTo.write(buffKey);
|
|
|
|
responseHasher.update(buffKey);
|
|
|
|
const responseHash = responseHasher.digest();
|
|
|
|
if (logger) logger.info(formatHash(responseHash, "Contribution Response Hash: "));
|
|
|
|
|
|
|
|
await fdTo.close();
|
|
|
|
await fdFrom.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
async function beacon(oldPtauFilename, newPTauFilename, name, beaconHashStr,numIterationsExp, logger) {
|
|
|
|
const beaconHash = hex2ByteArray(beaconHashStr);
|
|
|
|
if ( (beaconHash.byteLength == 0)
|
|
|
|
|| (beaconHash.byteLength*2 !=beaconHashStr.length))
|
|
|
|
{
|
|
|
|
if (logger) logger.error("Invalid Beacon Hash. (It must be a valid hexadecimal sequence)");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (beaconHash.length>=256) {
|
|
|
|
if (logger) logger.error("Maximum lenght of beacon hash is 255 bytes");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
numIterationsExp = parseInt(numIterationsExp);
|
|
|
|
if ((numIterationsExp<10)||(numIterationsExp>63)) {
|
|
|
|
if (logger) logger.error("Invalid numIterationsExp. (Must be between 10 and 63)");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
await blake2bWasm.ready();
|
|
|
|
|
|
|
|
const {fd: fdOld, sections} = await readBinFile(oldPtauFilename, "ptau", 1);
|
|
|
|
const {curve, power, ceremonyPower} = await readPTauHeader(fdOld, sections);
|
|
|
|
if (power != ceremonyPower) {
|
|
|
|
if (logger) logger.error("This file has been reduced. You cannot contribute into a reduced file.");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (sections[12]) {
|
|
|
|
if (logger) logger.warn("Contributing into a file that has phase2 calculated. You will have to prepare phase2 again.");
|
|
|
|
}
|
|
|
|
const contributions = await readContributions(fdOld, curve, sections);
|
|
|
|
const curContribution = {
|
|
|
|
name: name,
|
|
|
|
type: 1, // Beacon
|
|
|
|
numIterationsExp: numIterationsExp,
|
|
|
|
beaconHash: beaconHash
|
|
|
|
};
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
let lastChallengeHash;
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
if (contributions.length>0) {
|
2020-07-14 11:55:12 +02:00
|
|
|
lastChallengeHash = contributions[contributions.length-1].nextChallenge;
|
2020-07-11 10:31:52 +02:00
|
|
|
} else {
|
2020-07-14 11:55:12 +02:00
|
|
|
lastChallengeHash = calculateFirstChallengeHash(curve, power, logger);
|
2020-07-11 10:31:52 +02:00
|
|
|
}
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
curContribution.key = keyFromBeacon(curve, lastChallengeHash, beaconHash, numIterationsExp);
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
const responseHasher = new blake2bWasm(64);
|
2020-07-14 11:55:12 +02:00
|
|
|
responseHasher.update(lastChallengeHash);
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
const fdNew = await createBinFile(newPTauFilename, "ptau", 1, 7);
|
|
|
|
await writePTauHeader(fdNew, curve, power);
|
|
|
|
|
|
|
|
const startSections = [];
|
|
|
|
|
|
|
|
let firstPoints;
|
|
|
|
firstPoints = await processSection(2, "G1", (1<<power) * 2 -1, curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG1", logger );
|
|
|
|
curContribution.tauG1 = firstPoints[1];
|
|
|
|
firstPoints = await processSection(3, "G2", (1<<power) , curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG2", logger );
|
|
|
|
curContribution.tauG2 = firstPoints[1];
|
|
|
|
firstPoints = await processSection(4, "G1", (1<<power) , curContribution.key.alpha.prvKey, curContribution.key.tau.prvKey, "alphaTauG1", logger );
|
|
|
|
curContribution.alphaG1 = firstPoints[0];
|
|
|
|
firstPoints = await processSection(5, "G1", (1<<power) , curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG1", logger );
|
|
|
|
curContribution.betaG1 = firstPoints[0];
|
|
|
|
firstPoints = await processSection(6, "G2", 1, curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG2", logger );
|
|
|
|
curContribution.betaG2 = firstPoints[0];
|
|
|
|
|
|
|
|
curContribution.partialHash = responseHasher.getPartialHash();
|
|
|
|
|
|
|
|
const buffKey = new Uint8Array(curve.F1.n8*2*6+curve.F2.n8*2*3);
|
|
|
|
|
|
|
|
toPtauPubKeyRpr(buffKey, 0, curve, curContribution.key, false);
|
|
|
|
|
|
|
|
responseHasher.update(new Uint8Array(buffKey));
|
|
|
|
const hashResponse = responseHasher.digest();
|
|
|
|
|
|
|
|
if (logger) logger.info(formatHash(hashResponse, "Contribution Response Hash imported: "));
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
const nextChallengeHasher = new blake2bWasm(64);
|
|
|
|
nextChallengeHasher.update(hashResponse);
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
await hashSection(fdNew, "G1", 2, (1 << power) * 2 -1, "tauG1", logger);
|
|
|
|
await hashSection(fdNew, "G2", 3, (1 << power) , "tauG2", logger);
|
|
|
|
await hashSection(fdNew, "G1", 4, (1 << power) , "alphaTauG1", logger);
|
|
|
|
await hashSection(fdNew, "G1", 5, (1 << power) , "betaTauG1", logger);
|
|
|
|
await hashSection(fdNew, "G2", 6, 1 , "betaG2", logger);
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
curContribution.nextChallenge = nextChallengeHasher.digest();
|
2020-07-11 10:31:52 +02:00
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
if (logger) logger.info(formatHash(curContribution.nextChallenge, "Next Challenge Hash: "));
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
contributions.push(curContribution);
|
|
|
|
|
|
|
|
await writeContributions(fdNew, curve, contributions);
|
|
|
|
|
|
|
|
await fdOld.close();
|
|
|
|
await fdNew.close();
|
|
|
|
|
|
|
|
return hashResponse;
|
|
|
|
|
|
|
|
async function processSection(sectionId, groupName, NPoints, first, inc, sectionName, logger) {
|
|
|
|
const res = [];
|
|
|
|
fdOld.pos = sections[sectionId][0].p;
|
|
|
|
|
|
|
|
await startWriteSection(fdNew, sectionId);
|
|
|
|
|
|
|
|
startSections[sectionId] = fdNew.pos;
|
|
|
|
|
|
|
|
const G = curve[groupName];
|
|
|
|
const sG = G.F.n8*2;
|
|
|
|
const chunkSize = Math.floor((1<<20) / sG); // 128Mb chunks
|
|
|
|
let t = first;
|
|
|
|
for (let i=0 ; i<NPoints ; i+= chunkSize) {
|
|
|
|
if (logger) logger.debug(`applying key${sectionName}: ${i}/${NPoints}`);
|
|
|
|
const n= Math.min(NPoints-i, chunkSize );
|
|
|
|
const buffIn = await fdOld.read(n * sG);
|
|
|
|
const buffOutLEM = await G.batchApplyKey(buffIn, t, inc);
|
|
|
|
|
|
|
|
/* Code to test the case where we don't have the 2^m-2 component
|
|
|
|
if (sectionName== "tauG1") {
|
|
|
|
const bz = new Uint8Array(64);
|
|
|
|
buffOutLEM.set(bz, 64*((1 << power) - 1 ));
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
const promiseWrite = fdNew.write(buffOutLEM);
|
|
|
|
const buffOutC = await G.batchLEMtoC(buffOutLEM);
|
|
|
|
|
|
|
|
responseHasher.update(buffOutC);
|
|
|
|
await promiseWrite;
|
|
|
|
if (i==0) // Return the 2 first points.
|
|
|
|
for (let j=0; j<Math.min(2, NPoints); j++)
|
|
|
|
res.push(G.fromRprLEM(buffOutLEM, j*sG));
|
|
|
|
t = curve.Fr.mul(t, curve.Fr.exp(inc, n));
|
|
|
|
}
|
|
|
|
|
|
|
|
await endWriteSection(fdNew);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function hashSection(fdTo, groupName, sectionId, nPoints, sectionName, logger) {
|
|
|
|
|
|
|
|
const G = curve[groupName];
|
|
|
|
const sG = G.F.n8*2;
|
|
|
|
const nPointsChunk = Math.floor((1<<24)/sG);
|
|
|
|
|
|
|
|
const oldPos = fdTo.pos;
|
|
|
|
fdTo.pos = startSections[sectionId];
|
|
|
|
|
|
|
|
for (let i=0; i< nPoints; i += nPointsChunk) {
|
|
|
|
if (logger) logger.debug(`Hashing ${sectionName}: ${i}/${nPoints}`);
|
|
|
|
const n = Math.min(nPoints-i, nPointsChunk);
|
|
|
|
|
|
|
|
const buffLEM = await fdTo.read(n * sG);
|
|
|
|
|
|
|
|
const buffU = await G.batchLEMtoU(buffLEM);
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
nextChallengeHasher.update(buffU);
|
2020-07-11 10:31:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fdTo.pos = oldPos;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Format of the output
|
|
|
|
|
|
|
|
async function contribute(oldPtauFilename, newPTauFilename, name, entropy, logger) {
|
|
|
|
await blake2bWasm.ready();
|
|
|
|
|
|
|
|
const {fd: fdOld, sections} = await readBinFile(oldPtauFilename, "ptau", 1);
|
|
|
|
const {curve, power, ceremonyPower} = await readPTauHeader(fdOld, sections);
|
|
|
|
if (power != ceremonyPower) {
|
|
|
|
if (logger) logger.error("This file has been reduced. You cannot contribute into a reduced file.");
|
|
|
|
throw new Error("This file has been reduced. You cannot contribute into a reduced file.");
|
|
|
|
}
|
|
|
|
if (sections[12]) {
|
|
|
|
if (logger) logger.warn("WARNING: Contributing into a file that has phase2 calculated. You will have to prepare phase2 again.");
|
|
|
|
}
|
|
|
|
const contributions = await readContributions(fdOld, curve, sections);
|
|
|
|
const curContribution = {
|
|
|
|
name: name,
|
|
|
|
type: 0, // Beacon
|
|
|
|
};
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
let lastChallengeHash;
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
const rng = await getRandomRng(entropy);
|
|
|
|
|
|
|
|
if (contributions.length>0) {
|
2020-07-14 11:55:12 +02:00
|
|
|
lastChallengeHash = contributions[contributions.length-1].nextChallenge;
|
2020-07-11 10:31:52 +02:00
|
|
|
} else {
|
2020-07-14 11:55:12 +02:00
|
|
|
lastChallengeHash = calculateFirstChallengeHash(curve, power, logger);
|
2020-07-11 10:31:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Generate a random key
|
|
|
|
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
curContribution.key = createPTauKey(curve, lastChallengeHash, rng);
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
|
|
|
|
const responseHasher = new blake2bWasm(64);
|
2020-07-14 11:55:12 +02:00
|
|
|
responseHasher.update(lastChallengeHash);
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
const fdNew = await createBinFile(newPTauFilename, "ptau", 1, 7);
|
|
|
|
await writePTauHeader(fdNew, curve, power);
|
|
|
|
|
|
|
|
const startSections = [];
|
|
|
|
|
|
|
|
let firstPoints;
|
|
|
|
firstPoints = await processSection(2, "G1", (1<<power) * 2 -1, curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG1" );
|
|
|
|
curContribution.tauG1 = firstPoints[1];
|
|
|
|
firstPoints = await processSection(3, "G2", (1<<power) , curve.Fr.e(1), curContribution.key.tau.prvKey, "tauG2" );
|
|
|
|
curContribution.tauG2 = firstPoints[1];
|
|
|
|
firstPoints = await processSection(4, "G1", (1<<power) , curContribution.key.alpha.prvKey, curContribution.key.tau.prvKey, "alphaTauG1" );
|
|
|
|
curContribution.alphaG1 = firstPoints[0];
|
|
|
|
firstPoints = await processSection(5, "G1", (1<<power) , curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG1" );
|
|
|
|
curContribution.betaG1 = firstPoints[0];
|
|
|
|
firstPoints = await processSection(6, "G2", 1, curContribution.key.beta.prvKey, curContribution.key.tau.prvKey, "betaTauG2" );
|
|
|
|
curContribution.betaG2 = firstPoints[0];
|
|
|
|
|
|
|
|
curContribution.partialHash = responseHasher.getPartialHash();
|
|
|
|
|
|
|
|
const buffKey = new Uint8Array(curve.F1.n8*2*6+curve.F2.n8*2*3);
|
|
|
|
|
|
|
|
toPtauPubKeyRpr(buffKey, 0, curve, curContribution.key, false);
|
|
|
|
|
|
|
|
responseHasher.update(new Uint8Array(buffKey));
|
|
|
|
const hashResponse = responseHasher.digest();
|
|
|
|
|
|
|
|
if (logger) logger.info(formatHash(hashResponse, "Contribution Response Hash imported: "));
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
const nextChallengeHasher = new blake2bWasm(64);
|
|
|
|
nextChallengeHasher.update(hashResponse);
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
await hashSection(fdNew, "G1", 2, (1 << power) * 2 -1, "tauG1");
|
|
|
|
await hashSection(fdNew, "G2", 3, (1 << power) , "tauG2");
|
|
|
|
await hashSection(fdNew, "G1", 4, (1 << power) , "alphaTauG1");
|
|
|
|
await hashSection(fdNew, "G1", 5, (1 << power) , "betaTauG1");
|
|
|
|
await hashSection(fdNew, "G2", 6, 1 , "betaG2");
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
curContribution.nextChallenge = nextChallengeHasher.digest();
|
2020-07-11 10:31:52 +02:00
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
if (logger) logger.info(formatHash(curContribution.nextChallenge, "Next Challenge Hash: "));
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
contributions.push(curContribution);
|
|
|
|
|
|
|
|
await writeContributions(fdNew, curve, contributions);
|
|
|
|
|
|
|
|
await fdOld.close();
|
|
|
|
await fdNew.close();
|
|
|
|
|
|
|
|
return hashResponse;
|
|
|
|
|
|
|
|
async function processSection(sectionId, groupName, NPoints, first, inc, sectionName) {
|
|
|
|
const res = [];
|
|
|
|
fdOld.pos = sections[sectionId][0].p;
|
|
|
|
|
|
|
|
await startWriteSection(fdNew, sectionId);
|
|
|
|
|
|
|
|
startSections[sectionId] = fdNew.pos;
|
|
|
|
|
|
|
|
const G = curve[groupName];
|
|
|
|
const sG = G.F.n8*2;
|
|
|
|
const chunkSize = Math.floor((1<<20) / sG); // 128Mb chunks
|
|
|
|
let t = first;
|
|
|
|
for (let i=0 ; i<NPoints ; i+= chunkSize) {
|
|
|
|
if (logger) logger.debug(`processing: ${sectionName}: ${i}/${NPoints}`);
|
|
|
|
const n= Math.min(NPoints-i, chunkSize );
|
|
|
|
const buffIn = await fdOld.read(n * sG);
|
|
|
|
const buffOutLEM = await G.batchApplyKey(buffIn, t, inc);
|
|
|
|
|
|
|
|
/* Code to test the case where we don't have the 2^m-2 component
|
|
|
|
if (sectionName== "tauG1") {
|
|
|
|
const bz = new Uint8Array(64);
|
|
|
|
buffOutLEM.set(bz, 64*((1 << power) - 1 ));
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
const promiseWrite = fdNew.write(buffOutLEM);
|
|
|
|
const buffOutC = await G.batchLEMtoC(buffOutLEM);
|
|
|
|
|
|
|
|
responseHasher.update(buffOutC);
|
|
|
|
await promiseWrite;
|
|
|
|
if (i==0) // Return the 2 first points.
|
|
|
|
for (let j=0; j<Math.min(2, NPoints); j++)
|
|
|
|
res.push(G.fromRprLEM(buffOutLEM, j*sG));
|
|
|
|
t = curve.Fr.mul(t, curve.Fr.exp(inc, n));
|
|
|
|
}
|
|
|
|
|
|
|
|
await endWriteSection(fdNew);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function hashSection(fdTo, groupName, sectionId, nPoints, sectionName) {
|
|
|
|
|
|
|
|
const G = curve[groupName];
|
|
|
|
const sG = G.F.n8*2;
|
|
|
|
const nPointsChunk = Math.floor((1<<24)/sG);
|
|
|
|
|
|
|
|
const oldPos = fdTo.pos;
|
|
|
|
fdTo.pos = startSections[sectionId];
|
|
|
|
|
|
|
|
for (let i=0; i< nPoints; i += nPointsChunk) {
|
|
|
|
if ((logger)&&i) logger.debug(`Hashing ${sectionName}: ` + i);
|
|
|
|
const n = Math.min(nPoints-i, nPointsChunk);
|
|
|
|
|
|
|
|
const buffLEM = await fdTo.read(n * sG);
|
|
|
|
|
|
|
|
const buffU = await G.batchLEMtoU(buffLEM);
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
nextChallengeHasher.update(buffU);
|
2020-07-11 10:31:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fdTo.pos = oldPos;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
async function preparePhase2(oldPtauFilename, newPTauFilename, logger) {
|
|
|
|
|
|
|
|
const {fd: fdOld, sections} = await readBinFile(oldPtauFilename, "ptau", 1);
|
|
|
|
const {curve, power} = await readPTauHeader(fdOld, sections);
|
|
|
|
|
|
|
|
const fdNew = await createBinFile(newPTauFilename, "ptau", 1, 11);
|
|
|
|
await writePTauHeader(fdNew, curve, power);
|
|
|
|
|
|
|
|
// const fdTmp = await fastFile.createOverride(newPTauFilename+ ".tmp");
|
|
|
|
const fdTmp = await createOverride({type: "mem"});
|
|
|
|
|
|
|
|
await copySection(fdOld, sections, fdNew, 2);
|
|
|
|
await copySection(fdOld, sections, fdNew, 3);
|
|
|
|
await copySection(fdOld, sections, fdNew, 4);
|
|
|
|
await copySection(fdOld, sections, fdNew, 5);
|
|
|
|
await copySection(fdOld, sections, fdNew, 6);
|
|
|
|
await copySection(fdOld, sections, fdNew, 7);
|
|
|
|
|
|
|
|
await processSection(2, 12, "G1", "tauG1" );
|
|
|
|
await processSection(3, 13, "G2", "tauG2" );
|
|
|
|
await processSection(4, 14, "G1", "alphaTauG1" );
|
|
|
|
await processSection(5, 15, "G1", "betaTauG1" );
|
|
|
|
|
|
|
|
await fdOld.close();
|
|
|
|
await fdNew.close();
|
|
|
|
await fdTmp.close();
|
|
|
|
|
|
|
|
// await fs.promises.unlink(newPTauFilename+ ".tmp");
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
async function processSection(oldSectionId, newSectionId, Gstr, sectionName) {
|
|
|
|
const CHUNKPOW = 16;
|
|
|
|
if (logger) logger.debug("Starting section: "+sectionName);
|
|
|
|
|
|
|
|
await startWriteSection(fdNew, newSectionId);
|
|
|
|
|
|
|
|
for (let p=0; p<=power; p++) {
|
|
|
|
await processSectionPower(p);
|
|
|
|
}
|
|
|
|
|
|
|
|
await endWriteSection(fdNew);
|
|
|
|
|
|
|
|
async function processSectionPower(p) {
|
|
|
|
const chunkPower = p > CHUNKPOW ? CHUNKPOW : p;
|
|
|
|
const pointsPerChunk = 1<<chunkPower;
|
|
|
|
const nPoints = 1 << p;
|
|
|
|
const nChunks = nPoints / pointsPerChunk;
|
|
|
|
|
|
|
|
const G = curve[Gstr];
|
|
|
|
const Fr = curve.Fr;
|
|
|
|
const sGin = G.F.n8*2;
|
|
|
|
const sGmid = G.F.n8*3;
|
|
|
|
|
|
|
|
await startReadUniqueSection(fdOld, sections, oldSectionId);
|
|
|
|
// Build the initial tmp Buff
|
|
|
|
fdTmp.pos =0;
|
|
|
|
for (let i=0; i<nChunks; i++) {
|
|
|
|
let buff;
|
|
|
|
if (logger) logger.debug(`${sectionName} Prepare ${i+1}/${nChunks}`);
|
|
|
|
buff = await fdOld.read(pointsPerChunk*sGin);
|
|
|
|
buff = await G.batchToJacobian(buff);
|
|
|
|
for (let j=0; j<pointsPerChunk; j++) {
|
|
|
|
fdTmp.pos = bitReverse$1(i*pointsPerChunk+j, p)*sGmid;
|
|
|
|
await fdTmp.write(buff.slice(j*sGmid, (j+1)*sGmid ));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
await endReadSection(fdOld, true);
|
|
|
|
|
|
|
|
for (let j=0; j<nChunks; j++) {
|
|
|
|
if (logger) logger.debug(`${sectionName} ${p} FFTMix ${j+1}/${nChunks}`);
|
|
|
|
let buff;
|
|
|
|
fdTmp.pos = (j*pointsPerChunk)*sGmid;
|
|
|
|
buff = await fdTmp.read(pointsPerChunk*sGmid);
|
|
|
|
buff = await G.fftMix(buff);
|
|
|
|
fdTmp.pos = (j*pointsPerChunk)*sGmid;
|
|
|
|
await fdTmp.write(buff);
|
|
|
|
}
|
|
|
|
for (let i=chunkPower+1; i<= p; i++) {
|
|
|
|
const nGroups = 1 << (p - i);
|
|
|
|
const nChunksPerGroup = nChunks / nGroups;
|
|
|
|
for (let j=0; j<nGroups; j++) {
|
|
|
|
for (let k=0; k <nChunksPerGroup/2; k++) {
|
|
|
|
if (logger) logger.debug(`${sectionName} ${i}/${p} FFTJoin ${j+1}/${nGroups} ${k}/${nChunksPerGroup/2}`);
|
2020-08-03 22:00:03 +02:00
|
|
|
const first = Fr.exp( Fr.w[i], k*pointsPerChunk);
|
|
|
|
const inc = Fr.w[i];
|
2020-07-11 10:31:52 +02:00
|
|
|
const o1 = j*nChunksPerGroup + k;
|
|
|
|
const o2 = j*nChunksPerGroup + k + nChunksPerGroup/2;
|
|
|
|
|
|
|
|
let buff1, buff2;
|
|
|
|
fdTmp.pos = o1*pointsPerChunk*sGmid;
|
|
|
|
buff1 = await fdTmp.read(pointsPerChunk * sGmid);
|
|
|
|
fdTmp.pos = o2*pointsPerChunk*sGmid;
|
|
|
|
buff2 = await fdTmp.read(pointsPerChunk * sGmid);
|
|
|
|
|
|
|
|
[buff1, buff2] = await G.fftJoin(buff1, buff2, first, inc);
|
|
|
|
|
|
|
|
fdTmp.pos = o1*pointsPerChunk*sGmid;
|
|
|
|
await fdTmp.write(buff1);
|
|
|
|
fdTmp.pos = o2*pointsPerChunk*sGmid;
|
|
|
|
await fdTmp.write(buff2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
await finalInverse(p);
|
|
|
|
}
|
|
|
|
async function finalInverse(p) {
|
|
|
|
const G = curve[Gstr];
|
|
|
|
const Fr = curve.Fr;
|
|
|
|
const sGmid = G.F.n8*3;
|
|
|
|
const sGout = G.F.n8*2;
|
|
|
|
|
|
|
|
const chunkPower = p > CHUNKPOW ? CHUNKPOW : p;
|
|
|
|
const pointsPerChunk = 1<<chunkPower;
|
|
|
|
const nPoints = 1 << p;
|
|
|
|
const nChunks = nPoints / pointsPerChunk;
|
|
|
|
|
|
|
|
const o = fdNew.pos;
|
|
|
|
fdTmp.pos = 0;
|
|
|
|
const factor = Fr.inv( Fr.e( 1<< p));
|
|
|
|
for (let i=0; i<nChunks; i++) {
|
|
|
|
if (logger) logger.debug(`${sectionName} ${p} FFTFinal ${i+1}/${nChunks}`);
|
|
|
|
let buff;
|
|
|
|
buff = await fdTmp.read(pointsPerChunk * sGmid);
|
|
|
|
buff = await G.fftFinal(buff, factor);
|
|
|
|
|
|
|
|
if ( i == 0) {
|
|
|
|
fdNew.pos = o;
|
|
|
|
await fdNew.write(buff.slice((pointsPerChunk-1)*sGout));
|
|
|
|
fdNew.pos = o + ((nChunks - 1)*pointsPerChunk + 1) * sGout;
|
|
|
|
await fdNew.write(buff.slice(0, (pointsPerChunk-1)*sGout));
|
|
|
|
} else {
|
|
|
|
fdNew.pos = o + ((nChunks - 1 - i)*pointsPerChunk + 1) * sGout;
|
|
|
|
await fdNew.write(buff);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fdNew.pos = o + nChunks * pointsPerChunk * sGout;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function exportJson(pTauFilename, verbose) {
|
|
|
|
const {fd, sections} = await readBinFile(pTauFilename, "ptau", 1);
|
|
|
|
|
|
|
|
const {curve, power} = await readPTauHeader(fd, sections);
|
|
|
|
|
|
|
|
const pTau = {};
|
|
|
|
pTau.q = curve.q;
|
|
|
|
pTau.power = power;
|
|
|
|
pTau.contributions = await readContributions(fd, curve, sections);
|
|
|
|
|
|
|
|
pTau.tauG1 = await exportSection(2, "G1", (1 << power)*2 -1, "tauG1");
|
|
|
|
pTau.tauG2 = await exportSection(3, "G2", (1 << power), "tauG2");
|
|
|
|
pTau.alphaTauG1 = await exportSection(4, "G1", (1 << power), "alphaTauG1");
|
|
|
|
pTau.betaTauG1 = await exportSection(5, "G1", (1 << power), "betaTauG1");
|
|
|
|
pTau.betaG2 = await exportSection(6, "G2", 1, "betaG2");
|
|
|
|
|
|
|
|
pTau.lTauG1 = await exportLagrange(12, "G1", "lTauG1");
|
|
|
|
pTau.lTauG2 = await exportLagrange(13, "G2", "lTauG2");
|
|
|
|
pTau.lAlphaTauG1 = await exportLagrange(14, "G1", "lAlphaTauG2");
|
|
|
|
pTau.lBetaTauG1 = await exportLagrange(15, "G1", "lBetaTauG2");
|
|
|
|
|
|
|
|
await fd.close();
|
|
|
|
|
|
|
|
return pTau;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async function exportSection(sectionId, groupName, nPoints, sectionName) {
|
|
|
|
const G = curve[groupName];
|
|
|
|
const sG = G.F.n8*2;
|
|
|
|
|
|
|
|
const res = [];
|
|
|
|
await startReadUniqueSection(fd, sections, sectionId);
|
|
|
|
for (let i=0; i< nPoints; i++) {
|
|
|
|
if ((verbose)&&i&&(i%10000 == 0)) console.log(`${sectionName}: ` + i);
|
|
|
|
const buff = await fd.read(sG);
|
|
|
|
res.push(G.fromRprLEM(buff, 0));
|
|
|
|
}
|
|
|
|
await endReadSection(fd);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
async function exportLagrange(sectionId, groupName, sectionName) {
|
|
|
|
const G = curve[groupName];
|
|
|
|
const sG = G.F.n8*2;
|
|
|
|
|
|
|
|
const res = [];
|
|
|
|
await startReadUniqueSection(fd, sections, sectionId);
|
|
|
|
for (let p=0; p<=power; p++) {
|
|
|
|
if (verbose) console.log(`${sectionName}: Power: ${p}`);
|
|
|
|
res[p] = [];
|
|
|
|
const nPoints = (1<<p);
|
|
|
|
for (let i=0; i<nPoints; i++) {
|
|
|
|
if ((verbose)&&i&&(i%10000 == 0)) console.log(`${sectionName}: ${i}/${nPoints}`);
|
|
|
|
const buff = await fd.read(sG);
|
|
|
|
res[p].push(G.fromRprLEM(buff, 0));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
await endReadSection(fd);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
var powersoftau = /*#__PURE__*/Object.freeze({
|
|
|
|
__proto__: null,
|
|
|
|
newAccumulator: newAccumulator,
|
2020-07-14 11:55:12 +02:00
|
|
|
exportChallenge: exportChallenge,
|
2020-07-11 10:31:52 +02:00
|
|
|
importResponse: importResponse,
|
|
|
|
verify: verify,
|
2020-07-14 11:55:12 +02:00
|
|
|
challengeContribute: challengeContribute,
|
2020-07-11 10:31:52 +02:00
|
|
|
beacon: beacon,
|
|
|
|
contribute: contribute,
|
|
|
|
preparePhase2: preparePhase2,
|
|
|
|
exportJson: exportJson
|
|
|
|
});
|
|
|
|
|
|
|
|
function r1csPrint(r1cs, syms, logger) {
|
|
|
|
for (let i=0; i<r1cs.constraints.length; i++) {
|
|
|
|
printCostraint(r1cs.constraints[i]);
|
|
|
|
}
|
|
|
|
function printCostraint(c) {
|
|
|
|
const lc2str = (lc) => {
|
|
|
|
let S = "";
|
|
|
|
const keys = Object.keys(lc);
|
|
|
|
keys.forEach( (k) => {
|
|
|
|
let name = syms.varIdx2Name[k];
|
|
|
|
if (name == "one") name = "";
|
|
|
|
|
|
|
|
let vs = r1cs.Fr.toString(lc[k]);
|
|
|
|
if (vs == "1") vs = ""; // Do not show ones
|
|
|
|
if (vs == "-1") vs = "-"; // Do not show ones
|
|
|
|
if ((S!="")&&(vs[0]!="-")) vs = "+"+vs;
|
|
|
|
if (S!="") vs = " "+vs;
|
|
|
|
S= S + vs + name;
|
|
|
|
});
|
|
|
|
return S;
|
|
|
|
};
|
|
|
|
const S = `[ ${lc2str(c[0])} ] * [ ${lc2str(c[1])} ] - [ ${lc2str(c[2])} ] = 0`;
|
|
|
|
if (logger) logger.info(S);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-07-26 14:05:23 +02:00
|
|
|
async function open$1(fileName, openFlags, cacheSize) {
|
|
|
|
cacheSize = cacheSize || 4096*64;
|
|
|
|
if (["w+", "wx+", "r", "ax+", "a+"].indexOf(openFlags) <0)
|
|
|
|
throw new Error("Invalid open option");
|
|
|
|
const fd =await crypto.promises.open(fileName, openFlags);
|
|
|
|
|
|
|
|
const stats = await fd.stat();
|
|
|
|
|
|
|
|
return new FastFile$1(fd, stats, cacheSize, fileName);
|
|
|
|
}
|
|
|
|
|
|
|
|
class FastFile$1 {
|
|
|
|
|
|
|
|
constructor(fd, stats, cacheSize, fileName) {
|
|
|
|
this.fileName = fileName;
|
|
|
|
this.fd = fd;
|
|
|
|
this.pos = 0;
|
|
|
|
this.pageBits = 8;
|
|
|
|
this.pageSize = (1 << this.pageBits);
|
|
|
|
while (this.pageSize < stats.blksize*4) {
|
|
|
|
this.pageBits ++;
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
_loadPage(p) {
|
|
|
|
const self = this;
|
|
|
|
return new Promise((resolve, reject)=> {
|
|
|
|
self.pendingLoads.push({
|
|
|
|
page: p,
|
|
|
|
resolve: resolve,
|
|
|
|
reject: reject
|
|
|
|
});
|
|
|
|
setImmediate(self._triggerLoad.bind(self));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_triggerLoad() {
|
|
|
|
const self = this;
|
|
|
|
processPendingLoads();
|
|
|
|
if (self.pendingLoads.length == 0) return;
|
|
|
|
if (Object.keys(self.pages).length >= self.maxPagesLoaded) {
|
|
|
|
const dp = getDeletablePage();
|
|
|
|
if (dp<0) { // // No sizes available
|
|
|
|
// setTimeout(self._triggerLoad.bind(self), 10000);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
delete self.pages[dp];
|
|
|
|
}
|
|
|
|
const load = self.pendingLoads.shift();
|
|
|
|
if (load.page>=self.totalPages) {
|
|
|
|
self.pages[load.page] = {
|
|
|
|
dirty: false,
|
|
|
|
buff: new Uint8Array(self.pageSize),
|
|
|
|
pendingOps: 1,
|
|
|
|
size: 0
|
|
|
|
};
|
|
|
|
load.resolve();
|
|
|
|
setImmediate(self._triggerLoad.bind(self));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (self.reading) {
|
|
|
|
self.pendingLoads.unshift(load);
|
|
|
|
return; // Only one read at a time.
|
|
|
|
}
|
|
|
|
|
|
|
|
self.reading = true;
|
|
|
|
const page = {
|
|
|
|
dirty: false,
|
|
|
|
buff: new Uint8Array(self.pageSize),
|
|
|
|
pendingOps: 1,
|
|
|
|
size: 0
|
|
|
|
};
|
|
|
|
self.fd.read(page.buff, 0, self.pageSize, load.page*self.pageSize).then((res)=> {
|
|
|
|
page.size = res.bytesRead;
|
|
|
|
self.pages[load.page] = page;
|
|
|
|
self.reading = false;
|
|
|
|
load.resolve();
|
|
|
|
setImmediate(self._triggerLoad.bind(self));
|
|
|
|
}, (err) => {
|
|
|
|
load.reject(err);
|
|
|
|
});
|
|
|
|
|
|
|
|
function processPendingLoads() {
|
|
|
|
const newPendingLoads = [];
|
|
|
|
for (let i=0; i<self.pendingLoads.length; i++) {
|
|
|
|
const load = self.pendingLoads[i];
|
|
|
|
if (typeof self.pages[load.page] != "undefined") {
|
|
|
|
self.pages[load.page].pendingOps ++;
|
|
|
|
load.resolve();
|
|
|
|
} else {
|
|
|
|
newPendingLoads.push(load);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
self.pendingLoads = newPendingLoads;
|
|
|
|
}
|
|
|
|
|
|
|
|
function getDeletablePage() {
|
|
|
|
for (let p in self.pages) {
|
|
|
|
const page = self.pages[p];
|
|
|
|
if ((page.dirty == false)&&(page.pendingOps==0)) return p;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_triggerWrite() {
|
|
|
|
const self = this;
|
|
|
|
if (self.writing) return;
|
|
|
|
const p = self._getDirtyPage();
|
|
|
|
if (p<0) {
|
|
|
|
if (self.pendingClose) self.pendingClose();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
self.writing=true;
|
|
|
|
self.pages[p].dirty = false;
|
|
|
|
self.fd.write(self.pages[p].buff, 0, self.pages[p].size, p*self.pageSize).then(() => {
|
|
|
|
self.writing = false;
|
|
|
|
setImmediate(self._triggerWrite.bind(self));
|
|
|
|
setImmediate(self._triggerLoad.bind(self));
|
|
|
|
}, (err) => {
|
|
|
|
console.log("ERROR Writing: "+err);
|
|
|
|
self.error = err;
|
|
|
|
self._tryClose();
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
_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);
|
|
|
|
|
|
|
|
for (let i=firstPage; i<=lastPage; i++) await self._loadPage(i);
|
|
|
|
|
|
|
|
let p = firstPage;
|
|
|
|
let o = pos % self.pageSize;
|
|
|
|
let r = buff.byteLength;
|
|
|
|
while (r>0) {
|
|
|
|
const l = (o+r > self.pageSize) ? (self.pageSize -o) : r;
|
|
|
|
const srcView = new Uint8Array(buff.buffer, 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;
|
|
|
|
}
|
|
|
|
setImmediate(self._triggerWrite.bind(self));
|
|
|
|
}
|
|
|
|
|
|
|
|
async read(len, pos) {
|
|
|
|
if (len == 0) {
|
|
|
|
return new Uint8Array(0);
|
|
|
|
}
|
|
|
|
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);
|
|
|
|
|
|
|
|
for (let i=firstPage; i<=lastPage; i++) await self._loadPage(i);
|
|
|
|
|
|
|
|
let buff = new Uint8Array(len);
|
|
|
|
let dstView = new Uint8Array(buff);
|
|
|
|
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) {
|
|
|
|
// 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, o, l);
|
|
|
|
buff.set(srcView, dstView.byteLength-r);
|
|
|
|
self.pages[p].pendingOps --;
|
|
|
|
r = r-l;
|
|
|
|
p ++;
|
|
|
|
o = 0;
|
|
|
|
}
|
|
|
|
setImmediate(self._triggerLoad.bind(self));
|
|
|
|
return buff;
|
|
|
|
}
|
|
|
|
|
|
|
|
_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 crypto.promises.unlink(this.fileName);
|
|
|
|
}
|
|
|
|
|
|
|
|
async writeULE32(v, pos) {
|
|
|
|
const self = this;
|
|
|
|
|
|
|
|
const b = Uint32Array.of(v);
|
|
|
|
|
|
|
|
await self.write(new Uint8Array(b.buffer), pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
async writeUBE32(v, pos) {
|
|
|
|
const self = this;
|
|
|
|
|
|
|
|
const buff = new Uint8Array(4);
|
|
|
|
const buffV = new DataView(buff.buffer);
|
|
|
|
buffV.setUint32(0, v, false);
|
|
|
|
|
|
|
|
await self.write(buff, pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async writeULE64(v, pos) {
|
|
|
|
const self = this;
|
|
|
|
|
|
|
|
const b = Uint32Array.of(v & 0xFFFFFFFF, Math.floor(v / 0x100000000));
|
|
|
|
|
|
|
|
await self.write(new Uint8Array(b.buffer), 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];
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
function readExisting$2(o) {
|
|
|
|
const fd = new MemFile$1();
|
|
|
|
fd.o = o;
|
|
|
|
fd.allocSize = o.data.byteLength;
|
|
|
|
fd.totalSize = o.data.byteLength;
|
|
|
|
fd.readOnly = true;
|
|
|
|
fd.pos = 0;
|
|
|
|
return fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
class MemFile$1 {
|
|
|
|
|
|
|
|
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, pos);
|
|
|
|
|
|
|
|
if (pos + buff.byteLength > this.totalSize) this.totalSize = pos + buff.byteLength;
|
|
|
|
|
|
|
|
this.pos = pos + buff.byteLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
async read(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 buff = this.o.data.slice(pos, pos+len);
|
|
|
|
this.pos = pos + len;
|
|
|
|
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;
|
|
|
|
|
|
|
|
const b = Uint32Array.of(v);
|
|
|
|
|
|
|
|
await self.write(new Uint8Array(b.buffer), pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
async writeUBE32(v, pos) {
|
|
|
|
const self = this;
|
|
|
|
|
|
|
|
const buff = new Uint8Array(4);
|
|
|
|
const buffV = new DataView(buff.buffer);
|
|
|
|
buffV.setUint32(0, v, false);
|
|
|
|
|
|
|
|
await self.write(buff, pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async writeULE64(v, pos) {
|
|
|
|
const self = this;
|
|
|
|
|
|
|
|
const b = Uint32Array.of(v & 0xFFFFFFFF, Math.floor(v / 0x100000000));
|
|
|
|
|
|
|
|
await self.write(new Uint8Array(b.buffer), 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];
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* global fetch */
|
|
|
|
|
|
|
|
async function readExisting$3(o, b) {
|
|
|
|
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$1(o.fileName, "r", o.cacheSize);
|
|
|
|
} else if (o.type == "mem") {
|
|
|
|
return await readExisting$2(o);
|
|
|
|
} else {
|
|
|
|
throw new Error("Invalid FastFile type: "+o.type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-11 10:31:52 +02:00
|
|
|
async function readBinFile$1(fileName, type, maxVersion) {
|
|
|
|
|
2020-07-26 14:05:23 +02:00
|
|
|
const fd = await readExisting$3(fileName);
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
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 startReadUniqueSection$1(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$1(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");
|
|
|
|
}
|
|
|
|
delete fd.readingSection;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function readBigInt$1(fd, n8, pos) {
|
|
|
|
const buff = await fd.read(n8, pos);
|
|
|
|
return Scalar$1.fromRprLE(buff, 0, n8);
|
|
|
|
}
|
|
|
|
|
|
|
|
async function loadHeader(fd,sections) {
|
|
|
|
|
|
|
|
|
|
|
|
const res = {};
|
|
|
|
await startReadUniqueSection$1(fd, sections, 1);
|
|
|
|
// Read Header
|
|
|
|
res.n8 = await fd.readULE32();
|
|
|
|
res.prime = await readBigInt$1(fd, res.n8);
|
|
|
|
res.Fr = new F1Field(res.prime);
|
|
|
|
|
|
|
|
res.nVars = await fd.readULE32();
|
|
|
|
res.nOutputs = await fd.readULE32();
|
|
|
|
res.nPubInputs = await fd.readULE32();
|
|
|
|
res.nPrvInputs = await fd.readULE32();
|
|
|
|
res.nLabels = await fd.readULE64();
|
|
|
|
res.nConstraints = await fd.readULE32();
|
|
|
|
await endReadSection$1(fd);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
async function load(fileName, loadConstraints, loadMap) {
|
|
|
|
|
|
|
|
const {fd, sections} = await readBinFile$1(fileName, "r1cs", 1);
|
|
|
|
const res = await loadHeader(fd, sections);
|
|
|
|
|
|
|
|
|
|
|
|
if (loadConstraints) {
|
|
|
|
await startReadUniqueSection$1(fd, sections, 2);
|
|
|
|
res.constraints = [];
|
|
|
|
for (let i=0; i<res.nConstraints; i++) {
|
|
|
|
const c = await readConstraint();
|
|
|
|
res.constraints.push(c);
|
|
|
|
}
|
|
|
|
await endReadSection$1(fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read Labels
|
|
|
|
|
|
|
|
if (loadMap) {
|
|
|
|
await startReadUniqueSection$1(fd, sections, 3);
|
|
|
|
|
|
|
|
res.map = [];
|
|
|
|
for (let i=0; i<res.nVars; i++) {
|
|
|
|
const idx = await fd.readULE64();
|
|
|
|
res.map.push(idx);
|
|
|
|
}
|
|
|
|
await endReadSection$1(fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
await fd.close();
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
|
|
|
async function readConstraint() {
|
|
|
|
const c = [];
|
|
|
|
c[0] = await readLC();
|
|
|
|
c[1] = await readLC();
|
|
|
|
c[2] = await readLC();
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
async function readLC() {
|
|
|
|
const lc= {};
|
|
|
|
const nIdx = await fd.readULE32();
|
|
|
|
for (let i=0; i<nIdx; i++) {
|
|
|
|
const idx = await fd.readULE32();
|
|
|
|
const val = res.Fr.e(await readBigInt$1(fd, res.n8));
|
|
|
|
lc[idx] = val;
|
|
|
|
}
|
|
|
|
return lc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const bls12381r$1 = Scalar$1.e("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", 16);
|
|
|
|
const bn128r$1 = Scalar$1.e("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
|
|
|
|
|
|
|
async function r1csInfo(r1csName, logger) {
|
|
|
|
|
|
|
|
const cir = await load(r1csName);
|
|
|
|
|
|
|
|
if (Scalar$1.eq(cir.prime, bn128r$1)) {
|
|
|
|
if (logger) logger.info("Curve: bn-128");
|
|
|
|
} else if (Scalar$1.eq(cir.prime, bls12381r$1)) {
|
|
|
|
if (logger) logger.info("Curve: bls12-381");
|
|
|
|
} else {
|
|
|
|
if (logger) logger.info(`Unknown Curve. Prime: ${Scalar$1.toString(cir.prime)}`);
|
|
|
|
}
|
|
|
|
if (logger) logger.info(`# of Wires: ${cir.nVars}`);
|
|
|
|
if (logger) logger.info(`# of Constraints: ${cir.nConstraints}`);
|
|
|
|
if (logger) logger.info(`# of Private Inputs: ${cir.nPrvInputs}`);
|
|
|
|
if (logger) logger.info(`# of Public Inputs: ${cir.nPubInputs}`);
|
|
|
|
if (logger) logger.info(`# of Outputs: ${cir.nOutputs}`);
|
|
|
|
|
|
|
|
return cir;
|
|
|
|
}
|
|
|
|
|
|
|
|
async function r1csExportJson(r1csFileName, logger) {
|
|
|
|
|
|
|
|
const cir = await load(r1csFileName, true, true);
|
|
|
|
|
|
|
|
return cir;
|
|
|
|
}
|
|
|
|
|
|
|
|
var r1cs = /*#__PURE__*/Object.freeze({
|
|
|
|
__proto__: null,
|
|
|
|
print: r1csPrint,
|
|
|
|
info: r1csInfo,
|
|
|
|
exportJson: r1csExportJson
|
|
|
|
});
|
|
|
|
|
|
|
|
async function loadSymbols(symFileName) {
|
|
|
|
const sym = {
|
|
|
|
labelIdx2Name: [ "one" ],
|
|
|
|
varIdx2Name: [ "one" ],
|
|
|
|
componentIdx2Name: []
|
|
|
|
};
|
|
|
|
const fd = await readExisting$1(symFileName);
|
|
|
|
const buff = await fd.read(fd.totalSize);
|
|
|
|
const symsStr = new TextDecoder("utf-8").decode(buff);
|
|
|
|
const lines = symsStr.split("\n");
|
|
|
|
for (let i=0; i<lines.length; i++) {
|
|
|
|
const arr = lines[i].split(",");
|
|
|
|
if (arr.length!=4) continue;
|
|
|
|
if (sym.varIdx2Name[arr[1]]) {
|
|
|
|
sym.varIdx2Name[arr[1]] += "|" + arr[3];
|
|
|
|
} else {
|
|
|
|
sym.varIdx2Name[arr[1]] = arr[3];
|
|
|
|
}
|
|
|
|
sym.labelIdx2Name[arr[0]] = arr[3];
|
|
|
|
if (!sym.componentIdx2Name[arr[2]]) {
|
|
|
|
sym.componentIdx2Name[arr[2]] = extractComponent(arr[3]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
await fd.close();
|
|
|
|
|
|
|
|
return sym;
|
|
|
|
|
|
|
|
function extractComponent(name) {
|
|
|
|
const arr = name.split(".");
|
|
|
|
arr.pop(); // Remove the lasr element
|
|
|
|
return arr.join(".");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const { WitnessCalculatorBuilder: WitnessCalculatorBuilder$2 } = circom_runtime;
|
|
|
|
|
|
|
|
async function wtnsDebug(input, wasmFileName, wtnsFileName, symName, options, logger) {
|
|
|
|
|
|
|
|
const fdWasm = await readExisting$1(wasmFileName);
|
|
|
|
const wasm = await fdWasm.read(fdWasm.totalSize);
|
|
|
|
await fdWasm.close();
|
|
|
|
|
|
|
|
|
|
|
|
let wcOps = {
|
|
|
|
sanityCheck: true
|
|
|
|
};
|
|
|
|
let sym = await loadSymbols(symName);
|
|
|
|
if (options.set) {
|
|
|
|
if (!sym) sym = await loadSymbols(symName);
|
|
|
|
wcOps.logSetSignal= function(labelIdx, value) {
|
|
|
|
if (logger) logger.info("SET " + sym.labelIdx2Name[labelIdx] + " <-- " + value.toString());
|
|
|
|
};
|
|
|
|
}
|
|
|
|
if (options.get) {
|
|
|
|
if (!sym) sym = await loadSymbols(symName);
|
|
|
|
wcOps.logGetSignal= function(varIdx, value) {
|
|
|
|
if (logger) logger.info("GET " + sym.labelIdx2Name[varIdx] + " --> " + value.toString());
|
|
|
|
};
|
|
|
|
}
|
|
|
|
if (options.trigger) {
|
|
|
|
if (!sym) sym = await loadSymbols(symName);
|
|
|
|
wcOps.logStartComponent= function(cIdx) {
|
|
|
|
if (logger) logger.info("START: " + sym.componentIdx2Name[cIdx]);
|
|
|
|
};
|
|
|
|
wcOps.logFinishComponent= function(cIdx) {
|
|
|
|
if (logger) logger.info("FINISH: " + sym.componentIdx2Name[cIdx]);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const wc = await WitnessCalculatorBuilder$2(wasm, wcOps);
|
|
|
|
const w = await wc.calculateWitness(input);
|
|
|
|
|
|
|
|
const fdWtns = await createBinFile(wtnsFileName, "wtns", 2, 2);
|
|
|
|
|
|
|
|
await write(fdWtns, w, wc.prime);
|
|
|
|
|
|
|
|
await fdWtns.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
async function wtnsExportJson(wtnsFileName) {
|
|
|
|
|
|
|
|
const w = await read(wtnsFileName);
|
|
|
|
|
|
|
|
return w;
|
|
|
|
}
|
|
|
|
|
|
|
|
var wtns = /*#__PURE__*/Object.freeze({
|
|
|
|
__proto__: null,
|
|
|
|
calculate: wtnsCalculate,
|
|
|
|
debug: wtnsDebug,
|
|
|
|
exportJson: wtnsExportJson
|
|
|
|
});
|
|
|
|
|
|
|
|
async function newZKey(r1csName, ptauName, zkeyName, logger) {
|
|
|
|
await blake2bWasm.ready();
|
|
|
|
const csHasher = blake2bWasm(64);
|
|
|
|
|
|
|
|
const {fd: fdR1cs, sections: sectionsR1cs} = await readBinFile(r1csName, "r1cs", 1);
|
|
|
|
const r1cs = await loadHeader(fdR1cs, sectionsR1cs);
|
|
|
|
|
|
|
|
const {fd: fdPTau, sections: sectionsPTau} = await readBinFile(ptauName, "ptau", 1);
|
|
|
|
const {curve, power} = await readPTauHeader(fdPTau, sectionsPTau);
|
|
|
|
|
|
|
|
const fdZKey = await createBinFile(zkeyName, "zkey", 1, 10);
|
|
|
|
|
|
|
|
const sG1 = curve.G1.F.n8*2;
|
|
|
|
const sG2 = curve.G2.F.n8*2;
|
|
|
|
|
|
|
|
if (r1cs.prime != curve.r) {
|
|
|
|
if (logger) logger.error("r1cs curve does not match powers of tau ceremony curve");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
const cirPower = log2$2(r1cs.nConstraints + r1cs.nPubInputs + r1cs.nOutputs +1 -1) +1;
|
|
|
|
|
|
|
|
if (cirPower > power) {
|
|
|
|
if (logger) logger.error(`circuit too big for this power of tau ceremony. ${r1cs.nConstraints} > 2**${power}`);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!sectionsPTau[12]) {
|
|
|
|
if (logger) logger.error("Powers of tau is not prepared.");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
const nPublic = r1cs.nOutputs + r1cs.nPubInputs;
|
|
|
|
const domainSize = 1 << cirPower;
|
|
|
|
|
|
|
|
// Write the header
|
|
|
|
///////////
|
|
|
|
await startWriteSection(fdZKey, 1);
|
|
|
|
await fdZKey.writeULE32(1); // Groth
|
|
|
|
await endWriteSection(fdZKey);
|
|
|
|
|
|
|
|
// Write the Groth header section
|
|
|
|
///////////
|
|
|
|
|
|
|
|
await startWriteSection(fdZKey, 2);
|
|
|
|
const primeQ = curve.q;
|
|
|
|
const n8q = (Math.floor( (Scalar$1.bitLength(primeQ) - 1) / 64) +1)*8;
|
|
|
|
|
|
|
|
const primeR = curve.r;
|
|
|
|
const n8r = (Math.floor( (Scalar$1.bitLength(primeR) - 1) / 64) +1)*8;
|
|
|
|
const Rr = Scalar$1.mod(Scalar$1.shl(1, n8r*8), primeR);
|
|
|
|
const R2r = curve.Fr.e(Scalar$1.mod(Scalar$1.mul(Rr,Rr), primeR));
|
|
|
|
|
|
|
|
await fdZKey.writeULE32(n8q);
|
|
|
|
await writeBigInt(fdZKey, primeQ, n8q);
|
|
|
|
await fdZKey.writeULE32(n8r);
|
|
|
|
await writeBigInt(fdZKey, primeR, n8r);
|
|
|
|
await fdZKey.writeULE32(r1cs.nVars); // Total number of bars
|
|
|
|
await fdZKey.writeULE32(nPublic); // Total number of public vars (not including ONE)
|
|
|
|
await fdZKey.writeULE32(domainSize); // domainSize
|
|
|
|
|
|
|
|
let bAlpha1;
|
|
|
|
bAlpha1 = await fdPTau.read(sG1, sectionsPTau[4][0].p);
|
|
|
|
await fdZKey.write(bAlpha1);
|
|
|
|
bAlpha1 = await curve.G1.batchLEMtoU(bAlpha1);
|
|
|
|
csHasher.update(bAlpha1);
|
|
|
|
|
|
|
|
let bBeta1;
|
|
|
|
bBeta1 = await fdPTau.read(sG1, sectionsPTau[5][0].p);
|
|
|
|
await fdZKey.write(bBeta1);
|
|
|
|
bBeta1 = await curve.G1.batchLEMtoU(bBeta1);
|
|
|
|
csHasher.update(bBeta1);
|
|
|
|
|
|
|
|
let bBeta2;
|
|
|
|
bBeta2 = await fdPTau.read(sG2, sectionsPTau[6][0].p);
|
|
|
|
await fdZKey.write(bBeta2);
|
|
|
|
bBeta2 = await curve.G2.batchLEMtoU(bBeta2);
|
|
|
|
csHasher.update(bBeta2);
|
|
|
|
|
|
|
|
const bg1 = new Uint8Array(sG1);
|
|
|
|
curve.G1.toRprLEM(bg1, 0, curve.G1.g);
|
|
|
|
const bg2 = new Uint8Array(sG2);
|
|
|
|
curve.G2.toRprLEM(bg2, 0, curve.G2.g);
|
|
|
|
const bg1U = new Uint8Array(sG1);
|
|
|
|
curve.G1.toRprUncompressed(bg1U, 0, curve.G1.g);
|
|
|
|
const bg2U = new Uint8Array(sG2);
|
|
|
|
curve.G2.toRprUncompressed(bg2U, 0, curve.G2.g);
|
|
|
|
|
|
|
|
await fdZKey.write(bg2); // gamma2
|
|
|
|
await fdZKey.write(bg1); // delta1
|
|
|
|
await fdZKey.write(bg2); // delta2
|
|
|
|
csHasher.update(bg2U); // gamma2
|
|
|
|
csHasher.update(bg1U); // delta1
|
|
|
|
csHasher.update(bg2U); // delta2
|
|
|
|
await endWriteSection(fdZKey);
|
|
|
|
|
|
|
|
|
|
|
|
const A = new Array(r1cs.nVars);
|
|
|
|
const B1 = new Array(r1cs.nVars);
|
|
|
|
const B2 = new Array(r1cs.nVars);
|
|
|
|
const C = new Array(r1cs.nVars- nPublic -1);
|
|
|
|
const IC = new Array(nPublic+1);
|
|
|
|
|
|
|
|
const lTauG1 = sectionsPTau[12][0].p + ((1 << cirPower) -1)*sG1;
|
|
|
|
const lTauG2 = sectionsPTau[13][0].p + ((1 << cirPower) -1)*sG2;
|
|
|
|
const lAlphaTauG1 = sectionsPTau[14][0].p + ((1 << cirPower) -1)*sG1;
|
|
|
|
const lBetaTauG1 = sectionsPTau[15][0].p + ((1 << cirPower) -1)*sG1;
|
|
|
|
|
|
|
|
await startWriteSection(fdZKey, 4);
|
|
|
|
await startReadUniqueSection(fdR1cs, sectionsR1cs, 2);
|
|
|
|
|
|
|
|
const pNCoefs = fdZKey.pos;
|
|
|
|
let nCoefs = 0;
|
|
|
|
fdZKey.pos += 4;
|
|
|
|
for (let c=0; c<r1cs.nConstraints; c++) {
|
|
|
|
if ((logger)&(c%10000 == 0)) logger.debug(`processing constraints: ${c}/${r1cs.nConstraints}`);
|
|
|
|
const nA = await fdR1cs.readULE32();
|
|
|
|
for (let i=0; i<nA; i++) {
|
|
|
|
const s = await fdR1cs.readULE32();
|
|
|
|
const coef = await fdR1cs.read(r1cs.n8);
|
|
|
|
|
|
|
|
const l1 = lTauG1 + sG1*c;
|
|
|
|
const l2 = lBetaTauG1 + sG1*c;
|
|
|
|
if (typeof A[s] === "undefined") A[s] = [];
|
|
|
|
A[s].push([l1, coef]);
|
|
|
|
|
|
|
|
if (s <= nPublic) {
|
|
|
|
if (typeof IC[s] === "undefined") IC[s] = [];
|
|
|
|
IC[s].push([l2, coef]);
|
|
|
|
} else {
|
|
|
|
if (typeof C[s- nPublic -1] === "undefined") C[s- nPublic -1] = [];
|
|
|
|
C[s - nPublic -1].push([l2, coef]);
|
|
|
|
}
|
|
|
|
await fdZKey.writeULE32(0);
|
|
|
|
await fdZKey.writeULE32(c);
|
|
|
|
await fdZKey.writeULE32(s);
|
|
|
|
await writeFr2(coef);
|
|
|
|
nCoefs ++;
|
|
|
|
}
|
|
|
|
|
|
|
|
const nB = await fdR1cs.readULE32();
|
|
|
|
for (let i=0; i<nB; i++) {
|
|
|
|
const s = await fdR1cs.readULE32();
|
|
|
|
const coef = await fdR1cs.read(r1cs.n8);
|
|
|
|
|
|
|
|
const l1 = lTauG1 + sG1*c;
|
|
|
|
const l2 = lTauG2 + sG2*c;
|
|
|
|
const l3 = lAlphaTauG1 + sG1*c;
|
|
|
|
if (typeof B1[s] === "undefined") B1[s] = [];
|
|
|
|
B1[s].push([l1, coef]);
|
|
|
|
if (typeof B2[s] === "undefined") B2[s] = [];
|
|
|
|
B2[s].push([l2, coef]);
|
|
|
|
|
|
|
|
if (s <= nPublic) {
|
|
|
|
if (typeof IC[s] === "undefined") IC[s] = [];
|
|
|
|
IC[s].push([l3, coef]);
|
|
|
|
} else {
|
|
|
|
if (typeof C[s- nPublic -1] === "undefined") C[s- nPublic -1] = [];
|
|
|
|
C[s- nPublic -1].push([l3, coef]);
|
|
|
|
}
|
|
|
|
await fdZKey.writeULE32(1);
|
|
|
|
await fdZKey.writeULE32(c);
|
|
|
|
await fdZKey.writeULE32(s);
|
|
|
|
await writeFr2(coef);
|
|
|
|
nCoefs ++;
|
|
|
|
}
|
|
|
|
|
|
|
|
const nC = await fdR1cs.readULE32();
|
|
|
|
for (let i=0; i<nC; i++) {
|
|
|
|
const s = await fdR1cs.readULE32();
|
|
|
|
const coef = await fdR1cs.read(r1cs.n8);
|
|
|
|
|
|
|
|
const l1 = lTauG1 + sG1*c;
|
|
|
|
if (s <= nPublic) {
|
|
|
|
if (typeof IC[s] === "undefined") IC[s] = [];
|
|
|
|
IC[s].push([l1, coef]);
|
|
|
|
} else {
|
|
|
|
if (typeof C[s- nPublic -1] === "undefined") C[s- nPublic -1] = [];
|
|
|
|
C[s- nPublic -1].push([l1, coef]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const bOne = new Uint8Array(curve.Fr.n8);
|
|
|
|
curve.Fr.toRprLE(bOne, 0, curve.Fr.e(1));
|
|
|
|
for (let s = 0; s <= nPublic ; s++) {
|
|
|
|
const l1 = lTauG1 + sG1*(r1cs.nConstraints + s);
|
|
|
|
const l2 = lBetaTauG1 + sG1*(r1cs.nConstraints + s);
|
|
|
|
if (typeof A[s] === "undefined") A[s] = [];
|
|
|
|
A[s].push([l1, bOne]);
|
|
|
|
if (typeof IC[s] === "undefined") IC[s] = [];
|
|
|
|
IC[s].push([l2, bOne]);
|
|
|
|
await fdZKey.writeULE32(0);
|
|
|
|
await fdZKey.writeULE32(r1cs.nConstraints + s);
|
|
|
|
await fdZKey.writeULE32(s);
|
|
|
|
await writeFr2(bOne);
|
|
|
|
nCoefs ++;
|
|
|
|
}
|
|
|
|
|
|
|
|
const oldPos = fdZKey.pos;
|
|
|
|
await fdZKey.writeULE32(nCoefs, pNCoefs);
|
|
|
|
fdZKey.pos = oldPos;
|
|
|
|
|
|
|
|
await endWriteSection(fdZKey);
|
|
|
|
await endReadSection(fdR1cs);
|
|
|
|
|
|
|
|
/*
|
|
|
|
zKey.hExps = new Array(zKey.domainSize-1);
|
|
|
|
for (let i=0; i< zKey.domainSize; i++) {
|
|
|
|
const t1 = await readEvaluation("tauG1", i);
|
|
|
|
const t2 = await readEvaluation("tauG1", i+zKey.domainSize);
|
|
|
|
zKey.hExps[i] = curve.G1.sub(t2, t1);
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
await composeAndWritePoints(3, "G1", IC, "IC");
|
|
|
|
|
|
|
|
// Write Hs
|
|
|
|
await startWriteSection(fdZKey, 9);
|
|
|
|
const o = sectionsPTau[12][0].p + ((1 << (cirPower+1)) -1)*sG1;
|
|
|
|
for (let i=0; i< domainSize; i++) {
|
|
|
|
const buff = await fdPTau.read(sG1, o + (i*2+1)*sG1 );
|
|
|
|
await fdZKey.write(buff);
|
|
|
|
}
|
|
|
|
await endWriteSection(fdZKey);
|
|
|
|
await hashHPoints();
|
|
|
|
|
|
|
|
await composeAndWritePoints(8, "G1", C, "C");
|
|
|
|
await composeAndWritePoints(5, "G1", A, "A");
|
|
|
|
await composeAndWritePoints(6, "G1", B1, "B1");
|
|
|
|
await composeAndWritePoints(7, "G2", B2, "B2");
|
|
|
|
|
|
|
|
const csHash = csHasher.digest();
|
|
|
|
// Contributions section
|
|
|
|
await startWriteSection(fdZKey, 10);
|
|
|
|
await fdZKey.write(csHash);
|
|
|
|
await fdZKey.writeULE32(0);
|
|
|
|
await endWriteSection(fdZKey);
|
|
|
|
|
|
|
|
if (logger) logger.info(formatHash(csHash, "Circuit hash: "));
|
|
|
|
|
|
|
|
|
|
|
|
await fdZKey.close();
|
|
|
|
await fdPTau.close();
|
|
|
|
await fdR1cs.close();
|
|
|
|
|
|
|
|
return csHash;
|
|
|
|
|
|
|
|
async function writeFr2(buff) {
|
|
|
|
const n = curve.Fr.fromRprLE(buff, 0);
|
|
|
|
const nR2 = curve.Fr.mul(n, R2r);
|
|
|
|
const buff2 = new Uint8Array(curve.Fr.n8);
|
|
|
|
curve.Fr.toRprLE(buff2, 0, nR2);
|
|
|
|
await fdZKey.write(buff2);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function composeAndWritePoints(idSection, groupName, arr, sectionName) {
|
|
|
|
const CHUNK_SIZE= 1<<18;
|
|
|
|
|
|
|
|
hashU32(arr.length);
|
|
|
|
await startWriteSection(fdZKey, idSection);
|
|
|
|
|
|
|
|
for (let i=0; i<arr.length; i+= CHUNK_SIZE) {
|
|
|
|
if (logger) logger.debug(`Writing points ${sectionName}: ${i}/${arr.length}`);
|
|
|
|
const n = Math.min(arr.length -i, CHUNK_SIZE);
|
|
|
|
const subArr = arr.slice(i, i + n);
|
|
|
|
await composeAndWritePointsChunk(groupName, subArr);
|
|
|
|
}
|
|
|
|
await endWriteSection(fdZKey);
|
|
|
|
}
|
|
|
|
|
|
|
|
async function composeAndWritePointsChunk(groupName, arr) {
|
|
|
|
const concurrency= curve.tm.concurrency;
|
|
|
|
const nElementsPerThread = Math.floor(arr.length / concurrency);
|
|
|
|
const opPromises = [];
|
|
|
|
const G = curve[groupName];
|
|
|
|
for (let i=0; i<concurrency; i++) {
|
|
|
|
let n;
|
|
|
|
if (i< concurrency-1) {
|
|
|
|
n = nElementsPerThread;
|
|
|
|
} else {
|
|
|
|
n = arr.length - i*nElementsPerThread;
|
|
|
|
}
|
|
|
|
if (n==0) continue;
|
|
|
|
|
|
|
|
const subArr = arr.slice(i*nElementsPerThread, i*nElementsPerThread + n);
|
|
|
|
opPromises.push(composeAndWritePointsThread(groupName, subArr));
|
|
|
|
}
|
|
|
|
|
|
|
|
const result = await Promise.all(opPromises);
|
|
|
|
|
|
|
|
for (let i=0; i<result.length; i++) {
|
|
|
|
await fdZKey.write(result[i][0]);
|
|
|
|
const buff = await G.batchLEMtoU(result[i][0]);
|
|
|
|
csHasher.update(buff);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function composeAndWritePointsThread(groupName, arr) {
|
|
|
|
const G = curve[groupName];
|
|
|
|
const sGin = G.F.n8*2;
|
|
|
|
const sGmid = G.F.n8*3;
|
|
|
|
const sGout = G.F.n8*2;
|
|
|
|
let fnExp, fnMultiExp, fnBatchToAffine, fnZero;
|
|
|
|
if (groupName == "G1") {
|
|
|
|
fnExp = "g1m_timesScalarAffine";
|
|
|
|
fnMultiExp = "g1m_multiexpAffine";
|
|
|
|
fnBatchToAffine = "g1m_batchToAffine";
|
|
|
|
fnZero = "g1m_zero";
|
|
|
|
} else if (groupName == "G2") {
|
|
|
|
fnExp = "g2m_timesScalarAffine";
|
|
|
|
fnMultiExp = "g2m_multiexpAffine";
|
|
|
|
fnBatchToAffine = "g2m_batchToAffine";
|
|
|
|
fnZero = "g2m_zero";
|
|
|
|
} else {
|
|
|
|
throw new Error("Invalid group");
|
|
|
|
}
|
|
|
|
let acc =0;
|
|
|
|
for (let i=0; i<arr.length; i++) acc += arr[i] ? arr[i].length : 0;
|
|
|
|
const bBases = new Uint8Array(acc*sGin);
|
|
|
|
const bScalars = new Uint8Array(acc*curve.Fr.n8);
|
|
|
|
let pB =0;
|
|
|
|
let pS =0;
|
|
|
|
for (let i=0; i<arr.length; i++) {
|
|
|
|
if (!arr[i]) continue;
|
|
|
|
for (let j=0; j<arr[i].length; j++) {
|
|
|
|
const bBase = await fdPTau.read(sGin, arr[i][j][0]);
|
|
|
|
bBases.set(bBase, pB);
|
|
|
|
pB += sGin;
|
|
|
|
bScalars.set(arr[i][j][1], pS);
|
|
|
|
pS += curve.Fr.n8;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const task = [];
|
|
|
|
task.push({cmd: "ALLOCSET", var: 0, buff: bBases});
|
|
|
|
task.push({cmd: "ALLOCSET", var: 1, buff: bScalars});
|
|
|
|
task.push({cmd: "ALLOC", var: 2, len: arr.length*sGmid});
|
|
|
|
pB = 0;
|
|
|
|
pS = 0;
|
|
|
|
let pD =0;
|
|
|
|
for (let i=0; i<arr.length; i++) {
|
|
|
|
if (!arr[i]) {
|
|
|
|
task.push({cmd: "CALL", fnName: fnZero, params: [
|
|
|
|
{var: 2, offset: pD}
|
|
|
|
]});
|
|
|
|
pD += sGmid;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (arr[i].length == 1) {
|
|
|
|
task.push({cmd: "CALL", fnName: fnExp, params: [
|
|
|
|
{var: 0, offset: pB},
|
|
|
|
{var: 1, offset: pS},
|
|
|
|
{val: curve.Fr.n8},
|
|
|
|
{var: 2, offset: pD}
|
|
|
|
]});
|
|
|
|
} else {
|
|
|
|
task.push({cmd: "CALL", fnName: fnMultiExp, params: [
|
|
|
|
{var: 0, offset: pB},
|
|
|
|
{var: 1, offset: pS},
|
|
|
|
{val: curve.Fr.n8},
|
|
|
|
{val: arr[i].length},
|
|
|
|
{var: 2, offset: pD}
|
|
|
|
]});
|
|
|
|
}
|
|
|
|
pB += sGin*arr[i].length;
|
|
|
|
pS += curve.Fr.n8*arr[i].length;
|
|
|
|
pD += sGmid;
|
|
|
|
}
|
|
|
|
task.push({cmd: "CALL", fnName: fnBatchToAffine, params: [
|
|
|
|
{var: 2},
|
|
|
|
{val: arr.length},
|
|
|
|
{var: 2},
|
|
|
|
]});
|
|
|
|
task.push({cmd: "GET", out: 0, var: 2, len: arr.length*sGout});
|
|
|
|
|
|
|
|
const res = await curve.tm.queueAction(task);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function hashHPoints() {
|
|
|
|
const CHUNK_SIZE = 1<<14;
|
|
|
|
|
|
|
|
hashU32(domainSize-1);
|
|
|
|
|
|
|
|
for (let i=0; i<domainSize-1; i+= CHUNK_SIZE) {
|
|
|
|
if (logger) logger.debug(`HashingHPoints: ${i}/${domainSize}`);
|
|
|
|
const n = Math.min(domainSize-1, CHUNK_SIZE);
|
|
|
|
await hashHPointsChunk(i, n);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function hashHPointsChunk(offset, nPoints) {
|
|
|
|
const buff1 = await fdPTau.read(nPoints *sG1, sectionsPTau[2][0].p + (offset + domainSize)*sG1);
|
|
|
|
const buff2 = await fdPTau.read(nPoints *sG1, sectionsPTau[2][0].p + offset*sG1);
|
|
|
|
const concurrency= curve.tm.concurrency;
|
|
|
|
const nPointsPerThread = Math.floor(nPoints / concurrency);
|
|
|
|
const opPromises = [];
|
|
|
|
for (let i=0; i<concurrency; i++) {
|
|
|
|
let n;
|
|
|
|
if (i< concurrency-1) {
|
|
|
|
n = nPointsPerThread;
|
|
|
|
} else {
|
|
|
|
n = nPoints - i*nPointsPerThread;
|
|
|
|
}
|
|
|
|
if (n==0) continue;
|
|
|
|
|
|
|
|
const subBuff1 = buff1.slice(i*nPointsPerThread*sG1, (i*nPointsPerThread+n)*sG1);
|
|
|
|
const subBuff2 = buff2.slice(i*nPointsPerThread*sG1, (i*nPointsPerThread+n)*sG1);
|
|
|
|
opPromises.push(hashHPointsThread(subBuff1, subBuff2));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const result = await Promise.all(opPromises);
|
|
|
|
|
|
|
|
for (let i=0; i<result.length; i++) {
|
|
|
|
csHasher.update(result[i][0]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function hashHPointsThread(buff1, buff2) {
|
|
|
|
const nPoints = buff1.byteLength/sG1;
|
|
|
|
const sGmid = curve.G1.F.n8*3;
|
|
|
|
const task = [];
|
|
|
|
task.push({cmd: "ALLOCSET", var: 0, buff: buff1});
|
|
|
|
task.push({cmd: "ALLOCSET", var: 1, buff: buff2});
|
|
|
|
task.push({cmd: "ALLOC", var: 2, len: nPoints*sGmid});
|
|
|
|
for (let i=0; i<nPoints; i++) {
|
|
|
|
task.push({
|
|
|
|
cmd: "CALL",
|
|
|
|
fnName: "g1m_subAffine",
|
|
|
|
params: [
|
|
|
|
{var: 0, offset: i*sG1},
|
|
|
|
{var: 1, offset: i*sG1},
|
|
|
|
{var: 2, offset: i*sGmid},
|
|
|
|
]
|
|
|
|
});
|
|
|
|
}
|
|
|
|
task.push({cmd: "CALL", fnName: "g1m_batchToAffine", params: [
|
|
|
|
{var: 2},
|
|
|
|
{val: nPoints},
|
|
|
|
{var: 2},
|
|
|
|
]});
|
|
|
|
task.push({cmd: "CALL", fnName: "g1m_batchLEMtoU", params: [
|
|
|
|
{var: 2},
|
|
|
|
{val: nPoints},
|
|
|
|
{var: 2},
|
|
|
|
]});
|
|
|
|
task.push({cmd: "GET", out: 0, var: 2, len: nPoints*sG1});
|
|
|
|
|
|
|
|
const res = await curve.tm.queueAction(task);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
function hashU32(n) {
|
|
|
|
const buff = new Uint8Array(4);
|
|
|
|
const buffV = new DataView(buff.buffer, buff.byteOffset, buff.byteLength);
|
|
|
|
buffV.setUint32(0, n, false);
|
|
|
|
csHasher.update(buff);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
async function phase2exportMPCParams(zkeyName, mpcparamsName, logger) {
|
|
|
|
|
|
|
|
const {fd: fdZKey, sections: sectionsZKey} = await readBinFile(zkeyName, "zkey", 2);
|
|
|
|
const zkey = await readHeader(fdZKey, sectionsZKey, "groth16");
|
|
|
|
|
|
|
|
const curve = await getCurveFromQ(zkey.q);
|
|
|
|
const sG1 = curve.G1.F.n8*2;
|
|
|
|
const sG2 = curve.G2.F.n8*2;
|
|
|
|
|
|
|
|
const mpcParams = await readMPCParams(fdZKey, curve, sectionsZKey);
|
|
|
|
|
|
|
|
const fdMPCParams = await createOverride(mpcparamsName);
|
|
|
|
|
|
|
|
/////////////////////
|
|
|
|
// Verification Key Section
|
|
|
|
/////////////////////
|
|
|
|
await writeG1(zkey.vk_alpha_1);
|
|
|
|
await writeG1(zkey.vk_beta_1);
|
|
|
|
await writeG2(zkey.vk_beta_2);
|
|
|
|
await writeG2(zkey.vk_gamma_2);
|
|
|
|
await writeG1(zkey.vk_delta_1);
|
|
|
|
await writeG2(zkey.vk_delta_2);
|
|
|
|
|
|
|
|
// IC
|
|
|
|
let buffBasesIC;
|
|
|
|
buffBasesIC = await readFullSection(fdZKey, sectionsZKey, 3);
|
|
|
|
buffBasesIC = await curve.G1.batchLEMtoU(buffBasesIC);
|
|
|
|
|
|
|
|
await writePointArray("G1", buffBasesIC);
|
|
|
|
|
|
|
|
/////////////////////
|
|
|
|
// h Section
|
|
|
|
/////////////////////
|
|
|
|
const buffBasesH_Lodd = await readFullSection(fdZKey, sectionsZKey, 9);
|
|
|
|
|
|
|
|
let buffBasesH_Tau;
|
|
|
|
buffBasesH_Tau = await curve.G1.fft(buffBasesH_Lodd, "affine", "jacobian", logger);
|
|
|
|
buffBasesH_Tau = await curve.G1.batchApplyKey(buffBasesH_Tau, curve.Fr.neg(curve.Fr.e(2)), curve.Fr.w[zkey.power+1], "jacobian", "affine", logger);
|
|
|
|
|
|
|
|
// Remove last element. (The degree of H will be allways m-2)
|
|
|
|
buffBasesH_Tau = buffBasesH_Tau.slice(0, buffBasesH_Tau.byteLength - sG1);
|
|
|
|
buffBasesH_Tau = await curve.G1.batchLEMtoU(buffBasesH_Tau);
|
|
|
|
await writePointArray("G1", buffBasesH_Tau);
|
|
|
|
|
|
|
|
/////////////////////
|
|
|
|
// L section
|
|
|
|
/////////////////////
|
|
|
|
let buffBasesC;
|
|
|
|
buffBasesC = await readFullSection(fdZKey, sectionsZKey, 8);
|
|
|
|
buffBasesC = await curve.G1.batchLEMtoU(buffBasesC);
|
|
|
|
await writePointArray("G1", buffBasesC);
|
|
|
|
|
|
|
|
/////////////////////
|
|
|
|
// A Section (C section)
|
|
|
|
/////////////////////
|
|
|
|
let buffBasesA;
|
|
|
|
buffBasesA = await readFullSection(fdZKey, sectionsZKey, 5);
|
|
|
|
buffBasesA = await curve.G1.batchLEMtoU(buffBasesA);
|
|
|
|
await writePointArray("G1", buffBasesA);
|
|
|
|
|
|
|
|
/////////////////////
|
|
|
|
// B1 Section
|
|
|
|
/////////////////////
|
|
|
|
let buffBasesB1;
|
|
|
|
buffBasesB1 = await readFullSection(fdZKey, sectionsZKey, 6);
|
|
|
|
buffBasesB1 = await curve.G1.batchLEMtoU(buffBasesB1);
|
|
|
|
await writePointArray("G1", buffBasesB1);
|
|
|
|
|
|
|
|
/////////////////////
|
|
|
|
// B2 Section
|
|
|
|
/////////////////////
|
|
|
|
let buffBasesB2;
|
|
|
|
buffBasesB2 = await readFullSection(fdZKey, sectionsZKey, 7);
|
|
|
|
buffBasesB2 = await curve.G2.batchLEMtoU(buffBasesB2);
|
|
|
|
await writePointArray("G2", buffBasesB2);
|
|
|
|
|
|
|
|
await fdMPCParams.write(mpcParams.csHash);
|
|
|
|
await writeU32(mpcParams.contributions.length);
|
|
|
|
|
|
|
|
for (let i=0; i<mpcParams.contributions.length; i++) {
|
|
|
|
const c = mpcParams.contributions[i];
|
|
|
|
await writeG1(c.deltaAfter);
|
|
|
|
await writeG1(c.delta.g1_s);
|
|
|
|
await writeG1(c.delta.g1_sx);
|
|
|
|
await writeG2(c.delta.g2_spx);
|
|
|
|
await fdMPCParams.write(c.transcript);
|
|
|
|
}
|
|
|
|
|
|
|
|
await fdZKey.close();
|
|
|
|
await fdMPCParams.close();
|
|
|
|
|
|
|
|
async function writeG1(P) {
|
|
|
|
const buff = new Uint8Array(sG1);
|
|
|
|
curve.G1.toRprUncompressed(buff, 0, P);
|
|
|
|
await fdMPCParams.write(buff);
|
|
|
|
}
|
|
|
|
|
|
|
|
async function writeG2(P) {
|
|
|
|
const buff = new Uint8Array(sG2);
|
|
|
|
curve.G2.toRprUncompressed(buff, 0, P);
|
|
|
|
await fdMPCParams.write(buff);
|
|
|
|
}
|
|
|
|
|
|
|
|
async function writePointArray(groupName, buff) {
|
|
|
|
let sG;
|
|
|
|
if (groupName == "G1") {
|
|
|
|
sG = sG1;
|
|
|
|
} else {
|
|
|
|
sG = sG2;
|
|
|
|
}
|
|
|
|
|
|
|
|
const buffSize = new Uint8Array(4);
|
|
|
|
const buffSizeV = new DataView(buffSize.buffer, buffSize.byteOffset, buffSize.byteLength);
|
|
|
|
buffSizeV.setUint32(0, buff.byteLength / sG, false);
|
|
|
|
|
|
|
|
await fdMPCParams.write(buffSize);
|
|
|
|
await fdMPCParams.write(buff);
|
|
|
|
}
|
|
|
|
|
|
|
|
async function writeU32(n) {
|
|
|
|
const buffSize = new Uint8Array(4);
|
|
|
|
const buffSizeV = new DataView(buffSize.buffer, buffSize.byteOffset, buffSize.byteLength);
|
|
|
|
buffSizeV.setUint32(0, n, false);
|
|
|
|
|
|
|
|
await fdMPCParams.write(buffSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
async function phase2importMPCParams(zkeyNameOld, mpcparamsName, zkeyNameNew, name, logger) {
|
|
|
|
|
|
|
|
const {fd: fdZKeyOld, sections: sectionsZKeyOld} = await readBinFile(zkeyNameOld, "zkey", 2);
|
|
|
|
const zkeyHeader = await readHeader(fdZKeyOld, sectionsZKeyOld, "groth16");
|
|
|
|
|
|
|
|
const curve = await getCurveFromQ(zkeyHeader.q);
|
|
|
|
const sG1 = curve.G1.F.n8*2;
|
|
|
|
const sG2 = curve.G2.F.n8*2;
|
|
|
|
|
|
|
|
const oldMPCParams = await readMPCParams(fdZKeyOld, curve, sectionsZKeyOld);
|
|
|
|
const newMPCParams = {};
|
|
|
|
|
|
|
|
const fdMPCParams = await readExisting$1(mpcparamsName);
|
|
|
|
|
|
|
|
fdMPCParams.pos =
|
|
|
|
sG1*3 + sG2*3 + // vKey
|
|
|
|
8 + sG1*zkeyHeader.nVars + // IC + C
|
|
|
|
4 + sG1*(zkeyHeader.domainSize-1) + // H
|
|
|
|
4 + sG1*zkeyHeader.nVars + // A
|
|
|
|
4 + sG1*zkeyHeader.nVars + // B1
|
|
|
|
4 + sG2*zkeyHeader.nVars; // B2
|
|
|
|
|
|
|
|
// csHash
|
|
|
|
newMPCParams.csHash = await fdMPCParams.read(64);
|
|
|
|
|
|
|
|
const nConttributions = await fdMPCParams.readUBE32();
|
|
|
|
newMPCParams.contributions = [];
|
|
|
|
for (let i=0; i<nConttributions; i++) {
|
|
|
|
const c = { delta:{} };
|
|
|
|
c.deltaAfter = await readG1(fdMPCParams);
|
|
|
|
c.delta.g1_s = await readG1(fdMPCParams);
|
|
|
|
c.delta.g1_sx = await readG1(fdMPCParams);
|
|
|
|
c.delta.g2_spx = await readG2(fdMPCParams);
|
|
|
|
c.transcript = await fdMPCParams.read(64);
|
|
|
|
if (i<oldMPCParams.contributions.length) {
|
|
|
|
c.type = oldMPCParams.contributions[i].type;
|
|
|
|
if (c.type==1) {
|
|
|
|
c.beaconHash = oldMPCParams.contributions[i].beaconHash;
|
|
|
|
c.numIterationsExp = oldMPCParams.contributions[i].numIterationsExp;
|
|
|
|
}
|
|
|
|
if (oldMPCParams.contributions[i].name) {
|
|
|
|
c.name = oldMPCParams.contributions[i].name;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
newMPCParams.contributions.push(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!hashIsEqual(newMPCParams.csHash, oldMPCParams.csHash)) {
|
|
|
|
if (logger) logger.error("Hash of the original circuit does not match with the MPC one");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (oldMPCParams.contributions.length > newMPCParams.contributions.length) {
|
|
|
|
if (logger) logger.error("The impoerted file does not include new contributions");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (let i=0; i<oldMPCParams.contributions.length; i++) {
|
|
|
|
if (!contributionIsEqual(oldMPCParams.contributions[i], newMPCParams.contributions[i])) {
|
|
|
|
if (logger) logger.error(`Previos contribution ${i} does not match`);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Set the same name to all new controbutions
|
|
|
|
if (name) {
|
|
|
|
for (let i=oldMPCParams.contributions.length; i<newMPCParams.contributions.length; i++) {
|
|
|
|
newMPCParams.contributions[i].name = name;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const fdZKeyNew = await createBinFile(zkeyNameNew, "zkey", 1, 10);
|
|
|
|
fdMPCParams.pos = 0;
|
|
|
|
|
|
|
|
// Header
|
|
|
|
fdMPCParams.pos += sG1; // ignore alpha1 (keep original)
|
|
|
|
fdMPCParams.pos += sG1; // ignore beta1
|
|
|
|
fdMPCParams.pos += sG2; // ignore beta2
|
|
|
|
fdMPCParams.pos += sG2; // ignore gamma2
|
|
|
|
zkeyHeader.vk_delta_1 = await readG1(fdMPCParams);
|
|
|
|
zkeyHeader.vk_delta_2 = await readG2(fdMPCParams);
|
|
|
|
await writeHeader(fdZKeyNew, zkeyHeader);
|
|
|
|
|
|
|
|
// IC (Keep original)
|
|
|
|
const nIC = await fdMPCParams.readUBE32();
|
|
|
|
if (nIC != zkeyHeader.nPublic +1) {
|
|
|
|
if (logger) logger.error("Invalid number of points in IC");
|
|
|
|
await fdZKeyNew.discard();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
fdMPCParams.pos += sG1*(zkeyHeader.nPublic+1);
|
|
|
|
await copySection(fdZKeyOld, sectionsZKeyOld, fdZKeyNew, 3);
|
|
|
|
|
|
|
|
// Coeffs (Keep original)
|
|
|
|
await copySection(fdZKeyOld, sectionsZKeyOld, fdZKeyNew, 4);
|
|
|
|
|
|
|
|
// H Section
|
|
|
|
const nH = await fdMPCParams.readUBE32();
|
|
|
|
if (nH != zkeyHeader.domainSize-1) {
|
|
|
|
if (logger) logger.error("Invalid number of points in H");
|
|
|
|
await fdZKeyNew.discard();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
let buffH;
|
|
|
|
const buffTauU = await fdMPCParams.read(sG1*(zkeyHeader.domainSize-1));
|
|
|
|
const buffTauLEM = await curve.G1.batchUtoLEM(buffTauU);
|
|
|
|
buffH = new Uint8Array(zkeyHeader.domainSize*sG1);
|
|
|
|
buffH.set(buffTauLEM); // Let the last one to zero.
|
|
|
|
const n2Inv = curve.Fr.neg(curve.Fr.inv(curve.Fr.e(2)));
|
|
|
|
const wInv = curve.Fr.inv(curve.Fr.w[zkeyHeader.power+1]);
|
|
|
|
buffH = await curve.G1.batchApplyKey(buffH, n2Inv, wInv, "affine", "jacobian", logger);
|
|
|
|
buffH = await curve.G1.ifft(buffH, "jacobian", "affine", logger);
|
|
|
|
await startWriteSection(fdZKeyNew, 9);
|
|
|
|
await fdZKeyNew.write(buffH);
|
|
|
|
await endWriteSection(fdZKeyNew);
|
|
|
|
|
|
|
|
// C Secion (L section)
|
|
|
|
const nL = await fdMPCParams.readUBE32();
|
|
|
|
if (nL != (zkeyHeader.nVars-zkeyHeader.nPublic-1)) {
|
|
|
|
if (logger) logger.error("Invalid number of points in L");
|
|
|
|
await fdZKeyNew.discard();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
let buffL;
|
|
|
|
buffL = await fdMPCParams.read(sG1*(zkeyHeader.nVars-zkeyHeader.nPublic-1));
|
|
|
|
buffL = await curve.G1.batchUtoLEM(buffL);
|
|
|
|
await startWriteSection(fdZKeyNew, 8);
|
|
|
|
await fdZKeyNew.write(buffL);
|
|
|
|
await endWriteSection(fdZKeyNew);
|
|
|
|
|
|
|
|
// A Section
|
|
|
|
const nA = await fdMPCParams.readUBE32();
|
|
|
|
if (nA != zkeyHeader.nVars) {
|
|
|
|
if (logger) logger.error("Invalid number of points in A");
|
|
|
|
await fdZKeyNew.discard();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
fdMPCParams.pos += sG1*(zkeyHeader.nVars);
|
|
|
|
await copySection(fdZKeyOld, sectionsZKeyOld, fdZKeyNew, 5);
|
|
|
|
|
|
|
|
// B1 Section
|
|
|
|
const nB1 = await fdMPCParams.readUBE32();
|
|
|
|
if (nB1 != zkeyHeader.nVars) {
|
|
|
|
if (logger) logger.error("Invalid number of points in B1");
|
|
|
|
await fdZKeyNew.discard();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
fdMPCParams.pos += sG1*(zkeyHeader.nVars);
|
|
|
|
await copySection(fdZKeyOld, sectionsZKeyOld, fdZKeyNew, 6);
|
|
|
|
|
|
|
|
// B2 Section
|
|
|
|
const nB2 = await fdMPCParams.readUBE32();
|
|
|
|
if (nB2 != zkeyHeader.nVars) {
|
|
|
|
if (logger) logger.error("Invalid number of points in B2");
|
|
|
|
await fdZKeyNew.discard();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
fdMPCParams.pos += sG2*(zkeyHeader.nVars);
|
|
|
|
await copySection(fdZKeyOld, sectionsZKeyOld, fdZKeyNew, 7);
|
|
|
|
|
|
|
|
await writeMPCParams(fdZKeyNew, curve, newMPCParams);
|
|
|
|
|
|
|
|
await fdMPCParams.close();
|
|
|
|
await fdZKeyNew.close();
|
|
|
|
await fdZKeyOld.close();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
async function readG1(fd) {
|
|
|
|
const buff = await fd.read(curve.G1.F.n8*2);
|
|
|
|
return curve.G1.fromRprUncompressed(buff, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
async function readG2(fd) {
|
|
|
|
const buff = await fd.read(curve.G2.F.n8*2);
|
|
|
|
return curve.G2.fromRprUncompressed(buff, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function contributionIsEqual(c1, c2) {
|
|
|
|
if (!curve.G1.eq(c1.deltaAfter , c2.deltaAfter)) return false;
|
|
|
|
if (!curve.G1.eq(c1.delta.g1_s , c2.delta.g1_s)) return false;
|
|
|
|
if (!curve.G1.eq(c1.delta.g1_sx , c2.delta.g1_sx)) return false;
|
|
|
|
if (!curve.G2.eq(c1.delta.g2_spx , c2.delta.g2_spx)) return false;
|
|
|
|
if (!hashIsEqual(c1.transcript, c2.transcript)) return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const sameRatio$2 = sameRatio;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async function phase2verify(r1csFileName, pTauFileName, zkeyFileName, logger) {
|
|
|
|
|
|
|
|
let sr;
|
|
|
|
await blake2bWasm.ready();
|
|
|
|
|
|
|
|
const {fd, sections} = await readBinFile(zkeyFileName, "zkey", 2);
|
|
|
|
const zkey = await readHeader(fd, sections, "groth16");
|
|
|
|
|
|
|
|
const curve = await getCurveFromQ(zkey.q);
|
|
|
|
const sG1 = curve.G1.F.n8*2;
|
|
|
|
const sG2 = curve.G2.F.n8*2;
|
|
|
|
|
|
|
|
const mpcParams = await readMPCParams(fd, curve, sections);
|
|
|
|
|
|
|
|
const accumulatedHasher = blake2bWasm(64);
|
|
|
|
accumulatedHasher.update(mpcParams.csHash);
|
|
|
|
let curDelta = curve.G1.g;
|
|
|
|
for (let i=0; i<mpcParams.contributions.length; i++) {
|
|
|
|
const c = mpcParams.contributions[i];
|
|
|
|
const ourHasher = cloneHasher(accumulatedHasher);
|
|
|
|
|
|
|
|
hashG1(ourHasher, curve, c.delta.g1_s);
|
|
|
|
hashG1(ourHasher, curve, c.delta.g1_sx);
|
|
|
|
|
|
|
|
if (!hashIsEqual(ourHasher.digest(), c.transcript)) {
|
|
|
|
console.log(`INVALID(${i}): Inconsistent transcript `);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const delta_g2_sp = hashToG2(curve, c.transcript);
|
|
|
|
|
|
|
|
sr = await sameRatio$2(curve, c.delta.g1_s, c.delta.g1_sx, delta_g2_sp, c.delta.g2_spx);
|
|
|
|
if (sr !== true) {
|
|
|
|
console.log(`INVALID(${i}): public key G1 and G2 do not have the same ration `);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
sr = await sameRatio$2(curve, curDelta, c.deltaAfter, delta_g2_sp, c.delta.g2_spx);
|
|
|
|
if (sr !== true) {
|
|
|
|
console.log(`INVALID(${i}): deltaAfter does not fillow the public key `);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (c.type == 1) {
|
|
|
|
const rng = rngFromBeaconParams(c.beaconHash, c.numIterationsExp);
|
|
|
|
const expected_prvKey = curve.Fr.fromRng(rng);
|
|
|
|
const expected_g1_s = curve.G1.toAffine(curve.G1.fromRng(rng));
|
|
|
|
const expected_g1_sx = curve.G1.toAffine(curve.G1.timesFr(expected_g1_s, expected_prvKey));
|
|
|
|
if (curve.G1.eq(expected_g1_s, c.delta.g1_s) !== true) {
|
|
|
|
console.log(`INVALID(${i}): Key of the beacon does not match. g1_s `);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (curve.G1.eq(expected_g1_sx, c.delta.g1_sx) !== true) {
|
|
|
|
console.log(`INVALID(${i}): Key of the beacon does not match. g1_sx `);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
hashPubKey(accumulatedHasher, curve, c);
|
|
|
|
|
|
|
|
const contributionHasher = blake2bWasm(64);
|
|
|
|
hashPubKey(contributionHasher, curve, c);
|
|
|
|
|
|
|
|
c.contributionHash = contributionHasher.digest();
|
|
|
|
|
|
|
|
curDelta = c.deltaAfter;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-07-11 10:48:50 +02:00
|
|
|
// const initFileName = "~" + zkeyFileName + ".init";
|
|
|
|
const initFileName = {type: "mem"};
|
2020-07-11 10:31:52 +02:00
|
|
|
await newZKey(r1csFileName, pTauFileName, initFileName);
|
|
|
|
|
|
|
|
const {fd: fdInit, sections: sectionsInit} = await readBinFile(initFileName, "zkey", 2);
|
|
|
|
const zkeyInit = await readHeader(fdInit, sectionsInit, "groth16");
|
|
|
|
|
|
|
|
if ( (!Scalar$1.eq(zkeyInit.q, zkey.q))
|
|
|
|
||(!Scalar$1.eq(zkeyInit.r, zkey.r))
|
|
|
|
||(zkeyInit.n8q != zkey.n8q)
|
|
|
|
||(zkeyInit.n8r != zkey.n8r))
|
|
|
|
{
|
|
|
|
if (logger) logger.error("INVALID: Different curves");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( (zkeyInit.nVars != zkey.nVars)
|
|
|
|
||(zkeyInit.nPublic != zkey.nPublic)
|
|
|
|
||(zkeyInit.domainSize != zkey.domainSize))
|
|
|
|
{
|
|
|
|
if (logger) logger.error("INVALID: Different circuit parameters");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!curve.G1.eq(zkey.vk_alpha_1, zkeyInit.vk_alpha_1)) {
|
|
|
|
if (logger) logger.error("INVALID: Invalid alpha1");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!curve.G1.eq(zkey.vk_beta_1, zkeyInit.vk_beta_1)) {
|
|
|
|
if (logger) logger.error("INVALID: Invalid beta1");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!curve.G2.eq(zkey.vk_beta_2, zkeyInit.vk_beta_2)) {
|
|
|
|
if (logger) logger.error("INVALID: Invalid beta2");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!curve.G2.eq(zkey.vk_gamma_2, zkeyInit.vk_gamma_2)) {
|
|
|
|
if (logger) logger.error("INVALID: Invalid gamma2");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!curve.G1.eq(zkey.vk_delta_1, curDelta)) {
|
|
|
|
if (logger) logger.error("INVALID: Invalud delta1");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
sr = await sameRatio$2(curve, curve.G1.g, curDelta, curve.G2.g, zkey.vk_delta_2);
|
|
|
|
if (sr !== true) {
|
|
|
|
if (logger) logger.error("INVALID: Invalud delta2");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const mpcParamsInit = await readMPCParams(fdInit, curve, sectionsInit);
|
|
|
|
if (!hashIsEqual(mpcParams.csHash, mpcParamsInit.csHash)) {
|
|
|
|
if (logger) logger.error("INVALID: Circuit does not match");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check sizes of sections
|
|
|
|
if (sections[8][0].size != sG1*(zkey.nVars-zkey.nPublic-1)) {
|
|
|
|
if (logger) logger.error("INVALID: Invalid L section size");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sections[9][0].size != sG1*(zkey.domainSize)) {
|
|
|
|
if (logger) logger.error("INVALID: Invalid H section size");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
let ss;
|
|
|
|
ss = await sectionIsEqual(fd, sections, fdInit, sectionsInit, 3);
|
|
|
|
if (!ss) {
|
|
|
|
if (logger) logger.error("INVALID: IC section is not identical");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
ss = await sectionIsEqual(fd, sections, fdInit, sectionsInit, 4);
|
|
|
|
if (!ss) {
|
|
|
|
if (logger) logger.error("Coeffs section is not identical");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
ss = await sectionIsEqual(fd, sections, fdInit, sectionsInit, 5);
|
|
|
|
if (!ss) {
|
|
|
|
if (logger) logger.error("A section is not identical");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
ss = await sectionIsEqual(fd, sections, fdInit, sectionsInit, 6);
|
|
|
|
if (!ss) {
|
|
|
|
if (logger) logger.error("B1 section is not identical");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
ss = await sectionIsEqual(fd, sections, fdInit, sectionsInit, 7);
|
|
|
|
if (!ss) {
|
|
|
|
if (logger) logger.error("B2 section is not identical");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check L
|
|
|
|
sr = await sectionHasSameRatio("G1", fdInit, sectionsInit, fd, sections, 8, zkey.vk_delta_2, zkeyInit.vk_delta_2, "L section");
|
|
|
|
if (sr!==true) {
|
|
|
|
if (logger) logger.error("L section does not match");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check H
|
|
|
|
sr = await sameRatioH();
|
|
|
|
if (sr!==true) {
|
|
|
|
if (logger) logger.error("H section does not match");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (logger) logger.info(formatHash(mpcParams.csHash, "Circuit Hash: "));
|
|
|
|
|
|
|
|
await fd.close();
|
|
|
|
await fdInit.close();
|
|
|
|
|
|
|
|
for (let i=mpcParams.contributions.length-1; i>=0; i--) {
|
|
|
|
const c = mpcParams.contributions[i];
|
|
|
|
if (logger) logger.info("-------------------------");
|
|
|
|
if (logger) logger.info(formatHash(c.contributionHash, `contribution #${i+1} ${c.name ? c.name : ""}:`));
|
|
|
|
if (c.type == 1) {
|
|
|
|
if (logger) logger.info(`Beacon generator: ${byteArray2hex(c.beaconHash)}`);
|
|
|
|
if (logger) logger.info(`Beacon iterations Exp: ${c.numIterationsExp}`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (logger) logger.info("-------------------------");
|
|
|
|
|
|
|
|
if (logger) logger.info("ZKey Ok!");
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
|
|
async function sectionHasSameRatio(groupName, fd1, sections1, fd2, sections2, idSection, g2sp, g2spx, sectionName) {
|
|
|
|
const MAX_CHUNK_SIZE = 1<<20;
|
|
|
|
const G = curve[groupName];
|
|
|
|
const sG = G.F.n8*2;
|
|
|
|
await startReadUniqueSection(fd1, sections1, idSection);
|
|
|
|
await startReadUniqueSection(fd2, sections2, idSection);
|
|
|
|
|
|
|
|
let R1 = G.zero;
|
|
|
|
let R2 = G.zero;
|
|
|
|
|
|
|
|
const nPoints = sections1[idSection][0].size / sG;
|
|
|
|
|
|
|
|
for (let i=0; i<nPoints; i += MAX_CHUNK_SIZE) {
|
|
|
|
if (logger) logger.debug(`Same ratio check ${sectionName}: ${i}/${nPoints}`);
|
|
|
|
const n = Math.min(nPoints - i, MAX_CHUNK_SIZE);
|
|
|
|
const bases1 = await fd1.read(n*sG);
|
|
|
|
const bases2 = await fd2.read(n*sG);
|
|
|
|
|
|
|
|
const scalars = new Uint8Array(4*n);
|
|
|
|
crypto.randomFillSync(scalars);
|
|
|
|
|
|
|
|
|
|
|
|
const r1 = await G.multiExpAffine(bases1, scalars);
|
|
|
|
const r2 = await G.multiExpAffine(bases2, scalars);
|
|
|
|
|
|
|
|
R1 = G.add(R1, r1);
|
|
|
|
R2 = G.add(R2, r2);
|
|
|
|
}
|
|
|
|
await endReadSection(fd1);
|
|
|
|
await endReadSection(fd2);
|
|
|
|
|
|
|
|
sr = await sameRatio$2(curve, R1, R2, g2sp, g2spx);
|
|
|
|
if (sr !== true) return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
async function sameRatioH() {
|
|
|
|
const MAX_CHUNK_SIZE = 1<<20;
|
|
|
|
const G = curve.G1;
|
|
|
|
const sG = G.F.n8*2;
|
|
|
|
|
|
|
|
const {fd: fdPTau, sections: sectionsPTau} = await readBinFile(pTauFileName, "ptau", 1);
|
|
|
|
|
|
|
|
let buff_r = new Uint8Array(zkey.domainSize * zkey.n8r);
|
|
|
|
|
|
|
|
const seed= new Array(8);
|
|
|
|
for (let i=0; i<8; i++) {
|
|
|
|
seed[i] = crypto.randomBytes(4).readUInt32BE(0, true);
|
|
|
|
}
|
|
|
|
const rng = new ChaCha(seed);
|
|
|
|
for (let i=0; i<zkey.domainSize-1; i++) { // Note that last one is zero
|
|
|
|
const e = curve.Fr.fromRng(rng);
|
|
|
|
curve.Fr.toRprLE(buff_r, i*zkey.n8r, e);
|
|
|
|
}
|
|
|
|
|
|
|
|
let R1 = G.zero;
|
|
|
|
for (let i=0; i<zkey.domainSize; i += MAX_CHUNK_SIZE) {
|
|
|
|
if (logger) logger.debug(`H Verificaition(tau): ${i}/${zkey.domainSize}`);
|
|
|
|
const n = Math.min(zkey.domainSize - i, MAX_CHUNK_SIZE);
|
|
|
|
|
|
|
|
const buff1 = await fdPTau.read(sG*n, sectionsPTau[2][0].p + zkey.domainSize*sG + i*MAX_CHUNK_SIZE*sG);
|
|
|
|
const buff2 = await fdPTau.read(sG*n, sectionsPTau[2][0].p + i*MAX_CHUNK_SIZE*sG);
|
|
|
|
|
|
|
|
const buffB = await batchSubstract(buff1, buff2);
|
|
|
|
const buffS = buff_r.slice((i*MAX_CHUNK_SIZE)*zkey.n8r, (i*MAX_CHUNK_SIZE+n)*zkey.n8r);
|
|
|
|
const r = await G.multiExpAffine(buffB, buffS);
|
|
|
|
|
|
|
|
R1 = G.add(R1, r);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Caluclate odd coeficients in transformed domain
|
|
|
|
|
|
|
|
buff_r = await curve.Fr.batchToMontgomery(buff_r);
|
|
|
|
// const first = curve.Fr.neg(curve.Fr.inv(curve.Fr.e(2)));
|
|
|
|
// Works*2 const first = curve.Fr.neg(curve.Fr.e(2));
|
|
|
|
const first = curve.Fr.neg(curve.Fr.e(2));
|
|
|
|
// const inc = curve.Fr.inv(curve.PFr.w[zkey.power+1]);
|
|
|
|
const inc = curve.Fr.w[zkey.power+1];
|
|
|
|
buff_r = await curve.Fr.batchApplyKey(buff_r, first, inc);
|
|
|
|
buff_r = await curve.Fr.fft(buff_r);
|
|
|
|
buff_r = await curve.Fr.batchFromMontgomery(buff_r);
|
|
|
|
|
|
|
|
await startReadUniqueSection(fd, sections, 9);
|
|
|
|
let R2 = G.zero;
|
|
|
|
for (let i=0; i<zkey.domainSize; i += MAX_CHUNK_SIZE) {
|
|
|
|
if (logger) logger.debug(`H Verificaition(lagrange): ${i}/${zkey.domainSize}`);
|
|
|
|
const n = Math.min(zkey.domainSize - i, MAX_CHUNK_SIZE);
|
|
|
|
|
|
|
|
const buff = await fd.read(sG*n);
|
|
|
|
const buffS = buff_r.slice((i*MAX_CHUNK_SIZE)*zkey.n8r, (i*MAX_CHUNK_SIZE+n)*zkey.n8r);
|
|
|
|
const r = await G.multiExpAffine(buff, buffS);
|
|
|
|
|
|
|
|
R2 = G.add(R2, r);
|
|
|
|
}
|
|
|
|
await endReadSection(fd);
|
|
|
|
|
|
|
|
sr = await sameRatio$2(curve, R1, R2, zkey.vk_delta_2, zkeyInit.vk_delta_2);
|
|
|
|
if (sr !== true) return false;
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
async function batchSubstract(buff1, buff2) {
|
|
|
|
const sG = curve.G1.F.n8*2;
|
|
|
|
const nPoints = buff1.byteLength / sG;
|
|
|
|
const concurrency= curve.tm.concurrency;
|
|
|
|
const nPointsPerThread = Math.floor(nPoints / concurrency);
|
|
|
|
const opPromises = [];
|
|
|
|
for (let i=0; i<concurrency; i++) {
|
|
|
|
let n;
|
|
|
|
if (i< concurrency-1) {
|
|
|
|
n = nPointsPerThread;
|
|
|
|
} else {
|
|
|
|
n = nPoints - i*nPointsPerThread;
|
|
|
|
}
|
|
|
|
if (n==0) continue;
|
|
|
|
|
|
|
|
const subBuff1 = buff1.slice(i*nPointsPerThread*sG1, (i*nPointsPerThread+n)*sG1);
|
|
|
|
const subBuff2 = buff2.slice(i*nPointsPerThread*sG1, (i*nPointsPerThread+n)*sG1);
|
|
|
|
opPromises.push(batchSubstractThread(subBuff1, subBuff2));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const result = await Promise.all(opPromises);
|
|
|
|
|
|
|
|
const fullBuffOut = new Uint8Array(nPoints*sG);
|
|
|
|
let p =0;
|
|
|
|
for (let i=0; i<result.length; i++) {
|
|
|
|
fullBuffOut.set(result[i][0], p);
|
|
|
|
p+=result[i][0].byteLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
return fullBuffOut;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async function batchSubstractThread(buff1, buff2) {
|
|
|
|
const sG1 = curve.G1.F.n8*2;
|
|
|
|
const sGmid = curve.G1.F.n8*3;
|
|
|
|
const nPoints = buff1.byteLength/sG1;
|
|
|
|
const task = [];
|
|
|
|
task.push({cmd: "ALLOCSET", var: 0, buff: buff1});
|
|
|
|
task.push({cmd: "ALLOCSET", var: 1, buff: buff2});
|
|
|
|
task.push({cmd: "ALLOC", var: 2, len: nPoints*sGmid});
|
|
|
|
for (let i=0; i<nPoints; i++) {
|
|
|
|
task.push({
|
|
|
|
cmd: "CALL",
|
|
|
|
fnName: "g1m_subAffine",
|
|
|
|
params: [
|
|
|
|
{var: 0, offset: i*sG1},
|
|
|
|
{var: 1, offset: i*sG1},
|
|
|
|
{var: 2, offset: i*sGmid},
|
|
|
|
]
|
|
|
|
});
|
|
|
|
}
|
|
|
|
task.push({cmd: "CALL", fnName: "g1m_batchToAffine", params: [
|
|
|
|
{var: 2},
|
|
|
|
{val: nPoints},
|
|
|
|
{var: 2},
|
|
|
|
]});
|
|
|
|
task.push({cmd: "GET", out: 0, var: 2, len: nPoints*sG1});
|
|
|
|
|
|
|
|
const res = await curve.tm.queueAction(task);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
async function phase2contribute(zkeyNameOld, zkeyNameNew, name, entropy, logger) {
|
|
|
|
await blake2bWasm.ready();
|
|
|
|
|
|
|
|
const {fd: fdOld, sections: sections} = await readBinFile(zkeyNameOld, "zkey", 2);
|
|
|
|
const zkey = await readHeader(fdOld, sections, "groth16");
|
|
|
|
|
|
|
|
const curve = await getCurveFromQ(zkey.q);
|
|
|
|
|
|
|
|
const mpcParams = await readMPCParams(fdOld, curve, sections);
|
|
|
|
|
|
|
|
const fdNew = await createBinFile(zkeyNameNew, "zkey", 1, 10);
|
|
|
|
|
|
|
|
|
|
|
|
const rng = await getRandomRng(entropy);
|
|
|
|
|
|
|
|
const transcriptHasher = blake2bWasm(64);
|
|
|
|
transcriptHasher.update(mpcParams.csHash);
|
|
|
|
for (let i=0; i<mpcParams.contributions.length; i++) {
|
|
|
|
hashPubKey(transcriptHasher, curve, mpcParams.contributions[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
const curContribution = {};
|
|
|
|
curContribution.delta = {};
|
|
|
|
curContribution.delta.prvKey = curve.Fr.fromRng(rng);
|
|
|
|
curContribution.delta.g1_s = curve.G1.toAffine(curve.G1.fromRng(rng));
|
|
|
|
curContribution.delta.g1_sx = curve.G1.toAffine(curve.G1.timesFr(curContribution.delta.g1_s, curContribution.delta.prvKey));
|
|
|
|
hashG1(transcriptHasher, curve, curContribution.delta.g1_s);
|
|
|
|
hashG1(transcriptHasher, curve, curContribution.delta.g1_sx);
|
|
|
|
curContribution.transcript = transcriptHasher.digest();
|
|
|
|
curContribution.delta.g2_sp = hashToG2(curve, curContribution.transcript);
|
|
|
|
curContribution.delta.g2_spx = curve.G2.toAffine(curve.G2.timesFr(curContribution.delta.g2_sp, curContribution.delta.prvKey));
|
|
|
|
|
|
|
|
zkey.vk_delta_1 = curve.G1.timesFr(zkey.vk_delta_1, curContribution.delta.prvKey);
|
|
|
|
zkey.vk_delta_2 = curve.G2.timesFr(zkey.vk_delta_2, curContribution.delta.prvKey);
|
|
|
|
|
|
|
|
curContribution.deltaAfter = zkey.vk_delta_1;
|
|
|
|
|
|
|
|
curContribution.type = 0;
|
|
|
|
if (name) curContribution.name = name;
|
|
|
|
|
|
|
|
mpcParams.contributions.push(curContribution);
|
|
|
|
|
|
|
|
await writeHeader(fdNew, zkey);
|
|
|
|
|
|
|
|
// IC
|
|
|
|
await copySection(fdOld, sections, fdNew, 3);
|
|
|
|
|
|
|
|
// Coeffs (Keep original)
|
|
|
|
await copySection(fdOld, sections, fdNew, 4);
|
|
|
|
|
|
|
|
// A Section
|
|
|
|
await copySection(fdOld, sections, fdNew, 5);
|
|
|
|
|
|
|
|
// B1 Section
|
|
|
|
await copySection(fdOld, sections, fdNew, 6);
|
|
|
|
|
|
|
|
// B2 Section
|
|
|
|
await copySection(fdOld, sections, fdNew, 7);
|
|
|
|
|
|
|
|
const invDelta = curve.Fr.inv(curContribution.delta.prvKey);
|
|
|
|
await applyKeyToSection(fdOld, sections, fdNew, 8, curve, "G1", invDelta, curve.Fr.e(1), "L Section", logger);
|
|
|
|
await applyKeyToSection(fdOld, sections, fdNew, 9, curve, "G1", invDelta, curve.Fr.e(1), "H Section", logger);
|
|
|
|
|
|
|
|
await writeMPCParams(fdNew, curve, mpcParams);
|
|
|
|
|
|
|
|
await fdOld.close();
|
|
|
|
await fdNew.close();
|
|
|
|
|
|
|
|
const contributionHasher = blake2bWasm(64);
|
|
|
|
hashPubKey(contributionHasher, curve, curContribution);
|
|
|
|
|
|
|
|
const contribuionHash = contributionHasher.digest();
|
|
|
|
|
|
|
|
if (logger) logger.info(formatHash(contribuionHash, "Contribution Hash: "));
|
|
|
|
|
|
|
|
return contribuionHash;
|
|
|
|
}
|
|
|
|
|
|
|
|
async function beacon$1(zkeyNameOld, zkeyNameNew, name, beaconHashStr, numIterationsExp, logger) {
|
|
|
|
await blake2bWasm.ready();
|
|
|
|
|
|
|
|
const beaconHash = hex2ByteArray(beaconHashStr);
|
|
|
|
if ( (beaconHash.byteLength == 0)
|
|
|
|
|| (beaconHash.byteLength*2 !=beaconHashStr.length))
|
|
|
|
{
|
|
|
|
if (logger) logger.error("Invalid Beacon Hash. (It must be a valid hexadecimal sequence)");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (beaconHash.length>=256) {
|
|
|
|
if (logger) logger.error("Maximum lenght of beacon hash is 255 bytes");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
numIterationsExp = parseInt(numIterationsExp);
|
|
|
|
if ((numIterationsExp<10)||(numIterationsExp>63)) {
|
|
|
|
if (logger) logger.error("Invalid numIterationsExp. (Must be between 10 and 63)");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const {fd: fdOld, sections: sections} = await readBinFile(zkeyNameOld, "zkey", 2);
|
|
|
|
const zkey = await readHeader(fdOld, sections, "groth16");
|
|
|
|
|
|
|
|
const curve = await getCurveFromQ(zkey.q);
|
|
|
|
|
|
|
|
const mpcParams = await readMPCParams(fdOld, curve, sections);
|
|
|
|
|
|
|
|
const fdNew = await createBinFile(zkeyNameNew, "zkey", 1, 10);
|
|
|
|
|
|
|
|
const rng = await rngFromBeaconParams(beaconHash, numIterationsExp);
|
|
|
|
|
|
|
|
const transcriptHasher = blake2bWasm(64);
|
|
|
|
transcriptHasher.update(mpcParams.csHash);
|
|
|
|
for (let i=0; i<mpcParams.contributions.length; i++) {
|
|
|
|
hashPubKey(transcriptHasher, curve, mpcParams.contributions[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
const curContribution = {};
|
|
|
|
curContribution.delta = {};
|
|
|
|
curContribution.delta.prvKey = curve.Fr.fromRng(rng);
|
|
|
|
curContribution.delta.g1_s = curve.G1.toAffine(curve.G1.fromRng(rng));
|
|
|
|
curContribution.delta.g1_sx = curve.G1.toAffine(curve.G1.timesFr(curContribution.delta.g1_s, curContribution.delta.prvKey));
|
|
|
|
hashG1(transcriptHasher, curve, curContribution.delta.g1_s);
|
|
|
|
hashG1(transcriptHasher, curve, curContribution.delta.g1_sx);
|
|
|
|
curContribution.transcript = transcriptHasher.digest();
|
|
|
|
curContribution.delta.g2_sp = hashToG2(curve, curContribution.transcript);
|
|
|
|
curContribution.delta.g2_spx = curve.G2.toAffine(curve.G2.timesFr(curContribution.delta.g2_sp, curContribution.delta.prvKey));
|
|
|
|
|
|
|
|
zkey.vk_delta_1 = curve.G1.timesFr(zkey.vk_delta_1, curContribution.delta.prvKey);
|
|
|
|
zkey.vk_delta_2 = curve.G2.timesFr(zkey.vk_delta_2, curContribution.delta.prvKey);
|
|
|
|
|
|
|
|
curContribution.deltaAfter = zkey.vk_delta_1;
|
|
|
|
|
|
|
|
curContribution.type = 1;
|
|
|
|
curContribution.numIterationsExp = numIterationsExp;
|
|
|
|
curContribution.beaconHash = beaconHash;
|
|
|
|
|
|
|
|
if (name) curContribution.name = name;
|
|
|
|
|
|
|
|
mpcParams.contributions.push(curContribution);
|
|
|
|
|
|
|
|
await writeHeader(fdNew, zkey);
|
|
|
|
|
|
|
|
// IC
|
|
|
|
await copySection(fdOld, sections, fdNew, 3);
|
|
|
|
|
|
|
|
// Coeffs (Keep original)
|
|
|
|
await copySection(fdOld, sections, fdNew, 4);
|
|
|
|
|
|
|
|
// A Section
|
|
|
|
await copySection(fdOld, sections, fdNew, 5);
|
|
|
|
|
|
|
|
// B1 Section
|
|
|
|
await copySection(fdOld, sections, fdNew, 6);
|
|
|
|
|
|
|
|
// B2 Section
|
|
|
|
await copySection(fdOld, sections, fdNew, 7);
|
|
|
|
|
|
|
|
const invDelta = curve.Fr.inv(curContribution.delta.prvKey);
|
|
|
|
await applyKeyToSection(fdOld, sections, fdNew, 8, curve, "G1", invDelta, curve.Fr.e(1), "L Section", logger);
|
|
|
|
await applyKeyToSection(fdOld, sections, fdNew, 9, curve, "G1", invDelta, curve.Fr.e(1), "H Section", logger);
|
|
|
|
|
|
|
|
await writeMPCParams(fdNew, curve, mpcParams);
|
|
|
|
|
|
|
|
await fdOld.close();
|
|
|
|
await fdNew.close();
|
|
|
|
|
|
|
|
const contributionHasher = blake2bWasm(64);
|
|
|
|
hashPubKey(contributionHasher, curve, curContribution);
|
|
|
|
|
|
|
|
const contribuionHash = contributionHasher.digest();
|
|
|
|
|
|
|
|
if (logger) logger.info(formatHash(contribuionHash, "Contribution Hash: "));
|
|
|
|
|
|
|
|
return contribuionHash;
|
|
|
|
}
|
|
|
|
|
|
|
|
async function zkeyExportJson(zkeyFileName, verbose) {
|
|
|
|
|
|
|
|
const zKey = await readZKey(zkeyFileName);
|
|
|
|
|
|
|
|
return zKey;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Format of the output
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
async function bellmanContribute(curve, challengeFilename, responesFileName, entropy, logger) {
|
2020-07-11 10:31:52 +02:00
|
|
|
await blake2bWasm.ready();
|
|
|
|
|
|
|
|
const rng = await getRandomRng(entropy);
|
|
|
|
|
|
|
|
const delta = curve.Fr.fromRng(rng);
|
|
|
|
const invDelta = curve.Fr.inv(delta);
|
|
|
|
|
|
|
|
const sG1 = curve.G1.F.n8*2;
|
|
|
|
const sG2 = curve.G2.F.n8*2;
|
|
|
|
|
2020-07-14 11:55:12 +02:00
|
|
|
const fdFrom = await readExisting$1(challengeFilename);
|
2020-07-11 10:31:52 +02:00
|
|
|
const fdTo = await createOverride(responesFileName);
|
|
|
|
|
|
|
|
|
|
|
|
await copy(sG1); // alpha1
|
|
|
|
await copy(sG1); // beta1
|
|
|
|
await copy(sG2); // beta2
|
|
|
|
await copy(sG2); // gamma2
|
|
|
|
const oldDelta1 = await readG1();
|
|
|
|
const delta1 = curve.G1.timesFr(oldDelta1, delta);
|
|
|
|
await writeG1(delta1);
|
|
|
|
const oldDelta2 = await readG2();
|
|
|
|
const delta2 = curve.G2.timesFr(oldDelta2, delta);
|
|
|
|
await writeG2(delta2);
|
|
|
|
|
|
|
|
// IC
|
|
|
|
const nIC = await fdFrom.readUBE32();
|
|
|
|
await fdTo.writeUBE32(nIC);
|
|
|
|
await copy(nIC*sG1);
|
|
|
|
|
|
|
|
// H
|
|
|
|
const nH = await fdFrom.readUBE32();
|
|
|
|
await fdTo.writeUBE32(nH);
|
2020-07-14 11:55:12 +02:00
|
|
|
await applyKeyToChallengeSection(fdFrom, fdTo, null, curve, "G1", nH, invDelta, curve.Fr.e(1), "UNCOMPRESSED", "H", logger);
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
// L
|
|
|
|
const nL = await fdFrom.readUBE32();
|
|
|
|
await fdTo.writeUBE32(nL);
|
2020-07-14 11:55:12 +02:00
|
|
|
await applyKeyToChallengeSection(fdFrom, fdTo, null, curve, "G1", nL, invDelta, curve.Fr.e(1), "UNCOMPRESSED", "L", logger);
|
2020-07-11 10:31:52 +02:00
|
|
|
|
|
|
|
// A
|
|
|
|
const nA = await fdFrom.readUBE32();
|
|
|
|
await fdTo.writeUBE32(nA);
|
|
|
|
await copy(nA*sG1);
|
|
|
|
|
|
|
|
// B1
|
|
|
|
const nB1 = await fdFrom.readUBE32();
|
|
|
|
await fdTo.writeUBE32(nB1);
|
|
|
|
await copy(nB1*sG1);
|
|
|
|
|
|
|
|
// B2
|
|
|
|
const nB2 = await fdFrom.readUBE32();
|
|
|
|
await fdTo.writeUBE32(nB2);
|
|
|
|
await copy(nB2*sG2);
|
|
|
|
|
|
|
|
|
|
|
|
//////////
|
|
|
|
/// Read contributions
|
|
|
|
//////////
|
|
|
|
const transcriptHasher = blake2bWasm(64);
|
|
|
|
|
|
|
|
const mpcParams = {};
|
|
|
|
// csHash
|
|
|
|
mpcParams.csHash = await fdFrom.read(64);
|
|
|
|
transcriptHasher.update(mpcParams.csHash);
|
|
|
|
|
|
|
|
const nConttributions = await fdFrom.readUBE32();
|
|
|
|
mpcParams.contributions = [];
|
|
|
|
for (let i=0; i<nConttributions; i++) {
|
|
|
|
const c = { delta:{} };
|
|
|
|
c.deltaAfter = await readG1();
|
|
|
|
c.delta.g1_s = await readG1();
|
|
|
|
c.delta.g1_sx = await readG1();
|
|
|
|
c.delta.g2_spx = await readG2();
|
|
|
|
c.transcript = await fdFrom.read(64);
|
|
|
|
mpcParams.contributions.push(c);
|
|
|
|
hashPubKey(transcriptHasher, curve, c);
|
|
|
|
}
|
|
|
|
|
|
|
|
const curContribution = {};
|
|
|
|
curContribution.delta = {};
|
|
|
|
curContribution.delta.prvKey = delta;
|
|
|
|
curContribution.delta.g1_s = curve.G1.toAffine(curve.G1.fromRng(rng));
|
|
|
|
curContribution.delta.g1_sx = curve.G1.toAffine(curve.G1.timesFr(curContribution.delta.g1_s, delta));
|
|
|
|
hashG1(transcriptHasher, curve, curContribution.delta.g1_s);
|
|
|
|
hashG1(transcriptHasher, curve, curContribution.delta.g1_sx);
|
|
|
|
curContribution.transcript = transcriptHasher.digest();
|
|
|
|
curContribution.delta.g2_sp = hashToG2(curve, curContribution.transcript);
|
|
|
|
curContribution.delta.g2_spx = curve.G2.toAffine(curve.G2.timesFr(curContribution.delta.g2_sp, delta));
|
|
|
|
curContribution.deltaAfter = delta1;
|
|
|
|
curContribution.type = 0;
|
|
|
|
mpcParams.contributions.push(curContribution);
|
|
|
|
|
|
|
|
|
|
|
|
//////////
|
|
|
|
/// Write COntribution
|
|
|
|
//////////
|
|
|
|
|
|
|
|
await fdTo.write(mpcParams.csHash);
|
|
|
|
await fdTo.writeUBE32(mpcParams.contributions.length);
|
|
|
|
|
|
|
|
for (let i=0; i<mpcParams.contributions.length; i++) {
|
|
|
|
const c = mpcParams.contributions[i];
|
|
|
|
await writeG1(c.deltaAfter);
|
|
|
|
await writeG1(c.delta.g1_s);
|
|
|
|
await writeG1(c.delta.g1_sx);
|
|
|
|
await writeG2(c.delta.g2_spx);
|
|
|
|
await fdTo.write(c.transcript);
|
|
|
|
}
|
|
|
|
|
|
|
|
const contributionHasher = blake2bWasm(64);
|
|
|
|
hashPubKey(contributionHasher, curve, curContribution);
|
|
|
|
|
|
|
|
const contributionHash = contributionHasher.digest();
|
|
|
|
|
|
|
|
if (logger) logger.info(formatHash(contributionHash, "Contribution Hash: "));
|
|
|
|
|
|
|
|
await fdTo.close();
|
|
|
|
await fdFrom.close();
|
|
|
|
|
|
|
|
return contributionHash;
|
|
|
|
|
|
|
|
async function copy(nBytes) {
|
|
|
|
const CHUNK_SIZE = fdFrom.pageSize*2;
|
|
|
|
for (let i=0; i<nBytes; i+= CHUNK_SIZE) {
|
|
|
|
const n = Math.min(nBytes -i, CHUNK_SIZE);
|
|
|
|
const buff = await fdFrom.read(n);
|
|
|
|
await fdTo.write(buff);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function readG1() {
|
|
|
|
const buff = await fdFrom.read(curve.G1.F.n8*2);
|
|
|
|
return curve.G1.fromRprUncompressed(buff, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
async function readG2() {
|
|
|
|
const buff = await fdFrom.read(curve.G2.F.n8*2);
|
|
|
|
return curve.G2.fromRprUncompressed(buff, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
async function writeG1(P) {
|
|
|
|
const buff = new Uint8Array(sG1);
|
|
|
|
curve.G1.toRprUncompressed(buff, 0, P);
|
|
|
|
await fdTo.write(buff);
|
|
|
|
}
|
|
|
|
|
|
|
|
async function writeG2(P) {
|
|
|
|
const buff = new Uint8Array(sG2);
|
|
|
|
curve.G2.toRprUncompressed(buff, 0, P);
|
|
|
|
await fdTo.write(buff);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const {stringifyBigInts: stringifyBigInts$4} = utils$1;
|
|
|
|
|
|
|
|
|
|
|
|
async function zkeyExportVerificationKey(zkeyName, logger) {
|
|
|
|
|
|
|
|
const {fd, sections} = await readBinFile(zkeyName, "zkey", 2);
|
|
|
|
const zkey = await readHeader(fd, sections, "groth16");
|
|
|
|
|
|
|
|
const curve = await getCurveFromQ(zkey.q);
|
|
|
|
const sG1 = curve.G1.F.n8*2;
|
|
|
|
|
|
|
|
const alphaBeta = await curve.pairing( zkey.vk_alpha_1 , zkey.vk_beta_2 );
|
|
|
|
|
|
|
|
let vKey = {
|
|
|
|
protocol: zkey.protocol,
|
|
|
|
curve: curve.name,
|
|
|
|
nPublic: zkey.nPublic,
|
|
|
|
|
|
|
|
vk_alpha_1: curve.G1.toObject(zkey.vk_alpha_1),
|
|
|
|
|
|
|
|
vk_beta_2: curve.G2.toObject(zkey.vk_beta_2),
|
|
|
|
vk_gamma_2: curve.G2.toObject(zkey.vk_gamma_2),
|
|
|
|
vk_delta_2: curve.G2.toObject(zkey.vk_delta_2),
|
|
|
|
|
|
|
|
vk_alphabeta_12: curve.Gt.toObject(alphaBeta)
|
|
|
|
};
|
|
|
|
|
|
|
|
// Read IC Section
|
|
|
|
///////////
|
|
|
|
await startReadUniqueSection(fd, sections, 3);
|
|
|
|
vKey.IC = [];
|
|
|
|
for (let i=0; i<= zkey.nPublic; i++) {
|
|
|
|
const buff = await fd.read(sG1);
|
|
|
|
const P = curve.G1.toObject(buff);
|
|
|
|
vKey.IC.push(P);
|
|
|
|
}
|
|
|
|
await endReadSection(fd);
|
|
|
|
|
|
|
|
vKey = stringifyBigInts$4(vKey);
|
|
|
|
|
|
|
|
await fd.close();
|
|
|
|
|
|
|
|
return vKey;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Not ready yet
|
|
|
|
// module.exports.generateVerifier_kimleeoh = generateVerifier_kimleeoh;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async function exportSolidityVerifier(zKeyName, templateName, logger) {
|
|
|
|
|
|
|
|
const verificationKey = await zkeyExportVerificationKey(zKeyName);
|
|
|
|
|
|
|
|
const fd = await readExisting$1(templateName);
|
|
|
|
const buff = await fd.read(fd.totalSize);
|
|
|
|
let template = new TextDecoder("utf-8").decode(buff);
|
|
|
|
|
|
|
|
const vkalpha1_str = `${verificationKey.vk_alpha_1[0].toString()},`+
|
|
|
|
`${verificationKey.vk_alpha_1[1].toString()}`;
|
|
|
|
template = template.replace("<%vk_alpha1%>", vkalpha1_str);
|
|
|
|
|
|
|
|
const vkbeta2_str = `[${verificationKey.vk_beta_2[0][1].toString()},`+
|
|
|
|
`${verificationKey.vk_beta_2[0][0].toString()}], `+
|
|
|
|
`[${verificationKey.vk_beta_2[1][1].toString()},` +
|
|
|
|
`${verificationKey.vk_beta_2[1][0].toString()}]`;
|
|
|
|
template = template.replace("<%vk_beta2%>", vkbeta2_str);
|
|
|
|
|
|
|
|
const vkgamma2_str = `[${verificationKey.vk_gamma_2[0][1].toString()},`+
|
|
|
|
`${verificationKey.vk_gamma_2[0][0].toString()}], `+
|
|
|
|
`[${verificationKey.vk_gamma_2[1][1].toString()},` +
|
|
|
|
`${verificationKey.vk_gamma_2[1][0].toString()}]`;
|
|
|
|
template = template.replace("<%vk_gamma2%>", vkgamma2_str);
|
|
|
|
|
|
|
|
const vkdelta2_str = `[${verificationKey.vk_delta_2[0][1].toString()},`+
|
|
|
|
`${verificationKey.vk_delta_2[0][0].toString()}], `+
|
|
|
|
`[${verificationKey.vk_delta_2[1][1].toString()},` +
|
|
|
|
`${verificationKey.vk_delta_2[1][0].toString()}]`;
|
|
|
|
template = template.replace("<%vk_delta2%>", vkdelta2_str);
|
|
|
|
|
|
|
|
// The points
|
|
|
|
|
|
|
|
template = template.replace("<%vk_input_length%>", (verificationKey.IC.length-1).toString());
|
|
|
|
template = template.replace("<%vk_ic_length%>", verificationKey.IC.length.toString());
|
|
|
|
let vi = "";
|
|
|
|
for (let i=0; i<verificationKey.IC.length; i++) {
|
|
|
|
if (vi != "") vi = vi + " ";
|
|
|
|
vi = vi + `vk.IC[${i}] = Pairing.G1Point(${verificationKey.IC[i][0].toString()},`+
|
|
|
|
`${verificationKey.IC[i][1].toString()});\n`;
|
|
|
|
}
|
|
|
|
template = template.replace("<%vk_ic_pts%>", vi);
|
|
|
|
|
|
|
|
return template;
|
|
|
|
}
|
|
|
|
|
|
|
|
var zkey = /*#__PURE__*/Object.freeze({
|
|
|
|
__proto__: null,
|
|
|
|
newZKey: newZKey,
|
|
|
|
exportBellman: phase2exportMPCParams,
|
|
|
|
importBellman: phase2importMPCParams,
|
|
|
|
verify: phase2verify,
|
|
|
|
contribute: phase2contribute,
|
|
|
|
beacon: beacon$1,
|
|
|
|
exportJson: zkeyExportJson,
|
|
|
|
bellmanContribute: bellmanContribute,
|
|
|
|
exportVerificationKey: zkeyExportVerificationKey,
|
|
|
|
exportSolidityVerifier: exportSolidityVerifier
|
|
|
|
});
|
|
|
|
|
|
|
|
exports.groth16 = groth16;
|
|
|
|
exports.powersOfTau = powersoftau;
|
|
|
|
exports.r1cs = r1cs;
|
|
|
|
exports.wtns = wtns;
|
|
|
|
exports.zKey = zkey;
|
|
|
|
|
|
|
|
return exports;
|
|
|
|
|
|
|
|
}({}));
|
2020-08-03 22:00:03 +02:00
|
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic25hcmtqcy5qcyIsInNvdXJjZXMiOlsiLi4vbm9kZV9tb2R1bGVzL2ZmamF2YXNjcmlwdC9zcmMvc2NhbGFyX25hdGl2ZS5qcyIsIi4uL25vZGVfbW9kdWxlcy9iaWctaW50ZWdlci9CaWdJbnRlZ2VyLmpzIiwiLi4vbm9kZV9tb2R1bGVzL2ZmamF2YXNjcmlwdC9zcmMvc2NhbGFyX2JpZ2ludC5qcyIsIi4uL25vZGVfbW9kdWxlcy9mZmphdmFzY3JpcHQvc3JjL3NjYWxhci5qcyIsIi4uL25vZGVfbW9kdWxlcy9mZmphdmFzY3JpcHQvc3JjL3BvbGZpZWxkLmpzIiwiLi4vbm9kZV9tb2R1bGVzL2ZmamF2YXNjcmlwdC9zcmMvZnV0aWxzLmpzIiwiLi4vbm9kZV9tb2R1bGVzL2ZmamF2YXNjcmlwdC9zcmMvZnNxcnQuanMiLCIuLi9ub2RlX21vZHVsZXMvZmZqYXZhc2NyaXB0L3NyYy9jaGFjaGEuanMiLCIuLi9ub2RlX21vZHVsZXMvZmZqYXZhc2NyaXB0L3NyYy9yYW5kb20uanMiLCIuLi9ub2RlX21vZHVsZXMvZmZqYXZhc2NyaXB0L3NyYy9mMWZpZWxkX25hdGl2ZS5qcyIsIi4uL25vZGVfbW9kdWxlcy9mZmphdmFzY3JpcHQvc3JjL2YxZmllbGRfYmlnaW50LmpzIiwiLi4vbm9kZV9tb2R1bGVzL2ZmamF2YXNjcmlwdC9zcmMvZjFmaWVsZC5qcyIsIi4uL25vZGVfbW9kdWxlcy9mZmphdmFzY3JpcHQvc3JjL2YyZmllbGQuanMiLCIuLi9ub2RlX21vZHVsZXMvZmZqYXZhc2NyaXB0L3NyYy9mM2ZpZWxkLmpzIiwiLi4vbm9kZV9tb2R1bGVzL2ZmamF2YXNjcmlwdC9zcmMvZWMuanMiLCIuLi9ub2RlX21vZHVsZXMvd2FzbWN1cnZlcy9idWlsZC9ibjEyOF93YXNtLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3dhc21jdXJ2ZXMvYnVpbGQvYmxzMTIzODFfd2FzbS5qcyIsIi4uL25vZGVfbW9kdWxlcy93YXNtY3VydmVzL2luZGV4LmpzIiwiLi4vbm9kZV9tb2R1bGVzL2ZmamF2YXNjcmlwdC9zcmMvdXRpbHNfbmF0aXZlLmpzIiwiLi4vbm9kZV9tb2R1bGVzL2ZmamF2YXNjcmlwdC9zcmMvdXRpbHNfYmlnaW50LmpzIiwiLi4vbm9kZV9tb2R1bGVzL2ZmamF2YXNjcmlwdC9zcmMvdXRpbHMuanMiLCIuLi9ub2RlX21vZHVsZXMvZmZqYXZhc2NyaXB0L3NyYy9lbmdpbmVfYmF0Y2hjb252ZXJ0LmpzIiwiLi4vbm9kZV9tb2R1bGVzL2ZmamF2YXNjcmlwdC9zcmMvd2FzbV9maWVsZDEuanMiLCIuLi9ub2RlX21vZHVsZXMvZmZqYXZhc2NyaXB0L3NyYy93YXNtX2ZpZWxkMi5qcyIsIi4uL25vZGVfbW9kdWxlcy9mZmphdmFzY3JpcHQvc3JjL3dhc21fZmllbGQzLmpzIiwiLi4vbm9kZV9tb2R1bGVzL2ZmamF2YXNjcmlwdC9zcmMvd2FzbV9jdXJ2ZS5qcyIsIi4uL25vZGVfbW9kdWxlcy9mZmphdmFzY3JpcHQvc3JjL3RocmVhZG1hbl90aHJlYWQuanMiLCIuLi9ub2RlX21vZHVsZXMvZmZqYXZhc2NyaXB0L3NyYy90aHJlYWRtYW4uanMiLCIuLi9ub2RlX21vZHVsZXMvZmZqYXZhc2NyaXB0L3NyYy9lbmdpbmVfYXBwbHlrZXkuanMiLCIuLi9ub2RlX21vZHVsZXMvZmZqYXZhc2NyaXB0L3NyYy9lbmdpbmVfcGFpcmluZy5qcyIsIi4uL25vZGVfbW9kdWxlcy9mZmphdmFzY3JpcHQvc3JjL2VuZ2luZV9tdWx0aWV4cC5qcyIsIi4uL25vZGVfbW9kdWxlcy9mZmphdmFzY3JpcHQvc3JjL2VuZ2luZV9mZnQuanMiLCIuLi9ub2RlX21vZHVsZXMvZmZqYXZhc2NyaXB0L3NyYy9lbmdpbmUuanMiLCIuLi9ub2RlX21vZHVsZXMvZmZqYXZhc2NyaXB0L3NyYy9ibjEyOC5qcyIsIi4uL25vZGVfbW9kdWxlcy9mZmphdmFzY3JpcHQvc3JjL2JsczEyMzgxLmpzIiwiLi4vbm9kZV9tb2R1bGVzL2ZmamF2YXNjcmlwdC9tYWluLmpzIiwiLi4vbm9kZV9tb2R1bGVzL2Zhc3RmaWxlL3NyYy9vc2ZpbGUuanMiLCIuLi9ub2RlX21vZHVsZXMvZmFzdGZpbGUvc3JjL21lbWZpbGUuanMiLCIuLi9ub2RlX21vZHVsZXMvZmFzdGZpbGUvc3JjL2Zhc3RmaWxlLmpzIiwiLi4vc3JjL2JpbmZpbGV1dGlscy5qcyIsIi4uL3NyYy9jdXJ2ZXMuanMiLCIuLi9ub2RlX21vZHVsZXMvbmFub2Fzc2VydC9pbmRleC5qcyIsIi4uL25vZGVfbW9kdWxlcy9ibGFrZTJiLXdhc20vYmxha2UyYi5qcyIsIi4uL25vZGVfbW9kdWxlcy9ibGFrZTJiLXdhc20vaW5kZXguanMiLCIuLi9zcmMvbWlzYy5qcyIsIi4uL3NyYy96a2V5X3V0aWxzLmpzIiwiLi4vc3JjL3d0bnNfdXRpbHMuanMiLCIuLi9zcmMvZ3JvdGgxNl9wcm92ZS5qcyIsIi4uL25vZGVfbW9kdWxlcy9mbnYtcGx1cy9pbmRleC5qcyIsIi4uL25vZGVfbW9kdWxlcy9jaXJjb21fcnVudGltZS9qcy91dGlscy5qcyIsIi4uL25vZGVfbW9kdWxlcy9jaXJjb21fcnVudGltZS9qcy93aXRuZXNzX2NhbGN1bGF0b3IuanMiLCIuLi9ub2RlX21vZHVsZXMvY2lyY29tX3J1bnRpbWUvaW5kZXguanMiLCIuLi9zcmMvd3Ruc19jYWxjdWxhdGUuanMiLCIuLi9zcmMvZ3JvdGgxNl9mdWxscHJvdmUuanMiLCIuLi9zcmMvZ3JvdGgxNl92ZXJpZnkuanMiLCIuLi9zcmMva2V5cGFpci5qcyIsIi4uL3NyYy9wb3dlcnNvZnRhdV91dGlscy5qcyIsIi4uL3NyYy9wb3dlcnNvZnRhdV9uZXcuanMiLCIuLi9zcmMvcG93ZXJzb2Z0YXVfZXhwb3J0X2NoYWxsZW5nZS5qcyIsIi4uL3NyYy9wb3dlcnNvZnRhdV9pbXBvcnQuanMiLCIuLi9zcmMvcG93ZXJzb2Z0YXVfdmVyaWZ5LmpzIiwiLi4vc3JjL21wY19hcHBseWtleS5qcyIsIi4uL3NyYy9wb3dlcnNvZnRhdV9jaGFsbGVuZ2VfY29udHJpYnV0ZS5qcyIsIi4uL3NyYy9wb3dlcnNvZnRhdV9iZWFjb24uanMiLCIuLi9zcmMvcG93ZXJzb2Z0YXVfY29udHJpYnV0ZS5qcyIsIi4uL3NyYy9wb3dlcnNvZnRhdV9wcmVwYXJlcGhhc2UyLmpzIiwiLi4vc3JjL3Bvd2Vyc29mdGF1X2V4cG9ydF9qc29uLmpzIiwiLi4vc3JjL3IxY3NfcHJpbnQuanMiLCIuLi9ub2RlX21vZHVsZXMvcjFjc2ZpbGUvbm9kZV9tb2R1bGVzL2Zhc3RmaWxlL3NyYy9vc2ZpbGUuanMiLCIuLi9ub2RlX21vZHVsZXMvcjFjc2ZpbGUvbm9kZV9tb2R1bGVzL2Zhc3RmaWxlL3NyYy9tZW1maWxlLmpzIiwiLi4vbm9kZV9tb2R1bGVzL3IxY3NmaWxlL25vZGVfbW9kdWxlcy9mYXN0ZmlsZS9zcmMvZmFzdGZpbGU
|