Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

♻ Move pipe reading logic into pipe, so that it's shared #24

Merged
merged 1 commit into from
Feb 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 3 additions & 30 deletions crates/preimage/src/hint.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::PipeHandle;
use alloc::vec;
use anyhow::{bail, Result};
use anyhow::Result;

/// A [HintWriter] is a high-level interface to the hint pipe. It provides a way to write hints to the host.
#[derive(Debug, Clone, Copy)]
Expand All @@ -24,38 +24,11 @@ impl HintWriter {
hint_bytes[4..].copy_from_slice(hint.as_bytes());

// Write the hint to the host.
let mut written = 0;
loop {
match self.pipe_handle.write(&hint_bytes[written..]) {
Ok(0) => break,
Ok(n) => {
written += n as usize;
continue;
}
Err(e) => bail!("Failed to write preimage key: {}", e),
}
}
self.pipe_handle.write(&hint_bytes)?;

// Read the hint acknowledgement from the host.
let mut hint_ack = [0u8; 1];
self.read_exact(&mut hint_ack)?;

Ok(())
}

/// Reads bytes into `buf` and returns the number of bytes read.
fn read(&self, buf: &mut [u8]) -> Result<usize> {
let read = self.pipe_handle.read(buf)?;
Ok(read as usize)
}

/// Reads exactly `buf.len()` bytes into `buf`, blocking until all bytes are read.
fn read_exact(&self, buf: &mut [u8]) -> Result<()> {
let mut read = 0;
while read < buf.len() {
let chunk_read = self.read(&mut buf[read..])?;
read += chunk_read;
}
self.pipe_handle.read_exact(&mut hint_ack)?;

Ok(())
}
Expand Down
36 changes: 4 additions & 32 deletions crates/preimage/src/oracle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ impl OracleReader {
let mut data_buffer = alloc::vec![0; self.length];

// Grab a read lock on the preimage pipe to read the data.
self.read_exact(&mut data_buffer)?;
self.cursor += self.pipe_handle.read_exact(&mut data_buffer)? as usize;

Ok(data_buffer)
}
Expand All @@ -68,7 +68,7 @@ impl OracleReader {
}

// Grab a read lock on the preimage pipe to read the data.
self.read_exact(buf)?;
self.cursor += self.pipe_handle.read_exact(buf)? as usize;

Ok(())
}
Expand All @@ -87,43 +87,15 @@ impl OracleReader {

// Write the key to the host so that it can prepare the preimage.
let key_bytes: [u8; 32] = key.into();
let mut written = 0;
loop {
match self.pipe_handle.write(&key_bytes[written..]) {
Ok(0) => break,
Ok(n) => {
written += n as usize;
continue;
}
Err(e) => bail!("Failed to write preimage key: {}", e),
}
}
self.pipe_handle.write(&key_bytes)?;

// Read the length prefix and reset the cursor.
let mut length_buffer = [0u8; 8];
self.read_exact(&mut length_buffer)?;
self.pipe_handle.read_exact(&mut length_buffer)?;
self.length = u64::from_be_bytes(length_buffer) as usize;
self.cursor = 0;
Ok(())
}

/// Reads bytes into `buf` and returns the number of bytes read.
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
let read = self.pipe_handle.read(buf)?;
self.cursor += read as usize;
Ok(read as usize)
}

/// Reads exactly `buf.len()` bytes into `buf`, blocking until all bytes are read.
fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
let mut read = 0;
while read < buf.len() {
let chunk_read = self.read(&mut buf[read..])?;
read += chunk_read;
}

Ok(())
}
}

#[cfg(test)]
Expand Down
25 changes: 23 additions & 2 deletions crates/preimage/src/pipe.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! This module contains a rudamentary pipe between two file descriptors, using [kona_common::io] for
//! reading and writing from the file descriptors.

use anyhow::Result;
use anyhow::{bail, Result};
use kona_common::{io, FileDescriptor, RegisterSize};

/// [PipeHandle] is a handle for one end of a bidirectional pipe.
Expand All @@ -27,8 +27,29 @@ impl PipeHandle {
io::read(self.read_handle, buf)
}

/// Reads exactly `buf.len()` bytes into `buf`, blocking until all bytes are read.
pub fn read_exact(&self, buf: &mut [u8]) -> Result<RegisterSize> {
let mut read = 0;
while read < buf.len() {
let chunk_read = self.read(&mut buf[read..])?;
read += chunk_read as usize;
}
Ok(read as RegisterSize)
}

/// Write the given buffer to the pipe.
pub fn write(&self, buf: &[u8]) -> Result<RegisterSize> {
io::write(self.write_handle, buf)
let mut written = 0;
loop {
match io::write(self.write_handle, &buf[written..]) {
Ok(0) => break,
Ok(n) => {
written += n as usize;
continue;
}
Err(e) => bail!("Failed to write preimage key: {}", e),
}
}
Ok(written as RegisterSize)
}
}
2 changes: 1 addition & 1 deletion fpvm-tests/cannon-go-tests/minimal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func TestMinimal(t *testing.T) {
us := mipsevm.NewInstrumentedState(state, oracle, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr))

for i := 0; i < 200_000; i++ {
_, err := us.Step(true)
_, err := us.Step(false)
require.NoError(t, err)
if state.Exited {
fmt.Printf("exited @ step #%d\n", state.Step)
Expand Down
Loading