CoinJoin Probing Attack
A practical analysis of how a malicious actor builds a live UTXO database of JoinMarket makers by probing, the conditions under which this enables maker identification in honest CoinJoins, and the countermeasures that limit the leakage.
1. The Problem: Privacy in CoinJoin
CoinJoin is a collaborative Bitcoin transaction where multiple participants combine their inputs and outputs into a single transaction. When done correctly, an outside observer cannot determine which input funded which output, providing transaction privacy.
In JoinMarket-style CoinJoins, there are two roles:
Makers are always-online bots that advertise offers on a public orderbook. Each maker has a wallet divided into multiple mixdepths (separate accounts, typically 5). They hold funds across these mixdepths and earn fees for participating in CoinJoins. Makers are selected weighted by their fidelity bond, a time-locked Bitcoin deposit that proves commitment and makes Sybil attacks expensive.
Takers initiate CoinJoin transactions. They select makers from the orderbook, agree on a CoinJoin amount, and coordinate the transaction. The taker's goal is privacy: after the CoinJoin, their output should be indistinguishable from the makers' outputs.
The anonymity set of a CoinJoin with N makers is N + 1: an observer cannot tell which of the N+1 equal-amount outputs belongs to the taker. A CoinJoin with 8 makers gives an anonymity set of 9.
That worst-case anonymity holds against a passive on-chain observer. This study isolates a different threat: an active attacker who participates in the protocol itself to build a live database of maker UTXOs. By repeatedly probing makers off-chain, the attacker learns which inputs each maker will contribute, enabling them to identify makers in subsequent honest CoinJoins (matching known UTXOs to transaction inputs). Identifying all N makers in a CoinJoin is a necessary condition for the taker's equal-output to become isolable by exclusion — but it is not sufficient on its own: that final step also requires knowing which equal-output belongs to each identified maker, which demands additional on-chain clustering (covered in the companion JoinMarket equal-output anonymity in practice study). For the on-chain side — equal-output reuse, change heuristics, and clustering across many transactions — see that companion study.
2. How Probing Works
A probing attack exploits the CoinJoin negotiation protocol. Before a CoinJoin transaction is signed and broadcast, makers must reveal their input UTXOs to the taker. Normally this is fine because the taker is honest and completes the transaction. But a malicious taker can abuse this:
- Probe: The attacker initiates a CoinJoin with a maker, requesting the maker's maximum offer amount. The maker reveals all UTXOs in their largest mixdepth. The attacker records them and aborts the transaction.
- Accumulate: The attacker repeats this with many or all makers, building a database of known UTXOs per maker.
- Identify: When an honest taker later creates a CoinJoin, the attacker observes the on-chain transaction. If any input matches a known UTXO from the attacker's database, the corresponding maker is identified.
- Cascade: When a maker is identified, the attacker also learns their co-spent inputs (other UTXOs the maker contributed) and their change output (distinguishable by value from the equal-amount outputs). These new UTXOs are added to the database, enabling identification in future CoinJoins. The attacker's knowledge snowballs.
- Deanonymize: Probing alone reveals maker inputs and change outputs, but does not directly identify which equal-amount output belongs to each maker — all equal outputs are the same size. To isolate the taker's equal-output, the attacker must additionally map each identified maker to their equal-output, for example by tracking the maker's wallet across multiple CoinJoins or by applying on-chain clustering (see the companion mainnet-deanon study). Once all N maker equal-outputs are accounted for, the remaining one is the taker's: the anonymity set collapses from N + 1 to 1.
Scope of this study. The simulator models only the probe-to-cascade leak: how rapidly the attacker's known-UTXO database grows as a function of probe rate, attacker share, and countermeasures. It does not model on-chain heuristics (change attribution, equal-output reuse, address reuse, timing). Those compound the leak in practice; the mainnet-deanon study quantifies them on a real corpus. Read the two studies as complementary lower bounds on a real attacker's capability.
The anonymity-set metric used here (N + 1 − identified makers) is a worst-case estimate. It assumes that for every identified maker the attacker can also determine which equal-amount output is theirs — an additional step that in practice requires on-chain wallet clustering on top of the probe database. The metric reported in this study (referred to as "all-maker input coverage") is therefore strictly the fraction of CoinJoins in which the attacker successfully matches every maker's known UTXOs to their inputs. Full taker deanonymization additionally requires the on-chain clustering step described in the companion mainnet-deanon study.
Existing protections and their limits
JoinMarket already has a protection against probing: PoDLE (Proof of Discrete Logarithm Equivalence). To initiate a CoinJoin, the taker must commit a real UTXO worth at least 20% of the requested amount. Each UTXO can only be used for up to 3 PoDLE commitments (to allow for honest failures). Makers broadcast used commitments to each other as a blacklist.
The problem: PoDLE works against casual abuse, but a well-resourced attacker can probe all makers simultaneously, before the blacklist propagates. Each maker is probed for their maximum offer amount, revealing as many UTXOs as possible. The attacker spends their PoDLE commitment UTXOs, but in return they get a complete snapshot of every maker's largest mixdepth. This is the attack scenario we simulate.
3. Baseline: How Bad Is It?
With no additional countermeasures beyond PoDLE, the CoinJoin protocol is highly vulnerable to probing. We simulate a network of 100 makers with realistic wallet structures sampled from the live JoinMarket orderbook.
Even at moderate attacker shares, in a meaningful fraction of honest CoinJoins the attacker can identify every maker from their inputs within 1,000 rounds. At 20% attacker share (1 in 5 rounds is a probe), roughly 32% of CoinJoins have all makers identifiable; at 40% it is about 48%, and at 80% it climbs to 83%. (This is the necessary precondition for taker deanonymization; the sufficient condition also requires on-chain clustering.)
The picture worsens with sustained probing. Because each identification reveals more UTXOs (the cascade effect), the attacker's database grows with every honest CoinJoin it observes. Over 5,000 rounds of mixed probe + honest traffic, the unmitigated baseline reaches roughly 40% all-maker input coverage at 10% attacker share, 57% at 20%, and 64% at 40%. This is the long-term steady-state risk an unmitigated network converges to. Variance across seeds is shown as a 95% CI band on the sustained-attack chart in section 5.
4. Countermeasures
We evaluate two classes of countermeasure. The first targets the structural information leak (what each probe reveals); the second raises the attacker's economic cost. Neither eliminates the UTXO leakage on its own; together they shrink the attack window enough that sustained probing stops being economically rational.
4.1 Timed sticky offer slot (offer_slot_size)
What it does: Each maker pre-selects a random
subset of N UTXOs from its active mixdepth — the
offer slot — and advertises only those. The advertised
maxsize equals the slot's total. The slot is sticky:
it stays fixed for a randomized lifetime drawn uniformly from
[slot_ttl_min_rounds, slot_ttl_max_rounds]
(default 4-20 rounds, roughly 1-5 hours at typical traffic).
Probes do not rotate the slot; only TTL expiry or a
successful CoinJoin (which spends a slot UTXO) rebuilds it.
Why it helps: Re-probing the same maker within its TTL reveals nothing new — the attacker pays the initiation fee again and learns the same N UTXOs. Across many makers the union of disclosed UTXOs grows much more slowly. With N=3, each maker exposes at most 3 UTXOs per TTL window regardless of how often it is probed, so the attacker's ability to pre-build a complete known-UTXO database is sharply throttled. Random TTLs prevent the attacker from synchronizing probes with rotation events.
4.2 Initiation fee (initiation_fee_sats)
What it does: Each maker charges a small fee (in sats) just to start the CoinJoin negotiation, paid regardless of whether the transaction completes. Both honest and malicious takers pay it.
Why it helps: It makes probing expensive. At 500 sats per maker with 100 makers, each full probe round costs 50,000 sats; at 10 rounds per day the attacker spends roughly 0.005 BTC/day. It is purely economic: on its own it does not reduce information leakage, but it forces the attacker into a cost-vs-coverage trade-off and, combined with the sticky slot, makes the per-bit-of-information cost rise sharply.
Individual effectiveness
The chart below shows each countermeasure's standalone impact against the probing attack, tested at 8 makers per CoinJoin over 1,000 rounds:
| Countermeasure | Effect on all-maker input coverage (40% evil share) | Mechanism |
|---|---|---|
| Sticky offer slot, size=1 | large reduction | Each maker exposes 1 UTXO per TTL window |
| Sticky offer slot, size=3 | large reduction | Each maker exposes up to 3 UTXOs per TTL window |
| Initiation fee (500 sats) | modest reduction (cost lever only) | Raises probing cost but does not reduce per-probe leakage |
| Initiation fee (1000 sats) | modest reduction (cost lever only) | Raises probing cost but does not reduce per-probe leakage |
| Combined (slot=3 + 500 sat fee) | large reduction | Defense in depth: structural cap + economic friction |
The structural lever — the timed sticky offer slot — is what drives the all-maker input coverage metric down. Initiation fees alone barely move the needle, but they raise the per-bit-of-information cost when layered on top of a sticky slot. Long-running attacks (Section 5) show that combining the structural and economic defenses matters, because at very high probe intensity each one alone degrades over time.
5. Recommended Policy
Rather than relying on any single countermeasure, we combine them into a defense-in-depth policy. The recommended configuration is:
| Parameter | Value | Purpose |
|---|---|---|
offer_slot_size |
3 |
Cap UTXOs per offer slot |
slot_ttl_min_rounds |
4 |
Minimum slot lifetime (sticky) |
slot_ttl_max_rounds |
20 |
Maximum slot lifetime (random rotation) |
initiation_fee_sats |
500 |
Economic deterrent |
n_makers_per_coinjoin |
8 |
Larger anonymity set |
n_mixdepths |
5 |
Wallet compartmentalization |
Sustained attack resistance
We test the recommended policy under harsh conditions: 5,000 rounds with a pre-probed attacker that snapshots every maker's offer slot before the first honest CoinJoin. At low to moderate attacker shares the recommended policy roughly halves the all-maker input coverage rate versus the unmitigated baseline; at high shares the absolute reduction stays meaningful but shrinks in relative terms.
At 10% attacker share, baseline ~40% vs recommended ~19% all-maker input coverage; at 20% share, ~57% vs ~22%; at 40% share, baseline 64.0% vs recommended 31.1%; at 60% share, ~85% vs ~60%. Beyond about 100 probes/day or attacker shares above ~60%, the gap narrows further (see Section 6) — defence-in-depth slows UTXO leakage rather than abolishing it.
6. Attack Economics
Mitigations don't make the attack impossible — they make it more expensive per unit of information extracted. The chart below tracks final-day all-maker input coverage and attacker cost across probe intensities for a 14-day attack window:
The picture is sobering. Against the baseline, a single probe round per day already drives final-day all-maker input coverage to roughly 84.7%, and 50 probes/day reaches ~96%. Against the recommended policy, the same intensities yield ~53% and ~87% respectively — a real reduction, but far from a fix. The attacker pays linearly with intensity (about 500 sats per probe round at the recommended fee, so 50 probes/day costs ~0.025 BTC/day), and the marginal information per probe drops once the slot has been seen, but a patient attacker still maps most of the network's UTXOs over a fortnight.
Initiation fees alone are not enough. Even at 1,000 sats per maker, an attacker still achieves all-maker input coverage for well over half of CoinJoins at moderate evil shares in our 1,000-round runs. Fees raise the per-probe cost but do not change what the attacker learns. The real defence comes from the timed sticky slot, which caps information-per-probe and forces the attacker to pay again to learn anything new.
7. Recovery After an Attack
What happens when the attacker stops? As honest CoinJoins continue, makers generate new UTXOs the attacker does not know about. The attacker's database becomes stale and identification rates drop.
After a 14-day attack at 20 probes/day, the baseline takes until approximately day 21 to recover below 5% all-maker input coverage, and the recommended policy recovers only marginally faster (around 19 days versus 21 in our runs). The recommended policy's main benefit is starting recovery from a lower peak, not accelerating the recovery itself: rotation of the offer slot is what eventually flushes the attacker's database, and that proceeds at the same rate either way.
8. Key Takeaways
- CoinJoin probing is a real privacy threat. Without countermeasures, a moderately resourced attacker can identify all makers in a substantial fraction of honest CoinJoins through the information cascade triggered by probing. This is a necessary precondition for full taker deanonymization (which additionally requires on-chain clustering — see the companion mainnet-deanon study). In our 5,000-round sustained-attack runs, the baseline all-maker input coverage climbs to roughly 40% at 10% attacker share and 64% at 40% attacker share, with an 85%+ tail at 60% attacker share.
-
The timed sticky offer slot is the structural lever:
capping the offer to N UTXOs and holding it fixed for a
random TTL (
offer_slot_size+slot_ttl_*) directly limits how much an attacker can learn per maker per time window. Re-probing within the TTL yields no new information, breaking the "probe everything every day" strategy without requiring per-attempt economic friction. - Initiation fees are necessary but not sufficient. They raise the attacker's cost but do not stop the information leakage. Fees only make sense as a complement to information-limiting measures.
- The recommended policy combines two layers. The timed sticky slot caps information leakage per probe (structural defence); the initiation fee raises the attacker's per-probe cost (economic friction). Under sustained, pre-probed, multi-thousand-round attacks this combination roughly halves the all-maker input coverage rate compared to the baseline. That is a meaningful improvement, but a determined long-running attacker can still map a notable fraction of the network's UTXOs — defence in depth is necessary, not optional.
- Recovery is slow either way. After a 2-week attack ends, both baseline and recommended policies need roughly 19-21 days to recover below 5% all-maker input coverage in our runs. The recommended policy's win is starting recovery from a lower peak, not converging faster: recovery rate is set by how quickly makers naturally rotate their slot UTXOs, which is independent of the policy in place.