diff --git a/.gitignore b/.gitignore index bc46f232f..cb362ccbe 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ report.txt report.json table_cache_dev_* .DS_Store -.env +tracing.folded +.env \ No newline at end of file diff --git a/ceno_zkvm/src/scheme/prover.rs b/ceno_zkvm/src/scheme/prover.rs index 2d31e656f..66bacb17f 100644 --- a/ceno_zkvm/src/scheme/prover.rs +++ b/ceno_zkvm/src/scheme/prover.rs @@ -138,15 +138,20 @@ impl> ZKVMProver { let (witness, num_instances) = wits .remove(circuit_name) .ok_or(ZKVMError::WitnessNotFound(circuit_name.clone()))?; - if witness.is_empty() { - continue; - } - let wits_commit = commitments.remove(circuit_name).unwrap(); // TODO: add an enum for circuit type either in constraint_system or vk let cs = pk.get_cs(); let is_opcode_circuit = cs.lk_table_expressions.is_empty() && cs.r_table_expressions.is_empty() && cs.w_table_expressions.is_empty(); + if is_opcode_circuit { + transcript.append_field_element(&E::BaseField::from(num_instances as u64)); + } + + if witness.is_empty() { + assert!(num_instances == 0); + continue; + } + let wits_commit = commitments.remove(circuit_name).unwrap(); if is_opcode_circuit { tracing::debug!( diff --git a/ceno_zkvm/src/scheme/verifier.rs b/ceno_zkvm/src/scheme/verifier.rs index c9593f24f..29cdf6f96 100644 --- a/ceno_zkvm/src/scheme/verifier.rs +++ b/ceno_zkvm/src/scheme/verifier.rs @@ -140,43 +140,63 @@ impl> ZKVMVerifier let point_eval = PointAndEval::default(); let mut transcripts = transcript.fork(self.vk.circuit_vks.len()); - for (name, (i, opcode_proof)) in vm_proof.opcode_proofs { - let transcript = &mut transcripts[i]; + // For each opcode, include the num_instances + // into its corresponding fork of the transcript. + for ((name, _), transcript) in self + .vk + .circuit_vks + .iter() // Sorted by key. + .zip_eq(transcripts.iter_mut()) + { + // get num_instances from opcode proof + let opcode_result = vm_proof.opcode_proofs.get(name); + let num_instances = opcode_result.map(|(_, p)| p.num_instances).unwrap_or(0); + if opcode_result.is_some() { + transcript.append_field_element(&E::BaseField::from(num_instances as u64)); + } + } - let circuit_vk = self - .vk - .circuit_vks - .get(&name) - .ok_or(ZKVMError::VKNotFound(name.clone()))?; - let _rand_point = self.verify_opcode_proof( - &name, - &self.vk.vp, - circuit_vk, - &opcode_proof, - pi_evals, - transcript, - NUM_FANIN, - &point_eval, - &challenges, - )?; - tracing::info!("verified proof for opcode {}", name); - - // getting the number of dummy padding item that we used in this opcode circuit - let num_lks = circuit_vk.get_cs().lk_expressions.len(); - let num_padded_lks_per_instance = next_pow2_instance_padding(num_lks) - num_lks; - let num_padded_instance = - next_pow2_instance_padding(opcode_proof.num_instances) - opcode_proof.num_instances; - dummy_table_item_multiplicity += num_padded_lks_per_instance - * opcode_proof.num_instances - + num_lks.next_power_of_two() * num_padded_instance; - - prod_r *= opcode_proof.record_r_out_evals.iter().product::(); - prod_w *= opcode_proof.record_w_out_evals.iter().product::(); - - logup_sum += - opcode_proof.lk_p1_out_eval * opcode_proof.lk_q1_out_eval.invert().unwrap(); - logup_sum += - opcode_proof.lk_p2_out_eval * opcode_proof.lk_q2_out_eval.invert().unwrap(); + for (name, (i, opcode_proof)) in &vm_proof.opcode_proofs { + let transcript = &mut transcripts[*i]; + let num_instances = opcode_proof.num_instances; + + if num_instances != 0 { + let opcode_proof = &vm_proof.opcode_proofs.get(name).unwrap().1; + let circuit_vk = self + .vk + .circuit_vks + .get(name) + .ok_or(ZKVMError::VKNotFound(name.clone()))?; + let _rand_point = self.verify_opcode_proof( + name, + &self.vk.vp, + circuit_vk, + opcode_proof, + pi_evals, + transcript, + NUM_FANIN, + &point_eval, + &challenges, + )?; + tracing::info!("verified proof for opcode {}", name); + + // getting the number of dummy padding item that we used in this opcode circuit + let num_lks = circuit_vk.get_cs().lk_expressions.len(); + let num_padded_lks_per_instance = next_pow2_instance_padding(num_lks) - num_lks; + let num_padded_instance = next_pow2_instance_padding(opcode_proof.num_instances) + - opcode_proof.num_instances; + dummy_table_item_multiplicity += num_padded_lks_per_instance + * opcode_proof.num_instances + + num_lks.next_power_of_two() * num_padded_instance; + + prod_r *= opcode_proof.record_r_out_evals.iter().product::(); + prod_w *= opcode_proof.record_w_out_evals.iter().product::(); + + logup_sum += + opcode_proof.lk_p1_out_eval * opcode_proof.lk_q1_out_eval.invert().unwrap(); + logup_sum += + opcode_proof.lk_p2_out_eval * opcode_proof.lk_q2_out_eval.invert().unwrap(); + } } for (name, (i, table_proof)) in vm_proof.table_proofs {