general updates
This commit is contained in:
parent
5a4eccba86
commit
9a91dcbbe4
21 changed files with 138 additions and 184 deletions
|
@ -1,8 +1,8 @@
|
|||
# Anonymity Mining
|
||||
# Anonymity mining
|
||||
|
||||
The anonymity mining protocol underpins the [Anonymity Mining Program](../../anonymity-mining.md), which rewards users according to the block duration that they wait before withdrawing their deposits.
|
||||
The anonymity mining protocol underpins the [Anonymity Mining Program](../../general/token/anonymity-mining.md), which rewards users according to the block duration that they wait before withdrawing their deposits.
|
||||
|
||||
Anonymity Mining uses a Tornado Trees contract as a ZK-efficient register of deposit and withdrawal transactions, which enables users to make efficient proofs regarding their usage.
|
||||
Anonymity Mining uses a Tornado trees contract as a ZK-efficient register of deposit and withdrawal transactions, which enables users to make efficient proofs regarding their usage.
|
||||
|
||||
[tornado-trees.md](tornado-trees.md)
|
||||
|
||||
|
|
|
@ -1,23 +1,16 @@
|
|||
---
|
||||
description: >-
|
||||
Anonymity Mining rewards are claimed using ZK proofs showing the block
|
||||
duration that notes were left deposited. Anonymity Points are kept in shielded
|
||||
accounts until swapped for TORN.
|
||||
---
|
||||
# Reward claim
|
||||
|
||||
# Reward Claim
|
||||
|
||||
## Account Tree
|
||||
## Account tsree
|
||||
|
||||
Anonymity Points claimed as rewards for anonymity mining are stored in "shielded" accounts within a Merkle Tree, using many of the same patterns as in the core deposit contract and Tornado Trees.
|
||||
|
||||
### Shielded Balance
|
||||
### Shielded balance
|
||||
|
||||
The special property that the accounts tree brings to the table is that only the owner of the account knows its balance. Each time that an account's balance is updated by claiming additional rewards, or withdrawing from it, a new account is created, and the old account is nullified.
|
||||
|
||||
The balance of an account is stored as a component of the commitment hash that is inserted into the tree. The balance of an account can only by known by having the private key used to produce an encrypted backup of its commitment inputs.
|
||||
|
||||
### Account Commitment
|
||||
### Account commitment
|
||||
|
||||
An account commitment consists of three components:
|
||||
|
||||
|
@ -27,9 +20,9 @@ An account commitment consists of three components:
|
|||
|
||||
An account commitment hash is the Poseidon hash of these three components
|
||||
|
||||
## Claiming a Reward
|
||||
## Claiming a reward
|
||||
|
||||
### Inputs to a Reward Proof
|
||||
### Inputs to a reward proof
|
||||
|
||||
#### The total set of public inputs for a reward proof are:
|
||||
|
||||
|
@ -64,7 +57,7 @@ An account commitment hash is the Poseidon hash of these three components
|
|||
14. The path indices to the withdrawal in the Tornado Trees withdrawal tree, as an integer, left-padded with zeroes
|
||||
15. An array of path elements to the withdrawal in the Tornado Trees withdrawal tree
|
||||
|
||||
### Proven Claims
|
||||
### Proven claims
|
||||
|
||||
Rewards are claimed by proving that:
|
||||
|
||||
|
@ -74,13 +67,13 @@ Rewards are claimed by proving that:
|
|||
4. The amount you're claiming is then a multiple of the agreed-upon reward rate, times the specified block duration
|
||||
5. The disclosed "reward nullifier" is the Poseidon hash of the original note nullifier
|
||||
|
||||
### Sanity Checks
|
||||
### Sanity checks
|
||||
|
||||
An invariant constraint is first created showing that the amount that is coming from an existing account, plus the block reward rate times the block duration, is equal to the new account's balance plus the relayer fee.
|
||||
|
||||
An overflow check is then performed on the input, output, and block duration values to ensure that they fit within 248 bits, 248 bits, and 32 bits, respectively, without overflowing.
|
||||
|
||||
### Input Account Validation
|
||||
### Input account validation
|
||||
|
||||
The input account balance, secret, and nullifier are hashed to obtain the input account commitment, and then the path elements and path indices are used to verify that such a commitment exists within the specified input root, but in such a way that if the input account balance is 0, the check passes regardless.
|
||||
|
||||
|
@ -88,13 +81,13 @@ This scheme allows for new accounts to be created without publicly disclosing th
|
|||
|
||||
The public input nullifier hash is checked against the input account's nullifier component.
|
||||
|
||||
### Output Account Validation
|
||||
### Output account validation
|
||||
|
||||
The output account balance, secret, and nullifier are hashed to obtain the output account commitment, and are checked against the public output commitment hash.
|
||||
|
||||
The account tree update is validated using the input root, output root, output commitment as a new leaf, and the specified output path elements and indices.
|
||||
|
||||
### Tornado Trees Validation
|
||||
### Tornado trees validation
|
||||
|
||||
The Tornado Commitment used for the note being claimed is computed using the note secret and nullifier, and then the corresponding commitment in the Tornado Trees deposit tree is computed using the Tornado instance address, note commitment, and deposit block number as components.
|
||||
|
||||
|
@ -102,15 +95,15 @@ The deposit commitment is then verified to exist at the specified deposit path b
|
|||
|
||||
The withdrawal commitment in the Tornado Trees withdrawal tree is then computed using the Tornado instance address, note nullifier hash, and withdrawal block number as components. The withdrawal commitment is verified to exist at the specified withdrawal path beneat the withdrawal tree root.
|
||||
|
||||
### Reward Nullifier
|
||||
### Reward nullifier
|
||||
|
||||
The reward nullifier for the provided note is then computed by generating the Poseidon hash of the note's nullifier. This is compared to the reward nullifier specified as a public input.
|
||||
|
||||
### Args Hash Square
|
||||
### Args hash square
|
||||
|
||||
As a last step, the args hash is squared into a public output, to ensure that the reward transaction parameters cannot be tampered with relative to the proof.
|
||||
|
||||
## Completing the Reward Transaction
|
||||
## Completing the reward transaction
|
||||
|
||||
Using the generated proof, we can now call the `reward` method of the Miner contract.
|
||||
|
||||
|
@ -133,7 +126,7 @@ If these preconditions are met, then:
|
|||
4. If applicable, the relayer is rewarded TORN using the fee AP at the current AMM rate
|
||||
5. A New Account event is emitted
|
||||
|
||||
#### Batch Rewards
|
||||
#### Batch bewards
|
||||
|
||||
There is an alternate method in the Miner contract which deals with "batch rewards". While most transactions claim rewards individually, batch reward transactions claim multiple rewards at once. This avoids having to wait for the next block for each reward claim, since each claim has to insert a new leaf from the last account root.
|
||||
|
||||
|
|
|
@ -1,19 +1,12 @@
|
|||
---
|
||||
description: >-
|
||||
The Tornado Trees contract and circuit acts as an ZK-efficient register of
|
||||
deposit and withdrawal transactions that the Anonymity Mining functions can
|
||||
use to validate claims made by users about their
|
||||
---
|
||||
# Tornado trees
|
||||
|
||||
# Tornado Trees
|
||||
|
||||
## Tornado Proxy
|
||||
## Tornado proxy
|
||||
|
||||
When accessing the Tornado.cash deposit contracts using the official UI, all transactions execute through a proxy contract called the [Tornado Proxy](https://github.com/tornadocash/tornado-trees/blob/master/contracts/TornadoTrees.sol). Since the deposit contracts themselves are immutable, and many features of Tornado.cash were added well after the original deposit contracts were deployed, the Tornado Proxy provides a way to inject additional functionality without replacing the battle-tested deposit contract instances.
|
||||
|
||||
The two most noteworthy functions of the Tornado Proxy are its ability to back up user deposits on-chain using encrypted note accounts, and the function which queues deposits and withdrawals for processing in the Tornado Trees contract.
|
||||
|
||||
### Registering Deposits and Withdrawals
|
||||
### Registering deposits and withdrawals
|
||||
|
||||
When you make a deposit through the Tornado Proxy, and when you later make a withdrawal through the same, the proxy calls corresponding methods on the [Tornado Trees](https://github.com/tornadocash/tornado-trees/blob/master/contracts/TornadoTrees.sol) contract.
|
||||
|
||||
|
@ -23,7 +16,7 @@ Registering a withdrawal is the essentially the same as registering a deposit, e
|
|||
|
||||
The `registerDeposit` and `registerWithdrawal` contract methods of the Tornado Trees contract each emit a corresponding event, `DepositData` and `WithdrawalData` containing the same values as were included in the computed hash, plus an additional event field indication the order in which they entered into the queue.
|
||||
|
||||
## Chunked Merkle Tree Update
|
||||
## Chunked Merkle Tree update
|
||||
|
||||
Standard Merkle Trees are fairly expensive to store and update, especially if you want to commit to a large number of leaves. Depositing a note into the Tornado.cash deposit contracts can cost upwards of 1.2M gas, which can be hundreds of dollars worth of ETH if depositing on Ethereum mainnet. Most of this gas cost results from simply inserting a commitment into the deposit contract Merkle Tree.
|
||||
|
||||
|
@ -31,7 +24,7 @@ What if, instead of spending all of that gas, we could instead simply propose a
|
|||
|
||||
However, verifying Zero Knowledge proofs is itself quite expensive. So, instead of updating the Merkle Tree for every change, we can batch insertions together into aggregate commitments which can be verified as a whole.
|
||||
|
||||
### Chunked Tree Structure
|
||||
### Chunked tree structure
|
||||
|
||||
The deposit and withdrawal trees are both fixed-size Merkle Trees 20 levels deep, but with a notable feature. The "chunk size" of the tree determines a level at which updates are computed in aggregate, instead of as individual insertions.
|
||||
|
||||
|
@ -39,13 +32,13 @@ In the case of Tornado Trees, the chunk size is 256 (2^8), so each chunk is 8 le
|
|||
|
||||
The hash function used to produce node labels is [Poseidon](https://www.poseidon-hash.info), which is similar to the [Pedersen](https://iden3-docs.readthedocs.io/en/latest/iden3\_repos/research/publications/zkproof-standards-workshop-2/pedersen-hash/pedersen.html) hash function used in the core deposit contract, in that it's an elliptic curve hashing algorithm. The major difference between the two is that Poseidon operates over the BN128 elliptic curve instead of Baby Jubjub, and where Pedersen uses 1.7 constraints per bit in a ZK proof, Poseidon only uses between 0.2 and 0.45 constraints per bit.
|
||||
|
||||
### Collecting the Events
|
||||
### Collecting the events
|
||||
|
||||
In order to compute an update to the tree, it's necessary to know the existing structure of the tree. To obtain this, you query from the contract logs the `DepositData` or `WithdrawalData` events emitted earlier, depending on which tree you're updating.
|
||||
|
||||
Using the index indicated by `lastProcessedDepositLeaf` or `lastProcessedWithdrawalLeaf`, you can then split the events into two sets of leaves - "committed" and "pending". As the names would imply, the former set of leaves are the ones that are already committed within the Merkle Tree, and the latter are all of the leaves which still need to be inserted.
|
||||
|
||||
### Computing a Tree Update
|
||||
### Computing a tree update
|
||||
|
||||
Using the committed events, we're able to reconstruct the current state of Merkle Tree by first computing the Poseidon hash for each of the existing leaves, using the Tornado instance address, commitment/nullifier hash, and block number as the inputs to the hashing algorithm.
|
||||
|
||||
|
@ -57,7 +50,7 @@ Now that we have the "old root", we can proceed to take a chunk of pending event
|
|||
|
||||
Next, we need to collect a list of path elements starting from the subtree leaf, as well as an array of `0/1` bits indicating whether each path element is to the left or right of its parent node.
|
||||
|
||||
### Computing the Args Hash
|
||||
### Computing the args hash
|
||||
|
||||
The last thing that we need before we can compute a proof is a hashed list of arguments that we'll be passing into our proving circuit, with a very particular structure.
|
||||
|
||||
|
@ -73,9 +66,9 @@ Construct a message that is the concatenation of these fields:
|
|||
|
||||
Compute the SHA-256 hash of this message, and then modulus the hash against the BN128 group modulus found in the `SNARK_FIELD` constant of the Tornado Trees contract.
|
||||
|
||||
## Generating a Merkle Tree Update Witness
|
||||
## Generating a Merkle Tree update witness
|
||||
|
||||
### Inputs to a Tree Update Witness
|
||||
### Inputs to a tree update witness
|
||||
|
||||
The [Batch Tree Update](https://github.com/tornadocash/tornado-trees/blob/master/circuits/BatchTreeUpdate.circom) circuit takes a single public input, which is the resulting SHA-256 args hash in the BN128 field.
|
||||
|
||||
|
@ -90,25 +83,25 @@ The additional private inputs for a Tree Update witness are:
|
|||
2. An array of Tornado instance addresses
|
||||
3. An array of block numbers
|
||||
|
||||
### Proven Claim
|
||||
### Prove claim
|
||||
|
||||
To prove that we have updated the tree correctly, we don't have to provide a proof that spans the entire tree. Instead, we can prove just that a subtree of the 8-level chunk size, with a list of specified leaves, was added in place of the left-most zero leaf of a 12-level tree.
|
||||
|
||||
### Proving the Args Hash
|
||||
### Proving the args hash
|
||||
|
||||
Instead of specifying all of the inputs publicly, we can take the Args Hash that we computed earlier and compare it to the result of computing the same hash within the ZK circuit, using the private inputs. This makes for a much more efficient proof verification execution.
|
||||
|
||||
### Build the Subtree
|
||||
### Build the subtree
|
||||
|
||||
Taking the three fields of each pending event in the order (instance, commitment/nullifier, block number), we compute the Poseidon hash of each leaf. We then construct the Merkle Tree just for the subtree that we're updating. Since the subtree is full, we don't need to worry about any zero leaves.
|
||||
|
||||
### Verify the Subtree Insertion
|
||||
### Verify the subtree insertion
|
||||
|
||||
Lastly, we verify that inserting the subtree root at the proposed position results in the old root transforming to the new root. This works essentially the same way as for the [Merkle Tree Check](../core-deposit-circuit.md#computing-the-witness) in the core deposit circuit, except using Poseidon instead of MiMC.
|
||||
|
||||
The [Merkle Tree Updater](https://github.com/tornadocash/tornado-trees/blob/master/circuits/MerkleTreeUpdater.circom) first verifies that the specified path contains a zero leaf by computing what the root would be given the path elements, path indices, and a zero leaf. It compares this against the specified old root, and then repeats that process again with the proposed subtree leaf, comparing the resulting root to the new root.
|
||||
|
||||
## Completing the Tree Update
|
||||
## Completing the tree update
|
||||
|
||||
With the witness generated, and the proof generated from it, we can now call the corresponding `updateDepositTree` or `updateWithdrawalTree` method on the Tornado Trees contract.
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue