Skip to content

Commit

Permalink
docs: add circuit and general documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
veigajoao committed Aug 30, 2023
1 parent 4b5b3e7 commit 169fe24
Show file tree
Hide file tree
Showing 33 changed files with 3,861 additions and 2,204 deletions.
2 changes: 0 additions & 2 deletions circom2/.npmrc

This file was deleted.

93 changes: 0 additions & 93 deletions circom2/README.md

This file was deleted.

File renamed without changes.
73 changes: 73 additions & 0 deletions circuits/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Opact Wallet circuits

Opact wallet is implemented using the snarkjs/circom2 stack.

The language used to create circuits is circom2. This module defines the circuits and performs unit tests for them

## Setup

To compile the circuits locally for test run:

```bash
pnpm run circuits circuit:setup
```

Provide sample entropy when prompted in the terminal.
This is an unsafe setup used to test the circuit in local instances.

To run unit tests:
```bash
pnpm run circuits circuit:tests
```

## Circuit Logic

### UTXOs and the Merkle Tree
The protocol is built around an UTXO model. Each UTXO is composed of the following variables:

```JSON
{
"token": "reference to the token type that the UTXO represents",
"amount": "amount of tokens in the UTXO",
"pubkey": "public key of the wallet of the owner of this UTXO",
"blinding": "randomly generated value"
}
```

The structure of the UTXOs can be found in the `circuits/utxo.circom` file.

UTXOs are stored inside a merkle tree structure. The merkle tree is composed of 2^depth leafs, each leaf is a hash of an UTXO. The merkle tree is implemented in the `circuits/lib/merkleproofposeidon.circom` file.

The merkle tree is used to store the state of the Opact Wallet. The root hash of the merkle tree is stored in the Opact Wallet smart contract and each leaf (UTXO hash) is stored as an event when it is created. The merkle tree is updated every time a user deposits or withdraws funds.

### Nullifiers
Whenever new funds are deposited to the smart contract, new UTXOs are created in the merkle tree. However, when said UTXOs are spent we cannot simply remove them from the tree - that would allow an attacker to infer the original owner of the UTXO and break the anonymity of the protocol.

We need a way to invalidate already used UTXOs without identifying them - this is achieved through nullifiers.

Nullifiers are deterministic values that are generated for each UTXO. They are generated using the Poseidon hash of the UTXO's data and the user's private key. This means that the nullifier is unique for each UTXO and each user.
```
nullifier = poseidon(poseidon(utxo), privkey)
```

Nullifiers are public parameters in the ZK circuit. When proofs are submitted to the contract, nullifiers are stored in the Opact Wallet smart contract and are used to prevent double spends of UTXOs.

### Transactions
Each transaction in the circuit is composed of a list of inputs and a list of outputs. Each input is a reference to a UTXO that is being spent and each output is a new UTXO that is being created.

The transaction is deemed valid as long as:
- All inputs being consumed belong to the user submitting the proof (checked through privkey)
- The sum of the inputs is equal to the sum of the outputs (plus value being deposited or minus value being withdrawn - referred to as `delta`)

Other business requirements are not checked in the circuit, but rather in the Opact Wallet smart contract. These include:
- Nullifiers of the inputs being spent are not already in the contract's state
- Delta value provided in the circuit is equal to value being deposited or withdrawn from Smart Contract
- `message_hash` provided in the circuit is equal to the hash of the message signed by the user when calling the contract - guarantees front runners are not tampering with the transaction

### Anti Money Laundry policy
The AML framework is enforced through the `subtree_root` and `subtree_mp_sibling`.

The subtree is an indexed Merkle Tree. It essentially mimics the UTXO merkle tree but only accepts 2 values: `accept` and `deny` (those values can be any random integer). The `subtree_root` is the root hash of the subtree and the `subtree_mp_sibling` is the list of siblings of the leaf being used in the proof.

