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

When coinswapping, use coinjoin via Pay-to-EndPoint (P2EP) #52

Open
chris-belcher opened this issue Sep 26, 2018 · 3 comments
Open

When coinswapping, use coinjoin via Pay-to-EndPoint (P2EP) #52

chris-belcher opened this issue Sep 26, 2018 · 3 comments

Comments

@chris-belcher
Copy link

chris-belcher commented Sep 26, 2018

One issue with coinswaps is that the common-input-ownership heuristic is not broken. So an adversary could cluster together all the addresses belonging to one coinswap server, which would obviously be bad (indeed one way of breaking traditional 2013-era mixers is to use walletexplorer.com and just see the money coming in and out).

Many people have thought about combining coinjoin with coinswap for this reason. But a downside is that coinjoins are usually quite obvious on the blockchain, especially in Joinmarket. That would heavily damage the deniability and fungibility property of coinswaps where coinswap transactions can look just like any other bitcoin transaction.

Instead of Joinmarket, Pay-to-EndPoint (https://blockstream.com/2018/08/08/improving-privacy-using-pay-to-endpoint.html) could be a very good fit for coinswap. The transactions are not obviously coinjoins, and there is already a client-server customer-merchant relationship that P2EP requires, and there is already lots of interaction so using P2EP doesn't make that much worse.

If every single coinswap use P2EP then that would also be bad because it would imply that transactions with only one input are definitely not coinswaps. So probably the best way of doing things would be that about 60% of coinswaps use P2EP while the other 40% don't.

@AdamISZ
Copy link
Owner

AdamISZ commented Sep 26, 2018

This feels like a nice combination of ideas. As has been discussed here at length, amount correlation is a big fly in the ointment of a simple coinswap design. This would work against that part.

I see a possible "attack", basically in that the two transactions would share a specific property: they'd both be intersections of wallet cluster "Alice" and wallet cluster "Carol" (to use the nomenclature of this repo), and that specific pattern wouldn't appear in any other transaction.

That's very debatable though and you can work with it. It's already a big step up by making the amount correlation either impossible or highly ambiguous (generally I think the former).

@chris-belcher
Copy link
Author

chris-belcher commented Sep 26, 2018

I see a possible "attack", basically in that the two transactions would share a specific property: they'd both be intersections of wallet cluster "Alice" and wallet cluster "Carol" (to use the nomenclature of this repo), and that specific pattern wouldn't appear in any other transaction.

So probably almost all the Alices and Carols would end up in the same cluster.

That could be used as an attack, because all coinswap participants would share one cluster. So that could be used to figure out whether a transaction is a coinswap or not (assuming nobody else uses P2EP). That could reduce the anonymity set a fair amount.

Although it's definitely better than the previous situation where each Alice and Carol are in their own cluster.

Another way to break clustering aside from coinjoin/p2ep is taking care to not reveal the change address (via a number of methods), or even not have a change address at all.

@ZmnSCPxj
Copy link

It seems to me, that the protocol would require a different script, and would require more intercommunications.

Suppose we restrict, such that Carol always requires P2EP coinjoin on TX0 creation, but Alice cannot propose to P2EP from Carol. Then the protocol (augmented with my proposals in #53 ) would proceed as follows:

  1. Alice creates initial TX0, unsigned, and gives transaction to Carol.
  2. Carol creates TX0-p2ep, which is a version of TX0 with an input from Carol, and with the inputs reshuffled and the output increased by the value of the new Carol input (the P2EP input), and gives transaction to Alice.
  3. Alice verifies that all of the inputs from TX0 exist in TX0-p2ep, and that the Carol P2EP input exists and is unspent.
  4. Alice creates TX2-p2ep, which spends TX0-p2ep and pays to the the script OP_IF OP_HASH160 <digest> OP_EQUALVERIFY <carol_pubkey> OP_CHECKSIG OP_ELSE <L0> OP_CHECKLOCKTIMEVERIFY OP_DROP 2 <alice_pubkey> <carol_pubkey> 2 OPCHECKMULTISIG OP_ENDIF.
  5. Alice creates TX2-backout, which spends TX2-p2ep via the CLTV path and pays to Carol the value of the Carol P2EP input and pays to Alice the remaining value. Alice creates a signature for TX2-backout and gives to Carol.
  6. Carol creates similar TX2-p2ep and TX2-backout transactions, verifies the TX2-backout signature from Alice is correct, then creates the TX2-backout signature from Carol and sends to Alice.
  7. Alice verifies the TX2-backout signature from Carol and then creates the TX2-p2ep signature from Alice side and sends to Carol.
  8. Carol verifies the TX2-p2ep signature from Alice. generates the TX2-p2ep signature from Carol, the TX0-p2ep witness stack for the Carol P2EP input, the TX1 txid, and the TX3 signature. Then Carol sends them all to Alice.
  9. Alice verifies everything from Carol and generates the remaining signatures for TX0-p2ep and broadcasts TX0-p2ep, and generates the TX2 signature and sends the TX3 signature to Carol.
  10. Carol verifies the TX3 signature, then signs and broadcasts TX1
  11. Carol generates TX0-backout, which spends TX0-p2ep with a nLockTime equal to L0, and pays out to Carol and Alice in the same way as TX2-backout, and TX1-backout, which spends TX1 with a nLockTime equal to L1 and gives back to Carol, generates signatures for them, and sends signatures to Alice.
  12. Alice verifies the TX0-backout and TX1-backout signatures from Carol, and generates her own signatures and sends signatures to Carol.
  13. Alice and Carol wait for TX0-p2ep and TX1 to confirm deeply.
  14. Once confirmed, Alice sends X to Carol.
  15. Carol sends the Carol private key on the TX1 output.
  16. Alice sends the Alice private key on the TX0-p2ep output.
  17. Carol generates TX4, and Alice generates TX5.

Now, for the purpose of P2EP, Carol should keep two separate pools of UTXOs.

The rule Carol follows, is that when selecting UTXOs for TX1, it should only get from one pool. Then it offers any UTXO from the other pool in the P2EP.

When claiming TX0 (i.e. when Carol creates TX4) Carol should assign it to the same pool it got the P2EP input from, since those will be associated together due to the P2EP.

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

No branches or pull requests

3 participants