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
wallet: Deniability API (Unilateral Transaction Meta-Privacy) #27792
base: master
Are you sure you want to change the base?
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. Code CoverageFor detailed information about the code coverage, see the test coverage report. 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. |
@achow101 - per our discussion, I've created a PR with the core "deniability" functionality in the main repo here. The GUI portion is rebased over this branch and is in the GUI repo. I've updated the PRs' descriptions to point to each other. |
Not sure how much this achieves. Bitcoin Core's wallet has a "unique" fingerprint on transactions that is shared by way less than 50% of transactions in the network, so creating additional transactions where it is likely (latest when the outputs are spent) that it was a self-transfer seems only to be bloating the utxo set and chain space? I haven't thought about this, but it would be good to have a more in-depth analysis of this, considering using a different "fingerprint vector". |
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.
NACK
It doesn't improve privacy. Not considering fingerprints. A better way to improve privacy in bitcoin payments using bitcoin core could be payjoin.
False sense of privacy implemented in this pull request only helps miners with fees.
By fingerprint, do you mean Bitcoin Core's transactions can be identified on the block chain? If that's the case that's unfortunate for sure. What's the nature of the difference? Is it on purpose and if not, would it be possible to fix? |
Thanks! |
Can you please elaborate why you think so?
It's important to point out that this PR doesn't add functionality that couldn't be achieved manually before. The API we're adding in this PR makes this a simple and robust single operation (C++ API call or RPC call). The GUI PR (bitcoin-core/gui#733) implements automation on top of this API, which is also entirely opt-in. We provide an explanation of how it works, so the user could make an educated decision on whether to use it or not. |
Good point and most of the people who tried this with coins involved in any incident regret doing it. Privacy in bitcoin is not as simple as doing some transactions with your own addresses automatically. There are lot of things you need to take care of. One mistake and your privacy is breached, publicly available for the whole world. Payjoin will improve privacy without wasting fees on these automated transactions by hiding the amounts involved in transaction. Presently, payjoin is less used because of the need for a server but this can be improved. |
What kind of incidents do you mean? Do you have some concrete examples? |
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.
Hey @denavila, welcome to Bitcoin Core and thanks for working on this! While I think that this idea could be useful to some extent if implemented correctly, I have a few concerns about the current implementation:
- Currently there is no precaution against a user spending two outputs of a deniabilization transaction together. IMO I think that this is quite problematic and could lead to these deniabilization transactions being rendered ineffective. Not only that, but then it also becomes obvious that a user is trying to deniabilize their funds, which is something that should be avoided.
- As mentioned by @MarcoFalke, currently it is simple to identify Bitcoin Core transactions. Given that the Bitcoin Core wallet does not make up a large portion of on-chain transactions, if a blockchain observer sees that there is a long chain of transactions sending to and receiving from Bitcoin Core wallets, it could become clear that these are deniabilization transactions.
- Additionally, in the current implementation all of the inputs of a deniabilization transaction must share the same address. It is not immediately obvious to me why this was done. This fact, combined with the previous two issues, could make it trivial to identify deniabilization transactions created by BItcoin Core.
Solving some of these problems could be tricky and might require significantly more code being added to the Bitcoin Core wallet. Given this, I’m unsure whether it would make sense for an implementation of something like this to be built directly into Bitcoin Core. I'd be curious to hear what others think.
Sorry. I cannot share exact incidents that involve "crime" on GitHub. However, you can look at this explanation from bitcoin privacy wiki to understand basics: "In a peeling chain, a single address begins with a relatively large amount of bitcoins. A smaller amount is then peeled off this larger amount, creating a transaction in which a small amount is transferred to one address, and the remainder is transferred to a one-time change address. This process is repeated - potentially for hundreds or thousands of hops - until the larger amount is pared down, at which point (in one usage) the amount remaining in the address might be aggregated with other such addresses to again yield a large amount in a single address, and the peeling process begins again[5]." |
Hi @ishaanam and thank you for looking at my PR. Here are my thoughts regarding your concerns:
I thought about if this could be implemented in some kind of a plugin, but as far as I know, there's no support for plugins yet? Thank you for your feedback. I greatly appreciate it. |
Not only that, but if you spend a UTXO that’s the change from the previous transaction with the output of the next, that’s one thing. But if you spend an output with the change from fifteen transactions prior, you may heavily imply that all payments in between were also self-sends.
Yeah, that sounds like a reasonable direction of development. It would e.g. be possible to pick from two otherwise similar inputs sets the one that creates a change output whose value is most different from other UTXOs already in the wallet. Otherwise, it is a bit difficult to predict what a “likely spendable size” is, since it depends on many different factors such as future exchange rate, and unknown future motivations for the user to create transactions. I would surmise that past transactions would only have a limited utility in predicting future spending sizes. In fact in my master-thesis, I explored a similar idea by attempting to always create change of a similar amount as the recipient output. Unfortunately, the resulting UTXO pool performed subpar. |
In a tx graph ( tree really ) with large and randomized fan out, eventual merging of some terminal UTXOs does not necessarily indicate that the later clustered entity is the same entity that was KYC’ed on an exchange prior to the deniabilization fan out. Some probability maybe assigned to both entities being the same but there’s also a combinatorial explosion of other possible clusterings in between. |
Would it not be better to postpone removing the Core tx fingerprints to Deniabilization 1.1 or 2.0 version and get this safe, isolated UI centric feature merged in sooner rather than later ? |
f231492
to
7f76f8e
Compare
b2a41f4
to
130f43c
Compare
130f43c
to
d6b497a
Compare
A failure in the "Win64 native, VS 2022" CI job is unrelated. See: #28905. |
d6b497a
to
21e39b9
Compare
This pull silently conflicts with master: wallet/rpc/spend.cpp: In lambda function:
wallet/rpc/spend.cpp:1806:49: error: ‘transaction_identifier<has_witness>::transaction_identifier(const uint256&) [with bool has_witness = false]’ is private within this context
1806 | COutPoint outpoint(txid, nOutput);
| ^
In file included from ./primitives/transaction.h:14,
from ./consensus/validation.h:11,
from wallet/rpc/spend.cpp:5:
./util/transaction_identifier.h:16:5: note: declared private here
16 | transaction_identifier(const uint256& wrapped) : m_wrapped{wrapped} {}
| ^~~~~~~~~~~~~~~~~~~~~~ |
21e39b9
to
928a0dc
Compare
928a0dc
to
78371b1
Compare
8533bcf
to
737fbc4
Compare
737fbc4
to
95e53e7
Compare
This PR is the wallet API and implementation portion of the GUI PR ( bitcoin-core/gui#733 ) which is an implementation of the ideas in Paul Sztorc's blog post "Deniability - Unilateral Transaction Meta-Privacy"(https://www.truthcoin.info/blog/deniability/). The GUI PR has all the details and screenshots of the GUI additions. Here I'll just copy the relevant context for the wallet API changes: " In short, Paul's idea is to periodically split coins and send them to yourself, making it look like common "spend" transactions, such that blockchain ownership analysis becomes more difficult, and thus improving the user's privacy. I've implemented this as an additional "Deniability" wallet view. The majority of the code is in a new deniabilitydialog.cpp/h source files containing a new DeniabilityDialog class, hooked up to the WalletView class. " While the Deniability dialog can be implemented entirely with the existing API, adding the core "deniabilization" functions to the CWallet and interfaces::Wallet API allows us to implement the GUI portion with much less code, and more importantly allows us to add RPC support and more thorough unit tests. ----- Implemented basic deniability unit tests to wallet_tests ----- Implemented a new 'walletdeniabilizecoin' RPC. ----- Implemented fingerprint spoofing for deniabilization (and fee bump) transactions. Currently spoofing with data for 6 different wallet implementations, with 4 specific fingerprint-able behaviors (version, anti-fee-sniping, bip69 ordering, no-rbf).
95e53e7
to
4e836f6
Compare
Tested it and I think it can be improved further before users can try it on mainnet: bitcoin-core/gui#733 (comment) |
This PR is the wallet API and implementation portion of the GUI PR ( bitcoin-core/gui#733 ) which is an implementation of the ideas in Paul Sztorc's blog post "Deniability - Unilateral Transaction Meta-Privacy"(https://www.truthcoin.info/blog/deniability/).
The GUI PR has all the details and screenshots of the GUI additions. Here I'll just copy the relevant context for the wallet API changes:
"In short, Paul's idea is to periodically split coins and send them to yourself, making it look like common "spend" transactions, such that blockchain ownership analysis becomes more difficult, and thus improving the user's privacy.
We've implemented this as an additional "Deniability" wallet view. The majority of the code is in a new deniabilitydialog.cpp/h source files containing a new DeniabilityDialog class, hooked up to the WalletView class. "
While the Deniability dialog can be implemented entirely with the existing API, adding the core "deniabilization" functions to the interfaces::Wallet API allows us to implement the GUI portion with much less code, and more importantly allows us to add RPC support and more thorough unit tests, which is what this PR attempts to do.
The main "deniabilization" functionality is implemented in spend.cpp/h and feebumper.cpp/h and exposed via the interfaces::Wallet API.
We've added RPC support via a new RPC call "walletdeniabilizecoin".
We also extended the Wallet tests with coverage for the functionality.