TL;DR
Blockchains like Bitcoin and Ethereum provide humanity with programmable digital money.
By programmable digital money, we mean that users can:
- Program what digital money represents, i.e. what store of value is assigned to which specific digital currency
- Define its properties and behavior, e.g., the rules of transmitting money, tracing it, destroying it, etc.
- Ensure that money follows the rules, properties, and behaviors that were programmed into it (without relying on a trusted third party to enforce those rules!)
{{blog_divider}}
Aztec is a privacy-first Layer 2 on Ethereum. It enables a critical dimension of programmable digital money that has heretofore been ignored: privacy.
To be more specific, Aztec is a zk-rollup providing humanity with privacy-preserving programmable digital money. Its privacy preserving properties mean that users can choose which information stays private and which information goes public, enabling use-cases such as private identity, private transactions, and private smart-contracts.
Contents
- Part 1:Introduction into privacy
- ~Do we need privacy?
- ~Do zero-knowledge proofs provide privacy by default
- ~Early years of blockchain privacy
- ~What is programmable blockchain privacy?
- Part 2: How has Aztec managed to provide privacy?
- ~Programmable composable privacy is the least we agree to
- ~Private state
- ~Composing private state and public state
- ~How Aztec smart contracts are executed
Disclaimer: this article assumes that the reader is somewhat familiar with definitions of smart contracts, circuits, Merkle Trees, UTXO, and basic understanding of how a zk-rollup works. Reading the article without a clear understanding of these definitions is not lethal but may be uncomfortable.
{{blog_divider}}
Part 1: Introduction to privacy
Do we need privacy?
Disclaimer: if you’re already an on-chain privacy maxi, feel free to skip this section.
Without privacy, every transaction is transparent. Everyone knows everything happening at all times.
Can you imagine our world with full financial transparency?
Today’s blockchain activity is transparent not only for individuals but also for governments, corporations, financial, social, and other institutions (e.g., Central Banks and insurance companies), small financial organizations (e.g., hedge funds and family offices), and literally everyone else.
Needless to say governments and institutions are loath to jump into a financial system whereby their operations are fully transparent. Where you spend your money–and how you spend it–is itself critical intellectual property (especially for financial institutions!).
The problem of transparency is not just in transparency itself but in its non-configurability.
Meaning: blockchain data is unalterably public.
For many use cases, such as personal data compliance, providing trading and financial services, and pulling off-chain assets on-chain, some data should stay public (i.e. transparent) while some data should be private.
A whole class of use-cases demands public-private flexibility:
- On-chain identity and KYC without data disclosure
- Bringing off-chain assets on-chain (e.g., property, pieces of art, and documents)
- Building small “boutique-style” financial services as an alternative to huge banks and insurance companies but operating permissionlessly and without trusted third parties
- Compliant dapps allowing privacy
- Customizable data disclosure (e.g., medical data or offering sensitive data sets for ML training.)
But what is privacy in the blockchain context? Which features and properties should it have?
Do zero knowledge proofs provide privacy?
It’s a well-known myth that zero-knowledge proofs offer privacy by default, or at least that zero-knowledge proofs make it simple to build dapps with on-chain privacy features.
The reality is that zero-knowledge proofs DO NOT provide privacy by default and it’s pretty hard in the current state of affairs to build dapps with privacy features.
What zero-knowledge proofs do
Before the advent of zero-knowledge proofs, checking that a network state transition is correct would require re-executing all network transactions and checking the results against an elected validator.
With zero-knowledge proofs, instead of re-executing all the transactions, one can simply verify a ~constant-size proof of correct computation.
Proving state transitions (as in the case of zk-rollups) or proving more general claims about arbitrary program execution has nothing to do with privacy.
More specifically zkRollups do not offer privacy by default, nor do they necessarily imply any privacy capability above and beyond public transparent blockchains.
Note: for those curious about how ZKPs work, check this Vitalik’s article and ZKP MOOC course.
Early years of blockchain privacy
You might think Ethereum already has privacy, and that would be a fair thought! There are a couple categories of existing privacy protocols worth mentioning:
- Mixnets: one or more proxy servers take in messages from multiple senders, shuffle them, and send them back out in a random order to the next destination. The next destination can be either a message receiver or another proxy server.
- “Monolithic” privacy dapps: dapps on Ethereum, privacy-specific L2s, or privacy-specific L1s allowing private transfers (i.e., the value transferred is hidden).
Nevertheless, the functionality of “monolithic” privacy-specific dapps is pretty limited. For example, private transfers are allowed only inside the specific dapp, with no cross-application composability.
That is, the dapp cannot interact with any other dapps and offers single-purpose functionality: obfuscation of simple transfers.
As we can see from these two examples, privacy alone is not enough. It must be programmable.
What is programmable blockchain privacy?
Blockchain privacy can be represented as a sum of two components:
- Data privacy: the ability of smart contracts to have private (encrypted) state owned by a user and unseen by the external world.
- Confidentiality: the ability of smart contracts to process encrypted data internally, that is, execute private functions and transactions. Confidentiality requires a private environment for the execution of sensitive operations, ensuring private information and decrypted data are not accessible to unauthorized applications.
{{blog_divider}}
Part 2: How has Aztec managed to provide privacy?
We discussed how privacy is insufficient without programmability. But even programmability is itself not very useful without composability.
Programmable composable privacy
Programmability in a blockchain context implies smart contracts.
Smart contracts are programs which execute predetermined logic automatically when some specific conditions are met. The result of every smart contract execution is stored in a blockchain’s state. Regular blockchains, where all the data is public, have public network state.
To make money programmable, composable, and privacy-preserving, we need two types of network state: public and private.
Composability for functional goals
Applications benefit from choosing to store information either in public state or private depending on their needs.
For example, imagine a privacy-preserving DEX (decentralized exchange) on Aztec network. In this context, privacy-preserving means that users can make swaps without disclosing what exactly they are swapping, in what volumes, etc. That is, let us say, asset names and transaction volumes should stay private.
However, if we make all DEX information private, users can’t know asset prices. Without knowing asset prices, they obviously can’t make any trading decisions and the DEX can’t operate. So, there is some information such as current asset prices, that we want to stay public.
Generalizing two abstracts above, one can say that we want privacy for user information but publicity for protocol information where by protocol information we mean all data that is required by the protocol to provide services successfully.
Composability for compliance goals
Applications benefit from the ability to configure compliance according to specific jurisdiction or other requirements. That is, depending on what is expected to be proven, just the required minimum of information can be disclosed while the rest is staying private.
That is, for example, users can be able to provide evidence that some specific event took place within their transaction history without disclosing any other details such as amounts, dates, addresses, etc.
To combine private and public data, applications need to manage private and public states in parallel and allow them to communicate with each other. Further in this article, we will shed the light on how Aztec makes it possible.
Private state
Aztec’s design for private state intends to leak no data at all. That is why we can’t just encrypt account-based state and modify it in-place in the tree, because modifying a particular encrypted leaf in a tree leaks information such as the leaf location in the tree, what contract and state it touches, etc.
Therefore, to store a private state, we need an “append only” approach. That is, the existing entries in the database (i.e., leaves in the Storage Tree) cannot be modified or deleted; only new entries can be appended.
To delete or update an entry appended earlier, we use nullifiers. Nullifiers live in a separate nullifier tree which we refer to as a Nullifier Set. To delete an entry, a matching nullifier is created in the nullifier tree.
To create a nullifier for the specific entry, one has to have a nullifier secret key that corresponds to the owner of this specific entry. No nullifier key – no nullifier! Nullifiers are deterministically generated from UTXO inputs and can’t be forged.
The entry is live, if there is no nullifier linked to this entry in the Nullifier Set.
Private state is structured as a UTXO, the same fundamental structure underlying the Bitcoin network.
So if there’s public state stored in an account-based Merkle Tree and private state stored in a UTXO-based Merkle tree, how are they composable?
Composing private state and public state
The requirements for private and public state transitions are entirely different, so to understand how they work together, let’s deconstruct each:
For private state transitions, we need client-side proof generation in order to prevent data leakage. That means after function execution, a proof of correct execution must be generated on a user’s device before being sent to a sequencer for verification. The private transaction is represented by the proof of its correct execution and a few other pieces of data (e.g., commitments, nullifiers, contract deployment data, etc.) that do not disclose any transaction data whatsoever.
For public state transitions, the correctness of transaction execution is proven by a third party (usually a prover) as there is no need to hide transaction data.
In both cases, transactions are forwarded to the mempool and ordered and executed by the sequencer. The key difference is that in the case of a private transaction, the transaction is executed privately and its correct execution proof is generated by a user before it lands in the mempool. In the case of a public function, the proof is generated after the transaction lands in the mempool and is processed by the sequencer.
To make privacy composable, Aztec introduces smart contracts that support both private and public states and execution.
In summary:
Public functions:
- Can read and write public state
- Can insert into the UTXO tree for use in private functions
- Can broadcast information to everyone (similar to msg.data on Ethereum)
- Can unshield data (move data from private state to public state), if the call was initiated by private function earlier
Private functions:
- Can privately read from, and insert into the private UTXO tree
- Can insert into the Nullifier Set
- Can create proofs from historical data (coprocessor functionality)
- Can shield data (move data from public state to private state)
- Can call public functions (but without any return values)
How Aztec smart contracts are executed
Aztec smart contract execution has a specific order:
- All private functions are executed in an execution trace
- A proof of correct execution is generated
- All public functions are executed
Private functions to zk-snark circuits
Private functions do NOT perform any state updates on their own. Instead, private functions are executed privately and proofs of their correct execution are generated on the user’s side. Each proof must then be verified by the kernel and rollup circuits.
Every private function is converted into a zk-snark circuit that is used by the smart contract for proof verification. This is made possible thanks to the Noir programming language (a Domain Specific Language for SNARK proving systems developed by the Aztec team.)
From a proof of a function’s correct execution to a proof of a transaction’s correct execution
As we mentioned before, smart contracts are composed of private and public functions. All the functions that are called in a transaction are stored in the call stack, with separate call stacks for private and public functions.
On the private side
To execute all private functions from the private call stack and build a proof of transaction execution correctness, we use The Private Kernel Circuit, which runs locally on the user’s device so all the private inputs stay private.
How The Private Kernel Circuit works:
The sequencer scans the mempool looking for new transactions and decides to add the specific transaction to the rollup block. The sequencer constructs a block and passes it into the rollup circuit (run by prover).
How the rollup circuit works:
- The rollup circuit creates proofs of pairs of transactions recursively until it gets a final block proof.
- The sequencer validates “Oracle” data provided as a public inputs to the circuits
- The sequencer performs UTXO updates.
- The sequencer performs nullifier updates and validates nullifiers that do not already exist.
Once the rollup circuit proof is generated, the sequencer then sanity checks that the calldata hash is correct and posts the calldata to L1. The proof is verified by smart contract on L1. State hashes and message boxes are updated.
{{blog_divider}}
Summary
Privacy is a fundamental human right.
We all expect privacy with our personal info, payments, and daily communications.
Aztec Labs is building towards a blockchain-based internet where privacy will be protected:
- Developers can build privacy-preserving applications
- Users can selectively reveal information bout their identities, finances, and more.
Privacy is the single critical feature that will bring users into this future.
You can help build this future today.
- Build with the Aztec Sandbox: A local developer testnet of Aztec’s privacy-first L2 on Ethereum
- Build with Noir: A privacy programming language developed by Aztec Labs
- Join the Aztec Labs team – we’re hiring on our cryptography, growth, and operations teams