Skip to content

Commit 8aacc83

Browse files
authored
reverse remainder commitment (#373)
1 parent b067ed5 commit 8aacc83

File tree

3 files changed

+17
-6
lines changed

3 files changed

+17
-6
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
- Update security estimator to take batching method into account (#361).
1212
- [BREAKING] Added option for algebraic batching to build constraint composition polynomial (#363).
1313
- Updated minimum supported Rust version to 1.84.
14+
- Commit to coefficients of FRI remainder polynomial in reverse order (#373).
1415

1516
## 0.11.0 (2024-11-24)
1617
- [BREAKING] Made the prover generic over the `ConstraintCommitment` type (#343).

fri/src/prover/mod.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,11 +223,16 @@ where
223223

224224
/// Creates remainder polynomial in coefficient form from a vector of `evaluations` over a
225225
/// domain.
226+
///
227+
/// We commit to the coefficients of the remainder polynomial in reverse order so that
228+
/// evaluating the remainder polynomial on the verifier's end, using Horner's evaluation
229+
/// method, becomes easier.
226230
fn set_remainder(&mut self, channel: &mut C, evaluations: &mut [E]) {
227231
let inv_twiddles = fft::get_inv_twiddles(evaluations.len());
228232
fft::interpolate_poly_with_offset(evaluations, &inv_twiddles, self.options.domain_offset());
229233
let remainder_poly_size = evaluations.len() / self.options.blowup_factor();
230-
let remainder_poly = evaluations[..remainder_poly_size].to_vec();
234+
let remainder_poly: Vec<_> =
235+
evaluations[..remainder_poly_size].iter().copied().rev().collect();
231236
let commitment = <H as ElementHasher>::hash_elements(&remainder_poly);
232237
channel.commit_fri_layer(commitment);
233238
self.remainder_poly = FriRemainder(remainder_poly);
@@ -240,7 +245,9 @@ where
240245
/// For each of the provided `positions`, corresponding evaluations from each of the layers
241246
/// (excluding the remainder layer) are recorded into the proof together with a batch opening
242247
/// proof against the sent vector commitment. For the remainder, we send the whole remainder
243-
/// polynomial resulting from interpolating the remainder layer evaluations.
248+
/// polynomial resulting from interpolating the remainder layer evaluations. The coefficients
249+
/// of the remainder polynomial are sent in reverse order so as to make evaluating it on
250+
/// the verifier's end, using Horner's evaluation method, easier.
244251
///
245252
/// # Panics
246253
/// Panics is the prover state is clean (no FRI layers have been build yet).

fri/src/verifier/mod.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -308,14 +308,16 @@ where
308308

309309
// read the remainder polynomial from the channel and make sure it agrees with the
310310
// evaluations from the previous layer.
311+
// note that the coefficients of the remainder polynomial are sent in reverse order and
312+
// this simplifies evaluation using Horner's method.
311313
let remainder_poly = channel.read_remainder()?;
312314
if remainder_poly.len() > max_degree_plus_1 {
313315
return Err(VerifierError::RemainderDegreeMismatch(max_degree_plus_1 - 1));
314316
}
315317
let offset: E::BaseField = self.options().domain_offset();
316318

317319
for (&position, evaluation) in positions.iter().zip(evaluations) {
318-
let comp_eval = eval_horner::<E>(
320+
let comp_eval = eval_horner_rev::<E>(
319321
&remainder_poly,
320322
offset * domain_generator.exp_vartime((position as u64).into()),
321323
);
@@ -348,10 +350,11 @@ fn get_query_values<E: FieldElement, const N: usize>(
348350
result
349351
}
350352

351-
// Evaluates a polynomial with coefficients in an extension field at a point in the base field.
352-
pub fn eval_horner<E>(p: &[E], x: E::BaseField) -> E
353+
/// Evaluates a polynomial with coefficients in an extension field given in reverse order at a point
354+
/// in the base field.
355+
fn eval_horner_rev<E>(p: &[E], x: E::BaseField) -> E
353356
where
354357
E: FieldElement,
355358
{
356-
p.iter().rev().fold(E::ZERO, |acc, &coeff| acc * E::from(x) + coeff)
359+
p.iter().fold(E::ZERO, |acc, &coeff| acc * E::from(x) + coeff)
357360
}

0 commit comments

Comments
 (0)