@noble/curves 1.6.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/README.md +54 -22
  2. package/_shortw_utils.d.ts.map +1 -1
  3. package/abstract/bls.d.ts +7 -5
  4. package/abstract/bls.d.ts.map +1 -1
  5. package/abstract/bls.js +9 -9
  6. package/abstract/bls.js.map +1 -1
  7. package/abstract/curve.d.ts +29 -6
  8. package/abstract/curve.d.ts.map +1 -1
  9. package/abstract/curve.js +184 -41
  10. package/abstract/curve.js.map +1 -1
  11. package/abstract/edwards.d.ts +2 -0
  12. package/abstract/edwards.d.ts.map +1 -1
  13. package/abstract/edwards.js +20 -9
  14. package/abstract/edwards.js.map +1 -1
  15. package/abstract/hash-to-curve.d.ts.map +1 -1
  16. package/abstract/hash-to-curve.js +3 -4
  17. package/abstract/hash-to-curve.js.map +1 -1
  18. package/abstract/modular.d.ts.map +1 -1
  19. package/abstract/modular.js +32 -21
  20. package/abstract/modular.js.map +1 -1
  21. package/abstract/montgomery.d.ts.map +1 -1
  22. package/abstract/montgomery.js +5 -3
  23. package/abstract/montgomery.js.map +1 -1
  24. package/abstract/poseidon.d.ts.map +1 -1
  25. package/abstract/poseidon.js +22 -22
  26. package/abstract/poseidon.js.map +1 -1
  27. package/abstract/tower.d.ts +1 -0
  28. package/abstract/tower.d.ts.map +1 -1
  29. package/abstract/tower.js +6 -6
  30. package/abstract/tower.js.map +1 -1
  31. package/abstract/utils.d.ts.map +1 -1
  32. package/abstract/utils.js +21 -23
  33. package/abstract/utils.js.map +1 -1
  34. package/abstract/weierstrass.d.ts +1 -0
  35. package/abstract/weierstrass.d.ts.map +1 -1
  36. package/abstract/weierstrass.js +54 -36
  37. package/abstract/weierstrass.js.map +1 -1
  38. package/bls12-381.js +8 -8
  39. package/bn254.d.ts +2 -1
  40. package/bn254.d.ts.map +1 -1
  41. package/bn254.js +9 -7
  42. package/bn254.js.map +1 -1
  43. package/ed448.js +1 -1
  44. package/ed448.js.map +1 -1
  45. package/esm/_shortw_utils.d.ts.map +1 -1
  46. package/esm/abstract/bls.d.ts +7 -5
  47. package/esm/abstract/bls.d.ts.map +1 -1
  48. package/esm/abstract/bls.js +9 -9
  49. package/esm/abstract/bls.js.map +1 -1
  50. package/esm/abstract/curve.d.ts +29 -6
  51. package/esm/abstract/curve.d.ts.map +1 -1
  52. package/esm/abstract/curve.js +183 -41
  53. package/esm/abstract/curve.js.map +1 -1
  54. package/esm/abstract/edwards.d.ts +2 -0
  55. package/esm/abstract/edwards.d.ts.map +1 -1
  56. package/esm/abstract/edwards.js +20 -9
  57. package/esm/abstract/edwards.js.map +1 -1
  58. package/esm/abstract/hash-to-curve.d.ts.map +1 -1
  59. package/esm/abstract/hash-to-curve.js +3 -4
  60. package/esm/abstract/hash-to-curve.js.map +1 -1
  61. package/esm/abstract/modular.d.ts.map +1 -1
  62. package/esm/abstract/modular.js +32 -21
  63. package/esm/abstract/modular.js.map +1 -1
  64. package/esm/abstract/montgomery.d.ts.map +1 -1
  65. package/esm/abstract/montgomery.js +5 -3
  66. package/esm/abstract/montgomery.js.map +1 -1
  67. package/esm/abstract/poseidon.d.ts.map +1 -1
  68. package/esm/abstract/poseidon.js +22 -22
  69. package/esm/abstract/poseidon.js.map +1 -1
  70. package/esm/abstract/tower.d.ts +1 -0
  71. package/esm/abstract/tower.d.ts.map +1 -1
  72. package/esm/abstract/tower.js +6 -6
  73. package/esm/abstract/tower.js.map +1 -1
  74. package/esm/abstract/utils.d.ts.map +1 -1
  75. package/esm/abstract/utils.js +21 -23
  76. package/esm/abstract/utils.js.map +1 -1
  77. package/esm/abstract/weierstrass.d.ts +1 -0
  78. package/esm/abstract/weierstrass.d.ts.map +1 -1
  79. package/esm/abstract/weierstrass.js +54 -36
  80. package/esm/abstract/weierstrass.js.map +1 -1
  81. package/esm/bls12-381.js +8 -8
  82. package/esm/bn254.d.ts +2 -1
  83. package/esm/bn254.d.ts.map +1 -1
  84. package/esm/bn254.js +7 -6
  85. package/esm/bn254.js.map +1 -1
  86. package/esm/ed448.js +1 -1
  87. package/esm/ed448.js.map +1 -1
  88. package/esm/p256.d.ts.map +1 -1
  89. package/esm/p256.js +6 -6
  90. package/esm/p256.js.map +1 -1
  91. package/esm/p384.d.ts.map +1 -1
  92. package/esm/p384.js +6 -6
  93. package/esm/p384.js.map +1 -1
  94. package/esm/p521.d.ts.map +1 -1
  95. package/esm/p521.js +7 -7
  96. package/esm/p521.js.map +1 -1
  97. package/esm/secp256k1.d.ts.map +1 -1
  98. package/esm/secp256k1.js +8 -8
  99. package/esm/secp256k1.js.map +1 -1
  100. package/p256.d.ts.map +1 -1
  101. package/p256.js +6 -6
  102. package/p256.js.map +1 -1
  103. package/p384.d.ts.map +1 -1
  104. package/p384.js +6 -6
  105. package/p384.js.map +1 -1
  106. package/p521.d.ts.map +1 -1
  107. package/p521.js +7 -7
  108. package/p521.js.map +1 -1
  109. package/package.json +4 -3
  110. package/secp256k1.d.ts.map +1 -1
  111. package/secp256k1.js +8 -8
  112. package/secp256k1.js.map +1 -1
  113. package/src/abstract/bls.ts +25 -13
  114. package/src/abstract/curve.ts +188 -39
  115. package/src/abstract/edwards.ts +25 -10
  116. package/src/abstract/hash-to-curve.ts +2 -5
  117. package/src/abstract/modular.ts +29 -19
  118. package/src/abstract/montgomery.ts +5 -3
  119. package/src/abstract/poseidon.ts +20 -24
  120. package/src/abstract/tower.ts +7 -6
  121. package/src/abstract/utils.ts +18 -24
  122. package/src/abstract/weierstrass.ts +57 -35
  123. package/src/bls12-381.ts +9 -9
  124. package/src/bn254.ts +16 -7
  125. package/src/ed448.ts +1 -1
  126. package/src/p256.ts +6 -6
  127. package/src/p384.ts +6 -6
  128. package/src/p521.ts +7 -7
  129. package/src/secp256k1.ts +8 -8
@@ -10,11 +10,11 @@ import {
10
10
  validateObject,
11
11
  } from './utils.js';
12
12
  // prettier-ignore
13
- const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3);
13
+ const _0n = BigInt(0), _1n = BigInt(1), _2n = /* @__PURE__ */ BigInt(2), _3n = /* @__PURE__ */ BigInt(3);
14
14
  // prettier-ignore
15
- const _4n = BigInt(4), _5n = BigInt(5), _8n = BigInt(8);
15
+ const _4n = /* @__PURE__ */ BigInt(4), _5n = /* @__PURE__ */ BigInt(5), _8n = /* @__PURE__ */ BigInt(8);
16
16
  // prettier-ignore
17
- const _9n = BigInt(9), _16n = BigInt(16);
17
+ const _9n =/* @__PURE__ */ BigInt(9), _16n = /* @__PURE__ */ BigInt(16);
18
18
 
19
19
  // Calculates a modulo b
20
20
  export function mod(a: bigint, b: bigint): bigint {
@@ -29,7 +29,8 @@ export function mod(a: bigint, b: bigint): bigint {
29
29
  */
30
30
  // TODO: use field version && remove
31
31
  export function pow(num: bigint, power: bigint, modulo: bigint): bigint {
32
- if (modulo <= _0n || power < _0n) throw new Error('Expected power/modulo > 0');
32
+ if (power < _0n) throw new Error('invalid exponent, negatives unsupported');
33
+ if (modulo <= _0n) throw new Error('invalid modulus');
33
34
  if (modulo === _1n) return _0n;
34
35
  let res = _1n;
35
36
  while (power > _0n) {
@@ -52,9 +53,8 @@ export function pow2(x: bigint, power: bigint, modulo: bigint): bigint {
52
53
 
53
54
  // Inverses number over modulo
54
55
  export function invert(number: bigint, modulo: bigint): bigint {
55
- if (number === _0n || modulo <= _0n) {
56
- throw new Error(`invert: expected positive integers, got n=${number} mod=${modulo}`);
57
- }
56
+ if (number === _0n) throw new Error('invert: expected non-zero number');
57
+ if (modulo <= _0n) throw new Error('invert: expected positive modulus, got ' + modulo);
58
58
  // Euclidean GCD https://brilliant.org/wiki/extended-euclidean-algorithm/
59
59
  // Fermat's little theorem "CT-like" version inv(n) = n^(m-2) mod m is 30x slower.
60
60
  let a = mod(number, modulo);
@@ -97,7 +97,10 @@ export function tonelliShanks(P: bigint) {
97
97
  for (Q = P - _1n, S = 0; Q % _2n === _0n; Q /= _2n, S++);
98
98
 
99
99
  // Step 2: Select a non-square z such that (z | p) ≡ -1 and set c ≡ zq
100
- for (Z = _2n; Z < P && pow(Z, legendreC, P) !== P - _1n; Z++);
100
+ for (Z = _2n; Z < P && pow(Z, legendreC, P) !== P - _1n; Z++) {
101
+ // Crash instead of infinity loop, we cannot reasonable count until P.
102
+ if (Z > 1000) throw new Error('Cannot find square root: likely non-prime P');
103
+ }
101
104
 
102
105
  // Fast-path
103
106
  if (S === 1) {
@@ -273,7 +276,7 @@ export function validateField<T>(field: IField<T>) {
273
276
  export function FpPow<T>(f: IField<T>, num: T, power: bigint): T {
274
277
  // Should have same speed as pow for bigints
275
278
  // TODO: benchmark!
276
- if (power < _0n) throw new Error('Expected power > 0');
279
+ if (power < _0n) throw new Error('invalid exponent, negatives unsupported');
277
280
  if (power === _0n) return f.ONE;
278
281
  if (power === _1n) return num;
279
282
  let p = f.ONE;
@@ -360,10 +363,10 @@ export function Field(
360
363
  isLE = false,
361
364
  redef: Partial<IField<bigint>> = {}
362
365
  ): Readonly<FpField> {
363
- if (ORDER <= _0n) throw new Error(`Expected Field ORDER > 0, got ${ORDER}`);
366
+ if (ORDER <= _0n) throw new Error('invalid field: expected ORDER > 0, got ' + ORDER);
364
367
  const { nBitLength: BITS, nByteLength: BYTES } = nLength(ORDER, bitLen);
365
- if (BYTES > 2048) throw new Error('Field lengths over 2048 bytes are not supported');
366
- const sqrtP = FpSqrt(ORDER);
368
+ if (BYTES > 2048) throw new Error('invalid field: expected ORDER of <= 2048 bytes');
369
+ let sqrtP: ReturnType<typeof FpSqrt>; // cached sqrtP
367
370
  const f: Readonly<FpField> = Object.freeze({
368
371
  ORDER,
369
372
  BITS,
@@ -374,7 +377,7 @@ export function Field(
374
377
  create: (num) => mod(num, ORDER),
375
378
  isValid: (num) => {
376
379
  if (typeof num !== 'bigint')
377
- throw new Error(`Invalid field element: expected bigint, got ${typeof num}`);
380
+ throw new Error('invalid field element: expected bigint, got ' + typeof num);
378
381
  return _0n <= num && num < ORDER; // 0 is valid element, but it's not invertible
379
382
  },
380
383
  is0: (num) => num === _0n,
@@ -396,7 +399,12 @@ export function Field(
396
399
  mulN: (lhs, rhs) => lhs * rhs,
397
400
 
398
401
  inv: (num) => invert(num, ORDER),
399
- sqrt: redef.sqrt || ((n) => sqrtP(f, n)),
402
+ sqrt:
403
+ redef.sqrt ||
404
+ ((n) => {
405
+ if (!sqrtP) sqrtP = FpSqrt(ORDER);
406
+ return sqrtP(f, n);
407
+ }),
400
408
  invertBatch: (lst) => FpInvertBatch(f, lst),
401
409
  // TODO: do we really need constant cmov?
402
410
  // We don't have const-time bigints anyway, so probably will be not very useful
@@ -404,7 +412,7 @@ export function Field(
404
412
  toBytes: (num) => (isLE ? numberToBytesLE(num, BYTES) : numberToBytesBE(num, BYTES)),
405
413
  fromBytes: (bytes) => {
406
414
  if (bytes.length !== BYTES)
407
- throw new Error(`Fp.fromBytes: expected ${BYTES}, got ${bytes.length}`);
415
+ throw new Error('Field.fromBytes: expected ' + BYTES + ' bytes, got ' + bytes.length);
408
416
  return isLE ? bytesToNumberLE(bytes) : bytesToNumberBE(bytes);
409
417
  },
410
418
  } as FpField);
@@ -412,13 +420,13 @@ export function Field(
412
420
  }
413
421
 
414
422
  export function FpSqrtOdd<T>(Fp: IField<T>, elm: T) {
415
- if (!Fp.isOdd) throw new Error(`Field doesn't have isOdd`);
423
+ if (!Fp.isOdd) throw new Error("Field doesn't have isOdd");
416
424
  const root = Fp.sqrt(elm);
417
425
  return Fp.isOdd(root) ? root : Fp.neg(root);
418
426
  }
419
427
 
420
428
  export function FpSqrtEven<T>(Fp: IField<T>, elm: T) {
421
- if (!Fp.isOdd) throw new Error(`Field doesn't have isOdd`);
429
+ if (!Fp.isOdd) throw new Error("Field doesn't have isOdd");
422
430
  const root = Fp.sqrt(elm);
423
431
  return Fp.isOdd(root) ? Fp.neg(root) : root;
424
432
  }
@@ -438,7 +446,9 @@ export function hashToPrivateScalar(
438
446
  const hashLen = hash.length;
439
447
  const minLen = nLength(groupOrder).nByteLength + 8;
440
448
  if (minLen < 24 || hashLen < minLen || hashLen > 1024)
441
- throw new Error(`hashToPrivateScalar: expected ${minLen}-1024 bytes of input, got ${hashLen}`);
449
+ throw new Error(
450
+ 'hashToPrivateScalar: expected ' + minLen + '-1024 bytes of input, got ' + hashLen
451
+ );
442
452
  const num = isLE ? bytesToNumberLE(hash) : bytesToNumberBE(hash);
443
453
  return mod(num, groupOrder - _1n) + _1n;
444
454
  }
@@ -486,7 +496,7 @@ export function mapHashToField(key: Uint8Array, fieldOrder: bigint, isLE = false
486
496
  const minLen = getMinHashLength(fieldOrder);
487
497
  // No small numbers: need to understand bias story. No huge numbers: easier to detect JS timings.
488
498
  if (len < 16 || len < minLen || len > 1024)
489
- throw new Error(`expected ${minLen}-1024 bytes of input, got ${len}`);
499
+ throw new Error('expected ' + minLen + '-1024 bytes of input, got ' + len);
490
500
  const num = isLE ? bytesToNumberBE(key) : bytesToNumberLE(key);
491
501
  // `mod(x, 11)` can sometimes produce 0. `mod(x, 10) + 1` is the same, but no 0
492
502
  const reduced = mod(num, fieldOrder - _1n) + _1n;
@@ -158,8 +158,10 @@ export function montgomery(curveDef: CurveType): CurveFn {
158
158
  function decodeScalar(n: Hex): bigint {
159
159
  const bytes = ensureBytes('scalar', n);
160
160
  const len = bytes.length;
161
- if (len !== montgomeryBytes && len !== fieldLen)
162
- throw new Error(`Expected ${montgomeryBytes} or ${fieldLen} bytes, got ${len}`);
161
+ if (len !== montgomeryBytes && len !== fieldLen) {
162
+ let valid = '' + montgomeryBytes + ' or ' + fieldLen;
163
+ throw new Error('invalid scalar, expected ' + valid + ' bytes, got ' + len);
164
+ }
163
165
  return bytesToNumberLE(adjustScalarBytes(bytes));
164
166
  }
165
167
  function scalarMult(scalar: Hex, u: Hex): Uint8Array {
@@ -168,7 +170,7 @@ export function montgomery(curveDef: CurveType): CurveFn {
168
170
  const pu = montgomeryLadder(pointU, _scalar);
169
171
  // The result was not contributory
170
172
  // https://cr.yp.to/ecdh.html#validate
171
- if (pu === _0n) throw new Error('Invalid private or public key received');
173
+ if (pu === _0n) throw new Error('invalid private or public key received');
172
174
  return encodeUCoordinate(pu);
173
175
  }
174
176
  // Computes public key from private. By doing scalar multiplication of base point.
@@ -21,40 +21,37 @@ export function validateOpts(opts: PoseidonOpts) {
21
21
  validateField(Fp);
22
22
  for (const i of ['t', 'roundsFull', 'roundsPartial'] as const) {
23
23
  if (typeof opts[i] !== 'number' || !Number.isSafeInteger(opts[i]))
24
- throw new Error(`Poseidon: invalid param ${i}=${opts[i]} (${typeof opts[i]})`);
24
+ throw new Error('invalid number ' + i);
25
25
  }
26
26
 
27
27
  // MDS is TxT matrix
28
- if (!Array.isArray(mds) || mds.length !== t) throw new Error('Poseidon: wrong MDS matrix');
28
+ if (!Array.isArray(mds) || mds.length !== t) throw new Error('Poseidon: invalid MDS matrix');
29
29
  const _mds = mds.map((mdsRow) => {
30
30
  if (!Array.isArray(mdsRow) || mdsRow.length !== t)
31
- throw new Error(`Poseidon MDS matrix row: ${mdsRow}`);
31
+ throw new Error('invalid MDS matrix row: ' + mdsRow);
32
32
  return mdsRow.map((i) => {
33
- if (typeof i !== 'bigint') throw new Error(`Poseidon MDS matrix value=${i}`);
33
+ if (typeof i !== 'bigint') throw new Error('invalid MDS matrix bigint: ' + i);
34
34
  return Fp.create(i);
35
35
  });
36
36
  });
37
37
 
38
38
  if (rev !== undefined && typeof rev !== 'boolean')
39
- throw new Error(`Poseidon: invalid param reversePartialPowIdx=${rev}`);
39
+ throw new Error('invalid param reversePartialPowIdx=' + rev);
40
40
 
41
- if (roundsFull % 2 !== 0) throw new Error(`Poseidon roundsFull is not even: ${roundsFull}`);
41
+ if (roundsFull & 1) throw new Error('roundsFull is not even' + roundsFull);
42
42
  const rounds = roundsFull + roundsPartial;
43
43
 
44
44
  if (!Array.isArray(rc) || rc.length !== rounds)
45
- throw new Error('Poseidon: wrong round constants');
45
+ throw new Error('Poseidon: invalid round constants');
46
46
  const roundConstants = rc.map((rc) => {
47
- if (!Array.isArray(rc) || rc.length !== t)
48
- throw new Error(`Poseidon wrong round constants: ${rc}`);
47
+ if (!Array.isArray(rc) || rc.length !== t) throw new Error('invalid round constants');
49
48
  return rc.map((i) => {
50
- if (typeof i !== 'bigint' || !Fp.isValid(i))
51
- throw new Error(`Poseidon wrong round constant=${i}`);
49
+ if (typeof i !== 'bigint' || !Fp.isValid(i)) throw new Error('invalid round constant');
52
50
  return Fp.create(i);
53
51
  });
54
52
  });
55
53
 
56
- if (!sboxPower || ![3, 5, 7].includes(sboxPower))
57
- throw new Error(`Poseidon wrong sboxPower=${sboxPower}`);
54
+ if (!sboxPower || ![3, 5, 7].includes(sboxPower)) throw new Error('invalid sboxPower');
58
55
  const _sboxPower = BigInt(sboxPower);
59
56
  let sboxFn = (n: bigint) => FpPow(Fp, n, _sboxPower);
60
57
  // Unwrapped sbox power for common cases (195->142μs)
@@ -65,8 +62,8 @@ export function validateOpts(opts: PoseidonOpts) {
65
62
  }
66
63
 
67
64
  export function splitConstants(rc: bigint[], t: number) {
68
- if (typeof t !== 'number') throw new Error('poseidonSplitConstants: wrong t');
69
- if (!Array.isArray(rc) || rc.length % t) throw new Error('poseidonSplitConstants: wrong rc');
65
+ if (typeof t !== 'number') throw new Error('poseidonSplitConstants: invalid t');
66
+ if (!Array.isArray(rc) || rc.length % t) throw new Error('poseidonSplitConstants: invalid rc');
70
67
  const res = [];
71
68
  let tmp = [];
72
69
  for (let i = 0; i < rc.length; i++) {
@@ -81,7 +78,7 @@ export function splitConstants(rc: bigint[], t: number) {
81
78
 
82
79
  export function poseidon(opts: PoseidonOpts) {
83
80
  const _opts = validateOpts(opts);
84
- const { Fp, mds, roundConstants, rounds, roundsPartial, sboxFn, t } = _opts;
81
+ const { Fp, mds, roundConstants, rounds: totalRounds, roundsPartial, sboxFn, t } = _opts;
85
82
  const halfRoundsFull = _opts.roundsFull / 2;
86
83
  const partialIdx = _opts.reversePartialPowIdx ? t - 1 : 0;
87
84
  const poseidonRound = (values: bigint[], isFull: boolean, idx: number) => {
@@ -95,21 +92,20 @@ export function poseidon(opts: PoseidonOpts) {
95
92
  };
96
93
  const poseidonHash = function poseidonHash(values: bigint[]) {
97
94
  if (!Array.isArray(values) || values.length !== t)
98
- throw new Error(`Poseidon: wrong values (expected array of bigints with length ${t})`);
95
+ throw new Error('invalid values, expected array of bigints with length ' + t);
99
96
  values = values.map((i) => {
100
- if (typeof i !== 'bigint') throw new Error(`Poseidon: wrong value=${i} (${typeof i})`);
97
+ if (typeof i !== 'bigint') throw new Error('invalid bigint=' + i);
101
98
  return Fp.create(i);
102
99
  });
103
- let round = 0;
100
+ let lastRound = 0;
104
101
  // Apply r_f/2 full rounds.
105
- for (let i = 0; i < halfRoundsFull; i++) values = poseidonRound(values, true, round++);
102
+ for (let i = 0; i < halfRoundsFull; i++) values = poseidonRound(values, true, lastRound++);
106
103
  // Apply r_p partial rounds.
107
- for (let i = 0; i < roundsPartial; i++) values = poseidonRound(values, false, round++);
104
+ for (let i = 0; i < roundsPartial; i++) values = poseidonRound(values, false, lastRound++);
108
105
  // Apply r_f/2 full rounds.
109
- for (let i = 0; i < halfRoundsFull; i++) values = poseidonRound(values, true, round++);
106
+ for (let i = 0; i < halfRoundsFull; i++) values = poseidonRound(values, true, lastRound++);
110
107
 
111
- if (round !== rounds)
112
- throw new Error(`Poseidon: wrong number of rounds: last round=${round}, total=${rounds}`);
108
+ if (lastRound !== totalRounds) throw new Error('invalid number of rounds');
113
109
  return values;
114
110
  };
115
111
  // For verification in tests
@@ -47,6 +47,7 @@ export type Fp12Bls = mod.IField<Fp12> & {
47
47
  mul034(num: Fp12, o0: Fp2, o3: Fp2, o4: Fp2): Fp12;
48
48
  conjugate(num: Fp12): Fp12;
49
49
  finalExponentiate(num: Fp12): Fp12;
50
+ fromBigTwelve(num: BigintTwelve): Fp12;
50
51
  };
51
52
 
52
53
  function calcFrobeniusCoefficients<T>(
@@ -163,7 +164,7 @@ export function tower12(opts: Tower12Opts) {
163
164
  frobeniusMap(num: Fp2, power: number): Fp2;
164
165
  };
165
166
  const Fp2fromBigTuple = (tuple: BigintTuple | bigint[]) => {
166
- if (tuple.length !== 2) throw new Error('Invalid tuple');
167
+ if (tuple.length !== 2) throw new Error('invalid tuple');
167
168
  const fps = tuple.map((n) => Fp.create(n)) as [Fp, Fp];
168
169
  return { c0: fps[0], c1: fps[1] };
169
170
  };
@@ -250,7 +251,7 @@ export function tower12(opts: Tower12Opts) {
250
251
  },
251
252
  // Bytes util
252
253
  fromBytes(b: Uint8Array): Fp2 {
253
- if (b.length !== Fp2.BYTES) throw new Error(`fromBytes wrong length=${b.length}`);
254
+ if (b.length !== Fp2.BYTES) throw new Error('fromBytes invalid length=' + b.length);
254
255
  return { c0: Fp.fromBytes(b.subarray(0, Fp.BYTES)), c1: Fp.fromBytes(b.subarray(Fp.BYTES)) };
255
256
  },
256
257
  toBytes: ({ c0, c1 }) => concatBytes(Fp.toBytes(c0), Fp.toBytes(c1)),
@@ -378,7 +379,7 @@ export function tower12(opts: Tower12Opts) {
378
379
  },
379
380
  // Bytes utils
380
381
  fromBytes: (b: Uint8Array): Fp6 => {
381
- if (b.length !== Fp6.BYTES) throw new Error(`fromBytes wrong length=${b.length}`);
382
+ if (b.length !== Fp6.BYTES) throw new Error('fromBytes invalid length=' + b.length);
382
383
  return {
383
384
  c0: Fp2.fromBytes(b.subarray(0, Fp2.BYTES)),
384
385
  c1: Fp2.fromBytes(b.subarray(Fp2.BYTES, 2 * Fp2.BYTES)),
@@ -393,7 +394,7 @@ export function tower12(opts: Tower12Opts) {
393
394
  c2: Fp2.cmov(c2, r2, c),
394
395
  }),
395
396
  fromBigSix: (t: BigintSix): Fp6 => {
396
- if (!Array.isArray(t) || t.length !== 6) throw new Error('Invalid Fp6 usage');
397
+ if (!Array.isArray(t) || t.length !== 6) throw new Error('invalid Fp6 usage');
397
398
  return {
398
399
  c0: Fp2.fromBigTuple(t.slice(0, 2)),
399
400
  c1: Fp2.fromBigTuple(t.slice(2, 4)),
@@ -526,7 +527,7 @@ export function tower12(opts: Tower12Opts) {
526
527
 
527
528
  // Bytes utils
528
529
  fromBytes: (b: Uint8Array): Fp12 => {
529
- if (b.length !== Fp12.BYTES) throw new Error(`fromBytes wrong length=${b.length}`);
530
+ if (b.length !== Fp12.BYTES) throw new Error('fromBytes invalid length=' + b.length);
530
531
  return {
531
532
  c0: Fp6.fromBytes(b.subarray(0, Fp6.BYTES)),
532
533
  c1: Fp6.fromBytes(b.subarray(Fp6.BYTES)),
@@ -539,7 +540,7 @@ export function tower12(opts: Tower12Opts) {
539
540
  }),
540
541
  // Utils
541
542
  // toString() {
542
- // return `Fp12(${this.c0} + ${this.c1} * w)`;
543
+ // return '' + 'Fp12(' + this.c0 + this.c1 + '* w');
543
544
  // },
544
545
  // fromTuple(c: [Fp6, Fp6]) {
545
546
  // return new Fp12(...c);
@@ -17,10 +17,7 @@ export type CHash = {
17
17
  export type FHash = (message: Uint8Array | string) => Uint8Array;
18
18
 
19
19
  export function isBytes(a: unknown): a is Uint8Array {
20
- return (
21
- a instanceof Uint8Array ||
22
- (a != null && typeof a === 'object' && a.constructor.name === 'Uint8Array')
23
- );
20
+ return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array');
24
21
  }
25
22
 
26
23
  export function abytes(item: unknown): void {
@@ -28,8 +25,7 @@ export function abytes(item: unknown): void {
28
25
  }
29
26
 
30
27
  export function abool(title: string, value: boolean): void {
31
- if (typeof value !== 'boolean')
32
- throw new Error(`${title} must be valid boolean, got "${value}".`);
28
+ if (typeof value !== 'boolean') throw new Error(title + ' boolean expected, got ' + value);
33
29
  }
34
30
 
35
31
  // Array where index 0xf0 (240) is mapped to string 'f0'
@@ -51,21 +47,20 @@ export function bytesToHex(bytes: Uint8Array): string {
51
47
 
52
48
  export function numberToHexUnpadded(num: number | bigint): string {
53
49
  const hex = num.toString(16);
54
- return hex.length & 1 ? `0${hex}` : hex;
50
+ return hex.length & 1 ? '0' + hex : hex;
55
51
  }
56
52
 
57
53
  export function hexToNumber(hex: string): bigint {
58
54
  if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex);
59
- // Big Endian
60
- return BigInt(hex === '' ? '0' : `0x${hex}`);
55
+ return hex === '' ? _0n : BigInt('0x' + hex); // Big Endian
61
56
  }
62
57
 
63
58
  // We use optimized technique to convert hex string to byte array
64
- const asciis = { _0: 48, _9: 57, _A: 65, _F: 70, _a: 97, _f: 102 } as const;
65
- function asciiToBase16(char: number): number | undefined {
66
- if (char >= asciis._0 && char <= asciis._9) return char - asciis._0;
67
- if (char >= asciis._A && char <= asciis._F) return char - (asciis._A - 10);
68
- if (char >= asciis._a && char <= asciis._f) return char - (asciis._a - 10);
59
+ const asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 } as const;
60
+ function asciiToBase16(ch: number): number | undefined {
61
+ if (ch >= asciis._0 && ch <= asciis._9) return ch - asciis._0; // '2' => 50-48
62
+ if (ch >= asciis.A && ch <= asciis.F) return ch - (asciis.A - 10); // 'B' => 66-(65-10)
63
+ if (ch >= asciis.a && ch <= asciis.f) return ch - (asciis.a - 10); // 'b' => 98-(97-10)
69
64
  return;
70
65
  }
71
66
 
@@ -76,7 +71,7 @@ export function hexToBytes(hex: string): Uint8Array {
76
71
  if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex);
77
72
  const hl = hex.length;
78
73
  const al = hl / 2;
79
- if (hl % 2) throw new Error('padded hex string expected, got unpadded hex of length ' + hl);
74
+ if (hl % 2) throw new Error('hex string expected, got unpadded hex of length ' + hl);
80
75
  const array = new Uint8Array(al);
81
76
  for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {
82
77
  const n1 = asciiToBase16(hex.charCodeAt(hi));
@@ -85,7 +80,7 @@ export function hexToBytes(hex: string): Uint8Array {
85
80
  const char = hex[hi] + hex[hi + 1];
86
81
  throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi);
87
82
  }
88
- array[ai] = n1 * 16 + n2;
83
+ array[ai] = n1 * 16 + n2; // multiply first octet, e.g. 'a3' => 10*16+3 => 160 + 3 => 163
89
84
  }
90
85
  return array;
91
86
  }
@@ -125,18 +120,18 @@ export function ensureBytes(title: string, hex: Hex, expectedLength?: number): U
125
120
  try {
126
121
  res = hexToBytes(hex);
127
122
  } catch (e) {
128
- throw new Error(`${title} must be valid hex string, got "${hex}". Cause: ${e}`);
123
+ throw new Error(title + ' must be hex string or Uint8Array, cause: ' + e);
129
124
  }
130
125
  } else if (isBytes(hex)) {
131
126
  // Uint8Array.from() instead of hash.slice() because node.js Buffer
132
127
  // is instance of Uint8Array, and its slice() creates **mutable** copy
133
128
  res = Uint8Array.from(hex);
134
129
  } else {
135
- throw new Error(`${title} must be hex string or Uint8Array`);
130
+ throw new Error(title + ' must be hex string or Uint8Array');
136
131
  }
137
132
  const len = res.length;
138
133
  if (typeof expectedLength === 'number' && len !== expectedLength)
139
- throw new Error(`${title} expected ${expectedLength} bytes, got ${len}`);
134
+ throw new Error(title + ' of length ' + expectedLength + ' expected, got ' + len);
140
135
  return res;
141
136
  }
142
137
 
@@ -175,7 +170,7 @@ declare const TextEncoder: any;
175
170
  * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99])
176
171
  */
177
172
  export function utf8ToBytes(str: string): Uint8Array {
178
- if (typeof str !== 'string') throw new Error(`utf8ToBytes expected string, got ${typeof str}`);
173
+ if (typeof str !== 'string') throw new Error('string expected');
179
174
  return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809
180
175
  }
181
176
 
@@ -198,7 +193,7 @@ export function aInRange(title: string, n: bigint, min: bigint, max: bigint) {
198
193
  // - b would commonly require subtraction: `inRange('x', x, 0n, P - 1n)`
199
194
  // - our way is the cleanest: `inRange('x', x, 0n, P)
200
195
  if (!inRange(n, min, max))
201
- throw new Error(`expected valid ${title}: ${min} <= n < ${max}, got ${typeof n} ${n}`);
196
+ throw new Error('expected valid ' + title + ': ' + min + ' <= n < ' + max + ', got ' + n);
202
197
  }
203
198
 
204
199
  // Bit operations
@@ -321,14 +316,13 @@ export function validateObject<T extends Record<string, any>>(
321
316
  ) {
322
317
  const checkField = (fieldName: keyof T, type: Validator, isOptional: boolean) => {
323
318
  const checkVal = validatorFns[type];
324
- if (typeof checkVal !== 'function')
325
- throw new Error(`Invalid validator "${type}", expected function`);
319
+ if (typeof checkVal !== 'function') throw new Error('invalid validator function');
326
320
 
327
321
  const val = object[fieldName as keyof typeof object];
328
322
  if (isOptional && val === undefined) return;
329
323
  if (!checkVal(val, object)) {
330
324
  throw new Error(
331
- `Invalid param ${String(fieldName)}=${val} (${typeof val}), expected ${type}`
325
+ 'param ' + String(fieldName) + ' is invalid. Expected ' + type + ', got ' + val
332
326
  );
333
327
  }
334
328
  };