Skip to content

Commit 898ecd8

Browse files
feat(abstract-utxo): add support for taproot descriptors in findDescriptors
Issue: BTC-1786
1 parent 2717de0 commit 898ecd8

File tree

2 files changed

+48
-36
lines changed

2 files changed

+48
-36
lines changed

modules/abstract-utxo/src/core/descriptor/psbt/findDescriptors.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ function findDescriptorForDerivationIndex(
4040
function getDerivationIndexFromPath(path: string): number {
4141
const indexStr = path.split('/').pop();
4242
if (!indexStr) {
43-
throw new Error('Invalid derivation path');
43+
throw new Error(`Invalid derivation path ${path}`);
4444
}
4545
const index = parseInt(indexStr, 10);
4646
if (index.toString() !== indexStr) {
@@ -84,14 +84,21 @@ export function findDescriptorForInput(
8484
if (!script) {
8585
throw new Error('Missing script');
8686
}
87-
if (!input.bip32Derivation) {
88-
throw new Error('Missing derivation paths');
87+
if (input.bip32Derivation !== undefined) {
88+
return findDescriptorForAnyDerivationPath(
89+
script,
90+
input.bip32Derivation.map((v) => v.path),
91+
descriptorMap
92+
);
8993
}
90-
return findDescriptorForAnyDerivationPath(
91-
script,
92-
input.bip32Derivation.map((v) => v.path),
93-
descriptorMap
94-
);
94+
if (input.tapBip32Derivation !== undefined) {
95+
return findDescriptorForAnyDerivationPath(
96+
script,
97+
input.tapBip32Derivation.filter((v) => v.path !== '' && v.path !== 'm').map((v) => v.path),
98+
descriptorMap
99+
);
100+
}
101+
throw new Error('Missing derivation path');
95102
}
96103

97104
/**
Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,43 @@
11
import * as assert from 'assert';
22

3-
import { getDefaultXPubs, getDescriptor } from '../descriptor.utils';
3+
import { DescriptorTemplate, getDefaultXPubs, getDescriptor } from '../descriptor.utils';
44
import { findDescriptorForInput, findDescriptorForOutput } from '../../../../src/core/descriptor/psbt/findDescriptors';
55

66
import { mockPsbt } from './mock.utils';
77

8-
describe('parsePsbt', function () {
9-
const descriptorA = getDescriptor('Wsh2Of3', getDefaultXPubs('a'));
10-
const descriptorB = getDescriptor('Wsh2Of3', getDefaultXPubs('b'));
11-
const descriptorMap = new Map([
12-
['a', descriptorA],
13-
['b', descriptorB],
14-
]);
8+
function describeWithTemplates(tA: DescriptorTemplate, tB: DescriptorTemplate) {
9+
describe(`parsePsbt [${tA},${tB}]`, function () {
10+
const descriptorA = getDescriptor(tA, getDefaultXPubs('a'));
11+
const descriptorB = getDescriptor(tB, getDefaultXPubs('b'));
12+
const descriptorMap = new Map([
13+
['a', descriptorA],
14+
['b', descriptorB],
15+
]);
1516

16-
it('finds descriptors for PSBT inputs/outputs', function () {
17-
const psbt = mockPsbt(
18-
[
19-
{ descriptor: descriptorA, index: 0 },
20-
{ descriptor: descriptorB, index: 1, id: { vout: 1 } },
21-
],
22-
[{ descriptor: descriptorA, index: 2, value: BigInt(1e6) }]
23-
);
17+
it('finds descriptors for PSBT inputs/outputs', function () {
18+
const psbt = mockPsbt(
19+
[
20+
{ descriptor: descriptorA, index: 0 },
21+
{ descriptor: descriptorB, index: 1, id: { vout: 1 } },
22+
],
23+
[{ descriptor: descriptorA, index: 2, value: BigInt(1e6) }]
24+
);
2425

25-
assert.deepStrictEqual(findDescriptorForInput(psbt.data.inputs[0], descriptorMap), {
26-
descriptor: descriptorA,
27-
index: 0,
28-
});
29-
assert.deepStrictEqual(findDescriptorForInput(psbt.data.inputs[1], descriptorMap), {
30-
descriptor: descriptorB,
31-
index: 1,
32-
});
33-
assert.deepStrictEqual(findDescriptorForOutput(psbt.txOutputs[0].script, psbt.data.outputs[0], descriptorMap), {
34-
descriptor: descriptorA,
35-
index: 2,
26+
assert.deepStrictEqual(findDescriptorForInput(psbt.data.inputs[0], descriptorMap), {
27+
descriptor: descriptorA,
28+
index: 0,
29+
});
30+
assert.deepStrictEqual(findDescriptorForInput(psbt.data.inputs[1], descriptorMap), {
31+
descriptor: descriptorB,
32+
index: 1,
33+
});
34+
assert.deepStrictEqual(findDescriptorForOutput(psbt.txOutputs[0].script, psbt.data.outputs[0], descriptorMap), {
35+
descriptor: descriptorA,
36+
index: 2,
37+
});
3638
});
3739
});
38-
});
40+
}
41+
42+
describeWithTemplates('Wsh2Of3', 'Wsh2Of3');
43+
describeWithTemplates('Wsh2Of3', 'Tr2Of3-NoKeyPath');

0 commit comments

Comments
 (0)