Skip to content

Commit df96d8b

Browse files
authored
Splitting PR #44: Optimize cycles in FRI rounds in BaseFold verifier (#56)
* Optimize FRI round * Small improve * Small improve * Small improve * Remove unnecessary computing coeff * Fix small issues * Improve comment
1 parent b0029f1 commit df96d8b

File tree

3 files changed

+35
-19
lines changed

3 files changed

+35
-19
lines changed

src/basefold_verifier/query_phase.rs

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -336,12 +336,13 @@ pub(crate) fn batch_verifier_query_phase<C: Config>(
336336
.iter()
337337
.enumerate()
338338
{
339-
let generator = builder.constant(C::F::from_canonical_usize(*val).inverse());
340-
builder.set_value(&two_adic_generators_inverses, index, generator);
339+
let generator_inverse = builder.constant(C::F::from_canonical_usize(*val).inverse());
340+
builder.set_value(&two_adic_generators_inverses, index, generator_inverse);
341341
}
342342
let zero: Ext<C::F, C::EF> = builder.constant(C::EF::ZERO);
343343
let zero_flag = builder.constant(C::N::ZERO);
344-
let two: Var<C::N> = builder.constant(C::N::from_canonical_usize(2));
344+
let two: Var<C::N> = builder.constant(C::N::TWO);
345+
let two_felt: Felt<C::F> = builder.constant(C::F::TWO);
345346

346347
// encode_small
347348
let final_message = &input.proof.final_message;
@@ -615,11 +616,10 @@ pub(crate) fn batch_verifier_query_phase<C: Config>(
615616
builder.assert_eq::<Var<C::N>>(commits.len(), opening_ext.len());
616617
builder.cycle_tracker_end("Initial folding");
617618
builder.cycle_tracker_start("FRI rounds");
618-
builder.range(0, commits.len()).for_each(|i_vec, builder| {
619-
builder.cycle_tracker_start("FRI round");
620-
let i = i_vec[0];
621-
let commit = builder.get(&commits, i);
622-
let commit_phase_step = builder.get(&opening_ext, i);
619+
let i: Var<C::N> = builder.constant(C::N::ZERO);
620+
iter_zip!(builder, commits, opening_ext).for_each(|ptr_vec, builder| {
621+
let commit = builder.iter_ptr_get(&commits, ptr_vec[0]);
622+
let commit_phase_step = builder.iter_ptr_get(&opening_ext, ptr_vec[1]);
623623
let i_plus_one = builder.eval_expr(i + Usize::from(1));
624624

625625
let sibling_value = commit_phase_step.sibling_value;
@@ -632,12 +632,36 @@ pub(crate) fn batch_verifier_query_phase<C: Config>(
632632
let new_involved_packed_codeword =
633633
builder.get(&reduced_codeword_by_height, log2_height.clone());
634634

635+
// Note that previous coeff is
636+
// 1/2 * generator_of_order(2^{level + 2})^{-prev_index}
637+
// = 1/2 * generator_of_order(2^{level + 2})^{-(index+2^level*prev_bit)}
638+
// = 1/2 * omega^{-2^(MAX - (level + 2)) * (index+2^level*prev_bit)}
639+
// where generator_of_order(2^k) returns the generator of order 2^k, which is omega^{2^(MAX - k)}
640+
// since omega is the generator of order 2^MAX, where MAX is the two-adicity of this field.
641+
// Here prev_bit is the most significant bit of prev_index, and index is removing this bit
642+
// from prev_index.
643+
//
644+
// So prev ^ 2 = 1/4 * omega^{-2^(MAX - (level + 2)) * 2 * (index+2^level*prev_bit)}
645+
// = 1/4 * omega^{-2^(MAX - (level + 1)) * (index+2^level*prev_bit)}
646+
// = 1/4 * omega^{-2^(MAX - (level + 1)) * index - 2^(MAX - (level + 1)) * 2^level*prev_bit}
647+
// = 1/2 * curr * omeag^{- 2^(MAX - 1) * prev_bit}
648+
// = 1/2 * curr * generator_of_order(2)^{-prev_bit}
649+
// Note that generator_of_order(2) is exactly -1, so
650+
// prev ^ 2 = 1/2 * curr * (-1)^{-prev_bit}
651+
// which gives us
652+
// curr = 2 * prev^2 * (-1)^{prev_bit}
653+
// Note that we haven't multplied the (-1)^{prev_bit} in the following line.
654+
// Because `folded_idx` is just the `prev_bit`, so we reuse the following `if_eq` and multiply -1
655+
// in the branch where `folded_idx` is != 0.
656+
builder.assign(&coeff, coeff * coeff * two_felt);
657+
635658
builder.if_eq(folded_idx, Usize::from(0)).then_or_else(
636659
|builder| {
637660
builder.assign(&folded, folded + new_involved_packed_codeword.low);
638661
},
639662
|builder| {
640663
builder.assign(&folded, folded + new_involved_packed_codeword.high);
664+
builder.assign(&coeff, -coeff);
641665
},
642666
);
643667

@@ -665,19 +689,12 @@ pub(crate) fn batch_verifier_query_phase<C: Config>(
665689
ext_mmcs_verify_batch::<C>(builder, ext_mmcs_verifier_input);
666690

667691
let r = builder.get(&input.fold_challenges, i_plus_one);
668-
let coeff = verifier_folding_coeffs_level(
669-
builder,
670-
&two_adic_generators_inverses,
671-
log2_height,
672-
&idx_pair,
673-
inv_2,
674-
);
675692
let left = builder.get(&leafs, 0);
676693
let right = builder.get(&leafs, 1);
677694
let new_folded =
678695
codeword_fold_with_challenge(builder, left, right, r, coeff, inv_2);
679696
builder.assign(&folded, new_folded);
680-
builder.cycle_tracker_end("FRI round");
697+
builder.assign(&i, i_plus_one);
681698
});
682699
builder.cycle_tracker_end("FRI rounds");
683700

src/basefold_verifier/rs.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,6 @@ pub fn verifier_folding_coeffs_level<C: Config>(
114114
) -> Felt<C::F> {
115115
let level_plus_one = builder.eval::<Var<C::N>, _>(level + C::N::ONE);
116116
let g_inv = builder.get(two_adic_generators_inverses, level_plus_one);
117-
118117
let g_inv_index = pow_felt_bits(builder, g_inv, index_bits, level.into());
119118

120119
builder.eval(g_inv_index * two_inv)

src/basefold_verifier/utils.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ pub fn pow_felt<C: Config>(
3131
pub fn pow_felt_bits<C: Config>(
3232
builder: &mut Builder<C>,
3333
base: Felt<C::F>,
34-
exponent_bits: &Array<C, Var<C::N>>, // FIXME: Should be big endian? There is a bit_reverse_rows() in Ceno native code
35-
exponent_len: Usize<C::N>,
34+
exponent_bits: &Array<C, Var<C::N>>,
35+
exponent_len: Usize<C::N>, // This is not exponent_bits.len(), possibly smaller than it
3636
) -> Felt<C::F> {
3737
let value: Felt<C::F> = builder.constant(C::F::ONE);
3838

0 commit comments

Comments
 (0)