Skip to content

Commit 1c92725

Browse files
committed
wip: tower proof, not pass yet
1 parent ad9dbab commit 1c92725

2 files changed

Lines changed: 82 additions & 113 deletions

File tree

ceno_recursion/src/tower_verifier/program.rs

Lines changed: 79 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -87,44 +87,44 @@ pub fn verify_tower_proof<C: Config>(
8787

8888
proof: &TowerProofInputVariable<C>,
8989
unipoly_extrapolator: &UniPolyExtrapolator<C>,
90+
// The number of product and lookup specs is fixed by the verifying key, so
91+
// thread them in explicitly to keep the verifier loops static.
92+
num_prod_specs: usize,
93+
num_logup_specs: usize,
9094
) -> (
9195
PointVariable<C>,
9296
Array<C, PointAndEvalVariable<C>>,
9397
Array<C, PointAndEvalVariable<C>>,
9498
Array<C, PointAndEvalVariable<C>>,
9599
) {
96-
let num_prod_spec = prod_out_evals.len();
97-
let num_logup_spec = logup_out_evals.len();
100+
let num_prod_spec = Usize::from(num_prod_specs);
101+
let num_logup_spec = Usize::from(num_logup_specs);
102+
let num_specs_usize = num_prod_specs + num_logup_specs;
98103

99104
let one: Ext<C::F, C::EF> = builder.constant(C::EF::ONE);
100105
let zero: Ext<C::F, C::EF> = builder.constant(C::EF::ZERO);
101106

102107
builder.assert_usize_eq(proof.prod_specs_eval.len(), num_prod_spec.clone());
103-
iter_zip!(builder, prod_out_evals).for_each(|ptr_vec, builder| {
104-
let ptr = ptr_vec[0];
105-
let evals = builder.iter_ptr_get(&prod_out_evals, ptr);
108+
for idx in 0..num_prod_specs {
109+
let evals = builder.get(&prod_out_evals, Usize::from(idx));
106110
builder.assert_usize_eq(evals.len(), num_fanin.clone());
107-
});
111+
}
108112
builder.assert_usize_eq(proof.logup_specs_eval.len(), num_logup_spec.clone());
109-
iter_zip!(builder, logup_out_evals).for_each(|ptr_vec, builder| {
110-
let ptr = ptr_vec[0];
111-
let evals = builder.iter_ptr_get(logup_out_evals, ptr);
113+
for idx in 0..num_logup_specs {
114+
let evals = builder.get(logup_out_evals, Usize::from(idx));
112115
builder.assert_usize_eq(evals.len(), RVar::from(4));
113-
});
116+
}
114117
builder.assert_usize_eq(
115118
num_variables.len(),
116119
num_prod_spec.clone() + num_logup_spec.clone(),
117120
);
118121

119122
let var_zero: Var<C::N> = builder.constant(C::N::ZERO);
120-
let num_specs: Var<C::N> = builder.eval(num_prod_spec.get_var() + num_logup_spec.get_var());
121-
let should_skip: Array<C, Var<C::N>> = builder.dyn_array(num_specs);
122-
builder.range(0, num_specs).for_each(|i_vec, builder| {
123-
let i = i_vec[0];
124-
123+
let should_skip: Array<C, Var<C::N>> = builder.uninit_fixed_array(num_specs_usize);
124+
for idx in 0..num_specs_usize {
125125
// all specs should not be skipped initially
126-
builder.set_value(&should_skip, i, var_zero);
127-
});
126+
builder.set_value(&should_skip, Usize::from(idx), var_zero);
127+
}
128128

129129
transcript_observe_label(builder, challenger, b"combine subset evals");
130130
let alpha = challenger.sample_ext(builder);
@@ -139,99 +139,79 @@ pub fn verify_tower_proof<C: Config>(
139139
builder.cycle_tracker_start("initial sum");
140140
let initial_rt: Array<C, Ext<C::F, C::EF>> = builder.dyn_array(log2_num_fanin);
141141
transcript_observe_label(builder, challenger, b"product_sum");
142-
builder
143-
.range(0, initial_rt.len())
144-
.for_each(|idx_vec, builder| {
145-
let idx = idx_vec[0];
146-
let c = challenger.sample_ext(builder);
147-
builder.set_value(&initial_rt, idx, c);
148-
});
142+
for idx in 0..log2_num_fanin {
143+
let c = challenger.sample_ext(builder);
144+
builder.set_value(&initial_rt, Usize::from(idx), c);
145+
}
149146

150147
let prod_spec_point_n_eval: Array<C, PointAndEvalVariable<C>> =
151-
builder.dyn_array(num_prod_spec.clone());
152-
153-
iter_zip!(builder, prod_out_evals, prod_spec_point_n_eval).for_each(|ptr_vec, builder| {
154-
let ptr = ptr_vec[0];
155-
let evals = builder.iter_ptr_get(&prod_out_evals, ptr);
148+
builder.uninit_fixed_array(num_prod_specs);
149+
for idx in 0..num_prod_specs {
150+
let evals = builder.get(&prod_out_evals, Usize::from(idx));
156151
let e = evaluate_at_point_degree_1(builder, &evals, &initial_rt);
157-
let p_ptr = ptr_vec[1];
158-
builder.iter_ptr_set(
152+
builder.set(
159153
&prod_spec_point_n_eval,
160-
p_ptr,
154+
Usize::from(idx),
161155
PointAndEvalVariable {
162156
point: PointVariable {
163157
fs: initial_rt.clone(),
164158
},
165159
eval: e,
166160
},
167161
);
168-
});
162+
}
169163

170164
let logup_spec_p_point_n_eval: Array<C, PointAndEvalVariable<C>> =
171-
builder.dyn_array(num_logup_spec.clone());
165+
builder.uninit_fixed_array(num_logup_specs);
172166
let logup_spec_q_point_n_eval: Array<C, PointAndEvalVariable<C>> =
173-
builder.dyn_array(num_logup_spec.clone());
174-
175-
iter_zip!(
176-
builder,
177-
logup_out_evals,
178-
logup_spec_p_point_n_eval,
179-
logup_spec_q_point_n_eval
180-
)
181-
.for_each(|ptr_vec, builder| {
182-
let ptr = ptr_vec[0];
183-
let evals = builder.iter_ptr_get(&prod_out_evals, ptr);
184-
167+
builder.uninit_fixed_array(num_logup_specs);
168+
for idx in 0..num_logup_specs {
169+
let evals = builder.get(logup_out_evals, Usize::from(idx));
185170
let p_slice = evals.slice(builder, 0, 2);
186171
let q_slice = evals.slice(builder, 2, 4);
187172

188173
let e1 = evaluate_at_point_degree_1(builder, &p_slice, &initial_rt);
189174
let e2 = evaluate_at_point_degree_1(builder, &q_slice, &initial_rt);
190175

191-
let p_ptr = ptr_vec[1];
192-
let q_ptr = ptr_vec[2];
193-
194-
builder.iter_ptr_set(
176+
builder.set(
195177
&logup_spec_p_point_n_eval,
196-
p_ptr,
178+
Usize::from(idx),
197179
PointAndEvalVariable {
198180
point: PointVariable {
199181
fs: initial_rt.clone(),
200182
},
201183
eval: e1,
202184
},
203185
);
204-
builder.iter_ptr_set(
186+
builder.set(
205187
&logup_spec_q_point_n_eval,
206-
q_ptr,
188+
Usize::from(idx),
207189
PointAndEvalVariable {
208190
point: PointVariable {
209191
fs: initial_rt.clone(),
210192
},
211193
eval: e2,
212194
},
213195
);
214-
});
196+
}
215197

216198
let initial_claim: Ext<C::F, C::EF> = builder.eval(zero + zero);
217199

218-
iter_zip!(builder, prod_spec_point_n_eval).for_each(|ptr_vec, builder| {
219-
let ptr = ptr_vec[0];
220-
let prod_eval = builder.iter_ptr_get(&prod_spec_point_n_eval, ptr);
200+
for idx in 0..num_prod_specs {
201+
let prod_eval = builder.get(&prod_spec_point_n_eval, Usize::from(idx));
221202
builder.assign(&initial_claim, initial_claim + prod_eval.eval * alpha_acc);
222203
builder.assign(&alpha_acc, alpha_acc * alpha);
223-
});
204+
}
224205

225-
builder
226-
.range(0, num_logup_spec.clone())
227-
.for_each(|i_vec, builder| {
228-
let p = builder.get(&logup_spec_p_point_n_eval, i_vec[0]);
229-
builder.assign(&initial_claim, initial_claim + p.eval * alpha_acc);
230-
builder.assign(&alpha_acc, alpha_acc * alpha);
231-
let q = builder.get(&logup_spec_q_point_n_eval, i_vec[0]);
232-
builder.assign(&initial_claim, initial_claim + q.eval * alpha_acc);
233-
builder.assign(&alpha_acc, alpha_acc * alpha);
234-
});
206+
for idx in 0..num_logup_specs {
207+
let lk_idx = Usize::from(idx);
208+
let p = builder.get(&logup_spec_p_point_n_eval, lk_idx.clone());
209+
builder.assign(&initial_claim, initial_claim + p.eval * alpha_acc);
210+
builder.assign(&alpha_acc, alpha_acc * alpha);
211+
let q = builder.get(&logup_spec_q_point_n_eval, lk_idx);
212+
builder.assign(&initial_claim, initial_claim + q.eval * alpha_acc);
213+
builder.assign(&alpha_acc, alpha_acc * alpha);
214+
}
235215
builder.cycle_tracker_end("initial sum");
236216

237217
let curr_pt = initial_rt.clone();
@@ -244,10 +224,9 @@ pub fn verify_tower_proof<C: Config>(
244224
eval: initial_claim,
245225
};
246226

247-
let next_layer_evals_output_len: Usize<C::N> = builder
248-
.eval(Usize::from(1) + num_prod_spec.clone() + Usize::from(2) * num_logup_spec.clone());
227+
let next_layer_evals_len = 1 + num_prod_specs + 2 * num_logup_specs;
249228
let next_layer_evals: Array<C, Ext<C::F, C::EF>> =
250-
builder.dyn_array(next_layer_evals_output_len);
229+
builder.dyn_array(next_layer_evals_len);
251230

252231
builder.range(0, op_range).for_each(|i_vec, builder| {
253232
let round_var = i_vec[0];
@@ -374,49 +353,37 @@ pub fn verify_tower_proof<C: Config>(
374353

375354
builder.if_ne(op_range, Usize::from(0)).then(|builder| {
376355
// update prod_spec and logup_spec evaluations at next_rt
377-
let product_evals = {
378-
let start: Var<C::N> = builder.eval(Usize::from(1));
379-
let end: Var<C::N> = builder.eval(start + num_prod_spec.clone());
380-
next_layer_evals.slice(builder, start, end)
381-
};
382-
let logup_evals = {
383-
let start: Var<C::N> = builder.eval(Usize::from(1) + num_prod_spec.clone());
384-
let end: Var<C::N> = builder.eval(start + Usize::from(2) * num_logup_spec.clone());
385-
next_layer_evals.slice(builder, start, end)
386-
};
387-
388-
builder
389-
.range(0, num_prod_spec.clone())
390-
.for_each(|i_vec, builder| {
391-
let i = i_vec[0];
392-
let eval = builder.get(&product_evals, i);
393-
394-
let point_and_eval: PointAndEvalVariable<C> = builder.eval(PointAndEvalVariable {
395-
point: next_rt.point.clone(),
396-
eval,
397-
});
398-
builder.set_value(&prod_spec_point_n_eval, i, point_and_eval);
356+
let product_evals = next_layer_evals.slice(builder, 1, 1 + num_prod_specs);
357+
let logup_start = 1 + num_prod_specs;
358+
let logup_evals =
359+
next_layer_evals.slice(builder, logup_start, logup_start + 2 * num_logup_specs);
360+
361+
for idx in 0..num_prod_specs {
362+
let eval = builder.get(&product_evals, Usize::from(idx));
363+
364+
let point_and_eval: PointAndEvalVariable<C> = builder.eval(PointAndEvalVariable {
365+
point: next_rt.point.clone(),
366+
eval,
367+
});
368+
builder.set_value(&prod_spec_point_n_eval, Usize::from(idx), point_and_eval);
369+
}
370+
for idx in 0..num_logup_specs {
371+
let lk_idx = Usize::from(idx);
372+
let q_idx = Usize::from(num_logup_specs + idx);
373+
let p_eval = builder.get(&logup_evals, lk_idx.clone());
374+
let q_eval = builder.get(&logup_evals, q_idx);
375+
376+
let p_eval: PointAndEvalVariable<C> = builder.eval(PointAndEvalVariable {
377+
point: next_rt.point.clone(),
378+
eval: p_eval,
399379
});
400-
builder
401-
.range(0, num_logup_spec.clone())
402-
.for_each(|i_vec, builder| {
403-
let i = i_vec[0];
404-
let p_idx = i;
405-
let q_idx: Var<C::N> = builder.eval(num_logup_spec.clone() + i);
406-
let p_eval = builder.get(&logup_evals, p_idx);
407-
let q_eval = builder.get(&logup_evals, q_idx);
408-
409-
let p_eval: PointAndEvalVariable<C> = builder.eval(PointAndEvalVariable {
410-
point: next_rt.point.clone(),
411-
eval: p_eval,
412-
});
413-
let q_eval: PointAndEvalVariable<C> = builder.eval(PointAndEvalVariable {
414-
point: next_rt.point.clone(),
415-
eval: q_eval,
416-
});
417-
builder.set_value(&logup_spec_p_point_n_eval, i, p_eval);
418-
builder.set_value(&logup_spec_q_point_n_eval, i, q_eval);
380+
let q_eval: PointAndEvalVariable<C> = builder.eval(PointAndEvalVariable {
381+
point: next_rt.point.clone(),
382+
eval: q_eval,
419383
});
384+
builder.set_value(&logup_spec_p_point_n_eval, lk_idx.clone(), p_eval);
385+
builder.set_value(&logup_spec_q_point_n_eval, lk_idx, q_eval);
386+
}
420387
});
421388

422389
(

ceno_recursion/src/zkvm_verifier/verifier.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,7 @@ pub fn verify_chip_proof<C: Config>(
584584
}
585585

586586
let tower_proof = &chip_proof.tower_proof;
587+
let num_rw_records_usize = r_len + w_len;
587588
let num_variables: Array<C, Usize<C::N>> = builder.uninit_fixed_array(num_batched_usize);
588589
// Every entry of `num_variables` is identical, so emit straight-line assignments
589590
// with a compile-time bound driven by the verifying key.
@@ -612,6 +613,8 @@ pub fn verify_chip_proof<C: Config>(
612613
num_var_with_rotation.clone(),
613614
tower_proof,
614615
unipoly_extrapolator,
616+
num_rw_records_usize,
617+
lk_len,
615618
);
616619
builder.cycle_tracker_end(format!("verify tower proof for opcode {circuit_name}",).as_str());
617620

@@ -627,7 +630,6 @@ pub fn verify_chip_proof<C: Config>(
627630
builder.cycle_tracker_end(format!("check tower proof p {circuit_name}",).as_str());
628631
}
629632

630-
let num_rw_records_usize = r_len + w_len;
631633
let num_rw_records: Usize<C::N> = Usize::from(num_rw_records_usize);
632634
builder.assert_usize_eq(record_evals.len(), num_rw_records.clone());
633635
builder.assert_usize_eq(logup_p_evals.len(), lk_counts_per_instance.clone());

0 commit comments

Comments
 (0)