FAQ
Contents
ZK Basics
Q: What is a zero-knowledge proof?
When Alice executes code inside the zkVM, Alice gets back a receipt. Alice can pass the receipt to Bob, who can then verify the receipt.
By verifying the receipt, Bob can confirm that the expected code executed and produced the asserted results. Any inputs Alice passes to the program during execution will be private unless Alice chooses to share them.
Building on the zkVM
Code Troubleshooting
Q: I'm running into build errors. Where should I look for help?
zkVM Application Design
Q: What do I do with the receipt once I’ve created it?
In our examples, the receipt is generated and verified within the same program, but typically the receipt will be passed to a third party for verification.
Q: When can information be shared with the guest zkVM? How do you prevent buffer overflows?
Q: How do I know which computations should be performed in the guest zkVM, and which can be offloaded to the host?
However, consider that code run in the RISC Zero zkVM can be shown to behave as expected even on a host that is entirely untrusted. To get the most value out of this guarantee, we recommend dividing the computational labor with an untrusted host in mind. That is, other parties should not need to trust the host's output or operations in order to benefit from the work done in the zkVM.
Q: What exactly is the ImageID of a zkVM application?
Specifically, the ImageID is a Merklization of the initial zkVM memory state, or MemoryImage, produced when the zkVM loads the application binary. The memory state is hashed to produce a single deterministic value via a pure function resembling:
fn compute_image_id(used_elf_pages, page_size, page_table_addr, pc) -> ImageID
Note: Only the loaded parts of the application binary, used_elf_pages,
are utilized to calculate the ImageID. Consequently, the hashing does not include elements of a compiled binary that do not affect program meaning, e.g., debug information and timestamps.
As a consequence, functionally equivilant binaries, from the zkVM perspective, will result in identical ImageIDs. However, the compiled binaries (ELFs) may be bitwise different if hashed directly from disk. This does not affect the zkVM security model.
Features, Performance, and Limitations
Q: Are performance benchmarks available?
Q: What languages can I use to develop zkVM applications?
Q: What is the maximum execution length for a program running on the zkVM?
Q: I have a specific Rust crate I'd like to use. Will it work inside the zkVM?
If the crate you'd like to use isn't working, there may be a workaround here. If there's not already a workaround, please open an issue or reach out on Discord.
Q: If I want the guest to process large volumes of data during execution, I might be constrained by space limitations. What are my options?
There are workarounds for data limitations if the data is only included to ensure that its integrity becomes part of the proof of computation. If the data can be processed externally and simply needs to be verifiably unchanged, consider processing data externally and sending the guest a Merkle proof or (if no processing is needed) generating a SHA of a large dataset.
In the future, we plan to lift these processing limitations using continuations and recursion.
Q: I’d like to speed up the processing done inside the zkVM. What are my options?
The RISC Zero Circuits
Q: Do I need to write a ZK circuit to build on RISC Zero?
Q: What do RISC Zero's circuits do?
- The RISC-V circuit receives an ELF binary file as a public input and private inputs from the host; the output of the RISC-V circuit is a receipt.
- The recursion circuit is specialized to prove the verification of RISC Zero receipts; this circuit is used in order to compress many RISC Zero receipts into a single receipt.
- The STARK-to-SNARK circuit is used to translate a STARK proof into a SNARK proof, which enables on-chain verification.
Q: How did you make your RISC-V circuit?
- Code to emulate RISC-V, including decoding RISC-V instructions and constructing the execution trace.
- Code to evaluate the constraint polynomials that check the execution trace.
- Auxiliary data to support structures such as ‘taps’.
Because the data structures supporting all three of these need to match very carefully, we created a ‘circuit compiler’ program that generates code for all three of these systems.
Security
Q: How can we use the ImageID to determine if an application is altered before execution?
Someone wishing to confirm that a receipt corresponds to specific Rust source code can locally reproduce a binary targeting the RISC Zero zkVM using our reproducible build tool and verify that the resulting ImageID matches the ImageID in the receipt.
For example, building our builtin zkVM test functions:
cargo risczero build --manifest-path risc0/zkvm/methods/guest/Cargo.toml
will produce similar output to:
ELFs ready at:
ImageID: 417778745b43c82a20db33a55c2b1d6e0805e0fa7eec80c9654e7321121e97af - "target/riscv-guest/riscv32im-risc0-zkvm-elf/docker/risc0_zkvm_methods_guest/multi_test"
ImageID: c7c399c25ecf26b79e987ed060efce1f0836a594ad1059b138b6ed2f123dad38 - "target/riscv-guest/riscv32im-risc0-zkvm-elf/docker/risc0_zkvm_methods_guest/hello_commit"
ImageID: a51a4b747f18b7e5f36a016bdd6f885e8293dbfca2759d6667a6df8edd5f2489 - "target/riscv-guest/riscv32im-risc0-zkvm-elf/docker/risc0_zkvm_methods_guest/slice_io"
These ImageIDs will stay consistent across all builds due to a containerized process working together with Cargo working norms. You can find more about our reproducible builds and how we test them in this pull request.
Q: If the guest zkVM lives on the host machine, can’t the host still tamper with the application?
- If the binary is modified, then the receipt’s seal will not match the ImageID of the expected binary.
- If the execution is modified, then the execution trace will be invalid.
- If the output is modified, then the journal’s hash will not match the hash recorded in the receipt.