@scure/btc-signer 1.2.2 → 1.3.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 (60) hide show
  1. package/README.md +30 -3
  2. package/lib/_type_test.d.ts +2 -0
  3. package/lib/_type_test.d.ts.map +1 -0
  4. package/lib/_type_test.js +59 -0
  5. package/lib/_type_test.js.map +1 -0
  6. package/lib/esm/_type_test.js +57 -0
  7. package/lib/esm/_type_test.js.map +1 -0
  8. package/lib/esm/index.js +13 -3007
  9. package/lib/esm/index.js.map +1 -1
  10. package/lib/esm/payment.js +681 -0
  11. package/lib/esm/payment.js.map +1 -0
  12. package/lib/esm/psbt.js +441 -0
  13. package/lib/esm/psbt.js.map +1 -0
  14. package/lib/esm/script.js +347 -0
  15. package/lib/esm/script.js.map +1 -0
  16. package/lib/esm/transaction.js +1013 -0
  17. package/lib/esm/transaction.js.map +1 -0
  18. package/lib/esm/utils.js +115 -0
  19. package/lib/esm/utils.js.map +1 -0
  20. package/lib/esm/utxo.js +528 -0
  21. package/lib/esm/utxo.js.map +1 -0
  22. package/lib/index.d.ts +18 -1439
  23. package/lib/index.d.ts.map +1 -1
  24. package/lib/index.js +53 -3042
  25. package/lib/index.js.map +1 -0
  26. package/lib/payment.d.ts +177 -0
  27. package/lib/payment.d.ts.map +1 -0
  28. package/lib/payment.js +704 -0
  29. package/lib/payment.js.map +1 -0
  30. package/lib/psbt.d.ts +834 -0
  31. package/lib/psbt.d.ts.map +1 -0
  32. package/lib/psbt.js +446 -0
  33. package/lib/psbt.js.map +1 -0
  34. package/lib/script.d.ts +154 -0
  35. package/lib/script.d.ts.map +1 -0
  36. package/lib/script.js +353 -0
  37. package/lib/script.js.map +1 -0
  38. package/lib/transaction.d.ts +223 -0
  39. package/lib/transaction.d.ts.map +1 -0
  40. package/lib/transaction.js +1022 -0
  41. package/lib/transaction.js.map +1 -0
  42. package/lib/utils.d.ts +30 -0
  43. package/lib/utils.d.ts.map +1 -0
  44. package/lib/utils.js +128 -0
  45. package/lib/utils.js.map +1 -0
  46. package/lib/utxo.d.ts +251 -0
  47. package/lib/utxo.d.ts.map +1 -0
  48. package/lib/utxo.js +538 -0
  49. package/lib/utxo.js.map +1 -0
  50. package/package.json +40 -10
  51. package/src/_type_test.ts +69 -0
  52. package/src/index.ts +28 -0
  53. package/src/package.json +3 -0
  54. package/src/payment.ts +755 -0
  55. package/src/psbt.ts +512 -0
  56. package/src/script.ts +236 -0
  57. package/src/transaction.ts +1065 -0
  58. package/src/utils.ts +118 -0
  59. package/src/utxo.ts +554 -0
  60. package/index.ts +0 -3067
package/lib/index.js CHANGED
@@ -1,3049 +1,60 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TAP_LEAF_VERSION = exports._sortPubkeys = exports.SigHash = exports.SignatureHash = exports.Address = exports.WIF = exports.programToWitness = exports.OutScript = exports.p2tr_ms = exports.p2tr_pk = exports.p2tr_ns = exports.combinations = exports.p2tr = exports.TAPROOT_UNSPENDABLE_KEY = exports.taprootListToTree = exports.p2ms = exports.p2wpkh = exports.p2wsh = exports.p2sh = exports.p2pkh = exports.p2pk = exports.RawPSBTV2 = exports.RawPSBTV0 = exports._DebugPSBT = exports._RawPSBTV2 = exports._RawPSBTV0 = exports.TaprootControlBlock = exports.RawTx = exports.RawWitness = exports.RawOutput = exports.RawInput = exports.VarBytes = exports.BTCArray = exports.CompactSize = exports.OpToNum = exports.ScriptNum = exports.Script = exports.OP = exports._cmpBytes = exports.Decimal = exports.DEFAULT_SEQUENCE = exports.DEFAULT_LOCKTIME = exports.DEFAULT_VERSION = exports.PRECISION = exports.TEST_NETWORK = exports.NETWORK = exports.taprootTweakPubkey = exports.taprootTweakPrivKey = exports.cloneDeep = exports.base58check = void 0;
4
- exports.selectUTXO = exports._Estimator = exports._cmpBig = exports.PSBTCombine = exports.bip32Path = exports.sortedMultisig = exports.multisig = exports.getAddress = exports.Transaction = exports.tapLeafHash = void 0;
3
+ exports._Estimator = exports._cmpBig = exports.DEFAULT_SEQUENCE = exports.PSBTCombine = exports.SigHash = exports.bip32Path = exports.Decimal = exports.TaprootControlBlock = exports._DebugPSBT = exports.combinations = exports.sortedMultisig = exports._sortPubkeys = exports.OutScript = exports.taprootListToTree = exports.WIF = exports.getAddress = exports.Address = exports.utils = exports.TAPROOT_UNSPENDABLE_KEY = exports.TEST_NETWORK = exports.NETWORK = exports.selectUTXO = exports.getInputType = exports.Transaction = exports.MAX_SCRIPT_BYTE_LENGTH = exports.ScriptNum = exports.Script = exports.CompactSize = exports.RawTx = exports.OP = exports.multisig = exports.p2tr_pk = exports.p2tr_ms = exports.p2tr_ns = exports.p2tr = exports.p2wpkh = exports.p2wsh = exports.p2ms = exports.p2sh = exports.p2pkh = exports.p2pk = void 0;
5
4
  /*! scure-btc-signer - MIT License (c) 2022 Paul Miller (paulmillr.com) */
6
- const secp256k1_1 = require("@noble/curves/secp256k1");
7
- const sha256_1 = require("@noble/hashes/sha256");
8
- const ripemd160_1 = require("@noble/hashes/ripemd160");
9
- const base_1 = require("@scure/base");
10
- const P = require("micro-packed");
11
- const { ProjectivePoint: ProjPoint, sign: _signECDSA, getPublicKey: _pubECDSA } = secp256k1_1.secp256k1;
12
- const CURVE_ORDER = secp256k1_1.secp256k1.CURVE.n;
13
- // Same as value || def, but doesn't overwrites zero ('0', 0, 0n, etc)
14
- const def = (value, def) => (value === undefined ? def : value);
15
- const isBytes = P.isBytes;
16
- const hash160 = (msg) => (0, ripemd160_1.ripemd160)((0, sha256_1.sha256)(msg));
17
- const sha256x2 = (...msgs) => (0, sha256_1.sha256)((0, sha256_1.sha256)(concat(...msgs)));
18
- const concat = P.concatBytes;
19
- // Make base58check work
20
- exports.base58check = (0, base_1.createBase58check)(sha256_1.sha256);
21
- function cloneDeep(obj) {
22
- if (Array.isArray(obj))
23
- return obj.map((i) => cloneDeep(i));
24
- // slice of nodejs Buffer doesn't copy
25
- else if (obj instanceof Uint8Array)
26
- return Uint8Array.from(obj);
27
- // immutable
28
- else if (['number', 'bigint', 'boolean', 'string', 'undefined'].includes(typeof obj))
29
- return obj;
30
- // null is object
31
- else if (obj === null)
32
- return obj;
33
- // should be last, so it won't catch other types
34
- else if (typeof obj === 'object') {
35
- return Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, cloneDeep(v)]));
36
- }
37
- throw new Error(`cloneDeep: unknown type=${obj} (${typeof obj})`);
38
- }
39
- exports.cloneDeep = cloneDeep;
40
- var PubT;
41
- (function (PubT) {
42
- PubT[PubT["ecdsa"] = 0] = "ecdsa";
43
- PubT[PubT["schnorr"] = 1] = "schnorr";
44
- })(PubT || (PubT = {}));
45
- function validatePubkey(pub, type) {
46
- const len = pub.length;
47
- if (type === PubT.ecdsa) {
48
- if (len === 32)
49
- throw new Error('Expected non-Schnorr key');
50
- ProjPoint.fromHex(pub); // does assertValidity
51
- return pub;
52
- }
53
- else if (type === PubT.schnorr) {
54
- if (len !== 32)
55
- throw new Error('Expected 32-byte Schnorr key');
56
- secp256k1_1.schnorr.utils.lift_x(secp256k1_1.schnorr.utils.bytesToNumberBE(pub));
57
- return pub;
58
- }
59
- else {
60
- throw new Error('Unknown key type');
61
- }
62
- }
63
- function isValidPubkey(pub, type) {
64
- try {
65
- validatePubkey(pub, type);
66
- return true;
67
- }
68
- catch (e) {
69
- return false;
70
- }
71
- }
72
- // low-r signature grinding. Used to reduce tx size by 1 byte.
73
- // noble/secp256k1 does not support the feature: it is not used outside of BTC.
74
- // We implement it manually, because in BTC it's common.
75
- // Not best way, but closest to bitcoin implementation (easier to check)
76
- const hasLowR = (sig) => sig.r < CURVE_ORDER / 2n;
77
- function signECDSA(hash, privateKey, lowR = false) {
78
- let sig = _signECDSA(hash, privateKey);
79
- if (lowR && !hasLowR(sig)) {
80
- const extraEntropy = new Uint8Array(32);
81
- for (let cnt = 0; cnt < Number.MAX_SAFE_INTEGER; cnt++) {
82
- extraEntropy.set(P.U32LE.encode(cnt));
83
- sig = _signECDSA(hash, privateKey, { extraEntropy });
84
- if (hasLowR(sig))
85
- break;
86
- }
87
- }
88
- return sig.toDERRawBytes();
89
- }
90
- function tapTweak(a, b) {
91
- const u = secp256k1_1.schnorr.utils;
92
- const t = u.taggedHash('TapTweak', a, b);
93
- const tn = u.bytesToNumberBE(t);
94
- if (tn >= CURVE_ORDER)
95
- throw new Error('tweak higher than curve order');
96
- return tn;
97
- }
98
- function taprootTweakPrivKey(privKey, merkleRoot = new Uint8Array()) {
99
- const u = secp256k1_1.schnorr.utils;
100
- const seckey0 = u.bytesToNumberBE(privKey); // seckey0 = int_from_bytes(seckey0)
101
- const P = ProjPoint.fromPrivateKey(seckey0); // P = point_mul(G, seckey0)
102
- // seckey = seckey0 if has_even_y(P) else SECP256K1_ORDER - seckey0
103
- const seckey = P.hasEvenY() ? seckey0 : u.mod(-seckey0, CURVE_ORDER);
104
- const xP = u.pointToBytes(P);
105
- // t = int_from_bytes(tagged_hash("TapTweak", bytes_from_int(x(P)) + h)); >= SECP256K1_ORDER check
106
- const t = tapTweak(xP, merkleRoot);
107
- // bytes_from_int((seckey + t) % SECP256K1_ORDER)
108
- return u.numberToBytesBE(u.mod(seckey + t, CURVE_ORDER), 32);
109
- }
110
- exports.taprootTweakPrivKey = taprootTweakPrivKey;
111
- function taprootTweakPubkey(pubKey, h) {
112
- const u = secp256k1_1.schnorr.utils;
113
- const t = tapTweak(pubKey, h); // t = int_from_bytes(tagged_hash("TapTweak", pubkey + h))
114
- const P = u.lift_x(u.bytesToNumberBE(pubKey)); // P = lift_x(int_from_bytes(pubkey))
115
- const Q = P.add(ProjPoint.fromPrivateKey(t)); // Q = point_add(P, point_mul(G, t))
116
- const parity = Q.hasEvenY() ? 0 : 1; // 0 if has_even_y(Q) else 1
117
- return [u.pointToBytes(Q), parity]; // bytes_from_int(x(Q))
118
- }
119
- exports.taprootTweakPubkey = taprootTweakPubkey;
120
- // Can be 33 or 64 bytes
121
- const PubKeyECDSA = P.validate(P.bytes(null), (pub) => validatePubkey(pub, PubT.ecdsa));
122
- const PubKeySchnorr = P.validate(P.bytes(32), (pub) => validatePubkey(pub, PubT.schnorr));
123
- const SignatureSchnorr = P.validate(P.bytes(null), (sig) => {
124
- if (sig.length !== 64 && sig.length !== 65)
125
- throw new Error('Schnorr signature should be 64 or 65 bytes long');
126
- return sig;
127
- });
128
- function uniqPubkey(pubkeys) {
129
- const map = {};
130
- for (const pub of pubkeys) {
131
- const key = base_1.hex.encode(pub);
132
- if (map[key])
133
- throw new Error(`Multisig: non-uniq pubkey: ${pubkeys.map(base_1.hex.encode)}`);
134
- map[key] = true;
135
- }
136
- }
137
- exports.NETWORK = {
138
- bech32: 'bc',
139
- pubKeyHash: 0x00,
140
- scriptHash: 0x05,
141
- wif: 0x80,
142
- };
143
- exports.TEST_NETWORK = {
144
- bech32: 'tb',
145
- pubKeyHash: 0x6f,
146
- scriptHash: 0xc4,
147
- wif: 0xef,
148
- };
149
- exports.PRECISION = 8;
150
- exports.DEFAULT_VERSION = 2;
151
- exports.DEFAULT_LOCKTIME = 0;
152
- exports.DEFAULT_SEQUENCE = 4294967295;
153
- const EMPTY32 = new Uint8Array(32);
154
- // Utils
155
- exports.Decimal = P.coders.decimal(exports.PRECISION);
156
- // Exported for tests, internal method
157
- function _cmpBytes(a, b) {
158
- if (!isBytes(a) || !isBytes(b))
159
- throw new Error(`cmp: wrong type a=${typeof a} b=${typeof b}`);
160
- // -1 -> a<b, 0 -> a==b, 1 -> a>b
161
- const len = Math.min(a.length, b.length);
162
- for (let i = 0; i < len; i++)
163
- if (a[i] != b[i])
164
- return Math.sign(a[i] - b[i]);
165
- return Math.sign(a.length - b.length);
166
- }
167
- exports._cmpBytes = _cmpBytes;
168
- // Coders
169
- // prettier-ignore
170
- var OP;
171
- (function (OP) {
172
- OP[OP["OP_0"] = 0] = "OP_0";
173
- OP[OP["PUSHDATA1"] = 76] = "PUSHDATA1";
174
- OP[OP["PUSHDATA2"] = 77] = "PUSHDATA2";
175
- OP[OP["PUSHDATA4"] = 78] = "PUSHDATA4";
176
- OP[OP["1NEGATE"] = 79] = "1NEGATE";
177
- OP[OP["RESERVED"] = 80] = "RESERVED";
178
- OP[OP["OP_1"] = 81] = "OP_1";
179
- OP[OP["OP_2"] = 82] = "OP_2";
180
- OP[OP["OP_3"] = 83] = "OP_3";
181
- OP[OP["OP_4"] = 84] = "OP_4";
182
- OP[OP["OP_5"] = 85] = "OP_5";
183
- OP[OP["OP_6"] = 86] = "OP_6";
184
- OP[OP["OP_7"] = 87] = "OP_7";
185
- OP[OP["OP_8"] = 88] = "OP_8";
186
- OP[OP["OP_9"] = 89] = "OP_9";
187
- OP[OP["OP_10"] = 90] = "OP_10";
188
- OP[OP["OP_11"] = 91] = "OP_11";
189
- OP[OP["OP_12"] = 92] = "OP_12";
190
- OP[OP["OP_13"] = 93] = "OP_13";
191
- OP[OP["OP_14"] = 94] = "OP_14";
192
- OP[OP["OP_15"] = 95] = "OP_15";
193
- OP[OP["OP_16"] = 96] = "OP_16";
194
- // Control
195
- OP[OP["NOP"] = 97] = "NOP";
196
- OP[OP["VER"] = 98] = "VER";
197
- OP[OP["IF"] = 99] = "IF";
198
- OP[OP["NOTIF"] = 100] = "NOTIF";
199
- OP[OP["VERIF"] = 101] = "VERIF";
200
- OP[OP["VERNOTIF"] = 102] = "VERNOTIF";
201
- OP[OP["ELSE"] = 103] = "ELSE";
202
- OP[OP["ENDIF"] = 104] = "ENDIF";
203
- OP[OP["VERIFY"] = 105] = "VERIFY";
204
- OP[OP["RETURN"] = 106] = "RETURN";
205
- // Stack
206
- OP[OP["TOALTSTACK"] = 107] = "TOALTSTACK";
207
- OP[OP["FROMALTSTACK"] = 108] = "FROMALTSTACK";
208
- OP[OP["2DROP"] = 109] = "2DROP";
209
- OP[OP["2DUP"] = 110] = "2DUP";
210
- OP[OP["3DUP"] = 111] = "3DUP";
211
- OP[OP["2OVER"] = 112] = "2OVER";
212
- OP[OP["2ROT"] = 113] = "2ROT";
213
- OP[OP["2SWAP"] = 114] = "2SWAP";
214
- OP[OP["IFDUP"] = 115] = "IFDUP";
215
- OP[OP["DEPTH"] = 116] = "DEPTH";
216
- OP[OP["DROP"] = 117] = "DROP";
217
- OP[OP["DUP"] = 118] = "DUP";
218
- OP[OP["NIP"] = 119] = "NIP";
219
- OP[OP["OVER"] = 120] = "OVER";
220
- OP[OP["PICK"] = 121] = "PICK";
221
- OP[OP["ROLL"] = 122] = "ROLL";
222
- OP[OP["ROT"] = 123] = "ROT";
223
- OP[OP["SWAP"] = 124] = "SWAP";
224
- OP[OP["TUCK"] = 125] = "TUCK";
225
- // Splice
226
- OP[OP["CAT"] = 126] = "CAT";
227
- OP[OP["SUBSTR"] = 127] = "SUBSTR";
228
- OP[OP["LEFT"] = 128] = "LEFT";
229
- OP[OP["RIGHT"] = 129] = "RIGHT";
230
- OP[OP["SIZE"] = 130] = "SIZE";
231
- // Boolean logic
232
- OP[OP["INVERT"] = 131] = "INVERT";
233
- OP[OP["AND"] = 132] = "AND";
234
- OP[OP["OR"] = 133] = "OR";
235
- OP[OP["XOR"] = 134] = "XOR";
236
- OP[OP["EQUAL"] = 135] = "EQUAL";
237
- OP[OP["EQUALVERIFY"] = 136] = "EQUALVERIFY";
238
- OP[OP["RESERVED1"] = 137] = "RESERVED1";
239
- OP[OP["RESERVED2"] = 138] = "RESERVED2";
240
- // Numbers
241
- OP[OP["1ADD"] = 139] = "1ADD";
242
- OP[OP["1SUB"] = 140] = "1SUB";
243
- OP[OP["2MUL"] = 141] = "2MUL";
244
- OP[OP["2DIV"] = 142] = "2DIV";
245
- OP[OP["NEGATE"] = 143] = "NEGATE";
246
- OP[OP["ABS"] = 144] = "ABS";
247
- OP[OP["NOT"] = 145] = "NOT";
248
- OP[OP["0NOTEQUAL"] = 146] = "0NOTEQUAL";
249
- OP[OP["ADD"] = 147] = "ADD";
250
- OP[OP["SUB"] = 148] = "SUB";
251
- OP[OP["MUL"] = 149] = "MUL";
252
- OP[OP["DIV"] = 150] = "DIV";
253
- OP[OP["MOD"] = 151] = "MOD";
254
- OP[OP["LSHIFT"] = 152] = "LSHIFT";
255
- OP[OP["RSHIFT"] = 153] = "RSHIFT";
256
- OP[OP["BOOLAND"] = 154] = "BOOLAND";
257
- OP[OP["BOOLOR"] = 155] = "BOOLOR";
258
- OP[OP["NUMEQUAL"] = 156] = "NUMEQUAL";
259
- OP[OP["NUMEQUALVERIFY"] = 157] = "NUMEQUALVERIFY";
260
- OP[OP["NUMNOTEQUAL"] = 158] = "NUMNOTEQUAL";
261
- OP[OP["LESSTHAN"] = 159] = "LESSTHAN";
262
- OP[OP["GREATERTHAN"] = 160] = "GREATERTHAN";
263
- OP[OP["LESSTHANOREQUAL"] = 161] = "LESSTHANOREQUAL";
264
- OP[OP["GREATERTHANOREQUAL"] = 162] = "GREATERTHANOREQUAL";
265
- OP[OP["MIN"] = 163] = "MIN";
266
- OP[OP["MAX"] = 164] = "MAX";
267
- OP[OP["WITHIN"] = 165] = "WITHIN";
268
- // Crypto
269
- OP[OP["RIPEMD160"] = 166] = "RIPEMD160";
270
- OP[OP["SHA1"] = 167] = "SHA1";
271
- OP[OP["SHA256"] = 168] = "SHA256";
272
- OP[OP["HASH160"] = 169] = "HASH160";
273
- OP[OP["HASH256"] = 170] = "HASH256";
274
- OP[OP["CODESEPARATOR"] = 171] = "CODESEPARATOR";
275
- OP[OP["CHECKSIG"] = 172] = "CHECKSIG";
276
- OP[OP["CHECKSIGVERIFY"] = 173] = "CHECKSIGVERIFY";
277
- OP[OP["CHECKMULTISIG"] = 174] = "CHECKMULTISIG";
278
- OP[OP["CHECKMULTISIGVERIFY"] = 175] = "CHECKMULTISIGVERIFY";
279
- // Expansion
280
- OP[OP["NOP1"] = 176] = "NOP1";
281
- OP[OP["CHECKLOCKTIMEVERIFY"] = 177] = "CHECKLOCKTIMEVERIFY";
282
- OP[OP["CHECKSEQUENCEVERIFY"] = 178] = "CHECKSEQUENCEVERIFY";
283
- OP[OP["NOP4"] = 179] = "NOP4";
284
- OP[OP["NOP5"] = 180] = "NOP5";
285
- OP[OP["NOP6"] = 181] = "NOP6";
286
- OP[OP["NOP7"] = 182] = "NOP7";
287
- OP[OP["NOP8"] = 183] = "NOP8";
288
- OP[OP["NOP9"] = 184] = "NOP9";
289
- OP[OP["NOP10"] = 185] = "NOP10";
290
- // BIP 342
291
- OP[OP["CHECKSIGADD"] = 186] = "CHECKSIGADD";
292
- // Invalid
293
- OP[OP["INVALID"] = 255] = "INVALID";
294
- })(OP || (exports.OP = OP = {}));
295
- // Converts script bytes to parsed script
296
- // 5221030000000000000000000000000000000000000000000000000000000000000001210300000000000000000000000000000000000000000000000000000000000000022103000000000000000000000000000000000000000000000000000000000000000353ae
297
- // =>
298
- // OP_2
299
- // 030000000000000000000000000000000000000000000000000000000000000001
300
- // 030000000000000000000000000000000000000000000000000000000000000002
301
- // 030000000000000000000000000000000000000000000000000000000000000003
302
- // OP_3
303
- // CHECKMULTISIG
304
- exports.Script = P.wrap({
305
- encodeStream: (w, value) => {
306
- for (let o of value) {
307
- if (typeof o === 'string') {
308
- if (OP[o] === undefined)
309
- throw new Error(`Unknown opcode=${o}`);
310
- w.byte(OP[o]);
311
- continue;
312
- }
313
- else if (typeof o === 'number') {
314
- if (o === 0x00) {
315
- w.byte(0x00);
316
- continue;
317
- }
318
- else if (1 <= o && o <= 16) {
319
- w.byte(OP.OP_1 - 1 + o);
320
- continue;
321
- }
322
- }
323
- // Encode big numbers
324
- if (typeof o === 'number')
325
- o = ScriptNum().encode(BigInt(o));
326
- if (!isBytes(o))
327
- throw new Error(`Wrong Script OP=${o} (${typeof o})`);
328
- // Bytes
329
- const len = o.length;
330
- if (len < OP.PUSHDATA1)
331
- w.byte(len);
332
- else if (len <= 0xff) {
333
- w.byte(OP.PUSHDATA1);
334
- w.byte(len);
335
- }
336
- else if (len <= 0xffff) {
337
- w.byte(OP.PUSHDATA2);
338
- w.bytes(P.U16LE.encode(len));
339
- }
340
- else {
341
- w.byte(OP.PUSHDATA4);
342
- w.bytes(P.U32LE.encode(len));
343
- }
344
- w.bytes(o);
345
- }
346
- },
347
- decodeStream: (r) => {
348
- const out = [];
349
- while (!r.isEnd()) {
350
- const cur = r.byte();
351
- // if 0 < cur < 78
352
- if (OP.OP_0 < cur && cur <= OP.PUSHDATA4) {
353
- let len;
354
- if (cur < OP.PUSHDATA1)
355
- len = cur;
356
- else if (cur === OP.PUSHDATA1)
357
- len = P.U8.decodeStream(r);
358
- else if (cur === OP.PUSHDATA2)
359
- len = P.U16LE.decodeStream(r);
360
- else if (cur === OP.PUSHDATA4)
361
- len = P.U32LE.decodeStream(r);
362
- else
363
- throw new Error('Should be not possible');
364
- out.push(r.bytes(len));
365
- }
366
- else if (cur === 0x00) {
367
- out.push(0);
368
- }
369
- else if (OP.OP_1 <= cur && cur <= OP.OP_16) {
370
- out.push(cur - (OP.OP_1 - 1));
371
- }
372
- else {
373
- const op = OP[cur];
374
- if (op === undefined)
375
- throw new Error(`Unknown opcode=${cur.toString(16)}`);
376
- out.push(op);
377
- }
378
- }
379
- return out;
380
- },
381
- });
382
- // We can encode almost any number as ScriptNum, however, parsing will be a problem
383
- // since we can't know if buffer is a number or something else.
384
- function ScriptNum(bytesLimit = 6, forceMinimal = false) {
385
- return P.wrap({
386
- encodeStream: (w, value) => {
387
- if (value === 0n)
388
- return;
389
- const neg = value < 0;
390
- const val = BigInt(value);
391
- const nums = [];
392
- for (let abs = neg ? -val : val; abs; abs >>= 8n)
393
- nums.push(Number(abs & 0xffn));
394
- if (nums[nums.length - 1] >= 0x80)
395
- nums.push(neg ? 0x80 : 0);
396
- else if (neg)
397
- nums[nums.length - 1] |= 0x80;
398
- w.bytes(new Uint8Array(nums));
399
- },
400
- decodeStream: (r) => {
401
- const len = r.leftBytes;
402
- if (len > bytesLimit)
403
- throw new Error(`ScriptNum: number (${len}) bigger than limit=${bytesLimit}`);
404
- if (len === 0)
405
- return 0n;
406
- if (forceMinimal) {
407
- // MSB is zero (without sign bit) -> not minimally encoded
408
- if ((r.data[len - 1] & 0x7f) === 0) {
409
- // exception
410
- if (len <= 1 || (r.data[len - 2] & 0x80) === 0)
411
- throw new Error('Non-minimally encoded ScriptNum');
412
- }
413
- }
414
- let last = 0;
415
- let res = 0n;
416
- for (let i = 0; i < len; ++i) {
417
- last = r.byte();
418
- res |= BigInt(last) << (8n * BigInt(i));
419
- }
420
- if (last >= 0x80) {
421
- res &= (2n ** BigInt(len * 8) - 1n) >> 1n;
422
- res = -res;
423
- }
424
- return res;
425
- },
426
- });
427
- }
428
- exports.ScriptNum = ScriptNum;
429
- function OpToNum(op, bytesLimit = 4, forceMinimal = true) {
430
- if (typeof op === 'number')
431
- return op;
432
- if (isBytes(op)) {
433
- try {
434
- const val = ScriptNum(bytesLimit, forceMinimal).decode(op);
435
- if (val > Number.MAX_SAFE_INTEGER)
436
- return;
437
- return Number(val);
438
- }
439
- catch (e) {
440
- return;
441
- }
442
- }
443
- return;
444
- }
445
- exports.OpToNum = OpToNum;
446
- // BTC specific variable length integer encoding
447
- // https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer
448
- const CSLimits = {
449
- 0xfd: [0xfd, 2, 253n, 65535n],
450
- 0xfe: [0xfe, 4, 65536n, 4294967295n],
451
- 0xff: [0xff, 8, 4294967296n, 18446744073709551615n],
452
- };
453
- exports.CompactSize = P.wrap({
454
- encodeStream: (w, value) => {
455
- if (typeof value === 'number')
456
- value = BigInt(value);
457
- if (0n <= value && value <= 252n)
458
- return w.byte(Number(value));
459
- for (const [flag, bytes, start, stop] of Object.values(CSLimits)) {
460
- if (start > value || value > stop)
461
- continue;
462
- w.byte(flag);
463
- for (let i = 0; i < bytes; i++)
464
- w.byte(Number((value >> (8n * BigInt(i))) & 0xffn));
465
- return;
466
- }
467
- throw w.err(`VarInt too big: ${value}`);
468
- },
469
- decodeStream: (r) => {
470
- const b0 = r.byte();
471
- if (b0 <= 0xfc)
472
- return BigInt(b0);
473
- const [_, bytes, start] = CSLimits[b0];
474
- let num = 0n;
475
- for (let i = 0; i < bytes; i++)
476
- num |= BigInt(r.byte()) << (8n * BigInt(i));
477
- if (num < start)
478
- throw r.err(`Wrong CompactSize(${8 * bytes})`);
479
- return num;
480
- },
481
- });
482
- // Same thing, but in number instead of bigint. Checks for safe integer inside
483
- const CompactSizeLen = P.apply(exports.CompactSize, P.coders.number);
484
- // Array of size <CompactSize>
485
- const BTCArray = (t) => P.array(exports.CompactSize, t);
486
- exports.BTCArray = BTCArray;
487
- // ui8a of size <CompactSize>
488
- exports.VarBytes = P.bytes(exports.CompactSize);
489
- exports.RawInput = P.struct({
490
- txid: P.bytes(32, true), // hash(prev_tx),
491
- index: P.U32LE, // output number of previous tx
492
- finalScriptSig: exports.VarBytes, // btc merges input and output script, executes it. If ok = tx passes
493
- sequence: P.U32LE, // ?
494
- });
495
- exports.RawOutput = P.struct({ amount: P.U64LE, script: exports.VarBytes });
496
- const EMPTY_OUTPUT = {
497
- amount: 0xffffffffffffffffn,
498
- script: P.EMPTY,
499
- };
500
- // SegWit v0 stack of witness buffers
501
- exports.RawWitness = P.array(CompactSizeLen, exports.VarBytes);
502
- // https://en.bitcoin.it/wiki/Protocol_documentation#tx
503
- const _RawTx = P.struct({
504
- version: P.I32LE,
505
- segwitFlag: P.flag(new Uint8Array([0x00, 0x01])),
506
- inputs: (0, exports.BTCArray)(exports.RawInput),
507
- outputs: (0, exports.BTCArray)(exports.RawOutput),
508
- witnesses: P.flagged('segwitFlag', P.array('inputs/length', exports.RawWitness)),
509
- // < 500000000 Block number at which this transaction is unlocked
510
- // >= 500000000 UNIX timestamp at which this transaction is unlocked
511
- // Handled as part of PSBTv2
512
- lockTime: P.U32LE,
513
- });
514
- function validateRawTx(tx) {
515
- if (tx.segwitFlag && tx.witnesses && !tx.witnesses.length)
516
- throw new Error('Segwit flag with empty witnesses array');
517
- return tx;
518
- }
519
- exports.RawTx = P.validate(_RawTx, validateRawTx);
520
- function PSBTKeyInfo(info) {
521
- const [type, kc, vc, reqInc, allowInc, silentIgnore] = info;
522
- return { type, kc, vc, reqInc, allowInc, silentIgnore };
523
- }
524
- const BIP32Der = P.struct({
525
- fingerprint: P.U32BE,
526
- path: P.array(null, P.U32LE),
527
- });
528
- // Complex structure for PSBT fields
529
- // <control byte with leaf version and parity bit> <internal key p> <C> <E> <AB>
530
- const _TaprootControlBlock = P.struct({
531
- version: P.U8, // With parity :(
532
- internalKey: P.bytes(32),
533
- merklePath: P.array(null, P.bytes(32)),
534
- });
535
- exports.TaprootControlBlock = P.validate(_TaprootControlBlock, (cb) => {
536
- if (cb.merklePath.length > 128)
537
- throw new Error('TaprootControlBlock: merklePath should be of length 0..128 (inclusive)');
538
- return cb;
539
- });
540
- const TaprootBIP32Der = P.struct({
541
- hashes: P.array(CompactSizeLen, P.bytes(32)),
542
- der: BIP32Der,
543
- });
544
- // The 78 byte serialized extended public key as defined by BIP 32.
545
- const GlobalXPUB = P.bytes(78);
546
- const tapScriptSigKey = P.struct({ pubKey: PubKeySchnorr, leafHash: P.bytes(32) });
547
- // {<8-bit uint depth> <8-bit uint leaf version> <compact size uint scriptlen> <bytes script>}*
548
- const tapTree = P.array(null, P.struct({
549
- depth: P.U8,
550
- version: P.U8,
551
- script: exports.VarBytes,
552
- }));
553
- const BytesInf = P.bytes(null); // Bytes will conflict with Bytes type
554
- const Bytes20 = P.bytes(20);
555
- const Bytes32 = P.bytes(32);
556
- // versionsRequiringExclusing = !versionsAllowsInclusion (as set)
557
- // {name: [tag, keyCoder, valueCoder, versionsRequiringInclusion, versionsRequiringExclusing, versionsAllowsInclusion, silentIgnore]}
558
- // SilentIgnore: we use some v2 fields for v1 representation too, so we just clean them before serialize
559
- // Tables from BIP-0174 (https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki)
5
+ const utils_js_1 = require("./utils.js");
560
6
  // prettier-ignore
561
- const PSBTGlobal = {
562
- unsignedTx: [0x00, false, exports.RawTx, [0], [0], false],
563
- xpub: [0x01, GlobalXPUB, BIP32Der, [], [0, 2], false],
564
- txVersion: [0x02, false, P.U32LE, [2], [2], false],
565
- fallbackLocktime: [0x03, false, P.U32LE, [], [2], false],
566
- inputCount: [0x04, false, CompactSizeLen, [2], [2], false],
567
- outputCount: [0x05, false, CompactSizeLen, [2], [2], false],
568
- txModifiable: [0x06, false, P.U8, [], [2], false], // TODO: bitfield
569
- version: [0xfb, false, P.U32LE, [], [0, 2], false],
570
- proprietary: [0xfc, BytesInf, BytesInf, [], [0, 2], false],
571
- };
7
+ var payment_js_1 = require("./payment.js");
8
+ Object.defineProperty(exports, "p2pk", { enumerable: true, get: function () { return payment_js_1.p2pk; } });
9
+ Object.defineProperty(exports, "p2pkh", { enumerable: true, get: function () { return payment_js_1.p2pkh; } });
10
+ Object.defineProperty(exports, "p2sh", { enumerable: true, get: function () { return payment_js_1.p2sh; } });
11
+ Object.defineProperty(exports, "p2ms", { enumerable: true, get: function () { return payment_js_1.p2ms; } });
12
+ Object.defineProperty(exports, "p2wsh", { enumerable: true, get: function () { return payment_js_1.p2wsh; } });
13
+ Object.defineProperty(exports, "p2wpkh", { enumerable: true, get: function () { return payment_js_1.p2wpkh; } });
14
+ Object.defineProperty(exports, "p2tr", { enumerable: true, get: function () { return payment_js_1.p2tr; } });
15
+ Object.defineProperty(exports, "p2tr_ns", { enumerable: true, get: function () { return payment_js_1.p2tr_ns; } });
16
+ Object.defineProperty(exports, "p2tr_ms", { enumerable: true, get: function () { return payment_js_1.p2tr_ms; } });
17
+ Object.defineProperty(exports, "p2tr_pk", { enumerable: true, get: function () { return payment_js_1.p2tr_pk; } });
18
+ Object.defineProperty(exports, "multisig", { enumerable: true, get: function () { return payment_js_1.multisig; } }); // => classicMultisig?
572
19
  // prettier-ignore
573
- const PSBTInput = {
574
- nonWitnessUtxo: [0x00, false, exports.RawTx, [], [0, 2], false],
575
- witnessUtxo: [0x01, false, exports.RawOutput, [], [0, 2], false],
576
- partialSig: [0x02, PubKeyECDSA, BytesInf, [], [0, 2], false],
577
- sighashType: [0x03, false, P.U32LE, [], [0, 2], false],
578
- redeemScript: [0x04, false, BytesInf, [], [0, 2], false],
579
- witnessScript: [0x05, false, BytesInf, [], [0, 2], false],
580
- bip32Derivation: [0x06, PubKeyECDSA, BIP32Der, [], [0, 2], false],
581
- finalScriptSig: [0x07, false, BytesInf, [], [0, 2], false],
582
- finalScriptWitness: [0x08, false, exports.RawWitness, [], [0, 2], false],
583
- porCommitment: [0x09, false, BytesInf, [], [0, 2], false],
584
- ripemd160: [0x0a, Bytes20, BytesInf, [], [0, 2], false],
585
- sha256: [0x0b, Bytes32, BytesInf, [], [0, 2], false],
586
- hash160: [0x0c, Bytes20, BytesInf, [], [0, 2], false],
587
- hash256: [0x0d, Bytes32, BytesInf, [], [0, 2], false],
588
- txid: [0x0e, false, Bytes32, [2], [2], true],
589
- index: [0x0f, false, P.U32LE, [2], [2], true],
590
- sequence: [0x10, false, P.U32LE, [], [2], true],
591
- requiredTimeLocktime: [0x11, false, P.U32LE, [], [2], false],
592
- requiredHeightLocktime: [0x12, false, P.U32LE, [], [2], false],
593
- tapKeySig: [0x13, false, SignatureSchnorr, [], [0, 2], false],
594
- tapScriptSig: [0x14, tapScriptSigKey, SignatureSchnorr, [], [0, 2], false],
595
- tapLeafScript: [0x15, exports.TaprootControlBlock, BytesInf, [], [0, 2], false],
596
- tapBip32Derivation: [0x16, Bytes32, TaprootBIP32Der, [], [0, 2], false],
597
- tapInternalKey: [0x17, false, PubKeySchnorr, [], [0, 2], false],
598
- tapMerkleRoot: [0x18, false, Bytes32, [], [0, 2], false],
599
- proprietary: [0xfc, BytesInf, BytesInf, [], [0, 2], false],
600
- };
601
- // All other keys removed when finalizing
602
- const PSBTInputFinalKeys = [
603
- 'txid',
604
- 'sequence',
605
- 'index',
606
- 'witnessUtxo',
607
- 'nonWitnessUtxo',
608
- 'finalScriptSig',
609
- 'finalScriptWitness',
610
- 'unknown',
611
- ];
612
- // Can be modified even on signed input
613
- const PSBTInputUnsignedKeys = [
614
- 'partialSig',
615
- 'finalScriptSig',
616
- 'finalScriptWitness',
617
- 'tapKeySig',
618
- 'tapScriptSig',
619
- ];
20
+ var script_js_1 = require("./script.js");
21
+ Object.defineProperty(exports, "OP", { enumerable: true, get: function () { return script_js_1.OP; } });
22
+ Object.defineProperty(exports, "RawTx", { enumerable: true, get: function () { return script_js_1.RawTx; } });
23
+ Object.defineProperty(exports, "CompactSize", { enumerable: true, get: function () { return script_js_1.CompactSize; } });
24
+ Object.defineProperty(exports, "Script", { enumerable: true, get: function () { return script_js_1.Script; } });
25
+ Object.defineProperty(exports, "ScriptNum", { enumerable: true, get: function () { return script_js_1.ScriptNum; } });
26
+ Object.defineProperty(exports, "MAX_SCRIPT_BYTE_LENGTH", { enumerable: true, get: function () { return script_js_1.MAX_SCRIPT_BYTE_LENGTH; } });
27
+ var transaction_js_1 = require("./transaction.js");
28
+ Object.defineProperty(exports, "Transaction", { enumerable: true, get: function () { return transaction_js_1.Transaction; } });
29
+ var utxo_js_1 = require("./utxo.js");
30
+ Object.defineProperty(exports, "getInputType", { enumerable: true, get: function () { return utxo_js_1.getInputType; } });
31
+ Object.defineProperty(exports, "selectUTXO", { enumerable: true, get: function () { return utxo_js_1.selectUTXO; } });
32
+ var utils_js_2 = require("./utils.js");
33
+ Object.defineProperty(exports, "NETWORK", { enumerable: true, get: function () { return utils_js_2.NETWORK; } });
34
+ Object.defineProperty(exports, "TEST_NETWORK", { enumerable: true, get: function () { return utils_js_2.TEST_NETWORK; } });
35
+ Object.defineProperty(exports, "TAPROOT_UNSPENDABLE_KEY", { enumerable: true, get: function () { return utils_js_2.TAPROOT_UNSPENDABLE_KEY; } });
36
+ exports.utils = { isBytes: utils_js_1.isBytes, concatBytes: utils_js_1.concatBytes, compareBytes: utils_js_1.compareBytes, pubSchnorr: utils_js_1.pubSchnorr, randomPrivateKeyBytes: utils_js_1.randomPrivateKeyBytes };
37
+ // Utils
620
38
  // prettier-ignore
621
- const PSBTOutput = {
622
- redeemScript: [0x00, false, BytesInf, [], [0, 2], false],
623
- witnessScript: [0x01, false, BytesInf, [], [0, 2], false],
624
- bip32Derivation: [0x02, PubKeyECDSA, BIP32Der, [], [0, 2], false],
625
- amount: [0x03, false, P.I64LE, [2], [2], true],
626
- script: [0x04, false, BytesInf, [2], [2], true],
627
- tapInternalKey: [0x05, false, PubKeySchnorr, [], [0, 2], false],
628
- tapTree: [0x06, false, tapTree, [], [0, 2], false],
629
- tapBip32Derivation: [0x07, PubKeySchnorr, TaprootBIP32Der, [], [0, 2], false],
630
- proprietary: [0xfc, BytesInf, BytesInf, [], [0, 2], false],
631
- };
632
- // Can be modified even on signed input
633
- const PSBTOutputUnsignedKeys = [];
634
- const PSBTKeyPair = P.array(P.NULL, P.struct({
635
- // <key> := <keylen> <keytype> <keydata> WHERE keylen = len(keytype)+len(keydata)
636
- key: P.prefix(CompactSizeLen, P.struct({ type: CompactSizeLen, key: P.bytes(null) })),
637
- // <value> := <valuelen> <valuedata>
638
- value: P.bytes(CompactSizeLen),
639
- }));
640
- const PSBTUnknownKey = P.struct({ type: CompactSizeLen, key: P.bytes(null) });
641
- // Key cannot be 'unknown', value coder cannot be array for elements with empty key
642
- function PSBTKeyMap(psbtEnum) {
643
- // -> Record<type, [keyName, ...coders]>
644
- const byType = {};
645
- for (const k in psbtEnum) {
646
- const [num, kc, vc] = psbtEnum[k];
647
- byType[num] = [k, kc, vc];
648
- }
649
- return P.wrap({
650
- encodeStream: (w, value) => {
651
- let out = [];
652
- // Because we use order of psbtEnum, keymap is sorted here
653
- for (const name in psbtEnum) {
654
- const val = value[name];
655
- if (val === undefined)
656
- continue;
657
- const [type, kc, vc] = psbtEnum[name];
658
- if (!kc) {
659
- out.push({ key: { type, key: P.EMPTY }, value: vc.encode(val) });
660
- }
661
- else {
662
- // Low level interface, returns keys as is (with duplicates). Useful for debug
663
- const kv = val.map(([k, v]) => [
664
- kc.encode(k),
665
- vc.encode(v),
666
- ]);
667
- // sort by keys
668
- kv.sort((a, b) => _cmpBytes(a[0], b[0]));
669
- for (const [key, value] of kv)
670
- out.push({ key: { key, type }, value });
671
- }
672
- }
673
- if (value.unknown) {
674
- value.unknown.sort((a, b) => _cmpBytes(a[0].key, b[0].key));
675
- for (const [k, v] of value.unknown)
676
- out.push({ key: k, value: v });
677
- }
678
- PSBTKeyPair.encodeStream(w, out);
679
- },
680
- decodeStream: (r) => {
681
- const raw = PSBTKeyPair.decodeStream(r);
682
- const out = {};
683
- const noKey = {};
684
- for (const elm of raw) {
685
- let name = 'unknown';
686
- let key = elm.key.key;
687
- let value = elm.value;
688
- if (byType[elm.key.type]) {
689
- const [_name, kc, vc] = byType[elm.key.type];
690
- name = _name;
691
- if (!kc && key.length) {
692
- throw new Error(`PSBT: Non-empty key for ${name} (key=${base_1.hex.encode(key)} value=${base_1.hex.encode(value)}`);
693
- }
694
- key = kc ? kc.decode(key) : undefined;
695
- value = vc.decode(value);
696
- if (!kc) {
697
- if (out[name])
698
- throw new Error(`PSBT: Same keys: ${name} (key=${key} value=${value})`);
699
- out[name] = value;
700
- noKey[name] = true;
701
- continue;
702
- }
703
- }
704
- else {
705
- // For unknown: add key type inside key
706
- key = { type: elm.key.type, key: elm.key.key };
707
- }
708
- // Only keyed elements at this point
709
- if (noKey[name])
710
- throw new Error(`PSBT: Key type with empty key and no key=${name} val=${value}`);
711
- if (!out[name])
712
- out[name] = [];
713
- out[name].push([key, value]);
714
- }
715
- return out;
716
- },
717
- });
718
- }
719
- // Basic sanity check for scripts
720
- function checkWSH(s, witnessScript) {
721
- if (!P.equalBytes(s.hash, (0, sha256_1.sha256)(witnessScript)))
722
- throw new Error('checkScript: wsh wrong witnessScript hash');
723
- const w = exports.OutScript.decode(witnessScript);
724
- if (w.type === 'tr' || w.type === 'tr_ns' || w.type === 'tr_ms')
725
- throw new Error(`checkScript: P2${w.type} cannot be wrapped in P2SH`);
726
- if (w.type === 'wpkh' || w.type === 'sh')
727
- throw new Error(`checkScript: P2${w.type} cannot be wrapped in P2WSH`);
728
- }
729
- function checkScript(script, redeemScript, witnessScript) {
730
- if (script) {
731
- const s = exports.OutScript.decode(script);
732
- // ms||pk maybe work, but there will be no address, hard to spend
733
- if (s.type === 'tr_ns' || s.type === 'tr_ms' || s.type === 'ms' || s.type == 'pk')
734
- throw new Error(`checkScript: non-wrapped ${s.type}`);
735
- if (s.type === 'sh' && redeemScript) {
736
- if (!P.equalBytes(s.hash, hash160(redeemScript)))
737
- throw new Error('checkScript: sh wrong redeemScript hash');
738
- const r = exports.OutScript.decode(redeemScript);
739
- if (r.type === 'tr' || r.type === 'tr_ns' || r.type === 'tr_ms')
740
- throw new Error(`checkScript: P2${r.type} cannot be wrapped in P2SH`);
741
- // Not sure if this unspendable, but we cannot represent this via PSBT
742
- if (r.type === 'sh')
743
- throw new Error('checkScript: P2SH cannot be wrapped in P2SH');
744
- }
745
- if (s.type === 'wsh' && witnessScript)
746
- checkWSH(s, witnessScript);
747
- }
748
- if (redeemScript) {
749
- const r = exports.OutScript.decode(redeemScript);
750
- if (r.type === 'wsh' && witnessScript)
751
- checkWSH(r, witnessScript);
752
- }
753
- }
754
- const PSBTInputCoder = P.validate(PSBTKeyMap(PSBTInput), (i) => {
755
- if (i.finalScriptWitness && !i.finalScriptWitness.length)
756
- throw new Error('validateInput: wmpty finalScriptWitness');
757
- //if (i.finalScriptSig && !i.finalScriptSig.length) throw new Error('validateInput: empty finalScriptSig');
758
- if (i.partialSig && !i.partialSig.length)
759
- throw new Error('Empty partialSig');
760
- if (i.partialSig)
761
- for (const [k] of i.partialSig)
762
- validatePubkey(k, PubT.ecdsa);
763
- if (i.bip32Derivation)
764
- for (const [k] of i.bip32Derivation)
765
- validatePubkey(k, PubT.ecdsa);
766
- // Locktime = unsigned little endian integer greater than or equal to 500000000 representing
767
- if (i.requiredTimeLocktime !== undefined && i.requiredTimeLocktime < 500000000)
768
- throw new Error(`validateInput: wrong timeLocktime=${i.requiredTimeLocktime}`);
769
- // unsigned little endian integer greater than 0 and less than 500000000
770
- if (i.requiredHeightLocktime !== undefined &&
771
- (i.requiredHeightLocktime <= 0 || i.requiredHeightLocktime >= 500000000))
772
- throw new Error(`validateInput: wrong heighLocktime=${i.requiredHeightLocktime}`);
773
- if (i.nonWitnessUtxo && i.index !== undefined) {
774
- const last = i.nonWitnessUtxo.outputs.length - 1;
775
- if (i.index > last)
776
- throw new Error(`validateInput: index(${i.index}) not in nonWitnessUtxo`);
777
- const prevOut = i.nonWitnessUtxo.outputs[i.index];
778
- if (i.witnessUtxo &&
779
- (!P.equalBytes(i.witnessUtxo.script, prevOut.script) ||
780
- i.witnessUtxo.amount !== prevOut.amount))
781
- throw new Error('validateInput: witnessUtxo different from nonWitnessUtxo');
782
- }
783
- if (i.tapLeafScript) {
784
- // tap leaf version appears here twice: in control block and at the end of script
785
- for (const [k, v] of i.tapLeafScript) {
786
- if ((k.version & 254) !== v[v.length - 1])
787
- throw new Error('validateInput: tapLeafScript version mimatch');
788
- if (v[v.length - 1] & 1)
789
- throw new Error('validateInput: tapLeafScript version has parity bit!');
790
- }
791
- }
792
- // Validate txid for nonWitnessUtxo is correct
793
- if (i.nonWitnessUtxo && i.index !== undefined && i.txid) {
794
- const outputs = i.nonWitnessUtxo.outputs;
795
- if (outputs.length - 1 < i.index)
796
- throw new Error('nonWitnessUtxo: incorect output index');
797
- // At this point, we are using previous tx output to create new input.
798
- // Script safety checks are unnecessary:
799
- // - User has no control over previous tx. If somebody send money in same tx
800
- // as unspendable output, we still want user able to spend money
801
- // - We still want some checks to notify user about possible errors early
802
- // in case user wants to use wrong input by mistake
803
- // - Worst case: tx will be rejected by nodes. Still better than disallowing user
804
- // to spend real input, no matter how broken it looks
805
- const tx = Transaction.fromRaw(exports.RawTx.encode(i.nonWitnessUtxo), {
806
- allowUnknownOutputs: true,
807
- disableScriptCheck: true,
808
- allowUnknownInputs: true,
809
- });
810
- const txid = base_1.hex.encode(i.txid);
811
- // PSBTv2 vectors have non-final tx in inputs
812
- if (tx.isFinal && tx.id !== txid)
813
- throw new Error(`nonWitnessUtxo: wrong txid, exp=${txid} got=${tx.id}`);
814
- }
815
- return i;
816
- });
817
- const PSBTOutputCoder = P.validate(PSBTKeyMap(PSBTOutput), (o) => {
818
- if (o.bip32Derivation)
819
- for (const [k] of o.bip32Derivation)
820
- validatePubkey(k, PubT.ecdsa);
821
- return o;
822
- });
823
- const PSBTGlobalCoder = P.validate(PSBTKeyMap(PSBTGlobal), (g) => {
824
- const version = g.version || 0;
825
- if (version === 0) {
826
- if (!g.unsignedTx)
827
- throw new Error('PSBTv0: missing unsignedTx');
828
- if (g.unsignedTx.segwitFlag || g.unsignedTx.witnesses)
829
- throw new Error('PSBTv0: witness in unsingedTx');
830
- for (const inp of g.unsignedTx.inputs)
831
- if (inp.finalScriptSig && inp.finalScriptSig.length)
832
- throw new Error('PSBTv0: input scriptSig found in unsignedTx');
833
- }
834
- return g;
835
- });
836
- exports._RawPSBTV0 = P.struct({
837
- magic: P.magic(P.string(new Uint8Array([0xff])), 'psbt'),
838
- global: PSBTGlobalCoder,
839
- inputs: P.array('global/unsignedTx/inputs/length', PSBTInputCoder),
840
- outputs: P.array(null, PSBTOutputCoder),
841
- });
842
- exports._RawPSBTV2 = P.struct({
843
- magic: P.magic(P.string(new Uint8Array([0xff])), 'psbt'),
844
- global: PSBTGlobalCoder,
845
- inputs: P.array('global/inputCount', PSBTInputCoder),
846
- outputs: P.array('global/outputCount', PSBTOutputCoder),
847
- });
848
- exports._DebugPSBT = P.struct({
849
- magic: P.magic(P.string(new Uint8Array([0xff])), 'psbt'),
850
- items: P.array(null, P.apply(P.array(P.NULL, P.tuple([P.hex(CompactSizeLen), P.bytes(exports.CompactSize)])), P.coders.dict())),
851
- });
852
- function validatePSBTFields(version, info, lst) {
853
- for (const k in lst) {
854
- if (k === 'unknown')
855
- continue;
856
- if (!info[k])
857
- continue;
858
- const { allowInc } = PSBTKeyInfo(info[k]);
859
- if (!allowInc.includes(version))
860
- throw new Error(`PSBTv${version}: field ${k} is not allowed`);
861
- }
862
- for (const k in info) {
863
- const { reqInc } = PSBTKeyInfo(info[k]);
864
- if (reqInc.includes(version) && lst[k] === undefined)
865
- throw new Error(`PSBTv${version}: missing required field ${k}`);
866
- }
867
- }
868
- function cleanPSBTFields(version, info, lst) {
869
- const out = {};
870
- for (const _k in lst) {
871
- const k = _k;
872
- if (k !== 'unknown') {
873
- if (!info[k])
874
- continue;
875
- const { allowInc, silentIgnore } = PSBTKeyInfo(info[k]);
876
- if (!allowInc.includes(version)) {
877
- if (silentIgnore)
878
- continue;
879
- throw new Error(`Failed to serialize in PSBTv${version}: ${k} but versions allows inclusion=${allowInc}`);
880
- }
881
- }
882
- out[k] = lst[k];
883
- }
884
- return out;
885
- }
886
- function validatePSBT(tx) {
887
- const version = (tx && tx.global && tx.global.version) || 0;
888
- validatePSBTFields(version, PSBTGlobal, tx.global);
889
- for (const i of tx.inputs)
890
- validatePSBTFields(version, PSBTInput, i);
891
- for (const o of tx.outputs)
892
- validatePSBTFields(version, PSBTOutput, o);
893
- // We allow only one empty element at the end of map (compat with bitcoinjs-lib bug)
894
- const inputCount = !version ? tx.global.unsignedTx.inputs.length : tx.global.inputCount;
895
- if (tx.inputs.length < inputCount)
896
- throw new Error('Not enough inputs');
897
- const inputsLeft = tx.inputs.slice(inputCount);
898
- if (inputsLeft.length > 1 || (inputsLeft.length && Object.keys(inputsLeft[0]).length))
899
- throw new Error(`Unexpected inputs left in tx=${inputsLeft}`);
900
- // Same for inputs
901
- const outputCount = !version ? tx.global.unsignedTx.outputs.length : tx.global.outputCount;
902
- if (tx.outputs.length < outputCount)
903
- throw new Error('Not outputs inputs');
904
- const outputsLeft = tx.outputs.slice(outputCount);
905
- if (outputsLeft.length > 1 || (outputsLeft.length && Object.keys(outputsLeft[0]).length))
906
- throw new Error(`Unexpected outputs left in tx=${outputsLeft}`);
907
- return tx;
908
- }
909
- function mergeKeyMap(psbtEnum, val, cur, allowedFields) {
910
- const res = { ...cur, ...val };
911
- // All arguments can be provided as hex
912
- for (const k in psbtEnum) {
913
- const key = k;
914
- const [_, kC, vC] = psbtEnum[key];
915
- const cannotChange = allowedFields && !allowedFields.includes(k);
916
- if (val[k] === undefined && k in val) {
917
- if (cannotChange)
918
- throw new Error(`Cannot remove signed field=${k}`);
919
- delete res[k];
920
- }
921
- else if (kC) {
922
- const oldKV = (cur && cur[k] ? cur[k] : []);
923
- let newKV = val[key];
924
- if (newKV) {
925
- if (!Array.isArray(newKV))
926
- throw new Error(`keyMap(${k}): KV pairs should be [k, v][]`);
927
- // Decode hex in k-v
928
- newKV = newKV.map((val) => {
929
- if (val.length !== 2)
930
- throw new Error(`keyMap(${k}): KV pairs should be [k, v][]`);
931
- return [
932
- typeof val[0] === 'string' ? kC.decode(base_1.hex.decode(val[0])) : val[0],
933
- typeof val[1] === 'string' ? vC.decode(base_1.hex.decode(val[1])) : val[1],
934
- ];
935
- });
936
- const map = {};
937
- const add = (kStr, k, v) => {
938
- if (map[kStr] === undefined) {
939
- map[kStr] = [k, v];
940
- return;
941
- }
942
- const oldVal = base_1.hex.encode(vC.encode(map[kStr][1]));
943
- const newVal = base_1.hex.encode(vC.encode(v));
944
- if (oldVal !== newVal)
945
- throw new Error(`keyMap(${key}): same key=${kStr} oldVal=${oldVal} newVal=${newVal}`);
946
- };
947
- for (const [k, v] of oldKV) {
948
- const kStr = base_1.hex.encode(kC.encode(k));
949
- add(kStr, k, v);
950
- }
951
- for (const [k, v] of newKV) {
952
- const kStr = base_1.hex.encode(kC.encode(k));
953
- // undefined removes previous value
954
- if (v === undefined) {
955
- if (cannotChange)
956
- throw new Error(`Cannot remove signed field=${key}/${k}`);
957
- delete map[kStr];
958
- }
959
- else
960
- add(kStr, k, v);
961
- }
962
- res[key] = Object.values(map);
963
- }
964
- }
965
- else if (typeof res[k] === 'string') {
966
- res[k] = vC.decode(base_1.hex.decode(res[k]));
967
- }
968
- else if (cannotChange && k in val && cur && cur[k] !== undefined) {
969
- if (!P.equalBytes(vC.encode(val[k]), vC.encode(cur[k])))
970
- throw new Error(`Cannot change signed field=${k}`);
971
- }
972
- }
973
- // Remove unknown keys
974
- for (const k in res)
975
- if (!psbtEnum[k])
976
- delete res[k];
977
- return res;
978
- }
979
- exports.RawPSBTV0 = P.validate(exports._RawPSBTV0, validatePSBT);
980
- exports.RawPSBTV2 = P.validate(exports._RawPSBTV2, validatePSBT);
981
- // (TxHash, Idx)
982
- const TxHashIdx = P.struct({ txid: P.bytes(32, true), index: P.U32LE });
983
- const OutPK = {
984
- encode(from) {
985
- if (from.length !== 2 ||
986
- !isBytes(from[0]) ||
987
- !isValidPubkey(from[0], PubT.ecdsa) ||
988
- from[1] !== 'CHECKSIG')
989
- return;
990
- return { type: 'pk', pubkey: from[0] };
991
- },
992
- decode: (to) => (to.type === 'pk' ? [to.pubkey, 'CHECKSIG'] : undefined),
993
- };
994
- // @ts-ignore
995
- const p2pk = (pubkey, network = exports.NETWORK) => {
996
- // network is unused
997
- if (!isValidPubkey(pubkey, PubT.ecdsa))
998
- throw new Error('P2PK: invalid publicKey');
999
- return {
1000
- type: 'pk',
1001
- script: exports.OutScript.encode({ type: 'pk', pubkey }),
1002
- };
1003
- };
1004
- exports.p2pk = p2pk;
1005
- const OutPKH = {
1006
- encode(from) {
1007
- if (from.length !== 5 || from[0] !== 'DUP' || from[1] !== 'HASH160' || !isBytes(from[2]))
1008
- return;
1009
- if (from[3] !== 'EQUALVERIFY' || from[4] !== 'CHECKSIG')
1010
- return;
1011
- return { type: 'pkh', hash: from[2] };
1012
- },
1013
- decode: (to) => to.type === 'pkh' ? ['DUP', 'HASH160', to.hash, 'EQUALVERIFY', 'CHECKSIG'] : undefined,
1014
- };
1015
- const p2pkh = (publicKey, network = exports.NETWORK) => {
1016
- if (!isValidPubkey(publicKey, PubT.ecdsa))
1017
- throw new Error('P2PKH: invalid publicKey');
1018
- const hash = hash160(publicKey);
1019
- return {
1020
- type: 'pkh',
1021
- script: exports.OutScript.encode({ type: 'pkh', hash }),
1022
- address: Address(network).encode({ type: 'pkh', hash }),
1023
- };
1024
- };
1025
- exports.p2pkh = p2pkh;
1026
- const OutSH = {
1027
- encode(from) {
1028
- if (from.length !== 3 || from[0] !== 'HASH160' || !isBytes(from[1]) || from[2] !== 'EQUAL')
1029
- return;
1030
- return { type: 'sh', hash: from[1] };
1031
- },
1032
- decode: (to) => to.type === 'sh' ? ['HASH160', to.hash, 'EQUAL'] : undefined,
1033
- };
1034
- const p2sh = (child, network = exports.NETWORK) => {
1035
- // It is already tested inside noble-hashes and checkScript
1036
- const cs = child.script;
1037
- if (!isBytes(cs))
1038
- throw new Error(`Wrong script: ${typeof child.script}, expected Uint8Array`);
1039
- const hash = hash160(cs);
1040
- const script = exports.OutScript.encode({ type: 'sh', hash });
1041
- checkScript(script, cs, child.witnessScript);
1042
- const res = {
1043
- type: 'sh',
1044
- redeemScript: cs,
1045
- script: exports.OutScript.encode({ type: 'sh', hash }),
1046
- address: Address(network).encode({ type: 'sh', hash }),
1047
- };
1048
- if (child.witnessScript)
1049
- res.witnessScript = child.witnessScript;
1050
- return res;
1051
- };
1052
- exports.p2sh = p2sh;
1053
- const OutWSH = {
1054
- encode(from) {
1055
- if (from.length !== 2 || from[0] !== 0 || !isBytes(from[1]))
1056
- return;
1057
- if (from[1].length !== 32)
1058
- return;
1059
- return { type: 'wsh', hash: from[1] };
1060
- },
1061
- decode: (to) => (to.type === 'wsh' ? [0, to.hash] : undefined),
1062
- };
1063
- const p2wsh = (child, network = exports.NETWORK) => {
1064
- const cs = child.script;
1065
- if (!isBytes(cs))
1066
- throw new Error(`Wrong script: ${typeof cs}, expected Uint8Array`);
1067
- const hash = (0, sha256_1.sha256)(cs);
1068
- const script = exports.OutScript.encode({ type: 'wsh', hash });
1069
- checkScript(script, undefined, cs);
1070
- return {
1071
- type: 'wsh',
1072
- witnessScript: cs,
1073
- script: exports.OutScript.encode({ type: 'wsh', hash }),
1074
- address: Address(network).encode({ type: 'wsh', hash }),
1075
- };
1076
- };
1077
- exports.p2wsh = p2wsh;
1078
- const OutWPKH = {
1079
- encode(from) {
1080
- if (from.length !== 2 || from[0] !== 0 || !isBytes(from[1]))
1081
- return;
1082
- if (from[1].length !== 20)
1083
- return;
1084
- return { type: 'wpkh', hash: from[1] };
1085
- },
1086
- decode: (to) => (to.type === 'wpkh' ? [0, to.hash] : undefined),
1087
- };
1088
- const p2wpkh = (publicKey, network = exports.NETWORK) => {
1089
- if (!isValidPubkey(publicKey, PubT.ecdsa))
1090
- throw new Error('P2WPKH: invalid publicKey');
1091
- if (publicKey.length === 65)
1092
- throw new Error('P2WPKH: uncompressed public key');
1093
- const hash = hash160(publicKey);
1094
- return {
1095
- type: 'wpkh',
1096
- script: exports.OutScript.encode({ type: 'wpkh', hash }),
1097
- address: Address(network).encode({ type: 'wpkh', hash }),
1098
- };
1099
- };
1100
- exports.p2wpkh = p2wpkh;
1101
- const OutMS = {
1102
- encode(from) {
1103
- const last = from.length - 1;
1104
- if (from[last] !== 'CHECKMULTISIG')
1105
- return;
1106
- const m = from[0];
1107
- const n = from[last - 1];
1108
- if (typeof m !== 'number' || typeof n !== 'number')
1109
- return;
1110
- const pubkeys = from.slice(1, -2);
1111
- if (n !== pubkeys.length)
1112
- return;
1113
- for (const pub of pubkeys)
1114
- if (!isBytes(pub))
1115
- return;
1116
- return { type: 'ms', m, pubkeys: pubkeys }; // we don't need n, since it is the same as pubkeys
1117
- },
1118
- // checkmultisig(n, ..pubkeys, m)
1119
- decode: (to) => to.type === 'ms' ? [to.m, ...to.pubkeys, to.pubkeys.length, 'CHECKMULTISIG'] : undefined,
1120
- };
1121
- const p2ms = (m, pubkeys, allowSamePubkeys = false) => {
1122
- if (!allowSamePubkeys)
1123
- uniqPubkey(pubkeys);
1124
- return { type: 'ms', script: exports.OutScript.encode({ type: 'ms', pubkeys, m }) };
1125
- };
1126
- exports.p2ms = p2ms;
1127
- const OutTR = {
1128
- encode(from) {
1129
- if (from.length !== 2 || from[0] !== 1 || !isBytes(from[1]))
1130
- return;
1131
- return { type: 'tr', pubkey: from[1] };
1132
- },
1133
- decode: (to) => (to.type === 'tr' ? [1, to.pubkey] : undefined),
1134
- };
1135
- // Helper for generating binary tree from list, with weights
1136
- function taprootListToTree(taprootList) {
1137
- // Clone input in order to not corrupt it
1138
- const lst = Array.from(taprootList);
1139
- // We have at least 2 elements => can create branch
1140
- while (lst.length >= 2) {
1141
- // Sort: elements with smallest weight are in the end of queue
1142
- lst.sort((a, b) => (b.weight || 1) - (a.weight || 1));
1143
- const b = lst.pop();
1144
- const a = lst.pop();
1145
- const weight = (a?.weight || 1) + (b?.weight || 1);
1146
- lst.push({
1147
- weight,
1148
- // Unwrap children array
1149
- // TODO: Very hard to remove any here
1150
- childs: [a?.childs || a, b?.childs || b],
1151
- });
1152
- }
1153
- // At this point there is always 1 element in lst
1154
- const last = lst[0];
1155
- return (last?.childs || last);
1156
- }
1157
- exports.taprootListToTree = taprootListToTree;
1158
- function checkTaprootScript(script, internalPubKey, allowUnknownOutputs = false) {
1159
- const out = exports.OutScript.decode(script);
1160
- if (out.type === 'unknown' && allowUnknownOutputs)
1161
- return;
1162
- if (!['tr_ns', 'tr_ms'].includes(out.type))
1163
- throw new Error(`P2TR: invalid leaf script=${out.type}`);
1164
- const outms = out;
1165
- if (!allowUnknownOutputs && outms.pubkeys) {
1166
- for (const p of outms.pubkeys) {
1167
- if (P.equalBytes(p, exports.TAPROOT_UNSPENDABLE_KEY))
1168
- throw new Error('Unspendable taproot key in leaf script');
1169
- // It's likely a mistake at this point:
1170
- // 1. p2tr(A, p2tr_ns(2, [A, B])) == p2tr(A, p2tr_pk(B)) (A or B key)
1171
- // but will take more space and fees.
1172
- // 2. For multi-sig p2tr(A, p2tr_ns(2, [A, B, C])) it's probably a security issue:
1173
- // User creates 2 of 3 multisig of keys [A, B, C],
1174
- // but key A always can spend whole output without signatures from other keys.
1175
- // p2tr(A, p2tr_ns(2, [B, C, D])) is ok: A or (B and C) or (B and D) or (C and D)
1176
- if (P.equalBytes(p, internalPubKey)) {
1177
- throw new Error('Using P2TR with leaf script with same key as internal key is not supported');
1178
- }
1179
- }
1180
- }
1181
- }
1182
- function taprootHashTree(tree, internalPubKey, allowUnknownOutputs = false) {
1183
- if (!tree)
1184
- throw new Error('taprootHashTree: empty tree');
1185
- if (Array.isArray(tree) && tree.length === 1)
1186
- tree = tree[0];
1187
- // Terminal node (leaf)
1188
- if (!Array.isArray(tree)) {
1189
- const { leafVersion: version, script: leafScript } = tree;
1190
- // Earliest tree walk where we can validate tapScripts
1191
- if (tree.tapLeafScript || (tree.tapMerkleRoot && !P.equalBytes(tree.tapMerkleRoot, P.EMPTY)))
1192
- throw new Error('P2TR: tapRoot leafScript cannot have tree');
1193
- const script = typeof leafScript === 'string' ? base_1.hex.decode(leafScript) : leafScript;
1194
- if (!isBytes(script))
1195
- throw new Error(`checkScript: wrong script type=${script}`);
1196
- checkTaprootScript(script, internalPubKey, allowUnknownOutputs);
1197
- return {
1198
- type: 'leaf',
1199
- version,
1200
- script,
1201
- hash: (0, exports.tapLeafHash)(script, version),
1202
- };
1203
- }
1204
- // If tree / branch is not binary tree, convert it
1205
- if (tree.length !== 2)
1206
- tree = taprootListToTree(tree);
1207
- if (tree.length !== 2)
1208
- throw new Error('hashTree: non binary tree!');
1209
- // branch
1210
- // Both nodes should exist
1211
- const left = taprootHashTree(tree[0], internalPubKey, allowUnknownOutputs);
1212
- const right = taprootHashTree(tree[1], internalPubKey, allowUnknownOutputs);
1213
- // We cannot swap left/right here, since it will change structure of tree
1214
- let [lH, rH] = [left.hash, right.hash];
1215
- if (_cmpBytes(rH, lH) === -1)
1216
- [lH, rH] = [rH, lH];
1217
- return { type: 'branch', left, right, hash: secp256k1_1.schnorr.utils.taggedHash('TapBranch', lH, rH) };
1218
- }
1219
- function taprootAddPath(tree, path = []) {
1220
- if (!tree)
1221
- throw new Error(`taprootAddPath: empty tree`);
1222
- if (tree.type === 'leaf')
1223
- return { ...tree, path };
1224
- if (tree.type !== 'branch')
1225
- throw new Error(`taprootAddPath: wrong type=${tree}`);
1226
- return {
1227
- ...tree,
1228
- path,
1229
- // Left element has right hash in path and otherwise
1230
- left: taprootAddPath(tree.left, [tree.right.hash, ...path]),
1231
- right: taprootAddPath(tree.right, [tree.left.hash, ...path]),
1232
- };
1233
- }
1234
- function taprootWalkTree(tree) {
1235
- if (!tree)
1236
- throw new Error(`taprootAddPath: empty tree`);
1237
- if (tree.type === 'leaf')
1238
- return [tree];
1239
- if (tree.type !== 'branch')
1240
- throw new Error(`taprootWalkTree: wrong type=${tree}`);
1241
- return [...taprootWalkTree(tree.left), ...taprootWalkTree(tree.right)];
1242
- }
1243
- // Another stupid decision, where lack of standard affects security.
1244
- // Multisig needs to be generated with some key.
1245
- // We are using approach from BIP 341/bitcoinjs-lib: SHA256(uncompressedDER(SECP256K1_GENERATOR_POINT))
1246
- // It is possible to switch SECP256K1_GENERATOR_POINT with some random point;
1247
- // but it's too complex to prove.
1248
- // Also used by bitcoin-core and bitcoinjs-lib
1249
- exports.TAPROOT_UNSPENDABLE_KEY = (0, sha256_1.sha256)(ProjPoint.BASE.toRawBytes(false));
1250
- // Works as key OR tree.
1251
- // If we only have tree, need to add unspendable key, otherwise
1252
- // complex multisig wallet can be spent by owner of key only. See TAPROOT_UNSPENDABLE_KEY
1253
- function p2tr(internalPubKey, tree, network = exports.NETWORK, allowUnknownOutputs = false) {
1254
- // Unspendable
1255
- if (!internalPubKey && !tree)
1256
- throw new Error('p2tr: should have pubKey or scriptTree (or both)');
1257
- const pubKey = typeof internalPubKey === 'string'
1258
- ? base_1.hex.decode(internalPubKey)
1259
- : internalPubKey || exports.TAPROOT_UNSPENDABLE_KEY;
1260
- if (!isValidPubkey(pubKey, PubT.schnorr))
1261
- throw new Error('p2tr: non-schnorr pubkey');
1262
- let hashedTree = tree
1263
- ? taprootAddPath(taprootHashTree(tree, pubKey, allowUnknownOutputs))
1264
- : undefined;
1265
- const tapMerkleRoot = hashedTree ? hashedTree.hash : undefined;
1266
- const [tweakedPubkey, parity] = taprootTweakPubkey(pubKey, tapMerkleRoot || P.EMPTY);
1267
- let leaves;
1268
- if (hashedTree) {
1269
- leaves = taprootWalkTree(hashedTree).map((l) => ({
1270
- ...l,
1271
- controlBlock: exports.TaprootControlBlock.encode({
1272
- version: (l.version || exports.TAP_LEAF_VERSION) + parity,
1273
- internalKey: pubKey,
1274
- merklePath: l.path,
1275
- }),
1276
- }));
1277
- }
1278
- let tapLeafScript;
1279
- if (leaves) {
1280
- tapLeafScript = leaves.map((l) => [
1281
- exports.TaprootControlBlock.decode(l.controlBlock),
1282
- concat(l.script, new Uint8Array([l.version || exports.TAP_LEAF_VERSION])),
1283
- ]);
1284
- }
1285
- const res = {
1286
- type: 'tr',
1287
- script: exports.OutScript.encode({ type: 'tr', pubkey: tweakedPubkey }),
1288
- address: Address(network).encode({ type: 'tr', pubkey: tweakedPubkey }),
1289
- // For tests
1290
- tweakedPubkey,
1291
- // PSBT stuff
1292
- tapInternalKey: pubKey,
1293
- };
1294
- // Just in case someone would want to select a specific script
1295
- if (leaves)
1296
- res.leaves = leaves;
1297
- if (tapLeafScript)
1298
- res.tapLeafScript = tapLeafScript;
1299
- if (tapMerkleRoot)
1300
- res.tapMerkleRoot = tapMerkleRoot;
1301
- return res;
1302
- }
1303
- exports.p2tr = p2tr;
1304
- const OutTRNS = {
1305
- encode(from) {
1306
- const last = from.length - 1;
1307
- if (from[last] !== 'CHECKSIG')
1308
- return;
1309
- const pubkeys = [];
1310
- // On error return, since it can be different script
1311
- for (let i = 0; i < last; i++) {
1312
- const elm = from[i];
1313
- if (i & 1) {
1314
- if (elm !== 'CHECKSIGVERIFY' || i === last - 1)
1315
- return;
1316
- continue;
1317
- }
1318
- if (!isBytes(elm))
1319
- return;
1320
- pubkeys.push(elm);
1321
- }
1322
- return { type: 'tr_ns', pubkeys };
1323
- },
1324
- decode: (to) => {
1325
- if (to.type !== 'tr_ns')
1326
- return;
1327
- const out = [];
1328
- for (let i = 0; i < to.pubkeys.length - 1; i++)
1329
- out.push(to.pubkeys[i], 'CHECKSIGVERIFY');
1330
- out.push(to.pubkeys[to.pubkeys.length - 1], 'CHECKSIG');
1331
- return out;
1332
- },
1333
- };
1334
- // Returns all combinations of size M from lst
1335
- function combinations(m, list) {
1336
- const res = [];
1337
- if (!Array.isArray(list))
1338
- throw new Error('combinations: lst arg should be array');
1339
- const n = list.length;
1340
- if (m > n)
1341
- throw new Error('combinations: m > lst.length, no combinations possible');
1342
- /*
1343
- Basically works as M nested loops like:
1344
- for (;idx[0]<lst.length;idx[0]++) for (idx[1]=idx[0]+1;idx[1]<lst.length;idx[1]++)
1345
- but since we cannot create nested loops dynamically, we unroll it to a single loop
1346
- */
1347
- const idx = Array.from({ length: m }, (_, i) => i);
1348
- const last = idx.length - 1;
1349
- main: for (;;) {
1350
- res.push(idx.map((i) => list[i]));
1351
- idx[last] += 1;
1352
- let i = last;
1353
- // Propagate increment
1354
- // idx[i] cannot be bigger than n-m+i, otherwise last elements in right part will overflow
1355
- for (; i >= 0 && idx[i] > n - m + i; i--) {
1356
- idx[i] = 0;
1357
- // Overflow in idx[0], break
1358
- if (i === 0)
1359
- break main;
1360
- idx[i - 1] += 1;
1361
- }
1362
- // Propagate: idx[i+1] = idx[idx]+1
1363
- for (i += 1; i < idx.length; i++)
1364
- idx[i] = idx[i - 1] + 1;
1365
- }
1366
- return res;
1367
- }
1368
- exports.combinations = combinations;
1369
- /**
1370
- * M-of-N multi-leaf wallet via p2tr_ns. If m == n, single script is emitted.
1371
- * Takes O(n^2) if m != n. 99-of-100 is ok, 5-of-100 is not.
1372
- * `2-of-[A,B,C] => [A,B] | [A,C] | [B,C]`
1373
- */
1374
- const p2tr_ns = (m, pubkeys, allowSamePubkeys = false) => {
1375
- if (!allowSamePubkeys)
1376
- uniqPubkey(pubkeys);
1377
- return combinations(m, pubkeys).map((i) => ({
1378
- type: 'tr_ns',
1379
- script: exports.OutScript.encode({ type: 'tr_ns', pubkeys: i }),
1380
- }));
1381
- };
1382
- exports.p2tr_ns = p2tr_ns;
1383
- // Taproot public key (case of p2tr_ns)
1384
- const p2tr_pk = (pubkey) => (0, exports.p2tr_ns)(1, [pubkey], undefined)[0];
1385
- exports.p2tr_pk = p2tr_pk;
1386
- const OutTRMS = {
1387
- encode(from) {
1388
- const last = from.length - 1;
1389
- if (from[last] !== 'NUMEQUAL' || from[1] !== 'CHECKSIG')
1390
- return;
1391
- const pubkeys = [];
1392
- const m = OpToNum(from[last - 1]);
1393
- if (typeof m !== 'number')
1394
- return;
1395
- for (let i = 0; i < last - 1; i++) {
1396
- const elm = from[i];
1397
- if (i & 1) {
1398
- if (elm !== (i === 1 ? 'CHECKSIG' : 'CHECKSIGADD'))
1399
- throw new Error('OutScript.encode/tr_ms: wrong element');
1400
- continue;
1401
- }
1402
- if (!isBytes(elm))
1403
- throw new Error('OutScript.encode/tr_ms: wrong key element');
1404
- pubkeys.push(elm);
1405
- }
1406
- return { type: 'tr_ms', pubkeys, m };
1407
- },
1408
- decode: (to) => {
1409
- if (to.type !== 'tr_ms')
1410
- return;
1411
- const out = [to.pubkeys[0], 'CHECKSIG'];
1412
- for (let i = 1; i < to.pubkeys.length; i++)
1413
- out.push(to.pubkeys[i], 'CHECKSIGADD');
1414
- out.push(to.m, 'NUMEQUAL');
1415
- return out;
1416
- },
1417
- };
1418
- function p2tr_ms(m, pubkeys, allowSamePubkeys = false) {
1419
- if (!allowSamePubkeys)
1420
- uniqPubkey(pubkeys);
1421
- return {
1422
- type: 'tr_ms',
1423
- script: exports.OutScript.encode({ type: 'tr_ms', pubkeys, m }),
1424
- };
1425
- }
1426
- exports.p2tr_ms = p2tr_ms;
1427
- const OutUnknown = {
1428
- encode(from) {
1429
- return { type: 'unknown', script: exports.Script.encode(from) };
1430
- },
1431
- decode: (to) => to.type === 'unknown' ? exports.Script.decode(to.script) : undefined,
1432
- };
1433
- // /Payments
1434
- const OutScripts = [
1435
- OutPK,
1436
- OutPKH,
1437
- OutSH,
1438
- OutWSH,
1439
- OutWPKH,
1440
- OutMS,
1441
- OutTR,
1442
- OutTRNS,
1443
- OutTRMS,
1444
- OutUnknown,
1445
- ];
1446
- // TODO: we can support user supplied output scripts now
1447
- // - addOutScript
1448
- // - removeOutScript
1449
- // - We can do that as log we modify array in-place
1450
- // - Actually is very hard, since there is sign/finalize logic
1451
- const _OutScript = P.apply(exports.Script, P.coders.match(OutScripts));
1452
- // We can validate this once, because of packed & coders
1453
- exports.OutScript = P.validate(_OutScript, (i) => {
1454
- if (i.type === 'pk' && !isValidPubkey(i.pubkey, PubT.ecdsa))
1455
- throw new Error('OutScript/pk: wrong key');
1456
- if ((i.type === 'pkh' || i.type === 'sh' || i.type === 'wpkh') &&
1457
- (!isBytes(i.hash) || i.hash.length !== 20))
1458
- throw new Error(`OutScript/${i.type}: wrong hash`);
1459
- if (i.type === 'wsh' && (!isBytes(i.hash) || i.hash.length !== 32))
1460
- throw new Error(`OutScript/wsh: wrong hash`);
1461
- if (i.type === 'tr' && (!isBytes(i.pubkey) || !isValidPubkey(i.pubkey, PubT.schnorr)))
1462
- throw new Error('OutScript/tr: wrong taproot public key');
1463
- if (i.type === 'ms' || i.type === 'tr_ns' || i.type === 'tr_ms')
1464
- if (!Array.isArray(i.pubkeys))
1465
- throw new Error('OutScript/multisig: wrong pubkeys array');
1466
- if (i.type === 'ms') {
1467
- const n = i.pubkeys.length;
1468
- for (const p of i.pubkeys)
1469
- if (!isValidPubkey(p, PubT.ecdsa))
1470
- throw new Error('OutScript/multisig: wrong pubkey');
1471
- if (i.m <= 0 || n > 16 || i.m > n)
1472
- throw new Error('OutScript/multisig: invalid params');
1473
- }
1474
- if (i.type === 'tr_ns' || i.type === 'tr_ms') {
1475
- for (const p of i.pubkeys)
1476
- if (!isValidPubkey(p, PubT.schnorr))
1477
- throw new Error(`OutScript/${i.type}: wrong pubkey`);
1478
- }
1479
- if (i.type === 'tr_ms') {
1480
- const n = i.pubkeys.length;
1481
- if (i.m <= 0 || n > 999 || i.m > n)
1482
- throw new Error('OutScript/tr_ms: invalid params');
1483
- }
1484
- return i;
1485
- });
1486
- // Address
1487
- function validateWitness(version, data) {
1488
- if (data.length < 2 || data.length > 40)
1489
- throw new Error('Witness: invalid length');
1490
- if (version > 16)
1491
- throw new Error('Witness: invalid version');
1492
- if (version === 0 && !(data.length === 20 || data.length === 32))
1493
- throw new Error('Witness: invalid length for version');
1494
- }
1495
- function programToWitness(version, data, network = exports.NETWORK) {
1496
- validateWitness(version, data);
1497
- const coder = version === 0 ? base_1.bech32 : base_1.bech32m;
1498
- return coder.encode(network.bech32, [version].concat(coder.toWords(data)));
1499
- }
1500
- exports.programToWitness = programToWitness;
1501
- function formatKey(hashed, prefix) {
1502
- return exports.base58check.encode(concat(Uint8Array.from(prefix), hashed));
1503
- }
1504
- function WIF(network = exports.NETWORK) {
1505
- return {
1506
- encode(privKey) {
1507
- const compressed = concat(privKey, new Uint8Array([0x01]));
1508
- return formatKey(compressed.subarray(0, 33), [network.wif]);
1509
- },
1510
- decode(wif) {
1511
- let parsed = exports.base58check.decode(wif);
1512
- if (parsed[0] !== network.wif)
1513
- throw new Error('Wrong WIF prefix');
1514
- parsed = parsed.subarray(1);
1515
- // Check what it is. Compressed flag?
1516
- if (parsed.length !== 33)
1517
- throw new Error('Wrong WIF length');
1518
- if (parsed[32] !== 0x01)
1519
- throw new Error('Wrong WIF postfix');
1520
- return parsed.subarray(0, -1);
1521
- },
1522
- };
1523
- }
1524
- exports.WIF = WIF;
1525
- // Returns OutType, which can be used to create outscript
1526
- function Address(network = exports.NETWORK) {
1527
- return {
1528
- encode(from) {
1529
- const { type } = from;
1530
- if (type === 'wpkh')
1531
- return programToWitness(0, from.hash, network);
1532
- else if (type === 'wsh')
1533
- return programToWitness(0, from.hash, network);
1534
- else if (type === 'tr')
1535
- return programToWitness(1, from.pubkey, network);
1536
- else if (type === 'pkh')
1537
- return formatKey(from.hash, [network.pubKeyHash]);
1538
- else if (type === 'sh')
1539
- return formatKey(from.hash, [network.scriptHash]);
1540
- throw new Error(`Unknown address type=${type}`);
1541
- },
1542
- decode(address) {
1543
- if (address.length < 14 || address.length > 74)
1544
- throw new Error('Invalid address length');
1545
- // Bech32
1546
- if (network.bech32 && address.toLowerCase().startsWith(network.bech32)) {
1547
- let res;
1548
- try {
1549
- res = base_1.bech32.decode(address);
1550
- if (res.words[0] !== 0)
1551
- throw new Error(`bech32: wrong version=${res.words[0]}`);
1552
- }
1553
- catch (_) {
1554
- // Starting from version 1 it is decoded as bech32m
1555
- res = base_1.bech32m.decode(address);
1556
- if (res.words[0] === 0)
1557
- throw new Error(`bech32m: wrong version=${res.words[0]}`);
1558
- }
1559
- if (res.prefix !== network.bech32)
1560
- throw new Error(`wrong bech32 prefix=${res.prefix}`);
1561
- const [version, ...program] = res.words;
1562
- const data = base_1.bech32.fromWords(program);
1563
- validateWitness(version, data);
1564
- if (version === 0 && data.length === 32)
1565
- return { type: 'wsh', hash: data };
1566
- else if (version === 0 && data.length === 20)
1567
- return { type: 'wpkh', hash: data };
1568
- else if (version === 1 && data.length === 32)
1569
- return { type: 'tr', pubkey: data };
1570
- else
1571
- throw new Error('Unknown witness program');
1572
- }
1573
- const data = exports.base58check.decode(address);
1574
- if (data.length !== 21)
1575
- throw new Error('Invalid base58 address');
1576
- // Pay To Public Key Hash
1577
- if (data[0] === network.pubKeyHash) {
1578
- return { type: 'pkh', hash: data.slice(1) };
1579
- }
1580
- else if (data[0] === network.scriptHash) {
1581
- return {
1582
- type: 'sh',
1583
- hash: data.slice(1),
1584
- };
1585
- }
1586
- throw new Error(`Invalid address prefix=${data[0]}`);
1587
- },
1588
- };
1589
- }
1590
- exports.Address = Address;
1591
- // /Address
1592
- /**
1593
- * Internal, exported only for backwards-compat. Use `SigHash` instead.
1594
- * @deprecated
1595
- */
1596
- var SignatureHash;
1597
- (function (SignatureHash) {
1598
- SignatureHash[SignatureHash["DEFAULT"] = 0] = "DEFAULT";
1599
- SignatureHash[SignatureHash["ALL"] = 1] = "ALL";
1600
- SignatureHash[SignatureHash["NONE"] = 2] = "NONE";
1601
- SignatureHash[SignatureHash["SINGLE"] = 3] = "SINGLE";
1602
- SignatureHash[SignatureHash["ANYONECANPAY"] = 128] = "ANYONECANPAY";
1603
- })(SignatureHash || (exports.SignatureHash = SignatureHash = {}));
1604
- var SigHash;
1605
- (function (SigHash) {
1606
- SigHash[SigHash["DEFAULT"] = 0] = "DEFAULT";
1607
- SigHash[SigHash["ALL"] = 1] = "ALL";
1608
- SigHash[SigHash["NONE"] = 2] = "NONE";
1609
- SigHash[SigHash["SINGLE"] = 3] = "SINGLE";
1610
- SigHash[SigHash["DEFAULT_ANYONECANPAY"] = 128] = "DEFAULT_ANYONECANPAY";
1611
- SigHash[SigHash["ALL_ANYONECANPAY"] = 129] = "ALL_ANYONECANPAY";
1612
- SigHash[SigHash["NONE_ANYONECANPAY"] = 130] = "NONE_ANYONECANPAY";
1613
- SigHash[SigHash["SINGLE_ANYONECANPAY"] = 131] = "SINGLE_ANYONECANPAY";
1614
- })(SigHash || (exports.SigHash = SigHash = {}));
1615
- function validateSigHash(s) {
1616
- if (typeof s !== 'number' || typeof SigHash[s] !== 'string')
1617
- throw new Error(`Invalid SigHash=${s}`);
1618
- return s;
1619
- }
1620
- function unpackSighash(hashType) {
1621
- const masked = hashType & 0b0011111;
1622
- return {
1623
- isAny: !!(hashType & SignatureHash.ANYONECANPAY),
1624
- isNone: masked === SignatureHash.NONE,
1625
- isSingle: masked === SignatureHash.SINGLE,
1626
- };
1627
- }
1628
- const _sortPubkeys = (pubkeys) => Array.from(pubkeys).sort(_cmpBytes);
1629
- exports._sortPubkeys = _sortPubkeys;
1630
- // Force check index/txid/sequence
1631
- function inputBeforeSign(i) {
1632
- if (i.txid === undefined || i.index === undefined)
1633
- throw new Error('Transaction/input: txid and index required');
1634
- return {
1635
- txid: i.txid,
1636
- index: i.index,
1637
- sequence: def(i.sequence, exports.DEFAULT_SEQUENCE),
1638
- finalScriptSig: def(i.finalScriptSig, P.EMPTY),
1639
- };
1640
- }
1641
- function cleanFinalInput(i) {
1642
- for (const _k in i) {
1643
- const k = _k;
1644
- if (!PSBTInputFinalKeys.includes(k))
1645
- delete i[k];
1646
- }
1647
- }
1648
- // Force check amount/script
1649
- function outputBeforeSign(i) {
1650
- if (i.script === undefined || i.amount === undefined)
1651
- throw new Error('Transaction/output: script and amount required');
1652
- return { script: i.script, amount: i.amount };
1653
- }
1654
- exports.TAP_LEAF_VERSION = 0xc0;
1655
- const tapLeafHash = (script, version = exports.TAP_LEAF_VERSION) => secp256k1_1.schnorr.utils.taggedHash('TapLeaf', new Uint8Array([version]), exports.VarBytes.encode(script));
1656
- exports.tapLeafHash = tapLeafHash;
1657
- function getTaprootKeys(privKey, pubKey, internalKey, merkleRoot = P.EMPTY) {
1658
- if (P.equalBytes(internalKey, pubKey)) {
1659
- privKey = taprootTweakPrivKey(privKey, merkleRoot);
1660
- pubKey = secp256k1_1.schnorr.getPublicKey(privKey);
1661
- }
1662
- return { privKey, pubKey };
1663
- }
1664
- const toStr = {}.toString;
1665
- function validateOpts(opts) {
1666
- if (opts !== undefined && toStr.call(opts) !== '[object Object]')
1667
- throw new Error(`Wrong object type for transaction options: ${opts}`);
1668
- const _opts = {
1669
- ...opts,
1670
- // Defaults
1671
- version: def(opts.version, exports.DEFAULT_VERSION),
1672
- lockTime: def(opts.lockTime, 0),
1673
- PSBTVersion: def(opts.PSBTVersion, 0),
1674
- };
1675
- if (typeof _opts.allowUnknowInput !== 'undefined')
1676
- opts.allowUnknownInputs = _opts.allowUnknowInput;
1677
- if (typeof _opts.allowUnknowOutput !== 'undefined')
1678
- opts.allowUnknownOutputs = _opts.allowUnknowOutput;
1679
- // 0 and -1 happens in tests
1680
- if (![-1, 0, 1, 2].includes(_opts.version))
1681
- throw new Error(`Unknown version: ${_opts.version}`);
1682
- if (typeof _opts.lockTime !== 'number')
1683
- throw new Error('Transaction lock time should be number');
1684
- P.U32LE.encode(_opts.lockTime); // Additional range checks that lockTime
1685
- // There is no PSBT v1, and any new version will probably have fields which we don't know how to parse, which
1686
- // can lead to constructing broken transactions
1687
- if (_opts.PSBTVersion !== 0 && _opts.PSBTVersion !== 2)
1688
- throw new Error(`Unknown PSBT version ${_opts.PSBTVersion}`);
1689
- // Flags
1690
- for (const k of [
1691
- 'allowUnknownOutputs',
1692
- 'allowUnknownInputs',
1693
- 'disableScriptCheck',
1694
- 'bip174jsCompat',
1695
- 'allowLegacyWitnessUtxo',
1696
- 'lowR',
1697
- ]) {
1698
- const v = _opts[k];
1699
- if (v === undefined)
1700
- continue; // optional
1701
- if (typeof v !== 'boolean')
1702
- throw new Error(`Transation options wrong type: ${k}=${v} (${typeof v})`);
1703
- }
1704
- return Object.freeze(_opts);
1705
- }
1706
- // Normalizes input
1707
- function getPrevOut(input) {
1708
- if (input.nonWitnessUtxo) {
1709
- if (input.index === undefined)
1710
- throw new Error('Unknown input index');
1711
- return input.nonWitnessUtxo.outputs[input.index];
1712
- }
1713
- else if (input.witnessUtxo)
1714
- return input.witnessUtxo;
1715
- else
1716
- throw new Error('Cannot find previous output info');
1717
- }
1718
- function normalizeInput(i, cur, allowedFields, disableScriptCheck = false) {
1719
- let { nonWitnessUtxo, txid } = i;
1720
- // String support for common fields. We usually prefer Uint8Array to avoid errors
1721
- // like hex looking string accidentally passed, however, in case of nonWitnessUtxo
1722
- // it is better to expect string, since constructing this complex object will be
1723
- // difficult for user
1724
- if (typeof nonWitnessUtxo === 'string')
1725
- nonWitnessUtxo = base_1.hex.decode(nonWitnessUtxo);
1726
- if (isBytes(nonWitnessUtxo))
1727
- nonWitnessUtxo = exports.RawTx.decode(nonWitnessUtxo);
1728
- if (!('nonWitnessUtxo' in i) && nonWitnessUtxo === undefined)
1729
- nonWitnessUtxo = cur?.nonWitnessUtxo;
1730
- if (typeof txid === 'string')
1731
- txid = base_1.hex.decode(txid);
1732
- // TODO: if we have nonWitnessUtxo, we can extract txId from here
1733
- if (txid === undefined)
1734
- txid = cur?.txid;
1735
- let res = { ...cur, ...i, nonWitnessUtxo, txid };
1736
- if (!('nonWitnessUtxo' in i) && res.nonWitnessUtxo === undefined)
1737
- delete res.nonWitnessUtxo;
1738
- if (res.sequence === undefined)
1739
- res.sequence = exports.DEFAULT_SEQUENCE;
1740
- if (res.tapMerkleRoot === null)
1741
- delete res.tapMerkleRoot;
1742
- res = mergeKeyMap(PSBTInput, res, cur, allowedFields);
1743
- PSBTInputCoder.encode(res); // Validates that everything is correct at this point
1744
- let prevOut;
1745
- if (res.nonWitnessUtxo && res.index !== undefined)
1746
- prevOut = res.nonWitnessUtxo.outputs[res.index];
1747
- else if (res.witnessUtxo)
1748
- prevOut = res.witnessUtxo;
1749
- if (prevOut && !disableScriptCheck)
1750
- checkScript(prevOut && prevOut.script, res.redeemScript, res.witnessScript);
1751
- return res;
1752
- }
1753
- function getInputType(input, allowLegacyWitnessUtxo = false) {
1754
- let txType = 'legacy';
1755
- let defaultSighash = SignatureHash.ALL;
1756
- const prevOut = getPrevOut(input);
1757
- const first = exports.OutScript.decode(prevOut.script);
1758
- let type = first.type;
1759
- let cur = first;
1760
- const stack = [first];
1761
- if (first.type === 'tr') {
1762
- defaultSighash = SignatureHash.DEFAULT;
1763
- return {
1764
- txType: 'taproot',
1765
- type: 'tr',
1766
- last: first,
1767
- lastScript: prevOut.script,
1768
- defaultSighash,
1769
- sighash: input.sighashType || defaultSighash,
1770
- };
1771
- }
1772
- else {
1773
- if (first.type === 'wpkh' || first.type === 'wsh')
1774
- txType = 'segwit';
1775
- if (first.type === 'sh') {
1776
- if (!input.redeemScript)
1777
- throw new Error('inputType: sh without redeemScript');
1778
- let child = exports.OutScript.decode(input.redeemScript);
1779
- if (child.type === 'wpkh' || child.type === 'wsh')
1780
- txType = 'segwit';
1781
- stack.push(child);
1782
- cur = child;
1783
- type += `-${child.type}`;
1784
- }
1785
- // wsh can be inside sh
1786
- if (cur.type === 'wsh') {
1787
- if (!input.witnessScript)
1788
- throw new Error('inputType: wsh without witnessScript');
1789
- let child = exports.OutScript.decode(input.witnessScript);
1790
- if (child.type === 'wsh')
1791
- txType = 'segwit';
1792
- stack.push(child);
1793
- cur = child;
1794
- type += `-${child.type}`;
1795
- }
1796
- const last = stack[stack.length - 1];
1797
- if (last.type === 'sh' || last.type === 'wsh')
1798
- throw new Error('inputType: sh/wsh cannot be terminal type');
1799
- const lastScript = exports.OutScript.encode(last);
1800
- const res = {
1801
- type,
1802
- txType,
1803
- last,
1804
- lastScript,
1805
- defaultSighash,
1806
- sighash: input.sighashType || defaultSighash,
1807
- };
1808
- if (txType === 'legacy' && !allowLegacyWitnessUtxo && !input.nonWitnessUtxo) {
1809
- throw new Error(`Transaction/sign: legacy input without nonWitnessUtxo, can result in attack that forces paying higher fees. Pass allowLegacyWitnessUtxo=true, if you sure`);
1810
- }
1811
- return res;
1812
- }
1813
- }
1814
- const toVsize = (weight) => Math.ceil(weight / 4);
1815
- class Transaction {
1816
- constructor(opts = {}) {
1817
- this.global = {};
1818
- this.inputs = []; // use getInput()
1819
- this.outputs = []; // use getOutput()
1820
- const _opts = (this.opts = validateOpts(opts));
1821
- // Merge with global structure of PSBTv2
1822
- if (_opts.lockTime !== exports.DEFAULT_LOCKTIME)
1823
- this.global.fallbackLocktime = _opts.lockTime;
1824
- this.global.txVersion = _opts.version;
1825
- }
1826
- // Import
1827
- static fromRaw(raw, opts = {}) {
1828
- const parsed = exports.RawTx.decode(raw);
1829
- const tx = new Transaction({ ...opts, version: parsed.version, lockTime: parsed.lockTime });
1830
- for (const o of parsed.outputs)
1831
- tx.addOutput(o);
1832
- tx.outputs = parsed.outputs;
1833
- tx.inputs = parsed.inputs;
1834
- if (parsed.witnesses) {
1835
- for (let i = 0; i < parsed.witnesses.length; i++)
1836
- tx.inputs[i].finalScriptWitness = parsed.witnesses[i];
1837
- }
1838
- return tx;
1839
- }
1840
- // PSBT
1841
- static fromPSBT(psbt, opts = {}) {
1842
- let parsed;
1843
- try {
1844
- parsed = exports.RawPSBTV0.decode(psbt);
1845
- }
1846
- catch (e0) {
1847
- try {
1848
- parsed = exports.RawPSBTV2.decode(psbt);
1849
- }
1850
- catch (e2) {
1851
- // Throw error for v0 parsing, since it popular, otherwise it would be shadowed by v2 error
1852
- throw e0;
1853
- }
1854
- }
1855
- const PSBTVersion = parsed.global.version || 0;
1856
- if (PSBTVersion !== 0 && PSBTVersion !== 2)
1857
- throw new Error(`Wrong PSBT version=${PSBTVersion}`);
1858
- const unsigned = parsed.global.unsignedTx;
1859
- const version = PSBTVersion === 0 ? unsigned?.version : parsed.global.txVersion;
1860
- const lockTime = PSBTVersion === 0 ? unsigned?.lockTime : parsed.global.fallbackLocktime;
1861
- const tx = new Transaction({ ...opts, version, lockTime, PSBTVersion });
1862
- // We need slice here, because otherwise
1863
- const inputCount = PSBTVersion === 0 ? unsigned?.inputs.length : parsed.global.inputCount;
1864
- tx.inputs = parsed.inputs.slice(0, inputCount).map((i, j) => ({
1865
- finalScriptSig: P.EMPTY,
1866
- ...parsed.global.unsignedTx?.inputs[j],
1867
- ...i,
1868
- }));
1869
- const outputCount = PSBTVersion === 0 ? unsigned?.outputs.length : parsed.global.outputCount;
1870
- tx.outputs = parsed.outputs.slice(0, outputCount).map((i, j) => ({
1871
- ...i,
1872
- ...parsed.global.unsignedTx?.outputs[j],
1873
- }));
1874
- tx.global = { ...parsed.global, txVersion: version }; // just in case proprietary/unknown fields
1875
- if (lockTime !== exports.DEFAULT_LOCKTIME)
1876
- tx.global.fallbackLocktime = lockTime;
1877
- return tx;
1878
- }
1879
- toPSBT(PSBTVersion = this.opts.PSBTVersion) {
1880
- if (PSBTVersion !== 0 && PSBTVersion !== 2)
1881
- throw new Error(`Wrong PSBT version=${PSBTVersion}`);
1882
- const inputs = this.inputs.map((i) => cleanPSBTFields(PSBTVersion, PSBTInput, i));
1883
- for (const inp of inputs) {
1884
- // Don't serialize empty fields
1885
- if (inp.partialSig && !inp.partialSig.length)
1886
- delete inp.partialSig;
1887
- if (inp.finalScriptSig && !inp.finalScriptSig.length)
1888
- delete inp.finalScriptSig;
1889
- if (inp.finalScriptWitness && !inp.finalScriptWitness.length)
1890
- delete inp.finalScriptWitness;
1891
- }
1892
- const outputs = this.outputs.map((i) => cleanPSBTFields(PSBTVersion, PSBTOutput, i));
1893
- const global = { ...this.global };
1894
- if (PSBTVersion === 0) {
1895
- global.unsignedTx = exports.RawTx.decode(this.unsignedTx);
1896
- delete global.fallbackLocktime;
1897
- delete global.txVersion;
1898
- }
1899
- else {
1900
- global.version = PSBTVersion;
1901
- global.txVersion = this.version;
1902
- global.inputCount = this.inputs.length;
1903
- global.outputCount = this.outputs.length;
1904
- if (global.fallbackLocktime && global.fallbackLocktime === exports.DEFAULT_LOCKTIME)
1905
- delete global.fallbackLocktime;
1906
- }
1907
- if (this.opts.bip174jsCompat) {
1908
- if (!inputs.length)
1909
- inputs.push({});
1910
- if (!outputs.length)
1911
- outputs.push({});
1912
- }
1913
- return (PSBTVersion === 0 ? exports.RawPSBTV0 : exports.RawPSBTV2).encode({
1914
- global,
1915
- inputs,
1916
- outputs,
1917
- });
1918
- }
1919
- // BIP370 lockTime (https://github.com/bitcoin/bips/blob/master/bip-0370.mediawiki#determining-lock-time)
1920
- get lockTime() {
1921
- let height = exports.DEFAULT_LOCKTIME;
1922
- let heightCnt = 0;
1923
- let time = exports.DEFAULT_LOCKTIME;
1924
- let timeCnt = 0;
1925
- for (const i of this.inputs) {
1926
- if (i.requiredHeightLocktime) {
1927
- height = Math.max(height, i.requiredHeightLocktime);
1928
- heightCnt++;
1929
- }
1930
- if (i.requiredTimeLocktime) {
1931
- time = Math.max(time, i.requiredTimeLocktime);
1932
- timeCnt++;
1933
- }
1934
- }
1935
- if (heightCnt && heightCnt >= timeCnt)
1936
- return height;
1937
- if (time !== exports.DEFAULT_LOCKTIME)
1938
- return time;
1939
- return this.global.fallbackLocktime || exports.DEFAULT_LOCKTIME;
1940
- }
1941
- get version() {
1942
- // Should be not possible
1943
- if (this.global.txVersion === undefined)
1944
- throw new Error('No global.txVersion');
1945
- return this.global.txVersion;
1946
- }
1947
- inputStatus(idx) {
1948
- this.checkInputIdx(idx);
1949
- const input = this.inputs[idx];
1950
- // Finalized
1951
- if (input.finalScriptSig && input.finalScriptSig.length)
1952
- return 'finalized';
1953
- if (input.finalScriptWitness && input.finalScriptWitness.length)
1954
- return 'finalized';
1955
- // Signed taproot
1956
- if (input.tapKeySig)
1957
- return 'signed';
1958
- if (input.tapScriptSig && input.tapScriptSig.length)
1959
- return 'signed';
1960
- // Signed
1961
- if (input.partialSig && input.partialSig.length)
1962
- return 'signed';
1963
- return 'unsigned';
1964
- }
1965
- // Cannot replace unpackSighash, tests rely on very generic implemenetation with signing inputs outside of range
1966
- // We will lose some vectors -> smaller test coverage of preimages (very important!)
1967
- inputSighash(idx) {
1968
- this.checkInputIdx(idx);
1969
- const sighash = getInputType(this.inputs[idx], this.opts.allowLegacyWitnessUtxo).sighash;
1970
- // ALL or DEFAULT -- everything signed
1971
- // NONE -- all inputs + no outputs
1972
- // SINGLE -- all inputs + output with same index
1973
- // ALL + ANYONE -- specific input + all outputs
1974
- // NONE + ANYONE -- specific input + no outputs
1975
- // SINGLE -- specific inputs + output with same index
1976
- const sigOutputs = sighash === SignatureHash.DEFAULT ? SignatureHash.ALL : sighash & 0b11;
1977
- const sigInputs = sighash & SignatureHash.ANYONECANPAY;
1978
- return { sigInputs, sigOutputs };
1979
- }
1980
- // Very nice for debug purposes, but slow. If there is too much inputs/outputs to add, will be quadratic.
1981
- // Some cache will be nice, but there chance to have bugs with cache invalidation
1982
- signStatus() {
1983
- // if addInput or addOutput is not possible, then all inputs or outputs are signed
1984
- let addInput = true, addOutput = true;
1985
- let inputs = [], outputs = [];
1986
- for (let idx = 0; idx < this.inputs.length; idx++) {
1987
- const status = this.inputStatus(idx);
1988
- // Unsigned input doesn't affect anything
1989
- if (status === 'unsigned')
1990
- continue;
1991
- const { sigInputs, sigOutputs } = this.inputSighash(idx);
1992
- // Input type
1993
- if (sigInputs === SignatureHash.ANYONECANPAY)
1994
- inputs.push(idx);
1995
- else
1996
- addInput = false;
1997
- // Output type
1998
- if (sigOutputs === SignatureHash.ALL)
1999
- addOutput = false;
2000
- else if (sigOutputs === SignatureHash.SINGLE)
2001
- outputs.push(idx);
2002
- else if (sigOutputs === SignatureHash.NONE) {
2003
- // Doesn't affect any outputs at all
2004
- }
2005
- else
2006
- throw new Error(`Wrong signature hash output type: ${sigOutputs}`);
2007
- }
2008
- return { addInput, addOutput, inputs, outputs };
2009
- }
2010
- get isFinal() {
2011
- for (let idx = 0; idx < this.inputs.length; idx++)
2012
- if (this.inputStatus(idx) !== 'finalized')
2013
- return false;
2014
- return true;
2015
- }
2016
- // Info utils
2017
- get hasWitnesses() {
2018
- let out = false;
2019
- for (const i of this.inputs)
2020
- if (i.finalScriptWitness && i.finalScriptWitness.length)
2021
- out = true;
2022
- return out;
2023
- }
2024
- // https://en.bitcoin.it/wiki/Weight_units
2025
- get weight() {
2026
- if (!this.isFinal)
2027
- throw new Error('Transaction is not finalized');
2028
- let out = 32;
2029
- // Outputs
2030
- const outputs = this.outputs.map(outputBeforeSign);
2031
- out += 4 * CompactSizeLen.encode(this.outputs.length).length;
2032
- for (const o of outputs)
2033
- out += 32 + 4 * exports.VarBytes.encode(o.script).length;
2034
- // Inputs
2035
- if (this.hasWitnesses)
2036
- out += 2;
2037
- out += 4 * CompactSizeLen.encode(this.inputs.length).length;
2038
- for (const i of this.inputs) {
2039
- out += 160 + 4 * exports.VarBytes.encode(i.finalScriptSig || P.EMPTY).length;
2040
- if (this.hasWitnesses && i.finalScriptWitness)
2041
- out += exports.RawWitness.encode(i.finalScriptWitness).length;
2042
- }
2043
- return out;
2044
- }
2045
- get vsize() {
2046
- return toVsize(this.weight);
2047
- }
2048
- toBytes(withScriptSig = false, withWitness = false) {
2049
- return exports.RawTx.encode({
2050
- version: this.version,
2051
- lockTime: this.lockTime,
2052
- inputs: this.inputs.map(inputBeforeSign).map((i) => ({
2053
- ...i,
2054
- finalScriptSig: (withScriptSig && i.finalScriptSig) || P.EMPTY,
2055
- })),
2056
- outputs: this.outputs.map(outputBeforeSign),
2057
- witnesses: this.inputs.map((i) => i.finalScriptWitness || []),
2058
- segwitFlag: withWitness && this.hasWitnesses,
2059
- });
2060
- }
2061
- get unsignedTx() {
2062
- return this.toBytes(false, false);
2063
- }
2064
- get hex() {
2065
- return base_1.hex.encode(this.toBytes(true, this.hasWitnesses));
2066
- }
2067
- get hash() {
2068
- if (!this.isFinal)
2069
- throw new Error('Transaction is not finalized');
2070
- return base_1.hex.encode(sha256x2(this.toBytes(true)));
2071
- }
2072
- get id() {
2073
- if (!this.isFinal)
2074
- throw new Error('Transaction is not finalized');
2075
- return base_1.hex.encode(sha256x2(this.toBytes(true)).reverse());
2076
- }
2077
- // Input stuff
2078
- checkInputIdx(idx) {
2079
- if (!Number.isSafeInteger(idx) || 0 > idx || idx >= this.inputs.length)
2080
- throw new Error(`Wrong input index=${idx}`);
2081
- }
2082
- getInput(idx) {
2083
- this.checkInputIdx(idx);
2084
- return cloneDeep(this.inputs[idx]);
2085
- }
2086
- get inputsLength() {
2087
- return this.inputs.length;
2088
- }
2089
- // Modification
2090
- addInput(input, _ignoreSignStatus = false) {
2091
- if (!_ignoreSignStatus && !this.signStatus().addInput)
2092
- throw new Error('Tx has signed inputs, cannot add new one');
2093
- this.inputs.push(normalizeInput(input, undefined, undefined, this.opts.disableScriptCheck));
2094
- return this.inputs.length - 1;
2095
- }
2096
- updateInput(idx, input, _ignoreSignStatus = false) {
2097
- this.checkInputIdx(idx);
2098
- let allowedFields = undefined;
2099
- if (!_ignoreSignStatus) {
2100
- const status = this.signStatus();
2101
- if (!status.addInput || status.inputs.includes(idx))
2102
- allowedFields = PSBTInputUnsignedKeys;
2103
- }
2104
- this.inputs[idx] = normalizeInput(input, this.inputs[idx], allowedFields, this.opts.disableScriptCheck);
2105
- }
2106
- // Output stuff
2107
- checkOutputIdx(idx) {
2108
- if (!Number.isSafeInteger(idx) || 0 > idx || idx >= this.outputs.length)
2109
- throw new Error(`Wrong output index=${idx}`);
2110
- }
2111
- getOutput(idx) {
2112
- this.checkOutputIdx(idx);
2113
- return cloneDeep(this.outputs[idx]);
2114
- }
2115
- get outputsLength() {
2116
- return this.outputs.length;
2117
- }
2118
- normalizeOutput(o, cur, allowedFields) {
2119
- let { amount, script } = o;
2120
- if (amount === undefined)
2121
- amount = cur?.amount;
2122
- if (typeof amount !== 'bigint')
2123
- throw new Error('amount must be bigint sats');
2124
- if (typeof script === 'string')
2125
- script = base_1.hex.decode(script);
2126
- if (script === undefined)
2127
- script = cur?.script;
2128
- let res = { ...cur, ...o, amount, script };
2129
- if (res.amount === undefined)
2130
- delete res.amount;
2131
- res = mergeKeyMap(PSBTOutput, res, cur, allowedFields);
2132
- PSBTOutputCoder.encode(res);
2133
- if (res.script &&
2134
- !this.opts.allowUnknownOutputs &&
2135
- exports.OutScript.decode(res.script).type === 'unknown') {
2136
- throw new Error('Transaction/output: unknown output script type, there is a chance that input is unspendable. Pass allowUnknownOutputs=true, if you sure');
2137
- }
2138
- if (!this.opts.disableScriptCheck)
2139
- checkScript(res.script, res.redeemScript, res.witnessScript);
2140
- return res;
2141
- }
2142
- addOutput(o, _ignoreSignStatus = false) {
2143
- if (!_ignoreSignStatus && !this.signStatus().addOutput)
2144
- throw new Error('Tx has signed outputs, cannot add new one');
2145
- this.outputs.push(this.normalizeOutput(o));
2146
- return this.outputs.length - 1;
2147
- }
2148
- updateOutput(idx, output, _ignoreSignStatus = false) {
2149
- this.checkOutputIdx(idx);
2150
- let allowedFields = undefined;
2151
- if (!_ignoreSignStatus) {
2152
- const status = this.signStatus();
2153
- if (!status.addOutput || status.outputs.includes(idx))
2154
- allowedFields = PSBTOutputUnsignedKeys;
2155
- }
2156
- this.outputs[idx] = this.normalizeOutput(output, this.outputs[idx], allowedFields);
2157
- }
2158
- addOutputAddress(address, amount, network = exports.NETWORK) {
2159
- return this.addOutput({ script: exports.OutScript.encode(Address(network).decode(address)), amount });
2160
- }
2161
- // Utils
2162
- get fee() {
2163
- let res = 0n;
2164
- for (const i of this.inputs) {
2165
- const prevOut = getPrevOut(i);
2166
- if (!prevOut)
2167
- throw new Error('Empty input amount');
2168
- res += prevOut.amount;
2169
- }
2170
- const outputs = this.outputs.map(outputBeforeSign);
2171
- for (const o of outputs)
2172
- res -= o.amount;
2173
- return res;
2174
- }
2175
- // Signing
2176
- // Based on https://github.com/bitcoin/bitcoin/blob/5871b5b5ab57a0caf9b7514eb162c491c83281d5/test/functional/test_framework/script.py#L624
2177
- // There is optimization opportunity to re-use hashes for multiple inputs for witness v0/v1,
2178
- // but we are trying to be less complicated for audit purpose for now.
2179
- preimageLegacy(idx, prevOutScript, hashType) {
2180
- const { isAny, isNone, isSingle } = unpackSighash(hashType);
2181
- if (idx < 0 || !Number.isSafeInteger(idx))
2182
- throw new Error(`Invalid input idx=${idx}`);
2183
- if ((isSingle && idx >= this.outputs.length) || idx >= this.inputs.length)
2184
- return P.U256BE.encode(1n);
2185
- prevOutScript = exports.Script.encode(exports.Script.decode(prevOutScript).filter((i) => i !== 'CODESEPARATOR'));
2186
- let inputs = this.inputs
2187
- .map(inputBeforeSign)
2188
- .map((input, inputIdx) => ({
2189
- ...input,
2190
- finalScriptSig: inputIdx === idx ? prevOutScript : P.EMPTY,
2191
- }));
2192
- if (isAny)
2193
- inputs = [inputs[idx]];
2194
- else if (isNone || isSingle) {
2195
- inputs = inputs.map((input, inputIdx) => ({
2196
- ...input,
2197
- sequence: inputIdx === idx ? input.sequence : 0,
2198
- }));
2199
- }
2200
- let outputs = this.outputs.map(outputBeforeSign);
2201
- if (isNone)
2202
- outputs = [];
2203
- else if (isSingle) {
2204
- outputs = outputs.slice(0, idx).fill(EMPTY_OUTPUT).concat([outputs[idx]]);
2205
- }
2206
- const tmpTx = exports.RawTx.encode({
2207
- lockTime: this.lockTime,
2208
- version: this.version,
2209
- segwitFlag: false,
2210
- inputs,
2211
- outputs,
2212
- });
2213
- return sha256x2(tmpTx, P.I32LE.encode(hashType));
2214
- }
2215
- preimageWitnessV0(idx, prevOutScript, hashType, amount) {
2216
- const { isAny, isNone, isSingle } = unpackSighash(hashType);
2217
- let inputHash = EMPTY32;
2218
- let sequenceHash = EMPTY32;
2219
- let outputHash = EMPTY32;
2220
- const inputs = this.inputs.map(inputBeforeSign);
2221
- const outputs = this.outputs.map(outputBeforeSign);
2222
- if (!isAny)
2223
- inputHash = sha256x2(...inputs.map(TxHashIdx.encode));
2224
- if (!isAny && !isSingle && !isNone)
2225
- sequenceHash = sha256x2(...inputs.map((i) => P.U32LE.encode(i.sequence)));
2226
- if (!isSingle && !isNone) {
2227
- outputHash = sha256x2(...outputs.map(exports.RawOutput.encode));
2228
- }
2229
- else if (isSingle && idx < outputs.length)
2230
- outputHash = sha256x2(exports.RawOutput.encode(outputs[idx]));
2231
- const input = inputs[idx];
2232
- return sha256x2(P.I32LE.encode(this.version), inputHash, sequenceHash, P.bytes(32, true).encode(input.txid), P.U32LE.encode(input.index), exports.VarBytes.encode(prevOutScript), P.U64LE.encode(amount), P.U32LE.encode(input.sequence), outputHash, P.U32LE.encode(this.lockTime), P.U32LE.encode(hashType));
2233
- }
2234
- preimageWitnessV1(idx, prevOutScript, hashType, amount, codeSeparator = -1, leafScript, leafVer = 0xc0, annex) {
2235
- if (!Array.isArray(amount) || this.inputs.length !== amount.length)
2236
- throw new Error(`Invalid amounts array=${amount}`);
2237
- if (!Array.isArray(prevOutScript) || this.inputs.length !== prevOutScript.length)
2238
- throw new Error(`Invalid prevOutScript array=${prevOutScript}`);
2239
- const out = [
2240
- P.U8.encode(0),
2241
- P.U8.encode(hashType), // U8 sigHash
2242
- P.I32LE.encode(this.version),
2243
- P.U32LE.encode(this.lockTime),
2244
- ];
2245
- const outType = hashType === SignatureHash.DEFAULT ? SignatureHash.ALL : hashType & 0b11;
2246
- const inType = hashType & SignatureHash.ANYONECANPAY;
2247
- const inputs = this.inputs.map(inputBeforeSign);
2248
- const outputs = this.outputs.map(outputBeforeSign);
2249
- if (inType !== SignatureHash.ANYONECANPAY) {
2250
- out.push(...[
2251
- inputs.map(TxHashIdx.encode),
2252
- amount.map(P.U64LE.encode),
2253
- prevOutScript.map(exports.VarBytes.encode),
2254
- inputs.map((i) => P.U32LE.encode(i.sequence)),
2255
- ].map((i) => (0, sha256_1.sha256)(concat(...i))));
2256
- }
2257
- if (outType === SignatureHash.ALL) {
2258
- out.push((0, sha256_1.sha256)(concat(...outputs.map(exports.RawOutput.encode))));
2259
- }
2260
- const spendType = (annex ? 1 : 0) | (leafScript ? 2 : 0);
2261
- out.push(new Uint8Array([spendType]));
2262
- if (inType === SignatureHash.ANYONECANPAY) {
2263
- const inp = inputs[idx];
2264
- out.push(TxHashIdx.encode(inp), P.U64LE.encode(amount[idx]), exports.VarBytes.encode(prevOutScript[idx]), P.U32LE.encode(inp.sequence));
2265
- }
2266
- else
2267
- out.push(P.U32LE.encode(idx));
2268
- if (spendType & 1)
2269
- out.push((0, sha256_1.sha256)(exports.VarBytes.encode(annex || P.EMPTY)));
2270
- if (outType === SignatureHash.SINGLE)
2271
- out.push(idx < outputs.length ? (0, sha256_1.sha256)(exports.RawOutput.encode(outputs[idx])) : EMPTY32);
2272
- if (leafScript)
2273
- out.push((0, exports.tapLeafHash)(leafScript, leafVer), P.U8.encode(0), P.I32LE.encode(codeSeparator));
2274
- return secp256k1_1.schnorr.utils.taggedHash('TapSighash', ...out);
2275
- }
2276
- // Signer can be privateKey OR instance of bip32 HD stuff
2277
- signIdx(privateKey, idx, allowedSighash, _auxRand) {
2278
- this.checkInputIdx(idx);
2279
- const input = this.inputs[idx];
2280
- const inputType = getInputType(input, this.opts.allowLegacyWitnessUtxo);
2281
- // Handle BIP32 HDKey
2282
- if (!isBytes(privateKey)) {
2283
- if (!input.bip32Derivation || !input.bip32Derivation.length)
2284
- throw new Error('bip32Derivation: empty');
2285
- const signers = input.bip32Derivation
2286
- .filter((i) => i[1].fingerprint == privateKey.fingerprint)
2287
- .map(([pubKey, { path }]) => {
2288
- let s = privateKey;
2289
- for (const i of path)
2290
- s = s.deriveChild(i);
2291
- if (!P.equalBytes(s.publicKey, pubKey))
2292
- throw new Error('bip32Derivation: wrong pubKey');
2293
- if (!s.privateKey)
2294
- throw new Error('bip32Derivation: no privateKey');
2295
- return s;
2296
- });
2297
- if (!signers.length)
2298
- throw new Error(`bip32Derivation: no items with fingerprint=${privateKey.fingerprint}`);
2299
- let signed = false;
2300
- for (const s of signers)
2301
- if (this.signIdx(s.privateKey, idx))
2302
- signed = true;
2303
- return signed;
2304
- }
2305
- // Sighash checks
2306
- // Just for compat with bitcoinjs-lib, so users won't face unexpected behaviour.
2307
- if (!allowedSighash)
2308
- allowedSighash = [inputType.defaultSighash];
2309
- else
2310
- allowedSighash.forEach(validateSigHash);
2311
- const sighash = inputType.sighash;
2312
- if (!allowedSighash.includes(sighash)) {
2313
- throw new Error(`Input with not allowed sigHash=${sighash}. Allowed: ${allowedSighash.join(', ')}`);
2314
- }
2315
- // It is possible to sign these inputs for legacy/segwit v0 (but no taproot!),
2316
- // however this was because of bug in bitcoin-core, which remains here because of consensus.
2317
- // If this is absolutely neccessary for your case, please open issue.
2318
- // We disable it to avoid complicated workflow where SINGLE will block adding new outputs
2319
- const { sigOutputs } = this.inputSighash(idx);
2320
- if (sigOutputs === SignatureHash.SINGLE && idx >= this.outputs.length) {
2321
- throw new Error(`Input with sighash SINGLE, but there is no output with corresponding index=${idx}`);
2322
- }
2323
- // Actual signing
2324
- // Taproot
2325
- const prevOut = getPrevOut(input);
2326
- if (inputType.txType === 'taproot') {
2327
- if (input.tapBip32Derivation)
2328
- throw new Error('tapBip32Derivation unsupported');
2329
- const prevOuts = this.inputs.map(getPrevOut);
2330
- const prevOutScript = prevOuts.map((i) => i.script);
2331
- const amount = prevOuts.map((i) => i.amount);
2332
- let signed = false;
2333
- let schnorrPub = secp256k1_1.schnorr.getPublicKey(privateKey);
2334
- let merkleRoot = input.tapMerkleRoot || P.EMPTY;
2335
- if (input.tapInternalKey) {
2336
- // internal + tweak = tweaked key
2337
- // if internal key == current public key, we need to tweak private key,
2338
- // otherwise sign as is. bitcoinjs implementation always wants tweaked
2339
- // priv key to be provided
2340
- const { pubKey, privKey } = getTaprootKeys(privateKey, schnorrPub, input.tapInternalKey, merkleRoot);
2341
- const [taprootPubKey, _] = taprootTweakPubkey(input.tapInternalKey, merkleRoot);
2342
- if (P.equalBytes(taprootPubKey, pubKey)) {
2343
- const hash = this.preimageWitnessV1(idx, prevOutScript, sighash, amount);
2344
- const sig = concat(secp256k1_1.schnorr.sign(hash, privKey, _auxRand), sighash !== SignatureHash.DEFAULT ? new Uint8Array([sighash]) : P.EMPTY);
2345
- this.updateInput(idx, { tapKeySig: sig }, true);
2346
- signed = true;
2347
- }
2348
- }
2349
- if (input.tapLeafScript) {
2350
- input.tapScriptSig = input.tapScriptSig || [];
2351
- for (const [_, _script] of input.tapLeafScript) {
2352
- const script = _script.subarray(0, -1);
2353
- const scriptDecoded = exports.Script.decode(script);
2354
- const ver = _script[_script.length - 1];
2355
- const hash = (0, exports.tapLeafHash)(script, ver);
2356
- // NOTE: no need to tweak internal key here, since we don't support nested p2tr
2357
- const pos = scriptDecoded.findIndex((i) => isBytes(i) && P.equalBytes(i, schnorrPub));
2358
- // Skip if there is no public key in tapLeafScript
2359
- if (pos === -1)
2360
- continue;
2361
- const msg = this.preimageWitnessV1(idx, prevOutScript, sighash, amount, undefined, script, ver);
2362
- const sig = concat(secp256k1_1.schnorr.sign(msg, privateKey, _auxRand), sighash !== SignatureHash.DEFAULT ? new Uint8Array([sighash]) : P.EMPTY);
2363
- this.updateInput(idx, { tapScriptSig: [[{ pubKey: schnorrPub, leafHash: hash }, sig]] }, true);
2364
- signed = true;
2365
- }
2366
- }
2367
- if (!signed)
2368
- throw new Error('No taproot scripts signed');
2369
- return true;
2370
- }
2371
- else {
2372
- // only compressed keys are supported for now
2373
- const pubKey = _pubECDSA(privateKey);
2374
- // TODO: replace with explicit checks
2375
- // Check if script has public key or its has inside
2376
- let hasPubkey = false;
2377
- const pubKeyHash = hash160(pubKey);
2378
- for (const i of exports.Script.decode(inputType.lastScript)) {
2379
- if (isBytes(i) && (P.equalBytes(i, pubKey) || P.equalBytes(i, pubKeyHash)))
2380
- hasPubkey = true;
2381
- }
2382
- if (!hasPubkey)
2383
- throw new Error(`Input script doesn't have pubKey: ${inputType.lastScript}`);
2384
- let hash;
2385
- if (inputType.txType === 'legacy') {
2386
- hash = this.preimageLegacy(idx, inputType.lastScript, sighash);
2387
- }
2388
- else if (inputType.txType === 'segwit') {
2389
- let script = inputType.lastScript;
2390
- // If wpkh OR sh-wpkh, wsh-wpkh is impossible, so looks ok
2391
- if (inputType.last.type === 'wpkh')
2392
- script = exports.OutScript.encode({ type: 'pkh', hash: inputType.last.hash });
2393
- hash = this.preimageWitnessV0(idx, script, sighash, prevOut.amount);
2394
- }
2395
- else
2396
- throw new Error(`Transaction/sign: unknown tx type: ${inputType.txType}`);
2397
- const sig = signECDSA(hash, privateKey, this.opts.lowR);
2398
- this.updateInput(idx, {
2399
- partialSig: [[pubKey, concat(sig, new Uint8Array([sighash]))]],
2400
- }, true);
2401
- }
2402
- return true;
2403
- }
2404
- // This is bad API. Will work if user creates and signs tx, but if
2405
- // there is some complex workflow with exchanging PSBT and signing them,
2406
- // then it is better to validate which output user signs. How could a better API look like?
2407
- // Example: user adds input, sends to another party, then signs received input (mixer etc),
2408
- // another user can add different input for same key and user will sign it.
2409
- // Even worse: another user can add bip32 derivation, and spend money from different address.
2410
- // Better api: signIdx
2411
- sign(privateKey, allowedSighash, _auxRand) {
2412
- let num = 0;
2413
- for (let i = 0; i < this.inputs.length; i++) {
2414
- try {
2415
- if (this.signIdx(privateKey, i, allowedSighash, _auxRand))
2416
- num++;
2417
- }
2418
- catch (e) { }
2419
- }
2420
- if (!num)
2421
- throw new Error('No inputs signed');
2422
- return num;
2423
- }
2424
- finalizeIdx(idx) {
2425
- this.checkInputIdx(idx);
2426
- if (this.fee < 0n)
2427
- throw new Error('Outputs spends more than inputs amount');
2428
- const input = this.inputs[idx];
2429
- const inputType = getInputType(input, this.opts.allowLegacyWitnessUtxo);
2430
- // Taproot finalize
2431
- if (inputType.txType === 'taproot') {
2432
- if (input.tapKeySig)
2433
- input.finalScriptWitness = [input.tapKeySig];
2434
- else if (input.tapLeafScript && input.tapScriptSig) {
2435
- // Sort leafs by control block length.
2436
- const leafs = input.tapLeafScript.sort((a, b) => exports.TaprootControlBlock.encode(a[0]).length - exports.TaprootControlBlock.encode(b[0]).length);
2437
- for (const [cb, _script] of leafs) {
2438
- // Last byte is version
2439
- const script = _script.slice(0, -1);
2440
- const ver = _script[_script.length - 1];
2441
- const outScript = exports.OutScript.decode(script);
2442
- const hash = (0, exports.tapLeafHash)(script, ver);
2443
- const scriptSig = input.tapScriptSig.filter((i) => P.equalBytes(i[0].leafHash, hash));
2444
- let signatures = [];
2445
- if (outScript.type === 'tr_ms') {
2446
- const m = outScript.m;
2447
- const pubkeys = outScript.pubkeys;
2448
- let added = 0;
2449
- for (const pub of pubkeys) {
2450
- const sigIdx = scriptSig.findIndex((i) => P.equalBytes(i[0].pubKey, pub));
2451
- // Should have exact amount of signatures (more -- will fail)
2452
- if (added === m || sigIdx === -1) {
2453
- signatures.push(P.EMPTY);
2454
- continue;
2455
- }
2456
- signatures.push(scriptSig[sigIdx][1]);
2457
- added++;
2458
- }
2459
- // Should be exact same as m
2460
- if (added !== m)
2461
- continue;
2462
- }
2463
- else if (outScript.type === 'tr_ns') {
2464
- for (const pub of outScript.pubkeys) {
2465
- const sigIdx = scriptSig.findIndex((i) => P.equalBytes(i[0].pubKey, pub));
2466
- if (sigIdx === -1)
2467
- continue;
2468
- signatures.push(scriptSig[sigIdx][1]);
2469
- }
2470
- if (signatures.length !== outScript.pubkeys.length)
2471
- continue;
2472
- }
2473
- else if (outScript.type === 'unknown' && this.opts.allowUnknownInputs) {
2474
- // Trying our best to sign what we can
2475
- const scriptDecoded = exports.Script.decode(script);
2476
- signatures = scriptSig
2477
- .map(([{ pubKey }, signature]) => {
2478
- const pos = scriptDecoded.findIndex((i) => isBytes(i) && P.equalBytes(i, pubKey));
2479
- if (pos === -1)
2480
- throw new Error('finalize/taproot: cannot find position of pubkey in script');
2481
- return { signature, pos };
2482
- })
2483
- // Reverse order (because witness is stack and we take last element first from it)
2484
- .sort((a, b) => a.pos - b.pos)
2485
- .map((i) => i.signature);
2486
- if (!signatures.length)
2487
- continue;
2488
- }
2489
- else
2490
- throw new Error('Finalize: Unknown tapLeafScript');
2491
- // Witness is stack, so last element will be used first
2492
- input.finalScriptWitness = signatures
2493
- .reverse()
2494
- .concat([script, exports.TaprootControlBlock.encode(cb)]);
2495
- break;
2496
- }
2497
- if (!input.finalScriptWitness)
2498
- throw new Error('finalize/taproot: empty witness');
2499
- }
2500
- else
2501
- throw new Error('finalize/taproot: unknown input');
2502
- input.finalScriptSig = P.EMPTY;
2503
- cleanFinalInput(input);
2504
- return;
2505
- }
2506
- if (!input.partialSig || !input.partialSig.length)
2507
- throw new Error('Not enough partial sign');
2508
- let inputScript = P.EMPTY;
2509
- let witness = [];
2510
- // TODO: move input scripts closer to payments/output scripts
2511
- // Multisig
2512
- if (inputType.last.type === 'ms') {
2513
- const m = inputType.last.m;
2514
- const pubkeys = inputType.last.pubkeys;
2515
- let signatures = [];
2516
- // partial: [pubkey, sign]
2517
- for (const pub of pubkeys) {
2518
- const sign = input.partialSig.find((s) => P.equalBytes(pub, s[0]));
2519
- if (!sign)
2520
- continue;
2521
- signatures.push(sign[1]);
2522
- }
2523
- signatures = signatures.slice(0, m);
2524
- if (signatures.length !== m) {
2525
- throw new Error(`Multisig: wrong signatures count, m=${m} n=${pubkeys.length} signatures=${signatures.length}`);
2526
- }
2527
- inputScript = exports.Script.encode([0, ...signatures]);
2528
- }
2529
- else if (inputType.last.type === 'pk') {
2530
- inputScript = exports.Script.encode([input.partialSig[0][1]]);
2531
- }
2532
- else if (inputType.last.type === 'pkh') {
2533
- inputScript = exports.Script.encode([input.partialSig[0][1], input.partialSig[0][0]]);
2534
- }
2535
- else if (inputType.last.type === 'wpkh') {
2536
- inputScript = P.EMPTY;
2537
- witness = [input.partialSig[0][1], input.partialSig[0][0]];
2538
- }
2539
- else if (inputType.last.type === 'unknown' && !this.opts.allowUnknownInputs)
2540
- throw new Error('Unknown inputs not allowed');
2541
- // Create final scripts (generic part)
2542
- let finalScriptSig, finalScriptWitness;
2543
- if (inputType.type.includes('wsh-')) {
2544
- // P2WSH
2545
- if (inputScript.length && inputType.lastScript.length) {
2546
- witness = exports.Script.decode(inputScript).map((i) => {
2547
- if (i === 0)
2548
- return P.EMPTY;
2549
- if (isBytes(i))
2550
- return i;
2551
- throw new Error(`Wrong witness op=${i}`);
2552
- });
2553
- }
2554
- witness = witness.concat(inputType.lastScript);
2555
- }
2556
- if (inputType.txType === 'segwit')
2557
- finalScriptWitness = witness;
2558
- if (inputType.type.startsWith('sh-wsh-')) {
2559
- finalScriptSig = exports.Script.encode([exports.Script.encode([0, (0, sha256_1.sha256)(inputType.lastScript)])]);
2560
- }
2561
- else if (inputType.type.startsWith('sh-')) {
2562
- finalScriptSig = exports.Script.encode([...exports.Script.decode(inputScript), inputType.lastScript]);
2563
- }
2564
- else if (inputType.type.startsWith('wsh-')) {
2565
- }
2566
- else if (inputType.txType !== 'segwit')
2567
- finalScriptSig = inputScript;
2568
- if (!finalScriptSig && !finalScriptWitness)
2569
- throw new Error('Unknown error finalizing input');
2570
- if (finalScriptSig)
2571
- input.finalScriptSig = finalScriptSig;
2572
- if (finalScriptWitness)
2573
- input.finalScriptWitness = finalScriptWitness;
2574
- cleanFinalInput(input);
2575
- }
2576
- finalize() {
2577
- for (let i = 0; i < this.inputs.length; i++)
2578
- this.finalizeIdx(i);
2579
- }
2580
- extract() {
2581
- if (!this.isFinal)
2582
- throw new Error('Transaction has unfinalized inputs');
2583
- if (!this.outputs.length)
2584
- throw new Error('Transaction has no outputs');
2585
- if (this.fee < 0n)
2586
- throw new Error('Outputs spends more than inputs amount');
2587
- return this.toBytes(true, true);
2588
- }
2589
- combine(other) {
2590
- for (const k of ['PSBTVersion', 'version', 'lockTime']) {
2591
- if (this.opts[k] !== other.opts[k]) {
2592
- throw new Error(`Transaction/combine: different ${k} this=${this.opts[k]} other=${other.opts[k]}`);
2593
- }
2594
- }
2595
- for (const k of ['inputs', 'outputs']) {
2596
- if (this[k].length !== other[k].length) {
2597
- throw new Error(`Transaction/combine: different ${k} length this=${this[k].length} other=${other[k].length}`);
2598
- }
2599
- }
2600
- const thisUnsigned = this.global.unsignedTx ? exports.RawTx.encode(this.global.unsignedTx) : P.EMPTY;
2601
- const otherUnsigned = other.global.unsignedTx ? exports.RawTx.encode(other.global.unsignedTx) : P.EMPTY;
2602
- if (!P.equalBytes(thisUnsigned, otherUnsigned))
2603
- throw new Error(`Transaction/combine: different unsigned tx`);
2604
- this.global = mergeKeyMap(PSBTGlobal, this.global, other.global);
2605
- for (let i = 0; i < this.inputs.length; i++)
2606
- this.updateInput(i, other.inputs[i], true);
2607
- for (let i = 0; i < this.outputs.length; i++)
2608
- this.updateOutput(i, other.outputs[i], true);
2609
- return this;
2610
- }
2611
- clone() {
2612
- // deepClone probably faster, but this enforces that encoding is valid
2613
- return Transaction.fromPSBT(this.toPSBT(this.opts.PSBTVersion), this.opts);
2614
- }
2615
- }
2616
- exports.Transaction = Transaction;
2617
- // User facing API?
2618
- // Simple pubkey address, without complex scripts
2619
- function getAddress(type, privKey, network = exports.NETWORK) {
2620
- if (type === 'tr') {
2621
- return p2tr(secp256k1_1.schnorr.getPublicKey(privKey), undefined, network).address;
2622
- }
2623
- const pubKey = _pubECDSA(privKey);
2624
- if (type === 'pkh')
2625
- return (0, exports.p2pkh)(pubKey, network).address;
2626
- if (type === 'wpkh')
2627
- return (0, exports.p2wpkh)(pubKey, network).address;
2628
- throw new Error(`getAddress: unknown type=${type}`);
2629
- }
2630
- exports.getAddress = getAddress;
2631
- function multisig(m, pubkeys, sorted = false, witness = false) {
2632
- const ms = (0, exports.p2ms)(m, sorted ? (0, exports._sortPubkeys)(pubkeys) : pubkeys);
2633
- return witness ? (0, exports.p2wsh)(ms) : (0, exports.p2sh)(ms);
2634
- }
2635
- exports.multisig = multisig;
2636
- function sortedMultisig(m, pubkeys, witness = false) {
2637
- return multisig(m, pubkeys, true, witness);
2638
- }
2639
- exports.sortedMultisig = sortedMultisig;
2640
- // Copy-pasted from bip32 derive, maybe do something like 'bip32.parsePath'?
2641
- const HARDENED_OFFSET = 0x80000000;
2642
- function bip32Path(path) {
2643
- const out = [];
2644
- if (!/^[mM]'?/.test(path))
2645
- throw new Error('Path must start with "m" or "M"');
2646
- if (/^[mM]'?$/.test(path))
2647
- return out;
2648
- const parts = path.replace(/^[mM]'?\//, '').split('/');
2649
- for (const c of parts) {
2650
- const m = /^(\d+)('?)$/.exec(c);
2651
- if (!m || m.length !== 3)
2652
- throw new Error(`Invalid child index: ${c}`);
2653
- let idx = +m[1];
2654
- if (!Number.isSafeInteger(idx) || idx >= HARDENED_OFFSET)
2655
- throw new Error('Invalid index');
2656
- // hardened key
2657
- if (m[2] === "'")
2658
- idx += HARDENED_OFFSET;
2659
- out.push(idx);
2660
- }
2661
- return out;
2662
- }
2663
- exports.bip32Path = bip32Path;
2664
- function PSBTCombine(psbts) {
2665
- if (!psbts || !Array.isArray(psbts) || !psbts.length)
2666
- throw new Error('PSBTCombine: wrong PSBT list');
2667
- const tx = Transaction.fromPSBT(psbts[0]);
2668
- for (let i = 1; i < psbts.length; i++)
2669
- tx.combine(Transaction.fromPSBT(psbts[i]));
2670
- return tx.toPSBT();
2671
- }
2672
- exports.PSBTCombine = PSBTCombine;
2673
- function estimateInput(inputType, input, opts) {
2674
- let script = P.EMPTY, witness;
2675
- // schnorr sig is always 64 bytes. except for cases when sighash is not default!
2676
- if (inputType.txType === 'taproot') {
2677
- const SCHNORR_SIG_SIZE = inputType.sighash !== SignatureHash.DEFAULT ? 65 : 64;
2678
- if (input.tapInternalKey && !P.equalBytes(input.tapInternalKey, exports.TAPROOT_UNSPENDABLE_KEY)) {
2679
- witness = [new Uint8Array(SCHNORR_SIG_SIZE)];
2680
- }
2681
- else if (input.tapLeafScript) {
2682
- // If user want to select specific leaf (which can signed, it is possible to remove all other leafs manually);
2683
- // Sort leafs by control block length.
2684
- const leafs = input.tapLeafScript.sort((a, b) => exports.TaprootControlBlock.encode(a[0]).length - exports.TaprootControlBlock.encode(b[0]).length);
2685
- for (const [cb, _script] of leafs) {
2686
- // Last byte is version
2687
- const script = _script.slice(0, -1);
2688
- const outScript = exports.OutScript.decode(script);
2689
- let signatures = [];
2690
- if (outScript.type === 'tr_ms') {
2691
- const m = outScript.m;
2692
- for (let i = 0; i < m; i++)
2693
- signatures.push(new Uint8Array(SCHNORR_SIG_SIZE));
2694
- const n = outScript.pubkeys.length - m;
2695
- for (let i = 0; i < n; i++)
2696
- signatures.push(P.EMPTY);
2697
- }
2698
- else if (outScript.type === 'tr_ns') {
2699
- for (const _pub of outScript.pubkeys)
2700
- signatures.push(new Uint8Array(SCHNORR_SIG_SIZE));
2701
- }
2702
- else
2703
- throw new Error('Finalize: Unknown tapLeafScript');
2704
- // Witness is stack, so last element will be used first
2705
- witness = signatures.reverse().concat([script, exports.TaprootControlBlock.encode(cb)]);
2706
- break;
2707
- }
2708
- }
2709
- else
2710
- throw new Error('estimateInput/taproot: unknown input');
2711
- }
2712
- else {
2713
- // It is possible to grind signatures until it has minimal size (but changing fee value +N satoshi),
2714
- // which will make estimations exact. But will be very hard for multi sig (need to make sure all signatures has small size).
2715
- const SIG_SIZE = 72; // Maximum size of signatures
2716
- const PUB_KEY_SIZE = 33;
2717
- let inputScript = P.EMPTY;
2718
- let inputWitness = [];
2719
- if (inputType.last.type === 'ms') {
2720
- const m = inputType.last.m;
2721
- const sig = [0];
2722
- for (let i = 0; i < m; i++)
2723
- sig.push(new Uint8Array(SIG_SIZE));
2724
- inputScript = exports.Script.encode(sig);
2725
- }
2726
- else if (inputType.last.type === 'pk') {
2727
- // 71 sig + 1 sighash
2728
- inputScript = exports.Script.encode([new Uint8Array(SIG_SIZE)]);
2729
- }
2730
- else if (inputType.last.type === 'pkh') {
2731
- inputScript = exports.Script.encode([new Uint8Array(SIG_SIZE), new Uint8Array(PUB_KEY_SIZE)]);
2732
- }
2733
- else if (inputType.last.type === 'wpkh') {
2734
- inputScript = P.EMPTY;
2735
- inputWitness = [new Uint8Array(SIG_SIZE), new Uint8Array(PUB_KEY_SIZE)];
2736
- }
2737
- else if (inputType.last.type === 'unknown' && !opts.allowUnknownInputs)
2738
- throw new Error('Unknown inputs not allowed');
2739
- if (inputType.type.includes('wsh-')) {
2740
- // P2WSH
2741
- if (inputScript.length && inputType.lastScript.length) {
2742
- inputWitness = exports.Script.decode(inputScript).map((i) => {
2743
- if (i === 0)
2744
- return P.EMPTY;
2745
- if (isBytes(i))
2746
- return i;
2747
- throw new Error(`Wrong witness op=${i}`);
2748
- });
2749
- }
2750
- inputWitness = inputWitness.concat(inputType.lastScript);
2751
- }
2752
- if (inputType.txType === 'segwit')
2753
- witness = inputWitness;
2754
- if (inputType.type.startsWith('sh-wsh-')) {
2755
- script = exports.Script.encode([exports.Script.encode([0, new Uint8Array(sha256_1.sha256.outputLen)])]);
2756
- }
2757
- else if (inputType.type.startsWith('sh-')) {
2758
- script = exports.Script.encode([...exports.Script.decode(inputScript), inputType.lastScript]);
2759
- }
2760
- else if (inputType.type.startsWith('wsh-')) {
2761
- }
2762
- else if (inputType.txType !== 'segwit')
2763
- script = inputScript;
2764
- }
2765
- let weight = 160 + 4 * exports.VarBytes.encode(script).length;
2766
- let hasWitnesses = false;
2767
- if (witness) {
2768
- weight += exports.RawWitness.encode(witness).length;
2769
- hasWitnesses = true;
2770
- }
2771
- return { weight, hasWitnesses };
2772
- }
2773
- // Exported for tests, internal method
2774
- const _cmpBig = (a, b) => {
2775
- const n = a - b;
2776
- if (n < 0n)
2777
- return -1;
2778
- else if (n > 0n)
2779
- return 1;
2780
- return 0;
2781
- };
2782
- exports._cmpBig = _cmpBig;
2783
- function getScript(o, opts = {}, network = exports.NETWORK) {
2784
- let script;
2785
- if ('script' in o && o.script instanceof Uint8Array) {
2786
- script = o.script;
2787
- }
2788
- if ('address' in o) {
2789
- if (typeof o.address !== 'string')
2790
- throw new Error(`Estimator: wrong output address=${o.address}`);
2791
- script = exports.OutScript.encode(Address(network).decode(o.address));
2792
- }
2793
- if (!script)
2794
- throw new Error('Estimator: wrong output script');
2795
- if (typeof o.amount !== 'bigint')
2796
- throw new Error(`Estimator: wrong output amount=${o.amount}`);
2797
- if (script && !opts.allowUnknownOutputs && exports.OutScript.decode(script).type === 'unknown') {
2798
- throw new Error('Estimator: unknown output script type, there is a chance that input is unspendable. Pass allowUnknownOutputs=true, if you sure');
2799
- }
2800
- if (!opts.disableScriptCheck)
2801
- checkScript(script);
2802
- return script;
2803
- }
2804
- // class, because we need to re-use normalized inputs, instead of parsing each time
2805
- // internal stuff, exported for tests only
2806
- class _Estimator {
2807
- constructor(inputs, outputs, opts) {
2808
- this.inputs = inputs;
2809
- this.outputs = outputs;
2810
- this.opts = opts;
2811
- // https://github.com/bitcoin/bitcoin/blob/f90603ac6d24f5263649675d51233f1fce8b2ecd/src/policy/policy.cpp#L44
2812
- // 32 + 4 + 1 + 107 + 4
2813
- // Dust used in accumExact + change address algo
2814
- // - change address: can be smaller for segwit
2815
- // - accumExact: ???
2816
- this.dust = 148n; // compat with coinselect
2817
- if (typeof opts.feePerByte !== 'bigint')
2818
- throw new Error(`Estimator: wrong feePerByte=${opts.feePerByte}`);
2819
- if (opts.dust) {
2820
- if (typeof opts.dust !== 'bigint')
2821
- throw new Error(`Estimator: wrong dust=${opts.dust}`);
2822
- this.dust = opts.dust;
2823
- }
2824
- const network = opts.network || exports.NETWORK;
2825
- let amount = 0n;
2826
- // Base weight: tx with outputs, no inputs
2827
- let baseWeight = 32;
2828
- for (const o of outputs) {
2829
- const script = getScript(o, opts, opts.network);
2830
- baseWeight += 32 + 4 * exports.VarBytes.encode(script).length;
2831
- amount += o.amount;
2832
- }
2833
- if (typeof opts.changeAddress !== 'string')
2834
- throw new Error(`Estimator: wrong change address=${opts.changeAddress}`);
2835
- let changeWeight = baseWeight +
2836
- 32 +
2837
- 4 * exports.VarBytes.encode(exports.OutScript.encode(Address(network).decode(opts.changeAddress))).length;
2838
- baseWeight += 4 * CompactSizeLen.encode(outputs.length).length;
2839
- // If there a lot of outputs change can change fee
2840
- changeWeight += 4 * CompactSizeLen.encode(outputs.length + 1).length;
2841
- this.baseWeight = baseWeight;
2842
- this.changeWeight = changeWeight;
2843
- this.amount = amount;
2844
- this.normalizedInputs = this.inputs.map((i) => {
2845
- const normalized = normalizeInput(i, undefined, undefined, opts.disableScriptCheck);
2846
- inputBeforeSign(normalized); // check fields
2847
- const inputType = getInputType(normalized, opts.allowLegacyWitnessUtxo);
2848
- const prev = getPrevOut(normalized);
2849
- const estimate = estimateInput(inputType, normalized, this.opts);
2850
- const value = prev.amount - opts.feePerByte * BigInt(toVsize(estimate.weight)); // value = amount-fee
2851
- return { inputType, normalized, amount: prev.amount, value, estimate };
2852
- });
2853
- }
2854
- checkInputIdx(idx) {
2855
- if (!Number.isSafeInteger(idx) || 0 > idx || idx >= this.inputs.length)
2856
- throw new Error(`Wrong input index=${idx}`);
2857
- return idx;
2858
- }
2859
- sortIndices(indices) {
2860
- return indices.slice().sort((a, b) => {
2861
- const ai = this.normalizedInputs[this.checkInputIdx(a)];
2862
- const bi = this.normalizedInputs[this.checkInputIdx(b)];
2863
- const out = _cmpBytes(ai.normalized.txid, bi.normalized.txid);
2864
- if (out !== 0)
2865
- return out;
2866
- return ai.normalized.index - bi.normalized.index;
2867
- });
2868
- }
2869
- sortOutputs(outputs) {
2870
- const scripts = outputs.map((o) => getScript(o, this.opts, this.opts.network));
2871
- const indices = outputs.map((_, j) => j);
2872
- return indices.sort((a, b) => {
2873
- const aa = outputs[a].amount;
2874
- const ba = outputs[b].amount;
2875
- const out = (0, exports._cmpBig)(aa, ba);
2876
- if (out !== 0)
2877
- return out;
2878
- return _cmpBytes(scripts[a], scripts[b]);
2879
- });
2880
- }
2881
- getSatoshi(weigth) {
2882
- return this.opts.feePerByte * BigInt(toVsize(weigth));
2883
- }
2884
- // Sort by value instead of amount
2885
- get biggest() {
2886
- return this.inputs
2887
- .map((_i, j) => j)
2888
- .sort((a, b) => (0, exports._cmpBig)(this.normalizedInputs[b].value, this.normalizedInputs[a].value));
2889
- }
2890
- get smallest() {
2891
- return this.biggest.reverse();
2892
- }
2893
- // These assume that UTXO array has historical order.
2894
- // Otherwise, we have no way to know which tx is oldest
2895
- // Explorers usually give UTXO in this order.
2896
- get oldest() {
2897
- return this.inputs.map((_i, j) => j);
2898
- }
2899
- get newest() {
2900
- return this.oldest.reverse();
2901
- }
2902
- // exact - like blackjack from coinselect.
2903
- // exact(biggest) will select one big utxo which is closer to targetValue+dust, if possible.
2904
- // If not, it will accumulate largest utxo until value is close to targetValue+dust.
2905
- accumulate(indices, exact = false, skipNegative = true, all = false) {
2906
- const { feePerByte } = this.opts;
2907
- // TODO: how to handle change addresses?
2908
- // - cost of input
2909
- // - cost of change output (if input requires change)
2910
- // - cost of output spending
2911
- // Dust threshold should be significantly bigger, no point in
2912
- // creating an output, which cannot be spent.
2913
- // coinselect doesn't consider cost of output address for dust.
2914
- // Changing that can actually reduce privacy
2915
- let weight = this.opts.alwaysChange ? this.changeWeight : this.baseWeight;
2916
- let hasWitnesses = false;
2917
- let num = 0;
2918
- let inputsAmount = 0n;
2919
- const targetAmount = this.amount;
2920
- const res = [];
2921
- let fee;
2922
- for (const idx of indices) {
2923
- this.checkInputIdx(idx);
2924
- const { estimate, amount, value } = this.normalizedInputs[idx];
2925
- let newWeight = weight + estimate.weight;
2926
- if (!hasWitnesses && estimate.hasWitnesses)
2927
- newWeight += 2; // enable witness if needed
2928
- const totalWeight = newWeight + 4 * CompactSizeLen.encode(num).length; // number of outputs can change weight
2929
- fee = this.getSatoshi(totalWeight);
2930
- // Best case scenario exact(biggest) -> we find biggest output, less than target+threshold
2931
- if (exact) {
2932
- const dust = this.dust * feePerByte;
2933
- // skip if added value is bigger than dust
2934
- if (amount + inputsAmount > targetAmount + fee + dust)
2935
- continue;
2936
- }
2937
- // Negative: cost of using input is more than value provided (negative)
2938
- // By default 'blackjack' mode in coinselect doesn't use that, which means
2939
- // it will use negative output if sorted by 'smallest'
2940
- if (skipNegative && value <= 0n)
2941
- continue;
2942
- weight = newWeight;
2943
- if (estimate.hasWitnesses)
2944
- hasWitnesses = true;
2945
- num++;
2946
- inputsAmount += amount;
2947
- res.push(idx);
2948
- // inputsAmount is enough to cover cost of tx
2949
- if (!all && targetAmount + fee < inputsAmount)
2950
- return { indices: res, fee, weight: totalWeight, total: inputsAmount };
2951
- }
2952
- if (all) {
2953
- const newWeight = weight + 4 * CompactSizeLen.encode(num).length;
2954
- return { indices: res, fee, weight: newWeight, total: inputsAmount };
2955
- }
2956
- return undefined;
2957
- }
2958
- // Works like coinselect default method
2959
- default() {
2960
- const { biggest } = this;
2961
- const exact = this.accumulate(biggest, true, false);
2962
- if (exact)
2963
- return exact;
2964
- return this.accumulate(biggest);
2965
- }
2966
- select(strategy) {
2967
- if (strategy === 'all') {
2968
- return this.accumulate(this.inputs.map((_, j) => j), false, true, true);
2969
- }
2970
- if (strategy === 'default')
2971
- return this.default();
2972
- const data = {
2973
- Oldest: () => this.oldest,
2974
- Newest: () => this.newest,
2975
- Smallest: () => this.smallest,
2976
- Biggest: () => this.biggest,
2977
- };
2978
- if (strategy.startsWith('exact')) {
2979
- const [exactData, left] = strategy.slice(5).split('/');
2980
- if (!data[exactData])
2981
- throw new Error(`Estimator.select: wrong strategy=${strategy}`);
2982
- strategy = left;
2983
- const exact = this.accumulate(data[exactData](), true, true);
2984
- if (exact)
2985
- return exact;
2986
- }
2987
- if (strategy.startsWith('accum')) {
2988
- const accumData = strategy.slice(5);
2989
- if (!data[accumData])
2990
- throw new Error(`Estimator.select: wrong strategy=${strategy}`);
2991
- return this.accumulate(data[accumData]());
2992
- }
2993
- throw new Error(`Estimator.select: wrong strategy=${strategy}`);
2994
- }
2995
- result(strategy) {
2996
- const s = this.select(strategy);
2997
- if (!s)
2998
- return;
2999
- const { indices, weight, total } = s;
3000
- let needChange = this.opts.alwaysChange;
3001
- const changeWeight = this.opts.alwaysChange
3002
- ? weight
3003
- : weight + (this.changeWeight - this.baseWeight);
3004
- const changeFee = this.getSatoshi(changeWeight);
3005
- let fee = s.fee;
3006
- const change = total - this.amount - changeFee;
3007
- if (change > this.dust)
3008
- needChange = true;
3009
- let inputs = indices;
3010
- let outputs = Array.from(this.outputs);
3011
- if (needChange) {
3012
- fee = changeFee;
3013
- // this shouldn't happen!
3014
- if (change < 0n)
3015
- throw new Error(`Estimator.result: negative change=${change}`);
3016
- outputs.push({ address: this.opts.changeAddress, amount: change });
3017
- }
3018
- if (this.opts.bip69) {
3019
- inputs = this.sortIndices(inputs);
3020
- outputs = this.sortOutputs(outputs).map((i) => outputs[i]);
3021
- }
3022
- const res = {
3023
- inputs: inputs.map((i) => this.inputs[i]),
3024
- outputs,
3025
- fee,
3026
- weight: this.opts.alwaysChange ? s.weight : changeWeight,
3027
- change: !!needChange,
3028
- };
3029
- let tx;
3030
- if (this.opts.createTx) {
3031
- const { inputs, outputs } = res;
3032
- tx = new Transaction(this.opts);
3033
- for (const i of inputs)
3034
- tx.addInput(i);
3035
- for (const o of outputs)
3036
- tx.addOutput({ ...o, script: getScript(o, this.opts, this.opts.network) });
3037
- }
3038
- return { ...res, tx };
3039
- }
3040
- }
3041
- exports._Estimator = _Estimator;
3042
- function selectUTXO(inputs, outputs, strategy, opts) {
3043
- // Defaults: do we want bip69 by default?
3044
- const _opts = { createTx: true, bip69: true, ...opts };
3045
- const est = new _Estimator(inputs, outputs, _opts);
3046
- return est.result(strategy);
3047
- }
3048
- exports.selectUTXO = selectUTXO;
39
+ var payment_js_2 = require("./payment.js"); // remove
40
+ Object.defineProperty(exports, "Address", { enumerable: true, get: function () { return payment_js_2.Address; } });
41
+ Object.defineProperty(exports, "getAddress", { enumerable: true, get: function () { return payment_js_2.getAddress; } });
42
+ Object.defineProperty(exports, "WIF", { enumerable: true, get: function () { return payment_js_2.WIF; } });
43
+ Object.defineProperty(exports, "taprootListToTree", { enumerable: true, get: function () { return payment_js_2.taprootListToTree; } });
44
+ Object.defineProperty(exports, "OutScript", { enumerable: true, get: function () { return payment_js_2.OutScript; } });
45
+ Object.defineProperty(exports, "_sortPubkeys", { enumerable: true, get: function () { return payment_js_2._sortPubkeys; } });
46
+ Object.defineProperty(exports, "sortedMultisig", { enumerable: true, get: function () { return payment_js_2.sortedMultisig; } });
47
+ Object.defineProperty(exports, "combinations", { enumerable: true, get: function () { return payment_js_2.combinations; } });
48
+ var psbt_js_1 = require("./psbt.js"); // remove
49
+ Object.defineProperty(exports, "_DebugPSBT", { enumerable: true, get: function () { return psbt_js_1._DebugPSBT; } });
50
+ Object.defineProperty(exports, "TaprootControlBlock", { enumerable: true, get: function () { return psbt_js_1.TaprootControlBlock; } });
51
+ var transaction_js_2 = require("./transaction.js"); // remove
52
+ Object.defineProperty(exports, "Decimal", { enumerable: true, get: function () { return transaction_js_2.Decimal; } });
53
+ Object.defineProperty(exports, "bip32Path", { enumerable: true, get: function () { return transaction_js_2.bip32Path; } });
54
+ Object.defineProperty(exports, "SigHash", { enumerable: true, get: function () { return transaction_js_2.SigHash; } });
55
+ Object.defineProperty(exports, "PSBTCombine", { enumerable: true, get: function () { return transaction_js_2.PSBTCombine; } });
56
+ Object.defineProperty(exports, "DEFAULT_SEQUENCE", { enumerable: true, get: function () { return transaction_js_2.DEFAULT_SEQUENCE; } });
57
+ var utxo_js_2 = require("./utxo.js");
58
+ Object.defineProperty(exports, "_cmpBig", { enumerable: true, get: function () { return utxo_js_2._cmpBig; } });
59
+ Object.defineProperty(exports, "_Estimator", { enumerable: true, get: function () { return utxo_js_2._Estimator; } });
3049
60
  //# sourceMappingURL=index.js.map