From ad1daffae6a20d0eb6194aea58f598b8840f7e71 Mon Sep 17 00:00:00 2001 From: kunxian xia Date: Thu, 18 Dec 2025 20:47:22 +0800 Subject: [PATCH 1/2] write at last layer in tower verifier --- ceno_recursion/src/tower_verifier/program.rs | 119 ++++++++----------- 1 file changed, 52 insertions(+), 67 deletions(-) diff --git a/ceno_recursion/src/tower_verifier/program.rs b/ceno_recursion/src/tower_verifier/program.rs index 33efc16d8..38a32372f 100644 --- a/ceno_recursion/src/tower_verifier/program.rs +++ b/ceno_recursion/src/tower_verifier/program.rs @@ -427,73 +427,7 @@ pub fn verify_tower_proof( &next_layer_evals, ); - let next_round = builder.eval_expr(round_var + RVar::from(1)); - builder - .range(0, num_prod_spec.clone()) - .for_each(|i_vec, builder| { - let spec_index = i_vec[0]; - let skip = builder.get(&should_skip, spec_index); - let max_round = builder.get(&num_variables, spec_index); - let round_limit: RVar = builder.eval_expr(max_round - RVar::from(1)); - - // now skip is 0 if and only if current round_var is smaller than round_limit. - builder.if_eq(skip, var_zero).then(|builder| { - builder.if_eq(next_round, round_limit).then(|builder| { - let evals_idx: Usize = builder.eval(spec_index + Usize::from(1)); - let evals = builder.get(&next_layer_evals, evals_idx); - - let point_and_eval: PointAndEvalVariable = - builder.eval(PointAndEvalVariable { - point: PointVariable { - fs: rt_prime.clone(), - }, - eval: evals, - }); - builder.set_value(&prod_spec_point_n_eval, spec_index, point_and_eval); - }); - }); - }); - - let num_variables_len = num_variables.len(); - let logup_num_variables_slice = - num_variables.slice(builder, num_prod_spec.clone(), num_variables_len.clone()); - - builder - .range(0, num_logup_spec.clone()) - .for_each(|i_vec, builder| { - let spec_index = i_vec[0]; - let max_round = builder.get(&logup_num_variables_slice, spec_index); - let round_limit: RVar = builder.eval_expr(max_round - RVar::from(1)); - let idx: Var = builder.eval(spec_index.variable() + num_prod_spec.get_var()); - let skip = builder.get(&should_skip, idx); - - // now skip is 0 if and only if current round_var is smaller than round_limit. - builder.if_eq(skip, var_zero).then(|builder| { - builder.if_eq(next_round, round_limit).then(|builder| { - let p_idx: Usize = builder.eval(idx + Usize::from(1)); - let q_idx: Usize = - builder.eval(idx + Usize::from(1) + num_logup_spec.clone()); - let p_eval = builder.get(&next_layer_evals, p_idx); - let q_eval = builder.get(&next_layer_evals, q_idx); - - let p_eval: PointAndEvalVariable = builder.eval(PointAndEvalVariable { - point: PointVariable { - fs: rt_prime.clone(), - }, - eval: p_eval, - }); - let q_eval: PointAndEvalVariable = builder.eval(PointAndEvalVariable { - point: PointVariable { - fs: rt_prime.clone(), - }, - eval: q_eval, - }); - builder.set_value(&logup_spec_p_point_n_eval, spec_index, p_eval); - builder.set_value(&logup_spec_q_point_n_eval, spec_index, q_eval); - }); - }); - }); - + // extract next layer's expected sum let output_eval = builder.get(&next_layer_evals, 0); builder.assign(&curr_pt, rt_prime.clone()); builder.assign(&curr_eval, output_eval); @@ -512,6 +446,57 @@ pub fn verify_tower_proof( ); }); + builder.if_ne(op_range, Usize::from(0)).then(|builder| { + // update prod_spec and logup_spec evaluations at next_rt + let product_evals = { + let start: Var = builder.eval(Usize::from(1)); + let end: Var = builder.eval(start + num_prod_spec.clone()); + next_layer_evals.slice(builder, start, end) + }; + let logup_evals = { + let start: Var = builder.eval(Usize::from(1) + num_prod_spec.clone()); + let end: Var = builder.eval(start + Usize::from(2) * num_logup_spec.clone()); + next_layer_evals.slice(builder, start, end) + }; + + builder + .range(0, num_prod_spec.clone()) + .for_each(|i_vec, builder| { + let i = i_vec[0]; + let eval = builder.get(&product_evals, i); + + let point_and_eval: PointAndEvalVariable = builder.eval(PointAndEvalVariable { + point: next_rt.point.clone(), + // point: PointVariable { fs: next_rt.point.fs.clone() }, + eval: eval, + }); + builder.set_value(&prod_spec_point_n_eval, i, point_and_eval); + }); + builder + .range(0, num_logup_spec.clone()) + .for_each(|i_vec, builder| { + let i = i_vec[0]; + let p_idx = i.clone(); + let q_idx: Var = builder.eval(num_logup_spec.clone() + i); + let p_eval = builder.get(&logup_evals, p_idx); + let q_eval = builder.get(&logup_evals, q_idx); + + let p_eval: PointAndEvalVariable = builder.eval(PointAndEvalVariable { + point: next_rt.point.clone(), + eval: p_eval, + }); + let q_eval: PointAndEvalVariable = builder.eval(PointAndEvalVariable { + point: PointVariable { + fs: next_rt.point.fs.clone(), + }, + // point: next_rt.point.clone(), + eval: q_eval, + }); + builder.set_value(&logup_spec_p_point_n_eval, i, p_eval); + builder.set_value(&logup_spec_q_point_n_eval, i, q_eval); + }); + }); + ( next_rt.point, prod_spec_point_n_eval, From c08a22c12f411c0a2aa08a4010bb5ec67ab0c0f2 Mon Sep 17 00:00:00 2001 From: kunxian xia Date: Fri, 19 Dec 2025 15:56:35 +0800 Subject: [PATCH 2/2] clippy --- ceno_recursion/src/aggregation/mod.rs | 2 ++ ceno_recursion/src/tower_verifier/program.rs | 10 +++------- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/ceno_recursion/src/aggregation/mod.rs b/ceno_recursion/src/aggregation/mod.rs index 27d6288c0..44291c244 100644 --- a/ceno_recursion/src/aggregation/mod.rs +++ b/ceno_recursion/src/aggregation/mod.rs @@ -377,7 +377,9 @@ impl CenoLeafVmVerifierConfig { let mut builder = Builder::::default(); { + builder.cycle_tracker_start("Read Ceno ZKVM Proof"); let ceno_leaf_input = CenoLeafVmVerifierInput::read(&mut builder); + builder.cycle_tracker_end("Read Ceno ZKVM Proof"); let stark_pvs = VmVerifierPvs::>::uninit(&mut builder); builder.cycle_tracker_start("Verify Ceno ZKVM Proof"); diff --git a/ceno_recursion/src/tower_verifier/program.rs b/ceno_recursion/src/tower_verifier/program.rs index 38a32372f..cf38b3f27 100644 --- a/ceno_recursion/src/tower_verifier/program.rs +++ b/ceno_recursion/src/tower_verifier/program.rs @@ -467,8 +467,7 @@ pub fn verify_tower_proof( let point_and_eval: PointAndEvalVariable = builder.eval(PointAndEvalVariable { point: next_rt.point.clone(), - // point: PointVariable { fs: next_rt.point.fs.clone() }, - eval: eval, + eval, }); builder.set_value(&prod_spec_point_n_eval, i, point_and_eval); }); @@ -476,7 +475,7 @@ pub fn verify_tower_proof( .range(0, num_logup_spec.clone()) .for_each(|i_vec, builder| { let i = i_vec[0]; - let p_idx = i.clone(); + let p_idx = i; let q_idx: Var = builder.eval(num_logup_spec.clone() + i); let p_eval = builder.get(&logup_evals, p_idx); let q_eval = builder.get(&logup_evals, q_idx); @@ -486,10 +485,7 @@ pub fn verify_tower_proof( eval: p_eval, }); let q_eval: PointAndEvalVariable = builder.eval(PointAndEvalVariable { - point: PointVariable { - fs: next_rt.point.fs.clone(), - }, - // point: next_rt.point.clone(), + point: next_rt.point.clone(), eval: q_eval, }); builder.set_value(&logup_spec_p_point_n_eval, i, p_eval);