Is there an existing issue for this?
- I have searched the existing issues
Current behaviour
Current Bitcoin Core accepts a multipath Miniscript descriptor when duplicate public keys appear only in a nonzero multipath branch, even though the identical concrete branch descriptor is rejected when written directly.
Verified locally on Core commit 400aa68b4aa8de52c1a8bf543dd195cd1b2b1f32.
In the repro below:
branch 0 is sane: /0 vs /2
branch 1 collides: /1 vs /1
The multipath descriptor is accepted and expanded into 2 concrete descriptors, but the explicit branch-1 descriptor is rejected with:
... is not sane: contains duplicate public keys
From local source review, this appears to happen because duplicate-key sanity is evaluated once on the template node before multipath expansion, and the key comparison samples only branch 0 / child 0.
This looks like a low-severity sanity-check completeness gap, not a validity or consensus issue. Duplicate keys are rejected under !IsSane(), not !IsValid().
Expected behaviour
If any concrete multipath branch is not sane due to duplicate public keys, the textual descriptor should be rejected. At minimum, duplicate-key sanity should be checked across the finite multipath dimension for all materialized branches, rather than only for branch 0. This does not require enumerating unbounded ranged children; it only requires checking the finite multipath <...> dimension that Core already expands.
Steps to reproduce
Reproduction
Build Bitcoin Core from source at commit 400aa68b4aa8de52c1a8bf543dd195cd1b2b1f32.
Call the descriptor parser on this multipath descriptor:
wsh(or_i(pk(xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ/<0;1>),pk(xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ/<2;1>)))
Observed locally:
parse succeeds
the descriptor expands into 2 concrete descriptors
Call the same parser on the explicit branch-1 expansion:
wsh(or_i(pk(xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ/1),pk(xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ/1)))
Observed locally:
parse fails with:
... is not sane: contains duplicate public keys
Optional control: the explicit branch-0 form is accepted as expected:
wsh(or_i(pk(xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ/0),pk(xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ/2)))
This same pattern also reproduces under tr(...).
Relevant log output
No response
How did you obtain Bitcoin Core
Compiled from source
What version of Bitcoin Core are you using?
Built from source at commit 400aa68b4aa8de52c1a8bf543dd195cd1b2b1f32
Operating system and version
MacOS 26.5.1
Machine specifications
No response