#![allow(unused_unsafe)]
use crate::{halt_invalid_hint, read_vec_raw, syscall_write, ReadVecResult};
use serde::{de::DeserializeOwned, Serialize};
use std::io::{Result, Write};
pub use sp1_primitives::consts::fd::*;
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(())
}
}
#[track_caller]
pub fn read_vec() -> Vec<u8> {
let ReadVecResult { ptr, len, capacity } = unsafe { read_vec_raw() };
if ptr.is_null() {
empty_input_stream_halt();
}
unsafe { Vec::from_raw_parts(ptr, len, capacity) }
}
#[track_caller]
#[cold]
#[inline(never)]
fn empty_input_stream_halt() -> ! {
let msg = std::format!(
"Tried to read from the input stream, but it was empty @ {}\n\
Was the correct data written into SP1Stdin?\n\
Halting with exit code 3 (invalid prover hint).\n",
std::panic::Location::caller()
);
unsafe {
syscall_write(2, msg.as_ptr(), msg.len());
}
halt_invalid_hint()
}
#[track_caller]
pub fn read<T: DeserializeOwned>() -> T {
let ReadVecResult { ptr, len, capacity } = unsafe { read_vec_raw() };
if ptr.is_null() {
empty_input_stream_halt();
}
let vec = unsafe { Vec::from_raw_parts(ptr, len, capacity) };
match bincode::deserialize(&vec) {
Ok(v) => v,
Err(_) => halt_invalid_hint(),
}
}
pub fn commit<T: Serialize>(value: &T) {
let writer = SyscallWriter { fd: FD_PUBLIC_VALUES };
bincode::serialize_into(writer, value).expect("serialization failed");
}
pub fn commit_slice(buf: &[u8]) {
let mut my_writer = SyscallWriter { fd: FD_PUBLIC_VALUES };
my_writer.write_all(buf).unwrap();
}
pub fn hint<T: Serialize>(value: &T) {
let writer = SyscallWriter { fd: FD_HINT };
bincode::serialize_into(writer, value).expect("serialization failed");
}
pub fn hint_slice(buf: &[u8]) {
let mut my_reader = SyscallWriter { fd: FD_HINT };
my_reader.write_all(buf).unwrap();
}
pub fn write(fd: u32, buf: &[u8]) {
SyscallWriter { fd }.write_all(buf).unwrap();
}