@vbyte/btc-dev 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/LICENSE +21 -121
  3. package/README.md +36 -227
  4. package/dist/error.d.ts +11 -0
  5. package/dist/error.js +20 -0
  6. package/dist/index.d.ts +1 -0
  7. package/dist/index.js +1 -0
  8. package/dist/lib/address/api.js +3 -2
  9. package/dist/lib/address/encode.js +6 -4
  10. package/dist/lib/address/p2pkh.js +4 -4
  11. package/dist/lib/address/p2sh.js +3 -3
  12. package/dist/lib/address/p2tr.js +3 -3
  13. package/dist/lib/address/p2wpkh.js +4 -4
  14. package/dist/lib/address/p2wsh.js +3 -3
  15. package/dist/lib/address/util.js +3 -1
  16. package/dist/lib/meta/locktime.js +3 -2
  17. package/dist/lib/meta/ref.js +4 -3
  18. package/dist/lib/meta/scribe.js +26 -6
  19. package/dist/lib/meta/sequence.js +8 -7
  20. package/dist/lib/script/decode.js +10 -9
  21. package/dist/lib/script/encode.js +4 -3
  22. package/dist/lib/script/words.js +4 -3
  23. package/dist/lib/sighash/segwit.js +9 -6
  24. package/dist/lib/sighash/taproot.js +7 -4
  25. package/dist/lib/sighash/util.js +4 -3
  26. package/dist/lib/signer/sign.js +7 -6
  27. package/dist/lib/signer/verify.js +8 -9
  28. package/dist/lib/taproot/cblock.js +3 -2
  29. package/dist/lib/taproot/encode.d.ts +1 -1
  30. package/dist/lib/taproot/encode.js +4 -3
  31. package/dist/lib/taproot/parse.js +9 -7
  32. package/dist/lib/taproot/tree.js +3 -2
  33. package/dist/lib/tx/create.js +1 -1
  34. package/dist/lib/tx/decode.js +13 -11
  35. package/dist/lib/tx/encode.js +1 -1
  36. package/dist/lib/tx/parse.js +3 -3
  37. package/dist/lib/tx/size.js +2 -4
  38. package/dist/lib/tx/util.js +2 -3
  39. package/dist/lib/tx/validate.js +36 -8
  40. package/dist/lib/witness/util.js +1 -1
  41. package/dist/main.cjs +1127 -1160
  42. package/dist/main.cjs.map +1 -1
  43. package/dist/module.mjs +1125 -1161
  44. package/dist/module.mjs.map +1 -1
  45. package/dist/package.json +13 -11
  46. package/dist/script.js +10 -12
  47. package/dist/script.js.map +1 -1
  48. package/docs/API.md +1145 -0
  49. package/docs/CONVENTIONS.md +316 -0
  50. package/docs/FAQ.md +396 -0
  51. package/docs/GUIDE.md +1102 -0
  52. package/package.json +13 -11
package/dist/module.mjs CHANGED
@@ -86,7 +86,10 @@ var Check;
86
86
  return true;
87
87
  }
88
88
  else if (Array.isArray(input) &&
89
- input.every(e => typeof e === 'number')) {
89
+ input.every(e => typeof e === 'number' &&
90
+ Number.isInteger(e) &&
91
+ e >= 0 &&
92
+ e <= 255)) {
90
93
  return true;
91
94
  }
92
95
  else {
@@ -96,26 +99,57 @@ var Check;
96
99
  Check.is_bytes = is_bytes;
97
100
  })(Check || (Check = {}));
98
101
 
99
- var Assert$1;
102
+ let ValidationError$1 = class ValidationError extends Error {
103
+ constructor(message) {
104
+ super(message);
105
+ this.name = 'ValidationError';
106
+ }
107
+ };
108
+ class HexValidationError extends ValidationError$1 {
109
+ constructor(message) {
110
+ super(message);
111
+ this.name = 'HexValidationError';
112
+ }
113
+ }
114
+ class ByteRangeError extends ValidationError$1 {
115
+ constructor(message) {
116
+ super(message);
117
+ this.name = 'ByteRangeError';
118
+ }
119
+ }
120
+ class IntegerBoundsError extends ValidationError$1 {
121
+ constructor(message) {
122
+ super(message);
123
+ this.name = 'IntegerBoundsError';
124
+ }
125
+ }
126
+ class SizeError extends ValidationError$1 {
127
+ constructor(message) {
128
+ super(message);
129
+ this.name = 'SizeError';
130
+ }
131
+ }
132
+
133
+ var Assert$2;
100
134
  (function (Assert) {
101
135
  function within_size(data, size) {
102
136
  if (data.length > size) {
103
- throw new TypeError(`Data is larger than array size: ${data.length} > ${size}`);
137
+ throw new SizeError(`Data is larger than array size: ${data.length} > ${size}`);
104
138
  }
105
139
  }
106
140
  Assert.within_size = within_size;
107
141
  function is_hex(hex) {
108
142
  if (hex.match(/[^a-fA-F0-9]/) !== null) {
109
- throw new TypeError(`Invalid characters in hex string: ${hex}`);
143
+ throw new HexValidationError(`Invalid characters in hex string: ${hex}`);
110
144
  }
111
145
  if (hex.length % 2 !== 0) {
112
- throw new Error(`Length of hex string is invalid: ${hex.length}`);
146
+ throw new HexValidationError(`Length of hex string is invalid: ${hex.length}`);
113
147
  }
114
148
  }
115
149
  Assert.is_hex = is_hex;
116
150
  function is_bytes(bytes) {
117
151
  if (!Check.is_bytes(bytes)) {
118
- throw new Error(`Bytes contains invalid elements: ${String(bytes)}`);
152
+ throw new ByteRangeError(`Bytes contains invalid elements: ${String(bytes)}`);
119
153
  }
120
154
  }
121
155
  Assert.is_bytes = is_bytes;
@@ -124,17 +158,17 @@ var Assert$1;
124
158
  JSON.parse(str);
125
159
  }
126
160
  catch {
127
- throw new TypeError('JSON string is invalid!');
161
+ throw new ValidationError$1('JSON string is invalid!');
128
162
  }
129
163
  }
130
164
  Assert.is_json = is_json;
131
165
  function is_safe_int(num) {
132
- if (num > Number.MAX_SAFE_INTEGER) {
133
- throw new TypeError('Number exceeds safe bounds!');
166
+ if (num > Number.MAX_SAFE_INTEGER || num < Number.MIN_SAFE_INTEGER) {
167
+ throw new IntegerBoundsError('Number exceeds safe bounds!');
134
168
  }
135
169
  }
136
170
  Assert.is_safe_int = is_safe_int;
137
- })(Assert$1 || (Assert$1 = {}));
171
+ })(Assert$2 || (Assert$2 = {}));
138
172
 
139
173
  const _0n$7 = BigInt(0);
140
174
  const _255n = BigInt(255);
@@ -228,7 +262,7 @@ function bytes_to_num(bytes) {
228
262
  let num = 0;
229
263
  for (let i = bytes.length - 1; i >= 0; i--) {
230
264
  num = (num * 256) + bytes[i];
231
- Assert$1.is_safe_int(num);
265
+ Assert$2.is_safe_int(num);
232
266
  }
233
267
  return num;
234
268
  }
@@ -259,7 +293,7 @@ function bytes_to_hex(bytes) {
259
293
  return chars;
260
294
  }
