@btc-vision/bitcoin 6.5.3 → 6.5.4

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 (92) hide show
  1. package/browser/address.d.ts +2 -6
  2. package/browser/bech32utils.d.ts +6 -0
  3. package/browser/chunks/{crypto-0PweVewC.js → crypto-BhCpKpek.js} +4 -4
  4. package/browser/chunks/{payments-CgasufRS.js → payments-Ngcm87h_.js} +670 -626
  5. package/browser/chunks/{psbt-BIwOrKer.js → psbt-CcM4rw3q.js} +1259 -1316
  6. package/browser/chunks/{script-CROJPzz_.js → script-DyPItFEl.js} +33 -33
  7. package/browser/chunks/{transaction-DchBu35N.js → transaction-C_UbhMGn.js} +3 -3
  8. package/browser/chunks/{utils-CO5kmxe9.js → utils-DNZi-T5W.js} +26 -26
  9. package/browser/index.d.ts +3 -1
  10. package/browser/index.js +102 -90
  11. package/browser/payments/embed.d.ts +1 -1
  12. package/browser/payments/index.d.ts +12 -104
  13. package/browser/payments/p2ms.d.ts +1 -1
  14. package/browser/payments/p2op.d.ts +1 -1
  15. package/browser/payments/p2pk.d.ts +1 -1
  16. package/browser/payments/p2pkh.d.ts +1 -1
  17. package/browser/payments/p2sh.d.ts +1 -1
  18. package/browser/payments/p2tr.d.ts +1 -1
  19. package/browser/payments/p2wpkh.d.ts +1 -1
  20. package/browser/payments/p2wsh.d.ts +1 -1
  21. package/browser/payments/types.d.ts +93 -0
  22. package/browser/psbt/bip371.d.ts +0 -1
  23. package/browser/psbt/psbtutils.d.ts +0 -7
  24. package/browser/pubkey.d.ts +8 -0
  25. package/browser/script.d.ts +1 -2
  26. package/browser/script_signature.d.ts +1 -0
  27. package/browser/types.d.ts +3 -0
  28. package/build/address.d.ts +2 -6
  29. package/build/address.js +19 -37
  30. package/build/bech32utils.d.ts +6 -0
  31. package/build/bech32utils.js +26 -0
  32. package/build/index.d.ts +3 -1
  33. package/build/index.js +1 -0
  34. package/build/payments/embed.d.ts +1 -1
  35. package/build/payments/embed.js +1 -1
  36. package/build/payments/index.d.ts +12 -104
  37. package/build/payments/index.js +12 -24
  38. package/build/payments/p2ms.d.ts +1 -1
  39. package/build/payments/p2ms.js +1 -1
  40. package/build/payments/p2op.d.ts +1 -1
  41. package/build/payments/p2op.js +2 -2
  42. package/build/payments/p2pk.d.ts +1 -1
  43. package/build/payments/p2pk.js +1 -1
  44. package/build/payments/p2pkh.d.ts +1 -1
  45. package/build/payments/p2pkh.js +2 -2
  46. package/build/payments/p2sh.d.ts +1 -1
  47. package/build/payments/p2sh.js +1 -1
  48. package/build/payments/p2tr.d.ts +1 -1
  49. package/build/payments/p2tr.js +2 -2
  50. package/build/payments/p2wpkh.d.ts +1 -1
  51. package/build/payments/p2wpkh.js +1 -1
  52. package/build/payments/p2wsh.d.ts +1 -1
  53. package/build/payments/p2wsh.js +2 -2
  54. package/build/payments/types.d.ts +93 -0
  55. package/build/payments/types.js +13 -0
  56. package/build/psbt/bip371.d.ts +0 -1
  57. package/build/psbt/bip371.js +2 -6
  58. package/build/psbt/psbtutils.d.ts +0 -7
  59. package/build/psbt/psbtutils.js +2 -54
  60. package/build/psbt.js +3 -2
  61. package/build/pubkey.d.ts +8 -0
  62. package/build/pubkey.js +56 -0
  63. package/build/script.d.ts +1 -2
  64. package/build/script.js +1 -4
  65. package/build/script_signature.d.ts +1 -0
  66. package/build/script_signature.js +4 -1
  67. package/build/tsconfig.tsbuildinfo +1 -1
  68. package/build/types.d.ts +3 -0
  69. package/package.json +5 -2
  70. package/src/address.ts +20 -50
  71. package/src/bech32utils.ts +43 -0
  72. package/src/index.ts +2 -3
  73. package/src/payments/embed.ts +2 -2
  74. package/src/payments/index.ts +40 -164
  75. package/src/payments/p2ms.ts +2 -2
  76. package/src/payments/p2op.ts +2 -2
  77. package/src/payments/p2pk.ts +2 -2
  78. package/src/payments/p2pkh.ts +3 -3
  79. package/src/payments/p2sh.ts +2 -10
  80. package/src/payments/p2tr.ts +2 -2
  81. package/src/payments/p2wpkh.ts +1 -1
  82. package/src/payments/p2wsh.ts +8 -2
  83. package/src/payments/types.ts +154 -0
  84. package/src/psbt/bip371.ts +6 -13
  85. package/src/psbt/psbtutils.ts +2 -104
  86. package/src/psbt.ts +3 -2
  87. package/src/pubkey.ts +99 -0
  88. package/src/script.ts +2 -7
  89. package/src/script_signature.ts +10 -1
  90. package/src/types.ts +5 -0
  91. package/test/address.spec.ts +3 -2
  92. package/test/integration/taproot.spec.ts +2 -1
