Skip to content

Commit

Permalink
Merge pull request #6 from RubenSomsen/patch-4
Browse files Browse the repository at this point in the history
Clarified inputs for shared secret derivation, plus small fixes
  • Loading branch information
josibake authored Jun 5, 2023
2 parents ecd936d + e4dcd02 commit b4ac7fd
Showing 1 changed file with 12 additions and 12 deletions.
24 changes: 12 additions & 12 deletions bip-0000.mediawiki
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Using a new address for each Bitcoin transaction is a crucial aspect of maintain

However, interaction is often infeasible and in many cases undesirable. To solve for this, various protocols have been proposed which use a static payment address and notifications sent via the blockchain <ref name="out_of_band_notifications">'''Why not use out-of-band notifications''' Out of band notifications (e.g. using something other than the Bitcoin blockchain) have been proposed as a way of addressing the privacy and cost concerns of using the Bitcoin blockchain as a messaging layer. This, however, simply moves the privacy and cost concerns somewhere else and increases the risk of losing money due to a notification not being reliably delivered, or even censored, and makes this notification data critical for backup to recover funds.</ref>. These protocols eliminate the need for interaction, but at the expense of increased costs for one-time payments and a noticeable footprint in the blockchain, potentially revealing metadata about the sender and receiver. Notification schemes also allow the receiver to link all payments from the same sender, compromising sender privacy.

