Skip to content

plan: add Plan::tap_sighash_default accessor#951

Open
evanlinjin wants to merge 1 commit into
rust-bitcoin:masterfrom
evanlinjin:master-plan-tap-sighash-default
Open

plan: add Plan::tap_sighash_default accessor#951
evanlinjin wants to merge 1 commit into
rust-bitcoin:masterfrom
evanlinjin:master-plan-tap-sighash-default

Conversation

@evanlinjin
Copy link
Copy Markdown
Contributor

@evanlinjin evanlinjin commented May 17, 2026

Summary

Adds a public accessor on Plan that exposes the existing per-Schnorr-placeholder size assumption — recorded when the plan was built from TaprootCanSign::sighash_default — as a single Option<bool>.

impl<Pk: MiniscriptKey + ToPublicKey> Plan<Pk> {
    /// Returns whether the witness was sized assuming `SIGHASH_DEFAULT` (the
    /// 64-byte Taproot signature encoding).
    pub fn tap_sighash_default(&self) -> Option<bool>;
}
  • Some(true) — every Schnorr placeholder is sized for a 64-byte signature (the SIGHASH_DEFAULT encoding).
  • Some(false) — every Schnorr placeholder is sized for a 65-byte signature (any non-Default Taproot sighash flag).
  • None — non-Taproot plans (signature size is invariant under the sighash flag for ECDSA), or mixed plans whose Schnorr placeholders have differing sizes — these cannot be expressed by a single uniform sighash policy per BIP-174.

Motivation

Callers building a PSBT from a Plan need to populate PSBT_IN_SIGHASH_TYPE consistently with the plan's witness-size assumption — otherwise weight estimates drift from reality. The information already lives inside the plan (on every Schnorr placeholder's size field); this just surfaces it as a single readable answer.

Concretely: bdk-tx is reworking per-input sighash handling and needs to derive the PSBT sighash policy from the plan rather than carrying separate state on its Input type (see bitcoindevkit/bdk-tx#69 for the full design). Without this accessor it would have to walk Plan::witness_template() and infer the bool from placeholder sizes, which leaks internals.

A 12.x backport is up at #950.
A 13.x backport is up at #952.

Test plan

  • cargo test --lib tap_sighash_default — new test covers Default-Taproot, non-Default-Taproot, and non-Taproot (wsh) plans.
  • cargo test --lib — full suite still passes (157 / 0 / 0).

🤖 Generated with Claude Code

Exposes the existing per-Schnorr-placeholder size assumption — recorded
when the plan was built from `TaprootCanSign::sighash_default` — as a
single `Option<bool>` on the Plan.

Returns `Some(true)` when every Schnorr placeholder is sized for a
64-byte signature (SIGHASH_DEFAULT), `Some(false)` when every one is
sized for 65 bytes (any non-Default Taproot sighash flag), and `None`
for non-Taproot plans or mixed plans that cannot be expressed by a
single uniform sighash policy per BIP-174.

Callers constructing a PSBT can use this to populate
`PSBT_IN_SIGHASH_TYPE` consistently with the witness-size assumption
baked into `Plan::satisfaction_weight`.
@evanlinjin evanlinjin force-pushed the master-plan-tap-sighash-default branch from a7eee98 to 0e6ce80 Compare May 17, 2026 08:18
@evanlinjin evanlinjin marked this pull request as ready for review May 17, 2026 08:21
Copy link
Copy Markdown

@nymius nymius left a comment

Choose a reason for hiding this comment

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

This is a guess based on information which was available at the moment of providing the assets. Why not surfacing directly the SIGHASH value obtained from the assets?

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants