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
base: master
Are you sure you want to change the base?
BIP 352: Silent Payments #1458
Conversation
0ef28f3
to
f1c188f
Compare
There was a problem hiding this 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.
There was a problem hiding this 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.
f1c188f
to
1ae1b4b
Compare
98f37a9
to
d9e5a1b
Compare
There was a problem hiding this 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.
889a0b6
to
be18f6f
Compare
Thanks for the continued review, @vostrnad !
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. |
ad7fa34
to
d342de6
Compare
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. |
87f3104
to
d920133
Compare
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. |
@luke-jr Unless you see anything objectionable, please assign BIP number. |
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. |
I mean its possible sure, its also possible people try to byte-swap your public keys and send to an invalid address. People can creatively mis-interpret specs in all kinds of fun ways, but if we tell them what to do and have a few wallets doing it "right" and not supporting anything "wrong", then new developers will figure out that they're doing it wrong real fast when they go to test it once.
Exactly! So lets improve the process and learn from past mistakes. Instead of not bothering to define anything remotely backwards compatible, lets use silent payments to show how to do it right in a way that lets people use new features without waiting five years for the whole ecosystem to adopt it. (or, honestly, more, taproot probably wont be usable until more than five years after activation...). More broadly, Bitcoin has grown up - the utter failure that is taproot address support should be an indication that we need to totally rethink this. Bitcoin is a much bigger world than it used to be, and just throwing things over the wall doesn't work anymore - there will probably always exist senders somewhere that don't support taproot addresses.
Indeed, we need to do something, and if I had to rewrite BIP21 today I'd write explicitly that "new address formats MUST define a key and be placed in the parameters section." I don't see a reason why we'd prefer some kind of generic optionN vs just saying "this is type Y" - the second makes it much clearer to the reader what they're dealing with (eg new address formats could elide the HRP if they wanted to save a bit on space in QR codes, which is often worth it), whereas the first is just an opaque "here's a thing", while wasting QR code space. |
@TheBlueMatt @RubenSomsen @kristapsk this discussion is broader than just BIP352 and is starting to feel off-topic for this BIP. I've opened a delving bitcoin topic where we can continue the discussion: https://delvingbitcoin.org/t/revisiting-bip21/630 Would love to have your input over there! |
I'm really not sure why this ended up being a whole discussion - a simple one-line "Silent payment instructions in bitcoin: URIs MUST be placed in the |
I went ahead and suggested concrete updates to BIP 21 at #1555 |
2857784
to
92b12ab
Compare
92b12ab
to
f6dd067
Compare
When calculating input_hash, should we select the smallest outpoint from the set of all outpoints in the transaction, or should we select it from the set of associated outpoints related to the inputs we used for shared secret derivation? While trying to reason about this, I looked at the test vectors. Two of the tests deal with excluding inputs for shared secret derivation; however, they both exclude the lexicographically largest outpoints. That means if I believed in either "set of all" or "set of associated", then the tests would pass, but my logic would be faulty. The BIP's test vectors related to my question:
|
@mplsgrant Not all outpoints can be used for shared secret derivation. The excluded inputs were not excluded because of their lexicographic positions, they were excluded because they did not meet the criteria defined in https://github.com/bitcoin/bips/blob/f6dd0672d81aa22368024c8ce7fe7e763a77a9f5/bip-0352.mediawiki#inputs-for-shared-secret-derivation Suppose we have a Transaction T, That said, it might be a good idea to add vectors that use an OUTPOINT(L) that is not in Set A. EDIT |
f6dd067
to
9c82669
Compare
Updated f6dd067 -> 9c82669 (compare):
For implementing sending, the tests give a set of inputs and outputs to match against. However, due to hashing with the counter I also included a small change based on @mplsgrant feedback which makes it more clear that the |
9c82669
to
57c89ae
Compare
We have implemented Silent Payments in Cake Wallet for iOS, Android, Mac, and Linux. Would love for you guys to test it and give some feedback back. |
We have implemented Silent Payments in Cake Wallet for iOS, Android, Mac, and Linux. Would love for you guys to test it and give some feedback back. |
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. |
Versions are specified as:
In the same Versions section:
and later in Address encoding section:
However, both BIP 350 and BIP 173 restrict the version numbers to range 0..16. BIP 350:
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"] |
There was a problem hiding this comment.
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):
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": [
{
@jirijakes thanks for the thorough review!
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.
Great suggestion, will add! |
There was a problem hiding this 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.
@@ -0,0 +1,162 @@ | |||
import hashlib |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add at the top of this file and in secp256k1.py
to allow invoking these files directly.
+#!/usr/bin/env python3
+
import hashlib
import struct
from io import BytesIO
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, these are library files and shouldn't be run directly. Not sure if there is a standard way in python to communicate that, but I think the only file that should have a shebang is reference.py
?
Co-Authored-By: Ruben Somsen <rsomsen@gmail.com>
a2822e3
to
cbac6bc
Compare
* 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>
cbac6bc
to
d8ed18c
Compare
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.