<pre>
  BIP: 376
  Layer: Applications
  Title: Spending Silent Payment outputs with PSBTs
  Authors: nymius <nymius@proton.me>
  Status: Draft
  Type: Specification
  Assigned: 2026-02-05
  License: BSD-2-Clause
  Discussion: 2024-05-17: https://delvingbitcoin.org/t/bip352-psbt-support/877/30 [delving bitcoin post] Original discussion
              2025-12-05: https://gist.github.com/nymius/b3dd0b8a08c6735d617e6216b73c4260 [gist] First draft
              2025-12-15: https://gnusha.org/pi/bitcoindev/R53cG3TeXgXDUUS4kH_q226GlaFCjI0DZVT6mdTQzSQdj3RnNqWA-bFT7uGgGQFJG6938kDGvDJVoFQj8ItEMsJ6NyOjCTvpVEarYiyW6-8=@proton.me/ [bitcoin-dev] [BIP Proposal] Add PSBT_IN_SP_TWEAK field
  Requires: 352, 370, 371
</pre>

== Introduction ==

=== Abstract ===

This document proposes additional per-input fields for BIP 370 PSBTv2 that allow BIP 352 Silent Payment tweaks to be included in a PSBT of version 2. These fields are relevant to Silent Payment output spending.

=== Motivation ===

BIP 352 specifies the Silent Payment protocol, which provides a new way to create P2TR outputs and spend them.

The existing PSBT fields are unable to support Silent Payment without changes, due to the new method by which outputs are created.

BIP 375 and complementary BIP 374 specify how to create outputs locked with Silent Payment keys using PSBTs. But they don't specify how to unlock these outputs in a transaction.<ref name="why_not_adding_this_field_in_bip_375">''' Why not including this new field in BIP 375?''' Historically, Silent Payment has been categorized from the perspective of the user of the protocol: receiver or sender. BIP 375 has followed this convention, as stated in its title: Sending Silent Payments with PSBTs. Given that spending belongs to the receiver’s sphere, and considering this convention, this specification should be a different BIP.</ref>

Therefore, new fields must be defined to allow PSBTs to carry the information necessary for tweaking taproot keys without following the BIP 341 tagging scheme.

== Specification ==

We use the following functions and conventions:

* ser<sub>32</sub>(i): serializes a 32-bit unsigned integer ''i'' as a 4-byte sequence, most significant byte first.
* ser<sub>256</sub>(p): serializes the integer p as a 32-byte sequence, most significant byte first.
* ser<sub>P</sub>(P): serializes the coordinate pair P = (x,y) as a byte sequence using SEC1's compressed form: (0x02 or 0x03) || ser<sub>256</sub>(x), where the header byte depends on the parity of the omitted Y coordinate.
* ''hash<sub>tag</sub>(x)'': refers to ''SHA256(SHA256(tag) || SHA256(tag) || x)''.

=== Fields ===

This document specifies new fields and new field inclusion/exclusion requirements.

The new per-input types are defined as follows:

{| class="wikitable"
! Name
! <tt><keytype></tt>
! <tt><keydata></tt>
! <tt><keydata></tt> Description
! <tt><valuedata></tt>
! <tt><valuedata></tt> Description
! Versions Requiring Inclusion
! Versions Requiring Exclusion
! Versions Allowing Inclusion
|-
| Silent Payment Spend Key BIP 32 Derivation Path<ref name="why_sticking_to_bip32_derivation">''' Why only considering BIP 32 for spend key generation?''' Although alternative key derivation methods exist (e.g., FROST) and have devised mechanisms to interact with PSBTs without modifying the format, the vast majority of hardware wallets are architected around the BIP 32 derivation scheme. As primary consumers of the PSBT format, these devices have significantly influenced its design. Consequently, this BIP avoids preemptively enforcing a shift away from the established BIP 32 paradigm.</ref>
| <tt>PSBT_IN_SP_SPEND_BIP32_DERIVATION = 0x1f</tt>
| <tt><33-byte spend key></tt>
| The 33-byte spend public key used to derive the key locking this input.
| <tt><4-byte fingerprint> <32-bit little endian uint path element>*</tt>
| The master key fingerprint as defined by BIP 32 concatenated with the derivation path of the spend public key. The derivation path is represented as indexed 32-bit unsigned integers concatenated with each other. Input Finalizers should remove this field after <tt>PSBT_IN_FINAL_SCRIPTWITNESS</tt> is constructed.
|
| 0
| 2
|-
| Silent Payment Tweak
| <tt>PSBT_IN_SP_TWEAK = 0x20</tt>
| None
| No key data
| <tt><32-byte tweak></tt>
| A 32-byte raw tweak. Input Finalizers should remove this field after <tt>PSBT_IN_FINAL_SCRIPTWITNESS</tt> is constructed.
|
| 0
| 2
|}

Per [https://github.com/bitcoin/bips/blob/master/bip-0352.mediawiki#spending BIP 352 spending] the <tt><32-byte tweak></tt> is ''hash<sub>BIP0352/SharedSecret</sub>(ser<sub>P</sub>(ecdh_shared_secret) || ser<sub>32</sub>(k))''

or ''hash<sub>BIP0352/SharedSecret</sub>(ser<sub>P</sub>(ecdh_shared_secret) || ser<sub>32</sub>(k)) + hash<sub>BIP0352/Label</sub>(ser<sub>256</sub>(b<sub>scan</sub>) || ser<sub>32</sub>(m))'',

where ''hash<sub>BIP0352/Label</sub>(ser<sub>256</sub>(b<sub>scan</sub>) || ser<sub>32</sub>(m))'' is the optional label derived by some integer ''m''.

=== Roles ===

This document modifies some existing roles.

==== Updater ====

The Updater MUST add <tt>PSBT_IN_SP_TWEAK</tt> when an input spends a Silent Payment output.

The Updater SHOULD add <tt>PSBT_IN_SP_SPEND_BIP32_DERIVATION</tt> when spending a Silent Payment output using the BIP 32 derivation scheme. If the Updater does not want to reveal the fingerprint or derivation path, it can set the value to a 4-byte zero fingerprint with no derivation paths.

==== Signer ====

Let ''P'' be the 32-byte output key from a P2TR output script contained in <tt>PSBT_IN_WITNESS_UTXO</tt>, i.e., in the form <tt>0x5120<32-bytes of output key P></tt>.

The Signer MUST compute the signing private key ''d = (b<sub>spend</sub> + tweak) mod n'', where ''tweak'' is the value of <tt>PSBT_IN_SP_TWEAK</tt> and ''b<sub>spend</sub>'' is the spend private key obtained using either <tt>PSBT_IN_SP_SPEND_BIP32_DERIVATION</tt> or other methods.

The Signer MUST negate ''d'' if the y-coordinate of ''d·G'' is odd.

The Signer MUST fail if the x-coordinate of ''d·G'' does not equal ''P'', as the tweak does not produce the expected spend output.<ref name="why_verify_tweak">''' Why must the Signer verify the tweak?''' The tweak is provided by the Updater and could be incorrect, either through error or malice. Without verification, the Signer would produce a valid Schnorr signature for a key it does not control, which could be used to steal funds. Verifying that the tweaked key matches the output key ensures the Signer is signing for the expected output.</ref>

The Signer MUST produce a BIP 340 Schnorr signature using the private key ''d'' and set the result in the <tt>PSBT_IN_TAP_KEY_SIG</tt> field as defined in BIP 371.

==== Input Finalizer ====

The Input Finalizer MUST verify that a <tt>PSBT_IN_TAP_KEY_SIG</tt> field is present for each input that has a <tt>PSBT_IN_SP_TWEAK</tt> field set. If not, the input is not fully signed and cannot be finalized.

The Input Finalizer MUST construct the <tt>PSBT_IN_FINAL_SCRIPTWITNESS</tt> containing the single witness element from <tt>PSBT_IN_TAP_KEY_SIG</tt>, as per the BIP 341 key path spending rule.

The Input Finalizer MUST remove the <tt>PSBT_IN_SP_TWEAK</tt>, <tt>PSBT_IN_SP_SPEND_BIP32_DERIVATION</tt>, <tt>PSBT_IN_TAP_KEY_SIG</tt>, and <tt>PSBT_IN_WITNESS_UTXO</tt> fields for any input where the <tt>PSBT_IN_FINAL_SCRIPTWITNESS</tt> is present.

== Rationale ==

On PSBTs, when spending non-Silent Payment outputs, one just relies on <tt>PSBT_IN_BIP32_DERIVATION</tt> or any of the allowed <tt>PSBT_IN_TAP_*</tt> combinations. These are used to get the right private keys to sign each input. For Silent Payment outputs, it is not that simple. To get the private key needed to sign a Silent Payment output, you have to combine a private key with the tweak obtained from the transaction corpus. Currently, there is no field prescribed for this.

==== Why not have the Signer compute the tweak? ====
The tweak is produced by combining some data from the transaction and the public keys belonging to the outputs being spent by that transaction. Providing these outputs not only imposes a burden on the signer, who has to perform extra cryptographic operations to combine this data, but it also increases the total amount of data included in the PSBT.

For example, if we consider a transaction with two P2WPKH outputs spent and one P2TR output created, and account for the weight of the prevouts, the total amount of bytes sent would increase by ~413 bytes, [[#gross-amount-of-bytes-required-for-tweak-computation-in-a-transaction-with-two-p2wpkh-inputs-and-one-p2tr-output|see the number details]].

This is ~10x more data than the 32 bytes required by the tweak. This tweak is computed during the scanning of a Silent Payment output, and is easier to store than to regenerate.

==== Why not use proprietary fields? ====

It is possible, but brittle. This may require extra lookups for keys that are not unified across implementations.

==== Why not reuse other 32-byte fields in PSBT? ====
<tt>PSBT_IN_TAP_MERKLE_ROOT</tt> was a candidate to host the tweak. It has the same size, and the tweaking operation for Schnorr is similar, but the tagged hash used for tweaking differs.

<tt>PSBT_IN_BIP32_DERIVATION</tt> was also considered, but discarded. A tweak would not fit exactly, and the purpose of this field is different.

In any case, reusing any of these fields would require another component to recognize the input as a Silent Payment output. This would create additional requirements that would not be worth the effort. A different field with a Silent Payment reference in the name would avoid the issue more simply.

==== Why not defining a general tweak field for Taproot? ====
Assuming different tweaking schemes are available, <tt>PSBT_IN_TAP_RAW_TWEAK</tt> would be a more general solution. However, PSBT fields are usually specified according to the nature of their contents, and it is unclear how a hardware wallet would determine the field’s content in the more general case.

==== Why add yet another BIP 32 derivation field? ====
The inclusion of the tweak in the PSBT is insufficient in isolation. It must be accompanied by the information required to derive the correct private key. Silent Payment spend public keys cannot use <tt>PSBT_IN_TAP_BIP32_DERIVATION</tt> because BIP 352 specifies 33-byte spend keys<ref name="why_33_byte_keys">''' Why not 32-byte x-only keys?''' The spend public key ''B<sub>spend</sub>'' is a 33-byte signed key. ''P = B<sub>spend</sub> + tweak·G'' is the derived key in the output script, also a 33-byte signed key. After computing ''d = b<sub>spend</sub> + tweak'' this extra sign byte is critical to decide whether the unlocking private key is ''d'' (''P = d·G'') or ''-d'' (''P = -d·G'').</ref>, which do not fit within this <tt>keydata</tt> field. Furthermore, reliance on <tt>PSBT_IN_BIP32_DERIVATION</tt> is precluded because BIP 352 spending rules follow BIP 341, which mandates the use of Schnorr signatures.

== Backward compatibility ==

These are new fields added to the existing PSBT format. Because PSBT is designed to be extensible, old software will ignore the new fields.

== Reference implementation ==

'''''TODO'''''

=== Test vectors ===

'''''TODO'''''

== Appendix ==

==== Gross amount of bytes required for tweak computation in a transaction with two P2WPKH inputs and one P2TR output ====

{| class="wikitable"
! colspan="2" style="font-weight:bold; text-align:center;" | Transaction header
|-
! Field
! Size
|-
| Version
| 4
|-
| Marker
| 1
|-
| Flag
| 1
|-
| Input count (Compact size)
| 1
|-
| Output count (Compact size)
| 1
|-
| Locktime
| 4
|-
! scope="row" style="font-weight:bold;" | Total bytes
| 12
|}

{| style="width:100%;"
! style="width:10%;" | Field
! style="width:45%;" | P2TR Output
! style="width:45%;" | P2WPKH Ouptut (x2)
|-
| Amount
| 8
| 8
|-
| Output script length (Compact size)
| 1
| 1
|-
| Output script
| 34
| 22
|-
! scope="row" style="font-weight:bold;" | Total bytes
| 43
| 31 x 2 = 62 bytes
|}

{| style="width:100%;"
! style="width:10%;" |
! style="width:45%;" | P2WPKH Input (x2)
! style="width:45%;" | P2WPKH Witness (x2)
|-
|
| style="vertical-align:top;" |

{| class="wikitable"
! Field
! Size
|-
| Txid
| 32
|-
| Vout
| 4
|-
| ScriptSig length (Compact size)
| 1
|-
| ScriptSig
| 0
|-
| Sequence
| 4
|-
|}


| style="vertical-align:top;" |

{| class="wikitable"
! Field
! Size
|-
| Stack items count
| 1
|-
| Signature length (Compact size)
| 1
|-
| Signature
| 71-73
|-
| Public key length (Compact size)
| 1
|-
| Public key
| 33
|}
|-
! scope="row" style="font-weight:bold;" | Total bytes
| 41 x 2 = 82
| 107 x 2 = 214
|}

The gross amount of bytes required for the Signer to compute the tweak is: 12 + 43 + 62 + 82 + 214 = 413 bytes

This could be reduced by removing unnecessary fields, but at the cost of increasing the complexity for the Signer, without any significant gain.

== Copyright ==

This document is licensed under the 2-clause BSD license.

== Acknowledgements ==

Thanks to Craig Raw, macgyver, josibake and all others who participated in discussions on this topic.

== References ==

<references/>
