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.