# Privacy Pools V1 Architecture Brainstorming
Hello everyone, We would like to get feedback on the architecture we think for the privacy pools v1 for the [MolochDAO Grant](https://paper.dropbox.com/doc/MGP-Privacy-Pools-v1--B52W5Y9LMNTM~IriCND_wW4JAg-Avz8gZgtlkFfvc3mfOwyd) which is basically tornado nova with [proof of innocence](https://medium.com/@chainway_xyz/introducing-proof-of-innocence-built-on-tornado-cash-7336d185cda6).
To achieve this, we believe that adding several more structures to the transactions simplifies the process without adding excessive overhead
Utxo stucture is same as Tornado Nova:
```graphviz
digraph UTXO {
node [shape=box];
commitment -> amount;
commitment -> pubkey;
commitment -> blinding;
pubkey -> privkey;
}
```
and every transaction has 2 inputs and 2 outputs
```graphviz
digraph TX {
rankdir=LR; // Set the direction from left to right
node [fontname=Monospace,fontsize=10,shape=box, width=2, height=0.5, fixedsize=true]
nullifier1 -> TX;
nullifier2 -> TX;
TX -> commitment1;
TX -> commitment2;
}
```
In order to achieve this we need to prove allowlists accordingly
```graphviz
digraph AllowLists {
rankdir=LR; // Set the direction from left to right
node [fontname=Monospace,fontsize=10,shape=box, width=2, height=0.5, fixedsize=true]
InputAllowList1 -> AllowList;
InputAllowList2 -> AllowList;
AllowList -> OutputAllowList1;
AllowList -> OutputAllowList2;
}
```
The AllowList should be a subset of OutputAllowList1 and OutputAllowList2, while InputAllowList1 and InputAllowList2 should be subsets of the AllowList.
Our privacy pool stores three main components on-chain:
- Merkle Root: merkle root of the commitments
- Transactions Root: Each transaction is hashed such as H(nullifier1, nullifier2, commitment1, commitment2) and added to the Transactions Root. This enables the proof of innocence.
- Proofs Root: this is the previous proof of innocence proofs' committed outputs. Each proof of innocence confirms that the output commitment comes from an allowlist, so we will add H(commitment, allowlist, random blinding) to the Merkle tree
Our goal is to create a recursive transaction circuit that allows both shielded transactions and private publication of the proof of innocence.
To achieve this, our circuit maintains this state:
```graphviz
digraph G {
rankdir=LR;
node [shape=box, width=3];
circuit [label="Circuit operations:\n1- Transaction\n2- Prove Innocence\n3- Reset AllowLists\n4- Remove from ALin\n5- Add to ALout", height=8];
{ rank=same; merkleRoot transactionsRoot proofsRoot ALmid ALin1 ALin2 ALout1 ALout2 toAddTransactions toAddProofs }
{ rank=same; newMerkleRoot newTransactionsRoot newProofsRoot newALmid newALin1 newALin2 newALout1 newALout2 newToAddTransactions newToAddProofs }
merkleRoot -> circuit;
transactionsRoot -> circuit ;
proofsRoot -> circuit ;
ALmid -> circuit ;
ALin1 -> circuit ;
ALin2 -> circuit ;
ALout1 -> circuit ;
ALout2 -> circuit ;
toAddTransactions -> circuit ;
toAddProofs -> circuit ;
circuit -> newMerkleRoot ;
circuit -> newTransactionsRoot ;
circuit -> newProofsRoot ;
circuit -> newALmid ;
circuit -> newALin1 ;
circuit -> newALin2 ;
circuit -> newALout1 ;
circuit -> newALout2 ;
circuit -> newToAddTransactions ;
circuit -> newToAddProofs ;
}
```
## Operations inside the circuit:
### Make Transaction
- Verify correctness of transaction inputs
- Verfiy correctness of transaction outputs
- Compute transaction hash: transactionHash <== H(nullifier1, nullifier2, commitment1, commitment2)
- newToAddTransactions <== H(toAddTransactions, transactionHash)
- Update merkleRoot with adding output commitments to the tree (To allow multiple transactions)
- Update transactionsRoot
### Prove Innocence
- Verify either commitmentIn1 is in ALin1 or H(commitmentIn1, ALin1, randIn1) is in proofs Root
- Verify either commitmentIn2 is in ALin2 or H(commitmentIn2, ALin2, randIn2) is in proofs Root
- if you want to add proofs onchain, update toAddProofs (in case you are sending some amoutns to someone shielded)
- update proofsRoot
### Update Allowlists
- reset allowlists, i.e. make ALin1, ALin2, ALmid, ALout1, ALout2 the same.
- Remove from ALin1 or ALin2 (Make a leaf zero)
- add to ALout1 or ALout2 (Add an element from merkle root to the ALout)
### Other
- The ordering of all allowlists is the same as the Merkle root, so the allowlists can be represented as a uint256[2^(MERKLE_DEPTH-8)].
- We are thinking to do IVC with Nova Folding Scheme on bn-grumpkin curve with a circom verifier
We would appreciate any feedback