AntoineRondelet/snark-mixer

Implement the withdrawDeposit function in the Mixer contract

AntoineRondelet opened this issue · 9 comments

Implement the withdrawDeposit function in the Mixer contract

[WIP]
This function has been implemented as forward (echoing the fact that the recipient does not withdraw his funds, but instead, provides a proof showing that he knows the secret to compute one "unspent" commitment in the tree, to create another payment for someone else).

Further testing on the forward function is required before closing this issue...

Ping me when you have described this a little more ;-)

Here is a bit more information about it @barryWhiteHat :)

If Bob "receives Alice's payment" (he can withdraw from the tree), but would like to pay someone through the Mixer without depositing one ether; he can "forward" Alice's payment to someone else. By doing so, he needs to provide a proof (like a normal withdrawal), but also, a new commitment to insert in the tree. Instead, of being credited of 1ether, the proof is verified, and the new commitment is appended to the tree ONLY IF the proof is valid. He has now "spent" his commitment (the corresponding nullifier has been revealed), in order to append a new leaf in the Merkle Tree.

The idea is to avoid to withdraw, and then deposit in case where Bob knows the secret of a an "unspent commitment in the tree" (for which the nullifier has not been revealed)

The longer the value stays within the contract the more secure it is IMO, think of it as a single step WithdrawThenDeposit, so internal transfers can be made without revealing the identity of either party?

Some background notes from me on another project: clearmatics/mobius#15

If we have:

  • Alice doing a deposit to append a commitment for Bob in the three (-1 ether on her balance, +1 on the contract balance)
  • Bob receiving the secret and having the nullifier, from Alice (assuming a secure channel)

If Bob; wants to pay Charlie 1ether, then he doesn't have to proceed to a desposit, he can just use the fact that he possess the information required to generate a proof that he "controls" a commitment in the three binded to an unspent nullifier.
By calling the "forward" function he can pay Charlie appending a new leaf in the tree.

The idea is just to avoid modifying the public balances too often (if we can get rid of these -1ether on sender balance, +1ether on contract's balance during deposit, and -1 contract balance, +1 recipient balance, I think it'd be better, as we'd remove one source of leakage of information)

so internal transfers can be made without revealing the identity of either party?

Hum... the sender needs to call the contract from a founded address so, his identity is still going to be leaked (we'll know that Bob did a payment to someone because his address called the "forward" function). Moreover, looking at the ways the nullifiers are generated for now (addressReceiver || salt), when Bob calls the "forward" function to pay Charlie, his discloses the nullifier that basically leaks his identity. Furthermore, Alice, who has appended the commitment in the merkle tree to pay Bob, also knows the salt of the nullifier, so she knows that Bob is paying someone using the payment he received from her (however, she can't track further because she didn't generated the nullifier for Charlie).

I guess the solution to this problem would be to generate commitments and nullifiers like they do in ZeroCash: The creation of the commitment takes the recipient's public key as argument so that sender can create a new coin for the recipient (by "binding" it to its public key), but, the nullifier is only computable by the recipient, by using a PRF (PRF(sk, randomness)). That way Alice should not be able to track when Bob "forwards" her payment to someone else because she has no way to generate the nullifier.
Doing so would require quite some new stuffs in the code base however..

There are 3 problems I'm thinking of:

  1. Hiding total values, e.g. so you cannot see transfer of value on a ledger, only total input and total output from the bubble of secrecy
  2. Hiding the actors submitting the transactions, so you cannot correlate events by the same person (working on solution for this at the mo using Whisper, alternatively waiting for account abstraction)
  3. Protocol doesn't leak long-term keys of each participant in any public information

The idea is just to avoid modifying the public balances too often (if we can get rid of these -1ether on sender balance, +1ether on contract's balance during deposit, and -1 contract balance, +1 recipient balance, I think it'd be better, as we'd remove one source of leakage of information)

Yup, the forward function does this 👍 It means you don't have to bounce ether into a real account then back into the mixer.

That solves problem 1.

Moreover, looking at the ways the nullifiers are generated for now (addressReceiver || salt), when Bob calls the "forward" function to pay Charlie, his discloses the nullifier that basically leaks his identity.

This could be any key that Bob controls, not just his permanent / long-term address, as long as he can supply a signature from that address that verifies to the same address via ecrecover.

e.g. instead of supplying the nullifier (address || salt) you provide the salt and the (v,r,s) components of an ECDSA signature, then the nullifier is constructed using the address that ecrecover returns.

That kinda solves problem 3 and you end up with a coin that only the owner of that one-time-key can spend.

But what if you wanted to use denominations that aren't 1 ether? e.g. you can deposit any amount, transfer any amount to anybody, and withdraw any amount?

That would require coin splitting, and coins of arbitrary value, where the values aren't known when being transferrer around - only that the sum of (inputs-outputs) >= 0.

I think if we want to provide private transactions of arbitrary size we need to move off chain. Otherwise it will be too expensive for the majority of people to use. Since we can use snarks to do confirm multiple transfers in a single transaction. It seems like a really nice way to encourage widespread adoption of private transactions.

That is my current research goal. I think that miximus is good to provide on chain anonymous coins, id and signals. But in order to get any kind of adoption and there for reasonable anonymity set we need to move off chain.

Also sorry for my delayed response. I have just been super busy.