Skip to content

Commit ceef001

Browse files
committed
optimize iop_verifier_state_verify
1 parent c2e58cf commit ceef001

6 files changed

Lines changed: 89 additions & 33 deletions

File tree

Cargo.lock

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ceno_recursion/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,12 @@ name = "e2e_aggregate"
5252
path = "src/bin/e2e_aggregate.rs"
5353

5454
[features]
55-
bench-metrics = ["openvm-circuit/metrics"]
55+
bench-metrics = ["openvm-sdk/metrics"]
5656
default = ["parallel", "nightly-features"]
5757
gpu = ["ceno_zkvm/gpu", "openvm-circuit/cuda", "openvm-native-circuit/cuda", "dep:openvm-cuda-backend"]
5858
nightly-features = [
5959
"ceno_zkvm/nightly-features",
6060
"openvm-stark-sdk/nightly-features",
6161
]
6262
parallel = ["openvm-stark-backend/parallel"]
63+
perf-metrics = ["openvm-sdk/perf-metrics"]

ceno_recursion/src/arithmetics/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -927,7 +927,7 @@ impl<C: Config> UniPolyExtrapolator<C> {
927927
res
928928
}
929929

930-
fn extrapolate_uni_poly_deg_1(
930+
pub fn extrapolate_uni_poly_deg_1(
931931
&self,
932932
builder: &mut Builder<C>,
933933
p_i_0: Ext<C::F, C::EF>,
@@ -946,7 +946,7 @@ impl<C: Config> UniPolyExtrapolator<C> {
946946
builder.eval(l * (t0 + t1))
947947
}
948948

949-
fn extrapolate_uni_poly_deg_2(
949+
pub fn extrapolate_uni_poly_deg_2(
950950
&self,
951951
builder: &mut Builder<C>,
952952
p_i_0: Ext<C::F, C::EF>,
@@ -970,7 +970,7 @@ impl<C: Config> UniPolyExtrapolator<C> {
970970
builder.eval(l * (t0 + t1 + t2))
971971
}
972972

973-
fn extrapolate_uni_poly_deg_3(
973+
pub fn extrapolate_uni_poly_deg_3(
974974
&self,
975975
builder: &mut Builder<C>,
976976
p_i_0: Ext<C::F, C::EF>,
@@ -998,7 +998,7 @@ impl<C: Config> UniPolyExtrapolator<C> {
998998
builder.eval(l * (t0 + t1 + t2 + t3))
999999
}
10001000

1001-
fn extrapolate_uni_poly_deg_4(
1001+
pub fn extrapolate_uni_poly_deg_4(
10021002
&self,
10031003
builder: &mut Builder<C>,
10041004
p_i_0: Ext<C::F, C::EF>,

ceno_recursion/src/tower_verifier/program.rs

Lines changed: 54 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ use crate::{
55
exts_to_felts,
66
},
77
tower_verifier::binding::IOPProverMessageVecVariable,
8-
transcript::transcript_observe_label,
8+
transcript::{
9+
transcript_label_as_array, transcript_observe_label, transcript_observe_label_felts,
10+
},
911
zkvm_verifier::binding::TowerProofInputVariable,
1012
};
1113
use openvm_native_compiler::prelude::*;
@@ -22,51 +24,84 @@ pub fn iop_verifier_state_verify<C: Config>(
2224
out_claim: &Ext<C::F, C::EF>,
2325
prover_messages: &IOPProverMessageVecVariable<C>,
2426
max_num_variables: Felt<C::F>,
25-
max_degree: Felt<C::F>,
27+
max_degree: usize,
2628
unipoly_extrapolator: &UniPolyExtrapolator<C>,
2729
) -> (
2830
Array<C, Ext<<C as Config>::F, <C as Config>::EF>>,
2931
Ext<<C as Config>::F, <C as Config>::EF>,
3032
) {
31-
// TODO: either store it in a global cache or pass them as parameters
32-
let zero: Ext<C::F, C::EF> = builder.constant(C::EF::ZERO);
33-
let zero_f: Felt<C::F> = builder.constant(C::F::ZERO);
34-
33+
let max_degree_felt: Felt<C::F> = builder.constant(C::F::from_canonical_usize(max_degree));
3534
let max_num_variables_usize: Usize<C::N> =
3635
Usize::from(builder.cast_felt_to_var(max_num_variables));
37-
challenger.observe(builder, max_num_variables);
38-
challenger.observe(builder, zero_f);
39-
challenger.observe(builder, max_degree);
40-
challenger.observe(builder, zero_f);
36+
let pre_verified_integrity_data: Array<C, Felt<C::F>> = builder.dyn_array(4);
37+
// Prover and verifier currently agree on how `usize` values are serialized.
38+
// On a 64-bit platform, a `usize` spans 64 bits, so it is represented
39+
// as two ordered `u32` Felts.
40+
//
41+
// `max_num_variables` occupies the first Felt,
42+
// with the second Felt padded with 0. The same layout applies to `max_degree`.
43+
//
44+
// TODO fix to single u32
45+
builder.set_value(&pre_verified_integrity_data, 0, max_num_variables);
46+
builder.set_value(&pre_verified_integrity_data, 2, max_degree_felt);
47+
challenger_multi_observe(builder, challenger, &pre_verified_integrity_data);
4148

4249
builder.assert_var_eq(max_num_variables_usize.get_var(), prover_messages.len());
4350

4451
let challenges: Array<C, Ext<C::F, C::EF>> = builder.dyn_array(max_num_variables_usize.clone());
45-
let expected: Ext<C::F, C::EF> = builder.eval(*out_claim + zero);
52+
let expected: Ext<C::F, C::EF> = builder.eval(*out_claim);
53+
let internal_round_label = transcript_label_as_array(builder, b"Internal round");
4654

4755
builder.cycle_tracker_start("IOPVerifierState::verify_round_and_update_state");
56+
let curr_offset: Var<C::N> = builder.eval(C::N::ZERO);
4857
builder
4958
.range(0, max_num_variables_usize.clone())
5059
.for_each(|i_vec, builder| {
5160
let i = i_vec[0];
5261

53-
// TODO: this takes 7 cycles, can we optimize it?
54-
let prover_msg = prover_messages.get(builder, i.variable());
62+
let next_offset: Var<C::N> =
63+
builder.eval(curr_offset + prover_messages.prover_message_size);
64+
let prover_msg = prover_messages
65+
.evaluations
66+
.slice(builder, curr_offset, next_offset);
67+
builder.assign(&curr_offset, next_offset);
5568

5669
unsafe {
5770
let prover_msg_felts = exts_to_felts(builder, &prover_msg);
5871
challenger_multi_observe(builder, challenger, &prover_msg_felts);
5972
}
6073

61-
transcript_observe_label(builder, challenger, b"Internal round");
74+
transcript_observe_label_felts(builder, challenger, &internal_round_label);
6275
let challenge = challenger.sample_ext(builder);
6376

6477
let e1 = builder.get(&prover_msg, 0);
6578
let e0 = builder.eval(expected - e1);
66-
let p_r =
67-
unipoly_extrapolator.extrapolate_uni_poly(builder, e0, &prover_msg, challenge);
68-
69-
builder.assign(&expected, p_r + zero);
79+
let p_r = match max_degree {
80+
1 => unipoly_extrapolator.extrapolate_uni_poly_deg_1(builder, e0, e1, challenge),
81+
2 => {
82+
let p1 = e1;
83+
let p2 = builder.get(&prover_msg, 1);
84+
unipoly_extrapolator.extrapolate_uni_poly_deg_2(builder, e0, p1, p2, challenge)
85+
}
86+
3 => {
87+
let p1 = e1;
88+
let p2 = builder.get(&prover_msg, 1);
89+
let p3 = builder.get(&prover_msg, 2);
90+
unipoly_extrapolator
91+
.extrapolate_uni_poly_deg_3(builder, e0, p1, p2, p3, challenge)
92+
}
93+
4 => {
94+
let p1 = e1;
95+
let p2 = builder.get(&prover_msg, 1);
96+
let p3 = builder.get(&prover_msg, 2);
97+
let p4 = builder.get(&prover_msg, 3);
98+
unipoly_extrapolator
99+
.extrapolate_uni_poly_deg_4(builder, e0, p1, p2, p3, p4, challenge)
100+
}
101+
_ => panic!("unsupported max_degree {max_degree}"),
102+
};
103+
104+
builder.assign(&expected, p_r);
70105
builder.set_value(&challenges, i, challenge);
71106
});
72107
builder.cycle_tracker_end("IOPVerifierState::verify_round_and_update_state");
@@ -258,16 +293,14 @@ pub fn verify_tower_proof<C: Config>(
258293
let max_num_variables: Felt<C::F> = builder.constant(C::F::ONE);
259294
builder.assign(&max_num_variables, max_num_variables + round);
260295

261-
let max_degree = builder.constant(C::F::from_canonical_usize(3));
262-
263296
builder.cycle_tracker_start("sumcheck verify");
264297
let (sub_rt, sub_e) = iop_verifier_state_verify(
265298
builder,
266299
challenger,
267300
out_claim,
268301
&prover_messages,
269302
max_num_variables,
270-
max_degree,
303+
3,
271304
unipoly_extrapolator,
272305
);
273306
builder.cycle_tracker_end("sumcheck verify");

ceno_recursion/src/transcript/mod.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ use openvm_native_recursion::challenger::{
55
};
66
use openvm_stark_backend::p3_field::FieldAlgebra;
77

8+
use crate::arithmetics::challenger_multi_observe;
9+
810
pub fn transcript_observe_label<C: Config>(
911
builder: &mut Builder<C>,
1012
challenger: &mut DuplexChallengerVariable<C>,
@@ -17,6 +19,27 @@ pub fn transcript_observe_label<C: Config>(
1719
}
1820
}
1921

22+
pub fn transcript_label_as_array<C: Config>(
23+
builder: &mut Builder<C>,
24+
label: &[u8],
25+
) -> Array<C, Felt<C::F>> {
26+
let label_f = <BabyBearExt4 as CenoExtensionField>::BaseField::bytes_to_field_elements(label);
27+
let arr: Array<C, Felt<C::F>> = builder.dyn_array(label_f.len());
28+
for (idx, n) in label_f.into_iter().enumerate() {
29+
let f: Felt<C::F> = builder.constant(C::F::from_canonical_u64(n.to_canonical_u64()));
30+
builder.set_value(&arr, idx, f);
31+
}
32+
arr
33+
}
34+
35+
pub fn transcript_observe_label_felts<C: Config>(
36+
builder: &mut Builder<C>,
37+
challenger: &mut DuplexChallengerVariable<C>,
38+
label_felts: &Array<C, Felt<C::F>>,
39+
) {
40+
challenger_multi_observe(builder, challenger, label_felts);
41+
}
42+
2043
pub fn transcript_check_pow_witness<C: Config>(
2144
builder: &mut Builder<C>,
2245
challenger: &mut DuplexChallengerVariable<C>,

ceno_recursion/src/zkvm_verifier/verifier.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -953,8 +953,6 @@ pub fn verify_gkr_circuit<C: Config>(
953953
});
954954

955955
// sigma = \sum_b sel(b) * zero_expr(b)
956-
let max_degree = builder.constant(C::F::from_canonical_usize(layer.max_expr_degree + 1));
957-
958956
let max_num_variables_f = builder.unsafe_cast_var_to_felt(max_num_variables.get_var());
959957

960958
let (in_point, expected_evaluation) = iop_verifier_state_verify(
@@ -963,7 +961,7 @@ pub fn verify_gkr_circuit<C: Config>(
963961
&sigma,
964962
&proof,
965963
max_num_variables_f,
966-
max_degree,
964+
layer.max_expr_degree + 1,
967965
unipoly_extrapolator,
968966
);
969967

@@ -1204,15 +1202,14 @@ pub fn verify_rotation<C: Config>(
12041202
let sigma: Ext<C::F, C::EF> = builder.constant(C::EF::ZERO);
12051203

12061204
let max_num_variables = builder.unsafe_cast_var_to_felt(max_num_variables.get_var());
1207-
let max_degree: Felt<C::F> = builder.constant(C::F::TWO);
12081205

12091206
let (origin_point, expected_evaluation) = iop_verifier_state_verify(
12101207
builder,
12111208
challenger,
12121209
&sigma,
12131210
proof,
12141211
max_num_variables,
1215-
max_degree,
1212+
2,
12161213
unipoly_extrapolator,
12171214
);
12181215

@@ -1756,15 +1753,14 @@ pub fn verify_ecc_proof<C: Config>(
17561753

17571754
let one_ext: Ext<C::F, C::EF> = builder.constant(C::EF::ONE);
17581755
let zero_ext: Ext<C::F, C::EF> = builder.constant(C::EF::ZERO);
1759-
let three_f: Felt<C::F> = builder.constant(C::F::from_canonical_u32(3));
17601756
let num_vars_f = builder.unsafe_cast_var_to_felt(num_vars.get_var());
17611757
let (rt, sumcheck_expected_evaluation) = iop_verifier_state_verify(
17621758
builder,
17631759
challenger,
17641760
&zero_ext,
17651761
&proof.zerocheck_proof,
17661762
num_vars_f,
1767-
three_f,
1763+
3,
17681764
unipoly_extrapolator,
17691765
);
17701766

0 commit comments

Comments
 (0)