feat: Add prover network parameter (#35)

* one shot :D

* update cargo.lock

* one shot

* commit

* remove unused parameter

* simplify

* derive default

* update

* update cargo.lock
This commit is contained in:
kevaundray
2025-06-17 17:37:10 +02:00
committed by GitHub
parent 8b84f257b9
commit 33f0b62d34
9 changed files with 158 additions and 22 deletions

46
Cargo.lock generated
View File

@@ -1193,7 +1193,7 @@ dependencies = [
"bitflags 2.9.0",
"cexpr",
"clang-sys",
"itertools 0.11.0",
"itertools 0.13.0",
"log",
"prettyplease",
"proc-macro2",
@@ -2621,7 +2621,6 @@ name = "ere-sp1"
version = "0.1.0"
dependencies = [
"bincode",
"indexmap 2.9.0",
"sp1-sdk",
"tempfile",
"thiserror 2.0.12",
@@ -3462,6 +3461,22 @@ version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "humantime"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f"
[[package]]
name = "humantime-serde"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57a3db5ea5923d99402c94e9feb261dc5ee9b4efa158b0315f788cf549cc200c"
dependencies = [
"humantime",
"serde",
]
[[package]]
name = "hybrid-array"
version = "0.2.3"
@@ -7156,7 +7171,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d"
dependencies = [
"anyhow",
"itertools 0.11.0",
"itertools 0.14.0",
"proc-macro2",
"quote",
"syn 2.0.101",
@@ -7643,9 +7658,9 @@ dependencies = [
[[package]]
name = "risc0-build"
version = "2.1.1"
version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31d104165340cba919a3dac26c4be7da04b20b941601a7ad50c04834c4d26de5"
checksum = "d17d6657b1fb615c0482bd4b57aae7850911ed7dbdc8e783df20e93f33209a8f"
dependencies = [
"anyhow",
"cargo_metadata 0.19.2",
@@ -7682,9 +7697,9 @@ dependencies = [
[[package]]
name = "risc0-circuit-keccak"
version = "2.0.1"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cd8acfc84307ed1be64cf9fefc390963fc22b2865d027f03405977a0cfa9747"
checksum = "8d339c65b0e011677404bd6bdfe1b0f29748187a568fb2f74df7fb650590181a"
dependencies = [
"anyhow",
"bytemuck",
@@ -7720,9 +7735,9 @@ dependencies = [
[[package]]
name = "risc0-circuit-recursion"
version = "2.0.1"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdd1514e94440e2da301f48d345e1937b315147f58c5dc4992feb045324651d"
checksum = "8c6501fd3936aea2dd3e55915f34328fe96e6ca25ef00320242f837ae668785b"
dependencies = [
"anyhow",
"bytemuck",
@@ -7759,9 +7774,9 @@ dependencies = [
[[package]]
name = "risc0-circuit-rv32im"
version = "2.0.3"
version = "2.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23f6ed144d8b8f93c4a6096e3dd90f9dcbd91eff83eae690a72fd6e640760b94"
checksum = "c80e0a8f0f56106295bb682dbc27093438e163a5f6384a79e877ab895a11d9ae"
dependencies = [
"anyhow",
"auto_ops",
@@ -7791,9 +7806,9 @@ dependencies = [
[[package]]
name = "risc0-circuit-rv32im-sys"
version = "2.0.1"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3904bb2fb2d26f96dd8dea5c5fcd7b86efd7e6f3e6dc56ef33e3e7fee51c4de"
checksum = "ddac6b8acb1db761872fafa063155d99fe2cc845dc60037cde9ac05466044898"
dependencies = [
"cc",
"cust",
@@ -7899,9 +7914,9 @@ dependencies = [
[[package]]
name = "risc0-zkvm"
version = "2.0.2"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a049319790277845335445b549d49e66341f4a7ffba7f7aaa1e77e2fc4a9c19"
checksum = "0f1014d2efcb3b359aff878c9aeb6aa949a6d91f091a2ffb5ffd8d928a1ab7f3"
dependencies = [
"addr2line 0.22.0",
"anyhow",
@@ -10819,6 +10834,7 @@ dependencies = [
"auto_impl",
"bincode",
"erased-serde",
"humantime-serde",
"indexmap 2.9.0",
"serde",
"serde_json",

View File

@@ -9,7 +9,7 @@ license.workspace = true
zkvm-interface = { workspace = true }
anyhow = "1.0" #TODO: remove only needed in tests
toml = "0.8"
risc0-zkvm = { version = "^2.0.2", features = ["unstable"] }
risc0-zkvm = { version = "^2.1.0", features = ["unstable"] }
borsh = "1.5.7"
hex = "*"

View File

@@ -40,6 +40,9 @@ impl EreRisc0 {
#[cfg(not(any(feature = "cuda", feature = "metal")))]
panic!("GPU selected but neither 'cuda' nor 'metal' feature is enabled");
}
ProverResourceType::Network(_) => {
panic!("Network proving not yet implemented for RISC Zero. Use CPU or GPU resource type.");
}
}
Self {

View File

@@ -13,7 +13,6 @@ tempfile = "3.3"
bincode = "1.3"
thiserror = "2"
tracing = "0.1"
indexmap = { version = "2.9.0", features = ["serde"] }
[lib]
name = "ere_succinct"

View File

@@ -4,13 +4,13 @@ use std::time::Instant;
use compile::compile_sp1_program;
use sp1_sdk::{
CpuProver, CudaProver, Prover, ProverClient, SP1ProofWithPublicValues, SP1ProvingKey, SP1Stdin,
SP1VerifyingKey,
CpuProver, CudaProver, NetworkProver, Prover, ProverClient, SP1ProofWithPublicValues,
SP1ProvingKey, SP1Stdin, SP1VerifyingKey,
};
use tracing::info;
use zkvm_interface::{
Compiler, Input, InputItem, ProgramExecutionReport, ProgramProvingReport, ProverResourceType,
zkVM, zkVMError,
Compiler, Input, InputItem, NetworkProverConfig, ProgramExecutionReport, ProgramProvingReport,
ProverResourceType, zkVM, zkVMError,
};
mod compile;
@@ -21,6 +21,7 @@ use error::{ExecuteError, ProveError, SP1Error, VerifyError};
enum ProverType {
Cpu(CpuProver),
Gpu(CudaProver),
Network(NetworkProver),
}
impl ProverType {
@@ -31,6 +32,7 @@ impl ProverType {
match self {
ProverType::Cpu(cpu_prover) => cpu_prover.setup(program),
ProverType::Gpu(cuda_prover) => cuda_prover.setup(program),
ProverType::Network(network_prover) => network_prover.setup(program),
}
}
@@ -42,6 +44,7 @@ impl ProverType {
let cpu_executor_builder = match self {
ProverType::Cpu(cpu_prover) => cpu_prover.execute(program, input),
ProverType::Gpu(cuda_prover) => cuda_prover.execute(program, input),
ProverType::Network(network_prover) => network_prover.execute(program, input),
};
cpu_executor_builder
@@ -56,6 +59,7 @@ impl ProverType {
match self {
ProverType::Cpu(cpu_prover) => cpu_prover.prove(pk, input).core().run(),
ProverType::Gpu(cuda_prover) => cuda_prover.prove(pk, input).core().run(),
ProverType::Network(network_prover) => network_prover.prove(pk, input).core().run(),
}
.map_err(|e| SP1Error::Prove(ProveError::Client(e.into())))
}
@@ -68,6 +72,7 @@ impl ProverType {
match self {
ProverType::Cpu(cpu_prover) => cpu_prover.verify(proof, vk),
ProverType::Gpu(cuda_prover) => cuda_prover.verify(proof, vk),
ProverType::Network(network_prover) => network_prover.verify(proof, vk),
}
.map_err(|e| SP1Error::Verify(VerifyError::Client(e.into())))
}
@@ -96,6 +101,28 @@ impl Compiler for RV32_IM_SUCCINCT_ZKVM_ELF {
}
impl EreSP1 {
fn create_network_prover(config: &NetworkProverConfig) -> NetworkProver {
let mut builder = ProverClient::builder().network();
// Check if we have a private key in the config or environment
if let Some(api_key) = &config.api_key {
builder = builder.private_key(api_key);
} else if let Ok(private_key) = std::env::var("NETWORK_PRIVATE_KEY") {
builder = builder.private_key(&private_key);
} else {
panic!(
"Network proving requires a private key. Set NETWORK_PRIVATE_KEY environment variable or provide api_key in NetworkProverConfig"
);
}
// Set the RPC URL if provided
if !config.endpoint.is_empty() {
builder = builder.rpc_url(&config.endpoint);
} else if let Ok(rpc_url) = std::env::var("NETWORK_RPC_URL") {
builder = builder.rpc_url(&rpc_url);
}
// Otherwise SP1 SDK will use its default RPC URL
builder.build()
}
pub fn new(
program: <RV32_IM_SUCCINCT_ZKVM_ELF as Compiler>::Program,
resource: ProverResourceType,
@@ -103,6 +130,9 @@ impl EreSP1 {
let client = match resource {
ProverResourceType::Cpu => ProverType::Cpu(ProverClient::builder().cpu().build()),
ProverResourceType::Gpu => ProverType::Gpu(ProverClient::builder().cuda().build()),
ProverResourceType::Network(config) => {
ProverType::Network(Self::create_network_prover(&config))
}
};
let (pk, vk) = client.setup(&program);
@@ -293,4 +323,52 @@ mod prove_tests {
let prove_result = zkvm.prove(&empty_input);
assert!(prove_result.is_err())
}
#[test]
#[ignore = "Requires NETWORK_PRIVATE_KEY environment variable to be set"]
fn test_prove_sp1_network() {
// Check if we have the required environment variable
if std::env::var("NETWORK_PRIVATE_KEY").is_err() {
eprintln!("Skipping network test: NETWORK_PRIVATE_KEY not set");
return;
}
let elf_bytes = get_compiled_test_sp1_elf_for_prove()
.expect("Failed to compile test SP1 guest for proving test");
let mut input_builder = Input::new();
let n: u32 = 42;
let a: u16 = 42;
input_builder.write(n);
input_builder.write(a);
// Create a network prover configuration
let network_config = NetworkProverConfig {
endpoint: std::env::var("NETWORK_RPC_URL").unwrap_or_default(),
api_key: std::env::var("NETWORK_PRIVATE_KEY").ok(),
};
let zkvm = EreSP1::new(elf_bytes, ProverResourceType::Network(network_config));
// Execute first to ensure the program works
let exec_result = zkvm.execute(&input_builder);
assert!(exec_result.is_ok(), "Execution should succeed");
// Now prove using the network
let proof_bytes = match zkvm.prove(&input_builder) {
Ok((prove_result, report)) => {
println!("Network proving completed in {:?}", report.proving_time);
prove_result
}
Err(err) => {
panic!("Network proving error: {:?}", err);
}
};
assert!(!proof_bytes.is_empty(), "Proof bytes should not be empty.");
// Verify the proof
let verify_result = zkvm.verify(&proof_bytes);
assert!(verify_result.is_ok(), "Verification should succeed");
}
}

View File

@@ -186,6 +186,9 @@ impl zkVM for EreZisk {
// `features = gpu` and call it here.
unimplemented!()
}
ProverResourceType::Network(_) => {
panic!("Network proving not yet implemented for ZisK. Use CPU or GPU resource type.");
}
}
let proving_time = start.elapsed();

View File

@@ -13,6 +13,7 @@ indexmap = { version = "2.9.0", features = ["serde"] }
thiserror = "2"
auto_impl = "1.0"
erased-serde = "0.4.6"
humantime-serde = "1.1"
[dev-dependencies]
serde_json = "1"

View File

@@ -7,6 +7,9 @@ pub use input::{Input, InputItem};
mod reports;
pub use reports::{ProgramExecutionReport, ProgramProvingReport};
mod network;
pub use network::NetworkProverConfig;
#[allow(non_camel_case_types)]
/// Compiler trait for compiling programs into an opaque sequence of bytes.
pub trait Compiler {
@@ -18,11 +21,13 @@ pub trait Compiler {
}
/// ResourceType specifies what resource will be used to create the proofs.
#[derive(Debug, Copy, Clone, Default)]
#[derive(Debug, Clone, Default)]
pub enum ProverResourceType {
#[default]
Cpu,
Gpu,
/// Use a remote prover network
Network(NetworkProverConfig),
}
/// An error that can occur during prove, execute or verification
@@ -33,6 +38,26 @@ pub enum ProverResourceType {
#[allow(non_camel_case_types)]
#[derive(Debug, Error)]
pub enum zkVMError {
/// Network-related errors
#[error("Network error: {0}")]
Network(String),
/// Authentication error
#[error("Authentication failed: {0}")]
Authentication(String),
/// Timeout error
#[error("Operation timed out after {0:?}")]
Timeout(std::time::Duration),
/// Service unavailable
#[error("Prover service unavailable: {0}")]
ServiceUnavailable(String),
/// Invalid response from network
#[error("Invalid response from prover network: {0}")]
InvalidResponse(String),
// TODO: We can add more variants as time goes by.
// TODO: for now, we use this catch-all as a way to prototype faster
#[error(transparent)]

View File

@@ -0,0 +1,11 @@
use serde::{Deserialize, Serialize};
/// Configuration for network-based proving
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct NetworkProverConfig {
/// The endpoint URL of the prover network service
pub endpoint: String,
/// Optional API key for authentication
pub api_key: Option<String>,
}