*From Esperanto, **miksi** (miks·i): to mingle, to blend, to mix, to shuffle*
Ethereum mixer where all the computation & constructions are done offchain and then proved inside a zkSNARK to the Smart Contract (for the *deposit* and for the*withdraw*).
Ethereum mixer where all the computation & constructions are done offchain and then proved inside a zkSNARK to the smart-contract (both to *deposit* and*withdraw*).
This means that the client builds a MerkleTree and makes all the needed computation, and then generates a zk-proof where proves that all the offchain computation is done following all the rules (no leaf deletion, only one leaf addition, correct leaf format).
This allows to use only `~325.000 gas` for the *deposit*, and `~308.000 gas` for the withdraw.
The client builds a MerkleTree, carries out the required computation, and then generates a zk-proof proving that the offchain computation has been done correctly (no leaf deletion, and only one correctly formatted leaf addition).
This approach requires only `~325.000 gas` to *deposit* (compared to `~1M gas` for an onchain computation approach) , and `~308.000 gas` to *withdraw*.
These gas savings come from the fact that we don't need to carry out the MerkleTree computations onchain. Instead, we prove the correctness of these offchain computations inside the snark proof, and verify this proof onchain. It's much cheaper to verify the proof than to carry out the necessary computations onchain.
![](miksi-logo00-small.png)
**Warning:** This repository is in a very early stage. The current version works, but is not finished and there are some improvements to be added.
**Warning:** This repository is in a very early stage. The current version works, but is not finished. There are some improvements in the works.
WebApp to use miksi-core can be found at https://github.com/arnaucube/miksi-app
The WebApp to use miksi-core can be found at https://github.com/arnaucube/miksi-app
## Circuits tests
```
@ -31,40 +33,55 @@ npm run test-sc
## Spec draft
**Note:** The spec & code is a work in progress, there are some pending works & improvements planned to do, and some diagrams for better explanation.
**Note:** Both the spec and the code are works in progress. There are some pending improvements in the works, and some diagrams are needed to better explain things.
### Deposit
*All computation & constructions are done offchain and then proved inside a zkSNARK to the Smart Contract*
- user generates a random `secret`&`nullifier`
- computes the `commitment`, which is the Poseidon hash: `commitment = H(coinCode, amount, secret, nullifier)`, where:
*All computations and constructions are done offchain and then proved inside a zkSNARK to the smart-contract*
From the depositer's perspective, the interface facilitates the following flow:
1. Generate a random `secret`&`nullifier`
2. Compute the `commitment`, which is the Poseidon hash: `commitment = H(coinCode, amount, secret, nullifier)`, where:
- `coinCode`: code that specifies which currency is being used (`0`==ETH)
- `amount`: the amount to be deposited
- `secret`: random, private
- `nullifier`: random
- get all the commitments from the SmartContract
- build the MerkleTree with the getted commitments
- add the new computed `commitment` into the MerkleTree
- generate zkSNARK proof, where is proving:
- prover knows the `secret`&`nullifier` for the `commitment` which is in a leaf in the merkletree
- the transition from `RootOld` (the current one in the Smart Contract) to `RootNew` has been done following the rules (only one leaf addition, no leaf deletion, correct leaf format, etc)
- user sends ETH to the smart contract `deposit` call, together with the zkProof data
- smart contract verifies the zkProof of the deposit, and if everything is ok stores the commitment & the new root
3. Fetch all the commitments from the smart-contract
4. Build the MerkleTree with the fetched commitments
5. Add the newly computed `commitment` to the MerkleTree
6. Generate a zkSNARK proof, which proves:
- you know the `secret`&`nullifier` for the `commitment` contained in the leaf you've just added to the MerkleTree
- the transition from `RootOld` (the current one in the Smart Contract) to `RootNew` has been done following the rules (no leaf deletion, and only one correctly formatted leaf addition, etc.)
7. Send ETH to the smart-contract `deposit` call, together with the zkProof data
Deposit circuit can be found [here](https://github.com/miksi-labs/miksi-core/blob/master/circuits/deposit.circom).
Once these steps have been carried out, the smart-contract verifies the zkProof of the deposit, and if everything checks out ok, stores the commitment and the new root.
The deposit circuit can be found [here](https://github.com/miksi-labs/miksi-core/blob/master/circuits/deposit.circom).
### Withdraw
*All computation & constructions are done offchain and then proved inside a zkSNARK to the Smart Contract*
- user gets all the commitments from the SmartContract
- build the MerkleTree with the getted commitments
- generate the siblings (merkle proof) for the `commitment` of which the user knows the `secret`&`nullifier`
- generate zkSNARK proof, where is proving:
- user knows a `secret` for a public `nullifier`
- which `commitment` is in the MerkleTree
- which MerkleTree `root` is the one that knows the SmartContract
- if the zkProof verification passes, and the nullifier was not already used, the Smart Contract sends the ETH to the specified address
*As before, all computations and constructions are done offchain and then proved inside a zkSNARK to the Smart Contract*
From the withdrawer's perspective, the interface facilitates the following flow:
1. Fetch all the commitments from the smart-contract
2. Build the MerkleTree with the fetched commitments
3. Generate the siblings (merkle proof) for the `commitment` whose `secret`&`nullifier` you know
4. Generate a zkSNARK proof, which proves:
- you know a `secret` for a `nullifier` you reveal, whose `commitment` is in a MerkleTree with `root` matching the one stored in the smart-contract
If the zkProof verification passes, and the nullifier has not already been used, the smart-contract sends the ETH to the specified address.
Withdraw circuit can be found [here](https://github.com/miksi-labs/miksi-core/blob/master/circuits/withdraw.circom).
The withdraw circuit can be found [here](https://github.com/miksi-labs/miksi-core/blob/master/circuits/withdraw.circom).
# Thanks
Miksi is possible thanks to [circom](https://github.com/iden3/circom), [circomlib](https://github.com/iden3/circomlib), [wasmsnark](https://github.com/iden3/wasmsnark), and thanks to the ideas about offchain computation validated with a zkSNARK in the [Zexe paper](https://eprint.iacr.org/2018/962.pdf).
Miksi is made possible thanks to [circom](https://github.com/iden3/circom), [circomlib](https://github.com/iden3/circomlib), [wasmsnark](https://github.com/iden3/wasmsnark), and the ideas developed in the [Zexe paper](https://eprint.iacr.org/2018/962.pdf).