AML providers are responsible for evaluating all deposits to the protocol and flagging any UTXOs that are deemed malicious. By default, all leafs in the subtree start out with the `accept` value. If an UTXO deposited to the contract is deemed to be malicious, its value must be changed to `deny` in the AML provider's state.
To build a proof, the user must provide a list of all UTXOs being spent in the transaction. The circuit then checks that all UTXOs being spent are not flagged as `deny` in the AML provider's state, according to the merkle root and path provided. This allow a proof that no malicious UTXO is being used in the transaction, following the AML provider's analysis.
File renamed without changes.
File renamed without changes.
File renamed without changes.
12 changes: 3 additions & 9 deletions circom2/package.json → circuits/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@hack-a-chain-software/kadena-product",
"version": "0.0.6",
"description": "A library for creating and verifying private transactions",
"name": "circuits",
"version": "0.0.1",
"description": "Circuits for the Opact Wallet project",
"main": "src/index.js",
"type": "module",
"scripts": {
Expand All @@ -25,12 +25,6 @@
"transaction",
"cryptocurrency"
],
"author": "Opact",
"license": "GPL-3.0",
"bugs": {
"url": "https://github.com/hack-a-chain-software/kadena-product/issues"
},
"homepage": "https://github.com/hack-a-chain-software/kadena-product#readme",
"dependencies": {
"assert": "^2.0.0",
"big-integer": "^1.6.51",
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
110 changes: 110 additions & 0 deletions media/circuit-aml-centralized.drawio
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<mxfile host="65bd71144e">
<diagram id="qsroIx07bEIxPQEreMCd" name="Page-1">
<mxGraphModel dx="1302" dy="1607" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0"/>
<mxCell id="1" parent="0"/>
<mxCell id="31" value="" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=none;" parent="1" vertex="1">
<mxGeometry y="-50" width="960" height="540" as="geometry"/>
</mxCell>
<mxCell id="7" style="edgeStyle=none;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="3" target="6" edge="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="12" value="Deposit Transaction" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="7" vertex="1" connectable="0">
<mxGeometry x="-0.2997" y="-3" relative="1" as="geometry">
<mxPoint x="10" as="offset"/>
</mxGeometry>
</mxCell>
<mxCell id="3" value="User 1" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;" parent="1" vertex="1">
<mxGeometry x="50" y="80" width="30" height="60" as="geometry"/>
</mxCell>
<mxCell id="8" style="edgeStyle=none;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="4" target="6" edge="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="10" value="Deposit Transaction" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="8" vertex="1" connectable="0">
<mxGeometry x="-0.2851" y="2" relative="1" as="geometry">
<mxPoint as="offset"/>
</mxGeometry>
</mxCell>
<mxCell id="4" value="User 2" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;" parent="1" vertex="1">
<mxGeometry x="50" y="180" width="30" height="60" as="geometry"/>
</mxCell>
<mxCell id="9" style="edgeStyle=none;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="5" target="6" edge="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="11" value="Deposit Transaction" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9" vertex="1" connectable="0">
<mxGeometry x="-0.187" y="-1" relative="1" as="geometry">
<mxPoint as="offset"/>
</mxGeometry>
</mxCell>
<mxCell id="5" value="User 3" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;" parent="1" vertex="1">
<mxGeometry x="50" y="290" width="30" height="60" as="geometry"/>
</mxCell>
<mxCell id="6" value="Opact Wallet&lt;br style=&quot;font-size: 14px;&quot;&gt;Contract" style="rounded=1;whiteSpace=wrap;html=1;fontSize=14;fontStyle=1" parent="1" vertex="1">
<mxGeometry x="340" y="190" width="120" height="60" as="geometry"/>
</mxCell>
<mxCell id="18" style="edgeStyle=none;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="1" source="13" target="6" edge="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="19" value="2. Flagged transactions are added to a list kept in the&lt;br&gt;contract's state" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="18" vertex="1" connectable="0">
<mxGeometry x="-0.1249" y="1" relative="1" as="geometry">
<mxPoint x="101" y="-39" as="offset"/>
</mxGeometry>
</mxCell>
<mxCell id="13" value="AML Provider" style="shape=hexagon;perimeter=hexagonPerimeter2;whiteSpace=wrap;html=1;fixedSize=1;fontStyle=1" parent="1" vertex="1">
<mxGeometry x="340" y="390" width="120" height="80" as="geometry"/>
</mxCell>
<mxCell id="15" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 3;strokeWidth=2;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="230" y="110" as="sourcePoint"/>
<mxPoint x="360" y="390" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="14" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 3;strokeWidth=2;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="30" y="250" as="sourcePoint"/>
<mxPoint x="340" y="430" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="16" value="1. AML Provider Analyses all deposit transactions and the accounts&lt;br&gt;they came from. If they deem a transaction to have risk of being&lt;br&gt;money laundry it is flagged" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="14" vertex="1" connectable="0">
<mxGeometry x="0.2651" relative="1" as="geometry">
<mxPoint x="64" y="-14" as="offset"/>
</mxGeometry>
</mxCell>
<mxCell id="21" style="edgeStyle=none;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="20" target="6" edge="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="23" value="3. Honest user N utilizes the official Flagged Transactions&lt;br&gt;List fetched from the contract to build their Zero-Knowledge proofs to&lt;br&gt;&amp;nbsp;withdraw funds. This transaction is accepted by the contract." style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="21" vertex="1" connectable="0">
<mxGeometry x="0.2158" y="-3" relative="1" as="geometry">
<mxPoint x="199" y="-25" as="offset"/>
</mxGeometry>
</mxCell>
<mxCell id="20" value="User N" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;" parent="1" vertex="1">
<mxGeometry x="665" y="240" width="30" height="60" as="geometry"/>
</mxCell>
<mxCell id="27" style="edgeStyle=none;html=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="24" target="6" edge="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="29" value="4. Malicious user M uses invalid list to build&amp;nbsp;their Zero&lt;br&gt;&amp;nbsp;Knowledge proof. This transaction is denied by the contract" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="27" vertex="1" connectable="0">
<mxGeometry x="-0.2508" y="1" relative="1" as="geometry">
<mxPoint x="-99" y="-39" as="offset"/>
</mxGeometry>
</mxCell>
<mxCell id="24" value="User M" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;" parent="1" vertex="1">
<mxGeometry x="665" y="50" width="30" height="60" as="geometry"/>
</mxCell>
<mxCell id="28" style="edgeStyle=none;html=1;" parent="1" source="26" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="700" y="80" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="26" value="Fake Flagged Transactions List" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="800" y="50" width="120" height="60" as="geometry"/>
</mxCell>
<mxCell id="30" value="&lt;h1&gt;Centralized AML Provider&lt;/h1&gt;&lt;p&gt;In this model, the smart contract does enforces a specific flagged transactions list that is stored on chain. Funds that have been flagged may be locked in the contract.&lt;/p&gt;" style="text;html=1;strokeColor=none;fillColor=none;spacing=5;spacingTop=-20;whiteSpace=wrap;overflow=hidden;rounded=0;" parent="1" vertex="1">
<mxGeometry y="-50" width="360" height="120" as="geometry"/>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
Binary file added media/circuit-aml-centralized.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 169fe24

Please sign in to comment.