Quick Start
First, create a new powdrVM project with
cargo-powdr new my-host
- Your new crate
my-host
is the host of the virtual machine's execution, and is responsible for preparing data and running the prover. - The
guest
crate in your new project contains the Rust code whose execution will be proven.
Most of these details are abstracted by the powdr
library.
Now that your project is set up, just run
cargo run -r
The host manages a powdr::Session
which can be used to share data
with the guest, test the execution, and generate ZK proofs.
use powdr::Session;
fn main() {
env_logger::init();
let some_data = vec![1, 2, 3, 4, 5];
// Create a new powdr session to make proofs for the `guest` crate.
// Store all temporary and final artifacts in `powdr-target`.
let mut session = Session::builder()
.guest_path("./guest")
.out_path("powdr-target")
// 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.
.chunk_size_log2(18)
.build()
// Write `some_data` to channel 1 and the sum of `some_data` to channel 2.
// Any serde-serializable type can be written to a channel.
.write(1, &some_data)
.write(2, &some_data.iter().sum::<u32>());
// Fast dry run to test execution.
session.run();
// Uncomment to compute the proof.
//session.prove();
}
The guest contains the custom logic that should be proved.
use powdr_riscv_runtime;
use powdr_riscv_runtime::io::read;
fn main() {
// Any serde-deserializable type can be read from a channel.
// Read some data from channel 1.
let data: Vec<u32> = read(1);
// Read the claimed sum from channel 2.
let sum: u32 = read(2);
// Check that the claimed sum is correct.
assert_eq!(data.iter().sum::<u32>(), sum);
}