-
Notifications
You must be signed in to change notification settings - Fork 119
Bad faith taker spy not filling orders so that it learns which UTXOs belong to which maker, allowing future unmixing #156
Comments
Yes. Does Coinshuffle address it? I think not; if you're able to figure out that all-bar-1 of the join outputs are from makers, it doesn't matter what order they're in. Just dropping the note here now, but continuing to think about it. |
Forgive me in advance if this is a bit rambling, but I want to record what I understand about it right now. The fundamental issue is that makers announce their utxos to anyone who (pretends to) start a transaction with them; whether this can be avoided without creating hideous DOS issues I don't know. Coinshuffle does not help, since its only purpose is to make the ownership of all the coinjoin outputs hidden from all participants (thus avoiding the current situation where there is a single coordinator, namely the taker, knowing all the linkages). This attack, to the extent that it works, sidesteps that. Chaumian blinding does not help either. You can think of it as a lower-tech version of Coinshuffle (because, to achieve the same result, it requires the additional step of breaking the network linkage between input and output, i.e. you have to anonymously reconnect during the protocol, which is .. icky). Possible Mitigations:
I don't think anonymity can help at all; the attacker doesn't care what your IRC nick is, only the linkages on the blockchain. |
I agree with you. I think the only way that will work and is practical is to code makers to raise the alarm if they detect this behavior. Each UTXO has a marker on it (boolean or integer type) which describes whether it's been broadcast to the network and then not consumed. If a large majority of a maker's UTXOs get marked in this way it should raise the alarm. I think there's enough altruism in the community that this could work despite not being financially incentivized. |
The algorithm used by yield generators has an important effect on this. The old original yield generator just announces one relorder, the spy taker will have to fill many orders to get all the UTXOs from each mixdepth. So maybe part of the solution is a polyculture of maker algorithms ? |
I might have a solution for this problem. The maker would send a new empty address to the taker. The taker would have to sign the coinjoin transaction with this address and send it to the maker. Now the maker verifies it and if it's acceptable he sends his coins to his new empty address. He then would have to broadcast the coinjoin transaction as fast as possible so that a bad taker couldn't move his coins. With this protocol the bad taker would have at least to bring own coins into the system. This is not a finished solution but it could be developed further or be used to give new ideas. |
@cqv2 If I understood your idea correctly, I have a feeling it doesn't work. When someone wants to sniff out the linkages, they will just have to traverse back one step. Say maker has utxo U1, taker proposes and he pledges to send U1 -> U2 (this will be a 1in 1out tx). In later analysis, the linkage U1-U2 can be seen directly on the blockchain and so U1 is always recoverable, even if U2 varies per taker. Problems with complexity, time, cost etc: agreed, but maybe the above point means it doesn't achieve much (again if I understood!). |
I understand the problem. I somehow initiated this discussion on reddit. |
The taker needs a utxo, not just an input address to construct a transaction. (Another comment that may or may not be important: which maker?) Also bear in mind one of the ideas of the handshake is to reduce complete faking on both side by requiring btc signatures with the addresses corresponding to the utxos that are proposed to be used for the transaction. If the maker doesn't have to provide the utxo, that breaks that property. As I said above "whether this can be avoided without creating hideous DOS issues I don't know." |
You are right, this doesn't work. I was missing the point that you need the utxo to sign a valid transaction. |
What if the takers signed transactions with Of course, this breaks the handshake as @AdamISZ commented. Perhaps a middle ground can be reached; makers can create and sign transactions the same way. Clients can then configure their scripts to either offer a TX to a maker, or wait for a maker to offer up a TX to them. Fee structures could reflect this with lower or higher fees respectively. |
As a taker, all you care about is that all the outputs match some pre-agreed amount, split over N txOuts, and that a particular amount goes to somewhere you control. My inputs are my inputs, so I'll sign them, and only them, and the outputs must be what I expect. In principle, maybe the handshake helps, but, it doesn't really aid in privacy at all. |
This description is a summary of some ideas discussed on IRC over the last week: https://gist.github.com/AdamISZ/9cbba5e9408d23813ca8P
(Assuming you're referring to the exchange in !fill - !pubkey - !auth - !ioauth (come to think of it, I should be clearer what I mean when I say 'handshake')): what's in place is designed to prevent MITM, so it's very relevant to privacy. And of course, the fact that it provides encryption. So basically I'm disagreeing and saying: it massively helps privacy by preventing non-participants from knowing what's going on. The hard part is how to gain privacy from, effectively, Sybil attacks, fake participants. |
Not seeing https://gist.github.com/AdamISZ/9cbba5e9408d23813ca8P (Page not found) |
An issue with the SIGHASH methods is they would make joinmarket transactions stand out more compared to regular bitcoin transactions. But otherwise that could probably solve the problem. |
@dcousens I vaguely remember earlier discussions of SIGHASH flags, but I somehow don't remember if this specific idea was discussed. It's a good idea, thanks, but just trying to get clear the mechanics:
In that sequence taker sees everything at the end because he's going to pushtx(). (Our recent spammer was mainly following this: do everything except pushtx). Have I missed something (probably!) or isn't it the case that if taker pushes, taker must know all the maker's inputs (distinctly, because he reserved locations for their inputs)? |
@AdamISZ The goal of ALL|ACP is that once a transaction is offered, it cannot be backed out of, short of spending the UTXO immediately As a taker:
As a maker:
I imagine that the party giving up their privacy first by sending their UTXOs should profit with lower/higher fees respectively. The downside is that allowing both parties to offer TXs is either party can now be a spy: A taker advertising high fees just to get maker UTXOs and a maker offering low fees just to see taker UTXOs. This could possibly be combated during a tumble by switching between offering and accepting TX. @chris-belcher mentioned these transactions will stand out by using exotic SIGHASH, and he is correct. Not sure if there is a way around that, but I don't know if there is any plausible deniability when doing coinjoin to begin with. Only a mixer can sever the link between coins. |
Some fundamentals here: the taker pays, and he pays for two things: (1) the fact that no other counterparty knows the mapping (2) he gets to initiate the transaction he wants immediately, and not wait. The second of the two scenarios you describe doesn't fit in Joinmarket because of that. The first doesn't work as cleanly as you describe, because there is more than 1 maker. As described, it just flips the problem around (as you say), where the maker gets to learn the taker's inputs before committing to actually doing the transaction. But the reality is even worse, because JM is basically always > 1 maker (with only 1 counterparty, you by definition can't hide your output from the counterparty; not useless, but nearly so). I suspect there are (much!) more complex variants involving passing the transaction around and obfuscating which inputs belong to who, but the pushtx() counterparty will always at least have the list of inputs and know which of them are not his. Even if such things worked I'd be reluctant; part of our model is that the taker is the one in control and knows the mapping, and the makers learn as little as possible. |
@chris-belcher to be fair, CoinJoin transactions already stand out.
This was exactly my thought.
This does expose the makers privacy. Somehow I feel like this is what happens currently? (Soon to re-iterate learning the protocol) |
That is true today; the maker gives the utxos first (except for the taker giving one pubkey, which is effectively giving a utxo). But I would argue that the order is not as important as it first appears, because if both sides have to give that information to the other, then there is the potential for both sides to fake and therefore snoop. Also please don't forget this is a 1-many relationship, that's part of the asymmetry. Takers learn the whole transaction mapping. Makers know only their own inputs/outputs and 1 taker input. Yes, your 1-4 is along the lines of what happens currently. Except for (3), which could be impacted by SIGHASH flags, but at the end each maker is going to send their own set of inputs to the taker (in this model), and so the taker will know everything and can simply not pushtx() to snoop. Re: adding costs/contracts, yes that's what's discussed here and in that gist. (For the protocol sequence, I know it's easy to forget, I recommend my poorly formatted encryption_protocol.txt file (the only part it doesn't have is the content of !tx and !sig messages but that's pretty obvious). I always find myself going back to that when i forget the sequence of messages and what fields are in them.) |
Is that not the case currently? |
@AdamISZ said
I would object espacially this last sentence as it's a flaw with no immediate benefit. It wasn't stated explicitly but what if the taker had to request unsigned partial transactions from a sequence of at least n makers according to min n provided via order book? Each maker would add its part and only the last one return the full list. Each maker should be able to extend the loop by further makers, eventually making the transaction bigger. In the second loop all would add their respective signatures. |
Oops. Can't edit? The makers would in both of the loops contribute their part encrypted for the taker but in random order. Ok in this model the makers can deliver garbage and nobody could know who's misbehaving. |
Yes, didn't mean to imply otherwise, trying to say that it doesn't change it. |
Couldn't you just then mix those UTXO's after the ban period... wait 10 minutes... and try again? |
That would still add a cost to the spy. It would mean they can only do one probe every block (and it would cost them miner fees) |
Plus remember that one probing isn't enough to see all the maker's UTXOs because they are in different mixdepths. And depending on the algorithm it wont be trivial to actually get the maker to send you his UTXOs. |
"UTXO commitments" (which I think we shouldn't use as a term, as it refers to something else in Bitcoin) is what we discussed at length in various forms in ~ December, you probably remember the gist. That list of 3 ideas isn't exhaustive, no doubt. All involve a protocol update as we've said. @chris-belcher did I miss some additional idea here? Also, the "blacklist" PR #328 is one tentative piece of code around that, also I think I still have branch with a primitive PoDLE implementation. And yes these ideas are just a "make it hard/expensive/slow"; indeed it could be very hard to snoop enough UTXOs to get good information, especially as the yg algos broaden out, making it really hard to get anywhere near to a "full" list of maker utxos. Is this enough of a defence in practice? Really don't know. Arguably, for an attacker, it makes a lot more sense to try to swamp the yieldgenerators with lowball offers (although that's a different attack - trying to de-anonymize takers), although some taker-customers are always going to try to pick more randomly than the default with -P (I do), or in various other ways. |
Yes there's nothing new I've come up with in terms of technology, only some thoughts on incentives/cost. JoinMarket itself relies on just making it hard/expensive anyway. It's mostly secured by game theory and incentives, we've always known that with a large amount of bitcoins owned you could be every maker in everyone's coinjoin. I will try to write a short gist about how much it costs to be a spy taker like this and so whether this is a good enough defense in practice. |
Not completely true right; you can swamp the orderbook, but unless you censor the message channel, you can't stop other people taking part, and some takers might choose price insensitivity. It's not a big difference admittedly. |
So it looks like somebody is actually doing this. https://www.reddit.com/r/joinmarket/comments/4mqpre/someone_is_submitting_fake_orders_to_makers_over/ I've been thinking about running an automated bot that detects this behavior and then kicks out the spy nick. But that can be beaten easily with delays and multiple nicks. I'm thinking the best thing to do now is to set an alert warning people not to use JoinMarket, with a link to a post explaining what's happening and what you can expect if you continue to use JoinMarket. |
It would be a shame to scare users away from join market. I have a thought on this. First takers must be forced to prove ownership of The database would be used to only ever present the same utxo matches to |
Another option would be a distributed hash table of seen, verified utxos |
I should clarify, I'm thinking only of having that alert until we create the fix to this, not forever. I'm thinking defense 2 from here https://gist.github.com/AdamISZ/9cbba5e9408d23813ca8#defence-2-committing-to-a-utxo-in-publicplaintext-at-the-start-of-the-handshake which is similar to what @bulldozer2003 writes. It would at least add a cost to this attack, which right now happens for free. I know it would be bad to scare users away from joinmarket but I think the scare is justified. JoinMarket provides them reduced privacy against this spy, we know about it luckily and it wouldn't be right to not raise the alarm. I saw today someone on IRC was mentioning it so the truth will out eventually whatever we do. JoinMarket is still useful, its much better than without where everybody in the distant future can see the graph between addresses. But it has this vulnerability which we need to fix. CoinSwap as in #335 is not vulnerable to this problem BTW. |
The PR #328 has a basic implementation of PoDLE here Of course this was ages ago, but it might not be too hard to recreate and merge. The code already uses the libsecp256k1 binding. The hard thing is having consensus on the right way to implement the protocol update and how to decide on what rules to use to limit reuse. |
Linking to the PR #328 reminds me of the question of wallet providers. From what I see, creating a PoDLE can't be used to steal someone's coins so hardware wallets (or any wallets) could blindly create them without worry. |
I have just posted this to all forums https://gist.github.com/chris-belcher/00255ecfe1bc4984fcf7c65e25aa8b4b A definite setback for JoinMarket. But there's no reason we can't recover from this and fix the exploit. |
Another solution is to have the makers scan the blockchain for coinjoin-like UTXO's, and run a sybil attack against the snoop where sometimes they offer UTXO's that don't belong to them. A persistent snoop trying to compile all maker UTXO's would thus end up with a list off all UTXO's in the blockchain that are plausibly from coinjoins - and even some that aren't. The only way for the snoop to distinguish genuine maker UTXO's is to procede with signing a transaction that pays the coinjoin fees. But then the taker will only know maker UTXO's and will be paying to make JoinMarket happen, and makers can raise prices and the attack gets progressively more expensive. |
I saw your post on reddit. That is a very novel idea that nobody had thought of. What would the maker do if the taker is actually genuine? Just back out of the coinjoin, but thats essentially a DOS. |
This has some similarity to an iterated prisoner's dilemma problem, so a
|
It wouldn't need to be implemented all at once. Unilateral action by makers
Edit: Changed point 4.D because I didn't mean to send this yet. |
You cannot really rely on nicknames because they're random by default on
every run, and a spy can randomize it furthermore during a session.
The only persistent IDs are UTXOs.
|
Newcomers wouldn't be automatically green-lighted though, but typically amber-lighted. A maker should be able to limit UTXO's disclosed to new comers and bad faith actors to one mix depth of his wallet, or equivalent. If one further capped offers to amber-lighted takers to a fraction of largest mix depth, then one could limit UTXO's disclosed to that fraction of the largest mix depth, and save the rest of the maker's UTXO's for demonstrated good faith actors. Without a public reputation system this would require takers to use the same maker a couple times each in order to protect themselves from the attack. Implementing a reputation system on top of this would mean a taker would just have to include a maker with good reputation in his first coinjoin, then that maker vouches for him and others disclose fresh UTXO's and he is protected from this attack. The red light category isn't strictly necessary, but I think it's value added because it offers up bad intelligence to the snoop, and that diminishes whatever value the attacker aims to get from snooping on JoinMarket UTXOs. As I think about this more though I think there may be an even simpler way. Makers could just limit mix depth X of their wallet to those takers that have participated with them in at least Y coinjoins successfully. Alternatively - and this is clever because it allows takers to verify that makers are defending against the attack as specified - makers could limit UTXO's offered to newcomers who have participated in Y coinjoins to those that satisfy ((amount+C) % M) <= Y for some integer M >= 2 and integer C<M which are announced. The "announcement" of integers M and C could just be appended to the nickname of a maker. Takers could adjust their expectations accordingly, as the value of M would involve a trade-off between security and user experience. Takers could verify that their first M coinjoins with a given maker under a given nickname involve UTXO's that satisfied ((amount+C) % M) <= Y, and even automatically reject the maker if that condition is ever not met. In case of some congestion of UTXO's from enforcing this policy, the maker can restart with a new random nick and choose a different M and C to avoid the congestion. |
An issue with this is it breaks pruning. Makers today can run with a pruned full node. However as a stopgap we could have one of us run a web server that scans for coinjoin UTXOs and uploads them by http to any maker who asks. I think the podle method will be more fruitful long term. |
My first reaction was to brainstorm quick fixes for a game theory solution using the existing rules of the information game implicit in an attack on JoinMarket by introducing strategy to the makers to replace the naive sharing of UTXO's, in a backwards compatible manner. After getting feedback and giving it some thought, I have concluded that all such solutions are only partial fixes - they will always leak some UTXO's to an attacker, and worse they will do so at no cost to the attacker, allowing repeat and continuous attacks to obtain a fractions of all JoinMarket UTXO's for free, while other market participants pay for any defense in the form of reduced liquidity or need for repeat coinjoins to build trust. I concur now that a cryptographic solution to change the rules of the information game to add a cost to the attack is better. PODLE looks like an elegant solution. I gather that it won't be backwards compatible - both makers and takers will have to update their software to participate in a more secure JoinMarket. That is the only drawback I see. Is that correct? |
Yes it requires a protocol break. There are many things wrong with the current protocol so we'd like to do a protocol break for other reasons anyway. (see #171) |
Partially addressed by 0.2.0 release. Still not closing it though! |
Here is a way a malicious taker could unmix every coinjoin.
Essentially this works by breaking the assumption that the taker cares about privacy.
Firstly this does nothing for passive observers of the blockchain.
It would be quite easy to detect this and raise the alarm. Look out for repeated unfilled orders for coinjoin amounts equal to your maxsize.
There could even be decoy bots which announce a large fee that no rational taker would fill, but that the spy taker would have to partially fill.
It could be defeated by radially changing the protocol to involve something like coinshuffle which would result in no single party knowing the mapping between inputs and outputs.
A third way is to write the yield generator algorithm so that it's very hard to find all the UTXOs.
Fourth way is to use that kind of blinded signatures described by gmaxwell in the coinjoin thread on bitcointalk
The text was updated successfully, but these errors were encountered: