diff --git a/docs/00-intro.md b/docs/00-intro.md new file mode 100644 index 0000000..8a81b94 --- /dev/null +++ b/docs/00-intro.md @@ -0,0 +1,10 @@ +# Welcome + +ZeroPool is multi-blockchain privacy engine, providing anonymous account based transactions for blockchains. + +Contents: + +- [ZeroPool](./zeropool/) section describes the smart-contract itself. + It starts from high-level, beginner-friendly overview and then proceeds into the technical details. + +- [Fawkes-crypto](./fawkes-crypto/) section describes Rust EDSL we implemented for describing zkSNARK circuits. diff --git a/docs/01-zeropool/01-background.md b/docs/01-zeropool/01-background.md new file mode 100644 index 0000000..1defd09 --- /dev/null +++ b/docs/01-zeropool/01-background.md @@ -0,0 +1,77 @@ +# Background + +Here, we briefly overview the main cryptographic primitives ZeroPool is built +with. + +## zkSNARK + +We use zkSNARKs to enable a smart contract verify conditions on secret +user-supplied data without seeing it. + +See [docs for fawkes-crypto library](/docs/fawkes-crypto/background) for a +high-level overview of what zkSNARKs can do. + +## Merkle Tree + +Merkle tree is a mechanism for cryptographically commiting to some values. It +allows efficiently revealing part of the commited values, and recalculating the +commitment when the values change. + +Leaves in a Merkle tree contain hashes of the commited values $v_0$ … +$v_{n-1}$. And each inner (that is, non-leaf) node contains the hash of its two +children. + +![Merkle tree illustration](diagrams/merkle-tree-illustration.png) + +Let's look at the illustration of Merkle tree above (real hash values will be +much longer, this is only an illustration). Suppose you know that the hash of +the root `3cf03f`, but you don't know the whole tree. + + - If I give you a **path** to the green leaf `6631e5` (path being the sequence + "left, right, right" that leads to that leaf from the root through the + green nodes), as well as the hashes of all the nodes (highlighted in green + and light yellow), you can verify that the leaf is indeed holding the + value `6631e5`. You do that by recalculating the hashes of all the nodes + along the path and, finally, verifying that the path starts with the + expected root hash. Note that you needed to see only $O(\log n)$ hash values + to verify this, and you didn't have to know all $O(n)$ tree nodes for this. + + The path (sequence of left-right turns) to a node in a Merkle tree together + with the hash values of the nodes encountered on the way is called **Merkle + proof** for that node. Merkle proof is well-defined for all nodes in the + tree, not only leaves. + + - If you're holding the root of a Merkle tree (call this "old tree"), and I + want to change exactly one leaf in it (producing "new tree"), I can show you + + 1. the Merkle proof of the leaf in the old tree, + 2. the hash of the new tree's root, + 3. the Merkle proof of the leaf in the new tree; + + using this information you can verify that the proofs are correct, and check + that the unmodified nodes (yellow on the picture) are the same in both + proofs (ensuring that exactly one leaf was modified). + + This also works with non-leaf nodes. In this case, the modification replaces + the subtree rooted in the corresponding inner node. + + - If you encode each "left" turn on the path from root to a leaf as 0, and + each "right" turn as 1, and compile them into a binary number, that will + yield the **number** (or **index**) of a leaf (counting left to right). + + For example, the left-most leaf on the illustration above will have path $0, + 0, 0$ and number $000_2 = 0$; its closest neighbor on the right is $001_2 = + 1$ and so on. + +The naive way of proving the value of a leaf in Merkle tree discloses location +of that leaf, as well as the hash of the result. The same goes for modifying +a leaf — verifier who is checking the proofs gets to see which leaf was +modified. + +With zkSNARKs we can overcome this and perform both operations privately. A +Verifier (for example, a smart-contract) can hold the root of a Merkle tree and +allow users to replace it with a new value, only if the user supplies a zkSNARK +proof that modifications satisfy some criteria (for example, that only one leaf +whose index is within a certain range was modified). We can prove Merkle proofs +within a zkSNARK proof keeping them private and having Verifier store only the +root hash of a (potentially huge) Merkle tree. diff --git a/docs/01-zeropool/02-overview.md b/docs/01-zeropool/02-overview.md new file mode 100644 index 0000000..f2a0203 --- /dev/null +++ b/docs/01-zeropool/02-overview.md @@ -0,0 +1,66 @@ +# Functionality + +Every user in ZeroPool is associated with her private spending key +$\sigma$. + +ZeroPool maintains a set of accounts and notes. Each account and each note +stores some amount of tokens specified by its balance. Each note belongs to +some account. A user Alice who owns an account can join a note which belongs +to this account (destroying the note and and transferring its balance to +the account), or create a new note (transferring some of account balance to +it). She may choose to make the created note owned by a different account, say, +Bob's — which Bob can later join with his account. This way, accounts store the +balance of users and notes enable that balance to be fragmented and transferred +between accounts. + +In other words, ZeroPool provides the following actions to a user Alice: + + - Creating a private ZeroPool account for spending key $\sigma$ chosen + randomly by her. + + - Depositing tokens to a ZeroPool account $\sigma$ from a public account (on + the underlying blockchain). + + - Creating notes that belong to another user Bob's account, and topping them + up with tokens from Alice's account $\sigma$. + + - Joining the notes that belong to her account with it. + + - Withdrawing the tokens from her ZeroPool account $\sigma$ back to a public + account (on the underlying blockchain). + +In order to keep the action that Alice performs secret, we implement all five +using one single transaction type. Let $\sigma$ be Alice's spending key. Then +one ZeroPool transaction does the following: + +1. consumes the existing account associated with spending key $\sigma$ and + `INPUT` number of notes belonging to it, + +2. creates a new account associated with $\sigma$ and `OUTPUT` number of notes + which may belong to any (potentially different) accounts. + +The consumed account and notes are called “input”, while the produced ones are +called “output” of the transaction. So the transaction always “overwrites” one +(input) account of the user with a new (output) one, optionally joining or +creating some notes in the process. In case input account equals to the special +zero value, the transaction will assume that output account is to be created +and initialized with zero balance. From this moment on, it can be used as input +to future transactions. + +The transaction keeps private the account that was created or modified by the +transaction, as well as balances of all involved notes. We fix the numbers +of `INPUT` and `OUTPUT` notes to prevent leaking the actual number of notes +used. If the user wants to use less than `INPUT` or `OUTPUT` notes, she can pad +her desired note lists with special dummy zero values — the transaction will +recognize them and understand that they shouldn't be used. + +The transaction reveals the difference between the total balance of input +account and its notes on one hand, and output account and notes on the other +hand. If the difference is negative (output is greater than input), this means +that the total number of tokens in the ZeroPool is going up and therefore the +transaction will expect the user to deposit the correct number of tokens to the +smart contract's public account (on the underlying blockchain). Symmetrically, +if the difference is positive, ZeroPool will allow the user to withdraw the +said difference of tokens from the smart-contract's account to a user specified +account. When the difference is zero, it means that the net balance of ZeroPool +hasn't changed and the transaction was only moving tokens within ZeroPool. diff --git a/docs/01-zeropool/03-transaction.md b/docs/01-zeropool/03-transaction.md new file mode 100644 index 0000000..ff257ef --- /dev/null +++ b/docs/01-zeropool/03-transaction.md @@ -0,0 +1,422 @@ +# Transaction Overview + +On this page we overview different pieces of data that are involved in a +transaction, and the invariant conditions on that data that the transactions +maintain. + +As mentioned in [Overview](overview), ZeroPool encodes all possible actions a +user may want to perform on the pool with a single transaction type. A ZeroPool +transaction consumes one account (associated with user's spending key $\sigma$) +and `INPUT` number of notes that belong to this account. In their place, it +creates a new account (associated with the same spending key $\sigma$ as the +old one) and `OUTPUT` number of new notes. The created new notes may belong to +accounts of other users (with keys different from $\sigma$). Consumed account +and notes can not be used again. + +:::tip + +Since the consumed and newly created account have the same associated +key $\sigma$ and belong to the same user, one can also view them as two +instantiations of the same account, and transaction as modifying this account: +creating a copy with some fields modified, invalidating the old version and +marking the new one as current. + +::: + +## Keys + +The spending key $\sigma$ is the main key that controls the account and from +which all the other keys — private and public — are derived. The following +diagram shows the keys ZeroPool uses and the dependencies between them. We +use straight arrows for deterministic mappings (which always produce the same +value) and snake-shaped arrows for randomized mappings (that can be run with +the same input many times and produce different random output each time). + +![ZeroPool Keys Diagram](diagrams/zeropool-keys.png) + + - Spending key $\sigma$ is used to sign each transaction, which is then + verified using verifier key $A$. + + The $\sigma$ is necessary for spending ZeroPool tokens. It's supposed to + never leave user's device, and is only used to sign transactions locally. + + - Intermediate key $\eta$ identifies user's account in a transaction. User + uses $\eta$ to create transactions, and later to prove the transaction + correctness using a zkSNARK proof. In zkSNARK, $\eta$ is treated as a secret + input so proof of transaction's correctness does not reveal $\eta$. + + Compromising $\eta$ will deanonymize the user, but won't allow the tokens to + be stolen (assuming that $\sigma$ is not compromised). + + - The diversified address $(d, P_d)$ is used as anonymous address that a user + gives to others in order to receive tokens (through notes) from them. It + does not reveal the user's $\eta$, but allows the user who presents the + correct $\eta$ to claim the tokens sent to this diversified address. + + A user can generate as many diversified addresses as she wants from the + same $\eta$. If two different senders send tokens to the same diversified + address, they won't learn anything about each other's transations. + + - The receiving and outgoing keys are picked fresh for each transaction and + used by the receivers of notes to decrypt notes posted on some public medium + (**TODO: Which one? More specificity.**). + +## Sequence of Accounts and Notes + +ZeroPool organizes all accounts and notes in a long, evergrowing sequence. Each +new transaction appends one account and `OUTPUT` notes to this sequence. We +only append values to the sequence via transactions, and never delete or modify +values that were added before. + +Since every transaction creates exactly one account and `OUTPUT` notes, the +sequence will contain them exactly in this order: each $(\texttt{OUTPUT}+1)$-th +element is an account, and everything in-between is notes. + +![](diagrams/transaction-acting-on-a-list.png) + +Consider the illustration above. Accounts are drawn as boxes and notes as +circles. We chose `OUTPUT` = 3 here (in practice `OUTPUT` will be much larger), +and the white accounts and notes belong to unspecified users (different from +Alice). + +It shows how the sequence of accounts and notes changes when a transaction +happens. In this example, user Alice transfers some tokens to three other +users. Doing so, she consumers her (always unique, identified by her spending +key $\sigma$) account (first green box) and some notes (green circles), and +transfers the tokens held by these to her new account (the second green box) +and three new notes which will belong to the recepient accounts. + +The ordering of notes that Alice's transation consumes with respect to her +account is not important, i.e. the consumed notes can be located both to the +left or to the right of the account in the sequence. But with respect to each +other, the notes are always consumed in the order in which they appear in the +sequence. If you own notes X, Y, Z that go in this order and you decide to +consume only X and Z, ZeroPool will treat Y as consumed too and forever lock +the tokens it's holding. Alice's account associated with her spending key +$\sigma$ is unique, so there's only one account that can serve as input to the +transaction that Alice performs. + +:::info + +Since the ordering between accounts and notes is not important for the +transaction, logically, it may be convenient to see this sequence as two +separate sequences merged together, one for accounts and one for notes. + +::: + +### Account Structure + +An Account in ZeroPool is described by four fields: + +1. Intermediate key $\eta$ of the account's owner. +2. Spent offset $i$. +3. Balance $b$, the amount of tokens that the account holds. +4. Random salt $t$. + +The $\eta$ here binds the account to is owner. Balance $b$ tells how many +tokens the note is holding. And random salt $t$ is there just to make sure +that hash of the account doesn't reveal anything about the fields. + +The field $i$ is pointing at some position in the sequence of accounts and +notes. All the notes belonging to this account that are located to the left +of $i$ are considered joined (spent), and the ones in position $i$ and to the +right of it are available for joining. + +![Account spent offset](diagrams/account-spent-offset.png) + +The picture above illustrates the meaning of spent offset. White accounts +and notes here stand for ones that belong to users other than Alice. + +When Alice performs a transaction joining some notes, she will change the +spent offser of her account from old value $i$ to new $i'$. And during that +transaction, she can join the notes that are located between indices $i$ and +$i'$ in the sequence (thus maintaining the invariant). The current position of +Alice's account has no effect on the notes that she can join with that account, +i.e. the joined notes can go either before of after the account (green box on +the picture). + +### Note Structure + +A Note in ZeroPool is described by the following three fields: + +1. $(d, P_d)$, diversified public address this note belongs to. +2. Balance $b$. +3. Random salt $t$. + +Balance $b$ and salt $t$ here have the same meaning as in account. + +The diversified public address $(d, P_d)$ is binding a note to the account it's +owned by. The values $d$ and $P_d$ are derived from $\eta$, but don't reveal +$\eta$ itself. In order to join a note, the user must know the value $\eta$ and +the account (belonging to $\eta$) to join the note with. + +:::info + +Accounts and notes where all fields are filled with zero values are called “blank” + and have special meaning in ZeroPool. + +- Blank account is used to create new accounts: + it has $0$ balance, + no notes can be associated with it, + it has no concrete spending key + but instead can be spent multiple times with any spending key $\sigma$. + If you want to create a new account, + you "spend" the blank account with your freshly sampled key $\sigma$, + and after that you can start using your new account in future transactions. + +- Blank note means "do not use this note". + Since the number of `INPUT` and `OUTPUT` notes transaction works on is fixed + (to keep the number of actually used notes private), + we need a way to encode dummy notes that are not to be used + if the user wants to use less of them. + Blank notes that have all fields set to zero do just that. + +::: + +### Nullifiers + +Nullifiers are special hash values that are computed based on account's data + and its corresponding intermediate key $\eta$. +An account's nullifier uniquely identifies the account + — yet it doesn't reveal the data of that account or its key. + +More concretely, an account's nullifier is a hash of the account structure (all the fields in it), + account's index in the sequence, + and the intermediate key $\eta$ that the transaction is being invoked with, + +$$ +\textsf{nullifier} = H(\textsf{account}, \textsf{index}, \eta). +$$ + +When submitting a transaction, the user publishes the nullifier of the account + that serves as input to this transaction. +The ZeroPool smart-contract keeps the global (public) history of all nullifiers it had seen, + and rejects the transaction if its corresponding nullifier was already recorded. +This way, we make sure that no account can serve as input to a transaction more than once. + +Each account in the sequence has a unique index, + its concrete field values and only one intermediate key $\eta$ that it can be spent with. +Therefore, each account will have only one unique nullifier + and won't be spent more than once. +One exception to this is the special blank account. +All of its fields are zero as well as its index, + but each time it's being passed as input to a transaction, + it's allowed to be spent with a new intermediate key $\eta$. +Each such call to "spend" blank account will have a different nullifier + due to different intermediate keys $\eta$ being used. +This way, zero account can be spent by any intermediate key, + but no more than once with each key. + +Nullifier prevents double spending of accounts, + and ensures that there exists at most one unique account associated with each intermediate key $\eta$. +In the meantime, account's spent offset $i$ ensures that no note can be spent twice + — spending the note will move the spent offset of the account it belongs to, + to the right of the note forever marking it as spent. + +:::tip + +An account does not have to be "created" in order to receive notes from +others. A user can simply generate keys $\sigma$, $\eta$, $(d, P_d)$ as usual +(no interaction with blockchain needed for this), give diversified public +address $(d, P_d)$ to a friend, and have the friend create notes on this +address. Notes will be stored in the sequence even though there's no record of +the account they belong to. + +Later, the user can create an account with $\sigma$ as usual, initialize its +spent offset $i$ to 0 And start joining notes which his friend has sent him. + +::: + +## Merkle Tree Commitment + +ZeroPool smart-contract does not store the whole sequence of nodes and +accounts, but instead only holds the (publicly known) commitment to it. We +use Merkle Tree to commit to the whole sequence of accounts and notes, and +incrementally append values to it. + +Consider a Merkle Tree of height $h$. To store the sequence $s_0, s_1 \dots +s_{n-1}$ of accounts and notes in it, we assign first (going from left to +right) $n$ leaves of the tree hashes $H(s_0), H(s_1) \dots H(s_{n-1})$ and +fill the remaining $2^h - n$ leaves with zeroes. We compute the values of all +inner nodes according to the usual Merkle Tree rule. (If no transactions have +happened yet and the sequence is empty, all leaves of the Merkle Tree will be +initialized with zeroes.) + +This way, for any sequence element $s_k$, its index $k$ can be naturally +interpreted as the path to the leaf where $H(s_k)$ is stored: decompose number +$k$ into $h$ bits and treat $0$s and $1$s in it as a sequence of "left" and +"right" turns leading from the tree root to a leaf. One can also efficiently +recompute the Merkle Tree if some leaf is modified, or even multiple leaves in +bulk by updating a subtree. We've covered this in [Background](background). + +Even though Merkle Tree allows modifying any leaf (including the ones we've +assigned before), we only use this functionality to append values to the +sequence and never modify elements that were added to it before. Say, if the +Merkle Tree leaves currently currently have values + +$$ +H(s_0), H(s_1) \dots H(s_{n-1}), 0, 0 \dots 0 +$$ + +assigned to them, the only modification we will do is overwriting the $0$ in +leaf $n$ with value $H(s_{n})$. + +Using Merkle Tree commitment to implement a sequence of accounts and notes in +ZeroPool means that the total length of the sequence can never exceed $2^h$. + +## Putting Everything Together + +Here's the breakdown of who holds each piece of data described above: + + - The ZeroPool smart-contract knows: + + 1. The `root` of the Merkle tree that commits to the current sequence of + accounts and notes. + 2. The set of nullifiers published by transactions so far. + + Since the operations performed by the smart-contract are public as well as + the data they operate on, these values are also visible to all users. + + - Each ZeroPool user knows: + + 1. His spending $\sigma$, verifying $A$, intermediate $\eta$ keys. + 2. His account: its index in the sequence and all the fields ($i, b, t$). + 3. The contents of all the notes that were sent to him by other users. + +### zkSNARK Constraint system + +In order to check that transactions proposed by users are valid, and avoid +disclosing the transaction details (accounts invonved, amounts of tokens +transferred) we use zkSNARKs. In this section, we define the zkSNARK constraint +system used. + +#### Public Inputs + +1. `old_root`, the current Merkle tree root that serves at the commitment of + the accounts and notes sequence state before the transaction. +2. `new_root`, the proposed root of the Merkle tree after the transaction. +3. `nullifier`, the nullifier of transaction's input account (the one that's + being "spent" or consumed by the transaction). +4. `delta`, the difference between the amount of tokens the transaction + produces and the amount it consumes (`delta` being a nonzero value means + that this transaction either involves a deposit into ZeroPool from an + account on the underlying blockchain or a withdrawal). + +#### Secret Inputs + +1. User's verifying $A$ and intermediate $\eta$ keys. + +1. Transaction: + + 1. The values of input account and notes, $\textsf{in\_account}$ and $\textsf{in\_notes}[\textsf{INPUT}]$. + 1. Merkle proofs pointing at the hashes of input accounts + and notes in the sequence bound by `old_root` committment. + 1. The values of the output account and notes, $\textsf{out\_account}$ and $\textsf{out\_notes}[\textsf{OUTPUT}]$. + 1. Index of the left-most zero leaf in the Merkle tree + (the position from which the output account and notes will be written to the sequence). + +1. The signature of the transaction above produced using user's spending key $\sigma$. + + +:::info + +Note that the spending key $\sigma$ which is necessary to create transactions + is not part of (public or secret) inputs to zkSNARK constraint system. +This means that $\sigma$ can be stored on a separate hardware ledger (capable of signing) + providing an extra level of security in case the device that computes zkSNARK proofs is compromised. + +::: + +#### Conditions Checked + +1. Input notes are unique or blank (all fields equal zero). + Output notes are unique or blank. + +1. Keys: + + - Transaction's signature is correct (checked using verifying key $A$). + - The intermediate key $\eta$ is the one derived from $A$, + (the mapping $A \mapsto \eta$ is deterministic). + - The $\eta$ is owner of input and output accounts — + checked using $\textsf{account}.\eta$ field. + - The $\eta$ is the owner of input notes (but not necessary owner of output notes). + This is checked by looking at note's diversified address $(d, P_d)$ + and checking that it's associated with $\eta$. + +1. The public nullifier for input account is computed correctly. + +1. Inputs Merkle proofs: + + - The input account is either blank + (meaning that it's being created for the first time) + or has a valid Merkle proof showing that it's present in the sequence. + + - The input notes are either blank (unused) or have valid Merkle proofs. + +1. Spent note index only moves forward, $\textsf{in\_account}.i \leq \textsf{out\_account}.i$. + +1. The positions of all non-blank input notes in the sequence (proven by Merkle proofs above) + must be between $\textsf{in\_account}.i$ and $\textsf{out\_account}.i$. + +1. Difference between input (account and notes) balances + and output (account and notes) balances should be equal to `delta`. + +The current ZeroPool implementation splits the conditions above into two separate sets of zkSNARK constraints + called “tree circuit” and “transaction circuit”. +This is done for performance reasons, + but the result is the same as checking all the conditions in one circuit. + +### Steps to Verify a Transaction + +ZeroPool smart-contract maintans an internal state consisting of two components: + +- `root`, root of the Merkle tree containing the current sequence of accounts and notes, +- `nullifiers`, history all nullifiers that were published in the past, +- `snark_vk`, verifying key for zkSNARK proofs (initialized when ZeroPool smart-contract is deployed and never modified). + +:::note + +Since the whole set of nullifiers can get quite large, + in practice one may store only Merkle commitment to the set + and have the transaction caller prove that certain nullifier is or isn't in the set. +This way, whole state maintained by the contract will consist only of two Merkle commitments. + +To simplify the exposition, + we will treat nullifiers as a list of values and have contract manipulate it directly in this section. + +::: + +ZeroPool expects the following parameters to each transaction it receives. +Note that since all computation steps of a smart-contract are public, + these values are publicly visible. + +- `new_root` +- `nullifier` +- `snark_proof` +- `delta` +- `withdrawal_address` + +A transaction peforms the following: + +1. Check that `nullifier` is not present in saved `nullifiers` state. + +1. Retrieve `old_root` saved in the smart-contract state, and verify the `snark_proof` with + - `snark_vk` as verifying key, + - `(delta, nullifier, old_root, new_root)` as public inputs. + +1. Handle net balance change: + + - If $\textsf{delta} < 0$, + ensure that the transaction has deposited `delta` tokens to ZeroPool smart-contracts's account + (on the underlying blockchain). + + - If $\textsf{delta} > 0$ and all the checks above passed, + send `delta` amount of tokens to address `withdrawal_address`. + +1. If no error occured in the steps above, + save `new_root` as the root and append `nullifier` to the `nullifiers` + in the new state. + + diff --git a/docs/01-zeropool/04-technical/README.md b/docs/01-zeropool/04-technical/README.md new file mode 100644 index 0000000..b920487 --- /dev/null +++ b/docs/01-zeropool/04-technical/README.md @@ -0,0 +1 @@ +# Technical Description diff --git a/docs/implementation/account-and-notes/README.md b/docs/01-zeropool/04-technical/account-and-notes/README.md similarity index 100% rename from docs/implementation/account-and-notes/README.md rename to docs/01-zeropool/04-technical/account-and-notes/README.md diff --git a/docs/implementation/account-and-notes/accounts.md b/docs/01-zeropool/04-technical/account-and-notes/accounts.md similarity index 100% rename from docs/implementation/account-and-notes/accounts.md rename to docs/01-zeropool/04-technical/account-and-notes/accounts.md diff --git a/docs/implementation/account-and-notes/notes.md b/docs/01-zeropool/04-technical/account-and-notes/notes.md similarity index 100% rename from docs/implementation/account-and-notes/notes.md rename to docs/01-zeropool/04-technical/account-and-notes/notes.md diff --git a/docs/implementation/contracts-and-circuits/README.md b/docs/01-zeropool/04-technical/contracts-and-circuits/README.md similarity index 100% rename from docs/implementation/contracts-and-circuits/README.md rename to docs/01-zeropool/04-technical/contracts-and-circuits/README.md diff --git a/docs/implementation/contracts-and-circuits/evm/README.md b/docs/01-zeropool/04-technical/contracts-and-circuits/evm/README.md similarity index 100% rename from docs/implementation/contracts-and-circuits/evm/README.md rename to docs/01-zeropool/04-technical/contracts-and-circuits/evm/README.md diff --git a/docs/implementation/contracts-and-circuits/evm/operator-manager-contract/README.md b/docs/01-zeropool/04-technical/contracts-and-circuits/evm/operator-manager-contract/README.md similarity index 100% rename from docs/implementation/contracts-and-circuits/evm/operator-manager-contract/README.md rename to docs/01-zeropool/04-technical/contracts-and-circuits/evm/operator-manager-contract/README.md diff --git a/docs/implementation/contracts-and-circuits/evm/operator-manager-contract/mutable-operator-manager.md b/docs/01-zeropool/04-technical/contracts-and-circuits/evm/operator-manager-contract/mutable-operator-manager.md similarity index 100% rename from docs/implementation/contracts-and-circuits/evm/operator-manager-contract/mutable-operator-manager.md rename to docs/01-zeropool/04-technical/contracts-and-circuits/evm/operator-manager-contract/mutable-operator-manager.md diff --git a/docs/implementation/contracts-and-circuits/evm/the-pool-contract/README.md b/docs/01-zeropool/04-technical/contracts-and-circuits/evm/the-pool-contract/README.md similarity index 100% rename from docs/implementation/contracts-and-circuits/evm/the-pool-contract/README.md rename to docs/01-zeropool/04-technical/contracts-and-circuits/evm/the-pool-contract/README.md diff --git a/docs/implementation/contracts-and-circuits/evm/the-pool-contract/transaction-calldata.md b/docs/01-zeropool/04-technical/contracts-and-circuits/evm/the-pool-contract/transaction-calldata.md similarity index 100% rename from docs/implementation/contracts-and-circuits/evm/the-pool-contract/transaction-calldata.md rename to docs/01-zeropool/04-technical/contracts-and-circuits/evm/the-pool-contract/transaction-calldata.md diff --git a/docs/implementation/contracts-and-circuits/evm/token-contract.md b/docs/01-zeropool/04-technical/contracts-and-circuits/evm/token-contract.md similarity index 100% rename from docs/implementation/contracts-and-circuits/evm/token-contract.md rename to docs/01-zeropool/04-technical/contracts-and-circuits/evm/token-contract.md diff --git a/docs/implementation/contracts-and-circuits/evm/verifier-contracts.md b/docs/01-zeropool/04-technical/contracts-and-circuits/evm/verifier-contracts.md similarity index 100% rename from docs/implementation/contracts-and-circuits/evm/verifier-contracts.md rename to docs/01-zeropool/04-technical/contracts-and-circuits/evm/verifier-contracts.md diff --git a/docs/implementation/contracts-and-circuits/evm/voucher-token-contract.md b/docs/01-zeropool/04-technical/contracts-and-circuits/evm/voucher-token-contract.md similarity index 100% rename from docs/implementation/contracts-and-circuits/evm/voucher-token-contract.md rename to docs/01-zeropool/04-technical/contracts-and-circuits/evm/voucher-token-contract.md diff --git a/docs/implementation/contracts-and-circuits/substrate/README.md b/docs/01-zeropool/04-technical/contracts-and-circuits/substrate/README.md similarity index 100% rename from docs/implementation/contracts-and-circuits/substrate/README.md rename to docs/01-zeropool/04-technical/contracts-and-circuits/substrate/README.md diff --git a/docs/implementation/contracts-and-circuits/substrate/alt_bn128.md b/docs/01-zeropool/04-technical/contracts-and-circuits/substrate/alt_bn128.md similarity index 100% rename from docs/implementation/contracts-and-circuits/substrate/alt_bn128.md rename to docs/01-zeropool/04-technical/contracts-and-circuits/substrate/alt_bn128.md diff --git a/docs/implementation/contracts-and-circuits/substrate/num.md b/docs/01-zeropool/04-technical/contracts-and-circuits/substrate/num.md similarity index 100% rename from docs/implementation/contracts-and-circuits/substrate/num.md rename to docs/01-zeropool/04-technical/contracts-and-circuits/substrate/num.md diff --git a/docs/implementation/contracts-and-circuits/substrate/operator.md b/docs/01-zeropool/04-technical/contracts-and-circuits/substrate/operator.md similarity index 100% rename from docs/implementation/contracts-and-circuits/substrate/operator.md rename to docs/01-zeropool/04-technical/contracts-and-circuits/substrate/operator.md diff --git a/docs/implementation/contracts-and-circuits/substrate/pallet.md b/docs/01-zeropool/04-technical/contracts-and-circuits/substrate/pallet.md similarity index 100% rename from docs/implementation/contracts-and-circuits/substrate/pallet.md rename to docs/01-zeropool/04-technical/contracts-and-circuits/substrate/pallet.md diff --git a/docs/implementation/contracts-and-circuits/substrate/tx_decoder.md b/docs/01-zeropool/04-technical/contracts-and-circuits/substrate/tx_decoder.md similarity index 100% rename from docs/implementation/contracts-and-circuits/substrate/tx_decoder.md rename to docs/01-zeropool/04-technical/contracts-and-circuits/substrate/tx_decoder.md diff --git a/docs/implementation/contracts-and-circuits/substrate/verifier.md b/docs/01-zeropool/04-technical/contracts-and-circuits/substrate/verifier.md similarity index 100% rename from docs/implementation/contracts-and-circuits/substrate/verifier.md rename to docs/01-zeropool/04-technical/contracts-and-circuits/substrate/verifier.md diff --git a/docs/implementation/elliptic-curve-cryptography.md b/docs/01-zeropool/04-technical/elliptic-curve-cryptography.md similarity index 100% rename from docs/implementation/elliptic-curve-cryptography.md rename to docs/01-zeropool/04-technical/elliptic-curve-cryptography.md diff --git a/docs/implementation/high-level-overview.md b/docs/01-zeropool/04-technical/high-level-overview.md similarity index 100% rename from docs/implementation/high-level-overview.md rename to docs/01-zeropool/04-technical/high-level-overview.md diff --git a/docs/implementation/relayer-node/README.md b/docs/01-zeropool/04-technical/relayer-node/README.md similarity index 100% rename from docs/implementation/relayer-node/README.md rename to docs/01-zeropool/04-technical/relayer-node/README.md diff --git a/docs/implementation/relayer-node/optimistic-state.md b/docs/01-zeropool/04-technical/relayer-node/optimistic-state.md similarity index 98% rename from docs/implementation/relayer-node/optimistic-state.md rename to docs/01-zeropool/04-technical/relayer-node/optimistic-state.md index c3ec754..1a763d3 100644 --- a/docs/implementation/relayer-node/optimistic-state.md +++ b/docs/01-zeropool/04-technical/relayer-node/optimistic-state.md @@ -39,4 +39,4 @@ It is essential that whatever happens with the client application or the relayer * If ok, the updates corresponding status in the Tx Db, otherwise it launches rollback mode and marks all the later transactions ( already processed by the relayer ) as failed * The client eventually loads the updated transaction status. If the transaction was successful, then the balance is updated, otherwise the transaction is shown as failed. -![](<../../../static/img/optimistic state.png>) +![](<../../../../static/img/optimistic state.png>) diff --git a/docs/implementation/relayer-node/relayer-operations.md b/docs/01-zeropool/04-technical/relayer-node/relayer-operations.md similarity index 100% rename from docs/implementation/relayer-node/relayer-operations.md rename to docs/01-zeropool/04-technical/relayer-node/relayer-operations.md diff --git a/docs/implementation/relayer-node/rest-api.md b/docs/01-zeropool/04-technical/relayer-node/rest-api.md similarity index 100% rename from docs/implementation/relayer-node/rest-api.md rename to docs/01-zeropool/04-technical/relayer-node/rest-api.md diff --git a/docs/implementation/transaction-overview/README.md b/docs/01-zeropool/04-technical/transaction-overview/README.md similarity index 100% rename from docs/implementation/transaction-overview/README.md rename to docs/01-zeropool/04-technical/transaction-overview/README.md diff --git a/docs/implementation/transaction-overview/common-structure.md b/docs/01-zeropool/04-technical/transaction-overview/common-structure.md similarity index 100% rename from docs/implementation/transaction-overview/common-structure.md rename to docs/01-zeropool/04-technical/transaction-overview/common-structure.md diff --git a/docs/implementation/transaction-overview/signing-a-transaction.md b/docs/01-zeropool/04-technical/transaction-overview/signing-a-transaction.md similarity index 100% rename from docs/implementation/transaction-overview/signing-a-transaction.md rename to docs/01-zeropool/04-technical/transaction-overview/signing-a-transaction.md diff --git a/docs/implementation/transaction-overview/the-nullifiers.md b/docs/01-zeropool/04-technical/transaction-overview/the-nullifiers.md similarity index 100% rename from docs/implementation/transaction-overview/the-nullifiers.md rename to docs/01-zeropool/04-technical/transaction-overview/the-nullifiers.md diff --git a/docs/implementation/transaction-overview/the-transaction-lifecycle.md b/docs/01-zeropool/04-technical/transaction-overview/the-transaction-lifecycle.md similarity index 100% rename from docs/implementation/transaction-overview/the-transaction-lifecycle.md rename to docs/01-zeropool/04-technical/transaction-overview/the-transaction-lifecycle.md diff --git a/docs/implementation/transaction-overview/transaction-types.md b/docs/01-zeropool/04-technical/transaction-overview/transaction-types.md similarity index 100% rename from docs/implementation/transaction-overview/transaction-types.md rename to docs/01-zeropool/04-technical/transaction-overview/transaction-types.md diff --git a/docs/implementation/transaction-overview/untitled-1/README.md b/docs/01-zeropool/04-technical/transaction-overview/untitled-1/README.md similarity index 97% rename from docs/implementation/transaction-overview/untitled-1/README.md rename to docs/01-zeropool/04-technical/transaction-overview/untitled-1/README.md index 74924b2..847ef0b 100644 --- a/docs/implementation/transaction-overview/untitled-1/README.md +++ b/docs/01-zeropool/04-technical/transaction-overview/untitled-1/README.md @@ -12,7 +12,7 @@ The memo block contains detailed transaction data such as output notes, accounts The memo block consists of the fields below. There are two optional fields in the memo block, dependent on transaction type: `native amount` and `receiver`. These values are only included in the withdrawal transaction's memo block. -![The memo block structure](../../../../static/img/memo\_new\_eng.png) +![The memo block structure](../../../../../static/img/memo\_new\_eng.png) | Field name | Size (bytes) | Description | | ----------------------- | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | diff --git a/docs/implementation/transaction-overview/untitled-1/memo-block-encryption.md b/docs/01-zeropool/04-technical/transaction-overview/untitled-1/memo-block-encryption.md similarity index 100% rename from docs/implementation/transaction-overview/untitled-1/memo-block-encryption.md rename to docs/01-zeropool/04-technical/transaction-overview/untitled-1/memo-block-encryption.md diff --git a/docs/implementation/untitled/README.md b/docs/01-zeropool/04-technical/untitled/README.md similarity index 96% rename from docs/implementation/untitled/README.md rename to docs/01-zeropool/04-technical/untitled/README.md index d4810dc..ab1e7b1 100644 --- a/docs/implementation/untitled/README.md +++ b/docs/01-zeropool/04-technical/untitled/README.md @@ -4,7 +4,7 @@ description: The main data structure # ZeroPool Merkle Tree -![Full Merkle tree](../../../static/img/Merkle_200dpi.png) +![Full Merkle tree](../../../../static/img/Merkle_200dpi.png) The merkle tree in the ZeroPool solution is used to link and store encrypted transaction data (accounts and notes) within a strict sequence. The accounts and note hashes are placed in the tree leaves. diff --git a/docs/implementation/untitled/the-poseidon-hash.md b/docs/01-zeropool/04-technical/untitled/the-poseidon-hash.md similarity index 100% rename from docs/implementation/untitled/the-poseidon-hash.md rename to docs/01-zeropool/04-technical/untitled/the-poseidon-hash.md diff --git a/docs/implementation/zeropool-keys/README.md b/docs/01-zeropool/04-technical/zeropool-keys/README.md similarity index 97% rename from docs/implementation/zeropool-keys/README.md rename to docs/01-zeropool/04-technical/zeropool-keys/README.md index d397082..288986f 100644 --- a/docs/implementation/zeropool-keys/README.md +++ b/docs/01-zeropool/04-technical/zeropool-keys/README.md @@ -6,7 +6,7 @@ description: Different key types ZeroPool is based on complex cryptography. There are several keys needed for private transactions. The relationship between these keys is presented in the scheme below. -![](../../../static/img/keys.png) +![](../../../../static/img/keys.png) * **Spending key (**$$\sigma$$**)** is the top secret key. It is used to derive other keys and to sign transactions. At a high level it is just a random 256-bit number which should be stored securely on the client side. The simplest way to get a spending key is to produce a random number. But in a production client software implementation more complex approaches should be used (e.g. [hierarchical deterministic wallets](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki)). Concrete approaches for spending key derivation by a client are not discussed here. * **Transaction verifier key (**$$A$$**)** is used for transaction signature verification. It's derived from the spending key and multiplied by the generator point in the JubJub elliptic curve field: $$A = \sigma G$$ diff --git a/docs/implementation/zeropool-keys/address-derivation.md b/docs/01-zeropool/04-technical/zeropool-keys/address-derivation.md similarity index 100% rename from docs/implementation/zeropool-keys/address-derivation.md rename to docs/01-zeropool/04-technical/zeropool-keys/address-derivation.md diff --git a/docs/implementation/zeropool-keys/ephemeral-keys.md b/docs/01-zeropool/04-technical/zeropool-keys/ephemeral-keys.md similarity index 100% rename from docs/implementation/zeropool-keys/ephemeral-keys.md rename to docs/01-zeropool/04-technical/zeropool-keys/ephemeral-keys.md diff --git a/docs/implementation/zksnarks-and-circuits/README.md b/docs/01-zeropool/04-technical/zksnarks-and-circuits/README.md similarity index 100% rename from docs/implementation/zksnarks-and-circuits/README.md rename to docs/01-zeropool/04-technical/zksnarks-and-circuits/README.md diff --git a/docs/implementation/zksnarks-and-circuits/transaction-verifier-circuit.md b/docs/01-zeropool/04-technical/zksnarks-and-circuits/transaction-verifier-circuit.md similarity index 100% rename from docs/implementation/zksnarks-and-circuits/transaction-verifier-circuit.md rename to docs/01-zeropool/04-technical/zksnarks-and-circuits/transaction-verifier-circuit.md diff --git a/docs/01-zeropool/README.md b/docs/01-zeropool/README.md new file mode 100644 index 0000000..45e7676 --- /dev/null +++ b/docs/01-zeropool/README.md @@ -0,0 +1,22 @@ +# ZeroPool Contract + +ZeroPool is a smart-contract that implements private token transactions on +top of a public blockchain. One can deposit public tokens into their private +account inside ZeroPool, transfer them to other private accounts inside the +pool, and withdraw them back to a public account. Deposits to and withdrawals +from the pool are visible to everyone — since they alter account balances on +the underlying public blockchain — while the transactions inside the pool, as +well as the balances, and the structure of private accounts are hidden from +everyone but the corresponding account owners. + +The core tool that allows ZeroPool to provide privacy on a public blockchain is +[zkSNARK](https://en.wikipedia.org/wiki/Non-interactive_zero-knowledge_proof)s. +We use [fawkes-crypto](/docs/fawkes-crypto) EDSL library to implement our +zkSNARK constraints. + +We keep the following description high-level and omit the blockchain-specific +technicalities until the appropriate section. ZeroPool is agnostic to the +choice of the underlying blockchain, and its core engine can be augmented with +extra functionality if needed (for example, limiting the maximum transaction +amounts, verifying that transactions satisfy some extra conditions — all while +maintaining privacy). diff --git a/docs/01-zeropool/diagrams/.gitignore b/docs/01-zeropool/diagrams/.gitignore new file mode 100644 index 0000000..f3df2e9 --- /dev/null +++ b/docs/01-zeropool/diagrams/.gitignore @@ -0,0 +1,2 @@ +*/* +!*/*.tex diff --git a/docs/01-zeropool/diagrams/Makefile b/docs/01-zeropool/diagrams/Makefile new file mode 100644 index 0000000..e71b403 --- /dev/null +++ b/docs/01-zeropool/diagrams/Makefile @@ -0,0 +1,15 @@ +.PHONY: all + +all: \ + account-spent-offset.png \ + zeropool-keys.png \ + merkle-tree-illustration.png \ + transaction-acting-on-a-list.png + +.SECONDARY: + +%.png: %/main.png + cp $^ $@ + +%/main.png: %/main.tex + cd $$(dirname "$^") && lualatex --shell-escape main.tex diff --git a/docs/01-zeropool/diagrams/account-spent-offset.png b/docs/01-zeropool/diagrams/account-spent-offset.png new file mode 100644 index 0000000..bff51a7 Binary files /dev/null and b/docs/01-zeropool/diagrams/account-spent-offset.png differ diff --git a/docs/01-zeropool/diagrams/account-spent-offset/main.tex b/docs/01-zeropool/diagrams/account-spent-offset/main.tex new file mode 100644 index 0000000..a78c5b9 --- /dev/null +++ b/docs/01-zeropool/diagrams/account-spent-offset/main.tex @@ -0,0 +1,85 @@ +\documentclass[convert={outfile=\jobname.png}]{standalone} +\usepackage{varwidth} +\usepackage{tikz} +\usepackage{xcolor} +\usepackage{tikz-cd} +\usetikzlibrary{graphs,graphdrawing,arrows.meta} +\usetikzlibrary{arrows.meta, positioning, quotes, calc, backgrounds, decorations.pathreplacing} +\usetikzlibrary{patterns,patterns.meta} +\usetikzlibrary{cd} +\usetikzlibrary{fit} +\tikzset + { filled/.style={fill=white}, + account/.style={draw,rectangle,minimum size=6mm,inner sep=2mm}, + note/.style={draw,circle,minimum size=2mm}, + spentMarker/.style={pattern=north east lines,pattern color=gray}, + boxAround/.style={ + rectangle,draw,dashed,rounded corners=0.2cm,inner sep=1.9mm,outer sep=1mm, + }, + } +% \tikzcdset{column sep/normal=0.2cm} +\begin{document} + \begin{tikzcd}[ + % row sep=normal, + column sep=5mm, + ampersand replacement=\&, + nodes in empty cells, + execute at end picture={ + \begin{scope}[on background layer] + % \node[below right=2cm and 0.1cm of consumedTwo,text width=3cm] (consumedCaption) { + % Joined before, can not be spent again + % }; + % \draw[-,in=-80,out=180] (consumedCaption) to (consumedOne); + % \draw[-,in=-80,out=110] (consumedCaption) to (consumedTwo); + % \draw[-,in=-90,out=90] (consumedCaption) to (consumedThree); + \node[fit=(consumedOne),spentMarker] {}; + \node[fit=(consumedTwo),spentMarker] {}; + \node[fit=(consumedThree),spentMarker] {}; + \node[above left=2cm and 0cm of spentOffset] (spentOffsetCaption) { + $\textsf{\colorbox{green}{account}}.i$ + }; + \node[above=2cm of aliceAccount] (aliceAccountCaption) { + Alice's $\textsf{\colorbox{green}{account}}$ + }; + \draw[->,in=90,out=0] (spentOffsetCaption) to (spentOffset); + \draw[-,in=90,out=-90] (aliceAccountCaption) to (aliceAccount); + % + \node[fit=(leftInf)(consumedThree),boxAround,pin={[text width=4cm,font=\normalsize]-90:{ + Alice's notes here are already joined, and can not be spent again + }}] (boxLeft) {}; + \node[fit=(spentOffset)(rightInf),boxAround,pin={[text width=4cm,font=\normalsize]-90:{ + Alice's notes here are available for joining + }}] (boxRight) {}; + % + \node[fill=white,opacity=1,draw=white,rectangle,minimum height=1.5cm,minimum width=0.5cm,left=1mm of leftInf] () {}; + \node[fill=white,opacity=1,draw=white,rectangle,minimum height=1.5cm,minimum width=0.5cm,right=1mm of rightInf] () {}; + \end{scope} + } + ] + % |[alias=a,note]| \& + |[alias=leftInf]| \dots \& + |[account]| \& + |[note,fill=green,alias=consumedOne]| \& + |[note]| \& + |[note,fill=green,alias=consumedTwo]| \& + |[account]| \& + |[note,fill=green,alias=consumedThree]| \& + |[note,alias=spentOffset]| \& + |[note,fill=green,alias=unconsumedOne]| \& + |[account]| \& + |[note]| \& + |[note,fill=green,alias=unconsumedTwo]| \& + |[note,alias=lastTransRight]| \& + |[account,alias=aliceAccount,fill=green]| \& + |[note]| \& + |[note]| \& + |[note]| \& + |[account]| \& + |[note]| \& + |[note,fill=green]| \& + % |[note]| \& + |[alias=rightInf]| \dots \& + \\ + \end{tikzcd} + +\end{document} diff --git a/docs/01-zeropool/diagrams/merkle-tree-illustration.png b/docs/01-zeropool/diagrams/merkle-tree-illustration.png new file mode 100644 index 0000000..1e17359 Binary files /dev/null and b/docs/01-zeropool/diagrams/merkle-tree-illustration.png differ diff --git a/docs/01-zeropool/diagrams/merkle-tree-illustration/main.tex b/docs/01-zeropool/diagrams/merkle-tree-illustration/main.tex new file mode 100644 index 0000000..cda99e1 --- /dev/null +++ b/docs/01-zeropool/diagrams/merkle-tree-illustration/main.tex @@ -0,0 +1,34 @@ +\documentclass[tikz,convert={outfile=\jobname.png}]{standalone} +\usepackage{xcolor} +\usetikzlibrary{graphs,graphdrawing,arrows.meta} +\usegdlibrary{trees} +\begin{document} +\begin{tikzpicture}[ + >=Stealth, + pth/.style={draw,rectangle,fill=green}, + prf/.style={draw,rectangle,dashed,fill=yellow!20}, + every node/.style={font={\ttfamily}} +] +\graph[binary tree layout]{ + "3cf03f"[pth,pin={[pin edge={dashed}]60:{$H(\texttt{5e7bce}, \texttt{e07bbd})$}}] -> { + "5e7bce"[pth] -> { + 3d3106[prf] -> { + c52280[pin={[pin edge={dashed}]-60:{$H(v_0)$}}], + 87428f[pin={[pin edge={dashed}]-60:{$H(v_1)$}}], + }, + "e07bbd"[pth] -> { e47509[prf], "6631e5"[pth] } + }, + 7a0fde[prf,pin={[pin edge={dashed}]60:{$H(\texttt{60c4cf}, \texttt{9989b6})$}}] -> { + 60c4cf -> { + 25c725, + 026382, + }, + 9989b6[pin={[pin edge={dashed}]60:{$H(\texttt{fd954f}, \texttt{72baaf})$}}] -> { + fd954f[pin={[pin edge={dashed}]-60:{$H(v_6)$}}], + 72baaf[pin={[pin edge={dashed}]-60:{$H(v_7)$}}], + } + } + } +}; +\end{tikzpicture} +\end{document} diff --git a/docs/01-zeropool/diagrams/transaction-acting-on-a-list.png b/docs/01-zeropool/diagrams/transaction-acting-on-a-list.png new file mode 100644 index 0000000..c91263d Binary files /dev/null and b/docs/01-zeropool/diagrams/transaction-acting-on-a-list.png differ diff --git a/docs/01-zeropool/diagrams/transaction-acting-on-a-list/main.tex b/docs/01-zeropool/diagrams/transaction-acting-on-a-list/main.tex new file mode 100644 index 0000000..8d42537 --- /dev/null +++ b/docs/01-zeropool/diagrams/transaction-acting-on-a-list/main.tex @@ -0,0 +1,76 @@ +\documentclass[convert={outfile=\jobname.png}]{standalone} +\usepackage{varwidth} +\usepackage{tikz} +\usepackage{xcolor} +\usepackage{tikz-cd} +\usetikzlibrary{graphs,graphdrawing,arrows.meta} +\usetikzlibrary{arrows.meta, positioning, quotes, calc, backgrounds, decorations.pathreplacing} +\usetikzlibrary{cd} +\usetikzlibrary{fit} +\tikzset + { filled/.style={fill=white}, + account/.style={draw,rectangle,minimum size=6mm,inner sep=2mm}, + note/.style={draw,circle,minimum size=2mm}, + } +% \tikzcdset{column sep/normal=0.2cm} +\begin{document} +\begin{varwidth}{25cm} + \begin{tikzcd}[ + % row sep=normal, + column sep=4mm, + ampersand replacement=\&, + nodes in empty cells, + execute at end picture={ + \begin{scope}[on background layer] + \node[rectangle,draw,dashed,fit=(lastTransLeft)(lastTransRight),rounded corners=0.2cm,inner sep=2mm,outer sep=1pt,pin={[font=\normalsize]90:{ + Created by the transaction + }}] (createdCaption) {}; + \node[below right=3cm and 1cm of consumedThree] (consumedCaption) { + % \begin{minipage}{4cm} + % Consumed by the transaction (can't be used again) + Transaction + % \end{minipage} + }; + \draw[<-,in=-80,out=180] (consumedCaption) to (consumedOne); + \draw[<-,in=-80,out=110] (consumedCaption) to (consumedTwo); + \draw[<-,in=-90,out=90] (consumedCaption) to (consumedThree); + \draw[->,in=-90,out=0] (consumedCaption) to (createdCaption); + \node[fit=(unconsumed),pin={[font=\normalsize]110:{ + Left unconsumed + }}] () {}; + \end{scope} + } + ] + % |[alias=a,note]| \& + \dots \& + |[account]| \& + |[note,fill=green,alias=consumedOne]| \& + |[note]| \& + |[note]| \& + |[account,fill=green,alias=consumedTwo]| \& + |[note]| \& + |[note]| \& + |[note]| \& + |[account]| \& + |[note,fill=green,alias=consumedThree]| \& + |[note,fill=green,alias=unconsumed]| \& + |[note]| \& + |[account,alias=lastTransLeft,fill=green]| \& + |[note,fill=red!30]| \& + |[note,fill=yellow!30]| \& + |[note,fill=blue!30,alias=lastTransRight]| \& + \\ + \end{tikzcd} + + \noindent + \begin{minipage}{15cm} + A transaction via which \colorbox{green}{Alice} creates three new + notes for \colorbox{red!30}{Bob}, \colorbox{yellow!30}{Carol}, + \colorbox{blue!30}{Dave}. Doing that, she consumes her old account + \tikz[baseline=-0.5ex] \node[account,minimum size=2mm,fill=green] () {}; + and two (but not all) of the notes + \tikz[baseline=-0.5ex] \node[note,minimum size=2mm,fill=green] () {}; + she owned before. For this example, we use \texttt{OUTPUT} = 3. + \end{minipage} +\end{varwidth} +\end{document} diff --git a/docs/01-zeropool/diagrams/zeropool-keys.png b/docs/01-zeropool/diagrams/zeropool-keys.png new file mode 100644 index 0000000..27e5793 Binary files /dev/null and b/docs/01-zeropool/diagrams/zeropool-keys.png differ diff --git a/docs/01-zeropool/diagrams/zeropool-keys/main.tex b/docs/01-zeropool/diagrams/zeropool-keys/main.tex new file mode 100644 index 0000000..8441a1a --- /dev/null +++ b/docs/01-zeropool/diagrams/zeropool-keys/main.tex @@ -0,0 +1,60 @@ +\documentclass[convert={outfile=\jobname.png}]{standalone} +\usepackage{varwidth} +\usepackage{tikz} +\usepackage{xcolor} +\usepackage{tikz-cd} +\usetikzlibrary{graphs,graphdrawing,arrows.meta} +\usetikzlibrary{arrows.meta, positioning, quotes, calc, backgrounds, decorations.pathreplacing} +\usetikzlibrary{decorations.pathmorphing} +\usetikzlibrary{cd} +\usetikzlibrary{fit} +\tikzset + { filled/.style={fill=white}, + titledBox/.style n args = {2}{draw, semithick, dashed, rounded corners, + inner xsep=1mm, inner ysep=3mm, + % + label={[name=#1,draw, fill=white, anchor=center]above:#2} + }, + pinnedBox/.style n args = {2}{draw, semithick, dashed, rounded corners, + inner xsep=1mm, inner ysep=3mm, + % + pin={[pin distance=2cm,fill=white,anchor=center,text width=2.7cm,font=\small]#1:#2} + }, + keyNode/.style = { + text width=2.5cm, + }, + snake/.style = { + decorate,decoration={snake,amplitude=.3mm,segment length=1.3mm,post length=1mm}, + }, + } +\begin{document} +\begin{varwidth}{25cm} + \noindent + \begin{description} + \item[] \tikz \draw[->] (0,0) to (1,0); denotes a deterministic mapping + \item[] \tikz \draw[->,snake] (0,0) to (1,0); denotes a randomized mapping + \end{description} + \noindent + \begin{tikzpicture} + \node[keyNode] (spending) {Spending key $\sigma$}; + \node[keyNode,below=of spending] (verifier) {Verifier key $A$}; + \node[keyNode,below=of verifier] (interm) {Intermediate key $\eta$}; + \draw[->] (spending) to (verifier); + \draw[->] (verifier) to (interm); + + \node[keyNode,below left=2cm and 0.2cm of interm] (recieving) {Receiving key}; + \node[keyNode,below=of recieving] (outgoing) {Outgoing key}; + \draw[->,snake,out=-90,in=90] (interm) to (recieving); + \draw[->,snake] (recieving) to (outgoing); + + \node[keyNode,below right=2cm and 0.2cm of interm] (address) {Anonymous address $(d, P_d)$}; + \draw[->,snake,out=-90,in=90] (interm) to (address); + + \node[fit=(spending)(interm),pinnedBox={30}{Private, genedated once per user}] {}; + \node[fit=(recieving)(outgoing),pinnedBox={-110}{Freshly sampled for each transaction, serve as session keys}] {}; + \node[fit=(address),pinnedBox={-70}{Freshly sampled on demand, hides user's identity $\sigma$}] {}; + \end{tikzpicture} + % \begin{minipage}{15cm} + % \end{minipage} +\end{varwidth} +\end{document} diff --git a/docs/fawkes-crypto/01-background.md b/docs/02-fawkes-crypto/01-background.md similarity index 100% rename from docs/fawkes-crypto/01-background.md rename to docs/02-fawkes-crypto/01-background.md diff --git a/docs/fawkes-crypto/02-api.md b/docs/02-fawkes-crypto/02-api.md similarity index 100% rename from docs/fawkes-crypto/02-api.md rename to docs/02-fawkes-crypto/02-api.md diff --git a/docs/fawkes-crypto/03-examples.md b/docs/02-fawkes-crypto/03-examples.md similarity index 100% rename from docs/fawkes-crypto/03-examples.md rename to docs/02-fawkes-crypto/03-examples.md diff --git a/docs/fawkes-crypto/README.md b/docs/02-fawkes-crypto/README.md similarity index 100% rename from docs/fawkes-crypto/README.md rename to docs/02-fawkes-crypto/README.md diff --git a/docs/fawkes-crypto/circuit.drawio b/docs/02-fawkes-crypto/circuit.drawio similarity index 100% rename from docs/fawkes-crypto/circuit.drawio rename to docs/02-fawkes-crypto/circuit.drawio diff --git a/docs/fawkes-crypto/circuit.svg b/docs/02-fawkes-crypto/circuit.svg similarity index 100% rename from docs/fawkes-crypto/circuit.svg rename to docs/02-fawkes-crypto/circuit.svg diff --git a/docs/intro.md b/docs/intro.md deleted file mode 100644 index 870bc92..0000000 --- a/docs/intro.md +++ /dev/null @@ -1,4 +0,0 @@ -# ZeroPool - -ZeroPool is multi-blockchain privacy engine, providing anonymous account based transactions for blockchains. -