Skip to content

Commit

Permalink
Implement fri verifier (#22)
Browse files Browse the repository at this point in the history
* bugfix: fix bug caused by not handling mont form of stone

* chore: clippy issue

* feat: Add helper function for LDE calculation

* chore: sync with varun's branch

* feat: implement fri parameters and foler function for verifying fri

* feat: implement commitment phase of fri verifier

* feat: add simple test mock

* feat: align domain element order with stone-prover

* feat: implement part of decommitment phase

* refactor: move choose_query_indices to details.rs

* feat: implement verify_inner_layers

* feat: implement verify_last_layer

* feat: complete verification of first layer

* feat: complete verification of inner layer

* feat: complete verification of last layer except decommitment

* feat: removed all testcode related garbage codes

* feat: implemented element reordering for stone

* fix: commitment phase

* feat: impl compute_next_fri_layer and add tests

* test: add fri layer tests

* chore: fix build from merge to main

* fix: apply reviews, add comments

* fix: separate test code from FriVerifier struct

* chore: clippy fix

* fix: change argument of next_layer_element_from_two_previous_layer_elements to prevent potential unnecessary calculation

* refactor: compute batch inverse

* fix: resolve previous commit conflicts

* fix: remove unnecessary prits

* fix: resolve broken test

* fix: resolve broken test

* chore: remove comments

---------

Co-authored-by: Varun Thakore <[email protected]>
  • Loading branch information
jaehunkim and varunthakore authored Oct 11, 2024
1 parent 1d89996 commit ee27cd3
Show file tree
Hide file tree
Showing 9 changed files with 530 additions and 35 deletions.
11 changes: 11 additions & 0 deletions channel/src/channel_states.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@ pub struct ChannelStates {
}

impl ChannelStates {
pub fn default() -> Self {
ChannelStates {
is_query_phase: false,
byte_count: 0,
hash_count: 0,
commitment_count: 0,
field_element_count: 0,
data_count: 0,
}
}

pub fn increment_byte_count(&mut self, n: usize) {
self.byte_count += n;
}
Expand Down
24 changes: 22 additions & 2 deletions commitment_scheme/src/table_verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,39 @@ use anyhow::{Error, Ok};
use ark_ff::{BigInteger, PrimeField};
use channel::fs_verifier_channel::FSVerifierChannel;
use channel::VerifierChannel;
use num_bigint::BigUint;
use randomness::Prng;
use sha3::Digest;
use std::collections::{BTreeMap, BTreeSet};

pub struct TableVerifier<F: PrimeField, P: Prng, W: Digest> {
n_columns: usize,
commitment_scheme: Box<dyn CommitmentSchemeVerifier<F, P, W>>,
convert_mont_decommitment: bool,
mont_r: F,
}

impl<F: PrimeField, P: Prng, W: Digest> TableVerifier<F, P, W> {
/// Create new TableVerifier.
pub fn new(
n_columns: usize,
commitment_scheme: Box<dyn CommitmentSchemeVerifier<F, P, W>>,
convert_mont_decommitment: bool,
) -> Self {
let mut mont_r = F::one();
if convert_mont_decommitment {
let size = F::MODULUS_BIT_SIZE.div_ceil(8) * 8;
let mont_r_bigint =
BigUint::from(2u64).modpow(&BigUint::from(size), &F::MODULUS.into());
mont_r = F::from_bigint(<F as PrimeField>::BigInt::try_from(mont_r_bigint).unwrap())
.unwrap();
}

Self {
n_columns,
commitment_scheme,
convert_mont_decommitment,
mont_r,
}
}

Expand Down Expand Up @@ -85,8 +100,13 @@ impl<F: PrimeField, P: Prng, W: Digest> TableVerifier<F, P, W> {
cur_row,
"Data skips to next row before finishing the current."
);

// Copy the field element bytes into the appropriate position in row_data.
let field_bytes = field_element.into_bigint().to_bytes_be();
let field_bytes: Vec<u8> = if self.convert_mont_decommitment {
field_element.mul(&self.mont_r).into_bigint().to_bytes_be()
} else {
field_element.into_bigint().to_bytes_be()
};
assert_eq!(field_bytes.len(), element_size);
row_data.extend_from_slice(&field_bytes);
} else {
Expand Down Expand Up @@ -219,7 +239,7 @@ mod tests {
let commitment_scheme =
make_commitment_scheme_verifier(size_of_row, n_rows, 0, commitment_hashes, n_columns);

let mut table_verifier = TableVerifier::new(n_columns, commitment_scheme);
let mut table_verifier = TableVerifier::new(n_columns, commitment_scheme, false);

let _ = table_verifier.read_commitment(&mut verifier_channel);

Expand Down
2 changes: 2 additions & 0 deletions fri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,6 @@ anyhow.workspace = true
num-bigint.workspace = true

[dev-dependencies]
paste.workspace = true
blake2.workspace = true
rand.workspace = true
35 changes: 13 additions & 22 deletions fri/src/details.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,12 @@ pub fn second_layer_queries_to_first_layer_queries(
query_indices: &[u64],
first_fri_step: usize,
) -> Vec<u64> {
let first_layer_coset_size = 1 << first_fri_step;
let mut first_layer_queries = Vec::with_capacity(query_indices.len() * first_layer_coset_size);

for &idx in query_indices {
for i in (idx * first_layer_coset_size as u64)..((idx + 1) * first_layer_coset_size as u64)
{
first_layer_queries.push(i);
}
}

first_layer_queries
let first_layer_coset_size = (1 << first_fri_step) as u64;
query_indices
.iter()
.copied()
.flat_map(|idx| (idx * first_layer_coset_size)..((idx + 1) * first_layer_coset_size))
.collect()
}

// Computes the element from the next FRI layer,
Expand All @@ -34,12 +29,12 @@ pub fn second_layer_queries_to_first_layer_queries(
// next_layer_element_from_two_previous_layer_elements().
pub fn apply_fri_layers<F: FftField + PrimeField, E: EvaluationDomain<F>>(
elements: &[F],
eval_point: Option<F>,
eval_point: &F,
params: &FriParameters<F, E>,
layer_num: usize,
mut first_element_index: usize,
) -> F {
let mut curr_eval_point = eval_point;
let mut curr_eval_point = *eval_point;
let mut cumulative_fri_step = 0;
for i in 0..layer_num {
cumulative_fri_step += params.fri_step_list[i];
Expand All @@ -54,18 +49,14 @@ pub fn apply_fri_layers<F: FftField + PrimeField, E: EvaluationDomain<F>>(

let mut cur_layer = elements.to_vec();
for basis_index in cumulative_fri_step..(cumulative_fri_step + layer_fri_step) {
assert!(
curr_eval_point.is_some(),
"evaluation point doesn't have a value"
);
let fft_domain = params.fft_domains[basis_index];

let mut next_layer = Vec::with_capacity(cur_layer.len() / 2);
for j in (0..cur_layer.len()).step_by(2) {
let res = MultiplicativeFriFolder::next_layer_element_from_two_previous_layer_elements(
cur_layer[j],
cur_layer[j + 1],
curr_eval_point.unwrap(),
curr_eval_point,
get_field_element_at_index(&fft_domain, first_element_index + j)
.inverse()
.unwrap(),
Expand All @@ -75,7 +66,7 @@ pub fn apply_fri_layers<F: FftField + PrimeField, E: EvaluationDomain<F>>(

cur_layer = next_layer;
// ApplyBasisTransform just calculates square of curr_eval_point
curr_eval_point = Some(curr_eval_point.unwrap() * curr_eval_point.unwrap());
curr_eval_point = curr_eval_point.square();
first_element_index /= 2;
}

Expand Down Expand Up @@ -190,7 +181,7 @@ mod tests {
// fri_step = 1.
let elements: Vec<Felt252> = (0..2).map(|_| Felt252::rand(&mut rng)).collect();
let coset_offset = 4;
let fri_out = apply_fri_layers(&elements, Some(eval_point), &params, 0, coset_offset);
let fri_out = apply_fri_layers(&elements, &eval_point, &params, 0, coset_offset);
let two_to_one_out =
MultiplicativeFriFolder::next_layer_element_from_two_previous_layer_elements(
elements[0],
Expand All @@ -205,7 +196,7 @@ mod tests {
// fri_step = 2.
let elements2: Vec<Felt252> = (0..4).map(|_| Felt252::rand(&mut rng)).collect();
let coset_offset2 = 12;
let fri_out2 = apply_fri_layers(&elements2, Some(eval_point), &params, 1, coset_offset2);
let fri_out2 = apply_fri_layers(&elements2, &eval_point, &params, 1, coset_offset2);

let fold_0_1 = MultiplicativeFriFolder::next_layer_element_from_two_previous_layer_elements(
elements2[0],
Expand Down Expand Up @@ -254,7 +245,7 @@ mod tests {
let x = &get_field_element_at_index(&bases[0], i as usize);
elements.push(poly.evaluate(x));
}
let res = apply_fri_layers(&elements, Some(eval_point), &params, 0, 0);
let res = apply_fri_layers(&elements, &eval_point, &params, 0, 0);
let correction_factor = Felt252::from(1 << fri_step);
assert_eq!(poly.evaluate(&eval_point) * correction_factor, res);
}
Expand Down
8 changes: 5 additions & 3 deletions fri/src/lde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,12 @@ impl<F: PrimeField> MultiplicativeLDE<F> {
// The results are ordered according to the order that the LDEs were added.
pub fn batch_eval(&self, offset: F) -> Vec<Vec<F>> {
let eval_domain = self.base.get_coset(offset).unwrap();

// let eval_domain = self.base;
let mut evals: Vec<Vec<F>> = vec![];
for lde_poly in self.ldes.iter() {
let evals_lde = lde_poly.evaluate_over_domain_by_ref(eval_domain);
evals.push(evals_lde.evals);
for lde in self.ldes.iter() {
let evals_lde = eval_domain.fft(lde);
evals.push(evals_lde);
}

evals
Expand Down
1 change: 1 addition & 0 deletions fri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ mod lde;
mod parameters;
mod prover;
mod stone_domain;
mod test;
mod verifier;
6 changes: 1 addition & 5 deletions fri/src/stone_domain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,15 @@ pub fn change_order_of_elements_in_domain<F: FftField>(elements: &[F]) -> Vec<F>
let size = elements.len().next_power_of_two();
// byte size of usize - log_len
let log_len = size.trailing_zeros() as usize;
// byte size of usize - log_len
println!("log_len: {}", log_len);
let mut new_elements = Vec::with_capacity(size);
for i in 0..size {
println!("i: {}", i);
println!("translate_index(i): {}", translate_index(i, log_len));
new_elements.push(elements[translate_index(i, log_len)])
}

new_elements
}

fn translate_index(index: usize, log_len: usize) -> usize {
pub fn translate_index(index: usize, log_len: usize) -> usize {
let sft = std::mem::size_of::<usize>() * 8 - log_len;
index.reverse_bits() >> sft
}
Expand Down
Loading

0 comments on commit ee27cd3

Please sign in to comment.