This title and content of this article was changed because the developer of XWallet addressed the concerns raised by weuse.cash. I won’t remove it because it’s still an interesting case of chainanalysis on the Monero blockchain. We are thankful towards Justin that he eventually understood the issue and decided to change his software implementation in such a way that the privacy of the users of his app is preserved.
On jan 25 the source code for Monero XWallet for iOS was released. Justin Smith (rusticbison) said on different occasions that he wants to monetize this app. Let me be clear from the start: I don’t have anything against this model. If you want to monetize your hard work, you should! But there is an issue with the way Justin wanted to monetize the app. Monero’s core value is privacy. I had good reasons to assume that the way XWallet were to be monetized would have been detrimental for the users’ privacy. Let’s explore this in this article. Note that for the larger part of the article I try to simplify the explanation by ignoring the fact that ring signatures are being used.
This is what the source was telling us about how the app were to be monetized:
The wallet provider fee is a flat 0.0005 XMR per outgoing transaction.
This means that every transaction would usually have 3 outputs: “payment”, “change” and “wallet fee”, while a non-XWallet transaction would usually only have 2 outputs: “payment” and “change”. Let’s look at how a normal transaction would look like compared to an XWallet transaction. Note that the image only shows one input. In general a transaction would have one or two inputs. However, if a user would have a lot of small unspent outputs in their wallet and wanted to send big amount, it’s possible that a lot more inputs were present in this transaction.
But this was not the whole picture… One could have expected that people using wallets would spend their change in the same way as they spent the original input. This is how in general normal user behavior would have looked like: (note that tx3, tx4 and tx6 have 2 inputs and the other transactions only have 1 input)
What’s clear from the image is that it would not at all have been obvious to see which output was the “payment” and which output was the “change” due to the fact that every transaction had 2 outputs. And due to the xmr stealth addresses, there wouldn’t ever be a reuse of the same (one time) address, making it nearly impossible to “cluster” certain txo’s. This means that the wallet privacy would be preserved.
Now let’s look at how an XWallet transactions looked like. Tx1 would be the first transaction using XWallet. It would have generated 3 outputs, as explained at the start. We see that tx3 and tx4 only would have had 2 outputs, so we can assume that these wouldn’t be XWallet transactions. Tx2 on the other hand would have 3 outputs! So the first obvious conclusion we can make is that tx2 would probably have been the XWallet user who sent out tx1 as well as using his change (o1) stemming from tx1. This means that we would have been able to cluster every transaction this user broadcasts using his XWallet.
Let’s analyze this transaction graph a bit more: tx4 would very likely have been a transaction made by the XWallet company grouping a bunch of the 0.0005 XMR wallet fee txo’s and sending them to a another wallet. We already established that o1 would be the change, so this means that it would have been very likely that the payment output in tx1 is o2. This transaction analysis would have been very bad for your privacy. Let’s expand our transaction graph a bit to show why:
In this example I’ve added 4 transactions. tx5 and tx7 would clearly be XWallet-transactions while tx6 and tx8 would not. Tx4 is still grouping wallet fees. It’s obvious using the same analysis techniques that tx1, tx2, tx5 and tx7 are would have been performed by the same user of XWallet. These transactions could be clustered. If tx1 would receive funds from an exchange wallet, this cluster of transactions would be identified and the user’s privacy would be at risk.
Imagine that a darknetmarket is taken down and they are seizing the wallets. Law enforcement has possession of the logs of outgoing and incoming transactions. A vendor has taken out XMR via tx6 and tx8 and received XMR from tx5 and tx7. If this vendor would perform a few successive transactions after tx6 and tx8, his funds would be anonymous. But… in this case there would have been a way to trace back the origin of the funds!
Tx6 gets input i1 from tx5o1. Note that this was received using a ring signature, so it’s either tx5o1 or one of the decoys in the ring signature. If law enforcement would visit the user of XWallet based on this information alone, he would still somewhat be able to plausibly deny that he send out tx5. Thanks to the ring signatures, it could have been one of the decoys. But…
Tx7 also shows up in the logs of the darknetmarket as an incoming transaction. i2 from tx8 originated from tx7o2! And this transaction is part of the cluster of the XWallet user! What are the odds that 2 times a transaction accidentally picked a decoy from the same cluster? This doesn’t really sound that likely. So now it would become almost a certainty that the suspicious user of XWallet did indeed performed tx5 and tx7, regardless of the use of ring signatures.
If the DNM buyer would have used a normal wallet (the GUI, Monerujo, …) the blockchain data wouldn’t contain any identifying transactions with 3 outputs and his privacy would be preserved. I think this example clearly shows why people needed to avoid the initial implementation of XWallet if they wanted to preserve their privacy using Monero.
XWallet original implementation would have weakened other people’s privacy as well!
We already established that when an XWallet user would have spent XMR he would be clustering his transactions. But this also means that certain txo’s would have been able to be marked as “spent”. In the above example all change outputs and wallet fee outputs from the cluster tx1, tx2, tx5 and tx7 would likely have been spent.
To be exact, this list of txo’s would likely have been spent: tx1o1, tx1o3, tx2o1, tx2o3, tx5o2, tx5o3 and tx7o3. Note that we can know this just by analyzing the blockchain.
Normally, thanks to ring signatures, we can’t really know if a certain txo is spent or not. But due to the fact that we can cluster the user behaviour, we can, with a very high degree of certainty “guess” that these txo’s are in fact spent.
This means that if your wallet picks a decoy from this set of outputs, chain analyzing software can just ignore this decoy. It was already spent in a previous transaction. So in case you’re using the default ring size of 5, your effective ring size is reduced to 4. So if people are using XWallet, it can actually weaken other people’s privacy as well!
Suggestions on how to monetize XWallet in a privacy-preserving way
XWallet eventually chose to become donationware.
I you use the app, please consider donating to the development:
As I said, I am not against paying for software. But it’s important to note that the “3rd output model” is bad for privacy and should be replaced by something else. I have a few suggestions:
1. Paying for the app using the Apple Store. By doing this, only the credit card company knows you bought the app, but doesn’t know what you do with the app. But I can see why (for ideological reasons) XWallet wants to support payments in XMR
2. Wallet Deposit Fee System. When you deposit money to the app, the app could “lock” the money and could ask the user to send a certain percentage to the XWallet company in a separate transaction. Once this fee is paid, the wallet will add a “fee paid flag” to the txo. This flag will carry over to the change so your wallet won’t ask for a fee when you receive change. This would introduce a little inconvenience, but you will be able to pay for the app using XMR.
Another disadvantage is that when you receive a small amount of xmr (for example a payment for a beer) you will need to “unlock” this payment by sending an additional transaction, which will cost you not only the wallet fee, but also the miners fee. Maybe it’s a good idea that the wallet sums up incoming payments and only asks for payment of the fee once the total of incoming transactions reaches a certain threshold.
An additional benefit would be that the fee transaction would also function as an additional “churn” making your funds a bit more private if you received them from a KYC/AML exchange. Note that if the user doesn’t want to pay the fee, he can import his seed in another wallet.
3. Transaction credits or pay per x transactions. XWallet could have a built-in system of “transaction credits” where the user pays a certain amount so he’s able to send out a few successive transactions. He could buy “packs” of 10, 100 or 1000 transactions. The wallet can keep track of how many transactions the wallet sent out. Once all the credits are used, the user needs to buy a new package (or he can import his seed in another wallet and get his funds out).
Another option could be that XWallet would lock the wallet every x (10, 20, 50, …) transactions. If the user wants to continue to use his wallet, he’ll need to pay a fee. If he doesn’t want to pay the fee, he can import the seed in another wallet.
I think these 3 solutions are worth taking a look at.
This article clearly shows that the way how you implement things actually matters. In this case, the old implementation was dangerous for the privacy (and maybe the life) of the users. I’m happy that, after the necessary feedback about the flaws, it’s fixed now and people can use XWallet in a privacy preserving way.
Support independent research: