@bitcoinerlab/descriptors 3.0.6 → 3.1.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.
- package/README.md +9 -487
- package/index.d.ts +13 -0
- package/index.js +27 -0
- package/package.json +25 -52
- package/dist/applyPR2137.d.ts +0 -2
- package/dist/applyPR2137.js +0 -153
- package/dist/bitcoinjs-lib-internals.d.ts +0 -10
- package/dist/bitcoinjs-lib-internals.js +0 -60
- package/dist/checksum.d.ts +0 -6
- package/dist/checksum.js +0 -58
- package/dist/descriptors.d.ts +0 -433
- package/dist/descriptors.js +0 -1743
- package/dist/index.d.ts +0 -21
- package/dist/index.js +0 -85
- package/dist/keyExpressions.d.ts +0 -83
- package/dist/keyExpressions.js +0 -247
- package/dist/ledger.d.ts +0 -167
- package/dist/ledger.js +0 -580
- package/dist/miniscript.d.ts +0 -123
- package/dist/miniscript.js +0 -305
- package/dist/multipath.d.ts +0 -13
- package/dist/multipath.js +0 -76
- package/dist/networkUtils.d.ts +0 -3
- package/dist/networkUtils.js +0 -16
- package/dist/parseUtils.d.ts +0 -7
- package/dist/parseUtils.js +0 -46
- package/dist/psbt.d.ts +0 -44
- package/dist/psbt.js +0 -193
- package/dist/re.d.ts +0 -31
- package/dist/re.js +0 -79
- package/dist/resourceLimits.d.ts +0 -25
- package/dist/resourceLimits.js +0 -89
- package/dist/scriptExpressions.d.ts +0 -95
- package/dist/scriptExpressions.js +0 -89
- package/dist/signers.d.ts +0 -84
- package/dist/signers.js +0 -215
- package/dist/stackResourceLimits.d.ts +0 -17
- package/dist/stackResourceLimits.js +0 -35
- package/dist/tapMiniscript.d.ts +0 -220
- package/dist/tapMiniscript.js +0 -510
- package/dist/tapTree.d.ts +0 -86
- package/dist/tapTree.js +0 -166
- package/dist/types.d.ts +0 -238
- package/dist/types.js +0 -4
package/dist/signers.d.ts
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import type { Psbt } from 'bitcoinjs-lib';
|
|
2
|
-
import type { ECPairInterface } from 'ecpair';
|
|
3
|
-
import type { BIP32Interface } from 'bip32';
|
|
4
|
-
import { LedgerManager } from './ledger';
|
|
5
|
-
/**
|
|
6
|
-
* Signs a specific input of a PSBT with an ECPair.
|
|
7
|
-
*
|
|
8
|
-
* Unlike bitcoinjs-lib's native `psbt.signInput()`, this function automatically detects
|
|
9
|
-
* if the input is a Taproot input and internally tweaks the key if needed.
|
|
10
|
-
*
|
|
11
|
-
* This behavior matches how `signInputBIP32` works, where the BIP32 node is automatically
|
|
12
|
-
* tweaked for Taproot inputs. In contrast, bitcoinjs-lib's native implementation requires
|
|
13
|
-
* manual pre-tweaking of ECPair signers for Taproot inputs.
|
|
14
|
-
*
|
|
15
|
-
* @see https://github.com/bitcoinjs/bitcoinjs-lib/pull/2137#issuecomment-2713264848
|
|
16
|
-
*
|
|
17
|
-
* @param {Object} params - The parameters object
|
|
18
|
-
* @param {Psbt} params.psbt - The PSBT to sign
|
|
19
|
-
* @param {number} params.index - The input index to sign
|
|
20
|
-
* @param {ECPairInterface} params.ecpair - The ECPair to sign with
|
|
21
|
-
*/
|
|
22
|
-
export declare function signInputECPair({ psbt, index, ecpair }: {
|
|
23
|
-
psbt: Psbt;
|
|
24
|
-
index: number;
|
|
25
|
-
ecpair: ECPairInterface;
|
|
26
|
-
}): void;
|
|
27
|
-
/**
|
|
28
|
-
* Signs all inputs of a PSBT with an ECPair.
|
|
29
|
-
*
|
|
30
|
-
* This function improves upon bitcoinjs-lib's native `psbt.signAllInputs()` by automatically
|
|
31
|
-
* handling Taproot inputs. For each input, it detects if it's a Taproot input and internally
|
|
32
|
-
* tweaks the key if needed.
|
|
33
|
-
*
|
|
34
|
-
* This creates consistency with the BIP32 signing methods (`signBIP32`/`signInputBIP32`),
|
|
35
|
-
* which also automatically handle key tweaking for Taproot inputs. In contrast, bitcoinjs-lib's
|
|
36
|
-
* native implementation requires users to manually pre-tweak ECPair signers for Taproot inputs.
|
|
37
|
-
*
|
|
38
|
-
* With this implementation, you can use a single ECPair to sign both Taproot and non-Taproot
|
|
39
|
-
* inputs in the same PSBT, similar to how `signBIP32` allows using a common node for both types.
|
|
40
|
-
*
|
|
41
|
-
* @see https://github.com/bitcoinjs/bitcoinjs-lib/pull/2137#issuecomment-2713264848
|
|
42
|
-
*
|
|
43
|
-
* @param {Object} params - The parameters object
|
|
44
|
-
* @param {Psbt} params.psbt - The PSBT to sign
|
|
45
|
-
* @param {ECPairInterface} params.ecpair - The ECPair to sign with
|
|
46
|
-
*/
|
|
47
|
-
export declare function signECPair({ psbt, ecpair }: {
|
|
48
|
-
psbt: Psbt;
|
|
49
|
-
ecpair: ECPairInterface;
|
|
50
|
-
}): void;
|
|
51
|
-
export declare function signInputBIP32({ psbt, index, node }: {
|
|
52
|
-
psbt: Psbt;
|
|
53
|
-
index: number;
|
|
54
|
-
node: BIP32Interface;
|
|
55
|
-
}): void;
|
|
56
|
-
export declare function signBIP32({ psbt, masterNode }: {
|
|
57
|
-
psbt: Psbt;
|
|
58
|
-
masterNode: BIP32Interface;
|
|
59
|
-
}): void;
|
|
60
|
-
/**
|
|
61
|
-
* Signs an input of the `psbt` where the keys are controlled by a Ledger
|
|
62
|
-
* device.
|
|
63
|
-
*
|
|
64
|
-
* The function will throw an error if it's unable to sign the input.
|
|
65
|
-
*/
|
|
66
|
-
export declare function signInputLedger({ psbt, index, ledgerManager }: {
|
|
67
|
-
psbt: Psbt;
|
|
68
|
-
index: number;
|
|
69
|
-
ledgerManager: LedgerManager;
|
|
70
|
-
}): Promise<void>;
|
|
71
|
-
/**
|
|
72
|
-
* Signs the inputs of the `psbt` where the keys are controlled by a Ledger
|
|
73
|
-
* device.
|
|
74
|
-
*
|
|
75
|
-
* `signLedger` can sign multiple inputs of the same wallet policy in a single
|
|
76
|
-
* pass by grouping inputs by their wallet policy type before the signing
|
|
77
|
-
* process.
|
|
78
|
-
*
|
|
79
|
-
* The function will throw an error if it's unable to sign any input.
|
|
80
|
-
*/
|
|
81
|
-
export declare function signLedger({ psbt, ledgerManager }: {
|
|
82
|
-
psbt: Psbt;
|
|
83
|
-
ledgerManager: LedgerManager;
|
|
84
|
-
}): Promise<void>;
|
package/dist/signers.js
DELETED
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// Copyright (c) 2025 Jose-Luis Landabaso - https://bitcoinerlab.com
|
|
3
|
-
// Distributed under the MIT software license
|
|
4
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
-
exports.signInputECPair = signInputECPair;
|
|
6
|
-
exports.signECPair = signECPair;
|
|
7
|
-
exports.signInputBIP32 = signInputBIP32;
|
|
8
|
-
exports.signBIP32 = signBIP32;
|
|
9
|
-
exports.signInputLedger = signInputLedger;
|
|
10
|
-
exports.signLedger = signLedger;
|
|
11
|
-
const bitcoinjs_lib_internals_1 = require("./bitcoinjs-lib-internals");
|
|
12
|
-
const ledger_1 = require("./ledger");
|
|
13
|
-
const applyPR2137_1 = require("./applyPR2137");
|
|
14
|
-
function range(n) {
|
|
15
|
-
return [...Array(n).keys()];
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Signs a specific input of a PSBT with an ECPair.
|
|
19
|
-
*
|
|
20
|
-
* Unlike bitcoinjs-lib's native `psbt.signInput()`, this function automatically detects
|
|
21
|
-
* if the input is a Taproot input and internally tweaks the key if needed.
|
|
22
|
-
*
|
|
23
|
-
* This behavior matches how `signInputBIP32` works, where the BIP32 node is automatically
|
|
24
|
-
* tweaked for Taproot inputs. In contrast, bitcoinjs-lib's native implementation requires
|
|
25
|
-
* manual pre-tweaking of ECPair signers for Taproot inputs.
|
|
26
|
-
*
|
|
27
|
-
* @see https://github.com/bitcoinjs/bitcoinjs-lib/pull/2137#issuecomment-2713264848
|
|
28
|
-
*
|
|
29
|
-
* @param {Object} params - The parameters object
|
|
30
|
-
* @param {Psbt} params.psbt - The PSBT to sign
|
|
31
|
-
* @param {number} params.index - The input index to sign
|
|
32
|
-
* @param {ECPairInterface} params.ecpair - The ECPair to sign with
|
|
33
|
-
*/
|
|
34
|
-
function signInputECPair({ psbt, index, ecpair }) {
|
|
35
|
-
//psbt.signInput(index, ecpair); <- Replaced for the code below
|
|
36
|
-
//that can handle taproot inputs automatically.
|
|
37
|
-
//See https://github.com/bitcoinjs/bitcoinjs-lib/pull/2137#issuecomment-2713264848
|
|
38
|
-
const input = psbt.data.inputs[index];
|
|
39
|
-
if (!input)
|
|
40
|
-
throw new Error('Invalid index');
|
|
41
|
-
if ((0, bitcoinjs_lib_internals_1.isTaprootInput)(input)) {
|
|
42
|
-
// If script-path (tapLeafScript present) -> DO NOT TWEAK
|
|
43
|
-
if (input.tapLeafScript && input.tapLeafScript.length > 0)
|
|
44
|
-
psbt.signInput(index, ecpair);
|
|
45
|
-
else {
|
|
46
|
-
const hash = (0, bitcoinjs_lib_internals_1.tapTweakHash)(ecpair.publicKey.slice(1, 33), undefined);
|
|
47
|
-
const tweakedEcpair = ecpair.tweak(hash);
|
|
48
|
-
psbt.signInput(index, tweakedEcpair);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
else
|
|
52
|
-
psbt.signInput(index, ecpair);
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Signs all inputs of a PSBT with an ECPair.
|
|
56
|
-
*
|
|
57
|
-
* This function improves upon bitcoinjs-lib's native `psbt.signAllInputs()` by automatically
|
|
58
|
-
* handling Taproot inputs. For each input, it detects if it's a Taproot input and internally
|
|
59
|
-
* tweaks the key if needed.
|
|
60
|
-
*
|
|
61
|
-
* This creates consistency with the BIP32 signing methods (`signBIP32`/`signInputBIP32`),
|
|
62
|
-
* which also automatically handle key tweaking for Taproot inputs. In contrast, bitcoinjs-lib's
|
|
63
|
-
* native implementation requires users to manually pre-tweak ECPair signers for Taproot inputs.
|
|
64
|
-
*
|
|
65
|
-
* With this implementation, you can use a single ECPair to sign both Taproot and non-Taproot
|
|
66
|
-
* inputs in the same PSBT, similar to how `signBIP32` allows using a common node for both types.
|
|
67
|
-
*
|
|
68
|
-
* @see https://github.com/bitcoinjs/bitcoinjs-lib/pull/2137#issuecomment-2713264848
|
|
69
|
-
*
|
|
70
|
-
* @param {Object} params - The parameters object
|
|
71
|
-
* @param {Psbt} params.psbt - The PSBT to sign
|
|
72
|
-
* @param {ECPairInterface} params.ecpair - The ECPair to sign with
|
|
73
|
-
*/
|
|
74
|
-
function signECPair({ psbt, ecpair }) {
|
|
75
|
-
//psbt.signAllInputs(ecpair); <- replaced for the code below that handles
|
|
76
|
-
//taptoot automatically.
|
|
77
|
-
//See https://github.com/bitcoinjs/bitcoinjs-lib/pull/2137#issuecomment-2713264848
|
|
78
|
-
const results = [];
|
|
79
|
-
for (const index of range(psbt.data.inputs.length)) {
|
|
80
|
-
try {
|
|
81
|
-
signInputECPair({ psbt, index, ecpair });
|
|
82
|
-
results.push(true);
|
|
83
|
-
}
|
|
84
|
-
catch (err) {
|
|
85
|
-
void err;
|
|
86
|
-
results.push(false);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
if (results.every(v => v === false)) {
|
|
90
|
-
throw new Error('No inputs were signed');
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
function signInputBIP32({ psbt, index, node }) {
|
|
94
|
-
(0, applyPR2137_1.applyPR2137)(psbt);
|
|
95
|
-
psbt.signInputHD(index, node);
|
|
96
|
-
}
|
|
97
|
-
function signBIP32({ psbt, masterNode }) {
|
|
98
|
-
(0, applyPR2137_1.applyPR2137)(psbt);
|
|
99
|
-
psbt.signAllInputsHD(masterNode);
|
|
100
|
-
}
|
|
101
|
-
const ledgerSignaturesForInputIndex = (index, ledgerSignatures) => ledgerSignatures
|
|
102
|
-
.filter(([i]) => i === index)
|
|
103
|
-
.map(([_i, partialSignature]) => partialSignature);
|
|
104
|
-
function addLedgerSignaturesToInput({ psbt, index, ledgerSignatures }) {
|
|
105
|
-
const input = psbt.data.inputs[index];
|
|
106
|
-
if (!input)
|
|
107
|
-
throw new Error(`Error: input ${index} not available`);
|
|
108
|
-
const signatures = ledgerSignaturesForInputIndex(index, ledgerSignatures);
|
|
109
|
-
if (signatures.length === 0)
|
|
110
|
-
throw new Error(`Error: no ledger signatures found for input ${index}`);
|
|
111
|
-
if ((0, bitcoinjs_lib_internals_1.isTaprootInput)(input)) {
|
|
112
|
-
// Ledger returns per-input signatures as [pubkey, signature, tapleafHash?].
|
|
113
|
-
// For taproot we must map them to PSBT taproot fields (not partialSig):
|
|
114
|
-
// - signatures with tapleafHash -> tapScriptSig[] (script-path)
|
|
115
|
-
// - signature without tapleafHash -> tapKeySig (key-path)
|
|
116
|
-
// A taproot input may contain script-path signatures, key-path signature,
|
|
117
|
-
// or both in edge cases; each must be written to its corresponding field.
|
|
118
|
-
const tapScriptSig = signatures
|
|
119
|
-
.filter((sig) => sig.tapleafHash)
|
|
120
|
-
.map((sig) => ({
|
|
121
|
-
pubkey: sig.pubkey,
|
|
122
|
-
signature: sig.signature,
|
|
123
|
-
leafHash: sig.tapleafHash
|
|
124
|
-
}));
|
|
125
|
-
const tapKeySigs = signatures.filter((sig) => !sig.tapleafHash);
|
|
126
|
-
if (tapScriptSig.length > 0) {
|
|
127
|
-
psbt.updateInput(index, { tapScriptSig });
|
|
128
|
-
}
|
|
129
|
-
if (tapKeySigs.length > 1)
|
|
130
|
-
throw new Error(`Error: expected at most one tapKeySig for input ${index}`);
|
|
131
|
-
const tapKeySig = tapKeySigs[0]?.signature;
|
|
132
|
-
if (tapKeySig) {
|
|
133
|
-
psbt.updateInput(index, { tapKeySig });
|
|
134
|
-
}
|
|
135
|
-
if (tapScriptSig.length === 0 && !tapKeySig)
|
|
136
|
-
throw new Error(`Error: no valid taproot ledger signatures found for input ${index}`);
|
|
137
|
-
}
|
|
138
|
-
else {
|
|
139
|
-
const partialSig = signatures.map((sig) => ({
|
|
140
|
-
pubkey: sig.pubkey,
|
|
141
|
-
signature: sig.signature
|
|
142
|
-
}));
|
|
143
|
-
psbt.updateInput(index, { partialSig });
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
async function signInputLedger({ psbt, index, ledgerManager }) {
|
|
147
|
-
const { ledgerClient } = ledgerManager;
|
|
148
|
-
const { DefaultWalletPolicy, WalletPolicy, AppClient } = (await (0, ledger_1.importAndValidateLedgerBitcoin)(ledgerClient));
|
|
149
|
-
if (!(ledgerClient instanceof AppClient))
|
|
150
|
-
throw new Error(`Error: pass a valid ledgerClient`);
|
|
151
|
-
const policy = await (0, ledger_1.ledgerPolicyFromPsbtInput)({
|
|
152
|
-
psbt,
|
|
153
|
-
index,
|
|
154
|
-
ledgerManager
|
|
155
|
-
});
|
|
156
|
-
if (!policy)
|
|
157
|
-
throw new Error(`Error: the ledger cannot sign this pstb input`);
|
|
158
|
-
let ledgerSignatures;
|
|
159
|
-
if (policy.policyName && policy.policyHmac && policy.policyId) {
|
|
160
|
-
//non-standard policy
|
|
161
|
-
const walletPolicy = new WalletPolicy(policy.policyName, policy.ledgerTemplate, policy.keyRoots);
|
|
162
|
-
const walletHmac = policy.policyHmac;
|
|
163
|
-
ledgerSignatures = await ledgerClient.signPsbt(psbt.toBase64(), walletPolicy, walletHmac);
|
|
164
|
-
}
|
|
165
|
-
else {
|
|
166
|
-
//standard policy
|
|
167
|
-
ledgerSignatures = await ledgerClient.signPsbt(psbt.toBase64(), new DefaultWalletPolicy(policy.ledgerTemplate, policy.keyRoots[0]), null);
|
|
168
|
-
}
|
|
169
|
-
addLedgerSignaturesToInput({ psbt, index, ledgerSignatures });
|
|
170
|
-
}
|
|
171
|
-
async function signLedger({ psbt, ledgerManager }) {
|
|
172
|
-
const { ledgerClient } = ledgerManager;
|
|
173
|
-
const { DefaultWalletPolicy, WalletPolicy, AppClient } = (await (0, ledger_1.importAndValidateLedgerBitcoin)(ledgerClient));
|
|
174
|
-
if (!(ledgerClient instanceof AppClient))
|
|
175
|
-
throw new Error(`Error: pass a valid ledgerClient`);
|
|
176
|
-
const ledgerPolicies = [];
|
|
177
|
-
for (let index = 0; index < psbt.data.inputs.length; index++) {
|
|
178
|
-
const policy = await (0, ledger_1.ledgerPolicyFromPsbtInput)({
|
|
179
|
-
psbt,
|
|
180
|
-
index,
|
|
181
|
-
ledgerManager
|
|
182
|
-
});
|
|
183
|
-
if (policy)
|
|
184
|
-
ledgerPolicies.push(policy);
|
|
185
|
-
}
|
|
186
|
-
if (ledgerPolicies.length === 0)
|
|
187
|
-
throw new Error(`Error: there are no inputs which could be signed`);
|
|
188
|
-
//cluster unique LedgerPolicies
|
|
189
|
-
const uniquePolicies = [];
|
|
190
|
-
for (const policy of ledgerPolicies) {
|
|
191
|
-
if (!uniquePolicies.find((uniquePolicy) => (0, ledger_1.comparePolicies)(uniquePolicy, policy)))
|
|
192
|
-
uniquePolicies.push(policy);
|
|
193
|
-
}
|
|
194
|
-
for (const uniquePolicy of uniquePolicies) {
|
|
195
|
-
let ledgerSignatures;
|
|
196
|
-
if (uniquePolicy.policyName &&
|
|
197
|
-
uniquePolicy.policyHmac &&
|
|
198
|
-
uniquePolicy.policyId) {
|
|
199
|
-
//non-standard policy
|
|
200
|
-
const walletPolicy = new WalletPolicy(uniquePolicy.policyName, uniquePolicy.ledgerTemplate, uniquePolicy.keyRoots);
|
|
201
|
-
const walletHmac = uniquePolicy.policyHmac;
|
|
202
|
-
ledgerSignatures = await ledgerClient.signPsbt(psbt.toBase64(), walletPolicy, walletHmac);
|
|
203
|
-
}
|
|
204
|
-
else {
|
|
205
|
-
//standard policy
|
|
206
|
-
ledgerSignatures = await ledgerClient.signPsbt(psbt.toBase64(), new DefaultWalletPolicy(uniquePolicy.ledgerTemplate, uniquePolicy.keyRoots[0]), null);
|
|
207
|
-
}
|
|
208
|
-
const signedIndexes = [
|
|
209
|
-
...new Set(ledgerSignatures.map(([index]) => index))
|
|
210
|
-
];
|
|
211
|
-
for (const index of signedIndexes) {
|
|
212
|
-
addLedgerSignaturesToInput({ psbt, index, ledgerSignatures });
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export declare const MAX_STACK_SIZE = 1000;
|
|
2
|
-
export declare const MAX_SCRIPT_ELEMENT_SIZE = 520;
|
|
3
|
-
export declare function assertConsensusStackResourceLimits({ stackItems, stackLabel, stackItemLabel }: {
|
|
4
|
-
stackItems: Uint8Array[];
|
|
5
|
-
stackLabel?: string;
|
|
6
|
-
stackItemLabel?: string;
|
|
7
|
-
}): void;
|
|
8
|
-
export declare function assertStandardPolicyStackItemCountLimit({ stackItems, maxStackItems, stackLabel }: {
|
|
9
|
-
stackItems: Uint8Array[];
|
|
10
|
-
maxStackItems: number;
|
|
11
|
-
stackLabel: string;
|
|
12
|
-
}): void;
|
|
13
|
-
export declare function assertStandardPolicyStackItemSizeLimit({ stackItems, maxStackItemSize, stackItemLabel }: {
|
|
14
|
-
stackItems: Uint8Array[];
|
|
15
|
-
maxStackItemSize: number;
|
|
16
|
-
stackItemLabel: string;
|
|
17
|
-
}): void;
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// Copyright (c) 2026 Jose-Luis Landabaso
|
|
3
|
-
// Distributed under the MIT software license
|
|
4
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
-
exports.MAX_SCRIPT_ELEMENT_SIZE = exports.MAX_STACK_SIZE = void 0;
|
|
6
|
-
exports.assertConsensusStackResourceLimits = assertConsensusStackResourceLimits;
|
|
7
|
-
exports.assertStandardPolicyStackItemCountLimit = assertStandardPolicyStackItemCountLimit;
|
|
8
|
-
exports.assertStandardPolicyStackItemSizeLimit = assertStandardPolicyStackItemSizeLimit;
|
|
9
|
-
// See Sipa's Miniscript "Resource limitations":
|
|
10
|
-
// https://bitcoin.sipa.be/miniscript/
|
|
11
|
-
// and Bitcoin Core policy/consensus constants.
|
|
12
|
-
// Consensus: max number of elements in initial stack (and stack+altstack after
|
|
13
|
-
// each opcode execution).
|
|
14
|
-
exports.MAX_STACK_SIZE = 1000;
|
|
15
|
-
// Consensus: max size for any pushed stack element. This is an element limit,
|
|
16
|
-
// not a full script-size limit.
|
|
17
|
-
exports.MAX_SCRIPT_ELEMENT_SIZE = 520;
|
|
18
|
-
function assertConsensusStackResourceLimits({ stackItems, stackLabel = 'stack', stackItemLabel = 'stack item' }) {
|
|
19
|
-
if (stackItems.length > exports.MAX_STACK_SIZE)
|
|
20
|
-
throw new Error(`Error: ${stackLabel} has too many items, ${stackItems.length} is larger than ${exports.MAX_STACK_SIZE}`);
|
|
21
|
-
for (const stackItem of stackItems) {
|
|
22
|
-
if (stackItem.length > exports.MAX_SCRIPT_ELEMENT_SIZE)
|
|
23
|
-
throw new Error(`Error: ${stackItemLabel} is too large, ${stackItem.length} bytes is larger than ${exports.MAX_SCRIPT_ELEMENT_SIZE} bytes`);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
function assertStandardPolicyStackItemCountLimit({ stackItems, maxStackItems, stackLabel }) {
|
|
27
|
-
if (stackItems.length > maxStackItems)
|
|
28
|
-
throw new Error(`Error: ${stackLabel} has too many items, ${stackItems.length} is larger than ${maxStackItems}`);
|
|
29
|
-
}
|
|
30
|
-
function assertStandardPolicyStackItemSizeLimit({ stackItems, maxStackItemSize, stackItemLabel }) {
|
|
31
|
-
for (const stackItem of stackItems) {
|
|
32
|
-
if (stackItem.length > maxStackItemSize)
|
|
33
|
-
throw new Error(`Error: ${stackItemLabel} exceeds standard policy, ${stackItem.length} bytes is larger than ${maxStackItemSize} bytes`);
|
|
34
|
-
}
|
|
35
|
-
}
|
package/dist/tapMiniscript.d.ts
DELETED
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
import { Network } from 'bitcoinjs-lib';
|
|
2
|
-
import type { BIP32API } from 'bip32';
|
|
3
|
-
import type { ECPairAPI } from 'ecpair';
|
|
4
|
-
import type { PartialSig, TapBip32Derivation } from 'bip174';
|
|
5
|
-
import type { ExpansionMap, KeyInfo, Preimage, TimeConstraints } from './types';
|
|
6
|
-
import type { TapLeafInfo, TapTreeInfoNode, TapTreeNode } from './tapTree';
|
|
7
|
-
type BitcoinJsTapleaf = {
|
|
8
|
-
output: Uint8Array;
|
|
9
|
-
version?: number;
|
|
10
|
-
};
|
|
11
|
-
type Taptree = [Taptree | BitcoinJsTapleaf, Taptree | BitcoinJsTapleaf] | BitcoinJsTapleaf;
|
|
12
|
-
export type TapLeafExpansionOverride = {
|
|
13
|
-
expandedExpression: string;
|
|
14
|
-
expansionMap: ExpansionMap;
|
|
15
|
-
tapScript: Uint8Array;
|
|
16
|
-
};
|
|
17
|
-
export type TaprootLeafSatisfaction = {
|
|
18
|
-
leaf: TapLeafInfo;
|
|
19
|
-
depth: number;
|
|
20
|
-
tapLeafHash: Uint8Array;
|
|
21
|
-
scriptSatisfaction: Uint8Array;
|
|
22
|
-
stackItems: Uint8Array[];
|
|
23
|
-
nLockTime: number | undefined;
|
|
24
|
-
nSequence: number | undefined;
|
|
25
|
-
totalWitnessSize: number;
|
|
26
|
-
};
|
|
27
|
-
export type TaprootPsbtLeafMetadata = {
|
|
28
|
-
leaf: TapLeafInfo;
|
|
29
|
-
depth: number;
|
|
30
|
-
tapLeafHash: Uint8Array;
|
|
31
|
-
controlBlock: Uint8Array;
|
|
32
|
-
};
|
|
33
|
-
/**
|
|
34
|
-
* Compiles a taproot miniscript tree into per-leaf metadata.
|
|
35
|
-
* Each leaf contains expanded expression metadata, key expansion map,
|
|
36
|
-
* compiled tapscript and leaf version. This keeps the taproot script-path data
|
|
37
|
-
* ready for satisfactions and witness building.
|
|
38
|
-
*
|
|
39
|
-
* `leafExpansionOverride` allows descriptor-level script expressions to provide:
|
|
40
|
-
* - user-facing expanded expression metadata (for selector/template use), and
|
|
41
|
-
* - custom expansion map and tapscript bytes for compilation.
|
|
42
|
-
*
|
|
43
|
-
* Example: sortedmulti_a can expose `expandedExpression=sortedmulti_a(...)`
|
|
44
|
-
* while providing a tapscript already compiled.
|
|
45
|
-
*/
|
|
46
|
-
export declare function buildTapTreeInfo({ tapTree, network, BIP32, ECPair, leafExpansionOverride }: {
|
|
47
|
-
tapTree: TapTreeNode;
|
|
48
|
-
network?: Network;
|
|
49
|
-
BIP32: BIP32API;
|
|
50
|
-
ECPair: ECPairAPI;
|
|
51
|
-
leafExpansionOverride: (expression: string) => TapLeafExpansionOverride | undefined;
|
|
52
|
-
}): TapTreeInfoNode;
|
|
53
|
-
export declare function tapTreeInfoToScriptTree(tapTreeInfo: TapTreeInfoNode): Taptree;
|
|
54
|
-
/**
|
|
55
|
-
* Builds taproot PSBT leaf metadata for every leaf in a `tapTreeInfo`.
|
|
56
|
-
*
|
|
57
|
-
* For each leaf, this function computes:
|
|
58
|
-
* - `tapLeafHash`: BIP341 leaf hash of tapscript + leaf version
|
|
59
|
-
* - `depth`: leaf depth in the tree (root children have depth 1)
|
|
60
|
-
* - `controlBlock`: script-path proof used in PSBT `tapLeafScript`
|
|
61
|
-
*
|
|
62
|
-
* The control block layout is:
|
|
63
|
-
*
|
|
64
|
-
* ```text
|
|
65
|
-
* [1-byte (leafVersion | parity)] [32-byte internal key]
|
|
66
|
-
* [32-byte sibling hash #1] ... [32-byte sibling hash #N]
|
|
67
|
-
* ```
|
|
68
|
-
*
|
|
69
|
-
* where:
|
|
70
|
-
* - `parity` is derived from tweaking the internal key with the tree root
|
|
71
|
-
* - sibling hashes are the merkle path from that leaf to the root
|
|
72
|
-
*
|
|
73
|
-
* Example tree:
|
|
74
|
-
*
|
|
75
|
-
* ```text
|
|
76
|
-
* root
|
|
77
|
-
* / \
|
|
78
|
-
* L1 L2
|
|
79
|
-
* / \
|
|
80
|
-
* L3 L4
|
|
81
|
-
* ```
|
|
82
|
-
*
|
|
83
|
-
* Depths:
|
|
84
|
-
* - L1 depth = 1
|
|
85
|
-
* - L3 depth = 2
|
|
86
|
-
* - L4 depth = 2
|
|
87
|
-
*
|
|
88
|
-
* Conceptual output:
|
|
89
|
-
*
|
|
90
|
-
* ```text
|
|
91
|
-
* [
|
|
92
|
-
* L1 -> { depth: 1, tapLeafHash: h1, controlBlock: [v|p, ik, hash(L2)] }
|
|
93
|
-
* L3 -> { depth: 2, tapLeafHash: h3, controlBlock: [v|p, ik, hash(L4), hash(L1)] }
|
|
94
|
-
* L4 -> { depth: 2, tapLeafHash: h4, controlBlock: [v|p, ik, hash(L3), hash(L1)] }
|
|
95
|
-
* ]
|
|
96
|
-
* ```
|
|
97
|
-
*
|
|
98
|
-
* Legend:
|
|
99
|
-
* - `ik`: the 32-byte internal key placed in the control block.
|
|
100
|
-
* - `hash(X)`: the merkle sibling hash at each level when proving leaf `X`.
|
|
101
|
-
*
|
|
102
|
-
* Note: in this diagram, `L2` is a branch node (right subtree), not a leaf,
|
|
103
|
-
* so `hash(L2) = TapBranch(hash(L3), hash(L4))`.
|
|
104
|
-
*
|
|
105
|
-
* Notes:
|
|
106
|
-
* - Leaves are returned in deterministic left-first order.
|
|
107
|
-
* - One metadata entry is returned per leaf.
|
|
108
|
-
* - `controlBlock.length === 33 + 32 * depth`.
|
|
109
|
-
* - Throws if internal key is invalid or control block cannot be derived.
|
|
110
|
-
*
|
|
111
|
-
* Typical usage:
|
|
112
|
-
* - Convert this metadata into PSBT `tapLeafScript[]` entries
|
|
113
|
-
* for all leaves.
|
|
114
|
-
*/
|
|
115
|
-
export declare function buildTaprootLeafPsbtMetadata({ tapTreeInfo, internalPubkey }: {
|
|
116
|
-
tapTreeInfo: TapTreeInfoNode;
|
|
117
|
-
internalPubkey: Uint8Array;
|
|
118
|
-
}): TaprootPsbtLeafMetadata[];
|
|
119
|
-
/**
|
|
120
|
-
* Builds PSBT `tapBip32Derivation` entries for taproot script-path spends.
|
|
121
|
-
*
|
|
122
|
-
* Leaf keys include the list of tapleaf hashes where they appear.
|
|
123
|
-
* If `internalKeyInfo` has derivation data, it is included with empty
|
|
124
|
-
* `leafHashes`.
|
|
125
|
-
*
|
|
126
|
-
* Example tree:
|
|
127
|
-
*
|
|
128
|
-
* ```text
|
|
129
|
-
* root
|
|
130
|
-
* / \
|
|
131
|
-
* L1 L2
|
|
132
|
-
*
|
|
133
|
-
* L1 uses key A
|
|
134
|
-
* L2 uses key A and key B
|
|
135
|
-
*
|
|
136
|
-
* h1 = tapleafHash(L1)
|
|
137
|
-
* h2 = tapleafHash(L2)
|
|
138
|
-
* ```
|
|
139
|
-
*
|
|
140
|
-
* Then output is conceptually:
|
|
141
|
-
*
|
|
142
|
-
* ```text
|
|
143
|
-
* [
|
|
144
|
-
* key A -> leafHashes [h1, h2]
|
|
145
|
-
* key B -> leafHashes [h2]
|
|
146
|
-
* internal key -> leafHashes []
|
|
147
|
-
* ]
|
|
148
|
-
* ```
|
|
149
|
-
*
|
|
150
|
-
* Notes:
|
|
151
|
-
* - Keys missing `masterFingerprint` or `path` are skipped.
|
|
152
|
-
* - Duplicate pubkeys are merged.
|
|
153
|
-
* - If the same pubkey appears with conflicting derivation metadata,
|
|
154
|
-
* this function throws.
|
|
155
|
-
* - Output and `leafHashes` are sorted deterministically.
|
|
156
|
-
*/
|
|
157
|
-
export declare function buildTaprootBip32Derivations({ tapTreeInfo, internalKeyInfo }: {
|
|
158
|
-
tapTreeInfo: TapTreeInfoNode;
|
|
159
|
-
internalKeyInfo?: KeyInfo;
|
|
160
|
-
}): TapBip32Derivation[];
|
|
161
|
-
export declare function normalizeTaprootPubkey(pubkey: Uint8Array): Uint8Array;
|
|
162
|
-
/**
|
|
163
|
-
* Compiles an expanded `sortedmulti_a(...)` leaf expression to its internal
|
|
164
|
-
* `multi_a(...)` form by sorting placeholders using the resolved pubkeys from
|
|
165
|
-
* `expansionMap`.
|
|
166
|
-
*/
|
|
167
|
-
export declare function compileSortedMultiAExpandedExpression({ expandedExpression, expansionMap }: {
|
|
168
|
-
expandedExpression: string;
|
|
169
|
-
expansionMap: ExpansionMap;
|
|
170
|
-
}): string;
|
|
171
|
-
/**
|
|
172
|
-
* Computes satisfactions for taproot script-path leaves.
|
|
173
|
-
*
|
|
174
|
-
* If `tapLeaf` is undefined, all satisfiable leaves are returned. If `tapLeaf`
|
|
175
|
-
* is provided, only that leaf is considered.
|
|
176
|
-
*
|
|
177
|
-
* Callers are expected to pass real signatures, or fake signatures generated
|
|
178
|
-
* during planning. See satisfyMiniscript() for how timeConstraints keep the
|
|
179
|
-
* chosen leaf consistent between planning and signing.
|
|
180
|
-
*/
|
|
181
|
-
export declare function collectTaprootLeafSatisfactions({ tapTreeInfo, preimages, signatures, timeConstraints, tapLeaf }: {
|
|
182
|
-
tapTreeInfo: TapTreeInfoNode;
|
|
183
|
-
preimages: Preimage[];
|
|
184
|
-
signatures: PartialSig[];
|
|
185
|
-
timeConstraints?: TimeConstraints;
|
|
186
|
-
tapLeaf?: Uint8Array | string;
|
|
187
|
-
}): TaprootLeafSatisfaction[];
|
|
188
|
-
/**
|
|
189
|
-
* Selects the taproot leaf satisfaction with the smallest total witness size.
|
|
190
|
-
* Assumes the input list is in left-first tree order for deterministic ties.
|
|
191
|
-
*/
|
|
192
|
-
export declare function selectBestTaprootLeafSatisfaction(satisfactions: TaprootLeafSatisfaction[]): TaprootLeafSatisfaction;
|
|
193
|
-
/**
|
|
194
|
-
* Collects a unique set of taproot leaf pubkeys (x-only) across the tree.
|
|
195
|
-
* This is useful for building fake signatures when no signer subset is given.
|
|
196
|
-
*/
|
|
197
|
-
export declare function collectTapTreePubkeys(tapTreeInfo: TapTreeInfoNode): Uint8Array[];
|
|
198
|
-
/**
|
|
199
|
-
* Returns the best satisfaction for a taproot tree, by witness size.
|
|
200
|
-
*
|
|
201
|
-
* If `tapLeaf` is provided, only that leaf is considered. If `tapLeaf` is a
|
|
202
|
-
* bytes, it is treated as a tapLeafHash and must match exactly one leaf. If
|
|
203
|
-
* `tapLeaf` is a string, it is treated as a raw leaf expression and must
|
|
204
|
-
* match exactly one leaf (whitespace-insensitive).
|
|
205
|
-
*
|
|
206
|
-
* This function is typically called twice:
|
|
207
|
-
* 1) Planning pass: call it with fake signatures (built by the caller) to
|
|
208
|
-
* choose the best leaf without requiring user signatures.
|
|
209
|
-
* 2) Signing pass: call it again with real signatures and the timeConstraints
|
|
210
|
-
* returned from the first pass (see satisfyMiniscript() for why this keeps
|
|
211
|
-
* the chosen leaf consistent between planning and signing).
|
|
212
|
-
*/
|
|
213
|
-
export declare function satisfyTapTree({ tapTreeInfo, signatures, preimages, tapLeaf, timeConstraints }: {
|
|
214
|
-
tapTreeInfo: TapTreeInfoNode;
|
|
215
|
-
signatures: PartialSig[];
|
|
216
|
-
preimages: Preimage[];
|
|
217
|
-
tapLeaf?: Uint8Array | string;
|
|
218
|
-
timeConstraints?: TimeConstraints;
|
|
219
|
-
}): TaprootLeafSatisfaction;
|
|
220
|
-
export {};
|