Client builders
EmbeddedClientBuilder and RemoteClientBuilder configure the proving
backend before constructing a client. Start the chain with
ProverClient::embedded() or ProverClient::remote(url), then finalize
with .build().
Overview
Builders are never constructed directly. They are returned by:
ProverClient::embedded() // → EmbeddedClientBuilder
ProverClient::remote("https://prover.tld") // → RemoteClientBuilder
Both follow the method-chaining pattern: every configuration method
returns Self, so options can be composed in any order. Call
.build() at the end to validate the configuration and produce the
client.
// Embedded client with the assembly executor and GPU
let client = ProverClient::embedded()
.assembly()
.gpu()
.build()?;
// Remote client with custom timeouts
let client = ProverClient::remote("https://prover.example.com")
.connect_timeout(Duration::from_secs(5))
.request_timeout(Duration::from_secs(600))
.build()?;
.build() may be called once per process — across both builder
kinds. A second call (embedded or remote) panics with
A ProverClient already exists. Only one instance is allowed per process.
Build the client once at startup and share it via Arc<…>, or for
the embedded client by cloning it directly.
EmbeddedClientBuilder
Builds an EmbeddedClient that runs the prover in your process.
Executor selection
Controls how the guest ELF is re-executed to build the witness.
| Method | Effect |
|---|---|
.emulator() | Use the software emulator. Default. Works on every platform. |
.assembly() | Use the native ASM execution engine. Linux x86_64 only. Faster. |
.executor(ExecutorKind) | Set the executor explicitly. ExecutorKind::Emulator (default) or ExecutorKind::Assembly. |
Device selection
| Method | Effect |
|---|---|
.gpu() | Enable GPU acceleration. Has no effect (and silently falls back) when no CUDA device is present. |
.gpu() takes no argument — it is a flag setter. CPU is the default
whenever .gpu() is not chained; there is no explicit .cpu() method.
Proving keys
| Method | Effect |
|---|---|
.proving_key(path: impl Into<PathBuf>) | Override the directory containing the STARK proving key. |
.proving_key_plonk(path: impl Into<PathBuf>) | Override the directory containing the PLONK proving key. |
Proof kind
| Method | Effect |
|---|---|
.plonk() | Switch the default proof kind to ProofKind::Plonk. |
.plonk() only sets the proof kind. It does not eagerly load
the PLONK proving key.
Diagnostics
| Method | Effect |
|---|---|
.verbose(level: u8) | Set log verbosity. 0 is quiet (default); higher values emit more detail. |
Runtime options
Two options structs configure the runtime behaviour of an embedded
client. Build each one with its chainable setters and apply it with
the corresponding .with_* method:
| Method | Effect |
|---|---|
.with_embedded_opts(opts: EmbeddedOpts) | Set proving-side tuning (memory caps, thread counts, key paths, PLONK preload). See EmbeddedOpts. |
.asm_options(opts: AsmOptions) | Pass extra options to the Assembly executor — requires .assembly(). See AsmOptions. |
If .asm_options(...) is set but the executor is not Assembly,
.build() panics. If both the builder and EmbeddedOpts set a value
for the STARK or PLONK key path, the builder-level .proving_key(...)
/ .proving_key_plonk(...) win on .build().
Build
| Method | Returns |
|---|---|
.build() | Result<EmbeddedClient> |
.build() validates the configuration and returns an error for
unsupported combinations (e.g. .assembly() on a non-Linux-x86_64
host, or .gpu() with no CUDA toolkit available). It also panics
if a ProverClient already exists in the process
or if .asm_options(...) is set without the Assembly executor.
Example
use std::path::PathBuf;
use zisk_sdk::{EmbeddedOpts, ProverClient};
let opts = EmbeddedOpts::default();
let client = ProverClient::embedded()
.assembly()
.gpu()
.proving_key("/data/keys/stark")
.proving_key_plonk("/data/keys/plonk")
.plonk()
.with_embedded_opts(opts)
.build()?;
EmbeddedOpts
Runtime tuning options applied via .with_embedded_opts(...). Every
field has a corresponding builder-style setter on EmbeddedOpts
itself, so options can be chained from EmbeddedOpts::default().
pub struct EmbeddedOpts {
pub minimal_memory: bool,
pub proving_key: Option<PathBuf>,
pub proving_key_snark: Option<PathBuf>,
pub preload_plonk: bool,
pub max_witness_stored: Option<usize>,
pub number_threads_witness: Option<usize>,
pub max_streams: Option<usize>,
}
| Field | Type | Description |
|---|---|---|
minimal_memory | bool | Reduce memory footprint during proving at the cost of speed. |
proving_key | Option<PathBuf> | STARK proving key directory. |
proving_key_snark | Option<PathBuf> | PLONK/SNARK proving key directory. |
preload_plonk | bool | Eagerly load PLONK/SNARK keys at startup instead of on first use. |
max_witness_stored | Option<usize> | Maximum bytes held for intermediate witness data. |
number_threads_witness | Option<usize> | Number of threads dedicated to witness generation. |
max_streams | Option<usize> | Maximum parallel streams during proving. |
Setters
| Method | Sets |
|---|---|
.minimal_memory() | minimal_memory = true |
.proving_key(path: impl Into<PathBuf>) | proving_key = Some(...) |
.proving_key_snark(path: impl Into<PathBuf>) | proving_key_snark = Some(...) |
.preload_plonk() | preload_plonk = true |
.max_witness_stored(max: usize) | max_witness_stored = Some(max) |
.number_threads_witness(threads: usize) | number_threads_witness = Some(threads) |
.max_streams(max: usize) | max_streams = Some(max) |
use zisk_sdk::EmbeddedOpts;
let opts = EmbeddedOpts::default()
.minimal_memory()
.preload_plonk()
.number_threads_witness(16)
.max_streams(4);
AsmOptions
Configuration for the native ASM executor, applied via
.asm_options(...). Re-exported by zisk_sdk from the prover backend.
pub struct AsmOptions {
pub asm_path: Option<PathBuf>,
pub no_auto_setup: bool,
pub unlock_mapped_memory: bool,
pub asm_out_file: bool,
pub is_distributed: bool,
}
| Field | Type | Description |
|---|---|---|
asm_path | Option<PathBuf> | Override the path of the precompiled ASM binary. |
no_auto_setup | bool | Skip the implicit setup pass before proving. |
unlock_mapped_memory | bool | Disable mlock on memory-mapped regions used by the runner. |
asm_out_file | bool | Have the ASM runner write its output to a file instead of shared memory. |
is_distributed | bool | Mark the runner as participating in a distributed (MPI) proving session. |
Setters
| Method | Sets |
|---|---|
.asm_path(path: impl Into<PathBuf>) | asm_path = Some(...) |
.no_auto_setup() | no_auto_setup = true |
.unlock_mapped_memory() | unlock_mapped_memory = true |
.asm_out_file() | asm_out_file = true |
.is_distributed() | is_distributed = true |
use zisk_sdk::AsmOptions;
let asm = AsmOptions::default()
.asm_path("/data/asm/zisk-runner")
.unlock_mapped_memory();
RemoteClientBuilder
Builds a RemoteClient that delegates proving to an external
coordinator over the network. The remote builder surface is
deliberately small: the executor, device, key paths, and ASM options
all live on the coordinator, not the client.
Constructor
ProverClient::remote(url: impl Into<String>) -> RemoteClientBuilder
| Parameter | Type | Description |
|---|---|---|
url | impl Into<String> | Full base URL of the remote coordinator. |
Timeouts
| Method | Default | Description |
|---|---|---|
.connect_timeout(d: Duration) | 10 s | Timeout for establishing the underlying connection. |
.request_timeout(d: Duration) | 300 s | Timeout applied to a full request round-trip. |
Setting request_timeout too low causes long proving jobs to error
out even though the prover is still running. Set it well above your
expected proof time.
Build
| Method | Returns |
|---|---|
.build() | Result<RemoteClient> |
.build() opens a connection to the coordinator. It is also subject
to the single-instance-per-process invariant — see the warning at the
top of this page.
Example
use std::time::Duration;
use zisk_sdk::ProverClient;
let client = ProverClient::remote("https://prover.example.com")
.connect_timeout(Duration::from_secs(5))
.request_timeout(Duration::from_secs(900))
.build()?;