Skip to content

Commit

Permalink
Adding a few Rust doc examples to Executor and ExecutorEnv (risc0#572)
Browse files Browse the repository at this point in the history
* adding examples to ExecutorEnv and Executor

* Update risc0/zkvm/src/exec/env.rs

Co-authored-by: Frank Laub <[email protected]>

* Update risc0/zkvm/src/exec/env.rs

Co-authored-by: Frank Laub <[email protected]>

* Update risc0/zkvm/src/exec/mod.rs

Co-authored-by: Frank Laub <[email protected]>

* updating executor/executor env doc examples after code review

* Update risc0/zkvm/src/exec/env.rs

Co-authored-by: Tim Zerrell <[email protected]>

---------

Co-authored-by: Frank Laub <[email protected]>
Co-authored-by: Tim Zerrell <[email protected]>
  • Loading branch information
3 people authored May 24, 2023
1 parent a5247ca commit 2d04249
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 3 deletions.
73 changes: 73 additions & 0 deletions risc0/zkvm/src/exec/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ pub struct ExecutorEnvBuilder<'a> {
}

/// The [super::Executor] is configured from this object.
///
/// The executor environment holds configuration details that inform how the
/// guest environment is set up prior to guest program execution.
#[derive(Clone)]
pub struct ExecutorEnv<'a> {
env_vars: HashMap<String, String>,
Expand All @@ -63,6 +66,16 @@ pub struct ExecutorEnv<'a> {