261
295
  function get_hex_size(hexstr, size) {
262
- Assert$1.is_hex(hexstr);
296
+ Assert$2.is_hex(hexstr);
263
297
  const len = hexstr.length / 2;
264
298
  if (size === undefined)
265
299
  size = len;
@@ -277,7 +311,7 @@ function buffer(bytes, size, endian) {
277
311
  return create_bytes(bytes, size, endian);
278
312
  }
279
313
  else if (typeof bytes === 'string') {
280
- Assert$1.is_hex(bytes);
314
+ Assert$2.is_hex(bytes);
281
315
  return hex_to_bytes(bytes, size, endian);
282
316
  }
283
317
  else if (typeof bytes === 'bigint') {
@@ -291,7 +325,7 @@ function buffer(bytes, size, endian) {
291
325
  function create_bytes(data, size, endian = 'le') {
292
326
  if (size === undefined)
293
327
  size = data.length;
294
- Assert$1.within_size(data, size);
328
+ Assert$2.within_size(data, size);
295
329
  const buffer = new Uint8Array(size).fill(0);
296
330
  const offset = (endian === 'be') ? 0 : size - data.length;
297
331
  buffer.set(data, offset);
@@ -368,10 +402,14 @@ function bytes_to_str(bytes) {
368
402
  return dc.decode(bytes);
369
403
  }
370
404
 
405
+ const MAX_RANDOM_LENGTH = 1024 * 1024;
371
406
  function get_random_bytes(length = 32) {
372
407
  if (!Number.isInteger(length) || length < 0) {
373
408
  throw new TypeError('Length must be a non-negative integer');
374
409
  }
410
+ if (length > MAX_RANDOM_LENGTH) {
411
+ throw new RangeError(`Length exceeds maximum allowed: ${length} > ${MAX_RANDOM_LENGTH}`);
412
+ }
375
413
  if (crypto &&
376
414
  typeof crypto.getRandomValues === 'function') {
377
415
  return crypto.getRandomValues(new Uint8Array(length));
@@ -404,11 +442,11 @@ class Buff extends Uint8Array {
404
442
  return new Buff(uint, size, endian);
405
443
  }; }
406
444
  static { this.hex = (data, size, endian) => {
407
- Assert$1.is_hex(data);
445
+ Assert$2.is_hex(data);
408
446
  return new Buff(data, size, endian);
409
447
  }; }
410
448
  static { this.bytes = (bytes, size, endian) => {
411
- Assert$1.is_bytes(bytes);
449
+ Assert$2.is_bytes(bytes);
412
450
  return new Buff(bytes, size, endian);
413
451
  }; }
414
452
  static { this.json = (data, replacer) => {
@@ -423,7 +461,15 @@ class Buff extends Uint8Array {
423
461
  return chunks.map(e => new Buff(e));
424
462
  }; }
425
463
  static { this.is_equal = (a, b) => {
426
- return new Buff(a).hex === new Buff(b).hex;
464
+ const buf_a = new Buff(a);
465
+ const buf_b = new Buff(b);
466
+ if (buf_a.length !== buf_b.length)
467
+ return false;
468
+ for (let i = 0; i < buf_a.length; i++) {
469
+ if (buf_a[i] !== buf_b[i])
470
+ return false;
471
+ }
472
+ return true;
427
473
  }; }
428
474
  static { this.is_bytes = Check.is_bytes; }
429
475
  static { this.is_hex = Check.is_hex; }
@@ -492,7 +538,14 @@ class Buff extends Uint8Array {
492
538
  return Buff.join([this, new Buff(data)]);
493
539
  }
494
540
  equals(data) {
495
- return new Buff(data).hex === this.hex;
541
+ const other = new Buff(data);
542
+ if (this.length !== other.length)
543
+ return false;
544
+ for (let i = 0; i < this.length; i++) {
545
+ if (this[i] !== other[i])
546
+ return false;
547
+ }
548
+ return true;
496
549
  }
497
550
  prepend(data) {
498
551
  return Buff.join([new Buff(data), this]);
@@ -541,6 +594,9 @@ class Buff extends Uint8Array {
541
594
  return hex.map(e => Buff.hex(e, size));
542
595
  }
543
596
  static create_varint(num, endian) {
597
+ if (num < 0) {
598
+ throw new Error(`Varint cannot be negative: ${num}`);
599
+ }
544
600
  if (num < 0xFD) {
545
601
  return Buff.num(num, 1);
546
602
  }
@@ -593,6 +649,27 @@ class Stream {
593
649
  }
594
650
  }
595
651
 
652
+ class ValidationError extends Error {
653
+ constructor(message, field) {
654
+ super(message);
655
+ this.name = "ValidationError";
656
+ this.field = field;
657
+ }
658
+ }
659
+ class DecodingError extends Error {
660
+ constructor(message, position) {
661
+ super(message);
662
+ this.name = "DecodingError";
663
+ this.position = position;
664
+ }
665
+ }
666
+ class ConfigError extends Error {
667
+ constructor(message) {
668
+ super(message);
669
+ this.name = "ConfigError";
670
+ }
671
+ }
672
+
596
673
  function is_return_script(script) {
597
674
  const bytes = Buff.bytes(script);
598
675
  return bytes.at(0) === 0x6a;
@@ -647,14 +724,20 @@ function is_opreturn_script(script) {
647
724
  return LOCK_SCRIPT_REGEX.opreturn.test(hex);
648
725
  }
649
726
 
650
- function sort_obj(obj) {
651
- if (obj instanceof Map || Array.isArray(obj) || typeof obj !== 'object') {
727
+ function sort(obj) {
728
+ if (obj === null ||
729
+ obj === undefined ||
730
+ obj instanceof Map ||
731
+ obj instanceof Set ||
732
+ obj instanceof Date ||
733
+ Array.isArray(obj) ||
734
+ typeof obj !== 'object') {
652
735
  return obj;
653
736
  }
654
737
  else {
655
738
  return Object.keys(obj)
656
739
  .sort()
657
- .filter(([_, value]) => value !== undefined)
740
+ .filter(key => obj[key] !== undefined)
658
741
  .reduce((sorted, key) => {
659
742
  sorted[key] = obj[key];
660
743
  return sorted;
@@ -681,10 +764,10 @@ var Test;
681
764
  Test.is_object = is_object;
682
765
  function is_deep_equal(a, b) {
683
766
  if (is_object(a))
684
- a = sort_obj(a);
767
+ a = sort(a);
685
768
  if (is_object(b))
686
- b = sort_obj(b);
687
- return String(a) === String(b);
769
+ b = sort(b);
770
+ return JSON.stringify(a) === JSON.stringify(b);
688
771
  }
689
772
  Test.is_deep_equal = is_deep_equal;
690
773
  function has_items(array) {
@@ -696,33 +779,33 @@ var Test;
696
779
  }
697
780
  Test.is_string = is_string;
698
781
  function is_number(value) {
699
- return Number.isInteger(value) && !Number.isNaN(value);
782
+ return typeof value === 'number' && Number.isFinite(value);
700
783
  }
701
784
  Test.is_number = is_number;
785
+ function is_integer(value) {
786
+ return Number.isInteger(value);
787
+ }
788
+ Test.is_integer = is_integer;
702
789
  function is_bigint(value) {
703
790
  return typeof value === 'bigint';
704
791
  }
705
792
  Test.is_bigint = is_bigint;
706
793
  function is_uchar(value) {
707
- return is_number(value) && value >= 0 && value <= 0xFF;
794
+ return is_integer(value) && value >= 0 && value <= 0xFF;
708
795
  }
709
796
  Test.is_uchar = is_uchar;
710
797
  function is_ushort(value) {
711
- return is_number(value) && value >= 0 && value <= 0xFFFF;
798
+ return is_integer(value) && value >= 0 && value <= 0xFFFF;
712
799
  }
713
800
  Test.is_ushort = is_ushort;
714
801
  function is_uint(value) {
715
- return is_number(value) && value >= 0 && value <= 0xFFFFFFFF;
802
+ return is_integer(value) && value >= 0 && value <= 0xFFFFFFFF;
716
803
  }
717
804
  Test.is_uint = is_uint;
718
805
  function is_u8a(value) {
719
806
  return value instanceof Uint8Array;
720
807
  }
721
808
  Test.is_u8a = is_u8a;
722
- function is_bytes(value) {
723
- return Buff.is_bytes(value);
724
- }
725
- Test.is_bytes = is_bytes;
726
809
  function is_base58(value) {
727
810
  if (typeof value !== 'string')
728
811
  return false;
@@ -757,9 +840,33 @@ var Test;
757
840
  return (is_string(value) && is_hex(value) && value.length === 64);
758
841
  }
759
842
  Test.is_hash = is_hash;
843
+ function is_null(value) {
844
+ return value === null;
845
+ }
846
+ Test.is_null = is_null;
847
+ function is_undefined(value) {
848
+ return value === undefined;
849
+ }
850
+ Test.is_undefined = is_undefined;
851
+ function is_array(value) {
852
+ return Array.isArray(value);
853
+ }
854
+ Test.is_array = is_array;
855
+ function is_function(value) {
856
+ return typeof value === 'function';
857
+ }
858
+ Test.is_function = is_function;
859
+ function is_error(value) {
860
+ return value instanceof Error;
861
+ }
862
+ Test.is_error = is_error;
863
+ function is_promise(value) {
864
+ return value instanceof Promise || (is_object(value) && is_function(value.then) && is_function(value.catch));
865
+ }
866
+ Test.is_promise = is_promise;
760
867
  })(Test || (Test = {}));
761
868
 
762
- var Assert;
869
+ var Assert$1;
763
870
  (function (Assert) {
764
871
  function ok(value, message) {
765
872
  if (value === false) {
@@ -809,6 +916,12 @@ var Assert;
809
916
  }
810
917
  }
811
918
  Assert.is_number = is_number;
919
+ function is_integer(value) {
920
+ if (!Test.is_integer(value)) {
921
+ throw new TypeError(`invalid integer: ${String(value)}`);
922
+ }
923
+ }
924
+ Assert.is_integer = is_integer;
812
925
  function is_bigint(value) {
813
926
  if (!Test.is_bigint(value)) {
814
927
  throw new TypeError(`invalid bigint: ${String(value)}`);
@@ -851,19 +964,6 @@ var Assert;
851
964
  }
852
965
  }
853
966
  Assert.is_hash = is_hash;
854
- function is_bytes(value, msg) {
855
- if (!Test.is_bytes(value)) {
856
- throw new TypeError(msg ?? `invalid bytes: ${String(value)}`);
857
- }
858
- }
859
- Assert.is_bytes = is_bytes;
860
- function size(input, size, msg) {
861
- const bytes = Buff.bytes(input);
862
- if (bytes.length !== size) {
863
- throw new Error(msg ?? `invalid input size: ${bytes.length} !== ${size}`);
864
- }
865
- }
866
- Assert.size = size;
867
967
  function has_items(array, err_msg) {
868
968
  if (!Test.has_items(array)) {
869
969
  throw new Error(err_msg ?? 'array does not contain any items');
@@ -894,41 +994,41 @@ var Assert;
894
994
  }
895
995
  }
896
996
  Assert.is_bech32 = is_bech32;
897
- })(Assert || (Assert = {}));
898
-
899
- const crypto$1 = typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined;
997
+ })(Assert$1 || (Assert$1 = {}));
900
998
 
901
999
  /**
902
1000
  * Utilities for hex, bytes, CSPRNG.
903
1001
  * @module
904
1002
  */
905
1003
  /*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */
906
- // We use WebCrypto aka globalThis.crypto, which exists in browsers and node.js 16+.
907
- // node.js versions earlier than v19 don't declare it in global scope.
908
- // For node.js, package.json#exports field mapping rewrites import
909
- // from `crypto` to `cryptoNode`, which imports native module.
910
- // Makes the utils un-importable in browsers without a bundler.
911
- // Once node.js 18 is deprecated (2025-04-30), we can just drop the import.
912
1004
  /** Checks if something is Uint8Array. Be careful: nodejs Buffer will return true. */
913
1005
  function isBytes$1(a) {
914
1006
  return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array');
915
1007
  }
916
1008
  /** Asserts something is positive integer. */
917
- function anumber$1(n) {
918
- if (!Number.isSafeInteger(n) || n < 0)
919
- throw new Error('positive integer expected, got ' + n);
1009
+ function anumber$1(n, title = '') {
1010
+ if (!Number.isSafeInteger(n) || n < 0) {
1011
+ const prefix = title && `"${title}" `;
1012
+ throw new Error(`${prefix}expected integer >= 0, got ${n}`);
1013
+ }
920
1014
  }
921
1015
  /** Asserts something is Uint8Array. */
922
- function abytes$1(b, ...lengths) {
923
- if (!isBytes$1(b))
924
- throw new Error('Uint8Array expected');
925
- if (lengths.length > 0 && !lengths.includes(b.length))
926
- throw new Error('Uint8Array expected of length ' + lengths + ', got length=' + b.length);
1016
+ function abytes$1(value, length, title = '') {
1017
+ const bytes = isBytes$1(value);
1018
+ const len = value?.length;
1019
+ const needsLen = length !== undefined;
1020
+ if (!bytes || (needsLen && len !== length)) {
1021
+ const prefix = title && `"${title}" `;
1022
+ const ofLen = needsLen ? ` of length ${length}` : '';
1023
+ const got = bytes ? `length=${len}` : `type=${typeof value}`;
1024
+ throw new Error(prefix + 'expected Uint8Array' + ofLen + ', got ' + got);
1025
+ }
1026
+ return value;
927
1027
  }
928
1028
  /** Asserts something is hash */
929
1029
  function ahash(h) {
930
1030
  if (typeof h !== 'function' || typeof h.create !== 'function')
931
- throw new Error('Hash should be wrapped by utils.createHasher');
1031
+ throw new Error('Hash must wrapped by utils.createHasher');
932
1032
  anumber$1(h.outputLen);
933
1033
  anumber$1(h.blockLen);
934
1034
  }
@@ -941,10 +1041,10 @@ function aexists(instance, checkFinished = true) {
941
1041
  }
942
1042
  /** Asserts output is properly-sized byte array */
943
1043
  function aoutput(out, instance) {
944
- abytes$1(out);
1044
+ abytes$1(out, undefined, 'digestInto() output');
945
1045
  const min = instance.outputLen;
946
1046
  if (out.length < min) {
947
- throw new Error('digestInto() expects output buffer of length at least ' + min);
1047
+ throw new Error('"digestInto() output" expected to be of length >=' + min);
948
1048
  }
949
1049
  }
950
1050
  /** Zeroize a byte array. Warning: JS provides no guarantees. */
@@ -1024,26 +1124,6 @@ function hexToBytes(hex) {
1024
1124
  }
1025
1125
  return array;
1026
1126
  }
1027
- /**
1028
- * Converts string to bytes using UTF8 encoding.
1029
- * @example utf8ToBytes('abc') // Uint8Array.from([97, 98, 99])
1030
- */
1031
- function utf8ToBytes(str) {
1032
- if (typeof str !== 'string')
1033
- throw new Error('string expected');
1034
- return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809
1035
- }
1036
- /**
1037
- * Normalizes (non-hex) string or Uint8Array to Uint8Array.
1038
- * Warning: when Uint8Array is passed, it would NOT get copied.
1039
- * Keep in mind for future mutable operations.
1040
- */
1041
- function toBytes(data) {
1042
- if (typeof data === 'string')
1043
- data = utf8ToBytes(data);
1044
- abytes$1(data);
1045
- return data;
1046
- }
1047
1127
  /** Copies several Uint8Arrays into one. */
1048
1128
  function concatBytes(...arrays) {
1049
1129
  let sum = 0;
@@ -1060,47 +1140,121 @@ function concatBytes(...arrays) {
1060
1140
  }
1061
1141
  return res;
1062
1142
  }
1063
- /** For runtime check if class implements interface */
1064
- class Hash {
1065
- }
1066
- /** Wraps hash function, creating an interface on top of it */
1067
- function createHasher(hashCons) {
1068
- const hashC = (msg) => hashCons().update(toBytes(msg)).digest();
1069
- const tmp = hashCons();
1143
+ /** Creates function with outputLen, blockLen, create properties from a class constructor. */
1144
+ function createHasher(hashCons, info = {}) {
1145
+ const hashC = (msg, opts) => hashCons(opts).update(msg).digest();
1146
+ const tmp = hashCons(undefined);
1070
1147
  hashC.outputLen = tmp.outputLen;
1071
1148
  hashC.blockLen = tmp.blockLen;
1072
- hashC.create = () => hashCons();
1073
- return hashC;
1149
+ hashC.create = (opts) => hashCons(opts);
1150
+ Object.assign(hashC, info);
1151
+ return Object.freeze(hashC);
1074
1152
  }
1075
1153
  /** Cryptographically secure PRNG. Uses internal OS-level `crypto.getRandomValues`. */
1076
1154
  function randomBytes(bytesLength = 32) {
1077
- if (crypto$1 && typeof crypto$1.getRandomValues === 'function') {
1078
- return crypto$1.getRandomValues(new Uint8Array(bytesLength));
1155
+ const cr = typeof globalThis === 'object' ? globalThis.crypto : null;
1156
+ if (typeof cr?.getRandomValues !== 'function')
1157
+ throw new Error('crypto.getRandomValues must be defined');
1158
+ return cr.getRandomValues(new Uint8Array(bytesLength));
1159
+ }
1160
+ /** Creates OID opts for NIST hashes, with prefix 06 09 60 86 48 01 65 03 04 02. */
1161
+ const oidNist = (suffix) => ({
1162
+ oid: Uint8Array.from([0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, suffix]),
1163
+ });
1164
+
1165
+ /**
1166
+ * HMAC: RFC2104 message authentication code.
1167
+ * @module
1168
+ */
1169
+ /** Internal class for HMAC. */
1170
+ class _HMAC {
1171
+ oHash;
1172
+ iHash;
1173
+ blockLen;
1174
+ outputLen;
1175
+ finished = false;
1176
+ destroyed = false;
1177
+ constructor(hash, key) {
1178
+ ahash(hash);
1179
+ abytes$1(key, undefined, 'key');
1180
+ this.iHash = hash.create();
1181
+ if (typeof this.iHash.update !== 'function')
1182
+ throw new Error('Expected instance of class which extends utils.Hash');
1183
+ this.blockLen = this.iHash.blockLen;
1184
+ this.outputLen = this.iHash.outputLen;
1185
+ const blockLen = this.blockLen;
1186
+ const pad = new Uint8Array(blockLen);
1187
+ // blockLen can be bigger than outputLen
1188
+ pad.set(key.length > blockLen ? hash.create().update(key).digest() : key);
1189
+ for (let i = 0; i < pad.length; i++)
1190
+ pad[i] ^= 0x36;
1191
+ this.iHash.update(pad);
1192
+ // By doing update (processing of first block) of outer hash here we can re-use it between multiple calls via clone
1193
+ this.oHash = hash.create();
1194
+ // Undo internal XOR && apply outer XOR
1195
+ for (let i = 0; i < pad.length; i++)
1196
+ pad[i] ^= 0x36 ^ 0x5c;
1197
+ this.oHash.update(pad);
1198
+ clean(pad);
1079
1199
  }
1080
- // Legacy Node.js compatibility
1081
- if (crypto$1 && typeof crypto$1.randomBytes === 'function') {
1082
- return Uint8Array.from(crypto$1.randomBytes(bytesLength));
1200
+ update(buf) {
1201
+ aexists(this);
1202
+ this.iHash.update(buf);
1203
+ return this;
1204
+ }
1205
+ digestInto(out) {
1206
+ aexists(this);
1207
+ abytes$1(out, this.outputLen, 'output');
1208
+ this.finished = true;
1209
+ this.iHash.digestInto(out);
1210
+ this.oHash.update(out);
1211
+ this.oHash.digestInto(out);
1212
+ this.destroy();
1213
+ }
1214
+ digest() {
1215
+ const out = new Uint8Array(this.oHash.outputLen);
1216
+ this.digestInto(out);
1217
+ return out;
1218
+ }
1219
+ _cloneInto(to) {
1220
+ // Create new instance without calling constructor since key already in state and we don't know it.
1221
+ to ||= Object.create(Object.getPrototypeOf(this), {});
1222
+ const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this;
1223
+ to = to;
1224
+ to.finished = finished;
1225
+ to.destroyed = destroyed;
1226
+ to.blockLen = blockLen;
1227
+ to.outputLen = outputLen;
1228
+ to.oHash = oHash._cloneInto(to.oHash);
1229
+ to.iHash = iHash._cloneInto(to.iHash);
1230
+ return to;
1231
+ }
1232
+ clone() {
1233
+ return this._cloneInto();
1234
+ }
1235
+ destroy() {
1236
+ this.destroyed = true;
1237
+ this.oHash.destroy();
1238
+ this.iHash.destroy();
1083
1239
  }
1084
- throw new Error('crypto.getRandomValues must be defined');
1085
1240
  }
1241
+ /**
1242
+ * HMAC: RFC2104 message authentication code.
1243
+ * @param hash - function that would be used e.g. sha256
1244
+ * @param key - message key
1245
+ * @param message - message data
1246
+ * @example
1247
+ * import { hmac } from '@noble/hashes/hmac';
1248
+ * import { sha256 } from '@noble/hashes/sha2';
1249
+ * const mac1 = hmac(sha256, 'key', 'message');
1250
+ */
1251
+ const hmac = (hash, key, message) => new _HMAC(hash, key).update(message).digest();
1252
+ hmac.create = (hash, key) => new _HMAC(hash, key);
1086
1253
 
1087
1254
  /**
1088
1255
  * Internal Merkle-Damgard hash utils.
1089
1256
  * @module
1090
1257
  */
1091
- /** Polyfill for Safari 14. https://caniuse.com/mdn-javascript_builtins_dataview_setbiguint64 */
1092
- function setBigUint64(view, byteOffset, value, isLE) {
1093
- if (typeof view.setBigUint64 === 'function')
1094
- return view.setBigUint64(byteOffset, value, isLE);
1095
- const _32n = BigInt(32);
1096
- const _u32_max = BigInt(0xffffffff);
1097
- const wh = Number((value >> _32n) & _u32_max);
1098
- const wl = Number(value & _u32_max);
1099
- const h = isLE ? 4 : 0;
1100
- const l = isLE ? 0 : 4;
1101
- view.setUint32(byteOffset + h, wh, isLE);
1102
- view.setUint32(byteOffset + l, wl, isLE);
1103
- }
1104
1258
  /** Choice: a ? b : c */
1105
1259
  function Chi(a, b, c) {
1106
1260
  return (a & b) ^ (~a & c);
@@ -1113,13 +1267,19 @@ function Maj(a, b, c) {
1113
1267
  * Merkle-Damgard hash construction base class.
1114
1268
  * Could be used to create MD5, RIPEMD, SHA1, SHA2.
1115
1269
  */
1116
- class HashMD extends Hash {
1270
+ class HashMD {
1271
+ blockLen;
1272
+ outputLen;
1273
+ padOffset;
1274
+ isLE;
1275
+ // For partial updates less than block size
1276
+ buffer;
1277
+ view;
1278
+ finished = false;
1279
+ length = 0;
1280
+ pos = 0;
1281
+ destroyed = false;
1117
1282
  constructor(blockLen, outputLen, padOffset, isLE) {
1118
- super();
1119
- this.finished = false;
1120
- this.length = 0;
1121
- this.pos = 0;
1122
- this.destroyed = false;
1123
1283
  this.blockLen = blockLen;
1124
1284
  this.outputLen = outputLen;
1125
1285
  this.padOffset = padOffset;
@@ -1129,7 +1289,6 @@ class HashMD extends Hash {
1129
1289
  }
1130
1290
  update(data) {
1131
1291
  aexists(this);
1132
- data = toBytes(data);
1133
1292
  abytes$1(data);
1134
1293
  const { view, buffer, blockLen } = this;
1135
1294
  const len = data.length;
@@ -1178,13 +1337,13 @@ class HashMD extends Hash {
1178
1337
  // Note: sha512 requires length to be 128bit integer, but length in JS will overflow before that
1179
1338
  // You need to write around 2 exabytes (u64_max / 8 / (1024**6)) for this to happen.
1180
1339
  // So we just write lowest 64 bits of that value.
1181
- setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE);
1340
+ view.setBigUint64(blockLen - 8, BigInt(this.length * 8), isLE);
1182
1341
  this.process(view, 0);
1183
1342
  const oview = createView(out);
1184
1343
  const len = this.outputLen;
1185
- // NOTE: we do division by 4 later, which should be fused in single op with modulo by JIT
1344
+ // NOTE: we do division by 4 later, which must be fused in single op with modulo by JIT
1186
1345
  if (len % 4)
1187
- throw new Error('_sha2: outputLen should be aligned to 32bit');
1346
+ throw new Error('_sha2: outputLen must be aligned to 32bit');
1188
1347
  const outLen = len / 4;
1189
1348
  const state = this.get();
1190
1349
  if (outLen > state.length)
@@ -1200,7 +1359,7 @@ class HashMD extends Hash {
1200
1359
  return res;
1201
1360
  }
1202
1361
  _cloneInto(to) {
1203
- to || (to = new this.constructor());
1362
+ to ||= new this.constructor();
1204
1363
  to.set(...this.get());
1205
1364
  const { blockLen, buffer, length, finished, destroyed, pos } = this;
1206
1365
  to.destroyed = destroyed;
@@ -1224,10 +1383,128 @@ const SHA256_IV = /* @__PURE__ */ Uint32Array.from([
1224
1383
  0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
1225
1384
  ]);
1226
1385
 
1386
+ /**
1387
+
1388
+ SHA1 (RFC 3174), MD5 (RFC 1321) and RIPEMD160 (RFC 2286) legacy, weak hash functions.
1389
+ Don't use them in a new protocol. What "weak" means:
1390
+
1391
+ - Collisions can be made with 2^18 effort in MD5, 2^60 in SHA1, 2^80 in RIPEMD160.
1392
+ - No practical pre-image attacks (only theoretical, 2^123.4)
1393
+ - HMAC seems kinda ok: https://www.rfc-editor.org/rfc/rfc6151
1394
+ * @module
1395
+ */
1396
+ // RIPEMD-160
1397
+ const Rho160 = /* @__PURE__ */ Uint8Array.from([
1398
+ 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
1399
+ ]);
1400
+ const Id160 = /* @__PURE__ */ (() => Uint8Array.from(new Array(16).fill(0).map((_, i) => i)))();
1401
+ const Pi160 = /* @__PURE__ */ (() => Id160.map((i) => (9 * i + 5) % 16))();
1402
+ const idxLR = /* @__PURE__ */ (() => {
1403
+ const L = [Id160];
1404
+ const R = [Pi160];
1405
+ const res = [L, R];
1406
+ for (let i = 0; i < 4; i++)
1407
+ for (let j of res)
1408
+ j.push(j[i].map((k) => Rho160[k]));
1409
+ return res;
1410
+ })();
1411
+ const idxL = /* @__PURE__ */ (() => idxLR[0])();
1412
+ const idxR = /* @__PURE__ */ (() => idxLR[1])();
1413
+ // const [idxL, idxR] = idxLR;
1414
+ const shifts160 = /* @__PURE__ */ [
1415
+ [11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8],
1416
+ [12, 13, 11, 15, 6, 9, 9, 7, 12, 15, 11, 13, 7, 8, 7, 7],
1417
+ [13, 15, 14, 11, 7, 7, 6, 8, 13, 14, 13, 12, 5, 5, 6, 9],
1418
+ [14, 11, 12, 14, 8, 6, 5, 5, 15, 12, 15, 14, 9, 9, 8, 6],
1419
+ [15, 12, 13, 13, 9, 5, 8, 6, 14, 11, 12, 11, 8, 6, 5, 5],
1420
+ ].map((i) => Uint8Array.from(i));
1421
+ const shiftsL160 = /* @__PURE__ */ idxL.map((idx, i) => idx.map((j) => shifts160[i][j]));
1422
+ const shiftsR160 = /* @__PURE__ */ idxR.map((idx, i) => idx.map((j) => shifts160[i][j]));
1423
+ const Kl160 = /* @__PURE__ */ Uint32Array.from([
1424
+ 0x00000000, 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xa953fd4e,
1425
+ ]);
1426
+ const Kr160 = /* @__PURE__ */ Uint32Array.from([
1427
+ 0x50a28be6, 0x5c4dd124, 0x6d703ef3, 0x7a6d76e9, 0x00000000,
1428
+ ]);
1429
+ // It's called f() in spec.
1430
+ function ripemd_f(group, x, y, z) {
1431
+ if (group === 0)
1432
+ return x ^ y ^ z;
1433
+ if (group === 1)
1434
+ return (x & y) | (~x & z);
1435
+ if (group === 2)
1436
+ return (x | ~y) ^ z;
1437
+ if (group === 3)
1438
+ return (x & z) | (y & ~z);
1439
+ return x ^ (y | ~z);
1440
+ }
1441
+ // Reusable temporary buffer
1442
+ const BUF_160 = /* @__PURE__ */ new Uint32Array(16);
1443
+ class _RIPEMD160 extends HashMD {
1444
+ h0 = 0x67452301 | 0;
1445
+ h1 = 0xefcdab89 | 0;
1446
+ h2 = 0x98badcfe | 0;
1447
+ h3 = 0x10325476 | 0;
1448
+ h4 = 0xc3d2e1f0 | 0;
1449
+ constructor() {
1450
+ super(64, 20, 8, true);
1451
+ }
1452
+ get() {
1453
+ const { h0, h1, h2, h3, h4 } = this;
1454
+ return [h0, h1, h2, h3, h4];
1455
+ }
1456
+ set(h0, h1, h2, h3, h4) {
1457
+ this.h0 = h0 | 0;
1458
+ this.h1 = h1 | 0;
1459
+ this.h2 = h2 | 0;
1460
+ this.h3 = h3 | 0;
1461
+ this.h4 = h4 | 0;
1462
+ }
1463
+ process(view, offset) {
1464
+ for (let i = 0; i < 16; i++, offset += 4)
1465
+ BUF_160[i] = view.getUint32(offset, true);
1466
+ // prettier-ignore
1467
+ let al = this.h0 | 0, ar = al, bl = this.h1 | 0, br = bl, cl = this.h2 | 0, cr = cl, dl = this.h3 | 0, dr = dl, el = this.h4 | 0, er = el;
1468
+ // Instead of iterating 0 to 80, we split it into 5 groups
1469
+ // And use the groups in constants, functions, etc. Much simpler
1470
+ for (let group = 0; group < 5; group++) {
1471
+ const rGroup = 4 - group;
1472
+ const hbl = Kl160[group], hbr = Kr160[group]; // prettier-ignore
1473
+ const rl = idxL[group], rr = idxR[group]; // prettier-ignore
1474
+ const sl = shiftsL160[group], sr = shiftsR160[group]; // prettier-ignore
1475
+ for (let i = 0; i < 16; i++) {
1476
+ const tl = (rotl(al + ripemd_f(group, bl, cl, dl) + BUF_160[rl[i]] + hbl, sl[i]) + el) | 0;
1477
+ al = el, el = dl, dl = rotl(cl, 10) | 0, cl = bl, bl = tl; // prettier-ignore
1478
+ }
1479
+ // 2 loops are 10% faster
1480
+ for (let i = 0; i < 16; i++) {
1481
+ const tr = (rotl(ar + ripemd_f(rGroup, br, cr, dr) + BUF_160[rr[i]] + hbr, sr[i]) + er) | 0;
1482
+ ar = er, er = dr, dr = rotl(cr, 10) | 0, cr = br, br = tr; // prettier-ignore
1483
+ }
1484
+ }
1485
+ // Add the compressed chunk to the current hash value
1486
+ this.set((this.h1 + cl + dr) | 0, (this.h2 + dl + er) | 0, (this.h3 + el + ar) | 0, (this.h4 + al + br) | 0, (this.h0 + bl + cr) | 0);
1487
+ }
1488
+ roundClean() {
1489
+ clean(BUF_160);
1490
+ }
1491
+ destroy() {
1492
+ this.destroyed = true;
1493
+ clean(this.buffer);
1494
+ this.set(0, 0, 0, 0, 0);
1495
+ }
1496
+ }
1497
+ /**
1498
+ * RIPEMD-160 - a legacy hash function from 1990s.
1499
+ * * https://homes.esat.kuleuven.be/~bosselae/ripemd160.html
1500
+ * * https://homes.esat.kuleuven.be/~bosselae/ripemd160/pdf/AB-9601/AB-9601.pdf
1501
+ */
1502
+ const ripemd160 = /* @__PURE__ */ createHasher(() => new _RIPEMD160());
1503
+
1227
1504
  /**
1228
1505
  * SHA2 hash function. A.k.a. sha256, sha384, sha512, sha512_224, sha512_256.
1229
1506
  * SHA256 is the fastest hash implementable in JS, even faster than Blake3.
1230
- * Check out [RFC 4634](https://datatracker.ietf.org/doc/html/rfc4634) and
1507
+ * Check out [RFC 4634](https://www.rfc-editor.org/rfc/rfc4634) and
1231
1508
  * [FIPS 180-4](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf).
1232
1509
  * @module
1233
1510
  */
@@ -1248,19 +1525,10 @@ const SHA256_K = /* @__PURE__ */ Uint32Array.from([
1248
1525
  ]);
1249
1526
  /** Reusable temporary buffer. "W" comes straight from spec. */
1250
1527
  const SHA256_W = /* @__PURE__ */ new Uint32Array(64);
1251
- class SHA256 extends HashMD {
1252
- constructor(outputLen = 32) {
1528
+ /** Internal 32-byte base SHA2 hash class. */
1529
+ class SHA2_32B extends HashMD {
1530
+ constructor(outputLen) {
1253
1531
  super(64, outputLen, 8, false);
1254
- // We cannot use array here since array allows indexing by variable
1255
- // which means optimizer/compiler cannot use registers.
1256
- this.A = SHA256_IV[0] | 0;
1257
- this.B = SHA256_IV[1] | 0;
1258
- this.C = SHA256_IV[2] | 0;
1259
- this.D = SHA256_IV[3] | 0;
1260
- this.E = SHA256_IV[4] | 0;
1261
- this.F = SHA256_IV[5] | 0;
1262
- this.G = SHA256_IV[6] | 0;
1263
- this.H = SHA256_IV[7] | 0;
1264
1532
  }
1265
1533
  get() {
1266
1534
  const { A, B, C, D, E, F, G, H } = this;
@@ -1323,99 +1591,104 @@ class SHA256 extends HashMD {
1323
1591
  clean(this.buffer);
1324
1592
  }
1325
1593
  }
1594
+ /** Internal SHA2-256 hash class. */
1595
+ class _SHA256 extends SHA2_32B {
1596
+ // We cannot use array here since array allows indexing by variable
1597
+ // which means optimizer/compiler cannot use registers.
1598
+ A = SHA256_IV[0] | 0;
1599
+ B = SHA256_IV[1] | 0;
1600
+ C = SHA256_IV[2] | 0;
1601
+ D = SHA256_IV[3] | 0;
1602
+ E = SHA256_IV[4] | 0;
1603
+ F = SHA256_IV[5] | 0;
1604
+ G = SHA256_IV[6] | 0;
1605
+ H = SHA256_IV[7] | 0;
1606
+ constructor() {
1607
+ super(32);
1608
+ }
1609
+ }
1326
1610
  /**
1327
- * SHA2-256 hash function from RFC 4634.
1611
+ * SHA2-256 hash function from RFC 4634. In JS it's the fastest: even faster than Blake3. Some info:
1328
1612
  *
1329
- * It is the fastest JS hash, even faster than Blake3.
1330
- * To break sha256 using birthday attack, attackers need to try 2^128 hashes.
1331
- * BTC network is doing 2^70 hashes/sec (2^95 hashes/year) as per 2025.
1613
+ * - Trying 2^128 hashes would get 50% chance of collision, using birthday attack.
1614
+ * - BTC network is doing 2^70 hashes/sec (2^95 hashes/year) as per 2025.
1615
+ * - Each sha256 hash is executing 2^18 bit operations.
1616
+ * - Good 2024 ASICs can do 200Th/sec with 3500 watts of power, corresponding to 2^36 hashes/joule.
1332
1617
  */
1333
- const sha256$1 = /* @__PURE__ */ createHasher(() => new SHA256());
1618
+ const sha256$1 = /* @__PURE__ */ createHasher(() => new _SHA256(),
1619
+ /* @__PURE__ */ oidNist(0x01));
1334
1620
 
1335
- /**
1336
- * HMAC: RFC2104 message authentication code.
1337
- * @module
1338
- */
1339
- class HMAC extends Hash {
1340
- constructor(hash, _key) {
1341
- super();
1342
- this.finished = false;
1343
- this.destroyed = false;
1344
- ahash(hash);
1345
- const key = toBytes(_key);
1346
- this.iHash = hash.create();
1347
- if (typeof this.iHash.update !== 'function')
1348
- throw new Error('Expected instance of class which extends utils.Hash');
1349
- this.blockLen = this.iHash.blockLen;
1350
- this.outputLen = this.iHash.outputLen;
1351
- const blockLen = this.blockLen;
1352
- const pad = new Uint8Array(blockLen);
1353
- // blockLen can be bigger than outputLen
1354
- pad.set(key.length > blockLen ? hash.create().update(key).digest() : key);
1355
- for (let i = 0; i < pad.length; i++)
1356
- pad[i] ^= 0x36;
1357
- this.iHash.update(pad);
1358
- // By doing update (processing of first block) of outer hash here we can re-use it between multiple calls via clone
1359
- this.oHash = hash.create();
1360
- // Undo internal XOR && apply outer XOR
1361
- for (let i = 0; i < pad.length; i++)
1362
- pad[i] ^= 0x36 ^ 0x5c;
1363
- this.oHash.update(pad);
1364
- clean(pad);
1621
+ function hash160(...input) {
1622
+ const buffer = Buff.join(input);
1623
+ const digest = ripemd160(sha256$1(buffer));
1624
+ return new Buff(digest);
1625
+ }
1626
+ function sha256(...input) {
1627
+ const buffer = Buff.join(input);
1628
+ const digest = sha256$1(buffer);
1629
+ return new Buff(digest);
1630
+ }
1631
+ function hash256(...input) {
1632
+ const buffer = Buff.join(input);
1633
+ const digest = sha256$1(sha256$1(buffer));
1634
+ return new Buff(digest);
1635
+ }
1636
+ function hashtag(tag) {
1637
+ const hash = sha256(Buff.str(tag));
1638
+ return Buff.join([hash, hash]);
1639
+ }
1640
+ function hash340(tag, ...input) {
1641
+ const htag = hashtag(tag);
1642
+ const pimg = Buff.join([htag, ...input]);
1643
+ return sha256(pimg);
1644
+ }
1645
+
1646
+ var Assert;
1647
+ (function (Assert) {
1648
+ function ok(value, message) {
1649
+ if (!value) {
1650
+ throw new Error(message ?? 'Assertion failed!');
1651
+ }
1365
1652
  }
1366
- update(buf) {
1367
- aexists(this);
1368
- this.iHash.update(buf);
1369
- return this;
1653
+ Assert.ok = ok;
1654
+ function size(input, size, msg) {
1655
+ const bytes = Buff.bytes(input);
1656
+ if (bytes.length !== size) {
1657
+ throw new Error(msg ?? `invalid input size: ${bytes.length} !== ${size}`);
1658
+ }
1370
1659
  }
1371
- digestInto(out) {
1372
- aexists(this);
1373
- abytes$1(out, this.outputLen);
1374
- this.finished = true;
1375
- this.iHash.digestInto(out);
1376
- this.oHash.update(out);
1377
- this.oHash.digestInto(out);
1378
- this.destroy();
1660
+ Assert.size = size;
1661
+ function is_u8a(value) {
1662
+ if (!(value instanceof Uint8Array)) {
1663
+ throw new TypeError(`invalid Uint8Array: ${String(value)}`);
1664
+ }
1379
1665
  }
1380
- digest() {
1381
- const out = new Uint8Array(this.oHash.outputLen);
1382
- this.digestInto(out);
1383
- return out;
1666
+ Assert.is_u8a = is_u8a;
1667
+ function is_base58(value) {
1668
+ if (typeof value !== 'string' || !/^[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+$/.test(value)) {
1669
+ throw new Error('invalid base58 string');
1670
+ }
1384
1671
  }
1385
- _cloneInto(to) {
1386
- // Create new instance without calling constructor since key already in state and we don't know it.
1387
- to || (to = Object.create(Object.getPrototypeOf(this), {}));
1388
- const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this;
1389
- to = to;
1390
- to.finished = finished;
1391
- to.destroyed = destroyed;
1392
- to.blockLen = blockLen;
1393
- to.outputLen = outputLen;
1394
- to.oHash = oHash._cloneInto(to.oHash);
1395
- to.iHash = iHash._cloneInto(to.iHash);
1396
- return to;
1672
+ Assert.is_base58 = is_base58;
1673
+ function is_base64(value) {
1674
+ if (typeof value !== 'string' || value.length === 0 || !/^[a-zA-Z0-9+/]+={0,2}$/.test(value)) {
1675
+ throw new Error('invalid base64 string');
1676
+ }
1397
1677
  }
1398
- clone() {
1399
- return this._cloneInto();
1678
+ Assert.is_base64 = is_base64;
1679
+ function is_b64url(value) {
1680
+ if (typeof value !== 'string' || value.length === 0 || !/^[a-zA-Z0-9\-_]+={0,2}$/.test(value)) {
1681
+ throw new Error('invalid base64url string');
1682
+ }
1400
1683
  }
1401
- destroy() {
1402
- this.destroyed = true;
1403
- this.oHash.destroy();
1404
- this.iHash.destroy();
1684
+ Assert.is_b64url = is_b64url;
1685
+ function is_bech32(value) {
1686
+ if (typeof value !== 'string' || !/^[a-z]+1[023456789acdefghjklmnpqrstuvwxyz]+$/.test(value)) {
1687
+ throw new Error('invalid bech32 string');
1688
+ }
1405
1689
  }
1406
- }
1407
- /**
1408
- * HMAC: RFC2104 message authentication code.
1409
- * @param hash - function that would be used e.g. sha256
1410
- * @param key - message key
1411
- * @param message - message data
1412
- * @example
1413
- * import { hmac } from '@noble/hashes/hmac';
1414
- * import { sha256 } from '@noble/hashes/sha2';
1415
- * const mac1 = hmac(sha256, 'key', 'message');
1416
- */
1417
- const hmac = (hash, key, message) => new HMAC(hash, key).update(message).digest();
1418
- hmac.create = (hash, key) => new HMAC(hash, key);
1690
+ Assert.is_bech32 = is_bech32;
1691
+ })(Assert || (Assert = {}));
1419
1692
 
1420
1693
  /**
1421
1694
  * Hex, bytes and number utilities.
@@ -1423,32 +1696,26 @@ hmac.create = (hash, key) => new HMAC(hash, key);
1423
1696
  */
1424
1697
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
1425
1698
  const _0n$6 = /* @__PURE__ */ BigInt(0);
1426
- const _1n$5 = /* @__PURE__ */ BigInt(1);
1427
- // tmp name until v2
1428
- function _abool2(value, title = '') {
1699
+ const _1n$4 = /* @__PURE__ */ BigInt(1);
1700
+ function abool(value, title = '') {
1429
1701
  if (typeof value !== 'boolean') {
1430
- const prefix = title && `"${title}"`;
1702
+ const prefix = title && `"${title}" `;
1431
1703
  throw new Error(prefix + 'expected boolean, got type=' + typeof value);
1432
1704
  }
1433
1705
  return value;
1434
1706
  }
1435
- // tmp name until v2
1436
- /** Asserts something is Uint8Array. */
1437
- function _abytes2(value, length, title = '') {
1438
- const bytes = isBytes$1(value);
1439
- const len = value?.length;
1440
- const needsLen = length !== undefined;
1441
- if (!bytes || (needsLen && len !== length)) {
1442
- const prefix = title && `"${title}" `;
1443
- const ofLen = needsLen ? ` of length ${length}` : '';
1444
- const got = bytes ? `length=${len}` : `type=${typeof value}`;
1445
- throw new Error(prefix + 'expected Uint8Array' + ofLen + ', got ' + got);
1707
+ // Used in weierstrass, der
1708
+ function abignumber(n) {
1709
+ if (typeof n === 'bigint') {
1710
+ if (!isPosBig(n))
1711
+ throw new Error('positive bigint expected, got ' + n);
1446
1712
  }
1447
- return value;
1713
+ else
1714
+ anumber$1(n);
1715
+ return n;
1448
1716
  }
1449
- // Used in weierstrass, der
1450
1717
  function numberToHexUnpadded(num) {
1451
- const hex = num.toString(16);
1718
+ const hex = abignumber(num).toString(16);
1452
1719
  return hex.length & 1 ? '0' + hex : hex;
1453
1720
  }
1454
1721
  function hexToNumber(hex) {
@@ -1461,56 +1728,40 @@ function bytesToNumberBE(bytes) {
1461
1728
  return hexToNumber(bytesToHex(bytes));
1462
1729
  }
1463
1730
  function bytesToNumberLE(bytes) {
1464
- abytes$1(bytes);
1465
- return hexToNumber(bytesToHex(Uint8Array.from(bytes).reverse()));
1466
- }
1467
- function numberToBytesBE(n, len) {
1468
- return hexToBytes(n.toString(16).padStart(len * 2, '0'));
1469
- }
1470
- function numberToBytesLE(n, len) {
1471
- return numberToBytesBE(n, len).reverse();
1472
- }
1473
- /**
1474
- * Takes hex string or Uint8Array, converts to Uint8Array.
1475
- * Validates output length.
1476
- * Will throw error for other types.
1477
- * @param title descriptive title for an error e.g. 'secret key'
1478
- * @param hex hex string or Uint8Array
1479
- * @param expectedLength optional, will compare to result array's length
1480
- * @returns
1481
- */
1482
- function ensureBytes(title, hex, expectedLength) {
1483
- let res;
1484
- if (typeof hex === 'string') {
1485
- try {
1486
- res = hexToBytes(hex);
1487
- }
1488
- catch (e) {
1489
- throw new Error(title + ' must be hex string or Uint8Array, cause: ' + e);
1490
- }
1491
- }
1492
- else if (isBytes$1(hex)) {
1493
- // Uint8Array.from() instead of hash.slice() because node.js Buffer
1494
- // is instance of Uint8Array, and its slice() creates **mutable** copy
1495
- res = Uint8Array.from(hex);
1496
- }
1497
- else {
1498
- throw new Error(title + ' must be hex string or Uint8Array');
1499
- }
1500
- const len = res.length;
1501
- if (typeof expectedLength === 'number' && len !== expectedLength)
1502
- throw new Error(title + ' of length ' + expectedLength + ' expected, got ' + len);
1731
+ return hexToNumber(bytesToHex(copyBytes(abytes$1(bytes)).reverse()));
1732
+ }
1733
+ function numberToBytesBE(n, len) {
1734
+ anumber$1(len);
1735
+ n = abignumber(n);
1736
+ const res = hexToBytes(n.toString(16).padStart(len * 2, '0'));
1737
+ if (res.length !== len)
1738
+ throw new Error('number too large');
1503
1739
  return res;
1504
1740
  }
1741
+ function numberToBytesLE(n, len) {
1742
+ return numberToBytesBE(n, len).reverse();
1743
+ }
1505
1744
  /**
1506
- * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99])
1745
+ * Copies Uint8Array. We can't use u8a.slice(), because u8a can be Buffer,
1746
+ * and Buffer#slice creates mutable copy. Never use Buffers!
1507
1747
  */
1508
- // export const utf8ToBytes: typeof utf8ToBytes_ = utf8ToBytes_;
1748
+ function copyBytes(bytes) {
1749
+ return Uint8Array.from(bytes);
1750
+ }
1509
1751
  /**
1510
- * Converts bytes to string using UTF8 encoding.
1511
- * @example bytesToUtf8(Uint8Array.from([97, 98, 99])) // 'abc'
1752
+ * Decodes 7-bit ASCII string to Uint8Array, throws on non-ascii symbols
1753
+ * Should be safe to use for things expected to be ASCII.
1754
+ * Returns exact same result as `TextEncoder` for ASCII or throws.
1512
1755
  */
1513
- // export const bytesToUtf8: typeof bytesToUtf8_ = bytesToUtf8_;
1756
+ function asciiToBytes(ascii) {
1757
+ return Uint8Array.from(ascii, (c, i) => {
1758
+ const charCode = c.charCodeAt(0);
1759
+ if (c.length !== 1 || charCode > 127) {
1760
+ throw new Error(`string contains non-ASCII character "${ascii[i]}" with code ${charCode} at position ${i}`);
1761
+ }
1762
+ return charCode;
1763
+ });
1764
+ }
1514
1765
  // Is positive bigint
1515
1766
  const isPosBig = (n) => typeof n === 'bigint' && _0n$6 <= n;
1516
1767
  function inRange(n, min, max) {
@@ -1538,7 +1789,7 @@ function aInRange(title, n, min, max) {
1538
1789
  */
1539
1790
  function bitLen(n) {
1540
1791
  let len;
1541
- for (len = 0; n > _0n$6; n >>= _1n$5, len += 1)
1792
+ for (len = 0; n > _0n$6; n >>= _1n$4, len += 1)
1542
1793
  ;
1543
1794
  return len;
1544
1795
  }
@@ -1546,7 +1797,7 @@ function bitLen(n) {
1546
1797
  * Calculate mask for N bits. Not using ** operator with bigints because of old engines.
1547
1798
  * Same as BigInt(`0b${Array(i).fill('1').join('')}`)
1548
1799
  */
1549
- const bitMask = (n) => (_1n$5 << BigInt(n)) - _1n$5;
1800
+ const bitMask = (n) => (_1n$4 << BigInt(n)) - _1n$4;
1550
1801
  /**
1551
1802
  * Minimal HMAC-DRBG from NIST 800-90 for RFC6979 sigs.
1552
1803
  * @returns function that will call DRBG until 2nd arg returns something meaningful
@@ -1555,15 +1806,16 @@ const bitMask = (n) => (_1n$5 << BigInt(n)) - _1n$5;
1555
1806
  * drbg(seed, bytesToKey); // bytesToKey must return Key or undefined
1556
1807
  */
1557
1808
  function createHmacDrbg(hashLen, qByteLen, hmacFn) {
1558
- if (typeof hashLen !== 'number' || hashLen < 2)
1559
- throw new Error('hashLen must be a number');
1560
- if (typeof qByteLen !== 'number' || qByteLen < 2)
1561
- throw new Error('qByteLen must be a number');
1809
+ anumber$1(hashLen, 'hashLen');
1810
+ anumber$1(qByteLen, 'qByteLen');
1562
1811
  if (typeof hmacFn !== 'function')
1563
1812
  throw new Error('hmacFn must be a function');
1564
- // Step B, Step C: set hashLen to 8*ceil(hlen/8)
1565
1813
  const u8n = (len) => new Uint8Array(len); // creates Uint8Array
1566
- const u8of = (byte) => Uint8Array.of(byte); // another shortcut
1814
+ const NULL = Uint8Array.of();
1815
+ const byte0 = Uint8Array.of(0x00);
1816
+ const byte1 = Uint8Array.of(0x01);
1817
+ const _maxDrbgIters = 1000;
1818
+ // Step B, Step C: set hashLen to 8*ceil(hlen/8)
1567
1819
  let v = u8n(hashLen); // Minimal non-full-spec HMAC-DRBG from NIST 800-90 for RFC6979 sigs.
1568
1820
  let k = u8n(hashLen); // Steps B and C of RFC6979 3.2: set hashLen, in our case always same
1569
1821
  let i = 0; // Iterations counter, will throw when over 1000
@@ -1572,20 +1824,20 @@ function createHmacDrbg(hashLen, qByteLen, hmacFn) {
1572
1824
  k.fill(0);
1573
1825
  i = 0;
1574
1826
  };
1575
- const h = (...b) => hmacFn(k, v, ...b); // hmac(k)(v, ...values)
1576
- const reseed = (seed = u8n(0)) => {
1827
+ const h = (...msgs) => hmacFn(k, concatBytes(v, ...msgs)); // hmac(k)(v, ...values)
1828
+ const reseed = (seed = NULL) => {
1577
1829
  // HMAC-DRBG reseed() function. Steps D-G
1578
- k = h(u8of(0x00), seed); // k = hmac(k || v || 0x00 || seed)
1830
+ k = h(byte0, seed); // k = hmac(k || v || 0x00 || seed)
1579
1831
  v = h(); // v = hmac(k || v)
1580
1832
  if (seed.length === 0)
1581
1833
  return;
1582
- k = h(u8of(0x01), seed); // k = hmac(k || v || 0x01 || seed)
1834
+ k = h(byte1, seed); // k = hmac(k || v || 0x01 || seed)
1583
1835
  v = h(); // v = hmac(k || v)
1584
1836
  };
1585
1837
  const gen = () => {
1586
1838
  // HMAC-DRBG generate() function
1587
- if (i++ >= 1000)
1588
- throw new Error('drbg: tried 1000 values');
1839
+ if (i++ >= _maxDrbgIters)
1840
+ throw new Error('drbg: tried max amount of iterations');
1589
1841
  let len = 0;
1590
1842
  const out = [];
1591
1843
  while (len < qByteLen) {
@@ -1607,7 +1859,7 @@ function createHmacDrbg(hashLen, qByteLen, hmacFn) {
1607
1859
  };
1608
1860
  return genUntil;
1609
1861
  }
1610
- function _validateObject(object, fields, optFields = {}) {
1862
+ function validateObject(object, fields = {}, optFields = {}) {
1611
1863
  if (!object || typeof object !== 'object')
1612
1864
  throw new Error('expected valid options object');
1613
1865
  function checkField(fieldName, expectedType, isOpt) {
@@ -1618,8 +1870,9 @@ function _validateObject(object, fields, optFields = {}) {
1618
1870
  if (current !== expectedType || val === null)
1619
1871
  throw new Error(`param "${fieldName}" is invalid: expected ${expectedType}, got ${current}`);
1620
1872
  }
1621
- Object.entries(fields).forEach(([k, v]) => checkField(k, v, false));
1622
- Object.entries(optFields).forEach(([k, v]) => checkField(k, v, true));
1873
+ const iter = (f, isOpt) => Object.entries(f).forEach(([k, v]) => checkField(k, v, isOpt));
1874
+ iter(fields, false);
1875
+ iter(optFields, true);
1623
1876
  }
1624
1877
  /**
1625
1878
  * Memoizes (caches) computation result.
@@ -1644,12 +1897,14 @@ function memoized(fn) {
1644
1897
  * @module
1645
1898
  */
1646
1899
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
1900
+ // Numbers aren't used in x25519 / x448 builds
1647
1901
  // prettier-ignore
1648
- const _0n$5 = BigInt(0), _1n$4 = BigInt(1), _2n$3 = /* @__PURE__ */ BigInt(2), _3n$1 = /* @__PURE__ */ BigInt(3);
1902
+ const _0n$5 = /* @__PURE__ */ BigInt(0), _1n$3 = /* @__PURE__ */ BigInt(1), _2n$3 = /* @__PURE__ */ BigInt(2);
1649
1903
  // prettier-ignore
1650
- const _4n$1 = /* @__PURE__ */ BigInt(4), _5n = /* @__PURE__ */ BigInt(5), _7n = /* @__PURE__ */ BigInt(7);
1904
+ const _3n$1 = /* @__PURE__ */ BigInt(3), _4n$1 = /* @__PURE__ */ BigInt(4), _5n = /* @__PURE__ */ BigInt(5);
1651
1905
  // prettier-ignore
1652
- const _8n = /* @__PURE__ */ BigInt(8), _9n = /* @__PURE__ */ BigInt(9), _16n = /* @__PURE__ */ BigInt(16);
1906
+ const _7n = /* @__PURE__ */ BigInt(7), _8n = /* @__PURE__ */ BigInt(8), _9n = /* @__PURE__ */ BigInt(9);
1907
+ const _16n = /* @__PURE__ */ BigInt(16);
1653
1908
  // Calculates a modulo b
1654
1909
  function mod(a, b) {
1655
1910
  const result = a % b;
@@ -1677,7 +1932,7 @@ function invert(number, modulo) {
1677
1932
  let a = mod(number, modulo);
1678
1933
  let b = modulo;
1679
1934
  // prettier-ignore
1680
- let x = _0n$5, u = _1n$4;
1935
+ let x = _0n$5, u = _1n$3;
1681
1936
  while (a !== _0n$5) {
1682
1937
  // JIT applies optimization if those two lines follow each other
1683
1938
  const q = b / a;
@@ -1687,7 +1942,7 @@ function invert(number, modulo) {
1687
1942
  b = a, a = r, x = u, u = m;
1688
1943
  }
1689
1944
  const gcd = b;
1690
- if (gcd !== _1n$4)
1945
+ if (gcd !== _1n$3)
1691
1946
  throw new Error('invert: does not exist');
1692
1947
  return mod(x, modulo);
1693
1948
  }
@@ -1700,7 +1955,7 @@ function assertIsSquare(Fp, root, n) {
1700
1955
  // n = 72057594037927816n;
1701
1956
  // Fp = Field(BigInt('0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab'));
1702
1957
  function sqrt3mod4(Fp, n) {
1703
- const p1div4 = (Fp.ORDER + _1n$4) / _4n$1;
1958
+ const p1div4 = (Fp.ORDER + _1n$3) / _4n$1;
1704
1959
  const root = Fp.pow(n, p1div4);
1705
1960
  assertIsSquare(Fp, root, n);
1706
1961
  return root;
@@ -1752,7 +2007,7 @@ function tonelliShanks(P) {
1752
2007
  if (P < _3n$1)
1753
2008
  throw new Error('sqrt is not defined for small field');
1754
2009
  // Factor P - 1 = Q * 2^S, where Q is odd
1755
- let Q = P - _1n$4;
2010
+ let Q = P - _1n$3;
1756
2011
  let S = 0;
1757
2012
  while (Q % _2n$3 === _0n$5) {
1758
2013
  Q /= _2n$3;
@@ -1773,7 +2028,7 @@ function tonelliShanks(P) {
1773
2028
  // Slow-path
1774
2029
  // TODO: test on Fp2 and others
1775
2030
  let cc = _Fp.pow(Z, Q); // c = z^Q
1776
- const Q1div2 = (Q + _1n$4) / _2n$3;
2031
+ const Q1div2 = (Q + _1n$3) / _2n$3;
1777
2032
  return function tonelliSlow(Fp, n) {
1778
2033
  if (Fp.is0(n))
1779
2034
  return n;
@@ -1800,7 +2055,7 @@ function tonelliShanks(P) {
1800
2055
  throw new Error('Cannot find square root');
1801
2056
  }
1802
2057
  // Calculate the exponent for b: 2^(M - i - 1)
1803
- const exponent = _1n$4 << BigInt(M - i - 1); // bigint is important
2058
+ const exponent = _1n$3 << BigInt(M - i - 1); // bigint is important
1804
2059
  const b = Fp.pow(c, exponent); // b = 2^(M - i - 1)
1805
2060
  // Update variables
1806
2061
  M = i;
@@ -1844,7 +2099,6 @@ const FIELD_FIELDS = [
1844
2099
  function validateField(field) {
1845
2100
  const initial = {
1846
2101
  ORDER: 'bigint',
1847
- MASK: 'bigint',
1848
2102
  BYTES: 'number',
1849
2103
  BITS: 'number',
1850
2104
  };
@@ -1852,7 +2106,7 @@ function validateField(field) {
1852
2106
  map[val] = 'function';
1853
2107
  return map;
1854
2108
  }, initial);
1855
- _validateObject(field, opts);
2109
+ validateObject(field, opts);
1856
2110
  // const max = 16384;
1857
2111
  // if (field.BYTES < 1 || field.BYTES > max) throw new Error('invalid field');
1858
2112
  // if (field.BITS < 1 || field.BITS > 8 * max) throw new Error('invalid field');
@@ -1868,15 +2122,15 @@ function FpPow(Fp, num, power) {
1868
2122
  throw new Error('invalid exponent, negatives unsupported');
1869
2123
  if (power === _0n$5)
1870
2124
  return Fp.ONE;
1871
- if (power === _1n$4)
2125
+ if (power === _1n$3)
1872
2126
  return num;
1873
2127
  let p = Fp.ONE;
1874
2128
  let d = num;
1875
2129
  while (power > _0n$5) {
1876
- if (power & _1n$4)
2130
+ if (power & _1n$3)
1877
2131
  p = Fp.mul(p, d);
1878
2132
  d = Fp.sqr(d);
1879
- power >>= _1n$4;
2133
+ power >>= _1n$3;
1880
2134
  }
1881
2135
  return p;
1882
2136
  }
@@ -1917,7 +2171,7 @@ function FpInvertBatch(Fp, nums, passZero = false) {
1917
2171
  function FpLegendre(Fp, n) {
1918
2172
  // We can use 3rd argument as optional cache of this value
1919
2173
  // but seems unneeded for now. The operation is very fast.
1920
- const p1mod2 = (Fp.ORDER - _1n$4) / _2n$3;
2174
+ const p1mod2 = (Fp.ORDER - _1n$3) / _2n$3;
1921
2175
  const powered = Fp.pow(n, p1mod2);
1922
2176
  const yes = Fp.eql(powered, Fp.ONE);
1923
2177
  const zero = Fp.eql(powered, Fp.ZERO);
@@ -1935,6 +2189,143 @@ function nLength(n, nBitLength) {
1935
2189
  const nByteLength = Math.ceil(_nBitLength / 8);
1936
2190
  return { nBitLength: _nBitLength, nByteLength };
1937
2191
  }
2192
+ class _Field {
2193
+ ORDER;
2194
+ BITS;
2195
+ BYTES;
2196
+ isLE;
2197
+ ZERO = _0n$5;
2198
+ ONE = _1n$3;
2199
+ _lengths;
2200
+ _sqrt; // cached sqrt
2201
+ _mod;
2202
+ constructor(ORDER, opts = {}) {
2203
+ if (ORDER <= _0n$5)
2204
+ throw new Error('invalid field: expected ORDER > 0, got ' + ORDER);
2205
+ let _nbitLength = undefined;
2206
+ this.isLE = false;
2207
+ if (opts != null && typeof opts === 'object') {
2208
+ if (typeof opts.BITS === 'number')
2209
+ _nbitLength = opts.BITS;
2210
+ if (typeof opts.sqrt === 'function')
2211
+ this.sqrt = opts.sqrt;
2212
+ if (typeof opts.isLE === 'boolean')
2213
+ this.isLE = opts.isLE;
2214
+ if (opts.allowedLengths)
2215
+ this._lengths = opts.allowedLengths?.slice();
2216
+ if (typeof opts.modFromBytes === 'boolean')
2217
+ this._mod = opts.modFromBytes;
2218
+ }
2219
+ const { nBitLength, nByteLength } = nLength(ORDER, _nbitLength);
2220
+ if (nByteLength > 2048)
2221
+ throw new Error('invalid field: expected ORDER of <= 2048 bytes');
2222
+ this.ORDER = ORDER;
2223
+ this.BITS = nBitLength;
2224
+ this.BYTES = nByteLength;
2225
+ this._sqrt = undefined;
2226
+ Object.preventExtensions(this);
2227
+ }
2228
+ create(num) {
2229
+ return mod(num, this.ORDER);
2230
+ }
2231
+ isValid(num) {
2232
+ if (typeof num !== 'bigint')
2233
+ throw new Error('invalid field element: expected bigint, got ' + typeof num);
2234
+ return _0n$5 <= num && num < this.ORDER; // 0 is valid element, but it's not invertible
2235
+ }
2236
+ is0(num) {
2237
+ return num === _0n$5;
2238
+ }
2239
+ // is valid and invertible
2240
+ isValidNot0(num) {
2241
+ return !this.is0(num) && this.isValid(num);
2242
+ }
2243
+ isOdd(num) {
2244
+ return (num & _1n$3) === _1n$3;
2245
+ }
2246
+ neg(num) {
2247
+ return mod(-num, this.ORDER);
2248
+ }
2249
+ eql(lhs, rhs) {
2250
+ return lhs === rhs;
2251
+ }
2252
+ sqr(num) {
2253
+ return mod(num * num, this.ORDER);
2254
+ }
2255
+ add(lhs, rhs) {
2256
+ return mod(lhs + rhs, this.ORDER);
2257
+ }
2258
+ sub(lhs, rhs) {
2259
+ return mod(lhs - rhs, this.ORDER);
2260
+ }
2261
+ mul(lhs, rhs) {
2262
+ return mod(lhs * rhs, this.ORDER);
2263
+ }
2264
+ pow(num, power) {
2265
+ return FpPow(this, num, power);
2266
+ }
2267
+ div(lhs, rhs) {
2268
+ return mod(lhs * invert(rhs, this.ORDER), this.ORDER);
2269
+ }
2270
+ // Same as above, but doesn't normalize
2271
+ sqrN(num) {
2272
+ return num * num;
2273
+ }
2274
+ addN(lhs, rhs) {
2275
+ return lhs + rhs;
2276
+ }
2277
+ subN(lhs, rhs) {
2278
+ return lhs - rhs;
2279
+ }
2280
+ mulN(lhs, rhs) {
2281
+ return lhs * rhs;
2282
+ }
2283
+ inv(num) {
2284
+ return invert(num, this.ORDER);
2285
+ }
2286
+ sqrt(num) {
2287
+ // Caching _sqrt speeds up sqrt9mod16 by 5x and tonneli-shanks by 10%
2288
+ if (!this._sqrt)
2289
+ this._sqrt = FpSqrt(this.ORDER);
2290
+ return this._sqrt(this, num);
2291
+ }
2292
+ toBytes(num) {
2293
+ return this.isLE ? numberToBytesLE(num, this.BYTES) : numberToBytesBE(num, this.BYTES);
2294
+ }
2295
+ fromBytes(bytes, skipValidation = false) {
2296
+ abytes$1(bytes);
2297
+ const { _lengths: allowedLengths, BYTES, isLE, ORDER, _mod: modFromBytes } = this;
2298
+ if (allowedLengths) {
2299
+ if (!allowedLengths.includes(bytes.length) || bytes.length > BYTES) {
2300
+ throw new Error('Field.fromBytes: expected ' + allowedLengths + ' bytes, got ' + bytes.length);
2301
+ }
2302
+ const padded = new Uint8Array(BYTES);
2303
+ // isLE add 0 to right, !isLE to the left.
2304
+ padded.set(bytes, isLE ? 0 : padded.length - bytes.length);
2305
+ bytes = padded;
2306
+ }
2307
+ if (bytes.length !== BYTES)
2308
+ throw new Error('Field.fromBytes: expected ' + BYTES + ' bytes, got ' + bytes.length);
2309
+ let scalar = isLE ? bytesToNumberLE(bytes) : bytesToNumberBE(bytes);
2310
+ if (modFromBytes)
2311
+ scalar = mod(scalar, ORDER);
2312
+ if (!skipValidation)
2313
+ if (!this.isValid(scalar))
2314
+ throw new Error('invalid field element: outside of range 0..ORDER');
2315
+ // NOTE: we don't validate scalar here, please use isValid. This done such way because some
2316
+ // protocol may allow non-reduced scalar that reduced later or changed some other way.
2317
+ return scalar;
2318
+ }
2319
+ // TODO: we don't need it here, move out to separate fn
2320
+ invertBatch(lst) {
2321
+ return FpInvertBatch(this, lst);
2322
+ }
2323
+ // We can't move this out because Fp6, Fp12 implement it
2324
+ // and it's unclear what to return in there.
2325
+ cmov(a, b, condition) {
2326
+ return condition ? b : a;
2327
+ }
2328
+ }
1938
2329
  /**
1939
2330
  * Creates a finite field. Major performance optimizations:
1940
2331
  * * 1. Denormalized operations like mulN instead of mul.
@@ -1954,107 +2345,8 @@ function nLength(n, nBitLength) {
1954
2345
  * @param isLE (default: false) if encoding / decoding should be in little-endian
1955
2346
  * @param redef optional faster redefinitions of sqrt and other methods
1956
2347
  */
1957
- function Field(ORDER, bitLenOrOpts, // TODO: use opts only in v2?
1958
- isLE = false, opts = {}) {
1959
- if (ORDER <= _0n$5)
1960
- throw new Error('invalid field: expected ORDER > 0, got ' + ORDER);
1961
- let _nbitLength = undefined;
1962
- let _sqrt = undefined;
1963
- let modFromBytes = false;
1964
- let allowedLengths = undefined;
1965
- if (typeof bitLenOrOpts === 'object' && bitLenOrOpts != null) {
1966
- if (opts.sqrt || isLE)
1967
- throw new Error('cannot specify opts in two arguments');
1968
- const _opts = bitLenOrOpts;
1969
- if (_opts.BITS)
1970
- _nbitLength = _opts.BITS;
1971
- if (_opts.sqrt)
1972
- _sqrt = _opts.sqrt;
1973
- if (typeof _opts.isLE === 'boolean')
1974
- isLE = _opts.isLE;
1975
- if (typeof _opts.modFromBytes === 'boolean')
1976
- modFromBytes = _opts.modFromBytes;
1977
- allowedLengths = _opts.allowedLengths;
1978
- }
1979
- else {
1980
- if (typeof bitLenOrOpts === 'number')
1981
- _nbitLength = bitLenOrOpts;
1982
- if (opts.sqrt)
1983
- _sqrt = opts.sqrt;
1984
- }
1985
- const { nBitLength: BITS, nByteLength: BYTES } = nLength(ORDER, _nbitLength);
1986
- if (BYTES > 2048)
1987
- throw new Error('invalid field: expected ORDER of <= 2048 bytes');
1988
- let sqrtP; // cached sqrtP
1989
- const f = Object.freeze({
1990
- ORDER,
1991
- isLE,
1992
- BITS,
1993
- BYTES,
1994
- MASK: bitMask(BITS),
1995
- ZERO: _0n$5,
1996
- ONE: _1n$4,
1997
- allowedLengths: allowedLengths,
1998
- create: (num) => mod(num, ORDER),
1999
- isValid: (num) => {
2000
- if (typeof num !== 'bigint')
2001
- throw new Error('invalid field element: expected bigint, got ' + typeof num);
2002
- return _0n$5 <= num && num < ORDER; // 0 is valid element, but it's not invertible
2003
- },
2004
- is0: (num) => num === _0n$5,
2005
- // is valid and invertible
2006
- isValidNot0: (num) => !f.is0(num) && f.isValid(num),
2007
- isOdd: (num) => (num & _1n$4) === _1n$4,
2008
- neg: (num) => mod(-num, ORDER),
2009
- eql: (lhs, rhs) => lhs === rhs,
2010
- sqr: (num) => mod(num * num, ORDER),
2011
- add: (lhs, rhs) => mod(lhs + rhs, ORDER),
2012
- sub: (lhs, rhs) => mod(lhs - rhs, ORDER),
2013
- mul: (lhs, rhs) => mod(lhs * rhs, ORDER),
2014
- pow: (num, power) => FpPow(f, num, power),
2015
- div: (lhs, rhs) => mod(lhs * invert(rhs, ORDER), ORDER),
2016
- // Same as above, but doesn't normalize
2017
- sqrN: (num) => num * num,
2018
- addN: (lhs, rhs) => lhs + rhs,
2019
- subN: (lhs, rhs) => lhs - rhs,
2020
- mulN: (lhs, rhs) => lhs * rhs,
2021
- inv: (num) => invert(num, ORDER),
2022
- sqrt: _sqrt ||
2023
- ((n) => {
2024
- if (!sqrtP)
2025
- sqrtP = FpSqrt(ORDER);
2026
- return sqrtP(f, n);
2027
- }),
2028
- toBytes: (num) => (isLE ? numberToBytesLE(num, BYTES) : numberToBytesBE(num, BYTES)),
2029
- fromBytes: (bytes, skipValidation = true) => {
2030
- if (allowedLengths) {
2031
- if (!allowedLengths.includes(bytes.length) || bytes.length > BYTES) {
2032
- throw new Error('Field.fromBytes: expected ' + allowedLengths + ' bytes, got ' + bytes.length);
2033
- }
2034
- const padded = new Uint8Array(BYTES);
2035
- // isLE add 0 to right, !isLE to the left.
2036
- padded.set(bytes, isLE ? 0 : padded.length - bytes.length);
2037
- bytes = padded;
2038
- }
2039
- if (bytes.length !== BYTES)
2040
- throw new Error('Field.fromBytes: expected ' + BYTES + ' bytes, got ' + bytes.length);
2041
- let scalar = isLE ? bytesToNumberLE(bytes) : bytesToNumberBE(bytes);
2042
- if (modFromBytes)
2043
- scalar = mod(scalar, ORDER);
2044
- if (!skipValidation)
2045
- if (!f.isValid(scalar))
2046
- throw new Error('invalid field element: outside of range 0..ORDER');
2047
- // NOTE: we don't validate scalar here, please use isValid. This done such way because some
2048
- // protocol may allow non-reduced scalar that reduced later or changed some other way.
2049
- return scalar;
2050
- },
2051
- // TODO: we don't need it here, move out to separate fn
2052
- invertBatch: (lst) => FpInvertBatch(f, lst),
2053
- // We can't move this out because Fp6, Fp12 implement it
2054
- // and it's unclear what to return in there.
2055
- cmov: (a, b, c) => (c ? b : a),
2056
- });
2057
- return Object.freeze(f);
2348
+ function Field(ORDER, opts = {}) {
2349
+ return new _Field(ORDER, opts);
2058
2350
  }
2059
2351
  /**
2060
2352
  * Returns total number of bytes consumed by the field element.
@@ -2088,11 +2380,12 @@ function getMinHashLength(fieldOrder) {
2088
2380
  * FIPS 186-5, A.2 https://csrc.nist.gov/publications/detail/fips/186/5/final
2089
2381
  * RFC 9380, https://www.rfc-editor.org/rfc/rfc9380#section-5
2090
2382
  * @param hash hash output from SHA3 or a similar function
2091
- * @param groupOrder size of subgroup - (e.g. secp256k1.CURVE.n)
2383
+ * @param groupOrder size of subgroup - (e.g. secp256k1.Point.Fn.ORDER)
2092
2384
  * @param isLE interpret hash bytes as LE num
2093
2385
  * @returns valid private scalar
2094
2386
  */
2095
2387
  function mapHashToField(key, fieldOrder, isLE = false) {
2388
+ abytes$1(key);
2096
2389
  const len = key.length;
2097
2390
  const fieldLen = getFieldBytesLength(fieldOrder);
2098
2391
  const minLen = getMinHashLength(fieldOrder);
@@ -2101,7 +2394,7 @@ function mapHashToField(key, fieldOrder, isLE = false) {
2101
2394
  throw new Error('expected ' + minLen + '-1024 bytes of input, got ' + len);
2102
2395
  const num = isLE ? bytesToNumberLE(key) : bytesToNumberBE(key);
2103
2396
  // `mod(x, 11)` can sometimes produce 0. `mod(x, 10) + 1` is the same, but no 0
2104
- const reduced = mod(num, fieldOrder - _1n$4) + _1n$4;
2397
+ const reduced = mod(num, fieldOrder - _1n$3) + _1n$3;
2105
2398
  return isLE ? numberToBytesLE(reduced, fieldLen) : numberToBytesBE(reduced, fieldLen);
2106
2399
  }
2107
2400
 
@@ -2111,8 +2404,8 @@ function mapHashToField(key, fieldOrder, isLE = false) {
2111
2404
  * @module
2112
2405
  */
2113
2406
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2114
- const _0n$4 = BigInt(0);
2115
- const _1n$3 = BigInt(1);
2407
+ const _0n$4 = /* @__PURE__ */ BigInt(0);
2408
+ const _1n$2 = /* @__PURE__ */ BigInt(1);
2116
2409
  function negateCt(condition, item) {
2117
2410
  const neg = item.negate();
2118
2411
  return condition ? neg : item;
@@ -2152,7 +2445,7 @@ function calcOffsets(n, window, wOpts) {
2152
2445
  if (wbits > windowSize) {
2153
2446
  // we skip zero, which means instead of `>= size-1`, we do `> size`
2154
2447
  wbits -= maxNumber; // -32, can be maxNumber - wbits, but then we need to set isNeg here.
2155
- nextN += _1n$3; // +256 (carry)
2448
+ nextN += _1n$2; // +256 (carry)
2156
2449
  }
2157
2450
  const offsetStart = window * windowSize;
2158
2451
  const offset = offsetStart + Math.abs(wbits) - 1; // -1 because we skip zero
@@ -2162,22 +2455,6 @@ function calcOffsets(n, window, wOpts) {
2162
2455
  const offsetF = offsetStart; // fake offset for noise
2163
2456
  return { nextN, offset, isZero, isNeg, isNegF, offsetF };
2164
2457
  }
2165
- function validateMSMPoints(points, c) {
2166
- if (!Array.isArray(points))
2167
- throw new Error('array expected');
2168
- points.forEach((p, i) => {
2169
- if (!(p instanceof c))
2170
- throw new Error('invalid point at index ' + i);
2171
- });
2172
- }
2173
- function validateMSMScalars(scalars, field) {
2174
- if (!Array.isArray(scalars))
2175
- throw new Error('array of scalars expected');
2176
- scalars.forEach((s, i) => {
2177
- if (!field.isValid(s))
2178
- throw new Error('invalid scalar at index ' + i);
2179
- });
2180
- }
2181
2458
  // Since points in different groups cannot be equal (different object constructor),
2182
2459
  // we can have single place to store precomputes.
2183
2460
  // Allows to make points frozen / immutable.
@@ -2211,6 +2488,10 @@ function assert0(n) {
2211
2488
  * This would allow windows to be in different memory locations
2212
2489
  */
2213
2490
  class wNAF {
2491
+ BASE;
2492
+ ZERO;
2493
+ Fn;
2494
+ bits;
2214
2495
  // Parametrized with a given Point class (not individual point)
2215
2496
  constructor(Point, bits) {
2216
2497
  this.BASE = Point.BASE;
@@ -2222,10 +2503,10 @@ class wNAF {
2222
2503
  _unsafeLadder(elm, n, p = this.ZERO) {
2223
2504
  let d = elm;
2224
2505
  while (n > _0n$4) {
2225
- if (n & _1n$3)
2506
+ if (n & _1n$2)
2226
2507
  p = p.add(d);
2227
2508
  d = d.double();
2228
- n >>= _1n$3;
2509
+ n >>= _1n$2;
2229
2510
  }
2230
2511
  return p;
2231
2512
  }
@@ -2367,73 +2648,16 @@ function mulEndoUnsafe(Point, point, k1, k2) {
2367
2648
  let p1 = Point.ZERO;
2368
2649
  let p2 = Point.ZERO;
2369
2650
  while (k1 > _0n$4 || k2 > _0n$4) {
2370
- if (k1 & _1n$3)
2651
+ if (k1 & _1n$2)
2371
2652
  p1 = p1.add(acc);
2372
- if (k2 & _1n$3)
2653
+ if (k2 & _1n$2)
2373
2654
  p2 = p2.add(acc);
2374
2655
  acc = acc.double();
2375
- k1 >>= _1n$3;
2376
- k2 >>= _1n$3;
2656
+ k1 >>= _1n$2;
2657
+ k2 >>= _1n$2;
2377
2658
  }
2378
2659
  return { p1, p2 };
2379
2660
  }
2380
- /**
2381
- * Pippenger algorithm for multi-scalar multiplication (MSM, Pa + Qb + Rc + ...).
2382
- * 30x faster vs naive addition on L=4096, 10x faster than precomputes.
2383
- * For N=254bit, L=1, it does: 1024 ADD + 254 DBL. For L=5: 1536 ADD + 254 DBL.
2384
- * Algorithmically constant-time (for same L), even when 1 point + scalar, or when scalar = 0.
2385
- * @param c Curve Point constructor
2386
- * @param fieldN field over CURVE.N - important that it's not over CURVE.P
2387
- * @param points array of L curve points
2388
- * @param scalars array of L scalars (aka secret keys / bigints)
2389
- */
2390
- function pippenger(c, fieldN, points, scalars) {
2391
- // If we split scalars by some window (let's say 8 bits), every chunk will only
2392
- // take 256 buckets even if there are 4096 scalars, also re-uses double.
2393
- // TODO:
2394
- // - https://eprint.iacr.org/2024/750.pdf
2395
- // - https://tches.iacr.org/index.php/TCHES/article/view/10287
2396
- // 0 is accepted in scalars
2397
- validateMSMPoints(points, c);
2398
- validateMSMScalars(scalars, fieldN);
2399
- const plength = points.length;
2400
- const slength = scalars.length;
2401
- if (plength !== slength)
2402
- throw new Error('arrays of points and scalars must have equal length');
2403
- // if (plength === 0) throw new Error('array must be of length >= 2');
2404
- const zero = c.ZERO;
2405
- const wbits = bitLen(BigInt(plength));
2406
- let windowSize = 1; // bits
2407
- if (wbits > 12)
2408
- windowSize = wbits - 3;
2409
- else if (wbits > 4)
2410
- windowSize = wbits - 2;
2411
- else if (wbits > 0)
2412
- windowSize = 2;
2413
- const MASK = bitMask(windowSize);
2414
- const buckets = new Array(Number(MASK) + 1).fill(zero); // +1 for zero array
2415
- const lastBits = Math.floor((fieldN.BITS - 1) / windowSize) * windowSize;
2416
- let sum = zero;
2417
- for (let i = lastBits; i >= 0; i -= windowSize) {
2418
- buckets.fill(zero);
2419
- for (let j = 0; j < slength; j++) {
2420
- const scalar = scalars[j];
2421
- const wbits = Number((scalar >> BigInt(i)) & MASK);
2422
- buckets[wbits] = buckets[wbits].add(points[j]);
2423
- }
2424
- let resI = zero; // not using this will do small speed-up, but will lose ct
2425
- // Skip first bucket, because it is zero
2426
- for (let j = buckets.length - 1, sumI = zero; j > 0; j--) {
2427
- sumI = sumI.add(buckets[j]);
2428
- resI = resI.add(sumI);
2429
- }
2430
- sum = sum.add(resI);
2431
- if (i !== 0)
2432
- for (let j = 0; j < windowSize; j++)
2433
- sum = sum.double();
2434
- }
2435
- return sum;
2436
- }
2437
2661
  function createField(order, field, isLE) {
2438
2662
  if (field) {
2439
2663
  if (field.ORDER !== order)
@@ -2446,7 +2670,7 @@ function createField(order, field, isLE) {
2446
2670
  }
2447
2671
  }
2448
2672
  /** Validates CURVE opts and creates fields */
2449
- function _createCurveFields(type, CURVE, curveOpts = {}, FpFnLE) {
2673
+ function createCurveFields(type, CURVE, curveOpts = {}, FpFnLE) {
2450
2674
  if (FpFnLE === undefined)
2451
2675
  FpFnLE = type === 'edwards';
2452
2676
  if (!CURVE || typeof CURVE !== 'object')
@@ -2468,6 +2692,12 @@ function _createCurveFields(type, CURVE, curveOpts = {}, FpFnLE) {
2468
2692
  CURVE = Object.freeze(Object.assign({}, CURVE));
2469
2693
  return { CURVE, Fp, Fn };
2470
2694
  }
2695
+ function createKeygen(randomSecretKey, getPublicKey) {
2696
+ return function keygen(seed) {
2697
+ const secretKey = randomSecretKey(seed);
2698
+ return { secretKey, publicKey: getPublicKey(secretKey) };
2699
+ };
2700
+ }
2471
2701
 
2472
2702
  /**
2473
2703
  * Short Weierstrass curve methods. The formula is: y² = x³ + ax + b.
@@ -2520,7 +2750,7 @@ function _splitEndoScalar(k, basis, n) {
2520
2750
  k2 = -k2;
2521
2751
  // Double check that resulting scalar less than half bits of N: otherwise wNAF will fail.
2522
2752
  // This should only happen on wrong basises. Also, math inside is too complex and I don't trust it.
2523
- const MAX_NUM = bitMask(Math.ceil(bitLen(n) / 2)) + _1n$2; // Half bits of N
2753
+ const MAX_NUM = bitMask(Math.ceil(bitLen(n) / 2)) + _1n$1; // Half bits of N
2524
2754
  if (k1 < _0n$3 || k1 >= MAX_NUM || k2 < _0n$3 || k2 >= MAX_NUM) {
2525
2755
  throw new Error('splitScalar (endomorphism): failed, k=' + k);
2526
2756
  }
@@ -2537,8 +2767,8 @@ function validateSigOpts(opts, def) {
2537
2767
  // @ts-ignore
2538
2768
  optsn[optName] = opts[optName] === undefined ? def[optName] : opts[optName];
2539
2769
  }
2540
- _abool2(optsn.lowS, 'lowS');
2541
- _abool2(optsn.prehash, 'prehash');
2770
+ abool(optsn.lowS, 'lowS');
2771
+ abool(optsn.prehash, 'prehash');
2542
2772
  if (optsn.format !== undefined)
2543
2773
  validateSigFormat(optsn.format);
2544
2774
  return optsn;
@@ -2568,10 +2798,10 @@ const DER = {
2568
2798
  throw new E('tlv.encode: unpadded data');
2569
2799
  const dataLen = data.length / 2;
2570
2800
  const len = numberToHexUnpadded(dataLen);
2571
- if ((len.length / 2) & 128)
2801
+ if ((len.length / 2) & 0b1000_0000)
2572
2802
  throw new E('tlv.encode: long form length too big');
2573
2803
  // length of length with long form flag
2574
- const lenLen = dataLen > 127 ? numberToHexUnpadded((len.length / 2) | 128) : '';
2804
+ const lenLen = dataLen > 127 ? numberToHexUnpadded((len.length / 2) | 0b1000_0000) : '';
2575
2805
  const t = numberToHexUnpadded(tag);
2576
2806
  return t + lenLen + len + data;
2577
2807
  },
@@ -2584,13 +2814,13 @@ const DER = {
2584
2814
  if (data.length < 2 || data[pos++] !== tag)
2585
2815
  throw new E('tlv.decode: wrong tlv');
2586
2816
  const first = data[pos++];
2587
- const isLong = !!(first & 128); // First bit of first length byte is flag for short/long form
2817
+ const isLong = !!(first & 0b1000_0000); // First bit of first length byte is flag for short/long form
2588
2818
  let length = 0;
2589
2819
  if (!isLong)
2590
2820
  length = first;
2591
2821
  else {
2592
2822
  // Long form: [longFlag(1bit), lengthLength(7bit), length (BE)]
2593
- const lenLen = first & 127;
2823
+ const lenLen = first & 0b0111_1111;
2594
2824
  if (!lenLen)
2595
2825
  throw new E('tlv.decode(long): indefinite length not supported');
2596
2826
  if (lenLen > 4)
@@ -2631,17 +2861,17 @@ const DER = {
2631
2861
  },
2632
2862
  decode(data) {
2633
2863
  const { Err: E } = DER;
2634
- if (data[0] & 128)
2864
+ if (data[0] & 0b1000_0000)
2635
2865
  throw new E('invalid signature integer: negative');
2636
- if (data[0] === 0x00 && !(data[1] & 128))
2866
+ if (data[0] === 0x00 && !(data[1] & 0b1000_0000))
2637
2867
  throw new E('invalid signature integer: unnecessary leading zero');
2638
2868
  return bytesToNumberBE(data);
2639
2869
  },
2640
2870
  },
2641
- toSig(hex) {
2871
+ toSig(bytes) {
2642
2872
  // parse DER signature
2643
2873
  const { Err: E, _int: int, _tlv: tlv } = DER;
2644
- const data = ensureBytes('signature', hex);
2874
+ const data = abytes$1(bytes, undefined, 'signature');
2645
2875
  const { v: seqBytes, l: seqLeftBytes } = tlv.decode(0x30, data);
2646
2876
  if (seqLeftBytes.length)
2647
2877
  throw new E('invalid signature: left bytes after parsing');
@@ -2661,56 +2891,38 @@ const DER = {
2661
2891
  };
2662
2892
  // Be friendly to bad ECMAScript parsers by not using bigint literals
2663
2893
  // prettier-ignore
2664
- const _0n$3 = BigInt(0), _1n$2 = BigInt(1), _2n$2 = BigInt(2), _3n = BigInt(3), _4n = BigInt(4);
2665
- function _normFnElement(Fn, key) {
2666
- const { BYTES: expected } = Fn;
2667
- let num;
2668
- if (typeof key === 'bigint') {
2669
- num = key;
2670
- }
2671
- else {
2672
- let bytes = ensureBytes('private key', key);
2673
- try {
2674
- num = Fn.fromBytes(bytes);
2675
- }
2676
- catch (error) {
2677
- throw new Error(`invalid private key: expected ui8a of size ${expected}, got ${typeof key}`);
2678
- }
2679
- }
2680
- if (!Fn.isValidNot0(num))
2681
- throw new Error('invalid private key: out of range [1..N-1]');
2682
- return num;
2683
- }
2894
+ const _0n$3 = BigInt(0), _1n$1 = BigInt(1), _2n$2 = BigInt(2), _3n = BigInt(3), _4n = BigInt(4);
2684
2895
  /**
2685
2896
  * Creates weierstrass Point constructor, based on specified curve options.
2686
2897
  *
2898
+ * See {@link WeierstrassOpts}.
2899
+ *
2687
2900
  * @example
2688
2901
  ```js
2689
2902
  const opts = {
2690
- p: BigInt('0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff'),
2691
- n: BigInt('0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551'),
2692
- h: BigInt(1),
2693
- a: BigInt('0xffffffff00000001000000000000000000000000fffffffffffffffffffffffc'),
2694
- b: BigInt('0x5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b'),
2695
- Gx: BigInt('0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296'),
2696
- Gy: BigInt('0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5'),
2903
+ p: 0xfffffffffffffffffffffffffffffffeffffac73n,
2904
+ n: 0x100000000000000000001b8fa16dfab9aca16b6b3n,
2905
+ h: 1n,
2906
+ a: 0n,
2907
+ b: 7n,
2908
+ Gx: 0x3b4c382ce37aa192a4019e763036f4f5dd4d7ebbn,
2909
+ Gy: 0x938cf935318fdced6bc28286531733c3f03c4feen,
2697
2910
  };
2698
- const p256_Point = weierstrass(opts);
2911
+ const secp160k1_Point = weierstrass(opts);
2699
2912
  ```
2700
2913
  */
2701
- function weierstrassN(params, extraOpts = {}) {
2702
- const validated = _createCurveFields('weierstrass', params, extraOpts);
2914
+ function weierstrass(params, extraOpts = {}) {
2915
+ const validated = createCurveFields('weierstrass', params, extraOpts);
2703
2916
  const { Fp, Fn } = validated;
2704
2917
  let CURVE = validated.CURVE;
2705
2918
  const { h: cofactor, n: CURVE_ORDER } = CURVE;
2706
- _validateObject(extraOpts, {}, {
2919
+ validateObject(extraOpts, {}, {
2707
2920
  allowInfinityPoint: 'boolean',
2708
2921
  clearCofactor: 'function',
2709
2922
  isTorsionFree: 'function',
2710
2923
  fromBytes: 'function',
2711
2924
  toBytes: 'function',
2712
2925
  endo: 'object',
2713
- wrapPrivateKey: 'boolean',
2714
2926
  });
2715
2927
  const { endo } = extraOpts;
2716
2928
  if (endo) {
@@ -2728,7 +2940,7 @@ function weierstrassN(params, extraOpts = {}) {
2728
2940
  function pointToBytes(_c, point, isCompressed) {
2729
2941
  const { x, y } = point.toAffine();
2730
2942
  const bx = Fp.toBytes(x);
2731
- _abool2(isCompressed, 'isCompressed');
2943
+ abool(isCompressed, 'isCompressed');
2732
2944
  if (isCompressed) {
2733
2945
  assertCompressionIsSupported();
2734
2946
  const hasEvenY = !Fp.isOdd(y);
@@ -2739,7 +2951,7 @@ function weierstrassN(params, extraOpts = {}) {
2739
2951
  }
2740
2952
  }
2741
2953
  function pointFromBytes(bytes) {
2742
- _abytes2(bytes, undefined, 'Point');
2954
+ abytes$1(bytes, undefined, 'Point');
2743
2955
  const { publicKey: comp, publicKeyUncompressed: uncomp } = lengths; // e.g. for 32-byte: 33, 65
2744
2956
  const length = bytes.length;
2745
2957
  const head = bytes[0];
@@ -2759,9 +2971,9 @@ function weierstrassN(params, extraOpts = {}) {
2759
2971
  throw new Error('bad point: is not on curve, sqrt error' + err);
2760
2972
  }
2761
2973
  assertCompressionIsSupported();
2762
- const isYOdd = Fp.isOdd(y); // (y & _1n) === _1n;
2763
- const isHeadOdd = (head & 1) === 1; // ECDSA-specific
2764
- if (isHeadOdd !== isYOdd)
2974
+ const evenY = Fp.isOdd(y);
2975
+ const evenH = (head & 1) === 1; // ECDSA-specific
2976
+ if (evenH !== evenY)
2765
2977
  y = Fp.neg(y);
2766
2978
  return { x, y };
2767
2979
  }
@@ -2810,7 +3022,7 @@ function weierstrassN(params, extraOpts = {}) {
2810
3022
  }
2811
3023
  function aprjpoint(other) {
2812
3024
  if (!(other instanceof Point))
2813
- throw new Error('ProjectivePoint expected');
3025
+ throw new Error('Weierstrass Point expected');
2814
3026
  }
2815
3027
  function splitEndoScalarN(k) {
2816
3028
  if (!endo || !endo.basises)
@@ -2873,6 +3085,17 @@ function weierstrassN(params, extraOpts = {}) {
2873
3085
  * We're doing calculations in projective, because its operations don't require costly inversion.
2874
3086
  */
2875
3087
  class Point {
3088
+ // base / generator point
3089
+ static BASE = new Point(CURVE.Gx, CURVE.Gy, Fp.ONE);
3090
+ // zero / infinity / identity point
3091
+ static ZERO = new Point(Fp.ZERO, Fp.ONE, Fp.ZERO); // 0, 1, 0
3092
+ // math field
3093
+ static Fp = Fp;
3094
+ // scalar field
3095
+ static Fn = Fn;
3096
+ X;
3097
+ Y;
3098
+ Z;
2876
3099
  /** Does NOT validate if the point is valid. Use `.assertValidity()`. */
2877
3100
  constructor(X, Y, Z) {
2878
3101
  this.X = acoord('x', X);
@@ -2896,12 +3119,12 @@ function weierstrassN(params, extraOpts = {}) {
2896
3119
  return new Point(x, y, Fp.ONE);
2897
3120
  }
2898
3121
  static fromBytes(bytes) {
2899
- const P = Point.fromAffine(decodePoint(_abytes2(bytes, undefined, 'point')));
3122
+ const P = Point.fromAffine(decodePoint(abytes$1(bytes, undefined, 'point')));
2900
3123
  P.assertValidity();
2901
3124
  return P;
2902
3125
  }
2903
3126
  static fromHex(hex) {
2904
- return Point.fromBytes(ensureBytes('pointHex', hex));
3127
+ return Point.fromBytes(hexToBytes(hex));
2905
3128
  }
2906
3129
  get x() {
2907
3130
  return this.toAffine().x;
@@ -3088,11 +3311,13 @@ function weierstrassN(params, extraOpts = {}) {
3088
3311
  if (!Fn.isValid(sc))
3089
3312
  throw new Error('invalid scalar: out of range'); // 0 is valid
3090
3313
  if (sc === _0n$3 || p.is0())
3091
- return Point.ZERO;
3092
- if (sc === _1n$2)
3093
- return p; // fast-path
3314
+ return Point.ZERO; // 0
3315
+ if (sc === _1n$1)
3316
+ return p; // 1
3094
3317
  if (wnaf.hasCache(this))
3095
- return this.multiply(sc);
3318
+ return this.multiply(sc); // precomputes
3319
+ // We don't have method for double scalar multiplication (aP + bQ):
3320
+ // Even with using Strauss-Shamir trick, it's 35% slower than naïve mul+add.
3096
3321
  if (endo) {
3097
3322
  const { k1neg, k1, k2neg, k2 } = splitEndoScalarN(sc);
3098
3323
  const { p1, p2 } = mulEndoUnsafe(Point, p, k1, k2); // 30% faster vs wnaf.unsafe
@@ -3102,10 +3327,6 @@ function weierstrassN(params, extraOpts = {}) {
3102
3327
  return wnaf.unsafe(p, sc);
3103
3328
  }
3104
3329
  }
3105
- multiplyAndAddUnsafe(Q, a, b) {
3106
- const sum = this.multiplyUnsafe(a).add(Q.multiplyUnsafe(b));
3107
- return sum.is0() ? undefined : sum;
3108
- }
3109
3330
  /**
3110
3331
  * Converts Projective point to affine (x, y) coordinates.
3111
3332
  * @param invertedZ Z^-1 (inverted zero) - optional, precomputation is useful for invertBatch
@@ -3119,7 +3340,7 @@ function weierstrassN(params, extraOpts = {}) {
3119
3340
  */
3120
3341
  isTorsionFree() {
3121
3342
  const { isTorsionFree } = extraOpts;
3122
- if (cofactor === _1n$2)
3343
+ if (cofactor === _1n$1)
3123
3344
  return true;
3124
3345
  if (isTorsionFree)
3125
3346
  return isTorsionFree(Point, this);
@@ -3127,7 +3348,7 @@ function weierstrassN(params, extraOpts = {}) {
3127
3348
  }
3128
3349
  clearCofactor() {
3129
3350
  const { clearCofactor } = extraOpts;
3130
- if (cofactor === _1n$2)
3351
+ if (cofactor === _1n$1)
3131
3352
  return this; // Fast-path
3132
3353
  if (clearCofactor)
3133
3354
  return clearCofactor(Point, this);
@@ -3138,7 +3359,7 @@ function weierstrassN(params, extraOpts = {}) {
3138
3359
  return this.multiplyUnsafe(cofactor).is0();
3139
3360
  }
3140
3361
  toBytes(isCompressed = true) {
3141
- _abool2(isCompressed, 'isCompressed');
3362
+ abool(isCompressed, 'isCompressed');
3142
3363
  this.assertValidity();
3143
3364
  return encodePoint(Point, this, isCompressed);
3144
3365
  }
@@ -3148,40 +3369,7 @@ function weierstrassN(params, extraOpts = {}) {
3148
3369
  toString() {
3149
3370
  return `<Point ${this.is0() ? 'ZERO' : this.toHex()}>`;
3150
3371
  }
3151
- // TODO: remove
3152
- get px() {
3153
- return this.X;
3154
- }
3155
- get py() {
3156
- return this.X;
3157
- }
3158
- get pz() {
3159
- return this.Z;
3160
- }
3161
- toRawBytes(isCompressed = true) {
3162
- return this.toBytes(isCompressed);
3163
- }
3164
- _setWindowSize(windowSize) {
3165
- this.precompute(windowSize);
3166
- }
3167
- static normalizeZ(points) {
3168
- return normalizeZ(Point, points);
3169
- }
3170
- static msm(points, scalars) {
3171
- return pippenger(Point, Fn, points, scalars);
3172
- }
3173
- static fromPrivateKey(privateKey) {
3174
- return Point.BASE.multiply(_normFnElement(Fn, privateKey));
3175
- }
3176
3372
  }
3177
- // base / generator point
3178
- Point.BASE = new Point(CURVE.Gx, CURVE.Gy, Fp.ONE);
3179
- // zero / infinity / identity point
3180
- Point.ZERO = new Point(Fp.ZERO, Fp.ONE, Fp.ZERO); // 0, 1, 0
3181
- // math field
3182
- Point.Fp = Fp;
3183
- // scalar field
3184
- Point.Fn = Fn;
3185
3373
  const bits = Fn.BITS;
3186
3374
  const wnaf = new wNAF(Point, extraOpts.endo ? Math.ceil(bits / 2) : bits);
3187
3375
  Point.BASE.precompute(8); // Enable precomputes. Slows down first publicKey computation by 20ms.
@@ -3210,7 +3398,8 @@ function ecdh(Point, ecdhOpts = {}) {
3210
3398
  const lengths = Object.assign(getWLengths(Point.Fp, Fn), { seed: getMinHashLength(Fn.ORDER) });
3211
3399
  function isValidSecretKey(secretKey) {
3212
3400
  try {
3213
- return !!_normFnElement(Fn, secretKey);
3401
+ const num = Fn.fromBytes(secretKey);
3402
+ return Fn.isValidNot0(num);
3214
3403
  }
3215
3404
  catch (error) {
3216
3405
  return false;
@@ -3235,7 +3424,7 @@ function ecdh(Point, ecdhOpts = {}) {
3235
3424
  * (groupLen + ceil(groupLen / 2)) with modulo bias being negligible.
3236
3425
  */
3237
3426
  function randomSecretKey(seed = randomBytes_(lengths.seed)) {
3238
- return mapHashToField(_abytes2(seed, lengths.seed, 'seed'), Fn.ORDER);
3427
+ return mapHashToField(abytes$1(seed, lengths.seed, 'seed'), Fn.ORDER);
3239
3428
  }
3240
3429
  /**
3241
3430
  * Computes public key for a secret key. Checks for validity of the secret key.
@@ -3243,24 +3432,18 @@ function ecdh(Point, ecdhOpts = {}) {
3243
3432
  * @returns Public key, full when isCompressed=false; short when isCompressed=true
3244
3433
  */
3245
3434
  function getPublicKey(secretKey, isCompressed = true) {
3246
- return Point.BASE.multiply(_normFnElement(Fn, secretKey)).toBytes(isCompressed);
3247
- }
3248
- function keygen(seed) {
3249
- const secretKey = randomSecretKey(seed);
3250
- return { secretKey, publicKey: getPublicKey(secretKey) };
3435
+ return Point.BASE.multiply(Fn.fromBytes(secretKey)).toBytes(isCompressed);
3251
3436
  }
3252
3437
  /**
3253
3438
  * Quick and dirty check for item being public key. Does not validate hex, or being on-curve.
3254
3439
  */
3255
3440
  function isProbPub(item) {
3256
- if (typeof item === 'bigint')
3257
- return false;
3258
- if (item instanceof Point)
3259
- return true;
3260
3441
  const { secretKey, publicKey, publicKeyUncompressed } = lengths;
3261
- if (Fn.allowedLengths || secretKey === publicKey)
3442
+ if (!isBytes$1(item))
3262
3443
  return undefined;
3263
- const l = ensureBytes('key', item).length;
3444
+ if (('_lengths' in Fn && Fn._lengths) || secretKey === publicKey)
3445
+ return undefined;
3446
+ const l = abytes$1(item, undefined, 'key').length;
3264
3447
  return l === publicKey || l === publicKeyUncompressed;
3265
3448
  }
3266
3449
  /**
@@ -3276,31 +3459,24 @@ function ecdh(Point, ecdhOpts = {}) {
3276
3459
  throw new Error('first arg must be private key');
3277
3460
  if (isProbPub(publicKeyB) === false)
3278
3461
  throw new Error('second arg must be public key');
3279
- const s = _normFnElement(Fn, secretKeyA);
3280
- const b = Point.fromHex(publicKeyB); // checks for being on-curve
3462
+ const s = Fn.fromBytes(secretKeyA);
3463
+ const b = Point.fromBytes(publicKeyB); // checks for being on-curve
3281
3464
  return b.multiply(s).toBytes(isCompressed);
3282
3465
  }
3283
3466
  const utils = {
3284
3467
  isValidSecretKey,
3285
3468
  isValidPublicKey,
3286
3469
  randomSecretKey,
3287
- // TODO: remove
3288
- isValidPrivateKey: isValidSecretKey,
3289
- randomPrivateKey: randomSecretKey,
3290
- normPrivateKeyToScalar: (key) => _normFnElement(Fn, key),
3291
- precompute(windowSize = 8, point = Point.BASE) {
3292
- return point.precompute(windowSize, false);
3293
- },
3294
3470
  };
3471
+ const keygen = createKeygen(randomSecretKey, getPublicKey);
3295
3472
  return Object.freeze({ getPublicKey, getSharedSecret, keygen, Point, utils, lengths });
3296
3473
  }
3297
3474
  /**
3298
3475
  * Creates ECDSA signing interface for given elliptic curve `Point` and `hash` function.
3299
- * We need `hash` for 2 features:
3300
- * 1. Message prehash-ing. NOT used if `sign` / `verify` are called with `prehash: false`
3301
- * 2. k generation in `sign`, using HMAC-drbg(hash)
3302
3476
  *
3303
- * ECDSAOpts are only rarely needed.
3477
+ * @param Point created using {@link weierstrass} function
3478
+ * @param hash used for 1) message prehash-ing 2) k generation in `sign`, using hmac_drbg(hash)
3479
+ * @param ecdsaOpts rarely needed, see {@link ECDSAOpts}
3304
3480
  *
3305
3481
  * @example
3306
3482
  * ```js
@@ -3312,28 +3488,28 @@ function ecdh(Point, ecdhOpts = {}) {
3312
3488
  */
3313
3489
  function ecdsa(Point, hash, ecdsaOpts = {}) {
3314
3490
  ahash(hash);
3315
- _validateObject(ecdsaOpts, {}, {
3491
+ validateObject(ecdsaOpts, {}, {
3316
3492
  hmac: 'function',
3317
3493
  lowS: 'boolean',
3318
3494
  randomBytes: 'function',
3319
3495
  bits2int: 'function',
3320
3496
  bits2int_modN: 'function',
3321
3497
  });
3498
+ ecdsaOpts = Object.assign({}, ecdsaOpts);
3322
3499
  const randomBytes$1 = ecdsaOpts.randomBytes || randomBytes;
3323
- const hmac$1 = ecdsaOpts.hmac ||
3324
- ((key, ...msgs) => hmac(hash, key, concatBytes(...msgs)));
3500
+ const hmac$1 = ecdsaOpts.hmac || ((key, msg) => hmac(hash, key, msg));
3325
3501
  const { Fp, Fn } = Point;
3326
3502
  const { ORDER: CURVE_ORDER, BITS: fnBits } = Fn;
3327
3503
  const { keygen, getPublicKey, getSharedSecret, utils, lengths } = ecdh(Point, ecdsaOpts);
3328
3504
  const defaultSigOpts = {
3329
- prehash: false,
3330
- lowS: typeof ecdsaOpts.lowS === 'boolean' ? ecdsaOpts.lowS : false,
3331
- format: undefined, //'compact' as ECDSASigFormat,
3505
+ prehash: true,
3506
+ lowS: typeof ecdsaOpts.lowS === 'boolean' ? ecdsaOpts.lowS : true,
3507
+ format: 'compact',
3332
3508
  extraEntropy: false,
3333
3509
  };
3334
- const defaultSigOpts_format = 'compact';
3510
+ const hasLargeCofactor = CURVE_ORDER * _2n$2 < Fp.ORDER; // Won't CURVE().h > 2n be more effective?
3335
3511
  function isBiggerThanHalfOrder(number) {
3336
- const HALF = CURVE_ORDER >> _1n$2;
3512
+ const HALF = CURVE_ORDER >> _1n$1;
3337
3513
  return number > HALF;
3338
3514
  }
3339
3515
  function validateRS(title, num) {
@@ -3341,28 +3517,47 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
3341
3517
  throw new Error(`invalid signature ${title}: out of range 1..Point.Fn.ORDER`);
3342
3518
  return num;
3343
3519
  }
3520
+ function assertSmallCofactor() {
3521
+ // ECDSA recovery is hard for cofactor > 1 curves.
3522
+ // In sign, `r = q.x mod n`, and here we recover q.x from r.
3523
+ // While recovering q.x >= n, we need to add r+n for cofactor=1 curves.
3524
+ // However, for cofactor>1, r+n may not get q.x:
3525
+ // r+n*i would need to be done instead where i is unknown.
3526
+ // To easily get i, we either need to:
3527
+ // a. increase amount of valid recid values (4, 5...); OR
3528
+ // b. prohibit non-prime-order signatures (recid > 1).
3529
+ if (hasLargeCofactor)
3530
+ throw new Error('"recovered" sig type is not supported for cofactor >2 curves');
3531
+ }
3344
3532
  function validateSigLength(bytes, format) {
3345
3533
  validateSigFormat(format);
3346
3534
  const size = lengths.signature;
3347
3535
  const sizer = format === 'compact' ? size : format === 'recovered' ? size + 1 : undefined;
3348
- return _abytes2(bytes, sizer, `${format} signature`);
3536
+ return abytes$1(bytes, sizer);
3349
3537
  }
3350
3538
  /**
3351
3539
  * ECDSA signature with its (r, s) properties. Supports compact, recovered & DER representations.
3352
3540
  */
3353
3541
  class Signature {
3542
+ r;
3543
+ s;
3544
+ recovery;
3354
3545
  constructor(r, s, recovery) {
3355
3546
  this.r = validateRS('r', r); // r in [1..N-1];
3356
3547
  this.s = validateRS('s', s); // s in [1..N-1];
3357
- if (recovery != null)
3548
+ if (recovery != null) {
3549
+ assertSmallCofactor();
3550
+ if (![0, 1, 2, 3].includes(recovery))
3551
+ throw new Error('invalid recovery id');
3358
3552
  this.recovery = recovery;
3553
+ }
3359
3554
  Object.freeze(this);
3360
3555
  }
3361
- static fromBytes(bytes, format = defaultSigOpts_format) {
3556
+ static fromBytes(bytes, format = defaultSigOpts.format) {
3362
3557
  validateSigLength(bytes, format);
3363
3558
  let recid;
3364
3559
  if (format === 'der') {
3365
- const { r, s } = DER.toSig(_abytes2(bytes));
3560
+ const { r, s } = DER.toSig(abytes$1(bytes));
3366
3561
  return new Signature(r, s);
3367
3562
  }
3368
3563
  if (format === 'recovered') {
@@ -3370,7 +3565,7 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
3370
3565
  format = 'compact';
3371
3566
  bytes = bytes.subarray(1);
3372
3567
  }
3373
- const L = Fn.BYTES;
3568
+ const L = lengths.signature / 2;
3374
3569
  const r = bytes.subarray(0, L);
3375
3570
  const s = bytes.subarray(L, L * 2);
3376
3571
  return new Signature(Fn.fromBytes(r), Fn.fromBytes(s), recid);
@@ -3378,38 +3573,31 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
3378
3573
  static fromHex(hex, format) {
3379
3574
  return this.fromBytes(hexToBytes(hex), format);
3380
3575
  }
3576
+ assertRecovery() {
3577
+ const { recovery } = this;
3578
+ if (recovery == null)
3579
+ throw new Error('invalid recovery id: must be present');
3580
+ return recovery;
3581
+ }
3381
3582
  addRecoveryBit(recovery) {
3382
3583
  return new Signature(this.r, this.s, recovery);
3383
3584
  }
3384
3585
  recoverPublicKey(messageHash) {
3385
- const FIELD_ORDER = Fp.ORDER;
3386
- const { r, s, recovery: rec } = this;
3387
- if (rec == null || ![0, 1, 2, 3].includes(rec))
3388
- throw new Error('recovery id invalid');
3389
- // ECDSA recovery is hard for cofactor > 1 curves.
3390
- // In sign, `r = q.x mod n`, and here we recover q.x from r.
3391
- // While recovering q.x >= n, we need to add r+n for cofactor=1 curves.
3392
- // However, for cofactor>1, r+n may not get q.x:
3393
- // r+n*i would need to be done instead where i is unknown.
3394
- // To easily get i, we either need to:
3395
- // a. increase amount of valid recid values (4, 5...); OR
3396
- // b. prohibit non-prime-order signatures (recid > 1).
3397
- const hasCofactor = CURVE_ORDER * _2n$2 < FIELD_ORDER;
3398
- if (hasCofactor && rec > 1)
3399
- throw new Error('recovery id is ambiguous for h>1 curve');
3400
- const radj = rec === 2 || rec === 3 ? r + CURVE_ORDER : r;
3586
+ const { r, s } = this;
3587
+ const recovery = this.assertRecovery();
3588
+ const radj = recovery === 2 || recovery === 3 ? r + CURVE_ORDER : r;
3401
3589
  if (!Fp.isValid(radj))
3402
- throw new Error('recovery id 2 or 3 invalid');
3590
+ throw new Error('invalid recovery id: sig.r+curve.n != R.x');
3403
3591
  const x = Fp.toBytes(radj);
3404
- const R = Point.fromBytes(concatBytes(pprefix((rec & 1) === 0), x));
3592
+ const R = Point.fromBytes(concatBytes(pprefix((recovery & 1) === 0), x));
3405
3593
  const ir = Fn.inv(radj); // r^-1
3406
- const h = bits2int_modN(ensureBytes('msgHash', messageHash)); // Truncate hash
3594
+ const h = bits2int_modN(abytes$1(messageHash, undefined, 'msgHash')); // Truncate hash
3407
3595
  const u1 = Fn.create(-h * ir); // -hr^-1
3408
3596
  const u2 = Fn.create(s * ir); // sr^-1
3409
3597
  // (sr^-1)R-(hr^-1)G = -(hr^-1)G + (sr^-1). unsafe is fine: there is no private data.
3410
3598
  const Q = Point.BASE.multiplyUnsafe(u1).add(R.multiplyUnsafe(u2));
3411
3599
  if (Q.is0())
3412
- throw new Error('point at infinify');
3600
+ throw new Error('invalid recovery: point at infinify');
3413
3601
  Q.assertValidity();
3414
3602
  return Q;
3415
3603
  }
@@ -3417,45 +3605,22 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
3417
3605
  hasHighS() {
3418
3606
  return isBiggerThanHalfOrder(this.s);
3419
3607
  }
3420
- toBytes(format = defaultSigOpts_format) {
3608
+ toBytes(format = defaultSigOpts.format) {
3421
3609
  validateSigFormat(format);
3422
3610
  if (format === 'der')
3423
3611
  return hexToBytes(DER.hexFromSig(this));
3424
- const r = Fn.toBytes(this.r);
3425
- const s = Fn.toBytes(this.s);
3612
+ const { r, s } = this;
3613
+ const rb = Fn.toBytes(r);
3614
+ const sb = Fn.toBytes(s);
3426
3615
  if (format === 'recovered') {
3427
- if (this.recovery == null)
3428
- throw new Error('recovery bit must be present');
3429
- return concatBytes(Uint8Array.of(this.recovery), r, s);
3616
+ assertSmallCofactor();
3617
+ return concatBytes(Uint8Array.of(this.assertRecovery()), rb, sb);
3430
3618
  }
3431
- return concatBytes(r, s);
3619
+ return concatBytes(rb, sb);
3432
3620
  }
3433
3621
  toHex(format) {
3434
3622
  return bytesToHex(this.toBytes(format));
3435
3623
  }
3436
- // TODO: remove
3437
- assertValidity() { }
3438
- static fromCompact(hex) {
3439
- return Signature.fromBytes(ensureBytes('sig', hex), 'compact');
3440
- }
3441
- static fromDER(hex) {
3442
- return Signature.fromBytes(ensureBytes('sig', hex), 'der');
3443
- }
3444
- normalizeS() {
3445
- return this.hasHighS() ? new Signature(this.r, Fn.neg(this.s), this.recovery) : this;
3446
- }
3447
- toDERRawBytes() {
3448
- return this.toBytes('der');
3449
- }
3450
- toDERHex() {
3451
- return bytesToHex(this.toBytes('der'));
3452
- }
3453
- toCompactRawBytes() {
3454
- return this.toBytes('compact');
3455
- }
3456
- toCompactHex() {
3457
- return bytesToHex(this.toBytes('compact'));
3458
- }
3459
3624
  }
3460
3625
  // RFC6979: ensure ECDSA msg is X bytes and < N. RFC suggests optional truncating via bits2octets.
3461
3626
  // FIPS 186-4 4.6 suggests the leftmost min(nBitLen, outLen) bits, which matches bits2int.
@@ -3485,8 +3650,8 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
3485
3650
  return Fn.toBytes(num);
3486
3651
  }
3487
3652
  function validateMsgAndHash(message, prehash) {
3488
- _abytes2(message, undefined, 'message');
3489
- return prehash ? _abytes2(hash(message), undefined, 'prehashed message') : message;
3653
+ abytes$1(message, undefined, 'message');
3654
+ return prehash ? abytes$1(hash(message), undefined, 'prehashed message') : message;
3490
3655
  }
3491
3656
  /**
3492
3657
  * Steps A, D of RFC6979 3.2.
@@ -3496,26 +3661,26 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
3496
3661
  * Warning: we cannot assume here that message has same amount of bytes as curve order,
3497
3662
  * this will be invalid at least for P521. Also it can be bigger for P224 + SHA256.
3498
3663
  */
3499
- function prepSig(message, privateKey, opts) {
3500
- if (['recovered', 'canonical'].some((k) => k in opts))
3501
- throw new Error('sign() legacy options not supported');
3664
+ function prepSig(message, secretKey, opts) {
3502
3665
  const { lowS, prehash, extraEntropy } = validateSigOpts(opts, defaultSigOpts);
3503
3666
  message = validateMsgAndHash(message, prehash); // RFC6979 3.2 A: h1 = H(m)
3504
3667
  // We can't later call bits2octets, since nested bits2int is broken for curves
3505
3668
  // with fnBits % 8 !== 0. Because of that, we unwrap it here as int2octets call.
3506
3669
  // const bits2octets = (bits) => int2octets(bits2int_modN(bits))
3507
3670
  const h1int = bits2int_modN(message);
3508
- const d = _normFnElement(Fn, privateKey); // validate secret key, convert to bigint
3671
+ const d = Fn.fromBytes(secretKey); // validate secret key, convert to bigint
3672
+ if (!Fn.isValidNot0(d))
3673
+ throw new Error('invalid private key');
3509
3674
  const seedArgs = [int2octets(d), int2octets(h1int)];
3510
3675
  // extraEntropy. RFC6979 3.6: additional k' (optional).
3511
3676
  if (extraEntropy != null && extraEntropy !== false) {
3512
3677
  // K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) || k')
3513
3678
  // gen random bytes OR pass as-is
3514
3679
  const e = extraEntropy === true ? randomBytes$1(lengths.secretKey) : extraEntropy;
3515
- seedArgs.push(ensureBytes('extraEntropy', e)); // check for being bytes
3680
+ seedArgs.push(abytes$1(e, undefined, 'extraEntropy')); // check for being bytes
3516
3681
  }
3517
3682
  const seed = concatBytes(...seedArgs); // Step D of RFC6979 3.2
3518
- const m = h1int; // NOTE: no need to call bits2int second time here, it is inside truncateHash!
3683
+ const m = h1int; // no need to call bits2int second time here, it is inside truncateHash!
3519
3684
  // Converts signature params into point w r/s, checks result for validity.
3520
3685
  // To transform k => Signature:
3521
3686
  // q = k⋅G
@@ -3527,7 +3692,7 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
3527
3692
  function k2sig(kBytes) {
3528
3693
  // RFC 6979 Section 3.2, step 3: k = bits2int(T)
3529
3694
  // Important: all mod() calls here must be done over N
3530
- const k = bits2int(kBytes); // mod n, not mod p
3695
+ const k = bits2int(kBytes); // Cannot use fields methods, since it is group element
3531
3696
  if (!Fn.isValidNot0(k))
3532
3697
  return; // Valid scalars (including k) must be in 1..N-1
3533
3698
  const ik = Fn.inv(k); // k^-1 mod n
@@ -3535,16 +3700,16 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
3535
3700
  const r = Fn.create(q.x); // r = q.x mod n
3536
3701
  if (r === _0n$3)
3537
3702
  return;
3538
- const s = Fn.create(ik * Fn.create(m + r * d)); // Not using blinding here, see comment above
3703
+ const s = Fn.create(ik * Fn.create(m + r * d)); // s = k^-1(m + rd) mod n
3539
3704
  if (s === _0n$3)
3540
3705
  return;
3541
- let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n$2); // recovery bit (2 or 3, when q.x > n)
3706
+ let recovery = (q.x === r ? 0 : 2) | Number(q.y & _1n$1); // recovery bit (2 or 3 when q.x>n)
3542
3707
  let normS = s;
3543
3708
  if (lowS && isBiggerThanHalfOrder(s)) {
3544
- normS = Fn.neg(s); // if lowS was passed, ensure s is always
3545
- recovery ^= 1; // // in the bottom half of N
3709
+ normS = Fn.neg(s); // if lowS was passed, ensure s is always in the bottom half of N
3710
+ recovery ^= 1;
3546
3711
  }
3547
- return new Signature(r, normS, recovery); // use normS, not s
3712
+ return new Signature(r, normS, hasLargeCofactor ? undefined : recovery);
3548
3713
  }
3549
3714
  return { seed, k2sig };
3550
3715
  }
@@ -3560,46 +3725,10 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
3560
3725
  * ```
3561
3726
  */
3562
3727
  function sign(message, secretKey, opts = {}) {
3563
- message = ensureBytes('message', message);
3564
3728
  const { seed, k2sig } = prepSig(message, secretKey, opts); // Steps A, D of RFC6979 3.2.
3565
3729
  const drbg = createHmacDrbg(hash.outputLen, Fn.BYTES, hmac$1);
3566
3730
  const sig = drbg(seed, k2sig); // Steps B, C, D, E, F, G
3567
- return sig;
3568
- }
3569
- function tryParsingSig(sg) {
3570
- // Try to deduce format
3571
- let sig = undefined;
3572
- const isHex = typeof sg === 'string' || isBytes$1(sg);
3573
- const isObj = !isHex &&
3574
- sg !== null &&
3575
- typeof sg === 'object' &&
3576
- typeof sg.r === 'bigint' &&
3577
- typeof sg.s === 'bigint';
3578
- if (!isHex && !isObj)
3579
- throw new Error('invalid signature, expected Uint8Array, hex string or Signature instance');
3580
- if (isObj) {
3581
- sig = new Signature(sg.r, sg.s);
3582
- }
3583
- else if (isHex) {
3584
- try {
3585
- sig = Signature.fromBytes(ensureBytes('sig', sg), 'der');
3586
- }
3587
- catch (derError) {
3588
- if (!(derError instanceof DER.Err))
3589
- throw derError;
3590
- }
3591
- if (!sig) {
3592
- try {
3593
- sig = Signature.fromBytes(ensureBytes('sig', sg), 'compact');
3594
- }
3595
- catch (error) {
3596
- return false;
3597
- }
3598
- }
3599
- }
3600
- if (!sig)
3601
- return false;
3602
- return sig;
3731
+ return sig.toBytes(opts.format);
3603
3732
  }
3604
3733
  /**
3605
3734
  * Verifies a signature against message and public key.
@@ -3616,16 +3745,15 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
3616
3745
  */
3617
3746
  function verify(signature, message, publicKey, opts = {}) {
3618
3747
  const { lowS, prehash, format } = validateSigOpts(opts, defaultSigOpts);
3619
- publicKey = ensureBytes('publicKey', publicKey);
3620
- message = validateMsgAndHash(ensureBytes('message', message), prehash);
3621
- if ('strict' in opts)
3622
- throw new Error('options.strict was renamed to lowS');
3623
- const sig = format === undefined
3624
- ? tryParsingSig(signature)
3625
- : Signature.fromBytes(ensureBytes('sig', signature), format);
3626
- if (sig === false)
3627
- return false;
3748
+ publicKey = abytes$1(publicKey, undefined, 'publicKey');
3749
+ message = validateMsgAndHash(message, prehash);
3750
+ if (!isBytes$1(signature)) {
3751
+ const end = signature instanceof Signature ? ', use sig.toBytes()' : '';
3752
+ throw new Error('verify expects Uint8Array signature' + end);
3753
+ }
3754
+ validateSigLength(signature, format); // execute this twice because we want loud error
3628
3755
  try {
3756
+ const sig = Signature.fromBytes(signature, format);
3629
3757
  const P = Point.fromBytes(publicKey);
3630
3758
  if (lowS && sig.hasHighS())
3631
3759
  return false;
@@ -3663,73 +3791,6 @@ function ecdsa(Point, hash, ecdsaOpts = {}) {
3663
3791
  hash,
3664
3792
  });
3665
3793
  }
3666
- function _weierstrass_legacy_opts_to_new(c) {
3667
- const CURVE = {
3668
- a: c.a,
3669
- b: c.b,
3670
- p: c.Fp.ORDER,
3671
- n: c.n,
3672
- h: c.h,
3673
- Gx: c.Gx,
3674
- Gy: c.Gy,
3675
- };
3676
- const Fp = c.Fp;
3677
- let allowedLengths = c.allowedPrivateKeyLengths
3678
- ? Array.from(new Set(c.allowedPrivateKeyLengths.map((l) => Math.ceil(l / 2))))
3679
- : undefined;
3680
- const Fn = Field(CURVE.n, {
3681
- BITS: c.nBitLength,
3682
- allowedLengths: allowedLengths,
3683
- modFromBytes: c.wrapPrivateKey,
3684
- });
3685
- const curveOpts = {
3686
- Fp,
3687
- Fn,
3688
- allowInfinityPoint: c.allowInfinityPoint,
3689
- endo: c.endo,
3690
- isTorsionFree: c.isTorsionFree,
3691
- clearCofactor: c.clearCofactor,
3692
- fromBytes: c.fromBytes,
3693
- toBytes: c.toBytes,
3694
- };
3695
- return { CURVE, curveOpts };
3696
- }
3697
- function _ecdsa_legacy_opts_to_new(c) {
3698
- const { CURVE, curveOpts } = _weierstrass_legacy_opts_to_new(c);
3699
- const ecdsaOpts = {
3700
- hmac: c.hmac,
3701
- randomBytes: c.randomBytes,
3702
- lowS: c.lowS,
3703
- bits2int: c.bits2int,
3704
- bits2int_modN: c.bits2int_modN,
3705
- };
3706
- return { CURVE, curveOpts, hash: c.hash, ecdsaOpts };
3707
- }
3708
- function _ecdsa_new_output_to_legacy(c, _ecdsa) {
3709
- const Point = _ecdsa.Point;
3710
- return Object.assign({}, _ecdsa, {
3711
- ProjectivePoint: Point,
3712
- CURVE: Object.assign({}, c, nLength(Point.Fn.ORDER, Point.Fn.BITS)),
3713
- });
3714
- }
3715
- // _ecdsa_legacy
3716
- function weierstrass(c) {
3717
- const { CURVE, curveOpts, hash, ecdsaOpts } = _ecdsa_legacy_opts_to_new(c);
3718
- const Point = weierstrassN(CURVE, curveOpts);
3719
- const signs = ecdsa(Point, hash, ecdsaOpts);
3720
- return _ecdsa_new_output_to_legacy(c, signs);
3721
- }
3722
-
3723
- /**
3724
- * Utilities for short weierstrass curves, combined with noble-hashes.
3725
- * @module
3726
- */
3727
- /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
3728
- /** @deprecated use new `weierstrass()` and `ecdsa()` methods */
3729
- function createCurve(curveDef, defHash) {
3730
- const create = (hash) => weierstrass({ ...curveDef, hash: hash });
3731
- return { ...create(defHash), create };
3732
- }
3733
3794
 
3734
3795
  /**
3735
3796
  * SECG secp256k1. See [pdf](https://www.secg.org/sec2-v2.pdf).
@@ -3740,7 +3801,7 @@ function createCurve(curveDef, defHash) {
3740
3801
  */
3741
3802
  /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
3742
3803
  // Seems like generator was produced from some seed:
3743
- // `Point.BASE.multiply(Point.Fn.inv(2n, N)).toAffine().x`
3804
+ // `Pointk1.BASE.multiply(Pointk1.Fn.inv(2n, N)).toAffine().x`
3744
3805
  // // gives short x 0x3b78ce563f89a0ed9414f5aa28ad0d96d6795f9c63n
3745
3806
  const secp256k1_CURVE = {
3746
3807
  p: BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f'),
@@ -3759,7 +3820,6 @@ const secp256k1_ENDO = {
3759
3820
  ],
3760
3821
  };
3761
3822
  const _0n$2 = /* @__PURE__ */ BigInt(0);
3762
- const _1n$1 = /* @__PURE__ */ BigInt(1);
3763
3823
  const _2n$1 = /* @__PURE__ */ BigInt(2);
3764
3824
  /**
3765
3825
  * √n = n^((p+1)/4) for fields p = 3 mod 4. We unwrap the loop and multiply bit-by-bit.
@@ -3790,21 +3850,28 @@ function sqrtMod(y) {
3790
3850
  return root;
3791
3851
  }
3792
3852
  const Fpk1 = Field(secp256k1_CURVE.p, { sqrt: sqrtMod });
3853
+ const Pointk1 = /* @__PURE__ */ weierstrass(secp256k1_CURVE, {
3854
+ Fp: Fpk1,
3855
+ endo: secp256k1_ENDO,
3856
+ });
3793
3857
  /**
3794
- * secp256k1 curve, ECDSA and ECDH methods.
3858
+ * secp256k1 curve: ECDSA and ECDH methods.
3795
3859
  *
3796
- * Field: `2n**256n - 2n**32n - 2n**9n - 2n**8n - 2n**7n - 2n**6n - 2n**4n - 1n`
3860
+ * Uses sha256 to hash messages. To use a different hash,
3861
+ * pass `{ prehash: false }` to sign / verify.
3797
3862
  *
3798
3863
  * @example
3799
3864
  * ```js
3800
- * import { secp256k1 } from '@noble/curves/secp256k1';
3865
+ * import { secp256k1 } from '@noble/curves/secp256k1.js';
3801
3866
  * const { secretKey, publicKey } = secp256k1.keygen();
3802
- * const msg = new TextEncoder().encode('hello');
3867
+ * // const publicKey = secp256k1.getPublicKey(secretKey);
3868
+ * const msg = new TextEncoder().encode('hello noble');
3803
3869
  * const sig = secp256k1.sign(msg, secretKey);
3804
- * const isValid = secp256k1.verify(sig, msg, publicKey) === true;
3870
+ * const isValid = secp256k1.verify(sig, msg, publicKey);
3871
+ * // const sigKeccak = secp256k1.sign(keccak256(msg), secretKey, { prehash: false });
3805
3872
  * ```
3806
3873
  */
3807
- const secp256k1 = createCurve({ ...secp256k1_CURVE, Fp: Fpk1, lowS: true, endo: secp256k1_ENDO }, sha256$1);
3874
+ const secp256k1 = /* @__PURE__ */ ecdsa(Pointk1, sha256$1);
3808
3875
  // Schnorr signatures are superior to ECDSA from above. Below is Schnorr-specific BIP0340 code.
3809
3876
  // https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki
3810
3877
  /** An object mapping tags to their tagged hash prefix of [SHA256(tag) | SHA256(tag)] */
@@ -3812,7 +3879,7 @@ const TAGGED_HASH_PREFIXES = {};
3812
3879
  function taggedHash(tag, ...messages) {
3813
3880
  let tagP = TAGGED_HASH_PREFIXES[tag];
3814
3881
  if (tagP === undefined) {
3815
- const tagH = sha256$1(utf8ToBytes(tag));
3882
+ const tagH = sha256$1(asciiToBytes(tag));
3816
3883
  tagP = concatBytes(tagH, tagH);
3817
3884
  TAGGED_HASH_PREFIXES[tag] = tagP;
3818
3885
  }
@@ -3820,12 +3887,11 @@ function taggedHash(tag, ...messages) {
3820
3887
  }
3821
3888
  // ECDSA compact points are 33-byte. Schnorr is 32: we strip first byte 0x02 or 0x03
3822
3889
  const pointToBytes = (point) => point.toBytes(true).slice(1);
3823
- const Pointk1 = /* @__PURE__ */ (() => secp256k1.Point)();
3824
3890
  const hasEven = (y) => y % _2n$1 === _0n$2;
3825
3891
  // Calculate point, scalar and bytes
3826
3892
  function schnorrGetExtPubKey(priv) {
3827
3893
  const { Fn, BASE } = Pointk1;
3828
- const d_ = _normFnElement(Fn, priv);
3894
+ const d_ = Fn.fromBytes(priv);
3829
3895
  const p = BASE.multiply(d_); // P = d'⋅G; 0 < d' < n check is done inside
3830
3896
  const scalar = hasEven(p.y) ? d_ : Fn.neg(d_);
3831
3897
  return { scalar, bytes: pointToBytes(p) };
@@ -3868,9 +3934,9 @@ function schnorrGetPublicKey(secretKey) {
3868
3934
  */
3869
3935
  function schnorrSign(message, secretKey, auxRand = randomBytes(32)) {
3870
3936
  const { Fn } = Pointk1;
3871
- const m = ensureBytes('message', message);
3937
+ const m = abytes$1(message, undefined, 'message');
3872
3938
  const { bytes: px, scalar: d } = schnorrGetExtPubKey(secretKey); // checks for isWithinCurveOrder
3873
- const a = ensureBytes('auxRand', auxRand, 32); // Auxiliary random data a: a 32-byte array
3939
+ const a = abytes$1(auxRand, 32, 'auxRand'); // Auxiliary random data a: a 32-byte array
3874
3940
  const t = Fn.toBytes(d ^ num$1(taggedHash('BIP0340/aux', a))); // Let t be the byte-wise xor of bytes(d) and hash/aux(a)
3875
3941
  const rand = taggedHash('BIP0340/nonce', t, px, m); // Let rand = hash/nonce(t || bytes(P) || m)
3876
3942
  // Let k' = int(rand) mod n. Fail if k' = 0. Let R = k'⋅G
@@ -3889,20 +3955,19 @@ function schnorrSign(message, secretKey, auxRand = randomBytes(32)) {
3889
3955
  * Will swallow errors & return false except for initial type validation of arguments.
3890
3956
  */
3891
3957
  function schnorrVerify(signature, message, publicKey) {
3892
- const { Fn, BASE } = Pointk1;
3893
- const sig = ensureBytes('signature', signature, 64);
3894
- const m = ensureBytes('message', message);
3895
- const pub = ensureBytes('publicKey', publicKey, 32);
3958
+ const { Fp, Fn, BASE } = Pointk1;
3959
+ const sig = abytes$1(signature, 64, 'signature');
3960
+ const m = abytes$1(message, undefined, 'message');
3961
+ const pub = abytes$1(publicKey, 32, 'publicKey');
3896
3962
  try {
3897
3963
  const P = lift_x(num$1(pub)); // P = lift_x(int(pk)); fail if that fails
3898
3964
  const r = num$1(sig.subarray(0, 32)); // Let r = int(sig[0:32]); fail if r ≥ p.
3899
- if (!inRange(r, _1n$1, secp256k1_CURVE.p))
3965
+ if (!Fp.isValidNot0(r))
3900
3966
  return false;
3901
3967
  const s = num$1(sig.subarray(32, 64)); // Let s = int(sig[32:64]); fail if s ≥ n.
3902
- if (!inRange(s, _1n$1, secp256k1_CURVE.n))
3968
+ if (!Fn.isValidNot0(s))
3903
3969
  return false;
3904
- // int(challenge(bytes(r)||bytes(P)||m))%n
3905
- const e = challenge(Fn.toBytes(r), pointToBytes(P), m);
3970
+ const e = challenge(Fn.toBytes(r), pointToBytes(P), m); // int(challenge(bytes(r)||bytes(P)||m))%n
3906
3971
  // R = s⋅G - e⋅P, where -eP == (n-e)P
3907
3972
  const R = BASE.multiplyUnsafe(s).add(P.multiplyUnsafe(Fn.neg(e)));
3908
3973
  const { x, y } = R.toAffine();
@@ -3920,7 +3985,7 @@ function schnorrVerify(signature, message, publicKey) {
3920
3985
  * https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki
3921
3986
  * @example
3922
3987
  * ```js
3923
- * import { schnorr } from '@noble/curves/secp256k1';
3988
+ * import { schnorr } from '@noble/curves/secp256k1.js';
3924
3989
  * const { secretKey, publicKey } = schnorr.keygen();
3925
3990
  * // const publicKey = schnorr.getPublicKey(secretKey);
3926
3991
  * const msg = new TextEncoder().encode('hello');
@@ -3934,26 +3999,17 @@ const schnorr = /* @__PURE__ */ (() => {
3934
3999
  const randomSecretKey = (seed = randomBytes(seedLength)) => {
3935
4000
  return mapHashToField(seed, secp256k1_CURVE.n);
3936
4001
  };
3937
- function keygen(seed) {
3938
- const secretKey = randomSecretKey(seed);
3939
- return { secretKey, publicKey: schnorrGetPublicKey(secretKey) };
3940
- }
3941
4002
  return {
3942
- keygen,
4003
+ keygen: createKeygen(randomSecretKey, schnorrGetPublicKey),
3943
4004
  getPublicKey: schnorrGetPublicKey,
3944
4005
  sign: schnorrSign,
3945
4006
  verify: schnorrVerify,
3946
4007
  Point: Pointk1,
3947
4008
  utils: {
3948
- randomSecretKey: randomSecretKey,
3949
- randomPrivateKey: randomSecretKey,
4009
+ randomSecretKey,
3950
4010
  taggedHash,
3951
- // TODO: remove
3952
4011
  lift_x,
3953
4012
  pointToBytes,
3954
- numberToBytesBE,
3955
- bytesToNumberBE,
3956
- mod,
3957
4013
  },
3958
4014
  lengths: {
3959
4015
  secretKey: size,
@@ -3967,8 +4023,8 @@ const schnorr = /* @__PURE__ */ (() => {
3967
4023
 
3968
4024
  const _0n$1 = BigInt(0);
3969
4025
  const _2n = BigInt(2);
3970
- const _N = secp256k1.CURVE.n;
3971
- Field(_N, 32, true);
4026
+ const _N = secp256k1.Point.Fn.ORDER;
4027
+ Field(_N, { isLE: true });
3972
4028
  const GP = secp256k1.Point.BASE;
3973
4029
  function tweak_pubkey(pubkey, tweak, format, even_y = false) {
3974
4030
  const twk_big = serialize_bytes(tweak).big;
@@ -3983,19 +4039,21 @@ function tweak_pubkey(pubkey, tweak, format, even_y = false) {
3983
4039
  }
3984
4040
  function sign_ecdsa(seckey, message) {
3985
4041
  const msg = serialize_bytes(message);
3986
- const sig = secp256k1.sign(msg, seckey).toDERRawBytes();
4042
+ const sk = serialize_bytes(seckey);
4043
+ const sig = secp256k1.sign(msg, sk, { format: 'der', prehash: false });
3987
4044
  return Buff.bytes(sig);
3988
4045
  }
3989
4046
  function sign_bip340(seckey, message) {
3990
4047
  const msg = serialize_bytes(message);
3991
- const sig = schnorr.sign(msg, seckey);
3992
- return serialize_bytes(sig);
4048
+ const sk = serialize_bytes(seckey);
4049
+ const sig = schnorr.sign(msg, sk);
4050
+ return Buff.bytes(sig);
3993
4051
  }
3994
4052
  function verify_ecdsa(signature, message, pubkey) {
3995
4053
  const sig = serialize_bytes(signature);
3996
4054
  const msg = serialize_bytes(message);
3997
4055
  const pk = serialize_pubkey(pubkey, 'ecdsa');
3998
- return secp256k1.verify(sig, msg, pk);
4056
+ return secp256k1.verify(sig, msg, pk, { format: 'der', prehash: false });
3999
4057
  }
4000
4058
  function verify_bip340(signature, message, pubkey) {
4001
4059
  const sig = serialize_bytes(signature);
@@ -4006,10 +4064,10 @@ function verify_bip340(signature, message, pubkey) {
4006
4064
  function lift_point(pubkey) {
4007
4065
  try {
4008
4066
  const pk = serialize_pubkey(pubkey, 'ecdsa');
4009
- return secp256k1.Point.fromHex(pk);
4067
+ return secp256k1.Point.fromHex(pk.hex);
4010
4068
  }
4011
- catch (err) {
4012
- throw new Error('invalid pubkey: ' + pubkey);
4069
+ catch {
4070
+ throw new Error(`invalid pubkey: ${pubkey}`);
4013
4071
  }
4014
4072
  }
4015
4073
  function serialize_pubkey(pubkey, format) {
@@ -4026,161 +4084,21 @@ function serialize_pubkey(pubkey, format) {
4026
4084
  return pk;
4027
4085
  }
4028
4086
  }
4029
- catch (err) {
4030
- throw new Error('invalid pubkey: ' + String(pubkey));
4087
+ catch {
4088
+ throw new Error(`invalid pubkey: ${String(pubkey)}`);
4031
4089
  }
4032
4090
  }
4033
4091
  function serialize_bytes(bytes) {
4034
- try {
4092
+ if (bytes instanceof Uint8Array) {
4035
4093
  return Buff.bytes(bytes);
4036
4094
  }
4037
- catch (err) {
4038
- throw new Error('invalid bytes: ' + String(bytes));
4039
- }
4040
- }
4041
-
4042
- /**
4043
-
4044
- SHA1 (RFC 3174), MD5 (RFC 1321) and RIPEMD160 (RFC 2286) legacy, weak hash functions.
4045
- Don't use them in a new protocol. What "weak" means:
4046
-
4047
- - Collisions can be made with 2^18 effort in MD5, 2^60 in SHA1, 2^80 in RIPEMD160.
4048
- - No practical pre-image attacks (only theoretical, 2^123.4)
4049
- - HMAC seems kinda ok: https://datatracker.ietf.org/doc/html/rfc6151
4050
- * @module
4051
- */
4052
- // RIPEMD-160
4053
- const Rho160 = /* @__PURE__ */ Uint8Array.from([
4054
- 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
4055
- ]);
4056
- const Id160 = /* @__PURE__ */ (() => Uint8Array.from(new Array(16).fill(0).map((_, i) => i)))();
4057
- const Pi160 = /* @__PURE__ */ (() => Id160.map((i) => (9 * i + 5) % 16))();
4058
- const idxLR = /* @__PURE__ */ (() => {
4059
- const L = [Id160];
4060
- const R = [Pi160];
4061
- const res = [L, R];
4062
- for (let i = 0; i < 4; i++)
4063
- for (let j of res)
4064
- j.push(j[i].map((k) => Rho160[k]));
4065
- return res;
4066
- })();
4067
- const idxL = /* @__PURE__ */ (() => idxLR[0])();
4068
- const idxR = /* @__PURE__ */ (() => idxLR[1])();
4069
- // const [idxL, idxR] = idxLR;
4070
- const shifts160 = /* @__PURE__ */ [
4071
- [11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8],
4072
- [12, 13, 11, 15, 6, 9, 9, 7, 12, 15, 11, 13, 7, 8, 7, 7],
4073
- [13, 15, 14, 11, 7, 7, 6, 8, 13, 14, 13, 12, 5, 5, 6, 9],
4074
- [14, 11, 12, 14, 8, 6, 5, 5, 15, 12, 15, 14, 9, 9, 8, 6],
4075
- [15, 12, 13, 13, 9, 5, 8, 6, 14, 11, 12, 11, 8, 6, 5, 5],
4076
- ].map((i) => Uint8Array.from(i));
4077
- const shiftsL160 = /* @__PURE__ */ idxL.map((idx, i) => idx.map((j) => shifts160[i][j]));
4078
- const shiftsR160 = /* @__PURE__ */ idxR.map((idx, i) => idx.map((j) => shifts160[i][j]));
4079
- const Kl160 = /* @__PURE__ */ Uint32Array.from([
4080
- 0x00000000, 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xa953fd4e,
4081
- ]);
4082
- const Kr160 = /* @__PURE__ */ Uint32Array.from([
4083
- 0x50a28be6, 0x5c4dd124, 0x6d703ef3, 0x7a6d76e9, 0x00000000,
4084
- ]);
4085
- // It's called f() in spec.
4086
- function ripemd_f(group, x, y, z) {
4087
- if (group === 0)
4088
- return x ^ y ^ z;
4089
- if (group === 1)
4090
- return (x & y) | (~x & z);
4091
- if (group === 2)
4092
- return (x | ~y) ^ z;
4093
- if (group === 3)
4094
- return (x & z) | (y & ~z);
4095
- return x ^ (y | ~z);
4096
- }
4097
- // Reusable temporary buffer
4098
- const BUF_160 = /* @__PURE__ */ new Uint32Array(16);
4099
- class RIPEMD160 extends HashMD {
4100
- constructor() {
4101
- super(64, 20, 8, true);
4102
- this.h0 = 0x67452301 | 0;
4103
- this.h1 = 0xefcdab89 | 0;
4104
- this.h2 = 0x98badcfe | 0;
4105
- this.h3 = 0x10325476 | 0;
4106
- this.h4 = 0xc3d2e1f0 | 0;
4107
- }
4108
- get() {
4109
- const { h0, h1, h2, h3, h4 } = this;
4110
- return [h0, h1, h2, h3, h4];
4111
- }
4112
- set(h0, h1, h2, h3, h4) {
4113
- this.h0 = h0 | 0;
4114
- this.h1 = h1 | 0;
4115
- this.h2 = h2 | 0;
4116
- this.h3 = h3 | 0;
4117
- this.h4 = h4 | 0;
4118
- }
4119
- process(view, offset) {
4120
- for (let i = 0; i < 16; i++, offset += 4)
4121
- BUF_160[i] = view.getUint32(offset, true);
4122
- // prettier-ignore
4123
- let al = this.h0 | 0, ar = al, bl = this.h1 | 0, br = bl, cl = this.h2 | 0, cr = cl, dl = this.h3 | 0, dr = dl, el = this.h4 | 0, er = el;
4124
- // Instead of iterating 0 to 80, we split it into 5 groups
4125
- // And use the groups in constants, functions, etc. Much simpler
4126
- for (let group = 0; group < 5; group++) {
4127
- const rGroup = 4 - group;
4128
- const hbl = Kl160[group], hbr = Kr160[group]; // prettier-ignore
4129
- const rl = idxL[group], rr = idxR[group]; // prettier-ignore
4130
- const sl = shiftsL160[group], sr = shiftsR160[group]; // prettier-ignore
4131
- for (let i = 0; i < 16; i++) {
4132
- const tl = (rotl(al + ripemd_f(group, bl, cl, dl) + BUF_160[rl[i]] + hbl, sl[i]) + el) | 0;
4133
- al = el, el = dl, dl = rotl(cl, 10) | 0, cl = bl, bl = tl; // prettier-ignore
4134
- }
4135
- // 2 loops are 10% faster
4136
- for (let i = 0; i < 16; i++) {
4137
- const tr = (rotl(ar + ripemd_f(rGroup, br, cr, dr) + BUF_160[rr[i]] + hbr, sr[i]) + er) | 0;
4138
- ar = er, er = dr, dr = rotl(cr, 10) | 0, cr = br, br = tr; // prettier-ignore
4139
- }
4095
+ if (typeof bytes === 'string') {
4096
+ if (bytes.length > 0 && bytes.length % 2 === 0 && /^[0-9a-fA-F]+$/.test(bytes)) {
4097
+ return Buff.hex(bytes);
4140
4098
  }
4141
- // Add the compressed chunk to the current hash value
4142
- this.set((this.h1 + cl + dr) | 0, (this.h2 + dl + er) | 0, (this.h3 + el + ar) | 0, (this.h4 + al + br) | 0, (this.h0 + bl + cr) | 0);
4143
- }
4144
- roundClean() {
4145
- clean(BUF_160);
4146
- }
4147
- destroy() {
4148
- this.destroyed = true;
4149
- clean(this.buffer);
4150
- this.set(0, 0, 0, 0, 0);
4099
+ throw new Error(`invalid hex string: ${bytes}`);
4151
4100
  }
4152
- }
4153
- /**
4154
- * RIPEMD-160 - a legacy hash function from 1990s.
4155
- * * https://homes.esat.kuleuven.be/~bosselae/ripemd160.html
4156
- * * https://homes.esat.kuleuven.be/~bosselae/ripemd160/pdf/AB-9601/AB-9601.pdf
4157
- */
4158
- const ripemd160 = /* @__PURE__ */ createHasher(() => new RIPEMD160());
4159
-
4160
- function hash160(...input) {
4161
- const buffer = Buff.join(input);
4162
- const digest = ripemd160(sha256$1(buffer));
4163
- return new Buff(digest);
4164
- }
4165
- function sha256(...input) {
4166
- const buffer = Buff.join(input);
4167
- const digest = sha256$1(buffer);
4168
- return new Buff(digest);
4169
- }
4170
- function hash256(...input) {
4171
- const buffer = Buff.join(input);
4172
- const digest = sha256$1(sha256$1(buffer));
4173
- return new Buff(digest);
4174
- }
4175
- function hashtag(tag) {
4176
- const hash = sha256(Buff.str(tag));
4177
- return Buff.join([hash, hash]);
4178
- }
4179
- function hash340(tag, ...input) {
4180
- const htag = hashtag(tag);
4181
- const data = input.map(e => new Buff(e));
4182
- const pimg = Buff.join([htag, ...data]);
4183
- return sha256(pimg);
4101
+ throw new Error(`invalid bytes: ${String(bytes)}`);
4184
4102
  }
4185
4103
 
4186
4104
  /*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) */
@@ -4188,11 +4106,9 @@ function isBytes(a) {
4188
4106
  return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array');
4189
4107
  }
4190
4108
  /** Asserts something is Uint8Array. */
4191
- function abytes(b, ...lengths) {
4109
+ function abytes(b) {
4192
4110
  if (!isBytes(b))
4193
4111
  throw new Error('Uint8Array expected');
4194
- if (lengths.length > 0 && !lengths.includes(b.length))
4195
- throw new Error('Uint8Array expected of length ' + lengths + ', got length=' + b.length);
4196
4112
  }
4197
4113
  function isArrayOf(isString, arr) {
4198
4114
  if (!Array.isArray(arr))
@@ -4206,7 +4122,6 @@ function isArrayOf(isString, arr) {
4206
4122
  return arr.every((item) => Number.isSafeInteger(item));
4207
4123
  }
4208
4124
  }
4209
- // no abytes: seems to have 10% slowdown. Why?!
4210
4125
  function afn(input) {
4211
4126
  if (typeof input !== 'function')
4212
4127
  throw new Error('function expected');
@@ -4757,14 +4672,14 @@ const VERSION = {
4757
4672
  function decode_address(address) {
4758
4673
  const format = get_address_format(address);
4759
4674
  if (format === null)
4760
- throw new Error(`unrecognized address format: ${address}`);
4675
+ throw new ValidationError(`unrecognized address format: ${address}`, "address");
4761
4676
  if (format === "base58")
4762
4677
  return base58_decode(address);
4763
4678
  if (format === "bech32")
4764
4679
  return bech32_decode(address);
4765
4680
  if (format === "bech32m")
4766
4681
  return bech32m_decode(address);
4767
- throw new Error("unable to find a matching address configuration");
4682
+ throw new ValidationError("unable to find a matching address configuration", "address");
4768
4683
  }
4769
4684
  function encode_address(config) {
4770
4685
  if (config.format === "base58")
@@ -4773,7 +4688,7 @@ function encode_address(config) {
4773
4688
  return bech32_encode(config);
4774
4689
  if (config.format === "bech32m")
4775
4690
  return bech32m_encode(config);
4776
- throw new Error(`unrecognized encoding format: ${config.format}`);
4691
+ throw new ValidationError(`unrecognized encoding format: ${config.format}`, "format");
4777
4692
  }
4778
4693
  function get_address_format(address) {
4779
4694
  for (const [format, regex] of Object.entries(ENCODING_REGEX)) {
@@ -4783,8 +4698,8 @@ function get_address_format(address) {
4783
4698
  return null;
4784
4699
  }
4785
4700
  function base58_encode(config) {
4786
- Assert.ok(config.format === "base58", "encoding mismatch");
4787
- Assert.exists(config.version, "must specify a version");
4701
+ Assert$1.ok(config.format === "base58", "encoding mismatch");
4702
+ Assert$1.exists(config.version, "must specify a version");
4788
4703
  const bytes = Buff.join([config.version, config.data]);
4789
4704
  return B58chk.encode(bytes);
4790
4705
  }
@@ -4795,8 +4710,8 @@ function base58_decode(encoded) {
4795
4710
  return { data, format: "base58", version };
4796
4711
  }
4797
4712
  function bech32_encode(config) {
4798
- Assert.ok(config.format === "bech32", "encoding mismatch");
4799
- Assert.exists(config.prefix, "prefix is required");
4713
+ Assert$1.ok(config.format === "bech32", "encoding mismatch");
4714
+ Assert$1.exists(config.prefix, "prefix is required");
4800
4715
  const bytes = Buff.bytes(config.data);
4801
4716
  const words = Bech32.to_words(bytes);
4802
4717
  return Bech32.encode(config.prefix, [VERSION.bech32, ...words]);
@@ -4804,13 +4719,13 @@ function bech32_encode(config) {
4804
4719
  function bech32_decode(encoded) {
4805
4720
  const { prefix, words } = Bech32.decode(encoded);
4806
4721
  const [version, ...rest] = words;
4807
- Assert.ok(version === VERSION.bech32, "bech32 version mismatch");
4722
+ Assert$1.ok(version === VERSION.bech32, "bech32 version mismatch");
4808
4723
  const data = Bech32.to_bytes(rest);
4809
4724
  return { data, format: "bech32", prefix, version };
4810
4725
  }
4811
4726
  function bech32m_encode(config) {
4812
- Assert.ok(config.format === "bech32m", "encoding mismatch");
4813
- Assert.exists(config.prefix, "prefix is required");
4727
+ Assert$1.ok(config.format === "bech32m", "encoding mismatch");
4728
+ Assert$1.exists(config.prefix, "prefix is required");
4814
4729
  const bytes = Buff.bytes(config.data);
4815
4730
  const words = Bech32m.to_words(bytes);
4816
4731
  return Bech32m.encode(config.prefix, [VERSION.bech32m, ...words]);
@@ -4818,7 +4733,7 @@ function bech32m_encode(config) {
4818
4733
  function bech32m_decode(encoded) {
4819
4734
  const { prefix, words } = Bech32m.decode(encoded);
4820
4735
  const [version, ...rest] = words;
4821
- Assert.ok(version === VERSION.bech32m, "bech32m version mismatch");
4736
+ Assert$1.ok(version === VERSION.bech32m, "bech32m version mismatch");
4822
4737
  const data = Bech32m.to_bytes(rest);
4823
4738
  return { data, format: "bech32m", prefix, version };
4824
4739
  }
@@ -4918,7 +4833,8 @@ function get_address_info(address) {
4918
4833
  const script = get_address_script(data, type);
4919
4834
  return { data, script, type, prefix, network, size, format, version };
4920
4835
  }
4921
- throw new Error("address configuration is invalid");
4836
+ throw new ConfigError(`unrecognized address configuration: format=${dec.format}, size=${dec.data.length}, version=${dec.version}. ` +
4837
+ `Supported formats: base58 (p2pkh, p2sh), bech32 (p2wpkh, p2wsh), bech32m (p2tr)`);
4922
4838
  }
4923
4839
 
4924
4840
  const ADDRESS_TYPE$4 = LOCK_SCRIPT_TYPE.P2PKH;
@@ -4937,7 +4853,7 @@ function create_p2pkh_address(pubkey, network = "main") {
4937
4853
  }
4938
4854
  function create_p2pkh_script(pubkey) {
4939
4855
  const bytes = Buff.bytes(pubkey);
4940
- Assert.size(bytes, 33, "invalid pubkey size");
4856
+ Assert$1.ok(bytes.length === 33, "invalid pubkey size");
4941
4857
  const hash = hash160(bytes);
4942
4858
  return encode_p2pkh_script(hash);
4943
4859
  }
@@ -4947,8 +4863,8 @@ function encode_p2pkh_script(pk_hash) {
4947
4863
  function encode_p2pkh_address(script, network = "main") {
4948
4864
  const pk_hash = decode_p2pkh_script(script);
4949
4865
  const config = get_address_config(network, ADDRESS_TYPE$4);
4950
- Assert.exists(config, `unrecognized address config: ${ADDRESS_TYPE$4} on ${network}`);
4951
- Assert.size(pk_hash, config.size, `invalid payload size: ${pk_hash.length} !== ${config.size}`);
4866
+ Assert$1.exists(config, `unrecognized address config: ${ADDRESS_TYPE$4} on ${network}`);
4867
+ Assert$1.ok(pk_hash.length === config.size, `invalid payload size: ${pk_hash.length} !== ${config.size}`);
4952
4868
  return encode_address({
4953
4869
  data: pk_hash,
4954
4870
  format: "base58",
@@ -4957,12 +4873,12 @@ function encode_p2pkh_address(script, network = "main") {
4957
4873
  }
4958
4874
  function decode_p2pkh_address(address) {
4959
4875
  const parsed = get_address_info(address);
4960
- Assert.ok(parsed.type === "p2pkh", `address type mismatch: ${parsed.type} !== ${ADDRESS_TYPE$4}`);
4876
+ Assert$1.ok(parsed.type === "p2pkh", `address type mismatch: ${parsed.type} !== ${ADDRESS_TYPE$4}`);
4961
4877
  return parsed;
4962
4878
  }
4963
4879
  function decode_p2pkh_script(script) {
4964
4880
  const bytes = Buff.bytes(script);
4965
- Assert.ok(is_p2pkh_script(script), `invalid p2pkh script`);
4881
+ Assert$1.ok(is_p2pkh_script(script), `invalid p2pkh script`);
4966
4882
  return bytes.slice(3, 23);
4967
4883
  }
4968
4884
 
@@ -4993,8 +4909,8 @@ function encode_p2sh_script(script_hash) {
4993
4909
  function encode_p2sh_address(script_pk, network = "main") {
4994
4910
  const script_hash = decode_p2sh_script(script_pk);
4995
4911
  const config = get_address_config(network, ADDRESS_TYPE$3);
4996
- Assert.exists(config, `unrecognized address config: ${ADDRESS_TYPE$3} on ${network}`);
4997
- Assert.size(script_hash, config.size, `invalid payload size: ${script_hash.length} !== ${config.size}`);
4912
+ Assert$1.exists(config, `unrecognized address config: ${ADDRESS_TYPE$3} on ${network}`);
4913
+ Assert$1.ok(script_hash.length === config.size, `invalid payload size: ${script_hash.length} !== ${config.size}`);
4998
4914
  return encode_address({
4999
4915
  data: script_hash,
5000
4916
  format: "base58",
@@ -5003,11 +4919,11 @@ function encode_p2sh_address(script_pk, network = "main") {
5003
4919
  }
5004
4920
  function decode_p2sh_address(address) {
5005
4921
  const parsed = get_address_info(address);
5006
- Assert.ok(parsed.type === "p2sh", `address type mismatch: ${parsed.type} !== ${ADDRESS_TYPE$3}`);
4922
+ Assert$1.ok(parsed.type === "p2sh", `address type mismatch: ${parsed.type} !== ${ADDRESS_TYPE$3}`);
5007
4923
  return parsed;
5008
4924
  }
5009
4925
  function decode_p2sh_script(script) {
5010
- Assert.ok(is_p2sh_script(script), `invalid p2sh script`);
4926
+ Assert$1.ok(is_p2sh_script(script), `invalid p2sh script`);
5011
4927
  const bytes = Buff.bytes(script);
5012
4928
  return bytes.slice(2, 22);
5013
4929
  }
@@ -5028,7 +4944,7 @@ function create_p2tr_address(pubkey, network = "main") {
5028
4944
  }
5029
4945
  function create_p2tr_script(pubkey) {
5030
4946
  const bytes = Buff.bytes(pubkey);
5031
- Assert.size(bytes, 32, "invalid pubkey size");
4947
+ Assert$1.ok(bytes.length === 32, "invalid pubkey size");
5032
4948
  return encode_p2tr_script(bytes);
5033
4949
  }
5034
4950
  function encode_p2tr_script(pubkey) {
@@ -5037,8 +4953,8 @@ function encode_p2tr_script(pubkey) {
5037
4953
  function encode_p2tr_address(script_pk, network = "main") {
5038
4954
  const pubkey = decode_p2tr_script(script_pk);
5039
4955
  const config = get_address_config(network, ADDRESS_TYPE$2);
5040
- Assert.exists(config, `unrecognized address config: ${ADDRESS_TYPE$2} on ${network}`);
5041
- Assert.size(pubkey, config.size, `invalid payload size: ${pubkey.length} !== ${config.size}`);
4956
+ Assert$1.exists(config, `unrecognized address config: ${ADDRESS_TYPE$2} on ${network}`);
4957
+ Assert$1.ok(pubkey.length === config.size, `invalid payload size: ${pubkey.length} !== ${config.size}`);
5042
4958
  return encode_address({
5043
4959
  data: pubkey,
5044
4960
  format: "bech32m",
@@ -5047,11 +4963,11 @@ function encode_p2tr_address(script_pk, network = "main") {
5047
4963
  }
5048
4964
  function decode_p2tr_address(address) {
5049
4965
  const parsed = get_address_info(address);
5050
- Assert.ok(parsed.type === "p2tr", `address type mismatch: ${parsed.type} !== ${ADDRESS_TYPE$2}`);
4966
+ Assert$1.ok(parsed.type === "p2tr", `address type mismatch: ${parsed.type} !== ${ADDRESS_TYPE$2}`);
5051
4967
  return parsed;
5052
4968
  }
5053
4969
  function decode_p2tr_script(script) {
5054
- Assert.ok(is_p2tr_script(script), `invalid p2tr script`);
4970
+ Assert$1.ok(is_p2tr_script(script), `invalid p2tr script`);
5055
4971
  const bytes = Buff.bytes(script);
5056
4972
  return bytes.slice(2, 34);
5057
4973
  }
@@ -5072,7 +4988,7 @@ function create_p2wpkh_address(pubkey, network = "main") {
5072
4988
  }
5073
4989
  function create_p2wpkh_script(pubkey) {
5074
4990
  const bytes = Buff.bytes(pubkey);
5075
- Assert.size(bytes, 33, "invalid pubkey size");
4991
+ Assert$1.ok(bytes.length === 33, "invalid pubkey size");
5076
4992
  const hash = hash160(bytes);
5077
4993
  return encode_p2wpkh_script(hash);
5078
4994
  }
@@ -5082,8 +4998,8 @@ function encode_p2wpkh_script(pk_hash) {
5082
4998
  function encode_p2wpkh_address(script_pk, network = "main") {
5083
4999
  const pk_hash = decode_p2wpkh_script(script_pk);
5084
5000
  const config = get_address_config(network, ADDRESS_TYPE$1);
5085
- Assert.exists(config, `unrecognized address config: ${ADDRESS_TYPE$1} on ${network}`);
5086
- Assert.size(pk_hash, config.size, `invalid payload size: ${pk_hash.length} !== ${config.size}`);
5001
+ Assert$1.exists(config, `unrecognized address config: ${ADDRESS_TYPE$1} on ${network}`);
5002
+ Assert$1.ok(pk_hash.length === config.size, `invalid payload size: ${pk_hash.length} !== ${config.size}`);
5087
5003
  return encode_address({
5088
5004
  data: pk_hash,
5089
5005
  format: "bech32",
@@ -5092,11 +5008,11 @@ function encode_p2wpkh_address(script_pk, network = "main") {
5092
5008
  }
5093
5009
  function decode_p2wpkh_address(address) {
5094
5010
  const parsed = get_address_info(address);
5095
- Assert.ok(parsed.type === "p2wpkh", `address type mismatch: ${parsed.type} !== ${ADDRESS_TYPE$1}`);
5011
+ Assert$1.ok(parsed.type === "p2wpkh", `address type mismatch: ${parsed.type} !== ${ADDRESS_TYPE$1}`);
5096
5012
  return parsed;
5097
5013
  }
5098
5014
  function decode_p2wpkh_script(script) {
5099
- Assert.ok(is_p2wpkh_script(script), `invalid p2wpkh script`);
5015
+ Assert$1.ok(is_p2wpkh_script(script), `invalid p2wpkh script`);
5100
5016
  const bytes = Buff.bytes(script);
5101
5017
  return bytes.slice(2, 22);
5102
5018
  }
@@ -5126,8 +5042,8 @@ function encode_p2wsh_script(script_hash) {
5126
5042
  function encode_p2wsh_address(script_pk, network = "main") {
5127
5043
  const script_hash = decode_p2wsh_script(script_pk);
5128
5044
  const config = get_address_config(network, ADDRESS_TYPE);
5129
- Assert.exists(config, `unrecognized address config: ${ADDRESS_TYPE} on ${network}`);
5130
- Assert.size(script_hash, config.size, `invalid payload size: ${script_hash.length} !== ${config.size}`);
5045
+ Assert$1.exists(config, `unrecognized address config: ${ADDRESS_TYPE} on ${network}`);
5046
+ Assert$1.ok(script_hash.length === config.size, `invalid payload size: ${script_hash.length} !== ${config.size}`);
5131
5047
  return encode_address({
5132
5048
  data: script_hash,
5133
5049
  format: "bech32",
@@ -5136,11 +5052,11 @@ function encode_p2wsh_address(script_pk, network = "main") {
5136
5052
  }
5137
5053
  function decode_p2wsh_address(address) {
5138
5054
  const parsed = get_address_info(address);
5139
- Assert.ok(parsed.type === "p2wsh", `address type mismatch: ${parsed.type} !== ${ADDRESS_TYPE}`);
5055
+ Assert$1.ok(parsed.type === "p2wsh", `address type mismatch: ${parsed.type} !== ${ADDRESS_TYPE}`);
5140
5056
  return parsed;
5141
5057
  }
5142
5058
  function decode_p2wsh_script(script) {
5143
- Assert.ok(is_p2wsh_script(script), `invalid p2wsh script`);
5059
+ Assert$1.ok(is_p2wsh_script(script), `invalid p2wsh script`);
5144
5060
  const bytes = Buff.bytes(script);
5145
5061
  return bytes.slice(2, 34);
5146
5062
  }
@@ -5149,7 +5065,7 @@ function get_address(script, network = "main") {
5149
5065
  const bytes = Buff.bytes(script);
5150
5066
  const type = get_lock_script_type(bytes);
5151
5067
  if (type === null)
5152
- throw new Error("Unknown or unsupported locking script type");
5068
+ throw new ConfigError("Unknown or unsupported locking script type");
5153
5069
  switch (type) {
5154
5070
  case LOCK_SCRIPT_TYPE.P2PKH:
5155
5071
  return P2PKH.encode_address(script, network);
@@ -5162,7 +5078,7 @@ function get_address(script, network = "main") {
5162
5078
  case LOCK_SCRIPT_TYPE.P2TR:
5163
5079
  return P2TR.encode_address(script, network);
5164
5080
  default:
5165
- throw new Error(`unknown script type: ${type}`);
5081
+ throw new ConfigError(`unknown script type: ${type}`);
5166
5082
  }
5167
5083
  }
5168
5084
  function parse_address(address) {
@@ -5189,14 +5105,14 @@ var LocktimeField;
5189
5105
  function encode_locktime(locktime) {
5190
5106
  switch (locktime.type) {
5191
5107
  case "timelock":
5192
- Assert.ok(locktime.stamp >= LOCKTIME_THRESHOLD, "Invalid timestamp");
5108
+ Assert$1.ok(locktime.stamp >= LOCKTIME_THRESHOLD, "Invalid timestamp");
5193
5109
  return locktime.stamp;
5194
5110
  case "heightlock":
5195
- Assert.ok(locktime.height > 0, "height must be greater than 0");
5196
- Assert.ok(locktime.height < LOCKTIME_THRESHOLD, "invalid block height");
5111
+ Assert$1.ok(locktime.height > 0, "height must be greater than 0");
5112
+ Assert$1.ok(locktime.height < LOCKTIME_THRESHOLD, "invalid block height");
5197
5113
  return locktime.height;
5198
5114
  default:
5199
- throw new Error("Invalid locktime type");
5115
+ throw new ConfigError(`Invalid locktime type: expected 'timelock' or 'heightlock'`);
5200
5116
  }
5201
5117
  }
5202
5118
  function decode_locktime(locktime) {
@@ -5251,7 +5167,7 @@ function verify_inscription_id(inscription_id) {
5251
5167
  }
5252
5168
  function assert_inscription_id(inscription_id) {
5253
5169
  if (!verify_inscription_id(inscription_id)) {
5254
- throw new Error(`invalid inscription id: ${inscription_id}`);
5170
+ throw new ValidationError(`invalid inscription id: "${inscription_id}". Expected format: <64-char-txid>i<index> (e.g., "abc123...i0")`);
5255
5171
  }
5256
5172
  }
5257
5173
  function encode_rune_id(block_height, block_index) {
@@ -5270,7 +5186,7 @@ function verify_rune_id(rune_id) {
5270
5186
  }
5271
5187
  function assert_rune_id(rune_id) {
5272
5188
  if (!verify_rune_id(rune_id)) {
5273
- throw new Error(`invalid rune id: ${rune_id}`);
5189
+ throw new ValidationError(`invalid rune id: "${rune_id}". Expected format: <block_height>:<block_index> (e.g., "840000:1")`);
5274
5190
  }
5275
5191
  }
5276
5192
  function encode_outpoint(txid, vout) {
@@ -5286,7 +5202,7 @@ function verify_outpoint(outpoint) {
5286
5202
  }
5287
5203
  function assert_outpoint(outpoint) {
5288
5204
  if (!verify_outpoint(outpoint)) {
5289
- throw new Error(`invalid outpoint: ${outpoint}`);
5205
+ throw new ValidationError(`invalid outpoint: "${outpoint}". Expected format: <64-char-txid>:<vout> (e.g., "abc123...:0")`);
5290
5206
  }
5291
5207
  }
5292
5208
 
@@ -5410,14 +5326,14 @@ function get_op_code(num) {
5410
5326
  if (v === num)
5411
5327
  return k;
5412
5328
  }
5413
- throw new Error(`OPCODE not found:${String(num)}`);
5329
+ throw new ValidationError(`opcode not found for value: ${num} (0x${num.toString(16)}). Valid range is 0x00-0xba`);
5414
5330
  }
5415
5331
  function get_asm_code(string) {
5416
5332
  for (const [k, v] of Object.entries(OPCODE_MAP)) {
5417
5333
  if (k === string)
5418
5334
  return Number(v);
5419
5335
  }
5420
- throw new Error(`OPCODE not found:${string}`);
5336
+ throw new ValidationError(`opcode not found: "${string}". Valid opcodes start with "OP_" (e.g., OP_DUP, OP_CHECKSIG)`);
5421
5337
  }
5422
5338
  function get_op_type(word) {
5423
5339
  switch (true) {
@@ -5434,7 +5350,7 @@ function get_op_type(word) {
5434
5350
  case word <= 254:
5435
5351
  return "opcode";
5436
5352
  default:
5437
- throw new Error(`Invalid word range: ${word}`);
5353
+ throw new ValidationError(`invalid word value: ${word}. Expected 0-254`);
5438
5354
  }
5439
5355
  }
5440
5356
  function is_valid_op(word) {
@@ -5480,7 +5396,7 @@ function decode_script(script) {
5480
5396
  stack.push(stream.read(word).hex);
5481
5397
  }
5482
5398
  catch {
5483
- throw new Error(`Malformed script: varint push at position ${count - 1} requires ${word} bytes but stream exhausted`);
5399
+ throw new DecodingError(`Malformed script: varint push at position ${count - 1} requires ${word} bytes but stream exhausted`, count - 1);
5484
5400
  }
5485
5401
  count += word;
5486
5402
  break;
@@ -5489,13 +5405,13 @@ function decode_script(script) {
5489
5405
  word_size = stream.read(1).reverse().num;
5490
5406
  }
5491
5407
  catch {
5492
- throw new Error(`Malformed script: PUSHDATA1 at position ${count - 1} missing size byte`);
5408
+ throw new DecodingError(`Malformed script: PUSHDATA1 at position ${count - 1} missing size byte`, count - 1);
5493
5409
  }
5494
5410
  try {
5495
5411
  stack.push(stream.read(word_size).hex);
5496
5412
  }
5497
5413
  catch {
5498
- throw new Error(`Malformed script: PUSHDATA1 at position ${count - 1} requires ${word_size} bytes but stream exhausted`);
5414
+ throw new DecodingError(`Malformed script: PUSHDATA1 at position ${count - 1} requires ${word_size} bytes but stream exhausted`, count - 1);
5499
5415
  }
5500
5416
  count += word_size + 1;
5501
5417
  break;
@@ -5504,13 +5420,13 @@ function decode_script(script) {
5504
5420
  word_size = stream.read(2).reverse().num;
5505
5421
  }
5506
5422
  catch {
5507
- throw new Error(`Malformed script: PUSHDATA2 at position ${count - 1} missing size bytes`);
5423
+ throw new DecodingError(`Malformed script: PUSHDATA2 at position ${count - 1} missing size bytes`, count - 1);
5508
5424
  }
5509
5425
  try {
5510
5426
  stack.push(stream.read(word_size).hex);
5511
5427
  }
5512
5428
  catch {
5513
- throw new Error(`Malformed script: PUSHDATA2 at position ${count - 1} requires ${word_size} bytes but stream exhausted`);
5429
+ throw new DecodingError(`Malformed script: PUSHDATA2 at position ${count - 1} requires ${word_size} bytes but stream exhausted`, count - 1);
5514
5430
  }
5515
5431
  count += word_size + 2;
5516
5432
  break;
@@ -5519,24 +5435,24 @@ function decode_script(script) {
5519
5435
  word_size = stream.read(4).reverse().num;
5520
5436
  }
5521
5437
  catch {
5522
- throw new Error(`Malformed script: PUSHDATA4 at position ${count - 1} missing size bytes`);
5438
+ throw new DecodingError(`Malformed script: PUSHDATA4 at position ${count - 1} missing size bytes`, count - 1);
5523
5439
  }
5524
5440
  try {
5525
5441
  stack.push(stream.read(word_size).hex);
5526
5442
  }
5527
5443
  catch {
5528
- throw new Error(`Malformed script: PUSHDATA4 at position ${count - 1} requires ${word_size} bytes but stream exhausted`);
5444
+ throw new DecodingError(`Malformed script: PUSHDATA4 at position ${count - 1} requires ${word_size} bytes but stream exhausted`, count - 1);
5529
5445
  }
5530
5446
  count += word_size + 4;
5531
5447
  break;
5532
5448
  case "opcode":
5533
5449
  if (!is_valid_op(word)) {
5534
- throw new Error(`Invalid OPCODE: ${word}`);
5450
+ throw new DecodingError(`Invalid OPCODE: ${word}`, count - 1);
5535
5451
  }
5536
5452
  stack.push(get_op_code(word));
5537
5453
  break;
5538
5454
  default:
5539
- throw new Error(`Word type undefined: ${word}`);
5455
+ throw new DecodingError(`Word type undefined: ${word}`, count - 1);
5540
5456
  }
5541
5457
  }
5542
5458
  return stack;
@@ -5561,7 +5477,7 @@ function encode_script(words, varint = false) {
5561
5477
  }
5562
5478
  const buffer = Buff.join(bytes);
5563
5479
  if (buffer.length > MAX_SCRIPT_SIZE) {
5564
- throw new Error(`script size ${buffer.length} exceeds consensus limit of ${MAX_SCRIPT_SIZE} bytes`);
5480
+ throw new ValidationError(`script size ${buffer.length} exceeds consensus limit of ${MAX_SCRIPT_SIZE} bytes`);
5565
5481
  }
5566
5482
  return varint
5567
5483
  ? buffer.prepend(Buff.create_varint(buffer.length, "le"))
@@ -5588,7 +5504,7 @@ function encode_script_word(word) {
5588
5504
  buff = new Buff(word);
5589
5505
  }
5590
5506
  else {
5591
- throw new Error(`invalid word type:${typeof word}`);
5507
+ throw new ValidationError(`invalid script word type: ${typeof word}. Expected string, number, or Uint8Array`);
5592
5508
  }
5593
5509
  if (buff.length === 1 && buff[0] <= 16) {
5594
5510
  if (buff[0] !== 0)
@@ -5629,7 +5545,7 @@ function get_size_varint(size) {
5629
5545
  case size >= 0x100 && size <= MAX_WORD_SIZE:
5630
5546
  return Buff.join([OP_PUSHDATA2, Buff.num(size, 2, "le")]);
5631
5547
  default:
5632
- throw new Error(`Invalid word size:${size.toString()}`);
5548
+ throw new ValidationError(`invalid script word size: ${size}. Maximum allowed is ${MAX_WORD_SIZE} bytes`);
5633
5549
  }
5634
5550
  }
5635
5551
 
@@ -5687,16 +5603,17 @@ function create_envelope(data) {
5687
5603
  function parse_envelopes(script) {
5688
5604
  const words = decode_script(script);
5689
5605
  const start_idx = words.indexOf("OP_0");
5690
- Assert.ok(start_idx !== -1, "inscription envelope not found");
5606
+ Assert$1.ok(start_idx !== -1, "inscription envelope not found");
5691
5607
  const envelopes = [];
5692
5608
  for (let idx = start_idx; idx < words.length; idx++) {
5693
- Assert.ok(words[idx + 1] === "OP_IF", "OP_IF missing from envelope");
5694
- Assert.ok(words[idx + 2] === "6f7264", "magic bytes missing from envelope");
5695
- const stop_idx = words.indexOf("OP_ENDIF");
5696
- Assert.ok(stop_idx !== -1, "inscription envelope missing END_IF statement");
5609
+ Assert$1.ok(idx + 2 < words.length, "incomplete envelope: missing OP_IF or magic bytes");
5610
+ Assert$1.ok(words[idx + 1] === "OP_IF", "OP_IF missing from envelope");
5611
+ Assert$1.ok(words[idx + 2] === "6f7264", "magic bytes missing from envelope");
5612
+ const stop_idx = words.indexOf("OP_ENDIF", idx);
5613
+ Assert$1.ok(stop_idx !== -1, "inscription envelope missing OP_ENDIF statement");
5697
5614
  const env = words.slice(idx + 3, stop_idx);
5698
5615
  envelopes.push(env);
5699
- idx += stop_idx;
5616
+ idx = stop_idx;
5700
5617
  }
5701
5618
  return envelopes;
5702
5619
  }
@@ -5742,8 +5659,21 @@ function parse_record(envelope) {
5742
5659
  function decode_bytes(bytes) {
5743
5660
  return Buff.bytes(bytes).hex;
5744
5661
  }
5662
+ function normalize_script_word(word) {
5663
+ if (typeof word === "string" && word.startsWith("OP_")) {
5664
+ if (word === "OP_0")
5665
+ return Buff.num(0).hex;
5666
+ const match = word.match(/^OP_(\d+)$/);
5667
+ if (match) {
5668
+ const num = parseInt(match[1], 10);
5669
+ if (num >= 1 && num <= 16)
5670
+ return Buff.num(num).hex;
5671
+ }
5672
+ }
5673
+ return word;
5674
+ }
5745
5675
  function encode_id(identifier) {
5746
- Assert.ok(identifier.includes("i"), "identifier must include an index");
5676
+ Assert$1.ok(identifier.includes("i"), "identifier must include an index");
5747
5677
  const parts = identifier.split("i");
5748
5678
  const bytes = Buff.hex(parts[0]);
5749
5679
  const idx = Number(parts[1]);
@@ -5752,6 +5682,9 @@ function encode_id(identifier) {
5752
5682
  }
5753
5683
  function decode_id(identifier) {
5754
5684
  const bytes = Buff.bytes(identifier);
5685
+ if (bytes.length === 32) {
5686
+ return `${bytes.reverse().hex}i0`;
5687
+ }
5755
5688
  const idx = bytes.at(-1) ?? 0;
5756
5689
  const txid = bytes.slice(0, -1).reverse().hex;
5757
5690
  return `${txid}i${String(idx)}`;
@@ -5760,7 +5693,7 @@ function encode_pointer(pointer) {
5760
5693
  return Buff.num(pointer).reverse().hex;
5761
5694
  }
5762
5695
  function decode_pointer(bytes) {
5763
- return Buff.bytes(bytes).reverse().num;
5696
+ return Buff.bytes(normalize_script_word(bytes)).reverse().num;
5764
5697
  }
5765
5698
  function encode_label(label) {
5766
5699
  return Buff.str(label).hex;
@@ -5795,12 +5728,16 @@ function encode_rune_label(label) {
5795
5728
  if (char >= "A" && char <= "Z") {
5796
5729
  big = big * _26n + BigInt(char.charCodeAt(0) - ("A".charCodeAt(0) - 1));
5797
5730
  }
5731
+ else {
5732
+ throw new ValidationError(`invalid character in rune label: '${char}' (only A-Z allowed)`, "label");
5733
+ }
5798
5734
  }
5799
5735
  big = big - _1n;
5800
5736
  return Buff.big(big).reverse().hex;
5801
5737
  }
5802
5738
  function decode_rune_label(label) {
5803
- let big = Buff.bytes(label).reverse().big;
5739
+ const normalized = normalize_script_word(label);
5740
+ let big = Buff.bytes(normalized).reverse().big;
5804
5741
  big = big + _1n;
5805
5742
  let result = "";
5806
5743
  while (big > _0n) {
@@ -5837,7 +5774,7 @@ function encode_sequence(data) {
5837
5774
  const stamp = parse_stamp(data.stamp);
5838
5775
  return (TIMELOCK_TYPE | (stamp & TIMELOCK_VALUE_MASK)) >>> 0;
5839
5776
  }
5840
- throw new Error(`invalid timelock mode: ${data.mode}`);
5777
+ throw new ValidationError(`invalid timelock mode: "${data.mode}". Valid modes are "height" or "stamp"`);
5841
5778
  }
5842
5779
  function decode_sequence(sequence) {
5843
5780
  const seq = parse_sequence(sequence);
@@ -5847,13 +5784,13 @@ function decode_sequence(sequence) {
5847
5784
  if (seq & TIMELOCK_TYPE) {
5848
5785
  const stamp = value * TIMELOCK_GRANULARITY;
5849
5786
  if (stamp > 0xffffffff) {
5850
- throw new Error("Decoded timestamp exceeds 32-bit limit");
5787
+ throw new ValidationError(`decoded timestamp ${stamp} exceeds 32-bit limit (max: ${0xffffffff})`);
5851
5788
  }
5852
5789
  return { mode: "stamp", stamp };
5853
5790
  }
5854
5791
  else {
5855
5792
  if (value > TIMELOCK_VALUE_MAX) {
5856
- throw new Error("Decoded height exceeds maximum");
5793
+ throw new ValidationError(`decoded height ${value} exceeds maximum (${TIMELOCK_VALUE_MAX})`);
5857
5794
  }
5858
5795
  return { mode: "height", height: value };
5859
5796
  }
@@ -5861,17 +5798,17 @@ function decode_sequence(sequence) {
5861
5798
  function parse_sequence(sequence) {
5862
5799
  const seq = typeof sequence === "string" ? parseInt(sequence, 16) : sequence;
5863
5800
  if (!Number.isInteger(seq) || seq < 0 || seq > 0xffffffff) {
5864
- throw new Error(`invalid sequence value: ${seq}`);
5801
+ throw new ValidationError(`invalid sequence value: ${seq}. Must be an integer between 0 and 0xffffffff`);
5865
5802
  }
5866
5803
  return seq;
5867
5804
  }
5868
5805
  function parse_stamp(stamp) {
5869
5806
  if (stamp === undefined || !Number.isInteger(stamp)) {
5870
- throw new Error(`timestamp must be a number`);
5807
+ throw new ValidationError(`timestamp must be an integer, got: ${stamp}`);
5871
5808
  }
5872
5809
  const ts = Math.floor(stamp / TIMELOCK_GRANULARITY);
5873
5810
  if (!Number.isInteger(ts) || ts < 0 || ts > TIMELOCK_VALUE_MAX) {
5874
- throw new Error(`timelock value must be an integer between 0 and ${TIMELOCK_VALUE_MAX} (in 512-second increments)`);
5811
+ throw new ValidationError(`timelock value must be an integer between 0 and ${TIMELOCK_VALUE_MAX} (in 512-second increments)`);
5875
5812
  }
5876
5813
  return ts;
5877
5814
  }
@@ -5880,7 +5817,7 @@ function parse_height(height) {
5880
5817
  !Number.isInteger(height) ||
5881
5818
  height < 0 ||
5882
5819
  height > TIMELOCK_VALUE_MAX) {
5883
- throw new Error(`Heightlock value must be an integer between 0 and ${TIMELOCK_VALUE_MAX}`);
5820
+ throw new ValidationError(`heightlock value must be an integer between 0 and ${TIMELOCK_VALUE_MAX}, got: ${height}`);
5884
5821
  }
5885
5822
  return height;
5886
5823
  }
@@ -5941,10 +5878,10 @@ var index$6 = /*#__PURE__*/Object.freeze({
5941
5878
  const MAX_TX_SIZE = 4_000_000;
5942
5879
  const MAX_TX_ELEMENTS = 100_000;
5943
5880
  function decode_tx(txdata, use_segwit = true) {
5944
- Assert.is_bytes(txdata, "txdata must be hex or bytes");
5881
+ Assert$1.ok(typeof txdata === "string" || txdata instanceof Uint8Array, "txdata must be hex or bytes");
5945
5882
  const txSize = typeof txdata === "string" ? txdata.length / 2 : txdata.length;
5946
5883
  if (txSize > MAX_TX_SIZE) {
5947
- throw new Error(`Transaction size ${txSize} exceeds maximum ${MAX_TX_SIZE} bytes`);
5884
+ throw new DecodingError(`Transaction size ${txSize} exceeds maximum ${MAX_TX_SIZE} bytes`);
5948
5885
  }
5949
5886
  const stream = new Stream(txdata);
5950
5887
  const version = read_version(stream);
@@ -5971,7 +5908,7 @@ function check_witness_flag(stream) {
5971
5908
  return true;
5972
5909
  }
5973
5910
  else {
5974
- throw new Error(`Invalid witness flag: ${flag}`);
5911
+ throw new DecodingError(`Invalid witness flag: ${flag}`, 1);
5975
5912
  }
5976
5913
  }
5977
5914
  return false;
@@ -5980,7 +5917,7 @@ function read_inputs(stream) {
5980
5917
  const inputs = [];
5981
5918
  const vinCount = stream.read_varint();
5982
5919
  if (vinCount > MAX_TX_ELEMENTS) {
5983
- throw new Error(`Input count ${vinCount} exceeds maximum ${MAX_TX_ELEMENTS}`);
5920
+ throw new DecodingError(`Input count ${vinCount} exceeds maximum ${MAX_TX_ELEMENTS}`);
5984
5921
  }
5985
5922
  for (let i = 0; i < vinCount; i++) {
5986
5923
  const txinput = read_vin(stream);
@@ -6021,14 +5958,15 @@ function read_outputs(stream) {
6021
5958
  const outputs = [];
6022
5959
  const vcount = stream.read_varint();
6023
5960
  if (vcount > MAX_TX_ELEMENTS) {
6024
- throw new Error(`Output count ${vcount} exceeds maximum ${MAX_TX_ELEMENTS}`);
5961
+ throw new DecodingError(`Output count ${vcount} exceeds maximum ${MAX_TX_ELEMENTS}`);
6025
5962
  }
6026
5963
  for (let i = 0; i < vcount; i++) {
6027
5964
  try {
6028
5965
  outputs.push(read_vout(stream));
6029
5966
  }
6030
- catch (_error) {
6031
- throw new Error(`failed to decode output at index ${i}`);
5967
+ catch (error) {
5968
+ const message = error instanceof Error ? error.message : String(error);
5969
+ throw new DecodingError(`Failed to decode output at index ${i}: ${message}`);
6032
5970
  }
6033
5971
  }
6034
5972
  return outputs;
@@ -6036,19 +5974,19 @@ function read_outputs(stream) {
6036
5974
  function read_vout(stream) {
6037
5975
  const value = stream.read(8).reverse().big;
6038
5976
  const script_pk = read_payload(stream);
6039
- Assert.exists(script_pk, "failed to decode script_pk");
5977
+ Assert$1.exists(script_pk, "failed to decode script_pk");
6040
5978
  return { value, script_pk };
6041
5979
  }
6042
5980
  function read_witness(stream) {
6043
5981
  const stack = [];
6044
5982
  const count = stream.read_varint();
6045
5983
  if (count > MAX_TX_ELEMENTS) {
6046
- throw new Error(`Witness element count ${count} exceeds maximum ${MAX_TX_ELEMENTS}`);
5984
+ throw new DecodingError(`Witness element count ${count} exceeds maximum ${MAX_TX_ELEMENTS}`);
6047
5985
  }
6048
5986
  for (let i = 0; i < count; i++) {
6049
5987
  const element = read_payload(stream);
6050
5988
  if (element === null) {
6051
- throw new Error(`failed to decode witness element at index ${i}`);
5989
+ throw new DecodingError(`Failed to decode witness element at index ${i}`);
6052
5990
  }
6053
5991
  stack.push(element);
6054
5992
  }
@@ -6057,7 +5995,7 @@ function read_witness(stream) {
6057
5995
  function read_payload(stream) {
6058
5996
  const size = stream.read_varint("le");
6059
5997
  if (size > MAX_VARINT_SIZE) {
6060
- throw new Error(`Payload size ${size} exceeds maximum ${MAX_VARINT_SIZE}`);
5998
+ throw new DecodingError(`Payload size ${size} exceeds maximum ${MAX_VARINT_SIZE}`);
6061
5999
  }
6062
6000
  return size > 0 ? stream.read(size).hex : null;
6063
6001
  }
@@ -7240,7 +7178,7 @@ class Doc {
7240
7178
  const version = {
7241
7179
  major: 4,
7242
7180
  minor: 3,
7243
- patch: 5,
7181
+ patch: 6,
7244
7182
  };
7245
7183
 
7246
7184
  const $ZodType = /*@__PURE__*/ $constructor("$ZodType", (inst, def) => {
@@ -8298,11 +8236,9 @@ const $ZodRecord = /*@__PURE__*/ $constructor("$ZodRecord", (inst, def) => {
8298
8236
  if (keyResult instanceof Promise) {
8299
8237
  throw new Error("Async schemas not supported in object keys currently");
8300
8238
  }
8301
- // Numeric string fallback: if key failed with "expected number", retry with Number(key)
8302
- const checkNumericKey = typeof key === "string" &&
8303
- number$1.test(key) &&
8304
- keyResult.issues.length &&
8305
- keyResult.issues.some((iss) => iss.code === "invalid_type" && iss.expected === "number");
8239
+ // Numeric string fallback: if key is a numeric string and failed, retry with Number(key)
8240
+ // This handles z.number(), z.literal([1, 2, 3]), and unions containing numeric literals
8241
+ const checkNumericKey = typeof key === "string" && number$1.test(key) && keyResult.issues.length;
8306
8242
  if (checkNumericKey) {
8307
8243
  const retryResult = def.keyType._zod.run({ value: Number(key), issues: [] }, ctx);
8308
8244
  if (retryResult instanceof Promise) {
@@ -9503,7 +9439,7 @@ function finalize(ctx, schema) {
9503
9439
  }
9504
9440
  }
9505
9441
  // When ref was extracted to $defs, remove properties that match the definition
9506
- if (refSchema.$ref) {
9442
+ if (refSchema.$ref && refSeen.def) {
9507
9443
  for (const key in schema) {
9508
9444
  if (key === "$ref" || key === "allOf")
9509
9445
  continue;
@@ -10905,32 +10841,59 @@ var index$5 = /*#__PURE__*/Object.freeze({
10905
10841
  tx: tx
10906
10842
  });
10907
10843
 
10844
+ function format_zod_error(error) {
10845
+ const issues = error.issues.map((issue) => {
10846
+ const path = issue.path.length > 0 ? `${issue.path.join(".")}: ` : "";
10847
+ return `${path}${issue.message}`;
10848
+ });
10849
+ return issues.join("; ");
10850
+ }
10908
10851
  function assert_tx_template(txdata) {
10909
- tx_template.parse(txdata);
10852
+ const result = tx_template.safeParse(txdata);
10853
+ if (!result.success) {
10854
+ throw new ValidationError(`invalid transaction template: ${format_zod_error(result.error)}`);
10855
+ }
10910
10856
  }
10911
10857
  function assert_has_prevouts(vin) {
10912
- if (vin.some((txin) => txin.prevout === null)) {
10913
- throw new Error("transaction missing prevouts");
10858
+ const missingIdx = vin.findIndex((txin) => txin.prevout === null || txin.prevout === undefined);
10859
+ if (missingIdx !== -1) {
10860
+ throw new ValidationError(`transaction input at index ${missingIdx} is missing prevout data. ` +
10861
+ `Prevout (previous output) is required for signing`);
10914
10862
  }
10915
10863
  }
10916
10864
  function assert_tx_data(txdata) {
10917
- tx_data.parse(txdata);
10865
+ const result = tx_data.safeParse(txdata);
10866
+ if (!result.success) {
10867
+ throw new ValidationError(`invalid transaction data: ${format_zod_error(result.error)}`);
10868
+ }
10918
10869
  }
10919
10870
  function assert_tx_spend_data(txdata) {
10920
10871
  assert_tx_data(txdata);
10921
10872
  assert_has_prevouts(txdata.vin);
10922
10873
  }
10923
10874
  function assert_tx_input(tx_input$1) {
10924
- tx_input.parse(tx_input$1);
10875
+ const result = tx_input.safeParse(tx_input$1);
10876
+ if (!result.success) {
10877
+ throw new ValidationError(`invalid transaction input: ${format_zod_error(result.error)}`);
10878
+ }
10925
10879
  }
10926
10880
  function assert_tx_output(tx_output$1) {
10927
- tx_output.parse(tx_output$1);
10881
+ const result = tx_output.safeParse(tx_output$1);
10882
+ if (!result.success) {
10883
+ throw new ValidationError(`invalid transaction output: ${format_zod_error(result.error)}`);
10884
+ }
10928
10885
  }
10929
10886
  function assert_vin_template(vin) {
10930
- vin_template.parse(vin);
10887
+ const result = vin_template.safeParse(vin);
10888
+ if (!result.success) {
10889
+ throw new ValidationError(`invalid input template: ${format_zod_error(result.error)}`);
10890
+ }
10931
10891
  }
10932
10892
  function assert_vout_template(vout) {
10933
- vout_template.parse(vout);
10893
+ const result = vout_template.safeParse(vout);
10894
+ if (!result.success) {
10895
+ throw new ValidationError(`invalid output template: ${format_zod_error(result.error)}`);
10896
+ }
10934
10897
  }
10935
10898
 
10936
10899
  function encode_tx(txdata, use_segwit = true) {
@@ -11013,7 +10976,7 @@ function encode_tx_locktime(locktime) {
11013
10976
  }
11014
10977
  function encode_script_data(script) {
11015
10978
  if (script !== null) {
11016
- Assert.is_hex(script);
10979
+ Assert$1.is_hex(script);
11017
10980
  return Buff.hex(script).prefix_varint("le");
11018
10981
  }
11019
10982
  else {
@@ -11031,10 +10994,10 @@ function parse_tx(txdata, prevouts) {
11031
10994
  tx = create_tx(txdata);
11032
10995
  }
11033
10996
  if (prevouts) {
11034
- Assert.has_items(prevouts, "prevouts must be a non-empty array");
10997
+ Assert$1.has_items(prevouts, "prevouts must be a non-empty array");
11035
10998
  for (const [idx, vin] of tx.vin.entries()) {
11036
10999
  const prevout = prevouts.at(idx);
11037
- Assert.exists(prevout, `prevout not found for input index: ${idx}`);
11000
+ Assert$1.exists(prevout, `prevout not found for input index: ${idx}`);
11038
11001
  vin.prevout = create_tx_output(prevout);
11039
11002
  }
11040
11003
  }
@@ -11050,14 +11013,14 @@ function serialize_tx(txdata) {
11050
11013
  if (e.prevout !== null) {
11051
11014
  vin.push({
11052
11015
  script_pk: e.prevout.script_pk,
11053
- value: Number(e.prevout.value),
11016
+ value: String(e.prevout.value),
11054
11017
  });
11055
11018
  }
11056
11019
  }
11057
11020
  for (const e of tx.vout) {
11058
11021
  vout.push({
11059
11022
  script_pk: e.script_pk,
11060
- value: Number(e.value),
11023
+ value: String(e.value),
11061
11024
  });
11062
11025
  }
11063
11026
  return { version, locktime, vin, vout };
@@ -11077,7 +11040,7 @@ function get_txid(txdata) {
11077
11040
  buffer = encode_tx(txdata, false);
11078
11041
  }
11079
11042
  else if (typeof txdata === "string") {
11080
- Assert.is_hex(txdata);
11043
+ Assert$1.is_hex(txdata);
11081
11044
  buffer = transcode_tx(txdata, false);
11082
11045
  }
11083
11046
  else {
@@ -11103,7 +11066,7 @@ function get_tx_value(txdata) {
11103
11066
  function get_prevouts(txdata) {
11104
11067
  assert_tx_template(txdata);
11105
11068
  const prevouts = txdata.vin.map((e) => e.prevout);
11106
- Assert.ok(prevouts.every((e) => e !== null), "prevouts missing from tx");
11069
+ Assert$1.ok(prevouts.every((e) => e !== null), "prevouts missing from tx");
11107
11070
  return prevouts;
11108
11071
  }
11109
11072
  function normalize_sequence(sequence) {
@@ -11131,7 +11094,7 @@ function normalize_prevout(prevout) {
11131
11094
 
11132
11095
  function create_coinbase_input(config) {
11133
11096
  assert_vin_template(config);
11134
- Assert.exists(config.coinbase, "coinbase is required");
11097
+ Assert$1.exists(config.coinbase, "coinbase is required");
11135
11098
  const txid = COINBASE.TXID;
11136
11099
  const vout = COINBASE.VOUT;
11137
11100
  const coinbase = config.coinbase;
@@ -11149,8 +11112,8 @@ function create_coinbase_input(config) {
11149
11112
  }
11150
11113
  function create_virtual_input(config) {
11151
11114
  assert_vin_template(config);
11152
- Assert.is_empty(config.coinbase, "coinbase is not allowed");
11153
- Assert.is_empty(config.prevout, "prevout is not allowed");
11115
+ Assert$1.is_empty(config.coinbase, "coinbase is not allowed");
11116
+ Assert$1.is_empty(config.prevout, "prevout is not allowed");
11154
11117
  const { txid, vout, script_sig = null, witness = [] } = config;
11155
11118
  const sequence = normalize_sequence(config.sequence);
11156
11119
  return {
@@ -11165,7 +11128,7 @@ function create_virtual_input(config) {
11165
11128
  }
11166
11129
  function create_spend_input(config) {
11167
11130
  assert_vin_template(config);
11168
- Assert.exists(config.prevout, "prevout is required");
11131
+ Assert$1.exists(config.prevout, "prevout is required");
11169
11132
  const { txid, vout, script_sig = null, witness = [] } = config;
11170
11133
  const prevout = normalize_prevout(config.prevout);
11171
11134
  const sequence = normalize_sequence(config.sequence);
@@ -11197,16 +11160,14 @@ function create_tx(config) {
11197
11160
  const WIT_FLAG_BYTES = 2;
11198
11161
  function get_vsize(bytes) {
11199
11162
  const weight = Buff.bytes(bytes).length;
11200
- const remain = weight % 4 > 0 ? 1 : 0;
11201
- return Math.ceil(weight / 4) + remain;
11163
+ return Math.ceil(weight / 4);
11202
11164
  }
11203
11165
  function get_txsize(txdata) {
11204
11166
  const json = parse_tx(txdata);
11205
11167
  const base = encode_tx(json, false).length;
11206
11168
  const total = encode_tx(json, true).length;
11207
11169
  const weight = base * 3 + total;
11208
- const remain = weight % 4 > 0 ? 1 : 0;
11209
- const vsize = Math.ceil(weight / 4) + remain;
11170
+ const vsize = Math.ceil(weight / 4);
11210
11171
  return { base, total, vsize, weight };
11211
11172
  }
11212
11173
  function get_vin_size(vin) {
@@ -11284,18 +11245,18 @@ var index$4 = /*#__PURE__*/Object.freeze({
11284
11245
  });
11285
11246
 
11286
11247
  function get_prevout(vin) {
11287
- Assert.exists(vin.prevout, `Prevout data missing for input: ${String(vin.txid)}`);
11248
+ Assert$1.exists(vin.prevout, `Prevout data missing for input: ${String(vin.txid)}`);
11288
11249
  return vin.prevout;
11289
11250
  }
11290
11251
  function parse_txinput(txdata, config) {
11291
11252
  let { txindex, txinput } = config ?? {};
11292
11253
  if (txindex !== undefined) {
11293
11254
  if (txindex >= txdata.vin.length) {
11294
- throw new Error(`Input index out of bounds: ${String(txindex)}`);
11255
+ throw new ValidationError(`input index ${txindex} out of bounds. Transaction has ${txdata.vin.length} inputs (indices 0-${txdata.vin.length - 1})`);
11295
11256
  }
11296
11257
  txinput = txdata.vin.at(txindex);
11297
11258
  }
11298
- Assert.ok(txinput !== undefined);
11259
+ Assert$1.ok(txinput !== undefined);
11299
11260
  return txinput;
11300
11261
  }
11301
11262
  function get_annex_data(witness) {
@@ -11317,14 +11278,16 @@ function hash_segwit_tx(txdata, options = {}) {
11317
11278
  const is_anypay = (sigflag & 0x80) === 0x80;
11318
11279
  const flag = sigflag % 0x80;
11319
11280
  if (!SIGHASH_SEGWIT.includes(flag)) {
11320
- throw new Error(`Invalid hash type: ${String(sigflag)}`);
11281
+ throw new ValidationError(`invalid sighash type: 0x${sigflag.toString(16)}. ` +
11282
+ `Valid values: SIGHASH_ALL (0x01), SIGHASH_NONE (0x02), SIGHASH_SINGLE (0x03), ` +
11283
+ `or combined with ANYONECANPAY (0x81, 0x82, 0x83)`);
11321
11284
  }
11322
11285
  const { version, vin, vout, locktime } = tx;
11323
11286
  const txinput = parse_txinput(tx, options);
11324
11287
  const { txid, vout: prevIdx, prevout, sequence } = txinput;
11325
11288
  const { value } = prevout ?? {};
11326
11289
  if (value === undefined) {
11327
- throw new Error("Prevout value is empty!");
11290
+ throw new ValidationError("Prevout value is required for segwit sighash calculation", "prevout.value");
11328
11291
  }
11329
11292
  let { pubkey, script } = options;
11330
11293
  if (script === undefined && pubkey !== undefined) {
@@ -11332,10 +11295,10 @@ function hash_segwit_tx(txdata, options = {}) {
11332
11295
  script = `76a914${String(pkhash)}88ac`;
11333
11296
  }
11334
11297
  if (script === undefined) {
11335
- throw new Error("No pubkey / script has been set!");
11298
+ throw new ValidationError("Either pubkey or script must be provided for segwit sighash", "pubkey/script");
11336
11299
  }
11337
11300
  if (decode_script(script).includes("OP_CODESEPARATOR")) {
11338
- throw new Error("This library does not currently support the use of OP_CODESEPARATOR in segwit scripts.");
11301
+ throw new ValidationError("OP_CODESEPARATOR is not supported in segwit scripts", "script");
11339
11302
  }
11340
11303
  const sighash = [
11341
11304
  encode_tx_version(version),
@@ -11383,8 +11346,8 @@ function bip143_hash_outputs(vout, sigflag, idx) {
11383
11346
  return hash256(Buff.join(stack));
11384
11347
  }
11385
11348
  if (sigflag === 0x03) {
11386
- Assert.ok(idx !== undefined, "txindex required for SIGHASH_SINGLE");
11387
- Assert.ok(idx >= 0, "txindex must be non-negative");
11349
+ Assert$1.ok(idx !== undefined, "txindex required for SIGHASH_SINGLE");
11350
+ Assert$1.ok(idx >= 0, "txindex must be non-negative");
11388
11351
  if (idx < vout.length) {
11389
11352
  const { value, script_pk } = vout[idx];
11390
11353
  stack.push(encode_vout_value(value));
@@ -11414,7 +11377,7 @@ function encode_leaf_version(version = 0xc0) {
11414
11377
  return version & 0xfe;
11415
11378
  }
11416
11379
  function encode_taptweak(pubkey, data = new Uint8Array()) {
11417
- Assert.size(pubkey, 32);
11380
+ Assert$1.ok(Buff.bytes(pubkey).length === 32, "pubkey must be 32 bytes");
11418
11381
  return hash340("TapTweak", pubkey, data);
11419
11382
  }
11420
11383
 
@@ -11429,10 +11392,12 @@ function get_taproot_tx_preimage(template, config = {}) {
11429
11392
  const txinput = parse_txinput(tx, config);
11430
11393
  const { txid, vout, sequence, witness = [] } = txinput;
11431
11394
  if (!SIGHASH_TAPROOT.includes(sigflag)) {
11432
- throw new Error(`Invalid hash type: ${String(sigflag)}`);
11395
+ throw new ValidationError(`invalid taproot sighash type: 0x${sigflag.toString(16)}. ` +
11396
+ `Valid values: SIGHASH_DEFAULT (0x00), SIGHASH_ALL (0x01), SIGHASH_NONE (0x02), SIGHASH_SINGLE (0x03), ` +
11397
+ `or combined with ANYONECANPAY (0x81, 0x82, 0x83)`);
11433
11398
  }
11434
11399
  if (extflag < 0 || extflag > 127) {
11435
- throw new Error(`Extention flag out of range: ${String(extflag)}`);
11400
+ throw new ValidationError(`extension flag out of range: ${extflag}. Valid range is 0-127`);
11436
11401
  }
11437
11402
  let { extension } = config;
11438
11403
  if (script !== undefined) {
@@ -11462,15 +11427,15 @@ function get_taproot_tx_preimage(template, config = {}) {
11462
11427
  preimage.push(encode_txin_txid(txid), encode_txin_vout(vout), encode_vout_value(value), encode_script_data(script_pk), encode_txin_sequence(sequence));
11463
11428
  }
11464
11429
  else {
11465
- Assert.ok(typeof txindex === "number");
11430
+ Assert$1.ok(typeof txindex === "number");
11466
11431
  preimage.push(Buff.num(txindex, 4).reverse());
11467
11432
  }
11468
11433
  if (annex !== undefined) {
11469
11434
  preimage.push(annex);
11470
11435
  }
11471
11436
  if ((sigflag & 0x03) === 0x03) {
11472
- Assert.ok(typeof txindex === "number", "txindex required for SIGHASH_SINGLE");
11473
- Assert.ok(txindex >= 0 && txindex < output.length, `txindex ${txindex} out of bounds for ${output.length} outputs`);
11437
+ Assert$1.ok(typeof txindex === "number", "txindex required for SIGHASH_SINGLE");
11438
+ Assert$1.ok(txindex >= 0 && txindex < output.length, `txindex ${txindex} out of bounds for ${output.length} outputs`);
11474
11439
  preimage.push(bip341_hash_output(output[txindex]));
11475
11440
  }
11476
11441
  if (extension !== undefined) {
@@ -11529,31 +11494,31 @@ var index$3 = /*#__PURE__*/Object.freeze({
11529
11494
  const SECKEY_REGEX = /^[0-9a-fA-F]{64}$/;
11530
11495
  function validate_seckey(seckey) {
11531
11496
  if (typeof seckey !== "string") {
11532
- throw new Error("Secret key must be a string");
11497
+ throw new ValidationError("Secret key must be a string", "seckey");
11533
11498
  }
11534
11499
  if (!SECKEY_REGEX.test(seckey)) {
11535
- throw new Error("Invalid secret key format: expected 32-byte hex string (64 characters)");
11500
+ throw new ValidationError("Invalid secret key format: expected 32-byte hex string (64 characters)", "seckey");
11536
11501
  }
11537
11502
  }
11538
11503
  function validate_sighash_options(options, validFlags) {
11539
11504
  const { sigflag, txindex } = options;
11540
11505
  if (sigflag !== undefined) {
11541
11506
  if (typeof sigflag !== "number" || !Number.isInteger(sigflag)) {
11542
- throw new Error("sigflag must be an integer");
11507
+ throw new ConfigError("sigflag must be an integer");
11543
11508
  }
11544
11509
  const normalizedFlag = sigflag & 0x7f;
11545
11510
  const isAnypay = (sigflag & 0x80) === 0x80;
11546
11511
  const baseFlag = isAnypay ? normalizedFlag | 0x80 : normalizedFlag;
11547
11512
  if (!validFlags.includes(baseFlag) &&
11548
11513
  !validFlags.includes(normalizedFlag)) {
11549
- throw new Error(`Invalid sigflag: ${sigflag}`);
11514
+ throw new ConfigError(`Invalid sigflag: ${sigflag}`);
11550
11515
  }
11551
11516
  }
11552
11517
  if (txindex !== undefined) {
11553
11518
  if (typeof txindex !== "number" ||
11554
11519
  !Number.isInteger(txindex) ||
11555
11520
  txindex < 0) {
11556
- throw new Error("txindex must be a non-negative integer");
11521
+ throw new ValidationError("txindex must be a non-negative integer", "txindex");
11557
11522
  }
11558
11523
  }
11559
11524
  }
@@ -11668,8 +11633,8 @@ function parse_witness_version(type) {
11668
11633
 
11669
11634
  function parse_taproot_witness(witness) {
11670
11635
  const { cblock, params, script } = parse_witness(witness);
11671
- Assert.exists(cblock, "cblock is null");
11672
- Assert.exists(script, "script is null");
11636
+ Assert$1.exists(cblock, "cblock is null");
11637
+ Assert$1.exists(script, "script is null");
11673
11638
  const cblk = parse_cblock(cblock);
11674
11639
  const target = encode_tapscript(script, cblk.version);
11675
11640
  let branch = target.hex;
@@ -11678,8 +11643,8 @@ function parse_taproot_witness(witness) {
11678
11643
  }
11679
11644
  const tweak = encode_taptweak(cblk.int_key, branch);
11680
11645
  const tapkey = tweak_pubkey(cblk.int_key, tweak, "bip340");
11681
- params.map((e) => Buff.bytes(e).hex);
11682
- return { cblock: cblk, params, script, tapkey: tapkey.hex, tweak: tweak.hex };
11646
+ const hexParams = params.map((e) => Buff.bytes(e).hex);
11647
+ return { cblock: cblk, params: hexParams, script, tapkey: tapkey.hex, tweak: tweak.hex };
11683
11648
  }
11684
11649
  function parse_cblock(cblock) {
11685
11650
  const buffer = new Stream(cblock);
@@ -11691,21 +11656,21 @@ function parse_cblock(cblock) {
11691
11656
  path.push(buffer.read(32).hex);
11692
11657
  }
11693
11658
  if (buffer.size !== 0) {
11694
- throw new Error(`Non-empty buffer on control block: ${String(buffer)}`);
11659
+ throw new DecodingError(`control block has ${buffer.size} extra bytes. Expected: 33 + (32 * path_length) bytes`);
11695
11660
  }
11696
11661
  return { int_key, path, parity, version };
11697
11662
  }
11698
11663
  function parse_cblock_parity(cbits) {
11699
- return cbits % 2 === 0 ? [cbits - 0, 0x02] : [cbits - 1, 0x03];
11664
+ return cbits % 2 === 0 ? [cbits, 0x02] : [cbits - 1, 0x03];
11700
11665
  }
11701
11666
  function parse_pubkey_parity(pubkey) {
11702
- Assert.size(pubkey, 33, "invalid pubkey size");
11667
+ Assert$1.ok(Buff.bytes(pubkey).length === 33, "invalid pubkey size");
11703
11668
  const [parity] = Buff.bytes(pubkey);
11704
11669
  if (parity === 0x02)
11705
11670
  return 0;
11706
11671
  if (parity === 0x03)
11707
11672
  return 1;
11708
- throw new Error(`Invalid parity bit: ${String(parity)}`);
11673
+ throw new ValidationError(`invalid pubkey parity prefix: 0x${parity.toString(16)}. Expected 0x02 (even) or 0x03 (odd)`);
11709
11674
  }
11710
11675
 
11711
11676
  const MAX_TAPROOT_DEPTH = 128;
@@ -11714,12 +11679,12 @@ function get_merkle_root(leaves) {
11714
11679
  }
11715
11680
  function merkleize(taptree, target, path = [], depth = 0) {
11716
11681
  if (depth > MAX_TAPROOT_DEPTH) {
11717
- throw new Error(`Taproot tree depth ${depth} exceeds maximum ${MAX_TAPROOT_DEPTH}`);
11682
+ throw new ValidationError(`Taproot tree depth ${depth} exceeds maximum ${MAX_TAPROOT_DEPTH}`, "depth");
11718
11683
  }
11719
11684
  const leaves = [];
11720
11685
  const tree = [];
11721
11686
  if (taptree.length < 1) {
11722
- throw new Error("Tree is empty!");
11687
+ throw new ValidationError("Taproot tree cannot be empty", "taptree");
11723
11688
  }
11724
11689
  for (let i = 0; i < taptree.length; i++) {
11725
11690
  const bytes = taptree[i];
@@ -11796,7 +11761,7 @@ function create_taproot(config$1) {
11796
11761
  };
11797
11762
  }
11798
11763
  function verify_taproot(tapkey, target, cblock) {
11799
- Assert.size(tapkey, 32);
11764
+ Assert$1.ok(Buff.bytes(tapkey).length === 32, "tapkey must be 32 bytes");
11800
11765
  const { parity, path, int_key } = parse_cblock(cblock);
11801
11766
  const ext_key = Buff.join([parity, tapkey]);
11802
11767
  let branch = Buff.bytes(target).hex;
@@ -11824,7 +11789,7 @@ function verify_tx(txdata, options = {}) {
11824
11789
  if (!result.valid) {
11825
11790
  allValid = false;
11826
11791
  if (throws) {
11827
- throw new Error(`Input ${i} verification failed: ${result.error}`);
11792
+ throw new ValidationError(`Input ${i} verification failed: ${result.error}`, `vin[${i}]`);
11828
11793
  }
11829
11794
  }
11830
11795
  }
@@ -11849,12 +11814,11 @@ function verify_input(tx, vin, index, options) {
11849
11814
  if (prevout === null || prevout === undefined) {
11850
11815
  return { index, valid: false, type, error: "Missing prevout data" };
11851
11816
  }
11852
- const scriptType = get_lock_script_type(prevout.script_pk);
11853
11817
  if (version === 0) {
11854
11818
  return verify_segwit_input(tx, vin, index, witnessData);
11855
11819
  }
11856
11820
  else if (version === 1) {
11857
- return verify_taproot_input(tx, vin, index, witnessData, scriptType, options);
11821
+ return verify_taproot_input(tx, vin, index, witnessData, options);
11858
11822
  }
11859
11823
  return {
11860
11824
  index,
@@ -11936,7 +11900,7 @@ function verify_segwit_input(tx, vin, index, witnessData, options) {
11936
11900
  error: isValid ? undefined : "Invalid ECDSA signature",
11937
11901
  };
11938
11902
  }
11939
- function verify_taproot_input(tx, vin, index, witnessData, _scriptType, options) {
11903
+ function verify_taproot_input(tx, vin, index, witnessData, options) {
11940
11904
  const { type, params, script, cblock } = witnessData;
11941
11905
  if (vin.prevout == null) {
11942
11906
  return {
@@ -12024,12 +11988,12 @@ function parse_schnorr_signature(sigHex) {
12024
11988
  else if (sigBytes.length === 65) {
12025
11989
  const sigflag = sigBytes.at(-1) ?? 0x00;
12026
11990
  if (sigflag === 0x00) {
12027
- throw new Error("0x00 is not a valid appended sigflag");
11991
+ throw new ValidationError("0x00 is not a valid appended sigflag (use 64-byte signature for SIGHASH_DEFAULT)", "sigflag");
12028
11992
  }
12029
11993
  const signature = sigBytes.slice(0, 64).hex;
12030
11994
  return { signature, sigflag };
12031
11995
  }
12032
- throw new Error(`Invalid Schnorr signature length: ${sigBytes.length}`);
11996
+ throw new ValidationError(`Invalid Schnorr signature length: ${sigBytes.length} (expected 64 or 65 bytes)`, "signature");
12033
11997
  }
12034
11998
 
12035
11999
  var index$2 = /*#__PURE__*/Object.freeze({
@@ -12064,8 +12028,8 @@ function get_witness_size(witness) {
12064
12028
  return { total: size, vsize };
12065
12029
  }
12066
12030
  function assert_witness(witness) {
12067
- Assert.ok(Array.isArray(witness), "witness must be an array");
12068
- Assert.ok(witness.every((e) => Buff.is_bytes(e)), "witness must be an array of strings or bytes");
12031
+ Assert$1.ok(Array.isArray(witness), "witness must be an array");
12032
+ Assert$1.ok(witness.every((e) => Buff.is_bytes(e)), "witness must be an array of strings or bytes");
12069
12033
  }
12070
12034
 
12071
12035
  var index = /*#__PURE__*/Object.freeze({
@@ -12075,5 +12039,5 @@ var index = /*#__PURE__*/Object.freeze({
12075
12039
  parse_witness: parse_witness
12076
12040
  });
12077
12041
 
12078
- export { index$8 as ADDRESS, _const as CONST, index$7 as META, index$5 as SCHEMA, index$6 as SCRIPT, index$3 as SIGHASH, index$2 as SIGNER, index$1 as TAPROOT, index$4 as TX, index as WITNESS };
12042
+ export { index$8 as ADDRESS, _const as CONST, ConfigError, DecodingError, index$7 as META, index$5 as SCHEMA, index$6 as SCRIPT, index$3 as SIGHASH, index$2 as SIGNER, index$1 as TAPROOT, index$4 as TX, ValidationError, index as WITNESS };
12079
12043
  //# sourceMappingURL=module.mjs.map