From 6fe7283855a67ea8d1f1bbb593293d64526db26e Mon Sep 17 00:00:00 2001 From: Yuncong Zhang Date: Thu, 4 Sep 2025 19:50:31 +0800 Subject: [PATCH 01/20] Add doc --- .gitignore | 1 + docs/.gitignore | 1 + docs/book.toml | 5 ++ docs/src/1-overview.md | 21 ++++++++ docs/src/2-getting-started.md | 41 +++++++++++++++ docs/src/3-your-first-zk-program.md | 79 ++++++++++++++++++++++++++++ docs/src/4-host-guest-interaction.md | 57 ++++++++++++++++++++ docs/src/SUMMARY.md | 6 +++ 8 files changed, 211 insertions(+) create mode 100644 docs/.gitignore create mode 100644 docs/book.toml create mode 100644 docs/src/1-overview.md create mode 100644 docs/src/2-getting-started.md create mode 100644 docs/src/3-your-first-zk-program.md create mode 100644 docs/src/4-host-guest-interaction.md create mode 100644 docs/src/SUMMARY.md diff --git a/.gitignore b/.gitignore index d06650102..2fe60e62e 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ table_cache_dev_* .DS_Store .env proptest-regressions/ +docs/book # ceno serialized files *.bin diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 000000000..7585238ef --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1 @@ +book diff --git a/docs/book.toml b/docs/book.toml new file mode 100644 index 000000000..37035b62a --- /dev/null +++ b/docs/book.toml @@ -0,0 +1,5 @@ +[book] +authors = ["Yuncong Zhang"] +language = "en" +src = "src" +title = "Ceno Docs" diff --git a/docs/src/1-overview.md b/docs/src/1-overview.md new file mode 100644 index 000000000..acb81c3f7 --- /dev/null +++ b/docs/src/1-overview.md @@ -0,0 +1,21 @@ +# Ceno Project Overview + +Ceno is a non-uniform, segmentable, and parallelizable RISC-V Zero-Knowledge Virtual Machine (zkVM). It allows for the execution of Rust code in a verifiable manner, leveraging the power of zero-knowledge proofs. + +## Key Features + +- **RISC-V Architecture**: Ceno is built around the RISC-V instruction set, providing a standardized and open-source foundation for the virtual machine. +- **Zero-Knowledge Proofs**: The core of Ceno is its ability to generate zero-knowledge proofs of computation, ensuring that programs have been executed correctly without revealing any private inputs. +- **Rust Support**: Ceno is written in Rust and is designed to run programs also written in Rust, allowing developers to leverage the safety and performance of the Rust language. +- **Modularity**: The project is divided into several key components, each with a specific role in the Ceno ecosystem. + +## Project Structure + +The Ceno workspace is organized into the following main crates: + +- `ceno_cli`: A command-line interface for interacting with the Ceno zkVM. +- `ceno_emul`: Provides emulation capabilities for the RISC-V instruction set. +- `ceno_host`: The host component responsible for managing the zkVM and orchestrating the proof generation process. +- `ceno_rt`: The runtime environment for guest programs running within the zkVM. +- `ceno_zkvm`: The core zkVM implementation, including the prover and verifier. +- `examples`: A collection of example programs that demonstrate how to use Ceno. diff --git a/docs/src/2-getting-started.md b/docs/src/2-getting-started.md new file mode 100644 index 000000000..27fce31d4 --- /dev/null +++ b/docs/src/2-getting-started.md @@ -0,0 +1,41 @@ +# Getting Started + +This chapter will guide you through setting up your local development environment for Ceno and running your first zero-knowledge program. + +## Local Build Requirements + +Ceno is built in Rust, so you must [install the Rust toolchain](https://www.rust-lang.org/tools/install) first. + +We also use `cargo-make` to orchestrate the build process. You can install it with the following command: + +```sh +cargo install cargo-make +``` + +Ceno executes RISC-V instructions, so you will also need to install the Risc-V target for Rust. You can do this with the following command: + +```sh +rustup target add riscv32im-unknown-none-elf +``` + +## Running an Example + +The Ceno project includes a variety of [examples](https://github.com/scroll-tech/ceno/tree/master/examples/examples) to help you get started. We will run the Fibonacci example. + +This example calculates the `n`-th Fibonacci number, where `n` is determined by a hint value provided at runtime. For this guide, we will calculate the 1024-th number (corresponding to hint value `10` as `2^10=1024`) in the sequence. + +Execute the following command in the Ceno repository root directory to compile and run the end-to-end example: + +```sh +RUST_LOG=info cargo run --release --package ceno_zkvm --bin e2e -- --platform=ceno --hints=10 --public-io=4191 examples/target/riscv32im-ceno-zkvm-elf/release/examples/fibonacci +``` + +Let's break down the command: + +- `cargo run --release --package ceno_zkvm --bin e2e`: This command runs the end-to-end test binary from the `ceno_zkvm` crate in release mode. +- `--platform=ceno`: Specifies that we are running on the Ceno zkVM. +- `--hints=10`: This is a private input to our program. In this case, it tells the program to run 2^10 (1024) Fibonacci steps. +- `--public-io=4191`: This is the expected public output. The program will verify that the result of the computation matches this value. +- `examples/target/riscv32im-ceno-zkvm-elf/release/examples/fibonacci`: This is the path to the compiled guest program. + +If the command runs successfully, you have just run your first ZK program with Ceno! The next chapter will dive into the code for this example. diff --git a/docs/src/3-your-first-zk-program.md b/docs/src/3-your-first-zk-program.md new file mode 100644 index 000000000..e547126e8 --- /dev/null +++ b/docs/src/3-your-first-zk-program.md @@ -0,0 +1,79 @@ +# Your First ZK Program + +In the previous chapter, you ran a pre-compiled Fibonacci example. Now, let's look at the actual Rust code for that guest program and understand how it works. + +The goal of this program is to calculate the `n`-th Fibonacci number inside the Ceno zkVM and then commit the result to the public output. + +## The Code + +Here is the complete source code for the Fibonacci example (`examples/examples/fibonacci.rs`): + +```rust +extern crate ceno_rt; +use rkyv::Archived; + +fn main() { + // Compute the (1 << log_n) 'th fibonacci number, using normal Rust code. + let log_n: &Archived = ceno_rt::read(); + let log_n: u32 = log_n.into(); + let mut a = 0_u32; + let mut b = 1_u32; + let n = 1 << log_n; + for _ in 0..n { + let mut c = a + b; + c %= 7919; // Modulus to prevent overflow. + a = b; + b = c; + } + // Constrain with public io + ceno_rt::commit::, _>(&b); +} +``` + +## Code Breakdown + +Let's break down the key parts of this program. + +### 1. Importing the Ceno Runtime + +```rust +extern crate ceno_rt; +use rkyv::Archived; +``` + +Every Ceno guest program needs to import the `ceno_rt` crate. This crate provides essential functions for interacting with the zkVM environment, such as reading private inputs and committing public outputs. `rkyv` is used for zero-copy deserialization, which is how data is passed into the program. + +### 2. Reading Private Inputs + +```rust +let log_n: &Archived = ceno_rt::read(); +let log_n: u32 = log_n.into(); +``` + +The `ceno_rt::read()` function is used to read private data that the host provides. In the previous chapter, we passed `--hints=10`. This is the value that `ceno_rt::read()` retrieves. The program receives it as an `Archived`, which is then converted into a standard `u32`. + +### 3. Core Logic + +```rust +let mut a = 0_u32; +let mut b = 1_u32; +let n = 1 << log_n; +for _ in 0..n { + let mut c = a + b; + c %= 7919; // Modulus to prevent overflow. + a = b; + b = c; +} +``` + +This is standard Rust code for calculating a Fibonacci sequence. It uses the `log_n` input to determine the number of iterations (`n = 1 << log_n`, which is `2^10 = 1024`). The calculation is performed modulo `7919` to keep the numbers within a manageable size. + +This is a key takeaway: **You can write normal Rust code for your core computational logic.** + +### 4. Committing Public Output + +```rust +ceno_rt::commit::, _>(&b); +``` + +After the calculation is complete, `ceno_rt::commit()` is called. This function takes the final result (`b`) and commits it as a public output of the zkVM. The host can then verify that the program produced the correct public output. In our `run` command, this is checked against the `--public-io=4191` argument. diff --git a/docs/src/4-host-guest-interaction.md b/docs/src/4-host-guest-interaction.md new file mode 100644 index 000000000..3f3d2e1d9 --- /dev/null +++ b/docs/src/4-host-guest-interaction.md @@ -0,0 +1,57 @@ +# Host-Guest Interaction + +A critical aspect of developing ZK applications is understanding how the "host" (the machine running the prover) and the "guest" (the ZK program running inside the vm) communicate with each other. + +In Ceno, this communication happens in two main ways: +1. **Private Inputs (Hints)**: The host can pass private data to the guest. +2. **Public Inputs/Outputs (I/O)**: The guest can receive public data and commit to public outputs that the host can verify. + +We saw both of these in the command used to run the Fibonacci example: + +```sh +... --hints=10 --public-io=4191 ... +``` + +## Private Inputs (Hints) + +Private inputs, which Ceno refers to as "hints," are data known only to the host and the guest. They are not revealed publicly and do not become part of the final proof. This is the primary way to provide secret inputs to your ZK program. + +In the guest code, you use the `ceno_rt::read()` function to access this data. + +**Guest Code:** +```rust +// Reads the private hint value provided by the host. +let log_n: &Archived = ceno_rt::read(); +let log_n: u32 = log_n.into(); +``` + +**Host Command:** +```sh +... --hints=10 ... +``` + +In this interaction, the value `10` is passed from the host to the guest. The guest program reads this value and uses it to determine how many Fibonacci iterations to perform. This input remains private. + +## Public Inputs and Outputs + +Public I/O is data that is known to both the host and the verifier. It is part of the public record and is used to ensure the ZK program is performing the correct computation on the correct public data. + +In Ceno, the guest program can commit data to the public record using the `ceno_rt::commit()` function. + +**Guest Code:** +```rust +// Commits the final result `b` to the public output. +ceno_rt::commit::, _>(&b); +``` + +**Host Command:** +```sh +... --public-io=4191 ... +``` + +Here, the guest calculates the final Fibonacci number and commits the result `b`. The Ceno host environment then checks that this committed value is equal to the value provided in the `--public-io` argument (`4191`). If they do not match, the proof will fail, indicating an incorrect computation or a different result than expected. + +This mechanism is crucial for creating verifiable computations. You can use public I/O to: + +- Provide public inputs that the program must use. +- Assert that the program produces a specific, known public output. diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md new file mode 100644 index 000000000..385a5cca4 --- /dev/null +++ b/docs/src/SUMMARY.md @@ -0,0 +1,6 @@ +# Summary + +- [Overview](./1-overview.md) + - [Getting Started](./2-getting-started.md) + - [Your First ZK Program](./3-your-first-zk-program.md) + - [Host-Guest Interaction](./4-host-guest-interaction.md) From 0fba355373784c9050c0867130ad29318fcff8d0 Mon Sep 17 00:00:00 2001 From: Yuncong Zhang Date: Thu, 4 Sep 2025 20:05:18 +0800 Subject: [PATCH 02/20] Update doc to use cargo ceno --- README.md | 34 +++++++++------------------- docs/src/2-getting-started.md | 33 +++++++++++++++++++++------ docs/src/3-your-first-zk-program.md | 21 +++++++++++++++++ docs/src/4-host-guest-interaction.md | 2 +- 4 files changed, 59 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 0981b8e1b..25488690a 100644 --- a/README.md +++ b/README.md @@ -23,38 +23,26 @@ You will also need to install the Risc-V target for Rust. You can do this with t rustup target add riscv32im-unknown-none-elf ``` -## Try end-to-end with examples - -A variety of [examples](https://github.com/scroll-tech/ceno/tree/master/examples/examples) are availables. +## Installing `cargo ceno` -To run an example in e2e, use the following command: +The `cargo ceno` command is the primary tool for interacting with the Ceno zkVM. You can install it by running the following command from the root of the repository: ```sh -# release mode -RUST_LOG=info cargo run --release --package ceno_zkvm --bin e2e -- \ - --platform=ceno \ - --hints= \ - --public-io= \ - examples/target/riscv32im-ceno-zkvm-elf/release/examples/ - -# run a guest program with debug output (e.g., `debug_print` / `debug_println` visible), works in non-release mode -RUST_LOG=info cargo run --package ceno_zkvm --bin e2e -- \ - --platform=ceno \ - --hints= \ - --public-io= \ - examples/target/riscv32im-ceno-zkvm-elf/debug/examples/ +cargo install --path ceno_cli ``` -The example will be automatically compiled before execution +## Try end-to-end with examples -For instance, with [fibonacci](https://github.com/scroll-tech/ceno/blob/master/examples/examples/fibonacci.rs) -Below example command runs **2^10 (1024) Fibonacci steps** via `--hints=10`. -The expected result is `4191`, which will be used as the `--public-io=4191`. +A variety of [examples](https://github.com/scroll-tech/ceno/tree/master/examples/examples) are availables. + +To run an example, you first need to build it. You can run a specific example using the `cargo ceno run` command. For instance, to run the [fibonacci](https://github.com/scroll-tech/ceno/blob/master/examples/examples/fibonacci.rs) example, use the following command: ```sh -RUST_LOG=info cargo run --release --package ceno_zkvm --bin e2e -- --platform=ceno --hints=10 --public-io=4191 examples/target/riscv32im-ceno-zkvm-elf/release/examples/fibonacci +cargo ceno run --example fibonacci --hints=10 --public-io=4191 ``` +This command runs **2^10 (1024) Fibonacci steps** via `--hints=10`. The expected result is `4191`, which is verified against the `--public-io=4191` argument. + ## Building Ceno and running tests To run the tests, you can use the following command: @@ -82,7 +70,7 @@ docker run -d ceno-runner ### Acknowledgements -Ceno stands on the shoulders of remarkable projects in the zero-knowledge ecosystem. +Ceno stands on the shoulders of remarkable projects in the zero-knowledge ecosystem. We extend our appreciation to the following works, which have shaped Ceno's design and direction: - [Plonky3](https://github.com/Plonky3/Plonky3) — Inspired by Plonky3’s modular architecture, enabling support for diff --git a/docs/src/2-getting-started.md b/docs/src/2-getting-started.md index 27fce31d4..515cf32e4 100644 --- a/docs/src/2-getting-started.md +++ b/docs/src/2-getting-started.md @@ -15,27 +15,46 @@ cargo install cargo-make Ceno executes RISC-V instructions, so you will also need to install the Risc-V target for Rust. You can do this with the following command: ```sh -rustup target add riscv32im-unknown-none-elf +rustup target add riscv32im-ceno-zkvm-elf ``` +## Installing `cargo ceno` + +The `cargo ceno` command is the primary tool for interacting with the Ceno zkVM. You can install it by running the following command from the root of the repository: + +```sh +cargo install --path ceno_cli +``` + +## Building the Examples + +The Ceno project includes a variety of [examples](https://github.com/scroll-tech/ceno/tree/master/examples/examples) to help you get started. + +You can build all the examples using the `cargo ceno` command-line tool. Execute the following command in the Ceno repository root directory: + +```sh +cargo ceno build --example fibonacci +``` + +This command will compile the example `fibonacci` located in the `examples/examples` directory and place the resulting ELF files in the `examples/target/riscv32im-ceno-zkvm-elf/release` directory. + ## Running an Example -The Ceno project includes a variety of [examples](https://github.com/scroll-tech/ceno/tree/master/examples/examples) to help you get started. We will run the Fibonacci example. +Once the examples are built, you can run any of them using the `cargo ceno run` command. We will run the Fibonacci example. This example calculates the `n`-th Fibonacci number, where `n` is determined by a hint value provided at runtime. For this guide, we will calculate the 1024-th number (corresponding to hint value `10` as `2^10=1024`) in the sequence. -Execute the following command in the Ceno repository root directory to compile and run the end-to-end example: +Execute the following command in the Ceno repository root directory to run the Fibonacci example: ```sh -RUST_LOG=info cargo run --release --package ceno_zkvm --bin e2e -- --platform=ceno --hints=10 --public-io=4191 examples/target/riscv32im-ceno-zkvm-elf/release/examples/fibonacci +cargo ceno run --example fibonacci --hints=10 --public-io=4191 ``` Let's break down the command: -- `cargo run --release --package ceno_zkvm --bin e2e`: This command runs the end-to-end test binary from the `ceno_zkvm` crate in release mode. -- `--platform=ceno`: Specifies that we are running on the Ceno zkVM. +- `cargo ceno run`: This is the command to run a Ceno program. +- `--example fibonacci`: This specifies that we want to run the `fibonacci` example. - `--hints=10`: This is a private input to our program. In this case, it tells the program to run 2^10 (1024) Fibonacci steps. - `--public-io=4191`: This is the expected public output. The program will verify that the result of the computation matches this value. -- `examples/target/riscv32im-ceno-zkvm-elf/release/examples/fibonacci`: This is the path to the compiled guest program. If the command runs successfully, you have just run your first ZK program with Ceno! The next chapter will dive into the code for this example. diff --git a/docs/src/3-your-first-zk-program.md b/docs/src/3-your-first-zk-program.md index e547126e8..c4fad7bab 100644 --- a/docs/src/3-your-first-zk-program.md +++ b/docs/src/3-your-first-zk-program.md @@ -77,3 +77,24 @@ ceno_rt::commit::, _>(&b); ``` After the calculation is complete, `ceno_rt::commit()` is called. This function takes the final result (`b`) and commits it as a public output of the zkVM. The host can then verify that the program produced the correct public output. In our `run` command, this is checked against the `--public-io=4191` argument. + + +## Building the Program + +To build this program so that it can be run inside the Ceno zkVM, you can use the `cargo ceno build` command: + +```sh +cargo ceno build --example fibonacci +``` + +This will produce an ELF file at `examples/target/riscv32im-ceno-zkvm-elf/release/fibonacci`. This is the file that is executed by the `run` command. + +## Running the Program + +As you saw in the previous chapter, you can run the program with `cargo ceno run`: + +```sh +cargo ceno run --example fibonacci --hints=10 --public-io=4191 +``` + +Now that you understand the basic components of a Ceno program, the next chapter will explore the interaction between the host and the guest in more detail. diff --git a/docs/src/4-host-guest-interaction.md b/docs/src/4-host-guest-interaction.md index 3f3d2e1d9..a8d1fd853 100644 --- a/docs/src/4-host-guest-interaction.md +++ b/docs/src/4-host-guest-interaction.md @@ -9,7 +9,7 @@ In Ceno, this communication happens in two main ways: We saw both of these in the command used to run the Fibonacci example: ```sh -... --hints=10 --public-io=4191 ... +cargo ceno run --example fibonacci --hints=10 --public-io=4191 ``` ## Private Inputs (Hints) From 7f3b924edebb1c0665f969149c1c9eda903423e9 Mon Sep 17 00:00:00 2001 From: Yuncong Zhang Date: Thu, 4 Sep 2025 20:36:33 +0800 Subject: [PATCH 03/20] Update doc to add additional contents --- docs/src/SUMMARY.md | 15 ++++-- docs/src/advanced-topics.md | 6 +++ docs/src/ceno-cli.md | 17 ++++++ docs/src/examples-walkthrough.md | 5 ++ docs/src/generating-and-verifying-proofs.md | 54 +++++++++++++++++++ ...-getting-started.md => getting-started.md} | 0 docs/src/guest-programming.md | 12 +++++ ...teraction.md => host-guest-interaction.md} | 0 docs/src/{1-overview.md => overview.md} | 0 docs/src/precompiles.md | 37 +++++++++++++ docs/src/profiling.md | 22 ++++++++ ...zk-program.md => your-first-zk-program.md} | 0 12 files changed, 164 insertions(+), 4 deletions(-) create mode 100644 docs/src/advanced-topics.md create mode 100644 docs/src/ceno-cli.md create mode 100644 docs/src/examples-walkthrough.md create mode 100644 docs/src/generating-and-verifying-proofs.md rename docs/src/{2-getting-started.md => getting-started.md} (100%) create mode 100644 docs/src/guest-programming.md rename docs/src/{4-host-guest-interaction.md => host-guest-interaction.md} (100%) rename docs/src/{1-overview.md => overview.md} (100%) create mode 100644 docs/src/precompiles.md create mode 100644 docs/src/profiling.md rename docs/src/{3-your-first-zk-program.md => your-first-zk-program.md} (100%) diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index 385a5cca4..2b27047b8 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -1,6 +1,13 @@ # Summary -- [Overview](./1-overview.md) - - [Getting Started](./2-getting-started.md) - - [Your First ZK Program](./3-your-first-zk-program.md) - - [Host-Guest Interaction](./4-host-guest-interaction.md) +- [Overview](./overview.md) +- [Getting Started](./getting-started.md) +- [Your First ZK Program](./your-first-zk-program.md) +- [Host-Guest Interaction](./host-guest-interaction.md) +- [Generating and Verifying Proofs](./generating-and-verifying-proofs.md) +- [The `ceno` CLI](./ceno-cli.md) +- [Guest Programming (`ceno_rt`)](./guest-programming.md) +- [Accelerated Operations with Precompiles (Syscalls)](./precompiles.md) +- [Profiling & Performance](./profiling.md) +- [Walkthroughs of Examples](./examples-walkthrough.md) +- [Advanced Topics](./advanced-topics.md) diff --git a/docs/src/advanced-topics.md b/docs/src/advanced-topics.md new file mode 100644 index 000000000..c323e0929 --- /dev/null +++ b/docs/src/advanced-topics.md @@ -0,0 +1,6 @@ +# Advanced Topics + +This chapter is for developers who want to dive deeper into the internals of Ceno. + +- **Ceno Internals** *(Content to be added)* +- **The GKR Protocol** *(Content to be added)* diff --git a/docs/src/ceno-cli.md b/docs/src/ceno-cli.md new file mode 100644 index 000000000..7c3db3793 --- /dev/null +++ b/docs/src/ceno-cli.md @@ -0,0 +1,17 @@ +# The `ceno` CLI + +The `ceno` command-line interface is the primary way to interact with the Ceno ZKVM. It allows you to build, run, and verify your ZK programs. + +The available commands are: + +- `cargo ceno build`: Compiles a guest program written in Rust into a RISC-V ELF file. +- `cargo ceno info`: Provides information about a compiled ELF file, such as its size and segments. +- `cargo ceno keygen`: Generates a proving key and a verification key for a guest program. +- `cargo ceno prove`: Compiles, runs, and proves a Ceno guest program in one go. +- `cargo ceno run`: Executes a guest program and generates a witness of its execution. +- `cargo ceno verify`: Verifies a proof generated by `cargo ceno prove`. +- `cargo ceno raw-keygen`: A lower-level command to generate keys from a compiled ELF file. +- `cargo ceno raw-prove`: A lower-level command to prove a program from a compiled ELF file and a witness. +- `cargo ceno raw-run`: A lower-level command to run a program without the full proof generation, useful for debugging. + +For detailed usage of each command, you can use the `--help` flag, for example: `cargo ceno run --help`. diff --git a/docs/src/examples-walkthrough.md b/docs/src/examples-walkthrough.md new file mode 100644 index 000000000..1c93a6cef --- /dev/null +++ b/docs/src/examples-walkthrough.md @@ -0,0 +1,5 @@ +# Walkthroughs of Examples + +This chapter will contain detailed walkthroughs of selected examples from the `examples/` directory. + +*(Content to be added)* diff --git a/docs/src/generating-and-verifying-proofs.md b/docs/src/generating-and-verifying-proofs.md new file mode 100644 index 000000000..528c4e171 --- /dev/null +++ b/docs/src/generating-and-verifying-proofs.md @@ -0,0 +1,54 @@ +# Generating and Verifying Proofs + +The `cargo ceno` command provides a streamlined workflow for generating and verifying proofs of your ZK programs. This is handled primarily by the `prove` and `verify` subcommands. + +## Proof Generation with `cargo ceno prove` + +The `cargo ceno prove` command compiles, runs, and proves a Ceno guest program in one go. It takes the guest program's package as an argument and produces a proof file. + +```bash +cargo ceno prove --package +``` + +This command will: + +1. Compile the guest program into a RISC-V ELF file. +2. Run the ELF file in the Ceno ZKVM. +3. Generate a proof of the execution. +4. Save the proof to a file, typically named `.proof` in the `target/` directory. + +You can also specify the output path for the proof file: + +```bash +cargo ceno prove --package --output +``` + +## Verification with `cargo ceno verify` + +Once you have a proof file, you can verify it using the `cargo ceno verify` command. This command takes the proof file as an argument and checks its validity. + +```bash +cargo ceno verify +``` + +If the proof is valid, the command will exit successfully. If the proof is invalid, it will report an error. + +## The Proving Process in Detail + +The `prove` command is a convenient wrapper around a multi-step process. Here's a more detailed look at the steps involved in generating a proof: + +1. **Key Generation (`cargo ceno keygen`):** Before proving, you need a proving key and a verification key. The `keygen` command generates these keys for a given guest program. + + ```bash + cargo ceno keygen --package --proving-key-path --verifying-key-path + ``` + +2. **Execution and Witness Generation (`cargo ceno run`):** The `run` command executes the program and generates a "witness", which is a record of the execution trace. This witness is then used in the proving step. + + ```bash + cargo ceno run --package --witness-path + ``` + +3. **Proof Generation (using the witness):** The final step is to use the proving key and the witness to generate the proof. The `prove` command automates this, but you can also perform this step manually using the lower-level `raw-prove` command if you have the ELF file, proving key, and witness. + +By using `cargo ceno prove`, you get a simplified experience that handles these steps for you. For most use cases, `cargo ceno prove` and `cargo ceno verify` are the primary commands you will use. diff --git a/docs/src/2-getting-started.md b/docs/src/getting-started.md similarity index 100% rename from docs/src/2-getting-started.md rename to docs/src/getting-started.md diff --git a/docs/src/guest-programming.md b/docs/src/guest-programming.md new file mode 100644 index 000000000..c3dffa0ee --- /dev/null +++ b/docs/src/guest-programming.md @@ -0,0 +1,12 @@ +# Guest Programming (`ceno_rt`) + +The `ceno_rt` crate provides the runtime environment for guest programs running inside the Ceno ZKVM. It offers essential functionalities for interacting with the host and the ZKVM environment. + +Key features of `ceno_rt` include: + +- **I/O:** Functions for reading input from the host and writing output. See the `ceno_rt::io` module. +- **Memory Management:** A simple allocator for dynamic memory allocation within the guest. See the `ceno_rt::allocator` module. +- **Syscalls:** Low-level functions to access precompiled operations for performance-critical tasks. See the `ceno_rt::syscalls` module and the "Accelerated Operations with Precompiles" chapter. +- **Panicking:** Macros and functions for handling unrecoverable errors in the guest. + +When writing a guest program, you will typically include `ceno_rt` as a dependency in your `Cargo.toml`. diff --git a/docs/src/4-host-guest-interaction.md b/docs/src/host-guest-interaction.md similarity index 100% rename from docs/src/4-host-guest-interaction.md rename to docs/src/host-guest-interaction.md diff --git a/docs/src/1-overview.md b/docs/src/overview.md similarity index 100% rename from docs/src/1-overview.md rename to docs/src/overview.md diff --git a/docs/src/precompiles.md b/docs/src/precompiles.md new file mode 100644 index 000000000..8c96cbd38 --- /dev/null +++ b/docs/src/precompiles.md @@ -0,0 +1,37 @@ +# Accelerated Operations with Precompiles (Syscalls) + +Ceno provides "precompiles" to accelerate common, computationally intensive operations. These are implemented as `syscalls` that the guest program can invoke. Using precompiles is much more efficient than executing the equivalent logic in standard RISC-V instructions. + +## Using Precompiles + +To use a precompile, you need to call the corresponding function from the `ceno_rt::syscalls` module in your guest code. + +For example, to compute a Keccak permutation, you can use `syscall_keccak_permute`: + +```rust +use ceno_rt::syscalls::syscall_keccak_permute; + +let mut state = [0u64; 25]; +// ... initialize state ... +syscall_keccak_permute(&mut state); +``` + +## Available Precompiles + +Ceno currently offers the following precompiles: + +- **Hashing:** + - `syscall_keccak_permute`: For Keccak-f[1600] permutation, the core of Keccak and SHA-3. + - `syscall_sha256_extend`: For the SHA-256 message schedule (`W` table) extension. + +- **Cryptography:** + - `syscall_secp256k1_add`: Elliptic curve addition on secp256k1. + - `syscall_secp256k1_double`: Elliptic curve point doubling on secp256k1. + - `syscall_secp256k1_decompress`: Decompress a secp256k1 public key. + - `syscall_bn254_add`: Elliptic curve addition on BN254. + - `syscall_bn254_double`: Elliptic curve point doubling on BN254. + - `syscall_bn254_fp_addmod`, `syscall_bn254_fp_mulmod`: Field arithmetic for BN254's base field. + - `syscall_bn254_fp2_addmod`, `syscall_bn254_fp2_mulmod`: Field arithmetic for BN254's quadratic extension field. + + +You can find examples of how to use each of these syscalls in the `examples/` directory of the project. diff --git a/docs/src/profiling.md b/docs/src/profiling.md new file mode 100644 index 000000000..f9a9183b5 --- /dev/null +++ b/docs/src/profiling.md @@ -0,0 +1,22 @@ +# Profiling & Performance + +Ceno includes tools to help you analyze and optimize the performance of your ZK programs. + +## Execution Profiling + +You can profile the execution of your guest program by using the `--profiling` flag with the `ceno run` or other binary commands. This will output detailed statistics about the execution, such as cycle counts for different parts of the program. + +For example: +```bash +ceno run --profiling=1 -- +``` + +The value passed to `--profiling` controls the granularity of the profiling information. + +The output will show a tree of spans with timing information, allowing you to identify performance bottlenecks in your code. + +## Benchmarking + +The `ceno_zkvm` crate contains a `benches` directory with several benchmarks. You can use these as a reference for writing your own benchmarks using `criterion`. + +Running the benchmarks can give you an idea of the performance of different operations and help you optimize your code. To run the benchmarks, you can use the standard `cargo bench` command. diff --git a/docs/src/3-your-first-zk-program.md b/docs/src/your-first-zk-program.md similarity index 100% rename from docs/src/3-your-first-zk-program.md rename to docs/src/your-first-zk-program.md From 302d09da89dec6f2b30a8dc73ed5f237aca29d47 Mon Sep 17 00:00:00 2001 From: Yuncong Zhang Date: Fri, 5 Sep 2025 09:06:31 +0800 Subject: [PATCH 04/20] Update generating and verifying proof --- docs/src/SUMMARY.md | 14 +- docs/src/generating-and-verifying-proofs.md | 153 +++++++++++++++++--- 2 files changed, 137 insertions(+), 30 deletions(-) diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index 2b27047b8..744cb96ba 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -1,13 +1,13 @@ # Summary - [Overview](./overview.md) -- [Getting Started](./getting-started.md) -- [Your First ZK Program](./your-first-zk-program.md) -- [Host-Guest Interaction](./host-guest-interaction.md) -- [Generating and Verifying Proofs](./generating-and-verifying-proofs.md) + - [Getting Started](./getting-started.md) + - [Your First ZK Program](./your-first-zk-program.md) + - [Host-Guest Interaction](./host-guest-interaction.md) + - [Generating and Verifying Proofs](./generating-and-verifying-proofs.md) - [The `ceno` CLI](./ceno-cli.md) -- [Guest Programming (`ceno_rt`)](./guest-programming.md) -- [Accelerated Operations with Precompiles (Syscalls)](./precompiles.md) -- [Profiling & Performance](./profiling.md) - [Walkthroughs of Examples](./examples-walkthrough.md) - [Advanced Topics](./advanced-topics.md) + - [Guest Programming (`ceno_rt`)](./guest-programming.md) + - [Accelerated Operations with Precompiles (Syscalls)](./precompiles.md) + - [Profiling & Performance](./profiling.md) diff --git a/docs/src/generating-and-verifying-proofs.md b/docs/src/generating-and-verifying-proofs.md index 528c4e171..f4ab00871 100644 --- a/docs/src/generating-and-verifying-proofs.md +++ b/docs/src/generating-and-verifying-proofs.md @@ -1,54 +1,161 @@ # Generating and Verifying Proofs -The `cargo ceno` command provides a streamlined workflow for generating and verifying proofs of your ZK programs. This is handled primarily by the `prove` and `verify` subcommands. +The `cargo ceno` command provides a streamlined workflow for generating and verifying proofs of your ZK programs. This is handled primarily by the `keygen`, `prove` and `verify` subcommands. -## Proof Generation with `cargo ceno prove` +Here's a more detailed look at the steps involved in generating a proof: -The `cargo ceno prove` command compiles, runs, and proves a Ceno guest program in one go. It takes the guest program's package as an argument and produces a proof file. +1. **Key Generation (`cargo ceno keygen`):** Before proving, you need a proving key and a verification key. The `keygen` command generates these keys for a given guest program. + + ```bash + cargo ceno keygen --example --out-vk + ``` + +2. **Proof Generation (using the witness):** The final step is to use the proving key and the witness to generate the proof. The `prove` command automates this, but you can also perform this step manually using the lower-level `raw-prove` command if you have the ELF file, proving key, and witness. + +By using `cargo ceno prove`, you get a simplified experience that handles these steps for you. For most use cases, `cargo ceno prove` and `cargo ceno verify` are the primary commands you will use. ```bash -cargo ceno prove --package +cargo ceno prove --example --hints= --public-io= --out-vk --out-proof target/fibonacci.proof ``` -This command will: +## Concrete Example: Fibonacci -1. Compile the guest program into a RISC-V ELF file. -2. Run the ELF file in the Ceno ZKVM. -3. Generate a proof of the execution. -4. Save the proof to a file, typically named `.proof` in the `target/` directory. +Let's walk through a concrete example using the `fibonacci` guest program included in the `examples` directory. -You can also specify the output path for the proof file: +### 1. Writing the Code + +The `fibonacci` example is already written. You can find it in `examples/examples/fibonacci.rs`. This program calculates the `n`-th Fibonacci number. + +### 2. Key Generation + +Before generating a proof, you need to generate a verification key. You can do this with the `keygen` subcommand: ```bash -cargo ceno prove --package --output +cargo ceno keygen --example fibonacci --out-vk target/fibonacci.vk ``` -## Verification with `cargo ceno verify` +This will create a `fibonacci.vk` file (the verification key) in the `target` directory. + +### 3. Generating the Proof -Once you have a proof file, you can verify it using the `cargo ceno verify` command. This command takes the proof file as an argument and checks its validity. +To generate a proof for the `fibonacci` program, run the following command from the root of the project: ```bash -cargo ceno verify +cargo ceno prove --example fibonacci --out-proof target/fibonacci.proof ``` -If the proof is valid, the command will exit successfully. If the proof is invalid, it will report an error. +This command will compile the `fibonacci` package, execute it in the ZKVM, and generate a proof file named `fibonacci.proof` in the `target` directory. It will also generate the verification key. -## The Proving Process in Detail +### 4. Verifying the Proof -The `prove` command is a convenient wrapper around a multi-step process. Here's a more detailed look at the steps involved in generating a proof: +Now that you have a proof file, you can verify it with the following command: -1. **Key Generation (`cargo ceno keygen`):** Before proving, you need a proving key and a verification key. The `keygen` command generates these keys for a given guest program. +```bash +cargo ceno verify --proof target/fibonacci.proof --vk target/fibonacci.vk +``` + +If the proof is valid, you will see a confirmation message, and the command will exit successfully. + +## Using a custom program + +You can also use `ceno` to generate proofs for your own custom Rust programs. Let's walk through how to set up a new project and use `ceno` with it. + +### 1. Project Setup + +First, create a new binary crate with `cargo`: + +```bash +cargo new my-ceno-program +cd my-ceno-program +``` + +Your project will have the following structure: + +``` +my-ceno-program/ +├── Cargo.toml +└── src/ + └── main.rs +``` + +### 2. Cargo.toml + +Next, you need to add `ceno_rt` as a dependency in your `Cargo.toml`. `ceno_rt` provides the runtime environment and syscalls for guest programs. + +```toml +[package] +name = "my-ceno-program" +version = "0.1.0" +edition = "2024" + +[dependencies] +ceno_rt = { git = "https://github.com/scroll-tech/ceno.git" } +rkyv = { version = "0.8", default-features = false, features = [ + "alloc", + "bytecheck", +] } +``` + +_Note: For local development, you can use a path dependency: `ceno_rt = { path = "../ceno/ceno_rt" }`_ + +### 3. Writing the Guest Program + +Now, let's write a simple guest program in `src/main.rs`. This program will read two `u32` values from the input, add them, and write the result to the output. + +```rust +extern crate ceno_rt; +use rkyv::Archived; + +fn main() { + let a: &Archived = ceno_rt::read(); + let a: u32 = a.into(); + let b: u32 = 3; + let c = a.wrapping_add(b); + + ceno_rt::commit::, _>(&c); +} +``` + +### 4. Building, Proving, and Verifying + +With your custom program ready, you can use `ceno` to manage the workflow. These commands are typically run from the root of your project (`my-ceno-program`). + +1. **Build the program:** + + The `build` command compiles your guest program into a RISC-V ELF file. ```bash - cargo ceno keygen --package --proving-key-path --verifying-key-path + cargo ceno build ``` -2. **Execution and Witness Generation (`cargo ceno run`):** The `run` command executes the program and generates a "witness", which is a record of the execution trace. This witness is then used in the proving step. + This will create an ELF file at `target/riscv32im-ceno-zkvm-elf/debug/my-ceno-program`. + +2. **Generate Keys:** + + Next, generate the proving and verification keys. ```bash - cargo ceno run --package --witness-path + cargo ceno keygen --out-vk vk.bin ``` -3. **Proof Generation (using the witness):** The final step is to use the proving key and the witness to generate the proof. The `prove` command automates this, but you can also perform this step manually using the lower-level `raw-prove` command if you have the ELF file, proving key, and witness. + This will save the keys in a `keys` directory. -By using `cargo ceno prove`, you get a simplified experience that handles these steps for you. For most use cases, `cargo ceno prove` and `cargo ceno verify` are the primary commands you will use. +3. **Generate a Proof:** + + Now, run the program and generate a proof. You can provide input via the `--stdin` flag. + + ```bash + cargo ceno prove --hints=5 --public-io=8 --out-proof proof.bin + ``` + + This command executes the ELF, generates a proof, and saves it as `proof.bin`. The output of the program will be printed to your console. + +4. **Verify the Proof:** + + Finally, verify the generated proof. + + ```bash + cargo ceno verify --vk vk.bin --proof proof.bin + ``` + +If the proof is valid, you'll see a success message. This workflow allows you to integrate `ceno`'s proving capabilities into your own Rust projects. From ac328afcbbc39cd8211727c5202129fb81d65a4c Mon Sep 17 00:00:00 2001 From: Yuncong Zhang Date: Fri, 5 Sep 2025 09:08:50 +0800 Subject: [PATCH 05/20] Remove gitignore in docs --- docs/.gitignore | 1 - 1 file changed, 1 deletion(-) delete mode 100644 docs/.gitignore diff --git a/docs/.gitignore b/docs/.gitignore deleted file mode 100644 index 7585238ef..000000000 --- a/docs/.gitignore +++ /dev/null @@ -1 +0,0 @@ -book From 76f59f49af216bae0467a80f794605a118f1f9d7 Mon Sep 17 00:00:00 2001 From: Yuncong Zhang Date: Fri, 5 Sep 2025 09:20:24 +0800 Subject: [PATCH 06/20] Remove fibonacci example --- docs/src/generating-and-verifying-proofs.md | 42 +-------------------- 1 file changed, 2 insertions(+), 40 deletions(-) diff --git a/docs/src/generating-and-verifying-proofs.md b/docs/src/generating-and-verifying-proofs.md index f4ab00871..9cc0220ae 100644 --- a/docs/src/generating-and-verifying-proofs.md +++ b/docs/src/generating-and-verifying-proofs.md @@ -18,47 +18,9 @@ By using `cargo ceno prove`, you get a simplified experience that handles these cargo ceno prove --example --hints= --public-io= --out-vk --out-proof target/fibonacci.proof ``` -## Concrete Example: Fibonacci +## Concrete Example -Let's walk through a concrete example using the `fibonacci` guest program included in the `examples` directory. - -### 1. Writing the Code - -The `fibonacci` example is already written. You can find it in `examples/examples/fibonacci.rs`. This program calculates the `n`-th Fibonacci number. - -### 2. Key Generation - -Before generating a proof, you need to generate a verification key. You can do this with the `keygen` subcommand: - -```bash -cargo ceno keygen --example fibonacci --out-vk target/fibonacci.vk -``` - -This will create a `fibonacci.vk` file (the verification key) in the `target` directory. - -### 3. Generating the Proof - -To generate a proof for the `fibonacci` program, run the following command from the root of the project: - -```bash -cargo ceno prove --example fibonacci --out-proof target/fibonacci.proof -``` - -This command will compile the `fibonacci` package, execute it in the ZKVM, and generate a proof file named `fibonacci.proof` in the `target` directory. It will also generate the verification key. - -### 4. Verifying the Proof - -Now that you have a proof file, you can verify it with the following command: - -```bash -cargo ceno verify --proof target/fibonacci.proof --vk target/fibonacci.vk -``` - -If the proof is valid, you will see a confirmation message, and the command will exit successfully. - -## Using a custom program - -You can also use `ceno` to generate proofs for your own custom Rust programs. Let's walk through how to set up a new project and use `ceno` with it. +You can use `ceno` to generate proofs for your own custom Rust programs. Let's walk through how to set up a new project and use `ceno` with it. ### 1. Project Setup From f7427521f4efbece20842bcd9f4041f5148fc728 Mon Sep 17 00:00:00 2001 From: Yuncong Zhang Date: Fri, 5 Sep 2025 09:22:11 +0800 Subject: [PATCH 07/20] Update --- docs/src/generating-and-verifying-proofs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/generating-and-verifying-proofs.md b/docs/src/generating-and-verifying-proofs.md index 9cc0220ae..f15b3bfee 100644 --- a/docs/src/generating-and-verifying-proofs.md +++ b/docs/src/generating-and-verifying-proofs.md @@ -62,7 +62,7 @@ _Note: For local development, you can use a path dependency: `ceno_rt = { path = ### 3. Writing the Guest Program -Now, let's write a simple guest program in `src/main.rs`. This program will read two `u32` values from the input, add them, and write the result to the output. +Now, let's write a simple guest program in `src/main.rs`. This program will read one `u32` values from the input, add a constant to it, and write the result to the output. ```rust extern crate ceno_rt; From d942232db713ce1a6ae8df61a8e152705a0c9e68 Mon Sep 17 00:00:00 2001 From: Yuncong Zhang Date: Fri, 5 Sep 2025 09:25:47 +0800 Subject: [PATCH 08/20] Update --- docs/src/SUMMARY.md | 1 + docs/src/differences-from-risc-v.md | 1 + 2 files changed, 2 insertions(+) create mode 100644 docs/src/differences-from-risc-v.md diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index 744cb96ba..32307293a 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -11,3 +11,4 @@ - [Guest Programming (`ceno_rt`)](./guest-programming.md) - [Accelerated Operations with Precompiles (Syscalls)](./precompiles.md) - [Profiling & Performance](./profiling.md) + - [Differences from RISC-V](./differences-from-risc-v.md) diff --git a/docs/src/differences-from-risc-v.md b/docs/src/differences-from-risc-v.md new file mode 100644 index 000000000..65a73db9b --- /dev/null +++ b/docs/src/differences-from-risc-v.md @@ -0,0 +1 @@ +# Differences from RISC-V From 2980a1d2dd1d48cb5b4479592e4fb650a3908ef5 Mon Sep 17 00:00:00 2001 From: Yuncong Zhang Date: Fri, 5 Sep 2025 09:26:48 +0800 Subject: [PATCH 09/20] Update --- docs/src/advanced-topics.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/src/advanced-topics.md b/docs/src/advanced-topics.md index c323e0929..cf8c5f122 100644 --- a/docs/src/advanced-topics.md +++ b/docs/src/advanced-topics.md @@ -1,6 +1,3 @@ # Advanced Topics This chapter is for developers who want to dive deeper into the internals of Ceno. - -- **Ceno Internals** *(Content to be added)* -- **The GKR Protocol** *(Content to be added)* From 822207d35a2f77a2b05a25f695787d0de5833094 Mon Sep 17 00:00:00 2001 From: Yuncong Zhang Date: Fri, 5 Sep 2025 09:29:33 +0800 Subject: [PATCH 10/20] Add more to the outline --- docs/src/SUMMARY.md | 3 +++ docs/src/integration-with-ethereum.md | 1 + docs/src/on-chain-verification.md | 1 + docs/src/prover-network.md | 1 + 4 files changed, 6 insertions(+) create mode 100644 docs/src/integration-with-ethereum.md create mode 100644 docs/src/on-chain-verification.md create mode 100644 docs/src/prover-network.md diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index 32307293a..8b98c246c 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -12,3 +12,6 @@ - [Accelerated Operations with Precompiles (Syscalls)](./precompiles.md) - [Profiling & Performance](./profiling.md) - [Differences from RISC-V](./differences-from-risc-v.md) +- [Integration with Ethereum](./integration-with-ethereum.md) + - [Prover Network](./prover-network.md) + - [On-chain verification](./on-chain-verification.md) diff --git a/docs/src/integration-with-ethereum.md b/docs/src/integration-with-ethereum.md new file mode 100644 index 000000000..4af8584d8 --- /dev/null +++ b/docs/src/integration-with-ethereum.md @@ -0,0 +1 @@ +# Integration with Ethereum diff --git a/docs/src/on-chain-verification.md b/docs/src/on-chain-verification.md new file mode 100644 index 000000000..635cefa43 --- /dev/null +++ b/docs/src/on-chain-verification.md @@ -0,0 +1 @@ +# On-chain verification diff --git a/docs/src/prover-network.md b/docs/src/prover-network.md new file mode 100644 index 000000000..556c1dcf4 --- /dev/null +++ b/docs/src/prover-network.md @@ -0,0 +1 @@ +# Prover Network From 459af416d315fd9cbf51da10eba528af7f9282c0 Mon Sep 17 00:00:00 2001 From: Yuncong Zhang Date: Fri, 5 Sep 2025 10:19:34 +0800 Subject: [PATCH 11/20] Fix --- docs/src/ceno-cli.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/ceno-cli.md b/docs/src/ceno-cli.md index 7c3db3793..482599082 100644 --- a/docs/src/ceno-cli.md +++ b/docs/src/ceno-cli.md @@ -8,7 +8,7 @@ The available commands are: - `cargo ceno info`: Provides information about a compiled ELF file, such as its size and segments. - `cargo ceno keygen`: Generates a proving key and a verification key for a guest program. - `cargo ceno prove`: Compiles, runs, and proves a Ceno guest program in one go. -- `cargo ceno run`: Executes a guest program and generates a witness of its execution. +- `cargo ceno run`: Executes a guest program. - `cargo ceno verify`: Verifies a proof generated by `cargo ceno prove`. - `cargo ceno raw-keygen`: A lower-level command to generate keys from a compiled ELF file. - `cargo ceno raw-prove`: A lower-level command to prove a program from a compiled ELF file and a witness. From 470733f666da0abafa2ccaf6a404a1e92001b2f3 Mon Sep 17 00:00:00 2001 From: Yuncong Zhang Date: Mon, 8 Sep 2025 08:30:04 +0800 Subject: [PATCH 12/20] Use binary file for hints --- docs/src/generating-and-verifying-proofs.md | 72 ++++++++++++++------- 1 file changed, 49 insertions(+), 23 deletions(-) diff --git a/docs/src/generating-and-verifying-proofs.md b/docs/src/generating-and-verifying-proofs.md index f15b3bfee..ba8597684 100644 --- a/docs/src/generating-and-verifying-proofs.md +++ b/docs/src/generating-and-verifying-proofs.md @@ -82,42 +82,68 @@ fn main() { With your custom program ready, you can use `ceno` to manage the workflow. These commands are typically run from the root of your project (`my-ceno-program`). -1. **Build the program:** +#### 4.1. Build the program - The `build` command compiles your guest program into a RISC-V ELF file. +The `build` command compiles your guest program into a RISC-V ELF file. - ```bash - cargo ceno build - ``` +```bash +cargo ceno build +``` - This will create an ELF file at `target/riscv32im-ceno-zkvm-elf/debug/my-ceno-program`. +This will create an ELF file at `target/riscv32im-ceno-zkvm-elf/debug/my-ceno-program`. -2. **Generate Keys:** +#### 4.2. Generate Keys - Next, generate the proving and verification keys. +Next, generate the proving and verification keys. - ```bash - cargo ceno keygen --out-vk vk.bin - ``` +```bash +cargo ceno keygen --out-vk vk.bin +``` - This will save the keys in a `keys` directory. +This will save the keys in a `keys` directory. -3. **Generate a Proof:** +#### 4.3. Generate a Proof - Now, run the program and generate a proof. You can provide input via the `--stdin` flag. +Now, run the program and generate a proof. You can provide input via the `--stdin` flag. - ```bash - cargo ceno prove --hints=5 --public-io=8 --out-proof proof.bin - ``` +```bash +cargo ceno prove --hints=5 --public-io=8 --out-proof proof.bin +``` - This command executes the ELF, generates a proof, and saves it as `proof.bin`. The output of the program will be printed to your console. +This command executes the ELF, generates a proof, and saves it as `proof.bin`. The output of the program will be printed to your console. -4. **Verify the Proof:** +#### 4.4. Providing Inputs via File - Finally, verify the generated proof. +In addition to providing hints and public I/O directly on the command line, you can also use files to provide these inputs. This is particularly useful for larger inputs or when you want to reuse the same inputs across multiple runs. - ```bash - cargo ceno verify --vk vk.bin --proof proof.bin - ``` +**Hints via File** + +You can provide hints to the prover using the `--hints-file` flag. The hints file should be a raw binary file containing the hint data. You can create this file using a simple Rust program. For example, to create a hints file with the value `5u32` and `8u32`: + +```rust +use std::fs::File; +use std::io::Write; + +fn main() { + let mut file = File::create("hints.bin").unwrap(); + file.write_all(&5u32.to_le_bytes()).unwrap(); +} +``` + +Then, you can use this file when generating a proof: + +```bash +cargo ceno prove --hints-file hints.bin --public-io=8 --out-proof proof.bin +``` + +This approach is useful when you have a large amount of hint data that is inconvenient to pass through the command line. + +#### 4.5. Verify the Proof + +Finally, verify the generated proof. + +```bash +cargo ceno verify --vk vk.bin --proof proof.bin +``` If the proof is valid, you'll see a success message. This workflow allows you to integrate `ceno`'s proving capabilities into your own Rust projects. From df0cc1ba45f31715d0bec57bdd7775981ca9f292 Mon Sep 17 00:00:00 2001 From: Yuncong Zhang Date: Mon, 8 Sep 2025 08:36:31 +0800 Subject: [PATCH 13/20] Use binary file for hints in example --- docs/src/your-first-zk-program.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/docs/src/your-first-zk-program.md b/docs/src/your-first-zk-program.md index c4fad7bab..6d0d3f921 100644 --- a/docs/src/your-first-zk-program.md +++ b/docs/src/your-first-zk-program.md @@ -78,7 +78,6 @@ ceno_rt::commit::, _>(&b); After the calculation is complete, `ceno_rt::commit()` is called. This function takes the final result (`b`) and commits it as a public output of the zkVM. The host can then verify that the program produced the correct public output. In our `run` command, this is checked against the `--public-io=4191` argument. - ## Building the Program To build this program so that it can be run inside the Ceno zkVM, you can use the `cargo ceno build` command: @@ -97,4 +96,22 @@ As you saw in the previous chapter, you can run the program with `cargo ceno run cargo ceno run --example fibonacci --hints=10 --public-io=4191 ``` +or alternatively using the hints file to provide the hints: + +```sh +cargo ceno run --example fibonacci --hints-file=hints.bin --public-io=4191 +``` + +where `hints.bin` can be generated by the following rust program: + +```rust +use std::fs::File; +use std::io::Write; + +fn main() { + let mut file = File::create("hints.bin").unwrap(); + file.write_all(&10u32.to_le_bytes()).unwrap(); +} +``` + Now that you understand the basic components of a Ceno program, the next chapter will explore the interaction between the host and the guest in more detail. From cac2e7ff8f9d64496db17ae658ddeba8c0130e32 Mon Sep 17 00:00:00 2001 From: Yuncong Zhang Date: Mon, 8 Sep 2025 08:42:23 +0800 Subject: [PATCH 14/20] Add some todos --- docs/src/your-first-zk-program.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/src/your-first-zk-program.md b/docs/src/your-first-zk-program.md index 6d0d3f921..7c9f0dc46 100644 --- a/docs/src/your-first-zk-program.md +++ b/docs/src/your-first-zk-program.md @@ -114,4 +114,8 @@ fn main() { } ``` +**TODO:** support generating hints file by running the guest program (possibly in a different mode, say, hint generating mode) + +**TODO:** support providing public io also in binary file + Now that you understand the basic components of a Ceno program, the next chapter will explore the interaction between the host and the guest in more detail. From ed6d254af2a4a8eb6c78be89af4b580a3bf68892 Mon Sep 17 00:00:00 2001 From: Yuncong Zhang Date: Mon, 15 Sep 2025 08:19:24 +0800 Subject: [PATCH 15/20] Update --- docs/src/your-first-zk-program.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/your-first-zk-program.md b/docs/src/your-first-zk-program.md index 7c9f0dc46..967dd667f 100644 --- a/docs/src/your-first-zk-program.md +++ b/docs/src/your-first-zk-program.md @@ -118,4 +118,4 @@ fn main() { **TODO:** support providing public io also in binary file -Now that you understand the basic components of a Ceno program, the next chapter will explore the interaction between the host and the guest in more detail. +Now that you understand the basic components of a Ceno program, the next section will explore the interaction between the host and the guest in more detail. From bc69b512d1553ef4297f58ce8c5c76a2ecb2a3a5 Mon Sep 17 00:00:00 2001 From: Yuncong Zhang Date: Mon, 15 Sep 2025 09:00:46 +0800 Subject: [PATCH 16/20] Update --- docs/src/SUMMARY.md | 3 +++ docs/src/ceno-cli/build.md | 20 ++++++++++++++++++++ docs/src/ceno-cli/raw.md | 33 +++++++++++++++++++++++++++++++++ docs/src/ceno-cli/run.md | 30 ++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+) create mode 100644 docs/src/ceno-cli/build.md create mode 100644 docs/src/ceno-cli/raw.md create mode 100644 docs/src/ceno-cli/run.md diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index 8b98c246c..eac3d3dd2 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -6,6 +6,9 @@ - [Host-Guest Interaction](./host-guest-interaction.md) - [Generating and Verifying Proofs](./generating-and-verifying-proofs.md) - [The `ceno` CLI](./ceno-cli.md) + - [`cargo ceno build`](./ceno-cli/build.md) + - [`cargo ceno run`](./ceno-cli/run.md) + - [Raw Commands](./ceno-cli/raw.md) - [Walkthroughs of Examples](./examples-walkthrough.md) - [Advanced Topics](./advanced-topics.md) - [Guest Programming (`ceno_rt`)](./guest-programming.md) diff --git a/docs/src/ceno-cli/build.md b/docs/src/ceno-cli/build.md new file mode 100644 index 000000000..17923c8d2 --- /dev/null +++ b/docs/src/ceno-cli/build.md @@ -0,0 +1,20 @@ +# `cargo ceno build` + +The `cargo ceno build` command compiles a Ceno program. It is a wrapper around the standard `cargo build` command, but it automatically sets the correct target and rustflags for building Ceno programs. + +## Usage + +```bash +cargo ceno build [OPTIONS] +``` + +## Options + +The `build` command accepts all the same options as `cargo build`. Some of the most common options are: + +- `--example `: Build a specific example. +- `--release`: Build in release mode. +- `--package ` or `-p `: Specify which package to build. +- `--workspace`: Build all packages in the workspace. + +For a full list of options, run `cargo ceno build --help`. diff --git a/docs/src/ceno-cli/raw.md b/docs/src/ceno-cli/raw.md new file mode 100644 index 000000000..797445fc0 --- /dev/null +++ b/docs/src/ceno-cli/raw.md @@ -0,0 +1,33 @@ +# Raw Commands + +The `raw-run`, `raw-prove`, and `raw-keygen` commands are lower-level commands that operate on ELF files directly. These are useful for debugging and for integrating Ceno with other build systems. + +## `cargo ceno raw-run` + +Executes a pre-compiled ELF file in the Ceno ZKVM. + +### Usage + +```bash +cargo ceno raw-run +``` + +## `cargo ceno raw-prove` + +Generates a proof for a pre-compiled ELF file. + +### Usage + +```bash +cargo ceno raw-prove +``` + +## `cargo ceno raw-keygen` + +Generates a proving key and a verification key for a pre-compiled ELF file. + +### Usage + +```bash +cargo ceno raw-keygen +``` diff --git a/docs/src/ceno-cli/run.md b/docs/src/ceno-cli/run.md new file mode 100644 index 000000000..ff522afc6 --- /dev/null +++ b/docs/src/ceno-cli/run.md @@ -0,0 +1,30 @@ +# Run, prove, and keygen + +The `run`, `prove`, and `keygen` commands are used to execute Ceno programs. They all share a similar set of options. + +- `cargo ceno run`: Executes a Ceno program in the ZKVM. +- `cargo ceno prove`: Executes a Ceno program and generates a proof of its execution. +- `cargo ceno keygen`: Generates a proving key and a verification key for a Ceno program. + +## Usage + +```bash +cargo ceno run [OPTIONS] +cargo ceno prove [OPTIONS] +cargo ceno keygen [OPTIONS] +``` + +## Options + +These commands accept all the same options as `cargo build`. Some of the most common options are: + +- `--example `: Run a specific example. +- `--release`: Run in release mode. +- `--package ` or `-p `: Specify which package to run. + +In addition, the `prove` and `keygen` commands have some Ceno-specific options: + +- `--proof `: Path to the output proof file (for `prove`). Defaults to `proof.bin`. +- `--out-vk `: Path to the output verification key file (for `keygen`). Defaults to `vk.bin`. + +For a full list of options, run `cargo ceno --help`. From e44face3572f61b16dd37cd7e20e015f95be9ffc Mon Sep 17 00:00:00 2001 From: Yuncong Zhang Date: Mon, 15 Sep 2025 09:08:56 +0800 Subject: [PATCH 17/20] Update --- docs/src/examples-walkthrough.md | 43 +++++++++++++++++++++++++++++++- docs/src/profiling.md | 5 ++-- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/docs/src/examples-walkthrough.md b/docs/src/examples-walkthrough.md index 1c93a6cef..89ffe97bc 100644 --- a/docs/src/examples-walkthrough.md +++ b/docs/src/examples-walkthrough.md @@ -2,4 +2,45 @@ This chapter will contain detailed walkthroughs of selected examples from the `examples/` directory. -*(Content to be added)* +## Fibonacci + +The `fibonacci` example computes the `n`-th Fibonacci number, where `n` is a power of 2. The purpose of this example is to show how to perform a simple computation within the zkVM. + +### Guest Code + +The guest program for the `fibonacci` example is located at `examples/examples/fibonacci.rs`. + +```rust +{{#include ../../examples/examples/fibonacci.rs}} +``` + +The code reads an input `log_n` from the host, which is used to calculate `n = 1 << log_n`. It then iteratively computes the `n`-th Fibonacci number modulo 7919. Finally, it commits the result `b` back to the host. + +Key things to note: + +- `ceno_rt::read()`: Reads private input from the host. +- `ceno_rt::commit()`: Commits public output to the host. +- The computation is standard Rust code. The zkVM can execute most simple Rust operations. + +## Is Prime + +The `is_prime` example counts the number of prime numbers up to a given integer `n`. This example showcases a slightly more complex algorithm and control flow. + +### Guest Code + +The guest program for the `is_prime` example is located at `examples/examples/is_prime.rs`. + +```rust +{{#include ../../examples/examples/is_prime.rs}} +``` + +The code reads an integer `n` from the host. It then iterates from 0 to `n`, checking if each number is prime using the `is_prime` helper function. The total count of prime numbers is accumulated in `cnt_primes`. The program doesn't explicitly output the result but performs a computation that can be proven. + +Key things to note: + +- The `is_prime` function uses a standard trial division method. +- The guest program can include helper functions and more complex logic. +- The `panic!()` macro is used to demonstrate that the program can terminate with an error if a certain condition is met (though in this specific case, the condition `cnt_primes > 1000 * 1000` is unlikely to be met with typical inputs, it shows the possibility). +- The program does not commit any public output. + +These examples provide a basic understanding of how to write programs for the Ceno zkVM. You can explore more complex examples in the `examples/` directory to learn about other features like syscalls and host-guest interaction. diff --git a/docs/src/profiling.md b/docs/src/profiling.md index f9a9183b5..31a73eff3 100644 --- a/docs/src/profiling.md +++ b/docs/src/profiling.md @@ -4,11 +4,12 @@ Ceno includes tools to help you analyze and optimize the performance of your ZK ## Execution Profiling -You can profile the execution of your guest program by using the `--profiling` flag with the `ceno run` or other binary commands. This will output detailed statistics about the execution, such as cycle counts for different parts of the program. +You can profile the execution of your guest program by using the `--profiling` flag with the `cargo ceno run` or other binary commands. This will output detailed statistics about the execution, such as cycle counts for different parts of the program. For example: + ```bash -ceno run --profiling=1 -- +cargo ceno run --profiling=1 -- ``` The value passed to `--profiling` controls the granularity of the profiling information. From dac8cdb1a56fb36292f2f6b79697e30aece7a442 Mon Sep 17 00:00:00 2001 From: Yuncong Zhang Date: Mon, 15 Sep 2025 09:14:22 +0800 Subject: [PATCH 18/20] Update --- docs/src/guest-programming.md | 36 +++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/docs/src/guest-programming.md b/docs/src/guest-programming.md index c3dffa0ee..9ea54ee24 100644 --- a/docs/src/guest-programming.md +++ b/docs/src/guest-programming.md @@ -2,11 +2,35 @@ The `ceno_rt` crate provides the runtime environment for guest programs running inside the Ceno ZKVM. It offers essential functionalities for interacting with the host and the ZKVM environment. -Key features of `ceno_rt` include: +## Execution Environment -- **I/O:** Functions for reading input from the host and writing output. See the `ceno_rt::io` module. -- **Memory Management:** A simple allocator for dynamic memory allocation within the guest. See the `ceno_rt::allocator` module. -- **Syscalls:** Low-level functions to access precompiled operations for performance-critical tasks. See the `ceno_rt::syscalls` module and the "Accelerated Operations with Precompiles" chapter. -- **Panicking:** Macros and functions for handling unrecoverable errors in the guest. +A guest program's execution begins at the `_start` symbol, which is defined in `ceno_rt`. This entry point sets up the global pointer and stack, and then calls the standard Rust `main` function. -When writing a guest program, you will typically include `ceno_rt` as a dependency in your `Cargo.toml`. +After `main` returns, or to exit explicitly, the program can call `ceno_rt::halt(exit_code)`. An `exit_code` of 0 indicates success. + +## Key features of `ceno_rt` include: + +### Memory-Mapped I/O (`mmio`) + +The `ceno_rt::mmio` module provides a way to read data provided by the host through memory-mapped regions. + +- **Hints**: These are private inputs from the host. You can read them using `ceno_rt::mmio::read_slice()` to get a byte slice or `ceno_rt::mmio::read::()` to deserialize a specific type. +- **Public I/O**: The `ceno_rt::mmio::commit` function is used to reveal public outputs. It verifies that the output produced by the guest matches the expected output provided by the host. + +### Standard I/O (`io`) + +The `ceno_rt::io` module contains `IOWriter` for writing data. In debug builds, a global `IOWriter` instance is available through `ceno_rt::io::info_out()`. You can use the `debug_print!` and `debug_println!` macros for logging during development. + +### Dynamic Memory (`allocator`) + +For dynamic memory needs, `ceno_rt::allocator` provides a simple allocator. + +### System Calls (`syscalls`) + +The `ceno_rt::syscalls` module offers low-level functions to access precompiled operations for performance-critical tasks. For more details, see the "Accelerated Operations with Precompiles" chapter. + +### Weakly Linked Functions + +`ceno_rt` defines several weakly linked functions (e.g., `sys_write`, `sys_alloc_words`, `sys_rand`) that provide default implementations for certain system-level operations. These can be overridden by the host environment. + +When writing a guest program, you will typically include `ceno_rt` as a dependency in your `Cargo.toml`. \ No newline at end of file From c3e2d1778e7908af06af261f487f32dd45681285 Mon Sep 17 00:00:00 2001 From: Yuncong Zhang Date: Wed, 24 Sep 2025 15:05:53 +0800 Subject: [PATCH 19/20] Update --- docs/src/ceno-cli.md | 2 +- docs/src/generating-and-verifying-proofs.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/src/ceno-cli.md b/docs/src/ceno-cli.md index 482599082..b22f6d50b 100644 --- a/docs/src/ceno-cli.md +++ b/docs/src/ceno-cli.md @@ -14,4 +14,4 @@ The available commands are: - `cargo ceno raw-prove`: A lower-level command to prove a program from a compiled ELF file and a witness. - `cargo ceno raw-run`: A lower-level command to run a program without the full proof generation, useful for debugging. -For detailed usage of each command, you can use the `--help` flag, for example: `cargo ceno run --help`. +For detailed usage of each command, you can use the `--help` flag, for example: `cargo ceno run --help`. The next sections will explain the three core commands. diff --git a/docs/src/generating-and-verifying-proofs.md b/docs/src/generating-and-verifying-proofs.md index ba8597684..e6eba2d07 100644 --- a/docs/src/generating-and-verifying-proofs.md +++ b/docs/src/generating-and-verifying-proofs.md @@ -15,7 +15,7 @@ Here's a more detailed look at the steps involved in generating a proof: By using `cargo ceno prove`, you get a simplified experience that handles these steps for you. For most use cases, `cargo ceno prove` and `cargo ceno verify` are the primary commands you will use. ```bash -cargo ceno prove --example --hints= --public-io= --out-vk --out-proof target/fibonacci.proof +cargo ceno prove --example --hints= --public-io= --out-proof target/fibonacci.proof ``` ## Concrete Example @@ -110,7 +110,7 @@ Now, run the program and generate a proof. You can provide input via the `--stdi cargo ceno prove --hints=5 --public-io=8 --out-proof proof.bin ``` -This command executes the ELF, generates a proof, and saves it as `proof.bin`. The output of the program will be printed to your console. +This command executes the ELF, generates a proof, and saves it as `proof.bin`. #### 4.4. Providing Inputs via File From 9b3157d931143bbdf984839cb7aa5f379031f772 Mon Sep 17 00:00:00 2001 From: Yuncong Zhang Date: Wed, 24 Sep 2025 15:30:23 +0800 Subject: [PATCH 20/20] Update --- docs/src/examples-walkthrough.md | 95 +++++++++++++++++++++++++++----- 1 file changed, 82 insertions(+), 13 deletions(-) diff --git a/docs/src/examples-walkthrough.md b/docs/src/examples-walkthrough.md index 89ffe97bc..2ccb4aa86 100644 --- a/docs/src/examples-walkthrough.md +++ b/docs/src/examples-walkthrough.md @@ -14,13 +14,9 @@ The guest program for the `fibonacci` example is located at `examples/examples/f {{#include ../../examples/examples/fibonacci.rs}} ``` -The code reads an input `log_n` from the host, which is used to calculate `n = 1 << log_n`. It then iteratively computes the `n`-th Fibonacci number modulo 7919. Finally, it commits the result `b` back to the host. +The guest program reads a private input `log_n` from the host. This input determines the number of iterations to perform. The program then calculates `n = 1 << log_n` and computes the `n`-th Fibonacci number using a standard iterative approach. To prevent the numbers from growing too large, the computation is performed modulo 7919. Finally, the program commits the result back to the host as a public output. -Key things to note: - -- `ceno_rt::read()`: Reads private input from the host. -- `ceno_rt::commit()`: Commits public output to the host. -- The computation is standard Rust code. The zkVM can execute most simple Rust operations. +This example demonstrates the basic workflow of a Ceno zkVM program: reading private inputs, performing computations, and committing public outputs. It shows that you can write standard Rust code for the guest, and the zkVM will execute it. ## Is Prime @@ -34,13 +30,86 @@ The guest program for the `is_prime` example is located at `examples/examples/is {{#include ../../examples/examples/is_prime.rs}} ``` -The code reads an integer `n` from the host. It then iterates from 0 to `n`, checking if each number is prime using the `is_prime` helper function. The total count of prime numbers is accumulated in `cnt_primes`. The program doesn't explicitly output the result but performs a computation that can be proven. +The guest program reads an integer `n` from the host. It then iterates from 0 to `n`, checking if each number is prime using a helper function `is_prime`. The `is_prime` function implements the trial division method. The total count of prime numbers is accumulated in `cnt_primes`. If the count of primes exceeds a certain threshold, the program will panic. This demonstrates how to handle exceptional cases in the guest. The program does not commit any public output, but the proof generated by the zkVM still guarantees that the computation was performed correctly. + +This example highlights the ability to define and use helper functions within the guest code, as well as the use of control flow constructs like loops and conditional statements. + +## BN254 Curve Syscalls + +The `bn254_curve_syscalls` example demonstrates the use of syscalls for elliptic curve operations on the BN254 curve. This is useful for cryptographic applications that require curve arithmetic. + +### Guest Code + +The guest program for the `bn254_curve_syscalls` example is located at `examples/examples/bn254_curve_syscalls.rs`. + +```rust +{{#include ../../examples/examples/bn254_curve_syscalls.rs}} +``` + +The guest program initializes two points on the BN254 curve. It then uses the `syscall_bn254_add` syscall to add the two points and asserts that the result is correct by comparing it with a pre-computed value. It also demonstrates the use of the `syscall_bn254_double` syscall to double a point. The program includes helper functions to convert between different representations of curve points. + +This example showcases how to leverage syscalls to perform complex and computationally expensive operations. By using syscalls, the guest can delegate these operations to the host, which can often execute them more efficiently. The guest can still verify the results of the syscalls to ensure the integrity of the computation. + +## Ceno RT Alloc -Key things to note: +The `ceno_rt_alloc` example shows how to use the allocator in the Ceno runtime to allocate memory on the heap. + +### Guest Code + +The guest program for the `ceno_rt_alloc` example is located at `examples/examples/ceno_rt_alloc.rs`. + +```rust +{{#include ../../examples/examples/ceno_rt_alloc.rs}} +``` + +The guest program demonstrates three different memory operations. First, it writes to a global static variable. Second, it allocates a small `Vec` on the heap. Third, it allocates a much larger `Vec` on the heap and writes a value to an element in it. The `black_box` function is used to ensure that the compiler does not optimize away these memory operations. + +This example is important for understanding how memory management works in the Ceno zkVM. It shows that the guest has access to both static memory and heap memory, and can perform dynamic memory allocation. + +## Keccak Syscall + +The `keccak_syscall` example demonstrates how to use a syscall to perform the Keccak permutation, which is the core of the Keccak hash function (used in SHA-3). + +### Guest Code + +The guest program for the `keccak_syscall` example is located at `examples/examples/keccak_syscall.rs`. + +```rust +{{#include ../../examples/examples/keccak_syscall.rs}} +``` + +The guest program initializes a 25-word state and then enters a loop where it repeatedly applies the Keccak permutation to the state using the `syscall_keccak_permute` syscall. The `log_state` function is used to log the state after the first permutation, which can be useful for debugging. + +This example further illustrates the power of syscalls. The Keccak permutation is a complex operation, and implementing it efficiently in the guest would be challenging. By providing it as a syscall, the Ceno platform makes it easy for guest programs to use this important cryptographic primitive. + +## Median + +The `median` example shows how to find the median of a list of numbers. It demonstrates a common pattern where the host provides a candidate answer, and the guest verifies it. + +### Guest Code + +The guest program for the `median` example is located at `examples/examples/median.rs`. + +```rust +{{#include ../../examples/examples/median.rs}} +``` + +The guest program reads a list of numbers and a median candidate from the host. It then verifies that the candidate is indeed the median by counting the number of elements in the list that are smaller than the candidate. If the count is equal to half the length of the list, the assertion passes, and the program successfully completes. + +This example showcases a powerful pattern for zkVM programming: verifiable computation. The host, which is not constrained by the limitations of the zkVM, can perform a complex computation (like finding the median of a large list) and then provide the answer to the guest. The guest's task is then to perform a much simpler computation to verify that the host's answer is correct. This allows for the verification of complex computations that would be too expensive to perform directly in the zkVM. + +## Sorting + +The `sorting` example demonstrates how to sort a list of numbers inside the guest. + +### Guest Code + +The guest program for the `sorting` example is located at `examples/examples/sorting.rs`. + +```rust +{{#include ../../examples/examples/sorting.rs}} +``` -- The `is_prime` function uses a standard trial division method. -- The guest program can include helper functions and more complex logic. -- The `panic!()` macro is used to demonstrate that the program can terminate with an error if a certain condition is met (though in this specific case, the condition `cnt_primes > 1000 * 1000` is unlikely to be met with typical inputs, it shows the possibility). -- The program does not commit any public output. +The guest program reads a list of numbers from the host, creates a mutable copy of it, and then sorts the copy using the standard `sort` method from the Rust standard library. The `debug_println!` macro is used to print the first element of the sorted vector, which can be useful for debugging. -These examples provide a basic understanding of how to write programs for the Ceno zkVM. You can explore more complex examples in the `examples/` directory to learn about other features like syscalls and host-guest interaction. +This example demonstrates that the Ceno zkVM supports a significant portion of the Rust standard library, including common data structures and algorithms. This makes it easy to write complex programs for the guest, as you can leverage the power and convenience of the standard library.