Skip to content

Commit 6445f84

Browse files
committed
Restore bundle/batch deferral fix for v0.9.0
- prover.rs: load child circuit handler and call enable_deferral for Batch/Bundle tasks - UniversalHandler: expose enable_deferral wrapper around Prover::enable_deferral - CircuitConfig: add child_circuit_vks for chunk/batch child lookup - 04-prover-up.sh: populate child_circuit_vks from openVmVk.json
1 parent 37689ad commit 6445f84

3 files changed

Lines changed: 74 additions & 22 deletions

File tree

crates/prover-bin/src/prover.rs

Lines changed: 61 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -191,14 +191,18 @@ pub struct CircuitConfig {
191191
/// cached vk value to save some initial cost, for debugging only
192192
#[serde(default)]
193193
pub vks: HashMap<ProofType, String>,
194+
/// Child circuit VKs used to enable OpenVM deferral for aggregation tasks.
195+
/// Required for batch (child=chunk) and bundle (child=batch) proving in v0.9.0+.
196+
#[serde(default)]
197+
pub child_circuit_vks: HashMap<ProofType, String>,
194198
}
195199

196200
pub struct LocalProver {
197201
config: LocalProverConfig,
198202
next_task_id: u64,
199203
current_task: Option<JoinHandle<Result<String>>>,
200204

201-
handlers: HashMap<String, Arc<dyn CircuitsHandler>>,
205+
handlers: HashMap<String, Arc<Mutex<UniversalHandler>>>,
202206
}
203207

204208
#[async_trait]
@@ -325,39 +329,44 @@ impl LocalProver {
325329
}
326330
let prover_task: ProvingTask = prover_task.into();
327331
let vk = hex::encode(&prover_task.vk);
328-
let handler = if let Some(handler) = self.handlers.get(&vk) {
329-
handler.clone()
330-
} else {
331-
let base_config = self
332+
333+
let parent_handler = self
334+
.get_or_load_handler(&req.hard_fork_name, req.proof_type, &vk)
335+
.await?;
336+
337+
// OpenVM v2+ aggregation circuits (batch/bundle) need deferral enabled
338+
// using their immediate child circuit's prover.
339+
let child_proof_type = match req.proof_type {
340+
ProofType::Batch => Some(ProofType::Chunk),
341+
ProofType::Bundle => Some(ProofType::Batch),
342+
_ => None,
343+
};
344+
if let Some(child_type) = child_proof_type {
345+
let child_vk = self
332346
.config
333347
.circuits
334348
.get(&req.hard_fork_name)
349+
.and_then(|c| c.child_circuit_vks.get(&child_type))
335350
.ok_or_else(|| {
336351
eyre::eyre!(
337-
"coordinator sent unexpected forkname {}",
352+
"missing child circuit vk for {:?} in fork {}",
353+
child_type,
338354
req.hard_fork_name
339355
)
340-
})?;
341-
let url_base = if let Some(url) = base_config.location_data.asset_detours.get(&vk) {
342-
url.clone()
343-
} else {
344-
base_config
345-
.location_data
346-
.gen_asset_url(&vk, req.proof_type)?
347-
};
348-
let asset_path = base_config
349-
.location_data
350-
.get_asset(&vk, &url_base, &base_config.workspace_path)
356+
})?
357+
.clone();
358+
let child_handler = self
359+
.get_or_load_handler(&req.hard_fork_name, child_type, &child_vk)
351360
.await?;
352-
let circuits_handler = Arc::new(Mutex::new(UniversalHandler::new(&asset_path)?));
353-
self.handlers.insert(vk, circuits_handler.clone());
354-
circuits_handler
355-
};
361+
let mut parent_guard = parent_handler.lock().await;
362+
let child_guard = child_handler.lock().await;
363+
parent_guard.enable_deferral(&*child_guard)?;
364+
}
356365

357366
let handle = Handle::current();
358367
let is_evm = req.proof_type == ProofType::Bundle;
359368
let task_handle = tokio::task::spawn_blocking(move || {
360-
handle.block_on(handler.get_proof_data(&prover_task, is_evm))
369+
handle.block_on(parent_handler.get_proof_data(&prover_task, is_evm))
361370
});
362371
self.current_task = Some(task_handle);
363372

@@ -372,4 +381,34 @@ impl LocalProver {
372381
..Default::default()
373382
})
374383
}
384+
385+
/// Load a handler for the given fork/proof-type/vk, reusing a cached one if available.
386+
async fn get_or_load_handler(
387+
&mut self,
388+
fork_name: &str,
389+
proof_type: ProofType,
390+
vk: &str,
391+
) -> Result<Arc<Mutex<UniversalHandler>>> {
392+
if let Some(handler) = self.handlers.get(vk) {
393+
return Ok(handler.clone());
394+
}
395+
396+
let base_config = self
397+
.config
398+
.circuits
399+
.get(fork_name)
400+
.ok_or_else(|| eyre::eyre!("coordinator sent unexpected forkname {}", fork_name))?;
401+
let url_base = if let Some(url) = base_config.location_data.asset_detours.get(vk) {
402+
url.clone()
403+
} else {
404+
base_config.location_data.gen_asset_url(vk, proof_type)?
405+
};
406+
let asset_path = base_config
407+
.location_data
408+
.get_asset(vk, &url_base, &base_config.workspace_path)
409+
.await?;
410+
let handler = Arc::new(Mutex::new(UniversalHandler::new(&asset_path)?));
411+
self.handlers.insert(vk.to_string(), handler.clone());
412+
Ok(handler)
413+
}
375414
}

crates/prover-bin/src/zk_circuits_handler/universal.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,15 @@ impl UniversalHandler {
2828
Ok(Self { prover })
2929
}
3030

31+
/// Enable OpenVM deferral using `child_prover` as the child circuit prover.
32+
/// Required for batch (child=chunk) and bundle (child=batch) aggregation proofs.
33+
pub fn enable_deferral(&mut self, child: &UniversalHandler) -> Result<()> {
34+
self.prover
35+
.enable_deferral(&child.prover)
36+
.map_err(|e| eyre::eyre!("failed to enable deferral: {}", e))?;
37+
Ok(())
38+
}
39+
3140
/// get_prover get the inner prover, later we would replace chunk/batch/bundle_prover with
3241
/// universal prover, before that, use bundle_prover as the represent one
3342
pub fn get_prover(&mut self) -> &mut Prover {

tests/shadow-testing/scripts/04-prover-up.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ for i in "${!GPU_ARRAY[@]}"; do
9393
"${BATCH_VK}": "${S3_URL}batch/",
9494
"${BUNDLE_VK}": "${S3_URL}bundle/"
9595
},
96+
"child_circuit_vks": {
97+
"Chunk": "${CHUNK_VK}",
98+
"Batch": "${BATCH_VK}"
99+
},
96100
"debug_mode": false
97101
}
98102
}

0 commit comments

Comments
 (0)