package/src/pubkey.ts ADDED
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Public key utilities for Bitcoin
3
+ * @packageDocumentation
4
+ */
5
+ import { ProjectivePoint } from '@noble/secp256k1';
6
+
7
+ /**
8
+ * Converts a public key to x-only format (32 bytes).
9
+ * @param pubKey - The public key buffer (33 or 65 bytes)
10
+ * @returns The x-only public key (32 bytes)
11
+ */
12
+ export const toXOnly = (pubKey: Buffer | Uint8Array): Buffer => {
13
+ const buffer = pubKey.length === 32 ? pubKey : pubKey.subarray(1, 33);
14
+ return Buffer.isBuffer(buffer) ? buffer : Buffer.from(buffer);
15
+ };
16
+
17
+ export interface UncompressedPublicKey {
18
+ hybrid: Buffer;
19
+ uncompressed: Buffer;
20
+ }
21
+
22
+ /**
23
+ * Converts bigint to 32-byte Buffer.
24
+ */
25
+ export function bigIntTo32Bytes(num: bigint): Buffer {
26
+ let hex = num.toString(16);
27
+ hex = hex.padStart(64, '0');
28
+ if (hex.length > 64) {
29
+ hex = hex.slice(-64);
30
+ }
31
+ return Buffer.from(hex, 'hex');
32
+ }
33
+
34
+ /**
35
+ * Converts an existing real Bitcoin public key (compressed or uncompressed)
36
+ * to its "hybrid" form (prefix 0x06/0x07), then derives a P2PKH address from it.
37
+ *
38
+ * @param realPubKey - 33-byte compressed (0x02/0x03) or 65-byte uncompressed (0x04) pubkey
39
+ * @returns Buffer | undefined
40
+ */
41
+ export function decompressPublicKey(
42
+ realPubKey: Uint8Array | Buffer,
43
+ ): UncompressedPublicKey | undefined {
44
+ if (realPubKey.length === 32) {
45
+ return;
46
+ }
47
+
48
+ if (![33, 65].includes(realPubKey.length)) {
49
+ console.warn(
50
+ `Unsupported key length=${realPubKey.length}. Must be 33 (compressed) or 65 (uncompressed).`,
51
+ );
52
+ return;
53
+ }
54
+
55
+ let point: ProjectivePoint;
56
+ try {
57
+ point = ProjectivePoint.fromHex(realPubKey);
58
+ } catch (err) {
59
+ throw new Error('Invalid secp256k1 public key bytes. Cannot parse.');
60
+ }
61
+
62
+ const xBuf = bigIntTo32Bytes(point.x);
63
+ const yBuf = bigIntTo32Bytes(point.y);
64
+
65
+ const isEven = point.y % 2n === 0n;
66
+ const prefix = isEven ? 0x06 : 0x07;
67
+
68
+ const hybridPubKey = Buffer.alloc(65);
69
+ hybridPubKey[0] = prefix;
70
+ xBuf.copy(hybridPubKey, 1);
71
+ yBuf.copy(hybridPubKey, 33);
72
+
73
+ const uncompressedPubKey = Buffer.concat([Buffer.from([0x04]), xBuf, yBuf]);
74
+
75
+ return {
76
+ hybrid: hybridPubKey,
77
+ uncompressed: uncompressedPubKey,
78
+ };
79
+ }
80
+
81
+ /**
82
+ * Compare two potential pubkey Buffers, treating hybrid keys (0x06/0x07)
83
+ * as equivalent to uncompressed (0x04).
84
+ */
85
+ export function pubkeysMatch(a: Buffer, b: Buffer): boolean {
86
+ if (a.equals(b)) return true;
87
+
88
+ if (a.length === 65 && b.length === 65) {
89
+ const aCopy = Buffer.from(a);
90
+ const bCopy = Buffer.from(b);
91
+
92
+ if (aCopy[0] === 0x06 || aCopy[0] === 0x07) aCopy[0] = 0x04;
93
+ if (bCopy[0] === 0x06 || bCopy[0] === 0x07) bCopy[0] = 0x04;
94
+
95
+ return aCopy.equals(bCopy);
96
+ }
97
+
98
+ return false;
99
+ }
package/src/script.ts CHANGED
@@ -4,11 +4,11 @@
4
4
  */
