The Composition example demonstrates how to verify RISC Zero receipts inside a guest program, allowing multiple zkVM programs to be composed into a single proof.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/risc0/risc0/llms.txt
Use this file to discover all available pages before exploring further.
What You’ll Learn
- How to verify receipts inside the zkVM
- How to use
add_assumption()in the host - How to use
env::verify()in the guest - Real-world applications of proof composition
Overview
Composition enables you to:- Split programs into multiple parts proven by different parties
- Aggregate many proofs into one for efficient batch verification
- Create single receipts for multi-step workflows
- Preserve privacy by distributing computation across parties
How It Works
This example builds on the Hello World example by adding an RSA-like encryption step that requires proof of knowing the modulus factorization.let env = ExecutorEnv::builder()
// add_assumption makes the receipt available to the prover
.add_assumption(multiply_receipt)
.unwrap()
.write(&(n, 9u64, 100u64))
.unwrap()
.build()
.unwrap();
use hello_world_methods::MULTIPLY_ID;
use risc0_zkvm::{guest::env, serde};
fn main() {
let (n, e, x): (u64, u64, u64) = env::read();
// Verify that n has a known factorization
env::verify(MULTIPLY_ID, &serde::to_vec(&n).unwrap()).unwrap();
// Commit n, e, and x^e mod n
env::commit(&(n, e, pow_mod(x, e, n)));
}
/// Compute x^e (mod n)
pub fn pow_mod(x: u64, mut e: u64, n: u64) -> u64 {
let mut x = x as u128;
let n = n as u128;
let mut z = 1u128;
// Exponentiation by squaring
while e > 0 {
if e % 2 == 1 {
z = (z * x) % n
}
e >>= 1;
x = (x * x) % n;
}
return z as u64;
}
What Gets Proven?
The final receipt proves two things simultaneously:- The modulus
nhas a known factorization (verified via composition) - The ciphertext
cis the result ofx^e mod nfor some secretx
Running the Example
Use Cases
Composition is powerful for multi-party computation and privacy-preserving workflows.
Privacy-Preserving Data Sharing
Produce a proof for a database query by joining receipts from queries over each privately-held shard. No single party sees the complete data.Batch Verification
Aggregate many transaction proofs into one:Image Processing Pipeline
Create a single receipt for a workflow with different filters:Verifiable Encryption
Prove a ciphertext is valid encryption to a legitimate public key:Key Methods
add_assumption() (Host)
Makes a receipt available for verification in the guest:
env::verify() (Guest)
Verifies a receipt inside the zkVM:
Performance Considerations
- Composition adds overhead but provides powerful capabilities
- The final receipt size is constant regardless of composition depth
- Verification time is constant - verifying a composed proof is as fast as verifying a single proof
Next Steps
- Explore cryptographic signatures
- Learn about blockchain integration
- Build complex workflows with composition