Succinct SP1: RISC-V Programs and Execution Proofs
Succinct SP1 proves the execution of Rust programs that its custom toolchain compiles into compatible RISC-V executables. The guest runs inside the zero-knowledge virtual machine, or zkVM, while a host application supplies inputs and manages proving. A verifier checks the proof against the expected program and public values. Proof format and version compatibility determine whether that proof fits the application.
The executable carries the logic that the proof establishes. Guest dependencies must fit the target runtime, and public outputs must communicate the statement that the application needs. These requirements connect software design to proof generation and verification.
Key takeaway: SP1 V6 and V5 use incompatible toolchains, so a guest executable must match the proving stack that consumes it.
From Rust Source to a Verifiable Executable
A compatible SP1 toolchain and a guest crate with the SP1 entrypoint are prerequisites for producing a provable executable.
Guest Compilation
The guest crate uses sp1-zkvm and the sp1_zkvm::entrypoint! macro to connect its main function to the runtime. The command cargo prove build compiles the guest into an ELF, short for Executable and Linkable Format. The host embeds or loads this binary for execution and proving. Host code that prepares inputs remains outside the guest's execution claim.
Compilation success establishes that the guest builds for the target. It does not establish that its outputs satisfy the application.
Execution and Proof Checks
Execution-only runs return public values and an execution report without generating a proof. They help isolate runtime failures and incorrect outputs before expensive proving. The SDK's ProverClient manages program setup, execution, proving, and verification. Program setup derives key material from the executable. Proof verification then checks the resulting execution claim under the expected program identity.
Guest Inputs and Public Output Encoding
The guest's input and output interfaces determine which data enters the computation and which values the proof exposes for verification. Host code populates SP1Stdin, and the guest reads the supplied values through its input API. Calls to sp1_zkvm::io::commit or commit_slice add public values to the execution claim. Their order defines how the consuming code must interpret the committed bytes.
Typed input reads and writes use serialization, which converts Rust values into bytes and reconstructs them inside the guest. SP1's ordinary typed interface uses bincode. Raw byte interfaces allow another serialization strategy when copying or decoding becomes expensive. A matching data layout matters independently of proof validity: a correct proof can accompany bytes that the receiving application interprets incorrectly.
Execution Shards, Recursion, and Proof Formats
SP1 divides long executions into shards, contiguous portions of the execution trace. That trace records the program's intermediate operations. Each shard proof checks instruction constraints, while cross-shard checks require later memory reads to match earlier writes. Hypercube, introduced in V6, uses multilinear polynomial techniques to encode and check these traces.
Core and Compressed Proofs
Core mode produces STARKs, or scalable transparent arguments of knowledge, whose aggregate size grows with execution. Compressed mode reduces the execution proofs to a proof whose size does not grow with the original execution length. These modes have different proving and verification requirements.
Proof Aggregation Within SP1
SP1's native recursive-verification syscall accepts compressed proofs. An aggregation program checks child proofs using their program keys and public-values digests. It must also enforce the relationships between child results that its application requires. Aggregation can combine work from separate programs or proving parties, with additional proving overhead. A patched sp1-verifier library also supports Groth16 and PLONK verification inside the guest.
Groth16 and PLONK Wrappers
Groth16 and PLONK convert the underlying execution proof into SNARKs, or succinct non-interactive arguments of knowledge, suitable for supported contract verifiers. Contract verification receives the program key, committed public values, and proof bytes. SP1VerifierGateway routes proofs by their verifier prefix. Verification through it reverts if the required route is missing or frozen.
Groth16 uses a circuit-specific trusted setup. PLONK uses a universal setup. Both rely on at least one setup contributor discarding their secret intermediate data.
Toolchain and Dependency Compatibility
Toolchain compatibility changes at the V5-to-V6 boundary. SP1 V6's 64-bit toolchain is incompatible with SP1 V5's 32-bit toolchain. An executable built for one generation cannot simply move into the other runtime. The SDK and guest dependencies also need compatible versions. A host build using the system compiler can succeed while the custom guest toolchain cannot compile its dependency tree.
Dependency requirements include the minimum supported Rust version, often abbreviated MSRV. A crate that requires newer compiler features can block guest compilation. Versions and enabled features also determine which implementation enters the binary. Changing those settings can change the ELF and its program key, even when the source-level function keeps the same name.
Precompiles and Proving Work
Proving work depends on the executed instructions, memory activity, and specialized cryptographic operations that the guest uses.
Cryptographic Circuits
A precompile is a dedicated proving component for an operation such as SHA-256 hashing or elliptic-curve arithmetic. SP1 exposes these components through runtime system calls. Patched Rust libraries route supported operations to them, avoiding the corresponding instruction-heavy implementation. Patch versions must fit the guest's dependencies and SP1 release. Low-level callers must preserve the precompile's input assumptions, including valid curve points and canonical field representations where required.
Execution Reports
The execution report records instruction and syscall activity. Its syscall counts show which accelerated operations the actual run used. Profiling and cycle tracking identify expensive program regions. Prover gas estimates proving work using more than raw cycle counts; it does not denote a blockchain transaction fee. V6's embedded allocator reuses memory addresses, so reducing instruction count alone does not establish faster proving.
Application Rules Inside the Proven Program
A proof establishes the computation that the guest actually performs. Missing validation remains missing from the proven statement.
Rollup proving and light-client verification require the guest to check the data relationships that the application accepts. Merely receiving an input does not authenticate its origin or connect it to the intended state. The program must enforce the required checks and commit the relevant result. The verifier application must bind that result to its expected program identity. Memory safety also matters: undefined behavior in unsafe code undermines SP1's program-safety assumptions.
Direct precompile calls require their own input validation and must use SP1's supported APIs instead of issuing ECALL manually. An elliptic-curve operation's constraints do not automatically establish that supplied points lie on the curve.
Privacy at the Proof and Prover Boundaries
Privacy depends on the proof format and input-handling path. Individual SP1 STARK proofs do not currently provide zero-knowledge privacy. Groth16 and PLONK wrappers provide zero knowledge for private witness data, while committed public values remain visible. An external prover that receives plaintext inputs can read them. The Prover Network's TEE Private Proving protects outsourced inputs inside a trusted execution environment, with availability limited to an Enterprise-only private beta. That path adds hardware and application-attestation assumptions.
Matching a Build to Its Intended Verifier
An application that fixes its accepted program key and proof format needs a compatible guest build. During repeated execution tests, the expected public values provide a baseline for the values that the guest actually returns.
- Confirm that the guest ELF, SDK, and toolchain target compatible SP1 versions before executing the program.
- Continue to proving when execution succeeds and its public values match the application's expected values.
- Select compressed proofs for native recursive verification, or the supported Groth16 or PLONK format that the receiving contract expects.
- Wait while a network proof request remains pending; its request identifier alone is not a verified proof.
- Stop using the candidate if proof verification fails, the program key differs, or the configured gateway route is frozen.
The integration completes when the intended verifier accepts the proof under the expected program key and the public values match the application's requirements. A proof for another valid program cannot satisfy that expectation. A rebuilt executable needs its own compatibility check before replacing the accepted program.
Popular questions about Succinct SP1
Can the SP1 V6 Blocking API Run Inside a Tokio Runtime?
SP1 V6 blocking calls that use Tokio's block_on panic inside an existing Tokio runtime. Since v6.8.0, constructing a blocking LightProver there is supported. Its synchronous interface requires the blocking feature in sp1-sdk. Code that already runs inside Tokio should use the asynchronous interface for execution, setup, and proving. Matching the API to the host runtime avoids a failure that is unrelated to the guest's RISC-V logic.
Why Can C Bindings Fail During SP1 Guest Compilation?
C bindings can fail when the build cannot find a compatible RISC-V C or C++ toolchain. For V6 guest builds, sp1up --c-toolchain installs the accompanying compiler and configures the target-specific compiler setting. A successful Rust host build does not establish that guest-side native dependencies can compile. Their compiler must target the guest architecture.
Which Output Encoding Lets Solidity Decode Committed Rust Values?
Solidity applications can decode committed Rust values when the guest encodes them using the matching Solidity ABI layout. SP1's project template uses alloy_sol_types to ABI-encode a public-values structure, then commits those bytes with commit_slice. The contract verifies the proof and decodes the same structure. Ordinary Rust serialization does not automatically produce that ABI layout.
When Does an SP1 Build Need Docker for Reproducibility?
SP1's reproducible build path uses cargo prove build --docker to produce the guest ELF. A plain development build can vary across build environments. Fix the intended release, dependency lockfile, and build settings when comparing executable hashes. A matching hash establishes binary agreement; it does not independently audit the source program's logic.
What Happens If I Disable sp1-sdk's Default Features?
In sp1-sdk v6.8.1, the default feature set is empty, so default-features = false does not itself remove NetworkProver. NetworkProver requires the network feature, enabled directly or through another feature that includes it. An application using external proving must retain the features that its chosen backend requires. Enabled features control which host SDK backends the application can use.
How Can Missing Verify Features Cause an SP1 Guest Linking Error?
A linking error for syscall_verify_sp1_proof can indicate that required verify features are missing from guest dependencies. SP1's native recursive-verification path needs that feature on sp1-zkvm, and directly used sp1-lib must enable it too. The correction concerns the guest manifest. Generating a different outer proof format does not supply a missing linker symbol.
Is There an SP1 Client for Checking Existing Proofs Without Initializing the Full CPU Prover?
SP1 V6's LightProver supports program execution and verification of pre-generated proofs without initializing the full CPU prover. It fits host tools that inspect executions or check existing proofs. It does not supply local proof-generation capacity. A verification tool can therefore avoid loading the heavier proving backend while retaining its checks for expected program identity and public values.