Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: run tests across zkVM using mocked guest programs #438

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,9 @@ pathdiff = "0.2.1"
dotenv = "0.15.0"
backoff = "0.4.0"

# test
test-log = "0.2.16"

[patch.crates-io]
revm = { git = "https://github.com/taikoxyz/revm.git", branch = "v36-taiko" }
revm-primitives = { git = "https://github.com/taikoxyz/revm.git", branch = "v36-taiko" }
Expand Down
2 changes: 2 additions & 0 deletions host/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,15 @@ assert_cmd = { workspace = true }
rstest = { workspace = true }
ethers-core = { workspace = true }
rand = { workspace = true }
test-log = { workspace = true }

[features]
default = []
sp1 = ["raiko-core/sp1"]
risc0 = ["raiko-core/risc0"]
sgx = ["raiko-core/sgx"]
integration = []
test-mock-guest = ["risc0-driver/test-mock-guest"]

[[bin]]
name = "raiko-host"
Expand Down
16 changes: 10 additions & 6 deletions host/tests/common/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,23 @@ impl Client {
.send()
.await?;

if !response.status().is_success() {
return Err(response.error_for_status().unwrap_err());
}
assert!(
response.status().is_success(),
"reqwest post error: {}",
response.text().await?
);

response.json().await
}

pub async fn get(&self, path: &str) -> Result<reqwest::Response, reqwest::Error> {
let response = self.reqwest_client.get(self.build_url(path)).send().await?;

if !response.status().is_success() {
return Err(response.error_for_status().unwrap_err());
}
assert!(
response.status().is_success(),
"reqwest get error: {}",
response.text().await?
);

Ok(response)
}
Expand Down
7 changes: 2 additions & 5 deletions host/tests/common/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ pub async fn v2_complete_proof_request(client: &Client, request: &ProofRequestOp
api::v2::Status::Ok {
data: api::v2::ProofResponse::Proof { proof },
} => {
println!("proof generation completed, proof: {}", json!(proof));
println!("proof generation completed, request: {request:?}");
return proof;
}

Expand Down Expand Up @@ -200,10 +200,7 @@ pub async fn v3_complete_aggregate_proof_request(
api::v2::Status::Ok {
data: api::v2::ProofResponse::Proof { proof },
} => {
println!(
"aggregation proof generation completed, proof: {}",
json!(proof)
);
println!("aggregation proof generation completed, request: {request:?}");
return proof;
}

Expand Down
15 changes: 5 additions & 10 deletions host/tests/test/aggregate_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,22 @@ use raiko_host::server::api;
use raiko_lib::consts::Network;
use raiko_lib::proof_type::ProofType;
use raiko_tasks::TaskStatus;
use test_log::test;

#[tokio::test]
#[test(tokio::test)]
async fn test_v2_mainnet_aggregate_native() {
test_v2_mainnet_aggregate(Network::TaikoMainnet, ProofType::Native).await;
}

// NOTE: Locally zkVM proof aggregation is not supported yet, we are not able to test it locally.
#[ignore]
#[cfg(feature = "risc0")]
#[tokio::test]
#[cfg(all(feature = "risc0", feature = "test-mock-guest"))]
#[test(tokio::test)]
async fn test_v2_mainnet_aggregate_risc0() {
test_v2_mainnet_aggregate(Network::TaikoMainnet, ProofType::Risc0).await;
}

async fn test_v2_mainnet_aggregate(network: Network, proof_type: ProofType) {
setup_mock_zkvm_elf();

let api_version = "v2";
let aggregate_block_count = 2;

Expand Down Expand Up @@ -92,8 +92,3 @@ async fn test_v2_mainnet_aggregate(network: Network, proof_type: ProofType) {
// santy check for report format
v2_assert_report(&client).await;
}

// Use mock zkvm elf for testing
fn setup_mock_zkvm_elf() {
std::env::set_var("RAIKO_MOCK_ZKVM_ELF", "true");
}
17 changes: 13 additions & 4 deletions host/tests/test/cancel_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,21 @@ use raiko_host::server::api;
use raiko_lib::consts::Network;
use raiko_lib::proof_type::ProofType;
use raiko_tasks::TaskStatus;
use test_log::test;

#[tokio::test]
pub async fn test_v2_mainnet_native_cancel() {
#[cfg(all(feature = "risc0", feature = "test-mock-guest"))]
#[test(tokio::test)]
async fn test_v2_mainnet_risc0_cancel() {
test_v2_cancel(Network::TaikoMainnet, ProofType::Risc0).await;
}

#[test(tokio::test)]
async fn test_v2_mainnet_native_cancel() {
test_v2_cancel(Network::TaikoMainnet, ProofType::Native).await;
}

async fn test_v2_cancel(network: Network, proof_type: ProofType) {
let api_version = "v2";
let network = Network::TaikoMainnet;
let proof_type = ProofType::Native;
let block_number = randomly_select_block(network)
.await
.expect("randomly select block failed");
Expand Down
22 changes: 19 additions & 3 deletions host/tests/test/manual_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use raiko_core::interfaces::{ProofRequestOpt, ProverSpecificOpts};
use raiko_host::server::api;
use raiko_tasks::TaskStatus;
use serde_json::json;
use test_log::test;

/// This test is used to manually test the proof process. Operator can use this to test case to
/// simplly test online service.
Expand All @@ -19,7 +20,7 @@ use serde_json::json;
/// RAIKO_TEST_MANUAL_PROVE_RAIKO_RPC_URL=https://rpc.raiko.xyz \
/// cargo test --test test_manual_prove -- --ignored
/// ```
#[tokio::test]
#[test(tokio::test)]
#[ignore]
pub async fn test_manual_prove() {
let enabled = std::env::var("RAIKO_TEST_MANUAL_PROVE_ENABLED").unwrap_or_default() == "false";
Expand All @@ -38,6 +39,14 @@ pub async fn test_manual_prove() {
let raiko_rpc_url = std::env::var("RAIKO_TEST_MANUAL_PROVE_RAIKO_RPC_URL").unwrap_or_default();

let client = Client::new(raiko_rpc_url.clone());

let json_guest_input = format!(
"make_prove_request_{}_{}_{}_{}.json",
network,
proof_type,
block_number,
std::time::Instant::now().elapsed().as_secs()
);
let request = ProofRequestOpt {
block_number: Some(block_number),
network: Some(network.clone()),
Expand All @@ -52,10 +61,17 @@ pub async fn test_manual_prove() {
prover: Some("0x70997970C51812dc3A010C7d01b50e0d17dc79C8".to_owned()),
blob_proof_type: Some("proof_of_equivalence".to_string()),
prover_args: ProverSpecificOpts {
native: None,
native: Some(json!({
"json_guest_input": json_guest_input,
})),
risc0: Some(json!({
"bonsai": false, // run locally
"snark": false,
"profile": false,
"execution_po2" : 20, // DEFAULT_SEGMENT_LIMIT_PO2 = 20
})),
sgx: None,
sp1: None,
risc0: None,
},
};

Expand Down
17 changes: 13 additions & 4 deletions host/tests/test/prove_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,21 @@ use raiko_host::server::api;
use raiko_lib::consts::Network;
use raiko_lib::proof_type::ProofType;
use raiko_tasks::TaskStatus;
use test_log::test;

#[tokio::test]
pub async fn test_v2_mainnet_native_prove() {
#[cfg(all(feature = "risc0", feature = "test-mock-guest"))]
#[test(tokio::test)]
async fn test_v2_mainnet_prove_risc0() {
test_v2_prove(Network::TaikoMainnet, ProofType::Risc0).await;
}

#[test(tokio::test)]
async fn test_v2_mainnet_native_prove() {
test_v2_prove(Network::TaikoMainnet, ProofType::Native).await;
}

async fn test_v2_prove(network: Network, proof_type: ProofType) {
let api_version = "v2";
let network = Network::TaikoMainnet;
let proof_type = ProofType::Native;
let block_number = randomly_select_block(network)
.await
.expect("randomly select block failed");
Expand Down
7 changes: 6 additions & 1 deletion provers/risc0/builder/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ use std::path::PathBuf;
fn main() {
let pipeline = Risc0Pipeline::new("provers/risc0/guest", "release");
pipeline.bins(
&["risc0-guest", "risc0-aggregation"],
&[
"risc0-guest",
"risc0-aggregation",
"risc0-guest-mock",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe better to use feature to separate build.
please also check if the image id output in compile log is clear or not as we need give that id to client to config the contract.

"risc0-aggregation-mock",
],
"provers/risc0/driver/src/methods",
);
#[cfg(feature = "test")]
Expand Down
1 change: 1 addition & 0 deletions provers/risc0/driver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,4 @@ cuda = ["risc0-zkvm?/cuda"]
metal = ["risc0-zkvm?/metal"]
bench = []
bonsai-auto-scaling = []
test-mock-guest = []
19 changes: 13 additions & 6 deletions provers/risc0/driver/src/bonsai.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
methods::risc0_guest::RISC0_GUEST_ID,
methods::RISC0_GUEST_ID,
snarks::{stark2snark, verify_groth16_from_snark_receipt},
Risc0Response,
};
Expand Down Expand Up @@ -208,12 +208,15 @@ pub async fn maybe_prove<I: Serialize, O: Eq + Debug + Serialize + DeserializeOw
assumption_instances,
param.profile,
) {
Ok(receipt) => (Default::default(), receipt, false),
Ok(receipt) => {
info!("end running local prover");
(Default::default(), receipt, false)
}
Err(e) => {
warn!("Failed to prove locally: {e:?}");
return Err(ProverError::GuestError(
"Failed to prove locally".to_string(),
));
return Err(ProverError::GuestError(format!(
"Failed to prove locally: {e:?}"
)));
}
}
};
Expand All @@ -223,7 +226,11 @@ pub async fn maybe_prove<I: Serialize, O: Eq + Debug + Serialize + DeserializeOw

// verify output
let output_guest: O = receipt.journal.decode().unwrap();
if expected_output == &output_guest {
#[cfg(feature = "test-mock-guest")]
let success = true;
#[cfg(not(feature = "test-mock-guest"))]
let success = expected_output == &output_guest;
if success {
info!("Prover succeeded");
} else {
error!("Output mismatch! Prover: {output_guest:?}, expected: {expected_output:?}");
Expand Down
7 changes: 2 additions & 5 deletions provers/risc0/driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@

#[cfg(feature = "bonsai-auto-scaling")]
use crate::bonsai::auto_scaling::shutdown_bonsai;
use crate::{
methods::risc0_aggregation::RISC0_AGGREGATION_ELF,
methods::risc0_guest::{RISC0_GUEST_ELF, RISC0_GUEST_ID},
};
use crate::methods::{RISC0_AGGREGATION_ELF, RISC0_GUEST_ELF, RISC0_GUEST_ID};
use alloy_primitives::{hex::ToHexExt, B256};
use bonsai::{cancel_proof, maybe_prove};
use log::{info, warn};
Expand Down Expand Up @@ -223,8 +220,8 @@ impl Prover for Risc0Prover {
#[cfg(test)]
mod test {
use super::*;
use methods::risc0_guest::RISC0_GUEST_ID;
use methods::test_risc0_guest::{TEST_RISC0_GUEST_ELF, TEST_RISC0_GUEST_ID};
use methods::RISC0_GUEST_ID;
use risc0_zkvm::{default_prover, ExecutorEnv};

#[test]
Expand Down
36 changes: 34 additions & 2 deletions provers/risc0/driver/src/methods/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,44 @@
pub mod risc0_aggregation;
pub mod risc0_guest;
//! RISC0 prover method definitions and configurations
//! This module handles both production and test mock implementations.

// Production implementations
#[cfg(not(feature = "test-mock-guest"))]
mod risc0_aggregation;
#[cfg(not(feature = "test-mock-guest"))]
mod risc0_guest;

// Test mock implementations
#[cfg(feature = "test-mock-guest")]
mod risc0_aggregation_mock;
#[cfg(feature = "test-mock-guest")]
mod risc0_guest_mock;

// Re-exports for production environment
#[cfg(not(feature = "test-mock-guest"))]
pub use risc0_aggregation::{RISC0_AGGREGATION_ELF, RISC0_AGGREGATION_ID};
#[cfg(not(feature = "test-mock-guest"))]
pub use risc0_guest::{RISC0_GUEST_ELF, RISC0_GUEST_ID};

// Re-exports for test environment with mock implementations
#[cfg(feature = "test-mock-guest")]
pub use risc0_aggregation_mock::{
RISC0_AGGREGATION_MOCK_ELF as RISC0_AGGREGATION_ELF,
RISC0_AGGREGATION_MOCK_ID as RISC0_AGGREGATION_ID,
};
#[cfg(feature = "test-mock-guest")]
pub use risc0_guest_mock::{
RISC0_GUEST_MOCK_ELF as RISC0_GUEST_ELF, RISC0_GUEST_MOCK_ID as RISC0_GUEST_ID,
};

// To build the following `$ cargo run --features test,bench --bin risc0-builder`
// or `$ $TARGET=risc0 make test`

// Benchmark-specific modules
#[cfg(feature = "bench")]
pub mod ecdsa;
#[cfg(feature = "bench")]
pub mod sha256;

// Test-specific modules
#[cfg(test)]
pub mod test_risc0_guest;
3 changes: 3 additions & 0 deletions provers/risc0/driver/src/methods/risc0_aggregation_mock.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

pub const RISC0_AGGREGATION_MOCK_ELF: &[u8] = include_bytes!("../../../guest/target/riscv32im-risc0-zkvm-elf/release/risc0-aggregation-mock");
pub const RISC0_AGGREGATION_MOCK_ID: [u32; 8] = [2792947449, 3119244021, 3706268267, 3522578639, 2979241120, 39440854, 3999921328, 3748768206];
3 changes: 3 additions & 0 deletions provers/risc0/driver/src/methods/risc0_guest_mock.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

pub const RISC0_GUEST_MOCK_ELF: &[u8] = include_bytes!("../../../guest/target/riscv32im-risc0-zkvm-elf/release/risc0-guest-mock");
pub const RISC0_GUEST_MOCK_ID: [u32; 8] = [3661074503, 456244050, 2356448233, 3555754962, 3799155047, 1867550507, 1560708289, 2016241489];
Loading