{"id":228,"date":"2023-04-27T10:58:00","date_gmt":"2023-04-27T10:58:00","guid":{"rendered":"https:\/\/santiagomarquezsolis.com\/index.php\/2026\/04\/20\/what-is-a-zk-rollup-a-little-example-in-rust-2\/"},"modified":"2026-04-20T16:13:04","modified_gmt":"2026-04-20T16:13:04","slug":"what-is-a-zk-rollup-a-little-example-in-rust-2","status":"publish","type":"post","link":"https:\/\/santiagomarquezsolis.com\/index.php\/en\/2023\/04\/27\/what-is-a-zk-rollup-a-little-example-in-rust-2\/","title":{"rendered":"What is a zk-Rollup? A little example in Rust"},"content":{"rendered":"<p>A <strong>zk-rollup<\/strong> is a Layer 2 scalability solution for blockchains that leverages <strong>zero-knowledge proofs (ZK)<\/strong> to efficiently process transactions off-chain. By doing so, it reduces the computational load on the main blockchain (Layer 1) while preserving its inherent security and decentralization.<\/p>\n<h3><strong>How zk-Rollups Work<\/strong><\/h3>\n<ol>\n<li><strong>Batching Transactions<\/strong>: Instead of processing every individual transaction on the main blockchain, zk-rollups bundle many transactions together off-chain into a single batch or \u00abrollup.\u00bb<\/li>\n<li><strong>Zero-Knowledge Proofs (ZKP)<\/strong>: A <strong>zero-knowledge proof<\/strong> (typically a zk-SNARK or zk-STARK) is generated for the batch of transactions. This proof validates the correctness of all transactions in the batch without needing to reveal the details of each one.<\/li>\n<li><strong>On-Chain Verification<\/strong>: Only the cryptographic proof (which is small in size) and the resulting state changes (such as updated balances) are published on the main blockchain. This proof allows the main chain to confirm that the rollup batch is valid without processing each individual transaction.<\/li>\n<li><strong>Data Compression<\/strong>: zk-rollups dramatically reduce the amount of data that needs to be stored on-chain. Only the proof and a minimal amount of transaction data are required, which significantly increases throughput compared to directly processing every transaction on-chain.<\/li>\n<\/ol>\n<h3><strong>Key Characteristics of zk-Rollups<\/strong><\/h3>\n<ul>\n<li><strong>Efficiency<\/strong>: By processing a large number of transactions off-chain, zk-rollups reduce the data and computational resources required on the main blockchain, resulting in significantly higher transactions per second (TPS).<\/li>\n<li><strong>Security<\/strong>: ZK proofs ensure that even though transactions are processed off-chain, the validators of the main blockchain can trust their validity. If anyone attempts to publish an invalid transaction, the proof will fail, and the main chain will reject it.<\/li>\n<li><strong>Reduced Costs<\/strong>: Since zk-rollups require much less data to be published on the main blockchain, transaction fees are significantly lower.<\/li>\n<li><strong>Censorship Resistance<\/strong>: zk-rollups retain the security and decentralization of Layer 1. Users can always withdraw their funds to the main chain even if the rollup operators act maliciously.<\/li>\n<\/ul>\n<h3><strong>zk-Rollups vs. Other Rollups<\/strong><\/h3>\n<ol>\n<li><strong>Optimistic Rollups<\/strong>: Unlike <strong>optimistic rollups<\/strong>, which assume transactions are valid by default and rely on a challenge period for verification, zk-rollups provide immediate cryptographic proofs of validity for every batch of transactions. This means that there is no need for a waiting period, and transactions are final as soon as the proof is verified on-chain.<\/li>\n<li><strong>Computation Costs<\/strong>: zk-rollups may have higher computational costs to generate the proofs, as the zk-SNARK or zk-STARK calculations are complex. However, the advantage is instant verification on-chain, whereas optimistic rollups require a longer waiting period (typically 1-2 weeks) for transaction finality.<\/li>\n<\/ol>\n<h3><strong>Applications and Use Cases<\/strong><\/h3>\n<p>zk-rollups are one of the most promising solutions for scaling smart contract blockchains like Ethereum. Some key applications include:<\/p>\n<ul>\n<li><strong>Scaling Ethereum<\/strong>: zk-rollups enable Ethereum to handle thousands of transactions per second without compromising on security.<\/li>\n<li><strong>Decentralized Exchanges (DEX)<\/strong>: zk-rollups allow for efficient token swaps and trading on DEXs with significantly lower gas fees and increased throughput.<\/li>\n<li><strong>Fast, Low-Cost Payments<\/strong>: zk-rollups facilitate micropayments and high-frequency transactions without congesting the main chain.<\/li>\n<\/ul>\n<h3><strong>Projects Utilizing zk-Rollups<\/strong><\/h3>\n<p>Several notable projects are actively developing and using zk-rollups for various purposes:<\/p>\n<ul>\n<li><strong>zkSync<\/strong>: A scalability solution for Ethereum that focuses on payments and smart contract applications using zk-rollups.<\/li>\n<li><strong>Loopring<\/strong>: A decentralized exchange (DEX) protocol utilizing zk-rollups to enable efficient and low-cost token swaps for ERC-20 tokens.<\/li>\n<li><strong>StarkWare<\/strong>: A project that uses zk-STARKs (a variant of zk-SNARKs) to provide scalability and privacy solutions for blockchains.<\/li>\n<\/ul>\n<hr \/>\n<h2><strong>Implementing a Basic Zero-Knowledge Proof System in Rust<\/strong><\/h2>\n<p>To implement a simple zero-knowledge proof system in Rust, you can use the <code>bellman<\/code> library, which is designed to build zk-SNARKs using elliptic curve cryptography. Below is a step-by-step example of a basic implementation.<\/p>\n<h2><strong>Understanding the <code>bellman<\/code> Library<\/strong><\/h2>\n<h3><strong>What is <code>bellman<\/code>?<\/strong><\/h3>\n<p><code>bellman<\/code> is a Rust library specifically designed to facilitate the construction of zk-SNARK circuits. Developed by the Zcash team, it&#8217;s a highly flexible library that allows developers to create complex constraint systems over elliptic curves, generate zk-SNARK proofs, and verify them efficiently.<\/p>\n<p>It supports cryptographic operations over elliptic curve pairings like <strong>BN256<\/strong>, making it suitable for zero-knowledge proof systems that need to be both secure and performant.<\/p>\n<h3><strong>Key Features of <code>bellman<\/code>:<\/strong><\/h3>\n<ul>\n<li><strong>Circuit Synthesis<\/strong>: The library provides a way to construct circuits that define relationships between variables in a zero-knowledge proof system. Developers use these circuits to enforce constraints (e.g., ensuring a transaction is valid).<\/li>\n<li><strong>Groth16 zk-SNARKs<\/strong>: <code>bellman<\/code> focuses on implementing the <strong>Groth16<\/strong> zk-SNARK scheme, which is highly efficient in terms of proof size and verification speed.<\/li>\n<li><strong>Trusted Setup<\/strong>: The library allows the generation of <strong>trusted setup parameters<\/strong>, which are necessary for many zk-SNARK protocols to ensure security and efficiency.<\/li>\n<li><strong>Constraint System Abstractions<\/strong>: Through its trait-based abstractions, <code>bellman<\/code> provides a powerful way to define complex relationships, helping developers build and manipulate cryptographic proofs easily.<\/li>\n<\/ul>\n<h3><strong>Use Cases<\/strong><\/h3>\n<ul>\n<li><strong>Confidential Transactions<\/strong>: With <code>bellman<\/code>, developers can create circuits that prove the validity of transactions without revealing their details.<\/li>\n<li><strong>Privacy-preserving Computations<\/strong>: Applications that require privacy, such as identity verification or private voting, can be developed with <code>bellman<\/code> by constructing zero-knowledge proofs.<\/li>\n<\/ul>\n<h3><strong>Step-by-Step Code Example<\/strong><\/h3>\n<ol>\n<li><strong>Install Dependencies<\/strong>: Add the necessary dependencies in your <code>Cargo.toml<\/code> file:<\/li>\n<\/ol>\n<div class=\"dark bg-gray-950 contain-inline-size rounded-md border-[0.5px] border-token-border-medium relative\">\n<pre class=\"flex items-center text-token-text-secondary bg-token-main-surface-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9\">[dependencies]\r\nbellman = \"0.9\"\r\nff = \"0.10\"\r\ngroup = \"0.10\"\r\npairing = \"0.22\"\r\nrand = \"0.8\"\r\n\r\n<\/pre>\n<ol start=\"2\">\n<li><strong>Import Dependencies<\/strong>: Import the required crates in your main Rust file (<code>main.rs<\/code>):<\/li>\n<\/ol>\n<div class=\"dark bg-gray-950 contain-inline-size rounded-md border-[0.5px] border-token-border-medium relative\">\n<div class=\"flex items-center text-token-text-secondary bg-token-main-surface-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9\">\n<pre>extern crate bellman;\r\nextern crate pairing;\r\nextern crate ff;\r\nextern crate rand;\r\n\r\nuse bellman::{Circuit, ConstraintSystem, SynthesisError};\r\nuse ff::{Field, PrimeField};\r\nuse pairing::bn256::{Bn256, Fr}; \/\/ Fr is the prime field used by BN256\r\nuse bellman::groth16::{create_random_proof, generate_random_parameters, prepare_verifying_key, verify_proof};\r\nuse rand::thread_rng;<\/pre>\n<\/div>\n<ol start=\"3\">\n<li><strong>Create the Circuit<\/strong>: Define a simple circuit that validates the product of two input variables.<\/li>\n<\/ol>\n<div class=\"dark bg-gray-950 contain-inline-size rounded-md border-[0.5px] border-token-border-medium relative\">\n<div class=\"flex items-center text-token-text-secondary bg-token-main-surface-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9\">\n<pre>struct DemoCircuit {\r\n   pub a: Option&lt;Fr&gt;,\r\n   pub b: Option&lt;Fr&gt;,\r\n}\r\n\r\nimpl Circuit&lt;Fr&gt; for DemoCircuit {\r\n   fn synthesize&lt;CS: ConstraintSystem&lt;Fr&gt;&gt;(self, cs: &amp;mut CS) -&gt; Result&lt;(), SynthesisError&gt; {\r\n\r\n       \/\/ Allocate input variables\r\n       let a = cs.alloc(|| \"a\", || self.a.ok_or(SynthesisError::AssignmentMissing))?;\r\n       let b = cs.alloc(|| \"b\", || self.b.ok_or(SynthesisError::AssignmentMissing))?;\r\n\r\n       \/\/ Allocate output variable (the product a * b)\r\n       let c = cs.alloc_input(|| \"c\", || {\r\n       let a_val = self.a.ok_or(SynthesisError::AssignmentMissing)?;\r\n       let b_val = self.b.ok_or(SynthesisError::AssignmentMissing)?;\r\n       Ok(a_val * b_val)\r\n   })?;\r\n\r\n   \/\/ Enforce the constraint (a * b = c)\r\n   cs.enforce(\r\n      || \"multiplication constraint\",\r\n      |lc| lc + a,\r\n      |lc| lc + b,\r\n      |lc| lc + c,\r\n   );\r\n\r\n   Ok(())\r\n  }\r\n}<\/pre>\n<\/div>\n<ol start=\"4\">\n<li><strong>Generate System Parameters and Proof<\/strong>:<\/li>\n<\/ol>\n<div class=\"dark bg-gray-950 contain-inline-size rounded-md border-[0.5px] border-token-border-medium relative\">\n<div class=\"flex items-center text-token-text-secondary bg-token-main-surface-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md h-9\">\n<pre>fn main() {\r\n   \/\/ Initialize the RNG\r\n   let rng = &amp;mut thread_rng();\r\n\r\n   \/\/ Define trusted setup parameters\r\n   let params = {\r\n     let c = DemoCircuit { a: None, b: None };\r\n     generate_random_parameters::&lt;Bn256, _, _&gt;(c, rng).unwrap()\r\n   };\r\n\r\n   \/\/ Prepare the verifying key\r\n   let pvk = prepare_verifying_key(&amp;params.vk);\r\n\r\n   \/\/ Example proof with a = 3, b = 4, c = 12\r\n   let a_value = Fr::from_str_vartime(\"3\").unwrap();\r\n   let b_value = Fr::from_str_vartime(\"4\").unwrap();\r\n\r\n   \/\/ Create the proof\r\n   let proof = {\r\n      let c = DemoCircuit {  \r\n         a: Some(a_value),\r\n         b: Some(b_value),\r\n       };\r\n\r\n       create_random_proof(c, &amp;params, rng).unwrap()\r\n   };\r\n\r\n   \/\/ Verify the proof\r\n   let c_value = Fr::from_str_vartime(\"12\").unwrap();\r\n   let is_valid = verify_proof(&amp;pvk, &amp;proof, &amp;[c_value]).unwrap();\r\n   println!(\"Is the proof valid?: {}\", is_valid);\r\n}<\/pre>\n<\/div>\n<h3><strong>Code Explanation<\/strong><\/h3>\n<ul>\n<li><strong>Circuit<\/strong>: A circuit is created that takes two inputs, <code>a<\/code> and <code>b<\/code>, and ensures that their product equals a third value, <code>c<\/code>. The ZKP system enforces this multiplication constraint.<\/li>\n<li><strong>Trusted Setup Parameters<\/strong>: A random set of parameters is generated for the zk-SNARK proof system using an empty circuit template.<\/li>\n<li><strong>Proof Generation<\/strong>: Using concrete values for <code>a<\/code> and <code>b<\/code>, a zk-SNARK proof is created.<\/li>\n<li><strong>Proof Verification<\/strong>: The generated proof is verified using the verifying key and expected result (<code>c = 12<\/code>).<\/li>\n<\/ul>\n<h3><strong>Running the Code<\/strong><\/h3>\n<p>Upon running this program, a valid zk-SNARK proof is generated and verified, confirming that without revealing the values of <code>a<\/code> and <code>b<\/code>, the verifier can trust the equation <code>a * b = c<\/code>.<\/p>\n<h3><strong>Conclusion<\/strong><\/h3>\n<p>And nothing else \ud83d\ude09 zk-rollups use similar zero-knowledge principles to batch and prove transactions efficiently. This example provides a foundation for building more complex circuits and exploring advanced zk-rollup applications in Rust.<\/p>\n<p>Please share your comments with me and happy coding \ud83d\ude42<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>A zk-rollup is a Layer 2 scalability solution for blockchains that leverages zero-knowledge proofs (ZK) to efficiently process transactions off-chain. By doing so, it reduces the computational load on the main blockchain (Layer 1) while preserving its inherent security and decentralization. How zk-Rollups Work Batching Transactions: Instead of processing every individual transaction on the main [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[180,182,296],"tags":[184,294,172,298],"class_list":["post-228","post","type-post","status-publish","format-standard","hentry","category-blockchain-en","category-cripto-en","category-rust-en","tag-blockchain-en","tag-programacion-en","tag-rust-en","tag-zkp-en"],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/santiagomarquezsolis.com\/index.php\/wp-json\/wp\/v2\/posts\/228","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/santiagomarquezsolis.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/santiagomarquezsolis.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/santiagomarquezsolis.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/santiagomarquezsolis.com\/index.php\/wp-json\/wp\/v2\/comments?post=228"}],"version-history":[{"count":1,"href":"https:\/\/santiagomarquezsolis.com\/index.php\/wp-json\/wp\/v2\/posts\/228\/revisions"}],"predecessor-version":[{"id":254,"href":"https:\/\/santiagomarquezsolis.com\/index.php\/wp-json\/wp\/v2\/posts\/228\/revisions\/254"}],"wp:attachment":[{"href":"https:\/\/santiagomarquezsolis.com\/index.php\/wp-json\/wp\/v2\/media?parent=228"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/santiagomarquezsolis.com\/index.php\/wp-json\/wp\/v2\/categories?post=228"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/santiagomarquezsolis.com\/index.php\/wp-json\/wp\/v2\/tags?post=228"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}