Skip to content

Commit 2e6a050

Browse files
authored
Merge pull request #9 from bitcoinerlab/dust-fix-unknown-unlock
Prevent crash in dustThreshold for addr() descriptors lacking miniscript
2 parents 8465750 + f228a36 commit 2e6a050

File tree

3 files changed

+33
-12
lines changed

3 files changed

+33
-12
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@bitcoinerlab/coinselect",
3-
"version": "1.3.0",
3+
"version": "1.3.1",
44
"author": "Jose-Luis Landabaso",
55
"license": "MIT",
66
"description": "A TypeScript library for Bitcoin transaction management, based on Bitcoin Descriptors for defining inputs and outputs. It facilitates optimal UTXO selection and transaction size calculation.",

src/dust.ts

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,37 @@ export function dustThreshold(
5252
) {
5353
const isSegwitOutput = output.isSegwit();
5454
if (isSegwitOutput === undefined) throw new Error(`Unknown output type`);
55+
// When sending to scripts (such as TR, SH, or WSH) using an addr() descriptor,
56+
// the actual input weight may be unknown because the unlocking script isn’t provided.
57+
// In such cases, we fall back to a conservative estimate based on a typical P2WPKH input.
58+
// Bitcoin Core Wallet does similar stuff...
59+
//
60+
// The fallback is derived as follows:
61+
// - Non-witness part:
62+
// • txid: 32 bytes
63+
// • vout: 4 bytes
64+
// • sequence: 4 bytes
65+
// • script length: 1 byte
66+
// Total non-witness bytes = 41 bytes → 41 * 4 = 164 weight units.
67+
// - Witness part (for P2WPKH):
68+
// • push count: 1 byte
69+
// • signature: 73 bytes
70+
// • public key: 34 bytes
71+
// Total witness bytes = 108 weight units.
72+
// Combined total input weight = 164 + 108 = 272 weight units.
73+
let inputWeight: number;
74+
try {
75+
//this may throw. F.ex. if the output is a wsh and the miniscript was
76+
//not provided.
77+
inputWeight = output.inputWeight(
78+
isSegwitOutput,
79+
'DANGEROUSLY_USE_FAKE_SIGNATURES'
80+
);
81+
} catch (err) {
82+
inputWeight = 272;
83+
}
5584
return Math.ceil(
56-
dustRelayFeeRate *
57-
Math.ceil(
58-
(output.outputWeight() +
59-
output.inputWeight(
60-
isSegwitOutput,
61-
'DANGEROUSLY_USE_FAKE_SIGNATURES'
62-
)) /
63-
4
64-
)
85+
dustRelayFeeRate * Math.ceil((output.outputWeight() + inputWeight) / 4)
6586
);
6687
}
6788

0 commit comments

Comments
 (0)