add zkVM interface crate

This commit is contained in:
Kevaundray Wedderburn
2025-05-11 21:39:40 +01:00
parent 60498c54eb
commit 401a95bba1
5 changed files with 293 additions and 0 deletions

View File

@@ -0,0 +1,41 @@
name: Check Non-zkVM crates
on:
push:
branches:
- master
pull_request:
branches:
- master
workflow_dispatch:
jobs:
test_interface_crates:
name: Build and Test Interface Crates
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Rust toolchain (stable)
uses: dtolnay/rust-toolchain@stable
with:
components: clippy, rustfmt
- name: Cache Cargo dependencies
uses: Swatinem/rust-cache@v2
with:
key: zkvm-interface-deps
- name: Check zkvm-interface
run: cargo check --package zkvm-interface --verbose
- name: Test zkvm-interface
run: cargo test --package zkvm-interface --verbose
- name: Check formatting for zkvm-interface
run: cargo fmt --package zkvm-interface -- --check
- name: Run Clippy for zkvm-interface
run: cargo clippy --package zkvm-interface -- -D warnings

126
Cargo.lock generated Normal file
View File

@@ -0,0 +1,126 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "anyhow"
version = "1.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
[[package]]
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"serde",
]
[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "hashbrown"
version = "0.15.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3"
[[package]]
name = "indexmap"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e"
dependencies = [
"equivalent",
"hashbrown",
]
[[package]]
name = "proc-macro2"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "serde"
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "syn"
version = "2.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "2.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "2.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "zkvm-interface"
version = "0.1.0"
dependencies = [
"anyhow",
"bincode",
"indexmap",
"serde",
"thiserror",
]

18
Cargo.toml Normal file
View File

@@ -0,0 +1,18 @@
[workspace]
members = [
# zkVM interface
"crates/zkvm-interface",
]
resolver = "2"
[workspace.package]
version = "0.1.0"
edition = "2024"
rust-version = "1.85"
license = "MIT OR Apache-2.0"
[workspace.lints]
[workspace.dependencies]
# local dependencies
zkvm-interface = { path = "crates/zkvm-interface" }

View File

@@ -0,0 +1,16 @@
[package]
name = "zkvm-interface"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
license.workspace = true
[dependencies]
anyhow = "1.0"
serde = { version = "1.0", features = ["derive"] }
bincode = "1.3"
indexmap = "2.9.0"
thiserror = "2"
[lints]
workspace = true

View File

@@ -0,0 +1,92 @@
use indexmap::IndexMap;
use serde::Serialize;
use std::{path::Path, time::Duration};
#[allow(non_camel_case_types)]
/// zkVM trait to abstract away the differences between each zkVM
pub trait zkVM {
type Error: std::error::Error + Send + Sync + 'static;
/// Compiles the program and returns the `ELF` as bytes
fn compile(path_to_program: &Path) -> Result<Vec<u8>, Self::Error>;
/// Executes the given ELF binary with the inputs accumulated in the Input struct.
fn execute(elf_bytes: &[u8], inputs: &Input) -> Result<ProgramExecutionReport, Self::Error>;
/// Creates a proof for the given program
fn prove(
elf_bytes: &[u8],
inputs: &Input,
) -> Result<(Vec<u8>, ProgramProvingReport), Self::Error>;
/// Verifies a proof for the given program
fn verify(elf_bytes: &[u8], proof: &[u8]) -> Result<(), Self::Error>;
}
/// ProgramExecutionReport produces information about a particular program
/// execution.
#[derive(Debug, Clone, Default)]
pub struct ProgramExecutionReport {
/// Total number of cycles for the entire workload execution.
pub total_num_cycles: u64,
/// Region-specific cycles, mapping region names (e.g., "setup", "compute") to their cycle counts.
pub region_cycles: IndexMap<String, u64>,
}
impl ProgramExecutionReport {
pub fn new(total_num_cycles: u64) -> Self {
ProgramExecutionReport {
total_num_cycles,
region_cycles: Default::default(),
}
}
pub fn insert_region(&mut self, region_name: String, num_cycles: u64) {
self.region_cycles.insert(region_name, num_cycles);
}
}
/// ProgramProvingReport produces information about proving a particular
/// program's instance.
#[derive(Debug, Clone, Default)]
pub struct ProgramProvingReport {
pub proving_time: Duration,
}
impl ProgramProvingReport {
pub fn new(proving_time: Duration) -> Self {
Self { proving_time }
}
}
/// Represents a builder for input data to be passed to a ZKVM guest program.
/// Values are serialized sequentially into an internal byte buffer.
#[derive(Debug, Clone, Default)] // Added Default for easy initialization
pub struct Input {
// TODO: Succinct has Vec<Vec<u8> while R0 has Vec<u8>
// TODO: Maybe change back to Vec<u8> with markers for perf
pub data: Vec<Vec<u8>>,
}
impl Input {
pub fn new() -> Self {
Input { data: Vec::new() }
}
/// Serializes the given value using bincode and appends it to the internal data buffer.
pub fn write<T: Serialize>(&mut self, value: &T) -> anyhow::Result<()> {
// TODO: Remove anyhow::error for thiserror
use anyhow::Context;
let mut data = Vec::new();
let _ = bincode::serialize_into(&mut data, value).with_context(|| {
format!(
"Failed to serialize and write value of type {}",
std::any::type_name::<T>()
)
})?;
self.data.push(data);
Ok(())
}
}