# How to Build a zk-VM Application A zkVM enables anyone to verify that a program has been executed correctly. Developers can focus on writing program logic without needing to design circuits manually, as the zkVM automatically converts the logic into a constraint system. This approach operates at a higher level of abstraction, making development more accessible and efficient. ## Overview ```mermaid graph LR Guest_Code --> ELF_Binary --> zkVM --step2-4 --> Receipt ``` The core of a zkVM application is the **guest program/code**, which is the part of the application that undergoes verification. The **host** constructs and runs the **zkVM** (including both the **executor** and the **prover**). To prove the correct execution of the guest program: 1. Compiling the guest program into an **ELF binary**. 2. (Host) Using the executor to run the ELF binary and record the execution session. 3. (Host) Leveraging the prover to validate the recorded session and generate a proof (**receipt**). Anyone with the receipt can independently verify the correct execution of the guest program and access its publicly shared outputs. ## Let's Build ### Step 1: Create a New Project Create a template project by running: - `cargo risczero new [my_project_name] --guest-name [guest_code_for_zk_proof]` :::info If `guest_code_for_zk_proof = add`, then the the RISC-V ELF and the image ID will be `ADD_ELF` and `ADD_ID`. ::: See [this video tutorial](https://www.youtube.com/watch?v=Yg_BGqj_6lg&list=PLcPzhUaCxlCgig7ofeARMPwQ8vbuD6hC5) for a walk-through of how to build with this template. ### Step 2 (Host): Environment Setup and Share Private Data as Input with the Guest The code is located in `host/src/main.rs`. The host 1. sets up an execution environment using `ExecutorEnv` 2. adds `private input` to the executor environment, so that the guest can read it. ### Step 3 (Guest): Read Input and Commit Output The guest code is implemented and located in `methods/guest/src/main.rs`. The guest 1. reads the `private input` 2. computes guest program operations (eg. addition, multiplication, signing algorithm) 3. commits the `public output` to the journal in the receipt ### Step 4 (Host): Proof Generation and Validation The code is typically located in `host/src/main.rs` or `host/src/lib.rs`. ```rust // Obtain the default prover. let prover = default_prover(); // Produce a receipt by proving the specified ELF binary. prover.prove(env, SPECIFIC_ELF_BINARY).unwrap().receipt ``` The zkVM's executor processes the ELF binary, while its prover generates a zero-knowledge proof (receipt) certifying that the binary was executed as specified. ## Two Coding projects - [Addition Example](https://github.com/YaoJGalteland/addvm) demonstrates how to verify an addition inside the zkVM. - [ChaCha20 Encryption Example](https://github.com/YaoJGalteland/chacha20vm) demonstrates how to verify a ciphertext that has been encrypted using the ChaCha20 encryption algorithm within the zkVM. The prover proves that it has knowledge of the plaintext message and the encryption key used to produce the ChaCha20 ciphertext. ## References * [RISC0: zkVM](https://dev.risczero.com/api/zkvm/) * [SP1: zkVM](https://docs.succinct.xyz/what-is-a-zkvm.html) <!-- comment * [scroll: zkEVM](https://scroll.io/blog/zkevm) * [consensys: zkEVM](https://cdn.consensys.io/uploads/2022/10/07104712/a_specification_for_a_zk_evm.pdf) -->