#35918 descriptor: Expose key expression parsing

ReviewabilityReviewsAgreementSize
#35918 pseudoramdom descriptor: Expose key expression parsingReady1Positive125 + 185 tests
  • Allow wallet flows to validate and inspect standalone descriptor key expressions directly
  • Eliminate the need for dummy descriptor wrappers when verifying pasted keys in setup wizards
  • Fix musig descriptor parsing to properly reject invalid trailing characters
  • Ready to review now
  • Approval without stated rationale (w0xlt)
  • Concept approval without stated reasons (pablomartin4btc)
  • Open suggestion to split the musig parser fix into a separate PR for backporting (fametrano)
  • 125 lines added or modified outside tests
  • 185 lines added or modified in tests
  • 95 lines removed in total
  • 3 files, 3 commits
Wallet#52 of 92
P3 · unblocks #35645
  • P3 because it unblocks multisig wizard tracking issue #35645
  • Enables wallet tools to parse standalone key expressions and inspect derivation paths cleanly
  • Ranking pass: Moved down to head a contiguous multisig-wizard (#35645) block with #36070 and #36143.
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

Exposes the `PubkeyProvider` interface in `descriptor.h` and adds a public `ParsePubkey()` function to parse standalone key expressions using P2TR context rules. It also adds a `GetOriginInfo()` virtual method on `PubkeyProvider` to inspect explicit derivation paths and master key fingerprints, and fixes `musig()` descriptor parsing to reject unexpected trailing characters.

Problem: External callers like GUI wallet wizards cannot validate or inspect standalone descriptor key expressions without wrapping them in dummy descriptors, because key parsing routines and `PubkeyProvider` are internal to `descriptor.cpp`. Furthermore, `musig()` descriptor parsing failed to reject invalid trailing characters following the closing parenthesis unless they started a derivation path.

Evidence of importance:

  • PR description: 'This is particularly useful in GUI multisig setup flows where the UI accepts a pasted key expression. The GUI can use this parser to validate input, inspect the parsed key, and apply setup-specific policy... (Multisig Wizard tracking issue: #35645)'
  • Commit 7835e0ef70: 'The musig() parser split the input at the closing parenthesis without validating the remaining text. This allowed unexpected characters after the expression to be ignored.'

Scope: Moving `PubkeyProvider` from `descriptor.cpp` to `descriptor.h` accounts for most of the diff and is mostly move-only.

Risk of a mistake: medium (wallet). A mistake in descriptor key parsing or the musig parsing fix could cause valid wallet descriptors to fail parsing or allow malformed descriptors to be accepted.

Changed since the previous assessment: Unchanged in scope and approach; commits rebased.

Reviewability

Ready

Nothing known that would invalidate a review now.

Waiting on (from the thread read):

  • author: respond to fametrano's suggestion to split the musig fix into its own PR 2026-10-18

Agreement

Positive

support without stated reasons, no open objection (w0xlt, w0xlt, pablomartin4btc)

Thread notes: Added pablomartin4btc's Concept ACK. Their inline comments and commit remarks are non-blocking doc/commit nits and not tracked as claims. fametrano's suggestion to split the musig fix remains open.

Objections, suggestions, and questions:

ReviewerTypeHarm, request, or questionStatusMust beAuthor repliedQuote
uqlidi (none)suggestion, interfaceAllow callers to pass ParseScriptContext rather than hardcoding P2TR rulesanswered · author explained P2TR rules are intentionally matched to standalone key expression requirementsansweredyes2026-08-28: 'I see you hardcoded it for p2tr. shouldn't be for all script types? Why are you making the overload follow the p2tr rules only?'
Status from: 2026-10-14: pseudoramdom: 'Using P2TR here is intentional, as mentioned in the PR description. Its key parsing rules match what we want for standal'
fametrano (none)suggestion, scopeSplit the musig parser bug fix into a separate PR so it can be reviewed and backported on its ownopenansweredno2026-10-18: 'Since it is a parser fix and the rest of the PR adds a new API, would you split it into its own PR? It could then be reviewed and backported on its own.'

Support:

  • w0xlt (contributor) (ACK, 2026-08-13): ACK 93600f9f0360bf48a1f616f0f5db3c9ce985ce4b [not substantive]
  • w0xlt (contributor) (ACK, 2026-10-20): reACK 17ddfdc0edc3ac35b1a87c884d61db2a58941bce [not substantive]
  • pablomartin4btc (member) (Concept ACK, 2026-10-31) [read: src/script/descriptor.h, descriptor.cpp]: Concept ACK [not substantive]

Participants:

  • w0xlt (contributor, support, 2 statements 2026-08-13 to 2026-10-20): ACKed and reACKed without rationale
  • uqlidi (none, question, 1 statements 2026-08-28 to 2026-08-28): asked why P2TR rules are hardcoded and suggested passing ParseScriptContext
  • sedited (member, neutral, 2 statements 2026-10-13 to 2026-10-14): pinged author for follow-up and rebase
  • fametrano (none, neutral, 1 statements 2026-10-18 to 2026-10-18): suggested splitting the musig parser bug fix into a separate PR for backporting
  • pablomartin4btc (member, support, 3 statements 2026-10-30 to 2026-10-31): Concept ACK; offered commit message and documentation nits

Dependencies

Enables:

Files

185 lines under test/bench/ci.

  • src/test/descriptor_tests.cpp +185/-0
  • src/script/descriptor.cpp +41/-95
  • src/script/descriptor.h +84/-0

Card

The short text the ranking pass compares across PRs.

Exposes the PubkeyProvider interface and introduces a public ParsePubkey function to validate and inspect individual descriptor key expressions under P2TR rules. This allows callers such as the multisig setup wizard in issue #35645 to validate pasted keys, inspect origin paths, and apply custom key policies without fabricating dummy descriptor strings. The change also patches a descriptor parsing bug where trailing garbage after musig expressions was erroneously accepted.

Data

dossier JSON · extract JSON · model ledger, generated 2026-11-01T01:16, confidence high, input hash 8db0c3a18747699b
thread read through 2026-10-31 (11 statements), head 17ddfdc0ed
labels: Descriptors

Categories

Wallet

P3 · unblocks #35645 (ranking pass: Moved down to head a contiguous multisig-wizard (#35645) block with #36070 and #36143.)

Exposes standalone descriptor key expression parsing and derivation path inspection needed by the GUI multisig setup wizard. As noted in the description, external callers like the GUI wizard currently cannot validate pasted key expressions without wrapping them in dummy descriptors; merging this unblocks tracking issue #35645.

Membership: Touches descriptor interfaces in src/script/descriptor.h specifically intended to support wallet and GUI wallet key validation flows.

Factors: security/stability 0, bug 1, performance 0, user value 1, leverage 2