@bitcoinerlab/descriptors 3.0.5 → 3.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bitcoinjs-lib-internals.d.ts +10 -10
- package/dist/bitcoinjs-lib-internals.js +54 -44
- package/dist/keyExpressions.d.ts +3 -3
- package/dist/keyExpressions.js +2 -3
- package/dist/stackResourceLimits.d.ts +17 -0
- package/dist/stackResourceLimits.js +35 -0
- package/dist/tapMiniscript.d.ts +7 -2
- package/dist/tapMiniscript.js +12 -17
- package/dist/tapTree.js +0 -1
- package/dist/types.d.ts +2 -2
- package/package.json +1 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export declare
|
|
7
|
-
export declare
|
|
8
|
-
export declare
|
|
9
|
-
export declare
|
|
10
|
-
export
|
|
1
|
+
import type { PsbtInput } from 'bip174';
|
|
2
|
+
type Tapleaf = {
|
|
3
|
+
output: Uint8Array;
|
|
4
|
+
version?: number;
|
|
5
|
+
};
|
|
6
|
+
export declare function tapleafHash(leaf: Tapleaf): Uint8Array;
|
|
7
|
+
export declare function tapTweakHash(pubKey: Uint8Array, h?: Uint8Array): Uint8Array;
|
|
8
|
+
export declare function witnessStackToScriptWitness(witness: Uint8Array[]): Uint8Array;
|
|
9
|
+
export declare function isTaprootInput(input: PsbtInput | undefined): boolean;
|
|
10
|
+
export {};
|
|
@@ -1,50 +1,60 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/* eslint-disable @typescript-eslint/no-require-imports */
|
|
3
2
|
/*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* Reimplements a small subset of bitcoinjs-lib internal helpers.
|
|
4
|
+
* Keep this module free of deep imports (for example `bitcoinjs-lib/src/*`)
|
|
5
|
+
* so it works consistently across Node.js, browser bundlers (including
|
|
6
|
+
* CodeSandbox), and React Native/Metro.
|
|
6
7
|
*/
|
|
7
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
9
|
+
exports.tapleafHash = tapleafHash;
|
|
10
|
+
exports.tapTweakHash = tapTweakHash;
|
|
11
|
+
exports.witnessStackToScriptWitness = witnessStackToScriptWitness;
|
|
12
|
+
exports.isTaprootInput = isTaprootInput;
|
|
13
|
+
const bitcoinjs_lib_1 = require("bitcoinjs-lib");
|
|
14
|
+
const varuint_bitcoin_1 = require("varuint-bitcoin");
|
|
15
|
+
const uint8array_tools_1 = require("uint8array-tools");
|
|
16
|
+
const TAPROOT_LEAF_VERSION_TAPSCRIPT = 0xc0;
|
|
17
|
+
const OP_1 = 0x51;
|
|
18
|
+
const PUSH_DATA_32 = 0x20;
|
|
19
|
+
function serializeScript(script) {
|
|
20
|
+
const { buffer: encodedLength } = (0, varuint_bitcoin_1.encode)(script.length);
|
|
21
|
+
return (0, uint8array_tools_1.concat)([encodedLength, script]);
|
|
21
22
|
}
|
|
22
|
-
function
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
23
|
+
function isP2TRScript(script) {
|
|
24
|
+
return (script instanceof Uint8Array &&
|
|
25
|
+
script.length === 34 &&
|
|
26
|
+
script[0] === OP_1 &&
|
|
27
|
+
script[1] === PUSH_DATA_32);
|
|
28
|
+
}
|
|
29
|
+
function tapleafHash(leaf) {
|
|
30
|
+
const version = leaf.version || TAPROOT_LEAF_VERSION_TAPSCRIPT;
|
|
31
|
+
return bitcoinjs_lib_1.crypto.taggedHash('TapLeaf', (0, uint8array_tools_1.concat)([Uint8Array.from([version]), serializeScript(leaf.output)]));
|
|
32
|
+
}
|
|
33
|
+
function tapTweakHash(pubKey, h) {
|
|
34
|
+
return bitcoinjs_lib_1.crypto.taggedHash('TapTweak', (0, uint8array_tools_1.concat)(h ? [pubKey, h] : [pubKey]));
|
|
35
|
+
}
|
|
36
|
+
function witnessStackToScriptWitness(witness) {
|
|
37
|
+
let buffer = new Uint8Array(0);
|
|
38
|
+
const writeSlice = (slice) => {
|
|
39
|
+
buffer = (0, uint8array_tools_1.concat)([buffer, slice]);
|
|
40
|
+
};
|
|
41
|
+
const writeVarInt = (value) => {
|
|
42
|
+
const { buffer: encoded } = (0, varuint_bitcoin_1.encode)(value);
|
|
43
|
+
writeSlice(encoded);
|
|
44
|
+
};
|
|
45
|
+
const writeVarSlice = (slice) => {
|
|
46
|
+
writeVarInt(slice.length);
|
|
47
|
+
writeSlice(slice);
|
|
48
|
+
};
|
|
49
|
+
writeVarInt(witness.length);
|
|
50
|
+
witness.forEach(writeVarSlice);
|
|
51
|
+
return buffer;
|
|
52
|
+
}
|
|
53
|
+
function isTaprootInput(input) {
|
|
54
|
+
return (!!input &&
|
|
55
|
+
!!(input.tapInternalKey ||
|
|
56
|
+
input.tapMerkleRoot ||
|
|
57
|
+
(input.tapLeafScript && input.tapLeafScript.length > 0) ||
|
|
58
|
+
(input.tapBip32Derivation && input.tapBip32Derivation.length > 0) ||
|
|
59
|
+
isP2TRScript(input.witnessUtxo?.script)));
|
|
40
60
|
}
|
|
41
|
-
const bip341 = requireBitcoinJsInternal('payments/bip341');
|
|
42
|
-
const bip371 = requireBitcoinJsInternal('psbt/bip371');
|
|
43
|
-
const psbtUtils = requireBitcoinJsInternal('psbt/psbtutils');
|
|
44
|
-
exports.findScriptPath = bip341.findScriptPath;
|
|
45
|
-
exports.tapleafHash = bip341.tapleafHash;
|
|
46
|
-
exports.tapTweakHash = bip341.tapTweakHash;
|
|
47
|
-
exports.toHashTree = bip341.toHashTree;
|
|
48
|
-
exports.tweakKey = bip341.tweakKey;
|
|
49
|
-
exports.witnessStackToScriptWitness = psbtUtils.witnessStackToScriptWitness;
|
|
50
|
-
exports.isTaprootInput = bip371.isTaprootInput;
|
package/dist/keyExpressions.d.ts
CHANGED
|
@@ -49,7 +49,7 @@ export declare function parseKeyExpression({ keyExpression, isSegwit, isTaproot,
|
|
|
49
49
|
*
|
|
50
50
|
* For detailed understanding and examples of terms like `originPath`,
|
|
51
51
|
* `change`, and `keyPath`, refer to the documentation of
|
|
52
|
-
* {@link
|
|
52
|
+
* {@link KeyExpressionParser}, which consists
|
|
53
53
|
* of the reverse procedure.
|
|
54
54
|
*
|
|
55
55
|
* @returns {string} - The formed key expression for the Ledger device.
|
|
@@ -65,9 +65,9 @@ export declare function keyExpressionLedger({ ledgerManager, originPath, keyPath
|
|
|
65
65
|
* Constructs a key expression string from its constituent components.
|
|
66
66
|
*
|
|
67
67
|
* This function essentially performs the reverse operation of
|
|
68
|
-
* {@link
|
|
68
|
+
* {@link KeyExpressionParser}. For detailed
|
|
69
69
|
* explanations and examples of the terms used here, refer to
|
|
70
|
-
* {@link
|
|
70
|
+
* {@link KeyExpressionParser}.
|
|
71
71
|
*/
|
|
72
72
|
export declare function keyExpressionBIP32({ masterNode, originPath, keyPath, change, index, isPublic }: {
|
|
73
73
|
masterNode: BIP32Interface;
|
package/dist/keyExpressions.js
CHANGED
|
@@ -211,7 +211,6 @@ function assertChangeIndexKeyPath({ change, index, keyPath }) {
|
|
|
211
211
|
if ((change !== undefined) === (keyPath !== undefined))
|
|
212
212
|
throw new Error(`Error: Pass either change and index or a keyPath`);
|
|
213
213
|
}
|
|
214
|
-
/** @hidden */
|
|
215
214
|
async function keyExpressionLedger({ ledgerManager, originPath, keyPath, change, index }) {
|
|
216
215
|
assertChangeIndexKeyPath({ change, index, keyPath });
|
|
217
216
|
const masterFingerprint = await (0, ledger_1.getLedgerMasterFingerPrint)({
|
|
@@ -229,9 +228,9 @@ async function keyExpressionLedger({ ledgerManager, originPath, keyPath, change,
|
|
|
229
228
|
* Constructs a key expression string from its constituent components.
|
|
230
229
|
*
|
|
231
230
|
* This function essentially performs the reverse operation of
|
|
232
|
-
* {@link
|
|
231
|
+
* {@link KeyExpressionParser}. For detailed
|
|
233
232
|
* explanations and examples of the terms used here, refer to
|
|
234
|
-
* {@link
|
|
233
|
+
* {@link KeyExpressionParser}.
|
|
235
234
|
*/
|
|
236
235
|
function keyExpressionBIP32({ masterNode, originPath, keyPath, change, index, isPublic = true }) {
|
|
237
236
|
assertChangeIndexKeyPath({ change, index, keyPath });
|
|
@@ -0,0 +1,17 @@
|
|
|
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;
|
|
@@ -0,0 +1,35 @@
|
|
|
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
CHANGED
|
@@ -2,9 +2,13 @@ import { Network } from 'bitcoinjs-lib';
|
|
|
2
2
|
import type { BIP32API } from 'bip32';
|
|
3
3
|
import type { ECPairAPI } from 'ecpair';
|
|
4
4
|
import type { PartialSig, TapBip32Derivation } from 'bip174';
|
|
5
|
-
import type { Taptree } from 'bitcoinjs-lib/src/cjs/types';
|
|
6
5
|
import type { ExpansionMap, KeyInfo, Preimage, TimeConstraints } from './types';
|
|
7
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;
|
|
8
12
|
export type TapLeafExpansionOverride = {
|
|
9
13
|
expandedExpression: string;
|
|
10
14
|
expansionMap: ExpansionMap;
|
|
@@ -102,7 +106,7 @@ export declare function tapTreeInfoToScriptTree(tapTreeInfo: TapTreeInfoNode): T
|
|
|
102
106
|
* - Leaves are returned in deterministic left-first order.
|
|
103
107
|
* - One metadata entry is returned per leaf.
|
|
104
108
|
* - `controlBlock.length === 33 + 32 * depth`.
|
|
105
|
-
* - Throws if internal key is invalid or
|
|
109
|
+
* - Throws if internal key is invalid or control block cannot be derived.
|
|
106
110
|
*
|
|
107
111
|
* Typical usage:
|
|
108
112
|
* - Convert this metadata into PSBT `tapLeafScript[]` entries
|
|
@@ -213,3 +217,4 @@ export declare function satisfyTapTree({ tapTreeInfo, signatures, preimages, tap
|
|
|
213
217
|
tapLeaf?: Uint8Array | string;
|
|
214
218
|
timeConstraints?: TimeConstraints;
|
|
215
219
|
}): TaprootLeafSatisfaction;
|
|
220
|
+
export {};
|
package/dist/tapMiniscript.js
CHANGED
|
@@ -19,6 +19,7 @@ const miniscript_1 = require("./miniscript");
|
|
|
19
19
|
const tapTree_1 = require("./tapTree");
|
|
20
20
|
const resourceLimits_1 = require("./resourceLimits");
|
|
21
21
|
const TAPROOT_LEAF_VERSION_TAPSCRIPT = 0xc0;
|
|
22
|
+
const { p2tr } = bitcoinjs_lib_1.payments;
|
|
22
23
|
function expandTaprootMiniscript({ miniscript, network = bitcoinjs_lib_1.networks.bitcoin, BIP32, ECPair }) {
|
|
23
24
|
return (0, miniscript_1.expandMiniscript)({
|
|
24
25
|
miniscript,
|
|
@@ -173,7 +174,7 @@ function tapTreeInfoToScriptTree(tapTreeInfo) {
|
|
|
173
174
|
* - Leaves are returned in deterministic left-first order.
|
|
174
175
|
* - One metadata entry is returned per leaf.
|
|
175
176
|
* - `controlBlock.length === 33 + 32 * depth`.
|
|
176
|
-
* - Throws if internal key is invalid or
|
|
177
|
+
* - Throws if internal key is invalid or control block cannot be derived.
|
|
177
178
|
*
|
|
178
179
|
* Typical usage:
|
|
179
180
|
* - Convert this metadata into PSBT `tapLeafScript[]` entries
|
|
@@ -182,10 +183,6 @@ function tapTreeInfoToScriptTree(tapTreeInfo) {
|
|
|
182
183
|
function buildTaprootLeafPsbtMetadata({ tapTreeInfo, internalPubkey }) {
|
|
183
184
|
const normalizedInternalPubkey = normalizeTaprootPubkey(internalPubkey);
|
|
184
185
|
const scriptTree = tapTreeInfoToScriptTree(tapTreeInfo);
|
|
185
|
-
const hashTree = (0, bitcoinjs_lib_internals_1.toHashTree)(scriptTree);
|
|
186
|
-
const tweaked = (0, bitcoinjs_lib_internals_1.tweakKey)(normalizedInternalPubkey, hashTree.hash);
|
|
187
|
-
if (!tweaked)
|
|
188
|
-
throw new Error(`Error: invalid taproot internal pubkey`);
|
|
189
186
|
return (0, tapTree_1.collectTapTreeLeaves)(tapTreeInfo).map(({ leaf, depth }) => {
|
|
190
187
|
if (depth > tapTree_1.MAX_TAPTREE_DEPTH)
|
|
191
188
|
throw new Error(`Error: taproot tree depth is too large, ${depth} is larger than ${tapTree_1.MAX_TAPTREE_DEPTH}`);
|
|
@@ -193,19 +190,17 @@ function buildTaprootLeafPsbtMetadata({ tapTreeInfo, internalPubkey }) {
|
|
|
193
190
|
output: leaf.tapScript,
|
|
194
191
|
version: leaf.version
|
|
195
192
|
});
|
|
196
|
-
const
|
|
197
|
-
|
|
193
|
+
const payment = p2tr({
|
|
194
|
+
internalPubkey: normalizedInternalPubkey,
|
|
195
|
+
scriptTree,
|
|
196
|
+
redeem: {
|
|
197
|
+
output: leaf.tapScript,
|
|
198
|
+
redeemVersion: leaf.version
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
const controlBlock = payment.witness?.[1];
|
|
202
|
+
if (!controlBlock)
|
|
198
203
|
throw new Error(`Error: could not build controlBlock for taproot leaf ${leaf.expression}`);
|
|
199
|
-
// controlBlock[0] packs:
|
|
200
|
-
// - leaf version (high bits), and
|
|
201
|
-
// - parity of the tweaked output key Q = P + t*G (low bit).
|
|
202
|
-
// `normalizedInternalPubkey` is x-only P, so parity is not encoded there.
|
|
203
|
-
// BIP341 requires carrying Q parity in controlBlock[0].
|
|
204
|
-
const controlBlock = (0, uint8array_tools_1.concat)([
|
|
205
|
-
Uint8Array.from([leaf.version | tweaked.parity]),
|
|
206
|
-
normalizedInternalPubkey,
|
|
207
|
-
...merklePath
|
|
208
|
-
]);
|
|
209
204
|
return { leaf, depth, tapLeafHash, controlBlock };
|
|
210
205
|
});
|
|
211
206
|
}
|
package/dist/tapTree.js
CHANGED
|
@@ -5,7 +5,6 @@ exports.assertTapTreeDepth = assertTapTreeDepth;
|
|
|
5
5
|
exports.collectTapTreeLeaves = collectTapTreeLeaves;
|
|
6
6
|
exports.selectTapLeafCandidates = selectTapLeafCandidates;
|
|
7
7
|
exports.parseTapTreeExpression = parseTapTreeExpression;
|
|
8
|
-
// NOTE: This uses an internal bitcoinjs-lib module. Consider adding a local wrapper.
|
|
9
8
|
const bitcoinjs_lib_internals_1 = require("./bitcoinjs-lib-internals");
|
|
10
9
|
const uint8array_tools_1 = require("uint8array-tools");
|
|
11
10
|
const parseUtils_1 = require("./parseUtils");
|
package/dist/types.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import type { Payment, Network } from 'bitcoinjs-lib';
|
|
|
4
4
|
import type { TapTreeNode, TapTreeInfoNode } from './tapTree';
|
|
5
5
|
/**
|
|
6
6
|
* Preimage
|
|
7
|
-
*
|
|
7
|
+
* Preimage material used by descriptor outputs that include hashlocks.
|
|
8
8
|
*/
|
|
9
9
|
export type Preimage = {
|
|
10
10
|
/**
|
|
@@ -25,7 +25,7 @@ export type TimeConstraints = {
|
|
|
25
25
|
nSequence: number | undefined;
|
|
26
26
|
};
|
|
27
27
|
/**
|
|
28
|
-
* See {@link
|
|
28
|
+
* See {@link KeyExpressionParser}.
|
|
29
29
|
*/
|
|
30
30
|
export type KeyInfo = {
|
|
31
31
|
keyExpression: string;
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@bitcoinerlab/descriptors",
|
|
3
3
|
"description": "This library parses and creates Bitcoin Miniscript Descriptors and generates Partially Signed Bitcoin Transactions (PSBTs). It provides PSBT finalizers and signers for single-signature, BIP32 and Hardware Wallets.",
|
|
4
4
|
"homepage": "https://github.com/bitcoinerlab/descriptors",
|
|
5
|
-
"version": "3.0.
|
|
5
|
+
"version": "3.0.6",
|
|
6
6
|
"author": "Jose-Luis Landabaso",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"repository": {
|