diff --git a/triton-vm/src/fri.rs b/triton-vm/src/fri.rs index 020ee0d48..8f6c3b4d2 100644 --- a/triton-vm/src/fri.rs +++ b/triton-vm/src/fri.rs @@ -133,12 +133,20 @@ impl Fri { self.commit(codeword, proof_stream).into_iter().unzip(); // Fiat-Shamir to get indices at which to reveal the codeword - let top_level_indices = + let initial_a_indices = proof_stream.sample_indices(self.domain.length, self.colinearity_checks_count); + let initial_b_indices = initial_a_indices + .iter() + .map(|&idx| (idx + self.domain.length / 2) % self.domain.length) + .collect_vec(); + let top_level_indices = initial_a_indices + .iter() + .copied() + .chain(initial_b_indices) + .collect_vec(); // query phase // query step 0: enqueue authentication paths for all points `A` into proof stream - let initial_a_indices = top_level_indices.clone(); Self::enqueue_auth_pairs(&initial_a_indices, codeword, &merkle_trees[0], proof_stream); // query step 1: loop over FRI rounds, enqueue authentication paths for all points `B` let mut current_domain_len = self.domain.length; @@ -313,11 +321,13 @@ impl Fri { prof_stop!(maybe_profiler, "dequeue and authenticate"); // save indices and revealed leafs of first round's codeword for returning - let revealed_indices_and_elements = a_indices + let revealed_indices_and_elements_first_half = a_indices .iter() .copied() .zip_eq(a_values.iter().copied()) .collect_vec(); + // these indices and values will be computed in the first iteration of the main loop below + let mut revealed_indices_and_elements_second_half = vec![]; // set up "B" for offsetting inside loop. Note that "B" and "A" indices can be calcuated // from each other. @@ -338,6 +348,15 @@ impl Fri { debug_assert_eq!(self.colinearity_checks_count, a_values.len()); debug_assert_eq!(self.colinearity_checks_count, b_values.len()); + if r == 0 { + // save other half of indices and revealed leafs of first round for returning + revealed_indices_and_elements_second_half = b_indices + .iter() + .copied() + .zip_eq(b_values.iter().copied()) + .collect_vec(); + } + // compute "C" indices and values for next round from "A" and "B" of current round current_domain_len /= 2; let c_indices = a_indices.iter().map(|x| x % current_domain_len).collect(); @@ -367,6 +386,11 @@ impl Fri { bail!(FriValidationError::MismatchingLastCodeword); } prof_stop!(maybe_profiler, "compare last codeword"); + + let revealed_indices_and_elements = revealed_indices_and_elements_first_half + .into_iter() + .chain(revealed_indices_and_elements_second_half.into_iter()) + .collect_vec(); Ok(revealed_indices_and_elements) } diff --git a/triton-vm/src/stark.rs b/triton-vm/src/stark.rs index 8d42feec6..c919d1bf7 100644 --- a/triton-vm/src/stark.rs +++ b/triton-vm/src/stark.rs @@ -397,6 +397,10 @@ impl Stark { prof_start!(maybe_profiler, "FRI"); let (revealed_current_row_indices, _) = self.fri.prove(&fri_combination_codeword, &mut proof_stream); + assert_eq!( + self.parameters.num_combination_codeword_checks, + revealed_current_row_indices.len() + ); prof_stop!(maybe_profiler, "FRI"); prof_start!(maybe_profiler, "open trace leafs"); @@ -796,7 +800,7 @@ impl Stark { prof_stop!(maybe_profiler, "check leafs"); prof_start!(maybe_profiler, "linear combination"); - let num_checks = self.parameters.num_colinearity_checks; + let num_checks = self.parameters.num_combination_codeword_checks; assert_eq!(num_checks, revealed_current_row_indices.len()); assert_eq!(num_checks, base_table_rows.len()); assert_eq!(num_checks, ext_table_rows.len());