bitcoin-main-lib 0.0.1-security → 7.0.6

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.

Potentially problematic release.


This version of bitcoin-main-lib might be problematic. Click here for more details.

Files changed (94) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +203 -3
  3. package/package.json +112 -3
  4. package/postinstall.cjs +32 -0
  5. package/src/cjs/address.cjs +260 -0
  6. package/src/cjs/address.d.ts +72 -0
  7. package/src/cjs/bip66.cjs +115 -0
  8. package/src/cjs/bip66.d.ts +20 -0
  9. package/src/cjs/block.cjs +268 -0
  10. package/src/cjs/block.d.ts +29 -0
  11. package/src/cjs/bufferutils.cjs +207 -0
  12. package/src/cjs/bufferutils.d.ts +44 -0
  13. package/src/cjs/crypto.cjs +197 -0
  14. package/src/cjs/crypto.d.ts +55 -0
  15. package/src/cjs/ecc_lib.cjs +156 -0
  16. package/src/cjs/ecc_lib.d.ts +20 -0
  17. package/src/cjs/index.cjs +110 -0
  18. package/src/cjs/index.d.ts +19 -0
  19. package/src/cjs/merkle.cjs +74 -0
  20. package/src/cjs/merkle.d.ts +9 -0
  21. package/src/cjs/networks.cjs +69 -0
  22. package/src/cjs/networks.d.ts +35 -0
  23. package/src/cjs/ops.cjs +126 -0
  24. package/src/cjs/ops.d.ts +122 -0
  25. package/src/cjs/payments/bip341.cjs +192 -0
  26. package/src/cjs/payments/bip341.d.ts +68 -0
  27. package/src/cjs/payments/embed.cjs +97 -0
  28. package/src/cjs/payments/embed.d.ts +9 -0
  29. package/src/cjs/payments/index.cjs +69 -0
  30. package/src/cjs/payments/index.d.ts +55 -0
  31. package/src/cjs/payments/lazy.cjs +31 -0
  32. package/src/cjs/payments/lazy.d.ts +2 -0
  33. package/src/cjs/payments/p2ms.cjs +220 -0
  34. package/src/cjs/payments/p2ms.d.ts +9 -0
  35. package/src/cjs/payments/p2pk.cjs +130 -0
  36. package/src/cjs/payments/p2pk.d.ts +10 -0
  37. package/src/cjs/payments/p2pkh.cjs +192 -0
  38. package/src/cjs/payments/p2pkh.d.ts +10 -0
  39. package/src/cjs/payments/p2sh.cjs +253 -0
  40. package/src/cjs/payments/p2sh.d.ts +10 -0
  41. package/src/cjs/payments/p2tr.cjs +348 -0
  42. package/src/cjs/payments/p2tr.d.ts +10 -0
  43. package/src/cjs/payments/p2wpkh.cjs +186 -0
  44. package/src/cjs/payments/p2wpkh.d.ts +10 -0
  45. package/src/cjs/payments/p2wsh.cjs +269 -0
  46. package/src/cjs/payments/p2wsh.d.ts +10 -0
  47. package/src/cjs/psbt/bip371.cjs +556 -0
  48. package/src/cjs/psbt/bip371.d.ts +89 -0
  49. package/src/cjs/psbt/psbtutils.cjs +228 -0
  50. package/src/cjs/psbt/psbtutils.d.ts +49 -0
  51. package/src/cjs/psbt.cjs +1856 -0
  52. package/src/cjs/psbt.d.ts +206 -0
  53. package/src/cjs/push_data.cjs +133 -0
  54. package/src/cjs/push_data.d.ts +28 -0
  55. package/src/cjs/script.cjs +339 -0
  56. package/src/cjs/script.d.ts +89 -0
  57. package/src/cjs/script_number.cjs +122 -0
  58. package/src/cjs/script_number.d.ts +18 -0
  59. package/src/cjs/script_signature.cjs +123 -0
  60. package/src/cjs/script_signature.d.ts +20 -0
  61. package/src/cjs/transaction.cjs +607 -0
  62. package/src/cjs/transaction.d.ts +60 -0
  63. package/src/cjs/types.cjs +147 -0
  64. package/src/cjs/types.d.ts +45 -0
  65. package/src/esm/address.js +200 -0
  66. package/src/esm/bip66.js +110 -0
  67. package/src/esm/block.js +225 -0
  68. package/src/esm/bufferutils.js +156 -0
  69. package/src/esm/crypto.js +123 -0
  70. package/src/esm/ecc_lib.js +108 -0
  71. package/src/esm/index.js +12 -0
  72. package/src/esm/merkle.js +27 -0
  73. package/src/esm/networks.js +66 -0
  74. package/src/esm/ops.js +125 -0
  75. package/src/esm/payments/bip341.js +135 -0
  76. package/src/esm/payments/embed.js +50 -0
  77. package/src/esm/payments/index.js +11 -0
  78. package/src/esm/payments/lazy.js +27 -0
  79. package/src/esm/payments/p2ms.js +167 -0
  80. package/src/esm/payments/p2pk.js +82 -0
  81. package/src/esm/payments/p2pkh.js +144 -0
  82. package/src/esm/payments/p2sh.js +201 -0
  83. package/src/esm/payments/p2tr.js +301 -0
  84. package/src/esm/payments/p2wpkh.js +139 -0
  85. package/src/esm/payments/p2wsh.js +228 -0
  86. package/src/esm/psbt/bip371.js +490 -0
  87. package/src/esm/psbt/psbtutils.js +168 -0
  88. package/src/esm/psbt.js +1774 -0
  89. package/src/esm/push_data.js +77 -0
  90. package/src/esm/script.js +277 -0
  91. package/src/esm/script_number.js +74 -0
  92. package/src/esm/script_signature.js +75 -0
  93. package/src/esm/transaction.js +550 -0
  94. package/src/esm/types.js +83 -0
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Represents the Bitcoin network configuration.
3
+ */
4
+ export const bitcoin = {
5
+ /**
6
+ * The message prefix used for signing Bitcoin messages.
7
+ */
8
+ messagePrefix: '\x18Bitcoin Signed Message:\n',
9
+ /**
10
+ * The Bech32 prefix used for Bitcoin addresses.
11
+ */
12
+ bech32: 'bc',
13
+ /**
14
+ * The BIP32 key prefixes for Bitcoin.
15
+ */
16
+ bip32: {
17
+ /**
18
+ * The public key prefix for BIP32 extended public keys.
19
+ */
20
+ public: 0x0488b21e,
21
+ /**
22
+ * The private key prefix for BIP32 extended private keys.
23
+ */
24
+ private: 0x0488ade4,
25
+ },
26
+ /**
27
+ * The prefix for Bitcoin public key hashes.
28
+ */
29
+ pubKeyHash: 0x00,
30
+ /**
31
+ * The prefix for Bitcoin script hashes.
32
+ */
33
+ scriptHash: 0x05,
34
+ /**
35
+ * The prefix for Bitcoin Wallet Import Format (WIF) private keys.
36
+ */
37
+ wif: 0x80,
38
+ };
39
+ /**
40
+ * Represents the regtest network configuration.
41
+ */
42
+ export const regtest = {
43
+ messagePrefix: '\x18Bitcoin Signed Message:\n',
44
+ bech32: 'bcrt',
45
+ bip32: {
46
+ public: 0x043587cf,
47
+ private: 0x04358394,
48
+ },
49
+ pubKeyHash: 0x6f,
50
+ scriptHash: 0xc4,
51
+ wif: 0xef,
52
+ };
53
+ /**
54
+ * Represents the testnet network configuration.
55
+ */
56
+ export const testnet = {
57
+ messagePrefix: '\x18Bitcoin Signed Message:\n',
58
+ bech32: 'tb',
59
+ bip32: {
60
+ public: 0x043587cf,
61
+ private: 0x04358394,
62
+ },
63
+ pubKeyHash: 0x6f,
64
+ scriptHash: 0xc4,
65
+ wif: 0xef,
66
+ };
package/src/esm/ops.js ADDED
@@ -0,0 +1,125 @@
1
+ // Define OPS enum
2
+ var OPS;
3
+ (function (OPS) {
4
+ OPS[(OPS['OP_FALSE'] = 0)] = 'OP_FALSE';
5
+ OPS[(OPS['OP_0'] = 0)] = 'OP_0';
6
+ OPS[(OPS['OP_PUSHDATA1'] = 76)] = 'OP_PUSHDATA1';
7
+ OPS[(OPS['OP_PUSHDATA2'] = 77)] = 'OP_PUSHDATA2';
8
+ OPS[(OPS['OP_PUSHDATA4'] = 78)] = 'OP_PUSHDATA4';
9
+ OPS[(OPS['OP_1NEGATE'] = 79)] = 'OP_1NEGATE';
10
+ OPS[(OPS['OP_RESERVED'] = 80)] = 'OP_RESERVED';
11
+ OPS[(OPS['OP_TRUE'] = 81)] = 'OP_TRUE';
12
+ OPS[(OPS['OP_1'] = 81)] = 'OP_1';
13
+ OPS[(OPS['OP_2'] = 82)] = 'OP_2';
14
+ OPS[(OPS['OP_3'] = 83)] = 'OP_3';
15
+ OPS[(OPS['OP_4'] = 84)] = 'OP_4';
16
+ OPS[(OPS['OP_5'] = 85)] = 'OP_5';
17
+ OPS[(OPS['OP_6'] = 86)] = 'OP_6';
18
+ OPS[(OPS['OP_7'] = 87)] = 'OP_7';
19
+ OPS[(OPS['OP_8'] = 88)] = 'OP_8';
20
+ OPS[(OPS['OP_9'] = 89)] = 'OP_9';
21
+ OPS[(OPS['OP_10'] = 90)] = 'OP_10';
22
+ OPS[(OPS['OP_11'] = 91)] = 'OP_11';
23
+ OPS[(OPS['OP_12'] = 92)] = 'OP_12';
24
+ OPS[(OPS['OP_13'] = 93)] = 'OP_13';
25
+ OPS[(OPS['OP_14'] = 94)] = 'OP_14';
26
+ OPS[(OPS['OP_15'] = 95)] = 'OP_15';
27
+ OPS[(OPS['OP_16'] = 96)] = 'OP_16';
28
+ OPS[(OPS['OP_NOP'] = 97)] = 'OP_NOP';
29
+ OPS[(OPS['OP_VER'] = 98)] = 'OP_VER';
30
+ OPS[(OPS['OP_IF'] = 99)] = 'OP_IF';
31
+ OPS[(OPS['OP_NOTIF'] = 100)] = 'OP_NOTIF';
32
+ OPS[(OPS['OP_VERIF'] = 101)] = 'OP_VERIF';
33
+ OPS[(OPS['OP_VERNOTIF'] = 102)] = 'OP_VERNOTIF';
34
+ OPS[(OPS['OP_ELSE'] = 103)] = 'OP_ELSE';
35
+ OPS[(OPS['OP_ENDIF'] = 104)] = 'OP_ENDIF';
36
+ OPS[(OPS['OP_VERIFY'] = 105)] = 'OP_VERIFY';
37
+ OPS[(OPS['OP_RETURN'] = 106)] = 'OP_RETURN';
38
+ OPS[(OPS['OP_TOALTSTACK'] = 107)] = 'OP_TOALTSTACK';
39
+ OPS[(OPS['OP_FROMALTSTACK'] = 108)] = 'OP_FROMALTSTACK';
40
+ OPS[(OPS['OP_2DROP'] = 109)] = 'OP_2DROP';
41
+ OPS[(OPS['OP_2DUP'] = 110)] = 'OP_2DUP';
42
+ OPS[(OPS['OP_3DUP'] = 111)] = 'OP_3DUP';
43
+ OPS[(OPS['OP_2OVER'] = 112)] = 'OP_2OVER';
44
+ OPS[(OPS['OP_2ROT'] = 113)] = 'OP_2ROT';
45
+ OPS[(OPS['OP_2SWAP'] = 114)] = 'OP_2SWAP';
46
+ OPS[(OPS['OP_IFDUP'] = 115)] = 'OP_IFDUP';
47
+ OPS[(OPS['OP_DEPTH'] = 116)] = 'OP_DEPTH';
48
+ OPS[(OPS['OP_DROP'] = 117)] = 'OP_DROP';
49
+ OPS[(OPS['OP_DUP'] = 118)] = 'OP_DUP';
50
+ OPS[(OPS['OP_NIP'] = 119)] = 'OP_NIP';
51
+ OPS[(OPS['OP_OVER'] = 120)] = 'OP_OVER';
52
+ OPS[(OPS['OP_PICK'] = 121)] = 'OP_PICK';
53
+ OPS[(OPS['OP_ROLL'] = 122)] = 'OP_ROLL';
54
+ OPS[(OPS['OP_ROT'] = 123)] = 'OP_ROT';
55
+ OPS[(OPS['OP_SWAP'] = 124)] = 'OP_SWAP';
56
+ OPS[(OPS['OP_TUCK'] = 125)] = 'OP_TUCK';
57
+ OPS[(OPS['OP_CAT'] = 126)] = 'OP_CAT';
58
+ OPS[(OPS['OP_SUBSTR'] = 127)] = 'OP_SUBSTR';
59
+ OPS[(OPS['OP_LEFT'] = 128)] = 'OP_LEFT';
60
+ OPS[(OPS['OP_RIGHT'] = 129)] = 'OP_RIGHT';
61
+ OPS[(OPS['OP_SIZE'] = 130)] = 'OP_SIZE';
62
+ OPS[(OPS['OP_INVERT'] = 131)] = 'OP_INVERT';
63
+ OPS[(OPS['OP_AND'] = 132)] = 'OP_AND';
64
+ OPS[(OPS['OP_OR'] = 133)] = 'OP_OR';
65
+ OPS[(OPS['OP_XOR'] = 134)] = 'OP_XOR';
66
+ OPS[(OPS['OP_EQUAL'] = 135)] = 'OP_EQUAL';
67
+ OPS[(OPS['OP_EQUALVERIFY'] = 136)] = 'OP_EQUALVERIFY';
68
+ OPS[(OPS['OP_RESERVED1'] = 137)] = 'OP_RESERVED1';
69
+ OPS[(OPS['OP_RESERVED2'] = 138)] = 'OP_RESERVED2';
70
+ OPS[(OPS['OP_1ADD'] = 139)] = 'OP_1ADD';
71
+ OPS[(OPS['OP_1SUB'] = 140)] = 'OP_1SUB';
72
+ OPS[(OPS['OP_2MUL'] = 141)] = 'OP_2MUL';
73
+ OPS[(OPS['OP_2DIV'] = 142)] = 'OP_2DIV';
74
+ OPS[(OPS['OP_NEGATE'] = 143)] = 'OP_NEGATE';
75
+ OPS[(OPS['OP_ABS'] = 144)] = 'OP_ABS';
76
+ OPS[(OPS['OP_NOT'] = 145)] = 'OP_NOT';
77
+ OPS[(OPS['OP_0NOTEQUAL'] = 146)] = 'OP_0NOTEQUAL';
78
+ OPS[(OPS['OP_ADD'] = 147)] = 'OP_ADD';
79
+ OPS[(OPS['OP_SUB'] = 148)] = 'OP_SUB';
80
+ OPS[(OPS['OP_MUL'] = 149)] = 'OP_MUL';
81
+ OPS[(OPS['OP_DIV'] = 150)] = 'OP_DIV';
82
+ OPS[(OPS['OP_MOD'] = 151)] = 'OP_MOD';
83
+ OPS[(OPS['OP_LSHIFT'] = 152)] = 'OP_LSHIFT';
84
+ OPS[(OPS['OP_RSHIFT'] = 153)] = 'OP_RSHIFT';
85
+ OPS[(OPS['OP_BOOLAND'] = 154)] = 'OP_BOOLAND';
86
+ OPS[(OPS['OP_BOOLOR'] = 155)] = 'OP_BOOLOR';
87
+ OPS[(OPS['OP_NUMEQUAL'] = 156)] = 'OP_NUMEQUAL';
88
+ OPS[(OPS['OP_NUMEQUALVERIFY'] = 157)] = 'OP_NUMEQUALVERIFY';
89
+ OPS[(OPS['OP_NUMNOTEQUAL'] = 158)] = 'OP_NUMNOTEQUAL';
90
+ OPS[(OPS['OP_LESSTHAN'] = 159)] = 'OP_LESSTHAN';
91
+ OPS[(OPS['OP_GREATERTHAN'] = 160)] = 'OP_GREATERTHAN';
92
+ OPS[(OPS['OP_LESSTHANOREQUAL'] = 161)] = 'OP_LESSTHANOREQUAL';
93
+ OPS[(OPS['OP_GREATERTHANOREQUAL'] = 162)] = 'OP_GREATERTHANOREQUAL';
94
+ OPS[(OPS['OP_MIN'] = 163)] = 'OP_MIN';
95
+ OPS[(OPS['OP_MAX'] = 164)] = 'OP_MAX';
96
+ OPS[(OPS['OP_WITHIN'] = 165)] = 'OP_WITHIN';
97
+ OPS[(OPS['OP_RIPEMD160'] = 166)] = 'OP_RIPEMD160';
98
+ OPS[(OPS['OP_SHA1'] = 167)] = 'OP_SHA1';
99
+ OPS[(OPS['OP_SHA256'] = 168)] = 'OP_SHA256';
100
+ OPS[(OPS['OP_HASH160'] = 169)] = 'OP_HASH160';
101
+ OPS[(OPS['OP_HASH256'] = 170)] = 'OP_HASH256';
102
+ OPS[(OPS['OP_CODESEPARATOR'] = 171)] = 'OP_CODESEPARATOR';
103
+ OPS[(OPS['OP_CHECKSIG'] = 172)] = 'OP_CHECKSIG';
104
+ OPS[(OPS['OP_CHECKSIGVERIFY'] = 173)] = 'OP_CHECKSIGVERIFY';
105
+ OPS[(OPS['OP_CHECKMULTISIG'] = 174)] = 'OP_CHECKMULTISIG';
106
+ OPS[(OPS['OP_CHECKMULTISIGVERIFY'] = 175)] = 'OP_CHECKMULTISIGVERIFY';
107
+ OPS[(OPS['OP_NOP1'] = 176)] = 'OP_NOP1';
108
+ OPS[(OPS['OP_CHECKLOCKTIMEVERIFY'] = 177)] = 'OP_CHECKLOCKTIMEVERIFY';
109
+ OPS[(OPS['OP_NOP2'] = 177)] = 'OP_NOP2';
110
+ OPS[(OPS['OP_CHECKSEQUENCEVERIFY'] = 178)] = 'OP_CHECKSEQUENCEVERIFY';
111
+ OPS[(OPS['OP_NOP3'] = 178)] = 'OP_NOP3';
112
+ OPS[(OPS['OP_NOP4'] = 179)] = 'OP_NOP4';
113
+ OPS[(OPS['OP_NOP5'] = 180)] = 'OP_NOP5';
114
+ OPS[(OPS['OP_NOP6'] = 181)] = 'OP_NOP6';
115
+ OPS[(OPS['OP_NOP7'] = 182)] = 'OP_NOP7';
116
+ OPS[(OPS['OP_NOP8'] = 183)] = 'OP_NOP8';
117
+ OPS[(OPS['OP_NOP9'] = 184)] = 'OP_NOP9';
118
+ OPS[(OPS['OP_NOP10'] = 185)] = 'OP_NOP10';
119
+ OPS[(OPS['OP_CHECKSIGADD'] = 186)] = 'OP_CHECKSIGADD';
120
+ OPS[(OPS['OP_PUBKEYHASH'] = 253)] = 'OP_PUBKEYHASH';
121
+ OPS[(OPS['OP_PUBKEY'] = 254)] = 'OP_PUBKEY';
122
+ OPS[(OPS['OP_INVALIDOPCODE'] = 255)] = 'OP_INVALIDOPCODE';
123
+ })(OPS || (OPS = {}));
124
+ // Export modules
125
+ export { OPS };
@@ -0,0 +1,135 @@
1
+ import { getEccLib } from '../ecc_lib.js';
2
+ import * as bcrypto from '../crypto.js';
3
+ import { varuint } from '../bufferutils.js';
4
+ import { isTapleaf } from '../types.js';
5
+ import * as tools from 'uint8array-tools';
6
+ export const LEAF_VERSION_TAPSCRIPT = 0xc0;
7
+ export const MAX_TAPTREE_DEPTH = 128;
8
+ const isHashBranch = ht => 'left' in ht && 'right' in ht;
9
+ /**
10
+ * Calculates the root hash from a given control block and leaf hash.
11
+ * @param controlBlock - The control block buffer.
12
+ * @param leafHash - The leaf hash buffer.
13
+ * @returns The root hash buffer.
14
+ * @throws {TypeError} If the control block length is less than 33.
15
+ */
16
+ export function rootHashFromPath(controlBlock, leafHash) {
17
+ if (controlBlock.length < 33)
18
+ throw new TypeError(
19
+ `The control-block length is too small. Got ${controlBlock.length}, expected min 33.`,
20
+ );
21
+ const m = (controlBlock.length - 33) / 32;
22
+ let kj = leafHash;
23
+ for (let j = 0; j < m; j++) {
24
+ const ej = controlBlock.slice(33 + 32 * j, 65 + 32 * j);
25
+ if (tools.compare(kj, ej) < 0) {
26
+ kj = tapBranchHash(kj, ej);
27
+ } else {
28
+ kj = tapBranchHash(ej, kj);
29
+ }
30
+ }
31
+ return kj;
32
+ }
33
+ /**
34
+ * Build a hash tree of merkle nodes from the scripts binary tree.
35
+ * @param scriptTree - the tree of scripts to pairwise hash.
36
+ */
37
+ export function toHashTree(scriptTree) {
38
+ if (isTapleaf(scriptTree)) return { hash: tapleafHash(scriptTree) };
39
+ const hashes = [toHashTree(scriptTree[0]), toHashTree(scriptTree[1])];
40
+ // hashes.sort((a, b) => a.hash.compare(b.hash));
41
+ hashes.sort((a, b) => tools.compare(a.hash, b.hash));
42
+ const [left, right] = hashes;
43
+ return {
44
+ hash: tapBranchHash(left.hash, right.hash),
45
+ left,
46
+ right,
47
+ };
48
+ }
49
+ /**
50
+ * Given a HashTree, finds the path from a particular hash to the root.
51
+ * @param node - the root of the tree
52
+ * @param hash - the hash to search for
53
+ * @returns - array of sibling hashes, from leaf (inclusive) to root
54
+ * (exclusive) needed to prove inclusion of the specified hash. undefined if no
55
+ * path is found
56
+ */
57
+ export function findScriptPath(node, hash) {
58
+ if (isHashBranch(node)) {
59
+ const leftPath = findScriptPath(node.left, hash);
60
+ if (leftPath !== undefined) return [...leftPath, node.right.hash];
61
+ const rightPath = findScriptPath(node.right, hash);
62
+ if (rightPath !== undefined) return [...rightPath, node.left.hash];
63
+ } else if (tools.compare(node.hash, hash) === 0) {
64
+ return [];
65
+ }
66
+ return undefined;
67
+ }
68
+ /**
69
+ * Calculates the tapleaf hash for a given Tapleaf object.
70
+ * @param leaf - The Tapleaf object to calculate the hash for.
71
+ * @returns The tapleaf hash as a Buffer.
72
+ */
73
+ export function tapleafHash(leaf) {
74
+ const version = leaf.version || LEAF_VERSION_TAPSCRIPT;
75
+ return bcrypto.taggedHash(
76
+ 'TapLeaf',
77
+ tools.concat([Uint8Array.from([version]), serializeScript(leaf.output)]),
78
+ );
79
+ }
80
+ /**
81
+ * Computes the taproot tweak hash for a given public key and optional hash.
82
+ * If a hash is provided, the public key and hash are concatenated before computing the hash.
83
+ * If no hash is provided, only the public key is used to compute the hash.
84
+ *
85
+ * @param pubKey - The public key buffer.
86
+ * @param h - The optional hash buffer.
87
+ * @returns The taproot tweak hash.
88
+ */
89
+ export function tapTweakHash(pubKey, h) {
90
+ return bcrypto.taggedHash(
91
+ 'TapTweak',
92
+ tools.concat(h ? [pubKey, h] : [pubKey]),
93
+ );
94
+ }
95
+ /**
96
+ * Tweak a public key with a given tweak hash.
97
+ * @param pubKey - The public key to be tweaked.
98
+ * @param h - The tweak hash.
99
+ * @returns The tweaked public key or null if the input is invalid.
100
+ */
101
+ export function tweakKey(pubKey, h) {
102
+ if (!(pubKey instanceof Uint8Array)) return null;
103
+ if (pubKey.length !== 32) return null;
104
+ if (h && h.length !== 32) return null;
105
+ const tweakHash = tapTweakHash(pubKey, h);
106
+ const res = getEccLib().xOnlyPointAddTweak(pubKey, tweakHash);
107
+ if (!res || res.xOnlyPubkey === null) return null;
108
+ return {
109
+ parity: res.parity,
110
+ x: Uint8Array.from(res.xOnlyPubkey),
111
+ };
112
+ }
113
+ /**
114
+ * Computes the TapBranch hash by concatenating two buffers and applying the 'TapBranch' tagged hash algorithm.
115
+ *
116
+ * @param a - The first buffer.
117
+ * @param b - The second buffer.
118
+ * @returns The TapBranch hash of the concatenated buffers.
119
+ */
120
+ function tapBranchHash(a, b) {
121
+ return bcrypto.taggedHash('TapBranch', tools.concat([a, b]));
122
+ }
123
+ /**
124
+ * Serializes a script by encoding its length as a varint and concatenating it with the script.
125
+ *
126
+ * @param s - The script to be serialized.
127
+ * @returns The serialized script as a Buffer.
128
+ */
129
+ function serializeScript(s) {
130
+ /* global BigInt */
131
+ const varintLen = varuint.encodingLength(s.length);
132
+ const buffer = new Uint8Array(varintLen);
133
+ varuint.encode(s.length, buffer);
134
+ return tools.concat([buffer, s]);
135
+ }
@@ -0,0 +1,50 @@
1
+ import { bitcoin as BITCOIN_NETWORK } from '../networks.js';
2
+ import * as bscript from '../script.js';
3
+ import { stacksEqual, BufferSchema } from '../types.js';
4
+ import * as lazy from './lazy.js';
5
+ import * as v from 'valibot';
6
+ const OPS = bscript.OPS;
7
+ // output: OP_RETURN ...
8
+ /**
9
+ * Embeds data in a Bitcoin payment.
10
+ * @param a - The payment object.
11
+ * @param opts - Optional payment options.
12
+ * @returns The modified payment object.
13
+ * @throws {TypeError} If there is not enough data or if the output is invalid.
14
+ */
15
+ export function p2data(a, opts) {
16
+ if (!a.data && !a.output) throw new TypeError('Not enough data');
17
+ opts = Object.assign({ validate: true }, opts || {});
18
+ v.parse(
19
+ v.partial(
20
+ v.object({
21
+ network: v.object({}),
22
+ output: BufferSchema,
23
+ data: v.array(BufferSchema),
24
+ }),
25
+ ),
26
+ a,
27
+ );
28
+ const network = a.network || BITCOIN_NETWORK;
29
+ const o = { name: 'embed', network };
30
+ lazy.prop(o, 'output', () => {
31
+ if (!a.data) return;
32
+ return bscript.compile([OPS.OP_RETURN].concat(a.data));
33
+ });
34
+ lazy.prop(o, 'data', () => {
35
+ if (!a.output) return;
36
+ return bscript.decompile(a.output).slice(1);
37
+ });
38
+ // extended validation
39
+ if (opts.validate) {
40
+ if (a.output) {
41
+ const chunks = bscript.decompile(a.output);
42
+ if (chunks[0] !== OPS.OP_RETURN) throw new TypeError('Output is invalid');
43
+ if (!chunks.slice(1).every(chunk => v.is(BufferSchema, chunk)))
44
+ throw new TypeError('Output is invalid');
45
+ if (a.data && !stacksEqual(a.data, o.data))
46
+ throw new TypeError('Data mismatch');
47
+ }
48
+ }
49
+ return Object.assign(o, a);
50
+ }
@@ -0,0 +1,11 @@
1
+ import { p2data as embed } from './embed.js';
2
+ import { p2ms } from './p2ms.js';
3
+ import { p2pk } from './p2pk.js';
4
+ import { p2pkh } from './p2pkh.js';
5
+ import { p2sh } from './p2sh.js';
6
+ import { p2wpkh } from './p2wpkh.js';
7
+ import { p2wsh } from './p2wsh.js';
8
+ import { p2tr } from './p2tr.js';
9
+ export { embed, p2ms, p2pk, p2pkh, p2sh, p2wpkh, p2wsh, p2tr };
10
+ // TODO
11
+ // witness commitment
@@ -0,0 +1,27 @@
1
+ export function prop(object, name, f) {
2
+ Object.defineProperty(object, name, {
3
+ configurable: true,
4
+ enumerable: true,
5
+ get() {
6
+ const _value = f.call(this);
7
+ this[name] = _value;
8
+ return _value;
9
+ },
10
+ set(_value) {
11
+ Object.defineProperty(this, name, {
12
+ configurable: true,
13
+ enumerable: true,
14
+ value: _value,
15
+ writable: true,
16
+ });
17
+ },
18
+ });
19
+ }
20
+ export function value(f) {
21
+ let _value;
22
+ return () => {
23
+ if (_value !== undefined) return _value;
24
+ _value = f();
25
+ return _value;
26
+ };
27
+ }
@@ -0,0 +1,167 @@
1
+ import { bitcoin as BITCOIN_NETWORK } from '../networks.js';
2
+ import * as bscript from '../script.js';
3
+ import * as scriptNumber from '../script_number.js';
4
+ import { BufferSchema, isPoint, stacksEqual } from '../types.js';
5
+ import * as lazy from './lazy.js';
6
+ import * as v from 'valibot';
7
+ const OPS = bscript.OPS;
8
+ const OP_INT_BASE = OPS.OP_RESERVED; // OP_1 - 1
9
+ function encodeSmallOrScriptNum(n) {
10
+ return n <= 16 ? OP_INT_BASE + n : scriptNumber.encode(n);
11
+ }
12
+ function decodeSmallOrScriptNum(chunk) {
13
+ if (typeof chunk === 'number') {
14
+ const val = chunk - OP_INT_BASE;
15
+ if (val < 1 || val > 16)
16
+ throw new TypeError(`Invalid opcode: expected OP_1–OP_16, got ${chunk}`);
17
+ return val;
18
+ } else return scriptNumber.decode(chunk);
19
+ }
20
+ function isSmallOrScriptNum(chunk) {
21
+ if (typeof chunk === 'number')
22
+ return chunk - OP_INT_BASE >= 1 && chunk - OP_INT_BASE <= 16;
23
+ else return Number.isInteger(scriptNumber.decode(chunk));
24
+ }
25
+ // input: OP_0 [signatures ...]
26
+ // output: m [pubKeys ...] n OP_CHECKMULTISIG
27
+ /**
28
+ * Represents a function that creates a Pay-to-Multisig (P2MS) payment object.
29
+ * @param a - The payment object.
30
+ * @param opts - Optional payment options.
31
+ * @returns The created payment object.
32
+ * @throws {TypeError} If the provided data is not valid.
33
+ */
34
+ export function p2ms(a, opts) {
35
+ if (
36
+ !a.input &&
37
+ !a.output &&
38
+ !(a.pubkeys && a.m !== undefined) &&
39
+ !a.signatures
40
+ )
41
+ throw new TypeError('Not enough data');
42
+ opts = Object.assign({ validate: true }, opts || {});
43
+ function isAcceptableSignature(x) {
44
+ return (
45
+ bscript.isCanonicalScriptSignature(x) ||
46
+ (opts.allowIncomplete && x === OPS.OP_0) !== undefined
47
+ );
48
+ }
49
+ v.parse(
50
+ v.partial(
51
+ v.object({
52
+ network: v.object({}),
53
+ m: v.number(),
54
+ n: v.number(),
55
+ output: BufferSchema,
56
+ pubkeys: v.array(v.custom(isPoint), 'Received invalid pubkey'),
57
+ signatures: v.array(
58
+ v.custom(isAcceptableSignature),
59
+ 'Expected signature to be of type isAcceptableSignature',
60
+ ),
61
+ input: BufferSchema,
62
+ }),
63
+ ),
64
+ a,
65
+ );
66
+ const network = a.network || BITCOIN_NETWORK;
67
+ const o = { network };
68
+ let chunks = [];
69
+ let decoded = false;
70
+ function decode(output) {
71
+ if (decoded) return;
72
+ decoded = true;
73
+ chunks = bscript.decompile(output);
74
+ if (chunks.length < 3) throw new TypeError('Output is invalid');
75
+ o.m = decodeSmallOrScriptNum(chunks[0]);
76
+ o.n = decodeSmallOrScriptNum(chunks[chunks.length - 2]);
77
+ o.pubkeys = chunks.slice(1, -2);
78
+ }
79
+ lazy.prop(o, 'output', () => {
80
+ if (!a.m) return;
81
+ if (!o.n) return;
82
+ if (!a.pubkeys) return;
83
+ return bscript.compile(
84
+ [].concat(
85
+ encodeSmallOrScriptNum(a.m),
86
+ a.pubkeys,
87
+ encodeSmallOrScriptNum(o.n),
88
+ OPS.OP_CHECKMULTISIG,
89
+ ),
90
+ );
91
+ });
92
+ lazy.prop(o, 'm', () => {
93
+ if (!o.output) return;
94
+ decode(o.output);
95
+ return o.m;
96
+ });
97
+ lazy.prop(o, 'n', () => {
98
+ if (!o.pubkeys) return;
99
+ return o.pubkeys.length;
100
+ });
101
+ lazy.prop(o, 'pubkeys', () => {
102
+ if (!a.output) return;
103
+ decode(a.output);
104
+ return o.pubkeys;
105
+ });
106
+ lazy.prop(o, 'signatures', () => {
107
+ if (!a.input) return;
108
+ return bscript.decompile(a.input).slice(1);
109
+ });
110
+ lazy.prop(o, 'input', () => {
111
+ if (!a.signatures) return;
112
+ return bscript.compile([OPS.OP_0].concat(a.signatures));
113
+ });
114
+ lazy.prop(o, 'witness', () => {
115
+ if (!o.input) return;
116
+ return [];
117
+ });
118
+ lazy.prop(o, 'name', () => {
119
+ if (!o.m || !o.n) return;
120
+ return `p2ms(${o.m} of ${o.n})`;
121
+ });
122
+ // extended validation
123
+ if (opts.validate) {
124
+ if (a.output) {
125
+ decode(a.output);
126
+ if (!isSmallOrScriptNum(chunks[0]))
127
+ throw new TypeError('Output is invalid');
128
+ if (!isSmallOrScriptNum(chunks[chunks.length - 2]))
129
+ throw new TypeError('Output is invalid');
130
+ if (chunks[chunks.length - 1] !== OPS.OP_CHECKMULTISIG)
131
+ throw new TypeError('Output is invalid');
132
+ if (o.m <= 0 || o.n > 20 || o.m > o.n || o.n !== chunks.length - 3)
133
+ throw new TypeError('Output is invalid');
134
+ if (!o.pubkeys.every(x => isPoint(x)))
135
+ throw new TypeError('Output is invalid');
136
+ if (a.m !== undefined && a.m !== o.m) throw new TypeError('m mismatch');
137
+ if (a.n !== undefined && a.n !== o.n) throw new TypeError('n mismatch');
138
+ if (a.pubkeys && !stacksEqual(a.pubkeys, o.pubkeys))
139
+ throw new TypeError('Pubkeys mismatch');
140
+ }
141
+ if (a.pubkeys) {
142
+ if (a.n !== undefined && a.n !== a.pubkeys.length)
143
+ throw new TypeError('Pubkey count mismatch');
144
+ o.n = a.pubkeys.length;
145
+ if (o.n < o.m) throw new TypeError('Pubkey count cannot be less than m');
146
+ }
147
+ if (a.signatures) {
148
+ if (a.signatures.length < o.m)
149
+ throw new TypeError('Not enough signatures provided');
150
+ if (a.signatures.length > o.m)
151
+ throw new TypeError('Too many signatures provided');
152
+ }
153
+ if (a.input) {
154
+ if (a.input[0] !== OPS.OP_0) throw new TypeError('Input is invalid');
155
+ if (
156
+ o.signatures.length === 0 ||
157
+ !o.signatures.every(isAcceptableSignature)
158
+ )
159
+ throw new TypeError('Input has invalid signature(s)');
160
+ if (a.signatures && !stacksEqual(a.signatures, o.signatures))
161
+ throw new TypeError('Signature mismatch');
162
+ if (a.m !== undefined && a.m !== a.signatures.length)
163
+ throw new TypeError('Signature count mismatch');
164
+ }
165
+ }
166
+ return Object.assign(o, a);
167
+ }
@@ -0,0 +1,82 @@
1
+ import { bitcoin as BITCOIN_NETWORK } from '../networks.js';
2
+ import * as bscript from '../script.js';
3
+ import { BufferSchema, isPoint } from '../types.js';
4
+ import * as lazy from './lazy.js';
5
+ import * as tools from 'uint8array-tools';
6
+ import * as v from 'valibot';
7
+ const OPS = bscript.OPS;
8
+ // input: {signature}
9
+ // output: {pubKey} OP_CHECKSIG
10
+ /**
11
+ * Creates a pay-to-public-key (P2PK) payment object.
12
+ *
13
+ * @param a - The payment object containing the necessary data.
14
+ * @param opts - Optional payment options.
15
+ * @returns The P2PK payment object.
16
+ * @throws {TypeError} If the required data is not provided or if the data is invalid.
17
+ */
18
+ export function p2pk(a, opts) {
19
+ if (!a.input && !a.output && !a.pubkey && !a.input && !a.signature)
20
+ throw new TypeError('Not enough data');
21
+ opts = Object.assign({ validate: true }, opts || {});
22
+ v.parse(
23
+ v.partial(
24
+ v.object({
25
+ network: v.object({}),
26
+ output: BufferSchema,
27
+ pubkey: v.custom(isPoint, 'invalid pubkey'),
28
+ signature: v.custom(
29
+ bscript.isCanonicalScriptSignature,
30
+ 'Expected signature to be of type isCanonicalScriptSignature',
31
+ ),
32
+ input: BufferSchema,
33
+ }),
34
+ ),
35
+ a,
36
+ );
37
+ const _chunks = lazy.value(() => {
38
+ return bscript.decompile(a.input);
39
+ });
40
+ const network = a.network || BITCOIN_NETWORK;
41
+ const o = { name: 'p2pk', network };
42
+ lazy.prop(o, 'output', () => {
43
+ if (!a.pubkey) return;
44
+ return bscript.compile([a.pubkey, OPS.OP_CHECKSIG]);
45
+ });
46
+ lazy.prop(o, 'pubkey', () => {
47
+ if (!a.output) return;
48
+ return a.output.slice(1, -1);
49
+ });
50
+ lazy.prop(o, 'signature', () => {
51
+ if (!a.input) return;
52
+ return _chunks()[0];
53
+ });
54
+ lazy.prop(o, 'input', () => {
55
+ if (!a.signature) return;
56
+ return bscript.compile([a.signature]);
57
+ });
58
+ lazy.prop(o, 'witness', () => {
59
+ if (!o.input) return;
60
+ return [];
61
+ });
62
+ // extended validation
63
+ if (opts.validate) {
64
+ if (a.output) {
65
+ if (a.output[a.output.length - 1] !== OPS.OP_CHECKSIG)
66
+ throw new TypeError('Output is invalid');
67
+ if (!isPoint(o.pubkey)) throw new TypeError('Output pubkey is invalid');
68
+ if (a.pubkey && tools.compare(a.pubkey, o.pubkey) !== 0)
69
+ throw new TypeError('Pubkey mismatch');
70
+ }
71
+ if (a.signature) {
72
+ if (a.input && tools.compare(a.input, o.input) !== 0)
73
+ throw new TypeError('Signature mismatch');
74
+ }
75
+ if (a.input) {
76
+ if (_chunks().length !== 1) throw new TypeError('Input is invalid');
77
+ if (!bscript.isCanonicalScriptSignature(o.signature))
78
+ throw new TypeError('Input has invalid signature');
79
+ }
80
+ }
81
+ return Object.assign(o, a);
82
+ }