when a descriptor mixes multipath key expressions with a non-multipath one, ParseScript clones the single-path provider into every multipath branch instead of rejecting or warning: https://github.com/bitcoin/bitcoin/blob/c90c23d388f66b7eef67f4c6f69184c088727d6a/src/script/descriptor.cpp#L2440-L2451
same pattern for tr():
miniscript:
and musig:
so wsh(multi(2,A/<0;1>/*,B/0/*)) imports as:
external: wsh(multi(2,A/0/*,B/0/*))
internal: wsh(multi(2,A/1/*,B/0/*))
B/0/i is the exact same pubkey in the receive script and in the change script at the same index. this seems intended & is covered by test vectors, what bothers me is the privacy impact:
once a receive output at index i and a change output at index i are both spent, the two witness scripts contain an identical pubkey. that is a hard link between the two utxos for any observer, similar to an address reuse but only after both coins has been spent.
it gets worse when the cloned key is not ranged at all, a bare pubkey or a fixed B/0/0, then the same pubkey appears in every script the wallet ever produces, receive and change, at every index.
i see two options to this:
- reject it in Parse() by default, with an opt-in flag on importdescriptors for anyone who already funded such a descriptor.
- or keep accepting it and emit a warning, from
importdescriptorsandgetdescriptorinfo.