impl<'a> ExecutorEnv<'a> {
/// Construct a [ExecutorEnvBuilder].
/// # Example
/// ```
/// use risc0_zkvm::{
/// ExecutorEnv,
/// ExecutorEnvBuilder};
///
/// let a: u64 = 400;
///
/// let env = ExecutorEnv::builder().build();
/// ```
pub fn builder() -> ExecutorEnvBuilder<'a> {
ExecutorEnvBuilder::default()
}
Expand Down Expand Up @@ -104,6 +117,14 @@ impl<'a> Default for ExecutorEnvBuilder<'a> {

impl<'a> ExecutorEnvBuilder<'a> {
/// Finalize this builder to construct an [ExecutorEnv].
/// # Example
/// ```
/// use risc0_zkvm::{
/// ExecutorEnv,
/// ExecutorEnvBuilder};
///
/// let env = ExecutorEnv::builder().build();
/// ```
pub fn build(&mut self) -> ExecutorEnv<'a> {
let mut result = self.clone();
let getenv = syscalls::Getenv(self.inner.env_vars.clone());
Expand Down Expand Up @@ -131,18 +152,55 @@ impl<'a> ExecutorEnvBuilder<'a> {
}

/// Set a session limit, specified in number of cycles.
/// # Example
/// ```
/// use risc0_zkvm::{
/// ExecutorEnv,
/// ExecutorEnvBuilder};
///
/// const NEW_SESSION_LIMIT: usize = 32 * 1024 * 1024; // 32M cycles
///
/// let env = ExecutorEnv::builder()
/// .session_limit(32 * 1024 * 1024) // 32M cycles
/// .build();
/// ```
pub fn session_limit(&mut self, limit: usize) -> &mut Self {
self.inner.session_limit = limit;
self
}

/// Add environment variables to the guest environment.
/// # Example
/// ```
/// use risc0_zkvm::{
/// ExecutorEnv,
/// ExecutorEnvBuilder};
/// use std::collections::HashMap;
///
/// let mut vars = HashMap::new();
/// vars.insert("VAR1".to_string(), "SOME_VALUE".to_string());
/// vars.insert("VAR2".to_string(), "SOME_VALUE".to_string());
///
/// let env = ExecutorEnv::builder()
/// .env_vars(vars)
/// .build();
/// ```
pub fn env_vars(&mut self, vars: HashMap<String, String>) -> &mut Self {
self.inner.env_vars = vars;
self
}

/// Add an environment variable to the guest environment.
/// # Example
/// ```
/// # use risc0_zkvm::{
/// # ExecutorEnv,
/// # ExecutorEnvBuilder};
///
/// let env = ExecutorEnv::builder()
/// .env_var("VAR1", "SOME_VALUE")
/// .build();
/// ```
pub fn env_var(&mut self, name: &str, val: &str) -> &mut Self {
self.inner
.env_vars
Expand All @@ -151,6 +209,21 @@ impl<'a> ExecutorEnvBuilder<'a> {
}

/// Add initial input that can be read by the guest from stdin.
/// Calling `ExecutorEnvBuilder::add_input()` iteratively concatenates
/// inputs; the guest can access each input using consecutive reads. ```
/// use risc0_zkvm::{
/// ExecutorEnv,
/// ExecutorEnvBuilder,
/// serde::to_vec};
///
/// let a: u64 = 400;
/// let b: u64 = 200;
///
/// let env = ExecutorEnv::builder()
/// .add_input(&to_vec(&a).unwrap())
/// .add_input(&to_vec(&b).unwrap())
/// .build();
/// ```
pub fn add_input<T: Pod>(&mut self, slice: &[T]) -> &mut Self {
self.inner
.input
Expand Down
38 changes: 35 additions & 3 deletions risc0/zkvm/src/exec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@

//! The execution phase is implemented by this module.
//!
//! The result of the execution phase is [Session], which contains one or more
//! [Segment]s, each which contains an execution trace of the specified program.
//! The result of the execution phase is a [Session]. Each [Session] contains
//! one or more [Segment]s, each of which contains an execution trace of the
//! specified program.
mod env;
pub(crate) mod io;
Expand Down Expand Up @@ -129,6 +130,12 @@ impl Write for Journal {

impl<'a> Executor<'a> {
/// Construct a new [Executor] from a [MemoryImage] and entry point.
///
/// Before a guest program is proven, the [Executor] is responsible for
/// deciding where a zkVM program should be split into [Segment]s and what
/// work will be done in each segment. This is the execution phase:
/// the guest program is executed to determine how its proof should be
/// divided into subparts.
pub fn new(env: ExecutorEnv<'a>, image: MemoryImage, pc: u32) -> Self {
let pre_image = image.clone();
let monitor = MemoryMonitor::new(image);
Expand All @@ -151,7 +158,20 @@ impl<'a> Executor<'a> {
}
}

/// Construct a new [Executor] from an ELF binary.
/// Construct a new [Executor] from the ELF binary of the guest program you
/// want to run and an [ExecutorEnv] containing relevant environmental
/// configuration details.
/// # Example
/// ```
/// use risc0_zkvm::{serde::to_vec, Executor, ExecutorEnv, Session};
/// use risc0_zkvm_methods::{BENCH_ELF, bench::{BenchmarkSpec, SpecWithIters}};
///
/// let spec = SpecWithIters(BenchmarkSpec::SimpleLoop, 1);
/// let env = ExecutorEnv::builder()
/// .add_input(&to_vec(&spec).unwrap())
/// .build();
/// let mut exec = Executor::from_elf(env, BENCH_ELF).unwrap();
/// ```
pub fn from_elf(env: ExecutorEnv<'a>, elf: &[u8]) -> Result<Self> {
let program = Program::load_elf(&elf, MEM_SIZE as u32)?;
let image = MemoryImage::new(&program, PAGE_SIZE as u32)?;
Expand All @@ -160,6 +180,18 @@ impl<'a> Executor<'a> {

/// Run the executor until [ExitCode::Paused] or [ExitCode::Halted] is
/// reached, producing a [Session] as a result.
/// # Example
/// ```
/// use risc0_zkvm::{serde::to_vec, Executor, ExecutorEnv, Session};
/// use risc0_zkvm_methods::{BENCH_ELF, bench::{BenchmarkSpec, SpecWithIters}};
///
/// let spec = SpecWithIters(BenchmarkSpec::SimpleLoop, 1);
/// let env = ExecutorEnv::builder()
/// .add_input(&to_vec(&spec).unwrap())
/// .build();
/// let mut exec = Executor::from_elf(env, BENCH_ELF).unwrap();
/// let session = exec.run().unwrap();
/// ```
pub fn run(&mut self) -> Result<Session> {
self.run_with_callback(|segment| Ok(Box::new(SimpleSegmentRef::new(segment))))
}
Expand Down

0 comments on commit 2d04249

Please sign in to comment.