diff --git a/cargo-powdr/template/Cargo.toml.template b/cargo-powdr/template/Cargo.toml.template index a2f03e3ee1..45091bb200 100644 --- a/cargo-powdr/template/Cargo.toml.template +++ b/cargo-powdr/template/Cargo.toml.template @@ -8,7 +8,7 @@ default = [] simd = ["powdr/plonky3-simd"] [dependencies] -powdr = { git = "https://github.com/powdr-labs/powdr", features = ["plonky3"] } +powdr = { git = "https://github.com/powdr-labs/powdr", tag = "v0.1.0", features = ["plonky3"] } serde = { version = "1.0", default-features = false, features = [ "alloc", diff --git a/cargo-powdr/template/README.md b/cargo-powdr/template/README.md index 6b2c56a503..d738ccd1a6 100644 --- a/cargo-powdr/template/README.md +++ b/cargo-powdr/template/README.md @@ -1,8 +1,16 @@ # powdrVM Usage Template -This is a foundational template for generating zero-knowledge proofs with powdrVM. You write the code to be proven as a guest program for the zkVM host. This template includes a structure for host/guest interaction, ZKP setup, and artifact generation. - -Guest programs are written in Rust. When creating your guest program, you can write Rust code in the usual way, including using std and importing packages others have written. We provide some additional powdrVM specific functionalities via system calls, such as IO operations for host <-> guest communication and precompiles to accelerate complex programs via optimized circuits. +This is a foundational template for generating zero-knowledge proofs with powdrVM. +You write the code to be proven as a guest program for the zkVM host. +This template includes a structure for host/guest interaction, ZKP setup, +and artifact generation. + +Guest programs are written in Rust. +When creating your guest program, you can write Rust code in the usual way, +including using std and importing packages others have written. +We provide some additional powdrVM specific functionalities via system calls, +such as IO operations for host <-> guest communication and precompiles to +accelerate complex programs via optimized circuits. ## Dependencies @@ -18,7 +26,8 @@ cargo run -r ## AVX / Neon -You can enable AVX or Neon support by using the `simd` feature and running the host with extra flags: +You can enable AVX or Neon support by using the `simd` feature and running +the host with extra flags: ```bash RUSTFLAGS='-C target-cpu=native' cargo run --features simd -r @@ -26,20 +35,13 @@ RUSTFLAGS='-C target-cpu=native' cargo run --features simd -r ## Structure -- `src/main.rs`: the host code. This is where you create a powdr `Session`, prepare data to be shared with the guest, and run the prover. -- `guest`: this is the guest crate. It contains the code that will be run inside the powdrVM. -- `powdr-target`: this is where all generated artifacts reside. This includes the compiled guest code to powdr-asm, the compiled PIL constraints, setup artifacts such as proving and verifying keys, and the final ZK proofs. - -## Troubleshooting - -powdrVM uses a default chunk size of 2^20 cycles for production cases. In some machines, key generation can run out-of-memory. To solve this, use - -```bash -export MAX_DEGREE_LOG=20 -``` - -and use a chunk size of 2^18 in the host, as explained in the section below. -This is being improved at the moment. +- `src/main.rs`: the host code. This is where you create a powdr `Session`, +prepare data to be shared with the guest, and run the prover. +- `guest`: this is the guest crate. It contains the code that will be +run inside the powdrVM. +- `powdr-target`: this is where all generated artifacts reside. +This includes the compiled guest code to powdr-asm, the compiled PIL constraints, +setup artifacts such as proving and verifying keys, and the final ZK proofs. ## Workflow @@ -53,39 +55,60 @@ let some_data = vec![1, 2, 3, 4, 5]; Create a new powdr session where we'll be running crate `guest` in powdrVM and all artifacts will be stored in `powdr-target`: + ```rust -let mut session = Session::new("./guest", "powdr-target") +let mut session = Session::builder() + .guest_path("./guest") + .out_path("powdr-target") + .build() ``` Write `some_data` to channel 1 and the sum of `some_data` to channel 2. Note that any `serde` type can be used to share data between host and guest. The guest will read this data from the channels: + ```rust -.write(1, &some_data).write(2, &some_data.iter().sum::()); + .write(1, &some_data) + .write(2, &some_data.iter().sum::()); ``` -The line below also creates a powdr `Session`, but tells powdrVM to use 2^18 rows -per chunk, if needed. In that case, make sure to also use `export MAX_DEGREE_LOG=20`. -This tells the powdr compiler to generate smaller circuits than the default production -size of 2^22. This is being improved at the moment. +The lines below also create a powdr `Session`, but tell powdrVM to use 2^18 rows +per chunk, instead of the default 2^20. This is useful to decrease memory usage, +for example, at the expense of proving time. + ```rust -let mut session = Session::new_with_chunk_size("./guest", "powdr-target", 18) +let mut session = Session::builder() + .guest_path("./guest") + .out_path("powdr-target") + .chunk_size_log2(18) ``` Run the session without generating a proof. Useful for testing the guest code: + ```rust session.run(); ``` Generate the ZK proof: + ```rust session.prove(); ``` -Before generating a proof, powdrVM has to create the proving and verifying keys (setup) for the given guest program. When run for the first time, this can take a while. Subsequent runs will be faster as the setup only changes if the guest changes. +Before generating a proof, powdrVM has to create the proving and verifying keys (setup) +for the given guest program. +When run for the first time, this can take a while. +Subsequent runs will be faster as the setup only changes if the guest changes. + +powdrVM also needs to compute the witnesses for the given execution trace, +needed by the ZK prover. +Currently this is done by an automated constraint solver, +which can be slow for complex programs. +We are working on a more efficient way to generate witnesses. + +You can run the host with INFO logs to have a deeper look at what's happening: -You can also run the host with INFO logs to have a deeper look at what's happening: ```bash RUST_LOG=info cargo run -r ``` diff --git a/cargo-powdr/template/guest/Cargo.toml.template b/cargo-powdr/template/guest/Cargo.toml.template index ee497e29a6..d09e19d6cb 100644 --- a/cargo-powdr/template/guest/Cargo.toml.template +++ b/cargo-powdr/template/guest/Cargo.toml.template @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -powdr-riscv-syscalls = { git = "https://github.com/powdr-labs/powdr" } -powdr-riscv-runtime = { git = "https://github.com/powdr-labs/powdr", features = ["std"]} +powdr-riscv-syscalls = { git = "https://github.com/powdr-labs/powdr", tag = "v0.1.0" } +powdr-riscv-runtime = { git = "https://github.com/powdr-labs/powdr", tag = "v0.1.0", features = ["std"]} [workspace] diff --git a/cargo-powdr/template/src/main.rs b/cargo-powdr/template/src/main.rs index 2d2986d5d2..49d02d4746 100644 --- a/cargo-powdr/template/src/main.rs +++ b/cargo-powdr/template/src/main.rs @@ -16,18 +16,19 @@ fn main() { .write(1, &some_data) .write(2, &some_data.iter().sum::()); - // Create a new powdr session with a custom chunk size for small traces/proofs. + // powdrVM splits long execution traces into chunks + // which are proven individually. + // The default size of a chunk is 2^20 = 1048576 rows. + // For experiments and smaller traces/proofs, it may be beneficial to reduce the chunk size. + // Create a new powdr session with a custom chunk size. // 2^18 = 262144 rows per chunk. - // When using this, make sure to also use - // `$ export MAX_DEGREE_LOG=20` - // to get faster setup times. - // let mut session = Session::builder() - // .guest_path("./guest") - // .out_path("powdr-target") - // .chunk_size_log2(18) - // .build() - // .write(1, &some_data) - // .write(2, &some_data.iter().sum::()); + let mut session = Session::builder() + .guest_path("./guest") + .out_path("powdr-target") + .chunk_size_log2(18) + .build() + .write(1, &some_data) + .write(2, &some_data.iter().sum::()); // Fast dry run to test execution. session.run(); diff --git a/examples/keccak/README.md b/examples/keccak/README.md index 5ecc84749f..989ac3f59d 100644 --- a/examples/keccak/README.md +++ b/examples/keccak/README.md @@ -1,9 +1,11 @@ # powdrVM tinykeccak example -This example demonstrates how to use the `powdrVM` to run a simple keccak hash function using the `tinykeccak` crate. +This example demonstrates how to use the `powdrVM` to run a simple +keccak hash function using the `tinykeccak` crate. We want to prove that we know the pre-image of a hash. -The host takes in a 32-byte challenge hash `C` as a hex string, and the pre-image string `P`, such that `Keccak(P) = C`. +The host takes in a 32-byte challenge hash `C` as a hex string, +and the pre-image string `P`, such that `Keccak(P) = C`. The guest receives the same data from the host and verifies that the claim is true.