-
Notifications
You must be signed in to change notification settings - Fork 5.8k
Add sp() output descriptor format for BIP352 Silent Payments #2047
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
craigraw
wants to merge
2
commits into
bitcoin:master
Choose a base branch
from
craigraw:spdescriptor
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| <pre> | ||
| BIP: spdescriptor | ||
| Layer: Applications | ||
| Title: Silent Payment Output Script Descriptors | ||
| Author: Craig Raw <[email protected]> | ||
| Comments-Summary: No comments yet. | ||
| Comments-URI: TBD | ||
| Status: Draft | ||
| Type: Informational | ||
| Created: 2025-12-03 | ||
| License: BSD-2-Clause | ||
| Post-History: https://groups.google.com/g/bitcoindev/c/bP6ktUyCOJI | ||
| Requires: 44, 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,BIRTHDAY,LABEL,...)</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 should specify the derivation path to the account level as defined in BIP44. | ||
| When combined with sender input public keys, the descriptor produces P2TR output scripts describing silent payments made to wallets represented by the key expression. | ||
|
|
||
| When using the minimal form <tt>sp(KEY)</tt>: | ||
| * The birthday defaults to block height 842579 (May 8, 2024, when BIP352 was merged) | ||
| * Only the change label (<tt>m = 0</tt>) is assumed | ||
|
|
||
| <tt>sp(KEY,BIRTHDAY,LABEL,...)</tt> takes: | ||
| * A key expression (first argument) | ||
| * A birthday as a positive integer representing a block height (second argument) | ||
| * Zero or more label integers (remaining arguments), where each label is a positive integer | ||
|
|
||
| The birthday indicates the block height at which scanning should begin, and must be ≥ 842579. | ||
| Each label represents a label integer <tt>m</tt> used with the wallet, corresponding to <tt>B<sub>m</sub> = B<sub>spend</sub> + hash<sub>BIP0352/Label</sub>(ser<sub>256</sub>(b<sub>scan</sub>) || ser<sub>32</sub>(m))·G</tt> as defined in BIP352. | ||
| When labels are specified, only those specific label integers are scanned for (in addition to the change label <tt>m = 0</tt> which is always scanned). | ||
|
|
||
| The output scripts produced are BIP341 taproot outputs as specified in BIP352. | ||
|
|
||
| ==Examples== | ||
|
|
||
| Valid descriptors: | ||
|
|
||
| * <tt>sp(spscan1q...)</tt> - Minimal form with default birthday and change label only | ||
| * <tt>sp([deadbeef/352'/0'/0']spscan1q...,900000)</tt> - With key origin and custom birthday | ||
| * <tt>sp(spspend1q...,842579,1,2,3)</tt> - With birthday and labels 1, 2, 3 | ||
| * <tt>sp([deadbeef/352'/0'/0']spscan1q...,900000,1,5,10)</tt> - With key origin, birthday, and labels 1, 5, 10 | ||
|
|
||
| Invalid descriptors: | ||
|
|
||
| * <tt>sp()</tt> requires a key expression | ||
| * <tt>sp(xpub...)</tt> requires spscan or spspend encoded key | ||
| * <tt>sp(spscan1q...,abc)</tt> birthday must be a positive integer | ||
| * <tt>sh(sp(spscan1q...))</tt> sp() is top level only | ||
| * <tt>wsh(sp(spscan1q...))</tt> sp() is top level only | ||
|
|
||
| ==Usage Notes== | ||
|
|
||
| The change label (<tt>m = 0</tt>) should always be scanned for, even when not explicitly listed. | ||
| This ensures compatibility across different wallet implementations and prevents loss of funds from change outputs. | ||
|
|
||
| When recovering a wallet from a descriptor, scanning should begin at the specified birthday block height. | ||
| All labels specified in the descriptor must be scanned for when detecting payments. | ||
|
|
||
| For watch-only wallets, use <tt>spscan</tt> encoding. | ||
| For full wallets that can both scan and spend, use <tt>spspend</tt> encoding. | ||
|
|
||
| ==Backwards Compatibility== | ||
|
|
||
| <tt>sp()</tt> descriptors use the format and general operation specified in [[bip-0380.mediawiki|380]]. | ||
| 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 | ||
|
|
||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.