Skip to main content

Advanced Usage

Advanced configuration and usage patterns for the Succinct Prover Network.

To use advanced features, you must set up a ProverClient using ProverClient::builder().network() instead of ProverClient::from_env().

// Default network client (uses `NETWORK_PRIVATE_KEY` env variable)
let client = ProverClient::builder()
.network()
.build();

// Network client with custom parameters
let client = ProverClient::builder()
.network()
.private_key("<PRIVATE_KEY>")
.rpc_url("<RPC_URL>")
.build();

You can see a full list of the builder parameters you can configure in the sp1-sdk docs.rs.

Skip Simulation

Skipping simulation locally can save minutes of latency depending on proof request size.

By default, the SDK will simulate program execution locally before submitting a proof request. This simulation takes anywhere from a few seconds to many minutes, depending on the size of your program. By adding .skip_simulation(true), you can skip the simulation step and send the proof optimistically. However, this means that if the program fails to execute, the proof request will fail with an "Unexecutable" error.

Since the network uses PGUs (prover gas units) for fee calculation, each request has a gas_limit parameter that sets the maximum PGUs allowed for proof generation. This value is normally set during simulation. If you skip simulation, you should manually set a gas_limit high enough to cover typical gas usage of your program.

let proof = client.prove(&pk, stdin)
.compressed()
.skip_simulation(true) // Skip simulation
.gas_limit(10_000_000_000) // 10B PGUs
.run()
.unwrap();

Async Operations

For non-blocking proof requests, use async methods to submit and track proofs separately:

use sp1_sdk::network::ProofRequestStatus;

// Submit proof request
let request_id = client.prove(&pk, &stdin)
.compressed()
.request_async()
.await?;

// Get proof status
let (status, maybe_proof) = client.get_proof_status(request_id).await?;

// Get request info
let maybe_request = client.get_proof_request(request_id).await?;

// Wait for completion
let proof = client.wait_proof(request_id, Some(Duration::from_secs(3600)), None)
.await?;

Timeout Configuration

danger

If you set the timeout too low, it may be impossible for provers to fulfill.

Set custom timeouts for proof requests. If a proof request is not fulfilled within the timeout, it will be aborted and fees will not be refunded.

use std::time::Duration;

let proof = client.prove(&pk, &stdin)
.timeout(Duration::from_secs(3600)) // 1 hour timeout
.run()
.await?;

Auction Configuration

danger

If you set the max price too low, it may not receive any bids from provers. We suggest using the default setting.

Make sure the network feature is enabled on sp1-sdk in script/Cargo.toml:

[dependencies]
sp1-sdk = { version = "...", default-features = false, features = ["network"] }

The SDK will use the Auction strategy with default parameters, but you can configure custom parameters as follows:

use std::time::Duration;
use sp1_sdk::network::FulfillmentStrategy;

let proof = client.prove(&pk, &stdin)
.compressed()
.strategy(FulfillmentStrategy::Auction)
.auction_timeout(Duration::from_secs(60))
.max_price_per_pgu(1_000_000_000_000u64) // 1 PROVE per 1M PGUs
.run()
.await?;

You can see a full list of parameters you can configure in the sp1-sdk docs.rs.

AWS KMS

As of sp1-sdk >= v5.1.1, you can pass a signer instead using of the NETWORK_PRIVATE_KEY environment variable or the private_key argument. This lets you use AWS KMS without storing your private key in plaintext.

Make sure the Key ARN is in this format: arn:aws:kms:REGION:ACCOUNT:key/KEY_ID.

// Network client with AWS KMS signer
let signer = NetworkSigner::aws_kms("<KMS_KEY_ARN>").await.unwrap();
let client = ProverClient::builder()
.network()
.signer(signer)
.build();

AWS Credentials

To use the AWS KMS signer, you need AWS credentials configured on your host machine via one of:

  • Environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)
  • IAM role with appropriate permissions attached to your instance or container
  • AWS credentials file

The credentials must have the kms:Sign and kms:GetPublicKey permissions.

Create a KMS key

You can create a KMS key in the AWS Console or via the AWS CLI. Make sure to select:

  • Type: Asymmetric
  • Usage: Sign and Verify
  • Spec: ECC_SECG_P256K1
  • Signing algorithm: ECDSA_SHA_256

For more details, see the AWS KMS Developer Guide.

Get the Address

To get the address that corresponds to the KMS key, you can either print it when setting up the NetworkSigner or use a script.

let signer = NetworkSigner::aws_kms("<KMS_KEY_ARN>").await.unwrap();
println!("address: {:?}", signer.address());

Or use a simple Python script:

import boto3
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend
from eth_utils import keccak, to_checksum_address

# 1. Fetch the DER‐encoded public key from KMS
kms = boto3.client("kms")
resp = kms.get_public_key(
KeyId="<KMS_KEY_ARN>"
)
pub_der = resp["PublicKey"]

# 2. Load it and extract (x, y)
pub = serialization.load_der_public_key(pub_der, backend=default_backend())
nums = pub.public_numbers()
raw = nums.x.to_bytes(32, "big") + nums.y.to_bytes(32, "big")

# 3. Keccak hash, take last 20 bytes, checksum it
addr = to_checksum_address(keccak(raw)[-20:])
print(addr)

Make sure that the machine running the script has AWS credentials with kms:GetPublicKey permissions.