sp1_lib/
io.rs

1#![allow(unused_unsafe)]
2use crate::{read_vec_raw, syscall_write, ReadVecResult};
3use serde::{de::DeserializeOwned, Serialize};
4use std::io::{Result, Write};
5
6pub use sp1_primitives::consts::fd::*;
7
8/// A writer that writes to a file descriptor inside the zkVM.
9struct SyscallWriter {
10    fd: u32,
11}
12
13impl Write for SyscallWriter {
14    fn write(&mut self, buf: &[u8]) -> Result<usize> {
15        let nbytes = buf.len();
16        let write_buf = buf.as_ptr();
17        unsafe {
18            syscall_write(self.fd, write_buf, nbytes);
19        }
20        Ok(nbytes)
21    }
22
23    fn flush(&mut self) -> Result<()> {
24        Ok(())
25    }
26}
27
28/// Read a buffer from the input stream. The buffer is read into uninitialized memory.
29///
30/// When the `bump` feature is enabled, the buffer is read into a new buffer allocated by the
31/// program.
32///
33/// When the `embedded` feature is enabled, the buffer is read into the reserved input region.
34///
35/// When there is no allocator selected, the program will fail to compile.
36///
37/// ### Examples
38/// ```ignore
39/// let data: Vec<u8> = sp1_zkvm::io::read_vec();
40/// ```
41#[track_caller]
42pub fn read_vec() -> Vec<u8> {
43    let ReadVecResult { ptr, len, capacity } = unsafe { read_vec_raw() };
44
45    if ptr.is_null() {
46        panic!(
47            "Tried to read from the input stream, but it was empty @ {} \n
48            Was the correct data written into SP1Stdin?",
49            std::panic::Location::caller()
50        )
51    }
52
53    unsafe { Vec::from_raw_parts(ptr, len, capacity) }
54}
55
56/// Read a deserializable object from the input stream.
57///
58/// ### Examples
59/// ```ignore
60/// use serde::{Deserialize, Serialize};
61///
62/// #[derive(Serialize, Deserialize)]
63/// struct MyStruct {
64///     a: u32,
65///     b: u32,
66/// }
67///
68/// let data: MyStruct = sp1_zkvm::io::read();
69/// ```
70#[track_caller]
71pub fn read<T: DeserializeOwned>() -> T {
72    let ReadVecResult { ptr, len, capacity } = unsafe { read_vec_raw() };
73
74    if ptr.is_null() {
75        panic!(
76            "Tried to read from the input stream, but it was empty @ {} \n
77            Was the correct data written into SP1Stdin?",
78            std::panic::Location::caller()
79        )
80    }
81
82    // 1. `ptr` was allocated using alloc
83    // 2. Assume that the allocator in the VM doesn't deallocate in the input space.
84    // 3. Size and length are correct from above. Length is <= capacity.
85    let vec = unsafe { Vec::from_raw_parts(ptr, len, capacity) };
86
87    bincode::deserialize(&vec).expect("deserialization failed")
88}
89
90/// Commit a serializable object to the public values stream.
91///
92/// ### Examples
93/// ```ignore
94/// use serde::{Deserialize, Serialize};
95///
96/// #[derive(Serialize, Deserialize)]
97/// struct MyStruct {
98///     a: u32,
99///     b: u32,
100/// }
101///
102/// let data = MyStruct {
103///     a: 1,
104///     b: 2,
105/// };
106/// sp1_zkvm::io::commit(&data);
107/// ```
108pub fn commit<T: Serialize>(value: &T) {
109    let writer = SyscallWriter { fd: FD_PUBLIC_VALUES };
110    bincode::serialize_into(writer, value).expect("serialization failed");
111}
112
113/// Commit bytes to the public values stream.
114///
115/// ### Examples
116/// ```ignore
117/// let data = vec![1, 2, 3, 4];
118/// sp1_zkvm::io::commit_slice(&data);
119/// ```
120pub fn commit_slice(buf: &[u8]) {
121    let mut my_writer = SyscallWriter { fd: FD_PUBLIC_VALUES };
122    my_writer.write_all(buf).unwrap();
123}
124
125/// Hint a serializable object to the hint stream.
126///
127/// ### Examples
128/// ```ignore
129/// use serde::{Deserialize, Serialize};
130///
131/// #[derive(Serialize, Deserialize)]
132/// struct MyStruct {
133///     a: u32,
134///     b: u32,
135/// }
136///
137/// let data = MyStruct {
138///     a: 1,
139///     b: 2,
140/// };
141/// sp1_zkvm::io::hint(&data);
142/// ```
143pub fn hint<T: Serialize>(value: &T) {
144    let writer = SyscallWriter { fd: FD_HINT };
145    bincode::serialize_into(writer, value).expect("serialization failed");
146}
147
148/// Hint bytes to the hint stream.
149///
150/// ### Examples
151/// ```ignore
152/// let data = vec![1, 2, 3, 4];
153/// sp1_zkvm::io::hint_slice(&data);
154/// ```
155pub fn hint_slice(buf: &[u8]) {
156    let mut my_reader = SyscallWriter { fd: FD_HINT };
157    my_reader.write_all(buf).unwrap();
158}
159
160/// Write the data `buf` to the file descriptor `fd`.
161///
162/// ### Examples
163/// ```ignore
164/// let data = vec![1, 2, 3, 4];
165/// sp1_zkvm::io::write(3, &data);
166/// ```
167pub fn write(fd: u32, buf: &[u8]) {
168    SyscallWriter { fd }.write_all(buf).unwrap();
169}