diff --git a/src/basefold_verifier/query_phase.rs b/src/basefold_verifier/query_phase.rs index 4af8dba..43bea9e 100644 --- a/src/basefold_verifier/query_phase.rs +++ b/src/basefold_verifier/query_phase.rs @@ -324,7 +324,6 @@ pub(crate) fn batch_verifier_query_phase( builder: &mut Builder, input: QueryPhaseVerifierInputVariable, ) { - builder.cycle_tracker_start("Before checking opening proofs"); let inv_2 = builder.constant(C::F::from_canonical_u32(0x3c000001)); let two_adic_generators_inverses: Array> = builder.dyn_array(28); for (index, val) in [ @@ -393,11 +392,11 @@ pub(crate) fn batch_verifier_query_phase( input.proof.commits.len() + Usize::from(1), input.fold_challenges.len(), ); - builder.cycle_tracker_end("Before checking opening proofs"); - builder.cycle_tracker_start("Build round context"); let rounds_context: Array> = builder.dyn_array(input.rounds.len()); let batch_coeffs_offset: Var = builder.constant(C::N::ZERO); + + builder.cycle_tracker_start("Construct round context"); iter_zip!(builder, input.rounds, rounds_context).for_each(|ptr_vec, builder| { let round = builder.iter_ptr_get(&input.rounds, ptr_vec[0]); // This buffer is not initialized here in providing the context. @@ -465,13 +464,10 @@ pub(crate) fn batch_verifier_query_phase( }; builder.iter_ptr_set(&rounds_context, ptr_vec[1], round_context); }); - builder.cycle_tracker_end("Build round context"); + builder.cycle_tracker_end("Construct round context"); - builder.cycle_tracker_start("Checking opening proofs"); iter_zip!(builder, input.indices, input.proof.query_opening_proof).for_each( |ptr_vec, builder| { - builder.cycle_tracker_start("Checking opening proofs (per index)"); - builder.cycle_tracker_start("Prepare"); // TODO: change type of input.indices to be `Array>>` let idx = builder.iter_ptr_get(&input.indices, ptr_vec[0]); let idx = builder.unsafe_cast_var_to_felt(idx); @@ -496,9 +492,8 @@ pub(crate) fn batch_verifier_query_phase( builder.set_value(&reduced_codeword_by_height, ptr_vec[0], zero_codeword); }); let query = builder.iter_ptr_get(&input.proof.query_opening_proof, ptr_vec[1]); - builder.cycle_tracker_end("Prepare"); - builder.cycle_tracker_start("MMCS Verify Loop Rounds"); + builder.cycle_tracker_start("Batching and first FRI round"); iter_zip!(builder, query.input_proofs, input.rounds, rounds_context).for_each( |ptr_vec, builder| { let batch_opening = builder.iter_ptr_get(&query.input_proofs, ptr_vec[0]); @@ -584,9 +579,7 @@ pub(crate) fn batch_verifier_query_phase( mmcs_verify_batch(builder, mmcs_verifier_input); }, ); - builder.cycle_tracker_end("MMCS Verify Loop Rounds"); - - builder.cycle_tracker_start("Initial folding"); + builder.cycle_tracker_end("Batching and first FRI round"); let opening_ext = query.commit_phase_openings; // fold 1st codeword @@ -614,7 +607,6 @@ pub(crate) fn batch_verifier_query_phase( // check commit phases let commits = &input.proof.commits; builder.assert_eq::>(commits.len(), opening_ext.len()); - builder.cycle_tracker_end("Initial folding"); builder.cycle_tracker_start("FRI rounds"); let i: Var = builder.constant(C::N::ZERO); iter_zip!(builder, commits, opening_ext).for_each(|ptr_vec, builder| { @@ -697,8 +689,6 @@ pub(crate) fn batch_verifier_query_phase( builder.assign(&i, i_plus_one); }); builder.cycle_tracker_end("FRI rounds"); - - builder.cycle_tracker_start("Finalizing"); // assert that final_value[i] = folded let final_idx: Var = builder.constant(C::N::ZERO); builder @@ -713,13 +703,8 @@ pub(crate) fn batch_verifier_query_phase( }); let final_value = builder.get(&final_codeword.values, final_idx); builder.assert_eq::>(final_value, folded); - builder.cycle_tracker_end("Finalizing"); - builder.cycle_tracker_end("Checking opening proofs (per index)"); }, ); - builder.cycle_tracker_end("Checking opening proofs"); - - builder.cycle_tracker_start("Checking sumcheck proofs"); // 1. check initial claim match with first round sumcheck value let batch_coeffs_offset: Var = builder.constant(C::N::ZERO); let expected_sum: Ext = builder.constant(C::EF::ZERO); @@ -766,9 +751,7 @@ pub(crate) fn batch_verifier_query_phase( let right: Ext = builder.eval(eval0 + eval1); builder.assert_eq::>(left, right); }); - builder.cycle_tracker_end("Checking sumcheck proofs"); - builder.cycle_tracker_start("Checking final evaluations"); // 3. check final evaluation are correct let final_evals = builder .get(&input.proof.sumcheck_proof, fold_len_minus_one.clone()) @@ -816,7 +799,6 @@ pub(crate) fn batch_verifier_query_phase( }); builder.assert_eq::>(j, input.proof.final_message.len()); builder.assert_eq::>(left, right); - builder.cycle_tracker_end("Checking final evaluations"); } #[cfg(test)] diff --git a/src/basefold_verifier/verifier.rs b/src/basefold_verifier/verifier.rs index 4f643fc..7183e7f 100644 --- a/src/basefold_verifier/verifier.rs +++ b/src/basefold_verifier/verifier.rs @@ -392,7 +392,8 @@ pub mod tests { let system_config = SystemConfig::default() .with_public_values(4) - .with_max_segment_len((1 << 25) - 100); + .with_max_segment_len((1 << 25) - 100) + .with_profiling(); let config = NativeConfig::new(system_config, Native); let executor = VmExecutor::::new(config); diff --git a/src/e2e/mod.rs b/src/e2e/mod.rs index cc9f8d0..afd5902 100644 --- a/src/e2e/mod.rs +++ b/src/e2e/mod.rs @@ -1,5 +1,5 @@ use crate::basefold_verifier::basefold::BasefoldCommitment; -use crate::tower_verifier::binding::IOPProverMessage; +use crate::tower_verifier::binding::IOPProverMessageVec; use crate::zkvm_verifier::binding::{TowerProofInput, ZKVMChipProofInput, ZKVMProofInput, E, F}; use crate::zkvm_verifier::verifier::verify_zkvm_proof; @@ -81,10 +81,11 @@ pub fn parse_zkvm_proof_import( // Tower proof let mut tower_proof = TowerProofInput::default(); - let mut proofs: Vec> = vec![]; + let mut proofs: Vec = vec![]; for proof in &chip_proof.tower_proof.proofs { - let mut proof_messages: Vec = vec![]; + let mut proof_messages: Vec = vec![]; + let mut prover_message_size = None; for m in proof { let mut evaluations_vec: Vec = vec![]; @@ -93,11 +94,17 @@ pub fn parse_zkvm_proof_import( serde_json::from_value(serde_json::to_value(v.clone()).unwrap()).unwrap(); evaluations_vec.push(v_e); } - proof_messages.push(IOPProverMessage { - evaluations: evaluations_vec, - }); + if let Some(size) = prover_message_size { + assert_eq!(size, evaluations_vec.len()); + } else { + prover_message_size = Some(evaluations_vec.len()); + } + proof_messages.extend_from_slice(&evaluations_vec); } - proofs.push(proof_messages); + proofs.push(IOPProverMessageVec { + prover_message_size: prover_message_size.unwrap(), + data: proof_messages, + }); } tower_proof.num_proofs = proofs.len(); tower_proof.proofs = proofs; @@ -118,7 +125,7 @@ pub fn parse_zkvm_proof_import( prod_specs_eval.push(inner_v); } tower_proof.num_prod_specs = prod_specs_eval.len(); - tower_proof.prod_specs_eval = prod_specs_eval; + tower_proof.prod_specs_eval = prod_specs_eval.into(); let mut logup_specs_eval: Vec>> = vec![]; for inner_val in &chip_proof.tower_proof.logup_specs_eval { @@ -136,11 +143,12 @@ pub fn parse_zkvm_proof_import( logup_specs_eval.push(inner_v); } tower_proof.num_logup_specs = logup_specs_eval.len(); - tower_proof.logup_specs_eval = logup_specs_eval; + tower_proof.logup_specs_eval = logup_specs_eval.into(); // main constraint and select sumcheck proof - let mut main_sumcheck_proofs: Vec = vec![]; - if chip_proof.main_sumcheck_proofs.is_some() { + let main_sumcheck_proofs = if chip_proof.main_sumcheck_proofs.is_some() { + let mut main_sumcheck_proofs: Vec = vec![]; + let mut prover_message_size = None; for m in chip_proof.main_sumcheck_proofs.as_ref().unwrap() { let mut evaluations_vec: Vec = vec![]; for v in &m.evaluations { @@ -148,11 +156,23 @@ pub fn parse_zkvm_proof_import( serde_json::from_value(serde_json::to_value(v.clone()).unwrap()).unwrap(); evaluations_vec.push(v_e); } - main_sumcheck_proofs.push(IOPProverMessage { - evaluations: evaluations_vec, - }); + main_sumcheck_proofs.extend_from_slice(&evaluations_vec); + if let Some(size) = prover_message_size { + assert_eq!(size, evaluations_vec.len()); + } else { + prover_message_size = Some(evaluations_vec.len()); + } } - } + IOPProverMessageVec { + prover_message_size: prover_message_size.unwrap(), + data: main_sumcheck_proofs, + } + } else { + IOPProverMessageVec { + prover_message_size: 0, + data: vec![], + } + }; let mut wits_in_evals: Vec = vec![]; for v in &chip_proof.wits_in_evals { diff --git a/src/tower_verifier/binding.rs b/src/tower_verifier/binding.rs index 26c888a..2cc0281 100644 --- a/src/tower_verifier/binding.rs +++ b/src/tower_verifier/binding.rs @@ -1,3 +1,4 @@ +use itertools::Itertools; use openvm_native_compiler::{ asm::AsmConfig, ir::{Array, Builder, Config}, @@ -29,6 +30,59 @@ pub struct IOPProverMessageVariable { pub evaluations: Array>, } +#[derive(DslVariable, Clone)] +pub struct IOPProverMessageVecVariable { + pub prover_message_size: Var, + pub length: Var, + pub evaluations: Array>, +} + +impl IOPProverMessageVecVariable { + pub fn get(&self, builder: &mut Builder, index: Var) -> Array> { + let start: Var = builder.eval(self.prover_message_size * index); + let end: Var = builder.eval(start + self.prover_message_size); + self.evaluations.slice(builder, start, end) + } + + pub fn len(&self) -> Var { + self.length + } +} + +#[derive(DslVariable, Clone)] +pub struct ThreeDimensionalVecVariable { + pub inner_inner_length: Var, + pub inner_length: Var, + pub length: Var, + pub data: Array>, +} + +impl ThreeDimensionalVecVariable { + pub fn get(&self, builder: &mut Builder, index: Var) -> Array> { + let start: Var = builder.eval(self.inner_inner_length * self.inner_length * index); + let end: Var = builder.eval(start + self.inner_inner_length * self.inner_length); + self.data.slice(builder, start, end) + } + + pub fn get_inner( + &self, + builder: &mut Builder, + outer_index: Var, + inner_index: Var, + ) -> Array> { + let start: Var = builder.eval( + self.inner_inner_length * self.inner_length * outer_index + + self.inner_inner_length * inner_index, + ); + let end: Var = builder.eval(start + self.inner_inner_length); + self.data.slice(builder, start, end) + } + + pub fn len(&self) -> Var { + self.length + } +} + #[derive(Clone, Deserialize)] pub struct Point { pub fs: Vec, @@ -103,6 +157,147 @@ impl Hintable for IOPProverMessage { } impl VecAutoHintable for IOPProverMessage {} +/// Assume that all the prover messages have the same size. +#[derive(Debug, Deserialize)] +pub struct IOPProverMessageVec { + pub prover_message_size: usize, + pub data: Vec, +} + +impl IOPProverMessageVec { + pub fn get(&self, index: usize) -> &[E] { + let start = index * self.prover_message_size; + let end = start + self.prover_message_size; + &self.data[start..end] + } +} + +impl From> for IOPProverMessageVec { + fn from(messages: Vec) -> Self { + let prover_message_size = messages[0].evaluations.len(); + assert!(messages + .iter() + .map(|message| message.evaluations.len()) + .all_equal()); + let data = messages + .into_iter() + .flat_map(|msg| msg.evaluations) + .collect(); + IOPProverMessageVec { + prover_message_size, + data, + } + } +} + +impl Hintable for IOPProverMessageVec { + type HintVariable = IOPProverMessageVecVariable; + + fn read(builder: &mut Builder) -> Self::HintVariable { + let prover_message_size: Var = usize::read(builder); + let length: Var = usize::read(builder); + let evaluations = Vec::::read(builder); + builder.assert_eq::>(evaluations.len(), prover_message_size * length); + IOPProverMessageVecVariable { + prover_message_size, + length, + evaluations, + } + } + + fn write(&self) -> Vec::N>> { + let mut stream = Vec::new(); + stream.extend(>::write( + &self.prover_message_size, + )); + stream.extend(>::write( + &if self.data.len() == 0 { + 0 + } else { + self.data.len() / self.prover_message_size + }, + )); + stream.extend(self.data.write()); + stream + } +} + +#[derive(Debug, Default, Deserialize)] +pub struct ThreeDimensionalVector { + pub inner_inner_length: usize, + pub inner_length: usize, + pub outer_length: usize, + /// Flattened data + pub data: Vec, +} + +impl ThreeDimensionalVector { + pub fn get(&self, outer_index: usize) -> &[E] { + let start = outer_index * self.inner_length * self.inner_inner_length; + let end = start + self.inner_length * self.inner_inner_length; + &self.data[start..end] + } + + pub fn get_inner(&self, outer_index: usize, inner_index: usize) -> &[E] { + let start = outer_index * self.inner_length * self.inner_inner_length + + inner_index * self.inner_inner_length; + let end = start + self.inner_inner_length; + &self.data[start..end] + } +} + +impl From>>> for ThreeDimensionalVector { + fn from(data: Vec>>) -> Self { + let inner_inner_length = if data.len() == 0 { + 0 + } else { + if data[0].len() == 0 { + 0 + } else { + data[0][0].len() + } + }; + let inner_length = if data.len() == 0 { 0 } else { data[0].len() }; + let outer_length = data.len(); + let flattened_data = data.into_iter().flatten().flatten().collect(); + ThreeDimensionalVector { + inner_inner_length, + inner_length, + outer_length, + data: flattened_data, + } + } +} + +impl Hintable for ThreeDimensionalVector { + type HintVariable = ThreeDimensionalVecVariable; + + fn read(builder: &mut Builder) -> Self::HintVariable { + let inner_inner_length: Var = usize::read(builder); + let inner_length: Var = usize::read(builder); + let length: Var = usize::read(builder); + let data = Vec::::read(builder); + builder.assert_eq::>(data.len(), inner_inner_length * inner_length * length); + ThreeDimensionalVecVariable { + inner_inner_length, + inner_length, + length, + data, + } + } + + fn write(&self) -> Vec::N>> { + let mut stream = Vec::new(); + stream.extend(>::write( + &self.inner_inner_length, + )); + stream.extend(>::write(&self.inner_length)); + stream.extend(>::write(&self.outer_length)); + stream.extend(self.data.write()); + stream + } +} + pub struct TowerVerifierInput { pub prod_out_evals: Vec>, pub logup_out_evals: Vec>, diff --git a/src/tower_verifier/program.rs b/src/tower_verifier/program.rs index 85d097b..b22d58a 100644 --- a/src/tower_verifier/program.rs +++ b/src/tower_verifier/program.rs @@ -4,6 +4,7 @@ use crate::arithmetics::{ exts_to_felts, fixed_dot_product, gen_alpha_pows, is_smaller_than, print_ext_arr, reverse, UniPolyExtrapolator, }; +use crate::tower_verifier::binding::IOPProverMessageVecVariable; use crate::transcript::transcript_observe_label; use crate::zkvm_verifier::binding::TowerProofInputVariable; use ceno_zkvm::scheme::constants::NUM_FANIN; @@ -135,7 +136,7 @@ pub fn iop_verifier_state_verify( builder: &mut Builder, challenger: &mut DuplexChallengerVariable, out_claim: &Ext, - prover_messages: &Array>, + prover_messages: &IOPProverMessageVecVariable, max_num_variables: Felt, max_degree: Felt, unipoly_extrapolator: &mut UniPolyExtrapolator, @@ -165,26 +166,22 @@ pub fn iop_verifier_state_verify( .for_each(|i_vec, builder| { let i = i_vec[0]; // TODO: this takes 7 cycles, can we optimize it? - let prover_msg = builder.get(&prover_messages, i); + let prover_msg = prover_messages.get(builder, i.variable()); unsafe { - let prover_msg_felts = exts_to_felts(builder, &prover_msg.evaluations); + let prover_msg_felts = exts_to_felts(builder, &prover_msg); challenger_multi_observe(builder, challenger, &prover_msg_felts); } transcript_observe_label(builder, challenger, b"Internal round"); let challenge = challenger.sample_ext(builder); - let e1 = builder.get(&prover_msg.evaluations, 0); - let e2 = builder.get(&prover_msg.evaluations, 1); + let e1 = builder.get(&prover_msg, 0); + let e2 = builder.get(&prover_msg, 1); let target: Ext<::F, ::EF> = builder.eval(e1 + e2); builder.assert_ext_eq(expected, target); - let p_r = unipoly_extrapolator.extrapolate_uni_poly( - builder, - &prover_msg.evaluations, - challenge, - ); + let p_r = unipoly_extrapolator.extrapolate_uni_poly(builder, &prover_msg, challenge); builder.assign(&expected, p_r + zero); builder.set_value(&challenges, i, challenge); @@ -427,8 +424,11 @@ pub fn verify_tower_proof( builder.if_eq(skip, var_zero.clone()).then(|builder| { builder.if_ne(round_var, round_limit).then_or_else( |builder| { - let prod_slice = builder.get(&proof.prod_specs_eval, spec_index); - let prod_round_slice = builder.get(&prod_slice, round_var); + let prod_round_slice = proof.prod_specs_eval.get_inner( + builder, + spec_index.variable(), + round_var.variable(), + ); builder.assign(&prod, one * one); for j in 0..NUM_FANIN { let prod_j = builder.get(&prod_round_slice, j); @@ -473,8 +473,11 @@ pub fn verify_tower_proof( builder.if_eq(skip, var_zero).then(|builder| { builder.if_ne(round_var, round_limit).then_or_else( |builder| { - let prod_slice = builder.get(&proof.logup_specs_eval, spec_index); - let prod_round_slice = builder.get(&prod_slice, round_var); + let prod_round_slice = proof.logup_specs_eval.get_inner( + builder, + spec_index.variable(), + round_var.variable(), + ); let p1 = builder.get(&prod_round_slice, 0); let p2 = builder.get(&prod_round_slice, 1); @@ -537,8 +540,11 @@ pub fn verify_tower_proof( // now skip is 0 if and only if current round_var is smaller than round_limit. builder.if_eq(skip, var_zero.clone()).then(|builder| { - let prod_slice = builder.get(&proof.prod_specs_eval, spec_index); - let prod_round_slice = builder.get(&prod_slice, round_var); + let prod_round_slice = proof.prod_specs_eval.get_inner( + builder, + spec_index.variable(), + round_var.variable(), + ); let evals = fixed_dot_product(builder, &coeffs, &prod_round_slice, zero); builder.if_ne(next_round, round_limit).then_or_else( @@ -594,8 +600,11 @@ pub fn verify_tower_proof( // now skip is 0 if and only if current round_var is smaller than round_limit. builder.if_eq(skip, var_zero).then(|builder| { - let prod_slice = builder.get(&proof.logup_specs_eval, spec_index); - let prod_round_slice = builder.get(&prod_slice, round_var); + let prod_round_slice = proof.logup_specs_eval.get_inner( + builder, + spec_index.variable(), + round_var.variable(), + ); let p1 = builder.get(&prod_round_slice, 0); let p2 = builder.get(&prod_round_slice, 1); let q1 = builder.get(&prod_round_slice, 2); diff --git a/src/zkvm_verifier/binding.rs b/src/zkvm_verifier/binding.rs index 3645f86..6b1feb4 100644 --- a/src/zkvm_verifier/binding.rs +++ b/src/zkvm_verifier/binding.rs @@ -5,6 +5,10 @@ use crate::basefold_verifier::basefold::{ use crate::basefold_verifier::query_phase::{ QueryPhaseVerifierInput, QueryPhaseVerifierInputVariable, }; +use crate::tower_verifier::binding::{ + IOPProverMessageVec, IOPProverMessageVecVariable, ThreeDimensionalVecVariable, + ThreeDimensionalVector, +}; use crate::{ arithmetics::ceil_log2, tower_verifier::binding::{IOPProverMessage, IOPProverMessageVariable}, @@ -43,11 +47,11 @@ pub struct ZKVMProofInputVariable { #[derive(DslVariable, Clone)] pub struct TowerProofInputVariable { pub num_proofs: Usize, - pub proofs: Array>>, + pub proofs: Array>, pub num_prod_specs: Usize, - pub prod_specs_eval: Array>>>, + pub prod_specs_eval: ThreeDimensionalVecVariable, pub num_logup_specs: Usize, - pub logup_specs_eval: Array>>>, + pub logup_specs_eval: ThreeDimensionalVecVariable, } #[derive(DslVariable, Clone)] @@ -68,7 +72,7 @@ pub struct ZKVMChipProofInputVariable { pub tower_proof: TowerProofInputVariable, - pub main_sel_sumcheck_proofs: Array>, + pub main_sel_sumcheck_proofs: IOPProverMessageVecVariable, pub wits_in_evals: Array>, pub fixed_in_evals: Array>, } @@ -182,13 +186,13 @@ impl Hintable for ZKVMProofInput { #[derive(Default, Debug)] pub struct TowerProofInput { pub num_proofs: usize, - pub proofs: Vec>, + pub proofs: Vec, // specs -> layers -> evals pub num_prod_specs: usize, - pub prod_specs_eval: Vec>>, + pub prod_specs_eval: ThreeDimensionalVector, // specs -> layers -> evals pub num_logup_specs: usize, - pub logup_specs_eval: Vec>>, + pub logup_specs_eval: ThreeDimensionalVector, } impl Hintable for TowerProofInput { @@ -199,25 +203,15 @@ impl Hintable for TowerProofInput { let proofs = builder.dyn_array(num_proofs.clone()); iter_zip!(builder, proofs).for_each(|idx_vec, builder| { let ptr = idx_vec[0]; - let proof = Vec::::read(builder); + let proof = IOPProverMessageVec::read(builder); builder.iter_ptr_set(&proofs, ptr, proof); }); let num_prod_specs = Usize::Var(usize::read(builder)); - let prod_specs_eval = builder.dyn_array(num_prod_specs.clone()); - iter_zip!(builder, prod_specs_eval).for_each(|idx_vec, builder| { - let ptr = idx_vec[0]; - let evals = Vec::>::read(builder); - builder.iter_ptr_set(&prod_specs_eval, ptr, evals); - }); + let prod_specs_eval = ThreeDimensionalVector::read(builder); let num_logup_specs = Usize::Var(usize::read(builder)); - let logup_specs_eval = builder.dyn_array(num_logup_specs.clone()); - iter_zip!(builder, logup_specs_eval).for_each(|idx_vec, builder| { - let ptr = idx_vec[0]; - let evals = Vec::>::read(builder); - builder.iter_ptr_set(&logup_specs_eval, ptr, evals); - }); + let logup_specs_eval = ThreeDimensionalVector::read(builder); TowerProofInputVariable { num_proofs, @@ -238,15 +232,12 @@ impl Hintable for TowerProofInput { stream.extend(>::write( &self.num_prod_specs, )); - for evals in &self.prod_specs_eval { - stream.extend(evals.write()); - } + stream.extend(self.prod_specs_eval.write()); stream.extend(>::write( &self.num_logup_specs, )); - for evals in &self.logup_specs_eval { - stream.extend(evals.write()); - } + stream.extend(self.logup_specs_eval.write()); + stream } } @@ -266,7 +257,7 @@ pub struct ZKVMChipProofInput { pub tower_proof: TowerProofInput, // main constraint and select sumcheck proof - pub main_sumcheck_proofs: Vec, + pub main_sumcheck_proofs: IOPProverMessageVec, pub wits_in_evals: Vec, pub fixed_in_evals: Vec, } @@ -292,7 +283,7 @@ impl Hintable for ZKVMChipProofInput { let record_lk_out_evals = Vec::>::read(builder); let tower_proof = TowerProofInput::read(builder); - let main_sel_sumcheck_proofs = Vec::::read(builder); + let main_sel_sumcheck_proofs = IOPProverMessageVec::read(builder); let wits_in_evals = Vec::::read(builder); let fixed_in_evals = Vec::::read(builder);