Wasabi produced a coinjoin with only 5 participants . This opens the door for a unique opportunity: it is possible to take a look at KYCP’s analysis on this transaction and compare it with the real mapping of the transaction, which is obvious just by looking at it in any block explorer.
Larger Wasabi transactions are problematic, not only because figuring out what’s going on manually is difficult, but also because analyzing them without sophisticated assumptions and heuristics is impossible, due to the exponentially growing complexity in solving subset sum problems.
At the first glance, KYCP’s analysis is just strange. Let’s uncover the real mapping by looking at the transaction in another block explorer instead:
The Real CoinJoin Mapping
inputs 0–3 have values of
input 4 has a value of
Regarding the outputs, every participant gets back
~0.0969, and there’s a coordinator fee
~0.001 and a change
~0.291. It cannot be easier to uncover the real mapping of this transaction:
But that’s not what is shown in KYCP. Why is that?
Analyzing KYCP: Coordinator Address
Let’s see what’s the deal with the coordinator address. We know that nobody got back their money to the coordinator address, thus it has no links with any input. KYCP correctly identifies the Wasabi coordinator address being
But it links inputs to the coordinator address, which is not right. Upon further examination of the links new mysteries emerge.
51% linkability from
input 1 (
~ 0.097) to the coordinator address. Another
51% linkability identified from
input 2. And they also identify a
94% linkability from
input 3 to the coordinator address.
Analyzing KYCP: Input Merging
input 0 and
input 3 as an input merge. We know that every input is a unique participant based on the equal number of outputs, so this isn’t the case. There’s a theory though where the analysis went wrong.
input 0 is the smallest input:
0.09691275 BTC, and the mixed outputs have a value of
0.0969102 BTC. The difference is
0.00000255 BTC . Thus
input 0 did not pay coordinator fees, but only paid network fee. KYCP may account for coordinator fee all the time, but not everyone pays coordinator fees in Wasabi. As a side note there are cases when the smallest input gets back more money than it puts into the mix, so even if the analyzer lets the coordinator and network fees go, it should also account for some further error.
Analyzing KYCP: Change
We also know for a fact that
output 6 (
0.291) came from
input 4 (
0.388), as this guy was the only participant with a large amount.
KYCP does a better job analyzing the unmixed change, but surprisingly it still isn’t precise. The linkability is not
94%, it is
100%. And what’s the deal with the remaining
Analyzing KYCP: Output Merge
output 1 and
output 6, which is of course wrong. However it is possible to tell where the analysis went wrong this time.
The output linking by KYCP happened because both of those outputs are registered to the same coinjoin. Because of this, we know exactly they are not only aren’t linked, but they cannot be from the same user, as Wasabi wouldn’t register more than one input into a coinjoin when both inputs are larger than the minimum registration amount. So where did KYCP make the mistake?
It naively applied the most well-known Blockchain analysis heuristic: The Common Input Ownership Heuristic:
Every input of a transaction belongs to the same entity.
And what is the most well-known exception to this heuristic? CoinJoin.
KYCP’s analysis on Wasabi coinjoins is unreliable, as it does not even resemble the real mapping of the transaction in the simplest possible case:
It’s been pointed out that KYCP is aware that they are applying common input and output ownership heuristics to coinjoins incorrectly, as they include the incorrect heuristic into their own definition:
Input/output merges show inputs coming from the same tx, and outputs spent with the same tx, thus belonging to the same wallet or collaborating together (no merge = good privacy).
Is it open source?
Since KYCP rolled out two new updates based on this article: 1.2.6, 1.2.7, it warrants making sure the above provided definition wasn’t modified, but curiously archive.org caches show blank pages and the GitHub repository only consists of autogenerated code like this: