Skip to content
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

BIP 352: Silent Payments #1458

Merged
merged 7 commits into from May 8, 2024
Merged

Conversation

josibake
Copy link
Member

@josibake josibake commented Jun 5, 2023

Silent payments is a static address protocol for Bitcoin, originally proposed on the mailing list here: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2022-March/020180.html

Since then, the proposal has received several rounds of review and has a WIP implementation here: bitcoin/bitcoin#27827 . The proposal has also been sent to the mailing list for review here: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2023-June/021750.html

Proposing this as an informational BIP to ensure wallets across the ecosystem can standardize and correctly implement the protocol.

bip-0000.mediawiki Outdated Show resolved Hide resolved
Copy link
Contributor

@brandonblack brandonblack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Glad to see this proposal advancing! I think with some minor changes it can be compatible with MuSig2 Taproot Keypaths (and potentially other off chain key aggregation schemes), which make it a powerful way of transacting privately even between users with advanced keys and scripts on Taproot.

bip-0000.mediawiki Outdated Show resolved Hide resolved
bip-0000.mediawiki Outdated Show resolved Hide resolved
bip-0000.mediawiki Outdated Show resolved Hide resolved
Copy link
Contributor

@vostrnad vostrnad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some light review so far, but I'm really liking the proposal. Being able to easily implement just the sending part will no doubt greatly accelerate adoption by wallets.

