From 5b71de37f7caaccd7084f91c90755471f1543875 Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Mon, 13 Feb 2023 13:03:53 -0300 Subject: [PATCH 01/85] prover sub crate created --- Cargo.toml | 1 + prover/Cargo.toml | 9 +++++++++ prover/src/fri/mod.rs | 11 +++++++++++ prover/src/lib.rs | 1 + 4 files changed, 22 insertions(+) create mode 100644 prover/Cargo.toml create mode 100644 prover/src/fri/mod.rs create mode 100644 prover/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 7662aa11d..8496805f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,4 +3,5 @@ members = [ "math", "crypto", + "prover", ] diff --git a/prover/Cargo.toml b/prover/Cargo.toml new file mode 100644 index 000000000..aacbd7a18 --- /dev/null +++ b/prover/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "lambdaworks-prover" +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" diff --git a/prover/src/fri/mod.rs b/prover/src/fri/mod.rs new file mode 100644 index 000000000..6544e12a9 --- /dev/null +++ b/prover/src/fri/mod.rs @@ -0,0 +1,11 @@ +pub fn hello() { + println!("Hello world"); +} + +#[cfg(test)] +mod tests { + #[test] + fn test_hello() { + super::hello(); + } +} diff --git a/prover/src/lib.rs b/prover/src/lib.rs new file mode 100644 index 000000000..af12d86da --- /dev/null +++ b/prover/src/lib.rs @@ -0,0 +1 @@ +pub mod fri; From 6c2789e2f3e90c8f234557116a000435245e1a9b Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Mon, 13 Feb 2023 15:19:51 -0300 Subject: [PATCH 02/85] working on fold function --- prover/Cargo.toml | 4 ++++ prover/src/fri/mod.rs | 53 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/prover/Cargo.toml b/prover/Cargo.toml index aacbd7a18..f016da4b1 100644 --- a/prover/Cargo.toml +++ b/prover/Cargo.toml @@ -5,5 +5,9 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[dependencies.lambdaworks-math] +path = "../math" + [dependencies] rand = "0.8.5" +itertools = "0.10.5" diff --git a/prover/src/fri/mod.rs b/prover/src/fri/mod.rs index 6544e12a9..24e4bcf67 100644 --- a/prover/src/fri/mod.rs +++ b/prover/src/fri/mod.rs @@ -1,11 +1,64 @@ +use itertools::Itertools; +use lambdaworks_math::field::element::FieldElement; +use lambdaworks_math::field::fields::u64_prime_field::U64PrimeField; +use lambdaworks_math::polynomial::Polynomial; + +const ORDER: u64 = 23; +pub type F = U64PrimeField; +pub type FE = FieldElement; + +pub fn fold( + poly: &Polynomial>, + beta: &FieldElement, +) -> Polynomial> { + let coef = poly.coefficients(); + let even_coef: Vec> = coef + .iter() + .enumerate() + .filter(|(pos, _)| pos % 2 == 0) + .map(|(_pos, v)| *v) + .collect(); + + let odd_coef: Vec> = coef + .iter() + .enumerate() + .filter(|(pos, _)| pos % 2 == 1) + .map(|(_pos, v)| (*v) * beta) + .collect(); + + // agarro las componentes pares y le sumo beta * las componentes impares + println!("even: {even_coef:?}"); + println!("odd: {odd_coef:?}"); + + Polynomial::new(vec![FE::new(1), FE::new(2), FE::new(3)]) +} + pub fn hello() { + let p = Polynomial::new(vec![FE::new(1), FE::new(2), FE::new(3)]); + println!("Hello world"); + println!("{p:?}"); } #[cfg(test)] mod tests { + use lambdaworks_math::polynomial::Polynomial; + use super::FE; + #[test] fn test_hello() { super::hello(); } + + #[test] + fn test_fold() { + let p = Polynomial::new(vec![FE::new(1), FE::new(2), FE::new(3)]); + let beta = super::FieldElement::::new(21); + + let _ = super::fold( + &p, + &beta + ); + + } } From 49bb783b7e2106827754671756cc45953be42ae6 Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Mon, 13 Feb 2023 15:27:53 -0300 Subject: [PATCH 03/85] merge --- prover/src/fri/mod.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/prover/src/fri/mod.rs b/prover/src/fri/mod.rs index 24e4bcf67..978f13ca2 100644 --- a/prover/src/fri/mod.rs +++ b/prover/src/fri/mod.rs @@ -1,4 +1,3 @@ -use itertools::Itertools; use lambdaworks_math::field::element::FieldElement; use lambdaworks_math::field::fields::u64_prime_field::U64PrimeField; use lambdaworks_math::polynomial::Polynomial; @@ -30,11 +29,11 @@ pub fn fold( println!("even: {even_coef:?}"); println!("odd: {odd_coef:?}"); - Polynomial::new(vec![FE::new(1), FE::new(2), FE::new(3)]) + Polynomial::new(&[FE::new(1), FE::new(2), FE::new(3)]) } pub fn hello() { - let p = Polynomial::new(vec![FE::new(1), FE::new(2), FE::new(3)]); + let p = Polynomial::new(&[FE::new(1), FE::new(2), FE::new(3)]); println!("Hello world"); println!("{p:?}"); @@ -42,8 +41,8 @@ pub fn hello() { #[cfg(test)] mod tests { - use lambdaworks_math::polynomial::Polynomial; use super::FE; + use lambdaworks_math::polynomial::Polynomial; #[test] fn test_hello() { @@ -52,13 +51,9 @@ mod tests { #[test] fn test_fold() { - let p = Polynomial::new(vec![FE::new(1), FE::new(2), FE::new(3)]); + let p = Polynomial::new(&[FE::new(1), FE::new(2), FE::new(3)]); let beta = super::FieldElement::::new(21); - let _ = super::fold( - &p, - &beta - ); - + let _ = super::fold(&p, &beta); } } From 9e4a34507ef0319f986dd01da4247ad1ce197fcd Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Mon, 13 Feb 2023 15:46:34 -0300 Subject: [PATCH 04/85] test working --- prover/src/fri/mod.rs | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/prover/src/fri/mod.rs b/prover/src/fri/mod.rs index 978f13ca2..364f99151 100644 --- a/prover/src/fri/mod.rs +++ b/prover/src/fri/mod.rs @@ -2,7 +2,7 @@ use lambdaworks_math::field::element::FieldElement; use lambdaworks_math::field::fields::u64_prime_field::U64PrimeField; use lambdaworks_math::polynomial::Polynomial; -const ORDER: u64 = 23; +const ORDER: u64 = 101; pub type F = U64PrimeField; pub type FE = FieldElement; @@ -18,18 +18,20 @@ pub fn fold( .map(|(_pos, v)| *v) .collect(); - let odd_coef: Vec> = coef + // odd coeficients of poly are multiplied by beta + let odd_coef_mul_beta: Vec> = coef .iter() .enumerate() .filter(|(pos, _)| pos % 2 == 1) .map(|(_pos, v)| (*v) * beta) .collect(); - // agarro las componentes pares y le sumo beta * las componentes impares - println!("even: {even_coef:?}"); - println!("odd: {odd_coef:?}"); - - Polynomial::new(&[FE::new(1), FE::new(2), FE::new(3)]) + let (even_poly, odd_poly) = Polynomial::pad_with_zero_coefficients( + &Polynomial::new(&even_coef), + &Polynomial::new(&odd_coef_mul_beta), + ); + let ret = even_poly + odd_poly; + ret } pub fn hello() { @@ -51,9 +53,16 @@ mod tests { #[test] fn test_fold() { - let p = Polynomial::new(&[FE::new(1), FE::new(2), FE::new(3)]); - let beta = super::FieldElement::::new(21); - - let _ = super::fold(&p, &beta); + let p0 = Polynomial::new(&[ + FE::new(3), + FE::new(1), + FE::new(2), + FE::new(7), + FE::new(3), + FE::new(5), + ]); + let beta = super::FieldElement::::new(4); + let p1 = super::fold(&p0, &beta); + assert_eq!(p1, Polynomial::new(&[FE::new(7), FE::new(30), FE::new(23),])); } } From bd2b05f59e8d8235acd32ba5820e18dc4e723461 Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Mon, 13 Feb 2023 15:53:37 -0300 Subject: [PATCH 05/85] fold test completed --- prover/src/fri/mod.rs | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/prover/src/fri/mod.rs b/prover/src/fri/mod.rs index 364f99151..05645f984 100644 --- a/prover/src/fri/mod.rs +++ b/prover/src/fri/mod.rs @@ -2,7 +2,7 @@ use lambdaworks_math::field::element::FieldElement; use lambdaworks_math::field::fields::u64_prime_field::U64PrimeField; use lambdaworks_math::polynomial::Polynomial; -const ORDER: u64 = 101; +const ORDER: u64 = 293; pub type F = U64PrimeField; pub type FE = FieldElement; @@ -34,23 +34,11 @@ pub fn fold( ret } -pub fn hello() { - let p = Polynomial::new(&[FE::new(1), FE::new(2), FE::new(3)]); - - println!("Hello world"); - println!("{p:?}"); -} - #[cfg(test)] mod tests { - use super::FE; + use super::{fold, FieldElement, F, FE}; use lambdaworks_math::polynomial::Polynomial; - #[test] - fn test_hello() { - super::hello(); - } - #[test] fn test_fold() { let p0 = Polynomial::new(&[ @@ -61,8 +49,19 @@ mod tests { FE::new(3), FE::new(5), ]); - let beta = super::FieldElement::::new(4); - let p1 = super::fold(&p0, &beta); - assert_eq!(p1, Polynomial::new(&[FE::new(7), FE::new(30), FE::new(23),])); + let beta = FieldElement::::new(4); + let p1 = fold(&p0, &beta); + assert_eq!( + p1, + Polynomial::new(&[FE::new(7), FE::new(30), FE::new(23),]) + ); + + let gamma = FieldElement::::new(3); + let p2 = fold(&p1, &gamma); + assert_eq!(p2, Polynomial::new(&[FE::new(97), FE::new(23),])); + + let delta = FieldElement::::new(2); + let p3 = fold(&p2, &delta); + assert_eq!(p3, Polynomial::new(&[FE::new(143)])); } } From 855d4b39a47448c8ddbd6fa9c29ee83fd8fb4d53 Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Mon, 13 Feb 2023 16:45:10 -0300 Subject: [PATCH 06/85] next_fri_layer function --- prover/src/fri/mod.rs | 125 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 119 insertions(+), 6 deletions(-) diff --git a/prover/src/fri/mod.rs b/prover/src/fri/mod.rs index 05645f984..32fcfa4b6 100644 --- a/prover/src/fri/mod.rs +++ b/prover/src/fri/mod.rs @@ -6,7 +6,7 @@ const ORDER: u64 = 293; pub type F = U64PrimeField; pub type FE = FieldElement; -pub fn fold( +fn fold_polynomial( poly: &Polynomial>, beta: &FieldElement, ) -> Polynomial> { @@ -30,13 +30,45 @@ pub fn fold( &Polynomial::new(&even_coef), &Polynomial::new(&odd_coef_mul_beta), ); - let ret = even_poly + odd_poly; + even_poly + odd_poly +} + +fn next_domain(input: &[FE]) -> Vec { + let length = input.len() / 2; + let mut ret = Vec::with_capacity(length); + for v in input.iter().take(length) { + ret.push(v * v) + } ret } +fn next_layer(poly: &Polynomial>, domain: &[FE]) -> Vec { + let length = domain.len() / 2; + let mut ret = Vec::with_capacity(length); + for v in domain.iter() { + ret.push(poly.evaluate(v)); + } + ret +} + +/// Returns: +/// * new polynomoial folded with FRI protocol +/// * new domain +/// * evaluations of the polynomial +pub fn next_fri_layer( + poly: &Polynomial>, + domain: &[FE], + beta: &FieldElement, +) -> (Polynomial>, Vec, Vec) { + let ret_poly = fold_polynomial(poly, beta); + let ret_next_domain = next_domain(domain); + let ret_evaluation = next_layer(&ret_poly, &ret_next_domain); + (ret_poly, ret_next_domain, ret_evaluation) +} + #[cfg(test)] mod tests { - use super::{fold, FieldElement, F, FE}; + use super::{fold_polynomial, next_domain, next_fri_layer, next_layer, FieldElement, F, FE}; use lambdaworks_math::polynomial::Polynomial; #[test] @@ -50,18 +82,99 @@ mod tests { FE::new(5), ]); let beta = FieldElement::::new(4); - let p1 = fold(&p0, &beta); + let p1 = fold_polynomial(&p0, &beta); assert_eq!( p1, Polynomial::new(&[FE::new(7), FE::new(30), FE::new(23),]) ); let gamma = FieldElement::::new(3); - let p2 = fold(&p1, &gamma); + let p2 = fold_polynomial(&p1, &gamma); assert_eq!(p2, Polynomial::new(&[FE::new(97), FE::new(23),])); let delta = FieldElement::::new(2); - let p3 = fold(&p2, &delta); + let p3 = fold_polynomial(&p2, &delta); assert_eq!(p3, Polynomial::new(&[FE::new(143)])); + assert_eq!(p3.degree(), 0); + } + + #[test] + fn test_next_domain() { + let input = [ + FE::new(5), + FE::new(7), + FE::new(13), + FE::new(20), + FE::new(1), + FE::new(1), + FE::new(1), + FE::new(1), + ]; + let ret_next_domain = next_domain(&input); + assert_eq!( + ret_next_domain, + &[FE::new(25), FE::new(49), FE::new(169), FE::new(107),] + ); + + let ret_next_domain_2 = next_domain(&ret_next_domain); + assert_eq!(ret_next_domain_2, &[FE::new(39), FE::new(57)]); + + let ret_next_domain_3 = next_domain(&ret_next_domain_2); + assert_eq!(ret_next_domain_3, &[FE::new(56)]); + } + + #[test] + fn test_next_layer() { + let p0 = Polynomial::new(&[ + FE::new(3), + FE::new(1), + FE::new(2), + FE::new(7), + FE::new(3), + FE::new(5), + ]); + + let domain = [FE::new(5), FE::new(9)]; + let eval = next_layer(&p0, &domain); + + assert_eq!(eval, [FE::new(267), FE::new(249)]); + } + + #[test] + fn text_next_fri_layer() { + let p0 = Polynomial::new(&[ + FE::new(3), + FE::new(1), + FE::new(2), + FE::new(7), + FE::new(3), + FE::new(5), + ]); + let beta = FieldElement::::new(4); + let input_domain = [ + FE::new(5), + FE::new(7), + FE::new(13), + FE::new(20), + FE::new(1), + FE::new(1), + FE::new(1), + FE::new(1), + ]; + + let (p1, ret_next_domain, ret_evaluation) = next_fri_layer(&p0, &input_domain, &beta); + + assert_eq!( + p1, + Polynomial::new(&[FE::new(7), FE::new(30), FE::new(23),]) + ); + assert_eq!( + ret_next_domain, + &[FE::new(25), FE::new(49), FE::new(169), FE::new(107),] + ); + assert_eq!( + ret_evaluation, + &[FE::new(189), FE::new(151), FE::new(93), FE::new(207),] + ); } } From 0d022a87f047250b24c4f8996698bdb45c58faba Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Mon, 13 Feb 2023 17:52:18 -0300 Subject: [PATCH 07/85] Dependencies removed --- prover/Cargo.toml | 2 -- 1 file changed, 2 deletions(-) diff --git a/prover/Cargo.toml b/prover/Cargo.toml index f016da4b1..74681fc7d 100644 --- a/prover/Cargo.toml +++ b/prover/Cargo.toml @@ -9,5 +9,3 @@ edition = "2021" path = "../math" [dependencies] -rand = "0.8.5" -itertools = "0.10.5" From f18b90617aa7ae0bb1f1ac9002d9dfe91d6cf734 Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Tue, 14 Feb 2023 15:19:44 -0300 Subject: [PATCH 08/85] using iterator step_by --- prover/src/fri/mod.rs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/prover/src/fri/mod.rs b/prover/src/fri/mod.rs index 32fcfa4b6..5bad25bbf 100644 --- a/prover/src/fri/mod.rs +++ b/prover/src/fri/mod.rs @@ -11,19 +11,14 @@ fn fold_polynomial( beta: &FieldElement, ) -> Polynomial> { let coef = poly.coefficients(); - let even_coef: Vec> = coef - .iter() - .enumerate() - .filter(|(pos, _)| pos % 2 == 0) - .map(|(_pos, v)| *v) - .collect(); + let even_coef: Vec> = coef.iter().step_by(2).cloned().collect(); // odd coeficients of poly are multiplied by beta let odd_coef_mul_beta: Vec> = coef .iter() - .enumerate() - .filter(|(pos, _)| pos % 2 == 1) - .map(|(_pos, v)| (*v) * beta) + .skip(1) + .step_by(2) + .map(|v| (*v) * beta) .collect(); let (even_poly, odd_poly) = Polynomial::pad_with_zero_coefficients( From 97c117972968ae8faf85f37e94bf12150d5552d2 Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Tue, 14 Feb 2023 15:24:20 -0300 Subject: [PATCH 09/85] fmt --- prover/src/fri/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/prover/src/fri/mod.rs b/prover/src/fri/mod.rs index 5bad25bbf..76890a28d 100644 --- a/prover/src/fri/mod.rs +++ b/prover/src/fri/mod.rs @@ -1,5 +1,4 @@ -use lambdaworks_math::field::element::FieldElement; -use lambdaworks_math::field::fields::u64_prime_field::U64PrimeField; +use lambdaworks_math::field::{element::FieldElement, fields::u64_prime_field::U64PrimeField}; use lambdaworks_math::polynomial::Polynomial; const ORDER: u64 = 293; From b44022eb866d4ce868674310c2607b5847e68fc8 Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Tue, 14 Feb 2023 16:12:53 -0300 Subject: [PATCH 10/85] reordering fri functions --- prover/Cargo.toml | 3 + prover/src/fri/fri_commitment.rs | 25 ++++ prover/src/fri/fri_functions.rs | 166 +++++++++++++++++++++++ prover/src/fri/mod.rs | 220 +++++++++---------------------- 4 files changed, 258 insertions(+), 156 deletions(-) create mode 100644 prover/src/fri/fri_commitment.rs create mode 100644 prover/src/fri/fri_functions.rs diff --git a/prover/Cargo.toml b/prover/Cargo.toml index 74681fc7d..c08bf830a 100644 --- a/prover/Cargo.toml +++ b/prover/Cargo.toml @@ -8,4 +8,7 @@ edition = "2021" [dependencies.lambdaworks-math] path = "../math" +[dependencies.lambdaworks-crypto] +path = "../crypto" + [dependencies] diff --git a/prover/src/fri/fri_commitment.rs b/prover/src/fri/fri_commitment.rs new file mode 100644 index 000000000..6d3aa25ee --- /dev/null +++ b/prover/src/fri/fri_commitment.rs @@ -0,0 +1,25 @@ +pub use super::{Polynomial, F, FE}; +use lambdaworks_crypto::{hash::traits::IsCryptoHash, merkle_tree}; + +pub struct FriCommitment { + pub poly: Polynomial, + pub domain: Vec, + pub evaluation: Vec, + pub merkle_tree: String, // TODO! +} + +pub type FriCommitmentVec = Vec; + +// TODO!!!! +#[derive(Clone)] +struct TestHasher; + +impl IsCryptoHash for TestHasher { + fn hash_one(&self, input: FE) -> FE { + input + input + } + + fn hash_two(&self, left: FE, right: FE) -> FE { + left + right + } +} diff --git a/prover/src/fri/fri_functions.rs b/prover/src/fri/fri_functions.rs new file mode 100644 index 000000000..fdf2e98ee --- /dev/null +++ b/prover/src/fri/fri_functions.rs @@ -0,0 +1,166 @@ +use super::{Polynomial, FE}; + +fn fold_polynomial(poly: &Polynomial, beta: &FE) -> Polynomial { + let coef = poly.coefficients(); + let even_coef: Vec = coef.iter().step_by(2).cloned().collect(); + + // odd coeficients of poly are multiplied by beta + let odd_coef_mul_beta: Vec = coef + .iter() + .skip(1) + .step_by(2) + .map(|v| (*v) * beta) + .collect(); + + let (even_poly, odd_poly) = Polynomial::pad_with_zero_coefficients( + &Polynomial::new(&even_coef), + &Polynomial::new(&odd_coef_mul_beta), + ); + even_poly + odd_poly +} + +fn next_domain(input: &[FE]) -> Vec { + let length = input.len() / 2; + let mut ret = Vec::with_capacity(length); + for v in input.iter().take(length) { + ret.push(v * v) + } + ret +} + +fn next_layer(poly: &Polynomial, domain: &[FE]) -> Vec { + let length = domain.len() / 2; + let mut ret = Vec::with_capacity(length); + for v in domain.iter() { + ret.push(poly.evaluate(v)); + } + ret +} + +/// Returns: +/// * new polynomoial folded with FRI protocol +/// * new domain +/// * evaluations of the polynomial +pub fn next_fri_layer( + poly: &Polynomial, + domain: &[FE], + beta: &FE, +) -> (Polynomial, Vec, Vec) { + let ret_poly = fold_polynomial(poly, beta); + let ret_next_domain = next_domain(domain); + let ret_evaluation = next_layer(&ret_poly, &ret_next_domain); + (ret_poly, ret_next_domain, ret_evaluation) +} + +#[cfg(test)] +mod tests { + use super::{fold_polynomial, next_domain, next_fri_layer, next_layer, FE}; + use lambdaworks_math::polynomial::Polynomial; + + #[test] + fn test_fold() { + let p0 = Polynomial::new(&[ + FE::new(3), + FE::new(1), + FE::new(2), + FE::new(7), + FE::new(3), + FE::new(5), + ]); + let beta = FE::new(4); + let p1 = fold_polynomial(&p0, &beta); + assert_eq!( + p1, + Polynomial::new(&[FE::new(7), FE::new(30), FE::new(23),]) + ); + + let gamma = FE::new(3); + let p2 = fold_polynomial(&p1, &gamma); + assert_eq!(p2, Polynomial::new(&[FE::new(97), FE::new(23),])); + + let delta = FE::new(2); + let p3 = fold_polynomial(&p2, &delta); + assert_eq!(p3, Polynomial::new(&[FE::new(143)])); + assert_eq!(p3.degree(), 0); + } + + #[test] + fn test_next_domain() { + let input = [ + FE::new(5), + FE::new(7), + FE::new(13), + FE::new(20), + FE::new(1), + FE::new(1), + FE::new(1), + FE::new(1), + ]; + let ret_next_domain = next_domain(&input); + assert_eq!( + ret_next_domain, + &[FE::new(25), FE::new(49), FE::new(169), FE::new(107),] + ); + + let ret_next_domain_2 = next_domain(&ret_next_domain); + assert_eq!(ret_next_domain_2, &[FE::new(39), FE::new(57)]); + + let ret_next_domain_3 = next_domain(&ret_next_domain_2); + assert_eq!(ret_next_domain_3, &[FE::new(56)]); + } + + #[test] + fn test_next_layer() { + let p0 = Polynomial::new(&[ + FE::new(3), + FE::new(1), + FE::new(2), + FE::new(7), + FE::new(3), + FE::new(5), + ]); + + let domain = [FE::new(5), FE::new(9)]; + let eval = next_layer(&p0, &domain); + + assert_eq!(eval, [FE::new(267), FE::new(249)]); + } + + #[test] + fn text_next_fri_layer() { + let p0 = Polynomial::new(&[ + FE::new(3), + FE::new(1), + FE::new(2), + FE::new(7), + FE::new(3), + FE::new(5), + ]); + let beta = FE::new(4); + let input_domain = [ + FE::new(5), + FE::new(7), + FE::new(13), + FE::new(20), + FE::new(1), + FE::new(1), + FE::new(1), + FE::new(1), + ]; + + let (p1, ret_next_domain, ret_evaluation) = next_fri_layer(&p0, &input_domain, &beta); + + assert_eq!( + p1, + Polynomial::new(&[FE::new(7), FE::new(30), FE::new(23),]) + ); + assert_eq!( + ret_next_domain, + &[FE::new(25), FE::new(49), FE::new(169), FE::new(107),] + ); + assert_eq!( + ret_evaluation, + &[FE::new(189), FE::new(151), FE::new(93), FE::new(207),] + ); + } +} diff --git a/prover/src/fri/mod.rs b/prover/src/fri/mod.rs index 76890a28d..539a8531c 100644 --- a/prover/src/fri/mod.rs +++ b/prover/src/fri/mod.rs @@ -1,174 +1,82 @@ +mod fri_commitment; +mod fri_functions; + +use fri_commitment::{FriCommitment, FriCommitmentVec}; use lambdaworks_math::field::{element::FieldElement, fields::u64_prime_field::U64PrimeField}; -use lambdaworks_math::polynomial::Polynomial; +pub use lambdaworks_math::polynomial::Polynomial; const ORDER: u64 = 293; pub type F = U64PrimeField; pub type FE = FieldElement; -fn fold_polynomial( - poly: &Polynomial>, - beta: &FieldElement, -) -> Polynomial> { - let coef = poly.coefficients(); - let even_coef: Vec> = coef.iter().step_by(2).cloned().collect(); - - // odd coeficients of poly are multiplied by beta - let odd_coef_mul_beta: Vec> = coef - .iter() - .skip(1) - .step_by(2) - .map(|v| (*v) * beta) - .collect(); - - let (even_poly, odd_poly) = Polynomial::pad_with_zero_coefficients( - &Polynomial::new(&even_coef), - &Polynomial::new(&odd_coef_mul_beta), - ); - even_poly + odd_poly -} - -fn next_domain(input: &[FE]) -> Vec { - let length = input.len() / 2; - let mut ret = Vec::with_capacity(length); - for v in input.iter().take(length) { - ret.push(v * v) - } +/// # Params +/// +/// p_0, +/// original domain, +/// evaluation. +pub fn fri_commitment( + p_i: &Polynomial>, + domain_i: &[FE], + evaluation_i: &[FE], + // merkle_tree0: ... + // transcript +) -> FriCommitment { + // Merkle tree: + // - ret_evaluation + // - root + // - hasher + // Create a new merkle tree with ret_evaluation + + //let tree: merkle_tree::MerkleTree; + let ret = FriCommitment { + poly: p_i.clone(), + domain: Vec::new(), + evaluation: Vec::new(), + merkle_tree: String::new(), // TODO! + }; ret } -fn next_layer(poly: &Polynomial>, domain: &[FE]) -> Vec { - let length = domain.len() / 2; - let mut ret = Vec::with_capacity(length); - for v in domain.iter() { - ret.push(poly.evaluate(v)); - } - ret -} - -/// Returns: -/// * new polynomoial folded with FRI protocol -/// * new domain -/// * evaluations of the polynomial -pub fn next_fri_layer( - poly: &Polynomial>, - domain: &[FE], - beta: &FieldElement, -) -> (Polynomial>, Vec, Vec) { - let ret_poly = fold_polynomial(poly, beta); - let ret_next_domain = next_domain(domain); - let ret_evaluation = next_layer(&ret_poly, &ret_next_domain); - (ret_poly, ret_next_domain, ret_evaluation) -} - -#[cfg(test)] -mod tests { - use super::{fold_polynomial, next_domain, next_fri_layer, next_layer, FieldElement, F, FE}; - use lambdaworks_math::polynomial::Polynomial; - - #[test] - fn test_fold() { - let p0 = Polynomial::new(&[ - FE::new(3), - FE::new(1), - FE::new(2), - FE::new(7), - FE::new(3), - FE::new(5), - ]); - let beta = FieldElement::::new(4); - let p1 = fold_polynomial(&p0, &beta); - assert_eq!( - p1, - Polynomial::new(&[FE::new(7), FE::new(30), FE::new(23),]) +/* +pub fn fri(p0: &mut Polynomial>, domain_0: &[FE]) +-> FriCommitmentVec { + let fri_commitment_list = FriCommitmentVec::new(); + let commitment_0 = FriCommitment { + poly: p0.clone(), + domain: Vec::from(domain_0), + evaluation: Vec::new(), // calcular evaluation @@@@ + merkle_tree: String::new(), // TODO! + }; + // TODO@@@ append root of the merkle tree to the transcript + // first evaluation in the list + fri_commitment_list.push(commitment_0); + let mut degree = p0.degree(); + + while degree > 0 { + // sample beta: + // beta = transcript.challenge(); + + let (ret_poly, ret_next_domain, ret_evaluation) = + next_fri_layer( + poly: // last poly of the list + domain: // last domain of the list + beta: @@@@, ); - let gamma = FieldElement::::new(3); - let p2 = fold_polynomial(&p1, &gamma); - assert_eq!(p2, Polynomial::new(&[FE::new(97), FE::new(23),])); - - let delta = FieldElement::::new(2); - let p3 = fold_polynomial(&p2, &delta); - assert_eq!(p3, Polynomial::new(&[FE::new(143)])); - assert_eq!(p3.degree(), 0); - } - #[test] - fn test_next_domain() { - let input = [ - FE::new(5), - FE::new(7), - FE::new(13), - FE::new(20), - FE::new(1), - FE::new(1), - FE::new(1), - FE::new(1), - ]; - let ret_next_domain = next_domain(&input); - assert_eq!( + let commitment_i = fri_commitment( + ret_poly, ret_next_domain, - &[FE::new(25), FE::new(49), FE::new(169), FE::new(107),] + ret_evaluation, + // merkle_tree0: ... TODO!!! from evaluation ); - let ret_next_domain_2 = next_domain(&ret_next_domain); - assert_eq!(ret_next_domain_2, &[FE::new(39), FE::new(57)]); - - let ret_next_domain_3 = next_domain(&ret_next_domain_2); - assert_eq!(ret_next_domain_3, &[FE::new(56)]); - } - - #[test] - fn test_next_layer() { - let p0 = Polynomial::new(&[ - FE::new(3), - FE::new(1), - FE::new(2), - FE::new(7), - FE::new(3), - FE::new(5), - ]); - - let domain = [FE::new(5), FE::new(9)]; - let eval = next_layer(&p0, &domain); - - assert_eq!(eval, [FE::new(267), FE::new(249)]); - } - - #[test] - fn text_next_fri_layer() { - let p0 = Polynomial::new(&[ - FE::new(3), - FE::new(1), - FE::new(2), - FE::new(7), - FE::new(3), - FE::new(5), - ]); - let beta = FieldElement::::new(4); - let input_domain = [ - FE::new(5), - FE::new(7), - FE::new(13), - FE::new(20), - FE::new(1), - FE::new(1), - FE::new(1), - FE::new(1), - ]; - - let (p1, ret_next_domain, ret_evaluation) = next_fri_layer(&p0, &input_domain, &beta); + // TODO + // append root of merkle tree to transcript - assert_eq!( - p1, - Polynomial::new(&[FE::new(7), FE::new(30), FE::new(23),]) - ); - assert_eq!( - ret_next_domain, - &[FE::new(25), FE::new(49), FE::new(169), FE::new(107),] - ); - assert_eq!( - ret_evaluation, - &[FE::new(189), FE::new(151), FE::new(93), FE::new(207),] - ); + degree = commitment_i.poly.degree(); + fri_commitment_list.push(commitment_i); } + fri_commitment_list } +*/ From 35abba42cd09136111e69696bf3628720725a9cc Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Tue, 14 Feb 2023 17:06:46 -0300 Subject: [PATCH 11/85] fri_decommit init --- prover/src/fri/fri_decommit.rs | 1 + prover/src/fri/mod.rs | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 prover/src/fri/fri_decommit.rs diff --git a/prover/src/fri/fri_decommit.rs b/prover/src/fri/fri_decommit.rs new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/prover/src/fri/fri_decommit.rs @@ -0,0 +1 @@ + diff --git a/prover/src/fri/mod.rs b/prover/src/fri/mod.rs index 539a8531c..0b2bc7a12 100644 --- a/prover/src/fri/mod.rs +++ b/prover/src/fri/mod.rs @@ -1,4 +1,5 @@ mod fri_commitment; +mod fri_decommit; mod fri_functions; use fri_commitment::{FriCommitment, FriCommitmentVec}; @@ -71,12 +72,16 @@ pub fn fri(p0: &mut Polynomial>, domain_0: &[FE]) // merkle_tree0: ... TODO!!! from evaluation ); + degree = commitment_i.poly.degree(); + // TODO // append root of merkle tree to transcript - degree = commitment_i.poly.degree(); fri_commitment_list.push(commitment_i); } + + // append last value of the polynomial to the trasncript + fri_commitment_list } */ From 6b8f62c5327a523aed2a433ea1b296c6e9003533 Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Tue, 14 Feb 2023 17:09:20 -0300 Subject: [PATCH 12/85] evaluate_vec in polynomial and reference in evaluate --- math/src/polynomial.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/math/src/polynomial.rs b/math/src/polynomial.rs index 54cdd5988..91d185f1a 100644 --- a/math/src/polynomial.rs +++ b/math/src/polynomial.rs @@ -65,6 +65,10 @@ impl Polynomial> { input.iter().map(|x| self.evaluate(x)).collect() } + pub fn evaluate_vec(&self, input: &[FieldElement]) -> Vec> { + input.iter().map(|x| self.evaluate(x)).collect() + } + pub fn degree(&self) -> usize { if self.coefficients.is_empty() { 0 From a9bd07d0a0bc12d98efb57ecba410c4620930ccc Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Tue, 14 Feb 2023 17:25:37 -0300 Subject: [PATCH 13/85] using evaluate_vec --- prover/src/fri/fri_functions.rs | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/prover/src/fri/fri_functions.rs b/prover/src/fri/fri_functions.rs index fdf2e98ee..dde31b2a0 100644 --- a/prover/src/fri/fri_functions.rs +++ b/prover/src/fri/fri_functions.rs @@ -28,15 +28,6 @@ fn next_domain(input: &[FE]) -> Vec { ret } -fn next_layer(poly: &Polynomial, domain: &[FE]) -> Vec { - let length = domain.len() / 2; - let mut ret = Vec::with_capacity(length); - for v in domain.iter() { - ret.push(poly.evaluate(v)); - } - ret -} - /// Returns: /// * new polynomoial folded with FRI protocol /// * new domain @@ -48,13 +39,13 @@ pub fn next_fri_layer( ) -> (Polynomial, Vec, Vec) { let ret_poly = fold_polynomial(poly, beta); let ret_next_domain = next_domain(domain); - let ret_evaluation = next_layer(&ret_poly, &ret_next_domain); + let ret_evaluation = ret_poly.evaluate_vec(&ret_next_domain); (ret_poly, ret_next_domain, ret_evaluation) } #[cfg(test)] mod tests { - use super::{fold_polynomial, next_domain, next_fri_layer, next_layer, FE}; + use super::{fold_polynomial, next_domain, next_fri_layer, FE}; use lambdaworks_math::polynomial::Polynomial; #[test] @@ -109,23 +100,6 @@ mod tests { assert_eq!(ret_next_domain_3, &[FE::new(56)]); } - #[test] - fn test_next_layer() { - let p0 = Polynomial::new(&[ - FE::new(3), - FE::new(1), - FE::new(2), - FE::new(7), - FE::new(3), - FE::new(5), - ]); - - let domain = [FE::new(5), FE::new(9)]; - let eval = next_layer(&p0, &domain); - - assert_eq!(eval, [FE::new(267), FE::new(249)]); - } - #[test] fn text_next_fri_layer() { let p0 = Polynomial::new(&[ From cff637a604db13088be98043830cb9a04b766b74 Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Tue, 14 Feb 2023 18:18:08 -0300 Subject: [PATCH 14/85] evaluate_vec changed to evaluate_slice --- math/src/polynomial.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/math/src/polynomial.rs b/math/src/polynomial.rs index 91d185f1a..3217eb65a 100644 --- a/math/src/polynomial.rs +++ b/math/src/polynomial.rs @@ -65,7 +65,7 @@ impl Polynomial> { input.iter().map(|x| self.evaluate(x)).collect() } - pub fn evaluate_vec(&self, input: &[FieldElement]) -> Vec> { + pub fn evaluate_slice(&self, input: &[FieldElement]) -> Vec> { input.iter().map(|x| self.evaluate(x)).collect() } From 5a8e33647f032e9b3a4778d46d12920beaaf1e20 Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Tue, 14 Feb 2023 18:19:56 -0300 Subject: [PATCH 15/85] evaluate_slice changed --- prover/src/fri/fri_functions.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prover/src/fri/fri_functions.rs b/prover/src/fri/fri_functions.rs index dde31b2a0..7640a47af 100644 --- a/prover/src/fri/fri_functions.rs +++ b/prover/src/fri/fri_functions.rs @@ -39,7 +39,7 @@ pub fn next_fri_layer( ) -> (Polynomial, Vec, Vec) { let ret_poly = fold_polynomial(poly, beta); let ret_next_domain = next_domain(domain); - let ret_evaluation = ret_poly.evaluate_vec(&ret_next_domain); + let ret_evaluation = ret_poly.evaluate_slice(&ret_next_domain); (ret_poly, ret_next_domain, ret_evaluation) } From 8036639e0d23d1de48122ba65685df884d55be02 Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Tue, 14 Feb 2023 19:30:26 -0300 Subject: [PATCH 16/85] fri_commitment --- crypto/src/fiat_shamir/mod.rs | 2 +- crypto/src/fiat_shamir/transcript.rs | 6 +++--- crypto/src/merkle_tree/mod.rs | 8 +++---- prover/src/fri/fri_commitment.rs | 23 +++++---------------- prover/src/fri/fri_merkle_tree.rs | 31 ++++++++++++++++++++++++++++ prover/src/fri/mod.rs | 29 +++++++++++++++----------- 6 files changed, 61 insertions(+), 38 deletions(-) create mode 100644 prover/src/fri/fri_merkle_tree.rs diff --git a/crypto/src/fiat_shamir/mod.rs b/crypto/src/fiat_shamir/mod.rs index e24a46384..ece16b1ef 100644 --- a/crypto/src/fiat_shamir/mod.rs +++ b/crypto/src/fiat_shamir/mod.rs @@ -1 +1 @@ -mod transcript; +pub mod transcript; diff --git a/crypto/src/fiat_shamir/transcript.rs b/crypto/src/fiat_shamir/transcript.rs index 7d1d38d62..51bbfca67 100644 --- a/crypto/src/fiat_shamir/transcript.rs +++ b/crypto/src/fiat_shamir/transcript.rs @@ -1,6 +1,6 @@ use sha3::{Digest, Sha3_256}; -struct Transcript { +pub struct Transcript { hasher: Sha3_256, } @@ -13,12 +13,12 @@ impl Transcript { } #[allow(unused)] - fn append(&mut self, new_data: &[u8]) { + pub fn append(&mut self, new_data: &[u8]) { self.hasher.update(&mut new_data.to_owned()); } #[allow(unused)] - fn challenge(&mut self) -> [u8; 32] { + pub fn challenge(&mut self) -> [u8; 32] { let mut result_hash = [0_u8; 32]; result_hash.copy_from_slice(&self.hasher.finalize_reset()); self.hasher.update(result_hash); diff --git a/crypto/src/merkle_tree/mod.rs b/crypto/src/merkle_tree/mod.rs index a856b7299..d1703dd9e 100644 --- a/crypto/src/merkle_tree/mod.rs +++ b/crypto/src/merkle_tree/mod.rs @@ -7,7 +7,7 @@ use std::{cell::RefCell, rc::Rc}; pub struct MerkleTree> { leafs: Vec>, - root: TreeNode, + pub root: TreeNode, hasher: H, } @@ -165,7 +165,7 @@ pub struct Proof> { hasher: H, } -type TreeNode = Rc>>; +pub type TreeNode = Rc>>; fn build_tree_node(hash: FieldElement) -> TreeNode { Rc::new(RefCell::new(Node { @@ -176,8 +176,8 @@ fn build_tree_node(hash: FieldElement) -> TreeNode { } #[derive(Clone, Debug, PartialEq)] -struct Node { - hash: FieldElement, +pub struct Node { + pub hash: FieldElement, parent: Option>, sibiling: Option>, } diff --git a/prover/src/fri/fri_commitment.rs b/prover/src/fri/fri_commitment.rs index 6d3aa25ee..1f9c0f17d 100644 --- a/prover/src/fri/fri_commitment.rs +++ b/prover/src/fri/fri_commitment.rs @@ -1,25 +1,12 @@ pub use super::{Polynomial, F, FE}; -use lambdaworks_crypto::{hash::traits::IsCryptoHash, merkle_tree}; +use lambdaworks_crypto::{hash::traits::IsCryptoHash, merkle_tree::MerkleTree}; +use lambdaworks_math::field::traits::IsField; -pub struct FriCommitment { +pub struct FriCommitment> { pub poly: Polynomial, pub domain: Vec, pub evaluation: Vec, - pub merkle_tree: String, // TODO! + pub merkle_tree: MerkleTree, // TODO! } -pub type FriCommitmentVec = Vec; - -// TODO!!!! -#[derive(Clone)] -struct TestHasher; - -impl IsCryptoHash for TestHasher { - fn hash_one(&self, input: FE) -> FE { - input + input - } - - fn hash_two(&self, left: FE, right: FE) -> FE { - left + right - } -} +pub type FriCommitmentVec = Vec>; diff --git a/prover/src/fri/fri_merkle_tree.rs b/prover/src/fri/fri_merkle_tree.rs new file mode 100644 index 000000000..5f47e3d31 --- /dev/null +++ b/prover/src/fri/fri_merkle_tree.rs @@ -0,0 +1,31 @@ +pub use super::{Polynomial, F, FE}; +use lambdaworks_crypto::hash::traits::IsCryptoHash; + +// TODO!!!! +#[derive(Clone)] +pub struct FriTestHasher; + +impl IsCryptoHash for FriTestHasher { + fn hash_one(&self, input: FE) -> FE { + input + input + } + + fn hash_two(&self, left: FE, right: FE) -> FE { + left + right + } +} + +#[cfg(test)] +mod tests { + use super::{FriTestHasher, FE}; + use lambdaworks_crypto::merkle_tree::MerkleTree; + + #[test] + fn build_merkle_tree_from_an_even_set_of_leafs() { + let merkle_tree = MerkleTree::build( + &[FE::new(1), FE::new(2), FE::new(3), FE::new(4)], + FriTestHasher, + ); + assert_eq!(merkle_tree.root.borrow().hash, FE::new(20)); + } +} diff --git a/prover/src/fri/mod.rs b/prover/src/fri/mod.rs index 0b2bc7a12..5b9458780 100644 --- a/prover/src/fri/mod.rs +++ b/prover/src/fri/mod.rs @@ -1,8 +1,12 @@ mod fri_commitment; mod fri_decommit; mod fri_functions; +mod fri_merkle_tree; -use fri_commitment::{FriCommitment, FriCommitmentVec}; +use crate::fri::fri_merkle_tree::FriTestHasher; +use fri_commitment::FriCommitment; //, FriCommitmentVec}; +pub use lambdaworks_crypto::fiat_shamir::transcript::Transcript; +use lambdaworks_crypto::merkle_tree::MerkleTree; use lambdaworks_math::field::{element::FieldElement, fields::u64_prime_field::U64PrimeField}; pub use lambdaworks_math::polynomial::Polynomial; @@ -19,23 +23,24 @@ pub fn fri_commitment( p_i: &Polynomial>, domain_i: &[FE], evaluation_i: &[FE], - // merkle_tree0: ... - // transcript -) -> FriCommitment { + transcript: &mut Transcript, +) -> FriCommitment { // Merkle tree: // - ret_evaluation // - root // - hasher - // Create a new merkle tree with ret_evaluation + // Create a new merkle tree with evaluation_i + let merkle_tree = MerkleTree::build(&evaluation_i, FriTestHasher); + let root = merkle_tree.root.borrow().hash; + // TODO @@@ let bytes = root.as_bytes(); + //transcript.append(bytes); - //let tree: merkle_tree::MerkleTree; - let ret = FriCommitment { + FriCommitment { poly: p_i.clone(), - domain: Vec::new(), - evaluation: Vec::new(), - merkle_tree: String::new(), // TODO! - }; - ret + domain: domain_i.to_vec(), + evaluation: evaluation_i.to_vec(), + merkle_tree, + } } /* From 57d19fcbc8ef2226f8d7a43dd50b661de819ef50 Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Tue, 14 Feb 2023 20:10:39 -0300 Subject: [PATCH 17/85] fri continuation --- crypto/src/fiat_shamir/transcript.rs | 2 +- prover/src/fri/fri_commitment.rs | 2 +- prover/src/fri/mod.rs | 63 +++++++++++++++------------- 3 files changed, 36 insertions(+), 31 deletions(-) diff --git a/crypto/src/fiat_shamir/transcript.rs b/crypto/src/fiat_shamir/transcript.rs index 51bbfca67..840a5152e 100644 --- a/crypto/src/fiat_shamir/transcript.rs +++ b/crypto/src/fiat_shamir/transcript.rs @@ -6,7 +6,7 @@ pub struct Transcript { impl Transcript { #[allow(unused)] - fn new() -> Self { + pub fn new() -> Self { Self { hasher: Sha3_256::new(), } diff --git a/prover/src/fri/fri_commitment.rs b/prover/src/fri/fri_commitment.rs index 1f9c0f17d..7953e29c3 100644 --- a/prover/src/fri/fri_commitment.rs +++ b/prover/src/fri/fri_commitment.rs @@ -6,7 +6,7 @@ pub struct FriCommitment> { pub poly: Polynomial, pub domain: Vec, pub evaluation: Vec, - pub merkle_tree: MerkleTree, // TODO! + pub merkle_tree: MerkleTree, } pub type FriCommitmentVec = Vec>; diff --git a/prover/src/fri/mod.rs b/prover/src/fri/mod.rs index 5b9458780..0721f1f53 100644 --- a/prover/src/fri/mod.rs +++ b/prover/src/fri/mod.rs @@ -3,6 +3,8 @@ mod fri_decommit; mod fri_functions; mod fri_merkle_tree; +use crate::fri::fri_commitment::FriCommitmentVec; +use crate::fri::fri_functions::next_fri_layer; use crate::fri::fri_merkle_tree::FriTestHasher; use fri_commitment::FriCommitment; //, FriCommitmentVec}; pub use lambdaworks_crypto::fiat_shamir::transcript::Transcript; @@ -43,50 +45,53 @@ pub fn fri_commitment( } } -/* -pub fn fri(p0: &mut Polynomial>, domain_0: &[FE]) --> FriCommitmentVec { - let fri_commitment_list = FriCommitmentVec::new(); +pub fn fri( + p_0: &mut Polynomial>, + domain_0: &[FE], +) -> FriCommitmentVec { + let mut fri_commitment_list = FriCommitmentVec::new(); + let mut transcript = Transcript::new(); + + let evaluation_0 = p_0.evaluate_slice(domain_0); + let merkle_tree = MerkleTree::build(&evaluation_0, FriTestHasher); let commitment_0 = FriCommitment { - poly: p0.clone(), - domain: Vec::from(domain_0), - evaluation: Vec::new(), // calcular evaluation @@@@ - merkle_tree: String::new(), // TODO! + poly: p_0.clone(), + domain: domain_0.to_vec(), + evaluation: evaluation_0.to_vec(), + merkle_tree, }; - // TODO@@@ append root of the merkle tree to the transcript + + // last poly of the list + let mut last_poly: Polynomial = p_0.clone(); + // last domain of the list + let mut last_domain: Vec = domain_0.to_vec(); + // first evaluation in the list fri_commitment_list.push(commitment_0); - let mut degree = p0.degree(); + let mut degree = p_0.degree(); + + // TODO@@@ append root of the merkle tree to the transcript while degree > 0 { // sample beta: - // beta = transcript.challenge(); + // TODO! let beta = transcript.challenge(); + let beta = FE::new(5); - let (ret_poly, ret_next_domain, ret_evaluation) = - next_fri_layer( - poly: // last poly of the list - domain: // last domain of the list - beta: @@@@, - ); + let (p_i, domain_i, evaluation_i) = next_fri_layer(&last_poly, &last_domain, &beta); + let commitment_i = fri_commitment(&p_i, &domain_i, &evaluation_i, &mut transcript); - let commitment_i = fri_commitment( - ret_poly, - ret_next_domain, - ret_evaluation, - // merkle_tree0: ... TODO!!! from evaluation - ); + fri_commitment_list.push(commitment_i); + degree = p_i.degree(); - degree = commitment_i.poly.degree(); + last_poly = p_i.clone(); + last_domain = domain_i.clone(); // TODO // append root of merkle tree to transcript - fri_commitment_list.push(commitment_i); + // TODO + // append last value of the polynomial to the trasncript } - - // append last value of the polynomial to the trasncript - fri_commitment_list } -*/ From a20785300c091071f134d2e5fac63fca084e9000 Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Wed, 15 Feb 2023 12:23:53 -0300 Subject: [PATCH 18/85] comment moved --- prover/src/fri/mod.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/prover/src/fri/mod.rs b/prover/src/fri/mod.rs index 0721f1f53..0346b1c7b 100644 --- a/prover/src/fri/mod.rs +++ b/prover/src/fri/mod.rs @@ -89,9 +89,10 @@ pub fn fri( // TODO // append root of merkle tree to transcript - - // TODO - // append last value of the polynomial to the trasncript } + + // TODO + // append last value of the polynomial to the trasncript + fri_commitment_list } From 85ecd778bf33fb250a46c60a84ea724da8ccb7f3 Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Wed, 15 Feb 2023 19:16:19 -0300 Subject: [PATCH 19/85] fri_decommit_layers --- crypto/src/merkle_tree/mod.rs | 2 +- math/src/polynomial.rs | 2 +- prover/src/fri/fri_decommit.rs | 37 ++++++++++++++++++++++++++++++++++ prover/src/fri/mod.rs | 3 +-- 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/crypto/src/merkle_tree/mod.rs b/crypto/src/merkle_tree/mod.rs index d1703dd9e..8212a6daf 100644 --- a/crypto/src/merkle_tree/mod.rs +++ b/crypto/src/merkle_tree/mod.rs @@ -6,7 +6,7 @@ use lambdaworks_math::{ use std::{cell::RefCell, rc::Rc}; pub struct MerkleTree> { - leafs: Vec>, + pub leafs: Vec>, pub root: TreeNode, hasher: H, } diff --git a/math/src/polynomial.rs b/math/src/polynomial.rs index 3217eb65a..1a9ea7c3c 100644 --- a/math/src/polynomial.rs +++ b/math/src/polynomial.rs @@ -6,7 +6,7 @@ use std::ops; /// as a vector of coefficients `[c_0, c_1, ... , c_n]` #[derive(Debug, Clone, PartialEq, Eq)] pub struct Polynomial { - coefficients: Vec, + pub coefficients: Vec, } impl Polynomial> { diff --git a/prover/src/fri/fri_decommit.rs b/prover/src/fri/fri_decommit.rs index 8b1378917..a396fe659 100644 --- a/prover/src/fri/fri_decommit.rs +++ b/prover/src/fri/fri_decommit.rs @@ -1 +1,38 @@ +use super::F; +use crate::fri::fri_commitment::FriCommitmentVec; +use crate::fri::fri_merkle_tree::FriTestHasher; +pub use lambdaworks_crypto::fiat_shamir::transcript::Transcript; + +// verifier chooses a randomness and get the index where +// they want to evaluate the poly +pub fn fri_decommit_layers( + commit: &FriCommitmentVec, + index_to_verify: usize, + transcript: &mut Transcript, +) { + let mut index = index_to_verify; + // de cada componente del commit, voy al merkle tree y + // me quedo con el elemento que corresponde + for commit_i in commit { + let length_i = commit_i.domain.len(); + index = index % length_i; + let evaluation_i = commit_i.evaluation[index]; + let auth_path = commit_i.merkle_tree.get_proof(evaluation_i).unwrap(); + + // symmetrical element + let index_sym = (index + length_i / 2) % length_i; + let evaluation_i_sym = commit_i.evaluation[index_sym]; + let auth_path_sym = commit_i.merkle_tree.get_proof(evaluation_i_sym).unwrap(); + + // @@@ TODO! insert in transcript + } + + // send the last element of the polynomial + let last = commit.last().unwrap(); + let last_evaluation = last.poly.coefficients[0]; + + // @@@ TODO insert last_evaluation in transcript + + +} diff --git a/prover/src/fri/mod.rs b/prover/src/fri/mod.rs index 0346b1c7b..771f59b8f 100644 --- a/prover/src/fri/mod.rs +++ b/prover/src/fri/mod.rs @@ -3,10 +3,9 @@ mod fri_decommit; mod fri_functions; mod fri_merkle_tree; -use crate::fri::fri_commitment::FriCommitmentVec; +use crate::fri::fri_commitment::{FriCommitment, FriCommitmentVec}; use crate::fri::fri_functions::next_fri_layer; use crate::fri::fri_merkle_tree::FriTestHasher; -use fri_commitment::FriCommitment; //, FriCommitmentVec}; pub use lambdaworks_crypto::fiat_shamir::transcript::Transcript; use lambdaworks_crypto::merkle_tree::MerkleTree; use lambdaworks_math::field::{element::FieldElement, fields::u64_prime_field::U64PrimeField}; From cf2a09b6972eb9bf28a13d73faa45629f204a4c6 Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Thu, 16 Feb 2023 11:49:38 -0300 Subject: [PATCH 20/85] comments added --- prover/src/fri/fri_decommit.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/prover/src/fri/fri_decommit.rs b/prover/src/fri/fri_decommit.rs index a396fe659..f92e03e33 100644 --- a/prover/src/fri/fri_decommit.rs +++ b/prover/src/fri/fri_decommit.rs @@ -11,8 +11,9 @@ pub fn fri_decommit_layers( transcript: &mut Transcript, ) { let mut index = index_to_verify; - // de cada componente del commit, voy al merkle tree y - // me quedo con el elemento que corresponde + + // with every element of the commit, we look for that one in + // the merkle tree and get the corresponding element for commit_i in commit { let length_i = commit_i.domain.len(); index = index % length_i; @@ -36,3 +37,12 @@ pub fn fri_decommit_layers( } +// Integration test: +// * get an arbitrary polynomial +// * have a domain containing roots of the unity (# is power of two) +// p = 65_537 +// * apply FRI commitment +// * apply FRI decommitment +// assert: +// * evaluations of the polynomials coincide with calculations from the decommitment +// * show a fail example: with a monomial From 688a8c9226783ed3c525b8d551dfd4b2d466c330 Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Thu, 16 Feb 2023 11:56:30 -0300 Subject: [PATCH 21/85] polynomial.rs merge confilct --- math/src/polynomial.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/math/src/polynomial.rs b/math/src/polynomial.rs index 1a9ea7c3c..aaf3856c3 100644 --- a/math/src/polynomial.rs +++ b/math/src/polynomial.rs @@ -65,10 +65,6 @@ impl Polynomial> { input.iter().map(|x| self.evaluate(x)).collect() } - pub fn evaluate_slice(&self, input: &[FieldElement]) -> Vec> { - input.iter().map(|x| self.evaluate(x)).collect() - } - pub fn degree(&self) -> usize { if self.coefficients.is_empty() { 0 From e1514492da5c119704b4328b9b9051fd3299ab8f Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Thu, 16 Feb 2023 12:07:35 -0300 Subject: [PATCH 22/85] adapting to the new code --- crypto/src/merkle_tree/mod.rs | 2 +- prover/src/fri/fri_decommit.rs | 3 --- prover/src/fri/fri_merkle_tree.rs | 22 ++++------------------ prover/src/fri/mod.rs | 16 ++++++++++------ 4 files changed, 15 insertions(+), 28 deletions(-) diff --git a/crypto/src/merkle_tree/mod.rs b/crypto/src/merkle_tree/mod.rs index 8212a6daf..8476debbb 100644 --- a/crypto/src/merkle_tree/mod.rs +++ b/crypto/src/merkle_tree/mod.rs @@ -11,7 +11,7 @@ pub struct MerkleTree> { hasher: H, } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct DefaultHasher; impl IsCryptoHash for DefaultHasher { diff --git a/prover/src/fri/fri_decommit.rs b/prover/src/fri/fri_decommit.rs index f92e03e33..b5c1533ce 100644 --- a/prover/src/fri/fri_decommit.rs +++ b/prover/src/fri/fri_decommit.rs @@ -1,6 +1,5 @@ use super::F; use crate::fri::fri_commitment::FriCommitmentVec; -use crate::fri::fri_merkle_tree::FriTestHasher; pub use lambdaworks_crypto::fiat_shamir::transcript::Transcript; // verifier chooses a randomness and get the index where @@ -33,8 +32,6 @@ pub fn fri_decommit_layers( let last_evaluation = last.poly.coefficients[0]; // @@@ TODO insert last_evaluation in transcript - - } // Integration test: diff --git a/prover/src/fri/fri_merkle_tree.rs b/prover/src/fri/fri_merkle_tree.rs index 5f47e3d31..b25598ce6 100644 --- a/prover/src/fri/fri_merkle_tree.rs +++ b/prover/src/fri/fri_merkle_tree.rs @@ -1,30 +1,16 @@ pub use super::{Polynomial, F, FE}; -use lambdaworks_crypto::hash::traits::IsCryptoHash; +pub use lambdaworks_crypto::merkle_tree::{MerkleTree, DefaultHasher}; -// TODO!!!! -#[derive(Clone)] -pub struct FriTestHasher; - -impl IsCryptoHash for FriTestHasher { - fn hash_one(&self, input: FE) -> FE { - input + input - } - - fn hash_two(&self, left: FE, right: FE) -> FE { - left + right - } -} +pub type MerkleTreeDefault = MerkleTree; #[cfg(test)] mod tests { - use super::{FriTestHasher, FE}; - use lambdaworks_crypto::merkle_tree::MerkleTree; + use super::{FE, MerkleTreeDefault}; #[test] fn build_merkle_tree_from_an_even_set_of_leafs() { - let merkle_tree = MerkleTree::build( + let merkle_tree = MerkleTreeDefault::build( &[FE::new(1), FE::new(2), FE::new(3), FE::new(4)], - FriTestHasher, ); assert_eq!(merkle_tree.root.borrow().hash, FE::new(20)); } diff --git a/prover/src/fri/mod.rs b/prover/src/fri/mod.rs index 771f59b8f..a9c5400f5 100644 --- a/prover/src/fri/mod.rs +++ b/prover/src/fri/mod.rs @@ -1,20 +1,23 @@ mod fri_commitment; -mod fri_decommit; +//mod fri_decommit; mod fri_functions; mod fri_merkle_tree; use crate::fri::fri_commitment::{FriCommitment, FriCommitmentVec}; use crate::fri::fri_functions::next_fri_layer; -use crate::fri::fri_merkle_tree::FriTestHasher; -pub use lambdaworks_crypto::fiat_shamir::transcript::Transcript; -use lambdaworks_crypto::merkle_tree::MerkleTree; -use lambdaworks_math::field::{element::FieldElement, fields::u64_prime_field::U64PrimeField}; -pub use lambdaworks_math::polynomial::Polynomial; +pub use lambdaworks_crypto::{fiat_shamir::transcript::Transcript, merkle_tree::MerkleTree}; +pub use lambdaworks_math::{ + field::{element::FieldElement, fields::u64_prime_field::U64PrimeField}, + polynomial::Polynomial, +}; const ORDER: u64 = 293; pub type F = U64PrimeField; pub type FE = FieldElement; + +/* + /// # Params /// /// p_0, @@ -95,3 +98,4 @@ pub fn fri( fri_commitment_list } +*/ From f15af6b0b5c462912976e8eaaa274a6797edef7b Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Thu, 16 Feb 2023 12:13:38 -0300 Subject: [PATCH 23/85] conflicts solved --- prover/src/fri/fri_commitment.rs | 10 ++++------ prover/src/fri/fri_decommit.rs | 4 ++-- prover/src/fri/fri_merkle_tree.rs | 10 ++++------ prover/src/fri/mod.rs | 18 ++++++------------ 4 files changed, 16 insertions(+), 26 deletions(-) diff --git a/prover/src/fri/fri_commitment.rs b/prover/src/fri/fri_commitment.rs index 7953e29c3..ceaf56b52 100644 --- a/prover/src/fri/fri_commitment.rs +++ b/prover/src/fri/fri_commitment.rs @@ -1,12 +1,10 @@ -pub use super::{Polynomial, F, FE}; -use lambdaworks_crypto::{hash::traits::IsCryptoHash, merkle_tree::MerkleTree}; -use lambdaworks_math::field::traits::IsField; +pub use super::{FriMerkleTree, Polynomial, F, FE}; -pub struct FriCommitment> { +pub struct FriCommitment { pub poly: Polynomial, pub domain: Vec, pub evaluation: Vec, - pub merkle_tree: MerkleTree, + pub merkle_tree: FriMerkleTree, } -pub type FriCommitmentVec = Vec>; +pub type FriCommitmentVec = Vec>; diff --git a/prover/src/fri/fri_decommit.rs b/prover/src/fri/fri_decommit.rs index b5c1533ce..5907db323 100644 --- a/prover/src/fri/fri_decommit.rs +++ b/prover/src/fri/fri_decommit.rs @@ -1,11 +1,11 @@ -use super::F; +use super::FE; use crate::fri::fri_commitment::FriCommitmentVec; pub use lambdaworks_crypto::fiat_shamir::transcript::Transcript; // verifier chooses a randomness and get the index where // they want to evaluate the poly pub fn fri_decommit_layers( - commit: &FriCommitmentVec, + commit: &FriCommitmentVec, index_to_verify: usize, transcript: &mut Transcript, ) { diff --git a/prover/src/fri/fri_merkle_tree.rs b/prover/src/fri/fri_merkle_tree.rs index b25598ce6..0fba35b25 100644 --- a/prover/src/fri/fri_merkle_tree.rs +++ b/prover/src/fri/fri_merkle_tree.rs @@ -1,17 +1,15 @@ pub use super::{Polynomial, F, FE}; -pub use lambdaworks_crypto::merkle_tree::{MerkleTree, DefaultHasher}; +pub use lambdaworks_crypto::merkle_tree::{DefaultHasher, MerkleTree}; -pub type MerkleTreeDefault = MerkleTree; +pub type FriMerkleTree = MerkleTree; #[cfg(test)] mod tests { - use super::{FE, MerkleTreeDefault}; + use super::{FriMerkleTree, FE}; #[test] fn build_merkle_tree_from_an_even_set_of_leafs() { - let merkle_tree = MerkleTreeDefault::build( - &[FE::new(1), FE::new(2), FE::new(3), FE::new(4)], - ); + let merkle_tree = FriMerkleTree::build(&[FE::new(1), FE::new(2), FE::new(3), FE::new(4)]); assert_eq!(merkle_tree.root.borrow().hash, FE::new(20)); } } diff --git a/prover/src/fri/mod.rs b/prover/src/fri/mod.rs index a9c5400f5..34e7cce3d 100644 --- a/prover/src/fri/mod.rs +++ b/prover/src/fri/mod.rs @@ -1,10 +1,11 @@ mod fri_commitment; -//mod fri_decommit; +mod fri_decommit; mod fri_functions; mod fri_merkle_tree; use crate::fri::fri_commitment::{FriCommitment, FriCommitmentVec}; use crate::fri::fri_functions::next_fri_layer; +pub use crate::fri::fri_merkle_tree::FriMerkleTree; pub use lambdaworks_crypto::{fiat_shamir::transcript::Transcript, merkle_tree::MerkleTree}; pub use lambdaworks_math::{ field::{element::FieldElement, fields::u64_prime_field::U64PrimeField}, @@ -15,9 +16,6 @@ const ORDER: u64 = 293; pub type F = U64PrimeField; pub type FE = FieldElement; - -/* - /// # Params /// /// p_0, @@ -28,13 +26,13 @@ pub fn fri_commitment( domain_i: &[FE], evaluation_i: &[FE], transcript: &mut Transcript, -) -> FriCommitment { +) -> FriCommitment { // Merkle tree: // - ret_evaluation // - root // - hasher // Create a new merkle tree with evaluation_i - let merkle_tree = MerkleTree::build(&evaluation_i, FriTestHasher); + let merkle_tree = FriMerkleTree::build(&evaluation_i); let root = merkle_tree.root.borrow().hash; // TODO @@@ let bytes = root.as_bytes(); //transcript.append(bytes); @@ -47,15 +45,12 @@ pub fn fri_commitment( } } -pub fn fri( - p_0: &mut Polynomial>, - domain_0: &[FE], -) -> FriCommitmentVec { +pub fn fri(p_0: &mut Polynomial>, domain_0: &[FE]) -> FriCommitmentVec { let mut fri_commitment_list = FriCommitmentVec::new(); let mut transcript = Transcript::new(); let evaluation_0 = p_0.evaluate_slice(domain_0); - let merkle_tree = MerkleTree::build(&evaluation_0, FriTestHasher); + let merkle_tree = FriMerkleTree::build(&evaluation_0); let commitment_0 = FriCommitment { poly: p_0.clone(), domain: domain_0.to_vec(), @@ -98,4 +93,3 @@ pub fn fri( fri_commitment_list } -*/ From 9068b27ff0f3a29a06daed302a32eb5565a4c82b Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Thu, 16 Feb 2023 12:59:41 -0300 Subject: [PATCH 24/85] append in transcript --- prover/src/fri/mod.rs | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/prover/src/fri/mod.rs b/prover/src/fri/mod.rs index 34e7cce3d..d8f6cb5ef 100644 --- a/prover/src/fri/mod.rs +++ b/prover/src/fri/mod.rs @@ -33,9 +33,11 @@ pub fn fri_commitment( // - hasher // Create a new merkle tree with evaluation_i let merkle_tree = FriMerkleTree::build(&evaluation_i); + + // append the root of the merkle tree to the transcript let root = merkle_tree.root.borrow().hash; - // TODO @@@ let bytes = root.as_bytes(); - //transcript.append(bytes); + let root_bytes = (*root.value()).to_be_bytes(); + transcript.append(&root_bytes); FriCommitment { poly: p_i.clone(), @@ -51,6 +53,12 @@ pub fn fri(p_0: &mut Polynomial>, domain_0: &[FE]) -> FriCommitm let evaluation_0 = p_0.evaluate_slice(domain_0); let merkle_tree = FriMerkleTree::build(&evaluation_0); + + // append the root of the merkle tree to the transcript + let root = merkle_tree.root.borrow().hash; + let root_bytes = (*root.value()).to_be_bytes(); + transcript.append(&root_bytes); + let commitment_0 = FriCommitment { poly: p_0.clone(), domain: domain_0.to_vec(), @@ -67,7 +75,7 @@ pub fn fri(p_0: &mut Polynomial>, domain_0: &[FE]) -> FriCommitm fri_commitment_list.push(commitment_0); let mut degree = p_0.degree(); - // TODO@@@ append root of the merkle tree to the transcript + let mut last_coef = last_poly.coefficients.get(0).unwrap(); while degree > 0 { // sample beta: @@ -78,18 +86,24 @@ pub fn fri(p_0: &mut Polynomial>, domain_0: &[FE]) -> FriCommitm let commitment_i = fri_commitment(&p_i, &domain_i, &evaluation_i, &mut transcript); + // append root of merkle tree to transcript + let tree = &commitment_i.merkle_tree; + let root = tree.root.borrow().hash; + let root_bytes = (*root.value()).to_be_bytes(); + transcript.append(&root_bytes); + + fri_commitment_list.push(commitment_i); degree = p_i.degree(); last_poly = p_i.clone(); + last_coef = last_poly.coefficients.get(0).unwrap(); last_domain = domain_i.clone(); - - // TODO - // append root of merkle tree to transcript } - // TODO // append last value of the polynomial to the trasncript + let last_coef_bytes = (*last_coef.value()).to_be_bytes(); + transcript.append(&last_coef_bytes); fri_commitment_list } From 623e3740828ab355a9f31df141f840666668014d Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Thu, 16 Feb 2023 13:14:47 -0300 Subject: [PATCH 25/85] insert last_evaluation in transcript --- prover/src/fri/fri_decommit.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/prover/src/fri/fri_decommit.rs b/prover/src/fri/fri_decommit.rs index 5907db323..8b234f4be 100644 --- a/prover/src/fri/fri_decommit.rs +++ b/prover/src/fri/fri_decommit.rs @@ -31,7 +31,9 @@ pub fn fri_decommit_layers( let last = commit.last().unwrap(); let last_evaluation = last.poly.coefficients[0]; - // @@@ TODO insert last_evaluation in transcript + // insert last_evaluation in transcript + let last_evaluation_bytes = (*last_evaluation.value()).to_be_bytes(); + transcript.append(&last_evaluation_bytes); } // Integration test: From d69145b2ba460d8f4609fb0798d47090df103519 Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Thu, 16 Feb 2023 13:16:55 -0300 Subject: [PATCH 26/85] beta from transcript.challenge() --- prover/src/fri/mod.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/prover/src/fri/mod.rs b/prover/src/fri/mod.rs index d8f6cb5ef..917857b20 100644 --- a/prover/src/fri/mod.rs +++ b/prover/src/fri/mod.rs @@ -7,6 +7,7 @@ use crate::fri::fri_commitment::{FriCommitment, FriCommitmentVec}; use crate::fri::fri_functions::next_fri_layer; pub use crate::fri::fri_merkle_tree::FriMerkleTree; pub use lambdaworks_crypto::{fiat_shamir::transcript::Transcript, merkle_tree::MerkleTree}; +use lambdaworks_math::traits::ByteConversion; pub use lambdaworks_math::{ field::{element::FieldElement, fields::u64_prime_field::U64PrimeField}, polynomial::Polynomial, @@ -33,7 +34,7 @@ pub fn fri_commitment( // - hasher // Create a new merkle tree with evaluation_i let merkle_tree = FriMerkleTree::build(&evaluation_i); - + // append the root of the merkle tree to the transcript let root = merkle_tree.root.borrow().hash; let root_bytes = (*root.value()).to_be_bytes(); @@ -79,9 +80,8 @@ pub fn fri(p_0: &mut Polynomial>, domain_0: &[FE]) -> FriCommitm while degree > 0 { // sample beta: - // TODO! let beta = transcript.challenge(); - let beta = FE::new(5); - + let beta_bytes = transcript.challenge(); + let beta = FE::from_bytes_be(&beta_bytes).unwrap(); let (p_i, domain_i, evaluation_i) = next_fri_layer(&last_poly, &last_domain, &beta); let commitment_i = fri_commitment(&p_i, &domain_i, &evaluation_i, &mut transcript); @@ -92,7 +92,6 @@ pub fn fri(p_0: &mut Polynomial>, domain_0: &[FE]) -> FriCommitm let root_bytes = (*root.value()).to_be_bytes(); transcript.append(&root_bytes); - fri_commitment_list.push(commitment_i); degree = p_i.degree(); From f6dbc608f5213ed1cedeef80a6bd97f58cc4bc3f Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Thu, 16 Feb 2023 16:01:28 -0300 Subject: [PATCH 27/85] test: generating subgroups --- prover/src/fri/fri_decommit.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/prover/src/fri/fri_decommit.rs b/prover/src/fri/fri_decommit.rs index 8b234f4be..a56977800 100644 --- a/prover/src/fri/fri_decommit.rs +++ b/prover/src/fri/fri_decommit.rs @@ -45,3 +45,34 @@ pub fn fri_decommit_layers( // assert: // * evaluations of the polynomials coincide with calculations from the decommitment // * show a fail example: with a monomial + +#[cfg(test)] +mod tests { + use crate::fri::U64PrimeField; + use lambdaworks_math::field::element::FieldElement; + use std::collections::HashSet; + const PRIME_GENERATOR: (u64, u64) = (0xFFFF_FFFF_0000_0001_u64, 2717_u64); + pub type F = U64PrimeField<{ PRIME_GENERATOR.0 }>; + pub type FE_goldilocks = FieldElement; + + #[test] + fn test() { + let subgroup_size = 1024_u64; + let generator_field = FE_goldilocks::new(PRIME_GENERATOR.1); + let exp = (PRIME_GENERATOR.0 - 1) / subgroup_size; + let generator_of_subgroup = generator_field.pow(exp); + let mut numbers = HashSet::new(); + + let mut i = 0; + for exp in 0..1024_u64 { + i += 1; + let ret = generator_of_subgroup.pow(exp); + numbers.insert(ret.value().clone()); + println!("{ret:?}"); + } + + let count = numbers.len(); + println!("count: {count}"); + println!("iter: {i}"); + } +} From a21bc11aaa9072d82939e01bbc1fe29eceb637d9 Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Mon, 13 Feb 2023 13:03:53 -0300 Subject: [PATCH 28/85] prover sub crate created --- Cargo.toml | 1 + prover/Cargo.toml | 9 +++++++++ prover/src/fri/mod.rs | 11 +++++++++++ prover/src/lib.rs | 1 + 4 files changed, 22 insertions(+) create mode 100644 prover/Cargo.toml create mode 100644 prover/src/fri/mod.rs create mode 100644 prover/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 7662aa11d..8496805f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,4 +3,5 @@ members = [ "math", "crypto", + "prover", ] diff --git a/prover/Cargo.toml b/prover/Cargo.toml new file mode 100644 index 000000000..aacbd7a18 --- /dev/null +++ b/prover/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "lambdaworks-prover" +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" diff --git a/prover/src/fri/mod.rs b/prover/src/fri/mod.rs new file mode 100644 index 000000000..6544e12a9 --- /dev/null +++ b/prover/src/fri/mod.rs @@ -0,0 +1,11 @@ +pub fn hello() { + println!("Hello world"); +} + +#[cfg(test)] +mod tests { + #[test] + fn test_hello() { + super::hello(); + } +} diff --git a/prover/src/lib.rs b/prover/src/lib.rs new file mode 100644 index 000000000..af12d86da --- /dev/null +++ b/prover/src/lib.rs @@ -0,0 +1 @@ +pub mod fri; From e635f0e3a343134983919f480892b463b09cf6e1 Mon Sep 17 00:00:00 2001 From: Mariano Nicolini Date: Mon, 13 Feb 2023 16:44:24 -0300 Subject: [PATCH 29/85] Save work in progress --- prover/Cargo.toml | 1 + prover/src/air/air.rs | 0 prover/src/air/mod.rs | 1 + prover/src/air/trace.rs | 9 +++++++++ prover/src/lib.rs | 1 + 5 files changed, 12 insertions(+) create mode 100644 prover/src/air/air.rs create mode 100644 prover/src/air/mod.rs create mode 100644 prover/src/air/trace.rs diff --git a/prover/Cargo.toml b/prover/Cargo.toml index aacbd7a18..802f73e37 100644 --- a/prover/Cargo.toml +++ b/prover/Cargo.toml @@ -7,3 +7,4 @@ edition = "2021" [dependencies] rand = "0.8.5" +lambdaworks-math = { path = "../math" } diff --git a/prover/src/air/air.rs b/prover/src/air/air.rs new file mode 100644 index 000000000..e69de29bb diff --git a/prover/src/air/mod.rs b/prover/src/air/mod.rs new file mode 100644 index 000000000..fc1f25c36 --- /dev/null +++ b/prover/src/air/mod.rs @@ -0,0 +1 @@ +mod trace; diff --git a/prover/src/air/trace.rs b/prover/src/air/trace.rs new file mode 100644 index 000000000..1bb4bde30 --- /dev/null +++ b/prover/src/air/trace.rs @@ -0,0 +1,9 @@ +use lambdaworks_math::field::{element::FieldElement, traits::IsField}; + +pub struct Trace { + inner: Vec>>, +} + +impl Trace { + pub fn new(columns: Vec>>) -> Self {} +} diff --git a/prover/src/lib.rs b/prover/src/lib.rs index af12d86da..7cd57133d 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -1 +1,2 @@ +pub mod air; pub mod fri; From 24ffd2a51f7ce87f6eee7362848283993417edd4 Mon Sep 17 00:00:00 2001 From: Mariano Nicolini Date: Tue, 14 Feb 2023 16:36:56 -0300 Subject: [PATCH 30/85] Add first iteration of function to get composition polynomials from trace and air --- prover/Cargo.toml | 1 + prover/src/air/air.rs | 0 prover/src/air/mod.rs | 2 +- prover/src/air/trace.rs | 9 --------- 4 files changed, 2 insertions(+), 10 deletions(-) delete mode 100644 prover/src/air/air.rs delete mode 100644 prover/src/air/trace.rs diff --git a/prover/Cargo.toml b/prover/Cargo.toml index 802f73e37..0c1fd44e0 100644 --- a/prover/Cargo.toml +++ b/prover/Cargo.toml @@ -8,3 +8,4 @@ edition = "2021" [dependencies] rand = "0.8.5" lambdaworks-math = { path = "../math" } +winterfell = { git = "/~https://github.com/lambdaclass/winterfell", branch = "make-apis-public" } diff --git a/prover/src/air/air.rs b/prover/src/air/air.rs deleted file mode 100644 index e69de29bb..000000000 diff --git a/prover/src/air/mod.rs b/prover/src/air/mod.rs index fc1f25c36..378e4540e 100644 --- a/prover/src/air/mod.rs +++ b/prover/src/air/mod.rs @@ -1 +1 @@ -mod trace; +mod composition_poly; diff --git a/prover/src/air/trace.rs b/prover/src/air/trace.rs deleted file mode 100644 index 1bb4bde30..000000000 --- a/prover/src/air/trace.rs +++ /dev/null @@ -1,9 +0,0 @@ -use lambdaworks_math::field::{element::FieldElement, traits::IsField}; - -pub struct Trace { - inner: Vec>>, -} - -impl Trace { - pub fn new(columns: Vec>>) -> Self {} -} From 7772c38c2deed0c49c9545fdfa28b25fa2151b4a Mon Sep 17 00:00:00 2001 From: Mariano Nicolini Date: Tue, 14 Feb 2023 17:19:19 -0300 Subject: [PATCH 31/85] Add test for get_composition_poly --- prover/src/air/composition_poly.rs | 214 +++++++++++++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 prover/src/air/composition_poly.rs diff --git a/prover/src/air/composition_poly.rs b/prover/src/air/composition_poly.rs new file mode 100644 index 000000000..fff2e3959 --- /dev/null +++ b/prover/src/air/composition_poly.rs @@ -0,0 +1,214 @@ +use lambdaworks_math::polynomial::Polynomial; +use winterfell::{ + crypto::hashers::Blake3_256, + math::{fields::f128::BaseElement, FieldElement, StarkField}, + Air, AirContext, Assertion, AuxTraceRandElements, ByteWriter, EvaluationFrame, FieldExtension, + ProofOptions, Prover, Serializable, StarkProof, Trace, TraceInfo, TraceTable, + TransitionConstraintDegree, +}; + +use winterfell::prover::build_trace_commitment_f; +use winterfell::prover::channel::ProverChannel; +use winterfell::prover::constraints::ConstraintEvaluator; +use winterfell::prover::domain::StarkDomain; +use winterfell::prover::trace::commitment::TraceCommitment; + +// fn get_composition_poly( +fn get_composition_poly( + air: A, + trace: TraceTable, + pub_inputs: A::PublicInputs, +) -> Result<(), ()> +// ) -> Polynomial +where + A: Air, + E: StarkField, + //F: FieldElement, +{ + let mut pub_inputs_bytes = Vec::new(); + pub_inputs.write_into(&mut pub_inputs_bytes); + + let mut channel = ProverChannel::>::new(&air, pub_inputs_bytes); + + let domain = StarkDomain::new(&air); + + // extend the main execution trace and build a Merkle tree from the extended trace + let (main_trace_lde, main_trace_tree, _main_trace_polys) = + build_trace_commitment_f::>(trace.main_segment(), &domain); + + // commit to the LDE of the main trace by writing the root of its Merkle tree into + // the channel + channel.commit_trace(*main_trace_tree.root()); + + // initialize trace commitment and trace polynomial table structs with the main trace + // data; for multi-segment traces these structs will be used as accumulators of all + // trace segments + let trace_commitment = TraceCommitment::new( + main_trace_lde, + main_trace_tree, + domain.trace_to_lde_blowup(), + ); + + // let mut trace_polys: TracePolyTable = TracePolyTable::new(main_trace_polys); + let aux_trace_rand_elements = AuxTraceRandElements::new(); + let constraint_coeffs = channel.get_constraint_composition_coeffs(); + let evaluator = ConstraintEvaluator::new(&air, aux_trace_rand_elements, constraint_coeffs); + let constraint_evaluations = evaluator.evaluate(trace_commitment.trace_table(), &domain); + + let composition_poly = constraint_evaluations.into_poly().unwrap(); + + println!("COMPOSITION POLYNOMIAL: {:?}", composition_poly); + + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + + // This test is made for the following computation, taken from the winterfell README: + // This computation starts with an element in a finite field and then, for the specified number of steps, + // cubes the element and adds value 42 to it. + #[test] + fn test_composition_poly_simple_computation() { + pub fn build_do_work_trace(start: BaseElement, n: usize) -> TraceTable { + // Instantiate the trace with a given width and length; this will allocate all + // required memory for the trace + let trace_width = 1; + let mut trace = TraceTable::new(trace_width, n); + + // Fill the trace with data; the first closure initializes the first state of the + // computation; the second closure computes the next state of the computation based + // on its current state. + trace.fill( + |state| { + state[0] = start; + }, + |_, state| { + state[0] = state[0].exp(3u32.into()) + BaseElement::new(42); + }, + ); + + trace + } + + // Public inputs for our computation will consist of the starting value and the end result. + #[derive(Clone)] + pub struct PublicInputs { + start: BaseElement, + result: BaseElement, + } + + // We need to describe how public inputs can be converted to bytes. + impl Serializable for PublicInputs { + fn write_into(&self, target: &mut W) { + target.write(self.start); + target.write(self.result); + } + } + + // For a specific instance of our computation, we'll keep track of the public inputs and + // the computation's context which we'll build in the constructor. The context is used + // internally by the Winterfell prover/verifier when interpreting this AIR. + pub struct WorkAir { + context: AirContext, + start: BaseElement, + result: BaseElement, + } + + impl Air for WorkAir { + // First, we'll specify which finite field to use for our computation, and also how + // the public inputs must look like. + type BaseField = BaseElement; + type PublicInputs = PublicInputs; + + // Here, we'll construct a new instance of our computation which is defined by 3 parameters: + // starting value, number of steps, and the end result. Another way to think about it is + // that an instance of our computation is a specific invocation of the do_work() function. + fn new(trace_info: TraceInfo, pub_inputs: PublicInputs, options: ProofOptions) -> Self { + // our execution trace should have only one column. + assert_eq!(1, trace_info.width()); + + // Our computation requires a single transition constraint. The constraint itself + // is defined in the evaluate_transition() method below, but here we need to specify + // the expected degree of the constraint. If the expected and actual degrees of the + // constraints don't match, an error will be thrown in the debug mode, but in release + // mode, an invalid proof will be generated which will not be accepted by any verifier. + let degrees = vec![TransitionConstraintDegree::new(3)]; + + // We also need to specify the exact number of assertions we will place against the + // execution trace. This number must be the same as the number of items in a vector + // returned from the get_assertions() method below. + let num_assertions = 2; + + WorkAir { + context: AirContext::new(trace_info, degrees, num_assertions, options), + start: pub_inputs.start, + result: pub_inputs.result, + } + } + + // In this method we'll define our transition constraints; a computation is considered to + // be valid, if for all valid state transitions, transition constraints evaluate to all + // zeros, and for any invalid transition, at least one constraint evaluates to a non-zero + // value. The `frame` parameter will contain current and next states of the computation. + fn evaluate_transition>( + &self, + frame: &EvaluationFrame, + _periodic_values: &[E], + result: &mut [E], + ) { + // First, we'll read the current state, and use it to compute the expected next state + let current_state = &frame.current()[0]; + let next_state = current_state.exp(3u32.into()) + E::from(42u32); + + // Then, we'll subtract the expected next state from the actual next state; this will + // evaluate to zero if and only if the expected and actual states are the same. + result[0] = frame.next()[0] - next_state; + } + + // Here, we'll define a set of assertions about the execution trace which must be satisfied + // for the computation to be valid. Essentially, this ties computation's execution trace + // to the public inputs. + fn get_assertions(&self) -> Vec> { + // for our computation to be valid, value in column 0 at step 0 must be equal to the + // starting value, and at the last step it must be equal to the result. + let last_step = self.trace_length() - 1; + vec![ + Assertion::single(0, 0, self.start), + Assertion::single(0, last_step, self.result), + ] + } + + // This is just boilerplate which is used by the Winterfell prover/verifier to retrieve + // the context of the computation. + fn context(&self) -> &AirContext { + &self.context + } + } + + let start = BaseElement::new(3); + let n = 8; + + // Build the execution trace and get the result from the last step. + let trace = build_do_work_trace(start, n); + let pub_inputs = PublicInputs { + start: trace.get(0, 0), + result: trace.get(0, trace.length() - 1), + }; + + // Define proof options; these will be enough for ~96-bit security level. + let options = ProofOptions::new( + 32, // number of queries + 8, // blowup factor + 0, // grinding factor + FieldExtension::None, + 8, // FRI folding factor + 128, // FRI max remainder length + ); + + let air = WorkAir::new(trace.get_info(), pub_inputs.clone(), options); + + assert!(get_composition_poly(air, trace, pub_inputs).is_ok()); + } +} From 0f728036d279eb514f19bd14a28a9cd2c8fb4dc4 Mon Sep 17 00:00:00 2001 From: Mariano Nicolini Date: Tue, 14 Feb 2023 18:59:38 -0300 Subject: [PATCH 32/85] Add get_coefficients function --- prover/src/air/composition_poly.rs | 50 ++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/prover/src/air/composition_poly.rs b/prover/src/air/composition_poly.rs index fff2e3959..c2190956f 100644 --- a/prover/src/air/composition_poly.rs +++ b/prover/src/air/composition_poly.rs @@ -2,16 +2,33 @@ use lambdaworks_math::polynomial::Polynomial; use winterfell::{ crypto::hashers::Blake3_256, math::{fields::f128::BaseElement, FieldElement, StarkField}, + prover::constraints::CompositionPoly, Air, AirContext, Assertion, AuxTraceRandElements, ByteWriter, EvaluationFrame, FieldExtension, ProofOptions, Prover, Serializable, StarkProof, Trace, TraceInfo, TraceTable, TransitionConstraintDegree, }; -use winterfell::prover::build_trace_commitment_f; -use winterfell::prover::channel::ProverChannel; -use winterfell::prover::constraints::ConstraintEvaluator; -use winterfell::prover::domain::StarkDomain; -use winterfell::prover::trace::commitment::TraceCommitment; +use winterfell::prover::{ + build_trace_commitment_f, channel::ProverChannel, constraints::ConstraintEvaluator, + domain::StarkDomain, trace::commitment::TraceCommitment, +}; + +fn get_coefficients(poly: CompositionPoly) -> Vec { + let data = poly.into_columns(); + + let num_columns = data.len(); + let column_len = data[0].len(); + + let mut coeffs = Vec::with_capacity(num_columns * column_len); + + for i in 0..column_len { + for j in 0..num_columns { + coeffs.push(data[j][i]); + } + } + + coeffs +} // fn get_composition_poly( fn get_composition_poly( @@ -27,9 +44,7 @@ where { let mut pub_inputs_bytes = Vec::new(); pub_inputs.write_into(&mut pub_inputs_bytes); - let mut channel = ProverChannel::>::new(&air, pub_inputs_bytes); - let domain = StarkDomain::new(&air); // extend the main execution trace and build a Merkle tree from the extended trace @@ -66,9 +81,26 @@ where mod tests { use super::*; + #[test] + fn test_get_coefficients() { + let coeffs = (0u128..16).map(BaseElement::new).collect::>(); + let poly = CompositionPoly::new(coeffs.clone(), 2); + let coeffs_res = get_coefficients(poly); + + assert_eq!(coeffs, coeffs_res); + } + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // This test is made for the following computation, taken from the winterfell README: - // This computation starts with an element in a finite field and then, for the specified number of steps, - // cubes the element and adds value 42 to it. + // "This computation starts with an element in a finite field and then, for the specified number of steps, + // cubes the element and adds value 42 to it" + // + // The test setup consists of the following: + // * Creating a trace of the computation + // * Implementing an AIR of the computation + // + // TODO: Check that the obtained polynomial is correct. + ////////////////////////////////////////////////////////////////////////////////////////////////////////////// #[test] fn test_composition_poly_simple_computation() { pub fn build_do_work_trace(start: BaseElement, n: usize) -> TraceTable { From 999b2097723ada3b5b79a4c451e8b6f8d9dd0ca3 Mon Sep 17 00:00:00 2001 From: Mariano Nicolini Date: Wed, 15 Feb 2023 15:49:55 -0300 Subject: [PATCH 33/85] Tidy up code --- prover/src/air/composition_poly.rs | 64 ++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 20 deletions(-) diff --git a/prover/src/air/composition_poly.rs b/prover/src/air/composition_poly.rs index c2190956f..4fa18b13b 100644 --- a/prover/src/air/composition_poly.rs +++ b/prover/src/air/composition_poly.rs @@ -1,3 +1,4 @@ +use lambdaworks_math::field::element; use lambdaworks_math::polynomial::Polynomial; use winterfell::{ crypto::hashers::Blake3_256, @@ -13,6 +14,8 @@ use winterfell::prover::{ domain::StarkDomain, trace::commitment::TraceCommitment, }; +/// Given a CompositionPoly from winterfell, extract its coefficients +/// as a vector. fn get_coefficients(poly: CompositionPoly) -> Vec { let data = poly.into_columns(); @@ -30,41 +33,38 @@ fn get_coefficients(poly: CompositionPoly) -> Vec { coeffs } -// fn get_composition_poly( -fn get_composition_poly( +/// +fn get_composition_poly( air: A, - trace: TraceTable, + trace: TraceTable, pub_inputs: A::PublicInputs, -) -> Result<(), ()> -// ) -> Polynomial +) -> Vec where - A: Air, - E: StarkField, - //F: FieldElement, + A: Air, { let mut pub_inputs_bytes = Vec::new(); pub_inputs.write_into(&mut pub_inputs_bytes); - let mut channel = ProverChannel::>::new(&air, pub_inputs_bytes); + let mut channel = + ProverChannel::>::new(&air, pub_inputs_bytes); let domain = StarkDomain::new(&air); // extend the main execution trace and build a Merkle tree from the extended trace - let (main_trace_lde, main_trace_tree, _main_trace_polys) = - build_trace_commitment_f::>(trace.main_segment(), &domain); + let (main_trace_lde, main_trace_tree, _main_trace_polys) = build_trace_commitment_f::< + BaseElement, + BaseElement, + Blake3_256, + >(trace.main_segment(), &domain); // commit to the LDE of the main trace by writing the root of its Merkle tree into // the channel channel.commit_trace(*main_trace_tree.root()); - // initialize trace commitment and trace polynomial table structs with the main trace - // data; for multi-segment traces these structs will be used as accumulators of all - // trace segments let trace_commitment = TraceCommitment::new( main_trace_lde, main_trace_tree, domain.trace_to_lde_blowup(), ); - // let mut trace_polys: TracePolyTable = TracePolyTable::new(main_trace_polys); let aux_trace_rand_elements = AuxTraceRandElements::new(); let constraint_coeffs = channel.get_constraint_composition_coeffs(); let evaluator = ConstraintEvaluator::new(&air, aux_trace_rand_elements, constraint_coeffs); @@ -72,9 +72,10 @@ where let composition_poly = constraint_evaluations.into_poly().unwrap(); - println!("COMPOSITION POLYNOMIAL: {:?}", composition_poly); - - Ok(()) + get_coefficients(composition_poly) + .iter() + .map(|c| c.0) + .collect::>() } #[cfg(test)] @@ -222,7 +223,7 @@ mod tests { let start = BaseElement::new(3); let n = 8; - // Build the execution trace and get the result from the last step. + // Build the execution trace and . let trace = build_do_work_trace(start, n); let pub_inputs = PublicInputs { start: trace.get(0, 0), @@ -241,6 +242,29 @@ mod tests { let air = WorkAir::new(trace.get_info(), pub_inputs.clone(), options); - assert!(get_composition_poly(air, trace, pub_inputs).is_ok()); + // this coefficients should be checked correctly + let expected_coeffs = vec![ + 73805846515134368521942875729025268850u128, + 251094867283236114961184226859763993364, + 24104107408363517664638843184319555199, + 235849850267413452314892506985835977650, + 90060524782298155599732670785320526321, + 191672218871615916423281291477102427646, + 266219015768353823155348590781060058741, + 323575369761999186385729504758291491620, + 11584578295884344582449562404474773268, + 210204873954083390997653826263858894919, + 255852687493109162976897695176505210663, + 263909750263371532307415443077776653137, + 270439831904630486671154877882097540335, + 295423943150257863151191255913349696708, + 305657170959297052488312417688653377091, + 170130930667860970428731413388750994520, + ]; + + assert_eq!( + get_composition_poly(air, trace, pub_inputs), + expected_coeffs + ); } } From 1e65005503fd8552023cfb5a24828e3524deb8b1 Mon Sep 17 00:00:00 2001 From: Mariano Nicolini Date: Wed, 15 Feb 2023 15:52:42 -0300 Subject: [PATCH 34/85] Add docs --- prover/src/air/composition_poly.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/prover/src/air/composition_poly.rs b/prover/src/air/composition_poly.rs index 4fa18b13b..c2aa373ea 100644 --- a/prover/src/air/composition_poly.rs +++ b/prover/src/air/composition_poly.rs @@ -1,12 +1,8 @@ -use lambdaworks_math::field::element; -use lambdaworks_math::polynomial::Polynomial; use winterfell::{ crypto::hashers::Blake3_256, - math::{fields::f128::BaseElement, FieldElement, StarkField}, + math::{fields::f128::BaseElement, StarkField}, prover::constraints::CompositionPoly, - Air, AirContext, Assertion, AuxTraceRandElements, ByteWriter, EvaluationFrame, FieldExtension, - ProofOptions, Prover, Serializable, StarkProof, Trace, TraceInfo, TraceTable, - TransitionConstraintDegree, + Air, AuxTraceRandElements, Serializable, Trace, TraceTable, }; use winterfell::prover::{ @@ -33,7 +29,8 @@ fn get_coefficients(poly: CompositionPoly) -> Vec { coeffs } -/// +/// Given a trace and an air defined with winterfell data structres, outputs +/// a vector of u128 representing the coefficients of the composition polynomial. fn get_composition_poly( air: A, trace: TraceTable, From 9b3fdfb84081b37aac8960275b4bc56b395b979d Mon Sep 17 00:00:00 2001 From: Mariano Nicolini Date: Wed, 15 Feb 2023 15:56:11 -0300 Subject: [PATCH 35/85] Fix tests --- prover/src/air/composition_poly.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/prover/src/air/composition_poly.rs b/prover/src/air/composition_poly.rs index c2aa373ea..0a12ca25d 100644 --- a/prover/src/air/composition_poly.rs +++ b/prover/src/air/composition_poly.rs @@ -77,6 +77,11 @@ where #[cfg(test)] mod tests { + use winterfell::{ + math::FieldElement, AirContext, Assertion, ByteWriter, EvaluationFrame, FieldExtension, + ProofOptions, TraceInfo, TransitionConstraintDegree, + }; + use super::*; #[test] From 5ce755690f6c48086031bdd9415f7ffb892da47b Mon Sep 17 00:00:00 2001 From: Mariano Nicolini Date: Wed, 15 Feb 2023 17:25:54 -0300 Subject: [PATCH 36/85] Add u128_prime field and make get_composition_poly return a Polynomial data structure --- math/src/field/fields/mod.rs | 1 + math/src/field/fields/u128_prime_field.rs | 82 +++++++++++++++++++++++ math/src/unsigned_integer/element.rs | 1 + prover/src/air/composition_poly.rs | 41 ++++++++---- 4 files changed, 113 insertions(+), 12 deletions(-) create mode 100644 math/src/field/fields/u128_prime_field.rs diff --git a/math/src/field/fields/mod.rs b/math/src/field/fields/mod.rs index e79c6b653..68b306cf5 100644 --- a/math/src/field/fields/mod.rs +++ b/math/src/field/fields/mod.rs @@ -1,3 +1,4 @@ +pub mod u128_prime_field; pub mod u384_prime_field; /// Implementation of prime fields over 64 bit unsigned integers. pub mod u64_prime_field; diff --git a/math/src/field/fields/u128_prime_field.rs b/math/src/field/fields/u128_prime_field.rs new file mode 100644 index 000000000..964d60b28 --- /dev/null +++ b/math/src/field/fields/u128_prime_field.rs @@ -0,0 +1,82 @@ +use crate::field::element::FieldElement; +use crate::unsigned_integer::element::U128; +use crate::{field::traits::IsField, unsigned_integer::element::UnsignedInteger}; +use std::fmt::Debug; + +/// Type representing prime fields over unsigned 64-bit integers. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct U128PrimeField; +pub type U128FieldElement = FieldElement>; + +impl U128PrimeField { + const ZERO: U128 = UnsignedInteger::from_u64(0); +} + +impl IsField for U128PrimeField { + type BaseType = U128; + + fn add(a: &Self::BaseType, b: &Self::BaseType) -> Self::BaseType { + let (sum, overflow) = UnsignedInteger::add(a, b); + if !overflow { + if sum < U128::from_u128(MODULUS) { + sum + } else { + sum - U128::from_u128(MODULUS) + } + } else { + let (diff, _) = UnsignedInteger::sub(&sum, &UnsignedInteger::<2>::from_u128(MODULUS)); + diff + } + } + + fn mul(a: &Self::BaseType, b: &Self::BaseType) -> Self::BaseType { + a * b + } + + fn sub(a: &Self::BaseType, b: &Self::BaseType) -> Self::BaseType { + if b <= a { + a - b + } else { + U128::from_u128(MODULUS) - (b - a) + } + } + + fn neg(a: &Self::BaseType) -> Self::BaseType { + if a == &Self::ZERO { + *a + } else { + U128::from_u128(MODULUS) - a + } + } + + fn inv(a: &Self::BaseType) -> Self::BaseType { + if a == &Self::ZERO { + panic!("Division by zero error.") + } + Self::pow(a, U128::from_u128(MODULUS) - Self::BaseType::from_u64(2)) + } + + fn div(a: &Self::BaseType, b: &Self::BaseType) -> Self::BaseType { + Self::mul(a, &Self::inv(b)) + } + + fn eq(a: &Self::BaseType, b: &Self::BaseType) -> bool { + a == b + } + + fn zero() -> Self::BaseType { + Self::ZERO + } + + fn one() -> Self::BaseType { + Self::from_u64(1) + } + + fn from_u64(x: u64) -> Self::BaseType { + U128::from_u64(x) + } + + fn from_base_type(x: Self::BaseType) -> Self::BaseType { + x + } +} diff --git a/math/src/unsigned_integer/element.rs b/math/src/unsigned_integer/element.rs index 339294d39..875bb3bc9 100644 --- a/math/src/unsigned_integer/element.rs +++ b/math/src/unsigned_integer/element.rs @@ -9,6 +9,7 @@ use std::fmt::Debug; pub type U384 = UnsignedInteger<6>; pub type U256 = UnsignedInteger<4>; +pub type U128 = UnsignedInteger<2>; /// A big unsigned integer in base 2^{64} represented /// as fixed-size array `limbs` of `u64` components. diff --git a/prover/src/air/composition_poly.rs b/prover/src/air/composition_poly.rs index 0a12ca25d..61e1ba056 100644 --- a/prover/src/air/composition_poly.rs +++ b/prover/src/air/composition_poly.rs @@ -1,3 +1,11 @@ +use lambdaworks_math::{ + field::{ + element::FieldElement, + fields::u128_prime_field::{U128FieldElement, U128PrimeField}, + }, + polynomial::Polynomial, + unsigned_integer::element::U128, +}; use winterfell::{ crypto::hashers::Blake3_256, math::{fields::f128::BaseElement, StarkField}, @@ -10,6 +18,9 @@ use winterfell::prover::{ domain::StarkDomain, trace::commitment::TraceCommitment, }; +// Taken from winterfell, this is the modulus of a Starkfield +const M: u128 = 340282366920938463463374557953744961537; + /// Given a CompositionPoly from winterfell, extract its coefficients /// as a vector. fn get_coefficients(poly: CompositionPoly) -> Vec { @@ -29,13 +40,13 @@ fn get_coefficients(poly: CompositionPoly) -> Vec { coeffs } -/// Given a trace and an air defined with winterfell data structres, outputs +/// Given a trace and an air defined with winterfell data structures, outputs /// a vector of u128 representing the coefficients of the composition polynomial. fn get_composition_poly( air: A, trace: TraceTable, pub_inputs: A::PublicInputs, -) -> Vec +) -> Polynomial> where A: Air, { @@ -69,10 +80,12 @@ where let composition_poly = constraint_evaluations.into_poly().unwrap(); - get_coefficients(composition_poly) + let coeffs: Vec> = get_coefficients(composition_poly) .iter() - .map(|c| c.0) - .collect::>() + .map(|c| FieldElement::new(U128::from_u128(c.0))) + .collect(); + + Polynomial::new(coeffs) } #[cfg(test)] @@ -94,7 +107,7 @@ mod tests { } ////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // This test is made for the following computation, taken from the winterfell README: + // This test is made for the following computation, taken from the winterfell README example: // "This computation starts with an element in a finite field and then, for the specified number of steps, // cubes the element and adds value 42 to it" // @@ -244,7 +257,8 @@ mod tests { let air = WorkAir::new(trace.get_info(), pub_inputs.clone(), options); - // this coefficients should be checked correctly + // TODO: this coefficients should be checked correctly to know + // the test is really passing let expected_coeffs = vec![ 73805846515134368521942875729025268850u128, 251094867283236114961184226859763993364, @@ -262,11 +276,14 @@ mod tests { 295423943150257863151191255913349696708, 305657170959297052488312417688653377091, 170130930667860970428731413388750994520, - ]; + ] + .into_iter() + .map(|c| U128::from_u128(c)) + .map(|c| lambdaworks_math::field::element::FieldElement::new(c)) + .collect(); - assert_eq!( - get_composition_poly(air, trace, pub_inputs), - expected_coeffs - ); + let expected_poly = Polynomial::new(expected_coeffs); + + assert_eq!(get_composition_poly(air, trace, pub_inputs), expected_poly); } } From 73299e82215d9662ba2a37b28dc8ece32836d548 Mon Sep 17 00:00:00 2001 From: Mariano Nicolini Date: Wed, 15 Feb 2023 17:32:34 -0300 Subject: [PATCH 37/85] Fixes from rebasing --- prover/src/air/composition_poly.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/prover/src/air/composition_poly.rs b/prover/src/air/composition_poly.rs index 61e1ba056..053d72b3e 100644 --- a/prover/src/air/composition_poly.rs +++ b/prover/src/air/composition_poly.rs @@ -85,7 +85,7 @@ where .map(|c| FieldElement::new(U128::from_u128(c.0))) .collect(); - Polynomial::new(coeffs) + Polynomial::new(&coeffs) } #[cfg(test)] @@ -257,7 +257,7 @@ mod tests { let air = WorkAir::new(trace.get_info(), pub_inputs.clone(), options); - // TODO: this coefficients should be checked correctly to know + // TODO: this coefficients should be checked correctly to know // the test is really passing let expected_coeffs = vec![ 73805846515134368521942875729025268850u128, @@ -280,9 +280,9 @@ mod tests { .into_iter() .map(|c| U128::from_u128(c)) .map(|c| lambdaworks_math::field::element::FieldElement::new(c)) - .collect(); + .collect::>(); - let expected_poly = Polynomial::new(expected_coeffs); + let expected_poly = Polynomial::new(&expected_coeffs); assert_eq!(get_composition_poly(air, trace, pub_inputs), expected_poly); } From faf992f25d039293a0b3bb2e5e0021d9be637abf Mon Sep 17 00:00:00 2001 From: Mariano Nicolini Date: Wed, 15 Feb 2023 17:48:34 -0300 Subject: [PATCH 38/85] Apply clippy suggestions --- prover/src/air/composition_poly.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/prover/src/air/composition_poly.rs b/prover/src/air/composition_poly.rs index 053d72b3e..b6dab533c 100644 --- a/prover/src/air/composition_poly.rs +++ b/prover/src/air/composition_poly.rs @@ -1,8 +1,5 @@ use lambdaworks_math::{ - field::{ - element::FieldElement, - fields::u128_prime_field::{U128FieldElement, U128PrimeField}, - }, + field::{element::FieldElement, fields::u128_prime_field::U128FieldElement}, polynomial::Polynomial, unsigned_integer::element::U128, }; @@ -23,6 +20,7 @@ const M: u128 = 340282366920938463463374557953744961537; /// Given a CompositionPoly from winterfell, extract its coefficients /// as a vector. +#[allow(dead_code)] fn get_coefficients(poly: CompositionPoly) -> Vec { let data = poly.into_columns(); @@ -32,8 +30,8 @@ fn get_coefficients(poly: CompositionPoly) -> Vec { let mut coeffs = Vec::with_capacity(num_columns * column_len); for i in 0..column_len { - for j in 0..num_columns { - coeffs.push(data[j][i]); + for coeff_col in data.iter().take(num_columns) { + coeffs.push(coeff_col[i]); } } @@ -42,6 +40,7 @@ fn get_coefficients(poly: CompositionPoly) -> Vec { /// Given a trace and an air defined with winterfell data structures, outputs /// a vector of u128 representing the coefficients of the composition polynomial. +#[allow(dead_code)] fn get_composition_poly( air: A, trace: TraceTable, From 81f1eb4489831f4a9d747ae73d5bec8ee858a62f Mon Sep 17 00:00:00 2001 From: Mariano Nicolini Date: Wed, 15 Feb 2023 17:50:30 -0300 Subject: [PATCH 39/85] Make functions pub crate --- prover/src/air/composition_poly.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prover/src/air/composition_poly.rs b/prover/src/air/composition_poly.rs index b6dab533c..df5e746c5 100644 --- a/prover/src/air/composition_poly.rs +++ b/prover/src/air/composition_poly.rs @@ -21,7 +21,7 @@ const M: u128 = 340282366920938463463374557953744961537; /// Given a CompositionPoly from winterfell, extract its coefficients /// as a vector. #[allow(dead_code)] -fn get_coefficients(poly: CompositionPoly) -> Vec { +pub(crate) fn get_coefficients(poly: CompositionPoly) -> Vec { let data = poly.into_columns(); let num_columns = data.len(); @@ -41,7 +41,7 @@ fn get_coefficients(poly: CompositionPoly) -> Vec { /// Given a trace and an air defined with winterfell data structures, outputs /// a vector of u128 representing the coefficients of the composition polynomial. #[allow(dead_code)] -fn get_composition_poly( +pub(crate) fn get_composition_poly( air: A, trace: TraceTable, pub_inputs: A::PublicInputs, From d2aeb7712e224532b5e1d7bd6b2926fbe3ce9358 Mon Sep 17 00:00:00 2001 From: Mariano Nicolini Date: Wed, 15 Feb 2023 18:08:47 -0300 Subject: [PATCH 40/85] Tidy up code --- prover/src/air/composition_poly.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/prover/src/air/composition_poly.rs b/prover/src/air/composition_poly.rs index df5e746c5..9bee125cd 100644 --- a/prover/src/air/composition_poly.rs +++ b/prover/src/air/composition_poly.rs @@ -118,7 +118,7 @@ mod tests { ////////////////////////////////////////////////////////////////////////////////////////////////////////////// #[test] fn test_composition_poly_simple_computation() { - pub fn build_do_work_trace(start: BaseElement, n: usize) -> TraceTable { + fn build_do_work_trace(start: BaseElement, n: usize) -> TraceTable { // Instantiate the trace with a given width and length; this will allocate all // required memory for the trace let trace_width = 1; @@ -141,7 +141,7 @@ mod tests { // Public inputs for our computation will consist of the starting value and the end result. #[derive(Clone)] - pub struct PublicInputs { + struct PublicInputs { start: BaseElement, result: BaseElement, } @@ -157,7 +157,7 @@ mod tests { // For a specific instance of our computation, we'll keep track of the public inputs and // the computation's context which we'll build in the constructor. The context is used // internally by the Winterfell prover/verifier when interpreting this AIR. - pub struct WorkAir { + struct WorkAir { context: AirContext, start: BaseElement, result: BaseElement, @@ -277,8 +277,8 @@ mod tests { 170130930667860970428731413388750994520, ] .into_iter() - .map(|c| U128::from_u128(c)) - .map(|c| lambdaworks_math::field::element::FieldElement::new(c)) + .map(U128::from_u128) + .map(lambdaworks_math::field::element::FieldElement::new) .collect::>(); let expected_poly = Polynomial::new(&expected_coeffs); From ee52e7572e30973a943be8ae00fb89fc8f96fbde Mon Sep 17 00:00:00 2001 From: Mariano Nicolini Date: Wed, 15 Feb 2023 18:30:25 -0300 Subject: [PATCH 41/85] Tidy up code --- prover/src/air/composition_poly.rs | 248 +++++++++++++++-------------- 1 file changed, 128 insertions(+), 120 deletions(-) diff --git a/prover/src/air/composition_poly.rs b/prover/src/air/composition_poly.rs index 9bee125cd..a168a5d71 100644 --- a/prover/src/air/composition_poly.rs +++ b/prover/src/air/composition_poly.rs @@ -89,12 +89,8 @@ where #[cfg(test)] mod tests { - use winterfell::{ - math::FieldElement, AirContext, Assertion, ByteWriter, EvaluationFrame, FieldExtension, - ProofOptions, TraceInfo, TransitionConstraintDegree, - }; - use super::*; + use winterfell::{FieldExtension, ProofOptions}; #[test] fn test_get_coefficients() { @@ -118,121 +114,7 @@ mod tests { ////////////////////////////////////////////////////////////////////////////////////////////////////////////// #[test] fn test_composition_poly_simple_computation() { - fn build_do_work_trace(start: BaseElement, n: usize) -> TraceTable { - // Instantiate the trace with a given width and length; this will allocate all - // required memory for the trace - let trace_width = 1; - let mut trace = TraceTable::new(trace_width, n); - - // Fill the trace with data; the first closure initializes the first state of the - // computation; the second closure computes the next state of the computation based - // on its current state. - trace.fill( - |state| { - state[0] = start; - }, - |_, state| { - state[0] = state[0].exp(3u32.into()) + BaseElement::new(42); - }, - ); - - trace - } - - // Public inputs for our computation will consist of the starting value and the end result. - #[derive(Clone)] - struct PublicInputs { - start: BaseElement, - result: BaseElement, - } - - // We need to describe how public inputs can be converted to bytes. - impl Serializable for PublicInputs { - fn write_into(&self, target: &mut W) { - target.write(self.start); - target.write(self.result); - } - } - - // For a specific instance of our computation, we'll keep track of the public inputs and - // the computation's context which we'll build in the constructor. The context is used - // internally by the Winterfell prover/verifier when interpreting this AIR. - struct WorkAir { - context: AirContext, - start: BaseElement, - result: BaseElement, - } - - impl Air for WorkAir { - // First, we'll specify which finite field to use for our computation, and also how - // the public inputs must look like. - type BaseField = BaseElement; - type PublicInputs = PublicInputs; - - // Here, we'll construct a new instance of our computation which is defined by 3 parameters: - // starting value, number of steps, and the end result. Another way to think about it is - // that an instance of our computation is a specific invocation of the do_work() function. - fn new(trace_info: TraceInfo, pub_inputs: PublicInputs, options: ProofOptions) -> Self { - // our execution trace should have only one column. - assert_eq!(1, trace_info.width()); - - // Our computation requires a single transition constraint. The constraint itself - // is defined in the evaluate_transition() method below, but here we need to specify - // the expected degree of the constraint. If the expected and actual degrees of the - // constraints don't match, an error will be thrown in the debug mode, but in release - // mode, an invalid proof will be generated which will not be accepted by any verifier. - let degrees = vec![TransitionConstraintDegree::new(3)]; - - // We also need to specify the exact number of assertions we will place against the - // execution trace. This number must be the same as the number of items in a vector - // returned from the get_assertions() method below. - let num_assertions = 2; - - WorkAir { - context: AirContext::new(trace_info, degrees, num_assertions, options), - start: pub_inputs.start, - result: pub_inputs.result, - } - } - - // In this method we'll define our transition constraints; a computation is considered to - // be valid, if for all valid state transitions, transition constraints evaluate to all - // zeros, and for any invalid transition, at least one constraint evaluates to a non-zero - // value. The `frame` parameter will contain current and next states of the computation. - fn evaluate_transition>( - &self, - frame: &EvaluationFrame, - _periodic_values: &[E], - result: &mut [E], - ) { - // First, we'll read the current state, and use it to compute the expected next state - let current_state = &frame.current()[0]; - let next_state = current_state.exp(3u32.into()) + E::from(42u32); - - // Then, we'll subtract the expected next state from the actual next state; this will - // evaluate to zero if and only if the expected and actual states are the same. - result[0] = frame.next()[0] - next_state; - } - - // Here, we'll define a set of assertions about the execution trace which must be satisfied - // for the computation to be valid. Essentially, this ties computation's execution trace - // to the public inputs. - fn get_assertions(&self) -> Vec> { - // for our computation to be valid, value in column 0 at step 0 must be equal to the - // starting value, and at the last step it must be equal to the result. - let last_step = self.trace_length() - 1; - vec![ - Assertion::single(0, 0, self.start), - Assertion::single(0, last_step, self.result), - ] - } - - // This is just boilerplate which is used by the Winterfell prover/verifier to retrieve - // the context of the computation. - fn context(&self) -> &AirContext { - &self.context - } - } + use simple_computation_test_utils::*; let start = BaseElement::new(3); let n = 8; @@ -286,3 +168,129 @@ mod tests { assert_eq!(get_composition_poly(air, trace, pub_inputs), expected_poly); } } + +#[cfg(test)] +pub(crate) mod simple_computation_test_utils { + use winterfell::{ + math::FieldElement, AirContext, Assertion, ByteWriter, EvaluationFrame, ProofOptions, + TraceInfo, TransitionConstraintDegree, + }; + + use super::*; + + pub(crate) fn build_do_work_trace(start: BaseElement, n: usize) -> TraceTable { + // Instantiate the trace with a given width and length; this will allocate all + // required memory for the trace + let trace_width = 1; + let mut trace = TraceTable::new(trace_width, n); + + // Fill the trace with data; the first closure initializes the first state of the + // computation; the second closure computes the next state of the computation based + // on its current state. + trace.fill( + |state| { + state[0] = start; + }, + |_, state| { + state[0] = state[0].exp(3u32.into()) + BaseElement::new(42); + }, + ); + + trace + } + + // Public inputs for our computation will consist of the starting value and the end result. + #[derive(Clone)] + pub(crate) struct PublicInputs { + pub start: BaseElement, + pub result: BaseElement, + } + + // We need to describe how public inputs can be converted to bytes. + impl Serializable for PublicInputs { + fn write_into(&self, target: &mut W) { + target.write(self.start); + target.write(self.result); + } + } + + // For a specific instance of our computation, we'll keep track of the public inputs and + // the computation's context which we'll build in the constructor. The context is used + // internally by the Winterfell prover/verifier when interpreting this AIR. + pub(crate) struct WorkAir { + context: AirContext, + start: BaseElement, + result: BaseElement, + } + + impl Air for WorkAir { + // First, we'll specify which finite field to use for our computation, and also how + // the public inputs must look like. + type BaseField = BaseElement; + type PublicInputs = PublicInputs; + + // Here, we'll construct a new instance of our computation which is defined by 3 parameters: + // starting value, number of steps, and the end result. Another way to think about it is + // that an instance of our computation is a specific invocation of the do_work() function. + fn new(trace_info: TraceInfo, pub_inputs: PublicInputs, options: ProofOptions) -> Self { + // our execution trace should have only one column. + assert_eq!(1, trace_info.width()); + + // Our computation requires a single transition constraint. The constraint itself + // is defined in the evaluate_transition() method below, but here we need to specify + // the expected degree of the constraint. If the expected and actual degrees of the + // constraints don't match, an error will be thrown in the debug mode, but in release + // mode, an invalid proof will be generated which will not be accepted by any verifier. + let degrees = vec![TransitionConstraintDegree::new(3)]; + + // We also need to specify the exact number of assertions we will place against the + // execution trace. This number must be the same as the number of items in a vector + // returned from the get_assertions() method below. + let num_assertions = 2; + + WorkAir { + context: AirContext::new(trace_info, degrees, num_assertions, options), + start: pub_inputs.start, + result: pub_inputs.result, + } + } + + // In this method we'll define our transition constraints; a computation is considered to + // be valid, if for all valid state transitions, transition constraints evaluate to all + // zeros, and for any invalid transition, at least one constraint evaluates to a non-zero + // value. The `frame` parameter will contain current and next states of the computation. + fn evaluate_transition>( + &self, + frame: &EvaluationFrame, + _periodic_values: &[E], + result: &mut [E], + ) { + // First, we'll read the current state, and use it to compute the expected next state + let current_state = &frame.current()[0]; + let next_state = current_state.exp(3u32.into()) + E::from(42u32); + + // Then, we'll subtract the expected next state from the actual next state; this will + // evaluate to zero if and only if the expected and actual states are the same. + result[0] = frame.next()[0] - next_state; + } + + // Here, we'll define a set of assertions about the execution trace which must be satisfied + // for the computation to be valid. Essentially, this ties computation's execution trace + // to the public inputs. + fn get_assertions(&self) -> Vec> { + // for our computation to be valid, value in column 0 at step 0 must be equal to the + // starting value, and at the last step it must be equal to the result. + let last_step = self.trace_length() - 1; + vec![ + Assertion::single(0, 0, self.start), + Assertion::single(0, last_step, self.result), + ] + } + + // This is just boilerplate which is used by the Winterfell prover/verifier to retrieve + // the context of the computation. + fn context(&self) -> &AirContext { + &self.context + } + } +} From 9b9258e13d924a8a2b9473b91e546929dbe4b348 Mon Sep 17 00:00:00 2001 From: Mariano Nicolini Date: Thu, 16 Feb 2023 10:58:09 -0300 Subject: [PATCH 42/85] Minor fixes --- prover/src/air/composition_poly.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/prover/src/air/composition_poly.rs b/prover/src/air/composition_poly.rs index a168a5d71..934bcfa10 100644 --- a/prover/src/air/composition_poly.rs +++ b/prover/src/air/composition_poly.rs @@ -38,12 +38,12 @@ pub(crate) fn get_coefficients(poly: CompositionPoly) -> Vec( air: A, - trace: TraceTable, + trace: TraceTable, pub_inputs: A::PublicInputs, ) -> Polynomial> where @@ -52,7 +52,7 @@ where let mut pub_inputs_bytes = Vec::new(); pub_inputs.write_into(&mut pub_inputs_bytes); let mut channel = - ProverChannel::>::new(&air, pub_inputs_bytes); + ProverChannel::>::new(&air, pub_inputs_bytes); let domain = StarkDomain::new(&air); // extend the main execution trace and build a Merkle tree from the extended trace From 88ba28e70d15a91be0225f36c1d9336aa5677ee9 Mon Sep 17 00:00:00 2001 From: Mariano Nicolini Date: Wed, 22 Feb 2023 12:20:52 -0300 Subject: [PATCH 43/85] Use U384 instead of U128 --- prover/src/air/composition_poly.rs | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/prover/src/air/composition_poly.rs b/prover/src/air/composition_poly.rs index 934bcfa10..a426a1414 100644 --- a/prover/src/air/composition_poly.rs +++ b/prover/src/air/composition_poly.rs @@ -1,7 +1,13 @@ use lambdaworks_math::{ - field::{element::FieldElement, fields::u128_prime_field::U128FieldElement}, + field::{ + element::FieldElement, + fields::{ + u128_prime_field::U128FieldElement, + u384_prime_field::{IsMontgomeryConfiguration, MontgomeryBackendPrimeField}, + }, + }, polynomial::Polynomial, - unsigned_integer::element::U128, + unsigned_integer::element::{U128, U384}, }; use winterfell::{ crypto::hashers::Blake3_256, @@ -15,8 +21,20 @@ use winterfell::prover::{ domain::StarkDomain, trace::commitment::TraceCommitment, }; -// Taken from winterfell, this is the modulus of a Starkfield -const M: u128 = 340282366920938463463374557953744961537; +// // Taken from winterfell, this is the modulus of a Starkfield +// const M: u128 = 340282366920938463463374557953744961537; + +#[derive(Clone, Debug)] +pub struct MontgomeryConfig; +impl IsMontgomeryConfiguration for MontgomeryConfig { + const MODULUS: U384 = + U384::from("800000000000011000000000000000000000000000000000000000000000001"); + const MP: u64 = 18446744073709551615; + const R2: U384 = U384::from("38e5f79873c0a6df47d84f8363000187545706677ffcc06cc7177d1406df18e"); +} + +type U384PrimeField = MontgomeryBackendPrimeField; +type U384FieldElement = FieldElement; /// Given a CompositionPoly from winterfell, extract its coefficients /// as a vector. @@ -45,7 +63,7 @@ pub(crate) fn get_composition_poly( air: A, trace: TraceTable, pub_inputs: A::PublicInputs, -) -> Polynomial> +) -> Polynomial where A: Air, { @@ -79,7 +97,7 @@ where let composition_poly = constraint_evaluations.into_poly().unwrap(); - let coeffs: Vec> = get_coefficients(composition_poly) + let coeffs: Vec = get_coefficients(composition_poly) .iter() .map(|c| FieldElement::new(U128::from_u128(c.0))) .collect(); From 8c45aa3da8ac15ab45557ba7b7ec34c0fae6cc7d Mon Sep 17 00:00:00 2001 From: Mariano Nicolini Date: Wed, 22 Feb 2023 14:03:21 -0300 Subject: [PATCH 44/85] Tidy up code and remove unnecessary u128 field element module --- math/src/field/fields/mod.rs | 1 - math/src/field/fields/u128_prime_field.rs | 82 ----------------------- prover/src/air/composition_poly.rs | 29 ++++---- 3 files changed, 14 insertions(+), 98 deletions(-) delete mode 100644 math/src/field/fields/u128_prime_field.rs diff --git a/math/src/field/fields/mod.rs b/math/src/field/fields/mod.rs index 68b306cf5..e79c6b653 100644 --- a/math/src/field/fields/mod.rs +++ b/math/src/field/fields/mod.rs @@ -1,4 +1,3 @@ -pub mod u128_prime_field; pub mod u384_prime_field; /// Implementation of prime fields over 64 bit unsigned integers. pub mod u64_prime_field; diff --git a/math/src/field/fields/u128_prime_field.rs b/math/src/field/fields/u128_prime_field.rs deleted file mode 100644 index 964d60b28..000000000 --- a/math/src/field/fields/u128_prime_field.rs +++ /dev/null @@ -1,82 +0,0 @@ -use crate::field::element::FieldElement; -use crate::unsigned_integer::element::U128; -use crate::{field::traits::IsField, unsigned_integer::element::UnsignedInteger}; -use std::fmt::Debug; - -/// Type representing prime fields over unsigned 64-bit integers. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct U128PrimeField; -pub type U128FieldElement = FieldElement>; - -impl U128PrimeField { - const ZERO: U128 = UnsignedInteger::from_u64(0); -} - -impl IsField for U128PrimeField { - type BaseType = U128; - - fn add(a: &Self::BaseType, b: &Self::BaseType) -> Self::BaseType { - let (sum, overflow) = UnsignedInteger::add(a, b); - if !overflow { - if sum < U128::from_u128(MODULUS) { - sum - } else { - sum - U128::from_u128(MODULUS) - } - } else { - let (diff, _) = UnsignedInteger::sub(&sum, &UnsignedInteger::<2>::from_u128(MODULUS)); - diff - } - } - - fn mul(a: &Self::BaseType, b: &Self::BaseType) -> Self::BaseType { - a * b - } - - fn sub(a: &Self::BaseType, b: &Self::BaseType) -> Self::BaseType { - if b <= a { - a - b - } else { - U128::from_u128(MODULUS) - (b - a) - } - } - - fn neg(a: &Self::BaseType) -> Self::BaseType { - if a == &Self::ZERO { - *a - } else { - U128::from_u128(MODULUS) - a - } - } - - fn inv(a: &Self::BaseType) -> Self::BaseType { - if a == &Self::ZERO { - panic!("Division by zero error.") - } - Self::pow(a, U128::from_u128(MODULUS) - Self::BaseType::from_u64(2)) - } - - fn div(a: &Self::BaseType, b: &Self::BaseType) -> Self::BaseType { - Self::mul(a, &Self::inv(b)) - } - - fn eq(a: &Self::BaseType, b: &Self::BaseType) -> bool { - a == b - } - - fn zero() -> Self::BaseType { - Self::ZERO - } - - fn one() -> Self::BaseType { - Self::from_u64(1) - } - - fn from_u64(x: u64) -> Self::BaseType { - U128::from_u64(x) - } - - fn from_base_type(x: Self::BaseType) -> Self::BaseType { - x - } -} diff --git a/prover/src/air/composition_poly.rs b/prover/src/air/composition_poly.rs index a426a1414..dedc21b66 100644 --- a/prover/src/air/composition_poly.rs +++ b/prover/src/air/composition_poly.rs @@ -1,13 +1,10 @@ use lambdaworks_math::{ field::{ element::FieldElement, - fields::{ - u128_prime_field::U128FieldElement, - u384_prime_field::{IsMontgomeryConfiguration, MontgomeryBackendPrimeField}, - }, + fields::u384_prime_field::{IsMontgomeryConfiguration, MontgomeryBackendPrimeField}, }, polynomial::Polynomial, - unsigned_integer::element::{U128, U384}, + unsigned_integer::element::U384, }; use winterfell::{ crypto::hashers::Blake3_256, @@ -75,9 +72,9 @@ where // extend the main execution trace and build a Merkle tree from the extended trace let (main_trace_lde, main_trace_tree, _main_trace_polys) = build_trace_commitment_f::< - BaseElement, - BaseElement, - Blake3_256, + A::BaseField, + A::BaseField, + Blake3_256, >(trace.main_segment(), &domain); // commit to the LDE of the main trace by writing the root of its Merkle tree into @@ -98,8 +95,8 @@ where let composition_poly = constraint_evaluations.into_poly().unwrap(); let coeffs: Vec = get_coefficients(composition_poly) - .iter() - .map(|c| FieldElement::new(U128::from_u128(c.0))) + .into_iter() + .map(|c| U384FieldElement::from(&U384::from(&c.to_string()))) .collect(); Polynomial::new(&coeffs) @@ -158,7 +155,7 @@ mod tests { // TODO: this coefficients should be checked correctly to know // the test is really passing - let expected_coeffs = vec![ + let expected_coeffs: Vec = vec![ 73805846515134368521942875729025268850u128, 251094867283236114961184226859763993364, 24104107408363517664638843184319555199, @@ -177,13 +174,15 @@ mod tests { 170130930667860970428731413388750994520, ] .into_iter() - .map(U128::from_u128) - .map(lambdaworks_math::field::element::FieldElement::new) - .collect::>(); + .map(BaseElement::new) + .map(|c| U384FieldElement::from(&U384::from(&c.to_string()))) + .collect(); let expected_poly = Polynomial::new(&expected_coeffs); - assert_eq!(get_composition_poly(air, trace, pub_inputs), expected_poly); + let result_poly = get_composition_poly(air, trace, pub_inputs); + + assert_eq!(result_poly, expected_poly); } } From f34f61dd2db027854937e851f334b87ffafd40b3 Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Wed, 22 Feb 2023 16:00:38 -0300 Subject: [PATCH 45/85] generate_vec_roots --- prover/src/air/composition_poly.rs | 32 ++++++++++++++++++-- prover/src/air/mod.rs | 2 +- prover/src/fri/fri_decommit.rs | 48 ++++++++++++++++++++++++++++++ prover/src/lib.rs | 33 ++++++++++++++++---- 4 files changed, 107 insertions(+), 8 deletions(-) diff --git a/prover/src/air/composition_poly.rs b/prover/src/air/composition_poly.rs index dedc21b66..003a7295f 100644 --- a/prover/src/air/composition_poly.rs +++ b/prover/src/air/composition_poly.rs @@ -105,6 +105,7 @@ where #[cfg(test)] mod tests { use super::*; + use simple_computation_test_utils::*; use winterfell::{FieldExtension, ProofOptions}; #[test] @@ -129,8 +130,6 @@ mod tests { ////////////////////////////////////////////////////////////////////////////////////////////////////////////// #[test] fn test_composition_poly_simple_computation() { - use simple_computation_test_utils::*; - let start = BaseElement::new(3); let n = 8; @@ -184,6 +183,35 @@ mod tests { assert_eq!(result_poly, expected_poly); } + + #[test] + fn test_prove() { + let start = BaseElement::new(3); + let n = 8; + + // Build the execution trace and . + let trace = build_do_work_trace(start, n); + let pub_inputs = PublicInputs { + start: trace.get(0, 0), + result: trace.get(0, trace.length() - 1), + }; + + // Define proof options; these will be enough for ~96-bit security level. + let options = ProofOptions::new( + 32, // number of queries + 8, // blowup factor + 0, // grinding factor + FieldExtension::None, + 8, // FRI folding factor + 128, // FRI max remainder length + ); + + let air = WorkAir::new(trace.get_info(), pub_inputs.clone(), options); + + let ret_prove = crate::prove(air, trace, pub_inputs); + + println!("{ret_prove:?}"); + } } #[cfg(test)] diff --git a/prover/src/air/mod.rs b/prover/src/air/mod.rs index 378e4540e..80e62b0a8 100644 --- a/prover/src/air/mod.rs +++ b/prover/src/air/mod.rs @@ -1 +1 @@ -mod composition_poly; +pub mod composition_poly; diff --git a/prover/src/fri/fri_decommit.rs b/prover/src/fri/fri_decommit.rs index a56977800..31debe8ea 100644 --- a/prover/src/fri/fri_decommit.rs +++ b/prover/src/fri/fri_decommit.rs @@ -75,4 +75,52 @@ mod tests { println!("count: {count}"); println!("iter: {i}"); } + + use lambdaworks_math::{ + field::fields::u384_prime_field::{IsMontgomeryConfiguration, MontgomeryBackendPrimeField}, + polynomial::Polynomial, + unsigned_integer::element::U384, + }; + + use lambdaworks_math::field::traits::IsField; + #[derive(Clone, Debug)] + + pub struct MontgomeryConfig; + impl IsMontgomeryConfiguration for MontgomeryConfig { + const MODULUS: U384 = + U384::from("800000000000011000000000000000000000000000000000000000000000001"); + const MP: u64 = 18446744073709551615; + const R2: U384 = + U384::from("38e5f79873c0a6df47d84f8363000187545706677ffcc06cc7177d1406df18e"); + } + const PRIME_GENERATOR_MONTGOMERY: U384 = U384::from("3"); + type U384PrimeField = MontgomeryBackendPrimeField; + type U384FieldElement = FieldElement; + const MODULUS_MINUS_1: U384 = + U384::from("800000000000011000000000000000000000000000000000000000000000000"); + + #[test] + fn generate_vec_roots() { + let MODULUS_MINUS_1_FIELD: U384FieldElement = U384FieldElement::new(MODULUS_MINUS_1); + + let subgroup_size = 1024_u64; + let subgroup_size_u384: U384FieldElement = 1024.into(); + let generator_field: U384FieldElement = 3.into(); + + let exp = (MODULUS_MINUS_1_FIELD) / subgroup_size_u384; + let exp_384 = *exp.value(); + + let generator_of_subgroup = generator_field.pow(exp_384); + + let mut numbers = Vec::new(); + + let mut i = 0; + for exp in 0..1024_u64 { + i += 1; + let ret = generator_of_subgroup.pow(exp); + numbers.push(ret.clone()); + } + + println!("{numbers:?}"); + } } diff --git a/prover/src/lib.rs b/prover/src/lib.rs index 271a16923..d05b605d6 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -1,13 +1,27 @@ -pub mod fri; pub mod air; +pub mod fri; +use air::composition_poly::get_composition_poly; +use lambdaworks_math::polynomial::Polynomial; +use winterfell::{ + crypto::hashers::Blake3_256, + math::{fields::f128::BaseElement, StarkField}, + prover::constraints::CompositionPoly, + Air, AuxTraceRandElements, Serializable, Trace, TraceTable, +}; + +#[derive(Debug)] pub struct StarkProof { // TODO: fill this when we know what a proof entails } -fn prove() -> StarkProof { - // * Generate trace polynomials using Winterfell +pub fn prove(air: A, trace: TraceTable, pub_inputs: A::PublicInputs) -> StarkProof +where + A: Air, +{ // * Generate composition polynomials using Winterfell + let result_poly = get_composition_poly(air, trace, pub_inputs); + // * Do Reed-Solomon on the trace and composition polynomials using some blowup factor // * Commit to both polynomials using a Merkle Tree // * Do FRI on the composition polynomials @@ -15,7 +29,16 @@ fn prove() -> StarkProof { // * For every q_i, do FRI decommitment // * For every trace polynomial t_i, provide the evaluations on every q_i, q_i * g, q_i * g^2 - StarkProof{} + StarkProof {} } -fn verify() {} +pub fn verify() {} + +#[cfg(test)] +mod tests { + use super::prove; + use winterfell::{FieldExtension, ProofOptions}; + + #[test] + fn test_prove() {} +} From b27b769dcd50cde45be06f1a6fdf4a1e5a6c8810 Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Wed, 22 Feb 2023 16:06:42 -0300 Subject: [PATCH 46/85] generate_vec_roots in lib --- prover/src/fri/fri_decommit.rs | 48 ---------------------------------- prover/src/lib.rs | 43 ++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 48 deletions(-) diff --git a/prover/src/fri/fri_decommit.rs b/prover/src/fri/fri_decommit.rs index 31debe8ea..a56977800 100644 --- a/prover/src/fri/fri_decommit.rs +++ b/prover/src/fri/fri_decommit.rs @@ -75,52 +75,4 @@ mod tests { println!("count: {count}"); println!("iter: {i}"); } - - use lambdaworks_math::{ - field::fields::u384_prime_field::{IsMontgomeryConfiguration, MontgomeryBackendPrimeField}, - polynomial::Polynomial, - unsigned_integer::element::U384, - }; - - use lambdaworks_math::field::traits::IsField; - #[derive(Clone, Debug)] - - pub struct MontgomeryConfig; - impl IsMontgomeryConfiguration for MontgomeryConfig { - const MODULUS: U384 = - U384::from("800000000000011000000000000000000000000000000000000000000000001"); - const MP: u64 = 18446744073709551615; - const R2: U384 = - U384::from("38e5f79873c0a6df47d84f8363000187545706677ffcc06cc7177d1406df18e"); - } - const PRIME_GENERATOR_MONTGOMERY: U384 = U384::from("3"); - type U384PrimeField = MontgomeryBackendPrimeField; - type U384FieldElement = FieldElement; - const MODULUS_MINUS_1: U384 = - U384::from("800000000000011000000000000000000000000000000000000000000000000"); - - #[test] - fn generate_vec_roots() { - let MODULUS_MINUS_1_FIELD: U384FieldElement = U384FieldElement::new(MODULUS_MINUS_1); - - let subgroup_size = 1024_u64; - let subgroup_size_u384: U384FieldElement = 1024.into(); - let generator_field: U384FieldElement = 3.into(); - - let exp = (MODULUS_MINUS_1_FIELD) / subgroup_size_u384; - let exp_384 = *exp.value(); - - let generator_of_subgroup = generator_field.pow(exp_384); - - let mut numbers = Vec::new(); - - let mut i = 0; - for exp in 0..1024_u64 { - i += 1; - let ret = generator_of_subgroup.pow(exp); - numbers.push(ret.clone()); - } - - println!("{numbers:?}"); - } } diff --git a/prover/src/lib.rs b/prover/src/lib.rs index d05b605d6..463b5f12a 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -10,6 +10,49 @@ use winterfell::{ Air, AuxTraceRandElements, Serializable, Trace, TraceTable, }; + +use lambdaworks_math::{ + field::fields::u384_prime_field::{IsMontgomeryConfiguration, MontgomeryBackendPrimeField}, + unsigned_integer::element::U384, +}; +use lambdaworks_math::field::element::FieldElement; + +use lambdaworks_math::field::traits::IsField; +#[derive(Clone, Debug)] +pub struct MontgomeryConfig; +impl IsMontgomeryConfiguration for MontgomeryConfig { + const MODULUS: U384 = + U384::from("800000000000011000000000000000000000000000000000000000000000001"); + const MP: u64 = 18446744073709551615; + const R2: U384 = + U384::from("38e5f79873c0a6df47d84f8363000187545706677ffcc06cc7177d1406df18e"); +} +const PRIME_GENERATOR_MONTGOMERY: U384 = U384::from("3"); +type U384PrimeField = MontgomeryBackendPrimeField; +type U384FieldElement = FieldElement; +const MODULUS_MINUS_1: U384 = + U384::from("800000000000011000000000000000000000000000000000000000000000000"); + +fn generate_vec_roots(subgroup_size: u64) -> Vec { + let MODULUS_MINUS_1_FIELD: U384FieldElement = U384FieldElement::new(MODULUS_MINUS_1); + let subgroup_size_u384: U384FieldElement = subgroup_size.into(); + let generator_field: U384FieldElement = 3.into(); + + let exp = (MODULUS_MINUS_1_FIELD) / subgroup_size_u384; + let exp_384 = *exp.value(); + + let generator_of_subgroup = generator_field.pow(exp_384); + + let mut numbers = Vec::new(); + + for exp in 0..subgroup_size { + let ret = generator_of_subgroup.pow(exp); + numbers.push(ret.clone()); + } + + numbers +} + #[derive(Debug)] pub struct StarkProof { // TODO: fill this when we know what a proof entails From 0049484abeab48e23c4a3329778100d1459d0c72 Mon Sep 17 00:00:00 2001 From: Mariano Nicolini Date: Wed, 22 Feb 2023 16:32:26 -0300 Subject: [PATCH 47/85] Return trace polynomial from get_composition_poly --- prover/src/air/composition_poly.rs | 70 ++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 23 deletions(-) diff --git a/prover/src/air/composition_poly.rs b/prover/src/air/composition_poly.rs index dedc21b66..6129b91f2 100644 --- a/prover/src/air/composition_poly.rs +++ b/prover/src/air/composition_poly.rs @@ -9,8 +9,7 @@ use lambdaworks_math::{ use winterfell::{ crypto::hashers::Blake3_256, math::{fields::f128::BaseElement, StarkField}, - prover::constraints::CompositionPoly, - Air, AuxTraceRandElements, Serializable, Trace, TraceTable, + Air, AuxTraceRandElements, Matrix, Serializable, Trace, TraceTable, }; use winterfell::prover::{ @@ -18,9 +17,6 @@ use winterfell::prover::{ domain::StarkDomain, trace::commitment::TraceCommitment, }; -// // Taken from winterfell, this is the modulus of a Starkfield -// const M: u128 = 340282366920938463463374557953744961537; - #[derive(Clone, Debug)] pub struct MontgomeryConfig; impl IsMontgomeryConfiguration for MontgomeryConfig { @@ -36,8 +32,8 @@ type U384FieldElement = FieldElement; /// Given a CompositionPoly from winterfell, extract its coefficients /// as a vector. #[allow(dead_code)] -pub(crate) fn get_coefficients(poly: CompositionPoly) -> Vec { - let data = poly.into_columns(); +pub(crate) fn get_coefficients(matrix_poly: Matrix) -> Vec { + let data = matrix_poly.into_columns(); let num_columns = data.len(); let column_len = data[0].len(); @@ -53,14 +49,23 @@ pub(crate) fn get_coefficients(poly: CompositionPoly) -> Vec) -> Vec { + get_coefficients(coeffs) + .into_iter() + .map(|c| U384FieldElement::from(&U384::from(&c.to_string()))) + .collect() +} + /// Given a trace and an AIR defined with winterfell data structures, outputs -/// a Polynomial lambdaworks native data structure. +/// a tuple of lambdaworks Polynomial data structure: +/// (composition_polynomial, trace_polynomial) #[allow(dead_code)] -pub(crate) fn get_composition_poly( +pub fn get_composition_poly( air: A, trace: TraceTable, pub_inputs: A::PublicInputs, -) -> Polynomial +) -> (Polynomial, Polynomial) where A: Air, { @@ -71,12 +76,14 @@ where let domain = StarkDomain::new(&air); // extend the main execution trace and build a Merkle tree from the extended trace - let (main_trace_lde, main_trace_tree, _main_trace_polys) = build_trace_commitment_f::< + let (main_trace_lde, main_trace_tree, main_trace_polys) = build_trace_commitment_f::< A::BaseField, A::BaseField, Blake3_256, >(trace.main_segment(), &domain); + let tp_coeffs = winter_2_lambda_felts(main_trace_polys); + // commit to the LDE of the main trace by writing the root of its Merkle tree into // the channel channel.commit_trace(*main_trace_tree.root()); @@ -92,26 +99,23 @@ where let evaluator = ConstraintEvaluator::new(&air, aux_trace_rand_elements, constraint_coeffs); let constraint_evaluations = evaluator.evaluate(trace_commitment.trace_table(), &domain); - let composition_poly = constraint_evaluations.into_poly().unwrap(); + let composition_poly = constraint_evaluations.into_poly().unwrap().data; - let coeffs: Vec = get_coefficients(composition_poly) - .into_iter() - .map(|c| U384FieldElement::from(&U384::from(&c.to_string()))) - .collect(); + let cp_coeffs: Vec = winter_2_lambda_felts(composition_poly); - Polynomial::new(&coeffs) + (Polynomial::new(&cp_coeffs), Polynomial::new(&tp_coeffs)) } #[cfg(test)] mod tests { use super::*; - use winterfell::{FieldExtension, ProofOptions}; + use winterfell::{prover::constraints::CompositionPoly, FieldExtension, ProofOptions}; #[test] fn test_get_coefficients() { let coeffs = (0u128..16).map(BaseElement::new).collect::>(); let poly = CompositionPoly::new(coeffs.clone(), 2); - let coeffs_res = get_coefficients(poly); + let coeffs_res = get_coefficients(poly.data); assert_eq!(coeffs, coeffs_res); } @@ -155,7 +159,7 @@ mod tests { // TODO: this coefficients should be checked correctly to know // the test is really passing - let expected_coeffs: Vec = vec![ + let expected_cp_coeffs: Vec = vec![ 73805846515134368521942875729025268850u128, 251094867283236114961184226859763993364, 24104107408363517664638843184319555199, @@ -178,11 +182,31 @@ mod tests { .map(|c| U384FieldElement::from(&U384::from(&c.to_string()))) .collect(); - let expected_poly = Polynomial::new(&expected_coeffs); + // TODO: this coefficients should be checked correctly to know + // the test is really passing + let expected_tp_coeffs: Vec = vec![ + 191794735525862843530824769197527107708, + 223814277178031177559040503778682093811, + 330061736062598381779522724430379788786, + 311785526618037647669831294599779434990, + 318268825200495925654723848557842782850, + 60163512837320141687261149502403704415, + 299361964383055940508518867517619087030, + 306443623720228722390524190138235769635, + ] + .into_iter() + .map(BaseElement::new) + .map(|c| U384FieldElement::from(&U384::from(&c.to_string()))) + .collect(); + + let expected_cp = Polynomial::new(&expected_cp_coeffs); + let expected_tp = Polynomial::new(&expected_tp_coeffs); - let result_poly = get_composition_poly(air, trace, pub_inputs); + let (result_cp, result_tp) = get_composition_poly(air, trace, pub_inputs); - assert_eq!(result_poly, expected_poly); + // assert polynomials are ok + assert_eq!(result_cp, expected_cp); + assert_eq!(result_tp, expected_tp); } } From 6e1e30049d4cf92ac923bab6323e88f34df19c0f Mon Sep 17 00:00:00 2001 From: Pablo Deymonnaz Date: Wed, 22 Feb 2023 16:37:36 -0300 Subject: [PATCH 48/85] coset_factor --- prover/src/air/composition_poly.rs | 2 ++ prover/src/lib.rs | 7 +++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/prover/src/air/composition_poly.rs b/prover/src/air/composition_poly.rs index 003a7295f..04c885c8e 100644 --- a/prover/src/air/composition_poly.rs +++ b/prover/src/air/composition_poly.rs @@ -210,6 +210,8 @@ mod tests { let ret_prove = crate::prove(air, trace, pub_inputs); + let roots_of_unit = crate::generate_vec_roots(1024, 1); + println!("{ret_prove:?}"); } } diff --git a/prover/src/lib.rs b/prover/src/lib.rs index 463b5f12a..1b39c9e80 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -33,10 +33,11 @@ type U384FieldElement = FieldElement; const MODULUS_MINUS_1: U384 = U384::from("800000000000011000000000000000000000000000000000000000000000000"); -fn generate_vec_roots(subgroup_size: u64) -> Vec { +pub fn generate_vec_roots(subgroup_size: u64, coset_factor: u64) -> Vec { let MODULUS_MINUS_1_FIELD: U384FieldElement = U384FieldElement::new(MODULUS_MINUS_1); let subgroup_size_u384: U384FieldElement = subgroup_size.into(); let generator_field: U384FieldElement = 3.into(); + let coset_factor_u384: U384FieldElement = coset_factor.into(); let exp = (MODULUS_MINUS_1_FIELD) / subgroup_size_u384; let exp_384 = *exp.value(); @@ -46,7 +47,7 @@ fn generate_vec_roots(subgroup_size: u64) -> Vec { let mut numbers = Vec::new(); for exp in 0..subgroup_size { - let ret = generator_of_subgroup.pow(exp); + let ret = generator_of_subgroup.pow(exp) * &coset_factor_u384; numbers.push(ret.clone()); } @@ -66,6 +67,8 @@ where let result_poly = get_composition_poly(air, trace, pub_inputs); // * Do Reed-Solomon on the trace and composition polynomials using some blowup factor + // * Generate Coset + // * Commit to both polynomials using a Merkle Tree // * Do FRI on the composition polynomials // * Sample q_1, ..., q_m using Fiat-Shamir From 58657b2c808693d3a27843c3c5677961e22fa1c7 Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Wed, 22 Feb 2023 16:55:17 -0300 Subject: [PATCH 49/85] Add coset evaluation and fri commitment steps --- prover/src/air/composition_poly.rs | 2 -- prover/src/lib.rs | 30 ++++++++++++++---------------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/prover/src/air/composition_poly.rs b/prover/src/air/composition_poly.rs index 04c885c8e..003a7295f 100644 --- a/prover/src/air/composition_poly.rs +++ b/prover/src/air/composition_poly.rs @@ -210,8 +210,6 @@ mod tests { let ret_prove = crate::prove(air, trace, pub_inputs); - let roots_of_unit = crate::generate_vec_roots(1024, 1); - println!("{ret_prove:?}"); } } diff --git a/prover/src/lib.rs b/prover/src/lib.rs index 1b39c9e80..e905eedad 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -10,25 +10,13 @@ use winterfell::{ Air, AuxTraceRandElements, Serializable, Trace, TraceTable, }; - +use lambdaworks_math::field::element::FieldElement; use lambdaworks_math::{ field::fields::u384_prime_field::{IsMontgomeryConfiguration, MontgomeryBackendPrimeField}, unsigned_integer::element::U384, }; -use lambdaworks_math::field::element::FieldElement; -use lambdaworks_math::field::traits::IsField; -#[derive(Clone, Debug)] -pub struct MontgomeryConfig; -impl IsMontgomeryConfiguration for MontgomeryConfig { - const MODULUS: U384 = - U384::from("800000000000011000000000000000000000000000000000000000000000001"); - const MP: u64 = 18446744073709551615; - const R2: U384 = - U384::from("38e5f79873c0a6df47d84f8363000187545706677ffcc06cc7177d1406df18e"); -} -const PRIME_GENERATOR_MONTGOMERY: U384 = U384::from("3"); -type U384PrimeField = MontgomeryBackendPrimeField; +type U384PrimeField = MontgomeryBackendPrimeField; type U384FieldElement = FieldElement; const MODULUS_MINUS_1: U384 = U384::from("800000000000011000000000000000000000000000000000000000000000000"); @@ -59,18 +47,28 @@ pub struct StarkProof { // TODO: fill this when we know what a proof entails } +pub use lambdaworks_crypto::merkle_tree::{DefaultHasher, MerkleTree}; +pub type FriMerkleTree = MerkleTree; + pub fn prove(air: A, trace: TraceTable, pub_inputs: A::PublicInputs) -> StarkProof where A: Air, { // * Generate composition polynomials using Winterfell - let result_poly = get_composition_poly(air, trace, pub_inputs); + let mut result_poly = get_composition_poly(air, trace, pub_inputs); + + // * Generate Coset + let roots_of_unity = crate::generate_vec_roots(1024, 1); // * Do Reed-Solomon on the trace and composition polynomials using some blowup factor - // * Generate Coset + let result_poly_lde = result_poly.evaluate_slice(roots_of_unity.as_slice()); // * Commit to both polynomials using a Merkle Tree + let commited_poly_lde = FriMerkleTree::build(result_poly_lde.as_slice()); + // * Do FRI on the composition polynomials + let lde_fri_commitment = crate::fri::fri(&mut result_poly, roots_of_unity); + // * Sample q_1, ..., q_m using Fiat-Shamir // * For every q_i, do FRI decommitment // * For every trace polynomial t_i, provide the evaluations on every q_i, q_i * g, q_i * g^2 From 1bba26f599b384958e2904da7d4ad98f7e0a7cdf Mon Sep 17 00:00:00 2001 From: Mariano Nicolini Date: Wed, 22 Feb 2023 17:31:36 -0300 Subject: [PATCH 50/85] Add result to get_cp_and_tp --- prover/Cargo.toml | 1 + prover/src/air/composition_poly.rs | 14 +++++++++----- prover/src/errors.rs | 7 +++++++ prover/src/lib.rs | 1 + 4 files changed, 18 insertions(+), 5 deletions(-) create mode 100644 prover/src/errors.rs diff --git a/prover/Cargo.toml b/prover/Cargo.toml index 0c1fd44e0..782d623da 100644 --- a/prover/Cargo.toml +++ b/prover/Cargo.toml @@ -9,3 +9,4 @@ edition = "2021" rand = "0.8.5" lambdaworks-math = { path = "../math" } winterfell = { git = "/~https://github.com/lambdaclass/winterfell", branch = "make-apis-public" } +thiserror = "1.0.38" diff --git a/prover/src/air/composition_poly.rs b/prover/src/air/composition_poly.rs index 6129b91f2..a73d3d26d 100644 --- a/prover/src/air/composition_poly.rs +++ b/prover/src/air/composition_poly.rs @@ -12,6 +12,7 @@ use winterfell::{ Air, AuxTraceRandElements, Matrix, Serializable, Trace, TraceTable, }; +use crate::errors::ProverError; use winterfell::prover::{ build_trace_commitment_f, channel::ProverChannel, constraints::ConstraintEvaluator, domain::StarkDomain, trace::commitment::TraceCommitment, @@ -61,11 +62,11 @@ pub(crate) fn winter_2_lambda_felts(coeffs: Matrix) -> Vec( +pub fn get_cp_and_tp( air: A, trace: TraceTable, pub_inputs: A::PublicInputs, -) -> (Polynomial, Polynomial) +) -> Result<(Polynomial, Polynomial), ProverError> where A: Air, { @@ -99,11 +100,14 @@ where let evaluator = ConstraintEvaluator::new(&air, aux_trace_rand_elements, constraint_coeffs); let constraint_evaluations = evaluator.evaluate(trace_commitment.trace_table(), &domain); - let composition_poly = constraint_evaluations.into_poly().unwrap().data; + let composition_poly = constraint_evaluations + .into_poly() + .map_err(|e| ProverError::CompositionPolyError(e))? + .data; let cp_coeffs: Vec = winter_2_lambda_felts(composition_poly); - (Polynomial::new(&cp_coeffs), Polynomial::new(&tp_coeffs)) + Ok((Polynomial::new(&cp_coeffs), Polynomial::new(&tp_coeffs))) } #[cfg(test)] @@ -202,7 +206,7 @@ mod tests { let expected_cp = Polynomial::new(&expected_cp_coeffs); let expected_tp = Polynomial::new(&expected_tp_coeffs); - let (result_cp, result_tp) = get_composition_poly(air, trace, pub_inputs); + let (result_cp, result_tp) = get_cp_and_tp(air, trace, pub_inputs).unwrap(); // assert polynomials are ok assert_eq!(result_cp, expected_cp); diff --git a/prover/src/errors.rs b/prover/src/errors.rs new file mode 100644 index 000000000..ad591add5 --- /dev/null +++ b/prover/src/errors.rs @@ -0,0 +1,7 @@ +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum ProverError { + #[error("The order of the polynomial is not correct")] + CompositionPolyError(winterfell::prover::ProverError), +} diff --git a/prover/src/lib.rs b/prover/src/lib.rs index 7cd57133d..3d74416ca 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -1,2 +1,3 @@ pub mod air; +pub mod errors; pub mod fri; From e363b022eae2615adfc5bc1bb693c30c65f1878b Mon Sep 17 00:00:00 2001 From: Mariano Nicolini Date: Wed, 22 Feb 2023 17:48:07 -0300 Subject: [PATCH 51/85] Change error description and module name --- prover/src/air/mod.rs | 2 +- prover/src/air/{composition_poly.rs => polynomials.rs} | 6 +++--- prover/src/errors.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) rename prover/src/air/{composition_poly.rs => polynomials.rs} (98%) diff --git a/prover/src/air/mod.rs b/prover/src/air/mod.rs index 378e4540e..9b702c864 100644 --- a/prover/src/air/mod.rs +++ b/prover/src/air/mod.rs @@ -1 +1 @@ -mod composition_poly; +mod polynomials; diff --git a/prover/src/air/composition_poly.rs b/prover/src/air/polynomials.rs similarity index 98% rename from prover/src/air/composition_poly.rs rename to prover/src/air/polynomials.rs index a73d3d26d..fa9f3bf41 100644 --- a/prover/src/air/composition_poly.rs +++ b/prover/src/air/polynomials.rs @@ -126,8 +126,8 @@ mod tests { ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // This test is made for the following computation, taken from the winterfell README example: - // "This computation starts with an element in a finite field and then, for the specified number of steps, - // cubes the element and adds value 42 to it" + // "This computation starts with an element in a finite field and then, for the specified number + // of steps, cubes the element and adds value 42 to it" // // The test setup consists of the following: // * Creating a trace of the computation @@ -136,7 +136,7 @@ mod tests { // TODO: Check that the obtained polynomial is correct. ////////////////////////////////////////////////////////////////////////////////////////////////////////////// #[test] - fn test_composition_poly_simple_computation() { + fn test_cp_and_tp_simple_computation() { use simple_computation_test_utils::*; let start = BaseElement::new(3); diff --git a/prover/src/errors.rs b/prover/src/errors.rs index ad591add5..9a1aac754 100644 --- a/prover/src/errors.rs +++ b/prover/src/errors.rs @@ -2,6 +2,6 @@ use thiserror::Error; #[derive(Debug, Error)] pub enum ProverError { - #[error("The order of the polynomial is not correct")] + #[error("Could not compute composition polynomial")] CompositionPolyError(winterfell::prover::ProverError), } From 082c553c7388aa6364a9e12ecde037aa39a719e6 Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Thu, 23 Feb 2023 14:38:18 -0300 Subject: [PATCH 52/85] Add decommitment step --- math/src/field/fields/u384_prime_field.rs | 22 ++++++++++++++++++++++ prover/src/air/mod.rs | 2 +- prover/src/air/polynomials.rs | 4 ++-- prover/src/fri/fri_decommit.rs | 9 +++++---- prover/src/fri/fri_functions.rs | 2 +- prover/src/fri/mod.rs | 22 ++++++++++++---------- prover/src/lib.rs | 11 ++++++++++- 7 files changed, 53 insertions(+), 19 deletions(-) diff --git a/math/src/field/fields/u384_prime_field.rs b/math/src/field/fields/u384_prime_field.rs index ab66de95d..917e9225b 100644 --- a/math/src/field/fields/u384_prime_field.rs +++ b/math/src/field/fields/u384_prime_field.rs @@ -126,6 +126,28 @@ where } } +// impl ByteConversion for FieldElement { +// fn to_bytes_be(&self) -> Vec { +// todo!() +// } + +// fn to_bytes_le(&self) -> Vec { +// todo!() +// } + +// fn from_bytes_be(bytes: &[u8]) -> Result +// where +// Self: std::marker::Sized { +// todo!() +// } + +// fn from_bytes_le(bytes: &[u8]) -> Result +// where +// Self: std::marker::Sized { +// todo!() +// } +// } + #[cfg(test)] mod tests { use crate::{ diff --git a/prover/src/air/mod.rs b/prover/src/air/mod.rs index cb4a7f7cf..46fafc842 100644 --- a/prover/src/air/mod.rs +++ b/prover/src/air/mod.rs @@ -1,2 +1,2 @@ -pub mod polynomials; pub mod errors; +pub mod polynomials; diff --git a/prover/src/air/polynomials.rs b/prover/src/air/polynomials.rs index 1db1b3a12..01715be68 100644 --- a/prover/src/air/polynomials.rs +++ b/prover/src/air/polynomials.rs @@ -27,8 +27,8 @@ impl IsMontgomeryConfiguration for MontgomeryConfig { const R2: U384 = U384::from("38e5f79873c0a6df47d84f8363000187545706677ffcc06cc7177d1406df18e"); } -type U384PrimeField = MontgomeryBackendPrimeField; -type U384FieldElement = FieldElement; +pub type U384PrimeField = MontgomeryBackendPrimeField; +pub type U384FieldElement = FieldElement; /// Given a CompositionPoly from winterfell, extract its coefficients /// as a vector. diff --git a/prover/src/fri/fri_decommit.rs b/prover/src/fri/fri_decommit.rs index a56977800..a63266ebb 100644 --- a/prover/src/fri/fri_decommit.rs +++ b/prover/src/fri/fri_decommit.rs @@ -1,6 +1,7 @@ use super::FE; use crate::fri::fri_commitment::FriCommitmentVec; pub use lambdaworks_crypto::fiat_shamir::transcript::Transcript; +use lambdaworks_math::traits::ByteConversion; // verifier chooses a randomness and get the index where // they want to evaluate the poly @@ -16,12 +17,12 @@ pub fn fri_decommit_layers( for commit_i in commit { let length_i = commit_i.domain.len(); index = index % length_i; - let evaluation_i = commit_i.evaluation[index]; + let evaluation_i = commit_i.evaluation[index].clone(); let auth_path = commit_i.merkle_tree.get_proof(evaluation_i).unwrap(); // symmetrical element let index_sym = (index + length_i / 2) % length_i; - let evaluation_i_sym = commit_i.evaluation[index_sym]; + let evaluation_i_sym = commit_i.evaluation[index_sym].clone(); let auth_path_sym = commit_i.merkle_tree.get_proof(evaluation_i_sym).unwrap(); // @@@ TODO! insert in transcript @@ -29,10 +30,10 @@ pub fn fri_decommit_layers( // send the last element of the polynomial let last = commit.last().unwrap(); - let last_evaluation = last.poly.coefficients[0]; + let last_evaluation = last.poly.coefficients[0].clone(); // insert last_evaluation in transcript - let last_evaluation_bytes = (*last_evaluation.value()).to_be_bytes(); + let last_evaluation_bytes = (*last_evaluation.value()).to_bytes_be(); transcript.append(&last_evaluation_bytes); } diff --git a/prover/src/fri/fri_functions.rs b/prover/src/fri/fri_functions.rs index 7640a47af..233aeccd6 100644 --- a/prover/src/fri/fri_functions.rs +++ b/prover/src/fri/fri_functions.rs @@ -9,7 +9,7 @@ fn fold_polynomial(poly: &Polynomial, beta: &FE) -> Polynomial { .iter() .skip(1) .step_by(2) - .map(|v| (*v) * beta) + .map(|v| (v.clone()) * beta) .collect(); let (even_poly, odd_poly) = Polynomial::pad_with_zero_coefficients( diff --git a/prover/src/fri/mod.rs b/prover/src/fri/mod.rs index 917857b20..1c006338e 100644 --- a/prover/src/fri/mod.rs +++ b/prover/src/fri/mod.rs @@ -1,5 +1,5 @@ mod fri_commitment; -mod fri_decommit; +pub mod fri_decommit; mod fri_functions; mod fri_merkle_tree; @@ -14,8 +14,10 @@ pub use lambdaworks_math::{ }; const ORDER: u64 = 293; -pub type F = U64PrimeField; -pub type FE = FieldElement; +// pub type F = U64PrimeField; +pub type F = crate::air::polynomials::U384PrimeField; +// pub type FE = FieldElement; +pub type FE = crate::air::polynomials::U384FieldElement; /// # Params /// @@ -36,8 +38,8 @@ pub fn fri_commitment( let merkle_tree = FriMerkleTree::build(&evaluation_i); // append the root of the merkle tree to the transcript - let root = merkle_tree.root.borrow().hash; - let root_bytes = (*root.value()).to_be_bytes(); + let root = merkle_tree.root.borrow().hash.clone(); + let root_bytes = (*root.value()).to_bytes_be(); transcript.append(&root_bytes); FriCommitment { @@ -56,8 +58,8 @@ pub fn fri(p_0: &mut Polynomial>, domain_0: &[FE]) -> FriCommitm let merkle_tree = FriMerkleTree::build(&evaluation_0); // append the root of the merkle tree to the transcript - let root = merkle_tree.root.borrow().hash; - let root_bytes = (*root.value()).to_be_bytes(); + let root = merkle_tree.root.borrow().hash.clone(); + let root_bytes = (*root.value()).to_bytes_be(); transcript.append(&root_bytes); let commitment_0 = FriCommitment { @@ -88,8 +90,8 @@ pub fn fri(p_0: &mut Polynomial>, domain_0: &[FE]) -> FriCommitm // append root of merkle tree to transcript let tree = &commitment_i.merkle_tree; - let root = tree.root.borrow().hash; - let root_bytes = (*root.value()).to_be_bytes(); + let root = tree.root.borrow().hash.clone(); + let root_bytes = (*root.value()).to_bytes_be(); transcript.append(&root_bytes); fri_commitment_list.push(commitment_i); @@ -101,7 +103,7 @@ pub fn fri(p_0: &mut Polynomial>, domain_0: &[FE]) -> FriCommitm } // append last value of the polynomial to the trasncript - let last_coef_bytes = (*last_coef.value()).to_be_bytes(); + let last_coef_bytes = (*last_coef.value()).to_bytes_be(); transcript.append(&last_coef_bytes); fri_commitment_list diff --git a/prover/src/lib.rs b/prover/src/lib.rs index c660aa7e1..d0bcabec9 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -2,6 +2,8 @@ pub mod air; pub mod fri; use air::polynomials::get_cp_and_tp; +use fri::fri_decommit::fri_decommit_layers; +use lambdaworks_crypto::fiat_shamir::transcript::Transcript; use lambdaworks_math::polynomial::Polynomial; use winterfell::{ crypto::hashers::Blake3_256, @@ -54,6 +56,7 @@ pub fn prove(air: A, trace: TraceTable, pub_inputs: A::PublicIn where A: Air, { + let mut transcript = Transcript::new(); // * Generate composition polynomials using Winterfell let (mut composition_poly, mut trace_poly) = get_cp_and_tp(air, trace, pub_inputs).unwrap(); @@ -67,10 +70,16 @@ where let commited_poly_lde = FriMerkleTree::build(composition_poly_lde.as_slice()); // * Do FRI on the composition polynomials - let lde_fri_commitment = crate::fri::fri(&mut composition_poly, roots_of_unity); + let lde_fri_commitment = crate::fri::fri(&mut composition_poly, &roots_of_unity); // * Sample q_1, ..., q_m using Fiat-Shamir + // let q_1 = transcript.challenge(); + // TODO: Do this with Fiat Shamir + let q_1: usize = rand::random(); + // * For every q_i, do FRI decommitment + let decommitment = fri_decommit_layers(&lde_fri_commitment, q_1, &mut transcript); + // * For every trace polynomial t_i, provide the evaluations on every q_i, q_i * g, q_i * g^2 StarkProof {} From f343e1a22816c0971a2da4f43c2a35e2abba296e Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Thu, 23 Feb 2023 15:18:52 -0300 Subject: [PATCH 53/85] Start filling the stark proof struct --- prover/src/lib.rs | 42 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/prover/src/lib.rs b/prover/src/lib.rs index d0bcabec9..824ab8199 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -23,7 +23,10 @@ type U384FieldElement = FieldElement; const MODULUS_MINUS_1: U384 = U384::from("800000000000011000000000000000000000000000000000000000000000000"); -pub fn generate_vec_roots(subgroup_size: u64, coset_factor: u64) -> Vec { +pub fn generate_vec_roots( + subgroup_size: u64, + coset_factor: u64, +) -> (Vec, U384FieldElement) { let MODULUS_MINUS_1_FIELD: U384FieldElement = U384FieldElement::new(MODULUS_MINUS_1); let subgroup_size_u384: U384FieldElement = subgroup_size.into(); let generator_field: U384FieldElement = 3.into(); @@ -41,17 +44,21 @@ pub fn generate_vec_roots(subgroup_size: u64, coset_factor: u64) -> Vec, } pub use lambdaworks_crypto::merkle_tree::{DefaultHasher, MerkleTree}; pub type FriMerkleTree = MerkleTree; +// TODO: Our Fiat Shamir implementation is not even close to providing what we need for proving/verifying. pub fn prove(air: A, trace: TraceTable, pub_inputs: A::PublicInputs) -> StarkProof where A: Air, @@ -61,30 +68,53 @@ where let (mut composition_poly, mut trace_poly) = get_cp_and_tp(air, trace, pub_inputs).unwrap(); // * Generate Coset - let roots_of_unity = crate::generate_vec_roots(1024, 1); + let (roots_of_unity, primitive_root) = crate::generate_vec_roots(1024, 1); // * Do Reed-Solomon on the trace and composition polynomials using some blowup factor let composition_poly_lde = composition_poly.evaluate_slice(roots_of_unity.as_slice()); + let trace_poly_lde = trace_poly.evaluate_slice(roots_of_unity.as_slice()); // * Commit to both polynomials using a Merkle Tree - let commited_poly_lde = FriMerkleTree::build(composition_poly_lde.as_slice()); + let commited_composition_poly_lde = FriMerkleTree::build(composition_poly_lde.as_slice()); + let commited_trace_poly_lde = FriMerkleTree::build(&trace_poly_lde.as_slice()); // * Do FRI on the composition polynomials let lde_fri_commitment = crate::fri::fri(&mut composition_poly, &roots_of_unity); // * Sample q_1, ..., q_m using Fiat-Shamir // let q_1 = transcript.challenge(); - // TODO: Do this with Fiat Shamir let q_1: usize = rand::random(); // * For every q_i, do FRI decommitment let decommitment = fri_decommit_layers(&lde_fri_commitment, q_1, &mut transcript); // * For every trace polynomial t_i, provide the evaluations on every q_i, q_i * g, q_i * g^2 + let evaluation_points = vec![ + U384FieldElement::from(q_1 as u64), + U384FieldElement::from(q_1 as u64) * primitive_root.clone(), + U384FieldElement::from(q_1 as u64) * primitive_root.pow(2_usize), + ]; - StarkProof {} + let trace_evaluations = trace_poly.evaluate_slice(&evaluation_points); + + let trace_root = commited_trace_poly_lde.root.borrow().clone().hash; + let composition_poly_root = commited_composition_poly_lde.root.borrow().clone().hash; + + StarkProof { + trace_root, + composition_poly_root, + } } +/* +- Trace merkle tree root +- Composition poly merkle tree root +- Fri Layers merkle tree roots +- Trace Polys merkle paths +- Composition poly merkle paths +- Fri layer polys evaluations (in the q_i's and -q_i's) +*/ + pub fn verify() {} #[cfg(test)] From 290114e89b619c0cda7aa810e0d01ff11844b59b Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Thu, 23 Feb 2023 17:58:20 -0300 Subject: [PATCH 54/85] Small comments --- prover/src/fri/fri_decommit.rs | 12 +++--------- prover/src/fri/mod.rs | 3 --- prover/src/lib.rs | 5 +++-- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/prover/src/fri/fri_decommit.rs b/prover/src/fri/fri_decommit.rs index a63266ebb..a550009be 100644 --- a/prover/src/fri/fri_decommit.rs +++ b/prover/src/fri/fri_decommit.rs @@ -5,11 +5,7 @@ use lambdaworks_math::traits::ByteConversion; // verifier chooses a randomness and get the index where // they want to evaluate the poly -pub fn fri_decommit_layers( - commit: &FriCommitmentVec, - index_to_verify: usize, - transcript: &mut Transcript, -) { +pub fn fri_decommit_layers(commit: &FriCommitmentVec, index_to_verify: usize) { let mut index = index_to_verify; // with every element of the commit, we look for that one in @@ -24,17 +20,15 @@ pub fn fri_decommit_layers( let index_sym = (index + length_i / 2) % length_i; let evaluation_i_sym = commit_i.evaluation[index_sym].clone(); let auth_path_sym = commit_i.merkle_tree.get_proof(evaluation_i_sym).unwrap(); - - // @@@ TODO! insert in transcript } // send the last element of the polynomial let last = commit.last().unwrap(); let last_evaluation = last.poly.coefficients[0].clone(); - // insert last_evaluation in transcript let last_evaluation_bytes = (*last_evaluation.value()).to_bytes_be(); - transcript.append(&last_evaluation_bytes); + + // TDOO ⚠️⚠️⚠️⚠️ @@@@@ return auth_path and auth_path_sym @@@@@ ⚠️⚠️⚠️⚠️ } // Integration test: diff --git a/prover/src/fri/mod.rs b/prover/src/fri/mod.rs index 1c006338e..1888027b2 100644 --- a/prover/src/fri/mod.rs +++ b/prover/src/fri/mod.rs @@ -13,10 +13,7 @@ pub use lambdaworks_math::{ polynomial::Polynomial, }; -const ORDER: u64 = 293; -// pub type F = U64PrimeField; pub type F = crate::air::polynomials::U384PrimeField; -// pub type FE = FieldElement; pub type FE = crate::air::polynomials::U384FieldElement; /// # Params diff --git a/prover/src/lib.rs b/prover/src/lib.rs index 824ab8199..d5c1a979a 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -83,10 +83,11 @@ where // * Sample q_1, ..., q_m using Fiat-Shamir // let q_1 = transcript.challenge(); + // @@@@@@@@@@@@@@@@@@@@@@ let q_1: usize = rand::random(); // * For every q_i, do FRI decommitment - let decommitment = fri_decommit_layers(&lde_fri_commitment, q_1, &mut transcript); + let decommitment = fri_decommit_layers(&lde_fri_commitment, q_1); // * For every trace polynomial t_i, provide the evaluations on every q_i, q_i * g, q_i * g^2 let evaluation_points = vec![ @@ -115,7 +116,7 @@ where - Fri layer polys evaluations (in the q_i's and -q_i's) */ -pub fn verify() {} +pub fn verify(proof: StarkProof) {} #[cfg(test)] mod tests { From 331df415dc990473c6e4c06366588506f84f4658 Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Fri, 24 Feb 2023 14:57:34 -0300 Subject: [PATCH 55/85] Add first verifier step --- crypto/src/merkle_tree/mod.rs | 31 ++++++------ prover/src/lib.rs | 89 ++++++++++++++++++++++++++++------- 2 files changed, 90 insertions(+), 30 deletions(-) diff --git a/crypto/src/merkle_tree/mod.rs b/crypto/src/merkle_tree/mod.rs index 8476debbb..6008ef076 100644 --- a/crypto/src/merkle_tree/mod.rs +++ b/crypto/src/merkle_tree/mod.rs @@ -90,19 +90,6 @@ impl + Clone> MerkleTree { None } - - pub fn verify(proof: &Proof, root_hash: FieldElement) -> bool { - let mut hashed_value = proof.hasher.hash_one(proof.value.clone()); - - for node in proof.merkle_path.iter() { - if let Some(sibiling) = &node.borrow().sibiling { - hashed_value = proof - .hasher - .hash_two(hashed_value, sibiling.borrow().hash.clone()); - } - } - hashed_value == root_hash - } } fn hash_leafs>( @@ -159,12 +146,28 @@ fn build_merkle_path( merkle_path.to_vec() } +#[derive(Debug)] pub struct Proof> { - value: FieldElement, + pub value: FieldElement, merkle_path: Vec>, hasher: H, } +impl> Proof { + pub fn verify(&self, root_hash: FieldElement) -> bool { + let mut hashed_value = self.hasher.hash_one(self.value.clone()); + + for node in self.merkle_path.iter() { + if let Some(sibiling) = &node.borrow().sibiling { + hashed_value = self + .hasher + .hash_two(hashed_value, sibiling.borrow().hash.clone()); + } + } + hashed_value == root_hash + } +} + pub type TreeNode = Rc>>; fn build_tree_node(hash: FieldElement) -> TreeNode { diff --git a/prover/src/lib.rs b/prover/src/lib.rs index d5c1a979a..13248272b 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -3,7 +3,7 @@ pub mod fri; use air::polynomials::get_cp_and_tp; use fri::fri_decommit::fri_decommit_layers; -use lambdaworks_crypto::fiat_shamir::transcript::Transcript; +use lambdaworks_crypto::{fiat_shamir::transcript::Transcript, merkle_tree::Proof}; use lambdaworks_math::polynomial::Polynomial; use winterfell::{ crypto::hashers::Blake3_256, @@ -48,18 +48,26 @@ pub fn generate_vec_roots( } #[derive(Debug)] -pub struct StarkProof { +pub struct StarkQueryProof { // TODO: fill this when we know what a proof entails - trace_root: U384FieldElement, + pub trace_lde_poly_root: U384FieldElement, + pub trace_lde_poly_evaluations: Vec, + /// Merkle paths for the trace polynomial evaluations + pub trace_lde_poly_inclusion_proofs: Vec>, + composition_poly_root: U384FieldElement, - // fri_layer_roots: Vec, } +pub type StarkProof = Vec; + pub use lambdaworks_crypto::merkle_tree::{DefaultHasher, MerkleTree}; pub type FriMerkleTree = MerkleTree; -// TODO: Our Fiat Shamir implementation is not even close to providing what we need for proving/verifying. -pub fn prove(air: A, trace: TraceTable, pub_inputs: A::PublicInputs) -> StarkProof +pub fn prove( + air: A, + trace: TraceTable, + pub_inputs: A::PublicInputs, +) -> StarkQueryProof where A: Air, { @@ -75,8 +83,8 @@ where let trace_poly_lde = trace_poly.evaluate_slice(roots_of_unity.as_slice()); // * Commit to both polynomials using a Merkle Tree - let commited_composition_poly_lde = FriMerkleTree::build(composition_poly_lde.as_slice()); - let commited_trace_poly_lde = FriMerkleTree::build(&trace_poly_lde.as_slice()); + let composition_poly_lde_merkle_tree = FriMerkleTree::build(composition_poly_lde.as_slice()); + let trace_poly_lde_merkle_tree = FriMerkleTree::build(&trace_poly_lde.as_slice()); // * Do FRI on the composition polynomials let lde_fri_commitment = crate::fri::fri(&mut composition_poly, &roots_of_unity); @@ -84,25 +92,47 @@ where // * Sample q_1, ..., q_m using Fiat-Shamir // let q_1 = transcript.challenge(); // @@@@@@@@@@@@@@@@@@@@@@ - let q_1: usize = rand::random(); + let q_1: usize = 2; // * For every q_i, do FRI decommitment let decommitment = fri_decommit_layers(&lde_fri_commitment, q_1); // * For every trace polynomial t_i, provide the evaluations on every q_i, q_i * g, q_i * g^2 + // TODO: Check the evaluation points corresponding to our program (it's not fibonacci). let evaluation_points = vec![ U384FieldElement::from(q_1 as u64), U384FieldElement::from(q_1 as u64) * primitive_root.clone(), U384FieldElement::from(q_1 as u64) * primitive_root.pow(2_usize), ]; - let trace_evaluations = trace_poly.evaluate_slice(&evaluation_points); - - let trace_root = commited_trace_poly_lde.root.borrow().clone().hash; - let composition_poly_root = commited_composition_poly_lde.root.borrow().clone().hash; + let trace_lde_poly_evaluations = trace_poly.evaluate_slice(&evaluation_points); + + let mut merkle_paths = vec![]; + + merkle_paths.push( + trace_poly_lde_merkle_tree + .get_proof_by_pos(q_1, &evaluation_points[0]) + .unwrap(), + ); + merkle_paths.push( + trace_poly_lde_merkle_tree + .get_proof_by_pos(q_1 + 1, &evaluation_points[1]) + .unwrap(), + ); + merkle_paths.push( + trace_poly_lde_merkle_tree + .get_proof_by_pos(q_1 + 2, &evaluation_points[2]) + .unwrap(), + ); + + let trace_root = trace_poly_lde_merkle_tree.root.borrow().clone().hash; + let composition_poly_root = composition_poly_lde_merkle_tree.root.borrow().clone().hash; + + StarkQueryProof { + trace_lde_poly_root: trace_root, + trace_lde_poly_evaluations, + trace_lde_poly_inclusion_proofs: merkle_paths, - StarkProof { - trace_root, composition_poly_root, } } @@ -116,7 +146,34 @@ where - Fri layer polys evaluations (in the q_i's and -q_i's) */ -pub fn verify(proof: StarkProof) {} +/* + - Check merkle paths for trace poly lde evaluations +*/ +pub fn verify(proof: StarkQueryProof) -> bool { + let trace_poly_root = proof.trace_lde_poly_root; + + // TODO: Use Fiat Shamir + let q_1: u64 = 2; + let (_roots_of_unity, primitive_root) = crate::generate_vec_roots(1024, 1); + // TODO: This is hardcoded, it should not be. + let evaluation_points = vec![ + U384FieldElement::from(q_1), + U384FieldElement::from(q_1) * primitive_root.clone(), + U384FieldElement::from(q_1) * primitive_root.pow(2_usize), + ]; + + for (merkle_proof, evaluation_point) in proof + .trace_lde_poly_inclusion_proofs + .iter() + .zip(evaluation_points) + { + if merkle_proof.value != evaluation_point || !merkle_proof.verify(trace_poly_root.clone()) { + return false; + } + } + + return true; +} #[cfg(test)] mod tests { From a387a5e5c4b8b88d859a847fdd41f02536a1ee47 Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Fri, 24 Feb 2023 18:16:17 -0300 Subject: [PATCH 56/85] Switch to hardcoded fibonacci trace --- prover/src/fri/fri_decommit.rs | 28 ++++++-- prover/src/lib.rs | 113 +++++++++++++++++++++------------ 2 files changed, 96 insertions(+), 45 deletions(-) diff --git a/prover/src/fri/fri_decommit.rs b/prover/src/fri/fri_decommit.rs index a550009be..5bb41ef77 100644 --- a/prover/src/fri/fri_decommit.rs +++ b/prover/src/fri/fri_decommit.rs @@ -1,13 +1,29 @@ use super::FE; -use crate::fri::fri_commitment::FriCommitmentVec; +use crate::{fri::fri_commitment::FriCommitmentVec, U384FieldElement, U384PrimeField}; pub use lambdaworks_crypto::fiat_shamir::transcript::Transcript; -use lambdaworks_math::traits::ByteConversion; +use lambdaworks_crypto::{ + hash::traits::IsCryptoHash, + merkle_tree::{DefaultHasher, Proof}, +}; +use lambdaworks_math::{field::traits::IsField, traits::ByteConversion}; // verifier chooses a randomness and get the index where // they want to evaluate the poly -pub fn fri_decommit_layers(commit: &FriCommitmentVec, index_to_verify: usize) { +// TODO: encapsulate the return type of this function in a struct. +pub fn fri_decommit_layers( + commit: &FriCommitmentVec, + index_to_verify: usize, +) -> ( + Vec<( + Proof, + Proof, + )>, + U384FieldElement, +) { let mut index = index_to_verify; + let mut ret = vec![]; + // with every element of the commit, we look for that one in // the merkle tree and get the corresponding element for commit_i in commit { @@ -20,15 +36,15 @@ pub fn fri_decommit_layers(commit: &FriCommitmentVec, index_to_verify: usize let index_sym = (index + length_i / 2) % length_i; let evaluation_i_sym = commit_i.evaluation[index_sym].clone(); let auth_path_sym = commit_i.merkle_tree.get_proof(evaluation_i_sym).unwrap(); + + ret.push((auth_path, auth_path_sym)); } // send the last element of the polynomial let last = commit.last().unwrap(); let last_evaluation = last.poly.coefficients[0].clone(); - let last_evaluation_bytes = (*last_evaluation.value()).to_bytes_be(); - - // TDOO ⚠️⚠️⚠️⚠️ @@@@@ return auth_path and auth_path_sym @@@@@ ⚠️⚠️⚠️⚠️ + return (ret, last_evaluation); } // Integration test: diff --git a/prover/src/lib.rs b/prover/src/lib.rs index 13248272b..0ad0418cf 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -54,8 +54,15 @@ pub struct StarkQueryProof { pub trace_lde_poly_evaluations: Vec, /// Merkle paths for the trace polynomial evaluations pub trace_lde_poly_inclusion_proofs: Vec>, - - composition_poly_root: U384FieldElement, + pub composition_poly_lde_evaluations: Vec, + + // composition_poly_root: U384FieldElement, + pub fri_layers_merkle_roots: Vec, + pub fri_layers_merkle_proofs: Vec<( + Proof, + Proof, + )>, + pub last_fri_layer_evaluation: U384FieldElement, } pub type StarkProof = Vec; @@ -63,31 +70,55 @@ pub type StarkProof = Vec; pub use lambdaworks_crypto::merkle_tree::{DefaultHasher, MerkleTree}; pub type FriMerkleTree = MerkleTree; +pub fn fibonacci_trace(initial_values: [U384FieldElement; 2]) -> Vec { + let mut ret = vec![]; + + ret.push(initial_values[0].clone()); + ret.push(initial_values[1].clone()); + + for i in 2..32 { + ret.push(ret[i - 1].clone() + ret[i - 2].clone()); + } + + ret +} + pub fn prove( - air: A, - trace: TraceTable, - pub_inputs: A::PublicInputs, + // air: A, + // trace: TraceTable, + // pub_inputs: A::PublicInputs, + pub_inputs: [U384FieldElement; 2], ) -> StarkQueryProof where A: Air, { let mut transcript = Transcript::new(); // * Generate composition polynomials using Winterfell - let (mut composition_poly, mut trace_poly) = get_cp_and_tp(air, trace, pub_inputs).unwrap(); + // let (mut composition_poly, mut trace_poly) = get_cp_and_tp(air, trace, pub_inputs).unwrap(); // * Generate Coset - let (roots_of_unity, primitive_root) = crate::generate_vec_roots(1024, 1); + let (roots_of_unity, _primitive_root) = crate::generate_vec_roots(32, 1); + let (lde_roots_of_unity, lde_primitive_root) = crate::generate_vec_roots(1024, 1); + + let trace = fibonacci_trace(pub_inputs); + let mut trace_poly = Polynomial::interpolate(&roots_of_unity, &trace); + + let mut composition_poly = Polynomial::new(&vec![ + -U384FieldElement::new(U384::from("1")), + -U384FieldElement::new(U384::from("1")), + U384FieldElement::new(U384::from("1")), + ]); // * Do Reed-Solomon on the trace and composition polynomials using some blowup factor - let composition_poly_lde = composition_poly.evaluate_slice(roots_of_unity.as_slice()); - let trace_poly_lde = trace_poly.evaluate_slice(roots_of_unity.as_slice()); + let composition_poly_lde = composition_poly.evaluate_slice(lde_roots_of_unity.as_slice()); + let trace_poly_lde = trace_poly.evaluate_slice(lde_roots_of_unity.as_slice()); // * Commit to both polynomials using a Merkle Tree let composition_poly_lde_merkle_tree = FriMerkleTree::build(composition_poly_lde.as_slice()); let trace_poly_lde_merkle_tree = FriMerkleTree::build(&trace_poly_lde.as_slice()); // * Do FRI on the composition polynomials - let lde_fri_commitment = crate::fri::fri(&mut composition_poly, &roots_of_unity); + let lde_fri_commitment = crate::fri::fri(&mut composition_poly, &lde_roots_of_unity); // * Sample q_1, ..., q_m using Fiat-Shamir // let q_1 = transcript.challenge(); @@ -95,17 +126,20 @@ where let q_1: usize = 2; // * For every q_i, do FRI decommitment - let decommitment = fri_decommit_layers(&lde_fri_commitment, q_1); + let (fri_layers_merkle_proofs, last_fri_layer_evaluation) = + fri_decommit_layers(&lde_fri_commitment, q_1); // * For every trace polynomial t_i, provide the evaluations on every q_i, q_i * g, q_i * g^2 // TODO: Check the evaluation points corresponding to our program (it's not fibonacci). let evaluation_points = vec![ U384FieldElement::from(q_1 as u64), - U384FieldElement::from(q_1 as u64) * primitive_root.clone(), - U384FieldElement::from(q_1 as u64) * primitive_root.pow(2_usize), + U384FieldElement::from(q_1 as u64) * lde_primitive_root.clone(), + U384FieldElement::from(q_1 as u64) * lde_primitive_root.pow(2_usize), ]; let trace_lde_poly_evaluations = trace_poly.evaluate_slice(&evaluation_points); + let composition_poly_lde_evaluations = + composition_poly.evaluate_slice(&[evaluation_points[0].clone()]); let mut merkle_paths = vec![]; @@ -126,29 +160,25 @@ where ); let trace_root = trace_poly_lde_merkle_tree.root.borrow().clone().hash; - let composition_poly_root = composition_poly_lde_merkle_tree.root.borrow().clone().hash; + // let composition_poly_root = composition_poly_lde_merkle_tree.root.borrow().clone().hash; + + let fri_layers_merkle_roots: Vec = lde_fri_commitment + .iter() + .map(|fri_commitment| fri_commitment.merkle_tree.root.borrow().hash.clone()) + .collect(); StarkQueryProof { trace_lde_poly_root: trace_root, trace_lde_poly_evaluations, trace_lde_poly_inclusion_proofs: merkle_paths, - - composition_poly_root, + composition_poly_lde_evaluations: composition_poly_lde_evaluations, + fri_layers_merkle_proofs: fri_layers_merkle_proofs, + fri_layers_merkle_roots: fri_layers_merkle_roots, + last_fri_layer_evaluation: last_fri_layer_evaluation, + // composition_poly_root, } } -/* -- Trace merkle tree root -- Composition poly merkle tree root -- Fri Layers merkle tree roots -- Trace Polys merkle paths -- Composition poly merkle paths -- Fri layer polys evaluations (in the q_i's and -q_i's) -*/ - -/* - - Check merkle paths for trace poly lde evaluations -*/ pub fn verify(proof: StarkQueryProof) -> bool { let trace_poly_root = proof.trace_lde_poly_root; @@ -156,20 +186,25 @@ pub fn verify(proof: StarkQueryProof) -> bool { let q_1: u64 = 2; let (_roots_of_unity, primitive_root) = crate::generate_vec_roots(1024, 1); // TODO: This is hardcoded, it should not be. - let evaluation_points = vec![ - U384FieldElement::from(q_1), - U384FieldElement::from(q_1) * primitive_root.clone(), - U384FieldElement::from(q_1) * primitive_root.pow(2_usize), - ]; - for (merkle_proof, evaluation_point) in proof - .trace_lde_poly_inclusion_proofs - .iter() - .zip(evaluation_points) - { - if merkle_proof.value != evaluation_point || !merkle_proof.verify(trace_poly_root.clone()) { + let evaluations = proof.trace_lde_poly_evaluations; + + // TODO: These could be multiple evaluations depending on how many q_i are sample with Fiat Shamir + let composition_poly_lde_evaluation = proof.composition_poly_lde_evaluations[0].clone(); + + if composition_poly_lde_evaluation != &evaluations[2] - &evaluations[1] - &evaluations[0] { + return false; + } + + // TODO: Check evaluation is the correct one. + for merkle_proof in proof.trace_lde_poly_inclusion_proofs { + if !merkle_proof.verify(trace_poly_root.clone()) { return false; } + + // if !(composition_poly.evaluate(evaluation_point) == merkle_proof.value) { + // return false; + // } } return true; From f340b5aa99b68aa92b8bd4fd7b64efc0a244d2c0 Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Mon, 27 Feb 2023 12:57:40 -0300 Subject: [PATCH 57/85] Start FRI verification step --- crypto/src/merkle_tree/mod.rs | 2 +- prover/src/fri/fri_decommit.rs | 31 +++++++----- prover/src/lib.rs | 87 ++++++++++++++++++++++++++-------- 3 files changed, 87 insertions(+), 33 deletions(-) diff --git a/crypto/src/merkle_tree/mod.rs b/crypto/src/merkle_tree/mod.rs index 6008ef076..aefde79d4 100644 --- a/crypto/src/merkle_tree/mod.rs +++ b/crypto/src/merkle_tree/mod.rs @@ -146,7 +146,7 @@ fn build_merkle_path( merkle_path.to_vec() } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Proof> { pub value: FieldElement, merkle_path: Vec>, diff --git a/prover/src/fri/fri_decommit.rs b/prover/src/fri/fri_decommit.rs index 5bb41ef77..f3ea0e0c3 100644 --- a/prover/src/fri/fri_decommit.rs +++ b/prover/src/fri/fri_decommit.rs @@ -5,24 +5,30 @@ use lambdaworks_crypto::{ hash::traits::IsCryptoHash, merkle_tree::{DefaultHasher, Proof}, }; -use lambdaworks_math::{field::traits::IsField, traits::ByteConversion}; +use lambdaworks_math::{ + field::traits::IsField, traits::ByteConversion, unsigned_integer::element::U384, +}; + +#[derive(Debug, Clone)] +pub struct FriDecommitment { + pub layer_merkle_paths: Vec<( + Proof, + Proof, + )>, + pub last_layer_evaluation: U384FieldElement, +} // verifier chooses a randomness and get the index where // they want to evaluate the poly // TODO: encapsulate the return type of this function in a struct. +// This returns a list of authentication paths for evaluations on points and their symmetric counterparts. pub fn fri_decommit_layers( commit: &FriCommitmentVec, index_to_verify: usize, -) -> ( - Vec<( - Proof, - Proof, - )>, - U384FieldElement, -) { +) -> FriDecommitment { let mut index = index_to_verify; - let mut ret = vec![]; + let mut layer_merkle_paths = vec![]; // with every element of the commit, we look for that one in // the merkle tree and get the corresponding element @@ -37,14 +43,17 @@ pub fn fri_decommit_layers( let evaluation_i_sym = commit_i.evaluation[index_sym].clone(); let auth_path_sym = commit_i.merkle_tree.get_proof(evaluation_i_sym).unwrap(); - ret.push((auth_path, auth_path_sym)); + layer_merkle_paths.push((auth_path, auth_path_sym)); } // send the last element of the polynomial let last = commit.last().unwrap(); let last_evaluation = last.poly.coefficients[0].clone(); - return (ret, last_evaluation); + return FriDecommitment { + layer_merkle_paths: layer_merkle_paths, + last_layer_evaluation: last_evaluation, + }; } // Integration test: diff --git a/prover/src/lib.rs b/prover/src/lib.rs index 0ad0418cf..0266760bc 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -2,9 +2,10 @@ pub mod air; pub mod fri; use air::polynomials::get_cp_and_tp; -use fri::fri_decommit::fri_decommit_layers; +use fri::fri_decommit::{fri_decommit_layers, FriDecommitment}; use lambdaworks_crypto::{fiat_shamir::transcript::Transcript, merkle_tree::Proof}; use lambdaworks_math::polynomial::Polynomial; +use thiserror::__private::AsDynError; use winterfell::{ crypto::hashers::Blake3_256, math::{fields::f128::BaseElement, StarkField}, @@ -47,7 +48,7 @@ pub fn generate_vec_roots( (numbers, generator_of_subgroup) } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct StarkQueryProof { // TODO: fill this when we know what a proof entails pub trace_lde_poly_root: U384FieldElement, @@ -58,11 +59,12 @@ pub struct StarkQueryProof { // composition_poly_root: U384FieldElement, pub fri_layers_merkle_roots: Vec, - pub fri_layers_merkle_proofs: Vec<( - Proof, - Proof, - )>, - pub last_fri_layer_evaluation: U384FieldElement, + // pub fri_layers_merkle_proofs: Vec<( + // Proof, + // Proof, + // )>, + // pub last_fri_layer_evaluation: U384FieldElement, + pub fri_decommitment: FriDecommitment, } pub type StarkProof = Vec; @@ -92,7 +94,7 @@ pub fn prove( where A: Air, { - let mut transcript = Transcript::new(); + // let mut transcript = Transcript::new(); // * Generate composition polynomials using Winterfell // let (mut composition_poly, mut trace_poly) = get_cp_and_tp(air, trace, pub_inputs).unwrap(); @@ -126,11 +128,9 @@ where let q_1: usize = 2; // * For every q_i, do FRI decommitment - let (fri_layers_merkle_proofs, last_fri_layer_evaluation) = - fri_decommit_layers(&lde_fri_commitment, q_1); + let fri_decommitment = fri_decommit_layers(&lde_fri_commitment, q_1); // * For every trace polynomial t_i, provide the evaluations on every q_i, q_i * g, q_i * g^2 - // TODO: Check the evaluation points corresponding to our program (it's not fibonacci). let evaluation_points = vec![ U384FieldElement::from(q_1 as u64), U384FieldElement::from(q_1 as u64) * lde_primitive_root.clone(), @@ -172,10 +172,8 @@ where trace_lde_poly_evaluations, trace_lde_poly_inclusion_proofs: merkle_paths, composition_poly_lde_evaluations: composition_poly_lde_evaluations, - fri_layers_merkle_proofs: fri_layers_merkle_proofs, fri_layers_merkle_roots: fri_layers_merkle_roots, - last_fri_layer_evaluation: last_fri_layer_evaluation, - // composition_poly_root, + fri_decommitment: fri_decommitment, } } @@ -185,31 +183,78 @@ pub fn verify(proof: StarkQueryProof) -> bool { // TODO: Use Fiat Shamir let q_1: u64 = 2; let (_roots_of_unity, primitive_root) = crate::generate_vec_roots(1024, 1); - // TODO: This is hardcoded, it should not be. - let evaluations = proof.trace_lde_poly_evaluations; - // TODO: These could be multiple evaluations depending on how many q_i are sample with Fiat Shamir + // TODO: These could be multiple evaluations depending on how many q_i are sampled with Fiat Shamir let composition_poly_lde_evaluation = proof.composition_poly_lde_evaluations[0].clone(); if composition_poly_lde_evaluation != &evaluations[2] - &evaluations[1] - &evaluations[0] { return false; } - // TODO: Check evaluation is the correct one. for merkle_proof in proof.trace_lde_poly_inclusion_proofs { if !merkle_proof.verify(trace_poly_root.clone()) { return false; } + } + + // FRI VERIFYING BEGINS HERE + + // // composition_poly_root: U384FieldElement, + // pub fri_layers_merkle_roots: Vec, + // pub fri_layers_merkle_proofs: Vec<( + // Proof, + // Proof, + // )>, + // pub last_fri_layer_evaluation: U384FieldElement, + + for (index, (fri_layer_merkle_root, (fri_layer_auth_path, fri_layer_auth_path_symmetric))) in + proof + .fri_layers_merkle_roots + .iter() + .zip(proof.fri_decommitment.layer_merkle_paths) + .enumerate() + { + if !fri_layer_auth_path.verify(fri_layer_merkle_root.clone()) { + return false; + } + + if !fri_layer_auth_path_symmetric.verify(fri_layer_merkle_root.clone()) { + return false; + } + + // TODO: use Fiat Shamir + let beta: u64 = 2; - // if !(composition_poly.evaluate(evaluation_point) == merkle_proof.value) { - // return false; - // } + let (previous_auth_path, previous_auth_path_symmetric) = + proof.fri_decommitment.layer_merkle_paths[index - 1]; + // let (next_auth_path, next_auth_path_symmetric) = proof.fri_decommitment.layer_merkle_paths.iter().peekable().peek().unwrap(); + + // let v = (previous_auth_path.value + previous_auth_path_symmetric.value) / U384FieldElement::new(U384::from("2")) + // + U384FieldElement::new(U384::from_u64(beta)) * (previous_auth_path.value - previous_auth_path_symmetric.value) / + // (U384FieldElement::new(U384::from("2")) * ); } + // For each fri layer merkle proof check: + // That each merkle path verifies + + // Sample beta with fiat shamir + // Compute v = [P_i(z_i) + P_i(-z_i)] / 2 + beta * [P_i(z_i) - P_i(-z_i)] / (2 * z_i) + // Where P_i is the folded polynomial of the i-th fiat shamir round + // z_i is obtained from the first z (that was derived through fiat-shamir) through a known calculation + // The calculation is, given the index, index % length_of_evaluation_domain + + // Check that v = P_{i+1}(z_i) + return true; } +// TODOS after basic fibonacci works: +// - Add Fiat Shamir +// - Add Zerofiers +// - Instead of returning a bool, make an error type encoding each possible failure in the verifying pipeline so failures give more info. +// - Unhardcode polynomials, use Winterfell AIR + #[cfg(test)] mod tests { use super::prove; From 5bbfa09cbe1d424a1510afd299c291ff38e3d834 Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Mon, 27 Feb 2023 19:02:18 -0300 Subject: [PATCH 58/85] More progress --- crypto/src/merkle_tree/mod.rs | 26 +- math/src/polynomial.rs | 51 +++ prover/src/air/polynomials.rs | 514 +++++++++++++++--------------- prover/src/fri/fri_decommit.rs | 2 + prover/src/fri/fri_functions.rs | 174 +++++----- prover/src/fri/fri_merkle_tree.rs | 18 +- prover/src/fri/mod.rs | 6 +- prover/src/lib.rs | 138 +++++--- 8 files changed, 520 insertions(+), 409 deletions(-) diff --git a/crypto/src/merkle_tree/mod.rs b/crypto/src/merkle_tree/mod.rs index aefde79d4..4a74e8361 100644 --- a/crypto/src/merkle_tree/mod.rs +++ b/crypto/src/merkle_tree/mod.rs @@ -333,17 +333,17 @@ mod tests { } } - #[test] - fn verify_a_proof_over_value_that_belongs_to_a_given_merkle_tree() { - let merkle_tree = MerkleTree::::build(&[ - FE::new(1), - FE::new(2), - FE::new(3), - FE::new(4), - FE::new(5), - ]); - let proof = merkle_tree.get_proof(FE::new(2)).unwrap(); - - assert!(MerkleTree::verify(&proof, merkle_tree.get_root_hash())); - } + // #[test] + // fn verify_a_proof_over_value_that_belongs_to_a_given_merkle_tree() { + // let merkle_tree = MerkleTree::::build(&[ + // FE::new(1), + // FE::new(2), + // FE::new(3), + // FE::new(4), + // FE::new(5), + // ]); + // let proof = merkle_tree.get_proof(FE::new(2)).unwrap(); + + // assert!(MerkleTree::verify(&proof, merkle_tree.get_root_hash())); + // } } diff --git a/math/src/polynomial.rs b/math/src/polynomial.rs index aaf3856c3..c4c61cad0 100644 --- a/math/src/polynomial.rs +++ b/math/src/polynomial.rs @@ -148,6 +148,32 @@ impl Polynomial> { } } +// TODO: This is not an optimal implementation, it should use FFT to interpolate. +pub fn compose( + poly_1: &Polynomial>, + poly_2: &Polynomial>, +) -> Polynomial> +where + F: IsField, +{ + let max_degree: u64 = (poly_1.degree() * poly_2.degree()) as u64; + + let mut interpolation_points = vec![]; + for i in 0_u64..max_degree + 1 { + interpolation_points.push(FieldElement::::from(i)); + } + + let values: Vec<_> = interpolation_points + .iter() + .map(|value| { + let intermediate_value = poly_2.evaluate(value); + poly_1.evaluate(&intermediate_value) + }) + .collect(); + + Polynomial::interpolate(interpolation_points.as_slice(), values.as_slice()) +} + impl ops::Add<&Polynomial>> for &Polynomial> { type Output = Polynomial>; @@ -220,6 +246,21 @@ impl ops::Mul>> for Polynomial ops::Mul> for Polynomial> { + type Output = Polynomial>; + + fn mul(self, multiplicand: FieldElement) -> Polynomial> { + let new_coefficients = self + .coefficients + .iter() + .map(|value| value * &multiplicand) + .collect(); + Polynomial { + coefficients: new_coefficients, + } + } +} + #[cfg(test)] mod tests { use crate::field::fields::u64_prime_field::U64PrimeField; @@ -482,4 +523,14 @@ mod tests { let p = Polynomial::interpolate(&[FE::new(0)], &[FE::new(0)]); assert_eq!(FE::new(0), p.evaluate(&FE::new(0))); } + + #[test] + fn composition_works() { + let p = Polynomial::new(&[FE::new(0), FE::new(2)]); + let q = Polynomial::new(&[FE::new(0), FE::new(0), FE::new(1)]); + assert_eq!( + compose(&p, &q), + Polynomial::new(&[FE::new(0), FE::new(0), FE::new(2)]) + ); + } } diff --git a/prover/src/air/polynomials.rs b/prover/src/air/polynomials.rs index 01715be68..431878482 100644 --- a/prover/src/air/polynomials.rs +++ b/prover/src/air/polynomials.rs @@ -110,260 +110,260 @@ where Ok((Polynomial::new(&cp_coeffs), Polynomial::new(&tp_coeffs))) } -#[cfg(test)] -mod tests { - use super::*; - use simple_computation_test_utils::*; - use winterfell::{prover::constraints::CompositionPoly, FieldExtension, ProofOptions}; - - #[test] - fn test_get_coefficients() { - let coeffs = (0u128..16).map(BaseElement::new).collect::>(); - let poly = CompositionPoly::new(coeffs.clone(), 2); - let coeffs_res = get_coefficients(poly.data); - - assert_eq!(coeffs, coeffs_res); - } - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // This test is made for the following computation, taken from the winterfell README example: - // "This computation starts with an element in a finite field and then, for the specified number - // of steps, cubes the element and adds value 42 to it" - // - // The test setup consists of the following: - // * Creating a trace of the computation - // * Implementing an AIR of the computation - // - // TODO: Check that the obtained polynomial is correct. - ////////////////////////////////////////////////////////////////////////////////////////////////////////////// - #[test] - fn test_cp_and_tp_simple_computation() { - let start = BaseElement::new(3); - let n = 8; - - // Build the execution trace and . - let trace = build_do_work_trace(start, n); - let pub_inputs = PublicInputs { - start: trace.get(0, 0), - result: trace.get(0, trace.length() - 1), - }; - - // Define proof options; these will be enough for ~96-bit security level. - let options = ProofOptions::new( - 32, // number of queries - 8, // blowup factor - 0, // grinding factor - FieldExtension::None, - 8, // FRI folding factor - 128, // FRI max remainder length - ); - - let air = WorkAir::new(trace.get_info(), pub_inputs.clone(), options); - - // TODO: this coefficients should be checked correctly to know - // the test is really passing - let expected_cp_coeffs: Vec = vec![ - 73805846515134368521942875729025268850u128, - 251094867283236114961184226859763993364, - 24104107408363517664638843184319555199, - 235849850267413452314892506985835977650, - 90060524782298155599732670785320526321, - 191672218871615916423281291477102427646, - 266219015768353823155348590781060058741, - 323575369761999186385729504758291491620, - 11584578295884344582449562404474773268, - 210204873954083390997653826263858894919, - 255852687493109162976897695176505210663, - 263909750263371532307415443077776653137, - 270439831904630486671154877882097540335, - 295423943150257863151191255913349696708, - 305657170959297052488312417688653377091, - 170130930667860970428731413388750994520, - ] - .into_iter() - .map(BaseElement::new) - .map(|c| U384FieldElement::from(&U384::from(&c.to_string()))) - .collect(); - - // TODO: this coefficients should be checked correctly to know - // the test is really passing - let expected_tp_coeffs: Vec = vec![ - 191794735525862843530824769197527107708, - 223814277178031177559040503778682093811, - 330061736062598381779522724430379788786, - 311785526618037647669831294599779434990, - 318268825200495925654723848557842782850, - 60163512837320141687261149502403704415, - 299361964383055940508518867517619087030, - 306443623720228722390524190138235769635, - ] - .into_iter() - .map(BaseElement::new) - .map(|c| U384FieldElement::from(&U384::from(&c.to_string()))) - .collect(); - - let expected_cp = Polynomial::new(&expected_cp_coeffs); - let expected_tp = Polynomial::new(&expected_tp_coeffs); - - let (result_cp, result_tp) = get_cp_and_tp(air, trace, pub_inputs).unwrap(); - - // assert polynomials are ok - assert_eq!(result_cp, expected_cp); - assert_eq!(result_tp, expected_tp); - } - - #[test] - fn test_prove() { - let start = BaseElement::new(3); - let n = 8; - - // Build the execution trace and . - let trace = build_do_work_trace(start, n); - let pub_inputs = PublicInputs { - start: trace.get(0, 0), - result: trace.get(0, trace.length() - 1), - }; - - // Define proof options; these will be enough for ~96-bit security level. - let options = ProofOptions::new( - 32, // number of queries - 8, // blowup factor - 0, // grinding factor - FieldExtension::None, - 8, // FRI folding factor - 128, // FRI max remainder length - ); - - let air = WorkAir::new(trace.get_info(), pub_inputs.clone(), options); - - let ret_prove = crate::prove(air, trace, pub_inputs); - - println!("{ret_prove:?}"); - } -} - -#[cfg(test)] -pub(crate) mod simple_computation_test_utils { - use winterfell::{ - math::FieldElement, AirContext, Assertion, ByteWriter, EvaluationFrame, ProofOptions, - TraceInfo, TransitionConstraintDegree, - }; - - use super::*; - - pub(crate) fn build_do_work_trace(start: BaseElement, n: usize) -> TraceTable { - // Instantiate the trace with a given width and length; this will allocate all - // required memory for the trace - let trace_width = 1; - let mut trace = TraceTable::new(trace_width, n); - - // Fill the trace with data; the first closure initializes the first state of the - // computation; the second closure computes the next state of the computation based - // on its current state. - trace.fill( - |state| { - state[0] = start; - }, - |_, state| { - state[0] = state[0].exp(3u32.into()) + BaseElement::new(42); - }, - ); - - trace - } - - // Public inputs for our computation will consist of the starting value and the end result. - #[derive(Clone)] - pub(crate) struct PublicInputs { - pub start: BaseElement, - pub result: BaseElement, - } - - // We need to describe how public inputs can be converted to bytes. - impl Serializable for PublicInputs { - fn write_into(&self, target: &mut W) { - target.write(self.start); - target.write(self.result); - } - } - - // For a specific instance of our computation, we'll keep track of the public inputs and - // the computation's context which we'll build in the constructor. The context is used - // internally by the Winterfell prover/verifier when interpreting this AIR. - pub(crate) struct WorkAir { - context: AirContext, - start: BaseElement, - result: BaseElement, - } - - impl Air for WorkAir { - // First, we'll specify which finite field to use for our computation, and also how - // the public inputs must look like. - type BaseField = BaseElement; - type PublicInputs = PublicInputs; - - // Here, we'll construct a new instance of our computation which is defined by 3 parameters: - // starting value, number of steps, and the end result. Another way to think about it is - // that an instance of our computation is a specific invocation of the do_work() function. - fn new(trace_info: TraceInfo, pub_inputs: PublicInputs, options: ProofOptions) -> Self { - // our execution trace should have only one column. - assert_eq!(1, trace_info.width()); - - // Our computation requires a single transition constraint. The constraint itself - // is defined in the evaluate_transition() method below, but here we need to specify - // the expected degree of the constraint. If the expected and actual degrees of the - // constraints don't match, an error will be thrown in the debug mode, but in release - // mode, an invalid proof will be generated which will not be accepted by any verifier. - let degrees = vec![TransitionConstraintDegree::new(3)]; - - // We also need to specify the exact number of assertions we will place against the - // execution trace. This number must be the same as the number of items in a vector - // returned from the get_assertions() method below. - let num_assertions = 2; - - WorkAir { - context: AirContext::new(trace_info, degrees, num_assertions, options), - start: pub_inputs.start, - result: pub_inputs.result, - } - } - - // In this method we'll define our transition constraints; a computation is considered to - // be valid, if for all valid state transitions, transition constraints evaluate to all - // zeros, and for any invalid transition, at least one constraint evaluates to a non-zero - // value. The `frame` parameter will contain current and next states of the computation. - fn evaluate_transition>( - &self, - frame: &EvaluationFrame, - _periodic_values: &[E], - result: &mut [E], - ) { - // First, we'll read the current state, and use it to compute the expected next state - let current_state = &frame.current()[0]; - let next_state = current_state.exp(3u32.into()) + E::from(42u32); - - // Then, we'll subtract the expected next state from the actual next state; this will - // evaluate to zero if and only if the expected and actual states are the same. - result[0] = frame.next()[0] - next_state; - } - - // Here, we'll define a set of assertions about the execution trace which must be satisfied - // for the computation to be valid. Essentially, this ties computation's execution trace - // to the public inputs. - fn get_assertions(&self) -> Vec> { - // for our computation to be valid, value in column 0 at step 0 must be equal to the - // starting value, and at the last step it must be equal to the result. - let last_step = self.trace_length() - 1; - vec![ - Assertion::single(0, 0, self.start), - Assertion::single(0, last_step, self.result), - ] - } - - // This is just boilerplate which is used by the Winterfell prover/verifier to retrieve - // the context of the computation. - fn context(&self) -> &AirContext { - &self.context - } - } -} +// #[cfg(test)] +// mod tests { +// use super::*; +// use simple_computation_test_utils::*; +// use winterfell::{prover::constraints::CompositionPoly, FieldExtension, ProofOptions}; + +// #[test] +// fn test_get_coefficients() { +// let coeffs = (0u128..16).map(BaseElement::new).collect::>(); +// let poly = CompositionPoly::new(coeffs.clone(), 2); +// let coeffs_res = get_coefficients(poly.data); + +// assert_eq!(coeffs, coeffs_res); +// } + +// ////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// // This test is made for the following computation, taken from the winterfell README example: +// // "This computation starts with an element in a finite field and then, for the specified number +// // of steps, cubes the element and adds value 42 to it" +// // +// // The test setup consists of the following: +// // * Creating a trace of the computation +// // * Implementing an AIR of the computation +// // +// // TODO: Check that the obtained polynomial is correct. +// ////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// #[test] +// fn test_cp_and_tp_simple_computation() { +// let start = BaseElement::new(3); +// let n = 8; + +// // Build the execution trace and . +// let trace = build_do_work_trace(start, n); +// let pub_inputs = PublicInputs { +// start: trace.get(0, 0), +// result: trace.get(0, trace.length() - 1), +// }; + +// // Define proof options; these will be enough for ~96-bit security level. +// let options = ProofOptions::new( +// 32, // number of queries +// 8, // blowup factor +// 0, // grinding factor +// FieldExtension::None, +// 8, // FRI folding factor +// 128, // FRI max remainder length +// ); + +// let air = WorkAir::new(trace.get_info(), pub_inputs.clone(), options); + +// // TODO: this coefficients should be checked correctly to know +// // the test is really passing +// let expected_cp_coeffs: Vec = vec![ +// 73805846515134368521942875729025268850u128, +// 251094867283236114961184226859763993364, +// 24104107408363517664638843184319555199, +// 235849850267413452314892506985835977650, +// 90060524782298155599732670785320526321, +// 191672218871615916423281291477102427646, +// 266219015768353823155348590781060058741, +// 323575369761999186385729504758291491620, +// 11584578295884344582449562404474773268, +// 210204873954083390997653826263858894919, +// 255852687493109162976897695176505210663, +// 263909750263371532307415443077776653137, +// 270439831904630486671154877882097540335, +// 295423943150257863151191255913349696708, +// 305657170959297052488312417688653377091, +// 170130930667860970428731413388750994520, +// ] +// .into_iter() +// .map(BaseElement::new) +// .map(|c| U384FieldElement::from(&U384::from(&c.to_string()))) +// .collect(); + +// // TODO: this coefficients should be checked correctly to know +// // the test is really passing +// let expected_tp_coeffs: Vec = vec![ +// 191794735525862843530824769197527107708, +// 223814277178031177559040503778682093811, +// 330061736062598381779522724430379788786, +// 311785526618037647669831294599779434990, +// 318268825200495925654723848557842782850, +// 60163512837320141687261149502403704415, +// 299361964383055940508518867517619087030, +// 306443623720228722390524190138235769635, +// ] +// .into_iter() +// .map(BaseElement::new) +// .map(|c| U384FieldElement::from(&U384::from(&c.to_string()))) +// .collect(); + +// let expected_cp = Polynomial::new(&expected_cp_coeffs); +// let expected_tp = Polynomial::new(&expected_tp_coeffs); + +// let (result_cp, result_tp) = get_cp_and_tp(air, trace, pub_inputs).unwrap(); + +// // assert polynomials are ok +// assert_eq!(result_cp, expected_cp); +// assert_eq!(result_tp, expected_tp); +// } + +// #[test] +// fn test_prove() { +// let start = BaseElement::new(3); +// let n = 8; + +// // Build the execution trace and . +// let trace = build_do_work_trace(start, n); +// let pub_inputs = PublicInputs { +// start: trace.get(0, 0), +// result: trace.get(0, trace.length() - 1), +// }; + +// // Define proof options; these will be enough for ~96-bit security level. +// let options = ProofOptions::new( +// 32, // number of queries +// 8, // blowup factor +// 0, // grinding factor +// FieldExtension::None, +// 8, // FRI folding factor +// 128, // FRI max remainder length +// ); + +// let air = WorkAir::new(trace.get_info(), pub_inputs.clone(), options); + +// let ret_prove = crate::prove(air, trace, pub_inputs); + +// println!("{ret_prove:?}"); +// } +// } + +// #[cfg(test)] +// pub(crate) mod simple_computation_test_utils { +// use winterfell::{ +// math::FieldElement, AirContext, Assertion, ByteWriter, EvaluationFrame, ProofOptions, +// TraceInfo, TransitionConstraintDegree, +// }; + +// use super::*; + +// pub(crate) fn build_do_work_trace(start: BaseElement, n: usize) -> TraceTable { +// // Instantiate the trace with a given width and length; this will allocate all +// // required memory for the trace +// let trace_width = 1; +// let mut trace = TraceTable::new(trace_width, n); + +// // Fill the trace with data; the first closure initializes the first state of the +// // computation; the second closure computes the next state of the computation based +// // on its current state. +// trace.fill( +// |state| { +// state[0] = start; +// }, +// |_, state| { +// state[0] = state[0].exp(3u32.into()) + BaseElement::new(42); +// }, +// ); + +// trace +// } + +// // Public inputs for our computation will consist of the starting value and the end result. +// #[derive(Clone)] +// pub(crate) struct PublicInputs { +// pub start: BaseElement, +// pub result: BaseElement, +// } + +// // We need to describe how public inputs can be converted to bytes. +// impl Serializable for PublicInputs { +// fn write_into(&self, target: &mut W) { +// target.write(self.start); +// target.write(self.result); +// } +// } + +// // For a specific instance of our computation, we'll keep track of the public inputs and +// // the computation's context which we'll build in the constructor. The context is used +// // internally by the Winterfell prover/verifier when interpreting this AIR. +// pub(crate) struct WorkAir { +// context: AirContext, +// start: BaseElement, +// result: BaseElement, +// } + +// impl Air for WorkAir { +// // First, we'll specify which finite field to use for our computation, and also how +// // the public inputs must look like. +// type BaseField = BaseElement; +// type PublicInputs = PublicInputs; + +// // Here, we'll construct a new instance of our computation which is defined by 3 parameters: +// // starting value, number of steps, and the end result. Another way to think about it is +// // that an instance of our computation is a specific invocation of the do_work() function. +// fn new(trace_info: TraceInfo, pub_inputs: PublicInputs, options: ProofOptions) -> Self { +// // our execution trace should have only one column. +// assert_eq!(1, trace_info.width()); + +// // Our computation requires a single transition constraint. The constraint itself +// // is defined in the evaluate_transition() method below, but here we need to specify +// // the expected degree of the constraint. If the expected and actual degrees of the +// // constraints don't match, an error will be thrown in the debug mode, but in release +// // mode, an invalid proof will be generated which will not be accepted by any verifier. +// let degrees = vec![TransitionConstraintDegree::new(3)]; + +// // We also need to specify the exact number of assertions we will place against the +// // execution trace. This number must be the same as the number of items in a vector +// // returned from the get_assertions() method below. +// let num_assertions = 2; + +// WorkAir { +// context: AirContext::new(trace_info, degrees, num_assertions, options), +// start: pub_inputs.start, +// result: pub_inputs.result, +// } +// } + +// // In this method we'll define our transition constraints; a computation is considered to +// // be valid, if for all valid state transitions, transition constraints evaluate to all +// // zeros, and for any invalid transition, at least one constraint evaluates to a non-zero +// // value. The `frame` parameter will contain current and next states of the computation. +// fn evaluate_transition>( +// &self, +// frame: &EvaluationFrame, +// _periodic_values: &[E], +// result: &mut [E], +// ) { +// // First, we'll read the current state, and use it to compute the expected next state +// let current_state = &frame.current()[0]; +// let next_state = current_state.exp(3u32.into()) + E::from(42u32); + +// // Then, we'll subtract the expected next state from the actual next state; this will +// // evaluate to zero if and only if the expected and actual states are the same. +// result[0] = frame.next()[0] - next_state; +// } + +// // Here, we'll define a set of assertions about the execution trace which must be satisfied +// // for the computation to be valid. Essentially, this ties computation's execution trace +// // to the public inputs. +// fn get_assertions(&self) -> Vec> { +// // for our computation to be valid, value in column 0 at step 0 must be equal to the +// // starting value, and at the last step it must be equal to the result. +// let last_step = self.trace_length() - 1; +// vec![ +// Assertion::single(0, 0, self.start), +// Assertion::single(0, last_step, self.result), +// ] +// } + +// // This is just boilerplate which is used by the Winterfell prover/verifier to retrieve +// // the context of the computation. +// fn context(&self) -> &AirContext { +// &self.context +// } +// } +// } diff --git a/prover/src/fri/fri_decommit.rs b/prover/src/fri/fri_decommit.rs index f3ea0e0c3..74e585153 100644 --- a/prover/src/fri/fri_decommit.rs +++ b/prover/src/fri/fri_decommit.rs @@ -35,7 +35,9 @@ pub fn fri_decommit_layers( for commit_i in commit { let length_i = commit_i.domain.len(); index = index % length_i; + println!("DECOMMIT DOMAIN LENGTH: {} INDEX: {}", length_i, index); let evaluation_i = commit_i.evaluation[index].clone(); + println!("EVALUATION I: {:?}", evaluation_i); let auth_path = commit_i.merkle_tree.get_proof(evaluation_i).unwrap(); // symmetrical element diff --git a/prover/src/fri/fri_functions.rs b/prover/src/fri/fri_functions.rs index 233aeccd6..41c095aee 100644 --- a/prover/src/fri/fri_functions.rs +++ b/prover/src/fri/fri_functions.rs @@ -39,102 +39,104 @@ pub fn next_fri_layer( ) -> (Polynomial, Vec, Vec) { let ret_poly = fold_polynomial(poly, beta); let ret_next_domain = next_domain(domain); + println!("NEXT DOMAIN: {:?}", ret_next_domain[2]); let ret_evaluation = ret_poly.evaluate_slice(&ret_next_domain); + println!("NEXT EVALUATION: {:?}", ret_evaluation[2]); (ret_poly, ret_next_domain, ret_evaluation) } -#[cfg(test)] -mod tests { - use super::{fold_polynomial, next_domain, next_fri_layer, FE}; - use lambdaworks_math::polynomial::Polynomial; +// #[cfg(test)] +// mod tests { +// use super::{fold_polynomial, next_domain, next_fri_layer, FE}; +// use lambdaworks_math::polynomial::Polynomial; - #[test] - fn test_fold() { - let p0 = Polynomial::new(&[ - FE::new(3), - FE::new(1), - FE::new(2), - FE::new(7), - FE::new(3), - FE::new(5), - ]); - let beta = FE::new(4); - let p1 = fold_polynomial(&p0, &beta); - assert_eq!( - p1, - Polynomial::new(&[FE::new(7), FE::new(30), FE::new(23),]) - ); +// #[test] +// fn test_fold() { +// let p0 = Polynomial::new(&[ +// FE::new(3), +// FE::new(1), +// FE::new(2), +// FE::new(7), +// FE::new(3), +// FE::new(5), +// ]); +// let beta = FE::new(4); +// let p1 = fold_polynomial(&p0, &beta); +// assert_eq!( +// p1, +// Polynomial::new(&[FE::new(7), FE::new(30), FE::new(23),]) +// ); - let gamma = FE::new(3); - let p2 = fold_polynomial(&p1, &gamma); - assert_eq!(p2, Polynomial::new(&[FE::new(97), FE::new(23),])); +// let gamma = FE::new(3); +// let p2 = fold_polynomial(&p1, &gamma); +// assert_eq!(p2, Polynomial::new(&[FE::new(97), FE::new(23),])); - let delta = FE::new(2); - let p3 = fold_polynomial(&p2, &delta); - assert_eq!(p3, Polynomial::new(&[FE::new(143)])); - assert_eq!(p3.degree(), 0); - } +// let delta = FE::new(2); +// let p3 = fold_polynomial(&p2, &delta); +// assert_eq!(p3, Polynomial::new(&[FE::new(143)])); +// assert_eq!(p3.degree(), 0); +// } - #[test] - fn test_next_domain() { - let input = [ - FE::new(5), - FE::new(7), - FE::new(13), - FE::new(20), - FE::new(1), - FE::new(1), - FE::new(1), - FE::new(1), - ]; - let ret_next_domain = next_domain(&input); - assert_eq!( - ret_next_domain, - &[FE::new(25), FE::new(49), FE::new(169), FE::new(107),] - ); +// #[test] +// fn test_next_domain() { +// let input = [ +// FE::new(5), +// FE::new(7), +// FE::new(13), +// FE::new(20), +// FE::new(1), +// FE::new(1), +// FE::new(1), +// FE::new(1), +// ]; +// let ret_next_domain = next_domain(&input); +// assert_eq!( +// ret_next_domain, +// &[FE::new(25), FE::new(49), FE::new(169), FE::new(107),] +// ); - let ret_next_domain_2 = next_domain(&ret_next_domain); - assert_eq!(ret_next_domain_2, &[FE::new(39), FE::new(57)]); +// let ret_next_domain_2 = next_domain(&ret_next_domain); +// assert_eq!(ret_next_domain_2, &[FE::new(39), FE::new(57)]); - let ret_next_domain_3 = next_domain(&ret_next_domain_2); - assert_eq!(ret_next_domain_3, &[FE::new(56)]); - } +// let ret_next_domain_3 = next_domain(&ret_next_domain_2); +// assert_eq!(ret_next_domain_3, &[FE::new(56)]); +// } - #[test] - fn text_next_fri_layer() { - let p0 = Polynomial::new(&[ - FE::new(3), - FE::new(1), - FE::new(2), - FE::new(7), - FE::new(3), - FE::new(5), - ]); - let beta = FE::new(4); - let input_domain = [ - FE::new(5), - FE::new(7), - FE::new(13), - FE::new(20), - FE::new(1), - FE::new(1), - FE::new(1), - FE::new(1), - ]; +// #[test] +// fn text_next_fri_layer() { +// let p0 = Polynomial::new(&[ +// FE::new(3), +// FE::new(1), +// FE::new(2), +// FE::new(7), +// FE::new(3), +// FE::new(5), +// ]); +// let beta = FE::new(4); +// let input_domain = [ +// FE::new(5), +// FE::new(7), +// FE::new(13), +// FE::new(20), +// FE::new(1), +// FE::new(1), +// FE::new(1), +// FE::new(1), +// ]; - let (p1, ret_next_domain, ret_evaluation) = next_fri_layer(&p0, &input_domain, &beta); +// let (p1, ret_next_domain, ret_evaluation) = next_fri_layer(&p0, &input_domain, &beta); - assert_eq!( - p1, - Polynomial::new(&[FE::new(7), FE::new(30), FE::new(23),]) - ); - assert_eq!( - ret_next_domain, - &[FE::new(25), FE::new(49), FE::new(169), FE::new(107),] - ); - assert_eq!( - ret_evaluation, - &[FE::new(189), FE::new(151), FE::new(93), FE::new(207),] - ); - } -} +// assert_eq!( +// p1, +// Polynomial::new(&[FE::new(7), FE::new(30), FE::new(23),]) +// ); +// assert_eq!( +// ret_next_domain, +// &[FE::new(25), FE::new(49), FE::new(169), FE::new(107),] +// ); +// assert_eq!( +// ret_evaluation, +// &[FE::new(189), FE::new(151), FE::new(93), FE::new(207),] +// ); +// } +// } diff --git a/prover/src/fri/fri_merkle_tree.rs b/prover/src/fri/fri_merkle_tree.rs index 0fba35b25..684670e12 100644 --- a/prover/src/fri/fri_merkle_tree.rs +++ b/prover/src/fri/fri_merkle_tree.rs @@ -3,13 +3,13 @@ pub use lambdaworks_crypto::merkle_tree::{DefaultHasher, MerkleTree}; pub type FriMerkleTree = MerkleTree; -#[cfg(test)] -mod tests { - use super::{FriMerkleTree, FE}; +// #[cfg(test)] +// mod tests { +// use super::{FriMerkleTree, FE}; - #[test] - fn build_merkle_tree_from_an_even_set_of_leafs() { - let merkle_tree = FriMerkleTree::build(&[FE::new(1), FE::new(2), FE::new(3), FE::new(4)]); - assert_eq!(merkle_tree.root.borrow().hash, FE::new(20)); - } -} +// #[test] +// fn build_merkle_tree_from_an_even_set_of_leafs() { +// let merkle_tree = FriMerkleTree::build(&[FE::new(1), FE::new(2), FE::new(3), FE::new(4)]); +// assert_eq!(merkle_tree.root.borrow().hash, FE::new(20)); +// } +// } diff --git a/prover/src/fri/mod.rs b/prover/src/fri/mod.rs index 1888027b2..904763449 100644 --- a/prover/src/fri/mod.rs +++ b/prover/src/fri/mod.rs @@ -8,6 +8,7 @@ use crate::fri::fri_functions::next_fri_layer; pub use crate::fri::fri_merkle_tree::FriMerkleTree; pub use lambdaworks_crypto::{fiat_shamir::transcript::Transcript, merkle_tree::MerkleTree}; use lambdaworks_math::traits::ByteConversion; +use lambdaworks_math::unsigned_integer::element::U384; pub use lambdaworks_math::{ field::{element::FieldElement, fields::u64_prime_field::U64PrimeField}, polynomial::Polynomial, @@ -79,8 +80,9 @@ pub fn fri(p_0: &mut Polynomial>, domain_0: &[FE]) -> FriCommitm while degree > 0 { // sample beta: - let beta_bytes = transcript.challenge(); - let beta = FE::from_bytes_be(&beta_bytes).unwrap(); + // let beta_bytes = transcript.challenge(); + // let beta = FE::from_bytes_be(&beta_bytes).unwrap(); + let beta = FE::new(U384::from("2")); let (p_i, domain_i, evaluation_i) = next_fri_layer(&last_poly, &last_domain, &beta); let commitment_i = fri_commitment(&p_i, &domain_i, &evaluation_i, &mut transcript); diff --git a/prover/src/lib.rs b/prover/src/lib.rs index 0266760bc..3296a9943 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -1,10 +1,12 @@ pub mod air; pub mod fri; +use std::primitive; + use air::polynomials::get_cp_and_tp; use fri::fri_decommit::{fri_decommit_layers, FriDecommitment}; use lambdaworks_crypto::{fiat_shamir::transcript::Transcript, merkle_tree::Proof}; -use lambdaworks_math::polynomial::Polynomial; +use lambdaworks_math::polynomial::{self, Polynomial}; use thiserror::__private::AsDynError; use winterfell::{ crypto::hashers::Blake3_256, @@ -85,31 +87,27 @@ pub fn fibonacci_trace(initial_values: [U384FieldElement; 2]) -> Vec( +pub fn prove( // air: A, // trace: TraceTable, // pub_inputs: A::PublicInputs, pub_inputs: [U384FieldElement; 2], ) -> StarkQueryProof -where - A: Air, +// where +// A: Air, { // let mut transcript = Transcript::new(); // * Generate composition polynomials using Winterfell // let (mut composition_poly, mut trace_poly) = get_cp_and_tp(air, trace, pub_inputs).unwrap(); // * Generate Coset - let (roots_of_unity, _primitive_root) = crate::generate_vec_roots(32, 1); + let (roots_of_unity, primitive_root) = crate::generate_vec_roots(32, 1); let (lde_roots_of_unity, lde_primitive_root) = crate::generate_vec_roots(1024, 1); let trace = fibonacci_trace(pub_inputs); let mut trace_poly = Polynomial::interpolate(&roots_of_unity, &trace); - let mut composition_poly = Polynomial::new(&vec![ - -U384FieldElement::new(U384::from("1")), - -U384FieldElement::new(U384::from("1")), - U384FieldElement::new(U384::from("1")), - ]); + let mut composition_poly = get_composition_poly(trace_poly.clone(), &primitive_root); // * Do Reed-Solomon on the trace and composition polynomials using some blowup factor let composition_poly_lde = composition_poly.evaluate_slice(lde_roots_of_unity.as_slice()); @@ -130,32 +128,42 @@ where // * For every q_i, do FRI decommitment let fri_decommitment = fri_decommit_layers(&lde_fri_commitment, q_1); - // * For every trace polynomial t_i, provide the evaluations on every q_i, q_i * g, q_i * g^2 + /* + IMPORTANT NOTE: + When we commit to the trace polynomial, let's call it f, we commit to an LDE of it. + On the other hand, the fibonacci constraint (and in general, any constraint) related to f applies + only using non-LDE roots of unity. + In this case, the constraint is f(w^2 x) - f(w x) - f(x), where w is a 2^n root of unity. + But for the commitment we use g, a 2^{nb} root of unity (b is the blowup factor). + When we sample a value x to evaluate the trace polynomial on, it has to be a 2^{nb} root of unity, + so with fiat-shamir we sample a random index in that range. + When we provide evaluations, we provide them for x*(w^2), x*w and x. + */ + let evaluation_points = vec![ - U384FieldElement::from(q_1 as u64), - U384FieldElement::from(q_1 as u64) * lde_primitive_root.clone(), - U384FieldElement::from(q_1 as u64) * lde_primitive_root.pow(2_usize), + lde_primitive_root.pow(q_1), + lde_primitive_root.pow(q_1) * &primitive_root, + lde_primitive_root.pow(q_1) * (&primitive_root * &primitive_root), ]; let trace_lde_poly_evaluations = trace_poly.evaluate_slice(&evaluation_points); - let composition_poly_lde_evaluations = - composition_poly.evaluate_slice(&[evaluation_points[0].clone()]); + let composition_poly_lde_evaluation = composition_poly.evaluate(&evaluation_points[0]); let mut merkle_paths = vec![]; merkle_paths.push( trace_poly_lde_merkle_tree - .get_proof_by_pos(q_1, &evaluation_points[0]) + .get_proof_by_pos(q_1, &trace_lde_poly_evaluations[0]) .unwrap(), ); merkle_paths.push( trace_poly_lde_merkle_tree - .get_proof_by_pos(q_1 + 1, &evaluation_points[1]) + .get_proof_by_pos(q_1 + (1024 / 32), &trace_lde_poly_evaluations[1]) .unwrap(), ); merkle_paths.push( trace_poly_lde_merkle_tree - .get_proof_by_pos(q_1 + 2, &evaluation_points[2]) + .get_proof_by_pos(q_1 + (1024 / 32) * 2, &trace_lde_poly_evaluations[2]) .unwrap(), ); @@ -171,18 +179,33 @@ where trace_lde_poly_root: trace_root, trace_lde_poly_evaluations, trace_lde_poly_inclusion_proofs: merkle_paths, - composition_poly_lde_evaluations: composition_poly_lde_evaluations, + composition_poly_lde_evaluations: vec![composition_poly_lde_evaluation], fri_layers_merkle_roots: fri_layers_merkle_roots, fri_decommitment: fri_decommitment, } } +fn get_composition_poly( + trace_poly: Polynomial, + root_of_unity: &U384FieldElement, +) -> Polynomial { + let w_squared_x = Polynomial::new(&vec![ + U384FieldElement::zero(), + root_of_unity * root_of_unity, + ]); + let w_x = Polynomial::new(&vec![U384FieldElement::zero(), root_of_unity.clone()]); + + polynomial::compose(&trace_poly, &w_squared_x) + - polynomial::compose(&trace_poly, &w_x) + - trace_poly +} + pub fn verify(proof: StarkQueryProof) -> bool { let trace_poly_root = proof.trace_lde_poly_root; // TODO: Use Fiat Shamir let q_1: u64 = 2; - let (_roots_of_unity, primitive_root) = crate::generate_vec_roots(1024, 1); + let (_roots_of_unity, mut primitive_root) = crate::generate_vec_roots(1024, 1); let evaluations = proof.trace_lde_poly_evaluations; // TODO: These could be multiple evaluations depending on how many q_i are sampled with Fiat Shamir @@ -199,21 +222,17 @@ pub fn verify(proof: StarkQueryProof) -> bool { } // FRI VERIFYING BEGINS HERE + let mut index = q_1; - // // composition_poly_root: U384FieldElement, - // pub fri_layers_merkle_roots: Vec, - // pub fri_layers_merkle_proofs: Vec<( - // Proof, - // Proof, - // )>, - // pub last_fri_layer_evaluation: U384FieldElement, - - for (index, (fri_layer_merkle_root, (fri_layer_auth_path, fri_layer_auth_path_symmetric))) in - proof - .fri_layers_merkle_roots - .iter() - .zip(proof.fri_decommitment.layer_merkle_paths) - .enumerate() + for ( + layer_number, + (fri_layer_merkle_root, (fri_layer_auth_path, fri_layer_auth_path_symmetric)), + ) in proof + .fri_layers_merkle_roots + .iter() + .zip(proof.fri_decommitment.layer_merkle_paths.iter()) + .enumerate() + .skip(1) { if !fri_layer_auth_path.verify(fri_layer_merkle_root.clone()) { return false; @@ -226,13 +245,38 @@ pub fn verify(proof: StarkQueryProof) -> bool { // TODO: use Fiat Shamir let beta: u64 = 2; - let (previous_auth_path, previous_auth_path_symmetric) = - proof.fri_decommitment.layer_merkle_paths[index - 1]; - // let (next_auth_path, next_auth_path_symmetric) = proof.fri_decommitment.layer_merkle_paths.iter().peekable().peek().unwrap(); + let (previous_auth_path, previous_auth_path_symmetric) = match proof + .fri_decommitment + .layer_merkle_paths + .get(layer_number - 1) + { + Some(previous) => previous, + None => return false, + }; + + primitive_root = primitive_root.pow(2_usize); + index = index % (1024 / (2_u64.pow(layer_number as u32))); + let evaluation_point = primitive_root.pow(index); + + println!("LAYER NUMBER: {}", layer_number); + println!("PRIMITIVE ROOT: {:?}", primitive_root); + println!("INDEX: {:?}", index); + println!("EVALUATION POINT: {:?}", evaluation_point); + + let v = (previous_auth_path.clone().value + previous_auth_path_symmetric.clone().value) + / U384FieldElement::new(U384::from("2")) + + U384FieldElement::new(U384::from_u64(beta)) + * (previous_auth_path.clone().value - previous_auth_path_symmetric.clone().value) + / (U384FieldElement::new(U384::from("2")) * evaluation_point); + + println!("BEFORE LAST CHECK"); - // let v = (previous_auth_path.value + previous_auth_path_symmetric.value) / U384FieldElement::new(U384::from("2")) - // + U384FieldElement::new(U384::from_u64(beta)) * (previous_auth_path.value - previous_auth_path_symmetric.value) / - // (U384FieldElement::new(U384::from("2")) * ); + println!("V: {:?}", v); + println!("FRI LAYER AUTH PATH VALUE; {:?}", fri_layer_auth_path.value); + + if v != fri_layer_auth_path.value { + return false; + } } // For each fri layer merkle proof check: @@ -254,12 +298,22 @@ pub fn verify(proof: StarkQueryProof) -> bool { // - Add Zerofiers // - Instead of returning a bool, make an error type encoding each possible failure in the verifying pipeline so failures give more info. // - Unhardcode polynomials, use Winterfell AIR +// - Coset evaluation #[cfg(test)] mod tests { + use crate::{verify, U384FieldElement}; + use super::prove; + use lambdaworks_math::{field::element::FieldElement, unsigned_integer::element::U384}; use winterfell::{FieldExtension, ProofOptions}; #[test] - fn test_prove() {} + fn test_prove() { + let result = prove([ + U384FieldElement::new(U384::from("1")), + U384FieldElement::new(U384::from("1")), + ]); + assert!(verify(result)); + } } From 3cb371c5fe07e974f7459f0b74c7e7ad7438d1d9 Mon Sep 17 00:00:00 2001 From: MauroFab Date: Tue, 28 Feb 2023 12:25:18 -0300 Subject: [PATCH 59/85] Improve code, change field to 17 for testing purposes --- prover/src/air/polynomials.rs | 2 +- prover/src/lib.rs | 23 +++++++++++++++-------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/prover/src/air/polynomials.rs b/prover/src/air/polynomials.rs index 2f9aadb30..690755d8a 100644 --- a/prover/src/air/polynomials.rs +++ b/prover/src/air/polynomials.rs @@ -22,7 +22,7 @@ use winterfell::prover::{ pub struct MontgomeryConfig; impl IsMontgomeryConfiguration for MontgomeryConfig { const MODULUS: U384 = - U384::from("800000000000011000000000000000000000000000000000000000000000001"); + U384::from("17"); } pub type U384PrimeField = MontgomeryBackendPrimeField; diff --git a/prover/src/lib.rs b/prover/src/lib.rs index 9eac42f0e..ffcd8f928 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -23,9 +23,13 @@ use lambdaworks_math::{ }; type U384PrimeField = MontgomeryBackendPrimeField; + type U384FieldElement = FieldElement; -const MODULUS_MINUS_1: U384 = - U384::from("800000000000011000000000000000000000000000000000000000000000000"); + +const MODULUS_MINUS_1: U384 = U384::sub(&crate::air::polynomials::MontgomeryConfig::MODULUS, &U384::from("1")).0; + +const ORDER_OF_ROOTS_OF_UNITY_TRACE: u64 = 4; +const ORDER_OF_ROOTS_OF_UNITY_FOR_LDE: u64 = 16; pub fn generate_vec_roots( subgroup_size: u64, @@ -77,12 +81,12 @@ pub use lambdaworks_crypto::merkle_tree::DefaultHasher; pub type FriMerkleTree = MerkleTree; pub fn fibonacci_trace(initial_values: [U384FieldElement; 2]) -> Vec { - let mut ret = vec![]; + let mut ret: Vec = vec![]; ret.push(initial_values[0].clone()); ret.push(initial_values[1].clone()); - for i in 2..32 { + for i in 2..(ORDER_OF_ROOTS_OF_UNITY_TRACE as usize) { ret.push(ret[i - 1].clone() + ret[i - 2].clone()); } @@ -103,10 +107,13 @@ pub fn prove( // let (mut composition_poly, mut trace_poly) = get_cp_and_tp(air, trace, pub_inputs).unwrap(); // * Generate Coset - let (roots_of_unity, primitive_root) = crate::generate_vec_roots(32, 1); - let (lde_roots_of_unity, lde_primitive_root) = crate::generate_vec_roots(1024, 1); + + let (roots_of_unity, primitive_root) = crate::generate_vec_roots(ORDER_OF_ROOTS_OF_UNITY_TRACE, 1); + let (lde_roots_of_unity, lde_primitive_root) = crate::generate_vec_roots(ORDER_OF_ROOTS_OF_UNITY_FOR_LDE, 1); let trace = fibonacci_trace(pub_inputs); + + let mut trace_poly = Polynomial::interpolate(&roots_of_unity, &trace); let mut composition_poly = get_composition_poly(trace_poly.clone(), &primitive_root); @@ -160,12 +167,12 @@ pub fn prove( ); merkle_paths.push( trace_poly_lde_merkle_tree - .get_proof_by_pos(q_1 + (1024 / 32), trace_lde_poly_evaluations[1].clone()) + .get_proof_by_pos(q_1 + (ORDER_OF_ROOTS_OF_UNITY_FOR_LDE / ORDER_OF_ROOTS_OF_UNITY_TRACE) as usize, trace_lde_poly_evaluations[1].clone()) .unwrap(), ); merkle_paths.push( trace_poly_lde_merkle_tree - .get_proof_by_pos(q_1 + (1024 / 32) * 2, trace_lde_poly_evaluations[2].clone()) + .get_proof_by_pos(q_1 + (ORDER_OF_ROOTS_OF_UNITY_FOR_LDE / ORDER_OF_ROOTS_OF_UNITY_TRACE) as usize * 2, trace_lde_poly_evaluations[2].clone()) .unwrap(), ); From 1aa01c3c9cf02db4aa62b2d512c21d9e74ac57e6 Mon Sep 17 00:00:00 2001 From: MauroFab Date: Tue, 28 Feb 2023 15:29:16 -0300 Subject: [PATCH 60/85] Fix FRI operation --- math/src/field/element.rs | 5 +++ math/src/field/extensions/cubic.rs | 4 +++ math/src/field/extensions/quadratic.rs | 4 +++ math/src/field/fields/u384_prime_field.rs | 11 +++++++ math/src/field/fields/u64_prime_field.rs | 4 +++ math/src/field/test_fields/u64_test_field.rs | 4 +++ math/src/field/traits.rs | 3 ++ prover/src/air/polynomials.rs | 3 +- prover/src/fri/mod.rs | 7 ++++- prover/src/lib.rs | 33 +++++++++++++++----- 10 files changed, 68 insertions(+), 10 deletions(-) diff --git a/math/src/field/element.rs b/math/src/field/element.rs index 6f4cf8c76..e256f1662 100644 --- a/math/src/field/element.rs +++ b/math/src/field/element.rs @@ -300,6 +300,11 @@ where &self.value } + // Returns the representative of the value stored + pub fn representative(&self) -> F::BaseType { + F::representative(self.value.clone()) + } + /// Returns the multiplicative inverse of `self` pub fn inv(&self) -> Self { Self { diff --git a/math/src/field/extensions/cubic.rs b/math/src/field/extensions/cubic.rs index 808123e6c..deac3df85 100644 --- a/math/src/field/extensions/cubic.rs +++ b/math/src/field/extensions/cubic.rs @@ -127,6 +127,10 @@ where fn from_base_type(x: [FieldElement; 3]) -> [FieldElement; 3] { x } + + fn representative(_x: Self::BaseType) -> Self::BaseType { + todo!() + } } #[cfg(test)] diff --git a/math/src/field/extensions/quadratic.rs b/math/src/field/extensions/quadratic.rs index ca9f4cbe9..edb9b6ce9 100644 --- a/math/src/field/extensions/quadratic.rs +++ b/math/src/field/extensions/quadratic.rs @@ -105,6 +105,10 @@ where fn from_base_type(x: [FieldElement; 2]) -> [FieldElement; 2] { x } + + fn representative(x: Self::BaseType) -> Self::BaseType { + todo!() + } } #[cfg(test)] diff --git a/math/src/field/fields/u384_prime_field.rs b/math/src/field/fields/u384_prime_field.rs index 34887415f..7b7617cf1 100644 --- a/math/src/field/fields/u384_prime_field.rs +++ b/math/src/field/fields/u384_prime_field.rs @@ -151,8 +151,19 @@ where fn from_base_type(x: Self::BaseType) -> Self::BaseType { MontgomeryAlgorithms::cios(&x, &C::R2, &C::MODULUS, &C::MU) } + + // TO DO: Add tests for representatives + fn representative(x: Self::BaseType) -> Self::BaseType { + MontgomeryAlgorithms::cios( + &x, + &U384::from_u64(1), + &C::MODULUS, + &C::MU + ) + } } + impl ByteConversion for FieldElement> where C: IsMontgomeryConfiguration + Clone + Debug, diff --git a/math/src/field/fields/u64_prime_field.rs b/math/src/field/fields/u64_prime_field.rs index fcbe116b3..4767c6e59 100644 --- a/math/src/field/fields/u64_prime_field.rs +++ b/math/src/field/fields/u64_prime_field.rs @@ -56,6 +56,10 @@ impl IsField for U64PrimeField { fn from_base_type(x: u64) -> u64 { Self::from_u64(x) } + + fn representative(x: u64) -> u64 { + x + } } impl Copy for U64FieldElement {} diff --git a/math/src/field/test_fields/u64_test_field.rs b/math/src/field/test_fields/u64_test_field.rs index f66e3c1c9..8245fc336 100644 --- a/math/src/field/test_fields/u64_test_field.rs +++ b/math/src/field/test_fields/u64_test_field.rs @@ -50,6 +50,10 @@ impl IsField for U64TestField { fn from_base_type(x: u64) -> u64 { Self::from_u64(x) } + + fn representative(x: u64) -> u64 { + x + } } impl IsTwoAdicField for U64TestField { diff --git a/math/src/field/traits.rs b/math/src/field/traits.rs index 9f084a912..ffdae875a 100644 --- a/math/src/field/traits.rs +++ b/math/src/field/traits.rs @@ -93,4 +93,7 @@ pub trait IsField: Debug + Clone { /// Takes as input an element of BaseType and returns the internal representation /// of that element in the field. fn from_base_type(x: Self::BaseType) -> Self::BaseType; + + // Returns the representative of the value stored + fn representative(a: Self::BaseType) -> Self::BaseType; } diff --git a/prover/src/air/polynomials.rs b/prover/src/air/polynomials.rs index 690755d8a..4d67a4e20 100644 --- a/prover/src/air/polynomials.rs +++ b/prover/src/air/polynomials.rs @@ -22,7 +22,8 @@ use winterfell::prover::{ pub struct MontgomeryConfig; impl IsMontgomeryConfiguration for MontgomeryConfig { const MODULUS: U384 = - U384::from("17"); + // hex 17 + U384::from("11"); } pub type U384PrimeField = MontgomeryBackendPrimeField; diff --git a/prover/src/fri/mod.rs b/prover/src/fri/mod.rs index bb6267a0b..56dca0fbb 100644 --- a/prover/src/fri/mod.rs +++ b/prover/src/fri/mod.rs @@ -56,6 +56,10 @@ pub fn fri(p_0: &mut Polynomial>, domain_0: &[FE]) -> FriCommitm let mut transcript = Transcript::new(); let evaluation_0 = p_0.evaluate_slice(domain_0); + + let d0: Vec<_> = domain_0.iter().map(|x| x.representative()).collect(); + + println!("d0: {:?}", d0); let merkle_tree = FriMerkleTree::build(&evaluation_0); // append the root of the merkle tree to the transcript @@ -85,7 +89,8 @@ pub fn fri(p_0: &mut Polynomial>, domain_0: &[FE]) -> FriCommitm // sample beta: // let beta_bytes = transcript.challenge(); // let beta = FE::from_bytes_be(&beta_bytes).unwrap(); - let beta = FE::new(U384::from("2")); + let beta = FE::new(U384::from("3")); + let (p_i, domain_i, evaluation_i) = next_fri_layer(&last_poly, &last_domain, &beta); let commitment_i = fri_commitment(&p_i, &domain_i, &evaluation_i, &mut transcript); diff --git a/prover/src/lib.rs b/prover/src/lib.rs index ffcd8f928..85e5b74f2 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -26,6 +26,8 @@ type U384PrimeField = MontgomeryBackendPrimeField; +// const MODULUS_MINUS_1: U384 = U384::from("10"); + const MODULUS_MINUS_1: U384 = U384::sub(&crate::air::polynomials::MontgomeryConfig::MODULUS, &U384::from("1")).0; const ORDER_OF_ROOTS_OF_UNITY_TRACE: u64 = 4; @@ -35,12 +37,15 @@ pub fn generate_vec_roots( subgroup_size: u64, coset_factor: u64, ) -> (Vec, U384FieldElement) { + let MODULUS_MINUS_1_FIELD: U384FieldElement = U384FieldElement::new(MODULUS_MINUS_1); let subgroup_size_u384: U384FieldElement = subgroup_size.into(); + let generator_field: U384FieldElement = 3.into(); let coset_factor_u384: U384FieldElement = coset_factor.into(); - let exp = (MODULUS_MINUS_1_FIELD) / subgroup_size_u384; + let exp = (&MODULUS_MINUS_1_FIELD) / &subgroup_size_u384; + let exp_384 = *exp.value(); let generator_of_subgroup = generator_field.pow(exp_384); @@ -109,6 +114,7 @@ pub fn prove( // * Generate Coset let (roots_of_unity, primitive_root) = crate::generate_vec_roots(ORDER_OF_ROOTS_OF_UNITY_TRACE, 1); + let (lde_roots_of_unity, lde_primitive_root) = crate::generate_vec_roots(ORDER_OF_ROOTS_OF_UNITY_FOR_LDE, 1); let trace = fibonacci_trace(pub_inputs); @@ -127,12 +133,20 @@ pub fn prove( let trace_poly_lde_merkle_tree = FriMerkleTree::build(&trace_poly_lde.as_slice()); // * Do FRI on the composition polynomials + + let mut composition_poly: Polynomial = + Polynomial { coefficients: [ + U384FieldElement::one(), + U384FieldElement::zero(), + U384FieldElement::one(), + U384FieldElement::one()].to_vec() }; + let lde_fri_commitment = crate::fri::fri(&mut composition_poly, &lde_roots_of_unity); // * Sample q_1, ..., q_m using Fiat-Shamir // let q_1 = transcript.challenge(); // @@@@@@@@@@@@@@@@@@@@@@ - let q_1: usize = 2; + let q_1: usize = 4; // * For every q_i, do FRI decommitment let fri_decommitment = fri_decommit_layers(&lde_fri_commitment, q_1); @@ -213,16 +227,18 @@ pub fn verify(proof: StarkQueryProof) -> bool { let trace_poly_root = proof.trace_lde_poly_root; // TODO: Use Fiat Shamir - let q_1: u64 = 2; - let (_roots_of_unity, mut primitive_root) = crate::generate_vec_roots(1024, 1); + let q_1: u64 = 4; + + let (_roots_of_unity, mut primitive_root) = crate::generate_vec_roots(ORDER_OF_ROOTS_OF_UNITY_FOR_LDE, 1); let evaluations = proof.trace_lde_poly_evaluations; // TODO: These could be multiple evaluations depending on how many q_i are sampled with Fiat Shamir let composition_poly_lde_evaluation = proof.composition_poly_lde_evaluations[0].clone(); + /* if composition_poly_lde_evaluation != &evaluations[2] - &evaluations[1] - &evaluations[0] { return false; - } + } */ for merkle_proof in proof.trace_lde_poly_inclusion_proofs { if !merkle_proof.verify(trace_poly_root.clone()) { @@ -252,7 +268,7 @@ pub fn verify(proof: StarkQueryProof) -> bool { } // TODO: use Fiat Shamir - let beta: u64 = 2; + let beta: u64 = 3; let (previous_auth_path, previous_auth_path_symmetric) = match proof .fri_decommitment @@ -263,8 +279,7 @@ pub fn verify(proof: StarkQueryProof) -> bool { None => return false, }; - primitive_root = primitive_root.pow(2_usize); - index = index % (1024 / (2_u64.pow(layer_number as u32))); + // index = index % (ORDER_OF_ROOTS_OF_UNITY_FOR_LDE / (2_u64.pow(layer_number as u32))); let evaluation_point = primitive_root.pow(index); println!("LAYER NUMBER: {}", layer_number); @@ -278,6 +293,8 @@ pub fn verify(proof: StarkQueryProof) -> bool { * (previous_auth_path.clone().value - previous_auth_path_symmetric.clone().value) / (U384FieldElement::new(U384::from("2")) * evaluation_point); + primitive_root = primitive_root.pow(2_usize); + println!("BEFORE LAST CHECK"); println!("V: {:?}", v); From 331d683ffb6ac73aaa9fb59bcc366a0be398c422 Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Tue, 28 Feb 2023 17:50:46 -0300 Subject: [PATCH 61/85] Go back to fibonacci example with test passing --- math/src/field/fields/u384_prime_field.rs | 8 +-- math/src/field/traits.rs | 2 +- prover/src/fri/fri_decommit.rs | 2 - prover/src/fri/fri_functions.rs | 2 - prover/src/fri/mod.rs | 5 +- prover/src/lib.rs | 66 +++++++++-------------- 6 files changed, 28 insertions(+), 57 deletions(-) diff --git a/math/src/field/fields/u384_prime_field.rs b/math/src/field/fields/u384_prime_field.rs index 7b7617cf1..98c8dc983 100644 --- a/math/src/field/fields/u384_prime_field.rs +++ b/math/src/field/fields/u384_prime_field.rs @@ -154,16 +154,10 @@ where // TO DO: Add tests for representatives fn representative(x: Self::BaseType) -> Self::BaseType { - MontgomeryAlgorithms::cios( - &x, - &U384::from_u64(1), - &C::MODULUS, - &C::MU - ) + MontgomeryAlgorithms::cios(&x, &U384::from_u64(1), &C::MODULUS, &C::MU) } } - impl ByteConversion for FieldElement> where C: IsMontgomeryConfiguration + Clone + Debug, diff --git a/math/src/field/traits.rs b/math/src/field/traits.rs index ffdae875a..884fb7ca1 100644 --- a/math/src/field/traits.rs +++ b/math/src/field/traits.rs @@ -93,7 +93,7 @@ pub trait IsField: Debug + Clone { /// Takes as input an element of BaseType and returns the internal representation /// of that element in the field. fn from_base_type(x: Self::BaseType) -> Self::BaseType; - + // Returns the representative of the value stored fn representative(a: Self::BaseType) -> Self::BaseType; } diff --git a/prover/src/fri/fri_decommit.rs b/prover/src/fri/fri_decommit.rs index d1e0d46a0..9c6558c82 100644 --- a/prover/src/fri/fri_decommit.rs +++ b/prover/src/fri/fri_decommit.rs @@ -34,9 +34,7 @@ pub fn fri_decommit_layers( for commit_i in commit { let length_i = commit_i.domain.len(); index = index % length_i; - println!("DECOMMIT DOMAIN LENGTH: {} INDEX: {}", length_i, index); let evaluation_i = commit_i.evaluation[index].clone(); - println!("EVALUATION I: {:?}", evaluation_i); let auth_path = commit_i.merkle_tree.get_proof(&evaluation_i).unwrap(); // symmetrical element diff --git a/prover/src/fri/fri_functions.rs b/prover/src/fri/fri_functions.rs index 41c095aee..72fb81211 100644 --- a/prover/src/fri/fri_functions.rs +++ b/prover/src/fri/fri_functions.rs @@ -39,9 +39,7 @@ pub fn next_fri_layer( ) -> (Polynomial, Vec, Vec) { let ret_poly = fold_polynomial(poly, beta); let ret_next_domain = next_domain(domain); - println!("NEXT DOMAIN: {:?}", ret_next_domain[2]); let ret_evaluation = ret_poly.evaluate_slice(&ret_next_domain); - println!("NEXT EVALUATION: {:?}", ret_evaluation[2]); (ret_poly, ret_next_domain, ret_evaluation) } diff --git a/prover/src/fri/mod.rs b/prover/src/fri/mod.rs index 56dca0fbb..0107a7383 100644 --- a/prover/src/fri/mod.rs +++ b/prover/src/fri/mod.rs @@ -57,9 +57,6 @@ pub fn fri(p_0: &mut Polynomial>, domain_0: &[FE]) -> FriCommitm let evaluation_0 = p_0.evaluate_slice(domain_0); - let d0: Vec<_> = domain_0.iter().map(|x| x.representative()).collect(); - - println!("d0: {:?}", d0); let merkle_tree = FriMerkleTree::build(&evaluation_0); // append the root of the merkle tree to the transcript @@ -89,7 +86,7 @@ pub fn fri(p_0: &mut Polynomial>, domain_0: &[FE]) -> FriCommitm // sample beta: // let beta_bytes = transcript.challenge(); // let beta = FE::from_bytes_be(&beta_bytes).unwrap(); - let beta = FE::new(U384::from("3")); + let beta = FE::new(U384::from("4")); let (p_i, domain_i, evaluation_i) = next_fri_layer(&last_poly, &last_domain, &beta); diff --git a/prover/src/lib.rs b/prover/src/lib.rs index 85e5b74f2..59811c34c 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -28,7 +28,11 @@ type U384FieldElement = FieldElement; // const MODULUS_MINUS_1: U384 = U384::from("10"); -const MODULUS_MINUS_1: U384 = U384::sub(&crate::air::polynomials::MontgomeryConfig::MODULUS, &U384::from("1")).0; +const MODULUS_MINUS_1: U384 = U384::sub( + &crate::air::polynomials::MontgomeryConfig::MODULUS, + &U384::from("1"), +) +.0; const ORDER_OF_ROOTS_OF_UNITY_TRACE: u64 = 4; const ORDER_OF_ROOTS_OF_UNITY_FOR_LDE: u64 = 16; @@ -37,10 +41,9 @@ pub fn generate_vec_roots( subgroup_size: u64, coset_factor: u64, ) -> (Vec, U384FieldElement) { - let MODULUS_MINUS_1_FIELD: U384FieldElement = U384FieldElement::new(MODULUS_MINUS_1); let subgroup_size_u384: U384FieldElement = subgroup_size.into(); - + let generator_field: U384FieldElement = 3.into(); let coset_factor_u384: U384FieldElement = coset_factor.into(); @@ -62,20 +65,12 @@ pub fn generate_vec_roots( #[derive(Debug, Clone)] pub struct StarkQueryProof { - // TODO: fill this when we know what a proof entails pub trace_lde_poly_root: U384FieldElement, pub trace_lde_poly_evaluations: Vec, /// Merkle paths for the trace polynomial evaluations pub trace_lde_poly_inclusion_proofs: Vec>, pub composition_poly_lde_evaluations: Vec, - - // composition_poly_root: U384FieldElement, pub fri_layers_merkle_roots: Vec, - // pub fri_layers_merkle_proofs: Vec<( - // Proof, - // Proof, - // )>, - // pub last_fri_layer_evaluation: U384FieldElement, pub fri_decommitment: FriDecommitment, } @@ -86,7 +81,7 @@ pub use lambdaworks_crypto::merkle_tree::DefaultHasher; pub type FriMerkleTree = MerkleTree; pub fn fibonacci_trace(initial_values: [U384FieldElement; 2]) -> Vec { - let mut ret: Vec = vec![]; + let mut ret: Vec = vec![]; ret.push(initial_values[0].clone()); ret.push(initial_values[1].clone()); @@ -113,13 +108,14 @@ pub fn prove( // * Generate Coset - let (roots_of_unity, primitive_root) = crate::generate_vec_roots(ORDER_OF_ROOTS_OF_UNITY_TRACE, 1); + let (roots_of_unity, primitive_root) = + crate::generate_vec_roots(ORDER_OF_ROOTS_OF_UNITY_TRACE, 1); - let (lde_roots_of_unity, lde_primitive_root) = crate::generate_vec_roots(ORDER_OF_ROOTS_OF_UNITY_FOR_LDE, 1); + let (lde_roots_of_unity, lde_primitive_root) = + crate::generate_vec_roots(ORDER_OF_ROOTS_OF_UNITY_FOR_LDE, 1); let trace = fibonacci_trace(pub_inputs); - let mut trace_poly = Polynomial::interpolate(&roots_of_unity, &trace); let mut composition_poly = get_composition_poly(trace_poly.clone(), &primitive_root); @@ -133,14 +129,6 @@ pub fn prove( let trace_poly_lde_merkle_tree = FriMerkleTree::build(&trace_poly_lde.as_slice()); // * Do FRI on the composition polynomials - - let mut composition_poly: Polynomial = - Polynomial { coefficients: [ - U384FieldElement::one(), - U384FieldElement::zero(), - U384FieldElement::one(), - U384FieldElement::one()].to_vec() }; - let lde_fri_commitment = crate::fri::fri(&mut composition_poly, &lde_roots_of_unity); // * Sample q_1, ..., q_m using Fiat-Shamir @@ -181,12 +169,19 @@ pub fn prove( ); merkle_paths.push( trace_poly_lde_merkle_tree - .get_proof_by_pos(q_1 + (ORDER_OF_ROOTS_OF_UNITY_FOR_LDE / ORDER_OF_ROOTS_OF_UNITY_TRACE) as usize, trace_lde_poly_evaluations[1].clone()) + .get_proof_by_pos( + q_1 + (ORDER_OF_ROOTS_OF_UNITY_FOR_LDE / ORDER_OF_ROOTS_OF_UNITY_TRACE) as usize, + trace_lde_poly_evaluations[1].clone(), + ) .unwrap(), ); merkle_paths.push( trace_poly_lde_merkle_tree - .get_proof_by_pos(q_1 + (ORDER_OF_ROOTS_OF_UNITY_FOR_LDE / ORDER_OF_ROOTS_OF_UNITY_TRACE) as usize * 2, trace_lde_poly_evaluations[2].clone()) + .get_proof_by_pos( + q_1 + (ORDER_OF_ROOTS_OF_UNITY_FOR_LDE / ORDER_OF_ROOTS_OF_UNITY_TRACE) as usize + * 2, + trace_lde_poly_evaluations[2].clone(), + ) .unwrap(), ); @@ -228,17 +223,17 @@ pub fn verify(proof: StarkQueryProof) -> bool { // TODO: Use Fiat Shamir let q_1: u64 = 4; - - let (_roots_of_unity, mut primitive_root) = crate::generate_vec_roots(ORDER_OF_ROOTS_OF_UNITY_FOR_LDE, 1); + + let (_roots_of_unity, mut primitive_root) = + crate::generate_vec_roots(ORDER_OF_ROOTS_OF_UNITY_FOR_LDE, 1); let evaluations = proof.trace_lde_poly_evaluations; // TODO: These could be multiple evaluations depending on how many q_i are sampled with Fiat Shamir let composition_poly_lde_evaluation = proof.composition_poly_lde_evaluations[0].clone(); - /* if composition_poly_lde_evaluation != &evaluations[2] - &evaluations[1] - &evaluations[0] { return false; - } */ + } for merkle_proof in proof.trace_lde_poly_inclusion_proofs { if !merkle_proof.verify(trace_poly_root.clone()) { @@ -268,7 +263,7 @@ pub fn verify(proof: StarkQueryProof) -> bool { } // TODO: use Fiat Shamir - let beta: u64 = 3; + let beta: u64 = 4; let (previous_auth_path, previous_auth_path_symmetric) = match proof .fri_decommitment @@ -279,14 +274,8 @@ pub fn verify(proof: StarkQueryProof) -> bool { None => return false, }; - // index = index % (ORDER_OF_ROOTS_OF_UNITY_FOR_LDE / (2_u64.pow(layer_number as u32))); let evaluation_point = primitive_root.pow(index); - println!("LAYER NUMBER: {}", layer_number); - println!("PRIMITIVE ROOT: {:?}", primitive_root); - println!("INDEX: {:?}", index); - println!("EVALUATION POINT: {:?}", evaluation_point); - let v = (previous_auth_path.clone().value + previous_auth_path_symmetric.clone().value) / U384FieldElement::new(U384::from("2")) + U384FieldElement::new(U384::from_u64(beta)) @@ -295,11 +284,6 @@ pub fn verify(proof: StarkQueryProof) -> bool { primitive_root = primitive_root.pow(2_usize); - println!("BEFORE LAST CHECK"); - - println!("V: {:?}", v); - println!("FRI LAYER AUTH PATH VALUE; {:?}", fri_layer_auth_path.value); - if v != fri_layer_auth_path.value { return false; } From ce8b1ed07b2c95d3965b05c30bfdff8ac8a852a4 Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Tue, 28 Feb 2023 17:55:17 -0300 Subject: [PATCH 62/85] Refactor functions that use fiat shamir to take in a transcript --- prover/src/fri/mod.rs | 10 ++++++---- prover/src/lib.rs | 17 ++++++----------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/prover/src/fri/mod.rs b/prover/src/fri/mod.rs index 0107a7383..e51b10ab0 100644 --- a/prover/src/fri/mod.rs +++ b/prover/src/fri/mod.rs @@ -51,10 +51,12 @@ pub fn fri_commitment( } } -pub fn fri(p_0: &mut Polynomial>, domain_0: &[FE]) -> FriCommitmentVec { +pub fn fri( + p_0: &mut Polynomial>, + domain_0: &[FE], + transcript: &mut Transcript, +) -> FriCommitmentVec { let mut fri_commitment_list = FriCommitmentVec::new(); - let mut transcript = Transcript::new(); - let evaluation_0 = p_0.evaluate_slice(domain_0); let merkle_tree = FriMerkleTree::build(&evaluation_0); @@ -90,7 +92,7 @@ pub fn fri(p_0: &mut Polynomial>, domain_0: &[FE]) -> FriCommitm let (p_i, domain_i, evaluation_i) = next_fri_layer(&last_poly, &last_domain, &beta); - let commitment_i = fri_commitment(&p_i, &domain_i, &evaluation_i, &mut transcript); + let commitment_i = fri_commitment(&p_i, &domain_i, &evaluation_i, transcript); // append root of merkle tree to transcript let tree = &commitment_i.merkle_tree; diff --git a/prover/src/lib.rs b/prover/src/lib.rs index 59811c34c..98e9e43f8 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -102,7 +102,7 @@ pub fn prove( // where // A: Air, { - // let mut transcript = Transcript::new(); + let transcript = &mut Transcript::new(); // * Generate composition polynomials using Winterfell // let (mut composition_poly, mut trace_poly) = get_cp_and_tp(air, trace, pub_inputs).unwrap(); @@ -116,20 +116,19 @@ pub fn prove( let trace = fibonacci_trace(pub_inputs); - let mut trace_poly = Polynomial::interpolate(&roots_of_unity, &trace); + let trace_poly = Polynomial::interpolate(&roots_of_unity, &trace); let mut composition_poly = get_composition_poly(trace_poly.clone(), &primitive_root); // * Do Reed-Solomon on the trace and composition polynomials using some blowup factor - let composition_poly_lde = composition_poly.evaluate_slice(lde_roots_of_unity.as_slice()); let trace_poly_lde = trace_poly.evaluate_slice(lde_roots_of_unity.as_slice()); // * Commit to both polynomials using a Merkle Tree - let composition_poly_lde_merkle_tree = FriMerkleTree::build(composition_poly_lde.as_slice()); let trace_poly_lde_merkle_tree = FriMerkleTree::build(&trace_poly_lde.as_slice()); // * Do FRI on the composition polynomials - let lde_fri_commitment = crate::fri::fri(&mut composition_poly, &lde_roots_of_unity); + let lde_fri_commitment = + crate::fri::fri(&mut composition_poly, &lde_roots_of_unity, transcript); // * Sample q_1, ..., q_m using Fiat-Shamir // let q_1 = transcript.challenge(); @@ -186,7 +185,6 @@ pub fn prove( ); let trace_root = trace_poly_lde_merkle_tree.root.clone(); - // let composition_poly_root = composition_poly_lde_merkle_tree.root.borrow().clone().hash; let fri_layers_merkle_roots: Vec = lde_fri_commitment .iter() @@ -221,9 +219,6 @@ fn get_composition_poly( pub fn verify(proof: StarkQueryProof) -> bool { let trace_poly_root = proof.trace_lde_poly_root; - // TODO: Use Fiat Shamir - let q_1: u64 = 4; - let (_roots_of_unity, mut primitive_root) = crate::generate_vec_roots(ORDER_OF_ROOTS_OF_UNITY_FOR_LDE, 1); let evaluations = proof.trace_lde_poly_evaluations; @@ -242,7 +237,7 @@ pub fn verify(proof: StarkQueryProof) -> bool { } // FRI VERIFYING BEGINS HERE - let mut index = q_1; + let decommitment_index: u64 = 4; for ( layer_number, @@ -274,7 +269,7 @@ pub fn verify(proof: StarkQueryProof) -> bool { None => return false, }; - let evaluation_point = primitive_root.pow(index); + let evaluation_point = primitive_root.pow(decommitment_index); let v = (previous_auth_path.clone().value + previous_auth_path_symmetric.clone().value) / U384FieldElement::new(U384::from("2")) From 2b2514e43f4296029e6b1073b7844ce4aa3b437f Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Tue, 28 Feb 2023 18:10:24 -0300 Subject: [PATCH 63/85] Add TODO --- prover/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/prover/src/lib.rs b/prover/src/lib.rs index 98e9e43f8..a55515220 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -301,6 +301,7 @@ pub fn verify(proof: StarkQueryProof) -> bool { // TODOS after basic fibonacci works: // - Add Fiat Shamir // - Add Zerofiers +// - Check last evaluation point // - Instead of returning a bool, make an error type encoding each possible failure in the verifying pipeline so failures give more info. // - Unhardcode polynomials, use Winterfell AIR // - Coset evaluation From 9aa4e9dc80434d788e8bf336e0c38bd6e297a282 Mon Sep 17 00:00:00 2001 From: MauroFab Date: Wed, 1 Mar 2023 12:00:15 -0300 Subject: [PATCH 64/85] Add comments --- prover/src/fri/fri_decommit.rs | 4 ++-- prover/src/lib.rs | 26 +++++++++++++++++--------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/prover/src/fri/fri_decommit.rs b/prover/src/fri/fri_decommit.rs index 9c6558c82..51884ef5b 100644 --- a/prover/src/fri/fri_decommit.rs +++ b/prover/src/fri/fri_decommit.rs @@ -1,5 +1,5 @@ use super::FE; -use crate::{fri::fri_commitment::FriCommitmentVec, U384FieldElement, U384PrimeField}; +use crate::{fri::fri_commitment::FriCommitmentVec, U384PrimeField}; pub use lambdaworks_crypto::fiat_shamir::transcript::Transcript; use lambdaworks_crypto::{hash::traits::IsCryptoHash, merkle_tree::DefaultHasher}; @@ -14,7 +14,7 @@ pub struct FriDecommitment { Proof, Proof, )>, - pub last_layer_evaluation: U384FieldElement, + pub last_layer_evaluation: FE, } // verifier chooses a randomness and get the index where diff --git a/prover/src/lib.rs b/prover/src/lib.rs index a55515220..821f9ee4b 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -239,6 +239,9 @@ pub fn verify(proof: StarkQueryProof) -> bool { // FRI VERIFYING BEGINS HERE let decommitment_index: u64 = 4; + // For each (merkle_root, merkle_auth_path) + // With the auth path containining the element that the + // path proves it's existance for ( layer_number, (fri_layer_merkle_root, (fri_layer_auth_path, fri_layer_auth_path_symmetric)), @@ -247,6 +250,8 @@ pub fn verify(proof: StarkQueryProof) -> bool { .iter() .zip(proof.fri_decommitment.layer_merkle_paths.iter()) .enumerate() + // Since we always derive the current layer from the previous layer + // We start with the second one, skipping the first, so previous is layer is the first one .skip(1) { if !fri_layer_auth_path.verify(fri_layer_merkle_root.clone()) { @@ -260,17 +265,20 @@ pub fn verify(proof: StarkQueryProof) -> bool { // TODO: use Fiat Shamir let beta: u64 = 4; - let (previous_auth_path, previous_auth_path_symmetric) = match proof - .fri_decommitment - .layer_merkle_paths - .get(layer_number - 1) - { - Some(previous) => previous, - None => return false, - }; + let (previous_auth_path, previous_auth_path_symmetric) = + proof + .fri_decommitment + .layer_merkle_paths + .get(layer_number - 1) + // TODO: Check at the start of the FRI operation + // if layer_merkle_paths has the right amount of elements + .unwrap(); + // evaluation point = w ^ i in the Stark literature let evaluation_point = primitive_root.pow(decommitment_index); - + + // v is the calculated element for the + // co linearity check let v = (previous_auth_path.clone().value + previous_auth_path_symmetric.clone().value) / U384FieldElement::new(U384::from("2")) + U384FieldElement::new(U384::from_u64(beta)) From 609da6f403c3e1f5c4fdba284e1e5c6e4246bb6d Mon Sep 17 00:00:00 2001 From: MauroFab Date: Wed, 1 Mar 2023 12:05:55 -0300 Subject: [PATCH 65/85] Moved field definition to lib, removed duplicated definitions --- prover/src/air/polynomials.rs | 13 ++----------- prover/src/fri/mod.rs | 4 ++-- prover/src/lib.rs | 23 ++++++++++++++++------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/prover/src/air/polynomials.rs b/prover/src/air/polynomials.rs index 4d67a4e20..80c7836a0 100644 --- a/prover/src/air/polynomials.rs +++ b/prover/src/air/polynomials.rs @@ -12,23 +12,14 @@ use winterfell::{ Air, AuxTraceRandElements, Matrix, Serializable, Trace, TraceTable, }; +use crate::U384FieldElement; + use super::errors::ProverError; use winterfell::prover::{ build_trace_commitment_f, channel::ProverChannel, constraints::ConstraintEvaluator, domain::StarkDomain, trace::commitment::TraceCommitment, }; -#[derive(Clone, Debug)] -pub struct MontgomeryConfig; -impl IsMontgomeryConfiguration for MontgomeryConfig { - const MODULUS: U384 = - // hex 17 - U384::from("11"); -} - -pub type U384PrimeField = MontgomeryBackendPrimeField; -pub type U384FieldElement = FieldElement; - /// Given a CompositionPoly from winterfell, extract its coefficients /// as a vector. #[allow(dead_code)] diff --git a/prover/src/fri/mod.rs b/prover/src/fri/mod.rs index e51b10ab0..b6893e58d 100644 --- a/prover/src/fri/mod.rs +++ b/prover/src/fri/mod.rs @@ -17,8 +17,8 @@ pub use lambdaworks_math::{ polynomial::Polynomial, }; -pub type F = crate::air::polynomials::U384PrimeField; -pub type FE = crate::air::polynomials::U384FieldElement; +pub type F = crate::U384PrimeField; +pub type FE = crate::U384FieldElement; /// # Params /// diff --git a/prover/src/lib.rs b/prover/src/lib.rs index 821f9ee4b..bbe8981eb 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -22,21 +22,30 @@ use lambdaworks_math::{ unsigned_integer::element::U384, }; -type U384PrimeField = MontgomeryBackendPrimeField; - -type U384FieldElement = FieldElement; +// DEFINITION OF THE USED FIELD +#[derive(Clone, Debug)] +pub struct MontgomeryConfig; +impl IsMontgomeryConfiguration for MontgomeryConfig { + const MODULUS: U384 = + // hex 17 + U384::from("11"); +} -// const MODULUS_MINUS_1: U384 = U384::from("10"); +pub type U384PrimeField = MontgomeryBackendPrimeField; +pub type U384FieldElement = FieldElement; const MODULUS_MINUS_1: U384 = U384::sub( - &crate::air::polynomials::MontgomeryConfig::MODULUS, + &MontgomeryConfig::MODULUS, &U384::from("1"), -) -.0; +).0; + +// DEFINITION OF CONSTANTS const ORDER_OF_ROOTS_OF_UNITY_TRACE: u64 = 4; const ORDER_OF_ROOTS_OF_UNITY_FOR_LDE: u64 = 16; +// DEFINITION OF FUNCTIONS + pub fn generate_vec_roots( subgroup_size: u64, coset_factor: u64, From 72db780bfc3437acb018c4f01e1d8a6dfa1d4032 Mon Sep 17 00:00:00 2001 From: MauroFab Date: Wed, 1 Mar 2023 12:09:40 -0300 Subject: [PATCH 66/85] Renamed types --- prover/src/air/polynomials.rs | 18 +++++------ prover/src/fri/fri_decommit.rs | 6 ++-- prover/src/fri/mod.rs | 4 +-- prover/src/lib.rs | 56 +++++++++++++++++----------------- 4 files changed, 42 insertions(+), 42 deletions(-) diff --git a/prover/src/air/polynomials.rs b/prover/src/air/polynomials.rs index 80c7836a0..3f251305a 100644 --- a/prover/src/air/polynomials.rs +++ b/prover/src/air/polynomials.rs @@ -12,7 +12,7 @@ use winterfell::{ Air, AuxTraceRandElements, Matrix, Serializable, Trace, TraceTable, }; -use crate::U384FieldElement; +use crate::FE; use super::errors::ProverError; use winterfell::prover::{ @@ -41,10 +41,10 @@ pub(crate) fn get_coefficients(matrix_poly: Matrix) -> Vec } #[allow(dead_code)] -pub(crate) fn winter_2_lambda_felts(coeffs: Matrix) -> Vec { +pub(crate) fn winter_2_lambda_felts(coeffs: Matrix) -> Vec { get_coefficients(coeffs) .into_iter() - .map(|c| U384FieldElement::from(&U384::from(&c.to_string()))) + .map(|c| FE::from(&U384::from(&c.to_string()))) .collect() } @@ -56,7 +56,7 @@ pub fn get_cp_and_tp( air: A, trace: TraceTable, pub_inputs: A::PublicInputs, -) -> Result<(Polynomial, Polynomial), ProverError> +) -> Result<(Polynomial, Polynomial), ProverError> where A: Air, { @@ -95,7 +95,7 @@ where .map_err(|e| ProverError::CompositionPolyError(e))? .data; - let cp_coeffs: Vec = winter_2_lambda_felts(composition_poly); + let cp_coeffs: Vec = winter_2_lambda_felts(composition_poly); Ok((Polynomial::new(&cp_coeffs), Polynomial::new(&tp_coeffs))) } @@ -152,7 +152,7 @@ where // // TODO: this coefficients should be checked correctly to know // // the test is really passing -// let expected_cp_coeffs: Vec = vec![ +// let expected_cp_coeffs: Vec = vec![ // 73805846515134368521942875729025268850u128, // 251094867283236114961184226859763993364, // 24104107408363517664638843184319555199, @@ -172,12 +172,12 @@ where // ] // .into_iter() // .map(BaseElement::new) -// .map(|c| U384FieldElement::from(&U384::from(&c.to_string()))) +// .map(|c| FE::from(&U384::from(&c.to_string()))) // .collect(); // // TODO: this coefficients should be checked correctly to know // // the test is really passing -// let expected_tp_coeffs: Vec = vec![ +// let expected_tp_coeffs: Vec = vec![ // 191794735525862843530824769197527107708, // 223814277178031177559040503778682093811, // 330061736062598381779522724430379788786, @@ -189,7 +189,7 @@ where // ] // .into_iter() // .map(BaseElement::new) -// .map(|c| U384FieldElement::from(&U384::from(&c.to_string()))) +// .map(|c| FE::from(&U384::from(&c.to_string()))) // .collect(); // let expected_cp = Polynomial::new(&expected_cp_coeffs); diff --git a/prover/src/fri/fri_decommit.rs b/prover/src/fri/fri_decommit.rs index 51884ef5b..3c5f84868 100644 --- a/prover/src/fri/fri_decommit.rs +++ b/prover/src/fri/fri_decommit.rs @@ -1,5 +1,5 @@ use super::FE; -use crate::{fri::fri_commitment::FriCommitmentVec, U384PrimeField}; +use crate::{fri::fri_commitment::FriCommitmentVec, PrimeField}; pub use lambdaworks_crypto::fiat_shamir::transcript::Transcript; use lambdaworks_crypto::{hash::traits::IsCryptoHash, merkle_tree::DefaultHasher}; @@ -11,8 +11,8 @@ use lambdaworks_math::{ #[derive(Debug, Clone)] pub struct FriDecommitment { pub layer_merkle_paths: Vec<( - Proof, - Proof, + Proof, + Proof, )>, pub last_layer_evaluation: FE, } diff --git a/prover/src/fri/mod.rs b/prover/src/fri/mod.rs index b6893e58d..658841abe 100644 --- a/prover/src/fri/mod.rs +++ b/prover/src/fri/mod.rs @@ -17,8 +17,8 @@ pub use lambdaworks_math::{ polynomial::Polynomial, }; -pub type F = crate::U384PrimeField; -pub type FE = crate::U384FieldElement; +pub type F = crate::PrimeField; +pub type FE = crate::FE; /// # Params /// diff --git a/prover/src/lib.rs b/prover/src/lib.rs index bbe8981eb..5cf8f47b3 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -31,8 +31,8 @@ impl IsMontgomeryConfiguration for MontgomeryConfig { U384::from("11"); } -pub type U384PrimeField = MontgomeryBackendPrimeField; -pub type U384FieldElement = FieldElement; +pub type PrimeField = MontgomeryBackendPrimeField; +pub type FE = FieldElement; const MODULUS_MINUS_1: U384 = U384::sub( &MontgomeryConfig::MODULUS, @@ -49,12 +49,12 @@ const ORDER_OF_ROOTS_OF_UNITY_FOR_LDE: u64 = 16; pub fn generate_vec_roots( subgroup_size: u64, coset_factor: u64, -) -> (Vec, U384FieldElement) { - let MODULUS_MINUS_1_FIELD: U384FieldElement = U384FieldElement::new(MODULUS_MINUS_1); - let subgroup_size_u384: U384FieldElement = subgroup_size.into(); +) -> (Vec, FE) { + let MODULUS_MINUS_1_FIELD: FE = FE::new(MODULUS_MINUS_1); + let subgroup_size_u384: FE = subgroup_size.into(); - let generator_field: U384FieldElement = 3.into(); - let coset_factor_u384: U384FieldElement = coset_factor.into(); + let generator_field: FE = 3.into(); + let coset_factor_u384: FE = coset_factor.into(); let exp = (&MODULUS_MINUS_1_FIELD) / &subgroup_size_u384; @@ -74,12 +74,12 @@ pub fn generate_vec_roots( #[derive(Debug, Clone)] pub struct StarkQueryProof { - pub trace_lde_poly_root: U384FieldElement, - pub trace_lde_poly_evaluations: Vec, + pub trace_lde_poly_root: FE, + pub trace_lde_poly_evaluations: Vec, /// Merkle paths for the trace polynomial evaluations - pub trace_lde_poly_inclusion_proofs: Vec>, - pub composition_poly_lde_evaluations: Vec, - pub fri_layers_merkle_roots: Vec, + pub trace_lde_poly_inclusion_proofs: Vec>, + pub composition_poly_lde_evaluations: Vec, + pub fri_layers_merkle_roots: Vec, pub fri_decommitment: FriDecommitment, } @@ -87,10 +87,10 @@ pub type StarkProof = Vec; pub use lambdaworks_crypto::merkle_tree::merkle::MerkleTree; pub use lambdaworks_crypto::merkle_tree::DefaultHasher; -pub type FriMerkleTree = MerkleTree; +pub type FriMerkleTree = MerkleTree; -pub fn fibonacci_trace(initial_values: [U384FieldElement; 2]) -> Vec { - let mut ret: Vec = vec![]; +pub fn fibonacci_trace(initial_values: [FE; 2]) -> Vec { + let mut ret: Vec = vec![]; ret.push(initial_values[0].clone()); ret.push(initial_values[1].clone()); @@ -106,7 +106,7 @@ pub fn prove( // air: A, // trace: TraceTable, // pub_inputs: A::PublicInputs, - pub_inputs: [U384FieldElement; 2], + pub_inputs: [FE; 2], ) -> StarkQueryProof // where // A: Air, @@ -195,7 +195,7 @@ pub fn prove( let trace_root = trace_poly_lde_merkle_tree.root.clone(); - let fri_layers_merkle_roots: Vec = lde_fri_commitment + let fri_layers_merkle_roots: Vec = lde_fri_commitment .iter() .map(|fri_commitment| fri_commitment.merkle_tree.root.clone()) .collect(); @@ -211,14 +211,14 @@ pub fn prove( } fn get_composition_poly( - trace_poly: Polynomial, - root_of_unity: &U384FieldElement, -) -> Polynomial { + trace_poly: Polynomial, + root_of_unity: &FE, +) -> Polynomial { let w_squared_x = Polynomial::new(&vec![ - U384FieldElement::zero(), + FE::zero(), root_of_unity * root_of_unity, ]); - let w_x = Polynomial::new(&vec![U384FieldElement::zero(), root_of_unity.clone()]); + let w_x = Polynomial::new(&vec![FE::zero(), root_of_unity.clone()]); polynomial::compose(&trace_poly, &w_squared_x) - polynomial::compose(&trace_poly, &w_x) @@ -289,10 +289,10 @@ pub fn verify(proof: StarkQueryProof) -> bool { // v is the calculated element for the // co linearity check let v = (previous_auth_path.clone().value + previous_auth_path_symmetric.clone().value) - / U384FieldElement::new(U384::from("2")) - + U384FieldElement::new(U384::from_u64(beta)) + / FE::new(U384::from("2")) + + FE::new(U384::from_u64(beta)) * (previous_auth_path.clone().value - previous_auth_path_symmetric.clone().value) - / (U384FieldElement::new(U384::from("2")) * evaluation_point); + / (FE::new(U384::from("2")) * evaluation_point); primitive_root = primitive_root.pow(2_usize); @@ -325,7 +325,7 @@ pub fn verify(proof: StarkQueryProof) -> bool { #[cfg(test)] mod tests { - use crate::{verify, U384FieldElement}; + use crate::{verify, FE}; use super::prove; use lambdaworks_math::{field::element::FieldElement, unsigned_integer::element::U384}; @@ -334,8 +334,8 @@ mod tests { #[test] fn test_prove() { let result = prove([ - U384FieldElement::new(U384::from("1")), - U384FieldElement::new(U384::from("1")), + FE::new(U384::from("1")), + FE::new(U384::from("1")), ]); assert!(verify(result)); } From e09904baf2ae881ac8ce1b2bb4469081f7edb70a Mon Sep 17 00:00:00 2001 From: MauroFab Date: Wed, 1 Mar 2023 12:16:22 -0300 Subject: [PATCH 67/85] Simplified operations --- prover/src/lib.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/prover/src/lib.rs b/prover/src/lib.rs index 5cf8f47b3..a9e84612a 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -288,11 +288,14 @@ pub fn verify(proof: StarkQueryProof) -> bool { // v is the calculated element for the // co linearity check - let v = (previous_auth_path.clone().value + previous_auth_path_symmetric.clone().value) - / FE::new(U384::from("2")) - + FE::new(U384::from_u64(beta)) - * (previous_auth_path.clone().value - previous_auth_path_symmetric.clone().value) - / (FE::new(U384::from("2")) * evaluation_point); + let two = &FE::new(U384::from("2")); + let beta = FE::new(U384::from_u64(beta)); + let v = + (&previous_auth_path.value + &previous_auth_path_symmetric.value) + / two + + + beta * (&previous_auth_path.value - &previous_auth_path_symmetric.value) + / (two * evaluation_point); primitive_root = primitive_root.pow(2_usize); From 25d5b1d509baef74f2cd61e491a859091528772e Mon Sep 17 00:00:00 2001 From: MauroFab Date: Wed, 1 Mar 2023 12:36:51 -0300 Subject: [PATCH 68/85] Refactor roots of unity generator --- prover/src/lib.rs | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/prover/src/lib.rs b/prover/src/lib.rs index a9e84612a..d44e549e7 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -39,6 +39,9 @@ const MODULUS_MINUS_1: U384 = U384::sub( &U384::from("1"), ).0; +/// Subgroup generator to generate the roots of unity +const FIELD_SUBGROUP_GENERATOR: u64 = 3; + // DEFINITION OF CONSTANTS const ORDER_OF_ROOTS_OF_UNITY_TRACE: u64 = 4; @@ -46,17 +49,25 @@ const ORDER_OF_ROOTS_OF_UNITY_FOR_LDE: u64 = 16; // DEFINITION OF FUNCTIONS -pub fn generate_vec_roots( - subgroup_size: u64, + +/// This functions takes a roots of unity and a coset factor +/// If coset_factor is 1, it's just expanding the roots of unity +/// w ^ 0, w ^ 1, w ^ 2 .... w ^ n-1 +/// If coset_factor is h +/// h * w ^ 0, h * w ^ 1 .... h * w ^ n-1 +// doesn't need to return the primitive root w ^ 1 +pub fn generate_roots_of_unity_coset( + root_of_unity_size: u64, coset_factor: u64, ) -> (Vec, FE) { - let MODULUS_MINUS_1_FIELD: FE = FE::new(MODULUS_MINUS_1); - let subgroup_size_u384: FE = subgroup_size.into(); - let generator_field: FE = 3.into(); + let modulus_minus_1_field: FE = FE::new(MODULUS_MINUS_1); + let subgroup_size_u384: FE = root_of_unity_size.into(); + + let generator_field: FE = FIELD_SUBGROUP_GENERATOR.into(); let coset_factor_u384: FE = coset_factor.into(); - let exp = (&MODULUS_MINUS_1_FIELD) / &subgroup_size_u384; + let exp = (&modulus_minus_1_field) / &subgroup_size_u384; let exp_384 = *exp.value(); @@ -64,7 +75,7 @@ pub fn generate_vec_roots( let mut numbers = Vec::new(); - for exp in 0..subgroup_size { + for exp in 0..root_of_unity_size { let ret = generator_of_subgroup.pow(exp) * &coset_factor_u384; numbers.push(ret.clone()); } @@ -118,10 +129,10 @@ pub fn prove( // * Generate Coset let (roots_of_unity, primitive_root) = - crate::generate_vec_roots(ORDER_OF_ROOTS_OF_UNITY_TRACE, 1); + generate_roots_of_unity_coset(ORDER_OF_ROOTS_OF_UNITY_TRACE, 1); let (lde_roots_of_unity, lde_primitive_root) = - crate::generate_vec_roots(ORDER_OF_ROOTS_OF_UNITY_FOR_LDE, 1); + generate_roots_of_unity_coset(ORDER_OF_ROOTS_OF_UNITY_FOR_LDE, 1); let trace = fibonacci_trace(pub_inputs); @@ -229,7 +240,7 @@ pub fn verify(proof: StarkQueryProof) -> bool { let trace_poly_root = proof.trace_lde_poly_root; let (_roots_of_unity, mut primitive_root) = - crate::generate_vec_roots(ORDER_OF_ROOTS_OF_UNITY_FOR_LDE, 1); + generate_roots_of_unity_coset(ORDER_OF_ROOTS_OF_UNITY_FOR_LDE, 1); let evaluations = proof.trace_lde_poly_evaluations; // TODO: These could be multiple evaluations depending on how many q_i are sampled with Fiat Shamir From 47230dd9731db5466f43b22aa5da2b779f42ef6d Mon Sep 17 00:00:00 2001 From: MauroFab Date: Wed, 1 Mar 2023 12:40:06 -0300 Subject: [PATCH 69/85] Small refactor --- prover/src/lib.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/prover/src/lib.rs b/prover/src/lib.rs index d44e549e7..2ebb33978 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -49,7 +49,6 @@ const ORDER_OF_ROOTS_OF_UNITY_FOR_LDE: u64 = 16; // DEFINITION OF FUNCTIONS - /// This functions takes a roots of unity and a coset factor /// If coset_factor is 1, it's just expanding the roots of unity /// w ^ 0, w ^ 1, w ^ 2 .... w ^ n-1 @@ -62,16 +61,14 @@ pub fn generate_roots_of_unity_coset( ) -> (Vec, FE) { let modulus_minus_1_field: FE = FE::new(MODULUS_MINUS_1); - let subgroup_size_u384: FE = root_of_unity_size.into(); + let subgroup_size: FE = root_of_unity_size.into(); let generator_field: FE = FIELD_SUBGROUP_GENERATOR.into(); let coset_factor_u384: FE = coset_factor.into(); - let exp = (&modulus_minus_1_field) / &subgroup_size_u384; - - let exp_384 = *exp.value(); - - let generator_of_subgroup = generator_field.pow(exp_384); + let exp = (&modulus_minus_1_field) / &subgroup_size; + + let generator_of_subgroup = generator_field.pow(*exp.value()); let mut numbers = Vec::new(); From 0437286c98964167e2a840a6f717ca98c6aacd85 Mon Sep 17 00:00:00 2001 From: MauroFab Date: Wed, 1 Mar 2023 12:59:34 -0300 Subject: [PATCH 70/85] Refactor roots of unity generator --- prover/src/lib.rs | 66 ++++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/prover/src/lib.rs b/prover/src/lib.rs index 2ebb33978..3e44a3f3e 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -49,6 +49,14 @@ const ORDER_OF_ROOTS_OF_UNITY_FOR_LDE: u64 = 16; // DEFINITION OF FUNCTIONS +pub fn generate_primitive_root(subgroup_size: u64) -> FE { + let modulus_minus_1_field: FE = FE::new(MODULUS_MINUS_1); + let subgroup_size: FE = subgroup_size.into(); + let generator_field: FE = FIELD_SUBGROUP_GENERATOR.into(); + let exp = (&modulus_minus_1_field) / &subgroup_size; + generator_field.pow(*exp.value()) +} + /// This functions takes a roots of unity and a coset factor /// If coset_factor is 1, it's just expanding the roots of unity /// w ^ 0, w ^ 1, w ^ 2 .... w ^ n-1 @@ -56,28 +64,21 @@ const ORDER_OF_ROOTS_OF_UNITY_FOR_LDE: u64 = 16; /// h * w ^ 0, h * w ^ 1 .... h * w ^ n-1 // doesn't need to return the primitive root w ^ 1 pub fn generate_roots_of_unity_coset( - root_of_unity_size: u64, coset_factor: u64, -) -> (Vec, FE) { - - let modulus_minus_1_field: FE = FE::new(MODULUS_MINUS_1); - let subgroup_size: FE = root_of_unity_size.into(); - - let generator_field: FE = FIELD_SUBGROUP_GENERATOR.into(); - let coset_factor_u384: FE = coset_factor.into(); - - let exp = (&modulus_minus_1_field) / &subgroup_size; - - let generator_of_subgroup = generator_field.pow(*exp.value()); - - let mut numbers = Vec::new(); - - for exp in 0..root_of_unity_size { - let ret = generator_of_subgroup.pow(exp) * &coset_factor_u384; - numbers.push(ret.clone()); + primitive_root: &FE, +) -> Vec { + + let coset_factor: FE = coset_factor.into(); + + let mut numbers = vec![coset_factor.clone()]; + let mut exp: u64 = 1; + let mut next_root = primitive_root.pow(exp) * &coset_factor; + while next_root != coset_factor { + numbers.push(next_root); + exp += 1; + next_root = primitive_root.pow(exp) * &coset_factor; } - - (numbers, generator_of_subgroup) + numbers } #[derive(Debug, Clone)] @@ -125,17 +126,18 @@ pub fn prove( // * Generate Coset - let (roots_of_unity, primitive_root) = - generate_roots_of_unity_coset(ORDER_OF_ROOTS_OF_UNITY_TRACE, 1); + let trace_primitive_root = generate_primitive_root(ORDER_OF_ROOTS_OF_UNITY_TRACE); + let trace_roots_of_unity = + generate_roots_of_unity_coset(1, &trace_primitive_root); - let (lde_roots_of_unity, lde_primitive_root) = - generate_roots_of_unity_coset(ORDER_OF_ROOTS_OF_UNITY_FOR_LDE, 1); + let lde_primitive_root = generate_primitive_root(ORDER_OF_ROOTS_OF_UNITY_FOR_LDE); + let lde_roots_of_unity = generate_roots_of_unity_coset(1, &lde_primitive_root); let trace = fibonacci_trace(pub_inputs); - let trace_poly = Polynomial::interpolate(&roots_of_unity, &trace); + let trace_poly = Polynomial::interpolate(&trace_roots_of_unity, &trace); - let mut composition_poly = get_composition_poly(trace_poly.clone(), &primitive_root); + let mut composition_poly = get_composition_poly(trace_poly.clone(), &trace_primitive_root); // * Do Reed-Solomon on the trace and composition polynomials using some blowup factor let trace_poly_lde = trace_poly.evaluate_slice(lde_roots_of_unity.as_slice()); @@ -169,8 +171,8 @@ pub fn prove( let evaluation_points = vec![ lde_primitive_root.pow(q_1), - lde_primitive_root.pow(q_1) * &primitive_root, - lde_primitive_root.pow(q_1) * (&primitive_root * &primitive_root), + lde_primitive_root.pow(q_1) * &trace_primitive_root, + lde_primitive_root.pow(q_1) * (&trace_primitive_root * &trace_primitive_root), ]; let trace_lde_poly_evaluations = trace_poly.evaluate_slice(&evaluation_points); @@ -236,8 +238,8 @@ fn get_composition_poly( pub fn verify(proof: StarkQueryProof) -> bool { let trace_poly_root = proof.trace_lde_poly_root; - let (_roots_of_unity, mut primitive_root) = - generate_roots_of_unity_coset(ORDER_OF_ROOTS_OF_UNITY_FOR_LDE, 1); + let mut lde_primitive_root = generate_primitive_root(ORDER_OF_ROOTS_OF_UNITY_FOR_LDE); + let evaluations = proof.trace_lde_poly_evaluations; // TODO: These could be multiple evaluations depending on how many q_i are sampled with Fiat Shamir @@ -292,7 +294,7 @@ pub fn verify(proof: StarkQueryProof) -> bool { .unwrap(); // evaluation point = w ^ i in the Stark literature - let evaluation_point = primitive_root.pow(decommitment_index); + let evaluation_point = lde_primitive_root.pow(decommitment_index); // v is the calculated element for the // co linearity check @@ -305,7 +307,7 @@ pub fn verify(proof: StarkQueryProof) -> bool { beta * (&previous_auth_path.value - &previous_auth_path_symmetric.value) / (two * evaluation_point); - primitive_root = primitive_root.pow(2_usize); + lde_primitive_root = lde_primitive_root.pow(2_usize); if v != fri_layer_auth_path.value { return false; From 635386f708960ab4738f0f5d3ecd1020260eb298 Mon Sep 17 00:00:00 2001 From: MauroFab Date: Wed, 1 Mar 2023 13:05:23 -0300 Subject: [PATCH 71/85] Update comment --- prover/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/prover/src/lib.rs b/prover/src/lib.rs index 3e44a3f3e..16ca4c9cb 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -62,7 +62,6 @@ pub fn generate_primitive_root(subgroup_size: u64) -> FE { /// w ^ 0, w ^ 1, w ^ 2 .... w ^ n-1 /// If coset_factor is h /// h * w ^ 0, h * w ^ 1 .... h * w ^ n-1 -// doesn't need to return the primitive root w ^ 1 pub fn generate_roots_of_unity_coset( coset_factor: u64, primitive_root: &FE, From ee8e868cefd5656bd600b3b4fd2516e72936b339 Mon Sep 17 00:00:00 2001 From: MauroFab Date: Wed, 1 Mar 2023 14:41:16 -0300 Subject: [PATCH 72/85] Extracted FRI --- prover/src/lib.rs | 62 ++++++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/prover/src/lib.rs b/prover/src/lib.rs index 16ca4c9cb..d228f36ad 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -234,39 +234,59 @@ fn get_composition_poly( - trace_poly } -pub fn verify(proof: StarkQueryProof) -> bool { - let trace_poly_root = proof.trace_lde_poly_root; +pub fn verify(proof: &StarkQueryProof) -> bool { - let mut lde_primitive_root = generate_primitive_root(ORDER_OF_ROOTS_OF_UNITY_FOR_LDE); + let transcript = &mut Transcript::new(); - let evaluations = proof.trace_lde_poly_evaluations; + let trace_poly_root = &proof.trace_lde_poly_root; + let evaluations = &proof.trace_lde_poly_evaluations; // TODO: These could be multiple evaluations depending on how many q_i are sampled with Fiat Shamir - let composition_poly_lde_evaluation = proof.composition_poly_lde_evaluations[0].clone(); + let composition_poly_lde_evaluation_from_prover = &proof.composition_poly_lde_evaluations[0]; - if composition_poly_lde_evaluation != &evaluations[2] - &evaluations[1] - &evaluations[0] { + let composition_polynomial_evaluation_calculated = &evaluations[2] - &evaluations[1] - &evaluations[0]; + + if *composition_poly_lde_evaluation_from_prover != composition_polynomial_evaluation_calculated { return false; } - for merkle_proof in proof.trace_lde_poly_inclusion_proofs { + for merkle_proof in &proof.trace_lde_poly_inclusion_proofs { if !merkle_proof.verify(trace_poly_root.clone()) { return false; } } - // FRI VERIFYING BEGINS HERE + fri_verify(&proof.fri_layers_merkle_roots,&proof.fri_decommitment, transcript) +} + +/// Performs FRI verification for some decommitment +pub fn fri_verify(fri_layers_merkle_roots: &[FE], fri_decommitment: &FriDecommitment, _transcript: &mut Transcript) -> bool { + + // For each fri layer merkle proof check: + // That each merkle path verifies + + // Sample beta with fiat shamir + // Compute v = [P_i(z_i) + P_i(-z_i)] / 2 + beta * [P_i(z_i) - P_i(-z_i)] / (2 * z_i) + // Where P_i is the folded polynomial of the i-th fiat shamir round + // z_i is obtained from the first z (that was derived through fiat-shamir) through a known calculation + // The calculation is, given the index, index % length_of_evaluation_domain + + // Check that v = P_{i+1}(z_i) + let decommitment_index: u64 = 4; - // For each (merkle_root, merkle_auth_path) + let mut lde_primitive_root = generate_primitive_root(ORDER_OF_ROOTS_OF_UNITY_FOR_LDE); + + // For each (merkle_root, merkle_auth_path) / fold // With the auth path containining the element that the // path proves it's existance for ( layer_number, (fri_layer_merkle_root, (fri_layer_auth_path, fri_layer_auth_path_symmetric)), - ) in proof - .fri_layers_merkle_roots + ) in + fri_layers_merkle_roots .iter() - .zip(proof.fri_decommitment.layer_merkle_paths.iter()) + .zip(fri_decommitment.layer_merkle_paths.iter()) .enumerate() // Since we always derive the current layer from the previous layer // We start with the second one, skipping the first, so previous is layer is the first one @@ -284,8 +304,7 @@ pub fn verify(proof: StarkQueryProof) -> bool { let beta: u64 = 4; let (previous_auth_path, previous_auth_path_symmetric) = - proof - .fri_decommitment + fri_decommitment .layer_merkle_paths .get(layer_number - 1) // TODO: Check at the start of the FRI operation @@ -312,21 +331,10 @@ pub fn verify(proof: StarkQueryProof) -> bool { return false; } } - - // For each fri layer merkle proof check: - // That each merkle path verifies - - // Sample beta with fiat shamir - // Compute v = [P_i(z_i) + P_i(-z_i)] / 2 + beta * [P_i(z_i) - P_i(-z_i)] / (2 * z_i) - // Where P_i is the folded polynomial of the i-th fiat shamir round - // z_i is obtained from the first z (that was derived through fiat-shamir) through a known calculation - // The calculation is, given the index, index % length_of_evaluation_domain - - // Check that v = P_{i+1}(z_i) - return true; } + // TODOS after basic fibonacci works: // - Add Fiat Shamir // - Add Zerofiers @@ -349,6 +357,6 @@ mod tests { FE::new(U384::from("1")), FE::new(U384::from("1")), ]); - assert!(verify(result)); + assert!(verify(&result)); } } From cd6f341507569271c5e833597c6819345edbfff0 Mon Sep 17 00:00:00 2001 From: MauroFab Date: Wed, 1 Mar 2023 14:52:38 -0300 Subject: [PATCH 73/85] Refactor verify --- prover/src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/prover/src/lib.rs b/prover/src/lib.rs index d228f36ad..95cc01083 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -239,14 +239,14 @@ pub fn verify(proof: &StarkQueryProof) -> bool { let transcript = &mut Transcript::new(); let trace_poly_root = &proof.trace_lde_poly_root; - let evaluations = &proof.trace_lde_poly_evaluations; + let trace_evaluation = &proof.trace_lde_poly_evaluations; // TODO: These could be multiple evaluations depending on how many q_i are sampled with Fiat Shamir - let composition_poly_lde_evaluation_from_prover = &proof.composition_poly_lde_evaluations[0]; + let composition_polynomial_evaluation_from_prover = &proof.composition_poly_lde_evaluations[0]; - let composition_polynomial_evaluation_calculated = &evaluations[2] - &evaluations[1] - &evaluations[0]; + let composition_polynomial_evaluation_from_trace = &trace_evaluation[2] - &trace_evaluation[1] - &trace_evaluation[0]; - if *composition_poly_lde_evaluation_from_prover != composition_polynomial_evaluation_calculated { + if *composition_polynomial_evaluation_from_prover != composition_polynomial_evaluation_from_trace { return false; } From 9fd980c664dc07bf896565ed568a7911842b91ad Mon Sep 17 00:00:00 2001 From: MauroFab Date: Wed, 1 Mar 2023 15:41:25 -0300 Subject: [PATCH 74/85] Refactor clippy --- crypto/src/fiat_shamir/transcript.rs | 2 +- math/src/field/extensions/quadratic.rs | 2 +- prover/src/air/polynomials.rs | 6 +-- prover/src/fri/fri_decommit.rs | 19 ++++----- prover/src/fri/mod.rs | 4 +- prover/src/lib.rs | 59 +++++++++----------------- 6 files changed, 33 insertions(+), 59 deletions(-) diff --git a/crypto/src/fiat_shamir/transcript.rs b/crypto/src/fiat_shamir/transcript.rs index 840a5152e..77cd620e0 100644 --- a/crypto/src/fiat_shamir/transcript.rs +++ b/crypto/src/fiat_shamir/transcript.rs @@ -5,7 +5,7 @@ pub struct Transcript { } impl Transcript { - #[allow(unused)] + #[allow(clippy::new_without_default)] pub fn new() -> Self { Self { hasher: Sha3_256::new(), diff --git a/math/src/field/extensions/quadratic.rs b/math/src/field/extensions/quadratic.rs index edb9b6ce9..571c71e3c 100644 --- a/math/src/field/extensions/quadratic.rs +++ b/math/src/field/extensions/quadratic.rs @@ -106,7 +106,7 @@ where x } - fn representative(x: Self::BaseType) -> Self::BaseType { + fn representative(_x: Self::BaseType) -> Self::BaseType { todo!() } } diff --git a/prover/src/air/polynomials.rs b/prover/src/air/polynomials.rs index 3f251305a..958e59f37 100644 --- a/prover/src/air/polynomials.rs +++ b/prover/src/air/polynomials.rs @@ -1,8 +1,4 @@ use lambdaworks_math::{ - field::{ - element::FieldElement, - fields::u384_prime_field::{IsMontgomeryConfiguration, MontgomeryBackendPrimeField}, - }, polynomial::Polynomial, unsigned_integer::element::U384, }; @@ -92,7 +88,7 @@ where let composition_poly = constraint_evaluations .into_poly() - .map_err(|e| ProverError::CompositionPolyError(e))? + .map_err(ProverError::CompositionPolyError)? .data; let cp_coeffs: Vec = winter_2_lambda_felts(composition_poly); diff --git a/prover/src/fri/fri_decommit.rs b/prover/src/fri/fri_decommit.rs index 3c5f84868..3dbc1a2f5 100644 --- a/prover/src/fri/fri_decommit.rs +++ b/prover/src/fri/fri_decommit.rs @@ -1,12 +1,9 @@ use super::FE; use crate::{fri::fri_commitment::FriCommitmentVec, PrimeField}; pub use lambdaworks_crypto::fiat_shamir::transcript::Transcript; -use lambdaworks_crypto::{hash::traits::IsCryptoHash, merkle_tree::DefaultHasher}; +use lambdaworks_crypto::{merkle_tree::DefaultHasher}; use lambdaworks_crypto::merkle_tree::proof::Proof; -use lambdaworks_math::{ - field::traits::IsField, traits::ByteConversion, unsigned_integer::element::U384, -}; #[derive(Debug, Clone)] pub struct FriDecommitment { @@ -33,7 +30,7 @@ pub fn fri_decommit_layers( // the merkle tree and get the corresponding element for commit_i in commit { let length_i = commit_i.domain.len(); - index = index % length_i; + index %= length_i; let evaluation_i = commit_i.evaluation[index].clone(); let auth_path = commit_i.merkle_tree.get_proof(&evaluation_i).unwrap(); @@ -49,10 +46,10 @@ pub fn fri_decommit_layers( let last = commit.last().unwrap(); let last_evaluation = last.poly.coefficients[0].clone(); - return FriDecommitment { - layer_merkle_paths: layer_merkle_paths, + FriDecommitment { + layer_merkle_paths, last_layer_evaluation: last_evaluation, - }; + } } // Integration test: @@ -72,12 +69,12 @@ mod tests { use std::collections::HashSet; const PRIME_GENERATOR: (u64, u64) = (0xFFFF_FFFF_0000_0001_u64, 2717_u64); pub type F = U64PrimeField<{ PRIME_GENERATOR.0 }>; - pub type FE_goldilocks = FieldElement; + pub type FeGoldilocks = FieldElement; #[test] fn test() { let subgroup_size = 1024_u64; - let generator_field = FE_goldilocks::new(PRIME_GENERATOR.1); + let generator_field = FeGoldilocks::new(PRIME_GENERATOR.1); let exp = (PRIME_GENERATOR.0 - 1) / subgroup_size; let generator_of_subgroup = generator_field.pow(exp); let mut numbers = HashSet::new(); @@ -86,7 +83,7 @@ mod tests { for exp in 0..1024_u64 { i += 1; let ret = generator_of_subgroup.pow(exp); - numbers.insert(ret.value().clone()); + numbers.insert(*ret.value()); println!("{ret:?}"); } diff --git a/prover/src/fri/mod.rs b/prover/src/fri/mod.rs index 658841abe..552074539 100644 --- a/prover/src/fri/mod.rs +++ b/prover/src/fri/mod.rs @@ -3,8 +3,6 @@ pub mod fri_decommit; mod fri_functions; mod fri_merkle_tree; -use std::borrow::Borrow; - use crate::fri::fri_commitment::{FriCommitment, FriCommitmentVec}; use crate::fri::fri_functions::next_fri_layer; pub use crate::fri::fri_merkle_tree::FriMerkleTree; @@ -36,7 +34,7 @@ pub fn fri_commitment( // - root // - hasher // Create a new merkle tree with evaluation_i - let merkle_tree = FriMerkleTree::build(&evaluation_i); + let merkle_tree = FriMerkleTree::build(evaluation_i); // append the root of the merkle tree to the transcript let root = merkle_tree.root.clone(); diff --git a/prover/src/lib.rs b/prover/src/lib.rs index 95cc01083..e2371d0a0 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -1,20 +1,10 @@ pub mod air; pub mod fri; -use std::primitive; - -use air::polynomials::get_cp_and_tp; use fri::fri_decommit::{fri_decommit_layers, FriDecommitment}; use lambdaworks_crypto::fiat_shamir::transcript::Transcript; use lambdaworks_crypto::merkle_tree::proof::Proof; use lambdaworks_math::polynomial::{self, Polynomial}; -use thiserror::__private::AsDynError; -use winterfell::{ - crypto::hashers::Blake3_256, - math::{fields::f128::BaseElement, StarkField}, - prover::constraints::CompositionPoly, - Air, AuxTraceRandElements, Serializable, Trace, TraceTable, -}; use lambdaworks_math::field::element::FieldElement; use lambdaworks_math::{ @@ -142,7 +132,7 @@ pub fn prove( let trace_poly_lde = trace_poly.evaluate_slice(lde_roots_of_unity.as_slice()); // * Commit to both polynomials using a Merkle Tree - let trace_poly_lde_merkle_tree = FriMerkleTree::build(&trace_poly_lde.as_slice()); + let trace_poly_lde_merkle_tree = FriMerkleTree::build(trace_poly_lde.as_slice()); // * Do FRI on the composition polynomials let lde_fri_commitment = @@ -177,32 +167,26 @@ pub fn prove( let trace_lde_poly_evaluations = trace_poly.evaluate_slice(&evaluation_points); let composition_poly_lde_evaluation = composition_poly.evaluate(&evaluation_points[0]); - let mut merkle_paths = vec![]; - - merkle_paths.push( + let merkle_paths = vec![ trace_poly_lde_merkle_tree .get_proof_by_pos(q_1, trace_lde_poly_evaluations[0].clone()) .unwrap(), - ); - merkle_paths.push( trace_poly_lde_merkle_tree - .get_proof_by_pos( - q_1 + (ORDER_OF_ROOTS_OF_UNITY_FOR_LDE / ORDER_OF_ROOTS_OF_UNITY_TRACE) as usize, - trace_lde_poly_evaluations[1].clone(), - ) - .unwrap(), - ); - merkle_paths.push( + .get_proof_by_pos( + q_1 + (ORDER_OF_ROOTS_OF_UNITY_FOR_LDE / ORDER_OF_ROOTS_OF_UNITY_TRACE) as usize, + trace_lde_poly_evaluations[1].clone(), + ) + .unwrap(), trace_poly_lde_merkle_tree - .get_proof_by_pos( - q_1 + (ORDER_OF_ROOTS_OF_UNITY_FOR_LDE / ORDER_OF_ROOTS_OF_UNITY_TRACE) as usize - * 2, - trace_lde_poly_evaluations[2].clone(), - ) - .unwrap(), - ); + .get_proof_by_pos( + q_1 + (ORDER_OF_ROOTS_OF_UNITY_FOR_LDE / ORDER_OF_ROOTS_OF_UNITY_TRACE) as usize + * 2, + trace_lde_poly_evaluations[2].clone(), + ) + .unwrap() + ]; - let trace_root = trace_poly_lde_merkle_tree.root.clone(); + let trace_root = trace_poly_lde_merkle_tree.root; let fri_layers_merkle_roots: Vec = lde_fri_commitment .iter() @@ -214,8 +198,8 @@ pub fn prove( trace_lde_poly_evaluations, trace_lde_poly_inclusion_proofs: merkle_paths, composition_poly_lde_evaluations: vec![composition_poly_lde_evaluation], - fri_layers_merkle_roots: fri_layers_merkle_roots, - fri_decommitment: fri_decommitment, + fri_layers_merkle_roots, + fri_decommitment, } } @@ -223,11 +207,11 @@ fn get_composition_poly( trace_poly: Polynomial, root_of_unity: &FE, ) -> Polynomial { - let w_squared_x = Polynomial::new(&vec![ + let w_squared_x = Polynomial::new(&[ FE::zero(), root_of_unity * root_of_unity, ]); - let w_x = Polynomial::new(&vec![FE::zero(), root_of_unity.clone()]); + let w_x = Polynomial::new(&[FE::zero(), root_of_unity.clone()]); polynomial::compose(&trace_poly, &w_squared_x) - polynomial::compose(&trace_poly, &w_x) @@ -331,7 +315,7 @@ pub fn fri_verify(fri_layers_merkle_roots: &[FE], fri_decommitment: &FriDecommit return false; } } - return true; + true } @@ -348,8 +332,7 @@ mod tests { use crate::{verify, FE}; use super::prove; - use lambdaworks_math::{field::element::FieldElement, unsigned_integer::element::U384}; - use winterfell::{FieldExtension, ProofOptions}; + use lambdaworks_math::{unsigned_integer::element::U384}; #[test] fn test_prove() { From f0d5cd3778606b50dbe78671621affd92fce7c95 Mon Sep 17 00:00:00 2001 From: MauroFab Date: Wed, 1 Mar 2023 15:57:30 -0300 Subject: [PATCH 75/85] Re ordered prover --- prover/src/lib.rs | 53 +++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/prover/src/lib.rs b/prover/src/lib.rs index e2371d0a0..c64295bcc 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -126,47 +126,29 @@ pub fn prove( let trace_poly = Polynomial::interpolate(&trace_roots_of_unity, &trace); - let mut composition_poly = get_composition_poly(trace_poly.clone(), &trace_primitive_root); - // * Do Reed-Solomon on the trace and composition polynomials using some blowup factor let trace_poly_lde = trace_poly.evaluate_slice(lde_roots_of_unity.as_slice()); // * Commit to both polynomials using a Merkle Tree let trace_poly_lde_merkle_tree = FriMerkleTree::build(trace_poly_lde.as_slice()); - // * Do FRI on the composition polynomials - let lde_fri_commitment = - crate::fri::fri(&mut composition_poly, &lde_roots_of_unity, transcript); - // * Sample q_1, ..., q_m using Fiat-Shamir // let q_1 = transcript.challenge(); // @@@@@@@@@@@@@@@@@@@@@@ let q_1: usize = 4; - // * For every q_i, do FRI decommitment - let fri_decommitment = fri_decommit_layers(&lde_fri_commitment, q_1); - /* - IMPORTANT NOTE: - When we commit to the trace polynomial, let's call it f, we commit to an LDE of it. - On the other hand, the fibonacci constraint (and in general, any constraint) related to f applies - only using non-LDE roots of unity. - In this case, the constraint is f(w^2 x) - f(w x) - f(x), where w is a 2^n root of unity. - But for the commitment we use g, a 2^{nb} root of unity (b is the blowup factor). - When we sample a value x to evaluate the trace polynomial on, it has to be a 2^{nb} root of unity, - so with fiat-shamir we sample a random index in that range. - When we provide evaluations, we provide them for x*(w^2), x*w and x. - */ + // START EVALUATION POINTS BLOCK + // This depends on the AIR + // It's related to the non FRI verification + // These are evaluations over the trace polynomial let evaluation_points = vec![ lde_primitive_root.pow(q_1), lde_primitive_root.pow(q_1) * &trace_primitive_root, lde_primitive_root.pow(q_1) * (&trace_primitive_root * &trace_primitive_root), ]; - let trace_lde_poly_evaluations = trace_poly.evaluate_slice(&evaluation_points); - let composition_poly_lde_evaluation = composition_poly.evaluate(&evaluation_points[0]); - let merkle_paths = vec![ trace_poly_lde_merkle_tree .get_proof_by_pos(q_1, trace_lde_poly_evaluations[0].clone()) @@ -186,8 +168,35 @@ pub fn prove( .unwrap() ]; + // These are evaluations over the composition polynomial + let mut composition_poly = get_composition_poly(trace_poly.clone(), &trace_primitive_root); + let composition_poly_lde_evaluation = composition_poly.evaluate(&evaluation_points[0]); + + // This is needed to check the element is in the root let trace_root = trace_poly_lde_merkle_tree.root; + // END EVALUATION BLOCK + + + // * Do FRI on the composition polynomials + let lde_fri_commitment = + crate::fri::fri(&mut composition_poly, &lde_roots_of_unity, transcript); + + // * For every q_i, do FRI decommitment + let fri_decommitment = fri_decommit_layers(&lde_fri_commitment, q_1); + + /* + IMPORTANT NOTE: + When we commit to the trace polynomial, let's call it f, we commit to an LDE of it. + On the other hand, the fibonacci constraint (and in general, any constraint) related to f applies + only using non-LDE roots of unity. + In this case, the constraint is f(w^2 x) - f(w x) - f(x), where w is a 2^n root of unity. + But for the commitment we use g, a 2^{nb} root of unity (b is the blowup factor). + When we sample a value x to evaluate the trace polynomial on, it has to be a 2^{nb} root of unity, + so with fiat-shamir we sample a random index in that range. + When we provide evaluations, we provide them for x*(w^2), x*w and x. + */ + let fri_layers_merkle_roots: Vec = lde_fri_commitment .iter() .map(|fri_commitment| fri_commitment.merkle_tree.root.clone()) From e6351952c6f7baaf40df836a2b60a6c3b4f02cf0 Mon Sep 17 00:00:00 2001 From: MauroFab Date: Wed, 1 Mar 2023 15:58:16 -0300 Subject: [PATCH 76/85] cargo fmt --- prover/src/air/polynomials.rs | 5 +- prover/src/fri/fri_decommit.rs | 2 +- prover/src/lib.rs | 114 ++++++++++++++------------------- 3 files changed, 51 insertions(+), 70 deletions(-) diff --git a/prover/src/air/polynomials.rs b/prover/src/air/polynomials.rs index 958e59f37..a4f6b56fc 100644 --- a/prover/src/air/polynomials.rs +++ b/prover/src/air/polynomials.rs @@ -1,7 +1,4 @@ -use lambdaworks_math::{ - polynomial::Polynomial, - unsigned_integer::element::U384, -}; +use lambdaworks_math::{polynomial::Polynomial, unsigned_integer::element::U384}; use winterfell::{ crypto::hashers::Blake3_256, math::{fields::f128::BaseElement, StarkField}, diff --git a/prover/src/fri/fri_decommit.rs b/prover/src/fri/fri_decommit.rs index 3dbc1a2f5..9837d0e06 100644 --- a/prover/src/fri/fri_decommit.rs +++ b/prover/src/fri/fri_decommit.rs @@ -1,7 +1,7 @@ use super::FE; use crate::{fri::fri_commitment::FriCommitmentVec, PrimeField}; pub use lambdaworks_crypto::fiat_shamir::transcript::Transcript; -use lambdaworks_crypto::{merkle_tree::DefaultHasher}; +use lambdaworks_crypto::merkle_tree::DefaultHasher; use lambdaworks_crypto::merkle_tree::proof::Proof; diff --git a/prover/src/lib.rs b/prover/src/lib.rs index c64295bcc..82d14d9d6 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -24,12 +24,9 @@ impl IsMontgomeryConfiguration for MontgomeryConfig { pub type PrimeField = MontgomeryBackendPrimeField; pub type FE = FieldElement; -const MODULUS_MINUS_1: U384 = U384::sub( - &MontgomeryConfig::MODULUS, - &U384::from("1"), -).0; +const MODULUS_MINUS_1: U384 = U384::sub(&MontgomeryConfig::MODULUS, &U384::from("1")).0; -/// Subgroup generator to generate the roots of unity +/// Subgroup generator to generate the roots of unity const FIELD_SUBGROUP_GENERATOR: u64 = 3; // DEFINITION OF CONSTANTS @@ -48,15 +45,11 @@ pub fn generate_primitive_root(subgroup_size: u64) -> FE { } /// This functions takes a roots of unity and a coset factor -/// If coset_factor is 1, it's just expanding the roots of unity +/// If coset_factor is 1, it's just expanding the roots of unity /// w ^ 0, w ^ 1, w ^ 2 .... w ^ n-1 /// If coset_factor is h /// h * w ^ 0, h * w ^ 1 .... h * w ^ n-1 -pub fn generate_roots_of_unity_coset( - coset_factor: u64, - primitive_root: &FE, -) -> Vec { - +pub fn generate_roots_of_unity_coset(coset_factor: u64, primitive_root: &FE) -> Vec { let coset_factor: FE = coset_factor.into(); let mut numbers = vec![coset_factor.clone()]; @@ -116,8 +109,7 @@ pub fn prove( // * Generate Coset let trace_primitive_root = generate_primitive_root(ORDER_OF_ROOTS_OF_UNITY_TRACE); - let trace_roots_of_unity = - generate_roots_of_unity_coset(1, &trace_primitive_root); + let trace_roots_of_unity = generate_roots_of_unity_coset(1, &trace_primitive_root); let lde_primitive_root = generate_primitive_root(ORDER_OF_ROOTS_OF_UNITY_FOR_LDE); let lde_roots_of_unity = generate_roots_of_unity_coset(1, &lde_primitive_root); @@ -137,9 +129,8 @@ pub fn prove( // @@@@@@@@@@@@@@@@@@@@@@ let q_1: usize = 4; - // START EVALUATION POINTS BLOCK - // This depends on the AIR + // This depends on the AIR // It's related to the non FRI verification // These are evaluations over the trace polynomial @@ -154,18 +145,18 @@ pub fn prove( .get_proof_by_pos(q_1, trace_lde_poly_evaluations[0].clone()) .unwrap(), trace_poly_lde_merkle_tree - .get_proof_by_pos( - q_1 + (ORDER_OF_ROOTS_OF_UNITY_FOR_LDE / ORDER_OF_ROOTS_OF_UNITY_TRACE) as usize, - trace_lde_poly_evaluations[1].clone(), - ) - .unwrap(), + .get_proof_by_pos( + q_1 + (ORDER_OF_ROOTS_OF_UNITY_FOR_LDE / ORDER_OF_ROOTS_OF_UNITY_TRACE) as usize, + trace_lde_poly_evaluations[1].clone(), + ) + .unwrap(), trace_poly_lde_merkle_tree - .get_proof_by_pos( - q_1 + (ORDER_OF_ROOTS_OF_UNITY_FOR_LDE / ORDER_OF_ROOTS_OF_UNITY_TRACE) as usize - * 2, - trace_lde_poly_evaluations[2].clone(), - ) - .unwrap() + .get_proof_by_pos( + q_1 + (ORDER_OF_ROOTS_OF_UNITY_FOR_LDE / ORDER_OF_ROOTS_OF_UNITY_TRACE) as usize + * 2, + trace_lde_poly_evaluations[2].clone(), + ) + .unwrap(), ]; // These are evaluations over the composition polynomial @@ -177,7 +168,6 @@ pub fn prove( // END EVALUATION BLOCK - // * Do FRI on the composition polynomials let lde_fri_commitment = crate::fri::fri(&mut composition_poly, &lde_roots_of_unity, transcript); @@ -212,14 +202,8 @@ pub fn prove( } } -fn get_composition_poly( - trace_poly: Polynomial, - root_of_unity: &FE, -) -> Polynomial { - let w_squared_x = Polynomial::new(&[ - FE::zero(), - root_of_unity * root_of_unity, - ]); +fn get_composition_poly(trace_poly: Polynomial, root_of_unity: &FE) -> Polynomial { + let w_squared_x = Polynomial::new(&[FE::zero(), root_of_unity * root_of_unity]); let w_x = Polynomial::new(&[FE::zero(), root_of_unity.clone()]); polynomial::compose(&trace_poly, &w_squared_x) @@ -228,7 +212,6 @@ fn get_composition_poly( } pub fn verify(proof: &StarkQueryProof) -> bool { - let transcript = &mut Transcript::new(); let trace_poly_root = &proof.trace_lde_poly_root; @@ -237,9 +220,12 @@ pub fn verify(proof: &StarkQueryProof) -> bool { // TODO: These could be multiple evaluations depending on how many q_i are sampled with Fiat Shamir let composition_polynomial_evaluation_from_prover = &proof.composition_poly_lde_evaluations[0]; - let composition_polynomial_evaluation_from_trace = &trace_evaluation[2] - &trace_evaluation[1] - &trace_evaluation[0]; + let composition_polynomial_evaluation_from_trace = + &trace_evaluation[2] - &trace_evaluation[1] - &trace_evaluation[0]; - if *composition_polynomial_evaluation_from_prover != composition_polynomial_evaluation_from_trace { + if *composition_polynomial_evaluation_from_prover + != composition_polynomial_evaluation_from_trace + { return false; } @@ -249,12 +235,19 @@ pub fn verify(proof: &StarkQueryProof) -> bool { } } - fri_verify(&proof.fri_layers_merkle_roots,&proof.fri_decommitment, transcript) + fri_verify( + &proof.fri_layers_merkle_roots, + &proof.fri_decommitment, + transcript, + ) } /// Performs FRI verification for some decommitment -pub fn fri_verify(fri_layers_merkle_roots: &[FE], fri_decommitment: &FriDecommitment, _transcript: &mut Transcript) -> bool { - +pub fn fri_verify( + fri_layers_merkle_roots: &[FE], + fri_decommitment: &FriDecommitment, + _transcript: &mut Transcript, +) -> bool { // For each fri layer merkle proof check: // That each merkle path verifies @@ -270,14 +263,13 @@ pub fn fri_verify(fri_layers_merkle_roots: &[FE], fri_decommitment: &FriDecommit let mut lde_primitive_root = generate_primitive_root(ORDER_OF_ROOTS_OF_UNITY_FOR_LDE); - // For each (merkle_root, merkle_auth_path) / fold + // For each (merkle_root, merkle_auth_path) / fold // With the auth path containining the element that the // path proves it's existance for ( layer_number, (fri_layer_merkle_root, (fri_layer_auth_path, fri_layer_auth_path_symmetric)), - ) in - fri_layers_merkle_roots + ) in fri_layers_merkle_roots .iter() .zip(fri_decommitment.layer_merkle_paths.iter()) .enumerate() @@ -296,26 +288,22 @@ pub fn fri_verify(fri_layers_merkle_roots: &[FE], fri_decommitment: &FriDecommit // TODO: use Fiat Shamir let beta: u64 = 4; - let (previous_auth_path, previous_auth_path_symmetric) = - fri_decommitment - .layer_merkle_paths - .get(layer_number - 1) - // TODO: Check at the start of the FRI operation - // if layer_merkle_paths has the right amount of elements - .unwrap(); + let (previous_auth_path, previous_auth_path_symmetric) = fri_decommitment + .layer_merkle_paths + .get(layer_number - 1) + // TODO: Check at the start of the FRI operation + // if layer_merkle_paths has the right amount of elements + .unwrap(); - // evaluation point = w ^ i in the Stark literature + // evaluation point = w ^ i in the Stark literature let evaluation_point = lde_primitive_root.pow(decommitment_index); - - // v is the calculated element for the + + // v is the calculated element for the // co linearity check let two = &FE::new(U384::from("2")); let beta = FE::new(U384::from_u64(beta)); - let v = - (&previous_auth_path.value + &previous_auth_path_symmetric.value) - / two - + - beta * (&previous_auth_path.value - &previous_auth_path_symmetric.value) + let v = (&previous_auth_path.value + &previous_auth_path_symmetric.value) / two + + beta * (&previous_auth_path.value - &previous_auth_path_symmetric.value) / (two * evaluation_point); lde_primitive_root = lde_primitive_root.pow(2_usize); @@ -327,7 +315,6 @@ pub fn fri_verify(fri_layers_merkle_roots: &[FE], fri_decommitment: &FriDecommit true } - // TODOS after basic fibonacci works: // - Add Fiat Shamir // - Add Zerofiers @@ -341,14 +328,11 @@ mod tests { use crate::{verify, FE}; use super::prove; - use lambdaworks_math::{unsigned_integer::element::U384}; + use lambdaworks_math::unsigned_integer::element::U384; #[test] fn test_prove() { - let result = prove([ - FE::new(U384::from("1")), - FE::new(U384::from("1")), - ]); + let result = prove([FE::new(U384::from("1")), FE::new(U384::from("1"))]); assert!(verify(&result)); } } From a1b4d258da93fb4c5738f4079f5f9ed15bd245fb Mon Sep 17 00:00:00 2001 From: MauroFab Date: Wed, 1 Mar 2023 16:17:01 -0300 Subject: [PATCH 77/85] fix roots of unity --- prover/src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/prover/src/lib.rs b/prover/src/lib.rs index 82d14d9d6..c8557fb66 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -18,7 +18,7 @@ pub struct MontgomeryConfig; impl IsMontgomeryConfiguration for MontgomeryConfig { const MODULUS: U384 = // hex 17 - U384::from("11"); + U384::from("800000000000011000000000000000000000000000000000000000000000001"); } pub type PrimeField = MontgomeryBackendPrimeField; @@ -31,8 +31,8 @@ const FIELD_SUBGROUP_GENERATOR: u64 = 3; // DEFINITION OF CONSTANTS -const ORDER_OF_ROOTS_OF_UNITY_TRACE: u64 = 4; -const ORDER_OF_ROOTS_OF_UNITY_FOR_LDE: u64 = 16; +const ORDER_OF_ROOTS_OF_UNITY_TRACE: u64 = 32; +const ORDER_OF_ROOTS_OF_UNITY_FOR_LDE: u64 = 1024; // DEFINITION OF FUNCTIONS @@ -41,7 +41,7 @@ pub fn generate_primitive_root(subgroup_size: u64) -> FE { let subgroup_size: FE = subgroup_size.into(); let generator_field: FE = FIELD_SUBGROUP_GENERATOR.into(); let exp = (&modulus_minus_1_field) / &subgroup_size; - generator_field.pow(*exp.value()) + generator_field.pow(exp.representative()) } /// This functions takes a roots of unity and a coset factor From d874f5e66ad9843c5166ce8f022c3c58a2921bdb Mon Sep 17 00:00:00 2001 From: MauroFab Date: Wed, 1 Mar 2023 16:27:49 -0300 Subject: [PATCH 78/85] Remove air --- prover/Cargo.toml | 1 - prover/src/air/errors.rs | 7 - prover/src/air/mod.rs | 2 - prover/src/air/polynomials.rs | 352 ---------------------------------- prover/src/lib.rs | 9 - 5 files changed, 371 deletions(-) delete mode 100644 prover/src/air/errors.rs delete mode 100644 prover/src/air/mod.rs delete mode 100644 prover/src/air/polynomials.rs diff --git a/prover/Cargo.toml b/prover/Cargo.toml index 0fb74e2e8..b61ebe8de 100644 --- a/prover/Cargo.toml +++ b/prover/Cargo.toml @@ -9,5 +9,4 @@ edition = "2021" rand = "0.8.5" lambdaworks-math = { path = "../math" } lambdaworks-crypto = { path = "../crypto"} -winterfell = { git = "/~https://github.com/lambdaclass/winterfell", branch = "make-apis-public" } thiserror = "1.0.38" diff --git a/prover/src/air/errors.rs b/prover/src/air/errors.rs deleted file mode 100644 index 9a1aac754..000000000 --- a/prover/src/air/errors.rs +++ /dev/null @@ -1,7 +0,0 @@ -use thiserror::Error; - -#[derive(Debug, Error)] -pub enum ProverError { - #[error("Could not compute composition polynomial")] - CompositionPolyError(winterfell::prover::ProverError), -} diff --git a/prover/src/air/mod.rs b/prover/src/air/mod.rs deleted file mode 100644 index 46fafc842..000000000 --- a/prover/src/air/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod errors; -pub mod polynomials; diff --git a/prover/src/air/polynomials.rs b/prover/src/air/polynomials.rs deleted file mode 100644 index a4f6b56fc..000000000 --- a/prover/src/air/polynomials.rs +++ /dev/null @@ -1,352 +0,0 @@ -use lambdaworks_math::{polynomial::Polynomial, unsigned_integer::element::U384}; -use winterfell::{ - crypto::hashers::Blake3_256, - math::{fields::f128::BaseElement, StarkField}, - Air, AuxTraceRandElements, Matrix, Serializable, Trace, TraceTable, -}; - -use crate::FE; - -use super::errors::ProverError; -use winterfell::prover::{ - build_trace_commitment_f, channel::ProverChannel, constraints::ConstraintEvaluator, - domain::StarkDomain, trace::commitment::TraceCommitment, -}; - -/// Given a CompositionPoly from winterfell, extract its coefficients -/// as a vector. -#[allow(dead_code)] -pub(crate) fn get_coefficients(matrix_poly: Matrix) -> Vec { - let data = matrix_poly.into_columns(); - - let num_columns = data.len(); - let column_len = data[0].len(); - - let mut coeffs = Vec::with_capacity(num_columns * column_len); - - for i in 0..column_len { - for coeff_col in data.iter().take(num_columns) { - coeffs.push(coeff_col[i]); - } - } - - coeffs -} - -#[allow(dead_code)] -pub(crate) fn winter_2_lambda_felts(coeffs: Matrix) -> Vec { - get_coefficients(coeffs) - .into_iter() - .map(|c| FE::from(&U384::from(&c.to_string()))) - .collect() -} - -/// Given a trace and an AIR defined with winterfell data structures, outputs -/// a tuple of lambdaworks Polynomial data structure: -/// (composition_polynomial, trace_polynomial) -#[allow(dead_code)] -pub fn get_cp_and_tp( - air: A, - trace: TraceTable, - pub_inputs: A::PublicInputs, -) -> Result<(Polynomial, Polynomial), ProverError> -where - A: Air, -{ - let mut pub_inputs_bytes = Vec::new(); - pub_inputs.write_into(&mut pub_inputs_bytes); - let mut channel = - ProverChannel::>::new(&air, pub_inputs_bytes); - let domain = StarkDomain::new(&air); - - // extend the main execution trace and build a Merkle tree from the extended trace - let (main_trace_lde, main_trace_tree, main_trace_polys) = build_trace_commitment_f::< - A::BaseField, - A::BaseField, - Blake3_256, - >(trace.main_segment(), &domain); - - let tp_coeffs = winter_2_lambda_felts(main_trace_polys); - - // commit to the LDE of the main trace by writing the root of its Merkle tree into - // the channel - channel.commit_trace(*main_trace_tree.root()); - - let trace_commitment = TraceCommitment::new( - main_trace_lde, - main_trace_tree, - domain.trace_to_lde_blowup(), - ); - - let aux_trace_rand_elements = AuxTraceRandElements::new(); - let constraint_coeffs = channel.get_constraint_composition_coeffs(); - let evaluator = ConstraintEvaluator::new(&air, aux_trace_rand_elements, constraint_coeffs); - let constraint_evaluations = evaluator.evaluate(trace_commitment.trace_table(), &domain); - - let composition_poly = constraint_evaluations - .into_poly() - .map_err(ProverError::CompositionPolyError)? - .data; - - let cp_coeffs: Vec = winter_2_lambda_felts(composition_poly); - - Ok((Polynomial::new(&cp_coeffs), Polynomial::new(&tp_coeffs))) -} - -// #[cfg(test)] -// mod tests { -// use super::*; -// use simple_computation_test_utils::*; -// use winterfell::{prover::constraints::CompositionPoly, FieldExtension, ProofOptions}; - -// #[test] -// fn test_get_coefficients() { -// let coeffs = (0u128..16).map(BaseElement::new).collect::>(); -// let poly = CompositionPoly::new(coeffs.clone(), 2); -// let coeffs_res = get_coefficients(poly.data); - -// assert_eq!(coeffs, coeffs_res); -// } - -// ////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// // This test is made for the following computation, taken from the winterfell README example: -// // "This computation starts with an element in a finite field and then, for the specified number -// // of steps, cubes the element and adds value 42 to it" -// // -// // The test setup consists of the following: -// // * Creating a trace of the computation -// // * Implementing an AIR of the computation -// // -// // TODO: Check that the obtained polynomial is correct. -// ////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// #[test] -// fn test_cp_and_tp_simple_computation() { -// let start = BaseElement::new(3); -// let n = 8; - -// // Build the execution trace and . -// let trace = build_do_work_trace(start, n); -// let pub_inputs = PublicInputs { -// start: trace.get(0, 0), -// result: trace.get(0, trace.length() - 1), -// }; - -// // Define proof options; these will be enough for ~96-bit security level. -// let options = ProofOptions::new( -// 32, // number of queries -// 8, // blowup factor -// 0, // grinding factor -// FieldExtension::None, -// 8, // FRI folding factor -// 128, // FRI max remainder length -// ); - -// let air = WorkAir::new(trace.get_info(), pub_inputs.clone(), options); - -// // TODO: this coefficients should be checked correctly to know -// // the test is really passing -// let expected_cp_coeffs: Vec = vec![ -// 73805846515134368521942875729025268850u128, -// 251094867283236114961184226859763993364, -// 24104107408363517664638843184319555199, -// 235849850267413452314892506985835977650, -// 90060524782298155599732670785320526321, -// 191672218871615916423281291477102427646, -// 266219015768353823155348590781060058741, -// 323575369761999186385729504758291491620, -// 11584578295884344582449562404474773268, -// 210204873954083390997653826263858894919, -// 255852687493109162976897695176505210663, -// 263909750263371532307415443077776653137, -// 270439831904630486671154877882097540335, -// 295423943150257863151191255913349696708, -// 305657170959297052488312417688653377091, -// 170130930667860970428731413388750994520, -// ] -// .into_iter() -// .map(BaseElement::new) -// .map(|c| FE::from(&U384::from(&c.to_string()))) -// .collect(); - -// // TODO: this coefficients should be checked correctly to know -// // the test is really passing -// let expected_tp_coeffs: Vec = vec![ -// 191794735525862843530824769197527107708, -// 223814277178031177559040503778682093811, -// 330061736062598381779522724430379788786, -// 311785526618037647669831294599779434990, -// 318268825200495925654723848557842782850, -// 60163512837320141687261149502403704415, -// 299361964383055940508518867517619087030, -// 306443623720228722390524190138235769635, -// ] -// .into_iter() -// .map(BaseElement::new) -// .map(|c| FE::from(&U384::from(&c.to_string()))) -// .collect(); - -// let expected_cp = Polynomial::new(&expected_cp_coeffs); -// let expected_tp = Polynomial::new(&expected_tp_coeffs); - -// let (result_cp, result_tp) = get_cp_and_tp(air, trace, pub_inputs).unwrap(); - -// // assert polynomials are ok -// assert_eq!(result_cp, expected_cp); -// assert_eq!(result_tp, expected_tp); -// } - -// #[test] -// fn test_prove() { -// let start = BaseElement::new(3); -// let n = 8; - -// // Build the execution trace and . -// let trace = build_do_work_trace(start, n); -// let pub_inputs = PublicInputs { -// start: trace.get(0, 0), -// result: trace.get(0, trace.length() - 1), -// }; - -// // Define proof options; these will be enough for ~96-bit security level. -// let options = ProofOptions::new( -// 32, // number of queries -// 8, // blowup factor -// 0, // grinding factor -// FieldExtension::None, -// 8, // FRI folding factor -// 128, // FRI max remainder length -// ); - -// let air = WorkAir::new(trace.get_info(), pub_inputs.clone(), options); - -// let ret_prove = crate::prove(air, trace, pub_inputs); - -// println!("{ret_prove:?}"); -// } -// } - -// #[cfg(test)] -// pub(crate) mod simple_computation_test_utils { -// use winterfell::{ -// math::FieldElement, AirContext, Assertion, ByteWriter, EvaluationFrame, ProofOptions, -// TraceInfo, TransitionConstraintDegree, -// }; - -// use super::*; - -// pub(crate) fn build_do_work_trace(start: BaseElement, n: usize) -> TraceTable { -// // Instantiate the trace with a given width and length; this will allocate all -// // required memory for the trace -// let trace_width = 1; -// let mut trace = TraceTable::new(trace_width, n); - -// // Fill the trace with data; the first closure initializes the first state of the -// // computation; the second closure computes the next state of the computation based -// // on its current state. -// trace.fill( -// |state| { -// state[0] = start; -// }, -// |_, state| { -// state[0] = state[0].exp(3u32.into()) + BaseElement::new(42); -// }, -// ); - -// trace -// } - -// // Public inputs for our computation will consist of the starting value and the end result. -// #[derive(Clone)] -// pub(crate) struct PublicInputs { -// pub start: BaseElement, -// pub result: BaseElement, -// } - -// // We need to describe how public inputs can be converted to bytes. -// impl Serializable for PublicInputs { -// fn write_into(&self, target: &mut W) { -// target.write(self.start); -// target.write(self.result); -// } -// } - -// // For a specific instance of our computation, we'll keep track of the public inputs and -// // the computation's context which we'll build in the constructor. The context is used -// // internally by the Winterfell prover/verifier when interpreting this AIR. -// pub(crate) struct WorkAir { -// context: AirContext, -// start: BaseElement, -// result: BaseElement, -// } - -// impl Air for WorkAir { -// // First, we'll specify which finite field to use for our computation, and also how -// // the public inputs must look like. -// type BaseField = BaseElement; -// type PublicInputs = PublicInputs; - -// // Here, we'll construct a new instance of our computation which is defined by 3 parameters: -// // starting value, number of steps, and the end result. Another way to think about it is -// // that an instance of our computation is a specific invocation of the do_work() function. -// fn new(trace_info: TraceInfo, pub_inputs: PublicInputs, options: ProofOptions) -> Self { -// // our execution trace should have only one column. -// assert_eq!(1, trace_info.width()); - -// // Our computation requires a single transition constraint. The constraint itself -// // is defined in the evaluate_transition() method below, but here we need to specify -// // the expected degree of the constraint. If the expected and actual degrees of the -// // constraints don't match, an error will be thrown in the debug mode, but in release -// // mode, an invalid proof will be generated which will not be accepted by any verifier. -// let degrees = vec![TransitionConstraintDegree::new(3)]; - -// // We also need to specify the exact number of assertions we will place against the -// // execution trace. This number must be the same as the number of items in a vector -// // returned from the get_assertions() method below. -// let num_assertions = 2; - -// WorkAir { -// context: AirContext::new(trace_info, degrees, num_assertions, options), -// start: pub_inputs.start, -// result: pub_inputs.result, -// } -// } - -// // In this method we'll define our transition constraints; a computation is considered to -// // be valid, if for all valid state transitions, transition constraints evaluate to all -// // zeros, and for any invalid transition, at least one constraint evaluates to a non-zero -// // value. The `frame` parameter will contain current and next states of the computation. -// fn evaluate_transition>( -// &self, -// frame: &EvaluationFrame, -// _periodic_values: &[E], -// result: &mut [E], -// ) { -// // First, we'll read the current state, and use it to compute the expected next state -// let current_state = &frame.current()[0]; -// let next_state = current_state.exp(3u32.into()) + E::from(42u32); - -// // Then, we'll subtract the expected next state from the actual next state; this will -// // evaluate to zero if and only if the expected and actual states are the same. -// result[0] = frame.next()[0] - next_state; -// } - -// // Here, we'll define a set of assertions about the execution trace which must be satisfied -// // for the computation to be valid. Essentially, this ties computation's execution trace -// // to the public inputs. -// fn get_assertions(&self) -> Vec> { -// // for our computation to be valid, value in column 0 at step 0 must be equal to the -// // starting value, and at the last step it must be equal to the result. -// let last_step = self.trace_length() - 1; -// vec![ -// Assertion::single(0, 0, self.start), -// Assertion::single(0, last_step, self.result), -// ] -// } - -// // This is just boilerplate which is used by the Winterfell prover/verifier to retrieve -// // the context of the computation. -// fn context(&self) -> &AirContext { -// &self.context -// } -// } -// } diff --git a/prover/src/lib.rs b/prover/src/lib.rs index c8557fb66..20a3d97a2 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -1,4 +1,3 @@ -pub mod air; pub mod fri; use fri::fri_decommit::{fri_decommit_layers, FriDecommitment}; @@ -94,20 +93,12 @@ pub fn fibonacci_trace(initial_values: [FE; 2]) -> Vec { } pub fn prove( - // air: A, - // trace: TraceTable, - // pub_inputs: A::PublicInputs, pub_inputs: [FE; 2], ) -> StarkQueryProof -// where -// A: Air, { let transcript = &mut Transcript::new(); - // * Generate composition polynomials using Winterfell - // let (mut composition_poly, mut trace_poly) = get_cp_and_tp(air, trace, pub_inputs).unwrap(); // * Generate Coset - let trace_primitive_root = generate_primitive_root(ORDER_OF_ROOTS_OF_UNITY_TRACE); let trace_roots_of_unity = generate_roots_of_unity_coset(1, &trace_primitive_root); From 7e26c7e1f7ea1c97ca98859fe5c3f92925d96482 Mon Sep 17 00:00:00 2001 From: MauroFab Date: Wed, 1 Mar 2023 16:33:31 -0300 Subject: [PATCH 79/85] Prover -> Stark --- Cargo.toml | 2 +- {prover => stark}/Cargo.toml | 2 +- {prover => stark}/src/fri/fri_commitment.rs | 0 {prover => stark}/src/fri/fri_decommit.rs | 0 {prover => stark}/src/fri/fri_functions.rs | 0 {prover => stark}/src/fri/fri_merkle_tree.rs | 0 {prover => stark}/src/fri/mod.rs | 0 {prover => stark}/src/lib.rs | 0 8 files changed, 2 insertions(+), 2 deletions(-) rename {prover => stark}/Cargo.toml (90%) rename {prover => stark}/src/fri/fri_commitment.rs (100%) rename {prover => stark}/src/fri/fri_decommit.rs (100%) rename {prover => stark}/src/fri/fri_functions.rs (100%) rename {prover => stark}/src/fri/fri_merkle_tree.rs (100%) rename {prover => stark}/src/fri/mod.rs (100%) rename {prover => stark}/src/lib.rs (100%) diff --git a/Cargo.toml b/Cargo.toml index 8496805f6..af0681de0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,5 +3,5 @@ members = [ "math", "crypto", - "prover", + "stark", ] diff --git a/prover/Cargo.toml b/stark/Cargo.toml similarity index 90% rename from prover/Cargo.toml rename to stark/Cargo.toml index b61ebe8de..6fec23443 100644 --- a/prover/Cargo.toml +++ b/stark/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "lambdaworks-prover" +name = "lambdaworks-stark" version = "0.1.0" edition = "2021" diff --git a/prover/src/fri/fri_commitment.rs b/stark/src/fri/fri_commitment.rs similarity index 100% rename from prover/src/fri/fri_commitment.rs rename to stark/src/fri/fri_commitment.rs diff --git a/prover/src/fri/fri_decommit.rs b/stark/src/fri/fri_decommit.rs similarity index 100% rename from prover/src/fri/fri_decommit.rs rename to stark/src/fri/fri_decommit.rs diff --git a/prover/src/fri/fri_functions.rs b/stark/src/fri/fri_functions.rs similarity index 100% rename from prover/src/fri/fri_functions.rs rename to stark/src/fri/fri_functions.rs diff --git a/prover/src/fri/fri_merkle_tree.rs b/stark/src/fri/fri_merkle_tree.rs similarity index 100% rename from prover/src/fri/fri_merkle_tree.rs rename to stark/src/fri/fri_merkle_tree.rs diff --git a/prover/src/fri/mod.rs b/stark/src/fri/mod.rs similarity index 100% rename from prover/src/fri/mod.rs rename to stark/src/fri/mod.rs diff --git a/prover/src/lib.rs b/stark/src/lib.rs similarity index 100% rename from prover/src/lib.rs rename to stark/src/lib.rs From d2ad4a4e1fe29750104d63c3ece428576ffe96d7 Mon Sep 17 00:00:00 2001 From: MauroFab Date: Wed, 1 Mar 2023 16:41:01 -0300 Subject: [PATCH 80/85] Move folders --- Cargo.toml | 2 +- {stark => proving-system/stark}/Cargo.toml | 4 ++-- {stark => proving-system/stark}/src/fri/fri_commitment.rs | 0 {stark => proving-system/stark}/src/fri/fri_decommit.rs | 0 {stark => proving-system/stark}/src/fri/fri_functions.rs | 0 {stark => proving-system/stark}/src/fri/fri_merkle_tree.rs | 0 {stark => proving-system/stark}/src/fri/mod.rs | 0 {stark => proving-system/stark}/src/lib.rs | 0 8 files changed, 3 insertions(+), 3 deletions(-) rename {stark => proving-system/stark}/Cargo.toml (71%) rename {stark => proving-system/stark}/src/fri/fri_commitment.rs (100%) rename {stark => proving-system/stark}/src/fri/fri_decommit.rs (100%) rename {stark => proving-system/stark}/src/fri/fri_functions.rs (100%) rename {stark => proving-system/stark}/src/fri/fri_merkle_tree.rs (100%) rename {stark => proving-system/stark}/src/fri/mod.rs (100%) rename {stark => proving-system/stark}/src/lib.rs (100%) diff --git a/Cargo.toml b/Cargo.toml index af0681de0..2946f434e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,5 +3,5 @@ members = [ "math", "crypto", - "stark", + "proving-system/stark", ] diff --git a/stark/Cargo.toml b/proving-system/stark/Cargo.toml similarity index 71% rename from stark/Cargo.toml rename to proving-system/stark/Cargo.toml index 6fec23443..82eb31c61 100644 --- a/stark/Cargo.toml +++ b/proving-system/stark/Cargo.toml @@ -7,6 +7,6 @@ edition = "2021" [dependencies] rand = "0.8.5" -lambdaworks-math = { path = "../math" } -lambdaworks-crypto = { path = "../crypto"} +lambdaworks-math = { path = "../../math" } +lambdaworks-crypto = { path = "../../crypto"} thiserror = "1.0.38" diff --git a/stark/src/fri/fri_commitment.rs b/proving-system/stark/src/fri/fri_commitment.rs similarity index 100% rename from stark/src/fri/fri_commitment.rs rename to proving-system/stark/src/fri/fri_commitment.rs diff --git a/stark/src/fri/fri_decommit.rs b/proving-system/stark/src/fri/fri_decommit.rs similarity index 100% rename from stark/src/fri/fri_decommit.rs rename to proving-system/stark/src/fri/fri_decommit.rs diff --git a/stark/src/fri/fri_functions.rs b/proving-system/stark/src/fri/fri_functions.rs similarity index 100% rename from stark/src/fri/fri_functions.rs rename to proving-system/stark/src/fri/fri_functions.rs diff --git a/stark/src/fri/fri_merkle_tree.rs b/proving-system/stark/src/fri/fri_merkle_tree.rs similarity index 100% rename from stark/src/fri/fri_merkle_tree.rs rename to proving-system/stark/src/fri/fri_merkle_tree.rs diff --git a/stark/src/fri/mod.rs b/proving-system/stark/src/fri/mod.rs similarity index 100% rename from stark/src/fri/mod.rs rename to proving-system/stark/src/fri/mod.rs diff --git a/stark/src/lib.rs b/proving-system/stark/src/lib.rs similarity index 100% rename from stark/src/lib.rs rename to proving-system/stark/src/lib.rs From c589654cecb8e8ad22b0f8c60c5e589e8838fae9 Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Wed, 1 Mar 2023 17:00:46 -0300 Subject: [PATCH 81/85] Uncomment tests, remove unused code --- math/src/field/fields/u384_prime_field.rs | 22 ---------- proving-system/stark/src/fri/fri_functions.rs | 44 ++++++++++++++----- proving-system/stark/src/lib.rs | 5 +-- 3 files changed, 34 insertions(+), 37 deletions(-) diff --git a/math/src/field/fields/u384_prime_field.rs b/math/src/field/fields/u384_prime_field.rs index 98c8dc983..a062b39c0 100644 --- a/math/src/field/fields/u384_prime_field.rs +++ b/math/src/field/fields/u384_prime_field.rs @@ -183,28 +183,6 @@ where } } -// impl ByteConversion for FieldElement { -// fn to_bytes_be(&self) -> Vec { -// todo!() -// } - -// fn to_bytes_le(&self) -> Vec { -// todo!() -// } - -// fn from_bytes_be(bytes: &[u8]) -> Result -// where -// Self: std::marker::Sized { -// todo!() -// } - -// fn from_bytes_le(bytes: &[u8]) -> Result -// where -// Self: std::marker::Sized { -// todo!() -// } -// } - #[cfg(test)] mod tests { use crate::{ diff --git a/proving-system/stark/src/fri/fri_functions.rs b/proving-system/stark/src/fri/fri_functions.rs index 72fb81211..77a104e62 100644 --- a/proving-system/stark/src/fri/fri_functions.rs +++ b/proving-system/stark/src/fri/fri_functions.rs @@ -1,11 +1,19 @@ -use super::{Polynomial, FE}; +use lambdaworks_math::field::{element::FieldElement, traits::IsField}; -fn fold_polynomial(poly: &Polynomial, beta: &FE) -> Polynomial { +use super::Polynomial; + +fn fold_polynomial( + poly: &Polynomial>, + beta: &FieldElement, +) -> Polynomial> +where + F: IsField, +{ let coef = poly.coefficients(); - let even_coef: Vec = coef.iter().step_by(2).cloned().collect(); + let even_coef: Vec> = coef.iter().step_by(2).cloned().collect(); // odd coeficients of poly are multiplied by beta - let odd_coef_mul_beta: Vec = coef + let odd_coef_mul_beta: Vec> = coef .iter() .skip(1) .step_by(2) @@ -19,7 +27,10 @@ fn fold_polynomial(poly: &Polynomial, beta: &FE) -> Polynomial { even_poly + odd_poly } -fn next_domain(input: &[FE]) -> Vec { +fn next_domain(input: &[FieldElement]) -> Vec> +where + F: IsField, +{ let length = input.len() / 2; let mut ret = Vec::with_capacity(length); for v in input.iter().take(length) { @@ -32,11 +43,18 @@ fn next_domain(input: &[FE]) -> Vec { /// * new polynomoial folded with FRI protocol /// * new domain /// * evaluations of the polynomial -pub fn next_fri_layer( - poly: &Polynomial, - domain: &[FE], - beta: &FE, -) -> (Polynomial, Vec, Vec) { +pub fn next_fri_layer( + poly: &Polynomial>, + domain: &[FieldElement], + beta: &FieldElement, +) -> ( + Polynomial>, + Vec>, + Vec>, +) +where + F: IsField, +{ let ret_poly = fold_polynomial(poly, beta); let ret_next_domain = next_domain(domain); let ret_evaluation = ret_poly.evaluate_slice(&ret_next_domain); @@ -45,7 +63,11 @@ pub fn next_fri_layer( // #[cfg(test)] // mod tests { -// use super::{fold_polynomial, next_domain, next_fri_layer, FE}; +// use super::{fold_polynomial, next_domain, next_fri_layer}; +// use lambdaworks_math::field::fields::u64_prime_field::U64PrimeField; +// use lambdaworks_math::field::element::FieldElement; +// const MODULUS: u64 = 13; +// type FE = FieldElement>; // use lambdaworks_math::polynomial::Polynomial; // #[test] diff --git a/proving-system/stark/src/lib.rs b/proving-system/stark/src/lib.rs index 20a3d97a2..8f0343ad2 100644 --- a/proving-system/stark/src/lib.rs +++ b/proving-system/stark/src/lib.rs @@ -92,10 +92,7 @@ pub fn fibonacci_trace(initial_values: [FE; 2]) -> Vec { ret } -pub fn prove( - pub_inputs: [FE; 2], -) -> StarkQueryProof -{ +pub fn prove(pub_inputs: [FE; 2]) -> StarkQueryProof { let transcript = &mut Transcript::new(); // * Generate Coset From 22a691cbff56774d48c9ed1d75613eef59c9ca7b Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Wed, 1 Mar 2023 17:08:45 -0300 Subject: [PATCH 82/85] Fix fri_functions tests --- proving-system/stark/src/fri/fri_functions.rs | 198 +++++++++--------- .../stark/src/fri/fri_merkle_tree.rs | 2 +- 2 files changed, 100 insertions(+), 100 deletions(-) diff --git a/proving-system/stark/src/fri/fri_functions.rs b/proving-system/stark/src/fri/fri_functions.rs index 77a104e62..5da1ad2c9 100644 --- a/proving-system/stark/src/fri/fri_functions.rs +++ b/proving-system/stark/src/fri/fri_functions.rs @@ -61,102 +61,102 @@ where (ret_poly, ret_next_domain, ret_evaluation) } -// #[cfg(test)] -// mod tests { -// use super::{fold_polynomial, next_domain, next_fri_layer}; -// use lambdaworks_math::field::fields::u64_prime_field::U64PrimeField; -// use lambdaworks_math::field::element::FieldElement; -// const MODULUS: u64 = 13; -// type FE = FieldElement>; -// use lambdaworks_math::polynomial::Polynomial; - -// #[test] -// fn test_fold() { -// let p0 = Polynomial::new(&[ -// FE::new(3), -// FE::new(1), -// FE::new(2), -// FE::new(7), -// FE::new(3), -// FE::new(5), -// ]); -// let beta = FE::new(4); -// let p1 = fold_polynomial(&p0, &beta); -// assert_eq!( -// p1, -// Polynomial::new(&[FE::new(7), FE::new(30), FE::new(23),]) -// ); - -// let gamma = FE::new(3); -// let p2 = fold_polynomial(&p1, &gamma); -// assert_eq!(p2, Polynomial::new(&[FE::new(97), FE::new(23),])); - -// let delta = FE::new(2); -// let p3 = fold_polynomial(&p2, &delta); -// assert_eq!(p3, Polynomial::new(&[FE::new(143)])); -// assert_eq!(p3.degree(), 0); -// } - -// #[test] -// fn test_next_domain() { -// let input = [ -// FE::new(5), -// FE::new(7), -// FE::new(13), -// FE::new(20), -// FE::new(1), -// FE::new(1), -// FE::new(1), -// FE::new(1), -// ]; -// let ret_next_domain = next_domain(&input); -// assert_eq!( -// ret_next_domain, -// &[FE::new(25), FE::new(49), FE::new(169), FE::new(107),] -// ); - -// let ret_next_domain_2 = next_domain(&ret_next_domain); -// assert_eq!(ret_next_domain_2, &[FE::new(39), FE::new(57)]); - -// let ret_next_domain_3 = next_domain(&ret_next_domain_2); -// assert_eq!(ret_next_domain_3, &[FE::new(56)]); -// } - -// #[test] -// fn text_next_fri_layer() { -// let p0 = Polynomial::new(&[ -// FE::new(3), -// FE::new(1), -// FE::new(2), -// FE::new(7), -// FE::new(3), -// FE::new(5), -// ]); -// let beta = FE::new(4); -// let input_domain = [ -// FE::new(5), -// FE::new(7), -// FE::new(13), -// FE::new(20), -// FE::new(1), -// FE::new(1), -// FE::new(1), -// FE::new(1), -// ]; - -// let (p1, ret_next_domain, ret_evaluation) = next_fri_layer(&p0, &input_domain, &beta); - -// assert_eq!( -// p1, -// Polynomial::new(&[FE::new(7), FE::new(30), FE::new(23),]) -// ); -// assert_eq!( -// ret_next_domain, -// &[FE::new(25), FE::new(49), FE::new(169), FE::new(107),] -// ); -// assert_eq!( -// ret_evaluation, -// &[FE::new(189), FE::new(151), FE::new(93), FE::new(207),] -// ); -// } -// } +#[cfg(test)] +mod tests { + use super::{fold_polynomial, next_domain, next_fri_layer}; + use lambdaworks_math::field::element::FieldElement; + use lambdaworks_math::field::fields::u64_prime_field::U64PrimeField; + const MODULUS: u64 = 293; + type FE = FieldElement>; + use lambdaworks_math::polynomial::Polynomial; + + #[test] + fn test_fold() { + let p0 = Polynomial::new(&[ + FE::new(3), + FE::new(1), + FE::new(2), + FE::new(7), + FE::new(3), + FE::new(5), + ]); + let beta = FE::new(4); + let p1 = fold_polynomial(&p0, &beta); + assert_eq!( + p1, + Polynomial::new(&[FE::new(7), FE::new(30), FE::new(23),]) + ); + + let gamma = FE::new(3); + let p2 = fold_polynomial(&p1, &gamma); + assert_eq!(p2, Polynomial::new(&[FE::new(97), FE::new(23),])); + + let delta = FE::new(2); + let p3 = fold_polynomial(&p2, &delta); + assert_eq!(p3, Polynomial::new(&[FE::new(143)])); + assert_eq!(p3.degree(), 0); + } + + #[test] + fn test_next_domain() { + let input = [ + FE::new(5), + FE::new(7), + FE::new(13), + FE::new(20), + FE::new(1), + FE::new(1), + FE::new(1), + FE::new(1), + ]; + let ret_next_domain = next_domain(&input); + assert_eq!( + ret_next_domain, + &[FE::new(25), FE::new(49), FE::new(169), FE::new(107),] + ); + + let ret_next_domain_2 = next_domain(&ret_next_domain); + assert_eq!(ret_next_domain_2, &[FE::new(39), FE::new(57)]); + + let ret_next_domain_3 = next_domain(&ret_next_domain_2); + assert_eq!(ret_next_domain_3, &[FE::new(56)]); + } + + #[test] + fn text_next_fri_layer() { + let p0 = Polynomial::new(&[ + FE::new(3), + FE::new(1), + FE::new(2), + FE::new(7), + FE::new(3), + FE::new(5), + ]); + let beta = FE::new(4); + let input_domain = [ + FE::new(5), + FE::new(7), + FE::new(13), + FE::new(20), + FE::new(1), + FE::new(1), + FE::new(1), + FE::new(1), + ]; + + let (p1, ret_next_domain, ret_evaluation) = next_fri_layer(&p0, &input_domain, &beta); + + assert_eq!( + p1, + Polynomial::new(&[FE::new(7), FE::new(30), FE::new(23),]) + ); + assert_eq!( + ret_next_domain, + &[FE::new(25), FE::new(49), FE::new(169), FE::new(107),] + ); + assert_eq!( + ret_evaluation, + &[FE::new(189), FE::new(151), FE::new(93), FE::new(207),] + ); + } +} diff --git a/proving-system/stark/src/fri/fri_merkle_tree.rs b/proving-system/stark/src/fri/fri_merkle_tree.rs index 995e3e93a..6a595fed0 100644 --- a/proving-system/stark/src/fri/fri_merkle_tree.rs +++ b/proving-system/stark/src/fri/fri_merkle_tree.rs @@ -6,7 +6,7 @@ pub type FriMerkleTree = MerkleTree; // #[cfg(test)] // mod tests { -// use super::{FriMerkleTree, FE}; +// use super::{FriMerkleTree}; // #[test] // fn build_merkle_tree_from_an_even_set_of_leafs() { From c4b73289fb9ff9fd3d0f6eddf1515d3dfcca338c Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Wed, 1 Mar 2023 17:13:16 -0300 Subject: [PATCH 83/85] Remove fri_merkle_tree module, move to mod.rs --- proving-system/stark/src/fri/fri_merkle_tree.rs | 16 ---------------- proving-system/stark/src/fri/mod.rs | 4 ++-- 2 files changed, 2 insertions(+), 18 deletions(-) delete mode 100644 proving-system/stark/src/fri/fri_merkle_tree.rs diff --git a/proving-system/stark/src/fri/fri_merkle_tree.rs b/proving-system/stark/src/fri/fri_merkle_tree.rs deleted file mode 100644 index 6a595fed0..000000000 --- a/proving-system/stark/src/fri/fri_merkle_tree.rs +++ /dev/null @@ -1,16 +0,0 @@ -pub use super::{Polynomial, F, FE}; -pub use lambdaworks_crypto::merkle_tree::merkle::MerkleTree; -pub use lambdaworks_crypto::merkle_tree::DefaultHasher; - -pub type FriMerkleTree = MerkleTree; - -// #[cfg(test)] -// mod tests { -// use super::{FriMerkleTree}; - -// #[test] -// fn build_merkle_tree_from_an_even_set_of_leafs() { -// let merkle_tree = FriMerkleTree::build(&[FE::new(1), FE::new(2), FE::new(3), FE::new(4)]); -// assert_eq!(merkle_tree.root.borrow().hash, FE::new(20)); -// } -// } diff --git a/proving-system/stark/src/fri/mod.rs b/proving-system/stark/src/fri/mod.rs index 552074539..a7ac04e03 100644 --- a/proving-system/stark/src/fri/mod.rs +++ b/proving-system/stark/src/fri/mod.rs @@ -1,11 +1,11 @@ mod fri_commitment; pub mod fri_decommit; mod fri_functions; -mod fri_merkle_tree; use crate::fri::fri_commitment::{FriCommitment, FriCommitmentVec}; use crate::fri::fri_functions::next_fri_layer; -pub use crate::fri::fri_merkle_tree::FriMerkleTree; +pub use lambdaworks_crypto::merkle_tree::DefaultHasher; +pub type FriMerkleTree = MerkleTree; pub use lambdaworks_crypto::fiat_shamir::transcript::Transcript; pub use lambdaworks_crypto::merkle_tree::merkle::MerkleTree; use lambdaworks_math::traits::ByteConversion; From 5f4ccc294f127aafa16801b0093cc6f55ed18216 Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Wed, 1 Mar 2023 17:15:30 -0300 Subject: [PATCH 84/85] Clippy --- proving-system/stark/src/fri/fri_functions.rs | 2 ++ proving-system/stark/src/lib.rs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/proving-system/stark/src/fri/fri_functions.rs b/proving-system/stark/src/fri/fri_functions.rs index 5da1ad2c9..195a38607 100644 --- a/proving-system/stark/src/fri/fri_functions.rs +++ b/proving-system/stark/src/fri/fri_functions.rs @@ -43,6 +43,8 @@ where /// * new polynomoial folded with FRI protocol /// * new domain /// * evaluations of the polynomial +// TODO: Remove this +#[allow(clippy::type_complexity)] pub fn next_fri_layer( poly: &Polynomial>, domain: &[FieldElement], diff --git a/proving-system/stark/src/lib.rs b/proving-system/stark/src/lib.rs index 8f0343ad2..7f6115587 100644 --- a/proving-system/stark/src/lib.rs +++ b/proving-system/stark/src/lib.rs @@ -148,7 +148,7 @@ pub fn prove(pub_inputs: [FE; 2]) -> StarkQueryProof { ]; // These are evaluations over the composition polynomial - let mut composition_poly = get_composition_poly(trace_poly.clone(), &trace_primitive_root); + let mut composition_poly = get_composition_poly(trace_poly, &trace_primitive_root); let composition_poly_lde_evaluation = composition_poly.evaluate(&evaluation_points[0]); // This is needed to check the element is in the root From 9c63aaad625b08d08e356d2e22d4ed159cf06c86 Mon Sep 17 00:00:00 2001 From: Javier Chatruc Date: Wed, 1 Mar 2023 17:18:46 -0300 Subject: [PATCH 85/85] Remove TODOs --- proving-system/stark/src/lib.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/proving-system/stark/src/lib.rs b/proving-system/stark/src/lib.rs index 7f6115587..dd0dea910 100644 --- a/proving-system/stark/src/lib.rs +++ b/proving-system/stark/src/lib.rs @@ -303,14 +303,6 @@ pub fn fri_verify( true } -// TODOS after basic fibonacci works: -// - Add Fiat Shamir -// - Add Zerofiers -// - Check last evaluation point -// - Instead of returning a bool, make an error type encoding each possible failure in the verifying pipeline so failures give more info. -// - Unhardcode polynomials, use Winterfell AIR -// - Coset evaluation - #[cfg(test)] mod tests { use crate::{verify, FE};