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