Skip to content

fix(compile): validate policy keys and hashes before compiling descriptors - #347

Open
Olorunshogo wants to merge 1 commit into
bitcoindevkit:masterfrom
Olorunshogo:fix/compile-key-validation
Open

Olorunshogo wants to merge 1 commit into
bitcoindevkit:masterfrom
Olorunshogo:fix/compile-key-validation

Conversation

@Olorunshogo

Copy link
Copy Markdown

PR summary

Description

compile parsed policies as Concrete<String>, so any placeholder string (pk(ABC))
or hash (sha256(H)) was accepted as a "key" with zero validation. The command would
succeed and print a syntactically valid descriptor that only failed later, when a real
consumer (e.g. bitcoin-cli deriveaddresses) tried to use it.

This PR parses as Concrete<DescriptorPublicKey> by default, so keys and hashes are
validated at parse time. The old permissive behavior is kept behind a new
--allow-placeholders flag, since pk(A)-style policies are still useful for
inspecting a policy's compiled shape without real keys.

Fixes #344

Notes to reviewers

  • The sh/wsh/sh-wsh/tr compile logic (including the tr branch's randomized
    NUMS-tweak internal key) is written once, as a new generic compile_policy<Pk>, and
    instantiated with either DescriptorPublicKey or String depending on the flag.
    Duplicating that match per key type was the alternative, but it would have meant two
    copies of the internal-key/tweak math to keep in sync.
  • String can't get a From<XOnlyPublicKey> impl in this crate (orphan rules), so the
    tr branch's internal-key construction goes through a small local TrInternalKey
    trait implemented for both key types instead.
  • --allow-placeholders only changes how strictly the policy is parsed; --type is
    untouched (out of scope here - see Use ValueEnum for --type in compile command #345).
  • test_compile_policy_beyond_legacy_limits uses placeholder keys on purpose (it only
    tests script-size limits, not key validity), so it now passes --allow-placeholders.

Behavior change

compile without --allow-placeholders now rejects invalid keys and hashes at parse
time instead of silently producing an unusable descriptor:

$ bdk-cli compile "pk(ABC)"
Error: Generic error: Invalid policy: unexpected «Key too short (<66 char), doesn't match any format»

$ bdk-cli compile "pk(ABC)" --allow-placeholders
{
  "descriptor": "wsh(pk(ABC))#8gmtcnaw"
}

Real keys and xpubs are unaffected.

Checklists

All Submissions:

  • I've signed all my commits
  • I followed the contribution guidelines
  • I ran cargo fmt and cargo clippy before committing

Bugfixes:

  • I've added tests to reproduce the issue which are now passing
  • I'm linking the issue being fixed by this PR

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

compile doesn't validate keys and returns unusable descriptors

1 participant