5
5
  import * as bip66 from './bip66.js';
6
6
  import { Opcodes, opcodes, REVERSE_OPS } from './opcodes.js';
7
- import { Stack } from './payments/index.js';
8
7
  import * as pushdata from './push_data.js';
9
8
  import * as scriptNumber from './script_number.js';
10
9
  import * as scriptSignature from './script_signature.js';
11
10
  import * as types from './types.js';
11
+ import type { Stack } from './types.js';
12
12
 
13
13
  const { typeforce } = types;
14
14
 
@@ -229,12 +229,7 @@ export function isCanonicalPubKey(buffer: Buffer): boolean {
229
229
  return types.isPoint(buffer);
230
230
  }
231
231
 
232
- export function isDefinedHashType(hashType: number): boolean {
233
- const hashTypeMod = hashType & ~0x80;
234
-
235
- // return hashTypeMod > SIGHASH_ALL && hashTypeMod < SIGHASH_SINGLE
236
- return hashTypeMod > 0x00 && hashTypeMod < 0x04;
237
- }
232
+ import { isDefinedHashType } from './script_signature.js';
238
233
 
239
234
  export function isCanonicalScriptSignature(buffer: Buffer): boolean {
240
235
  if (!Buffer.isBuffer(buffer)) return false;
@@ -1,11 +1,20 @@
1
1
  import * as bip66 from './bip66.js';
2
- import { isDefinedHashType } from './script.js';
3
2
  import * as types from './types.js';
4
3
 
5
4
  const { typeforce } = types;
6
5
 
7
6
  const ZERO = Buffer.alloc(1, 0);
8
7
 
8
+ /**
9
+ * Checks if a hash type is defined (valid for Bitcoin signatures).
10
+ * @param hashType - The hash type to check.
11
+ * @returns True if the hash type is valid, false otherwise.
12
+ */
13
+ export function isDefinedHashType(hashType: number): boolean {
14
+ const hashTypeMod = hashType & ~0x80;
15
+ return hashTypeMod > 0x00 && hashTypeMod < 0x04;
16
+ }
17
+
9
18
  /**
10
19
  * Converts a buffer to a DER-encoded buffer.
11
20
  * @param x - The buffer to be converted.
package/src/types.ts CHANGED
@@ -125,3 +125,8 @@ export const Function: TypeforceValidator = typeforce.Function;
125
125
  export const BufferN: (n: number) => TypeforceValidator = typeforce.BufferN;
126
126
  export const Null: TypeforceValidator = typeforce.Null;
127
127
  export const oneOf: (...types: unknown[]) => TypeforceValidator = typeforce.oneOf;
128
+
129
+ // Stack types - used by script and payments
130
+ export type StackElement = globalThis.Buffer | number;
131
+ export type Stack = StackElement[];
132
+ export type StackFunction = () => Stack;
@@ -2,6 +2,7 @@ import assert from 'assert';
2
2
  import { describe, it } from 'vitest';
3
3
  import * as ecc from 'tiny-secp256k1';
4
4
  import * as baddress from '../src/address.js';
5
+ import { fromBech32 } from '../src/bech32utils.js';
5
6
  import * as bscript from '../src/script.js';
6
7
  import fixtures from './fixtures/address.json' with { type: 'json' };
7
8
 
@@ -57,7 +58,7 @@ describe('address', () => {
57
58
  if (!f.bech32) return;
58
59
 
59
60
  it('decodes ' + f.bech32, () => {
60
- const actual = baddress.fromBech32(f.bech32);
61
+ const actual = fromBech32(f.bech32);
61
62
 
62
63
  assert.strictEqual(actual.version, f.version);
63
64
  // Support both bech32 and bech32Opnet prefixes
@@ -74,7 +75,7 @@ describe('address', () => {
74
75
  fixtures.invalid.bech32.forEach((f) => {
75
76
  it('decode fails for ' + f.address + '(' + f.exception + ')', () => {
76
77
  assert.throws(() => {
77
- baddress.fromBech32(f.address);
78
+ fromBech32(f.address);
78
79
  }, new RegExp(f.exception));
79
80
  });
80
81
  });
@@ -7,8 +7,9 @@ import { regtestUtils } from './_regtest.js';
7
7
  import * as bitcoin from '../../src/index.js';
8
8
  import type { PsbtInput, TapLeaf, TapLeafScript, Taptree } from '../../src/index.js';
9
9
  import { LEAF_VERSION_TAPSCRIPT } from '../../src/payments/bip341.js';
10
- import { tapTreeFromList, tapTreeToList, toXOnly } from '../../src/psbt/bip371.js';
10
+ import { tapTreeFromList, tapTreeToList } from '../../src/psbt/bip371.js';
11
11
  import { witnessStackToScriptWitness } from '../../src/psbt/psbtutils.js';
12
+ import { toXOnly } from '../../src/pubkey.js';
12
13
 
13
14
  import rng from 'randombytes';
14
15