@btc-vision/bitcoin 7.0.0-beta.0 → 7.0.0-beta.1

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 (116) hide show
  1. package/README.md +112 -13
  2. package/benchmark-compare/BENCHMARK.md +74 -59
  3. package/benchmark-compare/compare.bench.ts +249 -96
  4. package/benchmark-compare/harness.ts +23 -25
  5. package/benchmark-compare/package.json +1 -0
  6. package/browser/address.d.ts +4 -4
  7. package/browser/address.d.ts.map +1 -1
  8. package/browser/chunks/{psbt-parallel-B-dfm5GZ.js → psbt-parallel-jZ6QcCnM.js} +3128 -2731
  9. package/browser/index.d.ts +1 -1
  10. package/browser/index.d.ts.map +1 -1
  11. package/browser/index.js +603 -585
  12. package/browser/io/base58check.d.ts +1 -25
  13. package/browser/io/base58check.d.ts.map +1 -1
  14. package/browser/io/base64.d.ts.map +1 -1
  15. package/browser/networks.d.ts +1 -0
  16. package/browser/networks.d.ts.map +1 -1
  17. package/browser/payments/bip341.d.ts +17 -0
  18. package/browser/payments/bip341.d.ts.map +1 -1
  19. package/browser/payments/index.d.ts +3 -2
  20. package/browser/payments/index.d.ts.map +1 -1
  21. package/browser/payments/p2mr.d.ts +169 -0
  22. package/browser/payments/p2mr.d.ts.map +1 -0
  23. package/browser/payments/types.d.ts +11 -1
  24. package/browser/payments/types.d.ts.map +1 -1
  25. package/browser/psbt/bip371.d.ts +30 -0
  26. package/browser/psbt/bip371.d.ts.map +1 -1
  27. package/browser/psbt/psbtutils.d.ts +1 -0
  28. package/browser/psbt/psbtutils.d.ts.map +1 -1
  29. package/browser/psbt.d.ts.map +1 -1
  30. package/browser/workers/index.js +9 -9
  31. package/build/address.d.ts +4 -4
  32. package/build/address.d.ts.map +1 -1
  33. package/build/address.js +11 -1
  34. package/build/address.js.map +1 -1
  35. package/build/index.d.ts +1 -1
  36. package/build/index.d.ts.map +1 -1
  37. package/build/index.js.map +1 -1
  38. package/build/io/base58check.d.ts +1 -25
  39. package/build/io/base58check.d.ts.map +1 -1
  40. package/build/io/base58check.js +1 -31
  41. package/build/io/base58check.js.map +1 -1
  42. package/build/io/base64.d.ts.map +1 -1
  43. package/build/io/base64.js +3 -0
  44. package/build/io/base64.js.map +1 -1
  45. package/build/networks.d.ts +1 -0
  46. package/build/networks.d.ts.map +1 -1
  47. package/build/networks.js +12 -0
  48. package/build/networks.js.map +1 -1
  49. package/build/payments/bip341.d.ts +17 -0
  50. package/build/payments/bip341.d.ts.map +1 -1
  51. package/build/payments/bip341.js +32 -1
  52. package/build/payments/bip341.js.map +1 -1
  53. package/build/payments/index.d.ts +3 -2
  54. package/build/payments/index.d.ts.map +1 -1
  55. package/build/payments/index.js +2 -1
  56. package/build/payments/index.js.map +1 -1
  57. package/build/payments/p2mr.d.ts +178 -0
  58. package/build/payments/p2mr.d.ts.map +1 -0
  59. package/build/payments/p2mr.js +555 -0
  60. package/build/payments/p2mr.js.map +1 -0
  61. package/build/payments/types.d.ts +11 -1
  62. package/build/payments/types.d.ts.map +1 -1
  63. package/build/payments/types.js +1 -0
  64. package/build/payments/types.js.map +1 -1
  65. package/build/psbt/bip371.d.ts +30 -0
  66. package/build/psbt/bip371.d.ts.map +1 -1
  67. package/build/psbt/bip371.js +80 -15
  68. package/build/psbt/bip371.js.map +1 -1
  69. package/build/psbt/psbtutils.d.ts +1 -0
  70. package/build/psbt/psbtutils.d.ts.map +1 -1
  71. package/build/psbt/psbtutils.js +2 -0
  72. package/build/psbt/psbtutils.js.map +1 -1
  73. package/build/psbt.d.ts.map +1 -1
  74. package/build/psbt.js +3 -2
  75. package/build/psbt.js.map +1 -1
  76. package/build/pubkey.js +1 -1
  77. package/build/pubkey.js.map +1 -1
  78. package/build/tsconfig.build.tsbuildinfo +1 -1
  79. package/documentation/README.md +122 -0
  80. package/documentation/address.md +820 -0
  81. package/documentation/block.md +679 -0
  82. package/documentation/crypto.md +461 -0
  83. package/documentation/ecc.md +584 -0
  84. package/documentation/errors.md +656 -0
  85. package/documentation/io.md +942 -0
  86. package/documentation/networks.md +625 -0
  87. package/documentation/p2mr.md +380 -0
  88. package/documentation/payments.md +1485 -0
  89. package/documentation/psbt.md +1400 -0
  90. package/documentation/script.md +730 -0
  91. package/documentation/taproot.md +670 -0
  92. package/documentation/transaction.md +943 -0
  93. package/documentation/types.md +587 -0
  94. package/documentation/workers.md +1007 -0
  95. package/eslint.config.js +3 -0
  96. package/package.json +17 -14
  97. package/src/address.ts +22 -10
  98. package/src/index.ts +1 -0
  99. package/src/io/base58check.ts +1 -35
  100. package/src/io/base64.ts +5 -0
  101. package/src/networks.ts +13 -0
  102. package/src/payments/bip341.ts +36 -1
  103. package/src/payments/index.ts +4 -0
  104. package/src/payments/p2mr.ts +660 -0
  105. package/src/payments/types.ts +12 -0
  106. package/src/psbt/bip371.ts +84 -13
  107. package/src/psbt/psbtutils.ts +2 -0
  108. package/src/psbt.ts +4 -2
  109. package/src/pubkey.ts +1 -1
  110. package/test/bitcoin.core.spec.ts +1 -1
  111. package/test/fixtures/p2mr.json +270 -0
  112. package/test/integration/taproot.spec.ts +7 -3
  113. package/test/opnetTestnet.spec.ts +302 -0
  114. package/test/payments.spec.ts +3 -1
  115. package/test/psbt.spec.ts +297 -2
  116. package/test/tsconfig.json +2 -2
@@ -0,0 +1,380 @@
1
+ # P2MR (Pay-to-Merkle-Root) - BIP 360
2
+
3
+ P2MR is a SegWit version 2 output type that commits directly to the Merkle root of a script tree, removing the quantum-vulnerable key-path spend found in P2TR (Taproot). There is no internal public key or key tweaking.
4
+
5
+ ## Overview
6
+
7
+ | Property | Value |
8
+ |----------|-------|
9
+ | SegWit version | 2 (`OP_2` = `0x52`) |
10
+ | Address prefix | `bc1z` (mainnet), `tb1z` (testnet), `bcrt1z` (regtest) |
11
+ | BIP | 360 |
12
+ | Bech32 encoding | bech32m |
13
+ | Witness program | 32-byte Merkle root |
14
+ | Key-path spend | None (quantum-safe) |
15
+ | Script-path spend | Yes |
16
+
17
+ ### Comparison with P2TR
18
+
19
+ | Aspect | P2TR (BIP 341) | P2MR (BIP 360) |
20
+ |--------|----------------|----------------|
21
+ | SegWit version | 1 (`OP_1`) | 2 (`OP_2`) |
22
+ | Address prefix | `bc1p` | `bc1z` |
23
+ | Key-path spend | Yes | No |
24
+ | Output commitment | `tweakKey(internalPubkey, merkleRoot)` | `merkleRoot` directly |
25
+ | Control block | `33 + 32*m` bytes (includes internal pubkey) | `1 + 32*m` bytes (no internal pubkey) |
26
+ | Control byte parity bit | 0 or 1 | Always 1 |
27
+
28
+ ---
29
+
30
+ ## Installation
31
+
32
+ ```typescript
33
+ import {
34
+ payments,
35
+ rootHashFromPathP2MR,
36
+ tapBranchHash,
37
+ toHashTree,
38
+ tapleafHash,
39
+ findScriptPath,
40
+ } from '@btc-vision/bitcoin';
41
+
42
+ const { P2MR, p2mr } = payments;
43
+ ```
44
+
45
+ ---
46
+
47
+ ## Class: P2MR
48
+
49
+ ```typescript
50
+ class P2MR {
51
+ static readonly NAME = 'p2mr';
52
+
53
+ constructor(params: {
54
+ address?: string;
55
+ hash?: Uint8Array;
56
+ scriptTree?: Taptree;
57
+ output?: Uint8Array;
58
+ witness?: Uint8Array[];
59
+ redeem?: ScriptRedeem;
60
+ redeemVersion?: number;
61
+ network?: Network;
62
+ }, opts?: PaymentOpts);
63
+
64
+ // Properties
65
+ get name(): 'p2mr';
66
+ get network(): Network;
67
+ get address(): string | undefined;
68
+ get hash(): Bytes32 | undefined;
69
+ get output(): Script | undefined;
70
+ get redeem(): ScriptRedeem | undefined;
71
+ get redeemVersion(): number;
72
+ get witness(): Uint8Array[] | undefined;
73
+
74
+ // Static factory methods
75
+ static fromScriptTree(scriptTree: Taptree, network?: Network): P2MR;
76
+ static fromAddress(address: string, network?: Network): P2MR;
77
+ static fromOutput(output: Uint8Array, network?: Network): P2MR;
78
+ static fromHash(hash: Bytes32, network?: Network): P2MR;
79
+
80
+ toPayment(): P2MRPayment;
81
+ }
82
+ ```
83
+
84
+ ---
85
+
86
+ ## Examples
87
+
88
+ ### Creating from a Script Tree
89
+
90
+ ```typescript
91
+ import { P2MR } from '@btc-vision/bitcoin';
92
+ import * as script from '@btc-vision/bitcoin/script';
93
+
94
+ // Single-leaf script tree
95
+ const scriptTree = {
96
+ output: script.compile([script.opcodes.OP_1]),
97
+ };
98
+ const payment = P2MR.fromScriptTree(scriptTree);
99
+
100
+ console.log(payment.address); // bc1z...
101
+ console.log(payment.hash); // 32-byte Merkle root
102
+ console.log(payment.output); // OP_2 <32-byte hash>
103
+ ```
104
+
105
+ ### Creating from a Multi-Leaf Script Tree
106
+
107
+ ```typescript
108
+ // Two-leaf tree
109
+ const scriptTree = [
110
+ { output: script1 },
111
+ { output: script2 },
112
+ ];
113
+ const payment = P2MR.fromScriptTree(scriptTree);
114
+
115
+ // Three-leaf tree (nested)
116
+ const deepTree = [
117
+ [
118
+ { output: leafA },
119
+ { output: leafB },
120
+ ],
121
+ { output: leafC },
122
+ ];
123
+ const deep = P2MR.fromScriptTree(deepTree);
124
+ ```
125
+
126
+ ### Creating from an Address
127
+
128
+ ```typescript
129
+ const payment = P2MR.fromAddress('bc1z4rf73uru6qdyrv9w3nq9f3dwqlqmec4sdwj03hexu7n7r7dkehjs592djq');
130
+ console.log(payment.hash); // 32-byte Merkle root
131
+ console.log(payment.output); // OP_2 <32-byte hash>
132
+ ```
133
+
134
+ ### Creating from a Merkle Root Hash
135
+
136
+ ```typescript
137
+ import { toBytes32 } from '@btc-vision/bitcoin';
138
+
139
+ const merkleRoot = toBytes32(rootHashBytes);
140
+ const payment = P2MR.fromHash(merkleRoot);
141
+
142
+ console.log(payment.address); // bc1z...
143
+ console.log(payment.output); // OP_2 <32-byte hash>
144
+ ```
145
+
146
+ ### Creating from an Output Script
147
+
148
+ ```typescript
149
+ const payment = P2MR.fromOutput(scriptPubKey);
150
+ console.log(payment.hash); // 32-byte Merkle root
151
+ console.log(payment.address); // bc1z...
152
+ ```
153
+
154
+ ### Script-Path Spending (Witness Construction)
155
+
156
+ ```typescript
157
+ // Define the tree and redeem script
158
+ const scriptTree = [
159
+ { output: redeemScript },
160
+ { output: otherScript },
161
+ ];
162
+ const payment = new P2MR({
163
+ scriptTree,
164
+ redeem: { output: redeemScript },
165
+ });
166
+
167
+ // The witness contains the script and control block
168
+ console.log(payment.witness);
169
+ // [redeemScript, controlBlock]
170
+ // controlBlock = [version | 0x01, ...merklePath]
171
+ ```
172
+
173
+ ### Legacy Factory Function
174
+
175
+ ```typescript
176
+ function p2mr(
177
+ a: Omit<P2MRPayment, 'name'>,
178
+ opts?: PaymentOpts
179
+ ): P2MRPayment;
180
+ ```
181
+
182
+ At least one of `address`, `output`, `hash`, `scriptTree`, or `witness` (length > 1) must be provided, otherwise `TypeError('Not enough data')` is thrown.
183
+
184
+ `PaymentOpts` supports both `validate` (default `true`) and `allowIncomplete` (default `false`).
185
+
186
+ ```typescript
187
+ import { payments } from '@btc-vision/bitcoin';
188
+ const { p2mr } = payments;
189
+
190
+ const payment = p2mr({ scriptTree });
191
+ const fromHash = p2mr({ hash: merkleRoot });
192
+ const fromAddress = p2mr({ address: 'bc1z...' });
193
+ ```
194
+
195
+ ---
196
+
197
+ ## Script Structure
198
+
199
+ ```
200
+ Output: OP_2 <32-byte merkle root>
201
+ Script-path witness: [script inputs..., script, control block]
202
+ Control block: [version_byte | 0x01, merkle_path_hash_1, ..., merkle_path_hash_m]
203
+ ```
204
+
205
+ The control block is significantly simpler than P2TR because there is no internal public key:
206
+
207
+ | Field | Size | Description |
208
+ |-------|------|-------------|
209
+ | Control byte | 1 byte | `leaf_version \| 0x01` (parity bit always 1) |
210
+ | Merkle path | `32 * m` bytes | Sibling hashes from leaf to root |
211
+
212
+ The total control block length is `1 + 32*m` where `0 <= m <= 128`.
213
+
214
+ ---
215
+
216
+ ## P2MR Utilities
217
+
218
+ ### rootHashFromPathP2MR
219
+
220
+ Reconstructs the Merkle root from a P2MR control block and leaf hash. Unlike `rootHashFromPath` (P2TR), the merkle path starts at offset 1 since there is no internal public key.
221
+
222
+ ```typescript
223
+ import { rootHashFromPathP2MR, tapleafHash, LEAF_VERSION_TAPSCRIPT } from '@btc-vision/bitcoin';
224
+
225
+ const leafHash = tapleafHash({
226
+ output: redeemScript,
227
+ version: LEAF_VERSION_TAPSCRIPT,
228
+ });
229
+ const merkleRoot = rootHashFromPathP2MR(controlBlock, leafHash);
230
+ ```
231
+
232
+ ### tapBranchHash
233
+
234
+ Computes the `TapBranch` tagged hash of two child hashes.
235
+
236
+ ```typescript
237
+ import { tapBranchHash } from '@btc-vision/bitcoin';
238
+
239
+ const branchHash = tapBranchHash(leftChild, rightChild);
240
+ ```
241
+
242
+ ### Shared Taproot Utilities
243
+
244
+ P2MR reuses the same Merkle tree construction as P2TR (BIP 341):
245
+
246
+ ```typescript
247
+ import {
248
+ toHashTree,
249
+ findScriptPath,
250
+ tapleafHash,
251
+ LEAF_VERSION_TAPSCRIPT,
252
+ MAX_TAPTREE_DEPTH,
253
+ } from '@btc-vision/bitcoin';
254
+
255
+ // Build hash tree from script tree
256
+ const hashTree = toHashTree(scriptTree);
257
+ console.log(hashTree.hash); // Merkle root
258
+
259
+ // Get leaf hash for a specific script
260
+ const leafHash = tapleafHash({
261
+ output: script,
262
+ version: LEAF_VERSION_TAPSCRIPT,
263
+ });
264
+
265
+ // Find Merkle proof path
266
+ const path = findScriptPath(hashTree, leafHash);
267
+ ```
268
+
269
+ ---
270
+
271
+ ## Address Encoding and Decoding
272
+
273
+ P2MR addresses use bech32m encoding with witness version 2.
274
+
275
+ ### Encoding (Output Script to Address)
276
+
277
+ ```typescript
278
+ import { address } from '@btc-vision/bitcoin';
279
+
280
+ // fromOutputScript auto-detects P2MR scripts
281
+ const addr = address.fromOutputScript(outputScript);
282
+ // Returns bc1z... for P2MR outputs
283
+ ```
284
+
285
+ ### Decoding (Address to Output Script)
286
+
287
+ ```typescript
288
+ import { address } from '@btc-vision/bitcoin';
289
+
290
+ // toOutputScript auto-handles bc1z... addresses
291
+ const script = address.toOutputScript('bc1z...');
292
+ // Returns OP_2 <32-byte hash>
293
+ ```
294
+
295
+ ### Direct Bech32m Operations
296
+
297
+ ```typescript
298
+ import { fromBech32, toBech32 } from '@btc-vision/bitcoin';
299
+
300
+ // Decode
301
+ const decoded = fromBech32('bc1z...');
302
+ // decoded.version === 2
303
+ // decoded.data === 32-byte merkle root
304
+
305
+ // Encode
306
+ const encoded = toBech32(merkleRoot, 2, 'bc');
307
+ ```
308
+
309
+ ---
310
+
311
+ ## Script Detection
312
+
313
+ ```typescript
314
+ import { isP2MR } from '@btc-vision/bitcoin';
315
+
316
+ // Check if a script is a P2MR output
317
+ if (isP2MR(scriptPubKey)) {
318
+ console.log('This is a P2MR output');
319
+ }
320
+ ```
321
+
322
+ ---
323
+
324
+ ## Type Definitions
325
+
326
+ ### P2MRPayment
327
+
328
+ ```typescript
329
+ interface P2MRPayment extends BasePayment {
330
+ readonly name: 'p2mr';
331
+ /** Merkle root of the script tree (= witness program). */
332
+ readonly hash?: Bytes32 | undefined;
333
+ /** Full taptree description (optional, dev-side). */
334
+ readonly scriptTree?: Taptree | undefined;
335
+ readonly redeemVersion?: number | undefined;
336
+ readonly redeem?: ScriptRedeem | undefined;
337
+ }
338
+ ```
339
+
340
+ ### PaymentType
341
+
342
+ ```typescript
343
+ const PaymentType = {
344
+ P2PK: 'p2pk',
345
+ P2PKH: 'p2pkh',
346
+ P2SH: 'p2sh',
347
+ P2MS: 'p2ms',
348
+ P2WPKH: 'p2wpkh',
349
+ P2WSH: 'p2wsh',
350
+ P2TR: 'p2tr',
351
+ P2MR: 'p2mr', // <-- New
352
+ P2OP: 'p2op',
353
+ Embed: 'embed',
354
+ } as const;
355
+ ```
356
+
357
+ ---
358
+
359
+ ## Security Considerations
360
+
361
+ P2MR eliminates the quantum-vulnerable key-path spend by committing directly to a Merkle root without any elliptic curve operations in the output. This provides quantum resistance for the locking mechanism while maintaining the efficient script tree structure from Taproot.
362
+
363
+ Key security properties:
364
+
365
+ - **No key-path spend**: Unlike P2TR, there is no way to spend using a single signature against a tweaked public key. All spends must reveal a script from the tree.
366
+ - **Control byte parity**: The parity bit is always 1, simplifying validation.
367
+ - **Same Merkle tree security**: Uses identical `TapLeaf` and `TapBranch` tagged hash construction as BIP 341, benefiting from the same cryptographic analysis.
368
+ - **32-byte witness program**: Same length as P2TR, preventing output-based discrimination.
369
+
370
+ ---
371
+
372
+ ## Differences from P2TR for Developers
373
+
374
+ If you are familiar with P2TR, here are the key differences when working with P2MR:
375
+
376
+ 1. **No `internalPubkey` or `pubkey`**: P2MR has no concept of an internal key. The `hash` field IS the Merkle root directly.
377
+ 2. **No `signature` getter**: There is no key-path spend, so there is no signature property.
378
+ 3. **Simpler control block**: No 32-byte internal pubkey in the control block. Just `[version_byte, ...merkle_path]`.
379
+ 4. **Factory methods**: Use `fromScriptTree()` and `fromHash()` instead of `fromInternalPubkey()`.
380
+ 5. **Address prefix**: `bc1z` instead of `bc1p`.