Inputs and Outputs
In real world applications of zero-knowledge proofs, you almost always want to verify your proof in the context of some inputs and outputs. For example:
- Rollups: Given a list of transactions, prove the new state of the blockchain.
- Coprocessors: Given a block header, prove the historical state of some storage slot inside a smart contract.
- Attested Images: Given a signed image, prove that you made a restricted set of image transformations.
In this section, we cover how you pass inputs and outputs to the zkVM and create new types that support serialization.
Reading Data
Data that is read is not public to the verifier by default. Use the sp1_zkvm::io::read::<T>
method:
let a = sp1_zkvm::io::read::<u32>();
let b = sp1_zkvm::io::read::<u64>();
let c = sp1_zkvm::io::read::<String>();
Note that T
must implement the serde::Serialize
and serde::Deserialize
trait. If you want to read bytes directly, you can also use the sp1_zkvm::io::read_vec
method.
let my_vec = sp1_zkvm::io::read_vec();
Committing Data
Committing to data makes the data public to the verifier. Use the sp1_zkvm::io::commit::<T>
method:
sp1_zkvm::io::commit::<u32>(&a);
sp1_zkvm::io::commit::<u64>(&b);
sp1_zkvm::io::commit::<String>(&c);
Note that T
must implement the Serialize
and Deserialize
trait. If you want to write bytes directly, you can also use sp1_zkvm::io::commit_slice
method:
let mut my_slice = [0_u8; 32];
sp1_zkvm::io::commit_slice(&my_slice);
Creating Serializable Types
Typically, you can implement the Serialize
and Deserialize
traits using a simple derive macro on a struct.
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct MyStruct {
a: u32,
b: u64,
c: String
}
For more complex usecases, refer to the Serde docs.
Example
Here is a basic example of using inputs and outputs with more complex types.
#![no_main]
sp1_zkvm::entrypoint!(main);
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct MyPointUnaligned {
pub x: usize,
pub y: usize,
pub b: bool,
}
pub fn main() {
let p1 = sp1_zkvm::io::read::<MyPointUnaligned>();
println!("Read point: {:?}", p1);
let p2 = sp1_zkvm::io::read::<MyPointUnaligned>();
println!("Read point: {:?}", p2);
let p3: MyPointUnaligned = MyPointUnaligned { x: p1.x + p2.x, y: p1.y + p2.y, b: p1.b && p2.b };
println!("Addition of 2 points: {:?}", p3);
sp1_zkvm::io::commit(&p3);
}