Skip to content

Commit

Permalink
Merge pull request #110 from Al-Kindi-0/fri_extended_2
Browse files Browse the repository at this point in the history
Fri extended to folding factor 2
  • Loading branch information
irakliyk authored Sep 21, 2022
2 parents c7c9262 + f22950e commit 8dc47ee
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 54 deletions.
9 changes: 6 additions & 3 deletions fri/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ impl FriOptions {
/// # Panics
/// Panics if:
/// * `blowup_factor` is not a power of two.
/// * `folding_factor` is not 4, 8, or 16.
/// * `max_remainder_size` is not at least twice the size of the `blowup_factor`.
/// * `folding_factor` is not 2, 4, 8, or 16.
/// * `max_remainder_size` is not at least twice the size of the `folding_factor`.
pub fn new(blowup_factor: usize, folding_factor: usize, max_remainder_size: usize) -> Self {
// TODO: change panics to errors
assert!(
Expand All @@ -32,7 +32,10 @@ impl FriOptions {
blowup_factor
);
assert!(
folding_factor == 4 || folding_factor == 8 || folding_factor == 16,
folding_factor == 2
|| folding_factor == 4
|| folding_factor == 8
|| folding_factor == 16,
"folding factor {} is not supported",
folding_factor
);
Expand Down
2 changes: 2 additions & 0 deletions fri/src/prover/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ where
// is small enough; + 1 is for the remainder
for _ in 0..self.options.num_fri_layers(evaluations.len()) + 1 {
match self.folding_factor() {
2 => self.build_layer::<2>(channel, &mut evaluations),
4 => self.build_layer::<4>(channel, &mut evaluations),
8 => self.build_layer::<8>(channel, &mut evaluations),
16 => self.build_layer::<16>(channel, &mut evaluations),
Expand Down Expand Up @@ -244,6 +245,7 @@ where

// sort of a static dispatch for folding_factor parameter
let proof_layer = match folding_factor {
2 => query_layer::<B, E, H, 2>(&self.layers[i], &positions),
4 => query_layer::<B, E, H, 4>(&self.layers[i], &positions),
8 => query_layer::<B, E, H, 8>(&self.layers[i], &positions),
16 => query_layer::<B, E, H, 16>(&self.layers[i], &positions),
Expand Down
112 changes: 73 additions & 39 deletions fri/src/prover/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,45 +18,31 @@ type Blake3 = Blake3_256<BaseElement>;
// ================================================================================================

#[test]
fn fri_prove_verify() {
let trace_length = 4096;
let lde_blowup = 8;

let options = FriOptions::new(lde_blowup, 4, 256);
let mut channel = build_prover_channel(trace_length, &options);
let evaluations = build_evaluations(trace_length, lde_blowup);

// instantiate the prover and generate the proof
let mut prover = FriProver::new(options.clone());
prover.build_layers(&mut channel, evaluations.clone());
let positions = channel.draw_query_positions();
let proof = prover.build_proof(&positions);

// make sure the proof can be verified
let commitments = channel.layer_commitments().to_vec();
let max_degree = trace_length - 1;
let result = verify_proof(
proof.clone(),
commitments.clone(),
&evaluations,
max_degree,
trace_length * lde_blowup,
&positions,
&options,
);
assert!(result.is_ok(), "{:}", result.err().unwrap());
fn fri_folding_2() {
let trace_length_e = 12;
let lde_blowup_e = 3;
let folding_factor_e = 1;
let max_remainder_size_e = 3;
fri_prove_verify(
trace_length_e,
lde_blowup_e,
folding_factor_e,
max_remainder_size_e,
)
}

// make sure proof fails for invalid degree
let result = verify_proof(
proof,
commitments,
&evaluations,
max_degree - 256,
trace_length * lde_blowup,
&positions,
&options,
);
assert!(result.is_err());
#[test]
fn fri_folding_4() {
let trace_length_e = 12;
let lde_blowup_e = 3;
let folding_factor_e = 2;
let max_remainder_size_e = 8;
fri_prove_verify(
trace_length_e,
lde_blowup_e,
folding_factor_e,
max_remainder_size_e,
)
}

// TEST UTILS
Expand Down Expand Up @@ -107,10 +93,58 @@ pub fn verify_proof(
)
.unwrap();
let mut coin = RandomCoin::<BaseElement, Blake3>::new(&[]);
let verifier = FriVerifier::new(&mut channel, &mut coin, options.clone(), max_degree).unwrap();
let verifier = FriVerifier::new(&mut channel, &mut coin, options.clone(), max_degree)?;
let queried_evaluations = positions
.iter()
.map(|&p| evaluations[p])
.collect::<Vec<_>>();
verifier.verify(&mut channel, &queried_evaluations, &positions)
}

fn fri_prove_verify(
trace_length_e: usize,
lde_blowup_e: usize,
folding_factor_e: usize,
max_remainder_size_e: usize,
) {
let trace_length = 1 << trace_length_e;
let lde_blowup = 1 << lde_blowup_e;
let folding_factor = 1 << folding_factor_e;
let max_remainder_size = 1 << max_remainder_size_e;

let options = FriOptions::new(lde_blowup, folding_factor, max_remainder_size);
let mut channel = build_prover_channel(trace_length, &options);
let evaluations = build_evaluations(trace_length, lde_blowup);

// instantiate the prover and generate the proof
let mut prover = FriProver::new(options.clone());
prover.build_layers(&mut channel, evaluations.clone());
let positions = channel.draw_query_positions();
let proof = prover.build_proof(&positions);

// make sure the proof can be verified
let commitments = channel.layer_commitments().to_vec();
let max_degree = trace_length - 1;
let result = verify_proof(
proof.clone(),
commitments.clone(),
&evaluations,
max_degree,
trace_length * lde_blowup,
&positions,
&options,
);
assert!(result.is_ok(), "{:}", result.err().unwrap());

// make sure proof fails for invalid degree
let result = verify_proof(
proof,
commitments,
&evaluations,
max_degree - 8,
trace_length * lde_blowup,
&positions,
&options,
);
assert!(result.is_err());
}
34 changes: 22 additions & 12 deletions fri/src/verifier/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ where
// static dispatch for folding factor parameter
let folding_factor = self.options.folding_factor();
match folding_factor {
2 => self.verify_generic::<2>(channel, evaluations, positions),
4 => self.verify_generic::<4>(channel, evaluations, positions),
8 => self.verify_generic::<8>(channel, evaluations, positions),
16 => self.verify_generic::<16>(channel, evaluations, positions),
Expand Down Expand Up @@ -330,19 +331,28 @@ fn verify_remainder<B: StarkField, E: FieldElement<BaseField = B>>(
if max_degree >= remainder.len() - 1 {
return Err(VerifierError::RemainderDegreeNotValid);
}

// interpolate remainder polynomial from its evaluations; we don't shift the domain here
// because the degree of the polynomial will not change as long as we interpolate over a
// coset of the original domain.
let inv_twiddles = fft::get_inv_twiddles(remainder.len());
fft::interpolate_poly(&mut remainder, &inv_twiddles);
let poly = remainder;

// make sure the degree is valid
if max_degree < polynom::degree_of(&poly) {
Err(VerifierError::RemainderDegreeMismatch(max_degree))
// in case `remainder` represents a polynomial of degree `0` then the final check simplifies
// to checking that the codeword values are identical.
if max_degree == 0 {
if !remainder.windows(2).all(|a| a[0] == a[1]) {
Err(VerifierError::RemainderDegreeMismatch(max_degree))
} else {
Ok(())
}
} else {
Ok(())
// interpolate remainder polynomial from its evaluations; we don't shift the domain here
// because the degree of the polynomial will not change as long as we interpolate over a
// coset of the original domain.
let inv_twiddles = fft::get_inv_twiddles(remainder.len());
fft::interpolate_poly(&mut remainder, &inv_twiddles);
let poly = remainder;

// make sure the degree is valid
if max_degree < polynom::degree_of(&poly) {
Err(VerifierError::RemainderDegreeMismatch(max_degree))
} else {
Ok(())
}
}
}

Expand Down

0 comments on commit 8dc47ee

Please sign in to comment.