Overview
The Request Stream pattern continuously submits proof requests to the Boundless Market based on blockchain events. Use this pattern when your application proves properties about each block or block range: monitoring block hashes, tracking state transitions, or verifying computations across multiple blocks.
How It Works
The pattern monitors the blockchain for new blocks. Every N blocks (configurable; default is 2), it collects block hashes and constructs a proof request with them as input. The request is submitted to the Boundless Market, and the pattern waits for a prover to fulfill it before repeating for the next block range.
Setting Up
Environment Variables
You’ll need the same environment variables as a standard request:
For more details on storage providers, see Storage Providers.
CLI Arguments
The request stream example accepts the following arguments:
Creating a Block Range Stream
The core of the request stream pattern is creating an async stream that monitors the blockchain and emits events when new block ranges are ready.
Stream Pattern Benefits
Streams process events as they arrive, give consumers control over processing rate (backpressure), and compose with other stream operations like filter and map.
Implementation
Processing Events and Submitting Requests
Once you have a stream of block range events, you can process them and submit proof requests:
Main Processing Loop
The input data must be prepared in a format that your guest program can understand. In this example, we concatenate block hashes:
In production, you might want to serialize data in a structured format (e.g., using bincode, serde) or include additional metadata. Ensure your guest program can deserialize this format.
Request IDs
A Request ID is a 256-bit value containing your address and a 32-bit index. Bits 0-31 hold the index (u32), bits 32-191 hold the requestor address (160 bits), and bits 192+ hold flags such as the smart contract signature flag.
Choosing an Index
In this example, we use the start block number as the index:
Each block range receives a unique, deterministic request ID, making it straightforward to identify which block range a request corresponds to.
The index must be unique per requestor address. If you submit multiple requests with the same index, only one will be accepted.
Full Example
Use Cases
This pattern suits applications that prove properties about each block or block range, verify state transitions continuously, process data in batches as new blocks arrive, or generate proofs for events as they occur onchain.
Next Steps
See request configuration for fine-tuning requests, using proofs for integrating proofs into your application, and callbacks for automatic proof delivery.