-
Notifications
You must be signed in to change notification settings - Fork 37.4k
[Draft / POC] Silent Payments #24897
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
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
Concept ACK |
b97fee2
to
340f67d
Compare
Need some way to avoid users trying to send a silent payment to a wallet that doesn't support it... am I missing something? |
@luke-jr Yes, it will need to be further discussed if this concept proves to be valid. In this PR, all descriptor wallets support silent transactions as the As only Taproot addresses can be used for silent payments and only descriptor wallets support Taproot, this may suffice, but it certainly needs further discussion. |
@luke-jr When the recipient publishes their silent payment address, it needs to be clear that it is not a regular taproot address. The address format should be distinct. The tweaked silent payment address that is generated by the sender and is ultimately committed on-chain should be indistinguishable from a regular taproot output.
@w0xlt Note that nothing about the silent payment scheme is exclusive to taproot, but regardless I do think it's good to limit the specifications to creating taproot outputs only as it encourages taproot use and means transactions without taproot outputs (albeit hopefully rare in the eventual future) don't need to be scanned. |
But I don't see that in this current spec/code? |
340f67d
to
0fe8e02
Compare
ret.pushKV("label", label); | ||
ret.pushKV("identifier", identifier); | ||
if (identifier > 0) { | ||
ret.pushKV("warnings", "This address is not a new identity. It is a re-use of an existing identity with a different label."); |
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.
The term "identity" is confusing here. It's also confusing that you get this error when you g 10000 enerate a new silent payment address, but not when you request an existing one (by reusing a label).
I guess what you're trying to say here is that an outside observer can tell that two silent payment addresses belong to the same person? Maybe just say that:
The silent payment addresses are unique for accounting purposes only. They can be linked to the same wallet. For privacy a new wallet is required.
That said, I think this feature is a footgun. Also because poor coin control will eventually link funds from all labels.
This would be nice though, maybe in a followup. I was trying to test it with I guess one thing you need for that is the ability to dump the watch key. You could add an argument Finally I noticed that calling |
Co-authored-by: Aurèle Oulès <aurele@oules.com>
Co-authored-by: josibake <josibake@protonmail.com>
ee652ca
to
50a6320
Compare
I've rebased and created a slimmed-down version of this PR in #27827. Most notably, I took out labels and removed some of the RPC support, and made several updates as the silent payments spec has changed a bit since this PR was last updated. For anyone reviewing this PR, I'd appreciate your feedback on #27827. Big thanks to @w0xlt for moving this draft along as far as they did! My plan is to keep cherry-picking commits from this draft for follow-up PRs to add back in label support, RPC coverage, etc |
Closing this, in favour of #27827. |
This PR proposes an early version of Silent Payment (author:@RubenSomsen).
In this scheme, the recipient generates a public address, but the sender tweaks the address and the recipient detects the payment by verifying all transactions on the blockchain. An example use case would be private donations.
The purpose of this PR is not a final version, but to start the discussion and get benchmarks based on a real implementation.
This version is built on top of #994 (bitcoin-core/secp256k1) for x-only ECDH support and #23480 (bitcoin/bitcoin) for
rawtr()
. Each new silent transaction detected is stored in wallet as arawtr()
descriptor.In this implementation, the sender can tweak the recipient address by passing the
silent_payment
option to send RPC. The transaction output will be different from the address entered.For example
./src/bitcoin-cli -regtest -named send outputs="[{\"bcrt1pwlh5xuyrpgfunwyww8cfu78yfs2yqyevl7yturavahh5kgxwdd2q5hzgfu\": 1.1}]" fee_rate=1 options="{ \"silent_payment\": true}"
.will generate
vout
with completely unrelated outputs:Any wallet, as long as it has access to private keys, can send silent payments. Thus, this excludes watch-only wallets or wallets with external signers .
But the recipient's wallet needs a new flag called
SILENT_PAYMENT
. This flag allows an additional scan that verifies that the wallet keys match the silent payment scheme. When it detects a silent payment that belongs to the wallet, it is stored in arawtr()
descriptor../src/bitcoin-cli -regtest -named createwallet wallet_name="recipient" silent_payment=true
Therefore, scanning each address for each transaction is potentially prohibitive overhead, so the node can be initialized with
keypool=1
or a descriptor with range [0,1] can be imported into a blank wallet. Until there is more benchmark data, it is the safest option. The proposal recommends one static address.I've been running some silent payments on signet using wallets with default keypool and default range, I haven't noticed any relevant performance drops on the signet node.
Apparently this implementation is working as expected but I can't guarantee that the scheme is implemented correctly or safely, so I'm opening this PR for reviews, modifications and improvements.
There is a new functional test (
test/functional/wallet_silentpayment.py
) that can help to better understand the implementation.