Advanced Usage

Execution Only

We recommend that during development of large programs (> 1 million cycles) that 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::{utils, ProverClient, SP1Stdin};

/// The ELF we want to execute inside the zkVM.
const ELF: &[u8] = include_bytes!("../../program/elf/riscv32im-succinct-zkvm-elf");

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::new();
    let mut public_values = client.execute(&ELF, stdin).unwrap();

    println!("generated proof");

    // 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 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::{utils, ProverClient, SP1Stdin};

/// The ELF we want to execute inside the zkVM.
const ELF: &[u8] = include_bytes!("../../program/elf/riscv32im-succinct-zkvm-elf");

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::new();
    let (pk, vk) = client.setup(ELF);
    let mut proof = client.prove_compressed(&pk, stdin).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_compressed(&proof, &vk)
        .expect("verification failed");

    // Save the proof.
    proof
        .save("compressed-proof-with-pis.json")
        .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 = { git = "https://github.com/succinctlabs/sp1", 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 enviroment 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