Basics
All the methods you'll need for generating proofs are included in the sp1_sdk
crate. Most importantly, you'll need to use the ProverClient
to setup a proving key and verifying key for your program and then use the execute
, prove
and verify
methods to execute your program, and generate and verify proofs.
To make this more concrete, let's walk through a simple example of generating a proof for a Fibonacci program inside the zkVM.
Example: Fibonacci
use sp1_sdk::{include_elf, utils, ProverClient, SP1ProofWithPublicValues, SP1Stdin};
/// The ELF we want to execute inside the zkVM.
const ELF: &[u8] = include_elf!("fibonacci-program");
fn main() {
// Setup logging.
utils::setup_logger();
// Create an input stream and write '500' to it.
let n = 1000u32;
// The input stream that the program will read from using `sp1_zkvm::io::read`. Note that the
// types of the elements in the input stream must match the types being read in the program.
let mut stdin = SP1Stdin::new();
stdin.write(&n);
// Create a `ProverClient` method.
let client = ProverClient::new();
// Execute the program using the `ProverClient.execute` method, without generating a proof.
let (_, report) = client.execute(ELF, stdin.clone()).run().unwrap();
println!("executed program with {} cycles", report.total_instruction_count());
// Generate the proof for the given program and input.
let (pk, vk) = client.setup(ELF);
let mut proof = client.prove(&pk, stdin).run().unwrap();
println!("generated proof");
// Read and verify the output.
//
// Note that this output is read from values committed to in the program using
// `sp1_zkvm::io::commit`.
let _ = proof.public_values.read::<u32>();
let a = proof.public_values.read::<u32>();
let b = proof.public_values.read::<u32>();
println!("a: {}", a);
println!("b: {}", b);
// Verify proof and public values
client.verify(&proof, &vk).expect("verification failed");
// Test a round trip of proof serialization and deserialization.
proof.save("proof-with-pis.bin").expect("saving proof failed");
let deserialized_proof =
SP1ProofWithPublicValues::load("proof-with-pis.bin").expect("loading proof failed");
// Verify the deserialized proof.
client.verify(&deserialized_proof, &vk).expect("verification failed");
println!("successfully generated and verified proof for the program!")
}
You can run the above script in the script
directory with RUST_LOG=info cargo run --release
. Note that running the above script will generate a proof locally.
WARNING: Local proving often is much slower than the prover network and for certain proof types (e.g. Groth16, PLONK) require a significant amount of RAM and will likely not work on a laptop.
We recommend using the prover network to generate proofs. Read more about the recommended workflow for developing with SP1.