This proposal aims to address the limitations of these current approaches by presenting a solution that eliminates the need for interaction, eliminates the need for notifications, and protects both sender and receiver privacy. These benefits come at the cost of requiring wallets to scan the blockchain in order to detect payments. This added requirement is generally feasible for full nodes but poses a challenge for light clients. While it is possible today to implement a privacy-preserving light client at the cost of increased bandwidth, light client support is considered an area of open research (see [[bip-0000.mediawiki#appendix-a-light-client-support|Appendix A: Light Client Support]]).
This proposal aims to address the limitations of these current approaches by presenting a solution that eliminates the need for interaction, eliminates the need for notifications, and protects both sender and receiver privacy. These benefits come at the cost of requiring wallets to scan the blockchain in order to detect payments. This added requirement is generally feasible for full nodes but poses a challenge for light clients. While it is possible today to implement a privacy-preserving light client at the cost of increased bandwidth, light client support is considered an area of open research (see [[#appendix-a-light-client-support|Appendix A: Light Client Support]]).

== Goals ==

Expand All @@ -48,7 +48,7 @@ We aim to present a protocol which satisifies the following properties:
== Overview ==

We first present an informal overview of the protocol. In what follows, uppercase letters represent public keys, lowercase letters represent private keys, ''||'' refers to byte concatenation, and ''G'' represents the generator point for ''secp256k1''. Each section of the overview is incomplete on its own and is meant to build on the previous section in order to introduce and briefly explain each aspect of the protocol. For the full protocol specification, see [[bip-0000.mediawiki#specification|Specification]].
We first present an informal overview of the protocol. In what follows, uppercase letters represent public keys, lowercase letters represent private keys, ''||'' refers to byte concatenation, and ''G'' represents the generator point for ''secp256k1''. Each section of the overview is incomplete on its own and is meant to build on the previous section in order to introduce and briefly explain each aspect of the protocol. For the full protocol specification, see [[#specification|Specification]].

''' Simple case '''

Expand Down Expand Up @@ -145,13 +145,13 @@ For everything not defined above, we use the notation from [https://github.com/b
This document defines ''Silent Payments v0''. Version is communicated through the address in the same way as native Segwit addresses. Future upgrades to silent payments will require a new version. For ''Silent Payments v0'':
* Receiver addresses are always [https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki BIP341] taproot outputs<ref name="why_taproot">'''Why only taproot outputs?''' Providing too much optionality for the protocol makes it difficult to implement and can be at odds with the goal of providing the best privacy. Limiting to taproot outputs helps simplify the implementation significantly while also putting users in the best eventual anonymity set.</ref>
* The sender should sign with one of the sighash flags ''ALL, SINGLE, NONE'' (''ANYONECANPAY'' is unsafe). It is strongly recommended implementations only use ''SIGHASH_ALL'' for silent payments<ref name="why_sighash_all">'''Why recommend ''SIGHASH_ALL''?''' Since the output address for the receiver is derived from from the sum of the ''[[bip-0000.mediawiki#specification|Inputs For Shared Secret Derivation]]'' public keys, the inputs must not change once the sender has signed the transaction. If the inputs are allowed to change after the fact, the receiver will not be able to calculate the shared secret needed to find and spend the output. It is currently an open question on how a future version of silent payments could be made to work with new sighash flags such as ''SIGHASH_GROUP'' and ''SIGHASH_ANYPREVOUT''.</ref>
* Inputs used to derive the shared secret are from the ''[[bip-0000.mediawiki#specification|Inputs For Shared Secret Derivation]]'' list
* The sender should sign with one of the sighash flags ''ALL, SINGLE, NONE'' (''ANYONECANPAY'' is unsafe). It is strongly recommended implementations only use ''SIGHASH_ALL'' for silent payments<ref name="why_sighash_all">'''Why recommend ''SIGHASH_ALL''?''' Since the output address for the receiver is derived from from the sum of the ''[[#inputs-for-shared-secret-derivation|Inputs For Shared Secret Derivation]]'' public keys, the inputs must not change once the sender has signed the transaction. If the inputs are allowed to change after the fact, the receiver will not be able to calculate the shared secret needed to find and spend the output. It is currently an open question on how a future version of silent payments could be made to work with new sighash flags such as ''SIGHASH_GROUP'' and ''SIGHASH_ANYPREVOUT''.</ref>
* Inputs used to derive the shared secret are from the ''[[#inputs-for-shared-secret-derivation|Inputs For Shared Secret Derivation]]'' list
A transaction is not a ''Silent Payments v0'' transaction and should be skipped entirely<ref name="why_skip_transactions">'''Why skip transactions that spend unknown output scripts?''' Skipping transactions that spend unknown output scripts allows us to have a clean upgrade path for Silent Payments by avoiding the need to scan the same transaction multiple times with different rule sets. If a fancy new output type is added in the future and Silent Payments v1 is released with support, we would want to avoid having to first scan the transaction with the silent payment v0 rules and then again with the silent payment v1 rules.</ref> when scanning if any of the following are true:
* The transaction does not contain any BIP341 taproot outputs
* The transaction does not have at least one input from the ''[[bip-0000.mediawiki#specification|Inputs For Shared Secret Derivation]]'' list
* The transaction does not have at least one input from the ''[[#inputs-for-shared-secret-derivation|Inputs For Shared Secret Derivation]]'' list
* The transaction inputs contain a new, undefined output type (e.g SegWit versions > 1)
=== Address encoding ===
Expand Down Expand Up @@ -185,9 +185,11 @@ While any UTXO with known output scripts can be used to fund the transaction, th
* ''P2SH-P2WPKH''
* ''P2PKH''
Inputs with conditional branches or multiple public keys (e.g ''CHECKMULTISIG'') are not included as this introduces malleability and would allow a sender to re-sign with a different set of public keys after the silent payment output has been derived. This is not a concern when the sender controls all of the inputs, but is an issue for CoinJoins and other collaborative protocols, where a malicious participant can participate in deriving the silent payment address with one set of keys and then re-broadcast the transaction with signatures for a different set of public keys. P2TR can have hidden conditional branches (script path), but we work around that as described below.
''' P2TR (key path spends)'''
The sender MUST use the tweaked private key corresponding to the taproot output key (i.e. the tweaked private key for a key path spend). If the taproot output key is not available, the output cannot be used for sending a silent payment. The receiver always uses the taproot output key when scanning, regardless of whether the taproot output is a key path spend or a script path spend<ref name="why_always_output_pubkey">''' Why not skip all taproot script path spends? ''' This causes malleability issues for CoinJoin. If the silent payments protocol skipped taproot script path spends, this would allow an attacker to join a CoinJoin round, participate in deriving the silent payment address using the tweaked private key for a key path spend, and then broadcast their own version of the transaction using the script path spend. If receiver were to only consider key path spends, they would skip the attacker's script path spend input when deriving the shared secret and not be able to find the funds.</ref>.
The sender MUST use the tweaked private key corresponding to the taproot output key (i.e. the tweaked private key for a key path spend). If the taproot output key is not available, the output cannot be used for sending a silent payment. The receiver always uses the taproot output key when scanning, regardless of whether the taproot output is being used in a key path spend or a script path spend<ref name="why_always_output_pubkey">''' Why not skip all taproot script path spends? ''' This causes malleability issues for CoinJoins. If the silent payments protocol skipped taproot script path spends, this would allow an attacker to join a CoinJoin round, participate in deriving the silent payment address using the tweaked private key for a key path spend, and then broadcast their own version of the transaction using the script path spend. If the receiver were to only consider key path spends, they would skip the attacker's script path spend input when deriving the shared secret and not be able to find the funds.</ref>.
The one exception is script path spends that use NUMS point ''H'' as their internal key (as defined in [https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#constructing-and-spending-taproot-outputs BIP341: Constructing and spending Taproot outputs]), in which case the output will be skipped for the purposes of shared secret derivation<ref name="why_ignore_h">'''Why skip outputs with H as the internal taproot key?''' If use cases get popularized where the taproot key path cannot be used, these outputs can still be included without getting in the way of making a silent payment, provided they specifically use H as their internal taproot key.</ref>.
Expand All @@ -209,22 +211,20 @@ The sender performs the tweak using the private key for the output and SHOULD si
The receiver obtains the public key from the ''scriptSig''. The receiver MUST parse the ''scriptSig'' for the public key, even if the ''scriptSig'' is non-standard (e.g. <code><dummy> OP_DROP <Signature> <Public Key></code>). This is to address the [https://en.bitcoin.it/wiki/Transaction_malleability third-party malleability of ''P2PKH'' ''scriptSigs''].
Inputs with conditional branches or multiple public keys (e.g ''CHECKMULTISIG'') are not included as this introduces malleability and would allow a sender to re-sign with a different set of public keys after the silent payment output has been derived. This is not a concern when the sender controls all of the inputs, but is an issue for CoinJoins and other collaborative protocols, where a malicious participant can participate in deriving the silent payment address with one set of keys and then re-broadcast the transaction with signatures for a different set of public keys.
=== Sender ===
==== Selecting inputs ====
The sending wallet performs coin selection as usual with the following restrictions:
* At least one input MUST be from the ''[[bip-0000.mediawiki#specification|Inputs For Shared Secret Derivation]]'' list
* At least one input MUST be from the ''[[#inputs-for-shared-secret-derivation|Inputs For Shared Secret Derivation]]'' list
* Exclude ''P2TR'' script path spends, unless ''H'' is used as the internal public key
==== Creating outputs ====
After the inputs have been selected, the sender can create one or more outputs for one or more silent payment addresses in the following manner:
* Let ''a = a<sub>0</sub> + a<sub>1</sub> + … a<sub>i</sub>'', where each ''a<sub>i</sub>'' is the 256-bit private key(s) of an input from the ''[[bip-0000.mediawiki#specification|Inputs For Shared Secret Derivation]]'' list
* Let ''a = a<sub>0</sub> + a<sub>1</sub> + … a<sub>i</sub>'', where each ''a<sub>i</sub>'' is the 256-bit private key(s) of an input from the ''[[#inputs-for-shared-secret-derivation|Inputs For Shared Secret Derivation]]'' list
* Group receiver silent payment addresses by ''B<sub>scan</sub>'' (e.g. each group consists of one ''B<sub>scan</sub>'' and one or more ''B<sub>m</sub>'')
* For each group:
** Let ''ecdh_shared_secret = outpoints_hash·a·B<sub>scan</sub>''
Expand Down Expand Up @@ -257,7 +257,7 @@ Wallet software MUST use hardened derivation to ensure the master key is not exp
For each transaction the receiving wallet suspects might be a silent payment to themselves, it must:
* Generate the ''outpoints_hash'', using the method described above
* Let ''A = A<sub>0</sub> + A<sub>1</sub> + … A<sub>i</sub>'', where each ''A<sub>i</sub>'' is the public key of an input from the ''[[bip-0000.mediawiki#specification|Inputs For Shared Secret Derivation]]'' list
* Let ''A = A<sub>0</sub> + A<sub>1</sub> + … A<sub>i</sub>'', where each ''A<sub>i</sub>'' is the public key of an input from the ''[[#inputs-for-shared-secret-derivation|Inputs For Shared Secret Derivation]]'' list
* Let ''ecdh_shared_secret = outpoints_hash·b<sub>scan</sub>·A''
* Check for outputs:
** Let ''outputs_to_check = all unspent taproot outputs in the transaction''
Expand Down Expand Up @@ -302,7 +302,7 @@ Once a light client has the tweak data for a block, they can determine whether o
Assuming a secure messaging protocol exists, the sender can send an encrypted (using the scan public key of the silent payment address) notification to the receiver with the following information:
* The spend public key (communicates the label)
* The shared secret portion of the private key (i.e ''hash(a·B || 0)'')
* The shared secret portion of the private key (i.e ''hash(ecdh_shared_secret || n)'')
* The outpoint and amount (so it's immediately spendable)
It is important to note that these notifications are not required. At any point, the receiver can fall back to scanning for silent payment transactions if they don't trust the notifications they are receiving, are being spammed with fake notifications, or if they are concerned that they are not receiving notifications.
Expand Down

0 comments on commit b4ac7fd

Please sign in to comment.