Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider forbidding or warning on non-wallet-type outputs #864

Open
csH7KmCC9 opened this issue Apr 27, 2021 · 20 comments
Open

Consider forbidding or warning on non-wallet-type outputs #864

csH7KmCC9 opened this issue Apr 27, 2021 · 20 comments

Comments

@csH7KmCC9
Copy link
Contributor

See the discussion in #859 . Any output type other than v0 P2WPKH currently identifies the output as belonging to the taker or the taker's payee. Further, this presents a non-obvious fingerprinting risk from sending coins to e.g. atypical P2SH scriptPubKeys.

I think everyone agrees that at the very least non-v0 P2WPKH custom change addresses should prompt a warning. There is also an argument to also warn the user for non-v0 P2WPKH receiving addresses. Finally there is an argument simply to forbid sending directly to non-v0 P2WPKH addresses in the CoinJoin transaction at all.

What to do, if anything?

@AdamISZ
Copy link
Member

AdamISZ commented May 23, 2021

I can only express agreement really. I worry about the explosion of different features, advice, warning and configuration in this application. But on the other hand, I worry that people are too in the dark about what the smart way to use the application, is. These two are in tension.

I always tend to lean towards giving the user control, even at the cost of difficulty of grasping every detail. I guess a lot of "power" users already know that this ability exists (cj-out with non-standard address), and also know it's best not to use it, generally. But we still see coinjoins like this from time to time.

No strong opinion.

@chris-belcher
Copy link
Contributor

chris-belcher commented May 24, 2021

I think this is not a useful idea.

We already know that single JoinMarket coinjoins arent very useful for privacy, and users who want to mix their coins should use the tumbler algorithm to create multiple coinjoins. The main reason for this is that all the maker's TXOs will be later spent in another coinjoin, but the taker's TXOs will likely be spent in a non-coinjoin. So to a passive observer of the blockchain they can pretty easily tell which coinjoin output belonged to the taker just by looking at how the coinjoin outputs were later spent. This is true even if the taker's coinjoin address is the same address type.

So in summary: if a user creates just a single coinjoin then they are easily unmixed, even if the destination is the same address type. If a user creates multiple coinjoins with the tumbler algorithm then their privacy is good, even if the final destination addresses are of a different address type. So adding barriers to different-address-type makes joinmarket less useful (e.g. because you can't send to a merchant who uses a different address type), without any privacy benefit.

@AdamISZ
Copy link
Member

AdamISZ commented May 24, 2021

This is true even if the taker's coinjoin address is the same address type.

Well, not exactly. Everything here is probabilistic; the probability of the assumption "this is the taker's address" is substantially different if it's a legacy address cf if it happens to be the case that it doesn't get spent in a JM coinjoin. The latter could easily be a maker who changed roles (not assigning X% prob but it's much larger), cf basically 0% chance that makers will have reconfigured their JM software to send the cj-out to a legacy.

So adding barriers to different-address-type makes joinmarket less useful (e.g. because you can't send to a merchant who uses a different address type), without any privacy benefit.

Tend to agree, just don't think the case is at all watertight.

@chris-belcher
Copy link
Contributor

I'd argue the probability of a taker's single-coinjoin being spent by someone else who also creates JoinMarket coinjoins is very very low. The only time that probability will be non-negligible is if the ecosystem reaches the utopia of "make every transaction a coinjoin", and that to me seems very unlikely to ever happen because 1. it increases miner fee costs, and people who don't care about privacy won't pay extra, and 2. a huge amount of the economic weight in the ecosystem is like KYC exchanges, required by regulation to spy on their customers, and therefore will never adopt coinjoin themselves.

I think makers-changing-roles-to-sometimes-to-be-takers is irrelevant here? Because if a maker-turned-taker creates a taker-coinjoin which goes to a different address type, then the adversary still doesn't learn anyway because all the maker-turned-taker's UTXOs come from a long line of previous coinjoins.

@AdamISZ
Copy link
Member

AdamISZ commented May 24, 2021

I'd argue the probability of a taker's single-coinjoin being spent by someone else who also creates JoinMarket coinjoins is very very low.

Yes sure but that's not what I was saying. I was saying that: if the taker's single-coinjoin output is spent in a non-JMcoinjoin tx, the deduction "that is the taker's output" is wrong for the cases where a maker sent a non-JMcoinjoin tx using their output from that same coinjoin. I was comparing the case: output goes to non-JMcoinjoin against the case: output is legacy (i.e. not bech32), saying the latter is a tremendously stronger watermark of "definitely the taker", than the former.
But btw I wasn't strictly talking about single coinjoin only; i was talking about any JMcoinjoin where the taker's output is legacy (which could be a tumbler destn addr also).

@csH7KmCC9
Copy link
Contributor Author

I tend to agree that forbidding this would make JoinMarket less useful without necessarily protecting privacy. I also agree that non-wallet-type outputs tend to identify those outputs as belonging to the taker. However:

  • If the non-wallet-type output is a change output, that output is almost certainly already identifiable as belonging to the taker. In that case, the only additional fingerprinting risk is from consistently sending change to unusual P2SH types (like exotic m of n multisig script hashes).
  • If the non-wallet-type output is a CoinJoin output, then yes, this really harms privacy. I don't fully agree with @chris-belcher here that later non-CJ spends from a CJ output identify that output as belonging to the taker (I agree with @AdamISZ: a maker can directly spend from their own CJ output). However @chris-belcher is definitely right that the conditional probability a UTXO belongs to the parent CJ's taker is dramatically higher once that UTXO is spent in a non-CJ transaction.

I think the real problem here is not with non-wallet-type custom change addresses (except for the fingerprinting risk from using exotic P2SH scripts), but with non-wallet-type main CJ outputs. With a wallet-type main CJ output, there is no ambiguity about which inputs are the taker's, no ambiguity about which change output is the taker's or if it's a sweep, but some ambiguity about which main CJ output is being paid by the taker. On the other hand, with a non-wallet-type main CJ output, there is no ambiguity about anything. Which raises the question: If there is no benefit and only costs, does the user really want to do that?

Here's my idea:

  1. Leave the custom change address type logic as-is in Enable external change addresses #859 (with updates to check for wallet address type as mentioned here)
  2. Add a warning/confirmation message box if the user is doing a single join with a non-wallet-type main CJ destination address.

I appreciate @AdamISZ's concern about the proliferation of warnings, advice, etc. but this case seems to have zero benefit while users might mistakenly think they're getting some privacy benefit. For this kind of situation I think it's important to at least tell the user that we think they're doing something dumb.

@csH7KmCC9 csH7KmCC9 changed the title Consider forbidding or warning on non-P2WPKH outputs Consider forbidding or warning on non-wallet-type outputs May 25, 2021
@AdamISZ
Copy link
Member

AdamISZ commented Jul 14, 2021

This has been dormant but afaict there is a simple actionable item coming out of the discussion, namely:

Add a warning/confirmation message box if the user is doing a single join with a non-wallet-type main CJ destination address.

Labelling it as such.

@clay-v
Copy link

clay-v commented Jul 17, 2021

The path to follow is to forbid the use of non-v0 P2WPKH outputs for coinjoins and leave it available only when the number of counterparties is zero.

I worry about the explosion of different features, advice, warning and configuration in this application.

This isn't a new feature. We may even consider it removing a feature

I always tend to lean towards giving the user control, even at the cost of difficulty of grasping every detail. I guess a lot of "power" users already know that this ability exists (cj-out with non-standard address), and also know it's best not to use it, generally.

The thing is that sending funds to a non-v0 P2WPKH output inside a Joinmarket coinjoin is a mistake. So we shouldn't be looking at it as a tool that power users may know the existance of but rather as a way that newcomers may shoot themselves on the foot.

So in summary: if a user creates just a single coinjoin then they are easily unmixed, even if the destination is the same address type. If a user creates multiple coinjoins with the tumbler algorithm then their privacy is good, even if the final destination addresses are of a different address type. So adding barriers to different-address-type makes joinmarket less useful (e.g. because you can't send to a merchant who uses a different address type), without any privacy benefit.

I tend to agree that forbidding this would make JoinMarket less useful without necessarily protecting privacy.

Nothing is gained from sending payment to a non-v0 P2WPKH in a coinjoin the ability should be removed. If a user wants to pay a non-v0 P2WPKH output they should be only be able to do so with zero counterparties so it's made clear to them that there's no advantage in using the sendpayment tool for such case.

@chris-belcher
Copy link
Contributor

chris-belcher commented Jul 17, 2021

Nothing is gained from sending payment to a non-v0 P2WPKH in a coinjoin the ability should be removed.

What about non-v0 p2wpkh addresses that get used as tumbler destinations? If you do the quoted thing you said then it becomes impossible to use tumbler to send coins to many places if they don't use v0-P2WPKH, even though the privacy of sending coins somewhere with tumbler is pretty good regardless of the destination address type.

The real problem is from people using sendpayment.py where the inputs are UTXOs that didnt come from a long line of earlier coinjoins. Remember there's also the privacy leak of sending to a v0-P2WPKH address but where that coin is later not spent in another coinjoin, or where the address is reused, or otherwise clearly belonging to a non-maker.

@clay-v
Copy link

clay-v commented Jul 18, 2021

What about non-v0 p2wpkh addresses that get used as tumbler destinations? If you do the quoted thing you said then it becomes impossible to use tumbler to send coins to many places if they don't use v0-P2WPKH, even though the privacy of sending coins somewhere with tumbler is pretty good regardless of the destination address type.

I'm doubtful of that and I think that any speding towards a non-v0 p2wpkh output have no place in Joinmarket coinjoins. But assuming you are correct that should only apply to the Tumbler then and be removed from the Single Coinjoin tool.

@kristapsk
Copy link
Member

I don't think forbiding taker to send to different output type will solve anything, he will just be forced to send to p2wpkh first and then create another transaction with zero counterparties, thus just wasting extra blockchain space, to send to final address. Any blockchain observer will with high probablity figure out who is taker anyway. Warning is ok, as newcomers might not know the nuances of Bitcoin privacy, but forbiding is almost useless.

@chris-belcher
Copy link
Contributor

chris-belcher commented Jul 20, 2021

I'm doubtful of that and I think that any speding towards a non-v0 p2wpkh output have no place in Joinmarket coinjoins. But assuming you are correct that should only apply to the Tumbler then and be removed from the Single Coinjoin tool.

It's true, I will explain why. Imagine if you saw a coinjoin where one of the coinjoin outputs was a non-v0 p2wpkh address, because of this you know that this output is the taker's. OK so now you try to go backwards in history to figure out the initial source of these coins. But you have a problem, all the input UTXOs themselves come from a long line of previous coinjoins, which means you can't figure out much.

At the risk of repeating myself in this thread, trying to ban non-v0 p2wpkh address is not the root cause of the problem. The root cause is people doing single coinjoins where the input UTXOs did not come from a long list of previous coinjoins. We should add a warning about that.

Concretely, if you withdraw coins from a KYC exchange into your joinmarket wallet, and then do a single coinjoin to pay for a domain name, then that coinjoin can be unmixed even if you sent to a p2wpkh address. The reason is that it's overwhelmingly likely that the domain name host provider won't be spending your coins with a joinmarket coinjoin themselves.

@PulpCattel
Copy link
Member

@kristapsk

he will just be forced to send to p2wpkh first and then create another transaction with zero counterparties, thus just wasting extra blockchain space, to send to final address.

I think that's wrong? Why do we need to "send to p2wpkh" first? We can directly send with 0 counterparties, thus saving blockchain space.

let DAT = Different Address Type

Let's try to look at the actual scenarios:

  1. Bob has unmixed funds, that's it, he just received to JM wallet for the first time. If he wants to pay to a DAT with enhanced privacy, he'll have to do 1 or more CoinJoin before, he cannot skip this step because his funds are unmixed. (If he pays directly in a CoinJoin (trying to save blockspace and fees) to DAT, he'll have no privacy against smart observers). This leads Bob to a variant of point 2 below.
  2. Bob has mixed funds, that's it, he's mixing since 2015 with this wallet and now he wants to spend. If he wants to pay to a DAT, he should just do a normal send (0 counterparties), since there is no privacy benefit from using a CoinJoin and he can save fees.

These are the 2 extreme scenarios, but any shade in between does not sound much different.
If you need to "boost" your privacy, you'll have to CoinJoin without using a DAT anyway.
If you don't need more privacy, because as Belcher said "all the input UTXOs themselves come from a long line of previous coinjoins", then why create a taker CoinJoin where you, as a taker, get no privacy benefit but pay more?

@chris-belcher

At the risk of repeating myself in this thread, trying to ban non-v0 p2wpkh address is not the root cause of the problem. The root cause is people doing single coinjoins where the input UTXOs did not come from a long list of previous coinjoins. We should add a warning about that.

That's clearly true, but I don't think it's relevant? Point 2 above works better without a CoinJoin anyway.

All that being said, IMHO a warning is enough (if anything just to let tumblers happy), though I have to say this is one of the cases where I really don't see any benefit whatsoever in a taker CoinJoin to DAT.
Tumbler is a good point here, but even there it's just convenience no? User could manually direct send at the end of the process if he wants to.

@chris-belcher
Copy link
Contributor

chris-belcher commented Jul 21, 2021

@PulpCattel

You're right that if all UTXOs in a wallet come from a long line of coinjoins then you may as well use direct-send. And if they don't come from a long line of coinjoins then you shouldnt create a single coinjoin at all. To me that sounds like an argument for just removing single-coinjoins entirely from the project, and only supporting tumbler and direct-send. Thinking about it now, when are single coinjoins ever useful? I can only think of one specific case, which is when someone wants to run a yield-generator to slowly mix their coins, but after receiving coins they first do a sweep-coinjoin sending the coins back to themselves so that all their coins go through a coinjoin with no change address. After all as a yield-generator all your coinjoins will always have a change address.

@PulpCattel
Copy link
Member

If you remove the "DAT" element, then I think the argument is far weaker, as per what Waxwing said here.

Also, manual mixing relies on being able to do single CoinJoin over time, so it doesn't seem at all something that we want to remove from JoinMarket.

@chris-belcher
Copy link
Contributor

chris-belcher commented Jul 22, 2021

I'd argue the probability of maker's changing roles to sometimes become takers is very low, because it's just not incentive-compatible behaviour. Makers are there to earn money, not spend money. If you put cash in a savings account how often will you be transferring the whole stash in and out? You need a checking account not a savings account. Probably if yield-generators were not running bots those coins would just be sitting in cold storage doing nothing. Because a maker is an alternative to cold storage that means makers are unlikely to create many transactions. I bet many of them take part in thousands of coinjoin transactions and only single-digit numbers of initiating a transaction of their own.

Meaning if you replace DAT with "Address which is Later Spent in a Non-CoinJoin" (ALSNCJ) in your argument, then it still works.

Our only defence is multiple coinjoins.

We've been talking about how single coinjoins can be easily unmixed due to DAT and ALSNCJ, but their inputs and change addresses can also be often (but not always) unmixed due to solving the subset sum problem on the input and change values. See https://gist.github.com/chris-belcher/7e92810f07328fdfdef2ce444aad0968#appendix This is another reason that multiple coinjoins are our only defence, because they eventually make this subset sum problem stop working for the attacker.

Manual mixing is not in the documentation anywhere, the JoinMarket project doesn't tell its users to do that. I'd argue manual mixing is tricky to get right and users shouldn't do it. Tumbler is finely tuned to have as good privacy as possible. See the above document Plan to improve the privacy of JoinMarket's tumbler script, someone doing manual mixing would probably lose out on much of that. For example will manual mixers sometimes create coinjoins of round-number amounts? Maybe but why allow the user to make yet another mistake when tumbler already does the correct thing automatically. Users will also lose out on privacy things not in that document, for example timing analysis. We know humans are bad at generating random numbers, a human doing manual mixing could easily leak their timezone because they'd only make coinjoins when they are awake (unlike the tumbler bot which is left running for hours and can do coinjoins while the user sleeps)

That's why I'm thinking if we do anything it would be to put warnings on single coinjoins. Almost everyone should just be using tumbler instead. The only good example I know of single coinjoin is doing a sweep-coinjoin to the same wallet and then running a yield-generator.

@AdamISZ
Copy link
Member

AdamISZ commented Jul 22, 2021

I'd argue the probability of maker's changing roles to sometimes become takers is very low, because it's just not incentive-compatible behaviour. Makers are there to earn money, not spend money.

A sidebar to this issue, but:

I've always thought this argument isn't quite right. What I believe is the incorrect assumption: that the gain that makers seek is only sats reward. I believe that makers, over time, have correctly realised that their advantage is a mix of sats reward and privacy boost, traded off against what they increasingly perceived as a very low cost - which is mainly the hot wallet risk, and if I'm right that perception of that cost being low is a function of the software operating correctly, mainly.

In that regard, a maker's use of the coinjoin market as taker occasionally can certainly make sense. It's a calculation that everyone has to make, whether it's worthwhile to spend back most or all of the sats you earned, in return for increasing the quality of privacy gained by everyone including yourself, as well as changing the quality of privacy in that specific transfer, itself.

You can certainly reasonably assert that I'm wrong and in fact almost everyone running a maker is only focused on earning sats, and perhaps I am wrong. I think it's relevant, though, that unless you put very large amounts of BTC in, the return rate is tiny (for now! before fidelity bonds).

@PulpCattel
Copy link
Member

First, let me say that I don't disagree with the concept, I do think some users are erroneously overestimating their privacy even without a DAT element when using single CoinJoin, and general warnings about that can't be wrong.

Meaning if you replace DAT with "Address which is Later Spent in a Non-CoinJoin" (ALSNCJ) in your argument, then it still works.

IMHO comparing DAT and ALSNCJ like if they are equal is a fallacy, the latter can still be much better than nothing (while the former is basically 100% useless).
Unfortunately, this point remains open to interpretation until someone actually calculate from the blockchain how many outputs are spent in CoinJoin and how many are not (even better if distinguishing taker CJ from maker CJ).

Manual mixing is not in the documentation anywhere, the JoinMarket project doesn't tell its users to do that. I'd argue manual mixing is tricky to get right and users shouldn't do it

JoinMarket is a great tool for power users and manual mixing is part of that.
I'd argue, any competent user can outperform the tumbler at the cost of convenience (and possibly other trade-offs, as you mentioned). Various things related to that from the top of my head:

  • Waiting time between CoinJoin. Default for tumbler is 1h, but 1h is quite low (we may end up doing all our CoinJoin in a single day), so we may want to increase this value. But if we do, we quickly come to the extreme where our computer runs for days without doing anything at all, when it could be used just once every X days to do a CoinJoin.
  • Coin control. Manual mixing by definition gives you fine-grained control over your UTXOs, how/when they are splitted, how/when they are combined, etc.
  • Reliability. We all hate leaving our computer running, only to find it stuck when we come back.
  • Fee savings. The tumbler knows nothing about fees, so by doing it yourself you have fine-grained control over each individual CoinJoin fee.

And of course, manual mixing can be combined wth tumbler or YG, we don't have to pick one and forget the others.

Note how we could consider manual mixing as a variant of "stopping and resuming the tumbler multiple times, doing one or more CoinJoins with a new user defined schedule each time".

But anyway, I don't want to preach manual mixing, I was just noting how hugely different the impact/complexity is between just removing DAT from JM CoinJoin vs entirely removing single CoinJoins.

@AdamISZ
Copy link
Member

AdamISZ commented Jul 22, 2021

Huh, quite a discussion going on here :)

On "manual mixing" and "single vs tumbler" I just wanted to drop a mention of "schedule". It's not perhaps used much but the whole idea was we could fold the two scripts into one and it's just a question of if you use the tumbler's algorithm to generate the schedule, or do it your own way. Belcher's arguments for why using tumbler is better make sense, but I like that users can make their own schedule.

I'm in the "let people come up with their own way" camp, as long as it's backed up with "you can follow our advice based on detailed analysis" (tumbler).

Having said that I guess I have no objection to warnings about both single coinjoins and DAT. But removing single coinjoins (which in the software is a schedule of only one entry) I'd definitely be strongly against.

@kristapsk
Copy link
Member

when someone wants to run a yield-generator to slowly mix their coins, but after receiving coins they first do a sweep-coinjoin sending the coins back to themselves so that all their coins go through a coinjoin with no change address.

Maybe this is something that should be added to documentation as a recommended practice for increased privacy? In mixed maker/taker role scenario, this will ensure that, any inputs you have available for payment, in history will as a source have at least one cj-out output (not just series of cj change outputs, that could be case if you do a payment from mixdepth to which you have deposited funds previously).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants