Skip to main content

ZiskStdin

ZiskStdin is the host-side, in-memory input buffer passed to the guest program. Fill it with typed values or raw bytes before passing it to prove() or execute(). For runtime-streamed inputs, use ZiskStream instead.

Overview

The guest has no access to the outside world during execution. Every byte it consumes must be loaded into a ZiskStdin (or a ZiskStream) on the host before the run starts. ZiskStdin is a fully-buffered carrier: every byte sits in memory before proving begins. Both ZiskStdin and ZiskStream carry an Into<InputSource> implementation, so they are interchangeable in client.prove(&program, ...) and client.execute(&program, ...).


Type

pub struct ZiskStdin(/* private */);

Constructors

new

Create an empty buffer.

pub fn new() -> ZiskStdin

Example

use zisk_sdk::ZiskStdin;

let stdin = ZiskStdin::new();

let proof = client.prove(&PROGRAM, stdin).run()?.await?;

from_bytes

Create a buffer pre-filled with raw bytes, equivalent to a new() followed by a single write_slice.

pub fn from_bytes(bytes: Vec<u8>) -> ZiskStdin

Parameters

NameTypeDescription
bytesVec<u8>Raw bytes to load as the initial buffer.

Use this when the input already exists as a byte vector. For instance, when you build the bytes yourself or load them from a custom store.

from_file

Load a buffer from a binary file on disk. The file's contents become the entire input buffer.

pub fn from_file(path: impl AsRef<Path>) -> Result<ZiskStdin>

Parameters

NameTypeDescription
pathimpl AsRef<Path>Path to the binary input file.

Returns

TypeDescription
Result<ZiskStdin>The loaded input, or an error if the file is missing.

Use this to load pre-built inputs created by cargo-zisk or by a previous stdin.save(...) call. Useful for reproducible test vectors.

Example

use zisk_sdk::ZiskStdin;

let stdin = ZiskStdin::from_file("inputs/test-vector.bin")?;
let proof = client.prove(&PROGRAM, stdin).run()?.await?;

from_uri

Load a buffer from a URI. Accepts a file:// URI (or None for an empty buffer), letting the input location be configured at runtime.

pub fn from_uri<S: Into<String>>(uri: Option<S>) -> Result<ZiskStdin>

Parameters

NameTypeDescription
uriOption<impl Into<String>>Some(uri) to load from a file:// URI, None for an empty buffer.

Write methods

write

Serialize value with bincode and append it to the input buffer. Writes a u64 length header followed by the serialized bytes, zero-padded to the next 8-byte boundary.

pub fn write<T: Serialize>(&self, data: &T)

Parameters

NameTypeDescription
data&T: SerializeThe value to serialize and append.

The guest reads this value with io::read::<T>(). The type T must implement serde::Serialize on the host and serde::Deserialize on the guest.

Example

let stdin = ZiskStdin::new();

// Typed primitives
stdin.write::<u64>(&3);
stdin.write::<u32>(&10);

// Typed struct
stdin.write(&MyStruct { x: 1, y: 2 });

// String
stdin.write(&String::from("Hello Zisk"));

write_slice

Append raw bytes to the input buffer with the same framing write uses: a u64 length header followed by the bytes, zero-padded to the next 8-byte boundary. The difference vs write is that the bytes are not serialized through bincode.

pub fn write_slice(&self, data: &[u8])

Parameters

NameTypeDescription
data&[u8]Raw bytes to append to the buffer.

Use write_slice when the data is already in a specific binary format, or to avoid bincode overhead for large byte payloads.


Read methods

The read side mirrors the write side. It is most useful when the host needs to inspect a ZiskStdin it received from elsewhere — for example, replaying a saved test vector or asserting on the bytes built by another layer of the application.

Each ZiskStdin carries an internal read cursor. The first read starts at the beginning of the buffer; each subsequent read advances the cursor past the value just consumed. Call reset or rewind to bring the cursor back to the start.

read

Read and deserialize the next value from the buffer.

pub fn read<T: DeserializeOwned>(&self) -> Result<T>

Returns

TypeDescription
Result<T>The deserialized value, or an error on bad framing.

The value is decoded with the same bincode configuration write uses. The cursor advances past the length header and the payload (including the 8-byte padding).

Example

let stdin = ZiskStdin::from_file("inputs/test-vector.bin")?;

let count: u64 = stdin.read()?;
let header: MyHeader = stdin.read()?;

read_bytes

Read the next raw byte record from the buffer.

pub fn read_bytes(&self) -> Vec<u8>

Returns

TypeDescription
Vec<u8>The bytes consumed at the current cursor.

Pairs with write_slice on the host and io::read_slice on the guest. Use it when you need to inspect raw payloads the host wrote without going through bincode.


Cursor controls

reset

Reset the internal read position so the next read starts from the beginning of the buffer.

pub fn reset(&self)

rewind

Rewind the write cursor to the beginning. Equivalent to reset for the read cursor.

pub fn rewind(&self)

clear

Clear the entire buffer. Subsequent reads see an empty input.

pub fn clear(&self)

Persistence

save

Write the buffered input to a binary file on disk.

pub fn save(&self, path: impl AsRef<Path>) -> Result<()>

Parameters

NameTypeDescription
pathimpl AsRef<Path>Destination path for the input file.

The parent directory must exist. The file is created or overwritten if it already exists.

Example

let stdin = ZiskStdin::new();
stdin.write(&vec![10u32, 20, 30]);
stdin.write(&42u64);
stdin.save("inputs/test-vector.bin")?;