mirror of
https://github.com/bitcoin/bips.git
synced 2026-03-09 15:53:54 +00:00
BIP392: Silent Payment Output Script Descriptors (#2047)
* Add sp() output descriptor format for BIP352 Silent Payments * Update headers and remove space after comma in descriptors * Add label ranges with examples * Update with assigned number and adjust preamble for BIP3 * BIP392: Add table entry to README * Add two argument key expression form and remove birthday and label arguments * Add BIP392 sp() descriptor to BIP380 script expressions table * Add sp() descriptor to BIP390 allowed expressions and add musig() example to BIP392 * Add changelog and version header to BIP390
This commit is contained in:
@@ -1381,6 +1381,13 @@ users (see also: [https://en.bitcoin.it/wiki/Economic_majority economic majority
|
||||
| Informational
|
||||
| Draft
|
||||
|-
|
||||
| [[bip-0392.mediawiki|392]]
|
||||
| Applications
|
||||
| Silent Payment Output Script Descriptors
|
||||
| Craig Raw
|
||||
| Specification
|
||||
| Draft
|
||||
|-
|
||||
| [[bip-0431.mediawiki|431]]
|
||||
| Applications
|
||||
| Topology Restrictions for Pinning
|
||||
|
||||
@@ -334,4 +334,7 @@ This Table lists all available Script expressions and the BIPs specifying them.
|
||||
|-
|
||||
| <tt>musig(KEY, KEY, ..., KEY)</tt>
|
||||
| [[bip-0390.mediawiki|390]]
|
||||
|-
|
||||
| <tt>sp(KEY)</tt>, <tt>sp(KEY, KEY)</tt>
|
||||
| [[bip-0392.mediawiki|392]]
|
||||
|}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
Type: Informational
|
||||
Assigned: 2024-06-04
|
||||
License: CC0-1.0
|
||||
Version: 0.2.0
|
||||
Requires: 380, 328
|
||||
</pre>
|
||||
|
||||
@@ -33,8 +34,8 @@ and [[bip-0389.mediawiki|BIP-389]].
|
||||
|
||||
===<tt>musig(KEY, KEY, ..., KEY)</tt>===
|
||||
|
||||
The <tt>musig(KEY, KEY, ..., KEY)</tt> expression can only be used inside of a <tt>tr()</tt> or
|
||||
<tt>rawtr()</tt> expression as a key expression. It additionally cannot be nested within another <tt>musig()</tt>
|
||||
The <tt>musig(KEY, KEY, ..., KEY)</tt> expression can only be used inside of a <tt>tr()</tt>, <tt>rawtr()</tt>
|
||||
or <tt>sp()</tt> expression as a key expression. It additionally cannot be nested within another <tt>musig()</tt>
|
||||
expression. Participant public keys may be repeated. The aggregate public key is produced
|
||||
by using the <tt>KeyAgg</tt> algorithm on all KEYs specified in the expression after performing all
|
||||
specified derivation. As with script expressions, KEY can contain child derivation specified by
|
||||
@@ -118,6 +119,11 @@ are likely to be familiar with them.
|
||||
|
||||
The reference implementation is available in Bitcoin Core [[https://github.com/bitcoin/bitcoin/pull/31244|PR #31244]].
|
||||
|
||||
==Changelog==
|
||||
|
||||
* __0.2.0__ (2026-03-04) - Allow <tt>musig()</tt> inside <tt>sp()</tt> expressions.
|
||||
* __0.1.0__ (2025-12-08) - Allow <tt>musig()</tt> inside <tt>rawtr()</tt> expressions.
|
||||
|
||||
==Acknowledgements==
|
||||
|
||||
Thanks to Pieter Wuille, Andrew Poelstra, Sanket Kanjalkar, Salvatore Ingala, and all others who
|
||||
|
||||
114
bip-0392.mediawiki
Normal file
114
bip-0392.mediawiki
Normal file
@@ -0,0 +1,114 @@
|
||||
<pre>
|
||||
BIP: 392
|
||||
Layer: Applications
|
||||
Title: Silent Payment Output Script Descriptors
|
||||
Authors: Craig Raw <craig@sparrowwallet.com>
|
||||
Status: Draft
|
||||
Type: Specification
|
||||
Assigned: 2026-02-06
|
||||
License: BSD-2-Clause
|
||||
Discussion: https://groups.google.com/g/bitcoindev/c/bP6ktUyCOJI
|
||||
Requires: 341, 350, 352, 380
|
||||
</pre>
|
||||
|
||||
==Abstract==
|
||||
|
||||
This document specifies <tt>sp()</tt> output script descriptors for silent payments.
|
||||
<tt>sp()</tt> descriptors take silent payment key material and describe P2TR outputs when combined with sender input public keys as defined in BIP352.
|
||||
|
||||
==Copyright==
|
||||
|
||||
This BIP is licensed under the BSD 2-clause license.
|
||||
|
||||
==Motivation==
|
||||
|
||||
BIP352 defines silent payments, a protocol for static payment addresses without on-chain linkability.
|
||||
This descriptor provides a standardized way to represent silent payment outputs within the output descriptor framework, enabling wallet interoperability and backup/recovery using existing descriptor-based infrastructure.
|
||||
|
||||
==Specification==
|
||||
|
||||
A new top level script expression is defined: <tt>sp()</tt>.
|
||||
|
||||
===Key Expressions===
|
||||
|
||||
Two new key expression types are defined for use with <tt>sp()</tt> descriptors:
|
||||
|
||||
====<tt>spscan</tt>====
|
||||
|
||||
The <tt>spscan</tt> key expression encodes the scan private key and spend public key.
|
||||
It is a [https://github.com/bitcoin/bips/blob/master/bip-0350.mediawiki Bech32m] encoding of:
|
||||
* The human-readable part "spscan" for mainnet, "tspscan" for testnets
|
||||
* The data-part values:
|
||||
** The character "q", to represent silent payments version 0
|
||||
** The payload: <tt>ser<sub>256</sub>(b<sub>scan</sub>) || ser<sub>P</sub>(B<sub>spend</sub>)</tt>
|
||||
|
||||
====<tt>spspend</tt>====
|
||||
|
||||
The <tt>spspend</tt> key expression encodes both the scan and spend private keys.
|
||||
It is a [https://github.com/bitcoin/bips/blob/master/bip-0350.mediawiki Bech32m] encoding of:
|
||||
* The human-readable part "spspend" for mainnet, "tspspend" for testnets
|
||||
* The data-part values:
|
||||
** The character "q", to represent silent payments version 0
|
||||
** The payload: <tt>ser<sub>256</sub>(b<sub>scan</sub>) || ser<sub>256</sub>(b<sub>spend</sub>)</tt>
|
||||
|
||||
Note: The serialization of <tt>ser<sub>256</sub>(p)</tt> and <tt>ser<sub>P</sub>(P)</tt> follows the definition in BIP352.
|
||||
|
||||
===<tt>sp()</tt>===
|
||||
|
||||
The <tt>sp(KEY)</tt> or <tt>sp(KEY,KEY)</tt> expression can only be used as a top level descriptor.
|
||||
|
||||
<tt>sp(KEY)</tt> takes a single key expression as an argument, which must be either an <tt>spscan</tt> or <tt>spspend</tt> encoded key, optionally with key origin information.
|
||||
If included, the key origin information specifies the fingerprint and derivation path to the depth from which the scan and spend keys are derived using the child paths recommended in BIP352 (<tt>1h/0</tt> for scan, <tt>0h/0</tt> for spend).
|
||||
|
||||
<tt>sp(KEY,KEY)</tt> takes two key expressions.
|
||||
The first key expression represents the scan key and must be a single private key (e.g. a WIF compressed private key or <tt>xprv</tt> extended private key).
|
||||
The second key expression represents the spend key and may be any key expression as defined in BIP380 or other key expression BIPs (e.g. <tt>musig()</tt> as defined in BIP390) that represents a single key, public or private.
|
||||
Note however that uncompressed keys are not allowed under any <tt>sp()</tt> expression, as BIP352 only permits compressed public keys.
|
||||
|
||||
When combined with sender input public keys, the descriptor produces P2TR output scripts describing silent payments made to wallets represented by the key expression(s).
|
||||
|
||||
The output scripts produced are BIP341 taproot outputs as specified in BIP352.
|
||||
|
||||
==Examples==
|
||||
|
||||
Valid descriptors:
|
||||
|
||||
* <tt>sp(spscan1q...)</tt> - Using spscan encoded key (watch-only)
|
||||
* <tt>sp([deadbeef/352h/0h/0h]spscan1q...)</tt> - With key origin
|
||||
* <tt>sp(spspend1q...)</tt> - Using spspend encoded key (full wallet)
|
||||
* <tt>sp(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600)</tt> - WIF scan key with compressed public spend key (watch-only)
|
||||
* <tt>sp([deadbeef/352h/0h/0h]xprv.../0h,xpub.../0h)</tt> - Extended private scan key with extended public spend key (watch-only)
|
||||
* <tt>sp([deadbeef/352h/0h/0h]xprv.../0h,xprv.../0h)</tt> - Extended private keys for both scan and spend (full wallet)
|
||||
* <tt>sp(L4rK1yDtCWekvXuE6oXD9jCYfFNV2cWRpVuPLBcCU2z8TrisoyY1,musig(03dff1d77f2a671c5f36183726db2341be58feae1da2deced843240f7b502ba659,023590a94e768f8e1815c2f24b4d80a8e3149316c3518ce7b7ad338368d038ca66))</tt> - WIF scan key with MuSig2 aggregate spend key (watch-only)
|
||||
|
||||
Invalid descriptors:
|
||||
|
||||
* <tt>sp()</tt> requires at least one key expression
|
||||
* <tt>sp(xpub...)</tt> single argument form requires spscan or spspend encoded key
|
||||
* <tt>sp(xpub...,xpub...)</tt> two argument form requires private scan key (e.g. WIF or xprv)
|
||||
* <tt>sp(spscan1q...,spscan1q...)</tt> two argument form requires single key expressions
|
||||
* <tt>sp(5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss,0260b2003c386519fc9eadf2b5cf124dd8eea4c4e68d5e154050a9346ea98ce600)</tt> uncompressed private key
|
||||
* <tt>sh(sp(spscan1q...))</tt> sp() is top level only
|
||||
* <tt>wsh(sp(spscan1q...))</tt> sp() is top level only
|
||||
|
||||
==Usage Notes==
|
||||
|
||||
For watch-only wallets, use <tt>spscan</tt> encoding or the two argument form with a public spend key.
|
||||
For full wallets that can both scan and spend, use <tt>spspend</tt> encoding or the two argument form with a private spend key.
|
||||
|
||||
When using the two argument form, the scan key must be private (e.g. WIF or <tt>xprv</tt>) since scanning requires the private scan key.
|
||||
|
||||
==Backwards Compatibility==
|
||||
|
||||
<tt>sp()</tt> descriptors use the format and general operation specified in BIP380.
|
||||
As this is a wholly new descriptor, it is not compatible with any prior implementation.
|
||||
The scripts produced are BIP341 taproot outputs, making them indistinguishable from other taproot outputs on-chain.
|
||||
|
||||
==Reference Implementation==
|
||||
|
||||
TBD
|
||||
|
||||
==Test Vectors==
|
||||
|
||||
TBD
|
||||
|
||||
Reference in New Issue
Block a user