Skip to main content
Version: Next

Advanced Usage

Execution Only

We recommend that during the development of large programs (> 1 million cycles) you do not generate proofs each time. Instead, you should have your script only execute the program with the RISC-V runtime and read public_values. Here is an example:

use sp1_sdk::{include_elf, utils, ProverClient, 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 = 500u32;

let mut stdin = SP1Stdin::new();
stdin.write(&n);

// Only execute the program and get a `SP1PublicValues` object.
let client = ProverClient::from_env();
let (mut public_values, execution_report) = client.execute(ELF, stdin).run().unwrap();

// Print the total number of cycles executed and the full execution report with a breakdown of
// the RISC-V opcode and syscall counts.
println!(
"Executed program with {} cycles",
execution_report.total_instruction_count() + execution_report.total_syscall_count()
);
println!("Full execution report:\n{:?}", execution_report);

// Read and verify the output.
let _ = public_values.read::<u32>();
let a = public_values.read::<u32>();
let b = public_values.read::<u32>();

println!("a: {}", a);
println!("b: {}", b);
}

If the execution of your program succeeds, then proof generation should succeed as well! (Unless there is a bug in our zkVM implementation.)

Compressed Proofs

With the ProverClient, the default prove function generates a proof that is succinct, but can have size that scales with the number of cycles of the program. To generate a compressed proof of constant size, you can use the prove_compressed function instead. This will use STARK recursion to generate a proof that is constant size (around 7Kb), but will be slower than just calling prove, as it will use recursion to combine the core SP1 proof into a single constant-sized proof.

use sp1_sdk::{include_elf, utils, ProverClient, 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 = 500u32;
let mut stdin = SP1Stdin::new();
stdin.write(&n);

// Generate the constant-sized proof for the given program and input.
let client = ProverClient::from_env();
let (pk, vk) = client.setup(ELF);
let mut proof = client.prove(&pk, stdin).compressed().run().unwrap();

println!("generated proof");
// Read and verify the output.
let a = proof.public_values.read::<u32>();
let b = proof.public_values.read::<u32>();
println!("a: {}, b: {}", a, b);

// Verify proof and public values
client.verify(&proof, &vk).expect("verification failed");

// Save the proof.
proof.save("compressed-proof-with-pis.bin").expect("saving proof failed");

println!("successfully generated and verified proof for the program!")
}

You can run the above script with RUST_LOG=info cargo run --bin compressed --release from examples/fibonacci/script.

Logging and Tracing Information

You can use utils::setup_logger() to enable logging information respectively. You should only use one or the other of these functions.

Logging:

utils::setup_logger();

You must run your command with:

RUST_LOG=info cargo run --release

CPU Acceleration

To enable CPU acceleration, you can use the RUSTFLAGS environment variable to enable the target-cpu=native flag when running your script. This will enable the compiler to generate code that is optimized for your CPU.

RUSTFLAGS='-C target-cpu=native' cargo run --release

Currently there is support for AVX512 and NEON SIMD instructions. For NEON, you must also enable the sp1-sdk feature neon in your script crate's Cargo.toml file.

sp1-sdk = { version = "3.0.0", features = ["neon"] }

Performance

For maximal performance, you should run proof generation with the following command and vary your shard_size depending on your program's number of cycles.

SHARD_SIZE=4194304 RUST_LOG=info RUSTFLAGS='-C target-cpu=native' cargo run --release

Memory Usage

To reduce memory usage, set the SHARD_BATCH_SIZE environment variable depending on how much RAM your machine has. A higher number will use more memory, but will be faster.

SHARD_BATCH_SIZE=1 SHARD_SIZE=2097152 RUST_LOG=info RUSTFLAGS='-C target-cpu=native' cargo run --release