diff --git a/ceno_zkvm/src/instructions/riscv/add.rs b/ceno_zkvm/src/instructions/riscv/add.rs index ecde7ef4b..aa595a951 100644 --- a/ceno_zkvm/src/instructions/riscv/add.rs +++ b/ceno_zkvm/src/instructions/riscv/add.rs @@ -119,14 +119,14 @@ mod test { use ark_std::test_rng; use ff::Field; use ff_ext::ExtensionField; - use gkr::util::ceil_log2; + use gkr::{structs::PointAndEval, util::ceil_log2}; use goldilocks::{Goldilocks, GoldilocksExt2}; use multilinear_extensions::mle::DenseMultilinearExtension; use simple_frontend::structs::WitnessId; use singer_utils::{structs_v2::CircuitBuilderV2, util_v2::InstructionV2}; use transcript::Transcript; - use crate::scheme::prover::ZKVMProver; + use crate::scheme::{prover::ZKVMProver, verifier::ZKVMVerifier}; use super::AddInstruction; @@ -154,14 +154,24 @@ mod test { }); // get proof - let prover = ZKVMProver::new(circuit); + let prover = ZKVMProver::new(circuit.clone()); // circuit clone due to verifier alos need circuit reference let mut transcript = Transcript::new(b"riscv"); let challenges = vec![1.into(), 2.into()]; - let _ = prover + let proof = prover .create_proof(wits_in, num_instances, &mut transcript, &challenges) .expect("create_proof failed"); + let verifier = ZKVMVerifier::new(circuit); + let mut v_transcript = Transcript::new(b"riscv"); + verifier + .verify( + &proof, + &mut v_transcript, + &PointAndEval::default(), + &challenges, + ) + .expect("verifier failed"); // println!("circuit_builder {:?}", circuit_builder); } diff --git a/ceno_zkvm/src/scheme.rs b/ceno_zkvm/src/scheme.rs index f94afac28..378367e35 100644 --- a/ceno_zkvm/src/scheme.rs +++ b/ceno_zkvm/src/scheme.rs @@ -1,3 +1,10 @@ +use ff_ext::ExtensionField; +use gkr::structs::PointAndEval; + pub mod prover; +pub mod verifier; -pub struct ZKVMProof {} +#[derive(Clone)] +pub struct ZKVMProof { + pub input_point_and_evals: Vec>, +} diff --git a/ceno_zkvm/src/scheme/prover.rs b/ceno_zkvm/src/scheme/prover.rs index 8619bc90d..22263a215 100644 --- a/ceno_zkvm/src/scheme/prover.rs +++ b/ceno_zkvm/src/scheme/prover.rs @@ -20,6 +20,7 @@ use crate::error::ZKVMError; use super::ZKVMProof; +const MIN_PAR_SIZE: usize = 64; pub struct ZKVMProver { circuit: Circuit, } @@ -34,7 +35,7 @@ impl ZKVMProver { num_instances: usize, _transcript: &mut Transcript, challenges: &[E], - ) -> Result { + ) -> Result, ZKVMError> { let circuit = &self.circuit; let log2_instances = ceil_log2(num_instances); let next_pow2_instances = 1 << log2_instances; @@ -45,8 +46,8 @@ impl ZKVMProver { v.num_vars() == log2_instances && v.evaluations().len() == next_pow2_instances }); - // main constraint: read record witness inference - let span = entered_span!("inference::read_record_evaluation"); + // main constraint: read/write record witness inference + let span = entered_span!("wit_inference::record"); let records_wit: Vec> = circuit .r_expressions .iter() @@ -70,7 +71,7 @@ impl ZKVMProver { scalar }, &|challenge_id, pow, scalar, offset| { - // TODO cache challenge power to be aquire once + // TODO cache challenge power to be aquire once for each power let challenge = challenges[challenge_id as usize]; let challenge: ArcMultilinearExtension = Arc::new(DenseMultilinearExtension::from_evaluations_ext_vec( @@ -91,13 +92,19 @@ impl ZKVMProver { (1, _) => { Arc::new(DenseMultilinearExtension::from_evaluation_vec_smart( ceil_log2(b.len()), - b.par_iter().with_min_len(64).map(|b| a[0] + *b).collect(), + b.par_iter() + .with_min_len(MIN_PAR_SIZE) + .map(|b| a[0] + *b) + .collect(), )) } (_, 1) => { Arc::new(DenseMultilinearExtension::from_evaluation_vec_smart( ceil_log2(a.len()), - a.par_iter().with_min_len(64).map(|a| *a + b[0]).collect(), + a.par_iter() + .with_min_len(MIN_PAR_SIZE) + .map(|a| *a + b[0]) + .collect(), )) } (_, _) => { @@ -105,7 +112,7 @@ impl ZKVMProver { ceil_log2(a.len()), a.par_iter() .zip(b.par_iter()) - .with_min_len(64) + .with_min_len(MIN_PAR_SIZE) .map(|(a, b)| *a + b) .collect(), )) @@ -125,13 +132,19 @@ impl ZKVMProver { (1, _) => { Arc::new(DenseMultilinearExtension::from_evaluation_vec_smart( ceil_log2(b.len()), - b.par_iter().with_min_len(64).map(|b| a[0] * *b).collect(), + b.par_iter() + .with_min_len(MIN_PAR_SIZE) + .map(|b| a[0] * *b) + .collect(), )) } (_, 1) => { Arc::new(DenseMultilinearExtension::from_evaluation_vec_smart( ceil_log2(a.len()), - a.par_iter().with_min_len(64).map(|a| *a * b[0]).collect(), + a.par_iter() + .with_min_len(MIN_PAR_SIZE) + .map(|a| *a * b[0]) + .collect(), )) } (_, _) => { @@ -144,7 +157,10 @@ impl ZKVMProver { op_mle!(|a| { Arc::new(DenseMultilinearExtension::from_evaluation_vec_smart( ceil_log2(a.len()), - a.par_iter().with_min_len(64).map(|a| scalar * a).collect(), + a.par_iter() + .with_min_len(MIN_PAR_SIZE) + .map(|a| scalar * a) + .collect(), )) }) }, @@ -153,15 +169,27 @@ impl ZKVMProver { .collect(); let (r_records_wit, w_records_wit) = records_wit.split_at(circuit.r_expressions.len()); println!("r_records_wit {:?}", r_records_wit,); - println!("w_records_wit {:?}", w_records_wit); exit_span!(span); - // construct main constraint sumcheck virtual polynomial + // product constraint: tower witness inference + let span = entered_span!("wit_inference::tower_witness"); + // TODO + // we dont make the last layer as new vector to save memory + exit_span!(span); - // build first part of sumcheck: selector - // circuit. + // product constraint tower sumcheck + let span = entered_span!("sumcheck::tower"); + // TODO + exit_span!(span); + + // main constraints degree > 1 + selector sumcheck + let span = entered_span!("sumcheck::main_sel"); + // TODO + exit_span!(span); - Ok(ZKVMProof {}) + Ok(ZKVMProof { + input_point_and_evals: vec![], + }) } } diff --git a/ceno_zkvm/src/scheme/verifier.rs b/ceno_zkvm/src/scheme/verifier.rs new file mode 100644 index 000000000..a11c3c3e8 --- /dev/null +++ b/ceno_zkvm/src/scheme/verifier.rs @@ -0,0 +1,34 @@ +use ff_ext::ExtensionField; +use gkr::structs::PointAndEval; +use singer_utils::structs_v2::Circuit; +use transcript::Transcript; + +use crate::error::ZKVMError; + +use super::ZKVMProof; + +pub struct ZKVMVerifier { + circuit: Circuit, +} + +impl ZKVMVerifier { + pub fn new(circuit: Circuit) -> Self { + ZKVMVerifier { circuit } + } + pub fn verify( + &self, + proof: &ZKVMProof, + _transcript: &mut Transcript, + out_evals: &PointAndEval, + challenges: &[E], // derive challenge from PCS + ) -> Result<(), ZKVMError> { + // verify and reduce product tower sumcheck + + // verify main + sel sumcheck + + // verify record (degree = 1) statement, thus no sumcheck + + // verify zero expression (degree = 1) statement, thus no sumcheck + Ok(()) + } +} diff --git a/singer-utils/src/structs_v2.rs b/singer-utils/src/structs_v2.rs index ebde74af3..8f4be7e5e 100644 --- a/singer-utils/src/structs_v2.rs +++ b/singer-utils/src/structs_v2.rs @@ -27,6 +27,7 @@ pub struct CircuitBuilderV2 { pub(crate) phantom: PhantomData, } +#[derive(Clone, Debug)] pub struct Circuit { pub num_witin: WitnessId, pub r_expressions: Vec>,