Cracking the PayJoin
If you have been interested in Bitcoin privacy space for a while you have likely heard of the PayJoin, the newest and hottest BTC privacy tech around. It’s sometimes hailed as the savior of Bitcoin privacy and soon to be the bane of blockchain forensics companies everywhere. In this blog post I wish to be the Debbie Downer and demonstrate how, I believe, with some basic analysis and logic the privacy provided by PayJoin can be mitigated
If you do not know what a PayJoin is many smarter people have already written many great articles about how PayJoins looks and works. Check one of these out:
- The BIP78 specification according to which most PayJoin implementations are built:
- Deep dive into PayJoins and general transaction obfuscation by one of the co-creators and the founder of Wasabi wallet nopara73:
- Excellent exploration of PayJoin by Adam Gibson co-creator of PayJoin and JoinMarket:
As a basic reminder, the PayJoin is built on the same principle as CoinJoin with multiple parties owning inputs and outputs in one transaction only this time the maximum number of participants in the Join is 2 and one of them must be making a payment to the other. PayJoin has one massive advantage over CoinJoin, unlike CoinJoins, PayJoins are not easily detectable on the blockchain. In fact, they look exactly like regular multi-input, 2 outputs transactions.
The most likely implementation of this kind of scheme is a customer’s payment to the merchant. In which case the merchant commits one or more UTXO’s to the transaction as input and owns one of the outputs. Importantly, this obfuscates the payment amount that the customer has paid to the merchant.
Takes this random transaction as an example:
If we assume this transaction is a regular payment the normal possible interpretations for this transaction would be:
1) The sender owns both inputs as well as the first output (it’s change) and the recipient owns the second output. This is the most likely interpretation based on the “unnecessary input heuristic”, or in simpler English “this transaction wouldn’t need both of the inputs if it was paying only 0.011 BTC heuristic” (also the round output is obviously a dead giveaway). In this interpretation, the payment amount is 0.025 BTC.
2) The sender owns both inputs and the second output (as it’s change) and the recipient owns the first output. This interpretation is less likely as it does not follow the “unnecessary input heuristic”, but it’s nonetheless possible as some wallets are poorly optimized and will insert unnecessary inputs to a transaction for no reason. The payment amount in this interpretation is 0.011722121 BTC.
However, if we interpret this transaction as a PayJoin, 2 additional equally as likely interpretations of the payment are possible:
3) The sender owns the first input while the receiver owns the second input. In this case, the first output must be owned by the sender (as if he owned the second output he would have actually gained BTC, which is not possible since he is the one making the payment) and the receiver owns the second output. Assuming that the transaction fee was paid entirely by the sender, the payment amount is 0.01104023 BTC (difference between the receiver output and input). If the transaction fee is partly or fully paid by the receiver the payment amount can be as low as 0.01088048 BTC.
4) The sender owns the second input while the receiver owns the first input. In this case, once again the second output must be owned by the receiver (since once again if the sender owned it he would be gaining money), which means that the first output is owned by the sender. The payment can be as high as 0.00207881 BTC and as low as 0.00191906 depending on how much of the fee was paid by the receiver.
So, we can clearly see that the possibility of this kind of transaction being a PayJoin immediately adds at least 2 extra interpretations to the transaction and obfuscates the payment amount.
Currently, Payjoins have been implemented by only a few wallets and payment service providers, most notably BTCPay. PayJoin adoption can be tracked here:
Now that we know how PayJoin looks on a basic level, let’s discuss potential privacy attacks on PayJoin. I couldn’t find any on-chain PayJoin deanonymization techniques online, so I had to do something I don’t usually do … think for myself. Doing that is quite dangerous as you can sadly make mistakes, so I apologize if my further pondering turns out to contain any.
After some contemplation, I’ve come to the belief that if we define some basic rules of a PayJoin transaction we can come to conclusions that mitigate the privacy provided by PayJoin transactions.
The very basic rules of PayJoin transaction are the following:
- Rule 1 — In the PayJoin transaction at least one of the inputs is owned by the Receiver.
- Rule 2 — One of the outputs is owned by the Sender (Senders change) and the other is owned by the Receiver (Receiver’s change + payment).
- Rule 3 — The sender is necessarily paying the receiver.
- Rule 4 — PayJoin transaction will only have 2 outputs
Based on these rules a few definitive conclusions can be drawn about any transaction we suspect to be a PayJoin:
- Definite assumption 1 — If a transaction has more or less than 2 outputs it is not a PayJoin, if it has exactly 2 outputs it can be a PayJoin.
- Definite assumption 2 — The Senders output (change) cannot be bigger than the sum of the Senders inputs. This is because of Rule 3, the sender is making a payment, they cannot be gaining BTC.
- Definite assumption 3 — Payment amount can be calculated by either of these formulas:
Payment amount = Receiver output amount — sum of Receiver input amounts + Receiver Fee amount
Payment amount = sum of Sender input amounts — (Sender output amount + Sender Fee amount)
The assumption is based on all 3 rules
- Definite assumption 4 — In a PayJoin with more than 2 inputs, if any of the inputs is smaller than the smallest output, you can assume that if it belongs to the Sender it is not the only one or it belongs to the Receiver. Again Rule 3 tells us that the Sender is making a payment so they cannot be gaining money, if they owned an input smaller than either of the outputs and only that input, they would be gaining BTC no matter which output they owned
- Definite assumption 5 — If a 2 input PayJoin has an input that is smaller than both of the outputs you can automatically know that this input belongs to the Receiver.
- Definite assumption 6 — Since the sum of the Senders inputs must be bigger than the Sender output (assumption 2) if the combination of all input amounts minus the smallest input is smaller than the bigger output you can immediately assume that this output belongs to the Receiver (and conversely the smaller output belongs to the sender) in all PayJoin interpretations.
This I believe is the most damaging assumption. It’s the reason why in both the PayJoin transaction interpretations I wrote about earlier the output ownership is always the same:
This assumption can also scale remarkably well, as an example let’s take this PayJoin transaction:
Since this transaction has 5 inputs it can have as many as 20 PayJoin interpretations but in all of them the first output will belong to the Sender (change) and the second one will belong to the Receiver (change + payment).
- Definite assumption 7 — If a combination of inputs adds up to a larger amount than the largest output this means that this combination will result in 2 interpretations of the transaction (since either of the outputs could be owned by Sender/Receiver).
- Definite assumption 8 — The number of viable interpretations a PayJoin transaction will have can be easily calculated according to these formulas:
1. If no combination of the inputs (excluding smallest input) add up to more than the biggest output = x * x - x-y
2. If one or more combinations of inputs (excluding smallest input) add up to more than the biggest output = x * x -y + C
X = Number of inputs.
Y = Number of inputs smaller than the smallest output.
C = Number of combinations that add up to more than the largest output.
These are the 8 definite assumptions we can draw from just a few simple rules about the PayJoin transactions. With this information, we can already be much more successful when analyzing potential PayJoin transactions. Someone with adequate programming skills could create a program that quickly analyzes PayJoins aiding them in blockchain forensics investigations. Something akin to the KYCP.org site to tell how many interpretations a potential PayJoin will have, who likely or definitely owns each output and if any of the inputs definitely belong to the Sender/Receiver.
It’s possible to push these ideas further by allowing less safe rules about the PayJoins and building new assumptions from these extra rules. A few examples of these kinds of heuristics would be:
- The Receiver is unlikely to commit more than one input.
- The Receiver is unlikely to be a major contributor to the transaction fee, who if contributes to the fee will likely contribute only as much as is needed to cover the size of their input.
No doubt, with these kinds of additional heuristics PayJoin analysts could further refine their analysis although it would be a bit riskier.
PayJoins are sometimes hyped up as the solution to Bitcoins privacy issues, the Bitcoins wiki’s PayJoin page proudly claims:
If PayJoin transactions became even moderately used then it would make the common-input-ownership heuristic be completely flawed in practice.
The idea is that if only 10% or 20% of transactions on the blockchain become PayJoins that would make the most important heuristic for blockchain forensics completely unreliable.
Personally, I am skeptical of this, I believe a more likely scenario is that blockchain forensics companies will create simple tools based on the rules described above (or similar ones) to analyze potential PayJoin transactions and provide them with all possible interpretations of the transaction.
The Bitcoin wiki also claims that PayJoin transactions are “undetectable and indistinguishable from any regular bitcoin transaction”, while this is technically true I feel that this statement should come with a few asterisks, due to the following reasons:
Firstly, PayJoin transactions only look identical to the BTC transactions that have the same structure as PayJoins, that is, they have multiple inputs and 2 outputs, if a transaction does not follow this pattern, it can be pretty safely assumed to not be a PayJoin.
Furthermore, I believe that there can be some quite large indications that a transaction is not a PayJoin even if the structure is similar to a PayJoin if the transaction does something very uncharacteristic to a PayJoin. For example, if the transaction has address reuse between inputs and outputs. You could probably determine more of such indications if you closely examined PayJoins BIP78 specification and available implementations of PayJoin.
Also, BIP78 specification predicts a possible heuristic for detecting PayJoins based on fee calculation:
Most wallets are creating a round fee rate (like 2 sat/b). If the payjoin transaction’s fee was not increased by the added size, then those payjoin transactions could easily be identifiable on the blockchain. Not only would those transactions stand out by not having a round fee (like 1.87 sat/b), but any suspicion of payjoin could be confirmed by checking if removing one input would create a round fee rate.
As a solution specification suggests for the Receiver to increase the transaction fee till it reaches a round rate after adding the input. But if this recommendation is not followed that could lead to detectable PayJoin.
With this information, blockchain analysts may have more success lowering the pool of transactions that may be PayJoins.
It might seem that I am really overly critical of PayJoin here, and perhaps I am, after all undoubtedly a great privacy tool that is of massive importance and many of these attacks on PayJoin are based on assumptions that PayJoins are and will be uniform and will follow some common heuristics, this does not have to be the case (for example, as far as I know, nothing prevents PayJoin from having more or less (in the case, of the Sender sending the exact amount to the Receiver) than 2 outputs, it’s just that as far as I am aware available implementations of PayJoin do not this.
In any case, I am excited to see the future of PayJoins and I hope you enjoyed and gained some insight from this article. If there is anything you disagree with here or you detect any mistakes in my logic, please leave a comment! I would love to continue the discussion.
Join Coinmonks Telegram Channel and learn about crypto trading and investing
- Stackedinvest Review | Kraken Review | Futures Trading Bots
- Best Crypto Lending Platforms | Leveraged Token
- Best Crypto Charting Tool | Best Crypto Exchange
- How to buy Bitcoin in India? | WazirX Review | HitBTC Review
- WazirX vs CoinDCX vs Bitbns | BlockFi vs CoinLoan vs Nexo
- LocalBitcoins Review | Cryptocurrency Savings Accounts
- Coinbase Review| Deribit Review |FTX Review
- NGRAVE ZERO review | Phemex Review | PrimeXBT Review
- Best Blockchain Analysis Tools | Earn Bitcoin
- Crypto arbitrage Guide | How to Short Bitcoin | Prokey Review
- Binance Trading Bots | OKEx Review | Atani Review
- Best Crypto Trading Signals Telegram | MoonXBT Review
- Godex.io Review | Invity Review | BitForex Review