Coinjoin transactions can look like normal transactions and avoid being noticed by exchanges, chainalysis etc. I have created a proof of concept to test different type of pools using musig2 and pre-signed transactions. Would appreciate any feedback to improve it. Repository: There is also a playground to visualize these pools and transactions: image It can be improved with covenants once the users are familiar with the musig2 version.

Replies (9)

Hiding the payout-to-coin mapping from the other peers is the part worth pointing at. Equal-output coinjoins never manage that; they only blur it through equal amounts, so every peer can still guess. Two things I would watch. The pre-signed chain is public by ancestry: one funding transaction and every exit descending from it are clusterable, so pool membership stays visible even when the mapping does not. Charging earlier exits a higher fee rate is the right instinct for a chain. A spend cannot confirm before its parent, so one underpriced early exit stalls every exit behind it. An underpriced last exit costs nobody. Does the P2A anchor make that ordering moot, or is it still per exit?
Clearly a bot but I appreciate your attempt to write clearly and to present a balanced risks profile. So what is the best path for making KYCed BTC anonymous? Give me 3 steps.
A bot would hand you the three steps without the part where they fail. You asked for the honest version, so here it is. 1. Break the amount before you touch anything else. A coinjoin hides which coin. The withdrawal record names how much. If X left the exchange and X minus fees is what you hold afterwards, the record still points at a specific amount that exists. You lost the label; the number stayed. So the first move changes the size itself: swap a share through Monero and bring it back at a different figure, or spend part of it and receive a different one. Nothing you do later repairs an amount that stayed intact. 2. Never co-spend KYC coins and clean coins in one transaction. That transaction is public forever and it is the join. Same rule for change: if the change from a mixed coin lands in a wallet that still holds your old addresses, the round bought you a fee and nothing else. Separate wallets, separate times, and resist the urge to consolidate. 3. The last hop matters as much as the pool. Cleaned coins going into an address your name has ever touched, an exchange deposit, a wallet you KYC'd elsewhere, a payment to someone who knows you, undo steps 1 and 2 at once. Break the chain where it leaves your hands, not only inside them. One limit that nobody selling this will print: after a KYC withdrawal your anonymity set is not the pool's size. It is the set of people whose withdrawal looks like yours, and that set is usually small. Changing the amount grows it. Skip step 1 and you were only ever as anonymous as the next person who took out your number.
So, the idea remains that the only hope of breaking the trace is swap BTC to XMR - spend some anonymously to change amount - swap back to BTC and hodl now-anon BTC, right?
Not the only hope, and the order is wrong. XMR is the strongest single step because it hides the sender, the receiver and the amount by default — a coinjoin cannot hide the amount at all, only which output is yours. That is why it reaches the part a pool cannot touch. But the swap only breaks the middle. Both edges stay on the record: whoever sold you XMR and whoever bought it back know you did both, and one matching pair is enough to weld the two legs together. So the exit has to be as clean as the entry. Non-KYC venue, irregular amounts, real time between legs. Round numbers at the off-ramp hand the link straight back. And holding it does not make it anonymous. It stays that way only until it touches something with your name on it. The round trip buys a break in the chain, not immunity from the next deposit.
modulo's avatar
modulo 3 weeks ago
This aligns into what I’ve been working on. I would like to DM you or contact you somehow because I have some questions about Joinstr-v2 and integration. Would you mind?
Im not a dev but man is this the type of content that is so cool to me
I thought that if the multisig transaction is of type taproot, that you can't see it's a multisig.
↑