BIP 376: Spending Silent Payment outputs with PSBTs
2026-02-05
View on GitHub
  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

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.** 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.

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:

  • ser32(i): serializes a 32-bit unsigned integer i as a 4-byte sequence, most significant byte first.
  • ser256(p): serializes the integer p as a 32-byte sequence, most significant byte first.
  • serP(P): serializes the coordinate pair P = (x,y) as a byte sequence using SEC1's compressed form: (0x02 or 0x03) || ser256(x), where the header byte depends on the parity of the omitted Y coordinate.
  • hashtag(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:

Name<keytype><keydata><keydata> Description<valuedata><valuedata> DescriptionVersions Requiring InclusionVersions Requiring ExclusionVersions Allowing Inclusion
Silent Payment Spend Key BIP 32 Derivation Path** 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.PSBT_IN_SP_SPEND_BIP32_DERIVATION = 0x1f<33-byte spend key>The 33-byte spend public key used to derive the key locking this input.<4-byte fingerprint> <32-bit little endian uint path element>*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 PSBT_IN_FINAL_SCRIPTWITNESS is constructed.02
Silent Payment TweakPSBT_IN_SP_TWEAK = 0x20NoneNo key data<32-byte tweak>A 32-byte raw tweak. Input Finalizers should remove this field after PSBT_IN_FINAL_SCRIPTWITNESS is constructed.02

Per BIP 352 spending the <32-byte tweak> is hashBIP0352/SharedSecret(serP(ecdh_shared_secret) || ser32(k))

or hashBIP0352/SharedSecret(serP(ecdh_shared_secret) || ser32(k)) + hashBIP0352/Label(ser256(bscan) || ser32(m)),

where hashBIP0352/Label(ser256(bscan) || ser32(m)) is the optional label derived by some integer m.

Roles

This document modifies some existing roles.

Updater

The Updater MUST add PSBT_IN_SP_TWEAK when an input spends a Silent Payment output.

The Updater SHOULD add PSBT_IN_SP_SPEND_BIP32_DERIVATION 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 PSBT_IN_WITNESS_UTXO, i.e., in the form 0x5120<32-bytes of output key P>.

The Signer MUST compute the signing private key d = (bspend + tweak) mod n, where tweak is the value of PSBT_IN_SP_TWEAK and bspend is the spend private key obtained using either PSBT_IN_SP_SPEND_BIP32_DERIVATION 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.** 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.

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

Input Finalizer

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

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

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

Rationale

On PSBTs, when spending non-Silent Payment outputs, one just relies on PSBT_IN_BIP32_DERIVATION or any of the allowed PSBT_IN_TAP_* 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, 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?

PSBT_IN_TAP_MERKLE_ROOT 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.

PSBT_IN_BIP32_DERIVATION 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, PSBT_IN_TAP_RAW_TWEAK 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 PSBT_IN_TAP_BIP32_DERIVATION because BIP 352 specifies 33-byte spend keys** Why not 32-byte x-only keys?** The spend public key Bspend is a 33-byte signed key. P = Bspend + tweak·G is the derived key in the output script, also a 33-byte signed key. After computing d = bspend + tweak this extra sign byte is critical to decide whether the unlocking private key is d (P = d·G) or -d (P = -d·G)., which do not fit within this keydata field. Furthermore, reliance on PSBT_IN_BIP32_DERIVATION 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

FieldSize
Version4
Marker1
Flag1
Input count (Compact size)1
Output count (Compact size)1
Locktime4
scope="row" style="font-weight:bold;"Total bytes
FieldP2TR OutputP2WPKH Ouptut (x2)
Amount88
Output script length (Compact size)11
Output script3422
scope="row" style="font-weight:bold;"Total bytes43
P2WPKH Input (x2)P2WPKH Witness (x2)
Field
Txid32
Vout4
ScriptSig length (Compact size)1
ScriptSig0
Sequence4

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

FieldSize
Stack items count1
Signature length (Compact size)1
Signature71-73
Public key length (Compact size)1
Public key33

|- ! 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


Updated

2026-04-11

See an issue with rendering or formatting? Submit an issue on GitHub

Do you find this site useful? Please consider donating some sats to support ongoing development.

bips.dev is presented by nickmonad

All content is owned and licensed by the respective author(s). This website makes no claim of ownership.