To achieve privacy, Tornado Cash **uses smart contracts that accept token deposits from one address and enable their withdrawal from a different address**. Those smart contracts work as pools that combine all deposited assets.
Once the funds are withdrawn by a new address from those pools, the on-chain link between the source and the destination addresses is broken through anonymity. While assets are in anonymity pool the management of are non-custodial, individuals are the only ones in the control of their assets given that sufficient operational security is maintained.
* When a user transfers assets into a pool (deposit), a private note is generated. This private note works as **a private key or secret** to access the assets
The strength of such protocol is linked directly to its amount of users and the size of its pool. The more users deposit into the pool the larger the probability of correlation. However, to ensure anonymity individuals must be conscious of:
To process a deposit a random slice of bytes is generated by the individual, it is then encrypted using [Pedersen hashing](https://iden3-docs.readthedocs.io/en/latest/iden3\_repos/research/publications/zkproof-standards-workshop-2/pedersen-hash/pedersen.html). Pedersen hashing is optimized for the arithmetic circuits for zero-knowledge proofs and maintain low transactional costs in the Ethereum virtual machine. Depositing is fulfilled through inputing the hash for insertion into the Merkle tree.
To process a withdrawal, the same area of bytes is split into two separate parts: the **secret** on one side & the **nullifier** on the other side. The nullifier is hashed. This nullifier is a public input that is sent on-chain to be checked with the smart contract & the Merkle tree data. It avoids double-spending for instance.
Thanks to zk-SNARK, it is possible to prove the 20 MiMC hash of the initial commitment and of the nullifier without revealing any information. Even if the nullifier is public, privacy is sustained as there is no way to link the hashed nullifier to the initial commitment. Besides, even if the information about the transaction is present in the Merkle root, the information about the exact Merkle path, and subsequently the location of the transaction, is still kept private.
Deposits are simple from a technical point of view, but expensive in terms of gas as they need to compute the 20 MiMC hash & update the Merkle tree. On the other hand, the withdrawal process is complex but cheaper as gas is only needed for the nullifier hash and the zero-knowledge proof.