@bitcoinerlab/descriptors 3.0.6 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +9 -487
  2. package/index.d.ts +13 -0
  3. package/index.js +16 -0
  4. package/package.json +22 -53
  5. package/dist/applyPR2137.d.ts +0 -2
  6. package/dist/applyPR2137.js +0 -153
  7. package/dist/bitcoinjs-lib-internals.d.ts +0 -10
  8. package/dist/bitcoinjs-lib-internals.js +0 -60
  9. package/dist/checksum.d.ts +0 -6
  10. package/dist/checksum.js +0 -58
  11. package/dist/descriptors.d.ts +0 -433
  12. package/dist/descriptors.js +0 -1743
  13. package/dist/index.d.ts +0 -21
  14. package/dist/index.js +0 -85
  15. package/dist/keyExpressions.d.ts +0 -83
  16. package/dist/keyExpressions.js +0 -247
  17. package/dist/ledger.d.ts +0 -167
  18. package/dist/ledger.js +0 -580
  19. package/dist/miniscript.d.ts +0 -123
  20. package/dist/miniscript.js +0 -305
  21. package/dist/multipath.d.ts +0 -13
  22. package/dist/multipath.js +0 -76
  23. package/dist/networkUtils.d.ts +0 -3
  24. package/dist/networkUtils.js +0 -16
  25. package/dist/parseUtils.d.ts +0 -7
  26. package/dist/parseUtils.js +0 -46
  27. package/dist/psbt.d.ts +0 -44
  28. package/dist/psbt.js +0 -193
  29. package/dist/re.d.ts +0 -31
  30. package/dist/re.js +0 -79
  31. package/dist/resourceLimits.d.ts +0 -25
  32. package/dist/resourceLimits.js +0 -89
  33. package/dist/scriptExpressions.d.ts +0 -95
  34. package/dist/scriptExpressions.js +0 -89
  35. package/dist/signers.d.ts +0 -84
  36. package/dist/signers.js +0 -215
  37. package/dist/stackResourceLimits.d.ts +0 -17
  38. package/dist/stackResourceLimits.js +0 -35
  39. package/dist/tapMiniscript.d.ts +0 -220
  40. package/dist/tapMiniscript.js +0 -510
  41. package/dist/tapTree.d.ts +0 -86
  42. package/dist/tapTree.js +0 -166
  43. package/dist/types.d.ts +0 -238
  44. package/dist/types.js +0 -4
