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