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

feat: impl zkvm support for pacaya #526

Merged
merged 12 commits into from
Apr 7, 2025
3 changes: 1 addition & 2 deletions host/config/config.devnet.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,10 @@
"execution_po2": 20
},
"sp1": {
"recursion": "core",
"prover": "network",
"verify": false
},
"native": {
"json_guest_input": null
}
}
}
1 change: 0 additions & 1 deletion host/config/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
"execution_po2": 20
},
"sp1": {
"recursion": "core",
"prover": "network",
"verify": false
},
Expand Down
3 changes: 1 addition & 2 deletions host/config/config.sgx.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,10 @@
"verify": true
},
"sp1": {
"recursion": "core",
"prover": "network",
"verify": true
},
"native": {
"json_guest_input": null
}
}
}
3 changes: 1 addition & 2 deletions host/config/config.taiko_hekla.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
"execution_po2": 20
},
"sp1": {
"recursion": "core",
"prover": "network",
"verify": true
},
Expand All @@ -33,4 +32,4 @@
"native": {
"json_guest_input": null
}
}
}
3 changes: 1 addition & 2 deletions host/config/config.taiko_mainnet.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
"execution_po2": 20
},
"sp1": {
"recursion": "core",
"prover": "network",
"verify": true
},
Expand All @@ -33,4 +32,4 @@
"native": {
"json_guest_input": null
}
}
}
2 changes: 2 additions & 0 deletions host/src/server/api/v2/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ pub enum Status {
Ok {
#[serde(with = "raiko_lib::proof_type::lowercase")]
proof_type: ProofType,
#[serde(skip_serializing_if = "Option::is_none")]
batch_id: Option<u64>,
data: ProofResponse,
},
Error {
Expand Down
18 changes: 6 additions & 12 deletions host/src/server/api/v2/proof/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use raiko_tasks::TaskStatus;
use serde_json::Value;
use utoipa::OpenApi;

use crate::server::utils::{draw_for_zk_any_request, fulfill_sp1_params, is_zk_any_request};
use crate::server::utils::{draw_for_zk_any_request, is_zk_any_request};
use crate::{
interfaces::HostResult,
metrics::{inc_current_req, inc_guest_req_count, inc_host_req_count},
Expand Down Expand Up @@ -39,16 +39,9 @@ pub mod report;
/// - sgx - uses the sgx environment to construct a block and produce proof of execution
/// - sp1 - uses the sp1 prover
/// - risc0 - uses the risc0 prover
async fn proof_handler(
State(actor): State<Actor>,
Json(mut req): Json<Value>,
) -> HostResult<Status> {
async fn proof_handler(State(actor): State<Actor>, Json(req): Json<Value>) -> HostResult<Status> {
inc_current_req();

if is_zk_any_request(&req) {
fulfill_sp1_params(&mut req);
}

// Override the existing proof request config from the config file and command line
// options with the request from the client.
let mut config = actor.default_request_config().clone();
Expand All @@ -61,6 +54,7 @@ async fn proof_handler(
None => {
return Ok(Status::Ok {
proof_type: ProofType::Native,
batch_id: None,
data: ProofResponse::Status {
status: TaskStatus::ZKAnyNotDrawn,
},
Expand Down Expand Up @@ -126,10 +120,10 @@ async fn proof_handler(
.into();

let result = crate::server::prove(&actor, request_key, request_entity).await;
Ok(to_v2_status(proof_type, result))
Ok(to_v2_status(proof_type, None, result))
}
Ok(_) => Ok(to_v2_status(proof_type, result)),
Err(_) => Ok(to_v2_status(proof_type, result)),
Ok(_) => Ok(to_v2_status(proof_type, None, result)),
Err(_) => Ok(to_v2_status(proof_type, None, result)),
}
}

Expand Down
2 changes: 1 addition & 1 deletion host/src/server/api/v3/proof/aggregate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ async fn aggregation_handler(
.into();

let result = crate::server::prove(&actor, agg_request_key, agg_request_entity).await;
Ok(to_v3_status(proof_type, result))
Ok(to_v3_status(proof_type, None, result))
}

#[derive(OpenApi)]
Expand Down
53 changes: 42 additions & 11 deletions host/src/server/api/v3/proof/batch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ use crate::{
api::v3::{ProofResponse, Status},
handler::prove_many,
prove_aggregation,
utils::{is_zk_any_request, to_v3_status},
utils::{draw_for_zk_any_batch_request, is_zk_any_request, to_v3_status},
},
};
use axum::{extract::State, routing::post, Json, Router};
use raiko_core::{
interfaces::{BatchMetadata, BatchProofRequest, BatchProofRequestOpt},
interfaces::{BatchMetadata, BatchProofRequest, BatchProofRequestOpt, RaikoError},
merge,
};
use raiko_lib::{proof_type::ProofType, prover::Proof};
Expand Down Expand Up @@ -41,20 +41,46 @@ async fn batch_handler(
State(actor): State<Actor>,
Json(batch_request_opt): Json<Value>,
) -> HostResult<Status> {
if is_zk_any_request(&batch_request_opt) {
return Ok(Status::Ok {
proof_type: ProofType::Native,
data: ProofResponse::Status {
status: TaskStatus::ZKAnyNotDrawn,
},
});
}
tracing::debug!(
"Received batch request: {}",
serde_json::to_string(&batch_request_opt)?
);

let batch_request = {
// Override the existing proof request config from the config file and command line
// options with the request from the client, and convert to a BatchProofRequest.
let mut opts = serde_json::to_value(actor.default_request_config())?;
merge(&mut opts, &batch_request_opt);

let first_batch_id = {
let batches = opts["batches"]
.as_array()
.ok_or(RaikoError::InvalidRequestConfig(
"Missing batches".to_string(),
))?;
let first_batch = batches.first().ok_or(RaikoError::InvalidRequestConfig(
"batches is empty".to_string(),
))?;
let first_batch_id = first_batch["batch_id"].as_u64().expect("checked above");
first_batch_id
};

// For zk_any request, draw zk proof type based on the block hash.
if is_zk_any_request(&opts) {
match draw_for_zk_any_batch_request(&actor, &opts).await? {
Some(proof_type) => opts["proof_type"] = serde_json::to_value(proof_type).unwrap(),
None => {
return Ok(Status::Ok {
proof_type: ProofType::Native,
batch_id: Some(first_batch_id),
data: ProofResponse::Status {
status: TaskStatus::ZKAnyNotDrawn,
},
});
}
}
}

let batch_request_opt: BatchProofRequestOpt = serde_json::from_value(opts)?;
let batch_request: BatchProofRequest = batch_request_opt.try_into()?;

Expand Down Expand Up @@ -188,7 +214,12 @@ async fn batch_handler(
})
}
};
Ok(to_v3_status(batch_request.proof_type, result))
tracing::debug!("Batch proof result: {}", serde_json::to_string(&result)?);
Ok(to_v3_status(
batch_request.proof_type,
Some(batch_request.batches.first().unwrap().batch_id),
result,
))
}

#[derive(OpenApi)]
Expand Down
2 changes: 1 addition & 1 deletion host/src/server/api/v3/proof/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ async fn proof_handler(
sub_request_entities,
)
.await;
Ok(to_v3_status(proof_type, result))
Ok(to_v3_status(proof_type, None, result))
}

#[derive(OpenApi)]
Expand Down
65 changes: 37 additions & 28 deletions host/src/server/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,15 @@ use raiko_reqpool::Status;
use raiko_tasks::TaskStatus;
use serde_json::Value;

pub fn to_v2_status(proof_type: ProofType, result: Result<Status, String>) -> v2::Status {
pub fn to_v2_status(
proof_type: ProofType,
batch_id: Option<u64>,
result: Result<Status, String>,
) -> v2::Status {
match result {
Ok(status) => v2::Status::Ok {
proof_type,
batch_id,
data: {
match status {
Status::Registered => v2::ProofResponse::Status {
Expand Down Expand Up @@ -57,8 +62,12 @@ pub fn to_v2_cancel_status(result: Result<Status, String>) -> v2::CancelStatus {
}

// TODO: remove the staled interface
pub fn to_v3_status(proof_type: ProofType, result: Result<Status, String>) -> v3::Status {
to_v2_status(proof_type, result)
pub fn to_v3_status(
proof_type: ProofType,
batch_id: Option<u64>,
result: Result<Status, String>,
) -> v3::Status {
to_v2_status(proof_type, batch_id, result)
}

pub fn to_v3_cancel_status(result: Result<Status, String>) -> v3::CancelStatus {
Expand Down Expand Up @@ -90,29 +99,29 @@ pub async fn draw_for_zk_any_request(
Ok(actor.draw(&blockhash))
}

pub fn fulfill_sp1_params(req: &mut Value) {
let zk_any_opts = req["zk_any"].as_object().clone();
let sp1_recursion = match zk_any_opts {
None => serde_json::Value::String("plonk".to_string()),
Some(zk_any) => {
let aggregation = zk_any["aggregation"].as_bool().unwrap_or(false);
if aggregation {
serde_json::Value::String("compressed".to_string())
} else {
serde_json::Value::String("plonk".to_string())
}
}
};

let sp1_opts = req["sp1"].as_object_mut();
match sp1_opts {
None => {
let mut sp1_opts = serde_json::Map::new();
sp1_opts.insert("recursion".to_string(), sp1_recursion);
req["sp1"] = serde_json::Value::Object(sp1_opts);
}
Some(sp1_opts) => {
sp1_opts.insert("recursion".to_string(), sp1_recursion);
}
}
pub async fn draw_for_zk_any_batch_request(
actor: &Actor,
batch_proof_request_opt: &Value,
) -> HostResult<Option<ProofType>> {
let l1_network =
batch_proof_request_opt["l1_network"]
.as_str()
.ok_or(RaikoError::InvalidRequestConfig(
"Missing network".to_string(),
))?;
let batches =
batch_proof_request_opt["batches"]
.as_array()
.ok_or(RaikoError::InvalidRequestConfig(
"Missing batches".to_string(),
))?;
let first_batch = batches.first().ok_or(RaikoError::InvalidRequestConfig(
"batches is empty".to_string(),
))?;
let l1_inclusion_block_number = first_batch["l1_inclusion_block_number"].as_u64().ok_or(
RaikoError::InvalidRequestConfig("Missing l1_inclusion_block_number".to_string()),
)?;
let (_, blockhash) =
get_task_data(&l1_network, l1_inclusion_block_number, actor.chain_specs()).await?;
Ok(actor.draw(&blockhash))
}
2 changes: 1 addition & 1 deletion provers/risc0/builder/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ 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-batch"],
"provers/risc0/driver/src/methods",
);
#[cfg(feature = "test")]
Expand Down
5 changes: 3 additions & 2 deletions provers/risc0/driver/src/bonsai.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::{
methods::risc0_guest::RISC0_GUEST_ID,
snarks::{stark2snark, verify_groth16_from_snark_receipt},
Risc0Response,
};
Expand Down Expand Up @@ -313,8 +312,10 @@ pub async fn bonsai_stark_to_snark(
stark_uuid: String,
stark_receipt: Receipt,
input: B256,
elf: &[u8],
) -> ProverResult<Risc0Response> {
let image_id = Digest::from(RISC0_GUEST_ID);
let image_id = risc0_zkvm::compute_image_id(elf)
.map_err(|e| ProverError::GuestError(format!("Failed to compute image id: {e:?}")))?;
let (snark_uuid, snark_receipt) = stark2snark(
image_id,
stark_uuid.clone(),
Expand Down
Loading
Loading