# ZkEVM Note ## Ethereum: A Decentralized Blockchain with Embedded Computation Ethereum is a decentralized blockchain platform that serves as the foundation for building applications and organizations in a permissionless, censorship-resistant manner. At the core of Ethereum lies a virtual machine, known as the Ethereum Virtual Machine (EVM), which acts as a global, shared computer. The state of this virtual machine is agreed upon by all participants within the Ethereum network, ensuring a unified and consistent state across the entire platform. Every node participating in the Ethereum network maintains a copy of the EVM's state. This distributed consensus ensures that any changes to the EVM's state are verified, validated, and propagated across the entire network. Participants in the Ethereum network can broadcast requests for the EVM to perform computations. These requests, known as transaction requests, are processed by the network, leading to a state change in the EVM. Once executed, this new state is committed to the blockchain and synchronized across all nodes in the network. The blockchain serves as a permanent and tamper-resistant ledger of all transactions and the current state of the EVM. Cryptographic mechanisms inherent in Ethereum ensure the integrity and immutability of the blockchain. Once a transaction is validated and added to the blockchain, it becomes irreversible and cannot be altered. Moreover, these cryptographic safeguards ensure that transactions are executed with proper authorization—only the rightful owner of an account can initiate a transaction involving their digital assets. ## Ether (ETH): The Native Cryptocurrency of Ethereum Ether (ETH) is the native cryptocurrency of the Ethereum platform. Its primary function is to create a marketplace for computational resources within the Ethereum network, providing an economic incentive for participants to verify and execute transaction requests. This marketplace ensures that the network remains secure, functional, and efficient. When a participant broadcasts a transaction request on the Ethereum network, they must include a certain amount of ETH as a bounty. This bounty serves two purposes: a portion of it is burned (permanently removed from circulation), while the remainder is awarded to the participants who perform the work of verifying the transaction, executing it, committing it to the blockchain, and broadcasting the results to the network. The amount of ETH required for a transaction corresponds directly to the computational resources necessary to complete the task. This system not only compensates participants for their work but also acts as a deterrent against malicious activity. For instance, it prevents bad actors from intentionally overloading the network by requesting the execution of infinite loops or other resource-intensive scripts, as they would incur substantial costs in ETH. Beyond facilitating computation, ETH also plays a critical role in maintaining the security and integrity of the Ethereum network. It does so in three main ways: 1. **Rewarding Validators:** ETH is used to compensate validators who propose new blocks or expose dishonest behavior by other validators. 2. **Staking Collateral:** Validators are required to stake ETH as collateral. If they engage in dishonest behavior, their staked ETH can be destroyed (slashed), thereby incentivizing honest participation. 3. **Consensus Mechanism:** ETH is used to weigh votes for newly proposed blocks, which is an essential part of the fork-choice rule in the network's consensus mechanism. Through these functions, Ether ensures the smooth operation and security of the Ethereum network, making it indispensable to the platform's ecosystem. ## Smart Contracts: Programmable Agreements on the Ethereum Blockchain On the Ethereum network, participants do not need to write new code each time they want to request a computation. Instead, developers can upload reusable code snippets, known as smart contracts, to the Ethereum Virtual Machine (EVM). Users can then request the execution of these smart contracts with varying parameters, allowing for flexible and automated interactions. At its core, a smart contract is a self-executing program that performs specific actions or computations when certain conditions are met. For example, a simple smart contract might function like a digital vending machine: when a user sends a specified amount of ETH to the contract, it automatically triggers the creation and transfer of a digital asset to the user. Developers have the freedom to create and deploy smart contracts on the Ethereum network. Once deployed, these contracts become publicly accessible, and any user can interact with them by paying a fee in ETH. This fee compensates the network for the computational resources required to execute the contract. Smart contracts enable developers to build and deploy a wide range of applications and services, from decentralized marketplaces and financial instruments to games and other complex user-facing applications. By leveraging the blockchain as a data layer, smart contracts provide a secure, transparent, and tamper-proof environment for executing transactions and enforcing agreements without the need for intermediaries. ## Ethereum Accounts: Entities for Managing Transactions and Smart Contracts An Ethereum account is a fundamental entity within the Ethereum network, holding an Ether (ETH) balance and capable of sending transactions. Accounts in Ethereum can either be controlled directly by users or deployed as smart contracts, each serving different purposes within the ecosystem. ### Types of Ethereum Accounts Ethereum supports two primary types of accounts: 1. **Externally-Owned Account (EOA):** - An EOA is controlled by a user who possesses the corresponding private keys. - This type of account is typically used by individuals to manage their ETH and interact with the Ethereum network. 2. **Contract Account:** - A contract account is a smart contract that has been deployed on the Ethereum network. - Unlike EOAs, contract accounts are not controlled by private keys; instead, they are governed by the code of the smart contract. ### Capabilities of Ethereum Accounts Both externally-owned accounts and contract accounts have the ability to: - **Receive, Hold, and Send ETH and Tokens:** They can manage ETH and other tokens on the Ethereum network. - **Interact with Deployed Smart Contracts:** They can engage with smart contracts that have been deployed on the Ethereum blockchain. ### Key Differences Between Account Types 1. **Externally-Owned Accounts (EOA):** - **Cost of Creation:** Creating an EOA is free of charge, as it does not require the use of network storage. - **Initiating Transactions:** EOAs can independently initiate transactions on the Ethereum network. - **Transaction Types:** Transactions between EOAs are limited to the transfer of ETH or tokens. - **Key Structure:** An EOA consists of a cryptographic pair of keys—public and private keys—which control all account activities. The private key must be securely stored, as it grants the owner full control over the account. 2. **Contract Accounts:** - **Cost of Creation:** Deploying a contract account incurs a cost because it requires the use of network storage to hold the smart contract code. - **Transaction Behavior:** Contract accounts cannot initiate transactions on their own. They can only send transactions in response to receiving a transaction from an externally-owned account. - **Complex Actions:** When a contract account receives a transaction, it can trigger its code to execute various actions. These actions can range from transferring tokens to creating new contracts, depending on the logic programmed into the smart contract. - **Control Mechanism:** Unlike EOAs, contract accounts do not have private keys. Instead, they are controlled by the logic embedded in the smart contract's code, ensuring that the contract's behavior is predictable and automated based on predefined conditions. ## Merkle Tree: A Cryptographic Data Structure for Efficient Verification ![image](https://hackmd.io/_uploads/B1zEaT0sR.png) In cryptography and computer science, a Merkle tree, also known as a hash tree, is a type of data structure where each "leaf" node is labeled with the cryptographic hash of a data block. Nodes that are not leaf nodes, often referred to as branch nodes, inner nodes, or inodes, are labeled with the cryptographic hash of the concatenated labels of their child nodes. This structure allows for the efficient and secure verification of the contents of large data sets. The Merkle tree is a generalization of simpler structures such as hash lists and hash chains, offering significant advantages in terms of security and efficiency. In a Merkle tree, proving that a particular leaf node is part of a given tree requires calculating a number of hashes proportional to the logarithm of the total number of leaf nodes in the tree. This logarithmic relationship makes Merkle trees highly efficient, particularly when compared to hash lists, where the verification process scales linearly with the number of leaf nodes. Due to its properties, a Merkle tree is an effective cryptographic commitment scheme. In this context, the root of the Merkle tree serves as the cryptographic commitment, representing the entirety of the data structure. Individual leaf nodes can later be revealed and proven to belong to this original commitment, making Merkle trees an essential component in various cryptographic protocols and blockchain technologies. The concept of the Merkle tree was introduced and patented by Ralph Merkle in 1979, and it has since become a foundational element in the fields of cryptography and blockchain technology. ## Merkle Proofs: A Method for Verifying Data Inclusion in Merkle Trees Merkle proofs are cryptographic techniques used to verify whether a specific piece of data belongs to a Merkle tree. They provide a concise and secure way to validate the inclusion of data within a larger dataset, without the need to store or reveal the entire dataset. ### Key Uses of Merkle Proofs: 1. **Data Inclusion Verification:** Merkle proofs can confirm whether a particular data element is part of a given Merkle tree. 2. **Efficient Data Validation:** They allow the validation of a dataset's inclusion within a larger dataset, without requiring access to the full dataset or its subset. 3. **Secure Verification:** Merkle proofs ensure that the verification process remains secure and that no unnecessary data is exposed. ### How Merkle Proofs Work: Merkle trees rely heavily on one-way hashing functions. A one-way hash function is designed to be collision-resistant and deterministic, meaning that no two different pieces of data should produce the same hash, and the same data will always produce the same hash. To establish a Merkle proof, the process involves hashing together corresponding hashes of sibling nodes and moving up the tree until reaching the root hash, which is, or can be, publicly known. The root hash serves as the final verification point, proving the inclusion of the original data without needing to expose the data itself. ### Example of a Merkle Proof: ![image](https://hackmd.io/_uploads/rkE6zAAs0.png) Consider a scenario where we want to verify the inclusion of data element $K$ in a Merkle tree. The process is as follows: 1. **Hashing the Data:** First, we hash the data $K$ using a one-way function to obtain $H(K)$. 2. **Combining Hashes:** Next, $H(K)$ is hashed together with the hash of another unknown dataset $L$, resulting in $H(KL)$. 3. **Continuing the Process:** This combined hash $H(KL)$ is then hashed with another combined hash $H(IJ)$, leading to $H(IJKL)$. 4. **Climbing Up the Tree:** This process continues as $H(IJKL)$ is hashed with $H(MNOP)$, yielding $H(IJKLMNOP)$. Finally, $H(IJKLMNOP)$ is hashed with $H(ABCDEFGH)$ to produce the Merkle root $H(ABCDEFHGIJKLMNOP)$, which is publicly available. By using the hashes $H(L)$, $H(IJ)$, $H(MNOP)$, and $H(ABCDEFGH)$, we can prove that the data element $K$ is indeed part of the Merkle tree. Importantly, this proof does not require revealing the actual data $K$ or any other data in the tree. ### Applications of Merkle Proofs: Merkle proofs are widely used in various applications, particularly in blockchain technology. They are essential for proving the inclusion of data within large datasets, ensuring data integrity, and enabling secure and efficient validation processes in distributed systems. ## Trie: A Prefix-Based Data Structure for Efficient Key Retrieval In computer science, a trie (pronounced /ˈtraɪ/ or /ˈtriː/), also known as a digital tree or prefix tree, is a specialized k-ary search tree used for efficiently locating specific keys within a set. Unlike traditional search trees where each node stores a key, in a trie, the keys are distributed across the structure, with each node representing a single character of the key. This distribution allows for efficient retrieval, modification, and deletion of keys by traversing the trie in a [depth-first](https://en.wikipedia.org/wiki/Depth-first_search) manner. ![image](https://hackmd.io/_uploads/r1vzWxyhR.png) ### Key Characteristics of a Trie: 1. **Key Representation:** - In a trie, keys are typically strings. The links between nodes are not defined by the entire key but rather by individual characters within the key. - The position of a node within the trie determines the key it is associated with, rather than the node itself storing the key. 2. **Node Structure:** - Nodes in a trie do not store the complete key they represent. Instead, the key is derived from the path taken to reach the node. - The root of the trie corresponds to an empty string, and all children of a node share a common prefix, corresponding to the string associated with the parent node. 3. **Traversal and Operations:** - To access a key in a trie, whether to retrieve its value, modify it, or remove it, the trie is traversed from the root to the desired node. This traversal follows the links between nodes that represent each character of the key. - The key lookup complexity in a trie is proportional to the length of the key, making it highly efficient for operations on large datasets. ## Radix Tree: A Space-Optimized Data Structure for Efficient Key Retrieval In computer science, a radix tree, also known as a radix trie, compact prefix tree, or compressed trie, is a data structure designed to optimize the space usage of a traditional trie (prefix tree). This optimization is achieved by merging nodes that have only a single child with their parent nodes, resulting in a more compact structure. In a radix tree, the number of children for each internal node is limited by the radix $r$ of the tree, where $r=2^x$ for some integer $x \geq 1$. ![image](https://hackmd.io/_uploads/SJa05WyhA.png) ### Key Features of a Radix Tree: 1. **Space Optimization:** - Radix trees reduce redundancy by combining nodes that have only one child with their parent nodes, which minimizes the overall number of nodes in the tree. - This structure is particularly efficient for datasets that contain strings with long shared prefixes or for small sets of strings, especially when the strings themselves are long. 2. **Edge Labeling:** - Unlike regular trees, where edges are labeled by single elements, the edges in a radix tree can be labeled with sequences of elements. This feature contributes to the tree's efficiency, especially in cases where keys share long common prefixes. 3. **Key Comparison:** - In a radix tree, keys are compared bit by bit, or in chunks of bits, rather than comparing entire keys all at once. The size of these chunks is determined by the radix $r$ of the tree. - When $r=2$, the radix tree is binary, meaning it compares one bit at a time. This approach minimizes the tree's sparseness but increases its depth. - When $r$ is greater than or equal to $4$ and is a power of $2$, the radix tree becomes an $r$-ary trie. This reduces the tree's depth but may introduce some sparseness. 4. **Edge Label Storage:** - As an optimization, the labels on edges can be stored in a constant size by using two pointers to mark the start and end of the string sequence that the edge represents. This method enhances the efficiency of the tree while maintaining compactness. ### Flexibility in Data Types: Although examples of radix trees often use strings as sequences of characters, the elements of the string can be chosen based on the specific application. For instance, the elements could be bits, bytes, or any other units, making radix trees versatile for different types of data. ## Merkle Patricia Trie: An Optimized Data Structure for Efficient Storage and Retrieval In the context of blockchain and cryptography, a Merkle Patricia Trie is a hybrid data structure that combines the features of a radix trie and a Merkle tree, offering both space optimization and cryptographic security. The Merkle Patricia Trie is specifically designed to address inefficiencies in standard radix tries, particularly in environments like Ethereum, where paths can be 64 characters long, and the storage of each character at a separate level would be highly inefficient. ![image](https://hackmd.io/_uploads/Sy_2kG1n0.png) https://ethereum.stackexchange.com/questions/268/ethereum-block-architecture ### Key Features and Optimizations A node in a Merkle Patricia Trie can be one of the following: 1. **NULL Node:** Represented as an empty string. 2. **Branch Node:** A 17-item node represented as **[ v0 ... v15, vt ]**, where **v0** to **v15** correspond to possible values for each nibble (half a byte) and vt stores the value at that node if it is a terminal node. 3. **Leaf Node:** A 2-item node represented as **[ encodedPath, value ]**, where **encodedPath** is the compacted path to the leaf, and **value** is the stored value. 4. **Extension Node:** A 2-item node represented as **[ encodedPath, key ]**, where **encodedPath** contains a portion of the path that skips ahead to the next relevant node, and **key** is used for the next lookup in the database. #### Optimization Through Compaction: - In a Merkle Patricia Trie, paths are compacted to avoid storing redundant nodes. For example, after traversing several layers of the trie, you may encounter a node where no divergent paths exist for a certain portion of the path. Instead of creating sparse NULL nodes for each possible path, an extension node is used. This node contains a partial path that skips directly to the next relevant section of the trie. #### Handling Path Length and Ambiguity: - The compact encoding scheme introduces the potential for ambiguity, especially when dealing with odd numbers of nibbles (a nibble being 4 bits). Since all data is stored in bytes, it is necessary to differentiate between single nibbles and pairs. To do this, the first nibble of the partial path is flagged to indicate whether the remaining path length is odd or even, and whether the node is an extension or a leaf. ### Compact Encoding Specification: The first nibble of the partial path in any 2-item node serves to flag both the node type (leaf or extension) and the path length (odd or even): ``` hex char bits | node type partial path length ---------------------------------------------------------- 0 0000 | extension even 1 0001 | extension odd 2 0010 | terminating (leaf) even 3 0011 | terminating (leaf) odd ``` ### Example Trie Construction: Consider building a trie with the following path/value pairs: ('do', 'verb'), ('dog', 'puppy'), ('doge', 'coins'), ('horse', 'stallion') #### Steps to Build the Trie: 1. Convert paths and values to byte representations: ``` <64 6f> : 'verb' <64 6f 67> : 'puppy' <64 6f 67 65> : 'coins' <68 6f 72 73 65> : 'stallion' ``` 2. Construct the trie with key-value pairs stored in the underlying database: ``` rootHash: [ <16>, hashA ] hashA: [ <>, <>, <>, <>, hashB, <>, <>, <>, [ <20 6f 72 73 65>, 'stallion' ], <>, <>, <>, <>, <>, <>, <>, <> ] hashB: [ <00 6f>, hashC ] hashC: [ <>, <>, <>, <>, <>, <>, hashD, <>, <>, <>, <>, <>, <>, <>, <>, <>, 'verb' ] hashD: [ <17>, [ <>, <>, <>, <>, <>, <>, [ <35>, 'coins' ], <>, <>, <>, <>, <>, <>, <>, <>, <>, 'puppy' ] ] ``` Each node references others using the hash of the RLP-encoded node (**H(rlp.encode(node))**), where **H(x) = keccak256(x)** if **len(x) >= 32**, or **H(x) = x** otherwise. ### Trie Updates and Persistence: When updating a trie, if a newly created node has a length of 32 bytes or more, the key-value pair **(keccak256(x), x)** must be stored in a persistent lookup table. However, if the node is shorter, no additional storage is required since the function **f(x) = x** is reversible. ## Ethereum Virtual Machine (EVM): A Decentralized Execution Environment The Ethereum Virtual Machine (EVM) is a decentralized virtual environment designed to execute smart contracts consistently and securely across all Ethereum nodes. As the computational engine behind Ethereum, the EVM ensures that code is executed in a reliable and uniform manner throughout the network. It uses "gas" as a measure of computational effort, which not only helps in resource allocation but also in maintaining the security of the network. ### From Ledger to State Machine Traditional blockchains, such as Bitcoin, are often described using the analogy of a "distributed ledger." This ledger records all transactions and enforces rules that govern what can and cannot be done—such as ensuring that an address cannot spend more Bitcoin than it has received. Ethereum, while also operating as a ledger with its native cryptocurrency (Ether), extends this concept by enabling the execution of smart contracts. To accommodate this expanded functionality, Ethereum operates as a distributed [state machine](https://en.wikipedia.org/wiki/Finite-state_machine). Unlike a simple ledger, Ethereum's state machine is a complex data structure that tracks not only all accounts and balances but also the machine state, which can evolve from block to block according to predefined rules. These rules are defined by the EVM, making it the central component that governs state transitions within the Ethereum network. ![image](https://hackmd.io/_uploads/rk72JQy3A.png) ### The Ethereum State Transition Function The EVM can be understood as a mathematical function that takes an input and produces a deterministic output. Formally, this is represented by the Ethereum state transition function: $Y(S,T)=S^′$ Where: - $S$ represents the old valid state. - $T$ represents a new set of valid transactions. - $S^′$ represents the new valid output state produced by the function. This function ensures that given a valid initial state and a valid set of transactions, the EVM will consistently produce a new valid state. ### State in Ethereum In Ethereum, the state is represented by a large data structure known as a **modified Merkle Patricia Trie**. This trie links all accounts using hashes and can be reduced to a single root hash stored on the blockchain. This root hash serves as a unique identifier for the state at any given time, allowing for secure and efficient verification of the state across the network. ### Transactions Transactions in Ethereum are cryptographically signed instructions sent from accounts. They fall into two categories: 1. **Message Calls:** Transactions that interact with existing contracts. 2. **Contract Creation:** Transactions that result in the creation of new contract accounts containing compiled smart contract bytecode. When a transaction triggers a message call to a contract, the EVM executes the contract's bytecode, modifying the state according to the contract's logic. ### EVM Instructions and Execution The EVM operates as a [stack machine](https://en.wikipedia.org/wiki/Stack_machine) with a depth of 1024 items, where each item is a 256-bit word. This choice aligns with the 256-bit cryptographic standards used in Ethereum, such as Keccak-256 hashes and secp256k1 signatures. During execution, the EVM uses transient memory, organized as a word-addressed byte array, which is cleared between transactions. Contracts themselves maintain a **Merkle Patricia storage trie**, a persistent word-addressable word array associated with the contract's account. This storage trie is part of the global state and persists across transactions. The EVM executes compiled smart contract bytecode as a sequence of [EVM opcodes](https://ethereum.org/en/developers/docs/evm/opcodes/), which perform standard stack operations (e.g., XOR, AND, ADD, SUB) as well as blockchain-specific operations (e.g., ADDRESS, BALANCE, BLOCKHASH). ![image](https://hackmd.io/_uploads/ryymWQyhA.png) ### EVM Implementations All EVM implementations must adhere to the specifications outlined in the [Ethereum Yellowpaper](https://ethereum.github.io/yellowpaper/paper.pdf), which defines the rules and standards for the EVM's operation. This ensures consistency across different implementations, allowing the Ethereum network to function seamlessly as a decentralized platform for executing smart contracts. ## Scaling Blockchain Ecosystems: Layer-1 and Layer-2 Solutions Scaling a blockchain ecosystem is essential to increasing its transaction capacity and overall efficiency. There are two primary approaches to achieve this: **Layer-1 scaling** and **Layer-2 scaling**. ### Layer-1 Scaling Layer-1 scaling focuses on increasing the transaction capacity of the blockchain itself. This can be done by enhancing the base layer of the blockchain, such as increasing block size or improving the efficiency of client software. However, increasing block size comes with significant challenges. Larger blocks are more difficult to verify, which can lead to centralization as only a few powerful nodes would be capable of processing the larger blocks efficiently. To mitigate these risks, more sustainable solutions like **sharding** are implemented. Sharding involves dividing the blockchain’s data into smaller, manageable pieces, allowing the workload to be distributed across many nodes. This method improves the blockchain’s capacity without compromising its decentralization. Ethereum’s ongoing upgrade, often referred to as "eth2," is an example of a project working to implement sharding as a means of Layer-1 scaling. ### Layer-2 Scaling Layer-2 scaling takes a different approach by changing how the blockchain is used. Instead of executing all transactions directly on the blockchain, the majority of activities are handled off-chain within a Layer-2 protocol. This off-chain protocol interacts with the blockchain through a smart contract, which has two main functions: 1. **Processing deposits and withdrawals.** 2. **Verifying proofs** that off-chain activities are following the correct rules. By conducting most computations off-chain and only submitting proofs to the blockchain, Layer-2 scaling significantly reduces the computational load on the blockchain. This makes transactions faster and cheaper while maintaining security. ### Rollups: A Key Layer-2 Scaling Solution **Rollups** are a popular Layer-2 scaling technique where transaction execution occurs off-chain, but the data is posted to the Layer-1 blockchain, where consensus is reached. Rollups allow for high transaction throughput while still benefiting from the security provided by the Layer-1 blockchain, such as Ethereum. #### How Rollups Work ![image](https://hackmd.io/_uploads/SJW1_Xx2R.png) At the core of a rollup is a smart contract on the blockchain that maintains a state root—a Merkle root representing the current state of the rollup (including account balances, contract code, etc.). The process involves the following steps: 1. **Batch Submission:** Anyone can submit a batch of transactions to the rollup. This batch includes the transactions in a compressed form, the previous state root, and the new state root (the Merkle root after the transactions are processed). 2. **State Root Verification:** The smart contract verifies that the previous state root in the batch matches its current state root. If the roots match, the contract updates the state root to the new state root. 3. **Handling Deposits and Withdrawals:** To allow interaction with assets outside the rollup, special transactions are enabled. If a batch includes inputs from outside the rollup, the assets must be transferred to the rollup contract. Similarly, if a batch includes outputs to be withdrawn, the smart contract initiates these withdrawals after processing the batch. ![image](https://hackmd.io/_uploads/S1cf_Xl2C.png) The above process is straightforward, but ensuring the correctness of the new state root is critical to preventing fraud. There are two main types of rollups that address this challenge differently: **Optimistic Rollups** and **ZK Rollups**. ### Optimistic Rollups vs. ZK Rollups The key difference between Optimistic and ZK Rollups lies in how they ensure the correctness of the post-state roots. #### Optimistic Rollups Optimistic Rollups operate on the assumption that the batches are correct unless proven otherwise. They use **fraud proofs** to ensure security: - The rollup contract keeps a history of all state roots and batch hashes. - If someone discovers an incorrect state root in a batch, they can submit a fraud proof to the blockchain. - The contract then verifies the proof. If the proof is valid, the incorrect batch and all subsequent batches are reverted. This mechanism relies on the idea that fraud is the exception rather than the rule, hence the term "optimistic." #### ZK Rollups ZK Rollups use **validity proofs** to guarantee the correctness of each batch: - Every batch submitted to the rollup includes a cryptographic proof, known as a **ZK-SNARK** (Zero-Knowledge Succinct Non-Interactive Argument of Knowledge). - This proof verifies that the new state root is the correct result of executing the batch of transactions. - The proof is quickly verified on-chain, irrespective of the size of the batch. Because ZK Rollups rely on mathematical proofs to ensure correctness, they provide stronger security guarantees than Optimistic Rollups, without needing to assume that all batches are correct. ## Zero-Knowledge Rollups (ZK-Rollups) Zero-Knowledge Rollups (ZK-Rollups) represent an advanced layer-2 scaling solution for blockchain networks, particularly those like Ethereum. They work by bundling, or "rolling up," multiple transactions into a single batch that is processed off-chain. This off-chain computation significantly reduces the amount of data that needs to be posted on-chain, thereby alleviating congestion and lowering transaction costs. In a ZK-Rollup, instead of submitting each transaction individually to the blockchain, operators submit a concise summary of the necessary state changes resulting from the transactions in the batch. To ensure the integrity and correctness of these state changes, ZK-Rollup operators generate and submit a validity proof along with the batch. This validity proof is a cryptographic guarantee that the batch of transactions has been processed correctly and that the resulting state changes are accurate. The overall state of the ZK-Rollup is managed by a smart contract deployed on the Ethereum network. For the state to be updated, nodes within the ZK-Rollup must submit the aforementioned validity proof, which is then verified by the smart contract. Unlike other rollup solutions, such as optimistic rollups, ZK-Rollups do not require all transaction data to be posted on-chain. Instead, they rely solely on these validity proofs to finalize transactions, which enhances efficiency and reduces on-chain data requirements. A key advantage of ZK-Rollups is the immediate finality they provide when moving funds from the rollup to the Ethereum mainnet. Exit transactions can be executed immediately once the ZK-Rollup contract verifies the associated validity proof. In contrast, optimistic rollups often involve a delay during fund withdrawals, as this time window allows anyone to challenge the transaction with a fraud proof. ZK-Rollups write transaction data to Ethereum using calldata. Calldata is the storage area for data included in external calls to smart contract functions, and this data is published on the blockchain. By storing information in calldata, ZK-Rollups enable anyone to independently reconstruct the rollup's state if needed. Additionally, ZK-Rollups employ various data compression techniques to minimize the amount of transaction data posted on-chain. For instance, accounts are identified by an index rather than a full address, saving 28 bytes per transaction. Given that the publication of on-chain data is one of the most significant costs for rollups, these compression techniques help reduce fees for users, making the system more cost-effective and scalable. This combination of cryptographic security, data efficiency, and immediate finality makes ZK-Rollups a powerful tool for scaling blockchain networks while maintaining high levels of trust and decentralization. ## Interaction of Zero-Knowledge Rollups (ZK-Rollups) with the Ethereum Network Zero-Knowledge Rollups (ZK-Rollups) are off-chain protocols that enhance the scalability of blockchain networks by executing transactions outside the Ethereum mainnet. These transactions are periodically committed to the Ethereum blockchain, ensuring that the ZK-Rollup chain remains immutable and secure. The interaction between ZK-Rollups and Ethereum is critical to understanding how these rollups function and maintain the integrity of the blockchain ecosystem. ### Core Architecture of ZK-Rollups The architecture of a ZK-Rollup consists of several key components: 1. **On-Chain Contracts:** ZK-Rollups are governed by smart contracts that run on the Ethereum blockchain. The primary contract within this setup is responsible for storing rollup blocks, managing deposits, and monitoring state updates. Additionally, a verifier contract is employed to authenticate the zero-knowledge proofs submitted by the rollup’s block producers. In this way, Ethereum acts as the foundational layer, or "Layer 1," that provides the security and trust required for the ZK-Rollup protocol. 2. **Off-Chain Virtual Machine (VM):** While the ZK-Rollup protocol operates on Ethereum, the actual execution of transactions and storage of the state occur on a separate virtual machine (VM) that functions independently of the Ethereum Virtual Machine (EVM). This off-chain VM serves as the execution environment for transactions within the ZK-Rollup, effectively functioning as "Layer 2" of the protocol. The correctness of state transitions within this off-chain VM is guaranteed by the validity proofs verified on the Ethereum mainnet. ### Hybrid Scaling Solution ZK-Rollups are considered a hybrid scaling solution because they operate independently off-chain while deriving their security from the Ethereum network. Specifically, Ethereum enforces the validity of state updates within the ZK-Rollup and ensures the availability of the data behind every state update. This dual-layered approach provides a higher level of security compared to purely off-chain scaling solutions, such as sidechains, which must manage their own security, or validiums, which verify transactions on Ethereum but store transaction data elsewhere. ### Ethereum’s Role in ZK-Rollups The Ethereum network plays a crucial role in several aspects of the ZK-Rollup's operation: 1. **Data Availability:** ZK-Rollups publish the state data of each transaction processed off-chain to Ethereum. This allows participants to independently reconstruct the rollup’s state and verify the chain’s integrity. While ZK-Rollups do not need to publish extensive transaction data on-chain due to the validity proofs ensuring the authenticity of state transitions, storing data on-chain remains vital. It allows for permissionless and independent verification of the Layer 2 chain’s state, enabling anyone to submit batches of transactions and preventing malicious operators from censoring or freezing the chain. Users rely on this on-chain data to query their account balances and initiate transactions, such as withdrawals, that depend on accurate state information. 2. **Transaction Finality:** Ethereum serves as the settlement layer for ZK-Rollups, with Layer 2 transactions only achieving finality when the Layer 1 contract accepts the validity proof. This ensures that the chain cannot be corrupted by malicious operators, as every transaction must be approved by the Ethereum mainnet. Moreover, Ethereum guarantees that once a transaction is finalized on Layer 1, it cannot be reversed, providing strong assurances against the risk of fraud or data manipulation. 3. **Censorship Resistance:** Typically, ZK-Rollups utilize a "supernode" or operator to execute transactions, produce batches, and submit blocks to the Ethereum network. While this centralization can enhance efficiency, it also introduces the potential risk of censorship, where a malicious operator might refuse to include certain transactions in the batches. To counter this risk, ZK-Rollups incorporate a security feature that allows users to submit their transactions directly to the rollup contract on the Ethereum mainnet if they suspect censorship by the operator. This mechanism enables users to force an exit from the ZK-Rollup to Ethereum, thereby bypassing the need for operator approval. Through this intricate interaction with Ethereum, ZK-Rollups achieve a balance between scalability, security, and decentralization, offering a robust solution for processing large volumes of transactions while maintaining the integrity and trustworthiness of the blockchain network. ## How Zero-Knowledge Rollups (ZK-Rollups) Work Zero-Knowledge Rollups (ZK-Rollups) are advanced scaling solutions for blockchain networks, particularly Ethereum. They allow for the efficient processing of transactions by moving computation off-chain while ensuring the integrity and security of these transactions through cryptographic proofs. Here's a detailed, step-by-step explanation of how ZK-Rollups function: ### Transaction Processing Users on a ZK-Rollup network initiate transactions by signing them and submitting them to Layer 2 (L2) operators for processing. These operators play a central role in managing transactions on the ZK-Rollup: - **Centralized Operator (Sequencer):** In some ZK-Rollups, a centralized entity, known as the sequencer, is responsible for executing transactions, aggregating them into batches, and submitting these batches to the Ethereum mainnet (Layer 1, L1). The sequencer is the sole entity authorized to produce L2 blocks and add transactions to the ZK-Rollup contract on Ethereum. - **Decentralized Operators:** Other ZK-Rollups may employ a decentralized approach by rotating the operator role among a set of validators, typically selected through a proof-of-stake system. Prospective operators must deposit funds into the rollup contract, with their stake size influencing their chances of being selected to produce the next batch. If an operator behaves maliciously, their stake can be slashed, incentivizing them to maintain the integrity of the system. ### Publishing Transaction Data on Ethereum After processing transactions off-chain, ZK-Rollups publish the corresponding data on the Ethereum blockchain. This is done using a specific data storage method called calldata: - **Calldata:** Calldata is a low-cost way to store data on Ethereum without affecting the blockchain’s state. ZK-Rollup operators use calldata to publish compressed transaction data on-chain. They do this by invoking a function in the rollup contract and passing the compressed data as function arguments. This method reduces the cost for users, as a significant portion of rollup fees are associated with storing transaction data on-chain. ### State Commitments The state of the ZK-Rollup, including user accounts and balances, is represented as a Merkle tree, a data structure that allows efficient and secure verification of the contents within the tree. The key aspects of state commitments are: - **Merkle Root:** The Merkle root, a cryptographic hash of the entire Merkle tree, is stored in the ZK-Rollup’s smart contract on Ethereum. This root is essential for tracking changes in the rollup’s state. - **State Transitions:** When a new batch of transactions is executed, the ZK-Rollup transitions to a new state. The operator responsible for the transition computes a new state root and submits it to the on-chain contract. The verifier contract on Ethereum then authenticates the validity proof associated with the batch. If the proof is valid, the new Merkle root becomes the official state root of the ZK-Rollup. - **Batch Root:** Along with the state root, the operator also creates a batch root, representing all transactions within a batch. This root allows users to prove that a specific transaction was included in the batch using a Merkle proof. ## Validity Proofs in ZK-Rollups ### Overview of Validity Proofs In a ZK-rollup, the state of the system is represented by a Merkle tree, with each transaction potentially altering this state. When a user submits a transaction, such as Alice sending 10 tokens to Bob, the ZK-rollup operator updates the Merkle tree by reducing Alice's balance by 10 and increasing Bob's balance by the same amount. This updated state is then hashed to produce a new Merkle root, which is submitted to the Layer 1 (L1) contract on Ethereum. However, the L1 contract does not automatically accept this new Merkle root as the correct state. Instead, the ZK-rollup operator must generate a validity proof. This proof is a succinct cryptographic commitment that verifies the correctness of the batched transactions that led to the new state. Only after the validity proof is successfully verified does the L1 contract accept the new Merkle root as the ZK-rollup’s canonical state root. ### Types of Validity Proofs Validity proofs are a form of zero-knowledge proofs, which allow the operator to demonstrate the correctness of the off-chain state transitions without revealing the specific details of the transactions. The two main types of zero-knowledge proofs used in ZK-rollups are ZK-SNARKs and ZK-STARKs. **ZK-SNARKs (Zero-Knowledge Succinct Non-Interactive Argument of Knowledge):** For ZK-SNARKs to function, a Common Reference String (CRS) must be generated. The CRS is a set of public parameters used for both proving and verifying the validity proofs. The security of this system relies on the proper setup of the CRS. If malicious actors gain access to the information used in creating these parameters, they could potentially generate false proofs. To mitigate this risk, some ZK-rollups use a multi-party computation (MPC) ceremony involving trusted individuals to generate the CRS. During this process, each participant contributes some randomness, often referred to as "toxic waste," which they must destroy immediately after the CRS is generated. The security of the ZK-SNARK system is ensured as long as at least one participant in the MPC ceremony acts honestly. ZK-SNARKs are favored for their small proof sizes and constant-time verification, which make them cost-effective to verify on the Ethereum mainnet. This efficiency is crucial because verifying proofs on L1 is a significant cost for operating a ZK-rollup. **ZK-STARKs (Zero-Knowledge Scalable Transparent Argument of Knowledge):** ZK-STARKs also provide validity proofs for off-chain computations without revealing the underlying data. However, they are considered an improvement over ZK-SNARKs due to their scalability and transparency. Unlike ZK-SNARKs, ZK-STARKs do not require a trusted setup with a CRS. Instead, they use publicly verifiable randomness to establish the parameters for generating and verifying proofs, which enhances their transparency. ZK-STARKs also scale more effectively with large datasets. The time required for proof generation and verification increases quasilinearly with the complexity of the computation, whereas ZK-SNARKs scale linearly. This makes ZK-STARKs particularly suitable for applications with high transaction volumes. Additionally, ZK-STARKs are secure against quantum computing attacks, while the elliptic curve cryptography used in ZK-SNARKs may be vulnerable to such attacks. The primary drawback of ZK-STARKs is their larger proof sizes, which can be more expensive to verify on Ethereum. ### How Validity Proofs Work in ZK-Rollups **Proof Generation:** Before processing transactions, the operator must perform several checks, including verifying that: - The sender and receiver accounts are part of the current state tree. - The sender has sufficient funds to cover the transaction. - The transaction details match the sender’s public key. - The sender’s nonce is correct. Once the operator has accumulated enough transactions, they are aggregated into a batch, and the inputs are prepared for the proving circuit. These inputs include: - The Merkle tree root representing all transactions in the batch. - Merkle proofs for each transaction to demonstrate their inclusion in the batch. - Merkle proofs for each sender-receiver pair to confirm their presence in the state tree. - Intermediate state roots generated from updating the state root after processing each transaction. The proving circuit then iterates over each transaction, performing the same checks as the operator. It verifies the existence of the sender’s account in the current state root using the provided Merkle proof, updates the account balances, and generates a new Merkle root. This process is repeated for the receiver’s account. Each transaction in the batch results in a sequence of state root updates, with the final root becoming the new canonical state root for the ZK-rollup. **Proof Verification:** Once the validity proof is generated, the ZK-rollup operator submits it to the verifier contract on the Ethereum L1. The verifier contract checks the proof against several public inputs, including: - **Pre-state root:** The old state root before the batched transactions were executed, representing the last valid state of the ZK-rollup. - **Post-state root:** The new state root after executing the batched transactions, representing the updated state of the ZK-rollup. - **Batch root:** The Merkle root of the transaction batch, which is derived by hashing the transactions. - **Transaction inputs:** The data associated with the transactions in the batch. If the proof is valid, the verifier contract accepts the post-state root as the new canonical state root. This update ensures that the ZK-rollup’s state on L1 reflects all the changes made during the batch processing. ### User Interactions: Entries and Exits **Entries:** To participate in a ZK-rollup, users deposit tokens into the rollup’s smart contract deployed on the Ethereum L1 chain. These deposits are queued since only operators can submit transactions to the rollup contract. When the deposit queue grows, the ZK-rollup operator processes these deposits and adds them to the rollup. Once a user’s funds are in the rollup, they can initiate transactions, which are processed by the operator. Users can verify their balances by hashing their account data, sending the hash to the rollup contract, and providing a Merkle proof to verify against the current state root. **Exits:** Withdrawing funds from a ZK-rollup back to L1 is a straightforward process. Users initiate an exit transaction by sending their assets to a specified burn account within the rollup. Once the operator includes the transaction in the next batch, the user submits a withdrawal request to the on-chain contract. This request must include: - A Merkle proof proving that the user’s transaction was included in the batch. - The transaction data. - The batch root. - The user’s L1 address for receiving the withdrawn funds. The rollup contract then verifies the transaction data, checks if the batch root exists, and confirms that the transaction is part of the batch root using the provided Merkle proof. Once verified, the contract executes the exit transaction and transfers the funds to the user’s specified L1 address. ### ZK-Rollups and EVM Compatibility ZK-rollups, unlike optimistic rollups, face challenges when it comes to compatibility with the Ethereum Virtual Machine (EVM). The complexity lies in the difficulty and resource intensity of proving general-purpose EVM computations within zero-knowledge circuits. While it is relatively straightforward to prove simpler computations, such as token transfers, the broader functionality of EVM requires more advanced methods. However, recent advancements in zero-knowledge technology have sparked renewed interest in developing a zero-knowledge EVM (zkEVM). The goal of zkEVM is to wrap EVM computations in zero-knowledge proofs, enabling efficient verification of program execution while maintaining the EVM's versatility. A zkEVM essentially replicates the existing EVM opcodes within zero-knowledge circuits, allowing the execution of smart contracts under this new framework. The primary difference between the traditional EVM and zkEVM is the addition of zero-knowledge proofs. While the EVM transitions between states after computations are performed on certain inputs, the zkEVM also generates proofs to verify the correctness of every step in the program's execution. These validity proofs confirm not only that operations correctly interact with the virtual machine’s state (such as memory, stack, and storage) but also that the computation itself—whether the correct opcodes were called and executed properly—is accurate. The introduction of EVM-compatible ZK-rollups is a significant development for developers. It allows them to harness the scalability and security benefits of zero-knowledge proofs while continuing to use familiar tools and programming languages within the Ethereum ecosystem. This compatibility is expected to facilitate the creation of ZK-friendly decentralized applications (dApps), leveraging the robustness and reliability of native Ethereum infrastructure. ## How Do ZK-Rollups Scale Ethereum? ### Transaction Data Compression ZK-rollups significantly enhance Ethereum’s scalability by not only shifting computation off-chain but also by compressing transaction data. Ethereum’s block size inherently limits the amount of data that can be stored within each block, which in turn restricts the number of transactions that can be processed. By efficiently compressing transaction data, ZK-rollups enable a much higher number of transactions to be processed within a single block, compared to Ethereum’s base layer. Unlike optimistic rollups, ZK-rollups don’t need to post all the data required to validate each transaction. Instead, they only post the minimal data necessary to reconstruct the latest state of accounts and balances within the rollup. This streamlined approach allows for a significant increase in transaction throughput, as the network processes more transactions with less data. ### Recursive Proofs One of the powerful features of zero-knowledge proofs is their ability to verify other proofs—a process known as recursive proving. For example, a single ZK-SNARK can validate multiple other ZK-SNARKs. This concept of "proof-of-proofs" can dramatically increase the throughput capabilities of ZK-rollups. Currently, ZK-rollups generate validity proofs for each block and submit them to the Ethereum mainnet (Layer 1) for verification. While effective, this process inherently limits throughput, as only one block can be finalized at a time. Recursive proofs, however, offer a solution by allowing multiple block proofs to be aggregated into a single, final proof. This means that the ZK-rollup can finalize several blocks at once, dramatically increasing the number of transactions that can be confirmed on Ethereum within a given time frame. The use of recursive proofs significantly enhances the efficiency of ZK-rollups, enabling them to scale Ethereum to new levels of transaction processing capacity. ## zkEVM: The Future of Ethereum Scaling ### Introduction to zk-Rollups and Their Importance zk-Rollups are widely regarded as the most effective scaling solution for Ethereum, offering a level of security comparable to Ethereum's Layer 1 while delivering the fastest finalization times among all Layer 2 solutions. As zero-knowledge proof technology advances, it is anticipated that zk-Rollups will eventually dominate across all use cases, as stated by Ethereum co-founder Vitalik Buterin. The fundamental concept behind zk-Rollups is the aggregation of a large number of transactions into a single Rollup block. A succinct cryptographic proof is generated off-chain for this block, which is then submitted to Ethereum’s Layer 1. The smart contract on Layer 1 only needs to verify this proof and apply the updated state directly without re-executing the transactions. This approach drastically reduces gas fees, as proof verification is far less resource-intensive than re-executing computations. Moreover, additional savings are achieved through data compression, as only the minimal data required for verification is kept on-chain. ### Challenges with zk-Rollups for General-Purpose dApps Despite their security and efficiency, zk-Rollups currently face limitations, particularly in the realm of general-purpose decentralized applications (dApps). These challenges stem from two primary factors: 1. **Complexity of Smart Contract Development:** Developers who wish to build dApps on a zk-Rollup must write all smart contract logic using specialized languages, such as R1CS (Rank-1 Constraint Systems). These languages are not only complex but also demand a deep understanding of zero-knowledge proofs, making development difficult and time-consuming. 2. **Lack of Composability:** Existing zk-Rollups do not support composability, meaning that different zk-Rollup applications cannot interact with each other within Layer 2. This limitation significantly hampers the interconnected nature of DeFi applications, which rely heavily on composability. These challenges make zk-Rollups developer-unfriendly and restrict their functionality, particularly for building complex dApps. ### The Solution: zkEVM (Zero-Knowledge Ethereum Virtual Machine) To address these issues, the focus has shifted towards enhancing developer experience and supporting composability within Layer 2 by enabling native EVM (Ethereum Virtual Machine) verification directly on zk-Rollups. This approach allows existing Ethereum applications to migrate onto zk-Rollups without requiring significant changes. There are two primary approaches to building general-purpose dApps on zk-Rollups: 1. **Application-Specific Circuits (ASIC):** This approach involves designing specialized circuits for different dApps. While it minimizes overhead through customized circuit design, it also introduces challenges such as reduced composability and a steep learning curve for developers. 2. **Universal EVM Circuit (zkEVM):** This approach seeks to create a universal "EVM circuit" that can verify any program execution on the EVM. The high-level idea is that any program will eventually run on a CPU, so by building a universal CPU circuit, we can verify low-level CPU operations, which in this case, represent smart contract execution on the EVM. Though the second approach has historically faced challenges due to its large overhead, recent advancements in zero-knowledge proof technology have made it increasingly viable. For instance, zk-friendly primitives like the Poseidon hash, improvements in verifiable VMs like TinyRAM, and optimization techniques such as Plookup are helping to make zkEVMs more efficient. ### What is a zkEVM? A zkEVM (Zero-Knowledge Ethereum Virtual Machine) is an EVM-compatible virtual machine that incorporates zero-knowledge proof computation. Unlike traditional virtual machines, a zkEVM not only executes smart contracts but also generates zero-knowledge proofs to verify the correctness of each step in the program’s execution, including the validity of inputs and outputs. ### Key Characteristics of zkEVM - **EVM Compatibility:** The Ethereum Virtual Machine (EVM) is the environment where smart contracts on Ethereum are executed. zkEVMs are EVM-compatible, meaning they can run existing Ethereum smart contracts without requiring significant modifications to the underlying logic. This compatibility is crucial for ensuring that developers can easily migrate their dApps to zk-Rollups. - **Support for Zero-Knowledge Technology:** The EVM was not originally designed to support zero-knowledge proofs, making zkEVM development challenging. However, advances in research have enabled the integration of zero-knowledge proofs into EVM computation, allowing for the creation of zkEVMs that combine the benefits of zero-knowledge technology with the versatility of the EVM. Different zkEVM projects adopt various approaches to integrating EVM execution with zero-knowledge proofs, each with its own set of trade-offs. However, the overarching goal is to create a developer-friendly environment that supports the seamless execution of smart contracts on zk-Rollups, thereby unlocking the full potential of Ethereum’s scalability. ## How a zkEVM Works A zkEVM, or Zero-Knowledge Ethereum Virtual Machine, functions similarly to the Ethereum Virtual Machine (EVM) in that it transitions between different states based on program operations. However, the zkEVM goes a step further by generating cryptographic proofs to verify the correctness of every aspect of the computation. This mechanism ensures that each step of the execution process adheres to the prescribed rules, adding an additional layer of security and integrity. To fully understand how a zkEVM operates, it’s helpful to first review how the EVM currently works. ### How the EVM Works The Ethereum Virtual Machine (EVM) is a state machine that transitions from one state to another in response to specific inputs. Every time a smart contract is executed, the EVM undergoes what is known as a "state transition." Here’s a simplified overview of the process during a smart contract transaction: 1. **Loading and Execution of Contract Bytecode:** The contract bytecode, which is compiled from the smart contract’s source code, is loaded from the EVM’s storage. This bytecode is then executed by peer-to-peer (P2P) nodes within the EVM. These nodes utilize the same transaction inputs, ensuring that each node arrives at the same result, which is essential for maintaining consensus across the network. 2. **Interaction with the EVM’s State:** The [EVM bytecode](https://www.ethervm.io/) contains opcodes, which are low-level instructions that interact with different components of the EVM’s state, such as memory, storage, and the stack. These opcodes perform various read-write operations, such as retrieving values from state storage or writing new values back into the EVM’s storage. 3. **Computation and State Transition:** The opcodes then perform computations on the retrieved values and return new results. This leads to the EVM transitioning to a new state, a process replicated by other nodes on the network. This new state persists until another transaction is executed, triggering another state transition. ![image](https://hackmd.io/_uploads/S1NLXDg30.png) ### Workflow for zkEVM While the general workflow may seem similar to that of the EVM, the underlying processes between Layer 1 (L1) and Layer 2 (L2) differ significantly when using zkEVM: - **Layer 1 (L1):** In the traditional EVM on Ethereum’s Layer 1, smart contracts are stored in Ethereum’s storage. When a transaction occurs, it is broadcasted to the P2P network, where each full node loads the corresponding bytecode and executes it on the EVM. The transaction data serves as input, and the execution process ensures that all nodes reach the same state. - **Layer 2 (L2) with zkEVM:** In contrast, zkEVM transactions occur off-chain on a centralized zkEVM node. While the bytecode is similarly stored and transactions are executed, the zkEVM does not merely execute the bytecode. Instead, it generates a succinct cryptographic proof that the state was updated correctly after applying the transaction. This proof is then submitted to an L1 smart contract, which verifies the proof and updates the state without re-executing the transaction. ### Detailed Execution Process in zkEVM In a zkEVM, the native execution process involves the EVM loading the bytecode and executing the opcodes one by one. Each opcode typically involves three steps: 1. **Reading:** Elements are read from the stack, memory, or storage. 2. **Computation:** The opcode performs computations on these elements. 3. **Writing:** The results are written back to the stack, memory, or storage. For example, an **add** opcode would read two elements from the stack, add them together, and write the result back to the stack. To ensure the accuracy of this process, the zkEVM proof must demonstrate the following: - **Correct Bytecode Loading:** Verifying that the correct opcode was loaded from the designated address in persistent storage. - **Sequential Execution:** Ensuring that the opcodes were executed in the correct order without missing or skipping any steps. - **Correct Execution of Each Opcode:** Confirming that each opcode was executed correctly, including all reading, computation, and writing operations. ### The Architecture of a zkEVM A zkEVM is composed of three main components: the execution environment, the proving circuit, and the verifier contract. Each plays a crucial role in the program’s execution, proof generation, and proof verification processes. 1. **Execution Environment:** This component is where the smart contracts are executed within the zkEVM. It functions similarly to the EVM, taking the initial state and the current transaction to produce a new, final state. 2. **Proving Circuit:** The proving circuit is responsible for generating zero-knowledge proofs that verify the validity of the transactions processed in the execution environment. It uses inputs such as the pre-state, transaction data, and post-state information to produce a succinct proof that confirms the validity of the state transition. 3. **Verifier Contract:** The final component is the verifier contract, which is deployed on Ethereum’s Layer 1. This contract receives the validity proof, along with the input (pre-state and transaction data) and output (final state) information. The verifier then runs computations on the provided proof to confirm that the submitted outputs were correctly derived from the inputs. Once verified, the L1 contract updates the state accordingly without re-executing the transactions. ![image](https://hackmd.io/_uploads/S1xpSDlh0.png) By combining these components, the zkEVM provides a powerful and secure way to scale Ethereum, enabling complex computations to be processed off-chain while maintaining the security and decentralization of the Ethereum network. ## zkEVM Opcodes zkEVM opcodes are the low-level machine instructions used to execute programs in a zkEVM, which is an EVM-compatible ZK-rollup. Similar to how the Ethereum Virtual Machine (EVM) operates, smart contracts written in high-level languages like Solidity are compiled into a low-level bytecode that specifies the opcodes. These opcodes are then used by the virtual machine to execute the program when it is deployed. However, standard EVM opcodes are not efficient for use in zero-knowledge (ZK) proving circuits, which are essential for zkEVMs. To address this challenge, there are two primary approaches to creating opcodes for zkEVMs: 1. **Building Zero-Knowledge Circuits for Native EVM Opcodes:** This approach involves implementing the entire set of EVM instructions within an arithmetic circuit. While this method is complex and time-consuming, it allows developers to write smart contracts using the existing tools and languages familiar to Ethereum developers. It also enables easy migration of existing Ethereum contracts to ZK-rollups with minimal changes. 2. **Creating New Languages for ZK Proof Computation:** The alternative approach is to design a new programming language specifically for zero-knowledge proof computation, along with custom opcodes tailored to this purpose. Developers can either write contracts directly in this new language or compile Solidity code into the new zkEVM-specific opcodes. Although this method might be simpler to implement, it comes with trade-offs, such as limited access to the existing Ethereum ecosystem and its associated resources. These approaches highlight the trade-offs between ease of implementation and compatibility with existing blockchain development environments. ## Challenges in Building a zkEVM Building a zkEVM is an inherently complex task due to several technical challenges. The Ethereum Virtual Machine (EVM) was not originally designed to support zero-knowledge (zk) proof computation, making the integration of zk proofs particularly difficult. Here are the key challenges: 1. **Special Opcodes** The EVM utilizes unique opcodes for various operations, such as program execution (**CALL**, **DELEGATECALL**) and error handling (**REVERT**, **INVALID**). These special opcodes introduce complexity in the design of the proving circuit, which must accurately represent and verify these operations within a zkEVM. 2. **Stack-Based Architecture** The EVM operates on a stack-based architecture, where data is pushed and popped from a stack during computation. While this architecture simplifies certain aspects of the EVM, it significantly complicates the process of proving computations in a zk environment. In contrast, many zkVMs, like ZkSync’s zkEVM and StarkWare’s StarkNet, use a register-based architecture, which is more conducive to zk proof generation. 3. **Storage Overhead** The EVM’s storage layout relies heavily on Keccak hashing functions and a Merkle Patricia Trie (MPT) structure. These components create substantial overhead in the proving process, as they require complex computations that are not zk-friendly. For example, while some zkVMs attempt to replace Keccak with more efficient hashing functions like Poseidon, doing so can break compatibility with existing Ethereum tools and infrastructure. 4. **Proving Costs** Even after addressing the above challenges, generating zk proofs remains a costly process. Proof generation demands specialized hardware and significant investments in time, money, and expertise. The process of composing proofs to create a complete EVM circuit is particularly resource-intensive. 5. **Elliptic Curve Limitations** The EVM has limited support for elliptic curves, currently only supporting the BN254 pairing. This limitation complicates the implementation of recursive proofs, which are essential for efficient zk proofs. Additionally, specialized protocols may be difficult to implement under these constraints, as the verification algorithms must be compatible with the EVM. 6. **256-Bit Word Size** The EVM operates on 256-bit integers, a word size significantly larger than the 32- or 64-bit integers used by most regular virtual machines. zk proofs, however, work most efficiently over prime fields, creating a mismatch that requires range proofs to reconcile. This mismatch adds approximately 100 constraints per EVM operation, greatly increasing the size and complexity of the zkEVM circuit. 7. **Machine-Based Proof Overhead** Even if all the above challenges are resolved, the overall process of generating machine-based proofs carries enormous overhead. For instance, even simple operations like addition can lead to substantial increases in the size of the zkEVM circuit, making it difficult to achieve efficient proof generation. These challenges collectively illustrate the significant difficulties in developing a zkEVM that is both efficient and fully compatible with the existing Ethereum ecosystem. Despite clear theoretical concepts, successfully implementing a native EVM circuit remains a formidable task. ## Importance of zkEVMs A fully functional zkEVM is crucial for the advancement of EVM-compatible ZK-rollup projects, offering several significant advantages: ### Secure Scalability Ethereum’s current scalability is limited by the protocol rule that requires all validating nodes to re-execute every computation performed within the Ethereum Virtual Machine (EVM). While this ensures security, it restricts the network’s ability to scale, limiting Ethereum to processing only about 15-20 transactions per second. EVM-compatible ZK-rollups address these scalability limitations without compromising security. Unlike traditional scaling solutions, ZK-rollups are not constrained by Ethereum’s consensus protocol and can optimize execution speed. Estimates suggest that ZK-rollups can process up to 2000 transactions per second without incurring the high costs associated with Ethereum. Moreover, ZK-rollups offer superior security guarantees compared to other scaling solutions. They use validity proofs to verify the correctness of off-chain computations, ensuring that transactions executed by smart contracts on Layer 2 (L2) can be reliably verified on Layer 1 (L1) without the need for nodes to re-execute operations. This allows for significantly faster processing speeds while maintaining robust security. ### Reduced Costs Both optimistic rollups and ZK-rollups rely on Ethereum Mainnet for security by writing transaction data to Ethereum as CALLDATA. However, they differ significantly in the amount of data they must post on-chain. Optimistic rollups, which do not provide validity proofs for off-chain transactions, must publish all transaction-related data on-chain, including signatures and transaction parameters. This is necessary to enable the construction of fraud proofs, which are used to challenge invalid rollup transactions. ZK-rollups, on the other hand, can minimize the amount of data posted to Ethereum because validity proofs already ensure the trustworthiness of state transitions. A zkEVM might even omit transaction inputs, publishing only the final state changes, which further reduces the CALLDATA requirements. This reduction in on-chain data significantly lowers the costs associated with using decentralized applications (dApps) on ZK-rollups, making them more accessible for users and developers. This cost-efficiency is particularly beneficial for high-traffic applications like decentralized exchanges, NFT marketplaces, and prediction markets. ### Faster Finality and Improved Capital Efficiency ZK-rollups offer another advantage over optimistic rollups: faster finality. In blockchain terminology, finality refers to the point at which a transaction becomes irreversible. For a transaction to achieve finality, network participants must have objective proof of its validity. With ZK-rollups, transactions executed in the zkEVM are often finalized immediately after being posted on Ethereum. Since each batch of transactions is accompanied by an instantly verifiable proof of validity, the Ethereum main chain can quickly apply state updates. In contrast, optimistic rollups lack immediate validity proofs and therefore require a challenge period—typically lasting 1-2 weeks—before transactions can achieve finality. During this period, anyone can challenge a transaction, creating delays in asset withdrawals and other processes. This slower finality can be problematic for users who need quick access to their assets, such as NFT traders, DeFi investors, or arbitrage traders. A zkEVM eliminates these issues by providing near-instant finality, enabling users to move assets seamlessly between L1 and L2 without the delays imposed by optimistic rollups. ### Leveraging Network Effects One of the most compelling reasons to develop EVM-compatible zkVMs is to leverage the network effects of Ethereum. As the world’s largest smart contract platform, Ethereum boasts a vast ecosystem that offers tremendous value to both developers and projects. Developers on Ethereum have access to a wealth of resources, including battle-tested and audited code libraries, extensive tooling, and comprehensive documentation. A zkVM that is incompatible with Ethereum’s existing infrastructure would isolate projects and development teams from these valuable resources, hindering innovation and growth. By ensuring compatibility with the EVM, zkEVMs enable projects to tap into Ethereum’s extensive network effects, fostering a more vibrant and interconnected ecosystem. This compatibility not only simplifies the migration of existing Ethereum projects to ZK-rollups but also encourages the development of new dApps that can benefit from Ethereum’s robust infrastructure. ## References 1. https://ethereum.org/en/developers/docs/intro-to-ethereum/ 2. https://ethereum.org/en/developers/docs/accounts/ 3. https://ethereum.org/en/developers/docs/data-structures-and-encoding/patricia-merkle-trie/ 4. https://en.wikipedia.org/wiki/Merkle_tree 5. https://medium.com/crypto-0-nite/merkle-proofs-explained-6dd429623dc5 6. https://en.wikipedia.org/wiki/Trie 7. https://en.wikipedia.org/wiki/Radix_tree 8. https://ethereum.org/en/developers/docs/data-structures-and-encoding/patricia-merkle-trie/ 9. https://ethereum.org/en/developers/docs/evm/ 10. https://ethereum.org/en/developers/docs/scaling/ 11. https://vitalik.eth.limo/general/2021/01/05/rollup.html 12. https://ethereum.org/en/developers/docs/scaling/zk-rollups/ 13. https://www.alchemy.com/overviews/zkevm 14. https://hackmd.io/@yezhang/S1_KMMbGt