diff --git a/.gitignore b/.gitignore index 02bb41e..e9c0728 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ -book -target \ No newline at end of file +book \ No newline at end of file diff --git a/src/fri/code/Cargo.lock b/src/fri/code/Cargo.lock deleted file mode 100644 index 5f227c2..0000000 --- a/src/fri/code/Cargo.lock +++ /dev/null @@ -1,75 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "demo" -version = "0.1.0" -dependencies = [ - "rand", -] - -[[package]] -name = "getrandom" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "libc" -version = "0.2.150" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" diff --git a/src/fri/code/Cargo.toml b/src/fri/code/Cargo.toml deleted file mode 100644 index 951a165..0000000 --- a/src/fri/code/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "demo" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -rand = "0.8.5" \ No newline at end of file diff --git a/src/fri/code/readme.md b/src/fri/code/readme.md deleted file mode 100644 index eade85f..0000000 --- a/src/fri/code/readme.md +++ /dev/null @@ -1,20 +0,0 @@ -# what is this -This is an ongoing project to implement a FRI prover and verifier in rust. -The code aims to serve as a walkthrough of the FRI protocol. - -# run test -`cargo test ` - -# plans -## Naive FRI -It is to create layers with folded polynomial and then sample the result. No commitment involved. - -This is to demonstrate the natural structure of FRI, drawing the connection between the math and the idea of low degree testing. - -From PCP(probabilistic checkable proof) perspective, the naive FRI can save verifying time by sampling resulted layers. - -## FRI with commitment -*todo* - -## Soundness calculation -*todo* \ No newline at end of file diff --git a/src/fri/code/src/lib.rs b/src/fri/code/src/lib.rs deleted file mode 100644 index e792811..0000000 --- a/src/fri/code/src/lib.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod poly; \ No newline at end of file diff --git a/src/fri/code/src/poly.rs b/src/fri/code/src/poly.rs deleted file mode 100644 index ef5257c..0000000 --- a/src/fri/code/src/poly.rs +++ /dev/null @@ -1,212 +0,0 @@ -use std::collections::HashMap; // For generating random numbers - -#[derive(Debug, Clone)] -struct Polynomial { - coefficients: Vec, -} - -impl Polynomial { - // Constructor for the Polynomial struct - pub fn new(coefficients: Vec) -> Self { - Polynomial { coefficients } - } - - // Function to evaluate the polynomial at a given value of x - pub fn evaluate(&self, x: i32) -> i32 { - self.coefficients - .iter() - .enumerate() - .fold(0, |acc, (power, &coeff)| acc + coeff * x.pow(power as u32)) - } - - pub fn add(&self, other: &Polynomial) -> Polynomial { - let max_len = usize::max(self.coefficients.len(), other.coefficients.len()); - let mut result = vec![0; max_len]; - - for i in 0..max_len { - let a = *self.coefficients.get(i).unwrap_or(&0); - let b = *other.coefficients.get(i).unwrap_or(&0); - result[i] = a + b; - } - - Polynomial::new(result) - } -} - -impl PartialEq for Polynomial { - fn eq(&self, other: &Self) -> bool { - self.coefficients == other.coefficients - } -} - -// Trait for displaying a polynomial -trait DisplayPolynomial { - fn format(&self) -> String; -} - -// Implementing DisplayPolynomial for Polynomial -impl DisplayPolynomial for Polynomial { - fn format(&self) -> String { - let mut formatted_string = String::new(); - for (i, &coeff) in self.coefficients.iter().enumerate() { - if coeff != 0 { - if i == 0 { - // First coefficient - formatted_string.push_str(&format!("{}", coeff)); - } else { - // Add + sign for positive coefficients, except the first term - if formatted_string.len() > 0 && coeff > 0 { - formatted_string.push_str(" + "); - } else if coeff < 0 { - formatted_string.push_str(" - "); - } - - // Add coefficient (absolute value) and variable part - let abs_coeff = coeff.abs(); - if abs_coeff != 1 { - formatted_string.push_str(&format!("{}", abs_coeff)); - } - formatted_string.push_str(&format!("x^{}", i)); - } - } - } - formatted_string - } -} - -fn fold_polynomial(poly: &Polynomial, beta: i32) -> Polynomial { - let even_coef: Vec = poly.coefficients.iter().step_by(2).cloned().collect(); - let odd_coef: Vec = poly - .coefficients - .iter() - .skip(1) - .step_by(2) - .map(|&coef| coef * beta) // Multiply each odd coefficient by beta - .collect(); - - let even_poly = Polynomial::new(even_coef); - let odd_poly = Polynomial::new(odd_coef); - - even_poly.add(&odd_poly) -} - -fn recursively_fold_polynomials(poly: Polynomial, beta: i32) -> Vec { - let mut folded_polynomials = Vec::new(); - let mut current_poly = poly; - - loop { - folded_polynomials.push(current_poly.clone()); - - // Check if the degree of the current polynomial is 0 - if current_poly.coefficients.len() <= 1 { - break; - } - - // Fold the polynomial - current_poly = fold_polynomial(¤t_poly, beta); - } - - folded_polynomials -} - -fn create_layers(x_values: &[i32], poly_by_layer: Vec) -> Vec> { - let mut layer_evals: Vec> = Vec::new(); - - for &x in x_values { - println!("----\nz = {}\n", x); - - for (i, poly) in poly_by_layer.iter().enumerate() { - let degree = poly.coefficients.len() - 1; - let exponent = 2i32.pow(i as u32); - let elm_point = x.pow(exponent as u32); - let symmetric_elm_point = -elm_point; - let elm = poly.evaluate(elm_point); - let symmetric_elm = poly.evaluate(symmetric_elm_point); - - let poly_info = format!( - "p(x) at layer {}: {:?}, degree: {}", - i, - poly.format(), - degree - ); - let evaluations = if i == 0 { - format!( - "y_{} = z^{}, p(y_{}) = {}, p(-y_{}) = {}", - i, exponent, i, elm, i, symmetric_elm - ) - } else { - format!( - "y_{} = y_{}^2 = z^{}, p(y_{}) = {}, p(-y_{}) = {}", - i, - i - 1, - exponent, - i, - elm, - i, - symmetric_elm - ) - }; - - println!("{}\n{}\n", poly_info, evaluations); - - if layer_evals.get(i).is_none() { - layer_evals.push(HashMap::new()); - } - - let point_to_eval = layer_evals.get_mut(i).unwrap(); - point_to_eval.insert(elm_point, elm); - point_to_eval.insert(symmetric_elm_point, symmetric_elm); - } - } - - layer_evals -} - -fn check_layers(layer_evals: &[HashMap], query: i32, beta: i32) { - for (i, layer) in layer_evals.iter().enumerate() { - println!("current layer: {}", i); - - // Skip first layer - if i == 0 { - continue; - } - - let prev_exponent = 2i32.pow((i - 1) as u32); - let prev_query_point = query.pow(prev_exponent as u32); - let prev_symmetric_query_point = -(query).pow(prev_exponent as u32); - - let prev_layer = layer_evals.get(i - 1).unwrap(); - let prev_elm = prev_layer.get(&prev_query_point).unwrap(); - let prev_symmetric_elm = prev_layer.get(&prev_symmetric_query_point).unwrap(); - - let current_query_point = prev_query_point.pow(2); - println!("prev_query_point: {}", current_query_point); - - let current_elm = layer.get(¤t_query_point).unwrap(); - - let expected = (prev_elm + prev_symmetric_elm) / 2 - + beta * (prev_elm - prev_symmetric_elm) / (2 * prev_query_point); - - assert_eq!(expected, *current_elm); - } - - // Assert the values in the last layer are the same - let last_layer = layer_evals.last().unwrap(); - let mut values = std::collections::HashSet::new(); - for (_, &value) in last_layer.iter() { - values.insert(value); - } - assert_eq!(values.len(), 1); -} - -#[test] -fn naive_query() { - let beta = 1; - let poly = Polynomial::new(vec![1, 2, 3]); - let poly_by_layer = recursively_fold_polynomials(poly, beta); - - let layer_evals = create_layers(&[1, 2, 3], poly_by_layer); - - let query = 2; - check_layers(&layer_evals, query, beta); -} diff --git a/src/fri/naive.md b/src/fri/naive.md index 38fa9b6..b4b866f 100644 --- a/src/fri/naive.md +++ b/src/fri/naive.md @@ -20,7 +20,7 @@ $$ $p_0$ is the source polynomial. After a round of folding, it results in $p_1$. Then, the final round results in a constant polynomial $p_2$. -To see how this folding algorithm works, please refer to the [code](https://github.com/zksecurity/stark-book/blob/692ce671ca2d06a18fad3d3e12182aefdfd4f8fb/src/fri/code/src/poly.rs#L77). +To see how this folding algorithm works, please refer to the [code](https://github.com/katat/fri/blob/ab5aad54b8fd1e37b881ed7558d6ad22b6911442/src/poly.rs#L77). These folded polynomials have the following relationship with their source polynomials: