Open arnaucube opened 4 years ago
This approach has a few issues:
This can be solved by introducing fallback to onchain merkle tree update in case of incorrect or empty proof, but we don't want to introduce this additional complexity. Besides, tornado v2 contracts are already immutable.
In tornado pool (v3) we already use this approach since it stores additional data in commitment and requires a snark proof on deposit anyway.
You can check out our implementation of this technique here: https://github.com/tornadocash/tornado-pool/blob/master/circuits/treeUpdater.circom
Cool! Yes:
secret
generation, is just a matter of adding the proof.I guess that is a tradeoff with a bit of more complexity, and with the extra steps to cover these cases, butgetting less gas cost in the deposit transactions.
Anyway, nice to know that those things are been taking in account, I'll take a look to Tornado Cash docs to know better how Tornado specifically works ^^
If we submit the proof for the previous user, then he will be unable to withdraw until someone deposits after him. I don't see how is it different from requiring users to submit a proof for themselves.
Let me clarify a smart contract case. Imagine for example some lottery where users submit their commitments, and then at some point the smart contract randomly chooses a winning commitment and funds it by calling deposit function (this was the first design of Thresher contract to deal with leftover change without breaking privacy). In this case the smart contract would be unable to fund the chosen commitment without someone generating and submitting a proof for merkle tree update.
Instead of doing the MerkleTree computation onchain, it can be done offchain, and proved the correctness inside a zkSNARK proof.
This means that with the current approach (MerkleTree onchain) it needs
1M gas
for the deposit, while with this new approach (MerkleTree offchain + zkproof of correctness) in the tests that I did the gast cost is arround0.3M gas
. This is thanks to the fact that the MerkleTree is moved to offchain computation and then proved its correctness inside the snark proof which is much cheaper to verify in the smart contract. (The withdraw continues very similar as it is now, as it is already with a zkproof verified in the contract).I've made a proof of concept that works here: https://github.com/arnaucube/miksi-core , that can be tried here: https://arnaucube.github.io/miksi-app/ (still needs some improvements, but it works and can be currently used in Göerli testnet).
A bit of more detailed explaination:
Deposit
All computation & constructions are done offchain and then proved inside a zkSNARK to the Smart Contract
secret
&nullifier
commitment
, which is the hash:commitment = H(secret, nullifier, extradata)
commitment
into the MerkleTreesecret
&nullifier
for thecommitment
which is in a leaf in the merkletreeRootOld
(the current one in the Smart Contract) toRootNew
has been done following the rules (only one leaf addition, no leaf deletion, correct leaf format, etc)deposit
call, together with the zkProof dataWithdraw
All computation & constructions are done offchain and then proved inside a zkSNARK to the Smart Contract
commitment
of which the user knows thesecret
&nullifier
secret
for a publicnullifier
commitment
is in the MerkleTreeroot
is the one that knows the SmartContractThe proposal would be then, to move the MerkleTree computation offchain, and instead of building the MerkleTree in Solidity, could be done in the client side, and then proved its corretness inside the zk-proof.