Some notes about payjoins
- Simple Example
- Simple Chain Analysis Example
- Breaking Simple Chain Analysis Example
- Fake PayJoin Implementations
A meeting took place in 2018 which a number of individuals developed P2EP. Some summaries / overviews are:
- P2EP Meeting Overview by Adam Fiscor (Nopara73)
- Block Digest_118 from 40:30 by Adam Gibson (Waxwing)
- P2EP overview by Matthew Haywood
Waxwing later proposed the variant of P2EP called PayJoin
There are currently 3 live implementations;
- A feature in Samourai Wallet called Stowaway
- A feature in Joinmarket (PayJoin)
- A feature in BTCPayServer called P2EP (Specification, Guide)
There are plans for implementation in the following wallets;
Assume a store accepts payments via payjoin which are limited to 2 inputs, 2 outputs.
User 1 buys a product worth 0.05 BTC with payjoin, providing an input of 0.1 & receiving change of 0.05
INPUTS(User1, Merchant) -> OUTPUTS(User1, Merchant)
INPUTS(0.1, 0.2) -> OUTPUTS(0.05, 0.25)
This is a stenographic transaction, it is indistinguishable onchain as a PayJoin because there is an output which is greater than the largest input && there is no subset of the inputs that would be sufficient to make this output, i.e. There are no redundant inputs.
The fact that some payjoin transactions are stenographic should not be misunderstood to mean that all payjoins are non-trivial to figure out, particularly if the snowballing of the receiver utxo’s is done in a non stenographic way.
If the sending wallet is restricted to only stenographic transactions then it is likely that the sender will either;
- Need many utxo’s to pick from
- Be unable to participate in many potential PayJoin transactions
- Need to pre process utxo’s to make it possible to participate regularly.
As such, payjoin is not strictly superior to a CoinJoin. An equal output CoinJoin is not stenographic like PayJoin can be, but it is a useful tool for breaking deterministic links & has other benefits which PayJoin doesn’t offer. They are both types of multiparty bitcoin transactions. Other types include CoinSwap & CoinMerge.
Simple Chain Analysis Example
Now suppose User 1 in the above example was a chain analysis company.
The chain analysis company logs that the output worth 0.025 belongs to the merchant.
User 2 (a normal user) buys a product worth 0.2 with payjoin, providing an input of 0.5 & receiving change of 0.3. Merchant uses the output from the previous payjoin as an input in this one.
From the perspective of the chain analysis company:
INPUTS(Merchant, ?) -> OUTPUTS(?, ?)
INPUTS(0.25, 0.5) -> OUTPUTS(0.45, 0.3)
The chain analysis company detect that there is a redundant input here (the 0.025 input is not required to pay a 0.045 output). As such, they may flag as a possible payjoin.
They can compute the possible scenarios:
- Scenario1, Merchant paid 0.2 BTC: 0.25->0.45 (+0.2) , 0.5->0.3 (-0.2)
- Scenario2: Merchant pays 0.05 BTC: 0.25->0.3 (+0.05), 0.5->0.45 (-0.05)
They know that it’s possible (maybe even likely) that the merchant is getting paid by another user via payjoin, thus they conclude that Scenario1 is highly likely.
They can then track the resulting output (0.45) which they believe to be the merchant and repeat.
Additionally they now suspect that the user spent 0.2 BTC at the store, which could later be useful information.
Breaking Simple Chain Analysis Example
- Don’t limit to 2in2out
- Merchant spends at other merchants who use payjoin (Scenario2)
- Merchant constructs transactions with redundant inputs to create false flag PayJoins
- Merchant uses PayJoin to make payment (the output they provide is a payment to some other user)
- Wallets construct transactions with redundant inputs to create false flag PayJoins
Fake PayJoin Implementations
There are currently no wallets which have an explicit fake payjoin feature (where a redundant input is used).