pull down to refresh

JoinMarket Analyzer: Understanding CoinJoin Change Outputs

I've released a tool called joinmarket-analyzer to match inputs and change outputs in JoinMarket transactions, identifying who the taker was.
Goal: The purpose is not to spread FUD, but to raise awareness. It's crucial to understand that this analysis only affects change outputs. The equal-amount outputs—which provide the actual privacy in a CoinJoin—remain indistinguishable.
The tool uses Integer Linear Programming (ILP) to match inputs with their respective changes and determine which participant is the likely "Taker" (the one initiating the transaction and paying fees) and which are the "Makers" (liquidity providers earning fees).

Example Usage

You can run it easily with Docker:
docker run --rm ghcr.io/m0wer/joinmarket_analyzer:master \
  0cb4870cf2dfa3877851088c673d163ae3c20ebcd6505c0be964d8fbcc856bbf \
  --max-fee-rel 0.001 --max-solutions 1

Results

The tool outputs the probable structure of the transaction:
...
Taker: Participant 4 (pays 21,368 sats)
  💰 Participant 1 (maker)
    Inputs: [0]
    Outputs: Equal=6.3M sats, Change=113M sats
    Fee receives: 458 sats
  ...
  🎯 Participant 4 (taker)
    Inputs: [4]
    Outputs: Equal=6.3M sats, No change output
    Fee pays: 21,368 sats
...

Future Possibilities

This tool lays the groundwork for more advanced privacy research:
  • Entropy Evaluation: Measure how "ambiguous" change outputs are. If multiple valid solutions exist, the Taker is harder to pinpoint.
  • Algorithm Design: Evaluate and improve taker algorithms to intentionally create ambiguous change structures.
  • Market Stats: Analyze historical CoinJoins to gather statistics on fee limits used by takers and earnings by makers.
Check out the code and contribute: https://github.com/m0wer/joinmarket-analyzer
77 sats \ 10 replies \ @OT 30 Nov
Why does it matter that the taker is known? The next round is not necessarily the same taker.
reply
42 sats \ 1 reply \ @anon 1 Dec
Because if you pay someone using a JM tx (which is the goal when acting as a taker) the receiver can easily know your change output, which is not good.
JM provides good forward privacy but in some case really bad backward privacy IMO And if a taker gains no backward privacy, why would he even use the tool to spend in the first place ? Which lead to incentive problem because if there is no taker there is no Coinjoin anymore.
reply
Very good answer.
reply
Maybe it doesn't. But here are some cases where it does:
  • Taker immediately spends the equal amount output -> useless coinjoin.
  • Taker is doing a payjoin to a taproot address (bc1p...) and all other equal amounts are segwit (bc1q...) due to the limitations in the joinmarket clientserver implementation -> also useless coinjoin.
  • Taker spends change out (not the equal amount) thinking that it can't be linked to the input. It probably can be.
And I'm sure there might be other reasons depending on the case. The project is just a tool to do the matching.
reply
27 sats \ 6 replies \ @OT 30 Nov
I'm pretty sure in the docs they say that 1 round is not sufficiently conjoined.
Anyway, you're probably right that some people won't understand and are going to mess it up.
reply
Yes, and it also says that the protocol is designed for privacy of the equal outputs, not the change. And that change should not be spent together with equal outputs.
I actually just wanted a way to analyze transactions to gather stats on the fee limits used and optimize maker offers.
The other idea is to find ways to make change outputs ambiguous on purpose so that they gain some privacy as well and economize the coinjoin a bit more.
reply
change should not be spent together with equal outputs.
And normally it will not be, as equal output and change will end up in different mixdepths.
reply
0 sats \ 3 replies \ @OT 30 Nov
In Jam the change is always separated from the CJ output.
I actually just wanted a way to analyze transactions to gather stats on the fee limits used and optimize maker offers.
Negative offers might be the way.
The other idea is to find ways to make change outputs ambiguous on purpose so that they gain some privacy as well and economize the coinjoin a bit more.
I saw Floppy comment the other day on Joinstr about the change being submarine swapped into the LN channel.
reply
Optimize maker offers in terms of maximizing profits, not in number of rounds.
Change can also be mixed in coinjoins. There's actually a setting for consolidating change as a maker by providing multiple inputs. The alternative is of course the submarine swaps yes, but usually pretty expensive.
reply
0 sats \ 1 reply \ @OT 1 Dec
A submarine swap would be cheaper than paying for a number of CJ participants. The TX fee is already for too.
reply
Depends on the size, but most times yes.
But I meant as a maker, where a taker pays the extra transaction fees from the additional inputs. So you get the consolidation for free (or even making some profits), you help the taker disguise their inputs, and you get a proper equal output.
Argh the link is wrong in the post content, should be https://github.com/m0wer/joinmarket_analyzer
reply