Advanced
Embedded Allocator
SP1 programs use a simple bump allocator by default, which just increments a pointer to allocate memory. Although this works for many cases, some programs can still run out of memory in the SP1 zkVM. To address this, you can enable the embedded
allocator feature on the SP1 zkVM.
The embedded allocator uses the embedded-alloc
crate and offers more flexible memory management, albeit with extra cycle overhead.
To enable it, add the following to your sp1-zkvm
dependency in Cargo.toml
:
sp1-zkvm = { version = "...", features = ["embedded"] }
Once enabled, the embedded allocator replaces the default bump allocator.
Blake3 Public Values Hashing
This feature is supported on SP1 versions >= 4.2.0.
In certain verification contexts (e.g. Bitcoin script), verifying public values hashed with Blake3 is more efficient than verifying public values hashed with SHA-256.
To enable blake3
public values hashing for your program, enable the blake3
feature on the sp1-zkvm
dependency in Cargo.toml
:
sp1-zkvm = { version = "...", features = ["blake3"] }
The committed hash of the public values for your proof will be hashed with Blake3 instead of SHA-256.
The official SP1 Solidity verifier does not yet support Blake3 public values, as it currently hardcodes the use of SHA-256.
Requesting Multiple Proofs in Parallel
If you're building an application that generates many proofs, you may want to parallelize proof generation for performance gains. There are two recommended approaches:
1. Using Threads and .prove
You can spawn multiple threads (or async tasks) and invoke .prove()
on the NetworkProver
in each. Each call will wait until the corresponding proof is available.
This approach is simple and doesn't require tracking proof state manually.
2. Using request_async
and get_proof_status
Alternatively, you can use request_async()
to fire off proof requests without blocking. This returns a proof_id
immediately, which you can use to track the status of each request via get_proof_status(proof_id)
.
Example:
// Request a proof asynchronously and get the proof ID
let proof_id = network_prover
.prove(&program_key, &stdin)
.mode(proving_mode)
.strategy(proving_strategy)
.request_async()
.await?;
// Later, poll for the status of the proof
let (status, proof) = network_prover
.get_proof_status(&proof_id)
.await?;
This method is more flexible and may be preferable if you're working with large proofs or want more control over request timing and batching.