From 8efc4232089ddeeac7431c98a6ee84e3d39de612 Mon Sep 17 00:00:00 2001 From: Ho Date: Fri, 20 Dec 2024 12:39:48 +0900 Subject: [PATCH] [Feat] Add proof size / hash count statistic into e2e test (#777) This PR have add statistic of proof size / hash counts into e2e test, like the fibonacci bench. It also fixed some unresolved issues mentioned in PR #712 --- ceno_zkvm/Cargo.toml | 2 +- ceno_zkvm/benches/fibonacci.rs | 41 ++++++++++++++++------------------ ceno_zkvm/src/bin/e2e.rs | 15 ++++++++++++- ceno_zkvm/src/scheme/tests.rs | 6 ++--- transcript/src/lib.rs | 2 +- transcript/src/statistics.rs | 8 +++---- 6 files changed, 42 insertions(+), 32 deletions(-) diff --git a/ceno_zkvm/Cargo.toml b/ceno_zkvm/Cargo.toml index ec2e674fc..0f8241f57 100644 --- a/ceno_zkvm/Cargo.toml +++ b/ceno_zkvm/Cargo.toml @@ -37,6 +37,7 @@ tracing-forest.workspace = true tracing-subscriber.workspace = true +bincode = "1" clap = { version = "4.5", features = ["derive"] } generic_static = "0.2" rand.workspace = true @@ -44,7 +45,6 @@ tempfile = "3.14" thread_local = "1.1" [dev-dependencies] -bincode = "1" cfg-if.workspace = true criterion.workspace = true pprof2.workspace = true diff --git a/ceno_zkvm/benches/fibonacci.rs b/ceno_zkvm/benches/fibonacci.rs index 2324de7a6..bae26d21b 100644 --- a/ceno_zkvm/benches/fibonacci.rs +++ b/ceno_zkvm/benches/fibonacci.rs @@ -10,7 +10,7 @@ use ceno_zkvm::{ e2e::{Checkpoint, Preset, run_e2e_with_checkpoint, setup_platform}, }; use criterion::*; -use transcript::{BasicTranscriptWitStat, StatisticRecorder}; +use transcript::{BasicTranscriptWithStat, StatisticRecorder}; use goldilocks::GoldilocksExt2; use mpcs::BasefoldDefault; @@ -45,34 +45,31 @@ fn fibonacci_prove(c: &mut Criterion) { let (program, platform) = setup(); for max_steps in [1usize << 20, 1usize << 21, 1usize << 22] { // estimate proof size data first - let (sanity_check_state, _) = run_e2e_with_checkpoint::( + let (proof, verifier) = run_e2e_with_checkpoint::( program.clone(), platform.clone(), vec![], max_steps, Checkpoint::PrepSanityCheck, - ); + ) + .0 + .expect("PrepSanityCheck do not provide proof and verifier"); + + let serialize_size = bincode::serialize(&proof).unwrap().len(); + let stat_recorder = StatisticRecorder::default(); + let transcript = BasicTranscriptWithStat::new(&stat_recorder, b"riscv"); assert!( - sanity_check_state.is_some(), - "PrepSanityCheck do not provide proof and verifier" + verifier + .verify_proof_halt(proof, transcript, false) + .expect("verify proof return with error"), + ); + println!(); + println!( + "max_steps = {}, proof size = {}, hashes count = {}", + max_steps, + serialize_size, + stat_recorder.into_inner().field_appended_num ); - if let Some((proof, verifier)) = sanity_check_state { - let serialize_size = bincode::serialize(&proof).unwrap().len(); - let stat_recorder = StatisticRecorder::default(); - let transcript = BasicTranscriptWitStat::new(&stat_recorder, b"riscv"); - assert!( - verifier - .verify_proof_halt(proof, transcript, false) - .expect("verify proof return with error"), - ); - println!(); - println!( - "max_steps = {}, proof size = {}, hashes count = {}", - max_steps, - serialize_size, - stat_recorder.into_inner().field_appended_num - ); - } // expand more input size once runtime is acceptable let mut group = c.benchmark_group(format!("fibonacci_max_steps_{}", max_steps)); diff --git a/ceno_zkvm/src/bin/e2e.rs b/ceno_zkvm/src/bin/e2e.rs index d37784e6e..47f268b36 100644 --- a/ceno_zkvm/src/bin/e2e.rs +++ b/ceno_zkvm/src/bin/e2e.rs @@ -14,7 +14,9 @@ use tracing_forest::ForestLayer; use tracing_subscriber::{ EnvFilter, Registry, filter::filter_fn, fmt, layer::SubscriberExt, util::SubscriberInitExt, }; -use transcript::BasicTranscript as Transcript; +use transcript::{ + BasicTranscript as Transcript, BasicTranscriptWithStat as TranscriptWithStat, StatisticRecorder, +}; /// Prove the execution of a fixed RISC-V program. #[derive(Parser, Debug)] @@ -135,6 +137,17 @@ fn main() { let (mut zkvm_proof, verifier) = state.expect("PrepSanityCheck should yield state."); + // do statistics + let serialize_size = bincode::serialize(&zkvm_proof).unwrap().len(); + let stat_recorder = StatisticRecorder::default(); + let transcript = TranscriptWithStat::new(&stat_recorder, b"riscv"); + verifier.verify_proof(zkvm_proof.clone(), transcript).ok(); + println!( + "e2e proof stat: proof size = {}, hashes count = {}", + serialize_size, + stat_recorder.into_inner().field_appended_num + ); + // do sanity check let transcript = Transcript::new(b"riscv"); // change public input maliciously should cause verifier to reject proof diff --git a/ceno_zkvm/src/scheme/tests.rs b/ceno_zkvm/src/scheme/tests.rs index 0ce67e554..e694f03b5 100644 --- a/ceno_zkvm/src/scheme/tests.rs +++ b/ceno_zkvm/src/scheme/tests.rs @@ -14,7 +14,7 @@ use mpcs::{Basefold, BasefoldDefault, BasefoldRSParams, PolynomialCommitmentSche use multilinear_extensions::{ mle::IntoMLE, util::ceil_log2, virtual_poly_v2::ArcMultilinearExtension, }; -use transcript::{BasicTranscript, BasicTranscriptWitStat, StatisticRecorder, Transcript}; +use transcript::{BasicTranscript, BasicTranscriptWithStat, StatisticRecorder, Transcript}; use crate::{ circuit_builder::CircuitBuilder, @@ -157,7 +157,7 @@ fn test_rw_lk_expression_combination() { // verify proof let stat_recorder = StatisticRecorder::default(); let verifier = ZKVMVerifier::new(vk.clone()); - let mut v_transcript = BasicTranscriptWitStat::new(&stat_recorder, b"test"); + let mut v_transcript = BasicTranscriptWithStat::new(&stat_recorder, b"test"); // write commitment into transcript and derive challenges from it Pcs::write_commitment(&proof.wits_commit, &mut v_transcript).unwrap(); let verifier_challenges = [ @@ -298,7 +298,7 @@ fn test_single_add_instance_e2e() { let stat_recorder = StatisticRecorder::default(); { - let transcript = BasicTranscriptWitStat::new(&stat_recorder, b"riscv"); + let transcript = BasicTranscriptWithStat::new(&stat_recorder, b"riscv"); assert!( verifier .verify_proof(zkvm_proof, transcript) diff --git a/transcript/src/lib.rs b/transcript/src/lib.rs index f869d6265..8d01dd366 100644 --- a/transcript/src/lib.rs +++ b/transcript/src/lib.rs @@ -7,7 +7,7 @@ pub mod basic; mod statistics; pub mod syncronized; pub use basic::BasicTranscript; -pub use statistics::{BasicTranscriptWitStat, StatisticRecorder}; +pub use statistics::{BasicTranscriptWithStat, StatisticRecorder}; pub use syncronized::TranscriptSyncronized; #[derive(Default, Copy, Clone, Eq, PartialEq, Debug)] diff --git a/transcript/src/statistics.rs b/transcript/src/statistics.rs index 8f2b46af8..113f4aa1c 100644 --- a/transcript/src/statistics.rs +++ b/transcript/src/statistics.rs @@ -10,12 +10,12 @@ pub struct Statistic { pub type StatisticRecorder = RefCell; #[derive(Clone)] -pub struct BasicTranscriptWitStat<'a, E: ExtensionField> { +pub struct BasicTranscriptWithStat<'a, E: ExtensionField> { inner: BasicTranscript, stat: &'a StatisticRecorder, } -impl<'a, E: ExtensionField> BasicTranscriptWitStat<'a, E> { +impl<'a, E: ExtensionField> BasicTranscriptWithStat<'a, E> { pub fn new(stat: &'a StatisticRecorder, label: &'static [u8]) -> Self { Self { inner: BasicTranscript::<_>::new(label), @@ -24,7 +24,7 @@ impl<'a, E: ExtensionField> BasicTranscriptWitStat<'a, E> { } } -impl Transcript for BasicTranscriptWitStat<'_, E> { +impl Transcript for BasicTranscriptWithStat<'_, E> { fn append_field_elements(&mut self, elements: &[E::BaseField]) { self.stat.borrow_mut().field_appended_num += 1; self.inner.append_field_elements(elements) @@ -56,4 +56,4 @@ impl Transcript for BasicTranscriptWitStat<'_, E> { } } -impl ForkableTranscript for BasicTranscriptWitStat<'_, E> {} +impl ForkableTranscript for BasicTranscriptWithStat<'_, E> {}