- The first section, Sending A Request, shows the quickest and easiest way to request a proof using these sensible defaults, without any additional configuration.
- The second section, Request Configuration, covers all available configuration options for the 5% of requests that require fine-tuning.
The Sending a Request section uses the counter example as a template, its source code can be found at: boundless/examples/counter
Sending a Request
If you want to submit a one-off request via the Boundless CLI, please see Requesting a Proof via the Boundless
CLI.
1. Setting environment variables
Blockchain
Since we are submitting requests onchain, we will need private key for a wallet with sufficient funds on Sepolia, and a working RPC URL:Storage Provider
To make a program, and its inputs, accessible to provers, they need to be hosted at a public URL. We recommend using IPFS for storage, particularly via Pinata, as their free tier comfortably covers most Boundless use cases. Before submitting a request, you’ll need to:- Sign up for an account with Pinata.
- Generate an API key following their documentation.
- Copy the JWT token and set it as the
PINATA_JWTenvironment variable:
2. Build the Boundless Client
3. Create and Submit a Proof Request
4. Retrieve the Proof
Once submitted, you can keep track of the request using:journal and seal from the Boundless market, together they represent the public outputs of your guest and the proof itself, respectively. You can use a proof in your application to access the power of verifiable compute using Boundless.
Request Configuration
Storage Providers
The Boundless Market SDK automatically configures the storage provider based on environment variables; it supports both IPFS and S3 for uploading programs and inputs.IPFS
For example, if you set the following:.with_storage_provider():
S3
To use S3 as your storage provider, you need to set the following environment variables:No Storage Provider
A perfectly valid option forStorageProvider is None; if you don’t set any relevant environment variables for IPFS/S3, it won’t use a storage provider to upload programs or inputs at runtime. This means you will need to upload your program ahead of time, and provide the public URL. For the inputs, you can also pass them inline (i.e. in the transaction) if they are small enough. Otherwise, you can upload inputs ahead of time as well.
Uploading Programs
Provers must be able to access your guest program via a publicly accessible URL; the Boundless Market SDK allows you to directly upload your program in a few different ways.Manually
program_url, you do not need to upload the program again; you can simply use with_program_url with a hard-coded URL.
Automagically
If you are working in a monorepo (i.e. your zkVM host/guest is in the same repo), you can take advantage of risc0-build which automatically builds and exposes the ELF for the guest. The counter example uses this method:Inputs
To execute and run proving, the prover requires the inputs of the program. Inputs can be provides as a public URL, or “inline” by including them directly in the request. Program inputs are uploaded to the same storage provider. This can be done manually like so:Size Limits
Provers enforce limits on file and journal sizes. Requests exceeding these limits are ignored by most provers.File Size Limits
Programs and input files must be under 50MB. This applies to guest program ELF binaries and input files uploaded to storage providers. Oversized files would force provers to waste bandwidth and storage, so they reject such requests.Journal Size Limits
Journals delivered on-chain must be under 10KB. Larger journals would force provers to post expensive calldata, so they reject such requests. If your journal exceeds 10KB, use theClaimDigestMatch predicate and store journals off-chain. See Journal Size Limits for details.
Proof Types
By default, the Boundless SDK requests aggregated proofs. However, you can also request Groth16 proofs, which are SNARK proofs that are highly efficient for onchain verification.Requesting a Groth16 Proof
To request a Groth16 proof instead of the default aggregated proof, use thewith_groth16_proof() method when building your request:
Requesting a Blake3 Groth16 Proof
Blake3 Groth16 proofs allow verification in environments where SHA2 hashing is impossible or expensive (e.g. BitVM). To request a Blake3 Groth16 proof, use thewith_blake3_groth16_proof() method:
Blake3 Groth16 proofs are only supported with the
ClaimDigestMatch predicate, meaning you should only use this if you do not require the journal to be delivered on-chain. Additionally, the journal must be exactly 32 bytes.Onchain vs Offchain
The Boundless protocol allows you to submit requests both onchain and offchain.Onchain
To submit a request onchain, we use:Offchain
When using offchain requests, you are required to deposit funds into the Boundless market contract before you can make any proof requests. This can be done with the Boundless CLI.
Offer
The Offer specifies how much the requestor will pay for a proof, by setting the auction parameters; price, timing, stake requirements, and expiration. The Client helps you build requests and set these parameters. Within the client, the OfferLayer creates the offer. It contains a set of defaults, and logic to assign a price to your request. There are two ways to configure auction parameters:- Using
client_builder.config_offer_layerto configure the offer building logic. - Using
request.with_offerto override parameters for a specific request. This gives you direct control over the offer.
When to Use Each Approach
- Use
config_offer_layerwhen:- You want to configure cycle-based pricing that applies to all requests
- You need to adjust gas estimates or other calculation parameters
- You want consistent pricing logic across multiple requests
- Use
with_offerwhen:- You need to override the automatic calculations for a specific request
- You want to set exact prices rather than using cycle-based and gas-price calculations
- You have special requirements for a particular proof request
Per-Request Configuration with with_offer
Use with_offer when you want to override specific pricing parameters for an individual request:
showLineNumbers
Client-Level Configuration with config_offer_layer
Use config_offer_layer when you want to adjust how the SDK calculates auction parameters based on cycle count and gas prices. This is particularly useful when you want to use cycle-based pricing:
Funding Modes
When submitting requests onchain, the Boundless Market SDK needs to fund the request with ETH to cover themax_price (see Auction Parameters) of the proof.
For more advanced use-cases, the SDK provides several funding modes to control how this funding is handled, allowing you to optimize gas costs and manage your onchain balance efficiently.
The funding mode can be configured when building the client using with_funding_mode:
Always (Default)
TheAlways mode always sends max_price as the transaction value with each request. This is the simplest mode and ensures your requests are always fully funded.
Never
TheNever mode never sends value with the request. Use this mode only if you are managing the onchain balance through other means (e.g., manual top-ups, external funding management).
AvailableBalance
TheAvailableBalance mode uses the available onchain balance for funding the request. If the balance is insufficient, only the difference will be sent as value.
BelowThreshold
TheBelowThreshold mode sends value only if the balance is below a configurable threshold. If the balance is below the threshold, the difference will be sent as value (up to max_price).
MinMaxBalance
TheMinMaxBalance mode maintains a minimum and maximum balance by funding requests accordingly. If the balance is below min_balance, the request will be funded to bring the balance up to max_balance (or to cover max_price, whichever is greater).