Refactor mods to separate compiler and zkvm (#184)

This commit is contained in:
Han
2025-10-30 18:54:08 +08:00
committed by GitHub
parent 9957836858
commit ffc2fccaea
109 changed files with 3410 additions and 3019 deletions

View File

@@ -0,0 +1,14 @@
use serde::{Serialize, de::DeserializeOwned};
use std::path::Path;
/// Compiler trait for compiling programs into an opaque sequence of bytes.
pub trait Compiler {
type Error: std::error::Error + Send + Sync + 'static;
type Program: Clone + Send + Sync + Serialize + DeserializeOwned;
/// Compiles the program and returns the program
///
/// # Arguments
/// * `guest_directory` - The path to the guest program directory
fn compile(&self, guest_directory: &Path) -> Result<Self::Program, Self::Error>;
}

View File

@@ -1,134 +1,7 @@
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
#![allow(clippy::double_parens)]
#![allow(non_camel_case_types)]
use serde::{Deserialize, Serialize, de::DeserializeOwned};
use std::path::Path;
use strum::{EnumDiscriminants, EnumIs, EnumTryAs, FromRepr};
pub mod compiler;
pub mod zkvm;
mod error;
pub use error::CommonError;
mod reports;
pub use reports::{ProgramExecutionReport, ProgramProvingReport};
mod network;
pub use network::NetworkProverConfig;
/// Compiler trait for compiling programs into an opaque sequence of bytes.
pub trait Compiler {
type Error: std::error::Error + Send + Sync + 'static;
type Program: Clone + Send + Sync + Serialize + DeserializeOwned;
/// Compiles the program and returns the program
///
/// # Arguments
/// * `guest_directory` - The path to the guest program directory
fn compile(&self, guest_directory: &Path) -> Result<Self::Program, Self::Error>;
}
/// ResourceType specifies what resource will be used to create the proofs.
#[derive(Debug, Clone, Default)]
#[cfg_attr(feature = "clap", derive(clap::Subcommand))]
pub enum ProverResourceType {
#[default]
Cpu,
Gpu,
/// Use a remote prover network
Network(NetworkProverConfig),
}
#[cfg(feature = "clap")]
impl ProverResourceType {
pub fn to_args(&self) -> Vec<&str> {
match self {
Self::Cpu => vec!["cpu"],
Self::Gpu => vec!["gpu"],
Self::Network(config) => core::iter::once("network")
.chain(config.to_args())
.collect(),
}
}
}
/// Public values committed/revealed by guest program.
///
/// Use [`zkVM::deserialize_from`] to deserialize object from the bytes.
pub type PublicValues = Vec<u8>;
/// Proof generated by [`zkVM::prove`], that also includes the [`PublicValues`]
/// for [`zkVM::verify`] to work.
#[derive(Clone, Debug, Serialize, Deserialize, EnumDiscriminants, EnumIs, EnumTryAs)]
#[strum_discriminants(derive(Default, FromRepr))]
#[strum_discriminants(name(ProofKind))]
pub enum Proof {
/// Compressed proof in contant size regardless of the cycle count.
#[strum_discriminants(default)]
Compressed(Vec<u8>),
/// Groth16 proof that internally verifies a Compressed proof.
Groth16(Vec<u8>),
}
impl Proof {
/// Construct [`Proof`] from [`ProofKind`] and bytes.
pub fn new(proof_kind: ProofKind, bytes: Vec<u8>) -> Self {
match proof_kind {
ProofKind::Compressed => Self::Compressed(bytes),
ProofKind::Groth16 => Self::Groth16(bytes),
}
}
/// Returns [`ProofKind`].
pub fn kind(&self) -> ProofKind {
ProofKind::from(self)
}
/// Returns inner proof as bytes.
pub fn as_bytes(&self) -> &[u8] {
match self {
Self::Compressed(bytes) => bytes,
Self::Groth16(bytes) => bytes,
}
}
}
#[auto_impl::auto_impl(&, Arc, Box)]
/// zkVM trait to abstract away the differences between each zkVM.
///
/// This trait provides a unified interface, the workflow is:
/// 1. Compile a guest program using the corresponding `Compiler`.
/// 2. Create a zkVM instance with the compiled program and prover resource.
/// 3. Execute, prove, and verify using the zkVM instance methods.
///
/// Note that a zkVM instance is created for specific program, each zkVM
/// implementation will have their own construction function.
pub trait zkVM {
/// Executes the program with the given input.
fn execute(&self, input: &[u8]) -> anyhow::Result<(PublicValues, ProgramExecutionReport)>;
/// Creates a proof of the program execution with given input.
fn prove(
&self,
input: &[u8],
proof_kind: ProofKind,
) -> anyhow::Result<(PublicValues, Proof, ProgramProvingReport)>;
/// Verifies a proof of the program used to create this zkVM instance, then
/// returns the public values extracted from the proof.
#[must_use = "Public values must be used"]
fn verify(&self, proof: &Proof) -> anyhow::Result<PublicValues>;
/// Returns the name of the zkVM
fn name(&self) -> &'static str;
/// Returns the version of the zkVM SDK (e.g. 0.1.0)
fn sdk_version(&self) -> &'static str;
}
pub trait zkVMProgramDigest {
/// Digest of specific compiled guest program used when verify a proof.
type ProgramDigest: Clone + Serialize + DeserializeOwned;
/// Returns [`zkVMProgramDigest::ProgramDigest`].
fn program_digest(&self) -> anyhow::Result<Self::ProgramDigest>;
}
pub use compiler::*;
pub use zkvm::*;

View File

@@ -0,0 +1,59 @@
#![allow(non_camel_case_types)]
use serde::{Serialize, de::DeserializeOwned};
mod error;
mod proof;
mod report;
mod resource;
pub use error::CommonError;
pub use proof::{Proof, ProofKind};
pub use report::{ProgramExecutionReport, ProgramProvingReport};
pub use resource::{NetworkProverConfig, ProverResourceType};
/// Public values committed/revealed by guest program.
///
/// Use [`zkVM::deserialize_from`] to deserialize object from the bytes.
pub type PublicValues = Vec<u8>;
/// zkVM trait to abstract away the differences between each zkVM.
///
/// This trait provides a unified interface, the workflow is:
/// 1. Compile a guest program using the corresponding `Compiler`.
/// 2. Create a zkVM instance with the compiled program and prover resource.
/// 3. Execute, prove, and verify using the zkVM instance methods.
///
/// Note that a zkVM instance is created for specific program, each zkVM
/// implementation will have their own construction function.
#[auto_impl::auto_impl(&, Arc, Box)]
pub trait zkVM {
/// Executes the program with the given input.
fn execute(&self, input: &[u8]) -> anyhow::Result<(PublicValues, ProgramExecutionReport)>;
/// Creates a proof of the program execution with given input.
fn prove(
&self,
input: &[u8],
proof_kind: ProofKind,
) -> anyhow::Result<(PublicValues, Proof, ProgramProvingReport)>;
/// Verifies a proof of the program used to create this zkVM instance, then
/// returns the public values extracted from the proof.
#[must_use = "Public values must be used"]
fn verify(&self, proof: &Proof) -> anyhow::Result<PublicValues>;
/// Returns the name of the zkVM
fn name(&self) -> &'static str;
/// Returns the version of the zkVM SDK (e.g. 0.1.0)
fn sdk_version(&self) -> &'static str;
}
pub trait zkVMProgramDigest {
/// Digest of specific compiled guest program used when verify a proof.
type ProgramDigest: Clone + Serialize + DeserializeOwned;
/// Returns [`zkVMProgramDigest::ProgramDigest`].
fn program_digest(&self) -> anyhow::Result<Self::ProgramDigest>;
}

View File

@@ -1,4 +1,4 @@
use crate::ProofKind;
use crate::zkvm::ProofKind;
use std::{
io,
path::Path,

View File

@@ -0,0 +1,40 @@
#![allow(clippy::double_parens)]
use serde::{Deserialize, Serialize};
use strum::{EnumDiscriminants, EnumIs, EnumTryAs, FromRepr};
/// Proof generated by [`zkVM::prove`], that also includes the [`PublicValues`]
/// for [`zkVM::verify`] to work.
#[derive(Clone, Debug, Serialize, Deserialize, EnumDiscriminants, EnumIs, EnumTryAs)]
#[strum_discriminants(derive(Default, FromRepr))]
#[strum_discriminants(name(ProofKind))]
pub enum Proof {
/// Compressed proof in contant size regardless of the cycle count.
#[strum_discriminants(default)]
Compressed(Vec<u8>),
/// Groth16 proof that internally verifies a Compressed proof.
Groth16(Vec<u8>),
}
impl Proof {
/// Construct [`Proof`] from [`ProofKind`] and bytes.
pub fn new(proof_kind: ProofKind, bytes: Vec<u8>) -> Self {
match proof_kind {
ProofKind::Compressed => Self::Compressed(bytes),
ProofKind::Groth16 => Self::Groth16(bytes),
}
}
/// Returns [`ProofKind`].
pub fn kind(&self) -> ProofKind {
ProofKind::from(self)
}
/// Returns inner proof as bytes.
pub fn as_bytes(&self) -> &[u8] {
match self {
Self::Compressed(bytes) => bytes,
Self::Groth16(bytes) => bytes,
}
}
}

View File

@@ -22,3 +22,27 @@ impl NetworkProverConfig {
.collect()
}
}
/// ResourceType specifies what resource will be used to create the proofs.
#[derive(Debug, Clone, Default)]
#[cfg_attr(feature = "clap", derive(clap::Subcommand))]
pub enum ProverResourceType {
#[default]
Cpu,
Gpu,
/// Use a remote prover network
Network(NetworkProverConfig),
}
#[cfg(feature = "clap")]
impl ProverResourceType {
pub fn to_args(&self) -> Vec<&str> {
match self {
Self::Cpu => vec!["cpu"],
Self::Gpu => vec!["gpu"],
Self::Network(config) => core::iter::once("network")
.chain(config.to_args())
.collect(),
}
}
}