Skip to content

Commit 032e315

Browse files
committed
feat(provers): add zkvm support for batch requests
1 parent bf274d2 commit 032e315

File tree

9 files changed

+328
-27
lines changed

9 files changed

+328
-27
lines changed

provers/risc0/builder/src/main.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::path::PathBuf;
66
fn main() {
77
let pipeline = Risc0Pipeline::new("provers/risc0/guest", "release");
88
pipeline.bins(
9-
&["risc0-guest", "risc0-aggregation"],
9+
&["risc0-guest", "risc0-aggregation", "risc0-batch"],
1010
"provers/risc0/driver/src/methods",
1111
);
1212
#[cfg(feature = "test")]

provers/risc0/driver/src/bonsai.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use crate::{
2-
methods::risc0_guest::RISC0_GUEST_ID,
32
snarks::{stark2snark, verify_groth16_from_snark_receipt},
43
Risc0Response,
54
};
@@ -313,8 +312,10 @@ pub async fn bonsai_stark_to_snark(
313312
stark_uuid: String,
314313
stark_receipt: Receipt,
315314
input: B256,
315+
elf: &[u8],
316316
) -> ProverResult<Risc0Response> {
317-
let image_id = Digest::from(RISC0_GUEST_ID);
317+
let image_id = risc0_zkvm::compute_image_id(elf)
318+
.map_err(|e| ProverError::GuestError(format!("Failed to compute image id: {e:?}")))?;
318319
let (snark_uuid, snark_receipt) = stark2snark(
319320
image_id,
320321
stark_uuid.clone(),

provers/risc0/driver/src/lib.rs

+68-14
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
#[cfg(feature = "bonsai-auto-scaling")]
44
use crate::bonsai::auto_scaling::shutdown_bonsai;
55
use crate::{
6-
methods::risc0_aggregation::RISC0_AGGREGATION_ELF,
7-
methods::risc0_guest::{RISC0_GUEST_ELF, RISC0_GUEST_ID},
6+
methods::risc0_aggregation::RISC0_AGGREGATION_ELF, methods::risc0_batch::RISC0_BATCH_ELF,
7+
methods::risc0_guest::RISC0_GUEST_ELF,
88
};
99
use alloy_primitives::{hex::ToHexExt, B256};
1010
use bonsai::{cancel_proof, maybe_prove};
@@ -18,8 +18,10 @@ use raiko_lib::{
1818
prover::{IdStore, IdWrite, Proof, ProofKey, Prover, ProverConfig, ProverError, ProverResult},
1919
};
2020
use risc0_zkvm::{
21-
compute_image_id, default_prover, serde::to_vec, sha::Digestible, ExecutorEnv, ProverOpts,
22-
Receipt,
21+
compute_image_id, default_prover,
22+
serde::to_vec,
23+
sha::{Digest, Digestible},
24+
ExecutorEnv, ProverOpts, Receipt,
2325
};
2426
use serde::{Deserialize, Serialize};
2527
use serde_with::serde_as;
@@ -92,7 +94,7 @@ impl Prover for Risc0Prover {
9294
.await?;
9395

9496
let proof_gen_result = if config.snark && config.bonsai {
95-
bonsai::bonsai_stark_to_snark(uuid, receipt, output.hash)
97+
bonsai::bonsai_stark_to_snark(uuid, receipt, output.hash, RISC0_GUEST_ELF)
9698
.await
9799
.map(|r0_response| r0_response.into())
98100
.map_err(|e| ProverError::GuestError(e.to_string()))
@@ -147,11 +149,16 @@ impl Prover for Risc0Prover {
147149
.iter()
148150
.map(|proof| proof.input.unwrap())
149151
.collect::<Vec<_>>();
152+
153+
let input_proof_hex_str = input.proofs[0].proof.as_ref().unwrap();
154+
let input_proof_bytes = hex::decode(&input_proof_hex_str[2..]).unwrap();
155+
let input_image_id_bytes: [u8; 32] = input_proof_bytes[32..64].try_into().unwrap();
156+
let input_proof_image_id = Digest::from(input_image_id_bytes);
150157
let input = ZkAggregationGuestInput {
151-
image_id: RISC0_GUEST_ID,
158+
image_id: input_proof_image_id.as_words().try_into().unwrap(),
152159
block_inputs,
153160
};
154-
info!("Start aggregate proofs");
161+
155162
// add_assumption makes the receipt to be verified available to the prover.
156163
let env = {
157164
let mut env = ExecutorEnv::builder();
@@ -171,10 +178,9 @@ impl Prover for Risc0Prover {
171178
"Generate aggregation receipt journal: {:?}",
172179
alloy_primitives::hex::encode_prefixed(receipt.journal.bytes.clone())
173180
);
174-
let block_proof_image_id = compute_image_id(RISC0_GUEST_ELF).unwrap();
175181
let aggregation_image_id = compute_image_id(RISC0_AGGREGATION_ELF).unwrap();
176182
let proof_data = snarks::verify_aggregation_groth16_proof(
177-
block_proof_image_id,
183+
input_proof_image_id,
178184
aggregation_image_id,
179185
receipt.clone(),
180186
)
@@ -220,12 +226,60 @@ impl Prover for Risc0Prover {
220226
}
221227

222228
async fn batch_run(
223-
_input: GuestBatchInput,
224-
_output: &GuestBatchOutput,
225-
_config: &ProverConfig,
226-
_store: Option<&mut dyn IdWrite>,
229+
input: GuestBatchInput,
230+
output: &GuestBatchOutput,
231+
config: &ProverConfig,
232+
id_store: Option<&mut dyn IdWrite>,
227233
) -> ProverResult<Proof> {
228-
unimplemented!();
234+
let mut id_store = id_store;
235+
let config = Risc0Param::deserialize(config.get("risc0").unwrap()).unwrap();
236+
let proof_key = (
237+
input.taiko.chain_spec.chain_id,
238+
input.taiko.batch_id,
239+
output.hash,
240+
ProofType::Risc0 as u8,
241+
);
242+
243+
let encoded_input = to_vec(&input).expect("Could not serialize proving input!");
244+
245+
let (uuid, receipt) = maybe_prove::<GuestBatchInput, B256>(
246+
&config,
247+
encoded_input,
248+
RISC0_BATCH_ELF,
249+
&output.hash,
250+
(Vec::<Receipt>::new(), Vec::new()),
251+
proof_key,
252+
&mut id_store,
253+
)
254+
.await?;
255+
256+
let proof_gen_result = if config.snark && config.bonsai {
257+
bonsai::bonsai_stark_to_snark(uuid, receipt, output.hash, RISC0_BATCH_ELF)
258+
.await
259+
.map(|r0_response| r0_response.into())
260+
.map_err(|e| ProverError::GuestError(e.to_string()))
261+
} else {
262+
if !config.snark {
263+
warn!("proof is not in snark mode, please check.");
264+
}
265+
Ok(Risc0Response {
266+
proof: receipt.journal.encode_hex_with_prefix(),
267+
receipt: serde_json::to_string(&receipt).unwrap(),
268+
uuid,
269+
input: output.hash,
270+
}
271+
.into())
272+
};
273+
274+
#[cfg(feature = "bonsai-auto-scaling")]
275+
if config.bonsai {
276+
// shutdown bonsai
277+
shutdown_bonsai()
278+
.await
279+
.map_err(|e| ProverError::GuestError(e.to_string()))?;
280+
}
281+
282+
proof_gen_result
229283
}
230284
}
231285

provers/risc0/guest/Cargo.toml

+4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ path = "src/zk_op.rs"
1313
name = "risc0-aggregation"
1414
path = "src/aggregation.rs"
1515

16+
[[bin]]
17+
name = "risc0-batch"
18+
path = "src/batch.rs"
19+
1620
[[bin]]
1721
name = "sha256"
1822
path = "src/benchmark/sha256.rs"

provers/risc0/guest/src/batch.rs

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#![no_main]
2+
harness::entrypoint!(main, tests, zk_op::tests);
3+
use raiko_lib::{
4+
builder::calculate_batch_blocks_final_header, input::GuestBatchInput, proof_type::ProofType,
5+
protocol_instance::ProtocolInstance,
6+
};
7+
use revm_precompile::zk_op::ZkOperation;
8+
use risc0_zkvm::guest::env;
9+
use zk_op::Risc0Operator;
10+
11+
pub mod mem;
12+
13+
pub use mem::*;
14+
15+
fn main() {
16+
let batch_input: GuestBatchInput = env::read();
17+
18+
revm_precompile::zk_op::ZKVM_OPERATOR.get_or_init(|| Box::new(Risc0Operator {}));
19+
revm_precompile::zk_op::ZKVM_OPERATIONS
20+
.set(Box::new(vec![ZkOperation::Sha256, ZkOperation::Secp256k1]))
21+
.expect("Failed to set ZkvmOperations");
22+
23+
let final_blocks = calculate_batch_blocks_final_header(&batch_input);
24+
let pi = ProtocolInstance::new_batch(&batch_input, final_blocks, ProofType::Risc0)
25+
.unwrap()
26+
.instance_hash();
27+
28+
env::commit(&pi);
29+
}
30+
31+
harness::zk_suits!(
32+
pub mod tests {
33+
#[test]
34+
pub fn test_build_from_mock_input() {
35+
// Todo: impl mock input for static unit test
36+
assert_eq!(1, 1);
37+
}
38+
}
39+
);

provers/sp1/builder/src/main.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ use std::path::PathBuf;
55

66
fn main() {
77
let pipeline = Sp1Pipeline::new("provers/sp1/guest", "release");
8-
pipeline.bins(&["sp1-guest", "sp1-aggregation"], "provers/sp1/guest/elf");
8+
pipeline.bins(
9+
&["sp1-guest", "sp1-aggregation", "sp1-batch"],
10+
"provers/sp1/guest/elf",
11+
);
912
#[cfg(feature = "test")]
1013
pipeline.tests(&["sp1-guest"], "provers/sp1/guest/elf");
1114
#[cfg(feature = "bench")]

0 commit comments

Comments
 (0)