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
@josibake josibake force-pushed the silent-payments-bip branch from 0ef28f3 to f1c188f Compare June 6, 2023 13:15
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 josibake force-pushed the silent-payments-bip branch from f1c188f to 1ae1b4b Compare June 8, 2023 09:21
@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 josibake force-pushed the silent-payments-bip branch from 87f3104 to d920133 Compare June 16, 2023 11:07
@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
Contributor

@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.

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
Member

@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 murchandamus requested a review from RubenSomsen May 2, 2024 19:00
@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

@murchandamus murchandamus May 8, 2024

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 josibake force-pushed the silent-payments-bip branch from 5b17cd3 to 32a3293 Compare May 8, 2024 16:13
josibake and others added 5 commits May 8, 2024 18:14
Co-Authored-By: Ruben Somsen <[email protected]>
* 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 <[email protected]>
Co-Authored-By: Oghenovo Usiwoma <[email protected]>
Co-authored-by: S.Blagogee <[email protected]>
Punctuation and wording improvements.

Co-authored-by: Mark "Murch" Erhardt <[email protected]>
@josibake josibake force-pushed the silent-payments-bip branch from 32a3293 to 82c2f78 Compare May 8, 2024 16:17
@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!

@josibake josibake force-pushed the silent-payments-bip branch from 82c2f78 to a60bfc3 Compare May 8, 2024 16:30
josibake added 2 commits May 8, 2024 18:34
- Fix link
- Add explanation for scalar multiplication
- Spelling error in test section
@josibake josibake force-pushed the silent-payments-bip branch from a60bfc3 to 17e1d16 Compare May 8, 2024 16:34
@murchandamus murchandamus merged commit d2300be into bitcoin:master May 8, 2024
3 checks passed
@junderw
Copy link
Contributor

junderw commented Jun 3, 2024

@josibake When thinking about potential APIs for BitcoinJS with SP, the concept of PSBTs doesn't seem to work well with SP at all. It almost precludes the tx creation, signing, and finalizing MUST be done on the same device in one go.

I think the SP BIP should at least mention that PSBT use should be avoided in the case of fully unsigned PSBTs or only has signatures that are SIGHASH_ANYONECANPAY. Since someone could easily modify the input set.

In the long run, SP will require a few upgrades to PSBT one of which is backwards incompatible.

  1. Add an output data field containing SP data. I think this might require the scan-private-key, otherwise the finalizer can't double check the validity of the output scriptPubkey.
  2. (Backwards incompatible) Update the PSBT version field and add the rule that "When finalizing the last input, finalizers MUST verify the scriptPubkey of EVERY output with silent payment output data before finalizing."

There are a lot of use cases for PSBT which would be dangerous to use with SP and some loose non-required "conventions."

I would be interested to hear your thoughts. I don't have a clear change proposal so I couldn't think of a PR to make, so excuse my reviving a dead PR.

@josibake
Copy link
Member Author

josibake commented Jun 3, 2024

Hey @junderw , we are discussing PSBT proposals on delving bitcoin and @andrewtoth has already started a draft BIP. It would be great to have your input over there!

Regarding updates to this BIP, I think it would be more appropriate to finalize a silent payments PSBT BIP and then link to that BIP here. If we do end up needing a PSBTv3 for supporting silent payments, then we should definitely mention incompatibility with older PSBT versions here and point to the new PSBTv3 proposal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.