Skip to content

Commit eda3d9c

Browse files
committed
BIP376: Spending Silent Payment outputs with PSBTs
1 parent b382728 commit eda3d9c

3 files changed

Lines changed: 309 additions & 0 deletions

File tree

README.mediawiki

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1297,6 +1297,13 @@ users (see also: [https://en.bitcoin.it/wiki/Economic_majority economic majority
12971297
| Specification
12981298
| Draft
12991299
|-
1300+
| [[bip-0376.mediawiki|376]]
1301+
| Applications
1302+
| Spending Silent Payment outputs with PSBTs
1303+
| nymius
1304+
| Specification
1305+
| Draft
1306+
|-
13001307
| [[bip-0379.md|379]]
13011308
| Applications
13021309
| Miniscript

bip-0174.mediawiki

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,28 @@ derived from an aggregate key.
573573
| 2
574574
| [[bip-0375.mediawiki|375]]
575575
|-
576+
| Silent Payment Spend Key BIP 32 Derivation Path
577+
| <tt>PSBT_IN_SP_SPEND_BIP32_DERIVATION = 0x1f</tt>
578+
| <tt><33-byte spend key></tt>
579+
| The 33-byte spend public key used to derive the key locking this input.
580+
| <tt><4-byte fingerprint> <32-bit little endian uint path element>*</tt>
581+
| 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.
582+
|
583+
| 0
584+
| 2
585+
| [[bip-0376.mediawiki|376]]
586+
|-
587+
| Silent Payment Tweak
588+
| <tt>PSBT_IN_SP_TWEAK = 0x20</tt>
589+
| None
590+
| No key data
591+
| <tt><32-byte tweak></tt>
592+
| A 32-byte raw tweak. Input Finalizers should remove this field after <tt>PSBT_IN_FINAL_SCRIPTWITNESS</tt> is constructed.
593+
|
594+
| 0
595+
| 2
596+
| [[bip-0376.mediawiki|376]]
597+
|-
576598
| Proprietary Use Type
577599
| <tt>PSBT_IN_PROPRIETARY = 0xFC</tt>
578600
| <tt><compact size uint identifier length> <bytes identifier> <compact size uint subtype> <bytes subkeydata></tt>

bip-0376.mediawiki

Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
<pre>
2+
BIP: 376
3+
Layer: Applications
4+
Title: Spending Silent Payment outputs with PSBTs
5+
Authors: nymius <nymius@proton.me>
6+
Status: Draft
7+
Type: Specification
8+
Assigned: 2026-02-05
9+
License: BSD-2-Clause
10+
Discussion: 2024-05-17: https://delvingbitcoin.org/t/bip352-psbt-support/877/30 [delving bitcoin post] Original discussion
11+
2025-12-05: https://gist.github.com/nymius/b3dd0b8a08c6735d617e6216b73c4260 [gist] First draft
12+
2025-12-15: https://gnusha.org/pi/bitcoindev/R53cG3TeXgXDUUS4kH_q226GlaFCjI0DZVT6mdTQzSQdj3RnNqWA-bFT7uGgGQFJG6938kDGvDJVoFQj8ItEMsJ6NyOjCTvpVEarYiyW6-8=@proton.me/ [bitcoin-dev] [BIP Proposal] Add PSBT_IN_SP_TWEAK field
13+
Requires: 352, 370, 371
14+
</pre>
15+
16+
== Introduction ==
17+
18+
=== Abstract ===
19+
20+
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.
21+
22+
=== Motivation ===
23+
24+
BIP 352 specifies the Silent Payment protocol, which provides a new way to create P2TR outputs and spend them.
25+
26+
The existing PSBT fields are unable to support Silent Payment without changes, due to the new method by which outputs are created.
27+
28+
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>
29+
30+
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.
31+
32+
== Specification ==
33+
34+
We use the following functions and conventions:
35+
36+
* ser<sub>32</sub>(i): serializes a 32-bit unsigned integer ''i'' as a 4-byte sequence, most significant byte first.
37+
* ser<sub>256</sub>(p): serializes the integer p as a 32-byte sequence, most significant byte first.
38+
* 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.
39+
* ''hash<sub>tag</sub>(x)'': refers to ''SHA256(SHA256(tag) || SHA256(tag) || x)''.
40+
41+
=== Fields ===
42+
43+
This document specifies new fields and new field inclusion/exclusion requirements.
44+
45+
The new per-input types are defined as follows:
46+
47+
{| class="wikitable"
48+
! Name
49+
! <tt><keytype></tt>
50+
! <tt><keydata></tt>
51+
! <tt><keydata></tt> Description
52+
! <tt><valuedata></tt>
53+
! <tt><valuedata></tt> Description
54+
! Versions Requiring Inclusion
55+
! Versions Requiring Exclusion
56+
! Versions Allowing Inclusion
57+
|-
58+
| 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>
59+
| <tt>PSBT_IN_SP_SPEND_BIP32_DERIVATION = 0x1f</tt>
60+
| <tt><33-byte spend key></tt>
61+
| The 33-byte spend public key used to derive the key locking this input.
62+
| <tt><4-byte fingerprint> <32-bit little endian uint path element>*</tt>
63+
| 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.
64+
|
65+
| 0
66+
| 2
67+
|-
68+
| Silent Payment Tweak
69+
| <tt>PSBT_IN_SP_TWEAK = 0x20</tt>
70+
| None
71+
| No key data
72+
| <tt><32-byte tweak></tt>
73+
| A 32-byte raw tweak. Input Finalizers should remove this field after <tt>PSBT_IN_FINAL_SCRIPTWITNESS</tt> is constructed.
74+
|
75+
| 0
76+
| 2
77+
|}
78+
79+
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))''
80+
81+
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))'',
82+
83+
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''.
84+
85+
=== Roles ===
86+
87+
This document modifies some existing roles.
88+
89+
==== Updater ====
90+
91+
The Updater MUST add <tt>PSBT_IN_SP_TWEAK</tt> when an input spends a Silent Payment output.
92+
93+
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.
94+
95+
==== Signer ====
96+
97+
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>.
98+
99+
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.
100+
101+
The Signer MUST negate ''d'' if the y-coordinate of ''d·G'' is odd.
102+
103+
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>
104+
105+
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.
106+
107+
==== Input Finalizer ====
108+
109+
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.
110+
111+
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.
112+
113+
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.
114+
115+
== Rationale ==
116+
117+
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.
118+
119+
==== Why not have the Signer compute the tweak? ====
120+
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.
121+
122+
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]].
123+
124+
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.
125+
126+
==== Why not use proprietary fields? ====
127+
128+
It is possible, but brittle. This may require extra lookups for keys that are not unified across implementations.
129+
130+
==== Why not reuse other 32-byte fields in PSBT? ====
131+
<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.
132+
133+
<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.
134+
135+
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.
136+
137+
==== Why not defining a general tweak field for Taproot? ====
138+
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.
139+
140+
==== Why add yet another BIP 32 derivation field? ====
141+
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.
142+
143+
== Backward compatibility ==
144+
145+
These are new fields added to the existing PSBT format. Because PSBT is designed to be extensible, old software will ignore the new fields.
146+
147+
== Reference implementation ==
148+
149+
'''''TODO'''''
150+
151+
=== Test vectors ===
152+
153+
'''''TODO'''''
154+
155+
== Appendix ==
156+
157+
==== Gross amount of bytes required for tweak computation in a transaction with two P2WPKH inputs and one P2TR output ====
158+
159+
{| class="wikitable"
160+
! colspan="2" style="font-weight:bold; text-align:center;" | Transaction header
161+
|-
162+
! Field
163+
! Size
164+
|-
165+
| Version
166+
| 4
167+
|-
168+
| Marker
169+
| 1
170+
|-
171+
| Flag
172+
| 1
173+
|-
174+
| Input count (Compact size)
175+
| 1
176+
|-
177+
| Output count (Compact size)
178+
| 1
179+
|-
180+
| Locktime
181+
| 4
182+
|-
183+
! scope="row" style="font-weight:bold;" | Total bytes
184+
| 12
185+
|}
186+
187+
{| style="width:100%;"
188+
! style="width:10%;" | Field
189+
! style="width:45%;" | P2TR Output
190+
! style="width:45%;" | P2WPKH Ouptut (x2)
191+
|-
192+
| Amount
193+
| 8
194+
| 8
195+
|-
196+
| Output script length (Compact size)
197+
| 1
198+
| 1
199+
|-
200+
| Output script
201+
| 34
202+
| 22
203+
|-
204+
! scope="row" style="font-weight:bold;" | Total bytes
205+
| 43
206+
| 31 x 2 = 62 bytes
207+
|}
208+
209+
{| style="width:100%;"
210+
! style="width:10%;" |
211+
! style="width:45%;" | P2WPKH Input (x2)
212+
! style="width:45%;" | P2WPKH Witness (x2)
213+
|-
214+
|
215+
| style="vertical-align:top;" |
216+
217+
{| class="wikitable"
218+
! Field
219+
! Size
220+
|-
221+
| Txid
222+
| 32
223+
|-
224+
| Vout
225+
| 4
226+
|-
227+
| ScriptSig length (Compact size)
228+
| 1
229+
|-
230+
| ScriptSig
231+
| 0
232+
|-
233+
| Sequence
234+
| 4
235+
|-
236+
|}
237+
238+
239+
| style="vertical-align:top;" |
240+
241+
{| class="wikitable"
242+
! Field
243+
! Size
244+
|-
245+
| Stack items count
246+
| 1
247+
|-
248+
| Signature length (Compact size)
249+
| 1
250+
|-
251+
| Signature
252+
| 71-73
253+
|-
254+
| Public key length (Compact size)
255+
| 1
256+
|-
257+
| Public key
258+
| 33
259+
|}
260+
|-
261+
! scope="row" style="font-weight:bold;" | Total bytes
262+
| 41 x 2 = 82
263+
| 107 x 2 = 214
264+
|}
265+
266+
The gross amount of bytes required for the Signer to compute the tweak is: 12 + 43 + 62 + 82 + 214 = 413 bytes
267+
268+
This could be reduced by removing unnecessary fields, but at the cost of increasing the complexity for the Signer, without any significant gain.
269+
270+
== Copyright ==
271+
272+
This document is licensed under the 2-clause BSD license.
273+
274+
== Acknowledgements ==
275+
276+
Thanks to Craig Raw, macgyver, josibake and all others who participated in discussions on this topic.
277+
278+
== References ==
279+
280+
<references/>

0 commit comments

Comments
 (0)