diff --git a/prover/src/common/prover/evm.rs b/prover/src/common/prover/evm.rs index 90f911fb7..e73432cb9 100644 --- a/prover/src/common/prover/evm.rs +++ b/prover/src/common/prover/evm.rs @@ -8,7 +8,7 @@ use snark_verifier_sdk::{gen_evm_proof_shplonk, CircuitExt, Snark}; use std::{env::set_var, path::PathBuf}; impl Prover { - pub fn gen_comp_evm_proof( + pub fn load_or_gen_comp_evm_proof( &mut self, name: &str, id: &str, @@ -17,19 +17,33 @@ impl Prover { prev_snark: Snark, output_dir: Option<&str>, ) -> Result { - set_var("COMPRESSION_CONFIG", format!("./configs/{id}.config")); + let file_path = format!( + "{}/{}_full_proof.json", + output_dir.unwrap_or_default(), + name + ); - let mut rng = gen_rng(); - let circuit = CompressionCircuit::new(self.params(degree), prev_snark, is_fresh, &mut rng) - .map_err(|err| anyhow!("Failed to construct compression circuit: {err:?}"))?; + match output_dir.and_then(|_| Proof::from_json_file(&file_path).ok().flatten()) { + Some(proof) => Ok(proof), + None => { + set_var("COMPRESSION_CONFIG", format!("./configs/{id}.config")); - let result = self.gen_evm_proof(id, degree, &mut rng, circuit); + let mut rng = gen_rng(); + let circuit = + CompressionCircuit::new(self.params(degree), prev_snark, is_fresh, &mut rng) + .map_err(|err| { + anyhow!("Failed to construct compression circuit: {err:?}") + })?; - if let (Some(output_dir), Ok(proof)) = (output_dir, &result) { - proof.dump(&mut PathBuf::from(output_dir), name)?; - } + let result = self.gen_evm_proof(id, degree, &mut rng, circuit); + + if let (Some(output_dir), Ok(proof)) = (output_dir, &result) { + proof.dump(&mut PathBuf::from(output_dir), name)?; + } - result + result + } + } } fn gen_evm_proof>( diff --git a/prover/src/zkevm/prover.rs b/prover/src/zkevm/prover.rs index 6c523c109..0efebec79 100644 --- a/prover/src/zkevm/prover.rs +++ b/prover/src/zkevm/prover.rs @@ -5,13 +5,19 @@ use crate::{ Proof, }; use anyhow::Result; -use halo2_proofs::{halo2curves::bn256::Bn256, poly::kzg::commitment::ParamsKZG}; +use halo2_proofs::{ + halo2curves::bn256::{Bn256, Fr}, + poly::kzg::commitment::ParamsKZG, +}; +use snark_verifier_sdk::Snark; use std::collections::BTreeMap; use types::eth::BlockTrace; +use zkevm_circuits::evm_circuit::witness::Block; #[derive(Debug)] pub struct Prover { - inner: common::Prover, + // Make it public for testing with inner functions (unnecessary for FFI). + pub inner: common::Prover, } impl From for Prover { @@ -46,15 +52,40 @@ impl Prover { .low_u64() .to_string(); + let layer1_snark = self.load_or_gen_last_snark(&name, witness_block, output_dir)?; + + // Load or generate compression thin snark (layer-2). + let layer2_snark = self.inner.load_or_gen_comp_snark( + &name, + "layer2", + false, + *LAYER2_DEGREE, + layer1_snark, + output_dir, + )?; + log::info!("Got compression thin snark (layer-2): {name}"); + + let pk = self.inner.pk("layer2").unwrap(); + Proof::from_snark(pk, &layer2_snark) + } + + // Generate the previous snark before final proof. + // Then it could be used to generate a normal or EVM proof for verification. + pub fn load_or_gen_last_snark( + &mut self, + name: &str, + witness_block: Block, + output_dir: Option<&str>, + ) -> Result { // Load or generate inner snark. let inner_snark = self .inner - .load_or_gen_inner_snark(&name, witness_block, output_dir)?; + .load_or_gen_inner_snark(name, witness_block, output_dir)?; log::info!("Got inner snark: {name}"); // Load or generate compression wide snark (layer-1). let layer1_snark = self.inner.load_or_gen_comp_snark( - &name, + name, "layer1", true, *LAYER1_DEGREE, @@ -63,18 +94,6 @@ impl Prover { )?; log::info!("Got compression wide snark (layer-1): {name}"); - // Load or generate compression thin snark (layer-2). - let layer2_snark = self.inner.load_or_gen_comp_snark( - &name, - "layer2", - false, - *LAYER2_DEGREE, - layer1_snark, - output_dir, - )?; - log::info!("Got compression thin snark (layer-2): {name}"); - - let pk = self.inner.pk("layer2").unwrap(); - Proof::from_snark(pk, &layer2_snark) + Ok(layer1_snark) } } diff --git a/prover/src/zkevm/verifier.rs b/prover/src/zkevm/verifier.rs index 036339eae..104002c57 100644 --- a/prover/src/zkevm/verifier.rs +++ b/prover/src/zkevm/verifier.rs @@ -8,7 +8,8 @@ use halo2_proofs::{ #[derive(Debug)] pub struct Verifier { - inner: common::Verifier, + // Make it public for testing with inner functions (unnecessary for FFI). + pub inner: common::Verifier, } impl From for Verifier { @@ -33,20 +34,4 @@ impl Verifier { pub fn verify_chunk_proof(&self, proof: Proof) -> bool { self.inner.verify_proof::(proof) } - - /* TODO: verify inner proof. - pub fn verify_inner_proof(&mut self, snark: &Snark) -> Result<()> { - let verifier_params = self.inner_params.verifier_params(); - let vk = self.inner_vks.entry(C::name()).or_insert_with(|| { - let circuit = C::dummy_inner_circuit(); - keygen_vk(&self.inner_params, &circuit) - .unwrap_or_else(|_| panic!("Failed to generate {} vk", C::name())) - }); - if verify_snark_shplonk::(verifier_params, snark.clone(), vk) { - Ok(()) - } else { - bail!("Snark verification failed".to_string()) - } - } - */ } diff --git a/prover/tests/chunk_tests.rs b/prover/tests/chunk_tests.rs index 58e74ae7c..3c52316f6 100644 --- a/prover/tests/chunk_tests.rs +++ b/prover/tests/chunk_tests.rs @@ -1,51 +1,63 @@ use aggregator::CompressionCircuit; use prover::{ - common::{Prover, Verifier}, - config::{LAYER1_DEGREE, LAYER2_DEGREE, ZKEVM_DEGREES}, + config::LAYER2_DEGREE, test_util::{load_block_traces_for_test, PARAMS_DIR}, utils::{chunk_trace_to_witness_block, init_env_and_log}, + zkevm::{Prover, Verifier}, + Proof, }; #[cfg(feature = "prove_verify")] #[test] fn test_chunk_prove_verify() { - // Init, load block traces and construct prover. - - let output_dir = init_env_and_log("comp_tests"); + let test_name = "chunk_tests"; + let output_dir = init_env_and_log(test_name); log::info!("Initialized ENV and created output-dir {output_dir}"); let chunk_trace = load_block_traces_for_test().1; log::info!("Loaded chunk-trace"); let witness_block = chunk_trace_to_witness_block(chunk_trace).unwrap(); - log::info!("Got witness-block"); + log::info!("Got witness block"); - let mut prover = Prover::from_params_dir(PARAMS_DIR, &*ZKEVM_DEGREES); + let mut prover = Prover::from_params_dir(PARAMS_DIR); log::info!("Constructed prover"); - // Load or generate inner snark. - let inner_snark = prover - .load_or_gen_inner_snark("layer0", witness_block, Some(&output_dir)) - .unwrap(); - log::info!("Got inner-snark"); - // Load or generate compression wide snark (layer-1). let layer1_snark = prover + .load_or_gen_last_snark(test_name, witness_block, Some(&output_dir)) + .unwrap(); + + // Load or generate compression thin snark (layer-2). + let layer2_snark = prover + .inner .load_or_gen_comp_snark( - "layer1_0", - "layer1", - true, - *LAYER1_DEGREE, - inner_snark, + test_name, + "layer2", + false, + *LAYER2_DEGREE, + layer1_snark.clone(), Some(&output_dir), ) .unwrap(); - log::info!("Got compression-wide-snark (layer-1)"); + log::info!("Got compression thin snark (layer-2)"); + + let proof = Proof::from_snark(prover.inner.pk("layer2").unwrap(), &layer2_snark).unwrap(); + log::info!("Got normal proof"); + + let params = prover.inner.params(*LAYER2_DEGREE).clone(); + let vk = prover.inner.pk("layer2").unwrap().get_vk().clone(); + let verifier = Verifier::new(params, vk); + log::info!("Constructed verifier"); + + assert!(verifier.verify_chunk_proof(proof)); + log::info!("Finish normal verification"); // Load or generate compression EVM proof (layer-2). let proof = prover - .gen_comp_evm_proof( - "layer2_0", + .inner + .load_or_gen_comp_evm_proof( + test_name, "layer2", false, *LAYER2_DEGREE, @@ -55,10 +67,8 @@ fn test_chunk_prove_verify() { .unwrap(); log::info!("Got compression-EVM-proof (layer-2)"); - // Construct verifier and EVM verify. - let params = prover.params(*LAYER2_DEGREE).clone(); - let vk = proof.vk::(); - let verifier = Verifier::new(params, vk); - verifier.evm_verify::(&proof, &output_dir); - log::info!("Finish EVM verify"); + verifier + .inner + .evm_verify::(&proof, &output_dir); + log::info!("Finish EVM verification"); }