Skip to content

Overview of Basic Usage

Writing a Program

The first step to using OpenVM is to write a Rust program that can be executed by an OpenVM virtual machine. Writing a program for OpenVM is very similar to writing a standard Rust program, with a few key differences necessary to support the OpenVM environment. For more detailed information about writing programs, see the Writing a Program guide.

Building and Transpiling a Program

At this point, you should have a guest program with a Cargo.toml file in the root of your project directory. What's next?

The first thing you will want to do is build and transpile your program using the following command:

cargo openvm build

By default this will build the project located in the current directory. To execute the program, you can run the following command:

cargo openvm run --input <path_to_input | hex_string>

Note if your program doesn't require inputs, you can omit the --input flag.

For more information see the build and run docs.

Inputs

The --input field needs to either be a single hex string or a file path to a json file that contains the key input and an array of hex strings. Also note that if you need to provide multiple input streams, you have to use the file path option. Each hex string (either in the file or as the direct input) is either:

  • Hex string of bytes, which is prefixed with 0x01
  • Hex string of native field elements (represented as u32, little endian), prefixed with 0x02

If you are providing input for a struct of type T that will be deserialized by the openvm::io::read() function, then the corresponding hex string should be prefixed by 0x01 followed by the serialization of T into bytes according to openvm::serde::to_vec. The serialization will serialize primitive types (e.g., u8, u16, u32, u64) into little-endian bytes. All serialized bytes are zero-padded to a multiple of 4 byte length.

As an example, the code snippet below generates an input json file from a struct of type T:

use std::{fs, path::PathBuf};
use std::error::Error;
 
fn encode_input_file<T>(value: &T, path: PathBuf) -> Result<(), Box<dyn Error>>
where
    T: serde::Serialize + ?Sized,
{
  let words = openvm::serde::to_vec(value)?;
  let bytes: Vec<u8> = words
      .into_iter()
      .flat_map(|w| w.to_le_bytes())
      .collect();
  let hex_bytes = String::from("0x01") + &hex::encode(&bytes);
  let input = serde_json::json!({
      "input": [hex_bytes]
  });
  fs::write(path, serde_json::to_string(&input)?)?;
  Ok(())
}

For more details on how to serialize complex types into a VM-readable format, see the input utilities in the OpenVM example program.

Generating Application Proofs

To generate a proof, you first need to generate a proving and verifying key for the OpenVM configuration used by the program. This depends only on the configuration specified in openvm.toml and is done by the following command:

cargo openvm keygen

See the custom extensions docs for more information about openvm.toml.

Once you have generated the keys, you can generate commitments to the program binary and VM configuration using the following command:

cargo openvm commit

Also, after generating the keys, you can generate a proof by running:

cargo openvm prove app --input <path_to_input | hex_string>

Again, if your program doesn't require inputs, you can omit the --input flag. For more information on the keygen and prove commands, see the prove doc.

Verifying Application Proofs

To verify a proof using the CLI, you need to provide the verifying key and the proof.

cargo openvm verify app

For more information on the verify command, see the verify doc.

STARK and EVM Proof Generation and Verification

The process above details the workflow necessary to build, prove, and verify a guest program at the application level. As described in the specs, OpenVM supports proof aggregation into a single STARK proof or an EVM proof. Performing this aggregation requires key generation for the aggregation proving keys and the EVM verifier contract, which is done by:

cargo openvm setup [--evm]

This will write the files necessary for STARK aggregation and EVM proving to ~/.openvm/.

To generate and verify aggregated STARK or EVM proofs, you can run the following commands:

cargo openvm prove <stark | evm> --input <path_to_input | hex_string>
cargo openvm verify <stark | evm>

For more information on the prove and verify commands, see the prove and verify docs.