Skip to content
This repository was archived by the owner on Oct 22, 2026. It is now read-only.

fix(descriptor): reject raw pkh in Taproot leaves when parsing Tr - #1061

Merged
apoelstra merged 1 commit into
rust-bitcoin:masterfrom
PeterXMR:fix/tr-reject-raw-pkh
Oct 14, 2026
Merged

apoelstra merged 1 commit into
rust-bitcoin:masterfrom
PeterXMR:fix/tr-reject-raw-pkh

Conversation

@PeterXMR

@PeterXMR PeterXMR commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #1056.

Since #775, Tr::from_tree validates leaves with Tap::CONSENSUS, which allows
raw pkh, so Tr::from_str accepts c:expr_raw_pkh(..) where 12.x rejected it.
Descriptor::from_str was unaffected because it re-validates leaves with Tap::SANE.

This validates leaves with Tap::CONSENSUS minus allow_raw_pkh, the same params
as Miniscript::from_str_insane. I deliberately did not switch to full Tap::SANE.
12.x Tr::from_str also rejected malleable, repeated-key, mixed-timelock and
sigless leaves, and 13.x still accepts these via Tr::from_str (but not
Descriptor::from_str). That is the known #734 hack that the FromTree validation
rework (#991) is meant to remove, so it is left unchanged here.

Out of scope: wsh/sh/bare still accept raw pkh through Descriptor::from_str;
that is pre-existing and tracked in #734.

I'll follow up with a backport PR to release-13.x.

- Validate Tr leaves with Tap::CONSENSUS minus allow_raw_pkh, matching
  Miniscript::from_str_insane, so Tr::from_str no longer accepts
  expr_raw_pkh like v12 did
- Cover single, sibling and nested raw pkh leaves

Fixes rust-bitcoin#1056

Assisted-by: Claude Opus 5.5
@PeterXMR

Copy link
Copy Markdown
Contributor Author

I used AI tools for development, did many reviews and fixing rounds locally before opening this.
Hope you'll find this PR useful, happy to maintaint it

@Kixunil probably wont help here with review as he doesn't work on miniscript unfortunately

@trevarj trevarj left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 3642826

@apoelstra

Copy link
Copy Markdown
Member

Thanks! Yeah, this looks great. At some point I'll get back to this part of the code and remove the "hack" and hopefully we'll have something cleaner or more principled here.

Could you also open a backport PR to the release-13.x branch, and add a point release to it?

@apoelstra apoelstra left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 3642826; successfully ran local tests

@apoelstra
apoelstra merged commit 20d7133 into rust-bitcoin:master Oct 14, 2026
13 checks passed
@trevarj

trevarj commented Oct 15, 2026

Copy link
Copy Markdown
Contributor

Thanks! Yeah, this looks great. At some point I'll get back to this part of the code and remove the "hack" and hopefully we'll have something cleaner or more principled here.

Could you also open a backport PR to the release-13.x branch, and add a point release to it?

Taking care of the backport and version bump here: #1071

trevarj pushed a commit to trevarj/rust-miniscript that referenced this pull request Oct 17, 2026
- Backport PR rust-bitcoin#1061 using ExtParams::insane() on release-13.x.
- Preserve other accepted non-sane leaves and cover single, sibling and nested raw-pkh leaves.

Backport-of: 3642826
Assisted-by: Claude Opus 5.5
Assisted-by: OpenAI GPT-6.1-Sol
apoelstra added a commit that referenced this pull request Oct 17, 2026
c891370 chore(release): prepare 13.2.0 (Trevor Arjeski)
f7b7f86 fix(descriptor): mark WalletPolicyError as non-exhaustive (Trevor Arjeski)
b804c27 fix(descriptor): reject raw pkh in Taproot leaves when parsing Tr (PeterXMR)

Pull request description:

  Backport #1054 to `release-13.x`, marking `WalletPolicyError` as non-exhaustive.
  Backport #1061 (20d7133), rejecting raw public-key hashes in directly parsed Taproot leaves.
  Bump to 13.2.0 and update the lockfiles and changelog for changes since 13.1.0.
  
  Both backports precede the version bump commit.


ACKs for top commit:
  apoelstra:
    ACK c891370; successfully ran local tests


Tree-SHA512: 649a829acccb474caffe487774e305dbf0394c03c975c02c27c1a9434db62a91edf43c5c74bce5095ba7bde1d09a4f166dd1da0532157c0b5b693b5e6fd04aef
portlandhodl added a commit to portlandhodl/rust-miniscript that referenced this pull request Oct 18, 2026
Tr::from_tree (and therefore Tr::from_str) validated each tapscript leaf
with Tap::CONSENSUS plus a no-raw-pkh override, instead of Tap::SANE as
Miniscript parsing and Descriptor::from_str's later wrapper check do.
Signatureless leaves ("tr(K,or_i(pk(K),1))", "tr(K,after(1))") and
duplicate keys in "multi_a" script paths therefore parsed fine through
Tr::from_str / FromTree for Descriptor, while the same strings were
rejected by Descriptor::from_str -- a parser disagreement producing
anyone-can-spend tapleaves (or one-signer thresholds). rust-bitcoin#734.

Now Tr::from_tree (factored as from_tree_with_leaf_params with SANE at
the public entry points) validates every leaf with Tap::SANE, which
already includes the raw-pkh rejection from rust-bitcoin#1061. The redundant
tr-leaf validation loop in Descriptor::from_str is dropped, since the
public FromTree for Descriptor path now provides the same guarantee.

The taproot merkle fixed-vector tests intentionally use insane
(signatureless/unsatisfiable) leaves to exercise tree hashing; they now
use a test-only consensus-level parsing helper rather than depending on
the sane public parsers accepting non-sane leaves.

Not fixed by the still-open rust-bitcoin#991 refactor either (verified against its
PR head).

Assisted-by: kimi-k3
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

v13 regression: Taproot parsing accepts raw public-key hashes

3 participants