@etherspot/data-utils
Version:
Etherspot Data Utils
1,652 lines (1,645 loc) • 78.2 kB
JavaScript
import {
Hash,
abytes,
aexists,
ahash,
aoutput,
concatBytes,
createView,
randomBytes,
rotr,
toBytes,
wrapConstructor
} from "./chunk-S2KUQIEG.mjs";
import {
__export
} from "./chunk-PVVZGNOS.mjs";
// node_modules/@noble/hashes/esm/_md.js
function setBigUint64(view, byteOffset, value, isLE) {
if (typeof view.setBigUint64 === "function")
return view.setBigUint64(byteOffset, value, isLE);
const _32n = BigInt(32);
const _u32_max = BigInt(4294967295);
const wh = Number(value >> _32n & _u32_max);
const wl = Number(value & _u32_max);
const h = isLE ? 4 : 0;
const l = isLE ? 0 : 4;
view.setUint32(byteOffset + h, wh, isLE);
view.setUint32(byteOffset + l, wl, isLE);
}
function Chi(a, b, c) {
return a & b ^ ~a & c;
}
function Maj(a, b, c) {
return a & b ^ a & c ^ b & c;
}
var HashMD = class extends Hash {
constructor(blockLen, outputLen, padOffset, isLE) {
super();
this.blockLen = blockLen;
this.outputLen = outputLen;
this.padOffset = padOffset;
this.isLE = isLE;
this.finished = false;
this.length = 0;
this.pos = 0;
this.destroyed = false;
this.buffer = new Uint8Array(blockLen);
this.view = createView(this.buffer);
}
update(data) {
aexists(this);
const { view, buffer, blockLen } = this;
data = toBytes(data);
const len = data.length;
for (let pos = 0; pos < len; ) {
const take = Math.min(blockLen - this.pos, len - pos);
if (take === blockLen) {
const dataView = createView(data);
for (; blockLen <= len - pos; pos += blockLen)
this.process(dataView, pos);
continue;
}
buffer.set(data.subarray(pos, pos + take), this.pos);
this.pos += take;
pos += take;
if (this.pos === blockLen) {
this.process(view, 0);
this.pos = 0;
}
}
this.length += data.length;
this.roundClean();
return this;
}
digestInto(out) {
aexists(this);
aoutput(out, this);
this.finished = true;
const { buffer, view, blockLen, isLE } = this;
let { pos } = this;
buffer[pos++] = 128;
this.buffer.subarray(pos).fill(0);
if (this.padOffset > blockLen - pos) {
this.process(view, 0);
pos = 0;
}
for (let i = pos; i < blockLen; i++)
buffer[i] = 0;
setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE);
this.process(view, 0);
const oview = createView(out);
const len = this.outputLen;
if (len % 4)
throw new Error("_sha2: outputLen should be aligned to 32bit");
const outLen = len / 4;
const state = this.get();
if (outLen > state.length)
throw new Error("_sha2: outputLen bigger than state");
for (let i = 0; i < outLen; i++)
oview.setUint32(4 * i, state[i], isLE);
}
digest() {
const { buffer, outputLen } = this;
this.digestInto(buffer);
const res = buffer.slice(0, outputLen);
this.destroy();
return res;
}
_cloneInto(to) {
to || (to = new this.constructor());
to.set(...this.get());
const { blockLen, buffer, length, finished, destroyed, pos } = this;
to.length = length;
to.pos = pos;
to.finished = finished;
to.destroyed = destroyed;
if (length % blockLen)
to.buffer.set(buffer);
return to;
}
};
// node_modules/@noble/hashes/esm/sha256.js
var SHA256_K = /* @__PURE__ */ new Uint32Array([
1116352408,
1899447441,
3049323471,
3921009573,
961987163,
1508970993,
2453635748,
2870763221,
3624381080,
310598401,
607225278,
1426881987,
1925078388,
2162078206,
2614888103,
3248222580,
3835390401,
4022224774,
264347078,
604807628,
770255983,
1249150122,
1555081692,
1996064986,
2554220882,
2821834349,
2952996808,
3210313671,
3336571891,
3584528711,
113926993,
338241895,
666307205,
773529912,
1294757372,
1396182291,
1695183700,
1986661051,
2177026350,
2456956037,
2730485921,
2820302411,
3259730800,
3345764771,
3516065817,
3600352804,
4094571909,
275423344,
430227734,
506948616,
659060556,
883997877,
958139571,
1322822218,
1537002063,
1747873779,
1955562222,
2024104815,
2227730452,
2361852424,
2428436474,
2756734187,
3204031479,
3329325298
]);
var SHA256_IV = /* @__PURE__ */ new Uint32Array([
1779033703,
3144134277,
1013904242,
2773480762,
1359893119,
2600822924,
528734635,
1541459225
]);
var SHA256_W = /* @__PURE__ */ new Uint32Array(64);
var SHA256 = class extends HashMD {
constructor() {
super(64, 32, 8, false);
this.A = SHA256_IV[0] | 0;
this.B = SHA256_IV[1] | 0;
this.C = SHA256_IV[2] | 0;
this.D = SHA256_IV[3] | 0;
this.E = SHA256_IV[4] | 0;
this.F = SHA256_IV[5] | 0;
this.G = SHA256_IV[6] | 0;
this.H = SHA256_IV[7] | 0;
}
get() {
const { A, B, C, D, E, F, G, H } = this;
return [A, B, C, D, E, F, G, H];
}
// prettier-ignore
set(A, B, C, D, E, F, G, H) {
this.A = A | 0;
this.B = B | 0;
this.C = C | 0;
this.D = D | 0;
this.E = E | 0;
this.F = F | 0;
this.G = G | 0;
this.H = H | 0;
}
process(view, offset) {
for (let i = 0; i < 16; i++, offset += 4)
SHA256_W[i] = view.getUint32(offset, false);
for (let i = 16; i < 64; i++) {
const W15 = SHA256_W[i - 15];
const W2 = SHA256_W[i - 2];
const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ W15 >>> 3;
const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ W2 >>> 10;
SHA256_W[i] = s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16] | 0;
}
let { A, B, C, D, E, F, G, H } = this;
for (let i = 0; i < 64; i++) {
const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);
const T1 = H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i] | 0;
const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);
const T2 = sigma0 + Maj(A, B, C) | 0;
H = G;
G = F;
F = E;
E = D + T1 | 0;
D = C;
C = B;
B = A;
A = T1 + T2 | 0;
}
A = A + this.A | 0;
B = B + this.B | 0;
C = C + this.C | 0;
D = D + this.D | 0;
E = E + this.E | 0;
F = F + this.F | 0;
G = G + this.G | 0;
H = H + this.H | 0;
this.set(A, B, C, D, E, F, G, H);
}
roundClean() {
SHA256_W.fill(0);
}
destroy() {
this.set(0, 0, 0, 0, 0, 0, 0, 0);
this.buffer.fill(0);
}
};
var sha256 = /* @__PURE__ */ wrapConstructor(() => new SHA256());
// node_modules/@noble/hashes/esm/hmac.js
var HMAC = class extends Hash {
constructor(hash, _key) {
super();
this.finished = false;
this.destroyed = false;
ahash(hash);
const key = toBytes(_key);
this.iHash = hash.create();
if (typeof this.iHash.update !== "function")
throw new Error("Expected instance of class which extends utils.Hash");
this.blockLen = this.iHash.blockLen;
this.outputLen = this.iHash.outputLen;
const blockLen = this.blockLen;
const pad = new Uint8Array(blockLen);
pad.set(key.length > blockLen ? hash.create().update(key).digest() : key);
for (let i = 0; i < pad.length; i++)
pad[i] ^= 54;
this.iHash.update(pad);
this.oHash = hash.create();
for (let i = 0; i < pad.length; i++)
pad[i] ^= 54 ^ 92;
this.oHash.update(pad);
pad.fill(0);
}
update(buf) {
aexists(this);
this.iHash.update(buf);
return this;
}
digestInto(out) {
aexists(this);
abytes(out, this.outputLen);
this.finished = true;
this.iHash.digestInto(out);
this.oHash.update(out);
this.oHash.digestInto(out);
this.destroy();
}
digest() {
const out = new Uint8Array(this.oHash.outputLen);
this.digestInto(out);
return out;
}
_cloneInto(to) {
to || (to = Object.create(Object.getPrototypeOf(this), {}));
const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this;
to = to;
to.finished = finished;
to.destroyed = destroyed;
to.blockLen = blockLen;
to.outputLen = outputLen;
to.oHash = oHash._cloneInto(to.oHash);
to.iHash = iHash._cloneInto(to.iHash);
return to;
}
destroy() {
this.destroyed = true;
this.oHash.destroy();
this.iHash.destroy();
}
};
var hmac = (hash, key, message) => new HMAC(hash, key).update(message).digest();
hmac.create = (hash, key) => new HMAC(hash, key);
// node_modules/@noble/curves/esm/abstract/utils.js
var utils_exports = {};
__export(utils_exports, {
aInRange: () => aInRange,
abool: () => abool,
abytes: () => abytes2,
bitGet: () => bitGet,
bitLen: () => bitLen,
bitMask: () => bitMask,
bitSet: () => bitSet,
bytesToHex: () => bytesToHex,
bytesToNumberBE: () => bytesToNumberBE,
bytesToNumberLE: () => bytesToNumberLE,
concatBytes: () => concatBytes2,
createHmacDrbg: () => createHmacDrbg,
ensureBytes: () => ensureBytes,
equalBytes: () => equalBytes,
hexToBytes: () => hexToBytes,
hexToNumber: () => hexToNumber,
inRange: () => inRange,
isBytes: () => isBytes,
memoized: () => memoized,
notImplemented: () => notImplemented,
numberToBytesBE: () => numberToBytesBE,
numberToBytesLE: () => numberToBytesLE,
numberToHexUnpadded: () => numberToHexUnpadded,
numberToVarBytesBE: () => numberToVarBytesBE,
utf8ToBytes: () => utf8ToBytes,
validateObject: () => validateObject
});
var _0n = /* @__PURE__ */ BigInt(0);
var _1n = /* @__PURE__ */ BigInt(1);
var _2n = /* @__PURE__ */ BigInt(2);
function isBytes(a) {
return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
}
function abytes2(item) {
if (!isBytes(item))
throw new Error("Uint8Array expected");
}
function abool(title, value) {
if (typeof value !== "boolean")
throw new Error(title + " boolean expected, got " + value);
}
var hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, "0"));
function bytesToHex(bytes) {
abytes2(bytes);
let hex = "";
for (let i = 0; i < bytes.length; i++) {
hex += hexes[bytes[i]];
}
return hex;
}
function numberToHexUnpadded(num2) {
const hex = num2.toString(16);
return hex.length & 1 ? "0" + hex : hex;
}
function hexToNumber(hex) {
if (typeof hex !== "string")
throw new Error("hex string expected, got " + typeof hex);
return hex === "" ? _0n : BigInt("0x" + hex);
}
var asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 };
function asciiToBase16(ch) {
if (ch >= asciis._0 && ch <= asciis._9)
return ch - asciis._0;
if (ch >= asciis.A && ch <= asciis.F)
return ch - (asciis.A - 10);
if (ch >= asciis.a && ch <= asciis.f)
return ch - (asciis.a - 10);
return;
}
function hexToBytes(hex) {
if (typeof hex !== "string")
throw new Error("hex string expected, got " + typeof hex);
const hl = hex.length;
const al = hl / 2;
if (hl % 2)
throw new Error("hex string expected, got unpadded hex of length " + hl);
const array = new Uint8Array(al);
for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {
const n1 = asciiToBase16(hex.charCodeAt(hi));
const n2 = asciiToBase16(hex.charCodeAt(hi + 1));
if (n1 === void 0 || n2 === void 0) {
const char = hex[hi] + hex[hi + 1];
throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi);
}
array[ai] = n1 * 16 + n2;
}
return array;
}
function bytesToNumberBE(bytes) {
return hexToNumber(bytesToHex(bytes));
}
function bytesToNumberLE(bytes) {
abytes2(bytes);
return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse()));
}
function numberToBytesBE(n, len) {
return hexToBytes(n.toString(16).padStart(len * 2, "0"));
}
function numberToBytesLE(n, len) {
return numberToBytesBE(n, len).reverse();
}
function numberToVarBytesBE(n) {
return hexToBytes(numberToHexUnpadded(n));
}
function ensureBytes(title, hex, expectedLength) {
let res;
if (typeof hex === "string") {
try {
res = hexToBytes(hex);
} catch (e) {
throw new Error(title + " must be hex string or Uint8Array, cause: " + e);
}
} else if (isBytes(hex)) {
res = Uint8Array.from(hex);
} else {
throw new Error(title + " must be hex string or Uint8Array");
}
const len = res.length;
if (typeof expectedLength === "number" && len !== expectedLength)
throw new Error(title + " of length " + expectedLength + " expected, got " + len);
return res;
}
function concatBytes2(...arrays) {
let sum = 0;
for (let i = 0; i < arrays.length; i++) {
const a = arrays[i];
abytes2(a);
sum += a.length;
}
const res = new Uint8Array(sum);
for (let i = 0, pad = 0; i < arrays.length; i++) {
const a = arrays[i];
res.set(a, pad);
pad += a.length;
}
return res;
}
function equalBytes(a, b) {
if (a.length !== b.length)
return false;
let diff = 0;
for (let i = 0; i < a.length; i++)
diff |= a[i] ^ b[i];
return diff === 0;
}
function utf8ToBytes(str) {
if (typeof str !== "string")
throw new Error("string expected");
return new Uint8Array(new TextEncoder().encode(str));
}
var isPosBig = (n) => typeof n === "bigint" && _0n <= n;
function inRange(n, min, max) {
return isPosBig(n) && isPosBig(min) && isPosBig(max) && min <= n && n < max;
}
function aInRange(title, n, min, max) {
if (!inRange(n, min, max))
throw new Error("expected valid " + title + ": " + min + " <= n < " + max + ", got " + n);
}
function bitLen(n) {
let len;
for (len = 0; n > _0n; n >>= _1n, len += 1)
;
return len;
}
function bitGet(n, pos) {
return n >> BigInt(pos) & _1n;
}
function bitSet(n, pos, value) {
return n | (value ? _1n : _0n) << BigInt(pos);
}
var bitMask = (n) => (_2n << BigInt(n - 1)) - _1n;
var u8n = (data) => new Uint8Array(data);
var u8fr = (arr) => Uint8Array.from(arr);
function createHmacDrbg(hashLen, qByteLen, hmacFn) {
if (typeof hashLen !== "number" || hashLen < 2)
throw new Error("hashLen must be a number");
if (typeof qByteLen !== "number" || qByteLen < 2)
throw new Error("qByteLen must be a number");
if (typeof hmacFn !== "function")
throw new Error("hmacFn must be a function");
let v = u8n(hashLen);
let k = u8n(hashLen);
let i = 0;
const reset = () => {
v.fill(1);
k.fill(0);
i = 0;
};
const h = (...b) => hmacFn(k, v, ...b);
const reseed = (seed = u8n()) => {
k = h(u8fr([0]), seed);
v = h();
if (seed.length === 0)
return;
k = h(u8fr([1]), seed);
v = h();
};
const gen = () => {
if (i++ >= 1e3)
throw new Error("drbg: tried 1000 values");
let len = 0;
const out = [];
while (len < qByteLen) {
v = h();
const sl = v.slice();
out.push(sl);
len += v.length;
}
return concatBytes2(...out);
};
const genUntil = (seed, pred) => {
reset();
reseed(seed);
let res = void 0;
while (!(res = pred(gen())))
reseed();
reset();
return res;
};
return genUntil;
}
var validatorFns = {
bigint: (val) => typeof val === "bigint",
function: (val) => typeof val === "function",
boolean: (val) => typeof val === "boolean",
string: (val) => typeof val === "string",
stringOrUint8Array: (val) => typeof val === "string" || isBytes(val),
isSafeInteger: (val) => Number.isSafeInteger(val),
array: (val) => Array.isArray(val),
field: (val, object) => object.Fp.isValid(val),
hash: (val) => typeof val === "function" && Number.isSafeInteger(val.outputLen)
};
function validateObject(object, validators, optValidators = {}) {
const checkField = (fieldName, type, isOptional) => {
const checkVal = validatorFns[type];
if (typeof checkVal !== "function")
throw new Error("invalid validator function");
const val = object[fieldName];
if (isOptional && val === void 0)
return;
if (!checkVal(val, object)) {
throw new Error("param " + String(fieldName) + " is invalid. Expected " + type + ", got " + val);
}
};
for (const [fieldName, type] of Object.entries(validators))
checkField(fieldName, type, false);
for (const [fieldName, type] of Object.entries(optValidators))
checkField(fieldName, type, true);
return object;
}
var notImplemented = () => {
throw new Error("not implemented");
};
function memoized(fn) {
const map = /* @__PURE__ */ new WeakMap();
return (arg, ...args) => {
const val = map.get(arg);
if (val !== void 0)
return val;
const computed = fn(arg, ...args);
map.set(arg, computed);
return computed;
};
}
// node_modules/@noble/curves/esm/abstract/modular.js
var _0n2 = BigInt(0);
var _1n2 = BigInt(1);
var _2n2 = /* @__PURE__ */ BigInt(2);
var _3n = /* @__PURE__ */ BigInt(3);
var _4n = /* @__PURE__ */ BigInt(4);
var _5n = /* @__PURE__ */ BigInt(5);
var _8n = /* @__PURE__ */ BigInt(8);
var _9n = /* @__PURE__ */ BigInt(9);
var _16n = /* @__PURE__ */ BigInt(16);
function mod(a, b) {
const result = a % b;
return result >= _0n2 ? result : b + result;
}
function pow(num2, power, modulo) {
if (power < _0n2)
throw new Error("invalid exponent, negatives unsupported");
if (modulo <= _0n2)
throw new Error("invalid modulus");
if (modulo === _1n2)
return _0n2;
let res = _1n2;
while (power > _0n2) {
if (power & _1n2)
res = res * num2 % modulo;
num2 = num2 * num2 % modulo;
power >>= _1n2;
}
return res;
}
function pow2(x, power, modulo) {
let res = x;
while (power-- > _0n2) {
res *= res;
res %= modulo;
}
return res;
}
function invert(number, modulo) {
if (number === _0n2)
throw new Error("invert: expected non-zero number");
if (modulo <= _0n2)
throw new Error("invert: expected positive modulus, got " + modulo);
let a = mod(number, modulo);
let b = modulo;
let x = _0n2, y = _1n2, u = _1n2, v = _0n2;
while (a !== _0n2) {
const q = b / a;
const r = b % a;
const m = x - u * q;
const n = y - v * q;
b = a, a = r, x = u, y = v, u = m, v = n;
}
const gcd = b;
if (gcd !== _1n2)
throw new Error("invert: does not exist");
return mod(x, modulo);
}
function tonelliShanks(P) {
const legendreC = (P - _1n2) / _2n2;
let Q, S, Z;
for (Q = P - _1n2, S = 0; Q % _2n2 === _0n2; Q /= _2n2, S++)
;
for (Z = _2n2; Z < P && pow(Z, legendreC, P) !== P - _1n2; Z++) {
if (Z > 1e3)
throw new Error("Cannot find square root: likely non-prime P");
}
if (S === 1) {
const p1div4 = (P + _1n2) / _4n;
return function tonelliFast(Fp, n) {
const root = Fp.pow(n, p1div4);
if (!Fp.eql(Fp.sqr(root), n))
throw new Error("Cannot find square root");
return root;
};
}
const Q1div2 = (Q + _1n2) / _2n2;
return function tonelliSlow(Fp, n) {
if (Fp.pow(n, legendreC) === Fp.neg(Fp.ONE))
throw new Error("Cannot find square root");
let r = S;
let g = Fp.pow(Fp.mul(Fp.ONE, Z), Q);
let x = Fp.pow(n, Q1div2);
let b = Fp.pow(n, Q);
while (!Fp.eql(b, Fp.ONE)) {
if (Fp.eql(b, Fp.ZERO))
return Fp.ZERO;
let m = 1;
for (let t2 = Fp.sqr(b); m < r; m++) {
if (Fp.eql(t2, Fp.ONE))
break;
t2 = Fp.sqr(t2);
}
const ge = Fp.pow(g, _1n2 << BigInt(r - m - 1));
g = Fp.sqr(ge);
x = Fp.mul(x, ge);
b = Fp.mul(b, g);
r = m;
}
return x;
};
}
function FpSqrt(P) {
if (P % _4n === _3n) {
const p1div4 = (P + _1n2) / _4n;
return function sqrt3mod4(Fp, n) {
const root = Fp.pow(n, p1div4);
if (!Fp.eql(Fp.sqr(root), n))
throw new Error("Cannot find square root");
return root;
};
}
if (P % _8n === _5n) {
const c1 = (P - _5n) / _8n;
return function sqrt5mod8(Fp, n) {
const n2 = Fp.mul(n, _2n2);
const v = Fp.pow(n2, c1);
const nv = Fp.mul(n, v);
const i = Fp.mul(Fp.mul(nv, _2n2), v);
const root = Fp.mul(nv, Fp.sub(i, Fp.ONE));
if (!Fp.eql(Fp.sqr(root), n))
throw new Error("Cannot find square root");
return root;
};
}
if (P % _16n === _9n) {
}
return tonelliShanks(P);
}
var FIELD_FIELDS = [
"create",
"isValid",
"is0",
"neg",
"inv",
"sqrt",
"sqr",
"eql",
"add",
"sub",
"mul",
"pow",
"div",
"addN",
"subN",
"mulN",
"sqrN"
];
function validateField(field) {
const initial = {
ORDER: "bigint",
MASK: "bigint",
BYTES: "isSafeInteger",
BITS: "isSafeInteger"
};
const opts = FIELD_FIELDS.reduce((map, val) => {
map[val] = "function";
return map;
}, initial);
return validateObject(field, opts);
}
function FpPow(f, num2, power) {
if (power < _0n2)
throw new Error("invalid exponent, negatives unsupported");
if (power === _0n2)
return f.ONE;
if (power === _1n2)
return num2;
let p = f.ONE;
let d = num2;
while (power > _0n2) {
if (power & _1n2)
p = f.mul(p, d);
d = f.sqr(d);
power >>= _1n2;
}
return p;
}
function FpInvertBatch(f, nums) {
const tmp = new Array(nums.length);
const lastMultiplied = nums.reduce((acc, num2, i) => {
if (f.is0(num2))
return acc;
tmp[i] = acc;
return f.mul(acc, num2);
}, f.ONE);
const inverted = f.inv(lastMultiplied);
nums.reduceRight((acc, num2, i) => {
if (f.is0(num2))
return acc;
tmp[i] = f.mul(acc, tmp[i]);
return f.mul(acc, num2);
}, inverted);
return tmp;
}
function nLength(n, nBitLength) {
const _nBitLength = nBitLength !== void 0 ? nBitLength : n.toString(2).length;
const nByteLength = Math.ceil(_nBitLength / 8);
return { nBitLength: _nBitLength, nByteLength };
}
function Field(ORDER, bitLen2, isLE = false, redef = {}) {
if (ORDER <= _0n2)
throw new Error("invalid field: expected ORDER > 0, got " + ORDER);
const { nBitLength: BITS, nByteLength: BYTES } = nLength(ORDER, bitLen2);
if (BYTES > 2048)
throw new Error("invalid field: expected ORDER of <= 2048 bytes");
let sqrtP;
const f = Object.freeze({
ORDER,
isLE,
BITS,
BYTES,
MASK: bitMask(BITS),
ZERO: _0n2,
ONE: _1n2,
create: (num2) => mod(num2, ORDER),
isValid: (num2) => {
if (typeof num2 !== "bigint")
throw new Error("invalid field element: expected bigint, got " + typeof num2);
return _0n2 <= num2 && num2 < ORDER;
},
is0: (num2) => num2 === _0n2,
isOdd: (num2) => (num2 & _1n2) === _1n2,
neg: (num2) => mod(-num2, ORDER),
eql: (lhs, rhs) => lhs === rhs,
sqr: (num2) => mod(num2 * num2, ORDER),
add: (lhs, rhs) => mod(lhs + rhs, ORDER),
sub: (lhs, rhs) => mod(lhs - rhs, ORDER),
mul: (lhs, rhs) => mod(lhs * rhs, ORDER),
pow: (num2, power) => FpPow(f, num2, power),
div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER),
// Same as above, but doesn't normalize
sqrN: (num2) => num2 * num2,
addN: (lhs, rhs) => lhs + rhs,
subN: (lhs, rhs) => lhs - rhs,
mulN: (lhs, rhs) => lhs * rhs,
inv: (num2) => invert(num2, ORDER),
sqrt: redef.sqrt || ((n) => {
if (!sqrtP)
sqrtP = FpSqrt(ORDER);
return sqrtP(f, n);
}),
invertBatch: (lst) => FpInvertBatch(f, lst),
// TODO: do we really need constant cmov?
// We don't have const-time bigints anyway, so probably will be not very useful
cmov: (a, b, c) => c ? b : a,
toBytes: (num2) => isLE ? numberToBytesLE(num2, BYTES) : numberToBytesBE(num2, BYTES),
fromBytes: (bytes) => {
if (bytes.length !== BYTES)
throw new Error("Field.fromBytes: expected " + BYTES + " bytes, got " + bytes.length);
return isLE ? bytesToNumberLE(bytes) : bytesToNumberBE(bytes);
}
});
return Object.freeze(f);
}
function getFieldBytesLength(fieldOrder) {
if (typeof fieldOrder !== "bigint")
throw new Error("field order must be bigint");
const bitLength = fieldOrder.toString(2).length;
return Math.ceil(bitLength / 8);
}
function getMinHashLength(fieldOrder) {
const length = getFieldBytesLength(fieldOrder);
return length + Math.ceil(length / 2);
}
function mapHashToField(key, fieldOrder, isLE = false) {
const len = key.length;
const fieldLen = getFieldBytesLength(fieldOrder);
const minLen = getMinHashLength(fieldOrder);
if (len < 16 || len < minLen || len > 1024)
throw new Error("expected " + minLen + "-1024 bytes of input, got " + len);
const num2 = isLE ? bytesToNumberLE(key) : bytesToNumberBE(key);
const reduced = mod(num2, fieldOrder - _1n2) + _1n2;
return isLE ? numberToBytesLE(reduced, fieldLen) : numberToBytesBE(reduced, fieldLen);
}
// node_modules/@noble/curves/esm/abstract/curve.js
var _0n3 = BigInt(0);
var _1n3 = BigInt(1);
function constTimeNegate(condition, item) {
const neg = item.negate();
return condition ? neg : item;
}
function validateW(W, bits) {
if (!Number.isSafeInteger(W) || W <= 0 || W > bits)
throw new Error("invalid window size, expected [1.." + bits + "], got W=" + W);
}
function calcWOpts(W, bits) {
validateW(W, bits);
const windows = Math.ceil(bits / W) + 1;
const windowSize = 2 ** (W - 1);
return { windows, windowSize };
}
function validateMSMPoints(points, c) {
if (!Array.isArray(points))
throw new Error("array expected");
points.forEach((p, i) => {
if (!(p instanceof c))
throw new Error("invalid point at index " + i);
});
}
function validateMSMScalars(scalars, field) {
if (!Array.isArray(scalars))
throw new Error("array of scalars expected");
scalars.forEach((s, i) => {
if (!field.isValid(s))
throw new Error("invalid scalar at index " + i);
});
}
var pointPrecomputes = /* @__PURE__ */ new WeakMap();
var pointWindowSizes = /* @__PURE__ */ new WeakMap();
function getW(P) {
return pointWindowSizes.get(P) || 1;
}
function wNAF(c, bits) {
return {
constTimeNegate,
hasPrecomputes(elm) {
return getW(elm) !== 1;
},
// non-const time multiplication ladder
unsafeLadder(elm, n, p = c.ZERO) {
let d = elm;
while (n > _0n3) {
if (n & _1n3)
p = p.add(d);
d = d.double();
n >>= _1n3;
}
return p;
},
/**
* Creates a wNAF precomputation window. Used for caching.
* Default window size is set by `utils.precompute()` and is equal to 8.
* Number of precomputed points depends on the curve size:
* 2^(𝑊−1) * (Math.ceil(𝑛 / 𝑊) + 1), where:
* - 𝑊 is the window size
* - 𝑛 is the bitlength of the curve order.
* For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224.
* @param elm Point instance
* @param W window size
* @returns precomputed point tables flattened to a single array
*/
precomputeWindow(elm, W) {
const { windows, windowSize } = calcWOpts(W, bits);
const points = [];
let p = elm;
let base = p;
for (let window = 0; window < windows; window++) {
base = p;
points.push(base);
for (let i = 1; i < windowSize; i++) {
base = base.add(p);
points.push(base);
}
p = base.double();
}
return points;
},
/**
* Implements ec multiplication using precomputed tables and w-ary non-adjacent form.
* @param W window size
* @param precomputes precomputed tables
* @param n scalar (we don't check here, but should be less than curve order)
* @returns real and fake (for const-time) points
*/
wNAF(W, precomputes, n) {
const { windows, windowSize } = calcWOpts(W, bits);
let p = c.ZERO;
let f = c.BASE;
const mask = BigInt(2 ** W - 1);
const maxNumber = 2 ** W;
const shiftBy = BigInt(W);
for (let window = 0; window < windows; window++) {
const offset = window * windowSize;
let wbits = Number(n & mask);
n >>= shiftBy;
if (wbits > windowSize) {
wbits -= maxNumber;
n += _1n3;
}
const offset1 = offset;
const offset2 = offset + Math.abs(wbits) - 1;
const cond1 = window % 2 !== 0;
const cond2 = wbits < 0;
if (wbits === 0) {
f = f.add(constTimeNegate(cond1, precomputes[offset1]));
} else {
p = p.add(constTimeNegate(cond2, precomputes[offset2]));
}
}
return { p, f };
},
/**
* Implements ec unsafe (non const-time) multiplication using precomputed tables and w-ary non-adjacent form.
* @param W window size
* @param precomputes precomputed tables
* @param n scalar (we don't check here, but should be less than curve order)
* @param acc accumulator point to add result of multiplication
* @returns point
*/
wNAFUnsafe(W, precomputes, n, acc = c.ZERO) {
const { windows, windowSize } = calcWOpts(W, bits);
const mask = BigInt(2 ** W - 1);
const maxNumber = 2 ** W;
const shiftBy = BigInt(W);
for (let window = 0; window < windows; window++) {
const offset = window * windowSize;
if (n === _0n3)
break;
let wbits = Number(n & mask);
n >>= shiftBy;
if (wbits > windowSize) {
wbits -= maxNumber;
n += _1n3;
}
if (wbits === 0)
continue;
let curr = precomputes[offset + Math.abs(wbits) - 1];
if (wbits < 0)
curr = curr.negate();
acc = acc.add(curr);
}
return acc;
},
getPrecomputes(W, P, transform) {
let comp = pointPrecomputes.get(P);
if (!comp) {
comp = this.precomputeWindow(P, W);
if (W !== 1)
pointPrecomputes.set(P, transform(comp));
}
return comp;
},
wNAFCached(P, n, transform) {
const W = getW(P);
return this.wNAF(W, this.getPrecomputes(W, P, transform), n);
},
wNAFCachedUnsafe(P, n, transform, prev) {
const W = getW(P);
if (W === 1)
return this.unsafeLadder(P, n, prev);
return this.wNAFUnsafe(W, this.getPrecomputes(W, P, transform), n, prev);
},
// We calculate precomputes for elliptic curve point multiplication
// using windowed method. This specifies window size and
// stores precomputed values. Usually only base point would be precomputed.
setWindowSize(P, W) {
validateW(W, bits);
pointWindowSizes.set(P, W);
pointPrecomputes.delete(P);
}
};
}
function pippenger(c, fieldN, points, scalars) {
validateMSMPoints(points, c);
validateMSMScalars(scalars, fieldN);
if (points.length !== scalars.length)
throw new Error("arrays of points and scalars must have equal length");
const zero = c.ZERO;
const wbits = bitLen(BigInt(points.length));
const windowSize = wbits > 12 ? wbits - 3 : wbits > 4 ? wbits - 2 : wbits ? 2 : 1;
const MASK = (1 << windowSize) - 1;
const buckets = new Array(MASK + 1).fill(zero);
const lastBits = Math.floor((fieldN.BITS - 1) / windowSize) * windowSize;
let sum = zero;
for (let i = lastBits; i >= 0; i -= windowSize) {
buckets.fill(zero);
for (let j = 0; j < scalars.length; j++) {
const scalar = scalars[j];
const wbits2 = Number(scalar >> BigInt(i) & BigInt(MASK));
buckets[wbits2] = buckets[wbits2].add(points[j]);
}
let resI = zero;
for (let j = buckets.length - 1, sumI = zero; j > 0; j--) {
sumI = sumI.add(buckets[j]);
resI = resI.add(sumI);
}
sum = sum.add(resI);
if (i !== 0)
for (let j = 0; j < windowSize; j++)
sum = sum.double();
}
return sum;
}
function validateBasic(curve) {
validateField(curve.Fp);
validateObject(curve, {
n: "bigint",
h: "bigint",
Gx: "field",
Gy: "field"
}, {
nBitLength: "isSafeInteger",
nByteLength: "isSafeInteger"
});
return Object.freeze({
...nLength(curve.n, curve.nBitLength),
...curve,
...{ p: curve.Fp.ORDER }
});
}
// node_modules/@noble/curves/esm/abstract/weierstrass.js
function validateSigVerOpts(opts) {
if (opts.lowS !== void 0)
abool("lowS", opts.lowS);
if (opts.prehash !== void 0)
abool("prehash", opts.prehash);
}
function validatePointOpts(curve) {
const opts = validateBasic(curve);
validateObject(opts, {
a: "field",
b: "field"
}, {
allowedPrivateKeyLengths: "array",
wrapPrivateKey: "boolean",
isTorsionFree: "function",
clearCofactor: "function",
allowInfinityPoint: "boolean",
fromBytes: "function",
toBytes: "function"
});
const { endo, Fp, a } = opts;
if (endo) {
if (!Fp.eql(a, Fp.ZERO)) {
throw new Error("invalid endomorphism, can only be defined for Koblitz curves that have a=0");
}
if (typeof endo !== "object" || typeof endo.beta !== "bigint" || typeof endo.splitScalar !== "function") {
throw new Error("invalid endomorphism, expected beta: bigint and splitScalar: function");
}
}
return Object.freeze({ ...opts });
}
var { bytesToNumberBE: b2n, hexToBytes: h2b } = utils_exports;
var DERErr = class extends Error {
constructor(m = "") {
super(m);
}
};
var DER = {
// asn.1 DER encoding utils
Err: DERErr,
// Basic building block is TLV (Tag-Length-Value)
_tlv: {
encode: (tag, data) => {
const { Err: E } = DER;
if (tag < 0 || tag > 256)
throw new E("tlv.encode: wrong tag");
if (data.length & 1)
throw new E("tlv.encode: unpadded data");
const dataLen = data.length / 2;
const len = numberToHexUnpadded(dataLen);
if (len.length / 2 & 128)
throw new E("tlv.encode: long form length too big");
const lenLen = dataLen > 127 ? numberToHexUnpadded(len.length / 2 | 128) : "";
const t = numberToHexUnpadded(tag);
return t + lenLen + len + data;
},
// v - value, l - left bytes (unparsed)
decode(tag, data) {
const { Err: E } = DER;
let pos = 0;
if (tag < 0 || tag > 256)
throw new E("tlv.encode: wrong tag");
if (data.length < 2 || data[pos++] !== tag)
throw new E("tlv.decode: wrong tlv");
const first = data[pos++];
const isLong = !!(first & 128);
let length = 0;
if (!isLong)
length = first;
else {
const lenLen = first & 127;
if (!lenLen)
throw new E("tlv.decode(long): indefinite length not supported");
if (lenLen > 4)
throw new E("tlv.decode(long): byte length is too big");
const lengthBytes = data.subarray(pos, pos + lenLen);
if (lengthBytes.length !== lenLen)
throw new E("tlv.decode: length bytes not complete");
if (lengthBytes[0] === 0)
throw new E("tlv.decode(long): zero leftmost byte");
for (const b of lengthBytes)
length = length << 8 | b;
pos += lenLen;
if (length < 128)
throw new E("tlv.decode(long): not minimal encoding");
}
const v = data.subarray(pos, pos + length);
if (v.length !== length)
throw new E("tlv.decode: wrong value length");
return { v, l: data.subarray(pos + length) };
}
},
// https://crypto.stackexchange.com/a/57734 Leftmost bit of first byte is 'negative' flag,
// since we always use positive integers here. It must always be empty:
// - add zero byte if exists
// - if next byte doesn't have a flag, leading zero is not allowed (minimal encoding)
_int: {
encode(num2) {
const { Err: E } = DER;
if (num2 < _0n4)
throw new E("integer: negative integers are not allowed");
let hex = numberToHexUnpadded(num2);
if (Number.parseInt(hex[0], 16) & 8)
hex = "00" + hex;
if (hex.length & 1)
throw new E("unexpected DER parsing assertion: unpadded hex");
return hex;
},
decode(data) {
const { Err: E } = DER;
if (data[0] & 128)
throw new E("invalid signature integer: negative");
if (data[0] === 0 && !(data[1] & 128))
throw new E("invalid signature integer: unnecessary leading zero");
return b2n(data);
}
},
toSig(hex) {
const { Err: E, _int: int, _tlv: tlv } = DER;
const data = typeof hex === "string" ? h2b(hex) : hex;
abytes2(data);
const { v: seqBytes, l: seqLeftBytes } = tlv.decode(48, data);
if (seqLeftBytes.length)
throw new E("invalid signature: left bytes after parsing");
const { v: rBytes, l: rLeftBytes } = tlv.decode(2, seqBytes);
const { v: sBytes, l: sLeftBytes } = tlv.decode(2, rLeftBytes);
if (sLeftBytes.length)
throw new E("invalid signature: left bytes after parsing");
return { r: int.decode(rBytes), s: int.decode(sBytes) };
},
hexFromSig(sig) {
const { _tlv: tlv, _int: int } = DER;
const rs = tlv.encode(2, int.encode(sig.r));
const ss = tlv.encode(2, int.encode(sig.s));
const seq = rs + ss;
return tlv.encode(48, seq);
}
};
var _0n4 = BigInt(0);
var _1n4 = BigInt(1);
var _2n3 = BigInt(2);
var _3n2 = BigInt(3);
var _4n2 = BigInt(4);
function weierstrassPoints(opts) {
const CURVE = validatePointOpts(opts);
const { Fp } = CURVE;
const Fn = Field(CURVE.n, CURVE.nBitLength);
const toBytes2 = CURVE.toBytes || ((_c, point, _isCompressed) => {
const a = point.toAffine();
return concatBytes2(Uint8Array.from([4]), Fp.toBytes(a.x), Fp.toBytes(a.y));
});
const fromBytes = CURVE.fromBytes || ((bytes) => {
const tail = bytes.subarray(1);
const x = Fp.fromBytes(tail.subarray(0, Fp.BYTES));
const y = Fp.fromBytes(tail.subarray(Fp.BYTES, 2 * Fp.BYTES));
return { x, y };
});
function weierstrassEquation(x) {
const { a, b } = CURVE;
const x2 = Fp.sqr(x);
const x3 = Fp.mul(x2, x);
return Fp.add(Fp.add(x3, Fp.mul(x, a)), b);
}
if (!Fp.eql(Fp.sqr(CURVE.Gy), weierstrassEquation(CURVE.Gx)))
throw new Error("bad generator point: equation left != right");
function isWithinCurveOrder(num2) {
return inRange(num2, _1n4, CURVE.n);
}
function normPrivateKeyToScalar(key) {
const { allowedPrivateKeyLengths: lengths, nByteLength, wrapPrivateKey, n: N } = CURVE;
if (lengths && typeof key !== "bigint") {
if (isBytes(key))
key = bytesToHex(key);
if (typeof key !== "string" || !lengths.includes(key.length))
throw new Error("invalid private key");
key = key.padStart(nByteLength * 2, "0");
}
let num2;
try {
num2 = typeof key === "bigint" ? key : bytesToNumberBE(ensureBytes("private key", key, nByteLength));
} catch (error) {
throw new Error("invalid private key, expected hex or " + nByteLength + " bytes, got " + typeof key);
}
if (wrapPrivateKey)
num2 = mod(num2, N);
aInRange("private key", num2, _1n4, N);
return num2;
}
function assertPrjPoint(other) {
if (!(other instanceof Point2))
throw new Error("ProjectivePoint expected");
}
const toAffineMemo = memoized((p, iz) => {
const { px: x, py: y, pz: z } = p;
if (Fp.eql(z, Fp.ONE))
return { x, y };
const is0 = p.is0();
if (iz == null)
iz = is0 ? Fp.ONE : Fp.inv(z);
const ax = Fp.mul(x, iz);
const ay = Fp.mul(y, iz);
const zz = Fp.mul(z, iz);
if (is0)
return { x: Fp.ZERO, y: Fp.ZERO };
if (!Fp.eql(zz, Fp.ONE))
throw new Error("invZ was invalid");
return { x: ax, y: ay };
});
const assertValidMemo = memoized((p) => {
if (p.is0()) {
if (CURVE.allowInfinityPoint && !Fp.is0(p.py))
return;
throw new Error("bad point: ZERO");
}
const { x, y } = p.toAffine();
if (!Fp.isValid(x) || !Fp.isValid(y))
throw new Error("bad point: x or y not FE");
const left = Fp.sqr(y);
const right = weierstrassEquation(x);
if (!Fp.eql(left, right))
throw new Error("bad point: equation left != right");
if (!p.isTorsionFree())
throw new Error("bad point: not in prime-order subgroup");
return true;
});
class Point2 {
constructor(px, py, pz) {
this.px = px;
this.py = py;
this.pz = pz;
if (px == null || !Fp.isValid(px))
throw new Error("x required");
if (py == null || !Fp.isValid(py))
throw new Error("y required");
if (pz == null || !Fp.isValid(pz))
throw new Error("z required");
Object.freeze(this);
}
// Does not validate if the point is on-curve.
// Use fromHex instead, or call assertValidity() later.
static fromAffine(p) {
const { x, y } = p || {};
if (!p || !Fp.isValid(x) || !Fp.isValid(y))
throw new Error("invalid affine point");
if (p instanceof Point2)
throw new Error("projective point not allowed");
const is0 = (i) => Fp.eql(i, Fp.ZERO);
if (is0(x) && is0(y))
return Point2.ZERO;
return new Point2(x, y, Fp.ONE);
}
get x() {
return this.toAffine().x;
}
get y() {
return this.toAffine().y;
}
/**
* Takes a bunch of Projective Points but executes only one
* inversion on all of them. Inversion is very slow operation,
* so this improves performance massively.
* Optimization: converts a list of projective points to a list of identical points with Z=1.
*/
static normalizeZ(points) {
const toInv = Fp.invertBatch(points.map((p) => p.pz));
return points.map((p, i) => p.toAffine(toInv[i])).map(Point2.fromAffine);
}
/**
* Converts hash string or Uint8Array to Point.
* @param hex short/long ECDSA hex
*/
static fromHex(hex) {
const P = Point2.fromAffine(fromBytes(ensureBytes("pointHex", hex)));
P.assertValidity();
return P;
}
// Multiplies generator point by privateKey.
static fromPrivateKey(privateKey) {
return Point2.BASE.multiply(normPrivateKeyToScalar(privateKey));
}
// Multiscalar Multiplication
static msm(points, scalars) {
return pippenger(Point2, Fn, points, scalars);
}
// "Private method", don't use it directly
_setWindowSize(windowSize) {
wnaf.setWindowSize(this, windowSize);
}
// A point on curve is valid if it conforms to equation.
assertValidity() {
assertValidMemo(this);
}
hasEvenY() {
const { y } = this.toAffine();
if (Fp.isOdd)
return !Fp.isOdd(y);
throw new Error("Field doesn't support isOdd");
}
/**
* Compare one point to another.
*/
equals(other) {
assertPrjPoint(other);
const { px: X1, py: Y1, pz: Z1 } = this;
const { px: X2, py: Y2, pz: Z2 } = other;
const U1 = Fp.eql(Fp.mul(X1, Z2), Fp.mul(X2, Z1));
const U2 = Fp.eql(Fp.mul(Y1, Z2), Fp.mul(Y2, Z1));
return U1 && U2;
}
/**
* Flips point to one corresponding to (x, -y) in Affine coordinates.
*/
negate() {
return new Point2(this.px, Fp.neg(this.py), this.pz);
}
// Renes-Costello-Batina exception-free doubling formula.
// There is 30% faster Jacobian formula, but it is not complete.
// https://eprint.iacr.org/2015/1060, algorithm 3
// Cost: 8M + 3S + 3*a + 2*b3 + 15add.
double() {
const { a, b } = CURVE;
const b3 = Fp.mul(b, _3n2);
const { px: X1, py: Y1, pz: Z1 } = this;
let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO;
let t0 = Fp.mul(X1, X1);
let t1 = Fp.mul(Y1, Y1);
let t2 = Fp.mul(Z1, Z1);
let t3 = Fp.mul(X1, Y1);
t3 = Fp.add(t3, t3);
Z3 = Fp.mul(X1, Z1);
Z3 = Fp.add(Z3, Z3);
X3 = Fp.mul(a, Z3);
Y3 = Fp.mul(b3, t2);
Y3 = Fp.add(X3, Y3);
X3 = Fp.sub(t1, Y3);
Y3 = Fp.add(t1, Y3);
Y3 = Fp.mul(X3, Y3);
X3 = Fp.mul(t3, X3);
Z3 = Fp.mul(b3, Z3);
t2 = Fp.mul(a, t2);
t3 = Fp.sub(t0, t2);
t3 = Fp.mul(a, t3);
t3 = Fp.add(t3, Z3);
Z3 = Fp.add(t0, t0);
t0 = Fp.add(Z3, t0);
t0 = Fp.add(t0, t2);
t0 = Fp.mul(t0, t3);
Y3 = Fp.add(Y3, t0);
t2 = Fp.mul(Y1, Z1);
t2 = Fp.add(t2, t2);
t0 = Fp.mul(t2, t3);
X3 = Fp.sub(X3, t0);
Z3 = Fp.mul(t2, t1);
Z3 = Fp.add(Z3, Z3);
Z3 = Fp.add(Z3, Z3);
return new Point2(X3, Y3, Z3);
}
// Renes-Costello-Batina exception-free addition formula.
// There is 30% faster Jacobian formula, but it is not complete.
// https://eprint.iacr.org/2015/1060, algorithm 1
// Cost: 12M + 0S + 3*a + 3*b3 + 23add.
add(other) {
assertPrjPoint(other);
const { px: X1, py: Y1, pz: Z1 } = this;
const { px: X2, py: Y2, pz: Z2 } = other;
let X3 = Fp.ZERO, Y3 = Fp.ZERO, Z3 = Fp.ZERO;
const a = CURVE.a;
const b3 = Fp.mul(CURVE.b, _3n2);
let t0 = Fp.mul(X1, X2);
let t1 = Fp.mul(Y1, Y2);
let t2 = Fp.mul(Z1, Z2);
let t3 = Fp.add(X1, Y1);
let t4 = Fp.add(X2, Y2);
t3 = Fp.mul(t3, t4);
t4 = Fp.add(t0, t1);
t3 = Fp.sub(t3, t4);
t4 = Fp.add(X1, Z1);
let t5 = Fp.add(X2, Z2);
t4 = Fp.mul(t4, t5);
t5 = Fp.add(t0, t2);
t4 = Fp.sub(t4, t5);
t5 = Fp.add(Y1, Z1);
X3 = Fp.add(Y2, Z2);
t5 = Fp.mul(t5, X3);
X3 = Fp.add(t1, t2);
t5 = Fp.sub(t5, X3);
Z3 = Fp.mul(a, t4);
X3 = Fp.mul(b3, t2);
Z3 = Fp.add(X3, Z3);
X3 = Fp.sub(t1, Z3);
Z3 = Fp.add(t1, Z3);
Y3 = Fp.mul(X3, Z3);
t1 = Fp.add(t0, t0);
t1 = Fp.add(t1, t0);
t2 = Fp.mul(a, t2);
t4 = Fp.mul(b3, t4);
t1 = Fp.add(t1, t2);
t2 = Fp.sub(t0, t2);
t2 = Fp.mul(a, t2);
t4 = Fp.add(t4, t2);
t0 = Fp.mul(t1, t4);
Y3 = Fp.add(Y3, t0);
t0 = Fp.mul(t5, t4);
X3 = Fp.mul(t3, X3);
X3 = Fp.sub(X3, t0);
t0 = Fp.mul(t3, t1);
Z3 = Fp.mul(t5, Z3);
Z3 = Fp.add(Z3, t0);
return new Point2(X3, Y3, Z3);
}
subtract(other) {
return this.add(other.negate());
}
is0() {
return this.equals(Point2.ZERO);
}
wNAF(n) {
return wnaf.wNAFCached(this, n, Point2.normalizeZ);
}
/**
* Non-constant-time multiplication. Uses double-and-add algorithm.
* It's faster, but should only be used when you don't care about
* an exposed private key e.g. sig verification, which works over *public* keys.
*/
multiplyUnsafe(sc) {
const { endo, n: N } = CURVE;
aInRange("scalar", sc, _0n4, N);
const I = Point2.ZERO;
if (sc === _0n4)
return I;
if (this.is0() || sc === _1n4)
return this;
if (!endo || wnaf.hasPrecomputes(this))
return wnaf.wNAFCachedUnsafe(this, sc, Point2.normalizeZ);
let { k1neg, k1, k2neg, k2 } = endo.splitScalar(sc);
let k1p = I;
let k2p = I;
let d = this;
while (k1 > _0n4 || k2 > _0n4) {
if (k1 & _1n4)
k1p = k1p.add(d);
if (k2 & _1n4)
k2p = k2p.add(d);
d = d.double();
k1 >>= _1n4;
k2 >>= _1n4;
}
if (k1neg)
k1p = k1p.negate();
if (k2neg)
k2p = k2p.negate();
k2p = new Point2(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz);
return k1p.add(k2p);
}
/**
* Constant time multiplication.
* Uses wNAF method. Windowed method may be 10% faster,
* but takes 2x longer to generate and consumes 2x memory.
* Uses precomputes when available.
* Uses endomorphism for Koblitz curves.
* @param scalar by which the point would be multiplied
* @returns New point
*/
multiply(scalar) {
const { endo, n: N } = CURVE;
aInRange("scalar", scalar, _1n4, N);
let point, fake;
if (endo) {
const { k1neg, k1, k2neg, k2 } = endo.splitScalar(scalar);
let { p: k1p, f: f1p } = this.wNAF(k1);
let { p: k2p, f: f2p } = this.wNAF(k2);
k1p = wnaf.constTimeNegate(k1neg, k1p);
k2p = wnaf.constTimeNegate(k2neg, k2p);
k2p = new Point2(Fp.mul(k2p.px, endo.beta), k2p.py, k2p.pz);
point = k1p.add(k2p);
fake = f1p.add(f2p);
} else {
const { p, f } = this.wNAF(scalar);
point = p;
fake = f;
}
return Point2.normalizeZ([point, fake])[0];
}
/**
* Efficiently calculate `aP + bQ`. Unsafe, can expose private key, if used incorrectly.
* Not using Strauss-Shamir trick: precomputation tables are faster.
* The trick could be useful if both P and Q are not G (not in our case).
* @returns non-zero affine point
*/
multiplyAndAddUnsafe(Q, a, b) {
const G = Point2.BASE;
const mul = (P, a2) => a2 === _0n4 || a2 === _1n4 || !P.equals(G) ? P.multiplyUnsafe(a2) : P.multiply(a2);
const sum = mul(this, a).add(mul(Q, b));
return sum.is0() ? void 0 : sum;
}
// Converts Projective point to affine (x, y) coordinates.
// Can accept precomputed Z^-1 - for example, from invertBatch.
// (x, y, z) ∋ (x=x/z, y=y/z)
toAffine(iz) {
return toAffineMemo(this, iz);
}
isTorsionFree() {
const { h: cofactor, isTorsionFree } = CURVE;
if (cofactor === _1n4)
return true;
if (isTorsionFree)
return isTorsionFree(Point2, this);
throw new Error("isTorsionFree() has not been declared for the elliptic curve");
}
clearCofactor() {
const { h: cofactor, clearCofactor } = CURVE;
if (cofactor === _1n4)
return this;
if (clearCofactor)
return clearCofactor(Point2, this);
return this.multiplyUnsafe(CURVE.h);
}
toRawBytes(isCompressed = true) {
abool("isCompressed", isCompressed);
this.assertValidity();
return toBytes2(Point2, this, isCompressed);
}
toHex(isCompressed = true) {
abool("isCompressed", isCompressed);
return bytesToHex(this.toRawBytes(isCompressed));
}
}
Point2.BASE = new Point2(CURVE.Gx, CURVE.Gy, Fp.ONE);
Point2.ZERO = new Point2(Fp.ZERO, Fp.ONE, Fp.ZERO);
const _bits = CURVE.nBitLength;
const wnaf = wNAF(Point2, CURVE.endo ? Math.ceil(_bits / 2) : _bits);
return {
CURVE,
ProjectivePoint: Point2,
normPrivateKeyToScalar,
weierstrassEquation,
isWithinCurveOrder
};
}
function validateOpts(curve) {
const opts = validateBasic(curve);
valid