Prover
The zkm_sdk crate provides all the necessary tools for proof generation. Key features include the ProverClient
, enabling you to:
- Initialize proving/verifying keys via
setup()
. - Execute your program via
execute()
. - Generate proofs with
prove()
. - Verify proofs through
verify()
.
When generating Groth16 or PLONK proofs, the ProverClient
automatically downloads the pre-generated proving key (pk) from a trusted setup by calling try_install_circuit_artifacts()
.
Example: Fibonacci
The following code is an example of using zkm_sdk in host.
use zkm_sdk::{include_elf, utils, ProverClient, ZKMProofWithPublicValues, ZKMStdin}; /// The ELF we want to execute inside the zkVM. const ELF: &[u8] = include_elf!("fibonacci"); fn main() { // Create an input stream and write '1000' to it. let n = 1000u32; // The input stream that the guest will read from using `zkm_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 = ZKMStdin::new(); stdin.write(&n); // Create a `ProverClient` instance. let client = ProverClient::new(); // Execute the guest 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(); // Read and verify the output. // // Note that this output is read from values committed to in the program using // `zkm_zkvm::io::commit`. let n = proof.public_values.read::<u32>(); let a = proof.public_values.read::<u32>(); let b = proof.public_values.read::<u32>(); println!("n: {}", n); println!("a: {}", a); println!("b: {}", b); // Verify proof and public values client.verify(&proof, &vk).expect("verification failed"); }
Proof Types
Ziren provides customizable proof generation options:
#![allow(unused)] fn main() { /// A proof generated with Ziren of a particular proof mode. #[derive(Debug, Clone, Serialize, Deserialize, EnumDiscriminants, EnumTryAs)] #[strum_discriminants(derive(Default, Hash, PartialOrd, Ord))] #[strum_discriminants(name(ZKMProofKind))] pub enum ZKMProof { /// A proof generated by the core proof mode. /// /// The proof size scales linearly with the number of cycles. #[strum_discriminants(default)] Core(Vec<ShardProof<CoreSC>>), /// A proof generated by the compress proof mode. /// /// The proof size is constant, regardless of the number of cycles. Compressed(Box<ZKMReduceProof<InnerSC>>), /// A proof generated by the Plonk proof mode. Plonk(PlonkBn254Proof), /// A proof generated by the Groth16 proof mode. Groth16(Groth16Bn254Proof), } }
Core Proof (Default)
The default prover mode generates a sequence of STARK proofs whose cumulative proof size scales linearly with the execution trace length.
#![allow(unused)] fn main() { let client = ProverClient::new(); client.prove(&pk, stdin).run().unwrap(); }
Compressed Proof
The compressed proving mode generates constant-sized STARK proofs, but not suitable for on-chain verification.
#![allow(unused)] fn main() { let client = ProverClient::new(); client.prove(&pk, stdin).compressed().run().unwrap(); }
Groth16 Proof (Recommended)
The Groth16 proving mode generates succinct SNARK proofs with a compact size of approximately 260 bytes, and features on-chain verification.
#![allow(unused)] fn main() { let client = ProverClient::new(); client.prove(&pk, stdin).groth16().run().unwrap(); }
PLONK Proof
The PLONK proving mode generates succinct SNARK proofs with a compact size of approximately 868 bytes, while maintaining on-chain verifiability. In contrast to Groth16, PLONK removes the dependency on trusted setup ceremonies.
#![allow(unused)] fn main() { let client = ProverClient::new(); client.prove(&pk, stdin).plonk().run().unwrap(); }
Hardware Acceleration
Ziren provides hardware acceleration support for AVX256/AVX512
on x86 CPUs due to support in Plonky3
.
You can check your CPU's AVX compatibility by running:
grep avx /proc/cpuinfo
Check if you can see avx2
or avx512
in the results.
To activate AVX256 optimization, add these flags to your RUSTFLAGS environment variable:
RUSTFLAGS="-C target-cpu=native" cargo run --release
To activate AVX512 optimization, add these flags to your RUSTFLAGS environment variable:
RUSTFLAGS="-C target-cpu=native -C target-feature=+avx512f" cargo run --release
Network Prover
We support a network prover via the ZKM Proof Network, accessible through our RESTful API.The network prover currently supports only the Groth16 proving mode. >The proving process consists of several stages: queuing, splitting, proving, and finalizing. Each stage may take a different amount of time.
Requirements
- CA certificate:
ca.pem
,ca.key
. These keys are stored here - Register your address to gain access.
- SDK dependency: add
zkm_sdk
from the Ziren SDK to yourCargo.toml
:
zkm-sdk = { git = "https://github.com/ProjectZKM/Ziren", branch = "main" }
Environment Variable Setup
Before running your application, export the following environment variables to enable the network prover:
export ZKM_PRIVATE_KEY=<your_private_key> # Private key corresponding to your registered public key
export SSL_CERT_PATH=<path_to_ssl_certificate> # Path to the SSL client certificate (e.g., ssl.pem)
export SSL_KEY_PATH=<path_to_ssl_key> # Path to the SSL client private key (e.g., ssl.key)
You can generate the SSL certificate and key by running the certgen.sh
script.
Optional: You can also set the following environment variables to customize the network prover behavior:
export SHARD_SIZE=<shard_size> # Size of each shard in bytes.
export MAX_PROVER_NUM=<max_prover_num> # Maximum number of provers to use in parallel.
To host your own network prover, export the following variables to configure your endpoint:
export ENDPOINT=<proof_network_endpoint> # Proof network endpoint (default: https://152.32.186.45:20002)
export CA_CERT_PATH=<path_to_ca_certificate> # Path to CA certificate (default: ca.pem)
export DOMAIN_NAME=<domain_name> # Domain name (default: "stage")
Example
The following example shows how to use the network prover on the host:
use std::env; use zkm_sdk::{include_elf, ProverClient, ZKMStdin}; const FIBONACCI_ELF: &[u8] = include_elf!("fibonacci"); fn main() { utils::setup_logger(); let mut stdin = ZKMStdin::new(); stdin.write(&10usize); let elf = test_artifacts::FIBONACCI_ELF; // create network client let client = ProverClient::network(); let (pk, vk) = client.setup(elf); let proof = client.prove(&pk, stdin).run().unwrap(); client.verify(&proof, &vk).unwrap(); }