JoinMarket-Org / joinmarket

CoinJoin implementation with incentive structure to convince people to take part
398 stars 119 forks source link

sendpayment.py is too easy to be tracked #576

Closed nanana223 closed 8 years ago

nanana223 commented 8 years ago

Let's not talk about the tumbler.py which will cost hours to days. sendpayment.py is very easy to be tracked. e.g. you want to mix some coins and use those coins at microsoft/expedia/doastoldhitmanservice/coinbase/highratedrugdealer/moneylaunder/whateverelse later within a day:

sendpayment.py -N 5 wallet.json 500000 add1

in the blockchain it would be like:

IN:

mixer1 (from uppers multi-sign tx)
mixer2 (from uppers multi-sign tx)
mixer3 (from uppers multi-sign tx)
mixer4 (from uppers multi-sign tx)
your_source_add_being_watched (mostly not from multi-sign tx, or its uppers are not from multi-sign tx)
mixer5 (from uppers multi-sign tx)

OUT

someadds (wait here without moving until next move as another multi-sign task)
someadds (wait here without moving until next move as another multi-sign task)
add1 (later send to add2/add3/add*/microsoft/expedia/doastoldhitmanservice/coinbase/highratedrugdealer/moneylaunder/whateverelse)
someadds (wait here without moving until next move as another multi-sign task)
someadds (wait here without moving until next move as another multi-sign task)
someadds (wait here without moving until next move as another multi-sign task)

So, any one can now link your_source_add_being_watched with add1 easily. Just find the address moves first & doesn't continue the multi-input transaction. to solve this we need to do like blockchain.info sharedsend used to do, wait for all real users (mixers) to mix together so all coins will move just like yours. sounds like patientsendpayment.py 's job?

raedah commented 8 years ago

I do not follow your logic.

nanana223 commented 8 years ago

i think it's quite clearly described up there. which part don't you follow?

take this example: https://blockchain.info/tx/3b97544488cac0271a80b20822597342648d19ed02ac25041bd8d35e624d8e6b

It's very easy to tell which address send 40 btc to which address. (others are just mixing bots transactions)

The source: 19ZmRG6twcjMvqWCdMPutFUup1MnXuzkDo The destination: 127pTU6ZuZtuvcFFoxCrtGV7iC3sXP5HPy

AlexCato commented 8 years ago

While the point is clear with the example you give, I'd argue this is a bad example: the user of this diverted from the more secure default settings and just used 2 Makers to mix with (default would have used between 4-6 counterparties to mix with). The user probably also used the "-C" non-default option, which selects deterministically the which parties to join with, because the follow-up transactions of the coinjoin-bot often seem to be in the same joins and probably belong to the same owner offering cheap cj fees.

Let's not talk about the tumbler.py which will cost hours to days.

Well, we will have to talk about it. If sendpayment alone was good enough, we'd not need a tumbler. It does take some time to secure funds. I'd plan ahead and always keep part of my coins pre-tumbled to different wallets I control. Even if I dont need them right at this moment. When I do actually need them later, I can just spend pre-tumbled coins right away from my own wallet. And if it needs to be a bit faster, I'd not use sendpayment and override the reasonably secure default settings with more unsecure ones. But you must be aware that one single sendpayment does not give perfect results, even if the default settings are used.

Edit: I do agree that it would be awesome if patientsendpayment would something similar to sharedsend.

nanana223 commented 8 years ago

nah. the same weakness arises with the default setting send (sendpayment.py -N * wallet.json 500000 add1)

It's super easy to tell who is the bot & who is not in the mixing transaction.

AdamISZ commented 8 years ago

The source: 19ZmRG6twcjMvqWCdMPutFUup1MnXuzkDo The destination: 127pTU6ZuZtuvcFFoxCrtGV7iC3sXP5HPy

Yes and no. Within the transaction, the destination coinjoin output is fundamentally unknowable. If the three 40btc destination outputs are then used in some particular pattern (the obvious one being: 2 of them are reused in coinjoins, the other not), then one might infer the destination.

As for the change outputs, that will always be non-obscured; simple arithmetic will always show the source of that.

Nobody was ever told that sendpayment obscures the path of funds outwards in any reliable way; generally one should assume it doesn't. What it can do is help to break automated wallet closure analysis, where people are gathering databases based on assuming that all the inputs to a transaction are from the same identity.

There's a reason there's a tumbler script .. a single sendpayment is not a strong defence at all against privacy invasion, as you observe.

Tumbler is configurable to use more or less transactions, and more or less time. You could also do a series of sendpayment transactions, paying attention to mixdepths, to get a similar effect.

nanana223 commented 8 years ago

if most of parties are real users, like sharedcoin (disabled now) in blockchain.info. it would be very hard to tell the destination.

raedah commented 8 years ago

@nanana223 I hear what you are wanting, real parties like sharedcoin. I think its a great idea and would like to see it developed. I dont see how it would fit into joinmarket. It may be an entirely different project you are suggesting. If this is something you are interested in building, contact me on IRC and I will help.

AdamISZ commented 8 years ago

Not only sharedcoin, but also darkwallet had this kind of model. Sharedcoin apparently had some design weaknesses (discussed elsewhere) but they had the network effect of blockchain.info (pretty huge). Darkwallet not so much, but .. I shouldn't opine too much about that stuff without more knowledge.

The joinmarket concept is to create incentive to overcome the network effect barrier. I don't think anyone would argue that no other model is viable. It also depends what you're trying to achieve.

jamesphillipturpin commented 8 years ago

I looked up one of my transactions today on blockchain.info. I could tell which addresses were change and which were sends because there were multiple outputs of the same size. But I couldn't tell which one was maker or taker. I couldn't tell which one was mine if I didn't have a list of my addresses. My understanding is that tumbler, yield-generator, and patient-send all use multiple wallet depths - five by default. Also default setting and typical use has five (or more?) parties joining. So even if half of other users are spies, snoops, investigators, and doxers you still have the safety margin - a typical of two real users as counterparties to your coinjoin which means that no one user can unilaterally de-anonymize a transaction even if he paid the two snoops to share info.

I think there are worse problems than the issue described above. Snoops initiating transactions they never sign to uncover UTXO's of makers. Sybil attacks. Etc. Basically spies on the IRC channel collecting intelligence in real time. I haven't seen evidence that they are persistent though. Attacks would need to be persistent to be effective in my opinion. One would expect that even some benevolent parties interested in the project might play with such attacks intermittently. It's difficult to design and test countermeasures without designing and testing measures.

nanana223 commented 8 years ago

@jamesphillipturpin nope, you can easily tell which address was your source address by checking the last tx of each input address, find the one wasn't came from multi-input tx and it is the one.

raedah commented 8 years ago

@nanana223 I see your point, that in some cases it can be deduced in that way. Its an interesting point. I dont think anyone has ever said a single coinjoin offered any strong anonymity. My understanding has always been that it takes many coinjoins to achieve better anonymity. sendpayment.py works well to get one more level of mix when sending coins from your wallet which has already been mixed.

jamesphillipturpin commented 8 years ago

It's somewhat analagous to Tor network. You need multiple hops to anonymize because incoming/outgoing hops are more uniquely identifiable than in-networks hops. So to break connection between incoming/outgoing mixdepth you need intermediate mixdepths. The intermediate mix depths are where anonymization happens. It's not enforced though because it's designed to give you control over your money at all times. On Jun 19, 2016 3:34 PM, wrote:

Mine did come from a multi-input transaction though. The premise of JoinMarket is that everybody uses multiple depths, that you have at least three mix depths but typically five or more. If you have no middle mix depth you aren't using JoinMarket the way it's intended. On Jun 19, 2016 7:32 AM, "nanana223" notifications@github.com wrote:

@jamesphillipturpin https://github.com/jamesphillipturpin nope, you can easily tell which address was your source address by checking the last tx of each input address, find the one wasn't came from multi-input tx and it is the one.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/JoinMarket-Org/joinmarket/issues/576#issuecomment-227000460, or mute the thread https://github.com/notifications/unsubscribe/AD1LdxIui1yOQNI3zNY9BgzJoQRDzNESks5qNVL6gaJpZM4I3xoZ .

jamesphillipturpin commented 8 years ago

Mine did come from a multi-input transaction though. The premise of JoinMarket is that everybody uses multiple depths, that you have at least three mix depths but typically five or more. If you have no middle mix depth you aren't using JoinMarket the way it's intended. On Jun 19, 2016 7:32 AM, "nanana223" notifications@github.com wrote:

@jamesphillipturpin https://github.com/jamesphillipturpin nope, you can easily tell which address was your source address by checking the last tx of each input address, find the one wasn't came from multi-input tx and it is the one.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/JoinMarket-Org/joinmarket/issues/576#issuecomment-227000460, or mute the thread https://github.com/notifications/unsubscribe/AD1LdxIui1yOQNI3zNY9BgzJoQRDzNESks5qNVL6gaJpZM4I3xoZ .

nanana223 commented 8 years ago

@jamesphillipturpin You still don't see the point. lets say you do 7 depths of 5 parties with sendpayment.py. it will only take a very short time for a script to scan at most 5^7 address before finding the one who doesn't continue multi-tx but send to microsoft/expedia/doastoldhitmanservice/coinbase/highratedrugdealer/moneylaunder/whateverelse.

beside some one can also match with the amount you sent.

however if those parties are real users like you, 99% problem solved.

AdamISZ commented 8 years ago

You still don't see the point. lets say you do 7 depths of 5 parties with sendpayment.py. it will only take a very short time for a script to scan at most 5^7 address before finding the one who doesn't continue multi-tx but send to microsoft/expedia/doastoldhitmanservice/coinbase/highratedrugdealer/moneylaunder/whateverelse.

@nanana223 Now you're going a little too far. There isn't just one single in/out to the whole fan out of joins. Just because people run ygs doesn't mean that's the only transactions going on in their wallets (my yg has tons of single sendpayments mixed in). Suppose you start from an output which is not a JM join, and then trace back. You'll be tracing back each input and slowly growing the "fan" combinatorially. Will that backward search in only one non-join transaction? Certainly not. And because of equal sized join outputs, you'll have no basis to decide which one is the originator - unless you use size correlation (which tumbler addresses) or timing analysis (which it also addresses).

However, I fully agree that you need to think carefully about what you're doing. I put a bit of working into figuring out potential weaknesses of the tumbler structure here, I think you'd find it interesting.

I know you'd prefer a single "everyone doing the same thing" join. No need to go over that more, it's already been addressed.

chris-belcher commented 8 years ago

FWIW the patientsendpayment.py script existed since the beginning. It doesnt work for subtle reasons but thats besides the point.

AdamISZ commented 8 years ago

I'm going to close this, even though it's an important general discussion point about joinmarket (see e.g. fungibit's recent analysis), it doesn't seem that there's something actionable here for now