@@ -1,123 +0,0 @@
1
- import { Network } from 'bitcoinjs-lib';
2
- import type { ECPairAPI } from 'ecpair';
3
- import type { BIP32API } from 'bip32';
4
- import type { PartialSig } from 'bip174';
5
- import type { Preimage, TimeConstraints, ExpansionMap } from './types';
6
- /**
7
- * Expand a miniscript to a generalized form using variables instead of key
8
- * expressions. Variables will be of this form: @0, @1, ...
9
- * This is done so that it can be compiled with compileMiniscript and
10
- * satisfied with satisfier.
11
- * Also compute pubkeys from descriptors to use them later.
12
- */
13
- export declare function expandMiniscript({ miniscript, isSegwit, isTaproot, network, ECPair, BIP32 }: {
14
- miniscript: string;
15
- isSegwit: boolean;
16
- isTaproot: boolean;
17
- network?: Network;
18
- ECPair: ECPairAPI;
19
- BIP32: BIP32API;
20
- }): {
21
- expandedMiniscript: string;
22
- expansionMap: ExpansionMap;
23
- };
24
- export declare function miniscript2Script({ expandedMiniscript, expansionMap, tapscript }: {
25
- expandedMiniscript: string;
26
- expansionMap: ExpansionMap;
27
- tapscript?: boolean;
28
- }): Uint8Array;
29
- /**
30
- * Assumptions:
31
- * The attacker does not have access to any of the private keys of public keys
32
- * that participate in the Script.
33
- *
34
- * The attacker only has access to hash preimages that honest users have access
35
- * to as well.
36
- *
37
- * Pass timeConstraints to search for the first solution with this nLockTime and
38
- * nSequence. Throw if no solution is possible using these constraints.
39
- *
40
- * Time constraints are used to keep the chosen satisfaction stable between the
41
- * planning pass (fake signatures) and the signing pass (real signatures).
42
- * We run the satisfier once with fake signatures to discover the implied
43
- * nLockTime/nSequence without requiring user signatures. If real signatures
44
- * had the same length, the satisfier would typically pick the same
45
- * minimal-weight solution again. But ECDSA signature sizes can vary (71–73
46
- * bytes), which may change which solution is considered "smallest".
47
- *
48
- * Passing the previously derived timeConstraints in the second pass forces the
49
- * same solution to be selected, ensuring locktime/sequence do not change
50
- * between planning and finalization.
51
- *
52
- * Don't pass timeConstraints (this is the default) if you want to get the
53
- * smallest size solution altogether.
54
- *
55
- * If a solution is not found this function throws.
56
- */
57
- export declare function satisfyMiniscript({ expandedMiniscript, expansionMap, signatures, preimages, timeConstraints, tapscript }: {
58
- expandedMiniscript: string;
59
- expansionMap: ExpansionMap;
60
- signatures?: PartialSig[];
61
- preimages?: Preimage[];
62
- timeConstraints?: TimeConstraints;
63
- tapscript?: boolean;
64
- }): {
65
- scriptSatisfaction: Uint8Array;
66
- nLockTime: number | undefined;
67
- nSequence: number | undefined;
68
- };
69
- /**
70
- *
71
- * Use this function instead of bitcoinjs-lib's equivalent `script.number.encode`
72
- * when encoding numbers to be compiled with `fromASM` to avoid problems.
73
- *
74
- * Motivation:
75
- *
76
- * Numbers in Bitcoin assembly code are represented in hex and in Little Endian.
77
- * Decimal: 32766 - Big endian: 0x7FFE - Little Endian: 0xFE7F.
78
- *
79
- * This function takes an integer and encodes it so that bitcoinjs-lib `fromASM`
80
- * can compile it. This is basically what bitcoinjs-lib's `script.number.encode`
81
- * does.
82
- *
83
- * Note that `fromASM` already converts integers from 1 to 16 to
84
- * OP_1 ... OP_16 {@link https://github.com/bitcoinjs/bitcoinjs-lib/blob/59b21162a2c4645c64271ca004c7a3755a3d72fb/src/script.js#L33 here}.
85
- * This is done in Bitcoin to save some bits.
86
- *
87
- * Neither this function nor `script.number.encode` convert numbers to
88
- * their op code equivalent since this is done later in `fromASM`.
89
- *
90
- * Both functions simply convert numbers to Little Endian.
91
- *
92
- * However, the `0` number is an edge case that we specially handle with this
93
- * function.
94
- *
95
- * bitcoinjs-lib's `bscript.number.encode(0)` produces an empty array.
96
- * This is what the Bitcoin interpreter does and it is what `script.number.encode` was
97
- * implemented to do.
98
- *
99
- * The problem is `bscript.number.encode(0).toString('hex')` produces an
100
- * empty string and thus it should not be used to serialize number zero before `fromASM`.
101
- *
102
- * A zero should produce the OP_0 ASM symbolic code (corresponding to a `0` when
103
- * compiled).
104
- *
105
- * So, this function will produce a string in hex format in Little Endian
106
- * encoding for integers not equal to `0` and it will return `OP_0` for `0`.
107
- *
108
- * Read more about the this {@link https://github.com/bitcoinjs/bitcoinjs-lib/issues/1799#issuecomment-1122591738 here}.
109
- *
110
- * Use it in combination with `fromASM` like this:
111
- *
112
- * ```javascript
113
- * //To produce "0 1 OP_ADD":
114
- * fromASM(
115
- * `${numberEncodeAsm(0)} ${numberEncodeAsm(1)} OP_ADD`
116
- * .trim().replace(/\s+/g, ' ')
117
- * )
118
- * ```
119
- *
120
- * @param {number} number An integer.
121
- * @returns {string} Returns `"OP_0"` for `number === 0` and a hex string representing other numbers in Little Endian encoding.
122
- */
123
- export declare function numberEncodeAsm(number: number): string;
@@ -1,305 +0,0 @@
1
- "use strict";
2
- // Copyright (c) 2023 Jose-Luis Landabaso - https://bitcoinerlab.com
3
- // Distributed under the MIT software license
4
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
5
- if (k2 === undefined) k2 = k;
6
- var desc = Object.getOwnPropertyDescriptor(m, k);
7
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
8
- desc = { enumerable: true, get: function() { return m[k]; } };
9
- }
10
- Object.defineProperty(o, k2, desc);
11
- }) : (function(o, m, k, k2) {
12
- if (k2 === undefined) k2 = k;
13
- o[k2] = m[k];
14
- }));
15
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
16
- Object.defineProperty(o, "default", { enumerable: true, value: v });
17
- }) : function(o, v) {
18
- o["default"] = v;
19
- });
20
- var __importStar = (this && this.__importStar) || (function () {
21
- var ownKeys = function(o) {
22
- ownKeys = Object.getOwnPropertyNames || function (o) {
23
- var ar = [];
24
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
25
- return ar;
26
- };
27
- return ownKeys(o);
28
- };
29
- return function (mod) {
30
- if (mod && mod.__esModule) return mod;
31
- var result = {};
32
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
33
- __setModuleDefault(result, mod);
34
- return result;
35
- };
36
- })();
37
- Object.defineProperty(exports, "__esModule", { value: true });
38
- exports.expandMiniscript = expandMiniscript;
39
- exports.miniscript2Script = miniscript2Script;
40
- exports.satisfyMiniscript = satisfyMiniscript;
41
- exports.numberEncodeAsm = numberEncodeAsm;
42
- const bitcoinjs_lib_1 = require("bitcoinjs-lib");
43
- const keyExpressions_1 = require("./keyExpressions");
44
- const RE = __importStar(require("./re"));
45
- const miniscript_1 = require("@bitcoinerlab/miniscript");
46
- const uint8array_tools_1 = require("uint8array-tools");
47
- /**
48
- * Expand a miniscript to a generalized form using variables instead of key
49
- * expressions. Variables will be of this form: @0, @1, ...
50
- * This is done so that it can be compiled with compileMiniscript and
51
- * satisfied with satisfier.
52
- * Also compute pubkeys from descriptors to use them later.
53
- */
54
- function expandMiniscript({ miniscript, isSegwit, isTaproot, network = bitcoinjs_lib_1.networks.bitcoin, ECPair, BIP32 }) {
55
- const reKeyExp = isTaproot
56
- ? RE.reTaprootKeyExp
57
- : isSegwit
58
- ? RE.reSegwitKeyExp
59
- : RE.reNonSegwitKeyExp;
60
- const expansionMap = {};
61
- let keyIndex = 0;
62
- const keyExpressionRegex = new RegExp(String.raw `^${reKeyExp}$`);
63
- const replaceKeyExpression = (keyExpression) => {
64
- const trimmed = keyExpression.trim();
65
- if (!trimmed)
66
- throw new Error(`Error: expected a keyExpression but got ${keyExpression}`);
67
- if (!keyExpressionRegex.test(trimmed))
68
- throw new Error(`Error: expected a keyExpression but got ${trimmed}`);
69
- const key = `@${keyIndex}`;
70
- keyIndex += 1;
71
- expansionMap[key] = (0, keyExpressions_1.parseKeyExpression)({
72
- keyExpression: trimmed,
73
- isSegwit,
74
- isTaproot,
75
- network,
76
- ECPair,
77
- BIP32
78
- });
79
- return key;
80
- };
81
- // These are the Miniscript fragments where key arguments are expected.
82
- // We only replace key expressions inside these fragments to avoid confusing
83
- // hash preimages (e.g. sha256(03...)) with keys.
84
- //
85
- // Note: sorted script expressions (`sortedmulti`, `sortedmulti_a`) are
86
- // intentionally excluded here. They are descriptor-level expressions (not
87
- // Miniscript fragments) and are handled in descriptor/tap-tree code paths
88
- // before Miniscript compilation.
89
- const keyBearingFragmentRegex = /\b(pk|pkh|multi_a|multi)\(([^()]*)\)/g;
90
- const expandedMiniscript = miniscript.replace(keyBearingFragmentRegex, (_, name, inner) => {
91
- if (name === 'pk' || name === 'pkh')
92
- return `${name}(${replaceKeyExpression(inner)})`;
93
- //now do *multi* which has arguments:
94
- const parts = inner.split(',').map(part => part.trim());
95
- if (parts.length < 2)
96
- throw new Error(`Error: invalid miniscript ${miniscript} (missing keys)`);
97
- const k = parts[0] ?? '';
98
- if (!k)
99
- throw new Error(`Error: invalid miniscript ${miniscript} (missing threshold)`);
100
- const replacedKeys = parts
101
- .slice(1)
102
- .map(keyExpression => replaceKeyExpression(keyExpression));
103
- return `${name}(${[k, ...replacedKeys].join(',')})`;
104
- });
105
- //Do some assertions. Miniscript must not have duplicate keys, also all
106
- //keyExpressions must produce a valid pubkey (unless it's ranged and we want
107
- //to expand a generalized form, then we don't check)
108
- const pubkeysHex = Object.values(expansionMap)
109
- .filter(keyInfo => keyInfo.keyExpression.indexOf('*') === -1)
110
- .map(keyInfo => {
111
- if (!keyInfo.pubkey)
112
- throw new Error(`Error: keyExpression ${keyInfo.keyExpression} does not have a pubkey`);
113
- return (0, uint8array_tools_1.toHex)(keyInfo.pubkey);
114
- });
115
- if (new Set(pubkeysHex).size !== pubkeysHex.length) {
116
- throw new Error(`Error: miniscript ${miniscript} is not sane: contains duplicate public keys.`);
117
- }
118
- return { expandedMiniscript, expansionMap };
119
- }
120
- /**
121
- * Particularize an expanded ASM expression using the variables in
122
- * expansionMap.
123
- * This is the kind of the opposite to what expandMiniscript does.
124
- * Signatures and preimages are already subsituted by the satisfier calling
125
- * this function.
126
- */
127
- function substituteAsm({ expandedAsm, expansionMap }) {
128
- //Replace back variables into the pubkeys previously computed.
129
- let asm = Object.keys(expansionMap).reduce((accAsm, key) => {
130
- const pubkey = expansionMap[key]?.pubkey;
131
- if (!pubkey) {
132
- throw new Error(`Error: invalid expansionMap for ${key}`);
133
- }
134
- return accAsm
135
- .replaceAll(`<${key}>`, `<${(0, uint8array_tools_1.toHex)(pubkey)}>`)
136
- .replaceAll(`<HASH160(${key})>`, `<${(0, uint8array_tools_1.toHex)(bitcoinjs_lib_1.crypto.hash160(pubkey))}>`);
137
- }, expandedAsm);
138
- //Now clean it and prepare it so that fromASM can be called:
139
- asm = asm
140
- .trim()
141
- //Replace one or more consecutive whitespace characters (spaces, tabs,
142
- //or line breaks) with a single space.
143
- .replace(/\s+/g, ' ')
144
- //Now encode numbers to little endian hex. Note that numbers are not
145
- //enclosed in <>, since <> represents hex code already encoded.
146
- //The regex below will match one or more digits within a string,
147
- //except if the sequence is surrounded by "<" and ">"
148
- .replace(/(<\d+>)|\b\d+\b/g, match => match.startsWith('<') ? match : numberEncodeAsm(Number(match)))
149
- //we don't have numbers anymore, now it's safe to remove < and > since we
150
- //know that every remaining is either an op_code or a hex encoded number
151
- .replace(/[<>]/g, '');
152
- return asm;
153
- }
154
- function miniscript2Script({ expandedMiniscript, expansionMap, tapscript = false }) {
155
- const compiled = (0, miniscript_1.compileMiniscript)(expandedMiniscript, { tapscript });
156
- if (compiled.issane !== true) {
157
- throw new Error(`Error: Miniscript ${expandedMiniscript} is not sane`);
158
- }
159
- return bitcoinjs_lib_1.script.fromASM(substituteAsm({ expandedAsm: compiled.asm, expansionMap }));
160
- }
161
- /**
162
- * Assumptions:
163
- * The attacker does not have access to any of the private keys of public keys
164
- * that participate in the Script.
165
- *
166
- * The attacker only has access to hash preimages that honest users have access
167
- * to as well.
168
- *
169
- * Pass timeConstraints to search for the first solution with this nLockTime and
170
- * nSequence. Throw if no solution is possible using these constraints.
171
- *
172
- * Time constraints are used to keep the chosen satisfaction stable between the
173
- * planning pass (fake signatures) and the signing pass (real signatures).
174
- * We run the satisfier once with fake signatures to discover the implied
175
- * nLockTime/nSequence without requiring user signatures. If real signatures
176
- * had the same length, the satisfier would typically pick the same
177
- * minimal-weight solution again. But ECDSA signature sizes can vary (71–73
178
- * bytes), which may change which solution is considered "smallest".
179
- *
180
- * Passing the previously derived timeConstraints in the second pass forces the
181
- * same solution to be selected, ensuring locktime/sequence do not change
182
- * between planning and finalization.
183
- *
184
- * Don't pass timeConstraints (this is the default) if you want to get the
185
- * smallest size solution altogether.
186
- *
187
- * If a solution is not found this function throws.
188
- */
189
- function satisfyMiniscript({ expandedMiniscript, expansionMap, signatures = [], preimages = [], timeConstraints, tapscript = false }) {
190
- //convert 'sha256(6c...33)' to: { ['<sha256_preimage(6c...33)>']: '10...5f'}
191
- const preimageMap = {};
192
- preimages.forEach(preimage => {
193
- preimageMap['<' + preimage.digest.replace('(', '_preimage(') + '>'] =
194
- '<' + preimage.preimage + '>';
195
- });
196
- //convert the pubkeys in signatures into [{['<sig(@0)>']: '30450221'}, ...]
197
- //get the keyExpressions: @0, @1 from the keys in expansionMap
198
- const expandedSignatureMap = {};
199
- signatures.forEach(signature => {
200
- const pubkeyHex = (0, uint8array_tools_1.toHex)(signature.pubkey);
201
- const keyExpression = Object.keys(expansionMap).find(k => expansionMap[k]?.pubkey && (0, uint8array_tools_1.toHex)(expansionMap[k].pubkey) === pubkeyHex);
202
- expandedSignatureMap['<sig(' + keyExpression + ')>'] =
203
- '<' + (0, uint8array_tools_1.toHex)(signature.signature) + '>';
204
- });
205
- const expandedKnownsMap = { ...preimageMap, ...expandedSignatureMap };
206
- const knowns = Object.keys(expandedKnownsMap);
207
- //satisfier verifies again internally whether expandedKnownsMap with given knowns is sane
208
- const { nonMalleableSats } = (0, miniscript_1.satisfier)(expandedMiniscript, {
209
- knowns,
210
- tapscript
211
- });
212
- if (!Array.isArray(nonMalleableSats) || !nonMalleableSats[0])
213
- throw new Error(`Error: unresolvable miniscript ${expandedMiniscript}`);
214
- let sat;
215
- if (!timeConstraints) {
216
- sat = nonMalleableSats[0];
217
- }
218
- else {
219
- sat = nonMalleableSats.find(nonMalleableSat => nonMalleableSat.nSequence === timeConstraints.nSequence &&
220
- nonMalleableSat.nLockTime === timeConstraints.nLockTime);
221
- if (sat === undefined) {
222
- throw new Error(`Error: unresolvable miniscript ${expandedMiniscript}. Could not find solutions for sequence ${timeConstraints.nSequence} & locktime=${timeConstraints.nLockTime}. Signatures are applied to a hash that depends on sequence and locktime. Did you provide all the signatures wrt the signers keys declared and include all preimages?`);
223
- }
224
- }
225
- //substitute signatures and preimages:
226
- let expandedAsm = sat.asm;
227
- //replace in expandedAsm all the <sig(@0)> and <sha256_preimage(6c...33)>
228
- //to <304...01> and <107...5f> ...
229
- for (const search in expandedKnownsMap) {
230
- const replace = expandedKnownsMap[search];
231
- if (!replace || replace === '<>')
232
- throw new Error(`Error: invalid expandedKnownsMap`);
233
- expandedAsm = expandedAsm.replaceAll(search, replace);
234
- }
235
- const scriptSatisfaction = bitcoinjs_lib_1.script.fromASM(substituteAsm({ expandedAsm, expansionMap }));
236
- return {
237
- scriptSatisfaction,
238
- nLockTime: sat.nLockTime,
239
- nSequence: sat.nSequence
240
- };
241
- }
242
- /**
243
- *
244
- * Use this function instead of bitcoinjs-lib's equivalent `script.number.encode`
245
- * when encoding numbers to be compiled with `fromASM` to avoid problems.
246
- *
247
- * Motivation:
248
- *
249
- * Numbers in Bitcoin assembly code are represented in hex and in Little Endian.
250
- * Decimal: 32766 - Big endian: 0x7FFE - Little Endian: 0xFE7F.
251
- *
252
- * This function takes an integer and encodes it so that bitcoinjs-lib `fromASM`
253
- * can compile it. This is basically what bitcoinjs-lib's `script.number.encode`
254
- * does.
255
- *
256
- * Note that `fromASM` already converts integers from 1 to 16 to
257
- * OP_1 ... OP_16 {@link https://github.com/bitcoinjs/bitcoinjs-lib/blob/59b21162a2c4645c64271ca004c7a3755a3d72fb/src/script.js#L33 here}.
258
- * This is done in Bitcoin to save some bits.
259
- *
260
- * Neither this function nor `script.number.encode` convert numbers to
261
- * their op code equivalent since this is done later in `fromASM`.
262
- *
263
- * Both functions simply convert numbers to Little Endian.
264
- *
265
- * However, the `0` number is an edge case that we specially handle with this
266
- * function.
267
- *
268
- * bitcoinjs-lib's `bscript.number.encode(0)` produces an empty array.
269
- * This is what the Bitcoin interpreter does and it is what `script.number.encode` was
270
- * implemented to do.
271
- *
272
- * The problem is `bscript.number.encode(0).toString('hex')` produces an
273
- * empty string and thus it should not be used to serialize number zero before `fromASM`.
274
- *
275
- * A zero should produce the OP_0 ASM symbolic code (corresponding to a `0` when
276
- * compiled).
277
- *
278
- * So, this function will produce a string in hex format in Little Endian
279
- * encoding for integers not equal to `0` and it will return `OP_0` for `0`.
280
- *
281
- * Read more about the this {@link https://github.com/bitcoinjs/bitcoinjs-lib/issues/1799#issuecomment-1122591738 here}.
282
- *
283
- * Use it in combination with `fromASM` like this:
284
- *
285
- * ```javascript
286
- * //To produce "0 1 OP_ADD":
287
- * fromASM(
288
- * `${numberEncodeAsm(0)} ${numberEncodeAsm(1)} OP_ADD`
289
- * .trim().replace(/\s+/g, ' ')
290
- * )
291
- * ```
292
- *
293
- * @param {number} number An integer.
294
- * @returns {string} Returns `"OP_0"` for `number === 0` and a hex string representing other numbers in Little Endian encoding.
295
- */
296
- function numberEncodeAsm(number) {
297
- if (Number.isSafeInteger(number) === false) {
298
- throw new Error(`Error: invalid number ${number}`);
299
- }
300
- if (number === 0) {
301
- return 'OP_0';
302
- }
303
- else
304
- return (0, uint8array_tools_1.toHex)(bitcoinjs_lib_1.script.number.encode(number));
305
- }
@@ -1,13 +0,0 @@
1
- /**
2
- * Resolves all multipath tuple segments (for example `/<0;1>/*`) in lockstep
3
- * using the provided `change` value.
4
- *
5
- * - `/**` is first canonicalized to `/<0;1>/*`.
6
- * - All tuples in the descriptor must have the same cardinality.
7
- * - Tuple values must be strictly increasing decimal numbers.
8
- * - `change` must match one of the values in each tuple.
9
- */
10
- export declare function resolveMultipathDescriptor({ descriptor, change }: {
11
- descriptor: string;
12
- change?: number;
13
- }): string;
package/dist/multipath.js DELETED
@@ -1,76 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.resolveMultipathDescriptor = resolveMultipathDescriptor;
4
- /**
5
- * Replaces the receive/change shorthand `/**` with its canonical multipath
6
- * representation `/<0;1>/*`.
7
- */
8
- function expandReceiveChangeShorthand(descriptor) {
9
- return descriptor.replace(/\/\*\*/g, '/<0;1>/*');
10
- }
11
- /**
12
- * Parses a multipath tuple body from `<...>`.
13
- *
14
- * This implementation intentionally accepts only decimal numbers (no hardened
15
- * suffixes) and enforces strict left-to-right increase as a safety feature to
16
- * catch likely human errors such as `<1;0>`.
17
- */
18
- function parseMultipathTuple(tupleBody) {
19
- const parts = tupleBody.split(';');
20
- if (parts.length < 2)
21
- throw new Error(`Error: multipath tuple must contain at least 2 values, got <${tupleBody}>`);
22
- const values = parts.map(part => {
23
- if (!/^(0|[1-9]\d*)$/.test(part))
24
- throw new Error(`Error: multipath tuple values must be decimal numbers, got <${tupleBody}>`);
25
- const value = Number(part);
26
- if (!Number.isSafeInteger(value))
27
- throw new Error(`Error: multipath tuple value overflow, got <${tupleBody}>`);
28
- return value;
29
- });
30
- for (let i = 1; i < values.length; i++) {
31
- const prev = values[i - 1];
32
- const current = values[i];
33
- if (prev === undefined || current === undefined)
34
- throw new Error(`Error: invalid multipath tuple <${tupleBody}>`);
35
- if (current <= prev)
36
- throw new Error(`Error: multipath tuple values must be strictly increasing from left to right, got <${tupleBody}>`);
37
- }
38
- return values;
39
- }
40
- /**
41
- * Resolves all multipath tuple segments (for example `/<0;1>/*`) in lockstep
42
- * using the provided `change` value.
43
- *
44
- * - `/**` is first canonicalized to `/<0;1>/*`.
45
- * - All tuples in the descriptor must have the same cardinality.
46
- * - Tuple values must be strictly increasing decimal numbers.
47
- * - `change` must match one of the values in each tuple.
48
- */
49
- function resolveMultipathDescriptor({ descriptor, change }) {
50
- const canonicalDescriptor = expandReceiveChangeShorthand(descriptor);
51
- const tupleMatches = Array.from(canonicalDescriptor.matchAll(/\/<([^<>]+)>/g), match => ({
52
- token: match[0],
53
- tupleBody: match[1],
54
- values: parseMultipathTuple(match[1])
55
- }));
56
- if (tupleMatches.length === 0)
57
- return canonicalDescriptor;
58
- if (change === undefined)
59
- throw new Error(`Error: change was not provided for multipath descriptor`);
60
- if (!Number.isInteger(change) || change < 0)
61
- throw new Error(`Error: invalid change ${change}`);
62
- const tupleSize = tupleMatches[0]?.values.length;
63
- if (!tupleSize)
64
- throw new Error(`Error: invalid multipath tuple`);
65
- for (const tupleMatch of tupleMatches) {
66
- if (tupleMatch.values.length !== tupleSize)
67
- throw new Error(`Error: all multipath tuples must have the same number of options`);
68
- }
69
- let resolvedDescriptor = canonicalDescriptor;
70
- for (const tupleMatch of tupleMatches) {
71
- if (!tupleMatch.values.includes(change))
72
- throw new Error(`Error: change ${change} not found in multipath tuple <${tupleMatch.tupleBody}>`);
73
- resolvedDescriptor = resolvedDescriptor.replaceAll(tupleMatch.token, `/${change}`);
74
- }
75
- return resolvedDescriptor;
76
- }
@@ -1,3 +0,0 @@
1
- import type { Network } from 'bitcoinjs-lib';
2
- export declare function isBitcoinMainnet(network: Network): boolean;
3
- export declare function coinTypeFromNetwork(network: Network): 0 | 1;
@@ -1,16 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isBitcoinMainnet = isBitcoinMainnet;
4
- exports.coinTypeFromNetwork = coinTypeFromNetwork;
5
- const bitcoinjs_lib_1 = require("bitcoinjs-lib");
6
- function isBitcoinMainnet(network) {
7
- return (network.bech32 === bitcoinjs_lib_1.networks.bitcoin.bech32 &&
8
- network.bip32.public === bitcoinjs_lib_1.networks.bitcoin.bip32.public &&
9
- network.bip32.private === bitcoinjs_lib_1.networks.bitcoin.bip32.private &&
10
- network.pubKeyHash === bitcoinjs_lib_1.networks.bitcoin.pubKeyHash &&
11
- network.scriptHash === bitcoinjs_lib_1.networks.bitcoin.scriptHash &&
12
- network.wif === bitcoinjs_lib_1.networks.bitcoin.wif);
13
- }
14
- function coinTypeFromNetwork(network) {
15
- return isBitcoinMainnet(network) ? 0 : 1;
16
- }
@@ -1,7 +0,0 @@
1
- export declare function splitTopLevelComma({ expression, onError }: {
2
- expression: string;
3
- onError: (expression: string) => Error;
4
- }): {
5
- left: string;
6
- right: string;
7
- } | null;
@@ -1,46 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.splitTopLevelComma = splitTopLevelComma;
4
- function splitTopLevelComma({ expression, onError }) {
5
- let braceDepth = 0;
6
- let parenDepth = 0;
7
- let commaIndex = -1;
8
- for (let i = 0; i < expression.length; i++) {
9
- const char = expression[i];
10
- if (!char)
11
- continue;
12
- if (char === '{') {
13
- braceDepth++;
14
- }
15
- else if (char === '}') {
16
- if (braceDepth === 0)
17
- throw onError(expression);
18
- braceDepth--;
19
- }
20
- else if (char === '(') {
21
- //Track miniscript argument lists so we don't split on commas inside them.
22
- parenDepth++;
23
- }
24
- else if (char === ')') {
25
- if (parenDepth === 0)
26
- throw onError(expression);
27
- parenDepth--;
28
- }
29
- else if (char === ',') {
30
- if (braceDepth === 0 && parenDepth === 0) {
31
- if (commaIndex !== -1)
32
- throw onError(expression);
33
- commaIndex = i;
34
- }
35
- }
36
- }
37
- if (braceDepth !== 0 || parenDepth !== 0)
38
- throw onError(expression);
39
- if (commaIndex === -1)
40
- return null;
41
- const left = expression.slice(0, commaIndex).trim();
42
- const right = expression.slice(commaIndex + 1).trim();
43
- if (!left || !right)
44
- throw onError(expression);
45
- return { left, right };
46
- }
package/dist/psbt.d.ts DELETED
@@ -1,44 +0,0 @@
1
- import type { PsbtInput, TapBip32Derivation, TapLeafScript } from 'bip174';
2
- import type { KeyInfo } from './types';
3
- import { Network, Psbt } from 'bitcoinjs-lib';
4
- /**
5
- * This function must do two things:
6
- * 1. Check if the `input` can be finalized. If it can not be finalized, throw.
7
- * ie. `Can not finalize input #${inputIndex}`
8
- * 2. Create finalScriptSig and finalScriptWitness.
9
- */
10
- type FinalScriptsFunc = (inputIndex: number, // Which input is it?
11
- input: PsbtInput, // The PSBT input contents
12
- script: Uint8Array, // The "meaningful" locking script (redeemScript for P2SH etc.)
13
- isSegwit: boolean, // Is it segwit?
14
- isP2SH: boolean, // Is it P2SH?
15
- isP2WSH: boolean) => {
16
- finalScriptSig: Uint8Array | undefined;
17
- finalScriptWitness: Uint8Array | undefined;
18
- };
19
- export declare function finalScriptsFuncFactory(scriptSatisfaction: Uint8Array, network: Network): FinalScriptsFunc;
20
- /**
21
- * Important: Read comments on Output.updatePsbtAsInput regarding not passing txHex
22
- */
23
- export declare function addPsbtInput({ psbt, vout, txHex, txId, value, sequence, locktime, keysInfo, scriptPubKey, isSegwit, tapInternalKey, tapLeafScript, tapBip32Derivation, witnessScript, redeemScript, rbf }: {
24
- psbt: Psbt;
25
- vout: number;
26
- txHex?: string;
27
- txId?: string;
28
- value?: bigint;
29
- sequence: number | undefined;
30
- locktime: number | undefined;
31
- keysInfo: KeyInfo[];
32
- scriptPubKey: Uint8Array;
33
- isSegwit: boolean;
34
- /** for taproot **/
35
- tapInternalKey?: Uint8Array | undefined;
36
- /** for taproot script-path **/
37
- tapLeafScript?: TapLeafScript[] | undefined;
38
- /** for taproot **/
39
- tapBip32Derivation?: TapBip32Derivation[] | undefined;
40
- witnessScript: Uint8Array | undefined;
41
- redeemScript: Uint8Array | undefined;
42
- rbf: boolean;
43
- }): number;
44
- export {};