Apart from the inline comments I also have a few style nits:

  • "e.g" is used instead of "e.g." in a few places.
  • Mixed usage of curly () and straight (') single quotes.
  • Some footnotes ("Rationale and References") are missing a period at the end.
  • In Creating outputs, "Let a = a0 + a1 + … ai, where each ai" should have an be the last member of the sum, like in the rest of the document. Same goes for the sum in Scanning where the last member should be An.

bip-0000.mediawiki Outdated Show resolved Hide resolved
bip-0000.mediawiki Outdated Show resolved Hide resolved
bip-0000.mediawiki Outdated Show resolved Hide resolved
@josibake
Copy link
Member Author

josibake commented Jun 8, 2023

Thanks for the review, @vostrnad !

Apart from the inline comments I also have a few style nits:

These should all be fixed now in 1ae1b4b

bip-0000.mediawiki Outdated Show resolved Hide resolved
bip-0000.mediawiki Outdated Show resolved Hide resolved
@josibake josibake force-pushed the silent-payments-bip branch 3 times, most recently from 98f37a9 to d9e5a1b Compare June 14, 2023 12:37
Copy link
Contributor

@vostrnad vostrnad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Second round of review. To complement this I wrote a quick and dirty implementation covering most of both sending and receiving. It was quite easy and seems to work, can't wait for test vectors to see how many bugs it has! 😅

In addition to the inline comments I have one general comment and one style nit:

  • There are no specifics on how to deal with situations where EC operations fail to produce a valid point. I'm not sure if this is necessary, just mentioning this because my implementation has a lot of assertions.
  • Tweak expressions are not consistent in whether the G part comes first or second. For example, in BIP341 it always comes second.

bip-0000.mediawiki Outdated Show resolved Hide resolved
bip-0000.mediawiki Outdated Show resolved Hide resolved
bip-0000.mediawiki Outdated Show resolved Hide resolved
bip-0000.mediawiki Outdated Show resolved Hide resolved
bip-0000.mediawiki Outdated Show resolved Hide resolved
bip-0000.mediawiki Outdated Show resolved Hide resolved
bip-0000.mediawiki Outdated Show resolved Hide resolved
@josibake josibake force-pushed the silent-payments-bip branch 3 times, most recently from 889a0b6 to be18f6f Compare June 15, 2023 10:35
@josibake
Copy link
Member Author

Thanks for the continued review, @vostrnad !

There are no specifics on how to deal with situations where EC operations fail to produce a valid point. I'm not sure if this is necessary, just mentioning this because my implementation has a lot of assertions.

Do you have a specific scenario in mind? I'm certainly not an expert in this area, but I don't think we should get a failure by doing additions and multiplications (summing priv keys, pub keys, ecdh). If we can have a failure when summing up the private keys, public keys, or during the ECDH step, our only recourse would be to restart the coin selection process and ensure we get different inputs.

@josibake josibake force-pushed the silent-payments-bip branch 2 times, most recently from ad7fa34 to d342de6 Compare June 15, 2023 12:41
@vostrnad
Copy link
Contributor

I don't think we should get a failure by doing additions and multiplications (summing priv keys, pub keys, ecdh)

One reason EC operations can fail is when a pseudorandom scalar value exceeds the curve order, which should only happen with negligible probability but other BIPs still have special cases for when it happens (e.g. BIP32, BIP340 and BIP341). I suppose it could be fine to ignore this, but I'm certainly no expert either.

bip-0000.mediawiki Outdated Show resolved Hide resolved
bip-0000.mediawiki Outdated Show resolved Hide resolved
bip-0000.mediawiki Outdated Show resolved Hide resolved
bip-0000.mediawiki Outdated Show resolved Hide resolved
@josibake
Copy link
Member Author

I don't think we should get a failure by doing additions and multiplications (summing priv keys, pub keys, ecdh)

One reason EC operations can fail is when a pseudorandom scalar value exceeds the curve order, which should only happen with negligible probability but other BIPs still have special cases for when it happens (e.g. BIP32, BIP340 and BIP341). I suppose it could be fine to ignore this, but I'm certainly no expert either.

I'll take a look to see how it's being handled in those BIPs. Ideally, we can reuse the same solution here. The main thing is ensuring both the sender and receiver can deterministically handle these low-probability events.

bip-0000.mediawiki Outdated Show resolved Hide resolved
@kallewoof
Copy link
Member

@luke-jr Unless you see anything objectionable, please assign BIP number.

@josibake
Copy link
Member Author

@vostrnad

One reason EC operations can fail is when a pseudorandom scalar value exceeds the curve order, which should only happen with negligible probability but other BIPs still have special cases for when it happens (e.g. BIP32, BIP340 and BIP341). I suppose it could be fine to ignore this, but I'm certainly no expert either.

I did some more reading on this and from what I can tell this applies to choosing a scalar which results in a valid point on the curve, which is not true for every scalar. In our case, we are already using existing valid private keys or, in the case of the silent payment address, are using BIP32 to generate them. Adding these keys together (using the elliptic curve group operation) or multiplying a valid scalar with a point (ECDH) gives us a result that is guaranteed to be a valid point on the curve.

@RubenSomsen
Copy link
Contributor

Thanks everyone for all the precious feedback. It has been humbling to see the amount of support this BIP has received. @josibake and I feel the BIP is now mature and will no longer be making breaking changes. With various implementations well underway, we propose moving the BIP status to final.

@jirijakes
Copy link

jirijakes commented Apr 9, 2024

Versions are specified as:

If the receiver's silent payment address version is:

  • v0: check that the data part is exactly 66-bytes. Otherwise, fail
  • v1 through v30: read the first 66-bytes of the data part and discard the remaining bytes
  • v31: fail

In the same Versions section:

Version is communicated through the address in the same way as Segwit addresses.

and later in Address encoding section:

The final address is a Bech32m [refers to BIP 350] encoding of[…]

However, both BIP 350 and BIP 173 restrict the version numbers to range 0..16.

BIP 350:

The following code demonstrates the checks that need to be performed.

def decode(hrp, addr):
   […]
   # Witness versions are in range 0..16.
   if data[0] > 16:
       return (None, None)

So while technically the encoding format could handle whole 0..31 range, the BIPs restrict it. The existing Bech32 decoders might, therefore, fail with versions higher than 16, for example, rust-bech32.

Not sure what would be the best way to deal with it – either allow the same version range as BIP 350 or make it clear that the version range differs from BIP 350.

input_hash = get_input_hash([vin.outpoint for vin in vins], A_sum)
pre_computed_labels = {
(generate_label(b_scan, label) * G).get_bytes(False).hex(): generate_label(b_scan, label).hex()
for label in given["labels"]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a suggestion to reflect “always check for the change label” in reference implementation and test vector. I believe the following changes should be enough.

Given this, the address for change would have to be removed from the relevant test case but I believe that it would be consistent with “It is important that the wallet never hands out the label with m = 0.”

Reference (always check for m = 0):

Suggested change
for label in given["labels"]
for label in given["labels"] + [0]

And then in test data (don't explicitly refer to label 0):

diff --git a/bip-0352/send_and_receive_test_vectors.json b/bip-0352/send_and_receive_test_vectors.json
index 5d329f7..99cc52c 100644
--- a/bip-0352/send_and_receive_test_vectors.json
+++ b/bip-0352/send_and_receive_test_vectors.json
@@ -1829,14 +1829,11 @@
                         "spend_priv_key": "b8f87388cbb41934c50daca018901b00070a5ff6cc25a7e9e716a9d5b9e4d664",
                         "scan_priv_key": "11b7a82e06ca2648d5fded2366478078ec4fc9dc1d8ff487518226f229d768fd"
                     },
-                    "labels": [
-                        0
-                    ]
+                    "labels": []
                 },
                 "expected": {
                     "addresses": [
-                        "sp1qqw6vczcfpdh5nf5y2ky99kmqae0tr30hgdfg88parz50cp80wd2wqqauj52ymtc4xdkmx3tgyhrsemg2g3303xk2gtzfy8h8ejet8fz8jcw23zua",
-                        "sp1qqw6vczcfpdh5nf5y2ky99kmqae0tr30hgdfg88parz50cp80wd2wqqlv6saelkk5snl4wfutyxrchpzzwm8rjp3z6q7apna59z9huq4x754e5atr"
+                        "sp1qqw6vczcfpdh5nf5y2ky99kmqae0tr30hgdfg88parz50cp80wd2wqqauj52ymtc4xdkmx3tgyhrsemg2g3303xk2gtzfy8h8ejet8fz8jcw23zua"
                     ],
                     "outputs": [
                         {

@josibake
Copy link
Member Author

@jirijakes thanks for the thorough review!

So while technically the encoding format could handle whole 0..31 range, the BIPs restrict it. The existing Bech32 decoders might, therefore, fail with versions higher than 16, for example, rust-bech32.

Not sure what would be the best way to deal with it – either allow the same version range as BIP 350 or make it clear that the version range differs from BIP 350.

Great point, I'm leaning towards having it match the versioning restrictions of BIP350 to avoid unnecessary headache for implementers. Regardless, I think we also need to include sending to a higher version address in our test vectors.

I have a suggestion to reflect “always check for the change label” in reference implementation and test vector. I believe the following changes should be enough.

Given this, the address for change would have to be removed from the relevant test case but I believe that it would be consistent with “It is important that the wallet never hands out the label with m = 0.”

Great suggestion, will add!

Copy link
Contributor

@jonatack jonatack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Began an initial review a fortnight ago -- a couple comments I had at the time before GitHub loses them, that may or may not be relevant.

bip-0352/bitcoin_utils.py Show resolved Hide resolved
bip-0352/reference.py Show resolved Hide resolved
bip-0352/bitcoin_utils.py Outdated Show resolved Hide resolved
@josibake josibake force-pushed the silent-payments-bip branch 3 times, most recently from d8ed18c to 36fefe5 Compare May 1, 2024 15:21
@murchandamus
Copy link
Contributor

I’m not quite sure what the status of this PR is, but since at least it looked like it had an open Change Request from Ruben, I requested that he review again.

@murchandamus
Copy link
Contributor

murchandamus commented May 2, 2024

It has been pointed out to me that @RubenSomsen suggested that the document were ready for final. I interpret this as his prior change request having been satisfied and we can disregard the open Change Request.

However, it seems to me that the next step would be to move the proposal status from Draft to Proposed rather than Final.

@murchandamus murchandamus dismissed RubenSomsen’s stale review May 2, 2024 20:48

As pointed out in the prior comments, Ruben’s review from 2023 appears to be outdated.

Copy link
Contributor

@murchandamus murchandamus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This proposal seems to be complete and ready to go. I have left a few nits, but none of these are blockers. I’m not merging immediately to give the BIP champions a chance to respond to my review.

ACK 36fefe5

Status: Draft
Type: Standards Track
Created: 2023-03-09
License: BSD-2-Clause
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please consider adding the "Post-History" header to link to the mailing list and additional fora where this proposal has been discussed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

bip-0352.mediawiki Outdated Show resolved Hide resolved
bip-0352.mediawiki Outdated Show resolved Hide resolved

Bob publishes a public key ''B'' as a silent payment address. Alice discovers Bob's silent payment address, selects a UTXO with private key ''a'', public key ''A'' and creates a destination output ''P'' for Bob in the following manner:

* Let ''P = B + hash(a·B)·G''
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Let ''P = B + hash(a·B)·G''

Nit: I noticed that the symbol ''·'' (presumably elliptic curve scalar multiplication) was not introduced in the first paragraph of Overview.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added.

''' Spend and Scan Key '''

Since Bob needs his private key ''b'' to check for incoming payments, this requires ''b'' to be exposed to an online device. To minimize the risks involved, Bob can instead publish an address of the form ''(B<sub>scan</sub>, B<sub>spend</sub>)''. This allows Bob to keep ''b<sub>spend</sub>'' in offline cold storage and perform the scanning with the public key ''B<sub>spend</sub>'' and private key ''b<sub>scan</sub>''. Alice performs the tweak using both of Bob's public keys in the following manner:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this still an open todo?

bip-0352.mediawiki Outdated Show resolved Hide resolved
bip-0352.mediawiki Outdated Show resolved Hide resolved
bip-0352.mediawiki Outdated Show resolved Hide resolved
@murchandamus
Copy link
Contributor

Given that there is at least one implementation of your BIP already, I was wondering whether you have considered advancing it’s status to "Proposed".

@@ -140,7 +140,7 @@ For everything not defined above, we use the notation from [https://github.com/b

=== Versions ===

This document defines version 0 (''sp1q''). Version is communicated through the address in the same way as Segwit addresses. Future upgrades to silent payments will require a new version. As much as possible, future upgrades should support receiving from older wallets (e.g. a silent payments v0 wallet can send to both v0 and v1 addresses). Any changes that break compatibility with older silent payment versions should be a new BIP.
This document defines version 0 (''sp1q''). Version is communicated through the address in the same way as bech32 addresses (see [[https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki#bech32 BIP173]]. Future upgrades to silent payments will require a new version. As much as possible, future upgrades should support receiving from older wallets (e.g. a silent payments v0 wallet can send to both v0 and v1 addresses). Any changes that break compatibility with older silent payment versions should be a new BIP.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m sorry, I was confused, this link should have used single brackets instead of double brackets.

Suggested change
This document defines version 0 (''sp1q''). Version is communicated through the address in the same way as bech32 addresses (see [[https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki#bech32 BIP173]]. Future upgrades to silent payments will require a new version. As much as possible, future upgrades should support receiving from older wallets (e.g. a silent payments v0 wallet can send to both v0 and v1 addresses). Any changes that break compatibility with older silent payment versions should be a new BIP.
This document defines version 0 (''sp1q''). Version is communicated through the address in the same way as bech32 addresses (see [https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki#bech32 BIP173]. Future upgrades to silent payments will require a new version. As much as possible, future upgrades should support receiving from older wallets (e.g. a silent payments v0 wallet can send to both v0 and v1 addresses). Any changes that break compatibility with older silent payment versions should be a new BIP.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

josibake and others added 5 commits May 8, 2024 18:14
Co-Authored-By: Ruben Somsen <rsomsen@gmail.com>
* reference.py contains the silent payment specific code
* secp256k1.py for doing the EC operations
* bech32m.py contains code for encoding/decoding bech32(m) addresses
* bitcoin_utils.py contains some helper code, not specific to silent
  payments
* send_and_receive_test_vectors.json contains the wallet unit test
  vectors

Co-Authored-By: S3RK <1466284+S3RK@users.noreply.github.com>
Co-Authored-By: Oghenovo Usiwoma <37949128+Eunovo@users.noreply.github.com>
Co-authored-by: S.Blagogee <34041358+setavenger@users.noreply.github.com>
Punctuation and wording improvements.

Co-authored-by: Mark "Murch" Erhardt <murch@murch.one>
@josibake
Copy link
Member Author

josibake commented May 8, 2024

Given that there is at least one implementation of your BIP already, I was wondering whether you have considered advancing it’s status to "Proposed".

Updated to Proposed. Thanks for the review @murchandamus , RFM!

- Fix link
- Add explanation for scalar multiplication
- Spelling error in test section
@murchandamus murchandamus merged commit d2300be into bitcoin:master May 8, 2024
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet