#36005 rpc, descriptor: warn when multipath expansion clones single-path key expressions
| Reviewability | Reviews | Agreement | Size | |||||||
|---|---|---|---|---|---|---|---|---|---|---|
| #36005 rpc, descriptor: warn when multipath expansion clones single-path key expressions | Needs rebase | 1 | Strong | 57 + 88 tests | ||||||
|
|
|
|
| ||||||
Reviewability: ReadyStalePaused Agreement: StrongPositivePositive w/ caveatsNeutralMildDisputedBlockedCrickets Reviews: current code-review ACKs, then (+stale ACKs) and -NACKs; greener = more ACKs. Size: lines added or modified outside tests, then in tests; greener = smaller. | ||||||||||
Goal
Warns when a descriptor mixes multipath and single-path key expressions or Taproot tree elements, which causes single-path keys to be duplicated across each expanded branch. Adds a `warnings` field to the `getdescriptorinfo` RPC to surface descriptor-level warnings (including Miniscript safety checks), and updates the RPC helper `PushWarnings` to deduplicate warning strings.
Problem: When a multipath descriptor mixes multipath and single-path key expressions (for example, `wsh(multi(2, A/<0;1>/*, B/0/*))`), descriptor expansion silently clones the single-path keys across all branches. This can cause unintended key reuse and address clustering between receive and change outputs without the user realizing it. Furthermore, `getdescriptorinfo` lacked a `warnings` field, leaving existing descriptor warnings (such as unsafe Miniscript `older()` parameters) invisible until import, where warnings were also duplicated per expanded path.
Evidence of importance:
- Addresses issue #35985 ('importdescriptors: multipath expansion silently reuses key material across branches'), where silent key cloning across multipath expansions could lead to key reuse across wallet chains.
- Release notes highlight: 'Descriptors mixing multipath key expressions with single-path ones... now produce a warning, since the single-path key expressions are repeated in every expanded descriptor and the same keys end up in all of the resulting scripts.'
Reviewability
Ready · Needs rebase
Conflicts with master; review the logic now, the rebase is mechanical.
Waiting on (from the thread read):
- author: rebase and addressing review suggestion 2026-10-04
Agreement
Strong
substantive support, no open objection (jeanpablojp)
Thread notes: Author replied to sedited's ping confirming the PR is still on their todo list. Open claims and support remain unchanged.
Objections, suggestions, and questions:
| Reviewer | Type | Harm, request, or question | Status | Must be | Author replied | Quote |
|---|---|---|---|---|---|---|
| jeanpablojp (contributor) | suggestion, correctness | Add a test case covering multiple simultaneous warnings | open | answered | no | 2026-08-20: 'nit: this only allows one warning. I hit both with `wsh(and_v(v:pk(A/<0;1>/*),and_v(v:pk(B/0/*),older(65536))))`, which nothing covers at the moment. Worth adding one?' |
Support:
- jeanpablojp (contributor) (Tested ACK, 2026-08-20) [both: unit tests, functional tests]: Built and ran the unit tests and functional tests; verified that dropping each multipath_cloned line fails the new unit test and reverting PushWarnings dedup fails both functional tests
Participants:
- jeanpablojp (contributor, support, 2 statements 2026-08-20 to 2026-08-20): tested ACK after verifying unit and functional tests against deliberate code mutations; suggested adding a test for multiple simultaneous warnings
- sedited (member, neutral, 1 statements 2026-10-02 to 2026-10-02): pinged author regarding needed rebase and whether they are still working on the PR
Files
89 lines under test/bench/ci.
- src/test/descriptor_tests.cpp +54/-0
- src/script/descriptor.cpp +19/-5
- test/functional/wallet_importdescriptors.py +22/-0
- doc/release-notes-36005.md +15/-0
- test/functional/rpc_getdescriptorinfo.py +12/-1
- src/rpc/output_script.cpp +12/-0
- src/rpc/util.cpp +9/-3
- src/rpc/util.h +2/-1
Card
The short text the ranking pass compares across PRs.
When a descriptor combines multipath and single-path key expressions or Taproot components, parsing silently clones the single-path expressions across every expanded descriptor branch. This can lead to unintended on-chain key reuse between branches, such as between external receive and internal change addresses. This pull request adds a warning whenever single-path key expressions, internal keys, or Taproot subscripts are cloned across multipath expansions, addressing issue #35985. It also exposes descriptor-level warnings in getdescriptorinfo and deduplicates warning messages in RPC responses so repeated warnings are not emitted per expansion path.
Data
thread read through 2026-10-04 (4 statements), head 13ef865f84
labels: Needs rebase
Categories
RPC / REST / ZMQ
P3 · new feature
Surfaces descriptor warnings in `getdescriptorinfo` and deduplicates warnings across RPC output. As noted in the description, `getdescriptorinfo` previously 'lacked a warnings field, leaving existing descriptor warnings... invisible until import'.
Membership: Modifies src/rpc/output_script.cpp to add a warnings field to getdescriptorinfo and updates src/rpc/util.cpp/h PushWarnings deduplication logic.
Factors: security/stability 1, bug 1, performance 0, user value 1, leverage 0
Wallet
P3 · bug fix
Prevents silent address reuse and privacy loss across receive and change branches. The PR addresses issue #35985 where 'multipath expansion silently reuses key material across branches', warning users when single-path keys are unexpectedly duplicated.
Membership: Changes descriptor expansion logic in src/script/descriptor.cpp to warn against single-path key cloning, affecting wallet import descriptors and address generation.
Factors: security/stability 1, bug 1, performance 0, user value 1, leverage 0