@bitcoinerlab/descriptors 2.3.6 → 3.0.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.
@@ -0,0 +1,215 @@
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 { Taptree } from 'bitcoinjs-lib/src/cjs/types';
6
+ import type { ExpansionMap, KeyInfo, Preimage, TimeConstraints } from './types';
7
+ import type { TapLeafInfo, TapTreeInfoNode, TapTreeNode } from './tapTree';
8
+ export type TapLeafExpansionOverride = {
9
+ expandedExpression: string;
10
+ expansionMap: ExpansionMap;
11
+ tapScript: Uint8Array;
12
+ };
13
+ export type TaprootLeafSatisfaction = {
14
+ leaf: TapLeafInfo;
15
+ depth: number;
16
+ tapLeafHash: Uint8Array;
17
+ scriptSatisfaction: Uint8Array;
18
+ stackItems: Uint8Array[];
19
+ nLockTime: number | undefined;
20
+ nSequence: number | undefined;
21
+ totalWitnessSize: number;
22
+ };
23
+ export type TaprootPsbtLeafMetadata = {
24
+ leaf: TapLeafInfo;
25
+ depth: number;
26
+ tapLeafHash: Uint8Array;
27
+ controlBlock: Uint8Array;
28
+ };
29
+ /**
30
+ * Compiles a taproot miniscript tree into per-leaf metadata.
31
+ * Each leaf contains expanded expression metadata, key expansion map,
32
+ * compiled tapscript and leaf version. This keeps the taproot script-path data
33
+ * ready for satisfactions and witness building.
34
+ *
35
+ * `leafExpansionOverride` allows descriptor-level script expressions to provide:
36
+ * - user-facing expanded expression metadata (for selector/template use), and
37
+ * - custom expansion map and tapscript bytes for compilation.
38
+ *
39
+ * Example: sortedmulti_a can expose `expandedExpression=sortedmulti_a(...)`
40
+ * while providing a tapscript already compiled.
41
+ */
42
+ export declare function buildTapTreeInfo({ tapTree, network, BIP32, ECPair, leafExpansionOverride }: {
43
+ tapTree: TapTreeNode;
44
+ network?: Network;
45
+ BIP32: BIP32API;
46
+ ECPair: ECPairAPI;
47
+ leafExpansionOverride: (expression: string) => TapLeafExpansionOverride | undefined;
48
+ }): TapTreeInfoNode;
49
+ export declare function tapTreeInfoToScriptTree(tapTreeInfo: TapTreeInfoNode): Taptree;
50
+ /**
51
+ * Builds taproot PSBT leaf metadata for every leaf in a `tapTreeInfo`.
52
+ *
53
+ * For each leaf, this function computes:
54
+ * - `tapLeafHash`: BIP341 leaf hash of tapscript + leaf version
55
+ * - `depth`: leaf depth in the tree (root children have depth 1)
56
+ * - `controlBlock`: script-path proof used in PSBT `tapLeafScript`
57
+ *
58
+ * The control block layout is:
59
+ *
60
+ * ```text
61
+ * [1-byte (leafVersion | parity)] [32-byte internal key]
62
+ * [32-byte sibling hash #1] ... [32-byte sibling hash #N]
63
+ * ```
64
+ *
65
+ * where:
66
+ * - `parity` is derived from tweaking the internal key with the tree root
67
+ * - sibling hashes are the merkle path from that leaf to the root
68
+ *
69
+ * Example tree:
70
+ *
71
+ * ```text
72
+ * root
73
+ * / \
74
+ * L1 L2
75
+ * / \
76
+ * L3 L4
77
+ * ```
78
+ *
79
+ * Depths:
80
+ * - L1 depth = 1
81
+ * - L3 depth = 2
82
+ * - L4 depth = 2
83
+ *
84
+ * Conceptual output:
85
+ *
86
+ * ```text
87
+ * [
88
+ * L1 -> { depth: 1, tapLeafHash: h1, controlBlock: [v|p, ik, hash(L2)] }
89
+ * L3 -> { depth: 2, tapLeafHash: h3, controlBlock: [v|p, ik, hash(L4), hash(L1)] }
90
+ * L4 -> { depth: 2, tapLeafHash: h4, controlBlock: [v|p, ik, hash(L3), hash(L1)] }
91
+ * ]
92
+ * ```
93
+ *
94
+ * Legend:
95
+ * - `ik`: the 32-byte internal key placed in the control block.
96
+ * - `hash(X)`: the merkle sibling hash at each level when proving leaf `X`.
97
+ *
98
+ * Note: in this diagram, `L2` is a branch node (right subtree), not a leaf,
99
+ * so `hash(L2) = TapBranch(hash(L3), hash(L4))`.
100
+ *
101
+ * Notes:
102
+ * - Leaves are returned in deterministic left-first order.
103
+ * - One metadata entry is returned per leaf.
104
+ * - `controlBlock.length === 33 + 32 * depth`.
105
+ * - Throws if internal key is invalid or merkle path cannot be found.
106
+ *
107
+ * Typical usage:
108
+ * - Convert this metadata into PSBT `tapLeafScript[]` entries
109
+ * for all leaves.
110
+ */
111
+ export declare function buildTaprootLeafPsbtMetadata({ tapTreeInfo, internalPubkey }: {
112
+ tapTreeInfo: TapTreeInfoNode;
113
+ internalPubkey: Uint8Array;
114
+ }): TaprootPsbtLeafMetadata[];
115
+ /**
116
+ * Builds PSBT `tapBip32Derivation` entries for taproot script-path spends.
117
+ *
118
+ * Leaf keys include the list of tapleaf hashes where they appear.
119
+ * If `internalKeyInfo` has derivation data, it is included with empty
120
+ * `leafHashes`.
121
+ *
122
+ * Example tree:
123
+ *
124
+ * ```text
125
+ * root
126
+ * / \
127
+ * L1 L2
128
+ *
129
+ * L1 uses key A
130
+ * L2 uses key A and key B
131
+ *
132
+ * h1 = tapleafHash(L1)
133
+ * h2 = tapleafHash(L2)
134
+ * ```
135
+ *
136
+ * Then output is conceptually:
137
+ *
138
+ * ```text
139
+ * [
140
+ * key A -> leafHashes [h1, h2]
141
+ * key B -> leafHashes [h2]
142
+ * internal key -> leafHashes []
143
+ * ]
144
+ * ```
145
+ *
146
+ * Notes:
147
+ * - Keys missing `masterFingerprint` or `path` are skipped.
148
+ * - Duplicate pubkeys are merged.
149
+ * - If the same pubkey appears with conflicting derivation metadata,
150
+ * this function throws.
151
+ * - Output and `leafHashes` are sorted deterministically.
152
+ */
153
+ export declare function buildTaprootBip32Derivations({ tapTreeInfo, internalKeyInfo }: {
154
+ tapTreeInfo: TapTreeInfoNode;
155
+ internalKeyInfo?: KeyInfo;
156
+ }): TapBip32Derivation[];
157
+ export declare function normalizeTaprootPubkey(pubkey: Uint8Array): Uint8Array;
158
+ /**
159
+ * Compiles an expanded `sortedmulti_a(...)` leaf expression to its internal
160
+ * `multi_a(...)` form by sorting placeholders using the resolved pubkeys from
161
+ * `expansionMap`.
162
+ */
163
+ export declare function compileSortedMultiAExpandedExpression({ expandedExpression, expansionMap }: {
164
+ expandedExpression: string;
165
+ expansionMap: ExpansionMap;
166
+ }): string;
167
+ /**
168
+ * Computes satisfactions for taproot script-path leaves.
169
+ *
170
+ * If `tapLeaf` is undefined, all satisfiable leaves are returned. If `tapLeaf`
171
+ * is provided, only that leaf is considered.
172
+ *
173
+ * Callers are expected to pass real signatures, or fake signatures generated
174
+ * during planning. See satisfyMiniscript() for how timeConstraints keep the
175
+ * chosen leaf consistent between planning and signing.
176
+ */
177
+ export declare function collectTaprootLeafSatisfactions({ tapTreeInfo, preimages, signatures, timeConstraints, tapLeaf }: {
178
+ tapTreeInfo: TapTreeInfoNode;
179
+ preimages: Preimage[];
180
+ signatures: PartialSig[];
181
+ timeConstraints?: TimeConstraints;
182
+ tapLeaf?: Uint8Array | string;
183
+ }): TaprootLeafSatisfaction[];
184
+ /**
185
+ * Selects the taproot leaf satisfaction with the smallest total witness size.
186
+ * Assumes the input list is in left-first tree order for deterministic ties.
187
+ */
188
+ export declare function selectBestTaprootLeafSatisfaction(satisfactions: TaprootLeafSatisfaction[]): TaprootLeafSatisfaction;
189
+ /**
190
+ * Collects a unique set of taproot leaf pubkeys (x-only) across the tree.
191
+ * This is useful for building fake signatures when no signer subset is given.
192
+ */
193
+ export declare function collectTapTreePubkeys(tapTreeInfo: TapTreeInfoNode): Uint8Array[];
194
+ /**
195
+ * Returns the best satisfaction for a taproot tree, by witness size.
196
+ *
197
+ * If `tapLeaf` is provided, only that leaf is considered. If `tapLeaf` is a
198
+ * bytes, it is treated as a tapLeafHash and must match exactly one leaf. If
199
+ * `tapLeaf` is a string, it is treated as a raw leaf expression and must
200
+ * match exactly one leaf (whitespace-insensitive).
201
+ *
202
+ * This function is typically called twice:
203
+ * 1) Planning pass: call it with fake signatures (built by the caller) to
204
+ * choose the best leaf without requiring user signatures.
205
+ * 2) Signing pass: call it again with real signatures and the timeConstraints
206
+ * returned from the first pass (see satisfyMiniscript() for why this keeps
207
+ * the chosen leaf consistent between planning and signing).
208
+ */
209
+ export declare function satisfyTapTree({ tapTreeInfo, signatures, preimages, tapLeaf, timeConstraints }: {
210
+ tapTreeInfo: TapTreeInfoNode;
211
+ signatures: PartialSig[];
212
+ preimages: Preimage[];
213
+ tapLeaf?: Uint8Array | string;
214
+ timeConstraints?: TimeConstraints;
215
+ }): TaprootLeafSatisfaction;