-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Feature: Add Silent Payment sending support #9900
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
base: master
Are you sure you want to change the base?
Feature: Add Silent Payment sending support #9900
Conversation
According to updated BIP21 specification silent payment addresses should be put in a In fact, it is even disallowed to put a silent payment address in the BIP21 uri root: The bitcoinaddress body MUST be either a base58 P2SH or P2PKH address, bech32 Segwit version 0 address, bech32m Segwit address, or empty. Future address formats SHOULD instead be placed in query keys as optional payment instructions to provide backwards compatibility during upgrade cycles. The bitcoinaddress part of the URI MAY be left empty if there is at least one payment instruction provided in a query parameter, allowing for recipients wishing to avoid a standard on-chain fallback. |
0276bc3
to
b1d4144
Compare
@accumulator Yes thanks! I completely missed that bip21 had specifications for bip352. I addressed this in commit b1d4144. It was more complicated than I thought, especially dealing with the absence of fallback addresses in wallets that can't send silent payments. |
Yes, we currently do the same for lightning-only payment identifiers; The PI is valid, even if the wallet does not support lightning. This leads to silent payment specific parameters and code in quite a few places.. I've added some review comments. |
Have you considered OpenAlias resolving to a silent payment address? This would seem like an ideal combination.. |
Getting an exception when address_synchronizer emits
|
@accumulator Oh.. yes, this is very likely because remove_silent_payment_address is called with txo.address as argument, which of course is None when there is a non-address scriptpubkey. Then the assertion makes no sense... I haven't thought about this, thx! I will get to it and your other comments tonight. |
I looked into it. Do you think the silent payment address can just be placed into the
If we just place the sp_address into the |
The unreleased OA2 spec is a bit more formalized than OA1, and even explicitly mentions BIP352. However we only implement OA1 currently.
I think that would indeed be sufficient.
That TODO is orthogonal to this change, and there's currently no PR or branch changing this code, so feel free to make changes there. |
ce28a36
to
5877272
Compare
@accumulator I added openalias recognizing sp_addresses in 0c5e83d. It was almost nothing to change, which makes me think I missed something. I tested it by mocking the call to the openalias-server in
This worked fine, also in non-sp-wallets. |
No, you didn't miss anything, that's sufficient. You can even remove https://github.com/MorenoProg/electrum/blob/0c5e83d3af7a8a69ed32ad28ab6b923886950a57/electrum/payment_identifier.py#L701-L703 as that is stale code |
There are still two design points where feedback is appreciated:
EDIT: Both concerns addressed and changes implemented in 8b39e15. |
4686e9c
to
7b56c45
Compare
Tested ACK - tests/test_silent_payment.py Please consider implementing sending test vectors as well Big thank you to everyone that has reviewed this PR to date. |
@macgyver13 Thanks for testing. I am using a slightly modified version of the test vectors, in which the mapping of |
I missed the implementation of those test cases 😢. The attached patch has the following output:
|
Yes, that would be better. The current branch immediately signs the transaction as soon as the dialog is opened, which is different behavior than normal payments, and might be confusing.
Instead of passing See my commit accumulator@7334e77 |
send_change_to_lightning=self.config.WALLET_SEND_CHANGE_TO_LIGHTNING, | ||
merge_duplicate_outputs=self.config.WALLET_MERGE_DUPLICATE_OUTPUTS, | ||
password=password, | ||
mind_silent_payments=True # always mind silent payments to detect sending to a previous sp-onchain addr |
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.
Shouldn't mind_silent_payments
be conditional on any(o.is_silent_payment() for o in outputs)
?
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.
At this point in the code, the outputs haven't been given to wallet.add_silent_payment_output_info(output)
yet, so any(o.is_silent_payment() for o in outputs)
will not detect a reused sp-onchain address. We could catch the address reuse already in send_tab.py
, but I think its better to have all the edge-case-handling centralized in wallet.make_unsigned_transaction
.
I think what's lacking still is a check to verify a |
Agreed. I addressed this in ab8486a. I re-added the sign button (disabled) and added a tool tip that informs the user about the automatic signing. My motivation for immediate signing is to never expose an incomplete sp-transaction to the user (not even for adding to history).
Applied. |
@accumulator I added an integrity check in 5486dd0. Right after tx-creation all the relevant silent payment elements (inputs and sp-outputs) are hashed and bound to the tx. This binding can happen only once. The integrity hash is verified against the actual transaction at the time of signing to ensure it hasn't been tampered with. Actually, we could be even more careful and also add this check again when broadcasting... |
# Conflicts: # electrum/gui/qt/transaction_dialog.py
# Conflicts: # electrum/gui/qt/send_tab.py
- Avoid prompting user twice for password - sign before showing preview, because silent payment psbt's make no sense - hide `sign` and `combine option in transaction dialog
…use it as internal flag. Only allow RBF if tx originated from same wallet instance.
… included it may causes unnecessarily recalculating the outputs during fee bumping with strategy DECREASE_PAYMENT
26fa4e5
to
975cec1
Compare
I propose to consider this PR for merging, as rebases are hard to re-review with this large delta, and the PR IMO looks pretty solid. If there's still remaining doubts w.r.t. loss of coins, we could add an 'experimental feature' warning when pasting/scanning a silent payment identifier. |
Just in case @accumulator's comment has gone unnoticed, tagging @ecdsa and @SomberNight. |
@MorenoProg I am not keen to merge this feature into master. At the moment, there does not seem to be a realistic way to implement both sending and receiving silent payments in a light client. This implies that silent payments will probably remain a fringe feature, not something that will see mass adoption. However, this feature also comes at a significant cost, in terms of complexity and maintenance burden for developers. It touches a bunch of files, it has its own logic, and it requires new developers to understand that logic in order not to break it. We recently opened Electrum to third-party plugins. Why not add this as a plugin instead? |
@ecdsa Just last week, a PoC, Frigate, was released that demonstrates a practical path to receiving silent payments in light clients. It uses an optimized tweak index and extends the Electrum protocol with methods that let a light client subscribe to Silent Payment addresses, similar to normal addresses. With this, a light client can also recover from seed.
Mass adoption remains to be seen, but there is quite some WIP across the silent payment ecosystem.
Your concerns listed in opening issue #9728 affect receiving only and you would prefer the receiving part as a plugin. Since sending and receiving are independent, it was my understanding that sending should belong in the core codebase. |
This PR introduces support for sending silent payments (BIP-0352), integrated into the desktop Qt interface.
Key Notes
RBF is disabled for silent payment transactions to prevent potential fund loss. If a user shares the same seed across two devices, broadcasts the transaction from one, and later bumps the fee on the other with added or changed inputs, the shared secret used in silent payments is broken, causing the recipient to miss the payment. If a transaction gets stuck in the mempool, users can still use CPFP as an alternative.RBF is allowed for silent payment transactions only when the fee bump is performed by the same wallet instance that created the transaction.