@waku/discovery 0.0.7-b6339f7.0 → 0.0.7-c41b319.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.
package/bundle/index.js
CHANGED
@@ -23,7 +23,7 @@ const peerDiscoverySymbol = Symbol.for('@libp2p/peer-discovery');
|
|
23
23
|
* All PeerId implementations must use this symbol as the name of a property
|
24
24
|
* with a boolean `true` value
|
25
25
|
*/
|
26
|
-
const peerIdSymbol
|
26
|
+
const peerIdSymbol = Symbol.for('@libp2p/peer-id');
|
27
27
|
|
28
28
|
/**
|
29
29
|
* When this error is thrown it means an operation was aborted,
|
@@ -33,13 +33,23 @@ const peerIdSymbol$1 = Symbol.for('@libp2p/peer-id');
|
|
33
33
|
/**
|
34
34
|
* Thrown when invalid parameters are passed to a function or method call
|
35
35
|
*/
|
36
|
-
|
36
|
+
class InvalidParametersError extends Error {
|
37
37
|
static name = 'InvalidParametersError';
|
38
38
|
constructor(message = 'Invalid parameters') {
|
39
39
|
super(message);
|
40
40
|
this.name = 'InvalidParametersError';
|
41
41
|
}
|
42
|
-
}
|
42
|
+
}
|
43
|
+
/**
|
44
|
+
* Thrown when a public key is invalid
|
45
|
+
*/
|
46
|
+
class InvalidPublicKeyError extends Error {
|
47
|
+
static name = 'InvalidPublicKeyError';
|
48
|
+
constructor(message = 'Invalid public key') {
|
49
|
+
super(message);
|
50
|
+
this.name = 'InvalidPublicKeyError';
|
51
|
+
}
|
52
|
+
}
|
43
53
|
/**
|
44
54
|
* Thrown when an invalid multihash is encountered
|
45
55
|
*/
|
@@ -50,11 +60,25 @@ class InvalidMultihashError extends Error {
|
|
50
60
|
this.name = 'InvalidMultihashError';
|
51
61
|
}
|
52
62
|
}
|
63
|
+
/**
|
64
|
+
* Thrown when and attempt to operate on an unsupported key was made
|
65
|
+
*/
|
66
|
+
class UnsupportedKeyTypeError extends Error {
|
67
|
+
static name = 'UnsupportedKeyTypeError';
|
68
|
+
constructor(message = 'Unsupported key type') {
|
69
|
+
super(message);
|
70
|
+
this.name = 'UnsupportedKeyTypeError';
|
71
|
+
}
|
72
|
+
}
|
53
73
|
|
54
|
-
/**
|
74
|
+
/**
|
75
|
+
* Noop for browser compatibility
|
76
|
+
*/
|
55
77
|
function setMaxListeners$1() { }
|
56
78
|
|
57
|
-
|
79
|
+
/**
|
80
|
+
* Create a setMaxListeners that doesn't break browser usage
|
81
|
+
*/
|
58
82
|
const setMaxListeners = (n, ...eventTargets) => {
|
59
83
|
try {
|
60
84
|
setMaxListeners$1(n, ...eventTargets);
|
@@ -235,6 +259,10 @@ var EConnectionStateEvents;
|
|
235
259
|
|
236
260
|
const DNS_DISCOVERY_TAG = "@waku/bootstrap";
|
237
261
|
|
262
|
+
var HealthStatusChangeEvents;
|
263
|
+
(function (HealthStatusChangeEvents) {
|
264
|
+
HealthStatusChangeEvents["StatusChange"] = "health:change";
|
265
|
+
})(HealthStatusChangeEvents || (HealthStatusChangeEvents = {}));
|
238
266
|
var HealthStatus;
|
239
267
|
(function (HealthStatus) {
|
240
268
|
HealthStatus["Unhealthy"] = "Unhealthy";
|
@@ -246,43 +274,55 @@ function isDefined(value) {
|
|
246
274
|
return Boolean(value);
|
247
275
|
}
|
248
276
|
|
249
|
-
|
277
|
+
/**
|
278
|
+
* Internal assertion helpers.
|
279
|
+
* @module
|
280
|
+
*/
|
281
|
+
/** Asserts something is positive integer. */
|
282
|
+
function anumber(n) {
|
250
283
|
if (!Number.isSafeInteger(n) || n < 0)
|
251
|
-
throw new Error(
|
284
|
+
throw new Error('positive integer expected, got ' + n);
|
252
285
|
}
|
253
|
-
|
286
|
+
/** Is number an Uint8Array? Copied from utils for perf. */
|
254
287
|
function isBytes$2(a) {
|
255
|
-
return
|
256
|
-
(a != null && typeof a === 'object' && a.constructor.name === 'Uint8Array'));
|
288
|
+
return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array');
|
257
289
|
}
|
258
|
-
|
290
|
+
/** Asserts something is Uint8Array. */
|
291
|
+
function abytes$1(b, ...lengths) {
|
259
292
|
if (!isBytes$2(b))
|
260
293
|
throw new Error('Uint8Array expected');
|
261
294
|
if (lengths.length > 0 && !lengths.includes(b.length))
|
262
|
-
throw new Error(
|
295
|
+
throw new Error('Uint8Array expected of length ' + lengths + ', got length=' + b.length);
|
263
296
|
}
|
264
|
-
|
297
|
+
/** Asserts something is hash */
|
298
|
+
function ahash(h) {
|
265
299
|
if (typeof h !== 'function' || typeof h.create !== 'function')
|
266
300
|
throw new Error('Hash should be wrapped by utils.wrapConstructor');
|
267
|
-
|
268
|
-
|
301
|
+
anumber(h.outputLen);
|
302
|
+
anumber(h.blockLen);
|
269
303
|
}
|
270
|
-
|
304
|
+
/** Asserts a hash instance has not been destroyed / finished */
|
305
|
+
function aexists(instance, checkFinished = true) {
|
271
306
|
if (instance.destroyed)
|
272
307
|
throw new Error('Hash instance has been destroyed');
|
273
308
|
if (checkFinished && instance.finished)
|
274
309
|
throw new Error('Hash#digest() has already been called');
|
275
310
|
}
|
276
|
-
|
277
|
-
|
311
|
+
/** Asserts output is properly-sized byte array */
|
312
|
+
function aoutput(out, instance) {
|
313
|
+
abytes$1(out);
|
278
314
|
const min = instance.outputLen;
|
279
315
|
if (out.length < min) {
|
280
|
-
throw new Error(
|
316
|
+
throw new Error('digestInto() expects output buffer of length at least ' + min);
|
281
317
|
}
|
282
318
|
}
|
283
319
|
|
284
320
|
const crypto$2 = typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined;
|
285
321
|
|
322
|
+
/**
|
323
|
+
* Utilities for hex, bytes, CSPRNG.
|
324
|
+
* @module
|
325
|
+
*/
|
286
326
|
/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
287
327
|
// We use WebCrypto aka globalThis.crypto, which exists in browsers and node.js 16+.
|
288
328
|
// node.js versions earlier than v19 don't declare it in global scope.
|
@@ -291,16 +331,20 @@ const crypto$2 = typeof globalThis === 'object' && 'crypto' in globalThis ? glob
|
|
291
331
|
// Makes the utils un-importable in browsers without a bundler.
|
292
332
|
// Once node.js 18 is deprecated (2025-04-30), we can just drop the import.
|
293
333
|
// Cast array to view
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
334
|
+
function createView(arr) {
|
335
|
+
return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
|
336
|
+
}
|
337
|
+
/** The rotate right (circular right shift) operation for uint32 */
|
338
|
+
function rotr(word, shift) {
|
339
|
+
return (word << (32 - shift)) | (word >>> shift);
|
340
|
+
}
|
298
341
|
/**
|
342
|
+
* Convert JS string to byte array.
|
299
343
|
* @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99])
|
300
344
|
*/
|
301
345
|
function utf8ToBytes$2(str) {
|
302
346
|
if (typeof str !== 'string')
|
303
|
-
throw new Error(
|
347
|
+
throw new Error('utf8ToBytes expected string, got ' + typeof str);
|
304
348
|
return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809
|
305
349
|
}
|
306
350
|
/**
|
@@ -311,7 +355,7 @@ function utf8ToBytes$2(str) {
|
|
311
355
|
function toBytes$1(data) {
|
312
356
|
if (typeof data === 'string')
|
313
357
|
data = utf8ToBytes$2(data);
|
314
|
-
|
358
|
+
abytes$1(data);
|
315
359
|
return data;
|
316
360
|
}
|
317
361
|
/**
|
@@ -321,7 +365,7 @@ function concatBytes$2(...arrays) {
|
|
321
365
|
let sum = 0;
|
322
366
|
for (let i = 0; i < arrays.length; i++) {
|
323
367
|
const a = arrays[i];
|
324
|
-
|
368
|
+
abytes$1(a);
|
325
369
|
sum += a.length;
|
326
370
|
}
|
327
371
|
const res = new Uint8Array(sum);
|
@@ -332,13 +376,14 @@ function concatBytes$2(...arrays) {
|
|
332
376
|
}
|
333
377
|
return res;
|
334
378
|
}
|
335
|
-
|
379
|
+
/** For runtime check if class implements interface */
|
336
380
|
class Hash {
|
337
381
|
// Safe version that clones internal state
|
338
382
|
clone() {
|
339
383
|
return this._cloneInto();
|
340
384
|
}
|
341
385
|
}
|
386
|
+
/** Wraps hash function, creating an interface on top of it */
|
342
387
|
function wrapConstructor(hashCons) {
|
343
388
|
const hashC = (msg) => hashCons().update(toBytes$1(msg)).digest();
|
344
389
|
const tmp = hashCons();
|
@@ -347,9 +392,7 @@ function wrapConstructor(hashCons) {
|
|
347
392
|
hashC.create = () => hashCons();
|
348
393
|
return hashC;
|
349
394
|
}
|
350
|
-
/**
|
351
|
-
* Secure PRNG. Uses `crypto.getRandomValues`, which defers to OS.
|
352
|
-
*/
|
395
|
+
/** Cryptographically secure PRNG. Uses internal OS-level `crypto.getRandomValues`. */
|
353
396
|
function randomBytes(bytesLength = 32) {
|
354
397
|
if (crypto$2 && typeof crypto$2.getRandomValues === 'function') {
|
355
398
|
return crypto$2.getRandomValues(new Uint8Array(bytesLength));
|
@@ -362,8 +405,10 @@ function randomBytes(bytesLength = 32) {
|
|
362
405
|
}
|
363
406
|
|
364
407
|
/**
|
365
|
-
*
|
408
|
+
* Internal Merkle-Damgard hash utils.
|
409
|
+
* @module
|
366
410
|
*/
|
411
|
+
/** Polyfill for Safari 14. https://caniuse.com/mdn-javascript_builtins_dataview_setbiguint64 */
|
367
412
|
function setBigUint64(view, byteOffset, value, isLE) {
|
368
413
|
if (typeof view.setBigUint64 === 'function')
|
369
414
|
return view.setBigUint64(byteOffset, value, isLE);
|
@@ -376,14 +421,14 @@ function setBigUint64(view, byteOffset, value, isLE) {
|
|
376
421
|
view.setUint32(byteOffset + h, wh, isLE);
|
377
422
|
view.setUint32(byteOffset + l, wl, isLE);
|
378
423
|
}
|
379
|
-
/**
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
/**
|
384
|
-
|
385
|
-
|
386
|
-
|
424
|
+
/** Choice: a ? b : c */
|
425
|
+
function Chi(a, b, c) {
|
426
|
+
return (a & b) ^ (~a & c);
|
427
|
+
}
|
428
|
+
/** Majority function, true if any two inputs is true. */
|
429
|
+
function Maj(a, b, c) {
|
430
|
+
return (a & b) ^ (a & c) ^ (b & c);
|
431
|
+
}
|
387
432
|
/**
|
388
433
|
* Merkle-Damgard hash construction base class.
|
389
434
|
* Could be used to create MD5, RIPEMD, SHA1, SHA2.
|
@@ -403,7 +448,7 @@ class HashMD extends Hash {
|
|
403
448
|
this.view = createView(this.buffer);
|
404
449
|
}
|
405
450
|
update(data) {
|
406
|
-
|
451
|
+
aexists(this);
|
407
452
|
const { view, buffer, blockLen } = this;
|
408
453
|
data = toBytes$1(data);
|
409
454
|
const len = data.length;
|
@@ -429,8 +474,8 @@ class HashMD extends Hash {
|
|
429
474
|
return this;
|
430
475
|
}
|
431
476
|
digestInto(out) {
|
432
|
-
|
433
|
-
|
477
|
+
aexists(this);
|
478
|
+
aoutput(out, this);
|
434
479
|
this.finished = true;
|
435
480
|
// Padding
|
436
481
|
// We can avoid allocation of buffer for padding completely if it
|
@@ -487,10 +532,16 @@ class HashMD extends Hash {
|
|
487
532
|
}
|
488
533
|
}
|
489
534
|
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
535
|
+
/**
|
536
|
+
* SHA2-256 a.k.a. sha256. In JS, it is the fastest hash, even faster than Blake3.
|
537
|
+
*
|
538
|
+
* To break sha256 using birthday attack, attackers need to try 2^128 hashes.
|
539
|
+
* BTC network is doing 2^70 hashes/sec (2^95 hashes/year) as per 2025.
|
540
|
+
*
|
541
|
+
* Check out [FIPS 180-4](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf).
|
542
|
+
* @module
|
543
|
+
*/
|
544
|
+
/** Round constants: first 32 bits of fractional parts of the cube roots of the first 64 primes 2..311). */
|
494
545
|
// prettier-ignore
|
495
546
|
const SHA256_K = /* @__PURE__ */ new Uint32Array([
|
496
547
|
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
@@ -502,14 +553,15 @@ const SHA256_K = /* @__PURE__ */ new Uint32Array([
|
|
502
553
|
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
503
554
|
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
504
555
|
]);
|
505
|
-
|
506
|
-
// first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19
|
556
|
+
/** Initial state: first 32 bits of fractional parts of the square roots of the first 8 primes 2..19. */
|
507
557
|
// prettier-ignore
|
508
558
|
const SHA256_IV = /* @__PURE__ */ new Uint32Array([
|
509
559
|
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
|
510
560
|
]);
|
511
|
-
|
512
|
-
|
561
|
+
/**
|
562
|
+
* Temporary buffer, not used to store anything between runs.
|
563
|
+
* Named this way because it matches specification.
|
564
|
+
*/
|
513
565
|
const SHA256_W = /* @__PURE__ */ new Uint32Array(64);
|
514
566
|
class SHA256 extends HashMD {
|
515
567
|
constructor() {
|
@@ -586,10 +638,7 @@ class SHA256 extends HashMD {
|
|
586
638
|
this.buffer.fill(0);
|
587
639
|
}
|
588
640
|
}
|
589
|
-
/**
|
590
|
-
* SHA2-256 hash function
|
591
|
-
* @param message - data that would be hashed
|
592
|
-
*/
|
641
|
+
/** SHA2-256 hash function */
|
593
642
|
const sha256$1 = /* @__PURE__ */ wrapConstructor(() => new SHA256());
|
594
643
|
|
595
644
|
function equals$2(aa, bb) {
|
@@ -1241,7 +1290,7 @@ new TextDecoder();
|
|
1241
1290
|
|
1242
1291
|
/* eslint-disable */
|
1243
1292
|
var encode_1 = encode$7;
|
1244
|
-
var MSB$1 = 0x80,
|
1293
|
+
var MSB$1 = 0x80, MSBALL = -128, INT = Math.pow(2, 31);
|
1245
1294
|
/**
|
1246
1295
|
* @param {number} num
|
1247
1296
|
* @param {number[]} out
|
@@ -1265,7 +1314,7 @@ function encode$7(num, out, offset) {
|
|
1265
1314
|
return out;
|
1266
1315
|
}
|
1267
1316
|
var decode$8 = read$1;
|
1268
|
-
var MSB$1$1 = 0x80, REST$1
|
1317
|
+
var MSB$1$1 = 0x80, REST$1 = 0x7F;
|
1269
1318
|
/**
|
1270
1319
|
* @param {string | any[]} buf
|
1271
1320
|
* @param {number} offset
|
@@ -1280,8 +1329,8 @@ function read$1(buf, offset) {
|
|
1280
1329
|
}
|
1281
1330
|
b = buf[counter++];
|
1282
1331
|
res += shift < 28
|
1283
|
-
? (b & REST$1
|
1284
|
-
: (b & REST$1
|
1332
|
+
? (b & REST$1) << shift
|
1333
|
+
: (b & REST$1) * Math.pow(2, shift);
|
1285
1334
|
shift += 7;
|
1286
1335
|
} while (b >= MSB$1$1);
|
1287
1336
|
// @ts-ignore
|
@@ -2326,24 +2375,62 @@ function setup(env) {
|
|
2326
2375
|
createDebug.names = [];
|
2327
2376
|
createDebug.skips = [];
|
2328
2377
|
|
2329
|
-
|
2330
|
-
|
2331
|
-
|
2378
|
+
const split = (typeof namespaces === 'string' ? namespaces : '')
|
2379
|
+
.trim()
|
2380
|
+
.replace(' ', ',')
|
2381
|
+
.split(',')
|
2382
|
+
.filter(Boolean);
|
2332
2383
|
|
2333
|
-
for (
|
2334
|
-
if (
|
2335
|
-
|
2336
|
-
|
2384
|
+
for (const ns of split) {
|
2385
|
+
if (ns[0] === '-') {
|
2386
|
+
createDebug.skips.push(ns.slice(1));
|
2387
|
+
} else {
|
2388
|
+
createDebug.names.push(ns);
|
2337
2389
|
}
|
2390
|
+
}
|
2391
|
+
}
|
2338
2392
|
|
2339
|
-
|
2340
|
-
|
2341
|
-
|
2342
|
-
|
2393
|
+
/**
|
2394
|
+
* Checks if the given string matches a namespace template, honoring
|
2395
|
+
* asterisks as wildcards.
|
2396
|
+
*
|
2397
|
+
* @param {String} search
|
2398
|
+
* @param {String} template
|
2399
|
+
* @return {Boolean}
|
2400
|
+
*/
|
2401
|
+
function matchesTemplate(search, template) {
|
2402
|
+
let searchIndex = 0;
|
2403
|
+
let templateIndex = 0;
|
2404
|
+
let starIndex = -1;
|
2405
|
+
let matchIndex = 0;
|
2406
|
+
|
2407
|
+
while (searchIndex < search.length) {
|
2408
|
+
if (templateIndex < template.length && (template[templateIndex] === search[searchIndex] || template[templateIndex] === '*')) {
|
2409
|
+
// Match character or proceed with wildcard
|
2410
|
+
if (template[templateIndex] === '*') {
|
2411
|
+
starIndex = templateIndex;
|
2412
|
+
matchIndex = searchIndex;
|
2413
|
+
templateIndex++; // Skip the '*'
|
2414
|
+
} else {
|
2415
|
+
searchIndex++;
|
2416
|
+
templateIndex++;
|
2417
|
+
}
|
2418
|
+
} else if (starIndex !== -1) { // eslint-disable-line no-negated-condition
|
2419
|
+
// Backtrack to the last '*' and try to match more characters
|
2420
|
+
templateIndex = starIndex + 1;
|
2421
|
+
matchIndex++;
|
2422
|
+
searchIndex = matchIndex;
|
2343
2423
|
} else {
|
2344
|
-
|
2424
|
+
return false; // No match
|
2345
2425
|
}
|
2346
2426
|
}
|
2427
|
+
|
2428
|
+
// Handle trailing '*' in template
|
2429
|
+
while (templateIndex < template.length && template[templateIndex] === '*') {
|
2430
|
+
templateIndex++;
|
2431
|
+
}
|
2432
|
+
|
2433
|
+
return templateIndex === template.length;
|
2347
2434
|
}
|
2348
2435
|
|
2349
2436
|
/**
|
@@ -2354,8 +2441,8 @@ function setup(env) {
|
|
2354
2441
|
*/
|
2355
2442
|
function disable() {
|
2356
2443
|
const namespaces = [
|
2357
|
-
...createDebug.names
|
2358
|
-
...createDebug.skips.map(
|
2444
|
+
...createDebug.names,
|
2445
|
+
...createDebug.skips.map(namespace => '-' + namespace)
|
2359
2446
|
].join(',');
|
2360
2447
|
createDebug.enable('');
|
2361
2448
|
return namespaces;
|
@@ -2369,21 +2456,14 @@ function setup(env) {
|
|
2369
2456
|
* @api public
|
2370
2457
|
*/
|
2371
2458
|
function enabled(name) {
|
2372
|
-
|
2373
|
-
|
2374
|
-
}
|
2375
|
-
|
2376
|
-
let i;
|
2377
|
-
let len;
|
2378
|
-
|
2379
|
-
for (i = 0, len = createDebug.skips.length; i < len; i++) {
|
2380
|
-
if (createDebug.skips[i].test(name)) {
|
2459
|
+
for (const skip of createDebug.skips) {
|
2460
|
+
if (matchesTemplate(name, skip)) {
|
2381
2461
|
return false;
|
2382
2462
|
}
|
2383
2463
|
}
|
2384
2464
|
|
2385
|
-
for (
|
2386
|
-
if (
|
2465
|
+
for (const ns of createDebug.names) {
|
2466
|
+
if (matchesTemplate(name, ns)) {
|
2387
2467
|
return true;
|
2388
2468
|
}
|
2389
2469
|
}
|
@@ -2391,19 +2471,6 @@ function setup(env) {
|
|
2391
2471
|
return false;
|
2392
2472
|
}
|
2393
2473
|
|
2394
|
-
/**
|
2395
|
-
* Convert regexp to namespace
|
2396
|
-
*
|
2397
|
-
* @param {RegExp} regxep
|
2398
|
-
* @return {String} namespace
|
2399
|
-
* @api private
|
2400
|
-
*/
|
2401
|
-
function toNamespace(regexp) {
|
2402
|
-
return regexp.toString()
|
2403
|
-
.substring(2, regexp.toString().length - 2)
|
2404
|
-
.replace(/\.\*\?$/, '*');
|
2405
|
-
}
|
2406
|
-
|
2407
2474
|
/**
|
2408
2475
|
* Coerce `val`.
|
2409
2476
|
*
|
@@ -2565,6 +2632,7 @@ var common = setup;
|
|
2565
2632
|
|
2566
2633
|
// Is webkit? http://stackoverflow.com/a/16459606/376773
|
2567
2634
|
// document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
|
2635
|
+
// eslint-disable-next-line no-return-assign
|
2568
2636
|
return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
|
2569
2637
|
// Is firebug? http://stackoverflow.com/a/398120/376773
|
2570
2638
|
(typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
|
@@ -3005,10 +3073,10 @@ class JacobianPoint {
|
|
3005
3073
|
const cond1 = window % 2 !== 0;
|
3006
3074
|
const cond2 = wbits < 0;
|
3007
3075
|
if (wbits === 0) {
|
3008
|
-
f = f.add(constTimeNegate(cond1, precomputes[offset1]));
|
3076
|
+
f = f.add(constTimeNegate$1(cond1, precomputes[offset1]));
|
3009
3077
|
}
|
3010
3078
|
else {
|
3011
|
-
p = p.add(constTimeNegate(cond2, precomputes[offset2]));
|
3079
|
+
p = p.add(constTimeNegate$1(cond2, precomputes[offset2]));
|
3012
3080
|
}
|
3013
3081
|
}
|
3014
3082
|
return { p, f };
|
@@ -3021,8 +3089,8 @@ class JacobianPoint {
|
|
3021
3089
|
const { k1neg, k1, k2neg, k2 } = endo.splitScalar(n);
|
3022
3090
|
let { p: k1p, f: f1p } = this.wNAF(k1, affinePoint);
|
3023
3091
|
let { p: k2p, f: f2p } = this.wNAF(k2, affinePoint);
|
3024
|
-
k1p = constTimeNegate(k1neg, k1p);
|
3025
|
-
k2p = constTimeNegate(k2neg, k2p);
|
3092
|
+
k1p = constTimeNegate$1(k1neg, k1p);
|
3093
|
+
k2p = constTimeNegate$1(k2neg, k2p);
|
3026
3094
|
k2p = new JacobianPoint(mod$1(k2p.x * endo.beta), k2p.y, k2p.z);
|
3027
3095
|
point = k1p.add(k2p);
|
3028
3096
|
fake = f1p.add(f2p);
|
@@ -3054,7 +3122,7 @@ class JacobianPoint {
|
|
3054
3122
|
}
|
3055
3123
|
JacobianPoint.BASE = new JacobianPoint(CURVE.Gx, CURVE.Gy, _1n$7);
|
3056
3124
|
JacobianPoint.ZERO = new JacobianPoint(_0n$5, _1n$7, _0n$5);
|
3057
|
-
function constTimeNegate(condition, item) {
|
3125
|
+
function constTimeNegate$1(condition, item) {
|
3058
3126
|
const neg = item.negate();
|
3059
3127
|
return condition ? neg : item;
|
3060
3128
|
}
|
@@ -4974,7 +5042,7 @@ function parseIPv6(input) {
|
|
4974
5042
|
return parser.new(input).parseWith(() => parser.readIPv6Addr());
|
4975
5043
|
}
|
4976
5044
|
/** Parse `input` into IPv4 or IPv6 bytes. */
|
4977
|
-
function parseIP(input) {
|
5045
|
+
function parseIP(input, mapIPv4ToIPv6 = false) {
|
4978
5046
|
// strip zone index if it is present
|
4979
5047
|
if (input.includes("%")) {
|
4980
5048
|
input = input.split("%")[0];
|
@@ -4982,7 +5050,14 @@ function parseIP(input) {
|
|
4982
5050
|
if (input.length > MAX_IPV6_LENGTH) {
|
4983
5051
|
return undefined;
|
4984
5052
|
}
|
4985
|
-
|
5053
|
+
const addr = parser.new(input).parseWith(() => parser.readIPAddr());
|
5054
|
+
if (!addr) {
|
5055
|
+
return undefined;
|
5056
|
+
}
|
5057
|
+
if (mapIPv4ToIPv6 && addr.length === 4) {
|
5058
|
+
return Uint8Array.from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, addr[0], addr[1], addr[2], addr[3]]);
|
5059
|
+
}
|
5060
|
+
return addr;
|
4986
5061
|
}
|
4987
5062
|
|
4988
5063
|
/** Check if `input` is IPv4. */
|
@@ -5170,17 +5245,13 @@ function getProtocol(proto) {
|
|
5170
5245
|
throw new Error(`invalid protocol id type: ${typeof proto}`);
|
5171
5246
|
}
|
5172
5247
|
|
5173
|
-
/**
|
5174
|
-
* @packageDocumentation
|
5175
|
-
*
|
5176
|
-
* Provides methods for converting
|
5177
|
-
*/
|
5178
5248
|
getProtocol('ip4');
|
5179
5249
|
getProtocol('ip6');
|
5180
5250
|
getProtocol('ipcidr');
|
5181
5251
|
/**
|
5182
5252
|
* Convert [code,Uint8Array] to string
|
5183
5253
|
*/
|
5254
|
+
// eslint-disable-next-line complexity
|
5184
5255
|
function convertToString(proto, buf) {
|
5185
5256
|
const protocol = getProtocol(proto);
|
5186
5257
|
switch (protocol.code) {
|
@@ -5189,6 +5260,8 @@ function convertToString(proto, buf) {
|
|
5189
5260
|
return bytes2ip(buf);
|
5190
5261
|
case 42: // ipv6zone
|
5191
5262
|
return bytes2str(buf);
|
5263
|
+
case 43: // ipcidr
|
5264
|
+
return toString$6(buf, 'base10');
|
5192
5265
|
case 6: // tcp
|
5193
5266
|
case 273: // udp
|
5194
5267
|
case 33: // dccp
|
@@ -5216,6 +5289,7 @@ function convertToString(proto, buf) {
|
|
5216
5289
|
return toString$6(buf, 'base16'); // no clue. convert to hex
|
5217
5290
|
}
|
5218
5291
|
}
|
5292
|
+
// eslint-disable-next-line complexity
|
5219
5293
|
function convertToBytes(proto, str) {
|
5220
5294
|
const protocol = getProtocol(proto);
|
5221
5295
|
switch (protocol.code) {
|
@@ -5225,6 +5299,8 @@ function convertToBytes(proto, str) {
|
|
5225
5299
|
return ip2bytes(str);
|
5226
5300
|
case 42: // ipv6zone
|
5227
5301
|
return str2bytes(str);
|
5302
|
+
case 43: // ipcidr
|
5303
|
+
return fromString(str, 'base10');
|
5228
5304
|
case 6: // tcp
|
5229
5305
|
case 273: // udp
|
5230
5306
|
case 33: // dccp
|
@@ -5519,19 +5595,6 @@ function ParseError(str) {
|
|
5519
5595
|
return new Error('Error parsing address: ' + str);
|
5520
5596
|
}
|
5521
5597
|
|
5522
|
-
/**
|
5523
|
-
* @packageDocumentation
|
5524
|
-
*
|
5525
|
-
* An implementation of a Multiaddr in JavaScript
|
5526
|
-
*
|
5527
|
-
* @example
|
5528
|
-
*
|
5529
|
-
* ```js
|
5530
|
-
* import { multiaddr } from '@multiformats/multiaddr'
|
5531
|
-
*
|
5532
|
-
* const ma = multiaddr('/ip4/127.0.0.1/tcp/1234')
|
5533
|
-
* ```
|
5534
|
-
*/
|
5535
5598
|
const inspect$2 = Symbol.for('nodejs.util.inspect.custom');
|
5536
5599
|
const symbol$1 = Symbol.for('@multiformats/js-multiaddr/multiaddr');
|
5537
5600
|
const DNS_CODES = [
|
@@ -5643,10 +5706,20 @@ class Multiaddr {
|
|
5643
5706
|
return this.#tuples.map(([code]) => getProtocol(code).name);
|
5644
5707
|
}
|
5645
5708
|
tuples() {
|
5646
|
-
return this.#tuples
|
5709
|
+
return this.#tuples.map(([code, value]) => {
|
5710
|
+
if (value == null) {
|
5711
|
+
return [code];
|
5712
|
+
}
|
5713
|
+
return [code, value];
|
5714
|
+
});
|
5647
5715
|
}
|
5648
5716
|
stringTuples() {
|
5649
|
-
return this.#stringTuples
|
5717
|
+
return this.#stringTuples.map(([code, value]) => {
|
5718
|
+
if (value == null) {
|
5719
|
+
return [code];
|
5720
|
+
}
|
5721
|
+
return [code, value];
|
5722
|
+
});
|
5650
5723
|
}
|
5651
5724
|
encapsulate(addr) {
|
5652
5725
|
addr = new Multiaddr(addr);
|
@@ -5776,10 +5849,8 @@ class Multiaddr {
|
|
5776
5849
|
*
|
5777
5850
|
* ```TypeScript
|
5778
5851
|
* import { multiaddr } from '@multiformats/multiaddr'
|
5779
|
-
* const addr = multiaddr("/ip4/127.0.0.1/udp/1234")
|
5780
|
-
* // Multiaddr(/ip4/127.0.0.1/udp/1234)
|
5781
5852
|
*
|
5782
|
-
* const addr = multiaddr(
|
5853
|
+
* const addr = multiaddr('/ip4/127.0.0.1/udp/1234')
|
5783
5854
|
* // Multiaddr(/ip4/127.0.0.1/udp/1234)
|
5784
5855
|
*
|
5785
5856
|
* addr.bytes
|
@@ -5818,9 +5889,9 @@ class Multiaddr {
|
|
5818
5889
|
*
|
5819
5890
|
* ```TypeScript
|
5820
5891
|
* import { multiaddr, resolvers } from '@multiformats/multiaddr'
|
5821
|
-
* import {
|
5892
|
+
* import { dnsaddrResolver } from '@multiformats/multiaddr/resolvers'
|
5822
5893
|
*
|
5823
|
-
* resolvers.set('dnsaddr',
|
5894
|
+
* resolvers.set('dnsaddr', dnsaddrResolver)
|
5824
5895
|
*
|
5825
5896
|
* const ma = multiaddr('/dnsaddr/bootstrap.libp2p.io')
|
5826
5897
|
*
|
@@ -5829,7 +5900,7 @@ class Multiaddr {
|
|
5829
5900
|
* signal: AbortSignal.timeout(5000)
|
5830
5901
|
* })
|
5831
5902
|
*
|
5832
|
-
* console.info(
|
5903
|
+
* console.info(resolved)
|
5833
5904
|
* // [Multiaddr('/ip4/147.75...'), Multiaddr('/ip4/147.75...'), Multiaddr('/ip4/147.75...')...]
|
5834
5905
|
* ```
|
5835
5906
|
*
|
@@ -5843,7 +5914,9 @@ class Multiaddr {
|
|
5843
5914
|
* import { dnsJsonOverHttps } from '@multiformats/dns/resolvers'
|
5844
5915
|
*
|
5845
5916
|
* const resolver = dns({
|
5846
|
-
*
|
5917
|
+
* resolvers: {
|
5918
|
+
* '.': dnsJsonOverHttps('https://cloudflare-dns.com/dns-query')
|
5919
|
+
* }
|
5847
5920
|
* })
|
5848
5921
|
*
|
5849
5922
|
* const ma = multiaddr('/dnsaddr/bootstrap.libp2p.io')
|
@@ -5930,44 +6003,12 @@ function locationMultiaddrFromEnrFields(enr, protocol) {
|
|
5930
6003
|
}
|
5931
6004
|
|
5932
6005
|
/**
|
5933
|
-
*
|
5934
|
-
*
|
5935
|
-
*
|
6006
|
+
* Internal helpers for u64. BigUint64Array is too slow as per 2025, so we implement it using Uint32Array.
|
6007
|
+
* @todo re-check https://issues.chromium.org/issues/42212588
|
6008
|
+
* @module
|
5936
6009
|
*/
|
5937
|
-
/**
|
5938
|
-
* Thrown when invalid parameters are passed to a function or method call
|
5939
|
-
*/
|
5940
|
-
class InvalidParametersError extends Error {
|
5941
|
-
static name = 'InvalidParametersError';
|
5942
|
-
constructor(message = 'Invalid parameters') {
|
5943
|
-
super(message);
|
5944
|
-
this.name = 'InvalidParametersError';
|
5945
|
-
}
|
5946
|
-
}
|
5947
|
-
/**
|
5948
|
-
* Thrown when a public key is invalid
|
5949
|
-
*/
|
5950
|
-
class InvalidPublicKeyError extends Error {
|
5951
|
-
static name = 'InvalidPublicKeyError';
|
5952
|
-
constructor(message = 'Invalid public key') {
|
5953
|
-
super(message);
|
5954
|
-
this.name = 'InvalidPublicKeyError';
|
5955
|
-
}
|
5956
|
-
}
|
5957
|
-
/**
|
5958
|
-
* Thrown when and attempt to operate on an unsupported key was made
|
5959
|
-
*/
|
5960
|
-
let UnsupportedKeyTypeError$1 = class UnsupportedKeyTypeError extends Error {
|
5961
|
-
static name = 'UnsupportedKeyTypeError';
|
5962
|
-
constructor(message = 'Unsupported key type') {
|
5963
|
-
super(message);
|
5964
|
-
this.name = 'UnsupportedKeyTypeError';
|
5965
|
-
}
|
5966
|
-
};
|
5967
|
-
|
5968
6010
|
const U32_MASK64 = /* @__PURE__ */ BigInt(2 ** 32 - 1);
|
5969
6011
|
const _32n = /* @__PURE__ */ BigInt(32);
|
5970
|
-
// We are not using BigUint64Array, because they are extremely slow as per 2022
|
5971
6012
|
function fromBig(n, le = false) {
|
5972
6013
|
if (le)
|
5973
6014
|
return { h: Number(n & U32_MASK64), l: Number((n >> _32n) & U32_MASK64) };
|
@@ -6024,6 +6065,13 @@ const u64 = {
|
|
6024
6065
|
add, add3L, add3H, add4L, add4H, add5H, add5L,
|
6025
6066
|
};
|
6026
6067
|
|
6068
|
+
/**
|
6069
|
+
* SHA2-512 a.k.a. sha512 and sha384. It is slower than sha256 in js because u64 operations are slow.
|
6070
|
+
*
|
6071
|
+
* Check out [RFC 4634](https://datatracker.ietf.org/doc/html/rfc4634) and
|
6072
|
+
* [the paper on truncated SHA512/256](https://eprint.iacr.org/2010/548.pdf).
|
6073
|
+
* @module
|
6074
|
+
*/
|
6027
6075
|
// Round contants (first 32 bits of the fractional parts of the cube roots of the first 80 primes 2..409):
|
6028
6076
|
// prettier-ignore
|
6029
6077
|
const [SHA512_Kh, SHA512_Kl] = /* @__PURE__ */ (() => u64.split([
|
@@ -6178,8 +6226,13 @@ class SHA512 extends HashMD {
|
|
6178
6226
|
this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
6179
6227
|
}
|
6180
6228
|
}
|
6229
|
+
/** SHA2-512 hash function. */
|
6181
6230
|
const sha512 = /* @__PURE__ */ wrapConstructor(() => new SHA512());
|
6182
6231
|
|
6232
|
+
/**
|
6233
|
+
* Hex, bytes and number utilities.
|
6234
|
+
* @module
|
6235
|
+
*/
|
6183
6236
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
6184
6237
|
// 100 lines of code in the file are duplicated from noble-hashes (utils).
|
6185
6238
|
// This is OK: `abstract` directory does not use noble-hashes.
|
@@ -6189,8 +6242,7 @@ const _0n$4 = /* @__PURE__ */ BigInt(0);
|
|
6189
6242
|
const _1n$6 = /* @__PURE__ */ BigInt(1);
|
6190
6243
|
const _2n$4 = /* @__PURE__ */ BigInt(2);
|
6191
6244
|
function isBytes$1(a) {
|
6192
|
-
return
|
6193
|
-
(a != null && typeof a === 'object' && a.constructor.name === 'Uint8Array'));
|
6245
|
+
return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array');
|
6194
6246
|
}
|
6195
6247
|
function abytes(item) {
|
6196
6248
|
if (!isBytes$1(item))
|
@@ -6198,7 +6250,7 @@ function abytes(item) {
|
|
6198
6250
|
}
|
6199
6251
|
function abool(title, value) {
|
6200
6252
|
if (typeof value !== 'boolean')
|
6201
|
-
throw new Error(
|
6253
|
+
throw new Error(title + ' boolean expected, got ' + value);
|
6202
6254
|
}
|
6203
6255
|
// Array where index 0xf0 (240) is mapped to string 'f0'
|
6204
6256
|
const hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'));
|
@@ -6216,23 +6268,22 @@ function bytesToHex(bytes) {
|
|
6216
6268
|
}
|
6217
6269
|
function numberToHexUnpadded(num) {
|
6218
6270
|
const hex = num.toString(16);
|
6219
|
-
return hex.length & 1 ?
|
6271
|
+
return hex.length & 1 ? '0' + hex : hex;
|
6220
6272
|
}
|
6221
6273
|
function hexToNumber(hex) {
|
6222
6274
|
if (typeof hex !== 'string')
|
6223
6275
|
throw new Error('hex string expected, got ' + typeof hex);
|
6224
|
-
// Big Endian
|
6225
|
-
return BigInt(hex === '' ? '0' : `0x${hex}`);
|
6276
|
+
return hex === '' ? _0n$4 : BigInt('0x' + hex); // Big Endian
|
6226
6277
|
}
|
6227
6278
|
// We use optimized technique to convert hex string to byte array
|
6228
|
-
const asciis = { _0: 48, _9: 57,
|
6229
|
-
function asciiToBase16(
|
6230
|
-
if (
|
6231
|
-
return
|
6232
|
-
if (
|
6233
|
-
return
|
6234
|
-
if (
|
6235
|
-
return
|
6279
|
+
const asciis = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 };
|
6280
|
+
function asciiToBase16(ch) {
|
6281
|
+
if (ch >= asciis._0 && ch <= asciis._9)
|
6282
|
+
return ch - asciis._0; // '2' => 50-48
|
6283
|
+
if (ch >= asciis.A && ch <= asciis.F)
|
6284
|
+
return ch - (asciis.A - 10); // 'B' => 66-(65-10)
|
6285
|
+
if (ch >= asciis.a && ch <= asciis.f)
|
6286
|
+
return ch - (asciis.a - 10); // 'b' => 98-(97-10)
|
6236
6287
|
return;
|
6237
6288
|
}
|
6238
6289
|
/**
|
@@ -6244,7 +6295,7 @@ function hexToBytes(hex) {
|
|
6244
6295
|
const hl = hex.length;
|
6245
6296
|
const al = hl / 2;
|
6246
6297
|
if (hl % 2)
|
6247
|
-
throw new Error('
|
6298
|
+
throw new Error('hex string expected, got unpadded hex of length ' + hl);
|
6248
6299
|
const array = new Uint8Array(al);
|
6249
6300
|
for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {
|
6250
6301
|
const n1 = asciiToBase16(hex.charCodeAt(hi));
|
@@ -6253,7 +6304,7 @@ function hexToBytes(hex) {
|
|
6253
6304
|
const char = hex[hi] + hex[hi + 1];
|
6254
6305
|
throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi);
|
6255
6306
|
}
|
6256
|
-
array[ai] = n1 * 16 + n2;
|
6307
|
+
array[ai] = n1 * 16 + n2; // multiply first octet, e.g. 'a3' => 10*16+3 => 160 + 3 => 163
|
6257
6308
|
}
|
6258
6309
|
return array;
|
6259
6310
|
}
|
@@ -6291,7 +6342,7 @@ function ensureBytes(title, hex, expectedLength) {
|
|
6291
6342
|
res = hexToBytes(hex);
|
6292
6343
|
}
|
6293
6344
|
catch (e) {
|
6294
|
-
throw new Error(
|
6345
|
+
throw new Error(title + ' must be hex string or Uint8Array, cause: ' + e);
|
6295
6346
|
}
|
6296
6347
|
}
|
6297
6348
|
else if (isBytes$1(hex)) {
|
@@ -6300,11 +6351,11 @@ function ensureBytes(title, hex, expectedLength) {
|
|
6300
6351
|
res = Uint8Array.from(hex);
|
6301
6352
|
}
|
6302
6353
|
else {
|
6303
|
-
throw new Error(
|
6354
|
+
throw new Error(title + ' must be hex string or Uint8Array');
|
6304
6355
|
}
|
6305
6356
|
const len = res.length;
|
6306
6357
|
if (typeof expectedLength === 'number' && len !== expectedLength)
|
6307
|
-
throw new Error(
|
6358
|
+
throw new Error(title + ' of length ' + expectedLength + ' expected, got ' + len);
|
6308
6359
|
return res;
|
6309
6360
|
}
|
6310
6361
|
/**
|
@@ -6339,7 +6390,7 @@ function equalBytes(a, b) {
|
|
6339
6390
|
*/
|
6340
6391
|
function utf8ToBytes(str) {
|
6341
6392
|
if (typeof str !== 'string')
|
6342
|
-
throw new Error(
|
6393
|
+
throw new Error('string expected');
|
6343
6394
|
return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809
|
6344
6395
|
}
|
6345
6396
|
// Is positive bigint
|
@@ -6359,7 +6410,7 @@ function aInRange(title, n, min, max) {
|
|
6359
6410
|
// - b would commonly require subtraction: `inRange('x', x, 0n, P - 1n)`
|
6360
6411
|
// - our way is the cleanest: `inRange('x', x, 0n, P)
|
6361
6412
|
if (!inRange(n, min, max))
|
6362
|
-
throw new Error(
|
6413
|
+
throw new Error('expected valid ' + title + ': ' + min + ' <= n < ' + max + ', got ' + n);
|
6363
6414
|
}
|
6364
6415
|
// Bit operations
|
6365
6416
|
/**
|
@@ -6469,12 +6520,12 @@ function validateObject(object, validators, optValidators = {}) {
|
|
6469
6520
|
const checkField = (fieldName, type, isOptional) => {
|
6470
6521
|
const checkVal = validatorFns[type];
|
6471
6522
|
if (typeof checkVal !== 'function')
|
6472
|
-
throw new Error(
|
6523
|
+
throw new Error('invalid validator function');
|
6473
6524
|
const val = object[fieldName];
|
6474
6525
|
if (isOptional && val === undefined)
|
6475
6526
|
return;
|
6476
6527
|
if (!checkVal(val, object)) {
|
6477
|
-
throw new Error(
|
6528
|
+
throw new Error('param ' + String(fieldName) + ' is invalid. Expected ' + type + ', got ' + val);
|
6478
6529
|
}
|
6479
6530
|
};
|
6480
6531
|
for (const [fieldName, type] of Object.entries(validators))
|
@@ -6543,14 +6594,17 @@ var ut = /*#__PURE__*/Object.freeze({
|
|
6543
6594
|
validateObject: validateObject
|
6544
6595
|
});
|
6545
6596
|
|
6597
|
+
/**
|
6598
|
+
* Utils for modular division and finite fields.
|
6599
|
+
* A finite field over 11 is integer number operations `mod 11`.
|
6600
|
+
* There is no division: it is replaced by modular multiplicative inverse.
|
6601
|
+
* @module
|
6602
|
+
*/
|
6546
6603
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
6547
|
-
// Utilities for modular arithmetics and finite fields
|
6548
|
-
// prettier-ignore
|
6549
|
-
const _0n$3 = BigInt(0), _1n$5 = BigInt(1), _2n$3 = BigInt(2), _3n$1 = BigInt(3);
|
6550
6604
|
// prettier-ignore
|
6551
|
-
const
|
6605
|
+
const _0n$3 = BigInt(0), _1n$5 = BigInt(1), _2n$3 = /* @__PURE__ */ BigInt(2), _3n$1 = /* @__PURE__ */ BigInt(3);
|
6552
6606
|
// prettier-ignore
|
6553
|
-
BigInt(
|
6607
|
+
const _4n = /* @__PURE__ */ BigInt(4), _5n$1 = /* @__PURE__ */ BigInt(5), _8n$2 = /* @__PURE__ */ BigInt(8);
|
6554
6608
|
// Calculates a modulo b
|
6555
6609
|
function mod(a, b) {
|
6556
6610
|
const result = a % b;
|
@@ -6559,13 +6613,15 @@ function mod(a, b) {
|
|
6559
6613
|
/**
|
6560
6614
|
* Efficiently raise num to power and do modular division.
|
6561
6615
|
* Unsafe in some contexts: uses ladder, so can expose bigint bits.
|
6616
|
+
* @todo use field version && remove
|
6562
6617
|
* @example
|
6563
6618
|
* pow(2n, 6n, 11n) // 64n % 11n == 9n
|
6564
6619
|
*/
|
6565
|
-
// TODO: use field version && remove
|
6566
6620
|
function pow(num, power, modulo) {
|
6567
|
-
if (
|
6568
|
-
throw new Error('
|
6621
|
+
if (power < _0n$3)
|
6622
|
+
throw new Error('invalid exponent, negatives unsupported');
|
6623
|
+
if (modulo <= _0n$3)
|
6624
|
+
throw new Error('invalid modulus');
|
6569
6625
|
if (modulo === _1n$5)
|
6570
6626
|
return _0n$3;
|
6571
6627
|
let res = _1n$5;
|
@@ -6577,7 +6633,7 @@ function pow(num, power, modulo) {
|
|
6577
6633
|
}
|
6578
6634
|
return res;
|
6579
6635
|
}
|
6580
|
-
|
6636
|
+
/** Does `x^(2^power)` mod p. `pow2(30, 4)` == `30^(2^4)` */
|
6581
6637
|
function pow2(x, power, modulo) {
|
6582
6638
|
let res = x;
|
6583
6639
|
while (power-- > _0n$3) {
|
@@ -6586,12 +6642,15 @@ function pow2(x, power, modulo) {
|
|
6586
6642
|
}
|
6587
6643
|
return res;
|
6588
6644
|
}
|
6589
|
-
|
6645
|
+
/**
|
6646
|
+
* Inverses number over modulo.
|
6647
|
+
* Implemented using [Euclidean GCD](https://brilliant.org/wiki/extended-euclidean-algorithm/).
|
6648
|
+
*/
|
6590
6649
|
function invert(number, modulo) {
|
6591
|
-
if (number === _0n$3
|
6592
|
-
throw new Error(
|
6593
|
-
|
6594
|
-
|
6650
|
+
if (number === _0n$3)
|
6651
|
+
throw new Error('invert: expected non-zero number');
|
6652
|
+
if (modulo <= _0n$3)
|
6653
|
+
throw new Error('invert: expected positive modulus, got ' + modulo);
|
6595
6654
|
// Fermat's little theorem "CT-like" version inv(n) = n^(m-2) mod m is 30x slower.
|
6596
6655
|
let a = mod(number, modulo);
|
6597
6656
|
let b = modulo;
|
@@ -6631,8 +6690,11 @@ function tonelliShanks(P) {
|
|
6631
6690
|
for (Q = P - _1n$5, S = 0; Q % _2n$3 === _0n$3; Q /= _2n$3, S++)
|
6632
6691
|
;
|
6633
6692
|
// Step 2: Select a non-square z such that (z | p) ≡ -1 and set c ≡ zq
|
6634
|
-
for (Z = _2n$3; Z < P && pow(Z, legendreC, P) !== P - _1n$5; Z++)
|
6635
|
-
|
6693
|
+
for (Z = _2n$3; Z < P && pow(Z, legendreC, P) !== P - _1n$5; Z++) {
|
6694
|
+
// Crash instead of infinity loop, we cannot reasonable count until P.
|
6695
|
+
if (Z > 1000)
|
6696
|
+
throw new Error('Cannot find square root: likely non-prime P');
|
6697
|
+
}
|
6636
6698
|
// Fast-path
|
6637
6699
|
if (S === 1) {
|
6638
6700
|
const p1div4 = (P + _1n$5) / _4n;
|
@@ -6674,9 +6736,18 @@ function tonelliShanks(P) {
|
|
6674
6736
|
return x;
|
6675
6737
|
};
|
6676
6738
|
}
|
6739
|
+
/**
|
6740
|
+
* Square root for a finite field. It will try to check if optimizations are applicable and fall back to 4:
|
6741
|
+
*
|
6742
|
+
* 1. P ≡ 3 (mod 4)
|
6743
|
+
* 2. P ≡ 5 (mod 8)
|
6744
|
+
* 3. P ≡ 9 (mod 16)
|
6745
|
+
* 4. Tonelli-Shanks algorithm
|
6746
|
+
*
|
6747
|
+
* Different algorithms can give different roots, it is up to user to decide which one they want.
|
6748
|
+
* For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve).
|
6749
|
+
*/
|
6677
6750
|
function FpSqrt(P) {
|
6678
|
-
// NOTE: different algorithms can give different roots, it is up to user to decide which one they want.
|
6679
|
-
// For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve).
|
6680
6751
|
// P ≡ 3 (mod 4)
|
6681
6752
|
// √n = n^((P+1)/4)
|
6682
6753
|
if (P % _4n === _3n$1) {
|
@@ -6740,7 +6811,7 @@ function FpPow(f, num, power) {
|
|
6740
6811
|
// Should have same speed as pow for bigints
|
6741
6812
|
// TODO: benchmark!
|
6742
6813
|
if (power < _0n$3)
|
6743
|
-
throw new Error('
|
6814
|
+
throw new Error('invalid exponent, negatives unsupported');
|
6744
6815
|
if (power === _0n$3)
|
6745
6816
|
return f.ONE;
|
6746
6817
|
if (power === _1n$5)
|
@@ -6787,15 +6858,15 @@ function nLength(n, nBitLength) {
|
|
6787
6858
|
return { nBitLength: _nBitLength, nByteLength };
|
6788
6859
|
}
|
6789
6860
|
/**
|
6790
|
-
* Initializes a finite field over prime.
|
6791
|
-
* Do not init in loop: slow. Very fragile: always run a benchmark on a change.
|
6861
|
+
* Initializes a finite field over prime.
|
6792
6862
|
* Major performance optimizations:
|
6793
6863
|
* * a) denormalized operations like mulN instead of mul
|
6794
6864
|
* * b) same object shape: never add or remove keys
|
6795
6865
|
* * c) Object.freeze
|
6796
|
-
*
|
6866
|
+
* Fragile: always run a benchmark on a change.
|
6867
|
+
* Security note: operations don't check 'isValid' for all elements for performance reasons,
|
6797
6868
|
* it is caller responsibility to check this.
|
6798
|
-
* This is low-level code, please make sure you know what you doing.
|
6869
|
+
* This is low-level code, please make sure you know what you're doing.
|
6799
6870
|
* @param ORDER prime positive bigint
|
6800
6871
|
* @param bitLen how many bits the field consumes
|
6801
6872
|
* @param isLE (def: false) if encoding / decoding should be in little-endian
|
@@ -6803,13 +6874,14 @@ function nLength(n, nBitLength) {
|
|
6803
6874
|
*/
|
6804
6875
|
function Field(ORDER, bitLen, isLE = false, redef = {}) {
|
6805
6876
|
if (ORDER <= _0n$3)
|
6806
|
-
throw new Error(
|
6877
|
+
throw new Error('invalid field: expected ORDER > 0, got ' + ORDER);
|
6807
6878
|
const { nBitLength: BITS, nByteLength: BYTES } = nLength(ORDER, bitLen);
|
6808
6879
|
if (BYTES > 2048)
|
6809
|
-
throw new Error('
|
6810
|
-
|
6880
|
+
throw new Error('invalid field: expected ORDER of <= 2048 bytes');
|
6881
|
+
let sqrtP; // cached sqrtP
|
6811
6882
|
const f = Object.freeze({
|
6812
6883
|
ORDER,
|
6884
|
+
isLE,
|
6813
6885
|
BITS,
|
6814
6886
|
BYTES,
|
6815
6887
|
MASK: bitMask(BITS),
|
@@ -6818,7 +6890,7 @@ function Field(ORDER, bitLen, isLE = false, redef = {}) {
|
|
6818
6890
|
create: (num) => mod(num, ORDER),
|
6819
6891
|
isValid: (num) => {
|
6820
6892
|
if (typeof num !== 'bigint')
|
6821
|
-
throw new Error(
|
6893
|
+
throw new Error('invalid field element: expected bigint, got ' + typeof num);
|
6822
6894
|
return _0n$3 <= num && num < ORDER; // 0 is valid element, but it's not invertible
|
6823
6895
|
},
|
6824
6896
|
is0: (num) => num === _0n$3,
|
@@ -6837,7 +6909,12 @@ function Field(ORDER, bitLen, isLE = false, redef = {}) {
|
|
6837
6909
|
subN: (lhs, rhs) => lhs - rhs,
|
6838
6910
|
mulN: (lhs, rhs) => lhs * rhs,
|
6839
6911
|
inv: (num) => invert(num, ORDER),
|
6840
|
-
sqrt: redef.sqrt ||
|
6912
|
+
sqrt: redef.sqrt ||
|
6913
|
+
((n) => {
|
6914
|
+
if (!sqrtP)
|
6915
|
+
sqrtP = FpSqrt(ORDER);
|
6916
|
+
return sqrtP(f, n);
|
6917
|
+
}),
|
6841
6918
|
invertBatch: (lst) => FpInvertBatch(f, lst),
|
6842
6919
|
// TODO: do we really need constant cmov?
|
6843
6920
|
// We don't have const-time bigints anyway, so probably will be not very useful
|
@@ -6845,7 +6922,7 @@ function Field(ORDER, bitLen, isLE = false, redef = {}) {
|
|
6845
6922
|
toBytes: (num) => (isLE ? numberToBytesLE(num, BYTES) : numberToBytesBE(num, BYTES)),
|
6846
6923
|
fromBytes: (bytes) => {
|
6847
6924
|
if (bytes.length !== BYTES)
|
6848
|
-
throw new Error(
|
6925
|
+
throw new Error('Field.fromBytes: expected ' + BYTES + ' bytes, got ' + bytes.length);
|
6849
6926
|
return isLE ? bytesToNumberLE(bytes) : bytesToNumberBE(bytes);
|
6850
6927
|
},
|
6851
6928
|
});
|
@@ -6893,52 +6970,80 @@ function mapHashToField(key, fieldOrder, isLE = false) {
|
|
6893
6970
|
const minLen = getMinHashLength(fieldOrder);
|
6894
6971
|
// No small numbers: need to understand bias story. No huge numbers: easier to detect JS timings.
|
6895
6972
|
if (len < 16 || len < minLen || len > 1024)
|
6896
|
-
throw new Error(
|
6897
|
-
const num = isLE ?
|
6973
|
+
throw new Error('expected ' + minLen + '-1024 bytes of input, got ' + len);
|
6974
|
+
const num = isLE ? bytesToNumberLE(key) : bytesToNumberBE(key);
|
6898
6975
|
// `mod(x, 11)` can sometimes produce 0. `mod(x, 10) + 1` is the same, but no 0
|
6899
6976
|
const reduced = mod(num, fieldOrder - _1n$5) + _1n$5;
|
6900
6977
|
return isLE ? numberToBytesLE(reduced, fieldLen) : numberToBytesBE(reduced, fieldLen);
|
6901
6978
|
}
|
6902
6979
|
|
6980
|
+
/**
|
6981
|
+
* Methods for elliptic curve multiplication by scalars.
|
6982
|
+
* Contains wNAF, pippenger
|
6983
|
+
* @module
|
6984
|
+
*/
|
6903
6985
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
6904
|
-
// Abelian group utilities
|
6905
6986
|
const _0n$2 = BigInt(0);
|
6906
6987
|
const _1n$4 = BigInt(1);
|
6988
|
+
function constTimeNegate(condition, item) {
|
6989
|
+
const neg = item.negate();
|
6990
|
+
return condition ? neg : item;
|
6991
|
+
}
|
6992
|
+
function validateW(W, bits) {
|
6993
|
+
if (!Number.isSafeInteger(W) || W <= 0 || W > bits)
|
6994
|
+
throw new Error('invalid window size, expected [1..' + bits + '], got W=' + W);
|
6995
|
+
}
|
6996
|
+
function calcWOpts(W, bits) {
|
6997
|
+
validateW(W, bits);
|
6998
|
+
const windows = Math.ceil(bits / W) + 1; // +1, because
|
6999
|
+
const windowSize = 2 ** (W - 1); // -1 because we skip zero
|
7000
|
+
return { windows, windowSize };
|
7001
|
+
}
|
7002
|
+
function validateMSMPoints(points, c) {
|
7003
|
+
if (!Array.isArray(points))
|
7004
|
+
throw new Error('array expected');
|
7005
|
+
points.forEach((p, i) => {
|
7006
|
+
if (!(p instanceof c))
|
7007
|
+
throw new Error('invalid point at index ' + i);
|
7008
|
+
});
|
7009
|
+
}
|
7010
|
+
function validateMSMScalars(scalars, field) {
|
7011
|
+
if (!Array.isArray(scalars))
|
7012
|
+
throw new Error('array of scalars expected');
|
7013
|
+
scalars.forEach((s, i) => {
|
7014
|
+
if (!field.isValid(s))
|
7015
|
+
throw new Error('invalid scalar at index ' + i);
|
7016
|
+
});
|
7017
|
+
}
|
6907
7018
|
// Since points in different groups cannot be equal (different object constructor),
|
6908
7019
|
// we can have single place to store precomputes
|
6909
7020
|
const pointPrecomputes = new WeakMap();
|
6910
7021
|
const pointWindowSizes = new WeakMap(); // This allows use make points immutable (nothing changes inside)
|
6911
|
-
|
6912
|
-
|
6913
|
-
|
6914
|
-
|
6915
|
-
|
6916
|
-
|
6917
|
-
|
6918
|
-
|
6919
|
-
|
6920
|
-
|
6921
|
-
|
7022
|
+
function getW(P) {
|
7023
|
+
return pointWindowSizes.get(P) || 1;
|
7024
|
+
}
|
7025
|
+
/**
|
7026
|
+
* Elliptic curve multiplication of Point by scalar. Fragile.
|
7027
|
+
* Scalars should always be less than curve order: this should be checked inside of a curve itself.
|
7028
|
+
* Creates precomputation tables for fast multiplication:
|
7029
|
+
* - private scalar is split by fixed size windows of W bits
|
7030
|
+
* - every window point is collected from window's table & added to accumulator
|
7031
|
+
* - since windows are different, same point inside tables won't be accessed more than once per calc
|
7032
|
+
* - each multiplication is 'Math.ceil(CURVE_ORDER / 𝑊) + 1' point additions (fixed for any scalar)
|
7033
|
+
* - +1 window is neccessary for wNAF
|
7034
|
+
* - wNAF reduces table size: 2x less memory + 2x faster generation, but 10% slower multiplication
|
7035
|
+
*
|
7036
|
+
* @todo Research returning 2d JS array of windows, instead of a single window.
|
7037
|
+
* This would allow windows to be in different memory locations
|
7038
|
+
*/
|
6922
7039
|
function wNAF(c, bits) {
|
6923
|
-
const constTimeNegate = (condition, item) => {
|
6924
|
-
const neg = item.negate();
|
6925
|
-
return condition ? neg : item;
|
6926
|
-
};
|
6927
|
-
const validateW = (W) => {
|
6928
|
-
if (!Number.isSafeInteger(W) || W <= 0 || W > bits)
|
6929
|
-
throw new Error(`Wrong window size=${W}, should be [1..${bits}]`);
|
6930
|
-
};
|
6931
|
-
const opts = (W) => {
|
6932
|
-
validateW(W);
|
6933
|
-
const windows = Math.ceil(bits / W) + 1; // +1, because
|
6934
|
-
const windowSize = 2 ** (W - 1); // -1 because we skip zero
|
6935
|
-
return { windows, windowSize };
|
6936
|
-
};
|
6937
7040
|
return {
|
6938
7041
|
constTimeNegate,
|
7042
|
+
hasPrecomputes(elm) {
|
7043
|
+
return getW(elm) !== 1;
|
7044
|
+
},
|
6939
7045
|
// non-const time multiplication ladder
|
6940
|
-
unsafeLadder(elm, n) {
|
6941
|
-
let p = c.ZERO;
|
7046
|
+
unsafeLadder(elm, n, p = c.ZERO) {
|
6942
7047
|
let d = elm;
|
6943
7048
|
while (n > _0n$2) {
|
6944
7049
|
if (n & _1n$4)
|
@@ -6956,10 +7061,12 @@ function wNAF(c, bits) {
|
|
6956
7061
|
* - 𝑊 is the window size
|
6957
7062
|
* - 𝑛 is the bitlength of the curve order.
|
6958
7063
|
* For a 256-bit curve and window size 8, the number of precomputed points is 128 * 33 = 4224.
|
7064
|
+
* @param elm Point instance
|
7065
|
+
* @param W window size
|
6959
7066
|
* @returns precomputed point tables flattened to a single array
|
6960
7067
|
*/
|
6961
7068
|
precomputeWindow(elm, W) {
|
6962
|
-
const { windows, windowSize } =
|
7069
|
+
const { windows, windowSize } = calcWOpts(W, bits);
|
6963
7070
|
const points = [];
|
6964
7071
|
let p = elm;
|
6965
7072
|
let base = p;
|
@@ -6985,7 +7092,7 @@ function wNAF(c, bits) {
|
|
6985
7092
|
wNAF(W, precomputes, n) {
|
6986
7093
|
// TODO: maybe check that scalar is less than group order? wNAF behavious is undefined otherwise
|
6987
7094
|
// But need to carefully remove other checks before wNAF. ORDER == bits here
|
6988
|
-
const { windows, windowSize } =
|
7095
|
+
const { windows, windowSize } = calcWOpts(W, bits);
|
6989
7096
|
let p = c.ZERO;
|
6990
7097
|
let f = c.BASE;
|
6991
7098
|
const mask = BigInt(2 ** W - 1); // Create mask with W ones: 0b1111 for W=4 etc.
|
@@ -7029,8 +7136,44 @@ function wNAF(c, bits) {
|
|
7029
7136
|
// which makes it less const-time: around 1 bigint multiply.
|
7030
7137
|
return { p, f };
|
7031
7138
|
},
|
7032
|
-
|
7033
|
-
|
7139
|
+
/**
|
7140
|
+
* Implements ec unsafe (non const-time) multiplication using precomputed tables and w-ary non-adjacent form.
|
7141
|
+
* @param W window size
|
7142
|
+
* @param precomputes precomputed tables
|
7143
|
+
* @param n scalar (we don't check here, but should be less than curve order)
|
7144
|
+
* @param acc accumulator point to add result of multiplication
|
7145
|
+
* @returns point
|
7146
|
+
*/
|
7147
|
+
wNAFUnsafe(W, precomputes, n, acc = c.ZERO) {
|
7148
|
+
const { windows, windowSize } = calcWOpts(W, bits);
|
7149
|
+
const mask = BigInt(2 ** W - 1); // Create mask with W ones: 0b1111 for W=4 etc.
|
7150
|
+
const maxNumber = 2 ** W;
|
7151
|
+
const shiftBy = BigInt(W);
|
7152
|
+
for (let window = 0; window < windows; window++) {
|
7153
|
+
const offset = window * windowSize;
|
7154
|
+
if (n === _0n$2)
|
7155
|
+
break; // No need to go over empty scalar
|
7156
|
+
// Extract W bits.
|
7157
|
+
let wbits = Number(n & mask);
|
7158
|
+
// Shift number by W bits.
|
7159
|
+
n >>= shiftBy;
|
7160
|
+
// If the bits are bigger than max size, we'll split those.
|
7161
|
+
// +224 => 256 - 32
|
7162
|
+
if (wbits > windowSize) {
|
7163
|
+
wbits -= maxNumber;
|
7164
|
+
n += _1n$4;
|
7165
|
+
}
|
7166
|
+
if (wbits === 0)
|
7167
|
+
continue;
|
7168
|
+
let curr = precomputes[offset + Math.abs(wbits) - 1]; // -1 because we skip zero
|
7169
|
+
if (wbits < 0)
|
7170
|
+
curr = curr.negate();
|
7171
|
+
// NOTE: by re-using acc, we can save a lot of additions in case of MSM
|
7172
|
+
acc = acc.add(curr);
|
7173
|
+
}
|
7174
|
+
return acc;
|
7175
|
+
},
|
7176
|
+
getPrecomputes(W, P, transform) {
|
7034
7177
|
// Calculate precomputes on a first run, reuse them after
|
7035
7178
|
let comp = pointPrecomputes.get(P);
|
7036
7179
|
if (!comp) {
|
@@ -7038,62 +7181,66 @@ function wNAF(c, bits) {
|
|
7038
7181
|
if (W !== 1)
|
7039
7182
|
pointPrecomputes.set(P, transform(comp));
|
7040
7183
|
}
|
7041
|
-
return
|
7184
|
+
return comp;
|
7185
|
+
},
|
7186
|
+
wNAFCached(P, n, transform) {
|
7187
|
+
const W = getW(P);
|
7188
|
+
return this.wNAF(W, this.getPrecomputes(W, P, transform), n);
|
7189
|
+
},
|
7190
|
+
wNAFCachedUnsafe(P, n, transform, prev) {
|
7191
|
+
const W = getW(P);
|
7192
|
+
if (W === 1)
|
7193
|
+
return this.unsafeLadder(P, n, prev); // For W=1 ladder is ~x2 faster
|
7194
|
+
return this.wNAFUnsafe(W, this.getPrecomputes(W, P, transform), n, prev);
|
7042
7195
|
},
|
7043
7196
|
// We calculate precomputes for elliptic curve point multiplication
|
7044
7197
|
// using windowed method. This specifies window size and
|
7045
7198
|
// stores precomputed values. Usually only base point would be precomputed.
|
7046
7199
|
setWindowSize(P, W) {
|
7047
|
-
validateW(W);
|
7200
|
+
validateW(W, bits);
|
7048
7201
|
pointWindowSizes.set(P, W);
|
7049
7202
|
pointPrecomputes.delete(P);
|
7050
7203
|
},
|
7051
7204
|
};
|
7052
7205
|
}
|
7053
7206
|
/**
|
7054
|
-
* Pippenger algorithm for multi-scalar multiplication (MSM).
|
7055
|
-
* MSM is basically (Pa + Qb + Rc + ...).
|
7207
|
+
* Pippenger algorithm for multi-scalar multiplication (MSM, Pa + Qb + Rc + ...).
|
7056
7208
|
* 30x faster vs naive addition on L=4096, 10x faster with precomputes.
|
7057
7209
|
* For N=254bit, L=1, it does: 1024 ADD + 254 DBL. For L=5: 1536 ADD + 254 DBL.
|
7058
7210
|
* Algorithmically constant-time (for same L), even when 1 point + scalar, or when scalar = 0.
|
7059
7211
|
* @param c Curve Point constructor
|
7060
|
-
* @param
|
7212
|
+
* @param fieldN field over CURVE.N - important that it's not over CURVE.P
|
7061
7213
|
* @param points array of L curve points
|
7062
7214
|
* @param scalars array of L scalars (aka private keys / bigints)
|
7063
7215
|
*/
|
7064
|
-
function pippenger(c,
|
7216
|
+
function pippenger(c, fieldN, points, scalars) {
|
7065
7217
|
// If we split scalars by some window (let's say 8 bits), every chunk will only
|
7066
7218
|
// take 256 buckets even if there are 4096 scalars, also re-uses double.
|
7067
7219
|
// TODO:
|
7068
7220
|
// - https://eprint.iacr.org/2024/750.pdf
|
7069
7221
|
// - https://tches.iacr.org/index.php/TCHES/article/view/10287
|
7070
7222
|
// 0 is accepted in scalars
|
7071
|
-
|
7223
|
+
validateMSMPoints(points, c);
|
7224
|
+
validateMSMScalars(scalars, fieldN);
|
7225
|
+
if (points.length !== scalars.length)
|
7072
7226
|
throw new Error('arrays of points and scalars must have equal length');
|
7073
|
-
|
7074
|
-
if (!field.isValid(s))
|
7075
|
-
throw new Error(`wrong scalar at index ${i}`);
|
7076
|
-
});
|
7077
|
-
points.forEach((p, i) => {
|
7078
|
-
if (!(p instanceof c))
|
7079
|
-
throw new Error(`wrong point at index ${i}`);
|
7080
|
-
});
|
7227
|
+
const zero = c.ZERO;
|
7081
7228
|
const wbits = bitLen(BigInt(points.length));
|
7082
7229
|
const windowSize = wbits > 12 ? wbits - 3 : wbits > 4 ? wbits - 2 : wbits ? 2 : 1; // in bits
|
7083
7230
|
const MASK = (1 << windowSize) - 1;
|
7084
|
-
const buckets = new Array(MASK + 1).fill(
|
7085
|
-
const lastBits = Math.floor((
|
7086
|
-
let sum =
|
7231
|
+
const buckets = new Array(MASK + 1).fill(zero); // +1 for zero array
|
7232
|
+
const lastBits = Math.floor((fieldN.BITS - 1) / windowSize) * windowSize;
|
7233
|
+
let sum = zero;
|
7087
7234
|
for (let i = lastBits; i >= 0; i -= windowSize) {
|
7088
|
-
buckets.fill(
|
7235
|
+
buckets.fill(zero);
|
7089
7236
|
for (let j = 0; j < scalars.length; j++) {
|
7090
7237
|
const scalar = scalars[j];
|
7091
7238
|
const wbits = Number((scalar >> BigInt(i)) & BigInt(MASK));
|
7092
7239
|
buckets[wbits] = buckets[wbits].add(points[j]);
|
7093
7240
|
}
|
7094
|
-
let resI =
|
7241
|
+
let resI = zero; // not using this will do small speed-up, but will lose ct
|
7095
7242
|
// Skip first bucket, because it is zero
|
7096
|
-
for (let j = buckets.length - 1, sumI =
|
7243
|
+
for (let j = buckets.length - 1, sumI = zero; j > 0; j--) {
|
7097
7244
|
sumI = sumI.add(buckets[j]);
|
7098
7245
|
resI = resI.add(sumI);
|
7099
7246
|
}
|
@@ -7123,8 +7270,12 @@ function validateBasic(curve) {
|
|
7123
7270
|
});
|
7124
7271
|
}
|
7125
7272
|
|
7273
|
+
/**
|
7274
|
+
* Twisted Edwards curve. The formula is: ax² + y² = 1 + dx²y².
|
7275
|
+
* For design rationale of types / exports, see weierstrass module documentation.
|
7276
|
+
* @module
|
7277
|
+
*/
|
7126
7278
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
7127
|
-
// Twisted Edwards curve. The formula is: ax² + y² = 1 + dx²y²
|
7128
7279
|
// Be friendly to bad ECMAScript parsers by not using bigint literals
|
7129
7280
|
// prettier-ignore
|
7130
7281
|
const _0n$1 = BigInt(0), _1n$3 = BigInt(1), _2n$2 = BigInt(2), _8n$1 = BigInt(8);
|
@@ -7156,6 +7307,10 @@ function validateOpts$1(curve) {
|
|
7156
7307
|
function twistedEdwards(curveDef) {
|
7157
7308
|
const CURVE = validateOpts$1(curveDef);
|
7158
7309
|
const { Fp, n: CURVE_ORDER, prehash: prehash, hash: cHash, randomBytes, nByteLength, h: cofactor, } = CURVE;
|
7310
|
+
// Important:
|
7311
|
+
// There are some places where Fp.BYTES is used instead of nByteLength.
|
7312
|
+
// So far, everything has been tested with curves of Fp.BYTES == nByteLength.
|
7313
|
+
// TODO: test and find curves which behave otherwise.
|
7159
7314
|
const MASK = _2n$2 << (BigInt(nByteLength * 8) - _1n$3);
|
7160
7315
|
const modP = Fp.create; // Function overrides
|
7161
7316
|
const Fn = Field(CURVE.n, CURVE.nBitLength);
|
@@ -7369,16 +7524,15 @@ function twistedEdwards(curveDef) {
|
|
7369
7524
|
// It's faster, but should only be used when you don't care about
|
7370
7525
|
// an exposed private key e.g. sig verification.
|
7371
7526
|
// Does NOT allow scalars higher than CURVE.n.
|
7372
|
-
|
7527
|
+
// Accepts optional accumulator to merge with multiply (important for sparse scalars)
|
7528
|
+
multiplyUnsafe(scalar, acc = Point.ZERO) {
|
7373
7529
|
const n = scalar;
|
7374
7530
|
aInRange('scalar', n, _0n$1, CURVE_ORDER); // 0 <= scalar < L
|
7375
7531
|
if (n === _0n$1)
|
7376
7532
|
return I;
|
7377
|
-
if (this.
|
7533
|
+
if (this.is0() || n === _1n$3)
|
7378
7534
|
return this;
|
7379
|
-
|
7380
|
-
return this.wNAF(n).p;
|
7381
|
-
return wnaf.unsafeLadder(this, n);
|
7535
|
+
return wnaf.wNAFCachedUnsafe(this, n, Point.normalizeZ, acc);
|
7382
7536
|
}
|
7383
7537
|
// Checks if point is of small order.
|
7384
7538
|
// If you add something to small order point, you will have "dirty"
|
@@ -7412,8 +7566,9 @@ function twistedEdwards(curveDef) {
|
|
7412
7566
|
abool('zip215', zip215);
|
7413
7567
|
const normed = hex.slice(); // copy again, we'll manipulate it
|
7414
7568
|
const lastByte = hex[len - 1]; // select last byte
|
7415
|
-
normed[len - 1] = lastByte &
|
7569
|
+
normed[len - 1] = lastByte & -129; // clear last bit
|
7416
7570
|
const y = bytesToNumberLE(normed);
|
7571
|
+
// zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5.
|
7417
7572
|
// RFC8032 prohibits >= p, but ZIP215 doesn't
|
7418
7573
|
// zip215=true: 0 <= y < MASK (2^256 for ed25519)
|
7419
7574
|
// zip215=false: 0 <= y < P (2^255-19 for ed25519)
|
@@ -7462,7 +7617,7 @@ function twistedEdwards(curveDef) {
|
|
7462
7617
|
}
|
7463
7618
|
/** Convenience method that creates public key and other stuff. RFC8032 5.1.5 */
|
7464
7619
|
function getExtendedPublicKey(key) {
|
7465
|
-
const len =
|
7620
|
+
const len = Fp.BYTES;
|
7466
7621
|
key = ensureBytes('private key', key, len);
|
7467
7622
|
// Hash private key with curve's hash function to produce uniformingly random input
|
7468
7623
|
// Check byte lengths: ensure(64, h(ensure(32, key)))
|
@@ -7495,23 +7650,29 @@ function twistedEdwards(curveDef) {
|
|
7495
7650
|
const s = modN(r + k * scalar); // S = (r + k * s) mod L
|
7496
7651
|
aInRange('signature.s', s, _0n$1, CURVE_ORDER); // 0 <= s < l
|
7497
7652
|
const res = concatBytes(R, numberToBytesLE(s, Fp.BYTES));
|
7498
|
-
return ensureBytes('result', res,
|
7653
|
+
return ensureBytes('result', res, Fp.BYTES * 2); // 64-byte signature
|
7499
7654
|
}
|
7500
7655
|
const verifyOpts = VERIFY_DEFAULT;
|
7656
|
+
/**
|
7657
|
+
* Verifies EdDSA signature against message and public key. RFC8032 5.1.7.
|
7658
|
+
* An extended group equation is checked.
|
7659
|
+
*/
|
7501
7660
|
function verify(sig, msg, publicKey, options = verifyOpts) {
|
7502
7661
|
const { context, zip215 } = options;
|
7503
7662
|
const len = Fp.BYTES; // Verifies EdDSA signature against message and public key. RFC8032 5.1.7.
|
7504
7663
|
sig = ensureBytes('signature', sig, 2 * len); // An extended group equation is checked.
|
7505
7664
|
msg = ensureBytes('message', msg);
|
7665
|
+
publicKey = ensureBytes('publicKey', publicKey, len);
|
7506
7666
|
if (zip215 !== undefined)
|
7507
7667
|
abool('zip215', zip215);
|
7508
7668
|
if (prehash)
|
7509
7669
|
msg = prehash(msg); // for ed25519ph, etc
|
7510
7670
|
const s = bytesToNumberLE(sig.slice(len, 2 * len));
|
7511
|
-
// zip215: true is good for consensus-critical apps and allows points < 2^256
|
7512
|
-
// zip215: false follows RFC8032 / NIST186-5 and restricts points to CURVE.p
|
7513
7671
|
let A, R, SB;
|
7514
7672
|
try {
|
7673
|
+
// zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5.
|
7674
|
+
// zip215=true: 0 <= y < MASK (2^256 for ed25519)
|
7675
|
+
// zip215=false: 0 <= y < P (2^255-19 for ed25519)
|
7515
7676
|
A = Point.fromHex(publicKey, zip215);
|
7516
7677
|
R = Point.fromHex(sig.slice(0, len), zip215);
|
7517
7678
|
SB = G.multiplyUnsafe(s); // 0 <= s < l is done inside
|
@@ -7523,6 +7684,7 @@ function twistedEdwards(curveDef) {
|
|
7523
7684
|
return false;
|
7524
7685
|
const k = hashDomainToScalar(context, R.toRawBytes(), A.toRawBytes(), msg);
|
7525
7686
|
const RkA = R.add(A.multiplyUnsafe(k));
|
7687
|
+
// Extended group equation
|
7526
7688
|
// [8][S]B = [8]R + [8][k]A'
|
7527
7689
|
return RkA.subtract(SB).clearCofactor().equals(Point.ZERO);
|
7528
7690
|
}
|
@@ -7553,13 +7715,14 @@ function twistedEdwards(curveDef) {
|
|
7553
7715
|
};
|
7554
7716
|
}
|
7555
7717
|
|
7556
|
-
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
7557
7718
|
/**
|
7558
7719
|
* ed25519 Twisted Edwards curve with following addons:
|
7559
7720
|
* - X25519 ECDH
|
7560
7721
|
* - Ristretto cofactor elimination
|
7561
7722
|
* - Elligator hash-to-group / point indistinguishability
|
7723
|
+
* @module
|
7562
7724
|
*/
|
7725
|
+
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
7563
7726
|
const ED25519_P = BigInt('57896044618658097711785492504343953926634992332820282019728792003956564819949');
|
7564
7727
|
// √(-1) aka √(a) aka 2^((p-1)/4)
|
7565
7728
|
const ED25519_SQRT_M1 = /* @__PURE__ */ BigInt('19681161376707505956807079304988542015446066515923890162744021073123829784752');
|
@@ -7618,7 +7781,7 @@ function uvRatio(u, v) {
|
|
7618
7781
|
x = mod(-x, P);
|
7619
7782
|
return { isValid: useRoot1 || useRoot2, value: x };
|
7620
7783
|
}
|
7621
|
-
const Fp
|
7784
|
+
const Fp = /* @__PURE__ */ (() => Field(ED25519_P, undefined, true))();
|
7622
7785
|
const ed25519Defaults = /* @__PURE__ */ (() => ({
|
7623
7786
|
// Param: a
|
7624
7787
|
a: BigInt(-1), // Fp.create(-1) is proper; our way still works and is faster
|
@@ -7626,7 +7789,7 @@ const ed25519Defaults = /* @__PURE__ */ (() => ({
|
|
7626
7789
|
// Negative number is P - number, and division is invert(number, P)
|
7627
7790
|
d: BigInt('37095705934669439343138083508754565189542113879843219016388785533085940283555'),
|
7628
7791
|
// Finite field 𝔽p over which we'll do calculations; 2n**255n - 19n
|
7629
|
-
Fp
|
7792
|
+
Fp,
|
7630
7793
|
// Subgroup order: how many points curve has
|
7631
7794
|
// 2n**252n + 27742317777372353535851937790883648493n;
|
7632
7795
|
n: BigInt('7237005577332262213973186563042994240857116359379907606001950938285454250989'),
|
@@ -7645,6 +7808,14 @@ const ed25519Defaults = /* @__PURE__ */ (() => ({
|
|
7645
7808
|
}))();
|
7646
7809
|
/**
|
7647
7810
|
* ed25519 curve with EdDSA signatures.
|
7811
|
+
* @example
|
7812
|
+
* import { ed25519 } from '@noble/curves/ed25519';
|
7813
|
+
* const priv = ed25519.utils.randomPrivateKey();
|
7814
|
+
* const pub = ed25519.getPublicKey(priv);
|
7815
|
+
* const msg = new TextEncoder().encode('hello');
|
7816
|
+
* const sig = ed25519.sign(msg, priv);
|
7817
|
+
* ed25519.verify(sig, msg, pub); // Default mode: follows ZIP215
|
7818
|
+
* ed25519.verify(sig, msg, pub, { zip215: false }); // RFC8032 / FIPS 186-5
|
7648
7819
|
*/
|
7649
7820
|
const ed25519 = /* @__PURE__ */ (() => twistedEdwards(ed25519Defaults))();
|
7650
7821
|
|
@@ -9042,7 +9213,7 @@ var PrivateKey;
|
|
9042
9213
|
/*!
|
9043
9214
|
* MIT License
|
9044
9215
|
*
|
9045
|
-
* Copyright (c) 2017-
|
9216
|
+
* Copyright (c) 2017-2024 Peculiar Ventures, LLC
|
9046
9217
|
*
|
9047
9218
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
9048
9219
|
* of this software and associated documentation files (the "Software"), to deal
|
@@ -9154,7 +9325,7 @@ class BufferSourceConverter {
|
|
9154
9325
|
}
|
9155
9326
|
|
9156
9327
|
const STRING_TYPE = "string";
|
9157
|
-
const HEX_REGEX = /^[0-9a-f]+$/i;
|
9328
|
+
const HEX_REGEX = /^[0-9a-f\s]+$/i;
|
9158
9329
|
const BASE64_REGEX = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
|
9159
9330
|
const BASE64URL_REGEX = /^[a-zA-Z0-9-_]+$/;
|
9160
9331
|
class Utf8Converter {
|
@@ -9388,7 +9559,7 @@ class Convert {
|
|
9388
9559
|
return base64;
|
9389
9560
|
}
|
9390
9561
|
static formatString(data) {
|
9391
|
-
return (data === null || data ===
|
9562
|
+
return (data === null || data === undefined ? undefined : data.replace(/[\n\r\t ]/g, "")) || "";
|
9392
9563
|
}
|
9393
9564
|
}
|
9394
9565
|
Convert.DEFAULT_UTF8_ENCODING = "utf8";
|
@@ -9644,7 +9815,7 @@ function HexBlock(BaseClass) {
|
|
9644
9815
|
var _a;
|
9645
9816
|
super(...args);
|
9646
9817
|
const params = args[0] || {};
|
9647
|
-
this.isHexOnly = (_a = params.isHexOnly) !== null && _a !==
|
9818
|
+
this.isHexOnly = (_a = params.isHexOnly) !== null && _a !== undefined ? _a : false;
|
9648
9819
|
this.valueHexView = params.valueHex ? BufferSourceConverter_1.toUint8Array(params.valueHex) : EMPTY_VIEW;
|
9649
9820
|
}
|
9650
9821
|
get valueHex() {
|
@@ -9734,11 +9905,11 @@ class LocalIdentificationBlock extends HexBlock(LocalBaseBlock) {
|
|
9734
9905
|
var _a, _b, _c, _d;
|
9735
9906
|
super();
|
9736
9907
|
if (idBlock) {
|
9737
|
-
this.isHexOnly = (_a = idBlock.isHexOnly) !== null && _a !==
|
9908
|
+
this.isHexOnly = (_a = idBlock.isHexOnly) !== null && _a !== undefined ? _a : false;
|
9738
9909
|
this.valueHexView = idBlock.valueHex ? BufferSourceConverter_1.toUint8Array(idBlock.valueHex) : EMPTY_VIEW;
|
9739
|
-
this.tagClass = (_b = idBlock.tagClass) !== null && _b !==
|
9740
|
-
this.tagNumber = (_c = idBlock.tagNumber) !== null && _c !==
|
9741
|
-
this.isConstructed = (_d = idBlock.isConstructed) !== null && _d !==
|
9910
|
+
this.tagClass = (_b = idBlock.tagClass) !== null && _b !== undefined ? _b : -1;
|
9911
|
+
this.tagNumber = (_c = idBlock.tagNumber) !== null && _c !== undefined ? _c : -1;
|
9912
|
+
this.isConstructed = (_d = idBlock.isConstructed) !== null && _d !== undefined ? _d : false;
|
9742
9913
|
}
|
9743
9914
|
else {
|
9744
9915
|
this.tagClass = -1;
|
@@ -9905,9 +10076,9 @@ class LocalLengthBlock extends LocalBaseBlock {
|
|
9905
10076
|
constructor({ lenBlock = {}, } = {}) {
|
9906
10077
|
var _a, _b, _c;
|
9907
10078
|
super();
|
9908
|
-
this.isIndefiniteForm = (_a = lenBlock.isIndefiniteForm) !== null && _a !==
|
9909
|
-
this.longFormUsed = (_b = lenBlock.longFormUsed) !== null && _b !==
|
9910
|
-
this.length = (_c = lenBlock.length) !== null && _c !==
|
10079
|
+
this.isIndefiniteForm = (_a = lenBlock.isIndefiniteForm) !== null && _a !== undefined ? _a : false;
|
10080
|
+
this.longFormUsed = (_b = lenBlock.longFormUsed) !== null && _b !== undefined ? _b : false;
|
10081
|
+
this.length = (_c = lenBlock.length) !== null && _c !== undefined ? _c : 0;
|
9911
10082
|
}
|
9912
10083
|
fromBER(inputBuffer, inputOffset, inputLength) {
|
9913
10084
|
const view = BufferSourceConverter_1.toUint8Array(inputBuffer);
|
@@ -10679,7 +10850,7 @@ var _a$r;
|
|
10679
10850
|
class OctetString extends BaseBlock {
|
10680
10851
|
constructor({ idBlock = {}, lenBlock = {}, ...parameters } = {}) {
|
10681
10852
|
var _b, _c;
|
10682
|
-
(_b = parameters.isConstructed) !== null && _b !==
|
10853
|
+
(_b = parameters.isConstructed) !== null && _b !== undefined ? _b : (parameters.isConstructed = !!((_c = parameters.value) === null || _c === undefined ? undefined : _c.length));
|
10683
10854
|
super({
|
10684
10855
|
idBlock: {
|
10685
10856
|
isConstructed: parameters.isConstructed,
|
@@ -10840,7 +11011,7 @@ var _a$q;
|
|
10840
11011
|
class BitString extends BaseBlock {
|
10841
11012
|
constructor({ idBlock = {}, lenBlock = {}, ...parameters } = {}) {
|
10842
11013
|
var _b, _c;
|
10843
|
-
(_b = parameters.isConstructed) !== null && _b !==
|
11014
|
+
(_b = parameters.isConstructed) !== null && _b !== undefined ? _b : (parameters.isConstructed = !!((_c = parameters.value) === null || _c === undefined ? undefined : _c.length));
|
10844
11015
|
super({
|
10845
11016
|
idBlock: {
|
10846
11017
|
isConstructed: parameters.isConstructed,
|
@@ -12042,7 +12213,7 @@ class GeneralizedTime extends UTCTime {
|
|
12042
12213
|
constructor(parameters = {}) {
|
12043
12214
|
var _b;
|
12044
12215
|
super(parameters);
|
12045
|
-
(_b = this.millisecond) !== null && _b !==
|
12216
|
+
(_b = this.millisecond) !== null && _b !== undefined ? _b : (this.millisecond = 0);
|
12046
12217
|
this.idBlock.tagClass = 1;
|
12047
12218
|
this.idBlock.tagNumber = 24;
|
12048
12219
|
}
|
@@ -12393,8 +12564,8 @@ function pkixToJwk(bytes) {
|
|
12393
12564
|
const values = result.valueBlock.value[1].valueBlock.value[0].valueBlock.value;
|
12394
12565
|
return {
|
12395
12566
|
kty: 'RSA',
|
12396
|
-
n:
|
12397
|
-
e:
|
12567
|
+
n: asn1jsIntegerToBase64(values[0]),
|
12568
|
+
e: asn1jsIntegerToBase64(values[1])
|
12398
12569
|
};
|
12399
12570
|
}
|
12400
12571
|
/**
|
@@ -12430,21 +12601,13 @@ function jwkToPkix(jwk) {
|
|
12430
12601
|
const der = root.toBER();
|
12431
12602
|
return new Uint8Array(der, 0, der.byteLength);
|
12432
12603
|
}
|
12433
|
-
function
|
12434
|
-
let
|
12435
|
-
|
12436
|
-
|
12437
|
-
|
12438
|
-
const len = hex.length / 2;
|
12439
|
-
const u8 = new Uint8Array(len);
|
12440
|
-
let i = 0;
|
12441
|
-
let j = 0;
|
12442
|
-
while (i < len) {
|
12443
|
-
u8[i] = parseInt(hex.slice(j, j + 2), 16);
|
12444
|
-
i += 1;
|
12445
|
-
j += 2;
|
12604
|
+
function asn1jsIntegerToBase64(int) {
|
12605
|
+
let buf = int.valueBlock.valueHexView;
|
12606
|
+
// chrome rejects values with leading 0s
|
12607
|
+
while (buf[0] === 0) {
|
12608
|
+
buf = buf.subarray(1);
|
12446
12609
|
}
|
12447
|
-
return
|
12610
|
+
return toString$6(buf, 'base64url');
|
12448
12611
|
}
|
12449
12612
|
function bufToBn(u8) {
|
12450
12613
|
const hex = [];
|
@@ -12473,15 +12636,18 @@ function pkixToRSAPublicKey(bytes) {
|
|
12473
12636
|
return new RSAPublicKey(jwk, digest);
|
12474
12637
|
}
|
12475
12638
|
|
12476
|
-
|
12639
|
+
/**
|
12640
|
+
* HMAC: RFC2104 message authentication code.
|
12641
|
+
* @module
|
12642
|
+
*/
|
12477
12643
|
class HMAC extends Hash {
|
12478
|
-
constructor(hash
|
12644
|
+
constructor(hash, _key) {
|
12479
12645
|
super();
|
12480
12646
|
this.finished = false;
|
12481
12647
|
this.destroyed = false;
|
12482
|
-
|
12648
|
+
ahash(hash);
|
12483
12649
|
const key = toBytes$1(_key);
|
12484
|
-
this.iHash = hash
|
12650
|
+
this.iHash = hash.create();
|
12485
12651
|
if (typeof this.iHash.update !== 'function')
|
12486
12652
|
throw new Error('Expected instance of class which extends utils.Hash');
|
12487
12653
|
this.blockLen = this.iHash.blockLen;
|
@@ -12489,12 +12655,12 @@ class HMAC extends Hash {
|
|
12489
12655
|
const blockLen = this.blockLen;
|
12490
12656
|
const pad = new Uint8Array(blockLen);
|
12491
12657
|
// blockLen can be bigger than outputLen
|
12492
|
-
pad.set(key.length > blockLen ? hash
|
12658
|
+
pad.set(key.length > blockLen ? hash.create().update(key).digest() : key);
|
12493
12659
|
for (let i = 0; i < pad.length; i++)
|
12494
12660
|
pad[i] ^= 0x36;
|
12495
12661
|
this.iHash.update(pad);
|
12496
12662
|
// By doing update (processing of first block) of outer hash here we can re-use it between multiple calls via clone
|
12497
|
-
this.oHash = hash
|
12663
|
+
this.oHash = hash.create();
|
12498
12664
|
// Undo internal XOR && apply outer XOR
|
12499
12665
|
for (let i = 0; i < pad.length; i++)
|
12500
12666
|
pad[i] ^= 0x36 ^ 0x5c;
|
@@ -12502,13 +12668,13 @@ class HMAC extends Hash {
|
|
12502
12668
|
pad.fill(0);
|
12503
12669
|
}
|
12504
12670
|
update(buf) {
|
12505
|
-
|
12671
|
+
aexists(this);
|
12506
12672
|
this.iHash.update(buf);
|
12507
12673
|
return this;
|
12508
12674
|
}
|
12509
12675
|
digestInto(out) {
|
12510
|
-
|
12511
|
-
|
12676
|
+
aexists(this);
|
12677
|
+
abytes$1(out, this.outputLen);
|
12512
12678
|
this.finished = true;
|
12513
12679
|
this.iHash.digestInto(out);
|
12514
12680
|
this.oHash.update(out);
|
@@ -12552,8 +12718,33 @@ class HMAC extends Hash {
|
|
12552
12718
|
const hmac = (hash, key, message) => new HMAC(hash, key).update(message).digest();
|
12553
12719
|
hmac.create = (hash, key) => new HMAC(hash, key);
|
12554
12720
|
|
12721
|
+
/**
|
12722
|
+
* Short Weierstrass curve methods. The formula is: y² = x³ + ax + b.
|
12723
|
+
*
|
12724
|
+
* ### Design rationale for types
|
12725
|
+
*
|
12726
|
+
* * Interaction between classes from different curves should fail:
|
12727
|
+
* `k256.Point.BASE.add(p256.Point.BASE)`
|
12728
|
+
* * For this purpose we want to use `instanceof` operator, which is fast and works during runtime
|
12729
|
+
* * Different calls of `curve()` would return different classes -
|
12730
|
+
* `curve(params) !== curve(params)`: if somebody decided to monkey-patch their curve,
|
12731
|
+
* it won't affect others
|
12732
|
+
*
|
12733
|
+
* TypeScript can't infer types for classes created inside a function. Classes is one instance
|
12734
|
+
* of nominative types in TypeScript and interfaces only check for shape, so it's hard to create
|
12735
|
+
* unique type for every function call.
|
12736
|
+
*
|
12737
|
+
* We can use generic types via some param, like curve opts, but that would:
|
12738
|
+
* 1. Enable interaction between `curve(params)` and `curve(params)` (curves of same params)
|
12739
|
+
* which is hard to debug.
|
12740
|
+
* 2. Params can be generic and we can't enforce them to be constant value:
|
12741
|
+
* if somebody creates curve from non-constant params,
|
12742
|
+
* it would be allowed to interact with other curves with non-constant params
|
12743
|
+
*
|
12744
|
+
* @todo https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#unique-symbol
|
12745
|
+
* @module
|
12746
|
+
*/
|
12555
12747
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
12556
|
-
// Short Weierstrass curve. The formula is: y² = x³ + ax + b
|
12557
12748
|
function validateSigVerOpts(opts) {
|
12558
12749
|
if (opts.lowS !== undefined)
|
12559
12750
|
abool('lowS', opts.lowS);
|
@@ -12577,17 +12768,22 @@ function validatePointOpts(curve) {
|
|
12577
12768
|
const { endo, Fp, a } = opts;
|
12578
12769
|
if (endo) {
|
12579
12770
|
if (!Fp.eql(a, Fp.ZERO)) {
|
12580
|
-
throw new Error('
|
12771
|
+
throw new Error('invalid endomorphism, can only be defined for Koblitz curves that have a=0');
|
12581
12772
|
}
|
12582
12773
|
if (typeof endo !== 'object' ||
|
12583
12774
|
typeof endo.beta !== 'bigint' ||
|
12584
12775
|
typeof endo.splitScalar !== 'function') {
|
12585
|
-
throw new Error('
|
12776
|
+
throw new Error('invalid endomorphism, expected beta: bigint and splitScalar: function');
|
12586
12777
|
}
|
12587
12778
|
}
|
12588
12779
|
return Object.freeze({ ...opts });
|
12589
12780
|
}
|
12590
12781
|
const { bytesToNumberBE: b2n, hexToBytes: h2b } = ut;
|
12782
|
+
class DERErr extends Error {
|
12783
|
+
constructor(m = '') {
|
12784
|
+
super(m);
|
12785
|
+
}
|
12786
|
+
}
|
12591
12787
|
/**
|
12592
12788
|
* ASN.1 DER encoding utilities. ASN is very complex & fragile. Format:
|
12593
12789
|
*
|
@@ -12597,11 +12793,7 @@ const { bytesToNumberBE: b2n, hexToBytes: h2b } = ut;
|
|
12597
12793
|
*/
|
12598
12794
|
const DER = {
|
12599
12795
|
// asn.1 DER encoding utils
|
12600
|
-
Err:
|
12601
|
-
constructor(m = '') {
|
12602
|
-
super(m);
|
12603
|
-
}
|
12604
|
-
},
|
12796
|
+
Err: DERErr,
|
12605
12797
|
// Basic building block is TLV (Tag-Length-Value)
|
12606
12798
|
_tlv: {
|
12607
12799
|
encode: (tag, data) => {
|
@@ -12616,7 +12808,8 @@ const DER = {
|
|
12616
12808
|
throw new E('tlv.encode: long form length too big');
|
12617
12809
|
// length of length with long form flag
|
12618
12810
|
const lenLen = dataLen > 127 ? numberToHexUnpadded((len.length / 2) | 128) : '';
|
12619
|
-
|
12811
|
+
const t = numberToHexUnpadded(tag);
|
12812
|
+
return t + lenLen + len + data;
|
12620
12813
|
},
|
12621
12814
|
// v - value, l - left bytes (unparsed)
|
12622
12815
|
decode(tag, data) {
|
@@ -12669,15 +12862,15 @@ const DER = {
|
|
12669
12862
|
if (Number.parseInt(hex[0], 16) & 0b1000)
|
12670
12863
|
hex = '00' + hex;
|
12671
12864
|
if (hex.length & 1)
|
12672
|
-
throw new E('unexpected assertion');
|
12865
|
+
throw new E('unexpected DER parsing assertion: unpadded hex');
|
12673
12866
|
return hex;
|
12674
12867
|
},
|
12675
12868
|
decode(data) {
|
12676
12869
|
const { Err: E } = DER;
|
12677
12870
|
if (data[0] & 128)
|
12678
|
-
throw new E('
|
12871
|
+
throw new E('invalid signature integer: negative');
|
12679
12872
|
if (data[0] === 0x00 && !(data[1] & 128))
|
12680
|
-
throw new E('
|
12873
|
+
throw new E('invalid signature integer: unnecessary leading zero');
|
12681
12874
|
return b2n(data);
|
12682
12875
|
},
|
12683
12876
|
},
|
@@ -12688,16 +12881,18 @@ const DER = {
|
|
12688
12881
|
abytes(data);
|
12689
12882
|
const { v: seqBytes, l: seqLeftBytes } = tlv.decode(0x30, data);
|
12690
12883
|
if (seqLeftBytes.length)
|
12691
|
-
throw new E('
|
12884
|
+
throw new E('invalid signature: left bytes after parsing');
|
12692
12885
|
const { v: rBytes, l: rLeftBytes } = tlv.decode(0x02, seqBytes);
|
12693
12886
|
const { v: sBytes, l: sLeftBytes } = tlv.decode(0x02, rLeftBytes);
|
12694
12887
|
if (sLeftBytes.length)
|
12695
|
-
throw new E('
|
12888
|
+
throw new E('invalid signature: left bytes after parsing');
|
12696
12889
|
return { r: int.decode(rBytes), s: int.decode(sBytes) };
|
12697
12890
|
},
|
12698
12891
|
hexFromSig(sig) {
|
12699
12892
|
const { _tlv: tlv, _int: int } = DER;
|
12700
|
-
const
|
12893
|
+
const rs = tlv.encode(0x02, int.encode(sig.r));
|
12894
|
+
const ss = tlv.encode(0x02, int.encode(sig.s));
|
12895
|
+
const seq = rs + ss;
|
12701
12896
|
return tlv.encode(0x30, seq);
|
12702
12897
|
},
|
12703
12898
|
};
|
@@ -12751,7 +12946,7 @@ function weierstrassPoints(opts) {
|
|
12751
12946
|
key = bytesToHex(key);
|
12752
12947
|
// Normalize to hex string, pad. E.g. P521 would norm 130-132 char hex to 132-char bytes
|
12753
12948
|
if (typeof key !== 'string' || !lengths.includes(key.length))
|
12754
|
-
throw new Error('
|
12949
|
+
throw new Error('invalid private key');
|
12755
12950
|
key = key.padStart(nByteLength * 2, '0');
|
12756
12951
|
}
|
12757
12952
|
let num;
|
@@ -12762,7 +12957,7 @@ function weierstrassPoints(opts) {
|
|
12762
12957
|
: bytesToNumberBE(ensureBytes('private key', key, nByteLength));
|
12763
12958
|
}
|
12764
12959
|
catch (error) {
|
12765
|
-
throw new Error(
|
12960
|
+
throw new Error('invalid private key, expected hex or ' + nByteLength + ' bytes, got ' + typeof key);
|
12766
12961
|
}
|
12767
12962
|
if (wrapPrivateKey)
|
12768
12963
|
num = mod(num, N); // disabled by default, enabled for BLS
|
@@ -12802,7 +12997,7 @@ function weierstrassPoints(opts) {
|
|
12802
12997
|
if (p.is0()) {
|
12803
12998
|
// (0, 1, 0) aka ZERO is invalid in most contexts.
|
12804
12999
|
// In BLS, ZERO can be serialized, so we allow it.
|
12805
|
-
// (0, 0, 0) is
|
13000
|
+
// (0, 0, 0) is invalid representation of ZERO.
|
12806
13001
|
if (CURVE.allowInfinityPoint && !Fp.is0(p.py))
|
12807
13002
|
return;
|
12808
13003
|
throw new Error('bad point: ZERO');
|
@@ -13026,16 +13221,17 @@ function weierstrassPoints(opts) {
|
|
13026
13221
|
* an exposed private key e.g. sig verification, which works over *public* keys.
|
13027
13222
|
*/
|
13028
13223
|
multiplyUnsafe(sc) {
|
13029
|
-
|
13224
|
+
const { endo, n: N } = CURVE;
|
13225
|
+
aInRange('scalar', sc, _0n, N);
|
13030
13226
|
const I = Point.ZERO;
|
13031
13227
|
if (sc === _0n)
|
13032
13228
|
return I;
|
13033
|
-
if (sc === _1n$1)
|
13229
|
+
if (this.is0() || sc === _1n$1)
|
13034
13230
|
return this;
|
13035
|
-
|
13036
|
-
if (!endo)
|
13037
|
-
return wnaf.
|
13038
|
-
//
|
13231
|
+
// Case a: no endomorphism. Case b: has precomputes.
|
13232
|
+
if (!endo || wnaf.hasPrecomputes(this))
|
13233
|
+
return wnaf.wNAFCachedUnsafe(this, sc, Point.normalizeZ);
|
13234
|
+
// Case c: endomorphism
|
13039
13235
|
let { k1neg, k1, k2neg, k2 } = endo.splitScalar(sc);
|
13040
13236
|
let k1p = I;
|
13041
13237
|
let k2p = I;
|
@@ -13221,7 +13417,9 @@ function weierstrass(curveDef) {
|
|
13221
13417
|
return { x, y };
|
13222
13418
|
}
|
13223
13419
|
else {
|
13224
|
-
|
13420
|
+
const cl = compressedLen;
|
13421
|
+
const ul = uncompressedLen;
|
13422
|
+
throw new Error('invalid Point, expected length of ' + cl + ', or uncompressed ' + ul + ', got ' + len);
|
13225
13423
|
}
|
13226
13424
|
},
|
13227
13425
|
});
|
@@ -13386,6 +13584,9 @@ function weierstrass(curveDef) {
|
|
13386
13584
|
// int2octets can't be used; pads small msgs with 0: unacceptatble for trunc as per RFC vectors
|
13387
13585
|
const bits2int = CURVE.bits2int ||
|
13388
13586
|
function (bytes) {
|
13587
|
+
// Our custom check "just in case"
|
13588
|
+
if (bytes.length > 8192)
|
13589
|
+
throw new Error('input is too large');
|
13389
13590
|
// For curves with nBitLength % 8 !== 0: bits2octets(bits2octets(m)) !== bits2octets(m)
|
13390
13591
|
// for some cases, since bytes.length * 8 is not actual bitLength.
|
13391
13592
|
const num = bytesToNumberBE(bytes); // check for == u8 done here
|
@@ -13402,15 +13603,15 @@ function weierstrass(curveDef) {
|
|
13402
13603
|
* Converts to bytes. Checks if num in `[0..ORDER_MASK-1]` e.g.: `[0..2^256-1]`.
|
13403
13604
|
*/
|
13404
13605
|
function int2octets(num) {
|
13405
|
-
aInRange(
|
13606
|
+
aInRange('num < 2^' + CURVE.nBitLength, num, _0n, ORDER_MASK);
|
13406
13607
|
// works with order, can have different size than numToField!
|
13407
13608
|
return numberToBytesBE(num, CURVE.nByteLength);
|
13408
13609
|
}
|
13409
13610
|
// Steps A, D of RFC6979 3.2
|
13410
13611
|
// Creates RFC6979 seed; converts msg/privKey to numbers.
|
13411
13612
|
// Used only in sign, not in verify.
|
13412
|
-
// NOTE: we cannot assume here that msgHash has same amount of bytes as curve order,
|
13413
|
-
// Also it can be bigger for P224 + SHA256
|
13613
|
+
// NOTE: we cannot assume here that msgHash has same amount of bytes as curve order,
|
13614
|
+
// this will be invalid at least for P521. Also it can be bigger for P224 + SHA256
|
13414
13615
|
function prepSig(msgHash, privateKey, opts = defaultSigOpts) {
|
13415
13616
|
if (['recovered', 'canonical'].some((k) => k in opts))
|
13416
13617
|
throw new Error('sign() legacy options not supported');
|
@@ -13504,39 +13705,48 @@ function weierstrass(curveDef) {
|
|
13504
13705
|
const sg = signature;
|
13505
13706
|
msgHash = ensureBytes('msgHash', msgHash);
|
13506
13707
|
publicKey = ensureBytes('publicKey', publicKey);
|
13708
|
+
const { lowS, prehash, format } = opts;
|
13709
|
+
// Verify opts, deduce signature format
|
13710
|
+
validateSigVerOpts(opts);
|
13507
13711
|
if ('strict' in opts)
|
13508
13712
|
throw new Error('options.strict was renamed to lowS');
|
13509
|
-
|
13510
|
-
|
13713
|
+
if (format !== undefined && format !== 'compact' && format !== 'der')
|
13714
|
+
throw new Error('format must be compact or der');
|
13715
|
+
const isHex = typeof sg === 'string' || isBytes$1(sg);
|
13716
|
+
const isObj = !isHex &&
|
13717
|
+
!format &&
|
13718
|
+
typeof sg === 'object' &&
|
13719
|
+
sg !== null &&
|
13720
|
+
typeof sg.r === 'bigint' &&
|
13721
|
+
typeof sg.s === 'bigint';
|
13722
|
+
if (!isHex && !isObj)
|
13723
|
+
throw new Error('invalid signature, expected Uint8Array, hex string or Signature instance');
|
13511
13724
|
let _sig = undefined;
|
13512
13725
|
let P;
|
13513
13726
|
try {
|
13514
|
-
if (
|
13727
|
+
if (isObj)
|
13728
|
+
_sig = new Signature(sg.r, sg.s);
|
13729
|
+
if (isHex) {
|
13515
13730
|
// Signature can be represented in 2 ways: compact (2*nByteLength) & DER (variable-length).
|
13516
13731
|
// Since DER can also be 2*nByteLength bytes, we check for it first.
|
13517
13732
|
try {
|
13518
|
-
|
13733
|
+
if (format !== 'compact')
|
13734
|
+
_sig = Signature.fromDER(sg);
|
13519
13735
|
}
|
13520
13736
|
catch (derError) {
|
13521
13737
|
if (!(derError instanceof DER.Err))
|
13522
13738
|
throw derError;
|
13523
|
-
_sig = Signature.fromCompact(sg);
|
13524
13739
|
}
|
13525
|
-
|
13526
|
-
|
13527
|
-
const { r, s } = sg;
|
13528
|
-
_sig = new Signature(r, s);
|
13529
|
-
}
|
13530
|
-
else {
|
13531
|
-
throw new Error('PARSE');
|
13740
|
+
if (!_sig && format !== 'der')
|
13741
|
+
_sig = Signature.fromCompact(sg);
|
13532
13742
|
}
|
13533
13743
|
P = Point.fromHex(publicKey);
|
13534
13744
|
}
|
13535
13745
|
catch (error) {
|
13536
|
-
if (error.message === 'PARSE')
|
13537
|
-
throw new Error(`signature must be Signature instance, Uint8Array or hex string`);
|
13538
13746
|
return false;
|
13539
13747
|
}
|
13748
|
+
if (!_sig)
|
13749
|
+
return false;
|
13540
13750
|
if (lowS && _sig.hasHighS())
|
13541
13751
|
return false;
|
13542
13752
|
if (prehash)
|
@@ -13564,8 +13774,12 @@ function weierstrass(curveDef) {
|
|
13564
13774
|
};
|
13565
13775
|
}
|
13566
13776
|
|
13777
|
+
/**
|
13778
|
+
* Utilities for short weierstrass curves, combined with noble-hashes.
|
13779
|
+
* @module
|
13780
|
+
*/
|
13567
13781
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
13568
|
-
|
13782
|
+
/** connects noble-curves to noble-hashes */
|
13569
13783
|
function getHash(hash) {
|
13570
13784
|
return {
|
13571
13785
|
hash,
|
@@ -13575,9 +13789,21 @@ function getHash(hash) {
|
|
13575
13789
|
}
|
13576
13790
|
function createCurve(curveDef, defHash) {
|
13577
13791
|
const create = (hash) => weierstrass({ ...curveDef, ...getHash(hash) });
|
13578
|
-
return
|
13792
|
+
return { ...create(defHash), create };
|
13579
13793
|
}
|
13580
13794
|
|
13795
|
+
/**
|
13796
|
+
* NIST secp256k1. See [pdf](https://www.secg.org/sec2-v2.pdf).
|
13797
|
+
*
|
13798
|
+
* Seems to be rigid (not backdoored)
|
13799
|
+
* [as per discussion](https://bitcointalk.org/index.php?topic=289795.msg3183975#msg3183975).
|
13800
|
+
*
|
13801
|
+
* secp256k1 belongs to Koblitz curves: it has efficiently computable endomorphism.
|
13802
|
+
* Endomorphism uses 2x less RAM, speeds up precomputation by 2x and ECDH / key recovery by 20%.
|
13803
|
+
* For precomputed wNAF it trades off 1/2 init time & 1/3 ram for 20% perf hit.
|
13804
|
+
* [See explanation](https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066).
|
13805
|
+
* @module
|
13806
|
+
*/
|
13581
13807
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
13582
13808
|
const secp256k1P = BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f');
|
13583
13809
|
const secp256k1N = BigInt('0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141');
|
@@ -13608,31 +13834,35 @@ function sqrtMod(y) {
|
|
13608
13834
|
const t1 = (pow2(b223, _23n, P) * b22) % P;
|
13609
13835
|
const t2 = (pow2(t1, _6n, P) * b2) % P;
|
13610
13836
|
const root = pow2(t2, _2n, P);
|
13611
|
-
if (!
|
13837
|
+
if (!Fpk1.eql(Fpk1.sqr(root), y))
|
13612
13838
|
throw new Error('Cannot find square root');
|
13613
13839
|
return root;
|
13614
13840
|
}
|
13615
|
-
const
|
13841
|
+
const Fpk1 = Field(secp256k1P, undefined, undefined, { sqrt: sqrtMod });
|
13616
13842
|
/**
|
13617
13843
|
* secp256k1 short weierstrass curve and ECDSA signatures over it.
|
13844
|
+
*
|
13845
|
+
* @example
|
13846
|
+
* import { secp256k1 } from '@noble/curves/secp256k1';
|
13847
|
+
*
|
13848
|
+
* const priv = secp256k1.utils.randomPrivateKey();
|
13849
|
+
* const pub = secp256k1.getPublicKey(priv);
|
13850
|
+
* const msg = new Uint8Array(32).fill(1); // message hash (not message) in ecdsa
|
13851
|
+
* const sig = secp256k1.sign(msg, priv); // `{prehash: true}` option is available
|
13852
|
+
* const isValid = secp256k1.verify(sig, msg, pub) === true;
|
13618
13853
|
*/
|
13619
13854
|
const secp256k1 = createCurve({
|
13620
13855
|
a: BigInt(0), // equation params: a, b
|
13621
|
-
b: BigInt(7),
|
13622
|
-
Fp, // Field's prime: 2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n
|
13856
|
+
b: BigInt(7),
|
13857
|
+
Fp: Fpk1, // Field's prime: 2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n
|
13623
13858
|
n: secp256k1N, // Curve order, total count of valid points in the field
|
13624
13859
|
// Base point (x, y) aka generator point
|
13625
13860
|
Gx: BigInt('55066263022277343669578718895168534326250603453777594175500187360389116729240'),
|
13626
13861
|
Gy: BigInt('32670510020758816978083085130507043184471273380659243275938904335757337482424'),
|
13627
13862
|
h: BigInt(1), // Cofactor
|
13628
13863
|
lowS: true, // Allow only low-S signatures by default in sign() and verify()
|
13629
|
-
/**
|
13630
|
-
* secp256k1 belongs to Koblitz curves: it has efficiently computable endomorphism.
|
13631
|
-
* Endomorphism uses 2x less RAM, speeds up precomputation by 2x and ECDH / key recovery by 20%.
|
13632
|
-
* For precomputed wNAF it trades off 1/2 init time & 1/3 ram for 20% perf hit.
|
13633
|
-
* Explanation: https://gist.github.com/paulmillr/eb670806793e84df628a7c434a873066
|
13634
|
-
*/
|
13635
13864
|
endo: {
|
13865
|
+
// Endomorphism, see above
|
13636
13866
|
beta: BigInt('0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee'),
|
13637
13867
|
splitScalar: (k) => {
|
13638
13868
|
const n = secp256k1N;
|
@@ -13775,7 +14005,7 @@ function publicKeyFromMultihash(digest) {
|
|
13775
14005
|
case KeyType.secp256k1:
|
13776
14006
|
return unmarshalSecp256k1PublicKey(data);
|
13777
14007
|
default:
|
13778
|
-
throw new UnsupportedKeyTypeError
|
14008
|
+
throw new UnsupportedKeyTypeError();
|
13779
14009
|
}
|
13780
14010
|
}
|
13781
14011
|
/**
|
@@ -13788,28 +14018,6 @@ function publicKeyToProtobuf(key) {
|
|
13788
14018
|
});
|
13789
14019
|
}
|
13790
14020
|
|
13791
|
-
/**
|
13792
|
-
* All PeerId implementations must use this symbol as the name of a property
|
13793
|
-
* with a boolean `true` value
|
13794
|
-
*/
|
13795
|
-
const peerIdSymbol = Symbol.for('@libp2p/peer-id');
|
13796
|
-
|
13797
|
-
/**
|
13798
|
-
* When this error is thrown it means an operation was aborted,
|
13799
|
-
* usually in response to the `abort` event being emitted by an
|
13800
|
-
* AbortSignal.
|
13801
|
-
*/
|
13802
|
-
/**
|
13803
|
-
* Thrown when and attempt to operate on an unsupported key was made
|
13804
|
-
*/
|
13805
|
-
class UnsupportedKeyTypeError extends Error {
|
13806
|
-
static name = 'UnsupportedKeyTypeError';
|
13807
|
-
constructor(message = 'Unsupported key type') {
|
13808
|
-
super(message);
|
13809
|
-
this.name = 'UnsupportedKeyTypeError';
|
13810
|
-
}
|
13811
|
-
}
|
13812
|
-
|
13813
14021
|
/**
|
13814
14022
|
* @packageDocumentation
|
13815
14023
|
*
|
@@ -13933,7 +14141,7 @@ let Secp256k1PeerId$1 = class Secp256k1PeerId extends PeerIdImpl$1 {
|
|
13933
14141
|
*
|
13934
14142
|
* ```TypeScript
|
13935
14143
|
* import { peerIdFromString } from '@libp2p/peer-id'
|
13936
|
-
* const peer = peerIdFromString('
|
14144
|
+
* const peer = peerIdFromString('12D3KooWKnDdG3iXw9eTFijk3EWSunZcFi54Zka4wmtqtt6rPxc8')
|
13937
14145
|
*
|
13938
14146
|
* console.log(peer.toCID()) // CID(bafzaa...)
|
13939
14147
|
* console.log(peer.toString()) // "12D3K..."
|
@@ -15668,9 +15876,9 @@ function _copyActual (source, target, targetStart, sourceStart, sourceEnd) {
|
|
15668
15876
|
const QUERY_FLAG = 0;
|
15669
15877
|
const RESPONSE_FLAG = 1 << 15;
|
15670
15878
|
const FLUSH_MASK = 1 << 15;
|
15671
|
-
const NOT_FLUSH_MASK =
|
15879
|
+
const NOT_FLUSH_MASK = -32769;
|
15672
15880
|
const QU_MASK = 1 << 15;
|
15673
|
-
const NOT_QU_MASK =
|
15881
|
+
const NOT_QU_MASK = -32769;
|
15674
15882
|
|
15675
15883
|
function codec ({ bytes = 0, encode, decode, encodingLength }) {
|
15676
15884
|
encode.bytes = bytes;
|
@@ -20055,86 +20263,6 @@ function wakuDnsDiscovery(enrUrls, wantedNodeCapabilityCount = DEFAULT_NODE_REQU
|
|
20055
20263
|
return (components) => new PeerDiscoveryDns(components, { enrUrls, wantedNodeCapabilityCount });
|
20056
20264
|
}
|
20057
20265
|
|
20058
|
-
/**
|
20059
|
-
* Function to sort peers by latency from lowest to highest
|
20060
|
-
* @param peerStore - The Libp2p PeerStore
|
20061
|
-
* @param peers - The list of peers to choose from
|
20062
|
-
* @returns Sorted array of peers by latency
|
20063
|
-
*/
|
20064
|
-
async function sortPeersByLatency(peerStore, peers) {
|
20065
|
-
if (peers.length === 0)
|
20066
|
-
return [];
|
20067
|
-
const results = await Promise.all(peers.map(async (peer) => {
|
20068
|
-
try {
|
20069
|
-
const pingBytes = (await peerStore.get(peer.id)).metadata.get("ping");
|
20070
|
-
if (!pingBytes)
|
20071
|
-
return { peer, ping: Infinity };
|
20072
|
-
const ping = Number(bytesToUtf8(pingBytes));
|
20073
|
-
return { peer, ping };
|
20074
|
-
}
|
20075
|
-
catch (error) {
|
20076
|
-
return { peer, ping: Infinity };
|
20077
|
-
}
|
20078
|
-
}));
|
20079
|
-
// filter out null values
|
20080
|
-
const validResults = results.filter((result) => result !== null);
|
20081
|
-
return validResults
|
20082
|
-
.sort((a, b) => a.ping - b.ping)
|
20083
|
-
.map((result) => result.peer);
|
20084
|
-
}
|
20085
|
-
/**
|
20086
|
-
* Returns the list of peers that supports the given protocol.
|
20087
|
-
*/
|
20088
|
-
async function getPeersForProtocol(peerStore, protocols) {
|
20089
|
-
const peers = [];
|
20090
|
-
await peerStore.forEach((peer) => {
|
20091
|
-
for (let i = 0; i < protocols.length; i++) {
|
20092
|
-
if (peer.protocols.includes(protocols[i])) {
|
20093
|
-
peers.push(peer);
|
20094
|
-
break;
|
20095
|
-
}
|
20096
|
-
}
|
20097
|
-
});
|
20098
|
-
return peers;
|
20099
|
-
}
|
20100
|
-
|
20101
|
-
/**
|
20102
|
-
* Retrieves a list of peers based on the specified criteria:
|
20103
|
-
* 1. If numPeers is 0, return all peers
|
20104
|
-
* 2. Bootstrap peers are prioritized
|
20105
|
-
* 3. Non-bootstrap peers are randomly selected to fill up to numPeers
|
20106
|
-
*
|
20107
|
-
* @param peers - The list of peers to filter from.
|
20108
|
-
* @param numPeers - The total number of peers to retrieve. If 0, all peers are returned, irrespective of `maxBootstrapPeers`.
|
20109
|
-
* @param maxBootstrapPeers - The maximum number of bootstrap peers to retrieve.
|
20110
|
-
* @returns An array of peers based on the specified criteria.
|
20111
|
-
*/
|
20112
|
-
function filterPeersByDiscovery(peers, numPeers, maxBootstrapPeers) {
|
20113
|
-
// Collect the bootstrap peers up to the specified maximum
|
20114
|
-
let bootstrapPeers = peers
|
20115
|
-
.filter((peer) => peer.tags.has(Tags.BOOTSTRAP))
|
20116
|
-
.slice(0, maxBootstrapPeers);
|
20117
|
-
// If numPeers is less than the number of bootstrap peers, adjust the bootstrapPeers array
|
20118
|
-
if (numPeers > 0 && numPeers < bootstrapPeers.length) {
|
20119
|
-
bootstrapPeers = bootstrapPeers.slice(0, numPeers);
|
20120
|
-
}
|
20121
|
-
// Collect non-bootstrap peers
|
20122
|
-
const nonBootstrapPeers = peers.filter((peer) => !peer.tags.has(Tags.BOOTSTRAP));
|
20123
|
-
// If numPeers is 0, return all peers
|
20124
|
-
if (numPeers === 0) {
|
20125
|
-
return [...bootstrapPeers, ...nonBootstrapPeers];
|
20126
|
-
}
|
20127
|
-
// Initialize the list of selected peers with the bootstrap peers
|
20128
|
-
const selectedPeers = [...bootstrapPeers];
|
20129
|
-
// Fill up to numPeers with remaining random peers if needed
|
20130
|
-
while (selectedPeers.length < numPeers && nonBootstrapPeers.length > 0) {
|
20131
|
-
const randomIndex = Math.floor(Math.random() * nonBootstrapPeers.length);
|
20132
|
-
const randomPeer = nonBootstrapPeers.splice(randomIndex, 1)[0];
|
20133
|
-
selectedPeers.push(randomPeer);
|
20134
|
-
}
|
20135
|
-
return selectedPeers;
|
20136
|
-
}
|
20137
|
-
|
20138
20266
|
function selectOpenConnection(connections) {
|
20139
20267
|
return connections
|
20140
20268
|
.filter((c) => c.status === "open")
|
@@ -20157,36 +20285,36 @@ class StreamManager {
|
|
20157
20285
|
this.log = new Logger$1(`stream-manager:${multicodec}`);
|
20158
20286
|
this.addEventListener("peer:update", this.handlePeerUpdateStreamPool);
|
20159
20287
|
}
|
20160
|
-
async getStream(
|
20161
|
-
const
|
20162
|
-
const scheduledStream = this.streamPool.get(
|
20288
|
+
async getStream(peerId) {
|
20289
|
+
const peerIdStr = peerId.toString();
|
20290
|
+
const scheduledStream = this.streamPool.get(peerIdStr);
|
20163
20291
|
if (scheduledStream) {
|
20164
|
-
this.streamPool.delete(
|
20292
|
+
this.streamPool.delete(peerIdStr);
|
20165
20293
|
await scheduledStream;
|
20166
20294
|
}
|
20167
|
-
let stream = this.getOpenStreamForCodec(
|
20295
|
+
let stream = this.getOpenStreamForCodec(peerId);
|
20168
20296
|
if (stream) {
|
20169
|
-
this.log.info(`Found existing stream peerId=${
|
20170
|
-
this.lockStream(
|
20297
|
+
this.log.info(`Found existing stream peerId=${peerIdStr} multicodec=${this.multicodec}`);
|
20298
|
+
this.lockStream(peerIdStr, stream);
|
20171
20299
|
return stream;
|
20172
20300
|
}
|
20173
|
-
stream = await this.createStream(
|
20174
|
-
this.lockStream(
|
20301
|
+
stream = await this.createStream(peerId);
|
20302
|
+
this.lockStream(peerIdStr, stream);
|
20175
20303
|
return stream;
|
20176
20304
|
}
|
20177
|
-
async createStream(
|
20178
|
-
const connections = this.getConnections(
|
20305
|
+
async createStream(peerId, retries = 0) {
|
20306
|
+
const connections = this.getConnections(peerId);
|
20179
20307
|
const connection = selectOpenConnection(connections);
|
20180
20308
|
if (!connection) {
|
20181
|
-
throw new Error(`Failed to get a connection to the peer peerId=${
|
20309
|
+
throw new Error(`Failed to get a connection to the peer peerId=${peerId.toString()} multicodec=${this.multicodec}`);
|
20182
20310
|
}
|
20183
20311
|
let lastError;
|
20184
20312
|
let stream;
|
20185
20313
|
for (let i = 0; i < retries + 1; i++) {
|
20186
20314
|
try {
|
20187
|
-
this.log.info(`Attempting to create a stream for peerId=${
|
20315
|
+
this.log.info(`Attempting to create a stream for peerId=${peerId.toString()} multicodec=${this.multicodec}`);
|
20188
20316
|
stream = await connection.newStream(this.multicodec);
|
20189
|
-
this.log.info(`Created stream for peerId=${
|
20317
|
+
this.log.info(`Created stream for peerId=${peerId.toString()} multicodec=${this.multicodec}`);
|
20190
20318
|
break;
|
20191
20319
|
}
|
20192
20320
|
catch (error) {
|
@@ -20194,8 +20322,7 @@ class StreamManager {
|
|
20194
20322
|
}
|
20195
20323
|
}
|
20196
20324
|
if (!stream) {
|
20197
|
-
throw new Error(`Failed to create a new stream for ${
|
20198
|
-
lastError);
|
20325
|
+
throw new Error(`Failed to create a new stream for ${peerId.toString()} -- ` + lastError);
|
20199
20326
|
}
|
20200
20327
|
return stream;
|
20201
20328
|
}
|
@@ -20207,7 +20334,7 @@ class StreamManager {
|
|
20207
20334
|
}
|
20208
20335
|
try {
|
20209
20336
|
this.ongoingCreation.add(peerId);
|
20210
|
-
await this.createStream(peer);
|
20337
|
+
await this.createStream(peer.id);
|
20211
20338
|
}
|
20212
20339
|
catch (error) {
|
20213
20340
|
this.log.error(`Failed to createStreamWithLock:`, error);
|
@@ -20268,70 +20395,20 @@ class StreamManager {
|
|
20268
20395
|
class BaseProtocol {
|
20269
20396
|
multicodec;
|
20270
20397
|
components;
|
20271
|
-
log;
|
20272
20398
|
pubsubTopics;
|
20273
20399
|
addLibp2pEventListener;
|
20274
20400
|
removeLibp2pEventListener;
|
20275
20401
|
streamManager;
|
20276
|
-
constructor(multicodec, components,
|
20402
|
+
constructor(multicodec, components, pubsubTopics) {
|
20277
20403
|
this.multicodec = multicodec;
|
20278
20404
|
this.components = components;
|
20279
|
-
this.log = log;
|
20280
20405
|
this.pubsubTopics = pubsubTopics;
|
20281
20406
|
this.addLibp2pEventListener = components.events.addEventListener.bind(components.events);
|
20282
20407
|
this.removeLibp2pEventListener = components.events.removeEventListener.bind(components.events);
|
20283
20408
|
this.streamManager = new StreamManager(multicodec, components.connectionManager.getConnections.bind(components.connectionManager), this.addLibp2pEventListener);
|
20284
20409
|
}
|
20285
|
-
async getStream(
|
20286
|
-
return this.streamManager.getStream(
|
20287
|
-
}
|
20288
|
-
/**
|
20289
|
-
* Returns known peers from the address book (`libp2p.peerStore`) that support
|
20290
|
-
* the class protocol. Waku may or may not be currently connected to these
|
20291
|
-
* peers.
|
20292
|
-
*/
|
20293
|
-
async allPeers() {
|
20294
|
-
return getPeersForProtocol(this.components.peerStore, [this.multicodec]);
|
20295
|
-
}
|
20296
|
-
async connectedPeers() {
|
20297
|
-
const peers = await this.allPeers();
|
20298
|
-
return peers.filter((peer) => {
|
20299
|
-
const connections = this.components.connectionManager.getConnections(peer.id);
|
20300
|
-
return connections.length > 0;
|
20301
|
-
});
|
20302
|
-
}
|
20303
|
-
/**
|
20304
|
-
* Retrieves a list of connected peers that support the protocol. The list is sorted by latency.
|
20305
|
-
*
|
20306
|
-
* @param numPeers - The total number of peers to retrieve. If 0, all peers are returned.
|
20307
|
-
* @param maxBootstrapPeers - The maximum number of bootstrap peers to retrieve.
|
20308
|
-
* @returns A list of peers that support the protocol sorted by latency. By default, returns all peers available, including bootstrap.
|
20309
|
-
*/
|
20310
|
-
async getPeers({ numPeers, maxBootstrapPeers, peerIdStr } = {
|
20311
|
-
maxBootstrapPeers: 0,
|
20312
|
-
numPeers: 0
|
20313
|
-
}) {
|
20314
|
-
if (peerIdStr) {
|
20315
|
-
const peer = (await this.connectedPeers()).find((p) => p.id.toString() === peerIdStr);
|
20316
|
-
if (peer) {
|
20317
|
-
return [peer];
|
20318
|
-
}
|
20319
|
-
this.log.warn(`Passed node to use for ${this.multicodec} not found: ${peerIdStr}. Attempting to use random peers.`);
|
20320
|
-
return this.getPeers({ numPeers, maxBootstrapPeers });
|
20321
|
-
}
|
20322
|
-
// Retrieve all connected peers that support the protocol & shard (if configured)
|
20323
|
-
const allAvailableConnectedPeers = await this.connectedPeers();
|
20324
|
-
// Filter the peers based on discovery & number of peers requested
|
20325
|
-
const filteredPeers = filterPeersByDiscovery(allAvailableConnectedPeers, numPeers, maxBootstrapPeers);
|
20326
|
-
// Sort the peers by latency
|
20327
|
-
const sortedFilteredPeers = await sortPeersByLatency(this.components.peerStore, filteredPeers);
|
20328
|
-
if (sortedFilteredPeers.length === 0) {
|
20329
|
-
this.log.warn("No peers found. Ensure you have a connection to the network.");
|
20330
|
-
}
|
20331
|
-
if (sortedFilteredPeers.length < numPeers) {
|
20332
|
-
this.log.warn(`Only ${sortedFilteredPeers.length} peers found. Requested ${numPeers}.`);
|
20333
|
-
}
|
20334
|
-
return sortedFilteredPeers;
|
20410
|
+
async getStream(peerId) {
|
20411
|
+
return this.streamManager.getStream(peerId);
|
20335
20412
|
}
|
20336
20413
|
}
|
20337
20414
|
|
@@ -23958,6 +24035,105 @@ var WakuMetadataResponse;
|
|
23958
24035
|
};
|
23959
24036
|
})(WakuMetadataResponse || (WakuMetadataResponse = {}));
|
23960
24037
|
|
24038
|
+
/* eslint-disable import/export */
|
24039
|
+
/* eslint-disable complexity */
|
24040
|
+
/* eslint-disable @typescript-eslint/no-namespace */
|
24041
|
+
/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */
|
24042
|
+
/* eslint-disable @typescript-eslint/no-empty-interface */
|
24043
|
+
var SdsMessage;
|
24044
|
+
(function (SdsMessage) {
|
24045
|
+
let _codec;
|
24046
|
+
SdsMessage.codec = () => {
|
24047
|
+
if (_codec == null) {
|
24048
|
+
_codec = message((obj, w, opts = {}) => {
|
24049
|
+
if (opts.lengthDelimited !== false) {
|
24050
|
+
w.fork();
|
24051
|
+
}
|
24052
|
+
if ((obj.messageId != null && obj.messageId !== '')) {
|
24053
|
+
w.uint32(18);
|
24054
|
+
w.string(obj.messageId);
|
24055
|
+
}
|
24056
|
+
if ((obj.channelId != null && obj.channelId !== '')) {
|
24057
|
+
w.uint32(26);
|
24058
|
+
w.string(obj.channelId);
|
24059
|
+
}
|
24060
|
+
if (obj.lamportTimestamp != null) {
|
24061
|
+
w.uint32(80);
|
24062
|
+
w.int32(obj.lamportTimestamp);
|
24063
|
+
}
|
24064
|
+
if (obj.causalHistory != null) {
|
24065
|
+
for (const value of obj.causalHistory) {
|
24066
|
+
w.uint32(90);
|
24067
|
+
w.string(value);
|
24068
|
+
}
|
24069
|
+
}
|
24070
|
+
if (obj.bloomFilter != null) {
|
24071
|
+
w.uint32(98);
|
24072
|
+
w.bytes(obj.bloomFilter);
|
24073
|
+
}
|
24074
|
+
if (obj.content != null) {
|
24075
|
+
w.uint32(162);
|
24076
|
+
w.bytes(obj.content);
|
24077
|
+
}
|
24078
|
+
if (opts.lengthDelimited !== false) {
|
24079
|
+
w.ldelim();
|
24080
|
+
}
|
24081
|
+
}, (reader, length, opts = {}) => {
|
24082
|
+
const obj = {
|
24083
|
+
messageId: '',
|
24084
|
+
channelId: '',
|
24085
|
+
causalHistory: []
|
24086
|
+
};
|
24087
|
+
const end = length == null ? reader.len : reader.pos + length;
|
24088
|
+
while (reader.pos < end) {
|
24089
|
+
const tag = reader.uint32();
|
24090
|
+
switch (tag >>> 3) {
|
24091
|
+
case 2: {
|
24092
|
+
obj.messageId = reader.string();
|
24093
|
+
break;
|
24094
|
+
}
|
24095
|
+
case 3: {
|
24096
|
+
obj.channelId = reader.string();
|
24097
|
+
break;
|
24098
|
+
}
|
24099
|
+
case 10: {
|
24100
|
+
obj.lamportTimestamp = reader.int32();
|
24101
|
+
break;
|
24102
|
+
}
|
24103
|
+
case 11: {
|
24104
|
+
if (opts.limits?.causalHistory != null && obj.causalHistory.length === opts.limits.causalHistory) {
|
24105
|
+
throw new MaxLengthError('Decode error - map field "causalHistory" had too many elements');
|
24106
|
+
}
|
24107
|
+
obj.causalHistory.push(reader.string());
|
24108
|
+
break;
|
24109
|
+
}
|
24110
|
+
case 12: {
|
24111
|
+
obj.bloomFilter = reader.bytes();
|
24112
|
+
break;
|
24113
|
+
}
|
24114
|
+
case 20: {
|
24115
|
+
obj.content = reader.bytes();
|
24116
|
+
break;
|
24117
|
+
}
|
24118
|
+
default: {
|
24119
|
+
reader.skipType(tag & 7);
|
24120
|
+
break;
|
24121
|
+
}
|
24122
|
+
}
|
24123
|
+
}
|
24124
|
+
return obj;
|
24125
|
+
});
|
24126
|
+
}
|
24127
|
+
return _codec;
|
24128
|
+
};
|
24129
|
+
SdsMessage.encode = (obj) => {
|
24130
|
+
return encodeMessage(obj, SdsMessage.codec());
|
24131
|
+
};
|
24132
|
+
SdsMessage.decode = (buf, opts) => {
|
24133
|
+
return decodeMessage(buf, SdsMessage.codec(), opts);
|
24134
|
+
};
|
24135
|
+
})(SdsMessage || (SdsMessage = {}));
|
24136
|
+
|
23961
24137
|
/**
|
23962
24138
|
* PeerExchangeRPC represents a message conforming to the Waku Peer Exchange protocol
|
23963
24139
|
*/
|
@@ -24008,7 +24184,7 @@ class WakuPeerExchange extends BaseProtocol {
|
|
24008
24184
|
* @param components - libp2p components
|
24009
24185
|
*/
|
24010
24186
|
constructor(components, pubsubTopics) {
|
24011
|
-
super(PeerExchangeCodec, components,
|
24187
|
+
super(PeerExchangeCodec, components, pubsubTopics);
|
24012
24188
|
}
|
24013
24189
|
/**
|
24014
24190
|
* Make a peer exchange query to a peer
|
@@ -24027,7 +24203,7 @@ class WakuPeerExchange extends BaseProtocol {
|
|
24027
24203
|
}
|
24028
24204
|
let stream;
|
24029
24205
|
try {
|
24030
|
-
stream = await this.getStream(
|
24206
|
+
stream = await this.getStream(peerId);
|
24031
24207
|
}
|
24032
24208
|
catch (err) {
|
24033
24209
|
log$2.error("Failed to get stream", err);
|
@@ -24242,7 +24418,7 @@ class PeerExchangeDiscovery extends TypedEventEmitter {
|
|
24242
24418
|
const existingShardInfoBytes = peer.metadata.get("shardInfo");
|
24243
24419
|
if (existingShardInfoBytes) {
|
24244
24420
|
const existingShardInfo = decodeRelayShard(existingShardInfoBytes);
|
24245
|
-
|
24421
|
+
{
|
24246
24422
|
hasShardDiff =
|
24247
24423
|
existingShardInfo.clusterId !== shardInfo?.clusterId ||
|
24248
24424
|
existingShardInfo.shards.some((shard) => !shardInfo?.shards.includes(shard));
|
@@ -24290,7 +24466,7 @@ class PeerIdImpl {
|
|
24290
24466
|
get [Symbol.toStringTag]() {
|
24291
24467
|
return `PeerId(${this.toString()})`;
|
24292
24468
|
}
|
24293
|
-
[peerIdSymbol
|
24469
|
+
[peerIdSymbol] = true;
|
24294
24470
|
toString() {
|
24295
24471
|
if (this.string == null) {
|
24296
24472
|
this.string = base58btc.encode(this.multihash.bytes).slice(1);
|
@@ -24382,7 +24558,7 @@ class URLPeerId {
|
|
24382
24558
|
[inspect]() {
|
24383
24559
|
return `PeerId(${this.url})`;
|
24384
24560
|
}
|
24385
|
-
[peerIdSymbol
|
24561
|
+
[peerIdSymbol] = true;
|
24386
24562
|
toString() {
|
24387
24563
|
return this.toCID().toString();
|
24388
24564
|
}
|
@@ -24430,7 +24606,7 @@ function peerIdFromString(str, decoder) {
|
|
24430
24606
|
}
|
24431
24607
|
else {
|
24432
24608
|
{
|
24433
|
-
throw new InvalidParametersError
|
24609
|
+
throw new InvalidParametersError('Please pass a multibase decoder for strings that do not start with "1" or "Q"');
|
24434
24610
|
}
|
24435
24611
|
}
|
24436
24612
|
return peerIdFromMultihash(multihash);
|